diff --git a/packages/cli/README.md b/packages/cli/README.md index 752ef99b..644ad0f0 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -175,6 +175,44 @@ Options: - `--out`: Path to generate TypeScript types - `--format`: Format of the generated types (react or node) +### `bucket companies` + +Manage company data and feature access with the following subcommands. + +#### `bucket companies list` + +List all companies for the current app. +This helps you visualize the companies using your features and their basic metrics. + +```bash +bucket companies list [--app-id ap123456789] [--filter nameOrId] +``` + +Options: + +- `--app-id`: App ID to use +- `--filter`: Filter companies by name or ID + +#### `bucket companies features access` + +Grant or revoke access to specific features for a company. +If no feature key is provided, you'll be prompted to select one from a list. + +```bash +bucket companies features access [featureKey] [--enable|--disable] [--app-id ap123456789] +``` + +Arguments: + +- `companyId`: ID of the company to manage +- `featureKey`: Key of the feature to grant/revoke access to (optional, interactive selection if omitted) + +Options: + +- `--enable`: Enable the feature for this company +- `--disable`: Disable the feature for this company +- `--app-id`: App ID to use + ### `bucket apps` Commands for managing Bucket apps. diff --git a/packages/cli/commands/companies.ts b/packages/cli/commands/companies.ts new file mode 100644 index 00000000..e2d46983 --- /dev/null +++ b/packages/cli/commands/companies.ts @@ -0,0 +1,211 @@ +import { select } from "@inquirer/prompts"; +import chalk from "chalk"; +import { Argument, Command } from "commander"; +import ora, { Ora } from "ora"; + +import { getApp } from "../services/bootstrap.js"; +import { + CompanyFeatureAccess, + companyFeatureAccess, + listCompanies, +} from "../services/companies.js"; +import { listFeatures } from "../services/features.js"; +import { configStore } from "../stores/config.js"; +import { + handleError, + MissingAppIdError, + MissingEnvIdError, +} from "../utils/errors.js"; +import { + appIdOption, + companyFilterOption, + companyIdArgument, + disableFeatureOption, + enableFeatureOption, +} from "../utils/options.js"; +import { baseUrlSuffix } from "../utils/path.js"; + +export const listCompaniesAction = async (options: { filter?: string }) => { + const { baseUrl, appId } = configStore.getConfig(); + let spinner: Ora | undefined; + + if (!appId) { + return handleError(new MissingAppIdError(), "Companies List"); + } + const app = getApp(appId); + const production = app.environments.find((e) => e.isProduction); + if (!production) { + return handleError(new MissingEnvIdError(), "Companies List"); + } + + try { + spinner = ora( + `Loading companies for app ${chalk.cyan(app.name)}${baseUrlSuffix(baseUrl)}...`, + ).start(); + + const companiesResponse = await listCompanies(appId, { + envId: production.id, + // Use the filter for name/ID filtering if provided + idNameFilter: options.filter, + }); + + spinner.succeed( + `Loaded companies for app ${chalk.cyan(app.name)}${baseUrlSuffix(baseUrl)}.`, + ); + + console.table( + companiesResponse.data.map(({ id, name, userCount, lastSeen }) => ({ + id, + name: name || "(unnamed)", + users: userCount, + lastSeen: lastSeen ? new Date(lastSeen).toLocaleDateString() : "Never", + })), + ); + + console.log(`Total companies: ${companiesResponse.totalCount}`); + } catch (error) { + spinner?.fail("Loading companies failed."); + void handleError(error, "Companies List"); + } +}; + +export const companyFeatureAccessAction = async ( + companyId: string, + featureKey: string | undefined, + options: { enable: boolean; disable: boolean }, +) => { + const { baseUrl, appId } = configStore.getConfig(); + let spinner: Ora | undefined; + + if (!appId) { + return handleError(new MissingAppIdError(), "Company Feature Access"); + } + + const app = getApp(appId); + const production = app.environments.find((e) => e.isProduction); + if (!production) { + return handleError(new MissingEnvIdError(), "Company Feature Access"); + } + + // Validate conflicting options + if (options.enable && options.disable) { + return handleError( + "Cannot both enable and disable a feature.", + "Company Feature Access", + ); + } + + if (!options.enable && !options.disable) { + return handleError( + "Must specify either --enable or --disable.", + "Company Feature Access", + ); + } + + // If feature key is not provided, let user select one + if (!featureKey) { + try { + spinner = ora( + `Loading features for app ${chalk.cyan(app.name)}${baseUrlSuffix( + baseUrl, + )}...`, + ).start(); + + const featuresResponse = await listFeatures(appId, { + envId: production.id, + }); + + if (featuresResponse.data.length === 0) { + return handleError( + "No features found for this app.", + "Company Feature Access", + ); + } + + spinner.succeed( + `Loaded features for app ${chalk.cyan(app.name)}${baseUrlSuffix(baseUrl)}.`, + ); + + featureKey = await select({ + message: "Select a feature to manage access:", + choices: featuresResponse.data.map((feature) => ({ + name: `${feature.name} (${feature.key})`, + value: feature.key, + })), + }); + } catch (error) { + spinner?.fail("Loading features failed."); + return handleError(error, "Company Feature Access"); + } + } + + // Determine if enabling or disabling + const isEnabled = options.enable; + + try { + spinner = ora( + `${isEnabled ? "Enabling" : "Disabling"} feature ${chalk.cyan(featureKey)} for company ${chalk.cyan(companyId)}...`, + ).start(); + + const request: CompanyFeatureAccess = { + envId: production.id, + companyId, + featureKey, + isEnabled, + }; + + await companyFeatureAccess(appId, request); + + spinner.succeed( + `${isEnabled ? "Enabled" : "Disabled"} feature ${chalk.cyan(featureKey)} for company ${chalk.cyan(companyId)}.`, + ); + } catch (error) { + spinner?.fail(`Feature access update failed.`); + void handleError(error, "Company Feature Access"); + } +}; + +export function registerCompanyCommands(cli: Command) { + const companiesCommand = new Command("companies").description( + "Manage companies.", + ); + + const companyFeaturesCommand = new Command("features").description( + "Manage company features.", + ); + + companiesCommand + .command("list") + .description("List all companies.") + .addOption(appIdOption) + .addOption(companyFilterOption) + .action(listCompaniesAction); + + // Feature access command + companyFeaturesCommand + .command("access") + .description("Grant or revoke feature access for a specific company.") + .addOption(appIdOption) + .addArgument(companyIdArgument) + .addArgument( + new Argument( + "[featureKey]", + "Feature key. If not provided, you'll be prompted to select one", + ), + ) + .addOption(enableFeatureOption) + .addOption(disableFeatureOption) + .action(companyFeatureAccessAction); + + companiesCommand.addCommand(companyFeaturesCommand); + + // Update the config with the cli override values + companiesCommand.hook("preAction", (_, command) => { + const { appId } = command.opts(); + configStore.setConfig({ + appId, + }); + }); + + cli.addCommand(companiesCommand); +} diff --git a/packages/cli/commands/features.ts b/packages/cli/commands/features.ts index 8b22160d..5dd8288f 100644 --- a/packages/cli/commands/features.ts +++ b/packages/cli/commands/features.ts @@ -1,19 +1,23 @@ import { input } from "@inquirer/prompts"; import chalk from "chalk"; import { Command } from "commander"; -import { mkdir, writeFile } from "node:fs/promises"; -import { dirname, isAbsolute, join, relative } from "node:path"; +import { relative } from "node:path"; import ora, { Ora } from "ora"; -import { App, getApp, getOrg } from "../services/bootstrap.js"; +import { getApp, getOrg } from "../services/bootstrap.js"; import { createFeature, Feature, listFeatures } from "../services/features.js"; import { configStore } from "../stores/config.js"; -import { handleError, MissingAppIdError } from "../utils/errors.js"; +import { + handleError, + MissingAppIdError, + MissingEnvIdError, +} from "../utils/errors.js"; import { genFeatureKey, genTypes, indentLines, KeyFormatPatterns, + writeTypesToFile, } from "../utils/gen.js"; import { appIdOption, @@ -34,10 +38,15 @@ export const createFeatureAction = async ( ) => { const { baseUrl, appId } = configStore.getConfig(); let spinner: Ora | undefined; + + if (!appId) { + return handleError(new MissingAppIdError(), "Features Create"); + } + const app = getApp(appId); + const production = app.environments.find((e) => e.isProduction); + try { - if (!appId) throw new MissingAppIdError(); const org = getOrg(); - const app = getApp(appId); console.log( `Creating feature for app ${chalk.cyan(app.name)}${baseUrlSuffix(baseUrl)}.`, ); @@ -50,19 +59,19 @@ export const createFeatureAction = async ( if (!key) { const keyFormat = org.featureKeyFormat; + const keyValidator = KeyFormatPatterns[keyFormat]; key = await input({ message: "New feature key:", default: genFeatureKey(name, keyFormat), - validate: KeyFormatPatterns[keyFormat].validate, + validate: (str) => keyValidator.regex.test(str) || keyValidator.message, }); } spinner = ora(`Creating feature...`).start(); - const feature = await createFeature(appId, name, key); + const feature = await createFeature(appId, { name, key }); spinner.succeed( `Created feature ${chalk.cyan(feature.name)} with key ${chalk.cyan(feature.key)}:`, ); - const production = app.environments.find((e) => e.isProduction); if (production) { console.log( indentLines(chalk.magenta(featureUrl(baseUrl, production, feature))), @@ -78,18 +87,27 @@ export const listFeaturesAction = async () => { const { baseUrl, appId } = configStore.getConfig(); let spinner: Ora | undefined; + if (!appId) { + return handleError(new MissingAppIdError(), "Features Create"); + } + const app = getApp(appId); + const production = app.environments.find((e) => e.isProduction); + if (!production) { + return handleError(new MissingEnvIdError(), "Features Types"); + } + try { - if (!appId) throw new MissingAppIdError(); - const app = getApp(appId); spinner = ora( `Loading features of app ${chalk.cyan(app.name)}${baseUrlSuffix(baseUrl)}...`, ).start(); - const features = await listFeatures(appId); + const featuresResponse = await listFeatures(appId, { + envId: production.id, + }); spinner.succeed( `Loaded features of app ${chalk.cyan(app.name)}${baseUrlSuffix(baseUrl)}.`, ); console.table( - features.map(({ key, name, stage }) => ({ + featuresResponse.data.map(({ key, name, stage }) => ({ name, key, stage: stage?.name, @@ -107,16 +125,25 @@ export const generateTypesAction = async () => { let spinner: Ora | undefined; let features: Feature[] = []; - let app: App | undefined; + + if (!appId) { + return handleError(new MissingAppIdError(), "Features Types"); + } + + const app = getApp(appId); + const production = app.environments.find((e) => e.isProduction); + if (!production) { + return handleError(new MissingEnvIdError(), "Features Types"); + } + try { - if (!appId) throw new MissingAppIdError(); - app = getApp(appId); spinner = ora( `Loading features of app ${chalk.cyan(app.name)}${baseUrlSuffix(baseUrl)}...`, ).start(); features = await listFeatures(appId, { + envId: production.id, includeRemoteConfigs: true, - }); + }).then((res) => res.data); spinner.succeed( `Loaded features of app ${chalk.cyan(app.name)}${baseUrlSuffix(baseUrl)}.`, ); @@ -133,12 +160,7 @@ export const generateTypesAction = async () => { // Generate types for each output configuration for (const output of typesOutput) { const types = await genTypes(features, output.format); - const outPath = isAbsolute(output.path) - ? output.path - : join(projectPath, output.path); - - await mkdir(dirname(outPath), { recursive: true }); - await writeFile(outPath, types); + const outPath = await writeTypesToFile(types, output.path, projectPath); spinner.succeed( `Generated ${output.format} types in ${chalk.cyan(relative(projectPath, outPath))}.`, ); diff --git a/packages/cli/commands/mcp.ts b/packages/cli/commands/mcp.ts new file mode 100644 index 00000000..bc5b3b25 --- /dev/null +++ b/packages/cli/commands/mcp.ts @@ -0,0 +1,101 @@ +import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js"; +import chalk from "chalk"; +import { Command } from "commander"; +import express from "express"; +import { findUp } from "find-up"; +import { readFile } from "node:fs/promises"; +import ora, { Ora } from "ora"; + +import { registerMcpTools } from "../mcp/tools.js"; +import { handleError } from "../utils/errors.js"; +import { appIdOption } from "../utils/options.js"; + +type MCPArgs = { + port?: "auto" | number; + appId?: string; +}; + +export const mcpAction = async ({ appId, port = 8050 }: MCPArgs) => { + let spinner: Ora | undefined; + try { + const packageJSONPath = await findUp("package.json"); + if (!packageJSONPath) { + throw new Error("Unable to determine version using package.json"); + } + const { version } = JSON.parse( + (await readFile(packageJSONPath, "utf-8")) ?? "{}", + ); + if (!version) { + throw new Error("Unable to determine version using package.json"); + } + + // Create an MCP server + const mcp = new McpServer({ + name: "Bucket", + version: version, + }); + + const app = express(); + const transportMap = new Map(); + + app.get("/sse", async (_req, res) => { + const transport = new SSEServerTransport("/messages", res); + const sessionId = transport.sessionId; + + // Set the onclose handler to remove the transport from the transportMap + transport.onclose = () => { + transportMap.delete(sessionId); + console.log(`Transport ${sessionId} has been closed.`); + }; + + transportMap.set(sessionId, transport); + await mcp.connect(transport); + spinner?.succeed("Client connected to MCP server"); + }); + + app.post("/messages", async (req, res) => { + const sessionId = req.query.sessionId?.toString(); + if (!sessionId) { + res.status(400).json({ error: "SessionId is not found" }); + return; + } + + const transport = transportMap.get(sessionId); + if (!transport) { + res.redirect("/sse"); + return; + } + + await transport.handlePostMessage(req, res); + }); + + // Register tools and resources + //registerMcpResources(mcp); + await registerMcpTools(mcp, { appId }); + + const server = app.listen(port !== "auto" ? port : 0, () => { + // Get the port the server is listening on + const address = server.address(); + const assignedPort = + !!address && typeof address === "object" ? address.port : port; + console.log( + `\nMCP server listening at ${chalk.cyan(`http://localhost:${assignedPort}/sse`)}`, + ); + spinner = ora(`Waiting for connections...`).start(); + }); + } catch (error) { + spinner?.fail("MCP server failed to start"); + void handleError(error, "MCP"); + } +}; + +export function registerMcpCommand(cli: Command) { + cli + .command("mcp") + .description( + "Create an model context protocol (MCP) server between your AI assistant and the Bucket API (alpha).", + ) + .action(mcpAction) + .addOption(appIdOption); +} diff --git a/packages/cli/index.ts b/packages/cli/index.ts index 43569836..264645b6 100755 --- a/packages/cli/index.ts +++ b/packages/cli/index.ts @@ -1,11 +1,14 @@ #!/usr/bin/env node import chalk from "chalk"; import { program } from "commander"; +import ora from "ora"; import { registerAppCommands } from "./commands/apps.js"; import { registerAuthCommands } from "./commands/auth.js"; +import { registerCompanyCommands } from "./commands/companies.js"; import { registerFeatureCommands } from "./commands/features.js"; import { registerInitCommand } from "./commands/init.js"; +import { registerMcpCommand } from "./commands/mcp.js"; import { registerNewCommand } from "./commands/new.js"; import { bootstrap, getUser } from "./services/bootstrap.js"; import { authStore } from "./stores/auth.js"; @@ -42,22 +45,25 @@ async function main() { (cleanedBaseUrl && `${cleanedBaseUrl}/api`), }); + const spinner = ora("Bootstrapping...").start(); try { // Load bootstrap data if not already loaded await bootstrap(); + spinner.stop(); } catch (error) { + spinner.fail("Bootstrap failed."); void handleError( - debug ? error : `Unable to reach ${configStore.getConfig("baseUrl")}`, + debug ? error : `Unable to reach ${configStore.getConfig("baseUrl")}.`, "Connect", ); } if (debug) { - console.debug(chalk.cyan("\nDebug mode enabled")); + console.debug(chalk.cyan("\nDebug mode enabled.")); const user = getUser(); - console.debug(`Logged in as ${chalk.cyan(user.name ?? user.email)}`); + console.debug(`Logged in as ${chalk.cyan(user.name ?? user.email)}.`); console.debug( - "Reading config from", + "Reading config from:", chalk.cyan(configStore.getConfigPath()), ); console.table(configStore.getConfig()); @@ -70,6 +76,8 @@ async function main() { registerAuthCommands(program); registerAppCommands(program); registerFeatureCommands(program); + registerCompanyCommands(program); + registerMcpCommand(program); program.parse(process.argv); } diff --git a/packages/cli/mcp/resources.ts b/packages/cli/mcp/resources.ts new file mode 100644 index 00000000..613bb37d --- /dev/null +++ b/packages/cli/mcp/resources.ts @@ -0,0 +1,55 @@ +import { + McpServer, + ResourceTemplate, +} from "@modelcontextprotocol/sdk/server/mcp.js"; + +import { getApp } from "../services/bootstrap.js"; +import { getFeature, listFeatureNames } from "../services/features.js"; +import { configStore } from "../stores/config.js"; +import { MissingAppIdError, MissingEnvIdError } from "../utils/errors.js"; + +export function registerMcpResources(mcp: McpServer) { + const appId = configStore.getConfig("appId"); + if (!appId) { + throw new MissingAppIdError(); + } + const app = getApp(appId); + const production = app.environments.find((e) => e.isProduction); + if (!production) { + throw new MissingEnvIdError(); + } + + mcp.resource( + "feature", + new ResourceTemplate("features://{featureId}", { + list: async () => { + const response = await listFeatureNames(appId); + return { + resources: response.map(({ id, name }) => ({ + name, + uri: `features://${id}`, + description: `Feature ${name} of the app ${app.name}.`, + mimeType: "application/json", + })), + }; + }, + }), + { + description: "Returns a specific feature by ID.", + mimeType: "application/json", + }, + async (uri, { featureId }) => { + const data = await getFeature(appId, featureId.toString(), { + envId: production.id, + }); + return { + contents: [ + { + uri: uri.href, + text: JSON.stringify(data, null, 2), + }, + ], + }; + }, + ); +} diff --git a/packages/cli/mcp/tools.ts b/packages/cli/mcp/tools.ts new file mode 100644 index 00000000..152343e9 --- /dev/null +++ b/packages/cli/mcp/tools.ts @@ -0,0 +1,266 @@ +import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import { z } from "zod"; + +import { getApp, getOrg } from "../services/bootstrap.js"; +import { + CompaniesQuerySchema, + companyFeatureAccess, + CompanyFeatureAccessSchema, + listCompanies, +} from "../services/companies.js"; +import { + createFeature, + FeatureCreateSchema, + listFeatureNames, +} from "../services/features.js"; +import { FeedbackQuerySchema, listFeedback } from "../services/feedback.js"; +import { listStages, UpdateFeatureStage } from "../services/stages.js"; +import { configStore } from "../stores/config.js"; +import { + handleMcpError, + MissingAppIdError, + MissingEnvIdError, +} from "../utils/errors.js"; +import { KeyFormatPatterns } from "../utils/gen.js"; +import { featureUrl } from "../utils/path.js"; +import { + EnvironmentQuerySchema, + withDefaults, + withDescriptions, +} from "../utils/schemas.js"; + +export async function registerMcpTools( + mcp: McpServer, + { appId }: { appId?: string }, +) { + // const projectPath = configStore.getProjectPath(); + const { appId: configAppId, typesOutput: _ } = configStore.getConfig(); + appId = appId || configAppId; + if (!appId) { + throw new MissingAppIdError(); + } + const org = getOrg(); + const app = getApp(appId); + const production = app.environments.find((e) => e.isProduction); + if (!production) { + throw new MissingEnvIdError(); + } + + const stages = await listStages(appId); + + // Add features tool + mcp.tool( + "features", + "List all feature flags of the Bucket feature management service.", + async () => { + try { + const data = await listFeatureNames(appId); + return { + content: [ + { + type: "text", + text: ` +List of features. +>>> JSON Response >>> + ${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + return await handleMcpError(error); + } + }, + ); + + // Add feedback tool + mcp.tool( + "feedback", + "Get user feedback for the features of the Bucket feature management service.", + withDefaults(FeedbackQuerySchema, { + envId: production.id, + }).shape, + async (args) => { + try { + const data = await listFeedback(appId, args); + return { + content: [ + { + type: "text", + text: ` +Feedback is returned in a JSON format with pages. +Feedback score is between 1 and 5, with 0 being unknown. +>>> JSON Response >>> +${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + return await handleMcpError(error); + } + }, + ); + + // Add create feature tool + const keyFormatRules = KeyFormatPatterns[org.featureKeyFormat].message; + mcp.tool( + "featureCreate", + "Creates a new feature flag of the Bucket feature management service.", + withDescriptions(FeatureCreateSchema, { + key: `Feature key specified in ${org.featureKeyFormat} format:\n${keyFormatRules}`, + }).shape, + async (args) => { + try { + const feature = await createFeature(appId, args); + + const featureLink = featureUrl( + configStore.getConfig("baseUrl"), + production, + feature, + ); + return { + content: [ + { + type: "text", + text: `Feature created successfully. See it [on Bucket here](${featureLink}). Before moving on we need to generate the refreshed types to avoid linting errors. Run the Bucket CLI in a terminal: +\`shell +$ npx bucket features types +\` + +After that we can feature flag some code. Use the following pattern for React: + +\`\`\`typescript +import { useFeature } from "@bucketco/react-sdk"; +function MyComponent() { + const { isEnabled } = useFeatureFlag("${feature.key}"); + if (!isEnabled) { + // feature is disabled + return null; + } + return
Feature is disabled.
; +} +\`\`\` + +To track feature usage, call the \`track\` method on usage: + +\`\`\`typescript +import { useFeature } from "@bucketco/react-sdk"; + +function MyComponent() { + const { isEnabled } = useFeatureFlag("${feature.key}"); + if (!isEnabled) { + // feature is disabled + return null; + } + return ; +} +\`\`\` +`, + }, + ], + }; + } catch (error) { + return await handleMcpError(error); + } + }, + ); + + // Add companies tool + mcp.tool( + "companies", + "List of companies of the Bucket feature management service.", + withDefaults(CompaniesQuerySchema, { + envId: production.id, + }).shape, + async (args) => { + try { + const data = await listCompanies(appId, args); + return { + content: [ + { + type: "text", + text: ` +List of companies. +>>> JSON Response >>> +${JSON.stringify(data, null, 2)}`, + }, + ], + }; + } catch (error) { + return await handleMcpError(error); + } + }, + ); + + // Add company feature access tool + mcp.tool( + "companyFeatureAccess", + "Grant or revoke feature access for a specific company of the Bucket feature management service.", + withDefaults(CompanyFeatureAccessSchema, { + envId: production.id, + }).shape, + async (args) => { + try { + await companyFeatureAccess(appId, args); + return { + content: [ + { + type: "text", + text: `${args.isEnabled ? "Granted" : "Revoked"} access to feature '${args.featureKey}' for company ID '${args.companyId}'.`, + }, + ], + }; + } catch (error) { + return await handleMcpError(error); + } + }, + ); + + mcp.tool( + "updateFeatureStage", + "Update feature stage.", + withDefaults( + EnvironmentQuerySchema.extend({ + featureId: z.string(), + stageName: z + .enum(stages.map((s) => s.name) as [string, ...string[]]) + .describe( + "The name of the stage. Must be one of the following: " + + stages.map((s) => s.name).join(", "), + ), + targeting: z + .enum(["none", "some", "everyone"]) + .describe("The overarching targeting mode for the feature."), + changeDescription: z.string().describe("The reason for the change"), + }), + { + envId: production.id, + }, + ).shape, + async (args) => { + const stage = stages.find((s) => s.name === args.stageName); + if (!stage) { + throw new Error(`Stage '${args.stageName}' not found.`); + } + + try { + const { feature } = await UpdateFeatureStage(appId, { + featureId: args.featureId, + stageId: stage.id, + targetingMode: args.targeting, + envId: args.envId, + changeDescription: args.changeDescription, + }); + return { + content: [ + { + type: "text", + text: `Updated flag targeting for feature '${feature.key}'.`, + }, + ], + }; + } catch (error) { + return await handleMcpError(error); + } + }, + ); +} diff --git a/packages/cli/package.json b/packages/cli/package.json index a89bf006..0fb78100 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@bucketco/cli", - "version": "0.2.4", + "version": "0.4.0", "packageManager": "yarn@4.1.1", "description": "CLI for Bucket service", "main": "./dist/index.js", @@ -31,6 +31,7 @@ "scripts": { "build": "tsc && shx chmod +x dist/index.js", "bucket": "yarn build && ./dist/index.js", + "mcp:inspector": "SERVER_PORT=8051 npx @modelcontextprotocol/inspector", "test": "vitest -c vite.config.js", "test:ci": "vitest run -c vite.config.js --reporter=default --reporter=junit --outputFile=junit.xml", "coverage": "vitest run --coverage", @@ -42,20 +43,25 @@ }, "dependencies": { "@inquirer/prompts": "^5.3.8", + "@modelcontextprotocol/sdk": "^1.7.0", "ajv": "^8.17.1", "chalk": "^5.3.0", "change-case": "^5.4.4", "commander": "^12.1.0", + "express": "^4.21.2", "fast-deep-equal": "^3.1.3", "find-up": "^7.0.0", "json5": "^2.2.3", "open": "^10.1.0", "ora": "^8.1.0", - "slug": "^10.0.0" + "slug": "^10.0.0", + "zod": "^3.24.2" }, "devDependencies": { "@bucketco/eslint-config": "workspace:^", "@bucketco/tsconfig": "workspace:^", + "@modelcontextprotocol/inspector": "^0.6.0", + "@types/express": "^5.0.0", "@types/node": "^22.5.1", "@types/slug": "^5.0.9", "eslint": "^9.21.0", diff --git a/packages/cli/services/companies.ts b/packages/cli/services/companies.ts new file mode 100644 index 00000000..47ffe827 --- /dev/null +++ b/packages/cli/services/companies.ts @@ -0,0 +1,108 @@ +import { z } from "zod"; + +import { authRequest } from "../utils/auth.js"; +import { + booleanish, + EnvironmentQuerySchema, + PaginationQueryBaseSchema, +} from "../utils/schemas.js"; +import { + FunnelStep, + PaginatedResponse, + SatisfactionScore, +} from "../utils/types.js"; + +export type FeatureMetric = { + funnelStep: FunnelStep | null; + eventCount: number; + firstUsed: string | null; + lastUsed: string | null; + frequency: number | null; + satisfaction: SatisfactionScore; +}; + +export type CompanyName = { + id: string; + name: string | null; + avatarUrl: string | null; +}; + +export type Company = CompanyName & { + firstSeen: string | null; + lastSeen: string | null; + userCount: number; + eventCount: number; + feedbackCount: number; + attributes: Record; + featureMetrics: Record; +}; + +export type CompaniesResponse = PaginatedResponse; + +export const CompaniesSortByColumns = [ + "name", + "id", + "firstSeen", + "lastSeen", + "feedbackCount", + "userCount", +] as const; + +export const CompaniesSortBySchema = z + .enum(CompaniesSortByColumns) + .describe("Column to sort companies by"); + +export const CompaniesQuerySchema = EnvironmentQuerySchema.merge( + PaginationQueryBaseSchema(), +) + .extend({ + sortBy: CompaniesSortBySchema.default("name"), + idNameFilter: z.string().optional(), + }) + .strict(); + +export type CompaniesQuery = z.input; + +export async function listCompanies( + appId: string, + query: CompaniesQuery, +): Promise { + const { envId, ...body } = CompaniesQuerySchema.parse(query); + return authRequest(`/apps/${appId}/companies/search`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + params: { + envId, + }, + body: JSON.stringify(body), + }); +} + +export const CompanyFeatureAccessSchema = EnvironmentQuerySchema.extend({ + companyId: z.string().length(14).describe("Company ID"), + featureKey: z.string().describe("Feature key"), + isEnabled: booleanish.describe( + "Set feature to enabled or disabled for the company.", + ), +}).strict(); + +export type CompanyFeatureAccess = z.input; + +export async function companyFeatureAccess( + appId: string, + query: CompanyFeatureAccess, +): Promise { + const { envId, companyId, ...body } = CompanyFeatureAccessSchema.parse(query); + return authRequest(`/apps/${appId}/companies/${companyId}/features`, { + method: "PATCH", + params: { + envId, + }, + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ features: [body] }), + }); +} diff --git a/packages/cli/services/features.ts b/packages/cli/services/features.ts index 1096b8ba..53c90a86 100644 --- a/packages/cli/services/features.ts +++ b/packages/cli/services/features.ts @@ -1,7 +1,18 @@ +import { z } from "zod"; + import { authRequest } from "../utils/auth.js"; +import { + booleanish, + EnvironmentQuery, + EnvironmentQuerySchema, + sortTypeSchema, +} from "../utils/schemas.js"; +import { PaginatedResponse } from "../utils/types.js"; import { Stage } from "./stages.js"; +export type FeatureSourceType = "event" | "attribute"; + export type RemoteConfigVariant = { key?: string; payload?: any; @@ -15,53 +26,127 @@ export type RemoteConfig = { ]; }; -export type Feature = { +export type FeatureName = { id: string; name: string; key: string; - remoteConfigs: RemoteConfig[]; - stage: Stage | null; + source: FeatureSourceType; + parentFeatureId: string | null; }; -export type FeaturesResponse = { - data: Feature[]; +export type Flag = { + id: string; + currentVersions: { + id: string; + environment: { + id: string; + }; + targetingMode: string; + segmentIds: string[]; + companyIds: string[]; + userIds: string[]; + customRules: any; + }[]; }; -export type ListOptions = { - includeRemoteConfigs?: boolean; +export type Feature = FeatureName & { + description: string | null; + remoteConfigs: RemoteConfig[]; + stage: Stage | null; + flagId: string | null; }; -export async function listFeatures( - appId: string, - options: ListOptions = {}, -): Promise { +export type FeaturesResponse = PaginatedResponse; + +export const FeaturesQuerySchema = EnvironmentQuerySchema.extend({ + sortBy: z.string().default("key").describe("Field to sort features by"), + sortOrder: z + .enum(["asc", "desc"]) + .default("asc") + .describe("Sort direction (ascending or descending)"), + sortType: sortTypeSchema + .default("flat") + .describe("Type of sorting to apply (flat or hierarchical)"), + includeFeatureMetrics: booleanish + .default(false) + .describe("Include metrics data with features"), + includeRolloutStatus: booleanish + .default(false) + .describe("Include rollout status information"), + includeGoals: booleanish.default(false).describe("Include associated goals"), + includeProductionEstimatedTargetAudience: booleanish + .default(false) + .describe("Include estimated production target audience data"), + includeRemoteConfigs: booleanish + .default(false) + .describe("Include remote configuration data"), + useTargetingRules: booleanish.default(true).describe("Apply targeting rules"), +}).strict(); + +export type FeaturesQuery = z.input; + +export const FeatureCreateSchema = z + .object({ + name: z + .string() + .min(1, "Feature name is required") + .describe("Name of the feature"), + key: z + .string() + .min(1, "Feature key is required") + .describe("Unique identifier key for the feature"), + description: z + .string() + .optional() + .describe("Optional description of the feature"), + }) + .strict(); + +export type FeatureCreate = z.input; + +export async function listFeatures(appId: string, query: FeaturesQuery) { return authRequest(`/apps/${appId}/features`, { - params: { - sortBy: "key", - sortOrder: "asc", - includeRemoteConfigs: options.includeRemoteConfigs ? "true" : "false", - }, - }).then(({ data }) => data); + params: FeaturesQuerySchema.parse(query), + }); +} + +export async function listFeatureNames(appId: string) { + return authRequest(`/apps/${appId}/features/names`); } type FeatureResponse = { feature: Feature; }; -export async function createFeature( +export async function getFeature( appId: string, - name: string, - key: string, -): Promise { + featureId: string, + query: EnvironmentQuery, +) { + return authRequest(`/apps/${appId}/features/${featureId}`, { + params: EnvironmentQuerySchema.parse(query), + }).then(({ feature }) => feature); +} + +export async function getFlag( + appId: string, + flagId: string, + query: EnvironmentQuery, +) { + return await authRequest(`/apps/${appId}/flags/${flagId}`, { + params: EnvironmentQuerySchema.parse(query), + }); +} + +export async function createFeature(appId: string, featureData: FeatureCreate) { return authRequest(`/apps/${appId}/features`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ - name, - key, source: "event", + ...FeatureCreateSchema.parse(featureData), }), }).then(({ feature }) => feature); } diff --git a/packages/cli/services/feedback.ts b/packages/cli/services/feedback.ts new file mode 100644 index 00000000..586edfa4 --- /dev/null +++ b/packages/cli/services/feedback.ts @@ -0,0 +1,103 @@ +import { z } from "zod"; + +import { authRequest } from "../utils/auth.js"; +import { + EnvironmentQuerySchema, + ExternalIdSchema, + PaginationQueryBaseSchema, +} from "../utils/schemas.js"; +import { + FeedbackSource, + FunnelStep, + FunnelStepList, + PaginatedResponse, + SatisfactionScore, +} from "../utils/types.js"; + +export type Feedback = { + id: string; + companyId: string | null; + companyName: string | null; + companyAvatarUrl: string | null; + companyFunnelStep: FunnelStep | null; + featureId: string; + featureName: string | null; + userId: string | null; + userName: string | null; + userEmail: string | null; + userAvatarUrl: string | null; + question: string | null; + score: SatisfactionScore; + comment: string | null; + source: FeedbackSource | null; + timestamp: string; + updatedAt: string; +}; + +export type FeedbackResponse = PaginatedResponse; + +export const SatisfactionScoreFilterSchema = z.coerce + .number() + .int() + .gte(0) + .lte(5) + .array() + .describe("Array of satisfaction scores (0-5)"); + +export const FeedbackListSortByColumns = [ + "score", + "comment", + "userName", + "userEmail", + "companyName", + "companyFunnelStep", + "timestamp", +] as const; + +export const FeedbackListSortBySchema = z + .enum(FeedbackListSortByColumns) + .describe("Column to sort feedback by"); +export type FeedbackListSortBy = z.infer; + +export const FeedbackQuerySchema = EnvironmentQuerySchema.merge( + PaginationQueryBaseSchema({ + sortOrder: "desc", + }), +) + .extend({ + sortBy: FeedbackListSortBySchema.default("timestamp").describe( + "Field to sort feedback by", + ), + satisfaction: SatisfactionScoreFilterSchema.optional() + .default([0, 1, 2, 3, 4, 5]) + .describe("Filter by satisfaction scores (0-5)"), + featureId: z + .string() + .length(14) + .optional() + .describe("Filter by feature ID"), + companyId: ExternalIdSchema.optional().describe("Filter by company ID"), + funnelSteps: z + .enum(FunnelStepList) + .array() + .optional() + .default(["company", "segment", "tried", "adopted", "retained"]) + .describe("Filter by funnel steps"), + segmentId: z + .string() + .length(14) + .optional() + .describe("Filter by segment ID"), + }) + .strict(); + +export type FeedbackQuery = z.input; + +export async function listFeedback( + appId: string, + query: FeedbackQuery, +): Promise { + return authRequest(`/apps/${appId}/feedback`, { + params: FeedbackQuerySchema.parse(query), + }); +} diff --git a/packages/cli/services/stages.ts b/packages/cli/services/stages.ts index 381df957..ce04b414 100644 --- a/packages/cli/services/stages.ts +++ b/packages/cli/services/stages.ts @@ -1,5 +1,9 @@ +import { z } from "zod"; + import { authRequest } from "../utils/auth.js"; +import { getFeature, getFlag } from "./features.js"; + export type Stage = { id: string; name: string; @@ -14,3 +18,80 @@ export async function listStages(appId: string): Promise { const response = await authRequest(`/apps/${appId}/stages`); return response.stages; } + +export const FeatureTargetingModes = ["none", "some", "everyone"] as const; +export type FeatureTargetingMode = (typeof FeatureTargetingModes)[number]; +export const UpdateFeatureStageSchema = z.object({ + featureKey: z.string(), + targetingMode: z.enum(FeatureTargetingModes).optional(), +}); + +export type UpdateFeatureStageArgs = { + stageId: string; + changeDescription: string; + targetingMode: FeatureTargetingMode; + featureId: string; + envId: string; +}; + +export async function UpdateFeatureStage( + appId: string, + { + stageId, + targetingMode, + featureId, + envId, + changeDescription, + }: UpdateFeatureStageArgs, +) { + const feature = await getFeature(appId, featureId, { + envId, + }); + + if (!feature) { + throw new Error(`Feature not found for ID ${featureId}`); + } + + const flag = await getFlag(appId, feature.flagId!, { + envId, + }); + + const currFlagVersion = flag.currentVersions; + const envFlagVersion = currFlagVersion.find( + (v) => v.environment.id === envId, + ); + if (!envFlagVersion) { + throw new Error(`Flag version not found for environment ${envId}`); + } + envFlagVersion.targetingMode = targetingMode; + const body = { + stageId, + changeDescription, + versions: [ + { + environmentId: envId, + targetingMode: envFlagVersion.targetingMode, + segmentIds: envFlagVersion.segmentIds, + companyIds: envFlagVersion.companyIds, + userIds: envFlagVersion.userIds, + customRules: envFlagVersion.customRules, + }, + ], + }; + + await authRequest(`/apps/${appId}/flags/${flag.id}/versions`, { + method: "POST", + params: { + envId, + "currentVersionIds[]": flag.currentVersions.map((v) => v.id), + }, + + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(body), + }); + return { + feature, + }; +} diff --git a/packages/cli/utils/auth.ts b/packages/cli/utils/auth.ts index be81d123..ab94c337 100644 --- a/packages/cli/utils/auth.ts +++ b/packages/cli/utils/auth.ts @@ -7,6 +7,7 @@ import { authStore } from "../stores/auth.js"; import { configStore } from "../stores/config.js"; import { errorUrl, loginUrl, successUrl } from "./path.js"; +import { ParamType } from "./types.js"; interface waitForAccessToken { accessToken: string; @@ -122,7 +123,7 @@ export async function waitForAccessToken(baseUrl: string, apiUrl: string) { export async function authRequest>( url: string, options?: RequestInit & { - params?: Record; + params?: Record; }, retryCount = 0, ): Promise { @@ -137,7 +138,13 @@ export async function authRequest>( const resolvedUrl = new URL(`${apiUrl}/${url}`); if (options?.params) { Object.entries(options.params).forEach(([key, value]) => { - resolvedUrl.searchParams.append(key, value); + if (value !== null && value !== undefined) { + if (Array.isArray(value)) { + value.forEach((v) => resolvedUrl.searchParams.append(key, String(v))); + } else { + resolvedUrl.searchParams.set(key, String(value)); + } + } }); } diff --git a/packages/cli/utils/errors.ts b/packages/cli/utils/errors.ts index e7b9340e..f3799a15 100644 --- a/packages/cli/utils/errors.ts +++ b/packages/cli/utils/errors.ts @@ -11,6 +11,13 @@ export class MissingAppIdError extends Error { } } +export class MissingEnvIdError extends Error { + constructor() { + super("Environment ID is required."); + this.name = "MissingEnvIdError"; + } +} + export class ConfigValidationError extends Error { constructor(errors?: ErrorObject[] | null) { const messages = errors @@ -55,3 +62,43 @@ export async function handleError(error: unknown, tag: string) { } process.exit(1); } + +export async function handleMcpError(error: unknown): Promise<{ + isError: true; + content: Array<{ type: "text"; text: string }>; +}> { + let errorMessage: string; + + if (error instanceof Response) { + try { + const data = await error.json(); + errorMessage = data.error?.message ?? data.error?.code ?? "API Error"; + + if (data.validationErrors) { + const validationDetails = data.validationErrors + .map( + ({ path, message }: { path: string[]; message: string }) => + `- ${path.join(".")}: ${message}`, + ) + .join("\n"); + errorMessage += "\nValidation Errors:\n" + validationDetails; + } + } catch { + errorMessage = `API Error: ${error.statusText} (${error.status})`; + } + } else if (error instanceof Error) { + errorMessage = error.message; + if (error.cause) { + errorMessage += `\nCause: ${JSON.stringify(error.cause)}`; + } + } else if (typeof error === "string") { + errorMessage = error; + } else { + errorMessage = "An unknown error occurred: " + JSON.stringify(error); + } + + return { + isError: true, + content: [{ type: "text", text: errorMessage }], + }; +} diff --git a/packages/cli/utils/gen.ts b/packages/cli/utils/gen.ts index d02f21ce..67dbd015 100644 --- a/packages/cli/utils/gen.ts +++ b/packages/cli/utils/gen.ts @@ -1,4 +1,6 @@ import { camelCase, kebabCase, pascalCase, snakeCase } from "change-case"; +import { mkdir, writeFile } from "node:fs/promises"; +import { dirname, isAbsolute, join } from "node:path"; import { Feature, RemoteConfig } from "../services/features.js"; @@ -21,51 +23,48 @@ export type KeyFormat = (typeof KeyFormats)[number]; type KeyFormatPattern = { transform: (key: string) => string; - validate: (key: string) => true | string; + regex: RegExp; + message: string; }; export const KeyFormatPatterns: Record = { custom: { transform: (key) => key?.trim(), - validate: (key) => - /^[\p{L}\p{N}\p{P}\p{S}\p{Z}]+$/u.test(key) || - "Key must contain only letters, numbers, punctuation, symbols, or spaces", + regex: /^[\p{L}\p{N}\p{P}\p{S}\p{Z}]+$/u, + message: + "Key must contain only letters, numbers, punctuation, symbols, or spaces.", }, pascalCase: { transform: (key) => pascalCase(key), - validate: (key) => - /^[\p{Lu}][\p{L}\p{N}]*$/u.test(key) || - "Key must start with uppercase letter and contain only letters and numbers", + regex: /^[\p{Lu}][\p{L}\p{N}]*$/u, + message: + "Key must start with uppercase letter and contain only letters and numbers.", }, camelCase: { transform: (key) => camelCase(key), - validate: (key) => - /^[\p{Ll}][\p{L}\p{N}]*$/u.test(key) || - "Key must start with lowercase letter and contain only letters and numbers", + regex: /^[\p{Ll}][\p{L}\p{N}]*$/u, + message: + "Key must start with lowercase letter and contain only letters and numbers.", }, snakeCaseUpper: { transform: (key) => snakeCase(key).toUpperCase(), - validate: (key) => - /^[\p{Lu}][\p{Lu}\p{N}]*(?:_[\p{Lu}\p{N}]+)*$/u.test(key) || - "Key must be uppercase with words separated by underscores", + regex: /^[\p{Lu}][\p{Lu}\p{N}]*(?:_[\p{Lu}\p{N}]+)*$/u, + message: "Key must be uppercase with words separated by underscores.", }, snakeCaseLower: { transform: (key) => snakeCase(key).toLowerCase(), - validate: (key) => - /^[\p{Ll}][\p{Ll}\p{N}]*(?:_[\p{Ll}\p{N}]+)*$/u.test(key) || - "Key must be lowercase with words separated by underscores", + regex: /^[\p{Ll}][\p{Ll}\p{N}]*(?:_[\p{Ll}\p{N}]+)*$/u, + message: "Key must be lowercase with words separated by underscores.", }, kebabCaseUpper: { transform: (key) => kebabCase(key).toUpperCase(), - validate: (key) => - /^[\p{Lu}][\p{Lu}\p{N}]*(?:-[\p{Lu}\p{N}]+)*$/u.test(key) || - "Key must be uppercase with words separated by hyphens", + regex: /^[\p{Lu}][\p{Lu}\p{N}]*(?:-[\p{Lu}\p{N}]+)*$/u, + message: "Key must be uppercase with words separated by hyphens.", }, kebabCaseLower: { transform: (key) => kebabCase(key).toLowerCase(), - validate: (key) => - /^[\p{Ll}][\p{Ll}\p{N}]*(?:-[\p{Ll}\p{N}]+)*$/u.test(key) || - "Key must be lowercase with words separated by hyphens", + regex: /^[\p{Ll}][\p{Ll}\p{N}]*(?:-[\p{Ll}\p{N}]+)*$/u, + message: "Key must be lowercase with words separated by hyphens.", }, }; @@ -73,7 +72,7 @@ export function indentLines(str: string, indent = 2, lineBreak = "\n"): string { const indentStr = " ".repeat(indent); return str .split(lineBreak) - .map((line) => `${indentStr}${line}`) + .map((line) => `${indentStr}${line.trim()}`) .join(lineBreak); } @@ -125,3 +124,16 @@ ${Array.from(configDefs.values()) } `.trim(); } + +export async function writeTypesToFile( + types: string, + outPath: string, + projectPath: string, +) { + const fullPath = isAbsolute(outPath) ? outPath : join(projectPath, outPath); + + await mkdir(dirname(fullPath), { recursive: true }); + await writeFile(fullPath, types); + + return fullPath; +} diff --git a/packages/cli/utils/options.ts b/packages/cli/utils/options.ts index 912b9459..76bf58c7 100644 --- a/packages/cli/utils/options.ts +++ b/packages/cli/utils/options.ts @@ -34,9 +34,39 @@ export const typesFormatOption = new Option( "Single output format for generated feature types", ).choices(["react", "node"]); +export const featureNameArgument = new Argument( + "[name]", + "Feature's name. If not provided, you'll be prompted to enter one.", +); + export const featureKeyOption = new Option( "-k, --key [feature key]", "Feature key. If not provided, a key is generated from the feature's name.", ); -export const featureNameArgument = new Argument("[name]", "Feature's name."); +export const mcpPortOption = new Option( + "-p, --port [port]", + "Port for the MCP server to listen on.", +).default(8050); + +// Company related options +export const companyFilterOption = new Option( + "-f, --filter [name]", + "Filter companies by name or ID", +); + +export const companyIdArgument = new Argument("", "Company ID"); +export const featureKeyArgument = new Argument( + "[featureKey]", + "Feature key. If not provided, you'll be prompted to select one.", +); + +export const enableFeatureOption = new Option( + "--enable", + "Enable the feature for this company", +); + +export const disableFeatureOption = new Option( + "--disable", + "Disable the feature for this company", +); diff --git a/packages/cli/utils/schemas.ts b/packages/cli/utils/schemas.ts new file mode 100644 index 00000000..6cfb815a --- /dev/null +++ b/packages/cli/utils/schemas.ts @@ -0,0 +1,113 @@ +import { z } from "zod"; + +export const sortTypeSchema = z + .enum(["flat", "hierarchical"]) + .describe("Type of sorting to apply"); + +export const booleanish = z.preprocess((value) => { + if (typeof value === "string") { + return value === "true" || value === "1"; + } + return Boolean(value); +}, z.boolean().describe("Boolean value that can be parsed from strings like 'true' or '1'")) as z.ZodEffects< + z.ZodBoolean, + boolean, + boolean +>; + +export const PaginationQueryBaseSchema = ( + { + sortOrder = "asc", + pageIndex = 0, + pageSize = 20, + }: { + sortOrder?: "asc" | "desc"; + pageIndex?: number; + pageSize?: number; + } = { + sortOrder: "asc", + pageIndex: 0, + pageSize: 20, + }, +) => + z.object({ + sortOrder: z + .enum(["asc", "desc"]) + .default(sortOrder) + .describe("Sort direction (ascending or descending)"), + pageIndex: z.coerce + .number() + .int() + .nonnegative() + .default(pageIndex) + .describe("Zero-based page index"), + pageSize: z.coerce + .number() + .int() + .nonnegative() + .min(1) + .max(100) + .default(pageSize) + .describe("Number of items per page (1-100)"), + }); + +export const EnvironmentQuerySchema = z + .object({ + envId: z.string().min(1).describe("Environment identifier"), + }) + .strict(); +export type EnvironmentQuery = z.infer; + +export const ExternalIdSchema = z + .string() + .nonempty() + .max(256) + .describe("External identifier, non-empty string up to 256 characters"); + +export const withDefaults = ( + schema: z.ZodObject, + defaults: Partial>>, +): z.ZodObject => { + const entries = Object.entries(schema.shape); + + const newShape = entries.reduce( + (acc, [key, value]) => { + const defaultValue = defaults[key]; + + if (defaultValue !== undefined && value instanceof z.ZodType) { + acc[key] = value.default(defaultValue); + } else { + acc[key] = value; + } + + return acc; + }, + {} as Record, + ); + + return z.object(newShape as T); +}; + +export const withDescriptions = ( + schema: z.ZodObject, + descriptions: Partial>, +): z.ZodObject => { + const entries = Object.entries(schema.shape); + + const newShape = entries.reduce( + (acc, [key, value]) => { + const description = descriptions[key as keyof T]; + + if (description !== undefined && value instanceof z.ZodType) { + acc[key] = value.describe(description); + } else { + acc[key] = value; + } + + return acc; + }, + {} as Record, + ); + + return z.object(newShape as T); +}; diff --git a/packages/cli/utils/types.ts b/packages/cli/utils/types.ts new file mode 100644 index 00000000..001050f7 --- /dev/null +++ b/packages/cli/utils/types.ts @@ -0,0 +1,25 @@ +export const FunnelStepList = [ + "company", + "segment", + "tried", + "adopted", + "retained", +] as const; + +export type FunnelStep = (typeof FunnelStepList)[number]; + +export type FeedbackSource = "api" | "manual" | "prompt" | "sdk" | "widget"; + +export type SatisfactionScore = 0 | 1 | 2 | 3 | 4 | 5; + +export type ParamType = string | number | boolean | Date; + +export type PaginatedResponse = { + data: T[]; + metadata: Record; + totalCount: number; + pageIndex: number; + pageSize: number; + sortBy: string; + sortOrder: string; +}; diff --git a/yarn.lock b/yarn.lock index 50f1e403..3101669f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -498,6 +498,9 @@ __metadata: "@bucketco/eslint-config": "workspace:^" "@bucketco/tsconfig": "workspace:^" "@inquirer/prompts": "npm:^5.3.8" + "@modelcontextprotocol/inspector": "npm:^0.6.0" + "@modelcontextprotocol/sdk": "npm:^1.7.0" + "@types/express": "npm:^5.0.0" "@types/node": "npm:^22.5.1" "@types/slug": "npm:^5.0.9" ajv: "npm:^8.17.1" @@ -505,6 +508,7 @@ __metadata: change-case: "npm:^5.4.4" commander: "npm:^12.1.0" eslint: "npm:^9.21.0" + express: "npm:^4.21.2" fast-deep-equal: "npm:^3.1.3" find-up: "npm:^7.0.0" json5: "npm:^2.2.3" @@ -515,6 +519,7 @@ __metadata: slug: "npm:^10.0.0" typescript: "npm:^5.5.4" vitest: "npm:^3.0.8" + zod: "npm:^3.24.2" bin: bucket: ./dist/index.js languageName: unknown @@ -1602,6 +1607,16 @@ __metadata: languageName: node linkType: hard +"@floating-ui/dom@npm:^1.0.0": + version: 1.6.13 + resolution: "@floating-ui/dom@npm:1.6.13" + dependencies: + "@floating-ui/core": "npm:^1.6.0" + "@floating-ui/utils": "npm:^0.2.9" + checksum: 10c0/272242d2eb6238ffcee0cb1f3c66e0eafae804d5d7b449db5ecf904bc37d31ad96cf575a9e650b93c1190f64f49a684b1559d10e05ed3ec210628b19116991a9 + languageName: node + linkType: hard + "@floating-ui/dom@npm:^1.6.8": version: 1.6.8 resolution: "@floating-ui/dom@npm:1.6.8" @@ -1612,6 +1627,18 @@ __metadata: languageName: node linkType: hard +"@floating-ui/react-dom@npm:^2.0.0": + version: 2.1.2 + resolution: "@floating-ui/react-dom@npm:2.1.2" + dependencies: + "@floating-ui/dom": "npm:^1.0.0" + peerDependencies: + react: ">=16.8.0" + react-dom: ">=16.8.0" + checksum: 10c0/e855131c74e68cab505f7f44f92cd4e2efab1c125796db3116c54c0859323adae4bf697bf292ee83ac77b9335a41ad67852193d7aeace90aa2e1c4a640cafa60 + languageName: node + linkType: hard + "@floating-ui/utils@npm:^0.2.5": version: 0.2.5 resolution: "@floating-ui/utils@npm:0.2.5" @@ -1619,6 +1646,13 @@ __metadata: languageName: node linkType: hard +"@floating-ui/utils@npm:^0.2.9": + version: 0.2.9 + resolution: "@floating-ui/utils@npm:0.2.9" + checksum: 10c0/48bbed10f91cb7863a796cc0d0e917c78d11aeb89f98d03fc38d79e7eb792224a79f538ed8a2d5d5584511d4ca6354ef35f1712659fd569868e342df4398ad6f + languageName: node + linkType: hard + "@gerrit0/mini-shiki@npm:^1.24.0": version: 1.24.4 resolution: "@gerrit0/mini-shiki@npm:1.24.4" @@ -2205,6 +2239,105 @@ __metadata: languageName: node linkType: hard +"@modelcontextprotocol/inspector-client@npm:^0.6.0": + version: 0.6.0 + resolution: "@modelcontextprotocol/inspector-client@npm:0.6.0" + dependencies: + "@modelcontextprotocol/sdk": "npm:^1.6.1" + "@radix-ui/react-checkbox": "npm:^1.1.4" + "@radix-ui/react-dialog": "npm:^1.1.3" + "@radix-ui/react-icons": "npm:^1.3.0" + "@radix-ui/react-label": "npm:^2.1.0" + "@radix-ui/react-popover": "npm:^1.1.3" + "@radix-ui/react-select": "npm:^2.1.2" + "@radix-ui/react-slot": "npm:^1.1.0" + "@radix-ui/react-tabs": "npm:^1.1.1" + "@types/prismjs": "npm:^1.26.5" + class-variance-authority: "npm:^0.7.0" + clsx: "npm:^2.1.1" + cmdk: "npm:^1.0.4" + lucide-react: "npm:^0.447.0" + pkce-challenge: "npm:^4.1.0" + prismjs: "npm:^1.29.0" + react: "npm:^18.3.1" + react-dom: "npm:^18.3.1" + react-simple-code-editor: "npm:^0.14.1" + react-toastify: "npm:^10.0.6" + serve-handler: "npm:^6.1.6" + tailwind-merge: "npm:^2.5.3" + tailwindcss-animate: "npm:^1.0.7" + zod: "npm:^3.23.8" + bin: + mcp-inspector-client: bin/cli.js + checksum: 10c0/1912cb9e31b1047b1d70122e93497eb3032bbe0e31789993a0fa56df0ad9746208928aa94f692840a23de85627c4704e245de9baf44bf6d549cc1ea4f67ab9f3 + languageName: node + linkType: hard + +"@modelcontextprotocol/inspector-server@npm:^0.6.0": + version: 0.6.0 + resolution: "@modelcontextprotocol/inspector-server@npm:0.6.0" + dependencies: + "@modelcontextprotocol/sdk": "npm:^1.6.1" + cors: "npm:^2.8.5" + express: "npm:^4.21.0" + ws: "npm:^8.18.0" + zod: "npm:^3.23.8" + bin: + mcp-inspector-server: build/index.js + checksum: 10c0/69557e9f65a5b38339c173cae825868c6fdee41c17040cffd2421d1d6517619af4f0def3373285ec38a8a182b355431867a385f5bb0e4aa34a983646b6d1ccbc + languageName: node + linkType: hard + +"@modelcontextprotocol/inspector@npm:^0.6.0": + version: 0.6.0 + resolution: "@modelcontextprotocol/inspector@npm:0.6.0" + dependencies: + "@modelcontextprotocol/inspector-client": "npm:^0.6.0" + "@modelcontextprotocol/inspector-server": "npm:^0.6.0" + concurrently: "npm:^9.0.1" + shell-quote: "npm:^1.8.2" + spawn-rx: "npm:^5.1.2" + ts-node: "npm:^10.9.2" + bin: + mcp-inspector: bin/cli.js + checksum: 10c0/4f44579692164594202cbb4b49bb2cbf56a32d323173be199f943fe5e6b5b9425be6ea6efd2bbaccc08a148b1bd4b6f7c5e042136fdb938cf036981596ba1dbe + languageName: node + linkType: hard + +"@modelcontextprotocol/sdk@npm:^1.6.1": + version: 1.6.1 + resolution: "@modelcontextprotocol/sdk@npm:1.6.1" + dependencies: + content-type: "npm:^1.0.5" + cors: "npm:^2.8.5" + eventsource: "npm:^3.0.2" + express: "npm:^5.0.1" + express-rate-limit: "npm:^7.5.0" + pkce-challenge: "npm:^4.1.0" + raw-body: "npm:^3.0.0" + zod: "npm:^3.23.8" + zod-to-json-schema: "npm:^3.24.1" + checksum: 10c0/767aca8096c06aabfa9432fab6a4e7bafb671833b1bddb2797b8089e102a9d6ac0486e7a353b28df9984eff5c5291bde76cd5ad079b576ae70666cdff10c5b2a + languageName: node + linkType: hard + +"@modelcontextprotocol/sdk@npm:^1.7.0": + version: 1.7.0 + resolution: "@modelcontextprotocol/sdk@npm:1.7.0" + dependencies: + content-type: "npm:^1.0.5" + cors: "npm:^2.8.5" + eventsource: "npm:^3.0.2" + express: "npm:^5.0.1" + express-rate-limit: "npm:^7.5.0" + pkce-challenge: "npm:^4.1.0" + raw-body: "npm:^3.0.0" + zod: "npm:^3.23.8" + zod-to-json-schema: "npm:^3.24.1" + checksum: 10c0/8d2bc586e5d8d9d2ffd927700a7eeb0ae0e24e63cc139283d74dd380e17cde14e252ec2e8f9edcfa4359e4b7b68ca2d4b01d1b341dd715b10d74566f9e34c1ca + languageName: node + linkType: hard + "@mswjs/interceptors@npm:^0.29.0": version: 0.29.1 resolution: "@mswjs/interceptors@npm:0.29.1" @@ -2815,6 +2948,610 @@ __metadata: languageName: node linkType: hard +"@radix-ui/number@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/number@npm:1.1.0" + checksum: 10c0/a48e34d5ff1484de1b7cf5d7317fefc831d49e96a2229f300fd37b657bd8cfb59c922830c00ec02838ab21de3b299a523474592e4f30882153412ed47edce6a4 + languageName: node + linkType: hard + +"@radix-ui/primitive@npm:1.1.1": + version: 1.1.1 + resolution: "@radix-ui/primitive@npm:1.1.1" + checksum: 10c0/6457bd8d1aa4ecb948e5d2a2484fc570698b2ab472db6d915a8f1eec04823f80423efa60b5ba840f0693bec2ca380333cc5f3b52586b40f407d9f572f9261f8d + languageName: node + linkType: hard + +"@radix-ui/react-arrow@npm:1.1.2": + version: 1.1.2 + resolution: "@radix-ui/react-arrow@npm:1.1.2" + dependencies: + "@radix-ui/react-primitive": "npm:2.0.2" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/38e1a338da1131f325e417ac456b1b6c16c76aa9da0635916262b4682d4e648226fd37b23348964a8e909c98b4d2293c7c5789be8f243cfe03856e6f0765cf5d + languageName: node + linkType: hard + +"@radix-ui/react-checkbox@npm:^1.1.4": + version: 1.1.4 + resolution: "@radix-ui/react-checkbox@npm:1.1.4" + dependencies: + "@radix-ui/primitive": "npm:1.1.1" + "@radix-ui/react-compose-refs": "npm:1.1.1" + "@radix-ui/react-context": "npm:1.1.1" + "@radix-ui/react-presence": "npm:1.1.2" + "@radix-ui/react-primitive": "npm:2.0.2" + "@radix-ui/react-use-controllable-state": "npm:1.1.0" + "@radix-ui/react-use-previous": "npm:1.1.0" + "@radix-ui/react-use-size": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/182db383c02affd874c5bd4f81ebd3786ddc5d6525b958984b40673cb1d8ff0336428bea18c19175f20b27a833120c441ec6a97433e9f731284e56ea1a9f13fd + languageName: node + linkType: hard + +"@radix-ui/react-collection@npm:1.1.2": + version: 1.1.2 + resolution: "@radix-ui/react-collection@npm:1.1.2" + dependencies: + "@radix-ui/react-compose-refs": "npm:1.1.1" + "@radix-ui/react-context": "npm:1.1.1" + "@radix-ui/react-primitive": "npm:2.0.2" + "@radix-ui/react-slot": "npm:1.1.2" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/8376aa0c0f38efbb45e5c0a2e8724b0ca2ccdab511f5aee4c3eb62a89959b20be0d4dd410b7068bc13d722751cbc88e916e10573784fb26b084c43f930818715 + languageName: node + linkType: hard + +"@radix-ui/react-compose-refs@npm:1.1.1, @radix-ui/react-compose-refs@npm:^1.1.1": + version: 1.1.1 + resolution: "@radix-ui/react-compose-refs@npm:1.1.1" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/3e84580024e66e3cc5b9ae79355e787815c1d2a3c7d46e7f47900a29c33751ca24cf4ac8903314957ab1f7788aebe1687e2258641c188cf94653f7ddf8f70627 + languageName: node + linkType: hard + +"@radix-ui/react-context@npm:1.1.1": + version: 1.1.1 + resolution: "@radix-ui/react-context@npm:1.1.1" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/fc4ace9d79d7954c715ade765e06c95d7e1b12a63a536bcbe842fb904f03f88fc5bd6e38d44bd23243d37a270b4c44380fedddaeeae2d274f0b898a20665aba2 + languageName: node + linkType: hard + +"@radix-ui/react-dialog@npm:^1.1.3, @radix-ui/react-dialog@npm:^1.1.6": + version: 1.1.6 + resolution: "@radix-ui/react-dialog@npm:1.1.6" + dependencies: + "@radix-ui/primitive": "npm:1.1.1" + "@radix-ui/react-compose-refs": "npm:1.1.1" + "@radix-ui/react-context": "npm:1.1.1" + "@radix-ui/react-dismissable-layer": "npm:1.1.5" + "@radix-ui/react-focus-guards": "npm:1.1.1" + "@radix-ui/react-focus-scope": "npm:1.1.2" + "@radix-ui/react-id": "npm:1.1.0" + "@radix-ui/react-portal": "npm:1.1.4" + "@radix-ui/react-presence": "npm:1.1.2" + "@radix-ui/react-primitive": "npm:2.0.2" + "@radix-ui/react-slot": "npm:1.1.2" + "@radix-ui/react-use-controllable-state": "npm:1.1.0" + aria-hidden: "npm:^1.2.4" + react-remove-scroll: "npm:^2.6.3" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/98e425549573c5d6fb0fee94ecd40427a8b8897bb2d9bb2a44fe64e484754376ff23b64fcf64e061d42fc774b9627a28cb5b1bb5652e567908dac9a8d8618705 + languageName: node + linkType: hard + +"@radix-ui/react-direction@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/react-direction@npm:1.1.0" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/eb07d8cc3ae2388b824e0a11ae0e3b71fb0c49972b506e249cec9f27a5b7ef4305ee668c98b674833c92e842163549a83beb0a197dec1ec65774bdeeb61f932c + languageName: node + linkType: hard + +"@radix-ui/react-dismissable-layer@npm:1.1.5": + version: 1.1.5 + resolution: "@radix-ui/react-dismissable-layer@npm:1.1.5" + dependencies: + "@radix-ui/primitive": "npm:1.1.1" + "@radix-ui/react-compose-refs": "npm:1.1.1" + "@radix-ui/react-primitive": "npm:2.0.2" + "@radix-ui/react-use-callback-ref": "npm:1.1.0" + "@radix-ui/react-use-escape-keydown": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/05c5adfcd42a736c456f50bdca25bf7f6b25eef7328e4c05de535fea128328666433a89d68cb1445e039c188d7f1397df6a4a02e2da0970762f2a80fd29b48ea + languageName: node + linkType: hard + +"@radix-ui/react-focus-guards@npm:1.1.1": + version: 1.1.1 + resolution: "@radix-ui/react-focus-guards@npm:1.1.1" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/2e99750ca593083a530542a185d656b45b100752353a7a193a67566e3c256414a76fa9171d152f8c0167b8d6c1fdf62b2e07750d7af2974bf8ef39eb204aa537 + languageName: node + linkType: hard + +"@radix-ui/react-focus-scope@npm:1.1.2": + version: 1.1.2 + resolution: "@radix-ui/react-focus-scope@npm:1.1.2" + dependencies: + "@radix-ui/react-compose-refs": "npm:1.1.1" + "@radix-ui/react-primitive": "npm:2.0.2" + "@radix-ui/react-use-callback-ref": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/7b93866a9980bc938fc3fcfacfc49467c13144931c9b7a3b5423c0c3817685dc421499d73f58335f6c3c1c0f4fea9c9b7c16aa06a1d30571620787086082bea0 + languageName: node + linkType: hard + +"@radix-ui/react-icons@npm:^1.3.0": + version: 1.3.2 + resolution: "@radix-ui/react-icons@npm:1.3.2" + peerDependencies: + react: ^16.x || ^17.x || ^18.x || ^19.0.0 || ^19.0.0-rc + checksum: 10c0/3a380c7ae47e330ebd8ab4846729a543b4a0be5ecb1e2a7a571f4394728ff7d428b01f6620128051b6b69d63138a0ab8de77af78221ec364fbc5d126acf55b4a + languageName: node + linkType: hard + +"@radix-ui/react-id@npm:1.1.0, @radix-ui/react-id@npm:^1.1.0": + version: 1.1.0 + resolution: "@radix-ui/react-id@npm:1.1.0" + dependencies: + "@radix-ui/react-use-layout-effect": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/acf13e29e51ee96336837fc0cfecc306328b20b0e0070f6f0f7aa7a621ded4a1ee5537cfad58456f64bae76caa7f8769231e88dc7dc106197347ee433c275a79 + languageName: node + linkType: hard + +"@radix-ui/react-label@npm:^2.1.0": + version: 2.1.2 + resolution: "@radix-ui/react-label@npm:2.1.2" + dependencies: + "@radix-ui/react-primitive": "npm:2.0.2" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/c425ea25a67f60142645e6dd7669aa90bd9017e8d99c347736c9c19c44cea52e33224e4d086fd7e4945a7e9baa49335d42a5801d3bead884305515023e3ab31c + languageName: node + linkType: hard + +"@radix-ui/react-popover@npm:^1.1.3": + version: 1.1.6 + resolution: "@radix-ui/react-popover@npm:1.1.6" + dependencies: + "@radix-ui/primitive": "npm:1.1.1" + "@radix-ui/react-compose-refs": "npm:1.1.1" + "@radix-ui/react-context": "npm:1.1.1" + "@radix-ui/react-dismissable-layer": "npm:1.1.5" + "@radix-ui/react-focus-guards": "npm:1.1.1" + "@radix-ui/react-focus-scope": "npm:1.1.2" + "@radix-ui/react-id": "npm:1.1.0" + "@radix-ui/react-popper": "npm:1.2.2" + "@radix-ui/react-portal": "npm:1.1.4" + "@radix-ui/react-presence": "npm:1.1.2" + "@radix-ui/react-primitive": "npm:2.0.2" + "@radix-ui/react-slot": "npm:1.1.2" + "@radix-ui/react-use-controllable-state": "npm:1.1.0" + aria-hidden: "npm:^1.2.4" + react-remove-scroll: "npm:^2.6.3" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/63cc2761693193f8c28c43a25d9eea69e4095ba47da11413dfa19436d6116c814851c388ab78f93a3bda0cc88ec4c234bd31d971ade2fcfbc08a0645ccde1d91 + languageName: node + linkType: hard + +"@radix-ui/react-popper@npm:1.2.2": + version: 1.2.2 + resolution: "@radix-ui/react-popper@npm:1.2.2" + dependencies: + "@floating-ui/react-dom": "npm:^2.0.0" + "@radix-ui/react-arrow": "npm:1.1.2" + "@radix-ui/react-compose-refs": "npm:1.1.1" + "@radix-ui/react-context": "npm:1.1.1" + "@radix-ui/react-primitive": "npm:2.0.2" + "@radix-ui/react-use-callback-ref": "npm:1.1.0" + "@radix-ui/react-use-layout-effect": "npm:1.1.0" + "@radix-ui/react-use-rect": "npm:1.1.0" + "@radix-ui/react-use-size": "npm:1.1.0" + "@radix-ui/rect": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/556cef98c0fe50bcfaaa4ae2e85af737755c884b78a04b6bdac3682829051ea0a4cf1163fc8bde782e33280613424e2ebb10b8af507da53e1aea08966c13cc86 + languageName: node + linkType: hard + +"@radix-ui/react-portal@npm:1.1.4": + version: 1.1.4 + resolution: "@radix-ui/react-portal@npm:1.1.4" + dependencies: + "@radix-ui/react-primitive": "npm:2.0.2" + "@radix-ui/react-use-layout-effect": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/e4038eb2f20be10d9754d099d00620f429711919d20c4c630946d9c4941f1c83ef1a3f4110c221c70486e65bc565ebba4ada22a0e7e2d179c039f2a014300793 + languageName: node + linkType: hard + +"@radix-ui/react-presence@npm:1.1.2": + version: 1.1.2 + resolution: "@radix-ui/react-presence@npm:1.1.2" + dependencies: + "@radix-ui/react-compose-refs": "npm:1.1.1" + "@radix-ui/react-use-layout-effect": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/0c6fa281368636308044df3be4c1f02733094b5e35ba04f26e610dd1c4315a245ffc758e0e176c444742a7a46f4328af1a9d8181e860175ec39338d06525a78d + languageName: node + linkType: hard + +"@radix-ui/react-primitive@npm:2.0.2, @radix-ui/react-primitive@npm:^2.0.2": + version: 2.0.2 + resolution: "@radix-ui/react-primitive@npm:2.0.2" + dependencies: + "@radix-ui/react-slot": "npm:1.1.2" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/1af7a33a86f8bd2467f2300b1bb6ca9af67cae3950953ba543d2a625c17f341dff05d19056ece7b03e5ced8b9f8de99c74f806710ce0da6b9a000f2af063fffe + languageName: node + linkType: hard + +"@radix-ui/react-roving-focus@npm:1.1.2": + version: 1.1.2 + resolution: "@radix-ui/react-roving-focus@npm:1.1.2" + dependencies: + "@radix-ui/primitive": "npm:1.1.1" + "@radix-ui/react-collection": "npm:1.1.2" + "@radix-ui/react-compose-refs": "npm:1.1.1" + "@radix-ui/react-context": "npm:1.1.1" + "@radix-ui/react-direction": "npm:1.1.0" + "@radix-ui/react-id": "npm:1.1.0" + "@radix-ui/react-primitive": "npm:2.0.2" + "@radix-ui/react-use-callback-ref": "npm:1.1.0" + "@radix-ui/react-use-controllable-state": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/80e378e1156d5b8af14995e908fe2358c8f4757fbf274e30d2ee3c1cedc3a0c7192524df7e3bb1d5011ee9ab8ab7445b60eff06617370e58abcd1ae97e0e40f6 + languageName: node + linkType: hard + +"@radix-ui/react-select@npm:^2.1.2": + version: 2.1.6 + resolution: "@radix-ui/react-select@npm:2.1.6" + dependencies: + "@radix-ui/number": "npm:1.1.0" + "@radix-ui/primitive": "npm:1.1.1" + "@radix-ui/react-collection": "npm:1.1.2" + "@radix-ui/react-compose-refs": "npm:1.1.1" + "@radix-ui/react-context": "npm:1.1.1" + "@radix-ui/react-direction": "npm:1.1.0" + "@radix-ui/react-dismissable-layer": "npm:1.1.5" + "@radix-ui/react-focus-guards": "npm:1.1.1" + "@radix-ui/react-focus-scope": "npm:1.1.2" + "@radix-ui/react-id": "npm:1.1.0" + "@radix-ui/react-popper": "npm:1.2.2" + "@radix-ui/react-portal": "npm:1.1.4" + "@radix-ui/react-primitive": "npm:2.0.2" + "@radix-ui/react-slot": "npm:1.1.2" + "@radix-ui/react-use-callback-ref": "npm:1.1.0" + "@radix-ui/react-use-controllable-state": "npm:1.1.0" + "@radix-ui/react-use-layout-effect": "npm:1.1.0" + "@radix-ui/react-use-previous": "npm:1.1.0" + "@radix-ui/react-visually-hidden": "npm:1.1.2" + aria-hidden: "npm:^1.2.4" + react-remove-scroll: "npm:^2.6.3" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/bc953806b861c66f01371502ac7404e1e3c783290e979f9446e89b643bff7f90164ce91126f719e5aec4d9601b9ad0e4e7b7e747bfc0fbfcf7a31aeeac0a484d + languageName: node + linkType: hard + +"@radix-ui/react-slot@npm:1.1.2, @radix-ui/react-slot@npm:^1.1.0": + version: 1.1.2 + resolution: "@radix-ui/react-slot@npm:1.1.2" + dependencies: + "@radix-ui/react-compose-refs": "npm:1.1.1" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/81d45091806c52b507cec80b4477e4f31189d76ffcd7845b382eb3a034e6cf1faef71b881612028d5893f7580bf9ab59daa18fbf2792042dccd755c99a18df67 + languageName: node + linkType: hard + +"@radix-ui/react-tabs@npm:^1.1.1": + version: 1.1.3 + resolution: "@radix-ui/react-tabs@npm:1.1.3" + dependencies: + "@radix-ui/primitive": "npm:1.1.1" + "@radix-ui/react-context": "npm:1.1.1" + "@radix-ui/react-direction": "npm:1.1.0" + "@radix-ui/react-id": "npm:1.1.0" + "@radix-ui/react-presence": "npm:1.1.2" + "@radix-ui/react-primitive": "npm:2.0.2" + "@radix-ui/react-roving-focus": "npm:1.1.2" + "@radix-ui/react-use-controllable-state": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/2f621c43a8e1dd0d54c828f8b4d88414c9114af6b720a650ad9587cc0a7a7536da778f2fe5181a38494cc2956f2b238fbe64790f6daad1d058b34f4acaee520e + languageName: node + linkType: hard + +"@radix-ui/react-use-callback-ref@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/react-use-callback-ref@npm:1.1.0" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/e954863f3baa151faf89ac052a5468b42650efca924417470efd1bd254b411a94c69c30de2fdbb90187b38cb984795978e12e30423dc41e4309d93d53b66d819 + languageName: node + linkType: hard + +"@radix-ui/react-use-controllable-state@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/react-use-controllable-state@npm:1.1.0" + dependencies: + "@radix-ui/react-use-callback-ref": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/2af883b5b25822ac226e60a6bfde647c0123a76345052a90219026059b3f7225844b2c13a9a16fba859c1cda5fb3d057f2a04503f71780e607516492db4eb3a1 + languageName: node + linkType: hard + +"@radix-ui/react-use-escape-keydown@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/react-use-escape-keydown@npm:1.1.0" + dependencies: + "@radix-ui/react-use-callback-ref": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/910fd696e5a0994b0e06b9cb68def8a865f47951a013ec240c77db2a9e1e726105602700ef5e5f01af49f2f18fe0e73164f9a9651021f28538ef8a30d91f3fbb + languageName: node + linkType: hard + +"@radix-ui/react-use-layout-effect@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/react-use-layout-effect@npm:1.1.0" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/9bf87ece1845c038ed95863cfccf9d75f557c2400d606343bab0ab3192b9806b9840e6aa0a0333fdf3e83cf9982632852192f3e68d7d8367bc8c788dfdf8e62b + languageName: node + linkType: hard + +"@radix-ui/react-use-previous@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/react-use-previous@npm:1.1.0" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/9787d24790d4e330715127f2f4db56c4cbed9b0a47f97e11a68582c08a356a53c1ec41c7537382f6fb8d0db25de152770f17430e8eaf0fa59705be97760acbad + languageName: node + linkType: hard + +"@radix-ui/react-use-rect@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/react-use-rect@npm:1.1.0" + dependencies: + "@radix-ui/rect": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/c2e30150ab49e2cec238cda306fd748c3d47fb96dcff69a3b08e1d19108d80bac239d48f1747a25dadca614e3e967267d43b91e60ea59db2befbc7bea913ff84 + languageName: node + linkType: hard + +"@radix-ui/react-use-size@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/react-use-size@npm:1.1.0" + dependencies: + "@radix-ui/react-use-layout-effect": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/4c8b89037597fdc1824d009e0c941b510c7c6c30f83024cc02c934edd748886786e7d9f36f57323b02ad29833e7fa7e8974d81969b4ab33d8f41661afa4f30a6 + languageName: node + linkType: hard + +"@radix-ui/react-visually-hidden@npm:1.1.2": + version: 1.1.2 + resolution: "@radix-ui/react-visually-hidden@npm:1.1.2" + dependencies: + "@radix-ui/react-primitive": "npm:2.0.2" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/ea6dc8ec284b32bca6f24809db257394802e14af7c95e4a237af51009fa222c42e3b7a55b3bfc94d753f509086636555058ae8e535be25956c46529abf41b448 + languageName: node + linkType: hard + +"@radix-ui/rect@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/rect@npm:1.1.0" + checksum: 10c0/a26ff7f8708fb5f2f7949baad70a6b2a597d761ee4dd4aadaf1c1a33ea82ea23dfef6ce6366a08310c5d008cdd60b2e626e4ee03fa342bd5f246ddd9d427f6be + languageName: node + linkType: hard + "@rollup/pluginutils@npm:^5.1.0": version: 5.1.0 resolution: "@rollup/pluginutils@npm:5.1.0" @@ -3702,6 +4439,25 @@ __metadata: languageName: node linkType: hard +"@types/body-parser@npm:*": + version: 1.19.5 + resolution: "@types/body-parser@npm:1.19.5" + dependencies: + "@types/connect": "npm:*" + "@types/node": "npm:*" + checksum: 10c0/aebeb200f25e8818d8cf39cd0209026750d77c9b85381cdd8deeb50913e4d18a1ebe4b74ca9b0b4d21952511eeaba5e9fbbf739b52731a2061e206ec60d568df + languageName: node + linkType: hard + +"@types/connect@npm:*": + version: 3.4.38 + resolution: "@types/connect@npm:3.4.38" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/2e1cdba2c410f25649e77856505cd60223250fa12dff7a503e492208dbfdd25f62859918f28aba95315251fd1f5e1ffbfca1e25e73037189ab85dd3f8d0a148c + languageName: node + linkType: hard + "@types/cookie@npm:^0.6.0": version: 0.6.0 resolution: "@types/cookie@npm:0.6.0" @@ -3730,6 +4486,30 @@ __metadata: languageName: node linkType: hard +"@types/express-serve-static-core@npm:^5.0.0": + version: 5.0.6 + resolution: "@types/express-serve-static-core@npm:5.0.6" + dependencies: + "@types/node": "npm:*" + "@types/qs": "npm:*" + "@types/range-parser": "npm:*" + "@types/send": "npm:*" + checksum: 10c0/aced8cc88c1718adbbd1fc488756b0f22d763368d9eff2ae21b350698fab4a77d8d13c3699056dc662a887e43a8b67a3e8f6289ff76102ecc6bad4a7710d31a6 + languageName: node + linkType: hard + +"@types/express@npm:^5.0.0": + version: 5.0.0 + resolution: "@types/express@npm:5.0.0" + dependencies: + "@types/body-parser": "npm:*" + "@types/express-serve-static-core": "npm:^5.0.0" + "@types/qs": "npm:*" + "@types/serve-static": "npm:*" + checksum: 10c0/0d74b53aefa69c3b3817ee9b5145fd50d7dbac52a8986afc2d7500085c446656d0b6dc13158c04e2d9f18f4324d4d93b0452337c5ff73dd086dca3e4ff11f47b + languageName: node + linkType: hard + "@types/hast@npm:^3.0.4": version: 3.0.4 resolution: "@types/hast@npm:3.0.4" @@ -3739,6 +4519,13 @@ __metadata: languageName: node linkType: hard +"@types/http-errors@npm:*": + version: 2.0.4 + resolution: "@types/http-errors@npm:2.0.4" + checksum: 10c0/494670a57ad4062fee6c575047ad5782506dd35a6b9ed3894cea65830a94367bd84ba302eb3dde331871f6d70ca287bfedb1b2cf658e6132cd2cbd427ab56836 + languageName: node + linkType: hard + "@types/istanbul-lib-coverage@npm:^2.0.1": version: 2.0.4 resolution: "@types/istanbul-lib-coverage@npm:2.0.4" @@ -3785,6 +4572,13 @@ __metadata: languageName: node linkType: hard +"@types/mime@npm:^1": + version: 1.3.5 + resolution: "@types/mime@npm:1.3.5" + checksum: 10c0/c2ee31cd9b993804df33a694d5aa3fa536511a49f2e06eeab0b484fef59b4483777dbb9e42a4198a0809ffbf698081fdbca1e5c2218b82b91603dfab10a10fbc + languageName: node + linkType: hard + "@types/minimatch@npm:^3.0.3": version: 3.0.5 resolution: "@types/minimatch@npm:3.0.5" @@ -3849,6 +4643,13 @@ __metadata: languageName: node linkType: hard +"@types/prismjs@npm:^1.26.5": + version: 1.26.5 + resolution: "@types/prismjs@npm:1.26.5" + checksum: 10c0/5619cb449e0d8df098c8759d6f47bf8fdd510abf5dbdfa999e55c6a2545efbd1e209cc85a33d8d9f4ff2898089a1a6d9a70737c9baffaae635c46852c40d384a + languageName: node + linkType: hard + "@types/prop-types@npm:*": version: 15.7.12 resolution: "@types/prop-types@npm:15.7.12" @@ -3856,6 +4657,20 @@ __metadata: languageName: node linkType: hard +"@types/qs@npm:*": + version: 6.9.18 + resolution: "@types/qs@npm:6.9.18" + checksum: 10c0/790b9091348e06dde2c8e4118b5771ab386a8c22a952139a2eb0675360a2070d0b155663bf6f75b23f258fd0a1f7ffc0ba0f059d99a719332c03c40d9e9cd63b + languageName: node + linkType: hard + +"@types/range-parser@npm:*": + version: 1.2.7 + resolution: "@types/range-parser@npm:1.2.7" + checksum: 10c0/361bb3e964ec5133fa40644a0b942279ed5df1949f21321d77de79f48b728d39253e5ce0408c9c17e4e0fd95ca7899da36841686393b9f7a1e209916e9381a3c + languageName: node + linkType: hard + "@types/react-dom@npm:^18, @types/react-dom@npm:^18.0.0, @types/react-dom@npm:^18.3.0": version: 18.3.0 resolution: "@types/react-dom@npm:18.3.0" @@ -3875,6 +4690,27 @@ __metadata: languageName: node linkType: hard +"@types/send@npm:*": + version: 0.17.4 + resolution: "@types/send@npm:0.17.4" + dependencies: + "@types/mime": "npm:^1" + "@types/node": "npm:*" + checksum: 10c0/7f17fa696cb83be0a104b04b424fdedc7eaba1c9a34b06027239aba513b398a0e2b7279778af521f516a397ced417c96960e5f50fcfce40c4bc4509fb1a5883c + languageName: node + linkType: hard + +"@types/serve-static@npm:*": + version: 1.15.7 + resolution: "@types/serve-static@npm:1.15.7" + dependencies: + "@types/http-errors": "npm:*" + "@types/node": "npm:*" + "@types/send": "npm:*" + checksum: 10c0/26ec864d3a626ea627f8b09c122b623499d2221bbf2f470127f4c9ebfe92bd8a6bb5157001372d4c4bd0dd37a1691620217d9dc4df5aa8f779f3fd996b1c60ae + languageName: node + linkType: hard + "@types/slug@npm:^5.0.9": version: 5.0.9 resolution: "@types/slug@npm:5.0.9" @@ -4801,6 +5637,26 @@ __metadata: languageName: node linkType: hard +"accepts@npm:^2.0.0": + version: 2.0.0 + resolution: "accepts@npm:2.0.0" + dependencies: + mime-types: "npm:^3.0.0" + negotiator: "npm:^1.0.0" + checksum: 10c0/98374742097e140891546076215f90c32644feacf652db48412329de4c2a529178a81aa500fbb13dd3e6cbf6e68d829037b123ac037fc9a08bcec4b87b358eef + languageName: node + linkType: hard + +"accepts@npm:~1.3.8": + version: 1.3.8 + resolution: "accepts@npm:1.3.8" + dependencies: + mime-types: "npm:~2.1.34" + negotiator: "npm:0.6.3" + checksum: 10c0/3a35c5f5586cfb9a21163ca47a5f77ac34fa8ceb5d17d2fa2c0d81f41cbd7f8c6fa52c77e2c039acc0f4d09e71abdc51144246900f6bef5e3c4b333f77d89362 + languageName: node + linkType: hard + "acorn-import-attributes@npm:^1.9.5": version: 1.9.5 resolution: "acorn-import-attributes@npm:1.9.5" @@ -5142,6 +5998,15 @@ __metadata: languageName: node linkType: hard +"aria-hidden@npm:^1.2.4": + version: 1.2.4 + resolution: "aria-hidden@npm:1.2.4" + dependencies: + tslib: "npm:^2.0.0" + checksum: 10c0/8abcab2e1432efc4db415e97cb3959649ddf52c8fc815d7384f43f3d3abf56f1c12852575d00df9a8927f421d7e0712652dd5f8db244ea57634344e29ecfc74a + languageName: node + linkType: hard + "aria-query@npm:5.3.0": version: 5.3.0 resolution: "aria-query@npm:5.3.0" @@ -5197,6 +6062,13 @@ __metadata: languageName: node linkType: hard +"array-flatten@npm:1.1.1": + version: 1.1.1 + resolution: "array-flatten@npm:1.1.1" + checksum: 10c0/806966c8abb2f858b08f5324d9d18d7737480610f3bd5d3498aaae6eb5efdc501a884ba019c9b4a8f02ff67002058749d05548fd42fa8643f02c9c7f22198b91 + languageName: node + linkType: hard + "array-ify@npm:^1.0.0": version: 1.0.0 resolution: "array-ify@npm:1.0.0" @@ -5553,6 +6425,43 @@ __metadata: languageName: node linkType: hard +"body-parser@npm:1.20.3": + version: 1.20.3 + resolution: "body-parser@npm:1.20.3" + dependencies: + bytes: "npm:3.1.2" + content-type: "npm:~1.0.5" + debug: "npm:2.6.9" + depd: "npm:2.0.0" + destroy: "npm:1.2.0" + http-errors: "npm:2.0.0" + iconv-lite: "npm:0.4.24" + on-finished: "npm:2.4.1" + qs: "npm:6.13.0" + raw-body: "npm:2.5.2" + type-is: "npm:~1.6.18" + unpipe: "npm:1.0.0" + checksum: 10c0/0a9a93b7518f222885498dcecaad528cf010dd109b071bf471c93def4bfe30958b83e03496eb9c1ad4896db543d999bb62be1a3087294162a88cfa1b42c16310 + languageName: node + linkType: hard + +"body-parser@npm:^2.0.1": + version: 2.1.0 + resolution: "body-parser@npm:2.1.0" + dependencies: + bytes: "npm:^3.1.2" + content-type: "npm:^1.0.5" + debug: "npm:^4.4.0" + http-errors: "npm:^2.0.0" + iconv-lite: "npm:^0.5.2" + on-finished: "npm:^2.4.1" + qs: "npm:^6.14.0" + raw-body: "npm:^3.0.0" + type-is: "npm:^2.0.0" + checksum: 10c0/aec9bb327ba025808f04f86350ae9152ff9a6a8bc7429b69827cb7721b09f477ffd5e18cc954152a6a259b765322e33ebc4c50ab940f66d8e45ff1466e49ff2e + languageName: node + linkType: hard + "brace-expansion@npm:^1.1.7": version: 1.1.11 resolution: "brace-expansion@npm:1.1.11" @@ -5667,6 +6576,20 @@ __metadata: languageName: node linkType: hard +"bytes@npm:3.0.0": + version: 3.0.0 + resolution: "bytes@npm:3.0.0" + checksum: 10c0/91d42c38601c76460519ffef88371caacaea483a354c8e4b8808e7b027574436a5713337c003ea3de63ee4991c2a9a637884fdfe7f761760d746929d9e8fec60 + languageName: node + linkType: hard + +"bytes@npm:3.1.2, bytes@npm:^3.1.2": + version: 3.1.2 + resolution: "bytes@npm:3.1.2" + checksum: 10c0/76d1c43cbd602794ad8ad2ae94095cddeb1de78c5dddaa7005c51af10b0176c69971a6d88e805a90c2b6550d76636e43c40d8427a808b8645ede885de4a0358e + languageName: node + linkType: hard + "c8@npm:~10.1.0, c8@npm:~10.1.3": version: 10.1.3 resolution: "c8@npm:10.1.3" @@ -6015,6 +6938,15 @@ __metadata: languageName: node linkType: hard +"class-variance-authority@npm:^0.7.0": + version: 0.7.1 + resolution: "class-variance-authority@npm:0.7.1" + dependencies: + clsx: "npm:^2.1.1" + checksum: 10c0/0f438cea22131808b99272de0fa933c2532d5659773bfec0c583de7b3f038378996d3350683426b8e9c74a6286699382106d71fbec52f0dd5fbb191792cccb5b + languageName: node + linkType: hard + "clean-stack@npm:^2.0.0": version: 2.2.0 resolution: "clean-stack@npm:2.2.0" @@ -6115,6 +7047,13 @@ __metadata: languageName: node linkType: hard +"clsx@npm:^2.1.0, clsx@npm:^2.1.1": + version: 2.1.1 + resolution: "clsx@npm:2.1.1" + checksum: 10c0/c4c8eb865f8c82baab07e71bfa8897c73454881c4f99d6bc81585aecd7c441746c1399d08363dc096c550cceaf97bd4ce1e8854e1771e9998d9f94c4fe075839 + languageName: node + linkType: hard + "cmd-shim@npm:6.0.1": version: 6.0.1 resolution: "cmd-shim@npm:6.0.1" @@ -6122,6 +7061,21 @@ __metadata: languageName: node linkType: hard +"cmdk@npm:^1.0.4": + version: 1.1.1 + resolution: "cmdk@npm:1.1.1" + dependencies: + "@radix-ui/react-compose-refs": "npm:^1.1.1" + "@radix-ui/react-dialog": "npm:^1.1.6" + "@radix-ui/react-id": "npm:^1.1.0" + "@radix-ui/react-primitive": "npm:^2.0.2" + peerDependencies: + react: ^18 || ^19 || ^19.0.0-rc + react-dom: ^18 || ^19 || ^19.0.0-rc + checksum: 10c0/5605ac4396ec9bc65c82f954da19dd89a0636a54026df72780e2470da1381f9d57434a80a53f2d57eaa4e759660a3ebba9232b74258dc09970576591eae03116 + languageName: node + linkType: hard + "color-convert@npm:^1.9.0": version: 1.9.3 resolution: "color-convert@npm:1.9.3" @@ -6260,6 +7214,24 @@ __metadata: languageName: node linkType: hard +"concurrently@npm:^9.0.1": + version: 9.1.2 + resolution: "concurrently@npm:9.1.2" + dependencies: + chalk: "npm:^4.1.2" + lodash: "npm:^4.17.21" + rxjs: "npm:^7.8.1" + shell-quote: "npm:^1.8.1" + supports-color: "npm:^8.1.1" + tree-kill: "npm:^1.2.2" + yargs: "npm:^17.7.2" + bin: + conc: dist/bin/concurrently.js + concurrently: dist/bin/concurrently.js + checksum: 10c0/88e00269366aa885ca2b97fd53b04e7af2b0f31774d991bfc0e88c0de61cdebdf115ddacc9c897fbd1f1b90369014637fa77045a171d072a75693332b36dcc70 + languageName: node + linkType: hard + "confbox@npm:^0.1.7": version: 0.1.7 resolution: "confbox@npm:0.1.7" @@ -6274,6 +7246,38 @@ __metadata: languageName: node linkType: hard +"content-disposition@npm:0.5.2": + version: 0.5.2 + resolution: "content-disposition@npm:0.5.2" + checksum: 10c0/49eebaa0da1f9609b192e99d7fec31d1178cb57baa9d01f5b63b29787ac31e9d18b5a1033e854c68c9b6cce790e700a6f7fa60e43f95e2e416404e114a8f2f49 + languageName: node + linkType: hard + +"content-disposition@npm:0.5.4": + version: 0.5.4 + resolution: "content-disposition@npm:0.5.4" + dependencies: + safe-buffer: "npm:5.2.1" + checksum: 10c0/bac0316ebfeacb8f381b38285dc691c9939bf0a78b0b7c2d5758acadad242d04783cee5337ba7d12a565a19075af1b3c11c728e1e4946de73c6ff7ce45f3f1bb + languageName: node + linkType: hard + +"content-disposition@npm:^1.0.0": + version: 1.0.0 + resolution: "content-disposition@npm:1.0.0" + dependencies: + safe-buffer: "npm:5.2.1" + checksum: 10c0/c7b1ba0cea2829da0352ebc1b7f14787c73884bc707c8bc2271d9e3bf447b372270d09f5d3980dc5037c749ceef56b9a13fccd0b0001c87c3f12579967e4dd27 + languageName: node + linkType: hard + +"content-type@npm:^1.0.5, content-type@npm:~1.0.4, content-type@npm:~1.0.5": + version: 1.0.5 + resolution: "content-type@npm:1.0.5" + checksum: 10c0/b76ebed15c000aee4678c3707e0860cb6abd4e680a598c0a26e17f0bfae723ec9cc2802f0ff1bc6e4d80603719010431d2231018373d4dde10f9ccff9dadf5af + languageName: node + linkType: hard + "conventional-changelog-angular@npm:7.0.0": version: 7.0.0 resolution: "conventional-changelog-angular@npm:7.0.0" @@ -6383,6 +7387,27 @@ __metadata: languageName: node linkType: hard +"cookie-signature@npm:1.0.6": + version: 1.0.6 + resolution: "cookie-signature@npm:1.0.6" + checksum: 10c0/b36fd0d4e3fef8456915fcf7742e58fbfcc12a17a018e0eb9501c9d5ef6893b596466f03b0564b81af29ff2538fd0aa4b9d54fe5ccbfb4c90ea50ad29fe2d221 + languageName: node + linkType: hard + +"cookie-signature@npm:^1.2.1": + version: 1.2.2 + resolution: "cookie-signature@npm:1.2.2" + checksum: 10c0/54e05df1a293b3ce81589b27dddc445f462f6fa6812147c033350cd3561a42bc14481674e05ed14c7bd0ce1e8bb3dc0e40851bad75415733711294ddce0b7bc6 + languageName: node + linkType: hard + +"cookie@npm:0.7.1": + version: 0.7.1 + resolution: "cookie@npm:0.7.1" + checksum: 10c0/5de60c67a410e7c8dc8a46a4b72eb0fe925871d057c9a5d2c0e8145c4270a4f81076de83410c4d397179744b478e33cd80ccbcc457abf40a9409ad27dcd21dde + languageName: node + linkType: hard + "cookie@npm:^0.5.0": version: 0.5.0 resolution: "cookie@npm:0.5.0" @@ -6397,6 +7422,16 @@ __metadata: languageName: node linkType: hard +"cors@npm:^2.8.5": + version: 2.8.5 + resolution: "cors@npm:2.8.5" + dependencies: + object-assign: "npm:^4" + vary: "npm:^1" + checksum: 10c0/373702b7999409922da80de4a61938aabba6929aea5b6fd9096fefb9e8342f626c0ebd7507b0e8b0b311380744cc985f27edebc0a26e0ddb784b54e1085de761 + languageName: node + linkType: hard + "corser@npm:^2.0.1": version: 2.0.1 resolution: "corser@npm:2.0.1" @@ -6608,6 +7643,15 @@ __metadata: languageName: node linkType: hard +"debug@npm:2.6.9": + version: 2.6.9 + resolution: "debug@npm:2.6.9" + dependencies: + ms: "npm:2.0.0" + checksum: 10c0/121908fb839f7801180b69a7e218a40b5a0b718813b886b7d6bdb82001b931c938e2941d1e4450f33a1b1df1da653f5f7a0440c197f29fbf8a6e9d45ff6ef589 + languageName: node + linkType: hard + "debug@npm:4, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": version: 4.3.4 resolution: "debug@npm:4.3.4" @@ -6620,6 +7664,18 @@ __metadata: languageName: node linkType: hard +"debug@npm:4.3.6": + version: 4.3.6 + resolution: "debug@npm:4.3.6" + dependencies: + ms: "npm:2.1.2" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 10c0/3293416bff072389c101697d4611c402a6bacd1900ac20c0492f61a9cdd6b3b29750fc7f5e299f8058469ef60ff8fb79b86395a30374fbd2490113c1c7112285 + languageName: node + linkType: hard + "debug@npm:^3.2.7": version: 3.2.7 resolution: "debug@npm:3.2.7" @@ -6842,6 +7898,13 @@ __metadata: languageName: node linkType: hard +"depd@npm:2.0.0": + version: 2.0.0 + resolution: "depd@npm:2.0.0" + checksum: 10c0/58bd06ec20e19529b06f7ad07ddab60e504d9e0faca4bd23079fac2d279c3594334d736508dc350e06e510aba5e22e4594483b3a6562ce7c17dd797f4cc4ad2c + languageName: node + linkType: hard + "deprecation@npm:^2.0.0": version: 2.3.1 resolution: "deprecation@npm:2.3.1" @@ -6856,6 +7919,13 @@ __metadata: languageName: node linkType: hard +"destroy@npm:1.2.0, destroy@npm:^1.2.0": + version: 1.2.0 + resolution: "destroy@npm:1.2.0" + checksum: 10c0/bd7633942f57418f5a3b80d5cb53898127bcf53e24cdf5d5f4396be471417671f0fee48a4ebe9a1e9defbde2a31280011af58a57e090ff822f589b443ed4e643 + languageName: node + linkType: hard + "detect-indent@npm:^5.0.0": version: 5.0.0 resolution: "detect-indent@npm:5.0.0" @@ -6863,6 +7933,13 @@ __metadata: languageName: node linkType: hard +"detect-node-es@npm:^1.1.0": + version: 1.1.0 + resolution: "detect-node-es@npm:1.1.0" + checksum: 10c0/e562f00de23f10c27d7119e1af0e7388407eb4b06596a25f6d79a360094a109ff285de317f02b090faae093d314cf6e73ac3214f8a5bb3a0def5bece94557fbe + languageName: node + linkType: hard + "didyoumean@npm:^1.2.2": version: 1.2.2 resolution: "didyoumean@npm:1.2.2" @@ -6973,6 +8050,13 @@ __metadata: languageName: node linkType: hard +"ee-first@npm:1.1.1": + version: 1.1.1 + resolution: "ee-first@npm:1.1.1" + checksum: 10c0/b5bb125ee93161bc16bfe6e56c6b04de5ad2aa44234d8f644813cc95d861a6910903132b05093706de2b706599367c4130eb6d170f6b46895686b95f87d017b7 + languageName: node + linkType: hard + "ejs@npm:^3.1.7": version: 3.1.10 resolution: "ejs@npm:3.1.10" @@ -7019,6 +8103,20 @@ __metadata: languageName: node linkType: hard +"encodeurl@npm:^2.0.0, encodeurl@npm:~2.0.0": + version: 2.0.0 + resolution: "encodeurl@npm:2.0.0" + checksum: 10c0/5d317306acb13e6590e28e27924c754163946a2480de11865c991a3a7eed4315cd3fba378b543ca145829569eefe9b899f3d84bb09870f675ae60bc924b01ceb + languageName: node + linkType: hard + +"encodeurl@npm:~1.0.2": + version: 1.0.2 + resolution: "encodeurl@npm:1.0.2" + checksum: 10c0/f6c2387379a9e7c1156c1c3d4f9cb7bb11cf16dd4c1682e1f6746512564b053df5781029b6061296832b59fb22f459dbe250386d217c2f6e203601abb2ee0bec + languageName: node + linkType: hard + "encoding@npm:^0.1.13": version: 0.1.13 resolution: "encoding@npm:0.1.13" @@ -7640,6 +8738,13 @@ __metadata: languageName: node linkType: hard +"escape-html@npm:^1.0.3, escape-html@npm:~1.0.3": + version: 1.0.3 + resolution: "escape-html@npm:1.0.3" + checksum: 10c0/524c739d776b36c3d29fa08a22e03e8824e3b2fd57500e5e44ecf3cc4707c34c60f9ca0781c0e33d191f2991161504c295e98f68c78fe7baa6e57081ec6ac0a3 + languageName: node + linkType: hard + "escape-string-regexp@npm:^1.0.5": version: 1.0.5 resolution: "escape-string-regexp@npm:1.0.5" @@ -8181,6 +9286,13 @@ __metadata: languageName: node linkType: hard +"etag@npm:^1.8.1, etag@npm:~1.8.1": + version: 1.8.1 + resolution: "etag@npm:1.8.1" + checksum: 10c0/12be11ef62fb9817314d790089a0a49fae4e1b50594135dcb8076312b7d7e470884b5100d249b28c18581b7fd52f8b485689ffae22a11ed9ec17377a33a08f84 + languageName: node + linkType: hard + "eventemitter3@npm:^4.0.0, eventemitter3@npm:^4.0.4": version: 4.0.7 resolution: "eventemitter3@npm:4.0.7" @@ -8195,6 +9307,22 @@ __metadata: languageName: node linkType: hard +"eventsource-parser@npm:^3.0.0": + version: 3.0.0 + resolution: "eventsource-parser@npm:3.0.0" + checksum: 10c0/74ded91ff93330bd95243bd5a8fc61c805ea1843dd7ffac8e8ac36287fff419a7eec21b2fadf50d4e554ce0506de72f47928513e3c5b886fa4613fd49ef0024f + languageName: node + linkType: hard + +"eventsource@npm:^3.0.2": + version: 3.0.5 + resolution: "eventsource@npm:3.0.5" + dependencies: + eventsource-parser: "npm:^3.0.0" + checksum: 10c0/0283045a70b7ab7501fc290e60ee5ebd6e24648e0f0a6d6a1c1bbb7a421971e8140b85d6239d08c360e0a0b196205ca86b4ff7f9efe3c06877ba628136856489 + languageName: node + linkType: hard + "execa@npm:5.0.0": version: 5.0.0 resolution: "execa@npm:5.0.0" @@ -8243,6 +9371,94 @@ __metadata: languageName: node linkType: hard +"express-rate-limit@npm:^7.5.0": + version: 7.5.0 + resolution: "express-rate-limit@npm:7.5.0" + peerDependencies: + express: ^4.11 || 5 || ^5.0.0-beta.1 + checksum: 10c0/3e96afa05b4f577395688ede37e0cb19901f20c350b32575fb076f3d25176209fb88d3648151755c232aaf304147c58531f070757978f376e2f08326449299fd + languageName: node + linkType: hard + +"express@npm:^4.21.0, express@npm:^4.21.2": + version: 4.21.2 + resolution: "express@npm:4.21.2" + dependencies: + accepts: "npm:~1.3.8" + array-flatten: "npm:1.1.1" + body-parser: "npm:1.20.3" + content-disposition: "npm:0.5.4" + content-type: "npm:~1.0.4" + cookie: "npm:0.7.1" + cookie-signature: "npm:1.0.6" + debug: "npm:2.6.9" + depd: "npm:2.0.0" + encodeurl: "npm:~2.0.0" + escape-html: "npm:~1.0.3" + etag: "npm:~1.8.1" + finalhandler: "npm:1.3.1" + fresh: "npm:0.5.2" + http-errors: "npm:2.0.0" + merge-descriptors: "npm:1.0.3" + methods: "npm:~1.1.2" + on-finished: "npm:2.4.1" + parseurl: "npm:~1.3.3" + path-to-regexp: "npm:0.1.12" + proxy-addr: "npm:~2.0.7" + qs: "npm:6.13.0" + range-parser: "npm:~1.2.1" + safe-buffer: "npm:5.2.1" + send: "npm:0.19.0" + serve-static: "npm:1.16.2" + setprototypeof: "npm:1.2.0" + statuses: "npm:2.0.1" + type-is: "npm:~1.6.18" + utils-merge: "npm:1.0.1" + vary: "npm:~1.1.2" + checksum: 10c0/38168fd0a32756600b56e6214afecf4fc79ec28eca7f7a91c2ab8d50df4f47562ca3f9dee412da7f5cea6b1a1544b33b40f9f8586dbacfbdada0fe90dbb10a1f + languageName: node + linkType: hard + +"express@npm:^5.0.1": + version: 5.0.1 + resolution: "express@npm:5.0.1" + dependencies: + accepts: "npm:^2.0.0" + body-parser: "npm:^2.0.1" + content-disposition: "npm:^1.0.0" + content-type: "npm:~1.0.4" + cookie: "npm:0.7.1" + cookie-signature: "npm:^1.2.1" + debug: "npm:4.3.6" + depd: "npm:2.0.0" + encodeurl: "npm:~2.0.0" + escape-html: "npm:~1.0.3" + etag: "npm:~1.8.1" + finalhandler: "npm:^2.0.0" + fresh: "npm:2.0.0" + http-errors: "npm:2.0.0" + merge-descriptors: "npm:^2.0.0" + methods: "npm:~1.1.2" + mime-types: "npm:^3.0.0" + on-finished: "npm:2.4.1" + once: "npm:1.4.0" + parseurl: "npm:~1.3.3" + proxy-addr: "npm:~2.0.7" + qs: "npm:6.13.0" + range-parser: "npm:~1.2.1" + router: "npm:^2.0.0" + safe-buffer: "npm:5.2.1" + send: "npm:^1.1.0" + serve-static: "npm:^2.1.0" + setprototypeof: "npm:1.2.0" + statuses: "npm:2.0.1" + type-is: "npm:^2.0.0" + utils-merge: "npm:1.0.1" + vary: "npm:~1.1.2" + checksum: 10c0/6e533f28adb64178c90c3e357cbcdb5d1f233ca1290d023b3c4936c4ac67c6699aaba726edf6c148979220ec7ce6ed2e5e374cff904e3a2bf9ce91620cf8afff + languageName: node + linkType: hard + "external-editor@npm:^3.0.3, external-editor@npm:^3.1.0": version: 3.1.0 resolution: "external-editor@npm:3.1.0" @@ -8394,6 +9610,35 @@ __metadata: languageName: node linkType: hard +"finalhandler@npm:1.3.1": + version: 1.3.1 + resolution: "finalhandler@npm:1.3.1" + dependencies: + debug: "npm:2.6.9" + encodeurl: "npm:~2.0.0" + escape-html: "npm:~1.0.3" + on-finished: "npm:2.4.1" + parseurl: "npm:~1.3.3" + statuses: "npm:2.0.1" + unpipe: "npm:~1.0.0" + checksum: 10c0/d38035831865a49b5610206a3a9a9aae4e8523cbbcd01175d0480ffbf1278c47f11d89be3ca7f617ae6d94f29cf797546a4619cd84dd109009ef33f12f69019f + languageName: node + linkType: hard + +"finalhandler@npm:^2.0.0": + version: 2.1.0 + resolution: "finalhandler@npm:2.1.0" + dependencies: + debug: "npm:^4.4.0" + encodeurl: "npm:^2.0.0" + escape-html: "npm:^1.0.3" + on-finished: "npm:^2.4.1" + parseurl: "npm:^1.3.3" + statuses: "npm:^2.0.1" + checksum: 10c0/da0bbca6d03873472ee890564eb2183f4ed377f25f3628a0fc9d16dac40bed7b150a0d82ebb77356e4c6d97d2796ad2dba22948b951dddee2c8768b0d1b9fb1f + languageName: node + linkType: hard + "find-up@npm:^2.0.0": version: 2.1.0 resolution: "find-up@npm:2.1.0" @@ -8534,6 +9779,13 @@ __metadata: languageName: node linkType: hard +"forwarded@npm:0.2.0": + version: 0.2.0 + resolution: "forwarded@npm:0.2.0" + checksum: 10c0/9b67c3fac86acdbc9ae47ba1ddd5f2f81526fa4c8226863ede5600a3f7c7416ef451f6f1e240a3cc32d0fd79fcfe6beb08fd0da454f360032bde70bf80afbb33 + languageName: node + linkType: hard + "fraction.js@npm:^4.3.6": version: 4.3.7 resolution: "fraction.js@npm:4.3.7" @@ -8541,6 +9793,20 @@ __metadata: languageName: node linkType: hard +"fresh@npm:0.5.2, fresh@npm:^0.5.2": + version: 0.5.2 + resolution: "fresh@npm:0.5.2" + checksum: 10c0/c6d27f3ed86cc5b601404822f31c900dd165ba63fff8152a3ef714e2012e7535027063bc67ded4cb5b3a49fa596495d46cacd9f47d6328459cf570f08b7d9e5a + languageName: node + linkType: hard + +"fresh@npm:2.0.0": + version: 2.0.0 + resolution: "fresh@npm:2.0.0" + checksum: 10c0/0557548194cb9a809a435bf92bcfbc20c89e8b5eb38861b73ced36750437251e39a111fc3a18b98531be9dd91fe1411e4969f229dc579ec0251ce6c5d4900bbc + languageName: node + linkType: hard + "fs-constants@npm:^1.0.0": version: 1.0.0 resolution: "fs-constants@npm:1.0.0" @@ -8779,6 +10045,13 @@ __metadata: languageName: node linkType: hard +"get-nonce@npm:^1.0.0": + version: 1.0.1 + resolution: "get-nonce@npm:1.0.1" + checksum: 10c0/2d7df55279060bf0568549e1ffc9b84bc32a32b7541675ca092dce56317cdd1a59a98dcc4072c9f6a980779440139a3221d7486f52c488e69dc0fd27b1efb162 + languageName: node + linkType: hard + "get-pkg-repo@npm:^4.2.1": version: 4.2.1 resolution: "get-pkg-repo@npm:4.2.1" @@ -9412,6 +10685,19 @@ __metadata: languageName: node linkType: hard +"http-errors@npm:2.0.0, http-errors@npm:^2.0.0": + version: 2.0.0 + resolution: "http-errors@npm:2.0.0" + dependencies: + depd: "npm:2.0.0" + inherits: "npm:2.0.4" + setprototypeof: "npm:1.2.0" + statuses: "npm:2.0.1" + toidentifier: "npm:1.0.1" + checksum: 10c0/fc6f2715fe188d091274b5ffc8b3657bd85c63e969daa68ccb77afb05b071a4b62841acb7a21e417b5539014dff2ebf9550f0b14a9ff126f2734a7c1387f8e19 + languageName: node + linkType: hard + "http-proxy-agent@npm:^5.0.0": version: 5.0.0 resolution: "http-proxy-agent@npm:5.0.0" @@ -9520,6 +10806,15 @@ __metadata: languageName: node linkType: hard +"iconv-lite@npm:0.4.24, iconv-lite@npm:^0.4.24": + version: 0.4.24 + resolution: "iconv-lite@npm:0.4.24" + dependencies: + safer-buffer: "npm:>= 2.1.2 < 3" + checksum: 10c0/c6886a24cc00f2a059767440ec1bc00d334a89f250db8e0f7feb4961c8727118457e27c495ba94d082e51d3baca378726cd110aaf7ded8b9bbfd6a44760cf1d4 + languageName: node + linkType: hard + "iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2": version: 0.6.3 resolution: "iconv-lite@npm:0.6.3" @@ -9529,12 +10824,12 @@ __metadata: languageName: node linkType: hard -"iconv-lite@npm:^0.4.24": - version: 0.4.24 - resolution: "iconv-lite@npm:0.4.24" +"iconv-lite@npm:^0.5.2": + version: 0.5.2 + resolution: "iconv-lite@npm:0.5.2" dependencies: safer-buffer: "npm:>= 2.1.2 < 3" - checksum: 10c0/c6886a24cc00f2a059767440ec1bc00d334a89f250db8e0f7feb4961c8727118457e27c495ba94d082e51d3baca378726cd110aaf7ded8b9bbfd6a44760cf1d4 + checksum: 10c0/6c51c9996fe360b03f501c0f76f122f007c6a9be924cfdf0b007044cfbcdeeb9c9decb5435465934dbd3804f37e67fdc2fb3ed8c9948464299165776541dff25 languageName: node linkType: hard @@ -9630,7 +10925,7 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3": +"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 @@ -9739,6 +11034,13 @@ __metadata: languageName: node linkType: hard +"ipaddr.js@npm:1.9.1": + version: 1.9.1 + resolution: "ipaddr.js@npm:1.9.1" + checksum: 10c0/0486e775047971d3fdb5fb4f063829bac45af299ae0b82dcf3afa2145338e08290563a2a70f34b732d795ecc8311902e541a8530eeb30d75860a78ff4e94ce2a + languageName: node + linkType: hard + "is-arguments@npm:^1.1.1": version: 1.1.1 resolution: "is-arguments@npm:1.1.1" @@ -10135,6 +11437,13 @@ __metadata: languageName: node linkType: hard +"is-promise@npm:^4.0.0": + version: 4.0.0 + resolution: "is-promise@npm:4.0.0" + checksum: 10c0/ebd5c672d73db781ab33ccb155fb9969d6028e37414d609b115cc534654c91ccd061821d5b987eefaa97cf4c62f0b909bb2f04db88306de26e91bfe8ddc01503 + languageName: node + linkType: hard + "is-regex@npm:^1.1.4": version: 1.1.4 resolution: "is-regex@npm:1.1.4" @@ -11203,6 +12512,15 @@ __metadata: languageName: node linkType: hard +"lucide-react@npm:^0.447.0": + version: 0.447.0 + resolution: "lucide-react@npm:0.447.0" + peerDependencies: + react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc + checksum: 10c0/c8831795a4b4429d0cad28f33baf924d285eb64a0ecbce013a3307e7fab998cd5a48e3dce3607bbfa88fa383b8c603947965453acb60c94e2ef39956afe1eb67 + languageName: node + linkType: hard + "lunr@npm:^2.3.9": version: 2.3.9 resolution: "lunr@npm:2.3.9" @@ -11379,6 +12697,20 @@ __metadata: languageName: node linkType: hard +"media-typer@npm:0.3.0": + version: 0.3.0 + resolution: "media-typer@npm:0.3.0" + checksum: 10c0/d160f31246907e79fed398470285f21bafb45a62869dc469b1c8877f3f064f5eabc4bcc122f9479b8b605bc5c76187d7871cf84c4ee3ecd3e487da1993279928 + languageName: node + linkType: hard + +"media-typer@npm:^1.1.0": + version: 1.1.0 + resolution: "media-typer@npm:1.1.0" + checksum: 10c0/7b4baa40b25964bb90e2121ee489ec38642127e48d0cc2b6baa442688d3fde6262bfdca86d6bbf6ba708784afcac168c06840c71facac70e390f5f759ac121b9 + languageName: node + linkType: hard + "meow@npm:^8.1.2": version: 8.1.2 resolution: "meow@npm:8.1.2" @@ -11398,6 +12730,20 @@ __metadata: languageName: node linkType: hard +"merge-descriptors@npm:1.0.3": + version: 1.0.3 + resolution: "merge-descriptors@npm:1.0.3" + checksum: 10c0/866b7094afd9293b5ea5dcd82d71f80e51514bed33b4c4e9f516795dc366612a4cbb4dc94356e943a8a6914889a914530badff27f397191b9b75cda20b6bae93 + languageName: node + linkType: hard + +"merge-descriptors@npm:^2.0.0": + version: 2.0.0 + resolution: "merge-descriptors@npm:2.0.0" + checksum: 10c0/95389b7ced3f9b36fbdcf32eb946dc3dd1774c2fdf164609e55b18d03aa499b12bd3aae3a76c1c7185b96279e9803525550d3eb292b5224866060a288f335cb3 + languageName: node + linkType: hard + "merge-stream@npm:^2.0.0": version: 2.0.0 resolution: "merge-stream@npm:2.0.0" @@ -11412,6 +12758,13 @@ __metadata: languageName: node linkType: hard +"methods@npm:~1.1.2": + version: 1.1.2 + resolution: "methods@npm:1.1.2" + checksum: 10c0/bdf7cc72ff0a33e3eede03708c08983c4d7a173f91348b4b1e4f47d4cdbf734433ad971e7d1e8c77247d9e5cd8adb81ea4c67b0a2db526b758b2233d7814b8b2 + languageName: node + linkType: hard + "micromatch@npm:^4.0.4, micromatch@npm:^4.0.5, micromatch@npm:^4.0.8": version: 4.0.8 resolution: "micromatch@npm:4.0.8" @@ -11436,7 +12789,30 @@ __metadata: languageName: node linkType: hard -"mime-types@npm:^2.1.12": +"mime-db@npm:^1.53.0": + version: 1.53.0 + resolution: "mime-db@npm:1.53.0" + checksum: 10c0/1dcc37ba8ed5d1c179f5c6f0837e8db19371d5f2ea3690c3c2f3fa8c3858f976851d3460b172b4dee78ebd606762cbb407aa398545fbacd539e519f858cd7bf4 + languageName: node + linkType: hard + +"mime-db@npm:~1.33.0": + version: 1.33.0 + resolution: "mime-db@npm:1.33.0" + checksum: 10c0/79172ce5468c8503b49dddfdddc18d3f5fe2599f9b5fe1bc321a8cbee14c96730fc6db22f907b23701b05b2936f865795f62ec3a78a7f3c8cb2450bb68c6763e + languageName: node + linkType: hard + +"mime-types@npm:2.1.18": + version: 2.1.18 + resolution: "mime-types@npm:2.1.18" + dependencies: + mime-db: "npm:~1.33.0" + checksum: 10c0/a96a8d12f4bb98bc7bfac6a8ccbd045f40368fc1030d9366050c3613825d3715d1c1f393e10a75a885d2cdc1a26cd6d5e11f3a2a0d5c4d361f00242139430a0f + languageName: node + linkType: hard + +"mime-types@npm:^2.1.12, mime-types@npm:^2.1.35, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": version: 2.1.35 resolution: "mime-types@npm:2.1.35" dependencies: @@ -11454,7 +12830,16 @@ __metadata: languageName: node linkType: hard -"mime@npm:^1.6.0": +"mime-types@npm:^3.0.0": + version: 3.0.0 + resolution: "mime-types@npm:3.0.0" + dependencies: + mime-db: "npm:^1.53.0" + checksum: 10c0/8624501c75568f14e53fd9e12327fa18e70d6a85047c5beb9146990178f3adb31f893cb54d25ab58145cabf3e06c61953f2c5427ccd05b6b38fe09db8c5f5e7f + languageName: node + linkType: hard + +"mime@npm:1.6.0, mime@npm:^1.6.0": version: 1.6.0 resolution: "mime@npm:1.6.0" bin: @@ -11500,6 +12885,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:3.1.2, minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": + version: 3.1.2 + resolution: "minimatch@npm:3.1.2" + dependencies: + brace-expansion: "npm:^1.1.7" + checksum: 10c0/0262810a8fc2e72cca45d6fd86bd349eee435eb95ac6aa45c9ea2180e7ee875ef44c32b55b5973ceabe95ea12682f6e3725cbb63d7a2d1da3ae1163c8b210311 + languageName: node + linkType: hard + "minimatch@npm:9.0.3, minimatch@npm:^9.0.3": version: 9.0.3 resolution: "minimatch@npm:9.0.3" @@ -11509,15 +12903,6 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": - version: 3.1.2 - resolution: "minimatch@npm:3.1.2" - dependencies: - brace-expansion: "npm:^1.1.7" - checksum: 10c0/0262810a8fc2e72cca45d6fd86bd349eee435eb95ac6aa45c9ea2180e7ee875ef44c32b55b5973ceabe95ea12682f6e3725cbb63d7a2d1da3ae1163c8b210311 - languageName: node - linkType: hard - "minimatch@npm:^5.0.1": version: 5.1.6 resolution: "minimatch@npm:5.1.6" @@ -11737,6 +13122,13 @@ __metadata: languageName: node linkType: hard +"ms@npm:2.0.0": + version: 2.0.0 + resolution: "ms@npm:2.0.0" + checksum: 10c0/f8fda810b39fd7255bbdc451c46286e549794fcc700dc9cd1d25658bbc4dc2563a5de6fe7c60f798a16a60c6ceb53f033cb353f493f0cf63e5199b702943159d + languageName: node + linkType: hard + "ms@npm:2.1.2": version: 2.1.2 resolution: "ms@npm:2.1.2" @@ -11744,7 +13136,7 @@ __metadata: languageName: node linkType: hard -"ms@npm:^2.0.0, ms@npm:^2.1.1, ms@npm:^2.1.3": +"ms@npm:2.1.3, ms@npm:^2.0.0, ms@npm:^2.1.1, ms@npm:^2.1.3": version: 2.1.3 resolution: "ms@npm:2.1.3" checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48 @@ -11892,13 +13284,20 @@ __metadata: languageName: node linkType: hard -"negotiator@npm:^0.6.3": +"negotiator@npm:0.6.3, negotiator@npm:^0.6.3": version: 0.6.3 resolution: "negotiator@npm:0.6.3" checksum: 10c0/3ec9fd413e7bf071c937ae60d572bc67155262068ed522cf4b3be5edbe6ddf67d095ec03a3a14ebf8fc8e95f8e1d61be4869db0dbb0de696f6b837358bd43fc2 languageName: node linkType: hard +"negotiator@npm:^1.0.0": + version: 1.0.0 + resolution: "negotiator@npm:1.0.0" + checksum: 10c0/4c559dd52669ea48e1914f9d634227c561221dd54734070791f999c52ed0ff36e437b2e07d5c1f6e32909fc625fe46491c16e4a8f0572567d4dd15c3a4fda04b + languageName: node + linkType: hard + "neo-async@npm:^2.6.2": version: 2.6.2 resolution: "neo-async@npm:2.6.2" @@ -12421,7 +13820,7 @@ __metadata: languageName: node linkType: hard -"object-assign@npm:^4.0.1, object-assign@npm:^4.1.1": +"object-assign@npm:^4, object-assign@npm:^4.0.1, object-assign@npm:^4.1.1": version: 4.1.1 resolution: "object-assign@npm:4.1.1" checksum: 10c0/1f4df9945120325d041ccf7b86f31e8bcc14e73d29171e37a7903050e96b81323784ec59f93f102ec635bcf6fa8034ba3ea0a8c7e69fa202b87ae3b6cec5a414 @@ -12602,7 +14001,16 @@ __metadata: languageName: node linkType: hard -"once@npm:^1.3.0, once@npm:^1.4.0": +"on-finished@npm:2.4.1, on-finished@npm:^2.4.1": + version: 2.4.1 + resolution: "on-finished@npm:2.4.1" + dependencies: + ee-first: "npm:1.1.1" + checksum: 10c0/46fb11b9063782f2d9968863d9cbba33d77aa13c17f895f56129c274318b86500b22af3a160fe9995aa41317efcd22941b6eba747f718ced08d9a73afdb087b4 + languageName: node + linkType: hard + +"once@npm:1.4.0, once@npm:^1.3.0, once@npm:^1.4.0": version: 1.4.0 resolution: "once@npm:1.4.0" dependencies: @@ -13012,6 +14420,13 @@ __metadata: languageName: node linkType: hard +"parseurl@npm:^1.3.3, parseurl@npm:~1.3.3": + version: 1.3.3 + resolution: "parseurl@npm:1.3.3" + checksum: 10c0/90dd4760d6f6174adb9f20cf0965ae12e23879b5f5464f38e92fce8073354341e4b3b76fa3d878351efe7d01e617121955284cfd002ab087fba1a0726ec0b4f5 + languageName: node + linkType: hard + "path-browserify@npm:^1.0.1": version: 1.0.1 resolution: "path-browserify@npm:1.0.1" @@ -13047,6 +14462,13 @@ __metadata: languageName: node linkType: hard +"path-is-inside@npm:1.0.2": + version: 1.0.2 + resolution: "path-is-inside@npm:1.0.2" + checksum: 10c0/7fdd4b41672c70461cce734fc222b33e7b447fa489c7c4377c95e7e6852d83d69741f307d88ec0cc3b385b41cb4accc6efac3c7c511cd18512e95424f5fa980c + languageName: node + linkType: hard + "path-key@npm:^3.0.0, path-key@npm:^3.1.0": version: 3.1.1 resolution: "path-key@npm:3.1.1" @@ -13088,6 +14510,20 @@ __metadata: languageName: node linkType: hard +"path-to-regexp@npm:0.1.12": + version: 0.1.12 + resolution: "path-to-regexp@npm:0.1.12" + checksum: 10c0/1c6ff10ca169b773f3bba943bbc6a07182e332464704572962d277b900aeee81ac6aa5d060ff9e01149636c30b1f63af6e69dd7786ba6e0ddb39d4dee1f0645b + languageName: node + linkType: hard + +"path-to-regexp@npm:3.3.0": + version: 3.3.0 + resolution: "path-to-regexp@npm:3.3.0" + checksum: 10c0/ffa0ebe7088d38d435a8d08b0fe6e8c93ceb2a81a65d4dd1d9a538f52e09d5e3474ed5f553cb3b180d894b0caa10698a68737ab599fd1e56b4663d1a64c9f77b + languageName: node + linkType: hard + "path-to-regexp@npm:^6.2.0": version: 6.3.0 resolution: "path-to-regexp@npm:6.3.0" @@ -13095,6 +14531,13 @@ __metadata: languageName: node linkType: hard +"path-to-regexp@npm:^8.0.0": + version: 8.2.0 + resolution: "path-to-regexp@npm:8.2.0" + checksum: 10c0/ef7d0a887b603c0a142fad16ccebdcdc42910f0b14830517c724466ad676107476bba2fe9fffd28fd4c141391ccd42ea426f32bb44c2c82ecaefe10c37b90f5a + languageName: node + linkType: hard + "path-type@npm:^3.0.0": version: 3.0.0 resolution: "path-type@npm:3.0.0" @@ -13216,6 +14659,13 @@ __metadata: languageName: node linkType: hard +"pkce-challenge@npm:^4.1.0": + version: 4.1.0 + resolution: "pkce-challenge@npm:4.1.0" + checksum: 10c0/7cdc45977eb9af6f561a6f48ffcf19bd3e6f0c651727d00feef1c501384b1ed3c32d92ee67636f02011168959aedf099003a7c0bed668e7943444b20558c54e4 + languageName: node + linkType: hard + "pkg-dir@npm:^4.2.0": version: 4.2.0 resolution: "pkg-dir@npm:4.2.0" @@ -13833,6 +15283,13 @@ __metadata: languageName: node linkType: hard +"prismjs@npm:^1.29.0": + version: 1.30.0 + resolution: "prismjs@npm:1.30.0" + checksum: 10c0/f56205bfd58ef71ccfcbcb691fd0eb84adc96c6ff21b0b69fc6fdcf02be42d6ef972ba4aed60466310de3d67733f6a746f89f2fb79c00bf217406d465b3e8f23 + languageName: node + linkType: hard + "proc-log@npm:^3.0.0": version: 3.0.0 resolution: "proc-log@npm:3.0.0" @@ -13905,6 +15362,16 @@ __metadata: languageName: node linkType: hard +"proxy-addr@npm:~2.0.7": + version: 2.0.7 + resolution: "proxy-addr@npm:2.0.7" + dependencies: + forwarded: "npm:0.2.0" + ipaddr.js: "npm:1.9.1" + checksum: 10c0/c3eed999781a35f7fd935f398b6d8920b6fb00bbc14287bc6de78128ccc1a02c89b95b56742bf7cf0362cc333c61d138532049c7dedc7a328ef13343eff81210 + languageName: node + linkType: hard + "proxy-from-env@npm:^1.1.0": version: 1.1.0 resolution: "proxy-from-env@npm:1.1.0" @@ -13947,7 +15414,16 @@ __metadata: languageName: node linkType: hard -"qs@npm:^6.4.0": +"qs@npm:6.13.0": + version: 6.13.0 + resolution: "qs@npm:6.13.0" + dependencies: + side-channel: "npm:^1.0.6" + checksum: 10c0/62372cdeec24dc83a9fb240b7533c0fdcf0c5f7e0b83343edd7310f0ab4c8205a5e7c56406531f2e47e1b4878a3821d652be4192c841de5b032ca83619d8f860 + languageName: node + linkType: hard + +"qs@npm:^6.14.0, qs@npm:^6.4.0": version: 6.14.0 resolution: "qs@npm:6.14.0" dependencies: @@ -13986,7 +15462,45 @@ __metadata: languageName: node linkType: hard -"react-dom@npm:*, react-dom@npm:^18": +"range-parser@npm:1.2.0": + version: 1.2.0 + resolution: "range-parser@npm:1.2.0" + checksum: 10c0/c7aef4f6588eb974c475649c157f197d07437d8c6c8ff7e36280a141463fb5ab7a45918417334ebd7b665c6b8321cf31c763f7631dd5f5db9372249261b8b02a + languageName: node + linkType: hard + +"range-parser@npm:^1.2.1, range-parser@npm:~1.2.1": + version: 1.2.1 + resolution: "range-parser@npm:1.2.1" + checksum: 10c0/96c032ac2475c8027b7a4e9fe22dc0dfe0f6d90b85e496e0f016fbdb99d6d066de0112e680805075bd989905e2123b3b3d002765149294dce0c1f7f01fcc2ea0 + languageName: node + linkType: hard + +"raw-body@npm:2.5.2": + version: 2.5.2 + resolution: "raw-body@npm:2.5.2" + dependencies: + bytes: "npm:3.1.2" + http-errors: "npm:2.0.0" + iconv-lite: "npm:0.4.24" + unpipe: "npm:1.0.0" + checksum: 10c0/b201c4b66049369a60e766318caff5cb3cc5a900efd89bdac431463822d976ad0670912c931fdbdcf5543207daf6f6833bca57aa116e1661d2ea91e12ca692c4 + languageName: node + linkType: hard + +"raw-body@npm:^3.0.0": + version: 3.0.0 + resolution: "raw-body@npm:3.0.0" + dependencies: + bytes: "npm:3.1.2" + http-errors: "npm:2.0.0" + iconv-lite: "npm:0.6.3" + unpipe: "npm:1.0.0" + checksum: 10c0/f8daf4b724064a4811d118745a781ca0fb4676298b8adadfd6591155549cfea0a067523cf7dd3baeb1265fecc9ce5dfb2fc788c12c66b85202a336593ece0f87 + languageName: node + linkType: hard + +"react-dom@npm:*, react-dom@npm:^18, react-dom@npm:^18.3.1": version: 18.3.1 resolution: "react-dom@npm:18.3.1" dependencies: @@ -14019,7 +15533,80 @@ __metadata: languageName: node linkType: hard -"react@npm:*, react@npm:^18": +"react-remove-scroll-bar@npm:^2.3.7": + version: 2.3.8 + resolution: "react-remove-scroll-bar@npm:2.3.8" + dependencies: + react-style-singleton: "npm:^2.2.2" + tslib: "npm:^2.0.0" + peerDependencies: + "@types/react": "*" + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/9a0675c66cbb52c325bdbfaed80987a829c4504cefd8ff2dd3b6b3afc9a1500b8ec57b212e92c1fb654396d07bbe18830a8146fe77677d2a29ce40b5e1f78654 + languageName: node + linkType: hard + +"react-remove-scroll@npm:^2.6.3": + version: 2.6.3 + resolution: "react-remove-scroll@npm:2.6.3" + dependencies: + react-remove-scroll-bar: "npm:^2.3.7" + react-style-singleton: "npm:^2.2.3" + tslib: "npm:^2.1.0" + use-callback-ref: "npm:^1.3.3" + use-sidecar: "npm:^1.1.3" + peerDependencies: + "@types/react": "*" + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/068e9704ff26816fffc4c8903e2c6c8df7291ee08615d7c1ab0cf8751f7080e2c5a5d78ef5d908b11b9cfc189f176d312e44cb02ea291ca0466d8283b479b438 + languageName: node + linkType: hard + +"react-simple-code-editor@npm:^0.14.1": + version: 0.14.1 + resolution: "react-simple-code-editor@npm:0.14.1" + peerDependencies: + react: ">=16.8.0" + react-dom: ">=16.8.0" + checksum: 10c0/63264fce03315c80de4fc65b9e0a30b359cb0a6c269a90ad67ccff36c21d0f3ba1f9ac9bdfbe76477fc9a6d7033182debc64a58345f4914f0bc0b416eb686e61 + languageName: node + linkType: hard + +"react-style-singleton@npm:^2.2.2, react-style-singleton@npm:^2.2.3": + version: 2.2.3 + resolution: "react-style-singleton@npm:2.2.3" + dependencies: + get-nonce: "npm:^1.0.0" + tslib: "npm:^2.0.0" + peerDependencies: + "@types/react": "*" + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/841938ff16d16a6b76895f4cb2e1fea957e5fe3b30febbf03a54892dae1c9153f2383e231dea0b3ba41192ad2f2849448fa859caccd288943bce32639e971bee + languageName: node + linkType: hard + +"react-toastify@npm:^10.0.6": + version: 10.0.6 + resolution: "react-toastify@npm:10.0.6" + dependencies: + clsx: "npm:^2.1.0" + peerDependencies: + react: ">=18" + react-dom: ">=18" + checksum: 10c0/4042b716d008295d0feab32488d1e88ec655a1b7a9176fa7d253c70387578a8a0c04aca0ff86d20e1722f3b4baadae8970f50f462940d67a90453c307dd350a9 + languageName: node + linkType: hard + +"react@npm:*, react@npm:^18, react@npm:^18.3.1": version: 18.3.1 resolution: "react@npm:18.3.1" dependencies: @@ -14790,6 +16377,17 @@ __metadata: languageName: node linkType: hard +"router@npm:^2.0.0": + version: 2.1.0 + resolution: "router@npm:2.1.0" + dependencies: + is-promise: "npm:^4.0.0" + parseurl: "npm:^1.3.3" + path-to-regexp: "npm:^8.0.0" + checksum: 10c0/df17c5c07210cb72922185ea9378b318676c1e1af9110c52cfa8339bff43004f240cb6660d3b23c932f7867ab6a3ed3fe9d8e8fb0d7ac7402d0b7e7a59f9ba07 + languageName: node + linkType: hard + "rrweb-cssom@npm:^0.6.0": version: 0.6.0 resolution: "rrweb-cssom@npm:0.6.0" @@ -14836,6 +16434,15 @@ __metadata: languageName: node linkType: hard +"rxjs@npm:^7.8.1": + version: 7.8.2 + resolution: "rxjs@npm:7.8.2" + dependencies: + tslib: "npm:^2.1.0" + checksum: 10c0/1fcd33d2066ada98ba8f21fcbbcaee9f0b271de1d38dc7f4e256bfbc6ffcdde68c8bfb69093de7eeb46f24b1fb820620bf0223706cff26b4ab99a7ff7b2e2c45 + languageName: node + linkType: hard + "safe-array-concat@npm:^1.0.1": version: 1.0.1 resolution: "safe-array-concat@npm:1.0.1" @@ -14880,7 +16487,7 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:^5.1.0, safe-buffer@npm:~5.2.0": +"safe-buffer@npm:5.2.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:~5.2.0": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 @@ -15031,6 +16638,47 @@ __metadata: languageName: node linkType: hard +"send@npm:0.19.0": + version: 0.19.0 + resolution: "send@npm:0.19.0" + dependencies: + debug: "npm:2.6.9" + depd: "npm:2.0.0" + destroy: "npm:1.2.0" + encodeurl: "npm:~1.0.2" + escape-html: "npm:~1.0.3" + etag: "npm:~1.8.1" + fresh: "npm:0.5.2" + http-errors: "npm:2.0.0" + mime: "npm:1.6.0" + ms: "npm:2.1.3" + on-finished: "npm:2.4.1" + range-parser: "npm:~1.2.1" + statuses: "npm:2.0.1" + checksum: 10c0/ea3f8a67a8f0be3d6bf9080f0baed6d2c51d11d4f7b4470de96a5029c598a7011c497511ccc28968b70ef05508675cebff27da9151dd2ceadd60be4e6cf845e3 + languageName: node + linkType: hard + +"send@npm:^1.0.0, send@npm:^1.1.0": + version: 1.1.0 + resolution: "send@npm:1.1.0" + dependencies: + debug: "npm:^4.3.5" + destroy: "npm:^1.2.0" + encodeurl: "npm:^2.0.0" + escape-html: "npm:^1.0.3" + etag: "npm:^1.8.1" + fresh: "npm:^0.5.2" + http-errors: "npm:^2.0.0" + mime-types: "npm:^2.1.35" + ms: "npm:^2.1.3" + on-finished: "npm:^2.4.1" + range-parser: "npm:^1.2.1" + statuses: "npm:^2.0.1" + checksum: 10c0/0d73408bccfd008bb50cb97225434cf565f653b66cb7961befa962a321a936eaefa6c481a1a9c30606f341afb1f08d990bcbf44949f48a68e06d63344eb91105 + languageName: node + linkType: hard + "serialize-javascript@npm:^6.0.1": version: 6.0.2 resolution: "serialize-javascript@npm:6.0.2" @@ -15040,6 +16688,45 @@ __metadata: languageName: node linkType: hard +"serve-handler@npm:^6.1.6": + version: 6.1.6 + resolution: "serve-handler@npm:6.1.6" + dependencies: + bytes: "npm:3.0.0" + content-disposition: "npm:0.5.2" + mime-types: "npm:2.1.18" + minimatch: "npm:3.1.2" + path-is-inside: "npm:1.0.2" + path-to-regexp: "npm:3.3.0" + range-parser: "npm:1.2.0" + checksum: 10c0/1e1cb6bbc51ee32bc1505f2e0605bdc2e96605c522277c977b67f83be9d66bd1eec8604388714a4d728e036d86b629bc9aec02120ea030d3d2c3899d44696503 + languageName: node + linkType: hard + +"serve-static@npm:1.16.2": + version: 1.16.2 + resolution: "serve-static@npm:1.16.2" + dependencies: + encodeurl: "npm:~2.0.0" + escape-html: "npm:~1.0.3" + parseurl: "npm:~1.3.3" + send: "npm:0.19.0" + checksum: 10c0/528fff6f5e12d0c5a391229ad893910709bc51b5705962b09404a1d813857578149b8815f35d3ee5752f44cd378d0f31669d4b1d7e2d11f41e08283d5134bd1f + languageName: node + linkType: hard + +"serve-static@npm:^2.1.0": + version: 2.1.0 + resolution: "serve-static@npm:2.1.0" + dependencies: + encodeurl: "npm:^2.0.0" + escape-html: "npm:^1.0.3" + parseurl: "npm:^1.3.3" + send: "npm:^1.0.0" + checksum: 10c0/f5b36fd3a763cdb4bf367c9be2eff587c0e52685fcf9109aa28428457c4aad0f83d8b6a1bf4929488963270026f3647f2d221c898e6dbdf9f4f5b09ed0b1f51a + languageName: node + linkType: hard + "set-blocking@npm:^2.0.0": version: 2.0.0 resolution: "set-blocking@npm:2.0.0" @@ -15107,6 +16794,13 @@ __metadata: languageName: node linkType: hard +"setprototypeof@npm:1.2.0": + version: 1.2.0 + resolution: "setprototypeof@npm:1.2.0" + checksum: 10c0/68733173026766fa0d9ecaeb07f0483f4c2dc70ca376b3b7c40b7cda909f94b0918f6c5ad5ce27a9160bdfb475efaa9d5e705a11d8eaae18f9835d20976028bc + languageName: node + linkType: hard + "shallow-clone@npm:^3.0.0": version: 3.0.1 resolution: "shallow-clone@npm:3.0.1" @@ -15132,6 +16826,13 @@ __metadata: languageName: node linkType: hard +"shell-quote@npm:^1.8.1, shell-quote@npm:^1.8.2": + version: 1.8.2 + resolution: "shell-quote@npm:1.8.2" + checksum: 10c0/85fdd44f2ad76e723d34eb72c753f04d847ab64e9f1f10677e3f518d0e5b0752a176fd805297b30bb8c3a1556ebe6e77d2288dbd7b7b0110c7e941e9e9c20ce1 + languageName: node + linkType: hard + "shelljs@npm:^0.8.5": version: 0.8.5 resolution: "shelljs@npm:0.8.5" @@ -15380,6 +17081,16 @@ __metadata: languageName: node linkType: hard +"spawn-rx@npm:^5.1.2": + version: 5.1.2 + resolution: "spawn-rx@npm:5.1.2" + dependencies: + debug: "npm:^4.3.7" + rxjs: "npm:^7.8.1" + checksum: 10c0/1a8572da209161063c5ed25b44d5b5bd786ceb51c15d355e499c518feb1da675004fb40e3f20f653025a2ec2feb4c676d1e52cc2ed0fa40ae65e40cc972d60cd + languageName: node + linkType: hard + "spdx-correct@npm:^3.0.0": version: 3.2.0 resolution: "spdx-correct@npm:3.2.0" @@ -15478,7 +17189,7 @@ __metadata: languageName: node linkType: hard -"statuses@npm:^2.0.1": +"statuses@npm:2.0.1, statuses@npm:^2.0.1": version: 2.0.1 resolution: "statuses@npm:2.0.1" checksum: 10c0/34378b207a1620a24804ce8b5d230fea0c279f00b18a7209646d5d47e419d1cc23e7cbf33a25a1e51ac38973dc2ac2e1e9c647a8e481ef365f77668d72becfd0 @@ -15878,7 +17589,7 @@ __metadata: languageName: node linkType: hard -"supports-color@npm:^8.0.0, supports-color@npm:~8.1.1": +"supports-color@npm:^8.0.0, supports-color@npm:^8.1.1, supports-color@npm:~8.1.1": version: 8.1.1 resolution: "supports-color@npm:8.1.1" dependencies: @@ -15901,6 +17612,22 @@ __metadata: languageName: node linkType: hard +"tailwind-merge@npm:^2.5.3": + version: 2.6.0 + resolution: "tailwind-merge@npm:2.6.0" + checksum: 10c0/fc8a5535524de9f4dacf1c16ab298581c7bb757d68a95faaf28942b1c555a619bba9d4c6726fe83986e44973b315410c1a5226e5354c30ba82353bd6d2288fa5 + languageName: node + linkType: hard + +"tailwindcss-animate@npm:^1.0.7": + version: 1.0.7 + resolution: "tailwindcss-animate@npm:1.0.7" + peerDependencies: + tailwindcss: "*" + checksum: 10c0/ec7dbd1631076b97d66a1fbaaa06e0725fccfa63119221e8d87a997b02dcede98ad88bb1ef6665b968f5d260fcefb10592e0299ca70208d365b37761edf5e19a + languageName: node + linkType: hard + "tailwindcss@npm:^3.4.1": version: 3.4.6 resolution: "tailwindcss@npm:3.4.6" @@ -16187,6 +17914,13 @@ __metadata: languageName: node linkType: hard +"toidentifier@npm:1.0.1": + version: 1.0.1 + resolution: "toidentifier@npm:1.0.1" + checksum: 10c0/93937279934bd66cc3270016dd8d0afec14fb7c94a05c72dc57321f8bd1fa97e5bea6d1f7c89e728d077ca31ea125b78320a616a6c6cd0e6b9cb94cb864381c1 + languageName: node + linkType: hard + "tough-cookie@npm:^4.1.4": version: 4.1.4 resolution: "tough-cookie@npm:4.1.4" @@ -16215,6 +17949,15 @@ __metadata: languageName: node linkType: hard +"tree-kill@npm:^1.2.2": + version: 1.2.2 + resolution: "tree-kill@npm:1.2.2" + bin: + tree-kill: cli.js + checksum: 10c0/7b1b7c7f17608a8f8d20a162e7957ac1ef6cd1636db1aba92f4e072dc31818c2ff0efac1e3d91064ede67ed5dc57c565420531a8134090a12ac10cf792ab14d2 + languageName: node + linkType: hard + "trim-newlines@npm:^3.0.0": version: 3.0.1 resolution: "trim-newlines@npm:3.0.1" @@ -16308,6 +18051,13 @@ __metadata: languageName: node linkType: hard +"tslib@npm:^2.0.0": + version: 2.8.1 + resolution: "tslib@npm:2.8.1" + checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62 + languageName: node + linkType: hard + "tslib@npm:^2.1.0, tslib@npm:^2.3.0, tslib@npm:^2.4.0": version: 2.6.2 resolution: "tslib@npm:2.6.2" @@ -16409,6 +18159,27 @@ __metadata: languageName: node linkType: hard +"type-is@npm:^2.0.0": + version: 2.0.0 + resolution: "type-is@npm:2.0.0" + dependencies: + content-type: "npm:^1.0.5" + media-typer: "npm:^1.1.0" + mime-types: "npm:^3.0.0" + checksum: 10c0/c1fa697c8cb77bcb3f4aa3673a3fdbe3f1c2fe51ce8c9736e9773f25c3118562723369b471063c3945722bcda5d8bf969a0693ab7b6e7da012ff667294efe988 + languageName: node + linkType: hard + +"type-is@npm:~1.6.18": + version: 1.6.18 + resolution: "type-is@npm:1.6.18" + dependencies: + media-typer: "npm:0.3.0" + mime-types: "npm:~2.1.24" + checksum: 10c0/a23daeb538591b7efbd61ecf06b6feb2501b683ffdc9a19c74ef5baba362b4347e42f1b4ed81f5882a8c96a3bfff7f93ce3ffaf0cbbc879b532b04c97a55db9d + languageName: node + linkType: hard + "typed-array-buffer@npm:^1.0.0": version: 1.0.0 resolution: "typed-array-buffer@npm:1.0.0" @@ -16824,6 +18595,13 @@ __metadata: languageName: node linkType: hard +"unpipe@npm:1.0.0, unpipe@npm:~1.0.0": + version: 1.0.0 + resolution: "unpipe@npm:1.0.0" + checksum: 10c0/193400255bd48968e5c5383730344fbb4fa114cdedfab26e329e50dd2d81b134244bb8a72c6ac1b10ab0281a58b363d06405632c9d49ca9dfd5e90cbd7d0f32c + languageName: node + linkType: hard + "upath@npm:2.0.1": version: 2.0.1 resolution: "upath@npm:2.0.1" @@ -16885,6 +18663,37 @@ __metadata: languageName: node linkType: hard +"use-callback-ref@npm:^1.3.3": + version: 1.3.3 + resolution: "use-callback-ref@npm:1.3.3" + dependencies: + tslib: "npm:^2.0.0" + peerDependencies: + "@types/react": "*" + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/f887488c6e6075cdad4962979da1714b217bcb1ee009a9e57ce9a844bcfc4c3a99e93983dfc2e5af9e0913824d24e730090ff255e902c516dcb58d2d3837e01c + languageName: node + linkType: hard + +"use-sidecar@npm:^1.1.3": + version: 1.1.3 + resolution: "use-sidecar@npm:1.1.3" + dependencies: + detect-node-es: "npm:^1.1.0" + tslib: "npm:^2.0.0" + peerDependencies: + "@types/react": "*" + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/161599bf921cfaa41c85d2b01c871975ee99260f3e874c2d41c05890d41170297bdcf314bc5185e7a700de2034ac5b888e3efc8e9f35724f4918f53538d717c9 + languageName: node + linkType: hard + "util-deprecate@npm:^1.0.1, util-deprecate@npm:^1.0.2, util-deprecate@npm:~1.0.1": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2" @@ -16892,6 +18701,13 @@ __metadata: languageName: node linkType: hard +"utils-merge@npm:1.0.1": + version: 1.0.1 + resolution: "utils-merge@npm:1.0.1" + checksum: 10c0/02ba649de1b7ca8854bfe20a82f1dfbdda3fb57a22ab4a8972a63a34553cf7aa51bc9081cf7e001b035b88186d23689d69e71b510e610a09a4c66f68aa95b672 + languageName: node + linkType: hard + "uuid@npm:^9.0.0": version: 9.0.1 resolution: "uuid@npm:9.0.1" @@ -16961,6 +18777,13 @@ __metadata: languageName: node linkType: hard +"vary@npm:^1, vary@npm:~1.1.2": + version: 1.1.2 + resolution: "vary@npm:1.1.2" + checksum: 10c0/f15d588d79f3675135ba783c91a4083dcd290a2a5be9fcb6514220a1634e23df116847b1cc51f66bfb0644cf9353b2abb7815ae499bab06e46dd33c1a6bf1f4f + languageName: node + linkType: hard + "vite-node@npm:1.6.1": version: 1.6.1 resolution: "vite-node@npm:1.6.1" @@ -17862,6 +19685,21 @@ __metadata: languageName: node linkType: hard +"ws@npm:^8.18.0": + version: 8.18.1 + resolution: "ws@npm:8.18.1" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 10c0/e498965d6938c63058c4310ffb6967f07d4fa06789d3364829028af380d299fe05762961742971c764973dce3d1f6a2633fe8b2d9410c9b52e534b4b882a99fa + languageName: node + linkType: hard + "xml-name-validator@npm:^5.0.0": version: 5.0.0 resolution: "xml-name-validator@npm:5.0.0" @@ -18010,3 +19848,19 @@ __metadata: checksum: 10c0/3242da6b2d8da3bc9a66876ef01a1d5f0d0ad7bd70b0e3e24f5dc6ef5f6213e6e660f14f3dceee9b000692a47b86b365c0ea43b5340153efcb2808ccbfb3fc6f languageName: node linkType: hard + +"zod-to-json-schema@npm:^3.24.1": + version: 3.24.3 + resolution: "zod-to-json-schema@npm:3.24.3" + peerDependencies: + zod: ^3.24.1 + checksum: 10c0/5d626fa7a51539236962b1348a7b7e7111bd1722f23ad06dead2f76599e6bd918e4067ffba0695e0acac5a60f217b4953d2ad62ad403a482d034d94f025f3a4c + languageName: node + linkType: hard + +"zod@npm:^3.23.8, zod@npm:^3.24.2": + version: 3.24.2 + resolution: "zod@npm:3.24.2" + checksum: 10c0/c638c7220150847f13ad90635b3e7d0321b36cce36f3fc6050ed960689594c949c326dfe2c6fa87c14b126ee5d370ccdebd6efb304f41ef5557a4aaca2824565 + languageName: node + linkType: hard