diff --git a/apps/client/app/api-client/@tanstack/react-query.gen.ts b/apps/client/app/api-client/@tanstack/react-query.gen.ts index 7fc4838..10fd368 100644 --- a/apps/client/app/api-client/@tanstack/react-query.gen.ts +++ b/apps/client/app/api-client/@tanstack/react-query.gen.ts @@ -8,6 +8,8 @@ import { deleteVolume, getVolume, updateVolume, + mountVolume, + unmountVolume, } from "../sdk.gen"; import { queryOptions, type UseMutationOptions, type DefaultError } from "@tanstack/react-query"; import type { @@ -21,6 +23,10 @@ import type { GetVolumeData, UpdateVolumeData, UpdateVolumeResponse, + MountVolumeData, + MountVolumeResponse, + UnmountVolumeData, + UnmountVolumeResponse, } from "../types.gen"; import { client as _heyApiClient } from "../client.gen"; @@ -219,3 +225,81 @@ export const updateVolumeMutation = ( }; return mutationOptions; }; + +export const mountVolumeQueryKey = (options: Options) => createQueryKey("mountVolume", options); + +/** + * Mount a volume + */ +export const mountVolumeOptions = (options: Options) => { + return queryOptions({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await mountVolume({ + ...options, + ...queryKey[0], + signal, + throwOnError: true, + }); + return data; + }, + queryKey: mountVolumeQueryKey(options), + }); +}; + +/** + * Mount a volume + */ +export const mountVolumeMutation = ( + options?: Partial>, +): UseMutationOptions> => { + const mutationOptions: UseMutationOptions> = { + mutationFn: async (localOptions) => { + const { data } = await mountVolume({ + ...options, + ...localOptions, + throwOnError: true, + }); + return data; + }, + }; + return mutationOptions; +}; + +export const unmountVolumeQueryKey = (options: Options) => createQueryKey("unmountVolume", options); + +/** + * Unmount a volume + */ +export const unmountVolumeOptions = (options: Options) => { + return queryOptions({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await unmountVolume({ + ...options, + ...queryKey[0], + signal, + throwOnError: true, + }); + return data; + }, + queryKey: unmountVolumeQueryKey(options), + }); +}; + +/** + * Unmount a volume + */ +export const unmountVolumeMutation = ( + options?: Partial>, +): UseMutationOptions> => { + const mutationOptions: UseMutationOptions> = { + mutationFn: async (localOptions) => { + const { data } = await unmountVolume({ + ...options, + ...localOptions, + throwOnError: true, + }); + return data; + }, + }; + return mutationOptions; +}; diff --git a/apps/client/app/api-client/sdk.gen.ts b/apps/client/app/api-client/sdk.gen.ts index 0fa88b6..7c60be2 100644 --- a/apps/client/app/api-client/sdk.gen.ts +++ b/apps/client/app/api-client/sdk.gen.ts @@ -16,6 +16,12 @@ import type { UpdateVolumeData, UpdateVolumeResponses, UpdateVolumeErrors, + MountVolumeData, + MountVolumeResponses, + MountVolumeErrors, + UnmountVolumeData, + UnmountVolumeResponses, + UnmountVolumeErrors, } from "./types.gen"; import { client as _heyApiClient } from "./client.gen"; @@ -115,3 +121,25 @@ export const updateVolume = ( }, }); }; + +/** + * Mount a volume + */ +export const mountVolume = (options: Options) => { + return (options.client ?? _heyApiClient).post({ + url: "/api/v1/volumes/{name}/mount", + ...options, + }); +}; + +/** + * Unmount a volume + */ +export const unmountVolume = ( + options: Options, +) => { + return (options.client ?? _heyApiClient).post({ + url: "/api/v1/volumes/{name}/unmount", + ...options, + }); +}; diff --git a/apps/client/app/api-client/types.gen.ts b/apps/client/app/api-client/types.gen.ts index b5fe3eb..5528c0b 100644 --- a/apps/client/app/api-client/types.gen.ts +++ b/apps/client/app/api-client/types.gen.ts @@ -245,6 +245,60 @@ export type UpdateVolumeResponses = { export type UpdateVolumeResponse = UpdateVolumeResponses[keyof UpdateVolumeResponses]; +export type MountVolumeData = { + body?: never; + path: { + name: string; + }; + query?: never; + url: "/api/v1/volumes/{name}/mount"; +}; + +export type MountVolumeErrors = { + /** + * Volume not found + */ + 404: unknown; +}; + +export type MountVolumeResponses = { + /** + * Volume mounted successfully + */ + 200: { + message: string; + }; +}; + +export type MountVolumeResponse = MountVolumeResponses[keyof MountVolumeResponses]; + +export type UnmountVolumeData = { + body?: never; + path: { + name: string; + }; + query?: never; + url: "/api/v1/volumes/{name}/unmount"; +}; + +export type UnmountVolumeErrors = { + /** + * Volume not found + */ + 404: unknown; +}; + +export type UnmountVolumeResponses = { + /** + * Volume unmounted successfully + */ + 200: { + message: string; + }; +}; + +export type UnmountVolumeResponse = UnmountVolumeResponses[keyof UnmountVolumeResponses]; + export type ClientOptions = { baseUrl: "http://localhost:3000" | (string & {}); }; diff --git a/apps/client/app/app.css b/apps/client/app/app.css index 1233a32..79df160 100644 --- a/apps/client/app/app.css +++ b/apps/client/app/app.css @@ -5,8 +5,8 @@ @theme { --font-sans: - "Google Sans Code", ui-sans-serif, system-ui, sans-serif, - "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + "Google Sans Code", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", + "Noto Color Emoji"; } html, diff --git a/apps/client/app/components/ui/sonner.tsx b/apps/client/app/components/ui/sonner.tsx index ec702d9..53f162d 100644 --- a/apps/client/app/components/ui/sonner.tsx +++ b/apps/client/app/components/ui/sonner.tsx @@ -8,6 +8,7 @@ const Toaster = ({ ...props }: ToasterProps) => { { return { message: error.message as string }; } + if (typeof error === "string") { + return { message: error }; + } + return undefined; }; diff --git a/apps/client/app/routes/details.tsx b/apps/client/app/routes/details.tsx index 3ad6243..b31ba58 100644 --- a/apps/client/app/routes/details.tsx +++ b/apps/client/app/routes/details.tsx @@ -3,7 +3,12 @@ import { WifiIcon } from "lucide-react"; import { useNavigate, useParams } from "react-router"; import { toast } from "sonner"; import { getVolume } from "~/api-client"; -import { deleteVolumeMutation, getVolumeOptions } from "~/api-client/@tanstack/react-query.gen"; +import { + deleteVolumeMutation, + getVolumeOptions, + mountVolumeMutation, + unmountVolumeMutation, +} from "~/api-client/@tanstack/react-query.gen"; import { CreateVolumeForm } from "~/components/create-volume-form"; import { Button } from "~/components/ui/button"; import { Card } from "~/components/ui/card"; @@ -11,6 +16,7 @@ import { VolumeIcon } from "~/components/volume-icon"; import { parseError } from "~/lib/errors"; import { HealthchecksCard } from "~/modules/details/components/healthchecks-card"; import type { Route } from "./+types/details"; +import { cn } from "~/lib/utils"; export const clientLoader = async ({ params }: Route.ClientLoaderArgs) => { const volume = await getVolume({ path: { name: params.name ?? "" } }); @@ -39,6 +45,30 @@ export default function DetailsPage({ loaderData }: Route.ComponentProps) { }, }); + const mountVol = useMutation({ + ...mountVolumeMutation(), + onSuccess: () => { + toast.success("Volume mounted successfully"); + }, + onError: (error) => { + toast.error("Failed to mount volume", { + description: parseError(error)?.message, + }); + }, + }); + + const unmountVol = useMutation({ + ...unmountVolumeMutation(), + onSuccess: () => { + toast.success("Volume unmounted successfully"); + }, + onError: (error) => { + toast.error("Failed to unmount volume", { + description: parseError(error)?.message, + }); + }, + }); + const handleDeleteConfirm = (name: string) => { if (confirm(`Are you sure you want to delete the volume "${name}"? This action cannot be undone.`)) { deleteVol.mutate({ path: { name } }); @@ -67,7 +97,22 @@ export default function DetailsPage({ loaderData }: Route.ComponentProps) {
- + + diff --git a/apps/server/package.json b/apps/server/package.json index 6463398..5a0727e 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -16,7 +16,8 @@ "hono": "^4.9.2", "hono-openapi": "^0.4.8", "http-errors-enhanced": "^3.0.2", - "slugify": "^1.6.6" + "slugify": "^1.6.6", + "winston": "^3.17.0" }, "devDependencies": { "@types/bun": "^1.2.20", diff --git a/apps/server/src/index.ts b/apps/server/src/index.ts index c1f3740..a2a015f 100644 --- a/apps/server/src/index.ts +++ b/apps/server/src/index.ts @@ -1,11 +1,12 @@ import * as fs from "node:fs/promises"; import { Scalar } from "@scalar/hono-api-reference"; import { Hono } from "hono"; -import { logger } from "hono/logger"; +import { logger as honoLogger } from "hono/logger"; import { openAPISpecs } from "hono-openapi"; import { runDbMigrations } from "./db/db"; import { driverController } from "./modules/driver/driver.controller"; import { volumeController } from "./modules/volumes/volume.controller"; +import { logger } from "./utils/logger"; export const generalDescriptor = (app: Hono) => openAPISpecs(app, { @@ -25,9 +26,9 @@ export const scalarDescriptor = Scalar({ url: "/api/v1/openapi.json", }); -const driver = new Hono().use(logger()).route("/", driverController); +const driver = new Hono().use(honoLogger()).route("/", driverController); const app = new Hono() - .use(logger()) + .use(honoLogger()) .get("healthcheck", (c) => c.json({ status: "ok" })) .basePath("/api/v1") .route("/volumes", volumeController); @@ -56,7 +57,7 @@ const socketPath = "/run/docker/plugins/ironmount.sock"; fetch: app.fetch, }); - console.log(`Server is running at http://localhost:8080 and unix socket at ${socketPath}`); + logger.info(`Server is running at http://localhost:8080 and unix socket at ${socketPath}`); })(); export type AppType = typeof app; diff --git a/apps/server/src/modules/backends/directory/directory-backend.ts b/apps/server/src/modules/backends/directory/directory-backend.ts index 61cf41c..123c800 100644 --- a/apps/server/src/modules/backends/directory/directory-backend.ts +++ b/apps/server/src/modules/backends/directory/directory-backend.ts @@ -2,14 +2,15 @@ import * as fs from "node:fs/promises"; import * as npath from "node:path"; import { BACKEND_STATUS, type BackendConfig } from "@ironmount/schemas"; import type { VolumeBackend } from "../backend"; +import { logger } from "../../../utils/logger"; const mount = async (_config: BackendConfig, path: string) => { - console.log("Mounting directory volume..."); + logger.info("Mounting directory volume..."); await fs.mkdir(path, { recursive: true }); }; const unmount = async () => { - console.log("Cannot unmount directory volume."); + logger.info("Cannot unmount directory volume."); }; const checkHealth = async (path: string) => { @@ -23,7 +24,7 @@ const checkHealth = async (path: string) => { return { status: BACKEND_STATUS.mounted }; } catch (error) { - console.error("Directory health check failed:", error); + logger.error("Directory health check failed:", error); return { status: BACKEND_STATUS.error, error: error instanceof Error ? error.message : String(error) }; } }; diff --git a/apps/server/src/modules/backends/nfs/nfs-backend.ts b/apps/server/src/modules/backends/nfs/nfs-backend.ts index 6064042..4f2d70d 100644 --- a/apps/server/src/modules/backends/nfs/nfs-backend.ts +++ b/apps/server/src/modules/backends/nfs/nfs-backend.ts @@ -4,6 +4,7 @@ import * as os from "node:os"; import * as npath from "node:path"; import { BACKEND_STATUS, type BackendConfig } from "@ironmount/schemas"; import type { VolumeBackend } from "../backend"; +import { logger } from "../../../utils/logger"; const mount = async (config: BackendConfig, path: string) => { if (config.backend !== "nfs") { @@ -11,7 +12,7 @@ const mount = async (config: BackendConfig, path: string) => { } if (os.platform() !== "linux") { - console.error("NFS mounting is only supported on Linux hosts."); + logger.error("NFS mounting is only supported on Linux hosts."); return; } @@ -27,14 +28,14 @@ const mount = async (config: BackendConfig, path: string) => { }, 5000); exec(cmd, (error, stdout, stderr) => { - console.log("Mount command executed:", { cmd, error, stdout, stderr }); + logger.info("Mount command executed:", { cmd, error, stdout, stderr }); clearTimeout(timeout); if (error) { - console.error(`Error mounting NFS volume: ${stderr}`); + logger.error(`Error mounting NFS volume: ${stderr}`); return reject(new Error(`Failed to mount NFS volume: ${stderr}`)); } - console.log(`NFS volume mounted successfully: ${stdout}`); + logger.info(`NFS volume mounted successfully: ${stdout}`); resolve(); }); }); @@ -42,7 +43,14 @@ const mount = async (config: BackendConfig, path: string) => { const unmount = async (path: string) => { if (os.platform() !== "linux") { - console.error("NFS unmounting is only supported on Linux hosts."); + logger.error("NFS unmounting is only supported on Linux hosts."); + return; + } + + try { + await fs.access(path); + } catch { + logger.warn(`Path ${path} does not exist. Skipping unmount.`); return; } @@ -54,14 +62,14 @@ const unmount = async (path: string) => { }, 5000); exec(cmd, (error, stdout, stderr) => { - console.log("Unmount command executed:", { cmd, error, stdout, stderr }); + logger.info("Unmount command executed:", { cmd, error, stdout, stderr }); clearTimeout(timeout); if (error) { - console.error(`Error unmounting NFS volume: ${stderr}`); + logger.error(`Error unmounting NFS volume: ${stderr}`); return reject(new Error(`Failed to unmount NFS volume: ${stderr}`)); } - console.log(`NFS volume unmounted successfully: ${stdout}`); + logger.info(`NFS volume unmounted successfully: ${stdout}`); resolve(); }); }); @@ -78,7 +86,7 @@ const checkHealth = async (path: string) => { return { status: BACKEND_STATUS.mounted }; } catch (error) { - console.error("NFS volume health check failed:", error); + logger.error("NFS volume health check failed:", error); return { status: BACKEND_STATUS.error, error: error instanceof Error ? error.message : String(error) }; } }; diff --git a/apps/server/src/modules/volumes/volume.controller.ts b/apps/server/src/modules/volumes/volume.controller.ts index afc8c32..83bc936 100644 --- a/apps/server/src/modules/volumes/volume.controller.ts +++ b/apps/server/src/modules/volumes/volume.controller.ts @@ -13,8 +13,11 @@ import { updateVolumeBody, updateVolumeDto, type VolumeDto, + mountVolumeDto, + unmountVolumeDto, } from "./volume.dto"; import { volumeService } from "./volume.service"; +import { logger } from "../../utils/logger"; export const volumeController = new Hono() .get("/", listVolumesDto, async (c) => { @@ -100,4 +103,26 @@ export const volumeController = new Hono() }; return c.json(response, 200); + }) + .post("/:name/mount", mountVolumeDto, async (c) => { + const { name } = c.req.param(); + const res = await volumeService.mountVolume(name); + + if (res.error) { + const { message, status } = handleServiceError(res.error); + return c.json(message, status); + } + + return c.json({ message: "Volume mounted successfully" }, 200); + }) + .post("/:name/unmount", unmountVolumeDto, async (c) => { + const { name } = c.req.param(); + const res = await volumeService.unmountVolume(name); + + if (res.error) { + const { message, status } = handleServiceError(res.error); + return c.json(message, status); + } + + return c.json({ message: "Volume unmounted successfully" }, 200); }); diff --git a/apps/server/src/modules/volumes/volume.dto.ts b/apps/server/src/modules/volumes/volume.dto.ts index 63e38ca..ec9b06e 100644 --- a/apps/server/src/modules/volumes/volume.dto.ts +++ b/apps/server/src/modules/volumes/volume.dto.ts @@ -190,3 +190,57 @@ export const testConnectionDto = describeRoute({ }, }, }); + +/** + * Mount volume + */ +export const mountVolumeResponse = type({ + message: "string", +}); + +export const mountVolumeDto = describeRoute({ + description: "Mount a volume", + operationId: "mountVolume", + validateResponse: true, + tags: ["Volumes"], + responses: { + 200: { + description: "Volume mounted successfully", + content: { + "application/json": { + schema: resolver(mountVolumeResponse), + }, + }, + }, + 404: { + description: "Volume not found", + }, + }, +}); + +/** + * Unmount volume + */ +export const unmountVolumeResponse = type({ + message: "string", +}); + +export const unmountVolumeDto = describeRoute({ + description: "Unmount a volume", + operationId: "unmountVolume", + validateResponse: true, + tags: ["Volumes"], + responses: { + 200: { + description: "Volume unmounted successfully", + content: { + "application/json": { + schema: resolver(unmountVolumeResponse), + }, + }, + }, + 404: { + description: "Volume not found", + }, + }, +}); diff --git a/apps/server/src/modules/volumes/volume.service.ts b/apps/server/src/modules/volumes/volume.service.ts index ea32b0c..27d82d8 100644 --- a/apps/server/src/modules/volumes/volume.service.ts +++ b/apps/server/src/modules/volumes/volume.service.ts @@ -9,6 +9,7 @@ import { config } from "../../core/config"; import { db } from "../../db/db"; import { volumesTable } from "../../db/schema"; import { createVolumeBackend } from "../backends/backend"; +import { logger } from "../../utils/logger"; const listVolumes = async () => { const volumes = await db.query.volumesTable.findMany({}); @@ -76,7 +77,18 @@ const mountVolume = async (name: string) => { } const backend = createVolumeBackend(volume); + await backend.unmount().catch((_) => { + // Ignore unmount errors + }); + await backend.mount(); + + await db + .update(volumesTable) + .set({ status: "mounted", lastHealthCheck: new Date() }) + .where(eq(volumesTable.name, name)); + + return { status: 200 }; } catch (error) { return { error: new InternalServerError("Failed to mount volume", { @@ -86,6 +98,34 @@ const mountVolume = async (name: string) => { } }; +const unmountVolume = async (name: string) => { + try { + const volume = await db.query.volumesTable.findFirst({ + where: eq(volumesTable.name, name), + }); + + if (!volume) { + return { error: new NotFoundError("Volume not found") }; + } + + const backend = createVolumeBackend(volume); + await backend.unmount(); + + await db + .update(volumesTable) + .set({ status: "unmounted", lastHealthCheck: new Date() }) + .where(eq(volumesTable.name, name)); + + return { status: 200 }; + } catch (error) { + return { + error: new InternalServerError("Failed to unmount volume", { + cause: error, + }), + }; + } +}; + const getVolume = async (name: string) => { const volume = await db.query.volumesTable.findFirst({ where: eq(volumesTable.name, name), @@ -202,7 +242,7 @@ const testConnection = async (backendConfig: BackendConfig) => { await fs.rm(tempDir, { recursive: true, force: true }); } catch (cleanupError) { // Ignore cleanup errors if directory doesn't exist or can't be removed - console.warn("Failed to cleanup temp directory:", cleanupError); + logger.warn("Failed to cleanup temp directory:", cleanupError); } } } @@ -218,4 +258,5 @@ export const volumeService = { testConnection, updateVolumeStatus, getVolumeStatus, + unmountVolume, }; diff --git a/apps/server/src/utils/errors.ts b/apps/server/src/utils/errors.ts index 8dccf2f..3aea02c 100644 --- a/apps/server/src/utils/errors.ts +++ b/apps/server/src/utils/errors.ts @@ -1,4 +1,5 @@ import { ConflictError, NotFoundError } from "http-errors-enhanced"; +import { logger } from "./logger"; export const handleServiceError = (error: unknown) => { if (error instanceof ConflictError) { @@ -9,6 +10,6 @@ export const handleServiceError = (error: unknown) => { return { message: error.message, status: 404 as const }; } - console.error("Unhandled service error:", error); + logger.error("Unhandled service error:", error); return { message: "Internal Server Error", status: 500 as const }; }; diff --git a/apps/server/src/utils/logger.ts b/apps/server/src/utils/logger.ts new file mode 100644 index 0000000..bb21950 --- /dev/null +++ b/apps/server/src/utils/logger.ts @@ -0,0 +1,34 @@ +import { createLogger, format, transports } from "winston"; + +const { printf, combine, colorize } = format; + +const printConsole = printf((info) => `${info.level} > ${info.message}`); +const consoleFormat = combine(colorize(), printConsole); + +const winstonLogger = createLogger({ + level: "info", + format: format.json(), + transports: [new transports.Console({ level: "info", format: consoleFormat })], +}); + +const log = (level: "info" | "warn" | "error", messages: unknown[]) => { + const stringMessages = messages.flatMap((m) => { + if (m instanceof Error) { + return [m.message, m.stack]; + } + + if (typeof m === "object") { + return JSON.stringify(m, null, 2); + } + + return m; + }); + + winstonLogger.log(level, stringMessages.join(" | ")); +}; + +export const logger = { + info: (...messages: unknown[]) => log("info", messages), + warn: (...messages: unknown[]) => log("warn", messages), + error: (...messages: unknown[]) => log("error", messages), +}; diff --git a/bun.lock b/bun.lock index ca54246..5996b6f 100644 --- a/bun.lock +++ b/bun.lock @@ -63,6 +63,7 @@ "hono-openapi": "^0.4.8", "http-errors-enhanced": "^3.0.2", "slugify": "^1.6.6", + "winston": "^3.17.0", }, "devDependencies": { "@types/bun": "^1.2.20", @@ -142,6 +143,10 @@ "@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="], + "@colors/colors": ["@colors/colors@1.6.0", "", {}, "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA=="], + + "@dabh/diagnostics": ["@dabh/diagnostics@2.0.3", "", { "dependencies": { "colorspace": "1.1.x", "enabled": "2.0.x", "kuler": "^2.0.0" } }, "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA=="], + "@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="], "@esbuild-kit/core-utils": ["@esbuild-kit/core-utils@3.3.2", "", { "dependencies": { "esbuild": "~0.18.20", "source-map-support": "^0.5.21" } }, "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ=="], @@ -422,6 +427,8 @@ "@types/react-dom": ["@types/react-dom@19.1.7", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-i5ZzwYpqjmrKenzkoLM2Ibzt6mAsM7pxB6BCIouEVVmgiqaMj1TjaK7hnA36hbW5aZv20kx7Lw6hWzPWg0Rurw=="], + "@types/triple-beam": ["@types/triple-beam@1.3.5", "", {}, "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw=="], + "@vitejs/plugin-rsc": ["@vitejs/plugin-rsc@0.4.11", "", { "dependencies": { "@mjackson/node-fetch-server": "^0.7.0", "es-module-lexer": "^1.7.0", "estree-walker": "^3.0.3", "magic-string": "^0.30.17", "periscopic": "^4.0.2", "turbo-stream": "^3.1.0", "vitefu": "^1.1.1" }, "peerDependencies": { "react": "*", "react-dom": "*", "vite": "*" } }, "sha512-+4H4wLi+Y9yF58znBfKgGfX8zcqUGt8ngnmNgzrdGdF1SVz7EO0sg7WnhK5fFVHt6fUxsVEjmEabsCWHKPL1Tw=="], "accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="], @@ -444,6 +451,8 @@ "array-flatten": ["array-flatten@1.1.1", "", {}, "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="], + "async": ["async@3.2.6", "", {}, "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="], + "babel-dead-code-elimination": ["babel-dead-code-elimination@1.0.10", "", { "dependencies": { "@babel/core": "^7.23.7", "@babel/parser": "^7.23.6", "@babel/traverse": "^7.23.7", "@babel/types": "^7.23.6" } }, "sha512-DV5bdJZTzZ0zn0DC24v3jD7Mnidh6xhKa4GfKCbq3sfW8kaWhDdZjP3i81geA8T33tdYqWKw4D3fVv0CwEgKVA=="], "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], @@ -486,12 +495,18 @@ "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], - "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + "color": ["color@3.2.1", "", { "dependencies": { "color-convert": "^1.9.3", "color-string": "^1.6.0" } }, "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA=="], - "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + "color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="], + + "color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], + + "color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="], "color-support": ["color-support@1.1.3", "", { "bin": { "color-support": "bin.js" } }, "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg=="], + "colorspace": ["colorspace@1.1.4", "", { "dependencies": { "color": "^3.1.3", "text-hex": "1.0.x" } }, "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w=="], + "commander": ["commander@13.0.0", "", {}, "sha512-oPYleIY8wmTVzkvQq10AEok6YcTC4sRUBl8F9gVuwchGVUCTbl/vhLTaQqutuuySYOsu8YTgV+OxKc/8Yvx+mQ=="], "compressible": ["compressible@2.0.18", "", { "dependencies": { "mime-db": ">= 1.43.0 < 2" } }, "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg=="], @@ -554,6 +569,8 @@ "emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + "enabled": ["enabled@2.0.0", "", {}, "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ=="], + "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="], "enhanced-resolve": ["enhanced-resolve@5.18.3", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww=="], @@ -586,8 +603,12 @@ "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + "fecha": ["fecha@4.2.3", "", {}, "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw=="], + "finalhandler": ["finalhandler@1.3.1", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", "statuses": "2.0.1", "unpipe": "~1.0.0" } }, "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ=="], + "fn.name": ["fn.name@1.1.0", "", {}, "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="], + "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="], @@ -644,6 +665,8 @@ "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], + "is-arrayish": ["is-arrayish@0.3.4", "", {}, "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA=="], + "is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="], "is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="], @@ -654,6 +677,8 @@ "is-reference": ["is-reference@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.6" } }, "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw=="], + "is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], + "is-wsl": ["is-wsl@3.1.0", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw=="], "isbot": ["isbot@5.1.30", "", {}, "sha512-3wVJEonAns1OETX83uWsk5IAne2S5zfDcntD2hbtU23LelSqNXzXs9zKjMPOLMzroCgIjCfjYAEHrd2D6FOkiA=="], @@ -676,6 +701,8 @@ "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], + "kuler": ["kuler@2.0.0", "", {}, "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="], + "lightningcss": ["lightningcss@1.30.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.30.1", "lightningcss-darwin-x64": "1.30.1", "lightningcss-freebsd-x64": "1.30.1", "lightningcss-linux-arm-gnueabihf": "1.30.1", "lightningcss-linux-arm64-gnu": "1.30.1", "lightningcss-linux-arm64-musl": "1.30.1", "lightningcss-linux-x64-gnu": "1.30.1", "lightningcss-linux-x64-musl": "1.30.1", "lightningcss-win32-arm64-msvc": "1.30.1", "lightningcss-win32-x64-msvc": "1.30.1" } }, "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg=="], "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ=="], @@ -700,6 +727,8 @@ "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], + "logform": ["logform@2.7.0", "", { "dependencies": { "@colors/colors": "1.6.0", "@types/triple-beam": "^1.3.2", "fecha": "^4.2.0", "ms": "^2.1.1", "safe-stable-stringify": "^2.3.1", "triple-beam": "^1.3.0" } }, "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ=="], + "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], "lucide-react": ["lucide-react@0.539.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-VVISr+VF2krO91FeuCrm1rSOLACQUYVy7NQkzrOty52Y8TlTPcXcMdQFj9bYzBgXbWCiywlwSZ3Z8u6a+6bMlg=="], @@ -768,6 +797,8 @@ "on-headers": ["on-headers@1.1.0", "", {}, "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A=="], + "one-time": ["one-time@1.0.0", "", { "dependencies": { "fn.name": "1.x.x" } }, "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g=="], + "open": ["open@10.1.2", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "is-wsl": "^3.1.0" } }, "sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw=="], "openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="], @@ -830,6 +861,8 @@ "react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="], + "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], + "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], @@ -842,6 +875,8 @@ "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + "safe-stable-stringify": ["safe-stable-stringify@2.5.0", "", {}, "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA=="], + "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], "scheduler": ["scheduler@0.26.0", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="], @@ -870,6 +905,8 @@ "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + "simple-swizzle": ["simple-swizzle@0.2.4", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw=="], + "slugify": ["slugify@1.6.6", "", {}, "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw=="], "sonner": ["sonner@2.0.7", "", { "peerDependencies": { "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w=="], @@ -888,12 +925,16 @@ "spdx-license-ids": ["spdx-license-ids@3.0.22", "", {}, "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ=="], + "stack-trace": ["stack-trace@0.0.10", "", {}, "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg=="], + "statuses": ["statuses@2.0.1", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="], "string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], + "strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="], "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], @@ -906,12 +947,16 @@ "tar": ["tar@7.4.3", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.0.1", "mkdirp": "^3.0.1", "yallist": "^5.0.0" } }, "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw=="], + "text-hex": ["text-hex@1.0.0", "", {}, "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg=="], + "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], "tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="], "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], + "triple-beam": ["triple-beam@1.4.1", "", {}, "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg=="], + "tsconfck": ["tsconfck@3.1.6", "", { "peerDependencies": { "typescript": "^5.0.0" }, "optionalPeers": ["typescript"], "bin": { "tsconfck": "bin/tsconfck.js" } }, "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w=="], "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], @@ -952,6 +997,8 @@ "use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="], + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + "utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="], "valibot": ["valibot@0.41.0", "", { "peerDependencies": { "typescript": ">=5" }, "optionalPeers": ["typescript"] }, "sha512-igDBb8CTYr8YTQlOKgaN9nSS0Be7z+WRuaeYqGf3Cjz3aKmSnqEmYnkfVjzIuumGqfHpa3fLIvMEAfhrpqN8ng=="], @@ -972,6 +1019,10 @@ "which": ["which@3.0.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/which.js" } }, "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg=="], + "winston": ["winston@3.17.0", "", { "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.2", "async": "^3.2.3", "is-stream": "^2.0.0", "logform": "^2.7.0", "one-time": "^1.0.0", "readable-stream": "^3.4.0", "safe-stable-stringify": "^2.3.1", "stack-trace": "0.0.x", "triple-beam": "^1.3.0", "winston-transport": "^4.9.0" } }, "sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw=="], + + "winston-transport": ["winston-transport@4.9.0", "", { "dependencies": { "logform": "^2.7.0", "readable-stream": "^3.6.2", "triple-beam": "^1.3.0" } }, "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A=="], + "wordwrap": ["wordwrap@1.0.0", "", {}, "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="], "wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], @@ -1022,6 +1073,8 @@ "c12/dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="], + "color-string/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + "compression/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], "cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], @@ -1144,10 +1197,14 @@ "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "wrap-ansi-cjs/ansi-styles/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], "wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "giget/tar/minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "wrap-ansi-cjs/ansi-styles/color-convert/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], } }