From be959f7388aae147369b3f080bd0bc0aa7aa4429 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Tue, 17 Feb 2026 08:26:15 +0000 Subject: [PATCH 01/23] feat(codegen): add CLI command generator from GraphQL schema - Add cli config option (CliConfig | boolean) to GraphQLSDKConfigTarget - Add komoji dependency for toKebabCase casing - Create CLI generator orchestrator (cli/index.ts) - Create arg-mapper: converts CleanTypeRef to inquirerer Question[] - Create infra-generator: context + auth commands via Babel AST - Create executor-generator: ORM client init with appstash credentials - Create table-command-generator: per-table CRUD using ORM methods - Create custom-command-generator: per-operation using ORM methods - Create command-map-generator: command registry (Record) - Wire CLI generation into generate.ts alongside ORM/React Query - Update root barrel to include CLI exports Architecture: CLI -> ORM -> GraphQL (not CLI -> raw GraphQL) CLI commands: prompt for args -> call ORM method -> print JSON result Uses appstash@0.4.0 config-store for context/credential management --- graphql/codegen/package.json | 1 + graphql/codegen/src/core/codegen/barrel.ts | 8 +- .../src/core/codegen/cli/arg-mapper.ts | 139 + .../core/codegen/cli/command-map-generator.ts | 382 + .../codegen/cli/custom-command-generator.ts | 255 + .../core/codegen/cli/executor-generator.ts | 218 + graphql/codegen/src/core/codegen/cli/index.ts | 91 + .../src/core/codegen/cli/infra-generator.ts | 2054 +++ .../codegen/cli/table-command-generator.ts | 647 + graphql/codegen/src/core/generate.ts | 32 +- graphql/codegen/src/types/config.ts | 18 + pnpm-lock.yaml | 10871 ++++------------ 12 files changed, 6621 insertions(+), 8095 deletions(-) create mode 100644 graphql/codegen/src/core/codegen/cli/arg-mapper.ts create mode 100644 graphql/codegen/src/core/codegen/cli/command-map-generator.ts create mode 100644 graphql/codegen/src/core/codegen/cli/custom-command-generator.ts create mode 100644 graphql/codegen/src/core/codegen/cli/executor-generator.ts create mode 100644 graphql/codegen/src/core/codegen/cli/index.ts create mode 100644 graphql/codegen/src/core/codegen/cli/infra-generator.ts create mode 100644 graphql/codegen/src/core/codegen/cli/table-command-generator.ts diff --git a/graphql/codegen/package.json b/graphql/codegen/package.json index ac766470e..d55395a78 100644 --- a/graphql/codegen/package.json +++ b/graphql/codegen/package.json @@ -68,6 +68,7 @@ "inflekt": "^0.3.1", "inquirerer": "^4.4.0", "jiti": "^2.6.1", + "komoji": "^0.8.0", "oxfmt": "^0.26.0", "pg-cache": "workspace:^", "pg-env": "workspace:^", diff --git a/graphql/codegen/src/core/codegen/barrel.ts b/graphql/codegen/src/core/codegen/barrel.ts index 64032e99c..5321f0ff8 100644 --- a/graphql/codegen/src/core/codegen/barrel.ts +++ b/graphql/codegen/src/core/codegen/barrel.ts @@ -195,6 +195,7 @@ export interface RootBarrelOptions { hasTypes?: boolean; hasHooks?: boolean; hasOrm?: boolean; + hasCli?: boolean; } /** @@ -202,7 +203,7 @@ export interface RootBarrelOptions { * Re-exports from subdirectories based on which generators are enabled. */ export function generateRootBarrel(options: RootBarrelOptions = {}): string { - const { hasTypes = false, hasHooks = false, hasOrm = false } = options; + const { hasTypes = false, hasHooks = false, hasOrm = false, hasCli = false } = options; const statements: t.Statement[] = []; if (hasTypes) { @@ -214,8 +215,11 @@ export function generateRootBarrel(options: RootBarrelOptions = {}): string { if (hasOrm) { statements.push(exportAllFrom('./orm')); } + if (hasCli) { + statements.push(exportAllFrom('./cli')); + } - // Add file header as leading comment on first statement + // Add file headeras leading comment on first statement if (statements.length > 0) { addJSDocComment(statements[0], [ 'Generated SDK - auto-generated, do not edit', diff --git a/graphql/codegen/src/core/codegen/cli/arg-mapper.ts b/graphql/codegen/src/core/codegen/cli/arg-mapper.ts new file mode 100644 index 000000000..f560166ce --- /dev/null +++ b/graphql/codegen/src/core/codegen/cli/arg-mapper.ts @@ -0,0 +1,139 @@ +import * as t from '@babel/types'; + +import type { CleanArgument, CleanTypeRef } from '../../../types/schema'; + +function unwrapNonNull(typeRef: CleanTypeRef): { inner: CleanTypeRef; required: boolean } { + if (typeRef.kind === 'NON_NULL' && typeRef.ofType) { + return { inner: typeRef.ofType, required: true }; + } + return { inner: typeRef, required: false }; +} + +function resolveBaseType(typeRef: CleanTypeRef): CleanTypeRef { + if ((typeRef.kind === 'NON_NULL' || typeRef.kind === 'LIST') && typeRef.ofType) { + return resolveBaseType(typeRef.ofType); + } + return typeRef; +} + +export function buildQuestionObject(arg: CleanArgument): t.ObjectExpression { + const { inner, required } = unwrapNonNull(arg.type); + const base = resolveBaseType(arg.type); + const props: t.ObjectProperty[] = []; + + if (base.kind === 'ENUM' && base.enumValues && base.enumValues.length > 0) { + props.push( + t.objectProperty(t.identifier('type'), t.stringLiteral('autocomplete')), + ); + props.push( + t.objectProperty(t.identifier('name'), t.stringLiteral(arg.name)), + ); + props.push( + t.objectProperty( + t.identifier('message'), + t.stringLiteral(arg.description || arg.name), + ), + ); + props.push( + t.objectProperty( + t.identifier('options'), + t.arrayExpression(base.enumValues.map((v) => t.stringLiteral(v))), + ), + ); + } else if (base.kind === 'SCALAR' && base.name === 'Boolean') { + props.push( + t.objectProperty(t.identifier('type'), t.stringLiteral('confirm')), + ); + props.push( + t.objectProperty(t.identifier('name'), t.stringLiteral(arg.name)), + ); + props.push( + t.objectProperty( + t.identifier('message'), + t.stringLiteral(arg.description || arg.name), + ), + ); + props.push( + t.objectProperty(t.identifier('default'), t.booleanLiteral(false)), + ); + } else if ( + base.kind === 'SCALAR' && + (base.name === 'Int' || base.name === 'Float') + ) { + props.push( + t.objectProperty(t.identifier('type'), t.stringLiteral('text')), + ); + props.push( + t.objectProperty(t.identifier('name'), t.stringLiteral(arg.name)), + ); + props.push( + t.objectProperty( + t.identifier('message'), + t.stringLiteral(arg.description || `${arg.name} (number)`), + ), + ); + } else if (inner.kind === 'INPUT_OBJECT' && inner.inputFields) { + return buildInputObjectQuestion(arg.name, inner, required); + } else { + props.push( + t.objectProperty(t.identifier('type'), t.stringLiteral('text')), + ); + props.push( + t.objectProperty(t.identifier('name'), t.stringLiteral(arg.name)), + ); + props.push( + t.objectProperty( + t.identifier('message'), + t.stringLiteral(arg.description || arg.name), + ), + ); + } + + if (required) { + props.push( + t.objectProperty(t.identifier('required'), t.booleanLiteral(true)), + ); + } + + return t.objectExpression(props); +} + +function buildInputObjectQuestion( + _name: string, + typeRef: CleanTypeRef, + _required: boolean, +): t.ObjectExpression { + if (typeRef.inputFields && typeRef.inputFields.length > 0) { + const firstField = typeRef.inputFields[0]; + return buildQuestionObject(firstField); + } + return t.objectExpression([ + t.objectProperty(t.identifier('type'), t.stringLiteral('text')), + t.objectProperty(t.identifier('name'), t.stringLiteral(_name)), + t.objectProperty( + t.identifier('message'), + t.stringLiteral(_name), + ), + ]); +} + +export function buildQuestionsArray(args: CleanArgument[]): t.ArrayExpression { + const questions: t.Expression[] = []; + for (const arg of args) { + const base = resolveBaseType(arg.type); + const { inner } = unwrapNonNull(arg.type); + + if (inner.kind === 'INPUT_OBJECT' && inner.inputFields) { + for (const field of inner.inputFields) { + questions.push(buildQuestionObject(field)); + } + } else if (base.kind === 'INPUT_OBJECT' && base.inputFields) { + for (const field of base.inputFields) { + questions.push(buildQuestionObject(field)); + } + } else { + questions.push(buildQuestionObject(arg)); + } + } + return t.arrayExpression(questions); +} diff --git a/graphql/codegen/src/core/codegen/cli/command-map-generator.ts b/graphql/codegen/src/core/codegen/cli/command-map-generator.ts new file mode 100644 index 000000000..e938e59f9 --- /dev/null +++ b/graphql/codegen/src/core/codegen/cli/command-map-generator.ts @@ -0,0 +1,382 @@ +import * as t from '@babel/types'; +import { toKebabCase } from 'komoji'; + +import { generateCode } from '../babel-ast'; +import { getGeneratedFileHeader, getTableNames } from '../utils'; +import type { CleanTable, CleanOperation } from '../../../types/schema'; +import type { GeneratedFile } from './executor-generator'; + +function createImportDeclaration( + moduleSpecifier: string, + defaultImportName: string, +): t.ImportDeclaration { + return t.importDeclaration( + [t.importDefaultSpecifier(t.identifier(defaultImportName))], + t.stringLiteral(moduleSpecifier), + ); +} + +function createNamedImportDeclaration( + moduleSpecifier: string, + namedImports: string[], + typeOnly: boolean = false, +): t.ImportDeclaration { + const specifiers = namedImports.map((name) => + t.importSpecifier(t.identifier(name), t.identifier(name)), + ); + const decl = t.importDeclaration( + specifiers, + t.stringLiteral(moduleSpecifier), + ); + decl.importKind = typeOnly ? 'type' : 'value'; + return decl; +} + +export function generateCommandMap( + tables: CleanTable[], + customOperations: CleanOperation[], + toolName: string, +): GeneratedFile { + const statements: t.Statement[] = []; + + statements.push( + createNamedImportDeclaration('inquirerer', [ + 'CLIOptions', + 'Inquirerer', + 'extractFirst', + ]), + ); + + const commandEntries: { kebab: string; importName: string }[] = []; + + commandEntries.push({ kebab: 'context', importName: 'contextCmd' }); + statements.push( + createImportDeclaration('./commands/context', 'contextCmd'), + ); + + commandEntries.push({ kebab: 'auth', importName: 'authCmd' }); + statements.push(createImportDeclaration('./commands/auth', 'authCmd')); + + for (const table of tables) { + const { singularName } = getTableNames(table); + const kebab = toKebabCase(singularName); + const importName = `${singularName}Cmd`; + commandEntries.push({ kebab, importName }); + statements.push( + createImportDeclaration(`./commands/${kebab}`, importName), + ); + } + + for (const op of customOperations) { + const kebab = toKebabCase(op.name); + const importName = `${op.name}Cmd`; + commandEntries.push({ kebab, importName }); + statements.push( + createImportDeclaration(`./commands/${kebab}`, importName), + ); + } + + const mapProperties = commandEntries.map((entry) => + t.objectProperty( + t.stringLiteral(entry.kebab), + t.identifier(entry.importName), + ), + ); + + const createCommandMapFunc = t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('createCommandMap'), + t.arrowFunctionExpression( + [], + t.objectExpression(mapProperties), + ), + ), + ]); + + const createCommandMapAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('Record'), + t.tsTypeParameterInstantiation([ + t.tsStringKeyword(), + t.tsFunctionType(null, [], t.tsTypeAnnotation(t.tsAnyKeyword())), + ]), + ), + ); + + const createCommandMapId = t.identifier('createCommandMap'); + createCommandMapId.typeAnnotation = t.tsTypeAnnotation( + t.tsParenthesizedType( + t.tsFunctionType( + null, + [], + t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('Record'), + t.tsTypeParameterInstantiation([ + t.tsStringKeyword(), + t.tsFunctionType(null, [], t.tsTypeAnnotation(t.tsUnknownKeyword())), + ]), + ), + ), + ), + ), + ); + + statements.push(createCommandMapFunc); + + const usageLines = [ + '', + `${toolName} `, + '', + 'Commands:', + ' context Manage API contexts', + ' auth Manage authentication', + ]; + + for (const table of tables) { + const { singularName } = getTableNames(table); + const kebab = toKebabCase(singularName); + usageLines.push( + ` ${kebab.padEnd(20)} ${singularName} CRUD operations`, + ); + } + + for (const op of customOperations) { + const kebab = toKebabCase(op.name); + usageLines.push( + ` ${kebab.padEnd(20)} ${op.description || op.name}`, + ); + } + + usageLines.push(''); + usageLines.push(' --help, -h Show this help message'); + usageLines.push(' --version, -v Show version'); + usageLines.push(''); + + statements.push( + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('usage'), + t.stringLiteral(usageLines.join('\n')), + ), + ]), + ); + + const argvParam = t.identifier('argv'); + argvParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('Partial'), + t.tsTypeParameterInstantiation([ + t.tsTypeReference( + t.identifier('Record'), + t.tsTypeParameterInstantiation([ + t.tsStringKeyword(), + t.tsUnknownKeyword(), + ]), + ), + ]), + ), + ); + const prompterParam = t.identifier('prompter'); + prompterParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('Inquirerer')), + ); + const optionsParam = t.identifier('options'); + optionsParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('CLIOptions')), + ); + + const commandsBody: t.Statement[] = [ + t.ifStatement( + t.logicalExpression( + '||', + t.memberExpression(t.identifier('argv'), t.identifier('help')), + t.memberExpression(t.identifier('argv'), t.identifier('h')), + ), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [t.identifier('usage')], + ), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('process'), + t.identifier('exit'), + ), + [t.numericLiteral(0)], + ), + ), + ]), + ), + t.variableDeclaration('let', [ + t.variableDeclarator( + t.objectPattern([ + t.objectProperty( + t.identifier('first'), + t.identifier('command'), + ), + t.objectProperty( + t.identifier('newArgv'), + t.identifier('newArgv'), + false, + true, + ), + ]), + t.callExpression(t.identifier('extractFirst'), [ + t.identifier('argv'), + ]), + ), + ]), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('commandMap'), + t.callExpression(t.identifier('createCommandMap'), []), + ), + ]), + t.ifStatement( + t.unaryExpression('!', t.identifier('command')), + t.blockStatement([ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('answer'), + t.awaitExpression( + t.callExpression( + t.memberExpression( + t.identifier('prompter'), + t.identifier('prompt'), + ), + [ + t.identifier('argv'), + t.arrayExpression([ + t.objectExpression([ + t.objectProperty( + t.identifier('type'), + t.stringLiteral('autocomplete'), + ), + t.objectProperty( + t.identifier('name'), + t.stringLiteral('command'), + ), + t.objectProperty( + t.identifier('message'), + t.stringLiteral('What do you want to do?'), + ), + t.objectProperty( + t.identifier('options'), + t.callExpression( + t.memberExpression( + t.identifier('Object'), + t.identifier('keys'), + ), + [t.identifier('commandMap')], + ), + ), + ]), + ]), + ], + ), + ), + ), + ]), + t.expressionStatement( + t.assignmentExpression( + '=', + t.identifier('command'), + t.memberExpression( + t.identifier('answer'), + t.identifier('command'), + ), + ), + ), + ]), + ), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('commandFn'), + t.memberExpression( + t.identifier('commandMap'), + t.identifier('command'), + true, + ), + ), + ]), + t.ifStatement( + t.unaryExpression('!', t.identifier('commandFn')), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [t.identifier('usage')], + ), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('console'), + t.identifier('error'), + ), + [ + t.templateLiteral( + [ + t.templateElement({ + raw: 'Unknown command: ', + cooked: 'Unknown command: ', + }), + t.templateElement({ raw: '', cooked: '' }, true), + ], + [t.identifier('command')], + ), + ], + ), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('process'), + t.identifier('exit'), + ), + [t.numericLiteral(1)], + ), + ), + ]), + ), + t.expressionStatement( + t.awaitExpression( + t.callExpression(t.identifier('commandFn'), [ + t.identifier('newArgv'), + t.identifier('prompter'), + t.identifier('options'), + ]), + ), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('prompter'), t.identifier('close')), + [], + ), + ), + t.returnStatement(t.identifier('argv')), + ]; + + const commandsFunc = t.arrowFunctionExpression( + [argvParam, prompterParam, optionsParam], + t.blockStatement(commandsBody), + true, + ); + + const commandsDecl = t.variableDeclaration('const', [ + t.variableDeclarator(t.identifier('commands'), commandsFunc), + ]); + statements.push(t.exportNamedDeclaration(commandsDecl)); + + const header = getGeneratedFileHeader('CLI command map and entry point'); + const code = generateCode(statements); + + return { + fileName: 'commands.ts', + content: header + '\n' + code, + }; +} diff --git a/graphql/codegen/src/core/codegen/cli/custom-command-generator.ts b/graphql/codegen/src/core/codegen/cli/custom-command-generator.ts new file mode 100644 index 000000000..a345e84f9 --- /dev/null +++ b/graphql/codegen/src/core/codegen/cli/custom-command-generator.ts @@ -0,0 +1,255 @@ +import * as t from '@babel/types'; +import { toKebabCase } from 'komoji'; + +import { generateCode } from '../babel-ast'; +import { getGeneratedFileHeader } from '../utils'; +import type { CleanOperation } from '../../../types/schema'; +import type { GeneratedFile } from './executor-generator'; +import { buildQuestionsArray } from './arg-mapper'; + +function createImportDeclaration( + moduleSpecifier: string, + namedImports: string[], + typeOnly: boolean = false, +): t.ImportDeclaration { + const specifiers = namedImports.map((name) => + t.importSpecifier(t.identifier(name), t.identifier(name)), + ); + const decl = t.importDeclaration( + specifiers, + t.stringLiteral(moduleSpecifier), + ); + decl.importKind = typeOnly ? 'type' : 'value'; + return decl; +} + +function buildArgvType(): t.TSTypeAnnotation { + return t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('Partial'), + t.tsTypeParameterInstantiation([ + t.tsTypeReference( + t.identifier('Record'), + t.tsTypeParameterInstantiation([ + t.tsStringKeyword(), + t.tsUnknownKeyword(), + ]), + ), + ]), + ), + ); +} + +function buildJsonLog(expr: t.Expression): t.ExpressionStatement { + return t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [ + t.callExpression( + t.memberExpression(t.identifier('JSON'), t.identifier('stringify')), + [expr, t.nullLiteral(), t.numericLiteral(2)], + ), + ], + ), + ); +} + +function buildErrorCatch(errorMessage: string): t.CatchClause { + return t.catchClause( + t.identifier('error'), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('console'), + t.identifier('error'), + ), + [t.stringLiteral(errorMessage)], + ), + ), + t.ifStatement( + t.binaryExpression( + 'instanceof', + t.identifier('error'), + t.identifier('Error'), + ), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('console'), + t.identifier('error'), + ), + [ + t.memberExpression( + t.identifier('error'), + t.identifier('message'), + ), + ], + ), + ), + ]), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('process'), t.identifier('exit')), + [t.numericLiteral(1)], + ), + ), + ]), + ); +} + +function buildOrmCustomCall( + opKind: 'query' | 'mutation', + opName: string, + argsExpr: t.Expression, +): t.Expression { + return t.callExpression( + t.memberExpression( + t.callExpression( + t.memberExpression( + t.memberExpression( + t.identifier('client'), + t.identifier(opKind), + ), + t.identifier(opName), + ), + [argsExpr], + ), + t.identifier('execute'), + ), + [], + ); +} + +export function generateCustomCommand(op: CleanOperation): GeneratedFile { + const commandName = toKebabCase(op.name); + const opKind = op.kind === 'mutation' ? 'mutation' : 'query'; + const statements: t.Statement[] = []; + + statements.push( + createImportDeclaration('inquirerer', ['CLIOptions', 'Inquirerer']), + ); + statements.push( + createImportDeclaration('../executor', ['getClient']), + ); + + const questionsArray = + op.args.length > 0 + ? buildQuestionsArray(op.args) + : t.arrayExpression([]); + + const argvParam = t.identifier('argv'); + argvParam.typeAnnotation = buildArgvType(); + const prompterParam = t.identifier('prompter'); + prompterParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('Inquirerer')), + ); + const optionsParam = t.identifier('_options'); + optionsParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('CLIOptions')), + ); + + const bodyStatements: t.Statement[] = [ + t.ifStatement( + t.logicalExpression( + '||', + t.memberExpression(t.identifier('argv'), t.identifier('help')), + t.memberExpression(t.identifier('argv'), t.identifier('h')), + ), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [ + t.stringLiteral( + `${commandName} - ${op.description || op.name}\n\nUsage: ${commandName} [OPTIONS]\n`, + ), + ], + ), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('process'), + t.identifier('exit'), + ), + [t.numericLiteral(0)], + ), + ), + ]), + ), + ]; + + if (op.args.length > 0) { + bodyStatements.push( + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('answers'), + t.awaitExpression( + t.callExpression( + t.memberExpression( + t.identifier('prompter'), + t.identifier('prompt'), + ), + [t.identifier('argv'), questionsArray], + ), + ), + ), + ]), + ); + } + + bodyStatements.push( + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('client'), + t.callExpression(t.identifier('getClient'), []), + ), + ]), + ); + + const argsExpr = + op.args.length > 0 + ? t.identifier('answers') + : t.objectExpression([]); + + bodyStatements.push( + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('result'), + t.awaitExpression( + buildOrmCustomCall(opKind, op.name, argsExpr), + ), + ), + ]), + ); + + bodyStatements.push(buildJsonLog(t.identifier('result'))); + + const tryBlock = t.tryStatement( + t.blockStatement(bodyStatements), + buildErrorCatch(`Failed: ${op.name}`), + ); + + statements.push( + t.exportDefaultDeclaration( + t.arrowFunctionExpression( + [argvParam, prompterParam, optionsParam], + t.blockStatement([tryBlock]), + true, + ), + ), + ); + + const header = getGeneratedFileHeader( + `CLI command for ${op.kind} ${op.name}`, + ); + const code = generateCode(statements); + + return { + fileName: `commands/${commandName}.ts`, + content: header + '\n' + code, + }; +} diff --git a/graphql/codegen/src/core/codegen/cli/executor-generator.ts b/graphql/codegen/src/core/codegen/cli/executor-generator.ts new file mode 100644 index 000000000..d5d1183f9 --- /dev/null +++ b/graphql/codegen/src/core/codegen/cli/executor-generator.ts @@ -0,0 +1,218 @@ +import * as t from '@babel/types'; + +import { generateCode } from '../babel-ast'; +import { getGeneratedFileHeader } from '../utils'; + +export interface GeneratedFile { + fileName: string; + content: string; +} + +function createImportDeclaration( + moduleSpecifier: string, + namedImports: string[], + typeOnly: boolean = false, +): t.ImportDeclaration { + const specifiers = namedImports.map((name) => + t.importSpecifier(t.identifier(name), t.identifier(name)), + ); + const decl = t.importDeclaration( + specifiers, + t.stringLiteral(moduleSpecifier), + ); + decl.importKind = typeOnly ? 'type' : 'value'; + return decl; +} + +export function generateExecutorFile(toolName: string): GeneratedFile { + const statements: t.Statement[] = []; + + statements.push( + createImportDeclaration('appstash', ['createConfigStore']), + ); + statements.push( + createImportDeclaration('../orm', ['createClient']), + ); + + statements.push( + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('store'), + t.callExpression(t.identifier('createConfigStore'), [ + t.stringLiteral(toolName), + ]), + ), + ]), + ); + + const getStoreExport = t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('getStore'), + t.arrowFunctionExpression([], t.identifier('store')), + ), + ]); + statements.push(t.exportNamedDeclaration(getStoreExport)); + + const contextNameParam = t.identifier('contextName'); + contextNameParam.optional = true; + contextNameParam.typeAnnotation = t.tsTypeAnnotation(t.tsStringKeyword()); + + const getClientBody = t.blockStatement([ + t.variableDeclaration('let', [ + t.variableDeclarator(t.identifier('ctx'), t.nullLiteral()), + ]), + t.ifStatement( + t.identifier('contextName'), + t.blockStatement([ + t.expressionStatement( + t.assignmentExpression( + '=', + t.identifier('ctx'), + t.callExpression( + t.memberExpression( + t.identifier('store'), + t.identifier('loadContext'), + ), + [t.identifier('contextName')], + ), + ), + ), + t.ifStatement( + t.unaryExpression('!', t.identifier('ctx')), + t.blockStatement([ + t.throwStatement( + t.newExpression(t.identifier('Error'), [ + t.templateLiteral( + [ + t.templateElement({ raw: 'Context "', cooked: 'Context "' }), + t.templateElement({ raw: '" not found.', cooked: '" not found.' }, true), + ], + [t.identifier('contextName')], + ), + ]), + ), + ]), + ), + ]), + t.blockStatement([ + t.expressionStatement( + t.assignmentExpression( + '=', + t.identifier('ctx'), + t.callExpression( + t.memberExpression( + t.identifier('store'), + t.identifier('getCurrentContext'), + ), + [], + ), + ), + ), + t.ifStatement( + t.unaryExpression('!', t.identifier('ctx')), + t.blockStatement([ + t.throwStatement( + t.newExpression(t.identifier('Error'), [ + t.stringLiteral( + 'No active context. Run "context create" or "context use" first.', + ), + ]), + ), + ]), + ), + ]), + ), + + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('headers'), + t.objectExpression([]), + ), + ]), + + t.ifStatement( + t.callExpression( + t.memberExpression( + t.identifier('store'), + t.identifier('hasValidCredentials'), + ), + [t.memberExpression(t.identifier('ctx'), t.identifier('name'))], + ), + t.blockStatement([ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('creds'), + t.callExpression( + t.memberExpression( + t.identifier('store'), + t.identifier('getCredentials'), + ), + [t.memberExpression(t.identifier('ctx'), t.identifier('name'))], + ), + ), + ]), + t.ifStatement( + t.optionalMemberExpression( + t.identifier('creds'), + t.identifier('token'), + false, + true, + ), + t.blockStatement([ + t.expressionStatement( + t.assignmentExpression( + '=', + t.memberExpression( + t.identifier('headers'), + t.identifier('Authorization'), + ), + t.templateLiteral( + [ + t.templateElement({ raw: 'Bearer ', cooked: 'Bearer ' }), + t.templateElement({ raw: '', cooked: '' }, true), + ], + [ + t.memberExpression( + t.identifier('creds'), + t.identifier('token'), + ), + ], + ), + ), + ), + ]), + ), + ]), + ), + + t.returnStatement( + t.callExpression(t.identifier('createClient'), [ + t.objectExpression([ + t.objectProperty( + t.identifier('endpoint'), + t.memberExpression(t.identifier('ctx'), t.identifier('endpoint')), + ), + t.objectProperty( + t.identifier('headers'), + t.identifier('headers'), + ), + ]), + ]), + ), + ]); + + const getClientFunc = t.functionDeclaration( + t.identifier('getClient'), + [contextNameParam], + getClientBody, + ); + statements.push(t.exportNamedDeclaration(getClientFunc)); + + const header = getGeneratedFileHeader('Executor and config store for CLI'); + const code = generateCode(statements); + + return { + fileName: 'executor.ts', + content: header + '\n' + code, + }; +} diff --git a/graphql/codegen/src/core/codegen/cli/index.ts b/graphql/codegen/src/core/codegen/cli/index.ts new file mode 100644 index 000000000..c38f6d3d4 --- /dev/null +++ b/graphql/codegen/src/core/codegen/cli/index.ts @@ -0,0 +1,91 @@ +import type { GraphQLSDKConfigTarget } from '../../../types/config'; +import type { CleanOperation, CleanTable } from '../../../types/schema'; +import { generateCommandMap } from './command-map-generator'; +import { generateCustomCommand } from './custom-command-generator'; +import { generateExecutorFile } from './executor-generator'; +import type { GeneratedFile } from './executor-generator'; +import { generateAuthCommand, generateContextCommand } from './infra-generator'; +import { generateTableCommand } from './table-command-generator'; + +export interface GenerateCliOptions { + tables: CleanTable[]; + customOperations?: { + queries: CleanOperation[]; + mutations: CleanOperation[]; + }; + config: GraphQLSDKConfigTarget; +} + +export interface GenerateCliResult { + files: GeneratedFile[]; + stats: { + tables: number; + customQueries: number; + customMutations: number; + infraFiles: number; + totalFiles: number; + }; +} + +export function generateCli(options: GenerateCliOptions): GenerateCliResult { + const { tables, customOperations, config } = options; + const files: GeneratedFile[] = []; + + const cliConfig = config.cli; + const toolName = + typeof cliConfig === 'object' && cliConfig.toolName + ? cliConfig.toolName + : 'app'; + + const executorFile = generateExecutorFile(toolName); + files.push(executorFile); + + const contextFile = generateContextCommand(toolName); + files.push(contextFile); + + const authFile = generateAuthCommand(toolName); + files.push(authFile); + + for (const table of tables) { + const tableFile = generateTableCommand(table); + files.push(tableFile); + } + + const allCustomOps: CleanOperation[] = [ + ...(customOperations?.queries ?? []), + ...(customOperations?.mutations ?? []), + ]; + + for (const op of allCustomOps) { + const customFile = generateCustomCommand(op); + files.push(customFile); + } + + const commandMapFile = generateCommandMap( + tables, + allCustomOps, + toolName, + ); + files.push(commandMapFile); + + return { + files, + stats: { + tables: tables.length, + customQueries: customOperations?.queries.length ?? 0, + customMutations: customOperations?.mutations.length ?? 0, + infraFiles: 3, + totalFiles: files.length, + }, + }; +} + +export { generateExecutorFile } from './executor-generator'; +export { generateTableCommand } from './table-command-generator'; +export { generateCustomCommand } from './custom-command-generator'; +export { generateCommandMap } from './command-map-generator'; +export { + generateContextCommand, + generateAuthCommand, +} from './infra-generator'; +export type { GeneratedFile } from './executor-generator'; diff --git a/graphql/codegen/src/core/codegen/cli/infra-generator.ts b/graphql/codegen/src/core/codegen/cli/infra-generator.ts new file mode 100644 index 000000000..9433169ad --- /dev/null +++ b/graphql/codegen/src/core/codegen/cli/infra-generator.ts @@ -0,0 +1,2054 @@ +import * as t from '@babel/types'; + +import { generateCode } from '../babel-ast'; +import { getGeneratedFileHeader } from '../utils'; +import type { GeneratedFile } from './executor-generator'; + +function createImportDeclaration( + moduleSpecifier: string, + namedImports: string[], + typeOnly: boolean = false, +): t.ImportDeclaration { + const specifiers = namedImports.map((name) => + t.importSpecifier(t.identifier(name), t.identifier(name)), + ); + const decl = t.importDeclaration( + specifiers, + t.stringLiteral(moduleSpecifier), + ); + decl.importKind = typeOnly ? 'type' : 'value'; + return decl; +} + +function buildSwitchCase( + testValue: string, + handlerName: string, + args: t.Expression[], +): t.SwitchCase { + return t.switchCase(t.stringLiteral(testValue), [ + t.returnStatement(t.callExpression(t.identifier(handlerName), args)), + ]); +} + +function buildDefaultSwitchCase(usageVarName: string): t.SwitchCase { + return t.switchCase(null, [ + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [t.identifier(usageVarName)], + ), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('process'), t.identifier('exit')), + [t.numericLiteral(1)], + ), + ), + ]); +} + +function buildCommandHandler( + params: t.Identifier[], + body: t.Statement[], + isAsync: boolean = true, +): t.FunctionDeclaration { + const func = t.functionDeclaration( + null, + params, + t.blockStatement(body), + false, + isAsync, + ); + return func; +} + +export function generateContextCommand(toolName: string): GeneratedFile { + const statements: t.Statement[] = []; + + statements.push( + createImportDeclaration('inquirerer', [ + 'CLIOptions', + 'Inquirerer', + 'extractFirst', + ]), + ); + statements.push( + createImportDeclaration('../executor', ['getStore']), + ); + + const usageStr = ` +${toolName} context + +Commands: + create Create a new context + list List all contexts + use Set the active context + current Show current context + delete Delete a context + +Create Options: + --endpoint GraphQL endpoint URL + + --help, -h Show this help message +`; + + statements.push( + t.variableDeclaration('const', [ + t.variableDeclarator(t.identifier('usage'), t.stringLiteral(usageStr)), + ]), + ); + + const argvParam = t.identifier('argv'); + argvParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('Partial'), + t.tsTypeParameterInstantiation([ + t.tsTypeReference( + t.identifier('Record'), + t.tsTypeParameterInstantiation([ + t.tsStringKeyword(), + t.tsUnknownKeyword(), + ]), + ), + ]), + ), + ); + + const prompterParam = t.identifier('prompter'); + prompterParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('Inquirerer')), + ); + + const optionsParam = t.identifier('_options'); + optionsParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('CLIOptions')), + ); + + const mainBody: t.Statement[] = [ + t.ifStatement( + t.logicalExpression( + '||', + t.memberExpression(t.identifier('argv'), t.identifier('help')), + t.memberExpression(t.identifier('argv'), t.identifier('h')), + ), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [t.identifier('usage')], + ), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('process'), t.identifier('exit')), + [t.numericLiteral(0)], + ), + ), + ]), + ), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('store'), + t.callExpression(t.identifier('getStore'), []), + ), + ]), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.objectPattern([ + t.objectProperty( + t.identifier('first'), + t.identifier('subcommand'), + ), + t.objectProperty( + t.identifier('newArgv'), + t.identifier('newArgv'), + false, + true, + ), + ]), + t.callExpression(t.identifier('extractFirst'), [ + t.identifier('argv'), + ]), + ), + ]), + t.ifStatement( + t.unaryExpression('!', t.identifier('subcommand')), + t.blockStatement([ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('answer'), + t.awaitExpression( + t.callExpression( + t.memberExpression( + t.identifier('prompter'), + t.identifier('prompt'), + ), + [ + t.identifier('argv'), + t.arrayExpression([ + t.objectExpression([ + t.objectProperty( + t.identifier('type'), + t.stringLiteral('autocomplete'), + ), + t.objectProperty( + t.identifier('name'), + t.stringLiteral('subcommand'), + ), + t.objectProperty( + t.identifier('message'), + t.stringLiteral('What do you want to do?'), + ), + t.objectProperty( + t.identifier('options'), + t.arrayExpression([ + t.stringLiteral('create'), + t.stringLiteral('list'), + t.stringLiteral('use'), + t.stringLiteral('current'), + t.stringLiteral('delete'), + ]), + ), + ]), + ]), + ], + ), + ), + ), + ]), + t.returnStatement( + t.callExpression(t.identifier('handleSubcommand'), [ + t.memberExpression( + t.identifier('answer'), + t.identifier('subcommand'), + ), + t.identifier('newArgv'), + t.identifier('prompter'), + t.identifier('store'), + ]), + ), + ]), + ), + t.returnStatement( + t.callExpression(t.identifier('handleSubcommand'), [ + t.identifier('subcommand'), + t.identifier('newArgv'), + t.identifier('prompter'), + t.identifier('store'), + ]), + ), + ]; + + const mainExport = t.exportDefaultDeclaration( + t.arrowFunctionExpression( + [argvParam, prompterParam, optionsParam], + t.blockStatement(mainBody), + true, + ), + ); + statements.push(mainExport); + + const subcmdParam = t.identifier('subcommand'); + subcmdParam.typeAnnotation = t.tsTypeAnnotation(t.tsStringKeyword()); + const argvParam2 = t.identifier('argv'); + argvParam2.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('Partial'), + t.tsTypeParameterInstantiation([ + t.tsTypeReference( + t.identifier('Record'), + t.tsTypeParameterInstantiation([ + t.tsStringKeyword(), + t.tsUnknownKeyword(), + ]), + ), + ]), + ), + ); + const prompterParam2 = t.identifier('prompter'); + prompterParam2.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('Inquirerer')), + ); + const storeParam = t.identifier('store'); + storeParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('ReturnType'), + t.tsTypeParameterInstantiation([ + t.tsTypeQuery(t.identifier('getStore')), + ]), + ), + ); + + const handleSubcommandFunc = t.functionDeclaration( + t.identifier('handleSubcommand'), + [subcmdParam, argvParam2, prompterParam2, storeParam], + t.blockStatement([ + t.switchStatement(t.identifier('subcommand'), [ + buildSwitchCase('create', 'handleCreate', [ + t.identifier('argv'), + t.identifier('prompter'), + t.identifier('store'), + ]), + buildSwitchCase('list', 'handleList', [t.identifier('store')]), + buildSwitchCase('use', 'handleUse', [ + t.identifier('argv'), + t.identifier('prompter'), + t.identifier('store'), + ]), + buildSwitchCase('current', 'handleCurrent', [t.identifier('store')]), + buildSwitchCase('delete', 'handleDelete', [ + t.identifier('argv'), + t.identifier('prompter'), + t.identifier('store'), + ]), + buildDefaultSwitchCase('usage'), + ]), + ]), + false, + true, + ); + statements.push(handleSubcommandFunc); + + statements.push(buildCreateHandler()); + statements.push(buildListHandler()); + statements.push(buildUseHandler()); + statements.push(buildCurrentHandler()); + statements.push(buildDeleteHandler()); + + const header = getGeneratedFileHeader('Context management commands'); + const code = generateCode(statements); + + return { + fileName: 'commands/context.ts', + content: header + '\n' + code, + }; +} + +function buildCreateHandler(): t.FunctionDeclaration { + const argvParam = t.identifier('argv'); + argvParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('Partial'), + t.tsTypeParameterInstantiation([ + t.tsTypeReference( + t.identifier('Record'), + t.tsTypeParameterInstantiation([ + t.tsStringKeyword(), + t.tsUnknownKeyword(), + ]), + ), + ]), + ), + ); + const prompterParam = t.identifier('prompter'); + prompterParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('Inquirerer')), + ); + const storeParam = t.identifier('store'); + storeParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('ReturnType'), + t.tsTypeParameterInstantiation([ + t.tsTypeQuery(t.identifier('getStore')), + ]), + ), + ); + + const body: t.Statement[] = [ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.objectPattern([ + t.objectProperty(t.identifier('first'), t.identifier('name')), + t.objectProperty( + t.identifier('newArgv'), + t.identifier('restArgv'), + ), + ]), + t.callExpression(t.identifier('extractFirst'), [ + t.identifier('argv'), + ]), + ), + ]), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('answers'), + t.awaitExpression( + t.callExpression( + t.memberExpression( + t.identifier('prompter'), + t.identifier('prompt'), + ), + [ + t.objectExpression([ + t.objectProperty( + t.identifier('name'), + t.identifier('name'), + false, + true, + ), + t.spreadElement(t.identifier('restArgv')), + ]), + t.arrayExpression([ + t.objectExpression([ + t.objectProperty( + t.identifier('type'), + t.stringLiteral('text'), + ), + t.objectProperty( + t.identifier('name'), + t.stringLiteral('name'), + ), + t.objectProperty( + t.identifier('message'), + t.stringLiteral('Context name'), + ), + t.objectProperty( + t.identifier('required'), + t.booleanLiteral(true), + ), + ]), + t.objectExpression([ + t.objectProperty( + t.identifier('type'), + t.stringLiteral('text'), + ), + t.objectProperty( + t.identifier('name'), + t.stringLiteral('endpoint'), + ), + t.objectProperty( + t.identifier('message'), + t.stringLiteral('GraphQL endpoint URL'), + ), + t.objectProperty( + t.identifier('required'), + t.booleanLiteral(true), + ), + ]), + ]), + ], + ), + ), + ), + ]), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('contextName'), + t.memberExpression(t.identifier('answers'), t.identifier('name')), + ), + ]), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('endpoint'), + t.memberExpression( + t.identifier('answers'), + t.identifier('endpoint'), + ), + ), + ]), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('store'), t.identifier('createContext')), + [ + t.identifier('contextName'), + t.objectExpression([ + t.objectProperty( + t.identifier('endpoint'), + t.identifier('endpoint'), + ), + ]), + ], + ), + ), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('settings'), + t.callExpression( + t.memberExpression( + t.identifier('store'), + t.identifier('loadSettings'), + ), + [], + ), + ), + ]), + t.ifStatement( + t.unaryExpression( + '!', + t.memberExpression( + t.identifier('settings'), + t.identifier('currentContext'), + ), + ), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('store'), + t.identifier('setCurrentContext'), + ), + [t.identifier('contextName')], + ), + ), + ]), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [ + t.templateLiteral( + [ + t.templateElement({ raw: 'Created context: ', cooked: 'Created context: ' }), + t.templateElement({ raw: '', cooked: '' }, true), + ], + [t.identifier('contextName')], + ), + ], + ), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [ + t.templateLiteral( + [ + t.templateElement({ raw: ' Endpoint: ', cooked: ' Endpoint: ' }), + t.templateElement({ raw: '', cooked: '' }, true), + ], + [t.identifier('endpoint')], + ), + ], + ), + ), + ]; + + const func = t.functionDeclaration( + t.identifier('handleCreate'), + [argvParam, prompterParam, storeParam], + t.blockStatement(body), + false, + true, + ); + return func; +} + +function buildListHandler(): t.FunctionDeclaration { + const storeParam = t.identifier('store'); + storeParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('ReturnType'), + t.tsTypeParameterInstantiation([ + t.tsTypeQuery(t.identifier('getStore')), + ]), + ), + ); + + const body: t.Statement[] = [ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('contexts'), + t.callExpression( + t.memberExpression( + t.identifier('store'), + t.identifier('listContexts'), + ), + [], + ), + ), + ]), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('settings'), + t.callExpression( + t.memberExpression( + t.identifier('store'), + t.identifier('loadSettings'), + ), + [], + ), + ), + ]), + t.ifStatement( + t.binaryExpression( + '===', + t.memberExpression( + t.identifier('contexts'), + t.identifier('length'), + ), + t.numericLiteral(0), + ), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('console'), + t.identifier('log'), + ), + [t.stringLiteral('No contexts configured.')], + ), + ), + t.returnStatement(), + ]), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [t.stringLiteral('Contexts:')], + ), + ), + t.forOfStatement( + t.variableDeclaration('const', [ + t.variableDeclarator(t.identifier('ctx')), + ]), + t.identifier('contexts'), + t.blockStatement([ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('marker'), + t.conditionalExpression( + t.binaryExpression( + '===', + t.memberExpression( + t.identifier('ctx'), + t.identifier('name'), + ), + t.memberExpression( + t.identifier('settings'), + t.identifier('currentContext'), + ), + ), + t.stringLiteral('* '), + t.stringLiteral(' '), + ), + ), + ]), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('authStatus'), + t.conditionalExpression( + t.callExpression( + t.memberExpression( + t.identifier('store'), + t.identifier('hasValidCredentials'), + ), + [ + t.memberExpression( + t.identifier('ctx'), + t.identifier('name'), + ), + ], + ), + t.stringLiteral('[authenticated]'), + t.stringLiteral('[no token]'), + ), + ), + ]), + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('console'), + t.identifier('log'), + ), + [ + t.templateLiteral( + [ + t.templateElement({ raw: '', cooked: '' }), + t.templateElement({ raw: '', cooked: '' }), + t.templateElement({ raw: ' ', cooked: ' ' }), + t.templateElement({ raw: '', cooked: '' }, true), + ], + [ + t.identifier('marker'), + t.memberExpression( + t.identifier('ctx'), + t.identifier('name'), + ), + t.identifier('authStatus'), + ], + ), + ], + ), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('console'), + t.identifier('log'), + ), + [ + t.templateLiteral( + [ + t.templateElement({ raw: ' Endpoint: ', cooked: ' Endpoint: ' }), + t.templateElement({ raw: '', cooked: '' }, true), + ], + [ + t.memberExpression( + t.identifier('ctx'), + t.identifier('endpoint'), + ), + ], + ), + ], + ), + ), + ]), + ), + ]; + + const func = t.functionDeclaration( + t.identifier('handleList'), + [storeParam], + t.blockStatement(body), + ); + return func; +} + +function buildUseHandler(): t.FunctionDeclaration { + const argvParam = t.identifier('argv'); + argvParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('Partial'), + t.tsTypeParameterInstantiation([ + t.tsTypeReference( + t.identifier('Record'), + t.tsTypeParameterInstantiation([ + t.tsStringKeyword(), + t.tsUnknownKeyword(), + ]), + ), + ]), + ), + ); + const prompterParam = t.identifier('prompter'); + prompterParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('Inquirerer')), + ); + const storeParam = t.identifier('store'); + storeParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('ReturnType'), + t.tsTypeParameterInstantiation([ + t.tsTypeQuery(t.identifier('getStore')), + ]), + ), + ); + + const body: t.Statement[] = [ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.objectPattern([ + t.objectProperty(t.identifier('first'), t.identifier('name')), + ]), + t.callExpression(t.identifier('extractFirst'), [ + t.identifier('argv'), + ]), + ), + ]), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('contexts'), + t.callExpression( + t.memberExpression( + t.identifier('store'), + t.identifier('listContexts'), + ), + [], + ), + ), + ]), + t.ifStatement( + t.binaryExpression( + '===', + t.memberExpression( + t.identifier('contexts'), + t.identifier('length'), + ), + t.numericLiteral(0), + ), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('console'), + t.identifier('log'), + ), + [t.stringLiteral('No contexts configured.')], + ), + ), + t.returnStatement(), + ]), + ), + t.variableDeclaration('let', [ + t.variableDeclarator( + t.identifier('contextName'), + t.identifier('name'), + ), + ]), + t.ifStatement( + t.unaryExpression('!', t.identifier('contextName')), + t.blockStatement([ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('answer'), + t.awaitExpression( + t.callExpression( + t.memberExpression( + t.identifier('prompter'), + t.identifier('prompt'), + ), + [ + t.identifier('argv'), + t.arrayExpression([ + t.objectExpression([ + t.objectProperty( + t.identifier('type'), + t.stringLiteral('autocomplete'), + ), + t.objectProperty( + t.identifier('name'), + t.stringLiteral('name'), + ), + t.objectProperty( + t.identifier('message'), + t.stringLiteral('Select context'), + ), + t.objectProperty( + t.identifier('options'), + t.callExpression( + t.memberExpression( + t.identifier('contexts'), + t.identifier('map'), + ), + [ + t.arrowFunctionExpression( + [t.identifier('c')], + t.memberExpression( + t.identifier('c'), + t.identifier('name'), + ), + ), + ], + ), + ), + ]), + ]), + ], + ), + ), + ), + ]), + t.expressionStatement( + t.assignmentExpression( + '=', + t.identifier('contextName'), + t.memberExpression( + t.identifier('answer'), + t.identifier('name'), + ), + ), + ), + ]), + ), + t.ifStatement( + t.callExpression( + t.memberExpression( + t.identifier('store'), + t.identifier('setCurrentContext'), + ), + [t.identifier('contextName')], + ), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('console'), + t.identifier('log'), + ), + [ + t.templateLiteral( + [ + t.templateElement({ raw: 'Switched to context: ', cooked: 'Switched to context: ' }), + t.templateElement({ raw: '', cooked: '' }, true), + ], + [t.identifier('contextName')], + ), + ], + ), + ), + ]), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('console'), + t.identifier('error'), + ), + [ + t.templateLiteral( + [ + t.templateElement({ raw: 'Context "', cooked: 'Context "' }), + t.templateElement({ raw: '" not found.', cooked: '" not found.' }, true), + ], + [t.identifier('contextName')], + ), + ], + ), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('process'), t.identifier('exit')), + [t.numericLiteral(1)], + ), + ), + ]), + ), + ]; + + const func = t.functionDeclaration( + t.identifier('handleUse'), + [argvParam, prompterParam, storeParam], + t.blockStatement(body), + false, + true, + ); + return func; +} + +function buildCurrentHandler(): t.FunctionDeclaration { + const storeParam = t.identifier('store'); + storeParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('ReturnType'), + t.tsTypeParameterInstantiation([ + t.tsTypeQuery(t.identifier('getStore')), + ]), + ), + ); + + const body: t.Statement[] = [ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('current'), + t.callExpression( + t.memberExpression( + t.identifier('store'), + t.identifier('getCurrentContext'), + ), + [], + ), + ), + ]), + t.ifStatement( + t.unaryExpression('!', t.identifier('current')), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('console'), + t.identifier('log'), + ), + [t.stringLiteral('No current context set.')], + ), + ), + t.returnStatement(), + ]), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [ + t.templateLiteral( + [ + t.templateElement({ raw: 'Current context: ', cooked: 'Current context: ' }), + t.templateElement({ raw: '', cooked: '' }, true), + ], + [ + t.memberExpression( + t.identifier('current'), + t.identifier('name'), + ), + ], + ), + ], + ), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [ + t.templateLiteral( + [ + t.templateElement({ raw: ' Endpoint: ', cooked: ' Endpoint: ' }), + t.templateElement({ raw: '', cooked: '' }, true), + ], + [ + t.memberExpression( + t.identifier('current'), + t.identifier('endpoint'), + ), + ], + ), + ], + ), + ), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('hasAuth'), + t.callExpression( + t.memberExpression( + t.identifier('store'), + t.identifier('hasValidCredentials'), + ), + [ + t.memberExpression( + t.identifier('current'), + t.identifier('name'), + ), + ], + ), + ), + ]), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [ + t.templateLiteral( + [ + t.templateElement({ raw: ' Auth: ', cooked: ' Auth: ' }), + t.templateElement({ raw: '', cooked: '' }, true), + ], + [ + t.conditionalExpression( + t.identifier('hasAuth'), + t.stringLiteral('authenticated'), + t.stringLiteral('not authenticated'), + ), + ], + ), + ], + ), + ), + ]; + + const func = t.functionDeclaration( + t.identifier('handleCurrent'), + [storeParam], + t.blockStatement(body), + ); + return func; +} + +function buildDeleteHandler(): t.FunctionDeclaration { + const argvParam = t.identifier('argv'); + argvParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('Partial'), + t.tsTypeParameterInstantiation([ + t.tsTypeReference( + t.identifier('Record'), + t.tsTypeParameterInstantiation([ + t.tsStringKeyword(), + t.tsUnknownKeyword(), + ]), + ), + ]), + ), + ); + const prompterParam = t.identifier('prompter'); + prompterParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('Inquirerer')), + ); + const storeParam = t.identifier('store'); + storeParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('ReturnType'), + t.tsTypeParameterInstantiation([ + t.tsTypeQuery(t.identifier('getStore')), + ]), + ), + ); + + const body: t.Statement[] = [ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.objectPattern([ + t.objectProperty(t.identifier('first'), t.identifier('name')), + ]), + t.callExpression(t.identifier('extractFirst'), [ + t.identifier('argv'), + ]), + ), + ]), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('contexts'), + t.callExpression( + t.memberExpression( + t.identifier('store'), + t.identifier('listContexts'), + ), + [], + ), + ), + ]), + t.ifStatement( + t.binaryExpression( + '===', + t.memberExpression( + t.identifier('contexts'), + t.identifier('length'), + ), + t.numericLiteral(0), + ), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('console'), + t.identifier('log'), + ), + [t.stringLiteral('No contexts configured.')], + ), + ), + t.returnStatement(), + ]), + ), + t.variableDeclaration('let', [ + t.variableDeclarator( + t.identifier('contextName'), + t.identifier('name'), + ), + ]), + t.ifStatement( + t.unaryExpression('!', t.identifier('contextName')), + t.blockStatement([ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('answer'), + t.awaitExpression( + t.callExpression( + t.memberExpression( + t.identifier('prompter'), + t.identifier('prompt'), + ), + [ + t.identifier('argv'), + t.arrayExpression([ + t.objectExpression([ + t.objectProperty( + t.identifier('type'), + t.stringLiteral('autocomplete'), + ), + t.objectProperty( + t.identifier('name'), + t.stringLiteral('name'), + ), + t.objectProperty( + t.identifier('message'), + t.stringLiteral('Select context to delete'), + ), + t.objectProperty( + t.identifier('options'), + t.callExpression( + t.memberExpression( + t.identifier('contexts'), + t.identifier('map'), + ), + [ + t.arrowFunctionExpression( + [t.identifier('c')], + t.memberExpression( + t.identifier('c'), + t.identifier('name'), + ), + ), + ], + ), + ), + ]), + ]), + ], + ), + ), + ), + ]), + t.expressionStatement( + t.assignmentExpression( + '=', + t.identifier('contextName'), + t.memberExpression( + t.identifier('answer'), + t.identifier('name'), + ), + ), + ), + ]), + ), + t.ifStatement( + t.callExpression( + t.memberExpression( + t.identifier('store'), + t.identifier('deleteContext'), + ), + [t.identifier('contextName')], + ), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('console'), + t.identifier('log'), + ), + [ + t.templateLiteral( + [ + t.templateElement({ raw: 'Deleted context: ', cooked: 'Deleted context: ' }), + t.templateElement({ raw: '', cooked: '' }, true), + ], + [t.identifier('contextName')], + ), + ], + ), + ), + ]), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('console'), + t.identifier('error'), + ), + [ + t.templateLiteral( + [ + t.templateElement({ raw: 'Context "', cooked: 'Context "' }), + t.templateElement({ raw: '" not found.', cooked: '" not found.' }, true), + ], + [t.identifier('contextName')], + ), + ], + ), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('process'), t.identifier('exit')), + [t.numericLiteral(1)], + ), + ), + ]), + ), + ]; + + const func = t.functionDeclaration( + t.identifier('handleDelete'), + [argvParam, prompterParam, storeParam], + t.blockStatement(body), + false, + true, + ); + return func; +} + +export function generateAuthCommand(toolName: string): GeneratedFile { + const statements: t.Statement[] = []; + + statements.push( + createImportDeclaration('inquirerer', [ + 'CLIOptions', + 'Inquirerer', + 'extractFirst', + ]), + ); + statements.push( + createImportDeclaration('../executor', ['getStore']), + ); + + const usageStr = ` +${toolName} auth + +Commands: + set-token Set API token for the current context + status Show authentication status + logout Remove credentials for the current context + +Options: + --context Specify context (defaults to current context) + + --help, -h Show this help message +`; + + statements.push( + t.variableDeclaration('const', [ + t.variableDeclarator(t.identifier('usage'), t.stringLiteral(usageStr)), + ]), + ); + + const argvParam = t.identifier('argv'); + argvParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('Partial'), + t.tsTypeParameterInstantiation([ + t.tsTypeReference( + t.identifier('Record'), + t.tsTypeParameterInstantiation([ + t.tsStringKeyword(), + t.tsUnknownKeyword(), + ]), + ), + ]), + ), + ); + const prompterParam = t.identifier('prompter'); + prompterParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('Inquirerer')), + ); + const optionsParam = t.identifier('_options'); + optionsParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('CLIOptions')), + ); + + const mainBody: t.Statement[] = [ + t.ifStatement( + t.logicalExpression( + '||', + t.memberExpression(t.identifier('argv'), t.identifier('help')), + t.memberExpression(t.identifier('argv'), t.identifier('h')), + ), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [t.identifier('usage')], + ), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('process'), t.identifier('exit')), + [t.numericLiteral(0)], + ), + ), + ]), + ), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('store'), + t.callExpression(t.identifier('getStore'), []), + ), + ]), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.objectPattern([ + t.objectProperty( + t.identifier('first'), + t.identifier('subcommand'), + ), + t.objectProperty( + t.identifier('newArgv'), + t.identifier('newArgv'), + false, + true, + ), + ]), + t.callExpression(t.identifier('extractFirst'), [ + t.identifier('argv'), + ]), + ), + ]), + t.ifStatement( + t.unaryExpression('!', t.identifier('subcommand')), + t.blockStatement([ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('answer'), + t.awaitExpression( + t.callExpression( + t.memberExpression( + t.identifier('prompter'), + t.identifier('prompt'), + ), + [ + t.identifier('argv'), + t.arrayExpression([ + t.objectExpression([ + t.objectProperty( + t.identifier('type'), + t.stringLiteral('autocomplete'), + ), + t.objectProperty( + t.identifier('name'), + t.stringLiteral('subcommand'), + ), + t.objectProperty( + t.identifier('message'), + t.stringLiteral('What do you want to do?'), + ), + t.objectProperty( + t.identifier('options'), + t.arrayExpression([ + t.stringLiteral('set-token'), + t.stringLiteral('status'), + t.stringLiteral('logout'), + ]), + ), + ]), + ]), + ], + ), + ), + ), + ]), + t.returnStatement( + t.callExpression(t.identifier('handleAuthSubcommand'), [ + t.memberExpression( + t.identifier('answer'), + t.identifier('subcommand'), + ), + t.identifier('newArgv'), + t.identifier('prompter'), + t.identifier('store'), + ]), + ), + ]), + ), + t.returnStatement( + t.callExpression(t.identifier('handleAuthSubcommand'), [ + t.identifier('subcommand'), + t.identifier('newArgv'), + t.identifier('prompter'), + t.identifier('store'), + ]), + ), + ]; + + statements.push( + t.exportDefaultDeclaration( + t.arrowFunctionExpression( + [argvParam, prompterParam, optionsParam], + t.blockStatement(mainBody), + true, + ), + ), + ); + + const subcmdParam = t.identifier('subcommand'); + subcmdParam.typeAnnotation = t.tsTypeAnnotation(t.tsStringKeyword()); + const argvParam2 = t.identifier('argv'); + argvParam2.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('Partial'), + t.tsTypeParameterInstantiation([ + t.tsTypeReference( + t.identifier('Record'), + t.tsTypeParameterInstantiation([ + t.tsStringKeyword(), + t.tsUnknownKeyword(), + ]), + ), + ]), + ), + ); + const prompterParam2 = t.identifier('prompter'); + prompterParam2.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('Inquirerer')), + ); + const storeParam = t.identifier('store'); + storeParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('ReturnType'), + t.tsTypeParameterInstantiation([ + t.tsTypeQuery(t.identifier('getStore')), + ]), + ), + ); + + const handleAuthSubcommandFunc = t.functionDeclaration( + t.identifier('handleAuthSubcommand'), + [subcmdParam, argvParam2, prompterParam2, storeParam], + t.blockStatement([ + t.switchStatement(t.identifier('subcommand'), [ + buildSwitchCase('set-token', 'handleSetToken', [ + t.identifier('argv'), + t.identifier('prompter'), + t.identifier('store'), + ]), + buildSwitchCase('status', 'handleStatus', [t.identifier('store')]), + buildSwitchCase('logout', 'handleLogout', [ + t.identifier('argv'), + t.identifier('prompter'), + t.identifier('store'), + ]), + buildDefaultSwitchCase('usage'), + ]), + ]), + false, + true, + ); + statements.push(handleAuthSubcommandFunc); + + statements.push(buildSetTokenHandler()); + statements.push(buildStatusHandler()); + statements.push(buildLogoutHandler()); + + const header = getGeneratedFileHeader('Authentication commands'); + const code = generateCode(statements); + + return { + fileName: 'commands/auth.ts', + content: header + '\n' + code, + }; +} + +function buildSetTokenHandler(): t.FunctionDeclaration { + const argvParam = t.identifier('argv'); + argvParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('Partial'), + t.tsTypeParameterInstantiation([ + t.tsTypeReference( + t.identifier('Record'), + t.tsTypeParameterInstantiation([ + t.tsStringKeyword(), + t.tsUnknownKeyword(), + ]), + ), + ]), + ), + ); + const prompterParam = t.identifier('prompter'); + prompterParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('Inquirerer')), + ); + const storeParam = t.identifier('store'); + storeParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('ReturnType'), + t.tsTypeParameterInstantiation([ + t.tsTypeQuery(t.identifier('getStore')), + ]), + ), + ); + + const body: t.Statement[] = [ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('current'), + t.callExpression( + t.memberExpression( + t.identifier('store'), + t.identifier('getCurrentContext'), + ), + [], + ), + ), + ]), + t.ifStatement( + t.unaryExpression('!', t.identifier('current')), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('console'), + t.identifier('error'), + ), + [t.stringLiteral('No active context. Run "context create" first.')], + ), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('process'), t.identifier('exit')), + [t.numericLiteral(1)], + ), + ), + ]), + ), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.objectPattern([ + t.objectProperty(t.identifier('first'), t.identifier('token')), + ]), + t.callExpression(t.identifier('extractFirst'), [ + t.identifier('argv'), + ]), + ), + ]), + t.variableDeclaration('let', [ + t.variableDeclarator( + t.identifier('tokenValue'), + t.identifier('token'), + ), + ]), + t.ifStatement( + t.unaryExpression('!', t.identifier('tokenValue')), + t.blockStatement([ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('answer'), + t.awaitExpression( + t.callExpression( + t.memberExpression( + t.identifier('prompter'), + t.identifier('prompt'), + ), + [ + t.identifier('argv'), + t.arrayExpression([ + t.objectExpression([ + t.objectProperty( + t.identifier('type'), + t.stringLiteral('password'), + ), + t.objectProperty( + t.identifier('name'), + t.stringLiteral('token'), + ), + t.objectProperty( + t.identifier('message'), + t.stringLiteral('API Token'), + ), + t.objectProperty( + t.identifier('required'), + t.booleanLiteral(true), + ), + ]), + ]), + ], + ), + ), + ), + ]), + t.expressionStatement( + t.assignmentExpression( + '=', + t.identifier('tokenValue'), + t.memberExpression( + t.identifier('answer'), + t.identifier('token'), + ), + ), + ), + ]), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('store'), + t.identifier('setCredentials'), + ), + [ + t.memberExpression( + t.identifier('current'), + t.identifier('name'), + ), + t.objectExpression([ + t.objectProperty( + t.identifier('token'), + t.callExpression( + t.memberExpression( + t.callExpression( + t.memberExpression( + t.identifier('String'), + t.identifier('call'), + ), + [ + t.logicalExpression( + '||', + t.identifier('tokenValue'), + t.stringLiteral(''), + ), + ], + ), + t.identifier('trim'), + ), + [], + ), + ), + ]), + ], + ), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [ + t.templateLiteral( + [ + t.templateElement({ raw: 'Token saved for context: ', cooked: 'Token saved for context: ' }), + t.templateElement({ raw: '', cooked: '' }, true), + ], + [ + t.memberExpression( + t.identifier('current'), + t.identifier('name'), + ), + ], + ), + ], + ), + ), + ]; + + const func = t.functionDeclaration( + t.identifier('handleSetToken'), + [argvParam, prompterParam, storeParam], + t.blockStatement(body), + false, + true, + ); + return func; +} + +function buildStatusHandler(): t.FunctionDeclaration { + const storeParam = t.identifier('store'); + storeParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('ReturnType'), + t.tsTypeParameterInstantiation([ + t.tsTypeQuery(t.identifier('getStore')), + ]), + ), + ); + + const body: t.Statement[] = [ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('contexts'), + t.callExpression( + t.memberExpression( + t.identifier('store'), + t.identifier('listContexts'), + ), + [], + ), + ), + ]), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('settings'), + t.callExpression( + t.memberExpression( + t.identifier('store'), + t.identifier('loadSettings'), + ), + [], + ), + ), + ]), + t.ifStatement( + t.binaryExpression( + '===', + t.memberExpression( + t.identifier('contexts'), + t.identifier('length'), + ), + t.numericLiteral(0), + ), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('console'), + t.identifier('log'), + ), + [t.stringLiteral('No contexts configured.')], + ), + ), + t.returnStatement(), + ]), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [t.stringLiteral('Authentication Status:')], + ), + ), + t.forOfStatement( + t.variableDeclaration('const', [ + t.variableDeclarator(t.identifier('ctx')), + ]), + t.identifier('contexts'), + t.blockStatement([ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('isCurrent'), + t.binaryExpression( + '===', + t.memberExpression( + t.identifier('ctx'), + t.identifier('name'), + ), + t.memberExpression( + t.identifier('settings'), + t.identifier('currentContext'), + ), + ), + ), + ]), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('hasAuth'), + t.callExpression( + t.memberExpression( + t.identifier('store'), + t.identifier('hasValidCredentials'), + ), + [ + t.memberExpression( + t.identifier('ctx'), + t.identifier('name'), + ), + ], + ), + ), + ]), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('marker'), + t.conditionalExpression( + t.identifier('isCurrent'), + t.stringLiteral('* '), + t.stringLiteral(' '), + ), + ), + ]), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('status'), + t.conditionalExpression( + t.identifier('hasAuth'), + t.stringLiteral('authenticated'), + t.stringLiteral('no token'), + ), + ), + ]), + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('console'), + t.identifier('log'), + ), + [ + t.templateLiteral( + [ + t.templateElement({ raw: '', cooked: '' }), + t.templateElement({ raw: '', cooked: '' }), + t.templateElement({ raw: ' [', cooked: ' [' }), + t.templateElement({ raw: ']', cooked: ']' }, true), + ], + [ + t.identifier('marker'), + t.memberExpression( + t.identifier('ctx'), + t.identifier('name'), + ), + t.identifier('status'), + ], + ), + ], + ), + ), + ]), + ), + ]; + + const func = t.functionDeclaration( + t.identifier('handleStatus'), + [storeParam], + t.blockStatement(body), + ); + return func; +} + +function buildLogoutHandler(): t.FunctionDeclaration { + const argvParam = t.identifier('argv'); + argvParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('Partial'), + t.tsTypeParameterInstantiation([ + t.tsTypeReference( + t.identifier('Record'), + t.tsTypeParameterInstantiation([ + t.tsStringKeyword(), + t.tsUnknownKeyword(), + ]), + ), + ]), + ), + ); + const prompterParam = t.identifier('prompter'); + prompterParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('Inquirerer')), + ); + const storeParam = t.identifier('store'); + storeParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('ReturnType'), + t.tsTypeParameterInstantiation([ + t.tsTypeQuery(t.identifier('getStore')), + ]), + ), + ); + + const body: t.Statement[] = [ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('current'), + t.callExpression( + t.memberExpression( + t.identifier('store'), + t.identifier('getCurrentContext'), + ), + [], + ), + ), + ]), + t.ifStatement( + t.unaryExpression('!', t.identifier('current')), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('console'), + t.identifier('log'), + ), + [t.stringLiteral('No active context.')], + ), + ), + t.returnStatement(), + ]), + ), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('confirm'), + t.awaitExpression( + t.callExpression( + t.memberExpression( + t.identifier('prompter'), + t.identifier('prompt'), + ), + [ + t.identifier('argv'), + t.arrayExpression([ + t.objectExpression([ + t.objectProperty( + t.identifier('type'), + t.stringLiteral('confirm'), + ), + t.objectProperty( + t.identifier('name'), + t.stringLiteral('confirm'), + ), + t.objectProperty( + t.identifier('message'), + t.templateLiteral( + [ + t.templateElement({ + raw: 'Remove credentials for "', + cooked: 'Remove credentials for "', + }), + t.templateElement({ + raw: '"?', + cooked: '"?', + }, true), + ], + [ + t.memberExpression( + t.identifier('current'), + t.identifier('name'), + ), + ], + ), + ), + t.objectProperty( + t.identifier('default'), + t.booleanLiteral(false), + ), + ]), + ]), + ], + ), + ), + ), + ]), + t.ifStatement( + t.unaryExpression( + '!', + t.memberExpression( + t.identifier('confirm'), + t.identifier('confirm'), + ), + ), + t.blockStatement([t.returnStatement()]), + ), + t.ifStatement( + t.callExpression( + t.memberExpression( + t.identifier('store'), + t.identifier('removeCredentials'), + ), + [ + t.memberExpression( + t.identifier('current'), + t.identifier('name'), + ), + ], + ), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('console'), + t.identifier('log'), + ), + [ + t.templateLiteral( + [ + t.templateElement({ raw: 'Credentials removed for: ', cooked: 'Credentials removed for: ' }), + t.templateElement({ raw: '', cooked: '' }, true), + ], + [ + t.memberExpression( + t.identifier('current'), + t.identifier('name'), + ), + ], + ), + ], + ), + ), + ]), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('console'), + t.identifier('log'), + ), + [ + t.templateLiteral( + [ + t.templateElement({ raw: 'No credentials found for: ', cooked: 'No credentials found for: ' }), + t.templateElement({ raw: '', cooked: '' }, true), + ], + [ + t.memberExpression( + t.identifier('current'), + t.identifier('name'), + ), + ], + ), + ], + ), + ), + ]), + ), + ]; + + const func = t.functionDeclaration( + t.identifier('handleLogout'), + [argvParam, prompterParam, storeParam], + t.blockStatement(body), + false, + true, + ); + return func; +} diff --git a/graphql/codegen/src/core/codegen/cli/table-command-generator.ts b/graphql/codegen/src/core/codegen/cli/table-command-generator.ts new file mode 100644 index 000000000..82d42d8e0 --- /dev/null +++ b/graphql/codegen/src/core/codegen/cli/table-command-generator.ts @@ -0,0 +1,647 @@ +import * as t from '@babel/types'; +import { toKebabCase } from 'komoji'; + +import { generateCode } from '../babel-ast'; +import { + getGeneratedFileHeader, + getPrimaryKeyInfo, + getScalarFields, + getTableNames, + ucFirst, +} from '../utils'; +import type { CleanTable } from '../../../types/schema'; +import type { GeneratedFile } from './executor-generator'; + +function createImportDeclaration( + moduleSpecifier: string, + namedImports: string[], + typeOnly: boolean = false, +): t.ImportDeclaration { + const specifiers = namedImports.map((name) => + t.importSpecifier(t.identifier(name), t.identifier(name)), + ); + const decl = t.importDeclaration( + specifiers, + t.stringLiteral(moduleSpecifier), + ); + decl.importKind = typeOnly ? 'type' : 'value'; + return decl; +} + +function buildSelectObject(table: CleanTable): t.ObjectExpression { + const fields = getScalarFields(table); + return t.objectExpression( + fields.map((f) => + t.objectProperty(t.identifier(f.name), t.booleanLiteral(true)), + ), + ); +} + +function buildJsonLog(expr: t.Expression): t.ExpressionStatement { + return t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [ + t.callExpression( + t.memberExpression(t.identifier('JSON'), t.identifier('stringify')), + [expr, t.nullLiteral(), t.numericLiteral(2)], + ), + ], + ), + ); +} + +function buildOrmCall( + singularName: string, + methodName: string, + args: t.ObjectExpression, +): t.Expression { + return t.callExpression( + t.memberExpression( + t.callExpression( + t.memberExpression( + t.memberExpression( + t.identifier('client'), + t.identifier(singularName), + ), + t.identifier(methodName), + ), + [args], + ), + t.identifier('execute'), + ), + [], + ); +} + +function buildErrorCatch(errorMessage: string): t.CatchClause { + return t.catchClause( + t.identifier('error'), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('console'), + t.identifier('error'), + ), + [t.stringLiteral(errorMessage)], + ), + ), + t.ifStatement( + t.binaryExpression( + 'instanceof', + t.identifier('error'), + t.identifier('Error'), + ), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('console'), + t.identifier('error'), + ), + [ + t.memberExpression( + t.identifier('error'), + t.identifier('message'), + ), + ], + ), + ), + ]), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('process'), t.identifier('exit')), + [t.numericLiteral(1)], + ), + ), + ]), + ); +} + +function buildGetClientStatement(): t.VariableDeclaration { + return t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('client'), + t.callExpression(t.identifier('getClient'), []), + ), + ]); +} + +function buildArgvType(): t.TSTypeAnnotation { + return t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('Partial'), + t.tsTypeParameterInstantiation([ + t.tsTypeReference( + t.identifier('Record'), + t.tsTypeParameterInstantiation([ + t.tsStringKeyword(), + t.tsUnknownKeyword(), + ]), + ), + ]), + ), + ); +} + +function buildSubcommandSwitch( + subcommands: string[], + handlerPrefix: string, + usageVarName: string, +): t.SwitchStatement { + const cases = subcommands.map((sub) => + t.switchCase(t.stringLiteral(sub), [ + t.returnStatement( + t.callExpression(t.identifier(`${handlerPrefix}${ucFirst(sub)}`), [ + t.identifier('argv'), + t.identifier('prompter'), + ]), + ), + ]), + ); + cases.push( + t.switchCase(null, [ + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [t.identifier(usageVarName)], + ), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('process'), t.identifier('exit')), + [t.numericLiteral(1)], + ), + ), + ]), + ); + return t.switchStatement(t.identifier('subcommand'), cases); +} + +function buildListHandler(table: CleanTable): t.FunctionDeclaration { + const { singularName } = getTableNames(table); + const selectObj = buildSelectObject(table); + + const tryBody: t.Statement[] = [ + buildGetClientStatement(), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('result'), + t.awaitExpression( + buildOrmCall( + singularName, + 'findMany', + t.objectExpression([ + t.objectProperty(t.identifier('select'), selectObj), + ]), + ), + ), + ), + ]), + buildJsonLog(t.identifier('result')), + ]; + + const argvParam = t.identifier('_argv'); + argvParam.typeAnnotation = buildArgvType(); + const prompterParam = t.identifier('_prompter'); + prompterParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('Inquirerer')), + ); + + return t.functionDeclaration( + t.identifier('handleList'), + [argvParam, prompterParam], + t.blockStatement([ + t.tryStatement( + t.blockStatement(tryBody), + buildErrorCatch('Failed to list records.'), + ), + ]), + false, + true, + ); +} + +function buildGetHandler(table: CleanTable): t.FunctionDeclaration { + const { singularName } = getTableNames(table); + const pkFields = getPrimaryKeyInfo(table); + const pk = pkFields[0]; + const selectObj = buildSelectObject(table); + + const promptQuestion = t.objectExpression([ + t.objectProperty(t.identifier('type'), t.stringLiteral('text')), + t.objectProperty(t.identifier('name'), t.stringLiteral(pk.name)), + t.objectProperty(t.identifier('message'), t.stringLiteral(pk.name)), + t.objectProperty(t.identifier('required'), t.booleanLiteral(true)), + ]); + + const ormArgs = t.objectExpression([ + t.objectProperty( + t.identifier(pk.name), + t.memberExpression(t.identifier('answers'), t.identifier(pk.name)), + ), + t.objectProperty(t.identifier('select'), selectObj), + ]); + + const tryBody: t.Statement[] = [ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('answers'), + t.awaitExpression( + t.callExpression( + t.memberExpression( + t.identifier('prompter'), + t.identifier('prompt'), + ), + [t.identifier('argv'), t.arrayExpression([promptQuestion])], + ), + ), + ), + ]), + buildGetClientStatement(), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('result'), + t.awaitExpression(buildOrmCall(singularName, 'findOne', ormArgs)), + ), + ]), + buildJsonLog(t.identifier('result')), + ]; + + const argvParam = t.identifier('argv'); + argvParam.typeAnnotation = buildArgvType(); + const prompterParam = t.identifier('prompter'); + prompterParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('Inquirerer')), + ); + + return t.functionDeclaration( + t.identifier('handleGet'), + [argvParam, prompterParam], + t.blockStatement([ + t.tryStatement( + t.blockStatement(tryBody), + buildErrorCatch('Record not found.'), + ), + ]), + false, + true, + ); +} + +function buildMutationHandler( + table: CleanTable, + operation: 'create' | 'update' | 'delete', +): t.FunctionDeclaration { + const { singularName } = getTableNames(table); + const pkFields = getPrimaryKeyInfo(table); + const pk = pkFields[0]; + + const editableFields = getScalarFields(table).filter( + (f) => + f.name !== pk.name && + f.name !== 'nodeId' && + f.name !== 'createdAt' && + f.name !== 'updatedAt', + ); + + const questions: t.Expression[] = []; + + if (operation === 'update' || operation === 'delete') { + questions.push( + t.objectExpression([ + t.objectProperty(t.identifier('type'), t.stringLiteral('text')), + t.objectProperty(t.identifier('name'), t.stringLiteral(pk.name)), + t.objectProperty(t.identifier('message'), t.stringLiteral(pk.name)), + t.objectProperty(t.identifier('required'), t.booleanLiteral(true)), + ]), + ); + } + + if (operation !== 'delete') { + for (const field of editableFields) { + questions.push( + t.objectExpression([ + t.objectProperty(t.identifier('type'), t.stringLiteral('text')), + t.objectProperty( + t.identifier('name'), + t.stringLiteral(field.name), + ), + t.objectProperty( + t.identifier('message'), + t.stringLiteral(field.name), + ), + t.objectProperty( + t.identifier('required'), + t.booleanLiteral(operation === 'create'), + ), + ]), + ); + } + } + + const selectObj = + operation === 'delete' + ? t.objectExpression([ + t.objectProperty(t.identifier(pk.name), t.booleanLiteral(true)), + ]) + : buildSelectObject(table); + + let ormArgs: t.ObjectExpression; + + if (operation === 'create') { + const dataProps = editableFields.map((f) => + t.objectProperty( + t.identifier(f.name), + t.memberExpression(t.identifier('answers'), t.identifier(f.name)), + false, + true, + ), + ); + ormArgs = t.objectExpression([ + t.objectProperty(t.identifier('data'), t.objectExpression(dataProps)), + t.objectProperty(t.identifier('select'), selectObj), + ]); + } else if (operation === 'update') { + const dataProps = editableFields.map((f) => + t.objectProperty( + t.identifier(f.name), + t.memberExpression(t.identifier('answers'), t.identifier(f.name)), + false, + true, + ), + ); + ormArgs = t.objectExpression([ + t.objectProperty( + t.identifier(pk.name), + t.memberExpression(t.identifier('answers'), t.identifier(pk.name)), + ), + t.objectProperty(t.identifier('data'), t.objectExpression(dataProps)), + t.objectProperty(t.identifier('select'), selectObj), + ]); + } else { + ormArgs = t.objectExpression([ + t.objectProperty( + t.identifier(pk.name), + t.memberExpression(t.identifier('answers'), t.identifier(pk.name)), + ), + t.objectProperty(t.identifier('select'), selectObj), + ]); + } + + const tryBody: t.Statement[] = [ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('answers'), + t.awaitExpression( + t.callExpression( + t.memberExpression( + t.identifier('prompter'), + t.identifier('prompt'), + ), + [t.identifier('argv'), t.arrayExpression(questions)], + ), + ), + ), + ]), + buildGetClientStatement(), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('result'), + t.awaitExpression( + buildOrmCall(singularName, operation, ormArgs), + ), + ), + ]), + buildJsonLog(t.identifier('result')), + ]; + + const argvParam = t.identifier('argv'); + argvParam.typeAnnotation = buildArgvType(); + const prompterParam = t.identifier('prompter'); + prompterParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('Inquirerer')), + ); + + const handlerName = `handle${ucFirst(operation)}`; + + return t.functionDeclaration( + t.identifier(handlerName), + [argvParam, prompterParam], + t.blockStatement([ + t.tryStatement( + t.blockStatement(tryBody), + buildErrorCatch(`Failed to ${operation} record.`), + ), + ]), + false, + true, + ); +} + +export function generateTableCommand(table: CleanTable): GeneratedFile { + const { singularName } = getTableNames(table); + const commandName = toKebabCase(singularName); + const statements: t.Statement[] = []; + + statements.push( + createImportDeclaration('inquirerer', [ + 'CLIOptions', + 'Inquirerer', + 'extractFirst', + ]), + ); + statements.push( + createImportDeclaration('../executor', ['getClient']), + ); + + const subcommands = ['list', 'get', 'create', 'update', 'delete']; + + const usageLines = [ + '', + `${commandName} `, + '', + 'Commands:', + ` list List all ${singularName} records`, + ` get Get a ${singularName} by ID`, + ` create Create a new ${singularName}`, + ` update Update an existing ${singularName}`, + ` delete Delete a ${singularName}`, + '', + ' --help, -h Show this help message', + '', + ]; + + statements.push( + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('usage'), + t.stringLiteral(usageLines.join('\n')), + ), + ]), + ); + + const argvParam = t.identifier('argv'); + argvParam.typeAnnotation = buildArgvType(); + const prompterParam = t.identifier('prompter'); + prompterParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('Inquirerer')), + ); + const optionsParam = t.identifier('_options'); + optionsParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('CLIOptions')), + ); + + const mainBody: t.Statement[] = [ + t.ifStatement( + t.logicalExpression( + '||', + t.memberExpression(t.identifier('argv'), t.identifier('help')), + t.memberExpression(t.identifier('argv'), t.identifier('h')), + ), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [t.identifier('usage')], + ), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('process'), + t.identifier('exit'), + ), + [t.numericLiteral(0)], + ), + ), + ]), + ), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.objectPattern([ + t.objectProperty( + t.identifier('first'), + t.identifier('subcommand'), + ), + t.objectProperty( + t.identifier('newArgv'), + t.identifier('newArgv'), + false, + true, + ), + ]), + t.callExpression(t.identifier('extractFirst'), [ + t.identifier('argv'), + ]), + ), + ]), + t.ifStatement( + t.unaryExpression('!', t.identifier('subcommand')), + t.blockStatement([ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('answer'), + t.awaitExpression( + t.callExpression( + t.memberExpression( + t.identifier('prompter'), + t.identifier('prompt'), + ), + [ + t.identifier('argv'), + t.arrayExpression([ + t.objectExpression([ + t.objectProperty( + t.identifier('type'), + t.stringLiteral('autocomplete'), + ), + t.objectProperty( + t.identifier('name'), + t.stringLiteral('subcommand'), + ), + t.objectProperty( + t.identifier('message'), + t.stringLiteral('What do you want to do?'), + ), + t.objectProperty( + t.identifier('options'), + t.arrayExpression( + subcommands.map((s) => t.stringLiteral(s)), + ), + ), + ]), + ]), + ], + ), + ), + ), + ]), + t.returnStatement( + t.callExpression(t.identifier('handleTableSubcommand'), [ + t.memberExpression( + t.identifier('answer'), + t.identifier('subcommand'), + ), + t.identifier('newArgv'), + t.identifier('prompter'), + ]), + ), + ]), + ), + t.returnStatement( + t.callExpression(t.identifier('handleTableSubcommand'), [ + t.identifier('subcommand'), + t.identifier('newArgv'), + t.identifier('prompter'), + ]), + ), + ]; + + statements.push( + t.exportDefaultDeclaration( + t.arrowFunctionExpression( + [argvParam, prompterParam, optionsParam], + t.blockStatement(mainBody), + true, + ), + ), + ); + + const subcmdParam = t.identifier('subcommand'); + subcmdParam.typeAnnotation = t.tsTypeAnnotation(t.tsStringKeyword()); + const argvParam2 = t.identifier('argv'); + argvParam2.typeAnnotation = buildArgvType(); + const prompterParam2 = t.identifier('prompter'); + prompterParam2.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('Inquirerer')), + ); + + statements.push( + t.functionDeclaration( + t.identifier('handleTableSubcommand'), + [subcmdParam, argvParam2, prompterParam2], + t.blockStatement([ + buildSubcommandSwitch(subcommands, 'handle', 'usage'), + ]), + false, + true, + ), + ); + + statements.push(buildListHandler(table)); + statements.push(buildGetHandler(table)); + statements.push(buildMutationHandler(table, 'create')); + statements.push(buildMutationHandler(table, 'update')); + statements.push(buildMutationHandler(table, 'delete')); + + const header = getGeneratedFileHeader(`CLI commands for ${table.name}`); + const code = generateCode(statements); + + return { + fileName: `commands/${commandName}.ts`, + content: header + '\n' + code, + }; +} diff --git a/graphql/codegen/src/core/generate.ts b/graphql/codegen/src/core/generate.ts index ac09d72f0..3d4b22242 100644 --- a/graphql/codegen/src/core/generate.ts +++ b/graphql/codegen/src/core/generate.ts @@ -10,6 +10,7 @@ import type { GraphQLSDKConfigTarget } from '../types/config'; import { getConfigOptions } from '../types/config'; import { generate as generateReactQueryFiles } from './codegen'; import { generateRootBarrel } from './codegen/barrel'; +import { generateCli as generateCliFiles } from './codegen/cli'; import { generateOrm as generateOrmFiles } from './codegen/orm'; import { generateSharedTypes } from './codegen/shared'; import { createSchemaSource, validateSourceOptions } from './introspect'; @@ -51,12 +52,13 @@ export async function generate( const runReactQuery = config.reactQuery ?? false; const runOrm = runReactQuery || (options.orm !== undefined ? !!options.orm : false); + const runCli = !!config.cli; - if (!runReactQuery && !runOrm) { + if (!runReactQuery && !runOrm && !runCli) { return { success: false, message: - 'No generators enabled. Use reactQuery: true or orm: true in your config.', + 'No generators enabled. Use reactQuery: true, orm: true, or cli: true in your config.', output: outputRoot, }; } @@ -174,12 +176,32 @@ export async function generate( ); } + // Generate CLI commands + if (runCli) { + console.log('Generating CLI commands...'); + const { files } = generateCliFiles({ + tables, + customOperations: { + queries: customOperations.queries, + mutations: customOperations.mutations, + }, + config, + }); + filesToWrite.push( + ...files.map((file) => ({ + path: path.posix.join('cli', file.fileName), + content: file.content, + })), + ); + } + // Generate barrel file at output root // This re-exports from the appropriate subdirectories based on which generators are enabled const barrelContent = generateRootBarrel({ hasTypes: bothEnabled, hasHooks: runReactQuery, hasOrm: runOrm, + hasCli: runCli, }); filesToWrite.push({ path: 'index.ts', content: barrelContent }); @@ -198,7 +220,11 @@ export async function generate( allFilesWritten.push(...(writeResult.filesWritten ?? [])); } - const generators = [runReactQuery && 'React Query', runOrm && 'ORM'] + const generators = [ + runReactQuery && 'React Query', + runOrm && 'ORM', + runCli && 'CLI', + ] .filter(Boolean) .join(' and '); diff --git a/graphql/codegen/src/types/config.ts b/graphql/codegen/src/types/config.ts index 91cc9fd2d..54f0a6a18 100644 --- a/graphql/codegen/src/types/config.ts +++ b/graphql/codegen/src/types/config.ts @@ -136,6 +136,17 @@ export interface DbConfig { keepDb?: boolean; } +/** + * CLI generation configuration + */ +export interface CliConfig { + /** + * Tool name for appstash config storage (e.g., 'myapp' stores at ~/.myapp/) + * @default derived from output directory name + */ + toolName?: string; +} + /** * Target configuration for graphql-codegen * Represents a single schema source and output destination. @@ -259,6 +270,13 @@ export interface GraphQLSDKConfigTarget { */ reactQuery?: boolean; + /** + * CLI generation configuration + * When enabled, generates inquirerer-based CLI commands to {output}/cli + * Requires appstash for config storage and inquirerer for prompts + */ + cli?: CliConfig | boolean; + /** * Query key generation configuration * Controls how query keys are structured for cache management diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 19d1a67b3..ce9912cb8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,6 +10,7 @@ overrides: packageExtensionsChecksum: sha256-x8B4zkJ4KLRX+yspUWxuggXWlz6zrBLSIh72pNhpPiE= importers: + .: devDependencies: '@jest/test-sequencer': @@ -214,7 +215,7 @@ importers: version: 3.1.11 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@22.19.11)(typescript@5.9.3) + version: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) publishDirectory: dist graphile/graphile-query: @@ -376,7 +377,7 @@ importers: version: 3.1.11 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@22.19.11)(typescript@5.9.3) + version: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) publishDirectory: dist graphile/graphile-test: @@ -523,6 +524,9 @@ importers: jiti: specifier: ^2.6.1 version: 2.6.1 + komoji: + specifier: ^0.8.0 + version: 0.8.0 oxfmt: specifier: ^0.26.0 version: 0.26.0 @@ -644,7 +648,7 @@ importers: version: 3.1.11 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@22.19.11)(typescript@5.9.3) + version: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) publishDirectory: dist graphql/gql-ast: @@ -909,7 +913,7 @@ importers: version: 6.1.2 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@22.19.11)(typescript@5.9.3) + version: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) publishDirectory: dist graphql/server-test: @@ -1298,7 +1302,7 @@ importers: version: 7.2.2 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@22.19.11)(typescript@5.9.3) + version: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) publishDirectory: dist jobs/knative-job-worker: @@ -1585,7 +1589,7 @@ importers: version: 0.1.12 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@22.19.11)(typescript@5.9.3) + version: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) publishDirectory: dist packages/smtppostmaster: @@ -1614,7 +1618,7 @@ importers: version: 3.18.0 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@22.19.11)(typescript@5.9.3) + version: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) publishDirectory: dist packages/url-domains: @@ -2251,11 +2255,9 @@ importers: publishDirectory: dist packages: + '@0no-co/graphql.web@1.2.0': - resolution: - { - integrity: sha512-/1iHy9TTr63gE1YcR5idjx8UREz1s0kFhydf3bBLCXyqjhkIc6igAzTOx3zPifCwFR87tsh/4Pa9cNts6d2otw==, - } + resolution: {integrity: sha512-/1iHy9TTr63gE1YcR5idjx8UREz1s0kFhydf3bBLCXyqjhkIc6igAzTOx3zPifCwFR87tsh/4Pa9cNts6d2otw==} peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 peerDependenciesMeta: @@ -2263,405 +2265,231 @@ packages: optional: true '@antfu/install-pkg@1.1.0': - resolution: - { - integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==, - } + resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==} '@aws-crypto/crc32@5.2.0': - resolution: - { - integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==, - } - engines: { node: '>=16.0.0' } + resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} + engines: {node: '>=16.0.0'} '@aws-crypto/crc32c@5.2.0': - resolution: - { - integrity: sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==, - } + resolution: {integrity: sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==} '@aws-crypto/sha1-browser@5.2.0': - resolution: - { - integrity: sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==, - } + resolution: {integrity: sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==} '@aws-crypto/sha256-browser@5.2.0': - resolution: - { - integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==, - } + resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==} '@aws-crypto/sha256-js@5.2.0': - resolution: - { - integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==, - } - engines: { node: '>=16.0.0' } + resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==} + engines: {node: '>=16.0.0'} '@aws-crypto/supports-web-crypto@5.2.0': - resolution: - { - integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==, - } + resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==} '@aws-crypto/util@5.2.0': - resolution: - { - integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==, - } + resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} '@aws-sdk/client-s3@3.971.0': - resolution: - { - integrity: sha512-BBUne390fKa4C4QvZlUZ5gKcu+Uyid4IyQ20N4jl0vS7SK2xpfXlJcgKqPW5ts6kx6hWTQBk6sH5Lf12RvuJxg==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-BBUne390fKa4C4QvZlUZ5gKcu+Uyid4IyQ20N4jl0vS7SK2xpfXlJcgKqPW5ts6kx6hWTQBk6sH5Lf12RvuJxg==} + engines: {node: '>=20.0.0'} '@aws-sdk/client-sesv2@3.969.0': - resolution: - { - integrity: sha512-YnBJRtueyNAeKJvRNBVAeH9fh5X8KmMa4fp1Zn1Hex0G5bRKm0aUdS4i+p5cOIpCyBV9hyLGGkaCBDC4Han7aw==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-YnBJRtueyNAeKJvRNBVAeH9fh5X8KmMa4fp1Zn1Hex0G5bRKm0aUdS4i+p5cOIpCyBV9hyLGGkaCBDC4Han7aw==} + engines: {node: '>=20.0.0'} '@aws-sdk/client-sso@3.969.0': - resolution: - { - integrity: sha512-Qn0Uz6o15q2S+1E6OpwRKmaAMoT4LktEn+Oibk28qb2Mne+emaDawhZXahOJb/wFw5lN2FEH7XoiSNenNNUmCw==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-Qn0Uz6o15q2S+1E6OpwRKmaAMoT4LktEn+Oibk28qb2Mne+emaDawhZXahOJb/wFw5lN2FEH7XoiSNenNNUmCw==} + engines: {node: '>=20.0.0'} '@aws-sdk/client-sso@3.971.0': - resolution: - { - integrity: sha512-Xx+w6DQqJxDdymYyIxyKJnRzPvVJ4e/Aw0czO7aC9L/iraaV7AG8QtRe93OGW6aoHSh72CIiinnpJJfLsQqP4g==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-Xx+w6DQqJxDdymYyIxyKJnRzPvVJ4e/Aw0czO7aC9L/iraaV7AG8QtRe93OGW6aoHSh72CIiinnpJJfLsQqP4g==} + engines: {node: '>=20.0.0'} '@aws-sdk/core@3.969.0': - resolution: - { - integrity: sha512-qqmQt4z5rEK1OYVkVkboWgy/58CC5QaQ7oy0tvLe3iri/mfZbgJkA+pkwQyRP827DfCBZ3W7Ki9iwSa+B2U7uQ==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-qqmQt4z5rEK1OYVkVkboWgy/58CC5QaQ7oy0tvLe3iri/mfZbgJkA+pkwQyRP827DfCBZ3W7Ki9iwSa+B2U7uQ==} + engines: {node: '>=20.0.0'} '@aws-sdk/core@3.970.0': - resolution: - { - integrity: sha512-klpzObldOq8HXzDjDlY6K8rMhYZU6mXRz6P9F9N+tWnjoYFfeBMra8wYApydElTUYQKP1O7RLHwH1OKFfKcqIA==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-klpzObldOq8HXzDjDlY6K8rMhYZU6mXRz6P9F9N+tWnjoYFfeBMra8wYApydElTUYQKP1O7RLHwH1OKFfKcqIA==} + engines: {node: '>=20.0.0'} '@aws-sdk/crc64-nvme@3.969.0': - resolution: - { - integrity: sha512-IGNkP54HD3uuLnrPCYsv3ZD478UYq+9WwKrIVJ9Pdi3hxPg8562CH3ZHf8hEgfePN31P9Kj+Zu9kq2Qcjjt61A==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-IGNkP54HD3uuLnrPCYsv3ZD478UYq+9WwKrIVJ9Pdi3hxPg8562CH3ZHf8hEgfePN31P9Kj+Zu9kq2Qcjjt61A==} + engines: {node: '>=20.0.0'} '@aws-sdk/credential-provider-env@3.969.0': - resolution: - { - integrity: sha512-yS96heH5XDUqS3qQNcdObKKMOqZaivuNInMVRpRli48aXW8fX1M3fY67K/Onlqa3Wxu6WfDc3ZGF52SywdLvbg==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-yS96heH5XDUqS3qQNcdObKKMOqZaivuNInMVRpRli48aXW8fX1M3fY67K/Onlqa3Wxu6WfDc3ZGF52SywdLvbg==} + engines: {node: '>=20.0.0'} '@aws-sdk/credential-provider-env@3.970.0': - resolution: - { - integrity: sha512-rtVzXzEtAfZBfh+lq3DAvRar4c3jyptweOAJR2DweyXx71QSMY+O879hjpMwES7jl07a3O1zlnFIDo4KP/96kQ==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-rtVzXzEtAfZBfh+lq3DAvRar4c3jyptweOAJR2DweyXx71QSMY+O879hjpMwES7jl07a3O1zlnFIDo4KP/96kQ==} + engines: {node: '>=20.0.0'} '@aws-sdk/credential-provider-http@3.969.0': - resolution: - { - integrity: sha512-QCEFxBiUYFUW5VG6k8jKhT4luZndpC7uUY4u1olwt+OnJrl3N2yC7oS34isVBa3ioXZ4A0YagbXTa/3mXUhlAA==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-QCEFxBiUYFUW5VG6k8jKhT4luZndpC7uUY4u1olwt+OnJrl3N2yC7oS34isVBa3ioXZ4A0YagbXTa/3mXUhlAA==} + engines: {node: '>=20.0.0'} '@aws-sdk/credential-provider-http@3.970.0': - resolution: - { - integrity: sha512-CjDbWL7JxjLc9ZxQilMusWSw05yRvUJKRpz59IxDpWUnSMHC9JMMUUkOy5Izk8UAtzi6gupRWArp4NG4labt9Q==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-CjDbWL7JxjLc9ZxQilMusWSw05yRvUJKRpz59IxDpWUnSMHC9JMMUUkOy5Izk8UAtzi6gupRWArp4NG4labt9Q==} + engines: {node: '>=20.0.0'} '@aws-sdk/credential-provider-ini@3.969.0': - resolution: - { - integrity: sha512-lsXyTDkUrZPxjr0XruZrqdcHY9zHcIuoY3TOCQEm23VTc8Np2BenTtjGAIexkL3ar69K4u3FVLQroLpmFxeXqA==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-lsXyTDkUrZPxjr0XruZrqdcHY9zHcIuoY3TOCQEm23VTc8Np2BenTtjGAIexkL3ar69K4u3FVLQroLpmFxeXqA==} + engines: {node: '>=20.0.0'} '@aws-sdk/credential-provider-ini@3.971.0': - resolution: - { - integrity: sha512-c0TGJG4xyfTZz3SInXfGU8i5iOFRrLmy4Bo7lMyH+IpngohYMYGYl61omXqf2zdwMbDv+YJ9AviQTcCaEUKi8w==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-c0TGJG4xyfTZz3SInXfGU8i5iOFRrLmy4Bo7lMyH+IpngohYMYGYl61omXqf2zdwMbDv+YJ9AviQTcCaEUKi8w==} + engines: {node: '>=20.0.0'} '@aws-sdk/credential-provider-login@3.969.0': - resolution: - { - integrity: sha512-bIRFDf54qIUFFLTZNYt40d6EseNeK9w80dHEs7BVEAWoS23c9+MSqkdg/LJBBK9Kgy01vRmjiedfBZN+jGypLw==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-bIRFDf54qIUFFLTZNYt40d6EseNeK9w80dHEs7BVEAWoS23c9+MSqkdg/LJBBK9Kgy01vRmjiedfBZN+jGypLw==} + engines: {node: '>=20.0.0'} '@aws-sdk/credential-provider-login@3.971.0': - resolution: - { - integrity: sha512-yhbzmDOsk0RXD3rTPhZra4AWVnVAC4nFWbTp+sUty1hrOPurUmhuz8bjpLqYTHGnlMbJp+UqkQONhS2+2LzW2g==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-yhbzmDOsk0RXD3rTPhZra4AWVnVAC4nFWbTp+sUty1hrOPurUmhuz8bjpLqYTHGnlMbJp+UqkQONhS2+2LzW2g==} + engines: {node: '>=20.0.0'} '@aws-sdk/credential-provider-node@3.969.0': - resolution: - { - integrity: sha512-lImMjcy/5SGDIBk7PFJCqFO4rFuapKCvo1z2PidD3Cbz2D7wsJnyqUNQIp5Ix0Xc3/uAYG9zXI9kgaMf1dspIQ==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-lImMjcy/5SGDIBk7PFJCqFO4rFuapKCvo1z2PidD3Cbz2D7wsJnyqUNQIp5Ix0Xc3/uAYG9zXI9kgaMf1dspIQ==} + engines: {node: '>=20.0.0'} '@aws-sdk/credential-provider-node@3.971.0': - resolution: - { - integrity: sha512-epUJBAKivtJqalnEBRsYIULKYV063o/5mXNJshZfyvkAgNIzc27CmmKRXTN4zaNOZg8g/UprFp25BGsi19x3nQ==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-epUJBAKivtJqalnEBRsYIULKYV063o/5mXNJshZfyvkAgNIzc27CmmKRXTN4zaNOZg8g/UprFp25BGsi19x3nQ==} + engines: {node: '>=20.0.0'} '@aws-sdk/credential-provider-process@3.969.0': - resolution: - { - integrity: sha512-2qQkM0rwd8Hl9nIHtUaqT8Z/djrulovqx/wBHsbRKaISwc2fiT3De1Lk1jx34Jzrz/dTHAMJJi+cML1N4Lk3kw==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-2qQkM0rwd8Hl9nIHtUaqT8Z/djrulovqx/wBHsbRKaISwc2fiT3De1Lk1jx34Jzrz/dTHAMJJi+cML1N4Lk3kw==} + engines: {node: '>=20.0.0'} '@aws-sdk/credential-provider-process@3.970.0': - resolution: - { - integrity: sha512-0XeT8OaT9iMA62DFV9+m6mZfJhrD0WNKf4IvsIpj2Z7XbaYfz3CoDDvNoALf3rPY9NzyMHgDxOspmqdvXP00mw==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-0XeT8OaT9iMA62DFV9+m6mZfJhrD0WNKf4IvsIpj2Z7XbaYfz3CoDDvNoALf3rPY9NzyMHgDxOspmqdvXP00mw==} + engines: {node: '>=20.0.0'} '@aws-sdk/credential-provider-sso@3.969.0': - resolution: - { - integrity: sha512-JHqXw9Ct3dtZB86/zGFJYWyodr961GyIrqTBhV0brrZFPvcinM9abDSK58jt6GNBM2lqfMCvXL6I4ahNsMdkrg==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-JHqXw9Ct3dtZB86/zGFJYWyodr961GyIrqTBhV0brrZFPvcinM9abDSK58jt6GNBM2lqfMCvXL6I4ahNsMdkrg==} + engines: {node: '>=20.0.0'} '@aws-sdk/credential-provider-sso@3.971.0': - resolution: - { - integrity: sha512-dY0hMQ7dLVPQNJ8GyqXADxa9w5wNfmukgQniLxGVn+dMRx3YLViMp5ZpTSQpFhCWNF0oKQrYAI5cHhUJU1hETw==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-dY0hMQ7dLVPQNJ8GyqXADxa9w5wNfmukgQniLxGVn+dMRx3YLViMp5ZpTSQpFhCWNF0oKQrYAI5cHhUJU1hETw==} + engines: {node: '>=20.0.0'} '@aws-sdk/credential-provider-web-identity@3.969.0': - resolution: - { - integrity: sha512-mKCZtqrs3ts3YmIjT4NFlYgT2Oe6syW0nX5m2l7iyrFrLXw26Zo3rx29DjGzycPdJHZZvsIy5y6yqChDuF65ng==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-mKCZtqrs3ts3YmIjT4NFlYgT2Oe6syW0nX5m2l7iyrFrLXw26Zo3rx29DjGzycPdJHZZvsIy5y6yqChDuF65ng==} + engines: {node: '>=20.0.0'} '@aws-sdk/credential-provider-web-identity@3.971.0': - resolution: - { - integrity: sha512-F1AwfNLr7H52T640LNON/h34YDiMuIqW/ZreGzhRR6vnFGaSPtNSKAKB2ssAMkLM8EVg8MjEAYD3NCUiEo+t/w==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-F1AwfNLr7H52T640LNON/h34YDiMuIqW/ZreGzhRR6vnFGaSPtNSKAKB2ssAMkLM8EVg8MjEAYD3NCUiEo+t/w==} + engines: {node: '>=20.0.0'} '@aws-sdk/lib-storage@3.958.0': - resolution: - { - integrity: sha512-cd8CTiJ165ep2DKTc2PHHhVCxDn3byv10BXMGn+lkDY3KwMoatcgZ1uhFWCBuJvsCUnSExqGouJN/Q0qgjkWtg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-cd8CTiJ165ep2DKTc2PHHhVCxDn3byv10BXMGn+lkDY3KwMoatcgZ1uhFWCBuJvsCUnSExqGouJN/Q0qgjkWtg==} + engines: {node: '>=18.0.0'} peerDependencies: '@aws-sdk/client-s3': ^3.958.0 '@aws-sdk/middleware-bucket-endpoint@3.969.0': - resolution: - { - integrity: sha512-MlbrlixtkTVhYhoasblKOkr7n2yydvUZjjxTnBhIuHmkyBS1619oGnTfq/uLeGYb4NYXdeQ5OYcqsRGvmWSuTw==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-MlbrlixtkTVhYhoasblKOkr7n2yydvUZjjxTnBhIuHmkyBS1619oGnTfq/uLeGYb4NYXdeQ5OYcqsRGvmWSuTw==} + engines: {node: '>=20.0.0'} '@aws-sdk/middleware-expect-continue@3.969.0': - resolution: - { - integrity: sha512-qXygzSi8osok7tH9oeuS3HoKw6jRfbvg5Me/X5RlHOvSSqQz8c5O9f3MjUApaCUSwbAU92KrbZWasw2PKiaVHg==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-qXygzSi8osok7tH9oeuS3HoKw6jRfbvg5Me/X5RlHOvSSqQz8c5O9f3MjUApaCUSwbAU92KrbZWasw2PKiaVHg==} + engines: {node: '>=20.0.0'} '@aws-sdk/middleware-flexible-checksums@3.971.0': - resolution: - { - integrity: sha512-+hGUDUxeIw8s2kkjfeXym0XZxdh0cqkHkDpEanWYdS1gnWkIR+gf9u/DKbKqGHXILPaqHXhWpLTQTVlaB4sI7Q==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-+hGUDUxeIw8s2kkjfeXym0XZxdh0cqkHkDpEanWYdS1gnWkIR+gf9u/DKbKqGHXILPaqHXhWpLTQTVlaB4sI7Q==} + engines: {node: '>=20.0.0'} '@aws-sdk/middleware-host-header@3.969.0': - resolution: - { - integrity: sha512-AWa4rVsAfBR4xqm7pybQ8sUNJYnjyP/bJjfAw34qPuh3M9XrfGbAHG0aiAfQGrBnmS28jlO6Kz69o+c6PRw1dw==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-AWa4rVsAfBR4xqm7pybQ8sUNJYnjyP/bJjfAw34qPuh3M9XrfGbAHG0aiAfQGrBnmS28jlO6Kz69o+c6PRw1dw==} + engines: {node: '>=20.0.0'} '@aws-sdk/middleware-location-constraint@3.969.0': - resolution: - { - integrity: sha512-zH7pDfMLG/C4GWMOpvJEoYcSpj7XsNP9+irlgqwi667sUQ6doHQJ3yyDut3yiTk0maq1VgmriPFELyI9lrvH/g==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-zH7pDfMLG/C4GWMOpvJEoYcSpj7XsNP9+irlgqwi667sUQ6doHQJ3yyDut3yiTk0maq1VgmriPFELyI9lrvH/g==} + engines: {node: '>=20.0.0'} '@aws-sdk/middleware-logger@3.969.0': - resolution: - { - integrity: sha512-xwrxfip7Y2iTtCMJ+iifN1E1XMOuhxIHY9DreMCvgdl4r7+48x2S1bCYPWH3eNY85/7CapBWdJ8cerpEl12sQQ==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-xwrxfip7Y2iTtCMJ+iifN1E1XMOuhxIHY9DreMCvgdl4r7+48x2S1bCYPWH3eNY85/7CapBWdJ8cerpEl12sQQ==} + engines: {node: '>=20.0.0'} '@aws-sdk/middleware-recursion-detection@3.969.0': - resolution: - { - integrity: sha512-2r3PuNquU3CcS1Am4vn/KHFwLi8QFjMdA/R+CRDXT4AFO/0qxevF/YStW3gAKntQIgWgQV8ZdEtKAoJvLI4UWg==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-2r3PuNquU3CcS1Am4vn/KHFwLi8QFjMdA/R+CRDXT4AFO/0qxevF/YStW3gAKntQIgWgQV8ZdEtKAoJvLI4UWg==} + engines: {node: '>=20.0.0'} '@aws-sdk/middleware-sdk-s3@3.969.0': - resolution: - { - integrity: sha512-xjcyZrbtvVaqkmjkhmqX+16Wf7zFVS/cYnNFu/JyG6ekkIxSXEAjptNwSEDzlAiLzf0Hf6dYj5erLZYGa40eWg==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-xjcyZrbtvVaqkmjkhmqX+16Wf7zFVS/cYnNFu/JyG6ekkIxSXEAjptNwSEDzlAiLzf0Hf6dYj5erLZYGa40eWg==} + engines: {node: '>=20.0.0'} '@aws-sdk/middleware-sdk-s3@3.970.0': - resolution: - { - integrity: sha512-v/Y5F1lbFFY7vMeG5yYxuhnn0CAshz6KMxkz1pDyPxejNE9HtA0w8R6OTBh/bVdIm44QpjhbI7qeLdOE/PLzXQ==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-v/Y5F1lbFFY7vMeG5yYxuhnn0CAshz6KMxkz1pDyPxejNE9HtA0w8R6OTBh/bVdIm44QpjhbI7qeLdOE/PLzXQ==} + engines: {node: '>=20.0.0'} '@aws-sdk/middleware-ssec@3.971.0': - resolution: - { - integrity: sha512-QGVhvRveYG64ZhnS/b971PxXM6N2NU79Fxck4EfQ7am8v1Br0ctoeDDAn9nXNblLGw87we9Z65F7hMxxiFHd3w==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-QGVhvRveYG64ZhnS/b971PxXM6N2NU79Fxck4EfQ7am8v1Br0ctoeDDAn9nXNblLGw87we9Z65F7hMxxiFHd3w==} + engines: {node: '>=20.0.0'} '@aws-sdk/middleware-user-agent@3.969.0': - resolution: - { - integrity: sha512-Y6WkW8QQ2X9jG9HNBWyzp5KlJOCtLqX8VIvGLoGc2wXdZH7dgOy62uFhkfnHbgfiel6fkNYaycjGx/yyxi0JLQ==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-Y6WkW8QQ2X9jG9HNBWyzp5KlJOCtLqX8VIvGLoGc2wXdZH7dgOy62uFhkfnHbgfiel6fkNYaycjGx/yyxi0JLQ==} + engines: {node: '>=20.0.0'} '@aws-sdk/middleware-user-agent@3.970.0': - resolution: - { - integrity: sha512-dnSJGGUGSFGEX2NzvjwSefH+hmZQ347AwbLhAsi0cdnISSge+pcGfOFrJt2XfBIypwFe27chQhlfuf/gWdzpZg==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-dnSJGGUGSFGEX2NzvjwSefH+hmZQ347AwbLhAsi0cdnISSge+pcGfOFrJt2XfBIypwFe27chQhlfuf/gWdzpZg==} + engines: {node: '>=20.0.0'} '@aws-sdk/nested-clients@3.969.0': - resolution: - { - integrity: sha512-MJrejgODxVYZjQjSpPLJkVuxnbrue1x1R8+as3anT5V/wk9Qc/Pf5B1IFjM3Ak6uOtzuRYNY4auOvcg4U8twDA==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-MJrejgODxVYZjQjSpPLJkVuxnbrue1x1R8+as3anT5V/wk9Qc/Pf5B1IFjM3Ak6uOtzuRYNY4auOvcg4U8twDA==} + engines: {node: '>=20.0.0'} '@aws-sdk/nested-clients@3.971.0': - resolution: - { - integrity: sha512-TWaILL8GyYlhGrxxnmbkazM4QsXatwQgoWUvo251FXmUOsiXDFDVX3hoGIfB3CaJhV2pJPfebHUNJtY6TjZ11g==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-TWaILL8GyYlhGrxxnmbkazM4QsXatwQgoWUvo251FXmUOsiXDFDVX3hoGIfB3CaJhV2pJPfebHUNJtY6TjZ11g==} + engines: {node: '>=20.0.0'} '@aws-sdk/region-config-resolver@3.969.0': - resolution: - { - integrity: sha512-scj9OXqKpcjJ4jsFLtqYWz3IaNvNOQTFFvEY8XMJXTv+3qF5I7/x9SJtKzTRJEBF3spjzBUYPtGFbs9sj4fisQ==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-scj9OXqKpcjJ4jsFLtqYWz3IaNvNOQTFFvEY8XMJXTv+3qF5I7/x9SJtKzTRJEBF3spjzBUYPtGFbs9sj4fisQ==} + engines: {node: '>=20.0.0'} '@aws-sdk/signature-v4-multi-region@3.969.0': - resolution: - { - integrity: sha512-pv8BEQOlUzK+ww8ZfXZOnDzLfPO5+O7puBFtU1fE8CdCAQ/RP/B1XY3hxzW9Xs0dax7graYKnY8wd8ooYy7vBw==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-pv8BEQOlUzK+ww8ZfXZOnDzLfPO5+O7puBFtU1fE8CdCAQ/RP/B1XY3hxzW9Xs0dax7graYKnY8wd8ooYy7vBw==} + engines: {node: '>=20.0.0'} '@aws-sdk/signature-v4-multi-region@3.970.0': - resolution: - { - integrity: sha512-z3syXfuK/x/IsKf/AeYmgc2NT7fcJ+3fHaGO+fkghkV9WEba3fPyOwtTBX4KpFMNb2t50zDGZwbzW1/5ighcUQ==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-z3syXfuK/x/IsKf/AeYmgc2NT7fcJ+3fHaGO+fkghkV9WEba3fPyOwtTBX4KpFMNb2t50zDGZwbzW1/5ighcUQ==} + engines: {node: '>=20.0.0'} '@aws-sdk/token-providers@3.969.0': - resolution: - { - integrity: sha512-ucs6QczPkvGinbGmhMlPCQnagGJ+xsM6itsSWlJzxo9YsP6jR75cBU8pRdaM7nEbtCDnrUHf8W9g3D2Hd9mgVA==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-ucs6QczPkvGinbGmhMlPCQnagGJ+xsM6itsSWlJzxo9YsP6jR75cBU8pRdaM7nEbtCDnrUHf8W9g3D2Hd9mgVA==} + engines: {node: '>=20.0.0'} '@aws-sdk/token-providers@3.971.0': - resolution: - { - integrity: sha512-4hKGWZbmuDdONMJV0HJ+9jwTDb0zLfKxcCLx2GEnBY31Gt9GeyIQ+DZ97Bb++0voawj6pnZToFikXTyrEq2x+w==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-4hKGWZbmuDdONMJV0HJ+9jwTDb0zLfKxcCLx2GEnBY31Gt9GeyIQ+DZ97Bb++0voawj6pnZToFikXTyrEq2x+w==} + engines: {node: '>=20.0.0'} '@aws-sdk/types@3.969.0': - resolution: - { - integrity: sha512-7IIzM5TdiXn+VtgPdVLjmE6uUBUtnga0f4RiSEI1WW10RPuNvZ9U+pL3SwDiRDAdoGrOF9tSLJOFZmfuwYuVYQ==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-7IIzM5TdiXn+VtgPdVLjmE6uUBUtnga0f4RiSEI1WW10RPuNvZ9U+pL3SwDiRDAdoGrOF9tSLJOFZmfuwYuVYQ==} + engines: {node: '>=20.0.0'} '@aws-sdk/util-arn-parser@3.968.0': - resolution: - { - integrity: sha512-gqqvYcitIIM2K4lrDX9de9YvOfXBcVdxfT/iLnvHJd4YHvSXlt+gs+AsL4FfPCxG4IG9A+FyulP9Sb1MEA75vw==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-gqqvYcitIIM2K4lrDX9de9YvOfXBcVdxfT/iLnvHJd4YHvSXlt+gs+AsL4FfPCxG4IG9A+FyulP9Sb1MEA75vw==} + engines: {node: '>=20.0.0'} '@aws-sdk/util-endpoints@3.969.0': - resolution: - { - integrity: sha512-H2x2UwYiA1pHg40jE+OCSc668W9GXRShTiCWy1UPKtZKREbQ63Mgd7NAj+bEMsZUSCdHywqmSsLqKM9IcqQ3Bg==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-H2x2UwYiA1pHg40jE+OCSc668W9GXRShTiCWy1UPKtZKREbQ63Mgd7NAj+bEMsZUSCdHywqmSsLqKM9IcqQ3Bg==} + engines: {node: '>=20.0.0'} '@aws-sdk/util-endpoints@3.970.0': - resolution: - { - integrity: sha512-TZNZqFcMUtjvhZoZRtpEGQAdULYiy6rcGiXAbLU7e9LSpIYlRqpLa207oMNfgbzlL2PnHko+eVg8rajDiSOYCg==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-TZNZqFcMUtjvhZoZRtpEGQAdULYiy6rcGiXAbLU7e9LSpIYlRqpLa207oMNfgbzlL2PnHko+eVg8rajDiSOYCg==} + engines: {node: '>=20.0.0'} '@aws-sdk/util-locate-window@3.965.2': - resolution: - { - integrity: sha512-qKgO7wAYsXzhwCHhdbaKFyxd83Fgs8/1Ka+jjSPrv2Ll7mB55Wbwlo0kkfMLh993/yEc8aoDIAc1Fz9h4Spi4Q==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-qKgO7wAYsXzhwCHhdbaKFyxd83Fgs8/1Ka+jjSPrv2Ll7mB55Wbwlo0kkfMLh993/yEc8aoDIAc1Fz9h4Spi4Q==} + engines: {node: '>=20.0.0'} '@aws-sdk/util-user-agent-browser@3.969.0': - resolution: - { - integrity: sha512-bpJGjuKmFr0rA6UKUCmN8D19HQFMLXMx5hKBXqBlPFdalMhxJSjcxzX9DbQh0Fn6bJtxCguFmRGOBdQqNOt49g==, - } + resolution: {integrity: sha512-bpJGjuKmFr0rA6UKUCmN8D19HQFMLXMx5hKBXqBlPFdalMhxJSjcxzX9DbQh0Fn6bJtxCguFmRGOBdQqNOt49g==} '@aws-sdk/util-user-agent-node@3.969.0': - resolution: - { - integrity: sha512-D11ZuXNXdUMv8XTthMx+LPzkYNQAeQ68FnCTGnFLgLpnR8hVTeZMBBKjQ77wYGzWDk/csHKdCy697gU1On5KjA==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-D11ZuXNXdUMv8XTthMx+LPzkYNQAeQ68FnCTGnFLgLpnR8hVTeZMBBKjQ77wYGzWDk/csHKdCy697gU1On5KjA==} + engines: {node: '>=20.0.0'} peerDependencies: aws-crt: '>=1.0.0' peerDependenciesMeta: @@ -2669,11 +2497,8 @@ packages: optional: true '@aws-sdk/util-user-agent-node@3.971.0': - resolution: - { - integrity: sha512-Eygjo9mFzQYjbGY3MYO6CsIhnTwAMd3WmuFalCykqEmj2r5zf0leWrhPaqvA5P68V5JdGfPYgj7vhNOd6CtRBQ==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-Eygjo9mFzQYjbGY3MYO6CsIhnTwAMd3WmuFalCykqEmj2r5zf0leWrhPaqvA5P68V5JdGfPYgj7vhNOd6CtRBQ==} + engines: {node: '>=20.0.0'} peerDependencies: aws-crt: '>=1.0.0' peerDependenciesMeta: @@ -2681,437 +2506,263 @@ packages: optional: true '@aws-sdk/xml-builder@3.969.0': - resolution: - { - integrity: sha512-BSe4Lx/qdRQQdX8cSSI7Et20vqBspzAjBy8ZmXVoyLkol3y4sXBXzn+BiLtR+oh60ExQn6o2DU4QjdOZbXaKIQ==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-BSe4Lx/qdRQQdX8cSSI7Et20vqBspzAjBy8ZmXVoyLkol3y4sXBXzn+BiLtR+oh60ExQn6o2DU4QjdOZbXaKIQ==} + engines: {node: '>=20.0.0'} '@aws/lambda-invoke-store@0.2.3': - resolution: - { - integrity: sha512-oLvsaPMTBejkkmHhjf09xTgk71mOqyr/409NKhRIL08If7AhVfUsJhVsx386uJaqNd42v9kWamQ9lFbkoC2dYw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-oLvsaPMTBejkkmHhjf09xTgk71mOqyr/409NKhRIL08If7AhVfUsJhVsx386uJaqNd42v9kWamQ9lFbkoC2dYw==} + engines: {node: '>=18.0.0'} '@babel/code-frame@7.27.1': - resolution: - { - integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + engines: {node: '>=6.9.0'} '@babel/code-frame@7.28.6': - resolution: - { - integrity: sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==} + engines: {node: '>=6.9.0'} '@babel/compat-data@7.28.6': - resolution: - { - integrity: sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==} + engines: {node: '>=6.9.0'} '@babel/core@7.28.6': - resolution: - { - integrity: sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==} + engines: {node: '>=6.9.0'} '@babel/generator@7.28.6': - resolution: - { - integrity: sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==} + engines: {node: '>=6.9.0'} '@babel/helper-annotate-as-pure@7.27.3': - resolution: - { - integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} + engines: {node: '>=6.9.0'} '@babel/helper-compilation-targets@7.28.6': - resolution: - { - integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} + engines: {node: '>=6.9.0'} '@babel/helper-globals@7.28.0': - resolution: - { - integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} '@babel/helper-module-imports@7.27.1': - resolution: - { - integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + engines: {node: '>=6.9.0'} '@babel/helper-module-imports@7.28.6': - resolution: - { - integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} + engines: {node: '>=6.9.0'} '@babel/helper-module-transforms@7.28.6': - resolution: - { - integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} + engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 '@babel/helper-plugin-utils@7.27.1': - resolution: - { - integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} + engines: {node: '>=6.9.0'} '@babel/helper-plugin-utils@7.28.6': - resolution: - { - integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} + engines: {node: '>=6.9.0'} '@babel/helper-string-parser@7.27.1': - resolution: - { - integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} '@babel/helper-validator-identifier@7.28.5': - resolution: - { - integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} '@babel/helper-validator-option@7.27.1': - resolution: - { - integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} '@babel/helpers@7.28.6': - resolution: - { - integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==} + engines: {node: '>=6.9.0'} '@babel/parser@7.28.6': - resolution: - { - integrity: sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==, - } - engines: { node: '>=6.0.0' } + resolution: {integrity: sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==} + engines: {node: '>=6.0.0'} hasBin: true '@babel/plugin-syntax-async-generators@7.8.4': - resolution: - { - integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==, - } + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-bigint@7.8.3': - resolution: - { - integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==, - } + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-class-properties@7.12.13': - resolution: - { - integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==, - } + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-class-static-block@7.14.5': - resolution: - { - integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-import-attributes@7.28.6': - resolution: - { - integrity: sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==} + engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-import-meta@7.10.4': - resolution: - { - integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==, - } + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-json-strings@7.8.3': - resolution: - { - integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==, - } + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-jsx@7.27.1': - resolution: - { - integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==} + engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-jsx@7.28.6': - resolution: - { - integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==} + engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-logical-assignment-operators@7.10.4': - resolution: - { - integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==, - } + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': - resolution: - { - integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==, - } + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-numeric-separator@7.10.4': - resolution: - { - integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==, - } + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-object-rest-spread@7.8.3': - resolution: - { - integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==, - } + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-optional-catch-binding@7.8.3': - resolution: - { - integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==, - } + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-optional-chaining@7.8.3': - resolution: - { - integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==, - } + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-private-property-in-object@7.14.5': - resolution: - { - integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-top-level-await@7.14.5': - resolution: - { - integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-typescript@7.28.6': - resolution: - { - integrity: sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==} + engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-transform-react-jsx-self@7.27.1': - resolution: - { - integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} + engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-transform-react-jsx-source@7.27.1': - resolution: - { - integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==} + engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/runtime-corejs3@7.28.4': - resolution: - { - integrity: sha512-h7iEYiW4HebClDEhtvFObtPmIvrd1SSfpI9EhOeKk4CtIK/ngBWFpuhCzhdmRKtg71ylcue+9I6dv54XYO1epQ==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-h7iEYiW4HebClDEhtvFObtPmIvrd1SSfpI9EhOeKk4CtIK/ngBWFpuhCzhdmRKtg71ylcue+9I6dv54XYO1epQ==} + engines: {node: '>=6.9.0'} '@babel/runtime@7.28.4': - resolution: - { - integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} + engines: {node: '>=6.9.0'} '@babel/template@7.27.2': - resolution: - { - integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} + engines: {node: '>=6.9.0'} '@babel/template@7.28.6': - resolution: - { - integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} + engines: {node: '>=6.9.0'} '@babel/traverse@7.28.5': - resolution: - { - integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==} + engines: {node: '>=6.9.0'} '@babel/traverse@7.28.6': - resolution: - { - integrity: sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==} + engines: {node: '>=6.9.0'} '@babel/types@7.28.5': - resolution: - { - integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} + engines: {node: '>=6.9.0'} '@babel/types@7.28.6': - resolution: - { - integrity: sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==} + engines: {node: '>=6.9.0'} '@bcoe/v8-coverage@0.2.3': - resolution: - { - integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==, - } + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} '@braintree/sanitize-url@7.1.2': - resolution: - { - integrity: sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA==, - } + resolution: {integrity: sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA==} '@chevrotain/cst-dts-gen@11.0.3': - resolution: - { - integrity: sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==, - } + resolution: {integrity: sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==} '@chevrotain/gast@11.0.3': - resolution: - { - integrity: sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==, - } + resolution: {integrity: sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==} '@chevrotain/regexp-to-ast@11.0.3': - resolution: - { - integrity: sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==, - } + resolution: {integrity: sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==} '@chevrotain/types@11.0.3': - resolution: - { - integrity: sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==, - } + resolution: {integrity: sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==} '@chevrotain/utils@11.0.3': - resolution: - { - integrity: sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==, - } + resolution: {integrity: sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==} '@cspotcode/source-map-support@0.8.1': - resolution: - { - integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} '@dataplan/json@1.0.0-rc.4': - resolution: - { - integrity: sha512-H0edmEIh9MQk2xKlifHz3gB6rs1gYRpJcP7AkanQxEpKY7sQZLF8hv4T42OT9IZm5QF1QZX4QgimVIu+p93TjA==, - } - engines: { node: '>=22' } + resolution: {integrity: sha512-H0edmEIh9MQk2xKlifHz3gB6rs1gYRpJcP7AkanQxEpKY7sQZLF8hv4T42OT9IZm5QF1QZX4QgimVIu+p93TjA==} + engines: {node: '>=22'} peerDependencies: grafast: ^1.0.0-rc.5 '@dataplan/pg@1.0.0-rc.3': - resolution: - { - integrity: sha512-zDYsWx/uVKQWD4qVWHNq40es7jhlBrzna0HRla00h9l+i0jVUHbJHn0lv+Pupigrkyqc6YL+Vgi3nC1KH9hH0w==, - } - engines: { node: '>=22' } + resolution: {integrity: sha512-zDYsWx/uVKQWD4qVWHNq40es7jhlBrzna0HRla00h9l+i0jVUHbJHn0lv+Pupigrkyqc6YL+Vgi3nC1KH9hH0w==} + engines: {node: '>=22'} peerDependencies: '@dataplan/json': 1.0.0-rc.4 grafast: ^1.0.0-rc.4 @@ -3124,662 +2775,422 @@ packages: optional: true '@emnapi/core@1.7.1': - resolution: - { - integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==, - } + resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==} '@emnapi/core@1.8.1': - resolution: - { - integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==, - } + resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==} '@emnapi/runtime@1.7.1': - resolution: - { - integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==, - } + resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==} '@emnapi/runtime@1.8.1': - resolution: - { - integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==, - } + resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==} '@emnapi/wasi-threads@1.1.0': - resolution: - { - integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==, - } + resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} '@emotion/is-prop-valid@1.4.0': - resolution: - { - integrity: sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==, - } + resolution: {integrity: sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==} '@emotion/memoize@0.9.0': - resolution: - { - integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==, - } + resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==} '@emotion/stylis@0.8.5': - resolution: - { - integrity: sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==, - } + resolution: {integrity: sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==} '@emotion/unitless@0.7.5': - resolution: - { - integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==, - } + resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} '@esbuild/aix-ppc64@0.25.12': - resolution: - { - integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + engines: {node: '>=18'} cpu: [ppc64] os: [aix] '@esbuild/aix-ppc64@0.27.2': - resolution: - { - integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} + engines: {node: '>=18'} cpu: [ppc64] os: [aix] '@esbuild/android-arm64@0.25.12': - resolution: - { - integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + engines: {node: '>=18'} cpu: [arm64] os: [android] '@esbuild/android-arm64@0.27.2': - resolution: - { - integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==} + engines: {node: '>=18'} cpu: [arm64] os: [android] '@esbuild/android-arm@0.25.12': - resolution: - { - integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} + engines: {node: '>=18'} cpu: [arm] os: [android] '@esbuild/android-arm@0.27.2': - resolution: - { - integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==} + engines: {node: '>=18'} cpu: [arm] os: [android] '@esbuild/android-x64@0.25.12': - resolution: - { - integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} + engines: {node: '>=18'} cpu: [x64] os: [android] '@esbuild/android-x64@0.27.2': - resolution: - { - integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==} + engines: {node: '>=18'} cpu: [x64] os: [android] '@esbuild/darwin-arm64@0.25.12': - resolution: - { - integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} + engines: {node: '>=18'} cpu: [arm64] os: [darwin] '@esbuild/darwin-arm64@0.27.2': - resolution: - { - integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==} + engines: {node: '>=18'} cpu: [arm64] os: [darwin] '@esbuild/darwin-x64@0.25.12': - resolution: - { - integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + engines: {node: '>=18'} cpu: [x64] os: [darwin] '@esbuild/darwin-x64@0.27.2': - resolution: - { - integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==} + engines: {node: '>=18'} cpu: [x64] os: [darwin] '@esbuild/freebsd-arm64@0.25.12': - resolution: - { - integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} + engines: {node: '>=18'} cpu: [arm64] os: [freebsd] '@esbuild/freebsd-arm64@0.27.2': - resolution: - { - integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==} + engines: {node: '>=18'} cpu: [arm64] os: [freebsd] '@esbuild/freebsd-x64@0.25.12': - resolution: - { - integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} + engines: {node: '>=18'} cpu: [x64] os: [freebsd] '@esbuild/freebsd-x64@0.27.2': - resolution: - { - integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==} + engines: {node: '>=18'} cpu: [x64] os: [freebsd] '@esbuild/linux-arm64@0.25.12': - resolution: - { - integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + engines: {node: '>=18'} cpu: [arm64] os: [linux] '@esbuild/linux-arm64@0.27.2': - resolution: - { - integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==} + engines: {node: '>=18'} cpu: [arm64] os: [linux] '@esbuild/linux-arm@0.25.12': - resolution: - { - integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} + engines: {node: '>=18'} cpu: [arm] os: [linux] '@esbuild/linux-arm@0.27.2': - resolution: - { - integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==} + engines: {node: '>=18'} cpu: [arm] os: [linux] '@esbuild/linux-ia32@0.25.12': - resolution: - { - integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} + engines: {node: '>=18'} cpu: [ia32] os: [linux] '@esbuild/linux-ia32@0.27.2': - resolution: - { - integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==} + engines: {node: '>=18'} cpu: [ia32] os: [linux] '@esbuild/linux-loong64@0.25.12': - resolution: - { - integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} + engines: {node: '>=18'} cpu: [loong64] os: [linux] '@esbuild/linux-loong64@0.27.2': - resolution: - { - integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==} + engines: {node: '>=18'} cpu: [loong64] os: [linux] '@esbuild/linux-mips64el@0.25.12': - resolution: - { - integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} + engines: {node: '>=18'} cpu: [mips64el] os: [linux] '@esbuild/linux-mips64el@0.27.2': - resolution: - { - integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==} + engines: {node: '>=18'} cpu: [mips64el] os: [linux] '@esbuild/linux-ppc64@0.25.12': - resolution: - { - integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} + engines: {node: '>=18'} cpu: [ppc64] os: [linux] '@esbuild/linux-ppc64@0.27.2': - resolution: - { - integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==} + engines: {node: '>=18'} cpu: [ppc64] os: [linux] '@esbuild/linux-riscv64@0.25.12': - resolution: - { - integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} + engines: {node: '>=18'} cpu: [riscv64] os: [linux] '@esbuild/linux-riscv64@0.27.2': - resolution: - { - integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==} + engines: {node: '>=18'} cpu: [riscv64] os: [linux] '@esbuild/linux-s390x@0.25.12': - resolution: - { - integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} + engines: {node: '>=18'} cpu: [s390x] os: [linux] '@esbuild/linux-s390x@0.27.2': - resolution: - { - integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==} + engines: {node: '>=18'} cpu: [s390x] os: [linux] '@esbuild/linux-x64@0.25.12': - resolution: - { - integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} + engines: {node: '>=18'} cpu: [x64] os: [linux] '@esbuild/linux-x64@0.27.2': - resolution: - { - integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==} + engines: {node: '>=18'} cpu: [x64] os: [linux] '@esbuild/netbsd-arm64@0.25.12': - resolution: - { - integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} + engines: {node: '>=18'} cpu: [arm64] os: [netbsd] '@esbuild/netbsd-arm64@0.27.2': - resolution: - { - integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==} + engines: {node: '>=18'} cpu: [arm64] os: [netbsd] '@esbuild/netbsd-x64@0.25.12': - resolution: - { - integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} + engines: {node: '>=18'} cpu: [x64] os: [netbsd] '@esbuild/netbsd-x64@0.27.2': - resolution: - { - integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==} + engines: {node: '>=18'} cpu: [x64] os: [netbsd] '@esbuild/openbsd-arm64@0.25.12': - resolution: - { - integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} + engines: {node: '>=18'} cpu: [arm64] os: [openbsd] '@esbuild/openbsd-arm64@0.27.2': - resolution: - { - integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==} + engines: {node: '>=18'} cpu: [arm64] os: [openbsd] '@esbuild/openbsd-x64@0.25.12': - resolution: - { - integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} + engines: {node: '>=18'} cpu: [x64] os: [openbsd] '@esbuild/openbsd-x64@0.27.2': - resolution: - { - integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==} + engines: {node: '>=18'} cpu: [x64] os: [openbsd] '@esbuild/openharmony-arm64@0.25.12': - resolution: - { - integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} + engines: {node: '>=18'} cpu: [arm64] os: [openharmony] '@esbuild/openharmony-arm64@0.27.2': - resolution: - { - integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==} + engines: {node: '>=18'} cpu: [arm64] os: [openharmony] '@esbuild/sunos-x64@0.25.12': - resolution: - { - integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} + engines: {node: '>=18'} cpu: [x64] os: [sunos] '@esbuild/sunos-x64@0.27.2': - resolution: - { - integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==} + engines: {node: '>=18'} cpu: [x64] os: [sunos] '@esbuild/win32-arm64@0.25.12': - resolution: - { - integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} + engines: {node: '>=18'} cpu: [arm64] os: [win32] '@esbuild/win32-arm64@0.27.2': - resolution: - { - integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==} + engines: {node: '>=18'} cpu: [arm64] os: [win32] '@esbuild/win32-ia32@0.25.12': - resolution: - { - integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} + engines: {node: '>=18'} cpu: [ia32] os: [win32] '@esbuild/win32-ia32@0.27.2': - resolution: - { - integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==} + engines: {node: '>=18'} cpu: [ia32] os: [win32] '@esbuild/win32-x64@0.25.12': - resolution: - { - integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} + engines: {node: '>=18'} cpu: [x64] os: [win32] '@esbuild/win32-x64@0.27.2': - resolution: - { - integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==} + engines: {node: '>=18'} cpu: [x64] os: [win32] '@eslint-community/eslint-utils@4.9.0': - resolution: - { - integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 '@eslint-community/eslint-utils@4.9.1': - resolution: - { - integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 '@eslint-community/regexpp@4.12.2': - resolution: - { - integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==, - } - engines: { node: ^12.0.0 || ^14.0.0 || >=16.0.0 } + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} '@eslint/config-array@0.21.1': - resolution: - { - integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/config-helpers@0.4.2': - resolution: - { - integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/core@0.17.0': - resolution: - { - integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/eslintrc@3.3.3': - resolution: - { - integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/js@9.39.2': - resolution: - { - integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.7': - resolution: - { - integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/plugin-kit@0.4.1': - resolution: - { - integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@floating-ui/core@1.7.4': - resolution: - { - integrity: sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==, - } + resolution: {integrity: sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==} '@floating-ui/dom@1.7.5': - resolution: - { - integrity: sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==, - } + resolution: {integrity: sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==} '@floating-ui/react-dom@2.1.7': - resolution: - { - integrity: sha512-0tLRojf/1Go2JgEVm+3Frg9A3IW8bJgKgdO0BN5RkF//ufuz2joZM63Npau2ff3J6lUVYgDSNzNkR+aH3IVfjg==, - } + resolution: {integrity: sha512-0tLRojf/1Go2JgEVm+3Frg9A3IW8bJgKgdO0BN5RkF//ufuz2joZM63Npau2ff3J6lUVYgDSNzNkR+aH3IVfjg==} peerDependencies: react: '>=16.8.0' react-dom: '>=16.8.0' '@floating-ui/react@0.26.28': - resolution: - { - integrity: sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==, - } + resolution: {integrity: sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==} peerDependencies: react: '>=16.8.0' react-dom: '>=16.8.0' '@floating-ui/utils@0.2.10': - resolution: - { - integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==, - } + resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} '@graphile-contrib/pg-many-to-many@2.0.0-rc.1': - resolution: - { - integrity: sha512-qd6u50sxYFEzGPO6rjH+5OH6A8BFNhVsTuJaVD/JOfF2LIO+ANS8sT0MTicgZ9WLd+Eq6OYrYJD0iNUDN3Eing==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-qd6u50sxYFEzGPO6rjH+5OH6A8BFNhVsTuJaVD/JOfF2LIO+ANS8sT0MTicgZ9WLd+Eq6OYrYJD0iNUDN3Eing==} + engines: {node: '>=10'} '@graphile/lru@5.0.0-rc.4': - resolution: - { - integrity: sha512-QJibEzd/Fhxut3OS5opWd+b1kYUhg74hurepbhb4cHSW76U7Xp6vIPBh//eRznymIOVgE4KNDo7bKblM/NGbVA==, - } - engines: { node: '>=22' } + resolution: {integrity: sha512-QJibEzd/Fhxut3OS5opWd+b1kYUhg74hurepbhb4cHSW76U7Xp6vIPBh//eRznymIOVgE4KNDo7bKblM/NGbVA==} + engines: {node: '>=22'} '@graphile/simplify-inflection@8.0.0-rc.3': - resolution: - { - integrity: sha512-2ujrwI5P7tNDUfr0NegXmU6M9cwyBPoGGy+sykQne5jf2PUgdwJz4HxLsyFT/ykukwZt5Kcrm7Thik2f7reiJA==, - } + resolution: {integrity: sha512-2ujrwI5P7tNDUfr0NegXmU6M9cwyBPoGGy+sykQne5jf2PUgdwJz4HxLsyFT/ykukwZt5Kcrm7Thik2f7reiJA==} '@graphiql/plugin-doc-explorer@0.4.1': - resolution: - { - integrity: sha512-+ram1dDDGMqJn/f9n5I8E6grTvxcM9JZYt/HhtYLuCvkN8kERI6/E3zBHBshhIUnQZoXioZ03fAzXg7JOn0Kyg==, - } + resolution: {integrity: sha512-+ram1dDDGMqJn/f9n5I8E6grTvxcM9JZYt/HhtYLuCvkN8kERI6/E3zBHBshhIUnQZoXioZ03fAzXg7JOn0Kyg==} peerDependencies: '@graphiql/react': ^0.37.0 graphql: ^15.5.0 || ^16.0.0 || ^17.0.0 @@ -3788,10 +3199,7 @@ packages: react-dom: ^18 || ^19 '@graphiql/plugin-explorer@5.1.1': - resolution: - { - integrity: sha512-JknPfk3f/LBWz7HXSTeiRPN6O14rkYTK1ORew7YJsGWUJ3mqZNNlaxOleP5DD+yAgpLExIoCW4TDGOcPdJ0h0w==, - } + resolution: {integrity: sha512-JknPfk3f/LBWz7HXSTeiRPN6O14rkYTK1ORew7YJsGWUJ3mqZNNlaxOleP5DD+yAgpLExIoCW4TDGOcPdJ0h0w==} peerDependencies: '@graphiql/react': ^0.37.0 graphql: ^15.5.0 || ^16.0.0 || ^17.0.0-alpha.2 @@ -3799,10 +3207,7 @@ packages: react-dom: ^18 || ^19 '@graphiql/plugin-history@0.4.1': - resolution: - { - integrity: sha512-UyGI/Nm5tzKNMB71li41p6TfkthLqHkmNi9CgHzAM1zKgPIrtSq7Q8WCWKHLOEB5n4/8X8sXFeyQfHgnGYTXYg==, - } + resolution: {integrity: sha512-UyGI/Nm5tzKNMB71li41p6TfkthLqHkmNi9CgHzAM1zKgPIrtSq7Q8WCWKHLOEB5n4/8X8sXFeyQfHgnGYTXYg==} peerDependencies: '@graphiql/react': ^0.37.0 react: ^18 || ^19 @@ -3810,10 +3215,7 @@ packages: react-dom: ^18 || ^19 '@graphiql/react@0.37.3': - resolution: - { - integrity: sha512-rNJjwsYGhcZRdZ2FnyU6ss06xQaZ4UordyvOhp7+b/bEqQiEBpMOLJjuUr48Z6T7zEbZBnzCJpIJyXNqlcfQeA==, - } + resolution: {integrity: sha512-rNJjwsYGhcZRdZ2FnyU6ss06xQaZ4UordyvOhp7+b/bEqQiEBpMOLJjuUr48Z6T7zEbZBnzCJpIJyXNqlcfQeA==} peerDependencies: graphql: ^15.5.0 || ^16.0.0 || ^17.0.0 react: ^18 || ^19 @@ -3821,10 +3223,7 @@ packages: react-dom: ^18 || ^19 '@graphiql/toolkit@0.11.3': - resolution: - { - integrity: sha512-Glf0fK1cdHLNq52UWPzfSrYIJuNxy8h4451Pw1ZVpJ7dtU+tm7GVVC64UjEDQ/v2j3fnG4cX8jvR75IvfL6nzQ==, - } + resolution: {integrity: sha512-Glf0fK1cdHLNq52UWPzfSrYIJuNxy8h4451Pw1ZVpJ7dtU+tm7GVVC64UjEDQ/v2j3fnG4cX8jvR75IvfL6nzQ==} peerDependencies: graphql: ^15.5.0 || ^16.0.0 || ^17.0.0 graphql-ws: '>= 4.5.0' @@ -3833,76 +3232,46 @@ packages: optional: true '@graphql-typed-document-node/core@3.2.0': - resolution: - { - integrity: sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==, - } + resolution: {integrity: sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==} peerDependencies: graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 '@headlessui/react@2.2.9': - resolution: - { - integrity: sha512-Mb+Un58gwBn0/yWZfyrCh0TJyurtT+dETj7YHleylHk5od3dv2XqETPGWMyQ5/7sYN7oWdyM1u9MvC0OC8UmzQ==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-Mb+Un58gwBn0/yWZfyrCh0TJyurtT+dETj7YHleylHk5od3dv2XqETPGWMyQ5/7sYN7oWdyM1u9MvC0OC8UmzQ==} + engines: {node: '>=10'} peerDependencies: react: ^18 || ^19 || ^19.0.0-rc react-dom: ^18 || ^19 || ^19.0.0-rc '@humanfs/core@0.19.1': - resolution: - { - integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==, - } - engines: { node: '>=18.18.0' } + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} '@humanfs/node@0.16.7': - resolution: - { - integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==, - } - engines: { node: '>=18.18.0' } + resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} + engines: {node: '>=18.18.0'} '@humanwhocodes/module-importer@1.0.1': - resolution: - { - integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==, - } - engines: { node: '>=12.22' } + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} '@humanwhocodes/retry@0.4.3': - resolution: - { - integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==, - } - engines: { node: '>=18.18' } + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} '@hutson/parse-repository-url@3.0.2': - resolution: - { - integrity: sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==} + engines: {node: '>=6.9.0'} '@iconify/types@2.0.0': - resolution: - { - integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==, - } + resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} '@iconify/utils@3.1.0': - resolution: - { - integrity: sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw==, - } + resolution: {integrity: sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw==} '@inquirer/external-editor@1.0.3': - resolution: - { - integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} + engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' peerDependenciesMeta: @@ -3910,10 +3279,7 @@ packages: optional: true '@inquirerer/test@1.3.0': - resolution: - { - integrity: sha512-uKn1yJ66MKaPf8ECxoTRma6+lQSLy1YtBOXHDrTGn/j6xtCDdfDYw34h51gM0MLimPTd1vAoxMG+zQGXRSHZLg==, - } + resolution: {integrity: sha512-uKn1yJ66MKaPf8ECxoTRma6+lQSLy1YtBOXHDrTGn/j6xtCDdfDYw34h51gM0MLimPTd1vAoxMG+zQGXRSHZLg==} peerDependencies: jest: '>=29.0.0' peerDependenciesMeta: @@ -3921,79 +3287,46 @@ packages: optional: true '@inquirerer/utils@3.2.3': - resolution: - { - integrity: sha512-Ak0GspJ8fT9aW9pp1Op53xebtJOoZpt1/7eklI1TpUh7QuLxqmk2cl7sGMP1mROvR3q5Ms10ZvJ3eS2GKI++yw==, - } + resolution: {integrity: sha512-Ak0GspJ8fT9aW9pp1Op53xebtJOoZpt1/7eklI1TpUh7QuLxqmk2cl7sGMP1mROvR3q5Ms10ZvJ3eS2GKI++yw==} '@isaacs/balanced-match@4.0.1': - resolution: - { - integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} + engines: {node: 20 || >=22} '@isaacs/brace-expansion@5.0.0': - resolution: - { - integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==} + engines: {node: 20 || >=22} '@isaacs/brace-expansion@5.0.1': - resolution: - { - integrity: sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==} + engines: {node: 20 || >=22} '@isaacs/cliui@8.0.2': - resolution: - { - integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} '@isaacs/cliui@9.0.0': - resolution: - { - integrity: sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==} + engines: {node: '>=18'} '@isaacs/string-locale-compare@1.1.0': - resolution: - { - integrity: sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==, - } + resolution: {integrity: sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==} '@istanbuljs/load-nyc-config@1.1.0': - resolution: - { - integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} '@istanbuljs/schema@0.1.3': - resolution: - { - integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} '@jest/console@30.2.0': - resolution: - { - integrity: sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} '@jest/core@30.2.0': - resolution: - { - integrity: sha512-03W6IhuhjqTlpzh/ojut/pDB2LPRygyWX8ExpgHtQA8H/3K7+1vKmcINx5UzeOX1se6YEsBsOHQ1CRzf3fOwTQ==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-03W6IhuhjqTlpzh/ojut/pDB2LPRygyWX8ExpgHtQA8H/3K7+1vKmcINx5UzeOX1se6YEsBsOHQ1CRzf3fOwTQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 peerDependenciesMeta: @@ -4001,67 +3334,40 @@ packages: optional: true '@jest/diff-sequences@30.0.1': - resolution: - { - integrity: sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} '@jest/environment@30.2.0': - resolution: - { - integrity: sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} '@jest/expect-utils@30.2.0': - resolution: - { - integrity: sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} '@jest/expect@30.2.0': - resolution: - { - integrity: sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} '@jest/fake-timers@30.2.0': - resolution: - { - integrity: sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} '@jest/get-type@30.1.0': - resolution: - { - integrity: sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} '@jest/globals@30.2.0': - resolution: - { - integrity: sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} '@jest/pattern@30.0.1': - resolution: - { - integrity: sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} '@jest/reporters@30.2.0': - resolution: - { - integrity: sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 peerDependenciesMeta: @@ -4069,713 +3375,408 @@ packages: optional: true '@jest/schemas@29.6.3': - resolution: - { - integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==, - } - engines: { node: ^14.15.0 || ^16.10.0 || >=18.0.0 } + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} '@jest/schemas@30.0.5': - resolution: - { - integrity: sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} '@jest/snapshot-utils@30.2.0': - resolution: - { - integrity: sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} '@jest/source-map@30.0.1': - resolution: - { - integrity: sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} '@jest/test-result@30.2.0': - resolution: - { - integrity: sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} '@jest/test-sequencer@30.2.0': - resolution: - { - integrity: sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} '@jest/transform@30.2.0': - resolution: - { - integrity: sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} '@jest/types@26.6.2': - resolution: - { - integrity: sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==, - } - engines: { node: '>= 10.14.2' } + resolution: {integrity: sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==} + engines: {node: '>= 10.14.2'} '@jest/types@30.2.0': - resolution: - { - integrity: sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} '@jridgewell/gen-mapping@0.3.13': - resolution: - { - integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==, - } + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} '@jridgewell/remapping@2.3.5': - resolution: - { - integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==, - } + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} '@jridgewell/resolve-uri@3.1.2': - resolution: - { - integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==, - } - engines: { node: '>=6.0.0' } + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} '@jridgewell/sourcemap-codec@1.5.5': - resolution: - { - integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==, - } + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} '@jridgewell/trace-mapping@0.3.31': - resolution: - { - integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==, - } + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} '@jridgewell/trace-mapping@0.3.9': - resolution: - { - integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==, - } + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} '@launchql/mjml@0.1.1': - resolution: - { - integrity: sha512-6+OEmECuu5atRZ43ovsMfFs+T4NWNaKbzNG0uA8HYaBSn3kWR7GH3QnmL3lCIeymLtvgua8aZChYvg6SxrQdnw==, - } + resolution: {integrity: sha512-6+OEmECuu5atRZ43ovsMfFs+T4NWNaKbzNG0uA8HYaBSn3kWR7GH3QnmL3lCIeymLtvgua8aZChYvg6SxrQdnw==} peerDependencies: react: '>=16' react-dom: '>=16' '@launchql/protobufjs@7.2.6': - resolution: - { - integrity: sha512-vwi1nG2/heVFsIMHQU1KxTjUp5c757CTtRAZn/jutApCkFlle1iv8tzM/DHlSZJKDldxaYqnNYTg0pTyp8Bbtg==, - } - engines: { node: '>=12.0.0' } + resolution: {integrity: sha512-vwi1nG2/heVFsIMHQU1KxTjUp5c757CTtRAZn/jutApCkFlle1iv8tzM/DHlSZJKDldxaYqnNYTg0pTyp8Bbtg==} + engines: {node: '>=12.0.0'} '@launchql/styled-email@0.1.0': - resolution: - { - integrity: sha512-ISjzsY+3EOH/qAKHPq3evw9QmmEyA8Vw+0pUf+Zf8l4/rAHJJKrSa/uPiaUf2Abi8yAZKyx2uyaZq4ExNNkD+w==, - } + resolution: {integrity: sha512-ISjzsY+3EOH/qAKHPq3evw9QmmEyA8Vw+0pUf+Zf8l4/rAHJJKrSa/uPiaUf2Abi8yAZKyx2uyaZq4ExNNkD+w==} peerDependencies: react: '>=16' react-dom: '>=16' '@lerna/create@8.2.4': - resolution: - { - integrity: sha512-A8AlzetnS2WIuhijdAzKUyFpR5YbLLfV3luQ4lzBgIBgRfuoBDZeF+RSZPhra+7A6/zTUlrbhKZIOi/MNhqgvQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-A8AlzetnS2WIuhijdAzKUyFpR5YbLLfV3luQ4lzBgIBgRfuoBDZeF+RSZPhra+7A6/zTUlrbhKZIOi/MNhqgvQ==} + engines: {node: '>=18.0.0'} '@mermaid-js/parser@0.6.3': - resolution: - { - integrity: sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA==, - } + resolution: {integrity: sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA==} '@n1ru4l/push-pull-async-iterable-iterator@3.2.0': - resolution: - { - integrity: sha512-3fkKj25kEjsfObL6IlKPAlHYPq/oYwUkkQ03zsTTiDjD7vg/RxjdiLeCydqtxHZP0JgsXL3D/X5oAkMGzuUp/Q==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-3fkKj25kEjsfObL6IlKPAlHYPq/oYwUkkQ03zsTTiDjD7vg/RxjdiLeCydqtxHZP0JgsXL3D/X5oAkMGzuUp/Q==} + engines: {node: '>=12'} '@napi-rs/wasm-runtime@0.2.12': - resolution: - { - integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==, - } + resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} '@napi-rs/wasm-runtime@0.2.4': - resolution: - { - integrity: sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==, - } + resolution: {integrity: sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==} '@noble/hashes@1.8.0': - resolution: - { - integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==, - } - engines: { node: ^14.21.3 || >=16 } + resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} + engines: {node: ^14.21.3 || >=16} '@nodelib/fs.scandir@2.1.5': - resolution: - { - integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==, - } - engines: { node: '>= 8' } + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} '@nodelib/fs.stat@2.0.5': - resolution: - { - integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==, - } - engines: { node: '>= 8' } + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} '@nodelib/fs.walk@1.2.8': - resolution: - { - integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==, - } - engines: { node: '>= 8' } + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} '@npmcli/agent@2.2.2': - resolution: - { - integrity: sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==} + engines: {node: ^16.14.0 || >=18.0.0} '@npmcli/arborist@7.5.4': - resolution: - { - integrity: sha512-nWtIc6QwwoUORCRNzKx4ypHqCk3drI+5aeYdMTQQiRCcn4lOOgfQh7WyZobGYTxXPSq1VwV53lkpN/BRlRk08g==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-nWtIc6QwwoUORCRNzKx4ypHqCk3drI+5aeYdMTQQiRCcn4lOOgfQh7WyZobGYTxXPSq1VwV53lkpN/BRlRk08g==} + engines: {node: ^16.14.0 || >=18.0.0} hasBin: true '@npmcli/fs@3.1.1': - resolution: - { - integrity: sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} '@npmcli/git@5.0.8': - resolution: - { - integrity: sha512-liASfw5cqhjNW9UFd+ruwwdEf/lbOAQjLL2XY2dFW/bkJheXDYZgOyul/4gVvEV4BWkTXjYGmDqMw9uegdbJNQ==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-liASfw5cqhjNW9UFd+ruwwdEf/lbOAQjLL2XY2dFW/bkJheXDYZgOyul/4gVvEV4BWkTXjYGmDqMw9uegdbJNQ==} + engines: {node: ^16.14.0 || >=18.0.0} '@npmcli/installed-package-contents@2.1.0': - resolution: - { - integrity: sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} hasBin: true '@npmcli/map-workspaces@3.0.6': - resolution: - { - integrity: sha512-tkYs0OYnzQm6iIRdfy+LcLBjcKuQCeE5YLb8KnrIlutJfheNaPvPpgoFEyEFgbjzl5PLZ3IA/BWAwRU0eHuQDA==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-tkYs0OYnzQm6iIRdfy+LcLBjcKuQCeE5YLb8KnrIlutJfheNaPvPpgoFEyEFgbjzl5PLZ3IA/BWAwRU0eHuQDA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} '@npmcli/metavuln-calculator@7.1.1': - resolution: - { - integrity: sha512-Nkxf96V0lAx3HCpVda7Vw4P23RILgdi/5K1fmj2tZkWIYLpXAN8k2UVVOsW16TsS5F8Ws2I7Cm+PU1/rsVF47g==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-Nkxf96V0lAx3HCpVda7Vw4P23RILgdi/5K1fmj2tZkWIYLpXAN8k2UVVOsW16TsS5F8Ws2I7Cm+PU1/rsVF47g==} + engines: {node: ^16.14.0 || >=18.0.0} '@npmcli/name-from-folder@2.0.0': - resolution: - { - integrity: sha512-pwK+BfEBZJbKdNYpHHRTNBwBoqrN/iIMO0AiGvYsp3Hoaq0WbgGSWQR6SCldZovoDpY3yje5lkFUe6gsDgJ2vg==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-pwK+BfEBZJbKdNYpHHRTNBwBoqrN/iIMO0AiGvYsp3Hoaq0WbgGSWQR6SCldZovoDpY3yje5lkFUe6gsDgJ2vg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} '@npmcli/node-gyp@3.0.0': - resolution: - { - integrity: sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} '@npmcli/package-json@5.2.0': - resolution: - { - integrity: sha512-qe/kiqqkW0AGtvBjL8TJKZk/eBBSpnJkUWvHdQ9jM2lKHXRYYJuyNpJPlJw3c8QjC2ow6NZYiLExhUaeJelbxQ==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-qe/kiqqkW0AGtvBjL8TJKZk/eBBSpnJkUWvHdQ9jM2lKHXRYYJuyNpJPlJw3c8QjC2ow6NZYiLExhUaeJelbxQ==} + engines: {node: ^16.14.0 || >=18.0.0} '@npmcli/promise-spawn@7.0.2': - resolution: - { - integrity: sha512-xhfYPXoV5Dy4UkY0D+v2KkwvnDfiA/8Mt3sWCGI/hM03NsYIH8ZaG6QzS9x7pje5vHZBZJ2v6VRFVTWACnqcmQ==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-xhfYPXoV5Dy4UkY0D+v2KkwvnDfiA/8Mt3sWCGI/hM03NsYIH8ZaG6QzS9x7pje5vHZBZJ2v6VRFVTWACnqcmQ==} + engines: {node: ^16.14.0 || >=18.0.0} '@npmcli/query@3.1.0': - resolution: - { - integrity: sha512-C/iR0tk7KSKGldibYIB9x8GtO/0Bd0I2mhOaDb8ucQL/bQVTmGoeREaFj64Z5+iCBRf3dQfed0CjJL7I8iTkiQ==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-C/iR0tk7KSKGldibYIB9x8GtO/0Bd0I2mhOaDb8ucQL/bQVTmGoeREaFj64Z5+iCBRf3dQfed0CjJL7I8iTkiQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} '@npmcli/redact@2.0.1': - resolution: - { - integrity: sha512-YgsR5jCQZhVmTJvjduTOIHph0L73pK8xwMVaDY0PatySqVM9AZj93jpoXYSJqfHFxFkN9dmqTw6OiqExsS3LPw==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-YgsR5jCQZhVmTJvjduTOIHph0L73pK8xwMVaDY0PatySqVM9AZj93jpoXYSJqfHFxFkN9dmqTw6OiqExsS3LPw==} + engines: {node: ^16.14.0 || >=18.0.0} '@npmcli/run-script@8.1.0': - resolution: - { - integrity: sha512-y7efHHwghQfk28G2z3tlZ67pLG0XdfYbcVG26r7YIXALRsrVQcTq4/tdenSmdOrEsNahIYA/eh8aEVROWGFUDg==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-y7efHHwghQfk28G2z3tlZ67pLG0XdfYbcVG26r7YIXALRsrVQcTq4/tdenSmdOrEsNahIYA/eh8aEVROWGFUDg==} + engines: {node: ^16.14.0 || >=18.0.0} '@nx/devkit@20.8.3': - resolution: - { - integrity: sha512-5lbfJ6ICFOiGeirldQOU5fQ/W/VQ8L3dfWnmHG4UgpWSLoK/YFdRf4lTB4rS0aDXsBL0gyWABz3sZGLPGNYnPA==, - } + resolution: {integrity: sha512-5lbfJ6ICFOiGeirldQOU5fQ/W/VQ8L3dfWnmHG4UgpWSLoK/YFdRf4lTB4rS0aDXsBL0gyWABz3sZGLPGNYnPA==} peerDependencies: nx: '>= 19 <= 21' '@nx/nx-darwin-arm64@20.8.3': - resolution: - { - integrity: sha512-BeYnPAcnaerg6q+qR0bAb0nebwwrsvm4STSVqqVlaqLmmQpU3Bfpx44CEa5d6T9b0V11ZqVE/bkmRhMqhUcrhw==, - } - engines: { node: '>= 10' } + resolution: {integrity: sha512-BeYnPAcnaerg6q+qR0bAb0nebwwrsvm4STSVqqVlaqLmmQpU3Bfpx44CEa5d6T9b0V11ZqVE/bkmRhMqhUcrhw==} + engines: {node: '>= 10'} cpu: [arm64] os: [darwin] '@nx/nx-darwin-x64@20.8.3': - resolution: - { - integrity: sha512-RIFg1VkQ4jhI+ErqEZuIeGBcJGD8t+u9J5CdQBDIASd8QRhtudBkiYLYCJb+qaQly09G7nVfxuyItlS2uRW3qA==, - } - engines: { node: '>= 10' } + resolution: {integrity: sha512-RIFg1VkQ4jhI+ErqEZuIeGBcJGD8t+u9J5CdQBDIASd8QRhtudBkiYLYCJb+qaQly09G7nVfxuyItlS2uRW3qA==} + engines: {node: '>= 10'} cpu: [x64] os: [darwin] '@nx/nx-freebsd-x64@20.8.3': - resolution: - { - integrity: sha512-boQTgMUdnqpZhHMrV/xgnp/dTg5dfxw8I4d16NBwmW4j+Sez7zi/dydgsJpfZsj8TicOHvPu6KK4W5wzp82NPw==, - } - engines: { node: '>= 10' } + resolution: {integrity: sha512-boQTgMUdnqpZhHMrV/xgnp/dTg5dfxw8I4d16NBwmW4j+Sez7zi/dydgsJpfZsj8TicOHvPu6KK4W5wzp82NPw==} + engines: {node: '>= 10'} cpu: [x64] os: [freebsd] '@nx/nx-linux-arm-gnueabihf@20.8.3': - resolution: - { - integrity: sha512-wpiNyY1igx1rLN3EsTLum2lDtblFijdBZB9/9u/6UDub4z9CaQ4yaC4h9n5v7yFYILwfL44YTsQKzrE+iv0y1Q==, - } - engines: { node: '>= 10' } + resolution: {integrity: sha512-wpiNyY1igx1rLN3EsTLum2lDtblFijdBZB9/9u/6UDub4z9CaQ4yaC4h9n5v7yFYILwfL44YTsQKzrE+iv0y1Q==} + engines: {node: '>= 10'} cpu: [arm] os: [linux] '@nx/nx-linux-arm64-gnu@20.8.3': - resolution: - { - integrity: sha512-nbi/eZtJfWxuDwdUCiP+VJolFubtrz6XxVtB26eMAkODnREOKELHZtMOrlm8JBZCdtWCvTqibq9Az74XsqSfdA==, - } - engines: { node: '>= 10' } + resolution: {integrity: sha512-nbi/eZtJfWxuDwdUCiP+VJolFubtrz6XxVtB26eMAkODnREOKELHZtMOrlm8JBZCdtWCvTqibq9Az74XsqSfdA==} + engines: {node: '>= 10'} cpu: [arm64] os: [linux] - libc: [glibc] '@nx/nx-linux-arm64-musl@20.8.3': - resolution: - { - integrity: sha512-LTTGzI8YVPlF1v0YlVf+exM+1q7rpsiUbjTTHJcfHFRU5t4BsiZD54K19Y1UBg1XFx5cwhEaIomSmJ88RwPPVQ==, - } - engines: { node: '>= 10' } + resolution: {integrity: sha512-LTTGzI8YVPlF1v0YlVf+exM+1q7rpsiUbjTTHJcfHFRU5t4BsiZD54K19Y1UBg1XFx5cwhEaIomSmJ88RwPPVQ==} + engines: {node: '>= 10'} cpu: [arm64] os: [linux] - libc: [musl] '@nx/nx-linux-x64-gnu@20.8.3': - resolution: - { - integrity: sha512-SlA4GtXvQbSzSIWLgiIiLBOjdINPOUR/im+TUbaEMZ8wiGrOY8cnk0PVt95TIQJVBeXBCeb5HnoY0lHJpMOODg==, - } - engines: { node: '>= 10' } + resolution: {integrity: sha512-SlA4GtXvQbSzSIWLgiIiLBOjdINPOUR/im+TUbaEMZ8wiGrOY8cnk0PVt95TIQJVBeXBCeb5HnoY0lHJpMOODg==} + engines: {node: '>= 10'} cpu: [x64] os: [linux] - libc: [glibc] '@nx/nx-linux-x64-musl@20.8.3': - resolution: - { - integrity: sha512-MNzkEwPktp5SQH9dJDH2wP9hgG9LsBDhKJXJfKw6sUI/6qz5+/aAjFziKy+zBnhU4AO1yXt5qEWzR8lDcIriVQ==, - } - engines: { node: '>= 10' } + resolution: {integrity: sha512-MNzkEwPktp5SQH9dJDH2wP9hgG9LsBDhKJXJfKw6sUI/6qz5+/aAjFziKy+zBnhU4AO1yXt5qEWzR8lDcIriVQ==} + engines: {node: '>= 10'} cpu: [x64] os: [linux] - libc: [musl] '@nx/nx-win32-arm64-msvc@20.8.3': - resolution: - { - integrity: sha512-qUV7CyXKwRCM/lkvyS6Xa1MqgAuK5da6w27RAehh7LATBUKn1I4/M7DGn6L7ERCxpZuh1TrDz9pUzEy0R+Ekkg==, - } - engines: { node: '>= 10' } + resolution: {integrity: sha512-qUV7CyXKwRCM/lkvyS6Xa1MqgAuK5da6w27RAehh7LATBUKn1I4/M7DGn6L7ERCxpZuh1TrDz9pUzEy0R+Ekkg==} + engines: {node: '>= 10'} cpu: [arm64] os: [win32] '@nx/nx-win32-x64-msvc@20.8.3': - resolution: - { - integrity: sha512-gX1G8u6W6EPX6PO/wv07+B++UHyCHBXyVWXITA3Kv6HoSajOxIa2Kk1rv1iDQGmX1WWxBaj3bUyYJAFBDITe4w==, - } - engines: { node: '>= 10' } + resolution: {integrity: sha512-gX1G8u6W6EPX6PO/wv07+B++UHyCHBXyVWXITA3Kv6HoSajOxIa2Kk1rv1iDQGmX1WWxBaj3bUyYJAFBDITe4w==} + engines: {node: '>= 10'} cpu: [x64] os: [win32] '@octokit/auth-token@4.0.0': - resolution: - { - integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==, - } - engines: { node: '>= 18' } + resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==} + engines: {node: '>= 18'} '@octokit/core@5.2.2': - resolution: - { - integrity: sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==, - } - engines: { node: '>= 18' } + resolution: {integrity: sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==} + engines: {node: '>= 18'} '@octokit/endpoint@9.0.6': - resolution: - { - integrity: sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==, - } - engines: { node: '>= 18' } + resolution: {integrity: sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==} + engines: {node: '>= 18'} '@octokit/graphql@7.1.1': - resolution: - { - integrity: sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==, - } - engines: { node: '>= 18' } + resolution: {integrity: sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==} + engines: {node: '>= 18'} '@octokit/openapi-types@24.2.0': - resolution: - { - integrity: sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==, - } + resolution: {integrity: sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==} '@octokit/plugin-enterprise-rest@6.0.1': - resolution: - { - integrity: sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw==, - } + resolution: {integrity: sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw==} '@octokit/plugin-paginate-rest@11.4.4-cjs.2': - resolution: - { - integrity: sha512-2dK6z8fhs8lla5PaOTgqfCGBxgAv/le+EhPs27KklPhm1bKObpu6lXzwfUEQ16ajXzqNrKMujsFyo9K2eaoISw==, - } - engines: { node: '>= 18' } + resolution: {integrity: sha512-2dK6z8fhs8lla5PaOTgqfCGBxgAv/le+EhPs27KklPhm1bKObpu6lXzwfUEQ16ajXzqNrKMujsFyo9K2eaoISw==} + engines: {node: '>= 18'} peerDependencies: '@octokit/core': '5' '@octokit/plugin-request-log@4.0.1': - resolution: - { - integrity: sha512-GihNqNpGHorUrO7Qa9JbAl0dbLnqJVrV8OXe2Zm5/Y4wFkZQDfTreBzVmiRfJVfE4mClXdihHnbpyyO9FSX4HA==, - } - engines: { node: '>= 18' } + resolution: {integrity: sha512-GihNqNpGHorUrO7Qa9JbAl0dbLnqJVrV8OXe2Zm5/Y4wFkZQDfTreBzVmiRfJVfE4mClXdihHnbpyyO9FSX4HA==} + engines: {node: '>= 18'} peerDependencies: '@octokit/core': '5' '@octokit/plugin-rest-endpoint-methods@13.3.2-cjs.1': - resolution: - { - integrity: sha512-VUjIjOOvF2oELQmiFpWA1aOPdawpyaCUqcEBc/UOUnj3Xp6DJGrJ1+bjUIIDzdHjnFNO6q57ODMfdEZnoBkCwQ==, - } - engines: { node: '>= 18' } + resolution: {integrity: sha512-VUjIjOOvF2oELQmiFpWA1aOPdawpyaCUqcEBc/UOUnj3Xp6DJGrJ1+bjUIIDzdHjnFNO6q57ODMfdEZnoBkCwQ==} + engines: {node: '>= 18'} peerDependencies: '@octokit/core': ^5 '@octokit/request-error@5.1.1': - resolution: - { - integrity: sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==, - } - engines: { node: '>= 18' } + resolution: {integrity: sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==} + engines: {node: '>= 18'} '@octokit/request@8.4.1': - resolution: - { - integrity: sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==, - } - engines: { node: '>= 18' } + resolution: {integrity: sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==} + engines: {node: '>= 18'} '@octokit/rest@20.1.2': - resolution: - { - integrity: sha512-GmYiltypkHHtihFwPRxlaorG5R9VAHuk/vbszVoRTGXnAsY60wYLkh/E2XiFmdZmqrisw+9FaazS1i5SbdWYgA==, - } - engines: { node: '>= 18' } + resolution: {integrity: sha512-GmYiltypkHHtihFwPRxlaorG5R9VAHuk/vbszVoRTGXnAsY60wYLkh/E2XiFmdZmqrisw+9FaazS1i5SbdWYgA==} + engines: {node: '>= 18'} '@octokit/types@13.10.0': - resolution: - { - integrity: sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==, - } + resolution: {integrity: sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==} '@one-ini/wasm@0.1.1': - resolution: - { - integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==, - } + resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==} '@oxfmt/darwin-arm64@0.26.0': - resolution: - { - integrity: sha512-AAGc+8CffkiWeVgtWf4dPfQwHEE5c/j/8NWH7VGVxxJRCZFdmWcqCXprvL2H6qZFewvDLrFbuSPRCqYCpYGaTQ==, - } + resolution: {integrity: sha512-AAGc+8CffkiWeVgtWf4dPfQwHEE5c/j/8NWH7VGVxxJRCZFdmWcqCXprvL2H6qZFewvDLrFbuSPRCqYCpYGaTQ==} cpu: [arm64] os: [darwin] '@oxfmt/darwin-x64@0.26.0': - resolution: - { - integrity: sha512-xFx5ijCTjw577wJvFlZEMmKDnp3HSCcbYdCsLRmC5i3TZZiDe9DEYh3P46uqhzj8BkEw1Vm1ZCWdl48aEYAzvQ==, - } + resolution: {integrity: sha512-xFx5ijCTjw577wJvFlZEMmKDnp3HSCcbYdCsLRmC5i3TZZiDe9DEYh3P46uqhzj8BkEw1Vm1ZCWdl48aEYAzvQ==} cpu: [x64] os: [darwin] '@oxfmt/linux-arm64-gnu@0.26.0': - resolution: - { - integrity: sha512-GubkQeQT5d3B/Jx/IiR7NMkSmXrCZcVI0BPh1i7mpFi8HgD1hQ/LbhiBKAMsMqs5bbugdQOgBEl8bOhe8JhW1g==, - } + resolution: {integrity: sha512-GubkQeQT5d3B/Jx/IiR7NMkSmXrCZcVI0BPh1i7mpFi8HgD1hQ/LbhiBKAMsMqs5bbugdQOgBEl8bOhe8JhW1g==} cpu: [arm64] os: [linux] - libc: [glibc] '@oxfmt/linux-arm64-musl@0.26.0': - resolution: - { - integrity: sha512-OEypUwK69bFPj+aa3/LYCnlIUPgoOLu//WNcriwpnWNmt47808Ht7RJSg+MNK8a7pSZHpXJ5/E6CRK/OTwFdaQ==, - } + resolution: {integrity: sha512-OEypUwK69bFPj+aa3/LYCnlIUPgoOLu//WNcriwpnWNmt47808Ht7RJSg+MNK8a7pSZHpXJ5/E6CRK/OTwFdaQ==} cpu: [arm64] os: [linux] - libc: [musl] '@oxfmt/linux-x64-gnu@0.26.0': - resolution: - { - integrity: sha512-xO6iEW2bC6ZHyOTPmPWrg/nM6xgzyRPaS84rATy6F8d79wz69LdRdJ3l/PXlkqhi7XoxhvX4ExysA0Nf10ZZEQ==, - } + resolution: {integrity: sha512-xO6iEW2bC6ZHyOTPmPWrg/nM6xgzyRPaS84rATy6F8d79wz69LdRdJ3l/PXlkqhi7XoxhvX4ExysA0Nf10ZZEQ==} cpu: [x64] os: [linux] - libc: [glibc] '@oxfmt/linux-x64-musl@0.26.0': - resolution: - { - integrity: sha512-Z3KuZFC+MIuAyFCXBHY71kCsdRq1ulbsbzTe71v+hrEv7zVBn6yzql+/AZcgfIaKzWO9OXNuz5WWLWDmVALwow==, - } + resolution: {integrity: sha512-Z3KuZFC+MIuAyFCXBHY71kCsdRq1ulbsbzTe71v+hrEv7zVBn6yzql+/AZcgfIaKzWO9OXNuz5WWLWDmVALwow==} cpu: [x64] os: [linux] - libc: [musl] '@oxfmt/win32-arm64@0.26.0': - resolution: - { - integrity: sha512-3zRbqwVWK1mDhRhTknlQFpRFL9GhEB5GfU6U7wawnuEwpvi39q91kJ+SRJvJnhyPCARkjZBd1V8XnweN5IFd1g==, - } + resolution: {integrity: sha512-3zRbqwVWK1mDhRhTknlQFpRFL9GhEB5GfU6U7wawnuEwpvi39q91kJ+SRJvJnhyPCARkjZBd1V8XnweN5IFd1g==} cpu: [arm64] os: [win32] '@oxfmt/win32-x64@0.26.0': - resolution: - { - integrity: sha512-m8TfIljU22i9UEIkD+slGPifTFeaCwIUfxszN3E6ABWP1KQbtwSw9Ak0TdoikibvukF/dtbeyG3WW63jv9DnEg==, - } + resolution: {integrity: sha512-m8TfIljU22i9UEIkD+slGPifTFeaCwIUfxszN3E6ABWP1KQbtwSw9Ak0TdoikibvukF/dtbeyG3WW63jv9DnEg==} cpu: [x64] os: [win32] '@paralleldrive/cuid2@2.3.1': - resolution: - { - integrity: sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==, - } + resolution: {integrity: sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==} '@pgpm/database-jobs@0.16.0': - resolution: - { - integrity: sha512-s8I7958PlhfYXZKhYoU76R03yk6dlevjGk/Uy9uktveJkZ8C3JVsIhP6Lv4lo0SFEZCjFmXRCYpOY5xINIcX4w==, - } + resolution: {integrity: sha512-s8I7958PlhfYXZKhYoU76R03yk6dlevjGk/Uy9uktveJkZ8C3JVsIhP6Lv4lo0SFEZCjFmXRCYpOY5xINIcX4w==} '@pgpm/inflection@0.16.0': - resolution: - { - integrity: sha512-otjWGx+KkB113Wc5I9nsvoqPhBK6zD1ON2OcXw9PQRgqU43Y9f0yZjb559dDzZwDn5XUeiZMf6il5SIvJE5NPg==, - } + resolution: {integrity: sha512-otjWGx+KkB113Wc5I9nsvoqPhBK6zD1ON2OcXw9PQRgqU43Y9f0yZjb559dDzZwDn5XUeiZMf6il5SIvJE5NPg==} '@pgpm/metaschema-modules@0.16.4': - resolution: - { - integrity: sha512-sB3+5yljFEqUXTTHUOHBBxK52CwagHiUBumWjikHVN9C5w6NHUQ+xFde+3RJMCkoqnmcZn6HTGvWCF25QgciiA==, - } + resolution: {integrity: sha512-sB3+5yljFEqUXTTHUOHBBxK52CwagHiUBumWjikHVN9C5w6NHUQ+xFde+3RJMCkoqnmcZn6HTGvWCF25QgciiA==} '@pgpm/metaschema-schema@0.16.3': - resolution: - { - integrity: sha512-sDIWJY+uNaqMMGjL8NWo8ezzXH1OT0qdaqsX+YDrBL6v1u0PphWprdjd7HySzdqIGpPSax8sIy5u4P2M96wR9Q==, - } + resolution: {integrity: sha512-sDIWJY+uNaqMMGjL8NWo8ezzXH1OT0qdaqsX+YDrBL6v1u0PphWprdjd7HySzdqIGpPSax8sIy5u4P2M96wR9Q==} '@pgpm/services@0.16.3': - resolution: - { - integrity: sha512-TfYALB8RKPyR2WZIFH2Pirb5qfx1q2EKbr7gzG/CcZcQMgTGYyDHBtvSqIO4nDfJ6GgYcASoip9T0lzQmwGtlA==, - } + resolution: {integrity: sha512-TfYALB8RKPyR2WZIFH2Pirb5qfx1q2EKbr7gzG/CcZcQMgTGYyDHBtvSqIO4nDfJ6GgYcASoip9T0lzQmwGtlA==} '@pgpm/types@0.16.0': - resolution: - { - integrity: sha512-CioHCxZGQUnpLANw4aMOOq7Z6zi2SXCxJIRZ8CSBPJfJkWU1OgxX+EpSjnm4Td4bznJhOViXniLltibaaGkMPA==, - } + resolution: {integrity: sha512-CioHCxZGQUnpLANw4aMOOq7Z6zi2SXCxJIRZ8CSBPJfJkWU1OgxX+EpSjnm4Td4bznJhOViXniLltibaaGkMPA==} '@pgpm/verify@0.16.0': - resolution: - { - integrity: sha512-uG0zTXAWGLV8wTUiLdBn+2b4AO+gtiw7sZf+TFFU8h/mVGMBTHUb9Gbsl/GL/5/0zZKOxak7cRJ5deec79KB/A==, - } + resolution: {integrity: sha512-uG0zTXAWGLV8wTUiLdBn+2b4AO+gtiw7sZf+TFFU8h/mVGMBTHUb9Gbsl/GL/5/0zZKOxak7cRJ5deec79KB/A==} '@pgsql/types@17.6.2': - resolution: - { - integrity: sha512-1UtbELdbqNdyOShhrVfSz3a1gDi0s9XXiQemx+6QqtsrXe62a6zOGU+vjb2GRfG5jeEokI1zBBcfD42enRv0Rw==, - } + resolution: {integrity: sha512-1UtbELdbqNdyOShhrVfSz3a1gDi0s9XXiQemx+6QqtsrXe62a6zOGU+vjb2GRfG5jeEokI1zBBcfD42enRv0Rw==} '@pgsql/utils@17.8.11': - resolution: - { - integrity: sha512-gcaS9ATilQyGSIq8596tq+6rcb7TX54sdjOvOzGa9lu9NjqkptEKLbBae5UTjfkFGfH50duDFD1EpFogMnZToA==, - } + resolution: {integrity: sha512-gcaS9ATilQyGSIq8596tq+6rcb7TX54sdjOvOzGa9lu9NjqkptEKLbBae5UTjfkFGfH50duDFD1EpFogMnZToA==} '@pkgjs/parseargs@0.11.0': - resolution: - { - integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==, - } - engines: { node: '>=14' } + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} '@pkgr/core@0.2.9': - resolution: - { - integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==, - } - engines: { node: ^12.20.0 || ^14.18.0 || >=16.0.0 } + resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} '@playwright/test@1.57.0': - resolution: - { - integrity: sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==} + engines: {node: '>=18'} hasBin: true '@protobufjs/aspromise@1.1.2': - resolution: - { - integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==, - } + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} '@protobufjs/base64@1.1.2': - resolution: - { - integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==, - } + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} '@protobufjs/codegen@2.0.4': - resolution: - { - integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==, - } + resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} '@protobufjs/eventemitter@1.1.0': - resolution: - { - integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==, - } + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} '@protobufjs/fetch@1.1.0': - resolution: - { - integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==, - } + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} '@protobufjs/float@1.0.2': - resolution: - { - integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==, - } + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} '@protobufjs/inquire@1.1.0': - resolution: - { - integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==, - } + resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} '@protobufjs/path@1.1.2': - resolution: - { - integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==, - } + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} '@protobufjs/pool@1.1.0': - resolution: - { - integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==, - } + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} '@protobufjs/utf8@1.1.0': - resolution: - { - integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==, - } + resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} '@radix-ui/primitive@1.1.3': - resolution: - { - integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==, - } + resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==} '@radix-ui/react-arrow@1.1.7': - resolution: - { - integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==, - } + resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -4788,10 +3789,7 @@ packages: optional: true '@radix-ui/react-collection@1.1.7': - resolution: - { - integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==, - } + resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -4804,10 +3802,7 @@ packages: optional: true '@radix-ui/react-compose-refs@1.1.2': - resolution: - { - integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==, - } + resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -4816,10 +3811,7 @@ packages: optional: true '@radix-ui/react-context@1.1.2': - resolution: - { - integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==, - } + resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -4828,10 +3820,7 @@ packages: optional: true '@radix-ui/react-dialog@1.1.15': - resolution: - { - integrity: sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==, - } + resolution: {integrity: sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -4844,10 +3833,7 @@ packages: optional: true '@radix-ui/react-direction@1.1.1': - resolution: - { - integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==, - } + resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -4856,10 +3842,7 @@ packages: optional: true '@radix-ui/react-dismissable-layer@1.1.11': - resolution: - { - integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==, - } + resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -4872,10 +3855,7 @@ packages: optional: true '@radix-ui/react-dropdown-menu@2.1.16': - resolution: - { - integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==, - } + resolution: {integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -4888,10 +3868,7 @@ packages: optional: true '@radix-ui/react-focus-guards@1.1.3': - resolution: - { - integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==, - } + resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -4900,10 +3877,7 @@ packages: optional: true '@radix-ui/react-focus-scope@1.1.7': - resolution: - { - integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==, - } + resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -4916,10 +3890,7 @@ packages: optional: true '@radix-ui/react-id@1.1.1': - resolution: - { - integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==, - } + resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -4928,10 +3899,7 @@ packages: optional: true '@radix-ui/react-menu@2.1.16': - resolution: - { - integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==, - } + resolution: {integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -4944,10 +3912,7 @@ packages: optional: true '@radix-ui/react-popper@1.2.8': - resolution: - { - integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==, - } + resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -4960,10 +3925,7 @@ packages: optional: true '@radix-ui/react-portal@1.1.9': - resolution: - { - integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==, - } + resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -4976,10 +3938,7 @@ packages: optional: true '@radix-ui/react-presence@1.1.5': - resolution: - { - integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==, - } + resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -4992,10 +3951,7 @@ packages: optional: true '@radix-ui/react-primitive@2.1.3': - resolution: - { - integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==, - } + resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -5008,10 +3964,7 @@ packages: optional: true '@radix-ui/react-primitive@2.1.4': - resolution: - { - integrity: sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==, - } + resolution: {integrity: sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -5024,10 +3977,7 @@ packages: optional: true '@radix-ui/react-roving-focus@1.1.11': - resolution: - { - integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==, - } + resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -5040,10 +3990,7 @@ packages: optional: true '@radix-ui/react-slot@1.2.3': - resolution: - { - integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==, - } + resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -5052,10 +3999,7 @@ packages: optional: true '@radix-ui/react-slot@1.2.4': - resolution: - { - integrity: sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==, - } + resolution: {integrity: sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -5064,10 +4008,7 @@ packages: optional: true '@radix-ui/react-tooltip@1.2.8': - resolution: - { - integrity: sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==, - } + resolution: {integrity: sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -5080,10 +4021,7 @@ packages: optional: true '@radix-ui/react-use-callback-ref@1.1.1': - resolution: - { - integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==, - } + resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -5092,10 +4030,7 @@ packages: optional: true '@radix-ui/react-use-controllable-state@1.2.2': - resolution: - { - integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==, - } + resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -5104,10 +4039,7 @@ packages: optional: true '@radix-ui/react-use-effect-event@0.0.2': - resolution: - { - integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==, - } + resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -5116,10 +4048,7 @@ packages: optional: true '@radix-ui/react-use-escape-keydown@1.1.1': - resolution: - { - integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==, - } + resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -5128,10 +4057,7 @@ packages: optional: true '@radix-ui/react-use-layout-effect@1.1.1': - resolution: - { - integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==, - } + resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -5140,10 +4066,7 @@ packages: optional: true '@radix-ui/react-use-rect@1.1.1': - resolution: - { - integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==, - } + resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -5152,10 +4075,7 @@ packages: optional: true '@radix-ui/react-use-size@1.1.1': - resolution: - { - integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==, - } + resolution: {integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -5164,10 +4084,7 @@ packages: optional: true '@radix-ui/react-visually-hidden@1.2.3': - resolution: - { - integrity: sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==, - } + resolution: {integrity: sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -5180,10 +4097,7 @@ packages: optional: true '@radix-ui/react-visually-hidden@1.2.4': - resolution: - { - integrity: sha512-kaeiyGCe844dkb9AVF+rb4yTyb1LiLN/e3es3nLiRyN4dC8AduBYPMnnNlDjX2VDOcvDEiPnRNMJeWCfsX0txg==, - } + resolution: {integrity: sha512-kaeiyGCe844dkb9AVF+rb4yTyb1LiLN/e3es3nLiRyN4dC8AduBYPMnnNlDjX2VDOcvDEiPnRNMJeWCfsX0txg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -5196,2985 +4110,1659 @@ packages: optional: true '@radix-ui/rect@1.1.1': - resolution: - { - integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==, - } + resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} '@react-aria/focus@3.21.4': - resolution: - { - integrity: sha512-6gz+j9ip0/vFRTKJMl3R30MHopn4i19HqqLfSQfElxJD+r9hBnYG1Q6Wd/kl/WRR1+CALn2F+rn06jUnf5sT8Q==, - } + resolution: {integrity: sha512-6gz+j9ip0/vFRTKJMl3R30MHopn4i19HqqLfSQfElxJD+r9hBnYG1Q6Wd/kl/WRR1+CALn2F+rn06jUnf5sT8Q==} peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 '@react-aria/interactions@3.27.0': - resolution: - { - integrity: sha512-D27pOy+0jIfHK60BB26AgqjjRFOYdvVSkwC31b2LicIzRCSPOSP06V4gMHuGmkhNTF4+YWDi1HHYjxIvMeiSlA==, - } + resolution: {integrity: sha512-D27pOy+0jIfHK60BB26AgqjjRFOYdvVSkwC31b2LicIzRCSPOSP06V4gMHuGmkhNTF4+YWDi1HHYjxIvMeiSlA==} peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 '@react-aria/ssr@3.9.10': - resolution: - { - integrity: sha512-hvTm77Pf+pMBhuBm760Li0BVIO38jv1IBws1xFm1NoL26PU+fe+FMW5+VZWyANR6nYL65joaJKZqOdTQMkO9IQ==, - } - engines: { node: '>= 12' } + resolution: {integrity: sha512-hvTm77Pf+pMBhuBm760Li0BVIO38jv1IBws1xFm1NoL26PU+fe+FMW5+VZWyANR6nYL65joaJKZqOdTQMkO9IQ==} + engines: {node: '>= 12'} peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 '@react-aria/utils@3.33.0': - resolution: - { - integrity: sha512-yvz7CMH8d2VjwbSa5nGXqjU031tYhD8ddax95VzJsHSPyqHDEGfxul8RkhGV6oO7bVqZxVs6xY66NIgae+FHjw==, - } + resolution: {integrity: sha512-yvz7CMH8d2VjwbSa5nGXqjU031tYhD8ddax95VzJsHSPyqHDEGfxul8RkhGV6oO7bVqZxVs6xY66NIgae+FHjw==} peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 '@react-stately/flags@3.1.2': - resolution: - { - integrity: sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg==, - } + resolution: {integrity: sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg==} '@react-stately/utils@3.11.0': - resolution: - { - integrity: sha512-8LZpYowJ9eZmmYLpudbo/eclIRnbhWIJZ994ncmlKlouNzKohtM8qTC6B1w1pwUbiwGdUoyzLuQbeaIor5Dvcw==, - } + resolution: {integrity: sha512-8LZpYowJ9eZmmYLpudbo/eclIRnbhWIJZ994ncmlKlouNzKohtM8qTC6B1w1pwUbiwGdUoyzLuQbeaIor5Dvcw==} peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 '@react-types/shared@3.33.0': - resolution: - { - integrity: sha512-xuUpP6MyuPmJtzNOqF5pzFUIHH2YogyOQfUQHag54PRmWB7AbjuGWBUv0l1UDmz6+AbzAYGmDVAzcRDOu2PFpw==, - } + resolution: {integrity: sha512-xuUpP6MyuPmJtzNOqF5pzFUIHH2YogyOQfUQHag54PRmWB7AbjuGWBUv0l1UDmz6+AbzAYGmDVAzcRDOu2PFpw==} peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 '@rolldown/pluginutils@1.0.0-beta.27': - resolution: - { - integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==, - } + resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} '@rollup/rollup-android-arm-eabi@4.57.1': - resolution: - { - integrity: sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==, - } + resolution: {integrity: sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==} cpu: [arm] os: [android] '@rollup/rollup-android-arm64@4.57.1': - resolution: - { - integrity: sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==, - } + resolution: {integrity: sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==} cpu: [arm64] os: [android] '@rollup/rollup-darwin-arm64@4.57.1': - resolution: - { - integrity: sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==, - } + resolution: {integrity: sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==} cpu: [arm64] os: [darwin] '@rollup/rollup-darwin-x64@4.57.1': - resolution: - { - integrity: sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==, - } + resolution: {integrity: sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==} cpu: [x64] os: [darwin] '@rollup/rollup-freebsd-arm64@4.57.1': - resolution: - { - integrity: sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==, - } + resolution: {integrity: sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==} cpu: [arm64] os: [freebsd] '@rollup/rollup-freebsd-x64@4.57.1': - resolution: - { - integrity: sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==, - } + resolution: {integrity: sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==} cpu: [x64] os: [freebsd] '@rollup/rollup-linux-arm-gnueabihf@4.57.1': - resolution: - { - integrity: sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==, - } + resolution: {integrity: sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==} cpu: [arm] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.57.1': - resolution: - { - integrity: sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==, - } + resolution: {integrity: sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==} cpu: [arm] os: [linux] - libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.57.1': - resolution: - { - integrity: sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==, - } + resolution: {integrity: sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==} cpu: [arm64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.57.1': - resolution: - { - integrity: sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==, - } + resolution: {integrity: sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==} cpu: [arm64] os: [linux] - libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.57.1': - resolution: - { - integrity: sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==, - } + resolution: {integrity: sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==} cpu: [loong64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-loong64-musl@4.57.1': - resolution: - { - integrity: sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==, - } + resolution: {integrity: sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==} cpu: [loong64] os: [linux] - libc: [musl] '@rollup/rollup-linux-ppc64-gnu@4.57.1': - resolution: - { - integrity: sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==, - } + resolution: {integrity: sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==} cpu: [ppc64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-ppc64-musl@4.57.1': - resolution: - { - integrity: sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==, - } + resolution: {integrity: sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==} cpu: [ppc64] os: [linux] - libc: [musl] '@rollup/rollup-linux-riscv64-gnu@4.57.1': - resolution: - { - integrity: sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==, - } + resolution: {integrity: sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==} cpu: [riscv64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.57.1': - resolution: - { - integrity: sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==, - } + resolution: {integrity: sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==} cpu: [riscv64] os: [linux] - libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.57.1': - resolution: - { - integrity: sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==, - } + resolution: {integrity: sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==} cpu: [s390x] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.57.1': - resolution: - { - integrity: sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==, - } + resolution: {integrity: sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==} cpu: [x64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-musl@4.57.1': - resolution: - { - integrity: sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==, - } + resolution: {integrity: sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==} cpu: [x64] os: [linux] - libc: [musl] '@rollup/rollup-openbsd-x64@4.57.1': - resolution: - { - integrity: sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==, - } + resolution: {integrity: sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==} cpu: [x64] os: [openbsd] '@rollup/rollup-openharmony-arm64@4.57.1': - resolution: - { - integrity: sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==, - } + resolution: {integrity: sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==} cpu: [arm64] os: [openharmony] '@rollup/rollup-win32-arm64-msvc@4.57.1': - resolution: - { - integrity: sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==, - } + resolution: {integrity: sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==} cpu: [arm64] os: [win32] '@rollup/rollup-win32-ia32-msvc@4.57.1': - resolution: - { - integrity: sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==, - } + resolution: {integrity: sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==} cpu: [ia32] os: [win32] '@rollup/rollup-win32-x64-gnu@4.57.1': - resolution: - { - integrity: sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==, - } + resolution: {integrity: sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==} cpu: [x64] os: [win32] '@rollup/rollup-win32-x64-msvc@4.57.1': - resolution: - { - integrity: sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==, - } + resolution: {integrity: sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==} cpu: [x64] os: [win32] '@sigstore/bundle@2.3.2': - resolution: - { - integrity: sha512-wueKWDk70QixNLB363yHc2D2ItTgYiMTdPwK8D9dKQMR3ZQ0c35IxP5xnwQ8cNLoCgCRcHf14kE+CLIvNX1zmA==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-wueKWDk70QixNLB363yHc2D2ItTgYiMTdPwK8D9dKQMR3ZQ0c35IxP5xnwQ8cNLoCgCRcHf14kE+CLIvNX1zmA==} + engines: {node: ^16.14.0 || >=18.0.0} '@sigstore/core@1.1.0': - resolution: - { - integrity: sha512-JzBqdVIyqm2FRQCulY6nbQzMpJJpSiJ8XXWMhtOX9eKgaXXpfNOF53lzQEjIydlStnd/eFtuC1dW4VYdD93oRg==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-JzBqdVIyqm2FRQCulY6nbQzMpJJpSiJ8XXWMhtOX9eKgaXXpfNOF53lzQEjIydlStnd/eFtuC1dW4VYdD93oRg==} + engines: {node: ^16.14.0 || >=18.0.0} '@sigstore/protobuf-specs@0.3.3': - resolution: - { - integrity: sha512-RpacQhBlwpBWd7KEJsRKcBQalbV28fvkxwTOJIqhIuDysMMaJW47V4OqW30iJB9uRpqOSxxEAQFdr8tTattReQ==, - } - engines: { node: ^18.17.0 || >=20.5.0 } + resolution: {integrity: sha512-RpacQhBlwpBWd7KEJsRKcBQalbV28fvkxwTOJIqhIuDysMMaJW47V4OqW30iJB9uRpqOSxxEAQFdr8tTattReQ==} + engines: {node: ^18.17.0 || >=20.5.0} '@sigstore/sign@2.3.2': - resolution: - { - integrity: sha512-5Vz5dPVuunIIvC5vBb0APwo7qKA4G9yM48kPWJT+OEERs40md5GoUR1yedwpekWZ4m0Hhw44m6zU+ObsON+iDA==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-5Vz5dPVuunIIvC5vBb0APwo7qKA4G9yM48kPWJT+OEERs40md5GoUR1yedwpekWZ4m0Hhw44m6zU+ObsON+iDA==} + engines: {node: ^16.14.0 || >=18.0.0} '@sigstore/tuf@2.3.4': - resolution: - { - integrity: sha512-44vtsveTPUpqhm9NCrbU8CWLe3Vck2HO1PNLw7RIajbB7xhtn5RBPm1VNSCMwqGYHhDsBJG8gDF0q4lgydsJvw==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-44vtsveTPUpqhm9NCrbU8CWLe3Vck2HO1PNLw7RIajbB7xhtn5RBPm1VNSCMwqGYHhDsBJG8gDF0q4lgydsJvw==} + engines: {node: ^16.14.0 || >=18.0.0} '@sigstore/verify@1.2.1': - resolution: - { - integrity: sha512-8iKx79/F73DKbGfRf7+t4dqrc0bRr0thdPrxAtCKWRm/F0tG71i6O1rvlnScncJLLBZHn3h8M3c1BSUAb9yu8g==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-8iKx79/F73DKbGfRf7+t4dqrc0bRr0thdPrxAtCKWRm/F0tG71i6O1rvlnScncJLLBZHn3h8M3c1BSUAb9yu8g==} + engines: {node: ^16.14.0 || >=18.0.0} '@sinclair/typebox@0.27.8': - resolution: - { - integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==, - } + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} '@sinclair/typebox@0.34.47': - resolution: - { - integrity: sha512-ZGIBQ+XDvO5JQku9wmwtabcVTHJsgSWAHYtVuM9pBNNR5E88v6Jcj/llpmsjivig5X8A8HHOb4/mbEKPS5EvAw==, - } + resolution: {integrity: sha512-ZGIBQ+XDvO5JQku9wmwtabcVTHJsgSWAHYtVuM9pBNNR5E88v6Jcj/llpmsjivig5X8A8HHOb4/mbEKPS5EvAw==} '@sinonjs/commons@3.0.1': - resolution: - { - integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==, - } + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} '@sinonjs/fake-timers@13.0.5': - resolution: - { - integrity: sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==, - } + resolution: {integrity: sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==} '@smithy/abort-controller@4.2.7': - resolution: - { - integrity: sha512-rzMY6CaKx2qxrbYbqjXWS0plqEy7LOdKHS0bg4ixJ6aoGDPNUcLWk/FRNuCILh7GKLG9TFUXYYeQQldMBBwuyw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-rzMY6CaKx2qxrbYbqjXWS0plqEy7LOdKHS0bg4ixJ6aoGDPNUcLWk/FRNuCILh7GKLG9TFUXYYeQQldMBBwuyw==} + engines: {node: '>=18.0.0'} '@smithy/abort-controller@4.2.8': - resolution: - { - integrity: sha512-peuVfkYHAmS5ybKxWcfraK7WBBP0J+rkfUcbHJJKQ4ir3UAUNQI+Y4Vt/PqSzGqgloJ5O1dk7+WzNL8wcCSXbw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-peuVfkYHAmS5ybKxWcfraK7WBBP0J+rkfUcbHJJKQ4ir3UAUNQI+Y4Vt/PqSzGqgloJ5O1dk7+WzNL8wcCSXbw==} + engines: {node: '>=18.0.0'} '@smithy/chunked-blob-reader-native@4.2.1': - resolution: - { - integrity: sha512-lX9Ay+6LisTfpLid2zZtIhSEjHMZoAR5hHCR4H7tBz/Zkfr5ea8RcQ7Tk4mi0P76p4cN+Btz16Ffno7YHpKXnQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-lX9Ay+6LisTfpLid2zZtIhSEjHMZoAR5hHCR4H7tBz/Zkfr5ea8RcQ7Tk4mi0P76p4cN+Btz16Ffno7YHpKXnQ==} + engines: {node: '>=18.0.0'} '@smithy/chunked-blob-reader@5.2.0': - resolution: - { - integrity: sha512-WmU0TnhEAJLWvfSeMxBNe5xtbselEO8+4wG0NtZeL8oR21WgH1xiO37El+/Y+H/Ie4SCwBy3MxYWmOYaGgZueA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-WmU0TnhEAJLWvfSeMxBNe5xtbselEO8+4wG0NtZeL8oR21WgH1xiO37El+/Y+H/Ie4SCwBy3MxYWmOYaGgZueA==} + engines: {node: '>=18.0.0'} '@smithy/config-resolver@4.4.6': - resolution: - { - integrity: sha512-qJpzYC64kaj3S0fueiu3kXm8xPrR3PcXDPEgnaNMRn0EjNSZFoFjvbUp0YUDsRhN1CB90EnHJtbxWKevnH99UQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-qJpzYC64kaj3S0fueiu3kXm8xPrR3PcXDPEgnaNMRn0EjNSZFoFjvbUp0YUDsRhN1CB90EnHJtbxWKevnH99UQ==} + engines: {node: '>=18.0.0'} '@smithy/core@3.20.0': - resolution: - { - integrity: sha512-WsSHCPq/neD5G/MkK4csLI5Y5Pkd9c1NMfpYEKeghSGaD4Ja1qLIohRQf2D5c1Uy5aXp76DeKHkzWZ9KAlHroQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-WsSHCPq/neD5G/MkK4csLI5Y5Pkd9c1NMfpYEKeghSGaD4Ja1qLIohRQf2D5c1Uy5aXp76DeKHkzWZ9KAlHroQ==} + engines: {node: '>=18.0.0'} '@smithy/core@3.20.5': - resolution: - { - integrity: sha512-0Tz77Td8ynHaowXfOdrD0F1IH4tgWGUhwmLwmpFyTbr+U9WHXNNp9u/k2VjBXGnSe7BwjBERRpXsokGTXzNjhA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-0Tz77Td8ynHaowXfOdrD0F1IH4tgWGUhwmLwmpFyTbr+U9WHXNNp9u/k2VjBXGnSe7BwjBERRpXsokGTXzNjhA==} + engines: {node: '>=18.0.0'} '@smithy/core@3.20.7': - resolution: - { - integrity: sha512-aO7jmh3CtrmPsIJxUwYIzI5WVlMK8BMCPQ4D4nTzqTqBhbzvxHNzBMGcEg13yg/z9R2Qsz49NUFl0F0lVbTVFw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-aO7jmh3CtrmPsIJxUwYIzI5WVlMK8BMCPQ4D4nTzqTqBhbzvxHNzBMGcEg13yg/z9R2Qsz49NUFl0F0lVbTVFw==} + engines: {node: '>=18.0.0'} '@smithy/credential-provider-imds@4.2.8': - resolution: - { - integrity: sha512-FNT0xHS1c/CPN8upqbMFP83+ul5YgdisfCfkZ86Jh2NSmnqw/AJ6x5pEogVCTVvSm7j9MopRU89bmDelxuDMYw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-FNT0xHS1c/CPN8upqbMFP83+ul5YgdisfCfkZ86Jh2NSmnqw/AJ6x5pEogVCTVvSm7j9MopRU89bmDelxuDMYw==} + engines: {node: '>=18.0.0'} '@smithy/eventstream-codec@4.2.8': - resolution: - { - integrity: sha512-jS/O5Q14UsufqoGhov7dHLOPCzkYJl9QDzusI2Psh4wyYx/izhzvX9P4D69aTxcdfVhEPhjK+wYyn/PzLjKbbw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-jS/O5Q14UsufqoGhov7dHLOPCzkYJl9QDzusI2Psh4wyYx/izhzvX9P4D69aTxcdfVhEPhjK+wYyn/PzLjKbbw==} + engines: {node: '>=18.0.0'} '@smithy/eventstream-serde-browser@4.2.8': - resolution: - { - integrity: sha512-MTfQT/CRQz5g24ayXdjg53V0mhucZth4PESoA5IhvaWVDTOQLfo8qI9vzqHcPsdd2v6sqfTYqF5L/l+pea5Uyw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-MTfQT/CRQz5g24ayXdjg53V0mhucZth4PESoA5IhvaWVDTOQLfo8qI9vzqHcPsdd2v6sqfTYqF5L/l+pea5Uyw==} + engines: {node: '>=18.0.0'} '@smithy/eventstream-serde-config-resolver@4.3.8': - resolution: - { - integrity: sha512-ah12+luBiDGzBruhu3efNy1IlbwSEdNiw8fOZksoKoWW1ZHvO/04MQsdnws/9Aj+5b0YXSSN2JXKy/ClIsW8MQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-ah12+luBiDGzBruhu3efNy1IlbwSEdNiw8fOZksoKoWW1ZHvO/04MQsdnws/9Aj+5b0YXSSN2JXKy/ClIsW8MQ==} + engines: {node: '>=18.0.0'} '@smithy/eventstream-serde-node@4.2.8': - resolution: - { - integrity: sha512-cYpCpp29z6EJHa5T9WL0KAlq3SOKUQkcgSoeRfRVwjGgSFl7Uh32eYGt7IDYCX20skiEdRffyDpvF2efEZPC0A==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-cYpCpp29z6EJHa5T9WL0KAlq3SOKUQkcgSoeRfRVwjGgSFl7Uh32eYGt7IDYCX20skiEdRffyDpvF2efEZPC0A==} + engines: {node: '>=18.0.0'} '@smithy/eventstream-serde-universal@4.2.8': - resolution: - { - integrity: sha512-iJ6YNJd0bntJYnX6s52NC4WFYcZeKrPUr1Kmmr5AwZcwCSzVpS7oavAmxMR7pMq7V+D1G4s9F5NJK0xwOsKAlQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-iJ6YNJd0bntJYnX6s52NC4WFYcZeKrPUr1Kmmr5AwZcwCSzVpS7oavAmxMR7pMq7V+D1G4s9F5NJK0xwOsKAlQ==} + engines: {node: '>=18.0.0'} '@smithy/fetch-http-handler@5.3.8': - resolution: - { - integrity: sha512-h/Fi+o7mti4n8wx1SR6UHWLaakwHRx29sizvp8OOm7iqwKGFneT06GCSFhml6Bha5BT6ot5pj3CYZnCHhGC2Rg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-h/Fi+o7mti4n8wx1SR6UHWLaakwHRx29sizvp8OOm7iqwKGFneT06GCSFhml6Bha5BT6ot5pj3CYZnCHhGC2Rg==} + engines: {node: '>=18.0.0'} '@smithy/fetch-http-handler@5.3.9': - resolution: - { - integrity: sha512-I4UhmcTYXBrct03rwzQX1Y/iqQlzVQaPxWjCjula++5EmWq9YGBrx6bbGqluGc1f0XEfhSkiY4jhLgbsJUMKRA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-I4UhmcTYXBrct03rwzQX1Y/iqQlzVQaPxWjCjula++5EmWq9YGBrx6bbGqluGc1f0XEfhSkiY4jhLgbsJUMKRA==} + engines: {node: '>=18.0.0'} '@smithy/hash-blob-browser@4.2.9': - resolution: - { - integrity: sha512-m80d/iicI7DlBDxyQP6Th7BW/ejDGiF0bgI754+tiwK0lgMkcaIBgvwwVc7OFbY4eUzpGtnig52MhPAEJ7iNYg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-m80d/iicI7DlBDxyQP6Th7BW/ejDGiF0bgI754+tiwK0lgMkcaIBgvwwVc7OFbY4eUzpGtnig52MhPAEJ7iNYg==} + engines: {node: '>=18.0.0'} '@smithy/hash-node@4.2.8': - resolution: - { - integrity: sha512-7ZIlPbmaDGxVoxErDZnuFG18WekhbA/g2/i97wGj+wUBeS6pcUeAym8u4BXh/75RXWhgIJhyC11hBzig6MljwA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-7ZIlPbmaDGxVoxErDZnuFG18WekhbA/g2/i97wGj+wUBeS6pcUeAym8u4BXh/75RXWhgIJhyC11hBzig6MljwA==} + engines: {node: '>=18.0.0'} '@smithy/hash-stream-node@4.2.8': - resolution: - { - integrity: sha512-v0FLTXgHrTeheYZFGhR+ehX5qUm4IQsjAiL9qehad2cyjMWcN2QG6/4mSwbSgEQzI7jwfoXj7z4fxZUx/Mhj2w==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-v0FLTXgHrTeheYZFGhR+ehX5qUm4IQsjAiL9qehad2cyjMWcN2QG6/4mSwbSgEQzI7jwfoXj7z4fxZUx/Mhj2w==} + engines: {node: '>=18.0.0'} '@smithy/invalid-dependency@4.2.8': - resolution: - { - integrity: sha512-N9iozRybwAQ2dn9Fot9kI6/w9vos2oTXLhtK7ovGqwZjlOcxu6XhPlpLpC+INsxktqHinn5gS2DXDjDF2kG5sQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-N9iozRybwAQ2dn9Fot9kI6/w9vos2oTXLhtK7ovGqwZjlOcxu6XhPlpLpC+INsxktqHinn5gS2DXDjDF2kG5sQ==} + engines: {node: '>=18.0.0'} '@smithy/is-array-buffer@2.2.0': - resolution: - { - integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==, - } - engines: { node: '>=14.0.0' } + resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} + engines: {node: '>=14.0.0'} '@smithy/is-array-buffer@4.2.0': - resolution: - { - integrity: sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==} + engines: {node: '>=18.0.0'} '@smithy/md5-js@4.2.8': - resolution: - { - integrity: sha512-oGMaLj4tVZzLi3itBa9TCswgMBr7k9b+qKYowQ6x1rTyTuO1IU2YHdHUa+891OsOH+wCsH7aTPRsTJO3RMQmjQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-oGMaLj4tVZzLi3itBa9TCswgMBr7k9b+qKYowQ6x1rTyTuO1IU2YHdHUa+891OsOH+wCsH7aTPRsTJO3RMQmjQ==} + engines: {node: '>=18.0.0'} '@smithy/middleware-content-length@4.2.8': - resolution: - { - integrity: sha512-RO0jeoaYAB1qBRhfVyq0pMgBoUK34YEJxVxyjOWYZiOKOq2yMZ4MnVXMZCUDenpozHue207+9P5ilTV1zeda0A==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-RO0jeoaYAB1qBRhfVyq0pMgBoUK34YEJxVxyjOWYZiOKOq2yMZ4MnVXMZCUDenpozHue207+9P5ilTV1zeda0A==} + engines: {node: '>=18.0.0'} '@smithy/middleware-endpoint@4.4.1': - resolution: - { - integrity: sha512-gpLspUAoe6f1M6H0u4cVuFzxZBrsGZmjx2O9SigurTx4PbntYa4AJ+o0G0oGm1L2oSX6oBhcGHwrfJHup2JnJg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-gpLspUAoe6f1M6H0u4cVuFzxZBrsGZmjx2O9SigurTx4PbntYa4AJ+o0G0oGm1L2oSX6oBhcGHwrfJHup2JnJg==} + engines: {node: '>=18.0.0'} '@smithy/middleware-endpoint@4.4.6': - resolution: - { - integrity: sha512-dpq3bHqbEOBqGBjRVHVFP3eUSPpX0BYtg1D5d5Irgk6orGGAuZfY22rC4sErhg+ZfY/Y0kPqm1XpAmDZg7DeuA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-dpq3bHqbEOBqGBjRVHVFP3eUSPpX0BYtg1D5d5Irgk6orGGAuZfY22rC4sErhg+ZfY/Y0kPqm1XpAmDZg7DeuA==} + engines: {node: '>=18.0.0'} '@smithy/middleware-endpoint@4.4.8': - resolution: - { - integrity: sha512-TV44qwB/T0OMMzjIuI+JeS0ort3bvlPJ8XIH0MSlGADraXpZqmyND27ueuAL3E14optleADWqtd7dUgc2w+qhQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-TV44qwB/T0OMMzjIuI+JeS0ort3bvlPJ8XIH0MSlGADraXpZqmyND27ueuAL3E14optleADWqtd7dUgc2w+qhQ==} + engines: {node: '>=18.0.0'} '@smithy/middleware-retry@4.4.22': - resolution: - { - integrity: sha512-vwWDMaObSMjw6WCC/3Ae9G7uul5Sk95jr07CDk1gkIMpaDic0phPS1MpVAZ6+YkF7PAzRlpsDjxPwRlh/S11FQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-vwWDMaObSMjw6WCC/3Ae9G7uul5Sk95jr07CDk1gkIMpaDic0phPS1MpVAZ6+YkF7PAzRlpsDjxPwRlh/S11FQ==} + engines: {node: '>=18.0.0'} '@smithy/middleware-retry@4.4.24': - resolution: - { - integrity: sha512-yiUY1UvnbUFfP5izoKLtfxDSTRv724YRRwyiC/5HYY6vdsVDcDOXKSXmkJl/Hovcxt5r+8tZEUAdrOaCJwrl9Q==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-yiUY1UvnbUFfP5izoKLtfxDSTRv724YRRwyiC/5HYY6vdsVDcDOXKSXmkJl/Hovcxt5r+8tZEUAdrOaCJwrl9Q==} + engines: {node: '>=18.0.0'} '@smithy/middleware-serde@4.2.8': - resolution: - { - integrity: sha512-8rDGYen5m5+NV9eHv9ry0sqm2gI6W7mc1VSFMtn6Igo25S507/HaOX9LTHAS2/J32VXD0xSzrY0H5FJtOMS4/w==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-8rDGYen5m5+NV9eHv9ry0sqm2gI6W7mc1VSFMtn6Igo25S507/HaOX9LTHAS2/J32VXD0xSzrY0H5FJtOMS4/w==} + engines: {node: '>=18.0.0'} '@smithy/middleware-serde@4.2.9': - resolution: - { - integrity: sha512-eMNiej0u/snzDvlqRGSN3Vl0ESn3838+nKyVfF2FKNXFbi4SERYT6PR392D39iczngbqqGG0Jl1DlCnp7tBbXQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-eMNiej0u/snzDvlqRGSN3Vl0ESn3838+nKyVfF2FKNXFbi4SERYT6PR392D39iczngbqqGG0Jl1DlCnp7tBbXQ==} + engines: {node: '>=18.0.0'} '@smithy/middleware-stack@4.2.7': - resolution: - { - integrity: sha512-bsOT0rJ+HHlZd9crHoS37mt8qRRN/h9jRve1SXUhVbkRzu0QaNYZp1i1jha4n098tsvROjcwfLlfvcFuJSXEsw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-bsOT0rJ+HHlZd9crHoS37mt8qRRN/h9jRve1SXUhVbkRzu0QaNYZp1i1jha4n098tsvROjcwfLlfvcFuJSXEsw==} + engines: {node: '>=18.0.0'} '@smithy/middleware-stack@4.2.8': - resolution: - { - integrity: sha512-w6LCfOviTYQjBctOKSwy6A8FIkQy7ICvglrZFl6Bw4FmcQ1Z420fUtIhxaUZZshRe0VCq4kvDiPiXrPZAe8oRA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-w6LCfOviTYQjBctOKSwy6A8FIkQy7ICvglrZFl6Bw4FmcQ1Z420fUtIhxaUZZshRe0VCq4kvDiPiXrPZAe8oRA==} + engines: {node: '>=18.0.0'} '@smithy/node-config-provider@4.3.7': - resolution: - { - integrity: sha512-7r58wq8sdOcrwWe+klL9y3bc4GW1gnlfnFOuL7CXa7UzfhzhxKuzNdtqgzmTV+53lEp9NXh5hY/S4UgjLOzPfw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-7r58wq8sdOcrwWe+klL9y3bc4GW1gnlfnFOuL7CXa7UzfhzhxKuzNdtqgzmTV+53lEp9NXh5hY/S4UgjLOzPfw==} + engines: {node: '>=18.0.0'} '@smithy/node-config-provider@4.3.8': - resolution: - { - integrity: sha512-aFP1ai4lrbVlWjfpAfRSL8KFcnJQYfTl5QxLJXY32vghJrDuFyPZ6LtUL+JEGYiFRG1PfPLHLoxj107ulncLIg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-aFP1ai4lrbVlWjfpAfRSL8KFcnJQYfTl5QxLJXY32vghJrDuFyPZ6LtUL+JEGYiFRG1PfPLHLoxj107ulncLIg==} + engines: {node: '>=18.0.0'} '@smithy/node-http-handler@4.4.7': - resolution: - { - integrity: sha512-NELpdmBOO6EpZtWgQiHjoShs1kmweaiNuETUpuup+cmm/xJYjT4eUjfhrXRP4jCOaAsS3c3yPsP3B+K+/fyPCQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-NELpdmBOO6EpZtWgQiHjoShs1kmweaiNuETUpuup+cmm/xJYjT4eUjfhrXRP4jCOaAsS3c3yPsP3B+K+/fyPCQ==} + engines: {node: '>=18.0.0'} '@smithy/node-http-handler@4.4.8': - resolution: - { - integrity: sha512-q9u+MSbJVIJ1QmJ4+1u+cERXkrhuILCBDsJUBAW1MPE6sFonbCNaegFuwW9ll8kh5UdyY3jOkoOGlc7BesoLpg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-q9u+MSbJVIJ1QmJ4+1u+cERXkrhuILCBDsJUBAW1MPE6sFonbCNaegFuwW9ll8kh5UdyY3jOkoOGlc7BesoLpg==} + engines: {node: '>=18.0.0'} '@smithy/property-provider@4.2.7': - resolution: - { - integrity: sha512-jmNYKe9MGGPoSl/D7JDDs1C8b3dC8f/w78LbaVfoTtWy4xAd5dfjaFG9c9PWPihY4ggMQNQSMtzU77CNgAJwmA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-jmNYKe9MGGPoSl/D7JDDs1C8b3dC8f/w78LbaVfoTtWy4xAd5dfjaFG9c9PWPihY4ggMQNQSMtzU77CNgAJwmA==} + engines: {node: '>=18.0.0'} '@smithy/property-provider@4.2.8': - resolution: - { - integrity: sha512-EtCTbyIveCKeOXDSWSdze3k612yCPq1YbXsbqX3UHhkOSW8zKsM9NOJG5gTIya0vbY2DIaieG8pKo1rITHYL0w==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-EtCTbyIveCKeOXDSWSdze3k612yCPq1YbXsbqX3UHhkOSW8zKsM9NOJG5gTIya0vbY2DIaieG8pKo1rITHYL0w==} + engines: {node: '>=18.0.0'} '@smithy/protocol-http@5.3.7': - resolution: - { - integrity: sha512-1r07pb994I20dD/c2seaZhoCuNYm0rWrvBxhCQ70brNh11M5Ml2ew6qJVo0lclB3jMIXirD4s2XRXRe7QEi0xA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-1r07pb994I20dD/c2seaZhoCuNYm0rWrvBxhCQ70brNh11M5Ml2ew6qJVo0lclB3jMIXirD4s2XRXRe7QEi0xA==} + engines: {node: '>=18.0.0'} '@smithy/protocol-http@5.3.8': - resolution: - { - integrity: sha512-QNINVDhxpZ5QnP3aviNHQFlRogQZDfYlCkQT+7tJnErPQbDhysondEjhikuANxgMsZrkGeiAxXy4jguEGsDrWQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-QNINVDhxpZ5QnP3aviNHQFlRogQZDfYlCkQT+7tJnErPQbDhysondEjhikuANxgMsZrkGeiAxXy4jguEGsDrWQ==} + engines: {node: '>=18.0.0'} '@smithy/querystring-builder@4.2.7': - resolution: - { - integrity: sha512-eKONSywHZxK4tBxe2lXEysh8wbBdvDWiA+RIuaxZSgCMmA0zMgoDpGLJhnyj+c0leOQprVnXOmcB4m+W9Rw7sg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-eKONSywHZxK4tBxe2lXEysh8wbBdvDWiA+RIuaxZSgCMmA0zMgoDpGLJhnyj+c0leOQprVnXOmcB4m+W9Rw7sg==} + engines: {node: '>=18.0.0'} '@smithy/querystring-builder@4.2.8': - resolution: - { - integrity: sha512-Xr83r31+DrE8CP3MqPgMJl+pQlLLmOfiEUnoyAlGzzJIrEsbKsPy1hqH0qySaQm4oWrCBlUqRt+idEgunKB+iw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-Xr83r31+DrE8CP3MqPgMJl+pQlLLmOfiEUnoyAlGzzJIrEsbKsPy1hqH0qySaQm4oWrCBlUqRt+idEgunKB+iw==} + engines: {node: '>=18.0.0'} '@smithy/querystring-parser@4.2.7': - resolution: - { - integrity: sha512-3X5ZvzUHmlSTHAXFlswrS6EGt8fMSIxX/c3Rm1Pni3+wYWB6cjGocmRIoqcQF9nU5OgGmL0u7l9m44tSUpfj9w==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-3X5ZvzUHmlSTHAXFlswrS6EGt8fMSIxX/c3Rm1Pni3+wYWB6cjGocmRIoqcQF9nU5OgGmL0u7l9m44tSUpfj9w==} + engines: {node: '>=18.0.0'} '@smithy/querystring-parser@4.2.8': - resolution: - { - integrity: sha512-vUurovluVy50CUlazOiXkPq40KGvGWSdmusa3130MwrR1UNnNgKAlj58wlOe61XSHRpUfIIh6cE0zZ8mzKaDPA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-vUurovluVy50CUlazOiXkPq40KGvGWSdmusa3130MwrR1UNnNgKAlj58wlOe61XSHRpUfIIh6cE0zZ8mzKaDPA==} + engines: {node: '>=18.0.0'} '@smithy/service-error-classification@4.2.8': - resolution: - { - integrity: sha512-mZ5xddodpJhEt3RkCjbmUQuXUOaPNTkbMGR0bcS8FE0bJDLMZlhmpgrvPNCYglVw5rsYTpSnv19womw9WWXKQQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-mZ5xddodpJhEt3RkCjbmUQuXUOaPNTkbMGR0bcS8FE0bJDLMZlhmpgrvPNCYglVw5rsYTpSnv19womw9WWXKQQ==} + engines: {node: '>=18.0.0'} '@smithy/shared-ini-file-loader@4.4.2': - resolution: - { - integrity: sha512-M7iUUff/KwfNunmrgtqBfvZSzh3bmFgv/j/t1Y1dQ+8dNo34br1cqVEqy6v0mYEgi0DkGO7Xig0AnuOaEGVlcg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-M7iUUff/KwfNunmrgtqBfvZSzh3bmFgv/j/t1Y1dQ+8dNo34br1cqVEqy6v0mYEgi0DkGO7Xig0AnuOaEGVlcg==} + engines: {node: '>=18.0.0'} '@smithy/shared-ini-file-loader@4.4.3': - resolution: - { - integrity: sha512-DfQjxXQnzC5UbCUPeC3Ie8u+rIWZTvuDPAGU/BxzrOGhRvgUanaP68kDZA+jaT3ZI+djOf+4dERGlm9mWfFDrg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-DfQjxXQnzC5UbCUPeC3Ie8u+rIWZTvuDPAGU/BxzrOGhRvgUanaP68kDZA+jaT3ZI+djOf+4dERGlm9mWfFDrg==} + engines: {node: '>=18.0.0'} '@smithy/signature-v4@5.3.8': - resolution: - { - integrity: sha512-6A4vdGj7qKNRF16UIcO8HhHjKW27thsxYci+5r/uVRkdcBEkOEiY8OMPuydLX4QHSrJqGHPJzPRwwVTqbLZJhg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-6A4vdGj7qKNRF16UIcO8HhHjKW27thsxYci+5r/uVRkdcBEkOEiY8OMPuydLX4QHSrJqGHPJzPRwwVTqbLZJhg==} + engines: {node: '>=18.0.0'} '@smithy/smithy-client@4.10.2': - resolution: - { - integrity: sha512-D5z79xQWpgrGpAHb054Fn2CCTQZpog7JELbVQ6XAvXs5MNKWf28U9gzSBlJkOyMl9LA1TZEjRtwvGXfP0Sl90g==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-D5z79xQWpgrGpAHb054Fn2CCTQZpog7JELbVQ6XAvXs5MNKWf28U9gzSBlJkOyMl9LA1TZEjRtwvGXfP0Sl90g==} + engines: {node: '>=18.0.0'} '@smithy/smithy-client@4.10.7': - resolution: - { - integrity: sha512-Uznt0I9z3os3Z+8pbXrOSCTXCA6vrjyN7Ub+8l2pRDum44vLv8qw0qGVkJN0/tZBZotaEFHrDPKUoPNueTr5Vg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-Uznt0I9z3os3Z+8pbXrOSCTXCA6vrjyN7Ub+8l2pRDum44vLv8qw0qGVkJN0/tZBZotaEFHrDPKUoPNueTr5Vg==} + engines: {node: '>=18.0.0'} '@smithy/smithy-client@4.10.9': - resolution: - { - integrity: sha512-Je0EvGXVJ0Vrrr2lsubq43JGRIluJ/hX17aN/W/A0WfE+JpoMdI8kwk2t9F0zTX9232sJDGcoH4zZre6m6f/sg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-Je0EvGXVJ0Vrrr2lsubq43JGRIluJ/hX17aN/W/A0WfE+JpoMdI8kwk2t9F0zTX9232sJDGcoH4zZre6m6f/sg==} + engines: {node: '>=18.0.0'} '@smithy/types@4.11.0': - resolution: - { - integrity: sha512-mlrmL0DRDVe3mNrjTcVcZEgkFmufITfUAPBEA+AHYiIeYyJebso/He1qLbP3PssRe22KUzLRpQSdBPbXdgZ2VA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-mlrmL0DRDVe3mNrjTcVcZEgkFmufITfUAPBEA+AHYiIeYyJebso/He1qLbP3PssRe22KUzLRpQSdBPbXdgZ2VA==} + engines: {node: '>=18.0.0'} '@smithy/types@4.12.0': - resolution: - { - integrity: sha512-9YcuJVTOBDjg9LWo23Qp0lTQ3D7fQsQtwle0jVfpbUHy9qBwCEgKuVH4FqFB3VYu0nwdHKiEMA+oXz7oV8X1kw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-9YcuJVTOBDjg9LWo23Qp0lTQ3D7fQsQtwle0jVfpbUHy9qBwCEgKuVH4FqFB3VYu0nwdHKiEMA+oXz7oV8X1kw==} + engines: {node: '>=18.0.0'} '@smithy/url-parser@4.2.7': - resolution: - { - integrity: sha512-/RLtVsRV4uY3qPWhBDsjwahAtt3x2IsMGnP5W1b2VZIe+qgCqkLxI1UOHDZp1Q1QSOrdOR32MF3Ph2JfWT1VHg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-/RLtVsRV4uY3qPWhBDsjwahAtt3x2IsMGnP5W1b2VZIe+qgCqkLxI1UOHDZp1Q1QSOrdOR32MF3Ph2JfWT1VHg==} + engines: {node: '>=18.0.0'} '@smithy/url-parser@4.2.8': - resolution: - { - integrity: sha512-NQho9U68TGMEU639YkXnVMV3GEFFULmmaWdlu1E9qzyIePOHsoSnagTGSDv1Zi8DCNN6btxOSdgmy5E/hsZwhA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-NQho9U68TGMEU639YkXnVMV3GEFFULmmaWdlu1E9qzyIePOHsoSnagTGSDv1Zi8DCNN6btxOSdgmy5E/hsZwhA==} + engines: {node: '>=18.0.0'} '@smithy/util-base64@4.3.0': - resolution: - { - integrity: sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==} + engines: {node: '>=18.0.0'} '@smithy/util-body-length-browser@4.2.0': - resolution: - { - integrity: sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==} + engines: {node: '>=18.0.0'} '@smithy/util-body-length-node@4.2.1': - resolution: - { - integrity: sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==} + engines: {node: '>=18.0.0'} '@smithy/util-buffer-from@2.2.0': - resolution: - { - integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==, - } - engines: { node: '>=14.0.0' } + resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} + engines: {node: '>=14.0.0'} '@smithy/util-buffer-from@4.2.0': - resolution: - { - integrity: sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew==} + engines: {node: '>=18.0.0'} '@smithy/util-config-provider@4.2.0': - resolution: - { - integrity: sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==} + engines: {node: '>=18.0.0'} '@smithy/util-defaults-mode-browser@4.3.21': - resolution: - { - integrity: sha512-DtmVJarzqtjghtGjCw/PFJolcJkP7GkZgy+hWTAN3YLXNH+IC82uMoMhFoC3ZtIz5mOgCm5+hOGi1wfhVYgrxw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-DtmVJarzqtjghtGjCw/PFJolcJkP7GkZgy+hWTAN3YLXNH+IC82uMoMhFoC3ZtIz5mOgCm5+hOGi1wfhVYgrxw==} + engines: {node: '>=18.0.0'} '@smithy/util-defaults-mode-browser@4.3.23': - resolution: - { - integrity: sha512-mMg+r/qDfjfF/0psMbV4zd7F/i+rpyp7Hjh0Wry7eY15UnzTEId+xmQTGDU8IdZtDfbGQxuWNfgBZKBj+WuYbA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-mMg+r/qDfjfF/0psMbV4zd7F/i+rpyp7Hjh0Wry7eY15UnzTEId+xmQTGDU8IdZtDfbGQxuWNfgBZKBj+WuYbA==} + engines: {node: '>=18.0.0'} '@smithy/util-defaults-mode-node@4.2.24': - resolution: - { - integrity: sha512-JelBDKPAVswVY666rezBvY6b0nF/v9TXjUbNwDNAyme7qqKYEX687wJv0uze8lBIZVbg30wlWnlYfVSjjpKYFA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-JelBDKPAVswVY666rezBvY6b0nF/v9TXjUbNwDNAyme7qqKYEX687wJv0uze8lBIZVbg30wlWnlYfVSjjpKYFA==} + engines: {node: '>=18.0.0'} '@smithy/util-defaults-mode-node@4.2.26': - resolution: - { - integrity: sha512-EQqe/WkbCinah0h1lMWh9ICl0Ob4lyl20/10WTB35SC9vDQfD8zWsOT+x2FIOXKAoZQ8z/y0EFMoodbcqWJY/w==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-EQqe/WkbCinah0h1lMWh9ICl0Ob4lyl20/10WTB35SC9vDQfD8zWsOT+x2FIOXKAoZQ8z/y0EFMoodbcqWJY/w==} + engines: {node: '>=18.0.0'} '@smithy/util-endpoints@3.2.8': - resolution: - { - integrity: sha512-8JaVTn3pBDkhZgHQ8R0epwWt+BqPSLCjdjXXusK1onwJlRuN69fbvSK66aIKKO7SwVFM6x2J2ox5X8pOaWcUEw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-8JaVTn3pBDkhZgHQ8R0epwWt+BqPSLCjdjXXusK1onwJlRuN69fbvSK66aIKKO7SwVFM6x2J2ox5X8pOaWcUEw==} + engines: {node: '>=18.0.0'} '@smithy/util-hex-encoding@4.2.0': - resolution: - { - integrity: sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==} + engines: {node: '>=18.0.0'} '@smithy/util-middleware@4.2.7': - resolution: - { - integrity: sha512-i1IkpbOae6NvIKsEeLLM9/2q4X+M90KV3oCFgWQI4q0Qz+yUZvsr+gZPdAEAtFhWQhAHpTsJO8DRJPuwVyln+w==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-i1IkpbOae6NvIKsEeLLM9/2q4X+M90KV3oCFgWQI4q0Qz+yUZvsr+gZPdAEAtFhWQhAHpTsJO8DRJPuwVyln+w==} + engines: {node: '>=18.0.0'} '@smithy/util-middleware@4.2.8': - resolution: - { - integrity: sha512-PMqfeJxLcNPMDgvPbbLl/2Vpin+luxqTGPpW3NAQVLbRrFRzTa4rNAASYeIGjRV9Ytuhzny39SpyU04EQreF+A==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-PMqfeJxLcNPMDgvPbbLl/2Vpin+luxqTGPpW3NAQVLbRrFRzTa4rNAASYeIGjRV9Ytuhzny39SpyU04EQreF+A==} + engines: {node: '>=18.0.0'} '@smithy/util-retry@4.2.8': - resolution: - { - integrity: sha512-CfJqwvoRY0kTGe5AkQokpURNCT1u/MkRzMTASWMPPo2hNSnKtF1D45dQl3DE2LKLr4m+PW9mCeBMJr5mCAVThg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-CfJqwvoRY0kTGe5AkQokpURNCT1u/MkRzMTASWMPPo2hNSnKtF1D45dQl3DE2LKLr4m+PW9mCeBMJr5mCAVThg==} + engines: {node: '>=18.0.0'} '@smithy/util-stream@4.5.10': - resolution: - { - integrity: sha512-jbqemy51UFSZSp2y0ZmRfckmrzuKww95zT9BYMmuJ8v3altGcqjwoV1tzpOwuHaKrwQrCjIzOib499ymr2f98g==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-jbqemy51UFSZSp2y0ZmRfckmrzuKww95zT9BYMmuJ8v3altGcqjwoV1tzpOwuHaKrwQrCjIzOib499ymr2f98g==} + engines: {node: '>=18.0.0'} '@smithy/util-stream@4.5.8': - resolution: - { - integrity: sha512-ZnnBhTapjM0YPGUSmOs0Mcg/Gg87k503qG4zU2v/+Js2Gu+daKOJMeqcQns8ajepY8tgzzfYxl6kQyZKml6O2w==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-ZnnBhTapjM0YPGUSmOs0Mcg/Gg87k503qG4zU2v/+Js2Gu+daKOJMeqcQns8ajepY8tgzzfYxl6kQyZKml6O2w==} + engines: {node: '>=18.0.0'} '@smithy/util-uri-escape@4.2.0': - resolution: - { - integrity: sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==} + engines: {node: '>=18.0.0'} '@smithy/util-utf8@2.3.0': - resolution: - { - integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==, - } - engines: { node: '>=14.0.0' } + resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} + engines: {node: '>=14.0.0'} '@smithy/util-utf8@4.2.0': - resolution: - { - integrity: sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==} + engines: {node: '>=18.0.0'} '@smithy/util-waiter@4.2.8': - resolution: - { - integrity: sha512-n+lahlMWk+aejGuax7DPWtqav8HYnWxQwR+LCG2BgCUmaGcTe9qZCFsmw8TMg9iG75HOwhrJCX9TCJRLH+Yzqg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-n+lahlMWk+aejGuax7DPWtqav8HYnWxQwR+LCG2BgCUmaGcTe9qZCFsmw8TMg9iG75HOwhrJCX9TCJRLH+Yzqg==} + engines: {node: '>=18.0.0'} '@smithy/uuid@1.1.0': - resolution: - { - integrity: sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==} + engines: {node: '>=18.0.0'} '@styled-system/background@5.1.2': - resolution: - { - integrity: sha512-jtwH2C/U6ssuGSvwTN3ri/IyjdHb8W9X/g8Y0JLcrH02G+BW3OS8kZdHphF1/YyRklnrKrBT2ngwGUK6aqqV3A==, - } + resolution: {integrity: sha512-jtwH2C/U6ssuGSvwTN3ri/IyjdHb8W9X/g8Y0JLcrH02G+BW3OS8kZdHphF1/YyRklnrKrBT2ngwGUK6aqqV3A==} '@styled-system/border@5.1.5': - resolution: - { - integrity: sha512-JvddhNrnhGigtzWRCVuAHepniyVi6hBlimxWDVAdcTuk7aRn9BYJUwfHslURtwYFsF5FoEs8Zmr1oZq2M1AP0A==, - } + resolution: {integrity: sha512-JvddhNrnhGigtzWRCVuAHepniyVi6hBlimxWDVAdcTuk7aRn9BYJUwfHslURtwYFsF5FoEs8Zmr1oZq2M1AP0A==} '@styled-system/color@5.1.2': - resolution: - { - integrity: sha512-1kCkeKDZkt4GYkuFNKc7vJQMcOmTl3bJY3YBUs7fCNM6mMYJeT1pViQ2LwBSBJytj3AB0o4IdLBoepgSgGl5MA==, - } + resolution: {integrity: sha512-1kCkeKDZkt4GYkuFNKc7vJQMcOmTl3bJY3YBUs7fCNM6mMYJeT1pViQ2LwBSBJytj3AB0o4IdLBoepgSgGl5MA==} '@styled-system/core@5.1.2': - resolution: - { - integrity: sha512-XclBDdNIy7OPOsN4HBsawG2eiWfCcuFt6gxKn1x4QfMIgeO6TOlA2pZZ5GWZtIhCUqEPTgIBta6JXsGyCkLBYw==, - } + resolution: {integrity: sha512-XclBDdNIy7OPOsN4HBsawG2eiWfCcuFt6gxKn1x4QfMIgeO6TOlA2pZZ5GWZtIhCUqEPTgIBta6JXsGyCkLBYw==} '@styled-system/css@5.1.5': - resolution: - { - integrity: sha512-XkORZdS5kypzcBotAMPBoeckDs9aSZVkvrAlq5K3xP8IMAUek+x2O4NtwoSgkYkWWzVBu6DGdFZLR790QWGG+A==, - } + resolution: {integrity: sha512-XkORZdS5kypzcBotAMPBoeckDs9aSZVkvrAlq5K3xP8IMAUek+x2O4NtwoSgkYkWWzVBu6DGdFZLR790QWGG+A==} '@styled-system/flexbox@5.1.2': - resolution: - { - integrity: sha512-6hHV52+eUk654Y1J2v77B8iLeBNtc+SA3R4necsu2VVinSD7+XY5PCCEzBFaWs42dtOEDIa2lMrgL0YBC01mDQ==, - } + resolution: {integrity: sha512-6hHV52+eUk654Y1J2v77B8iLeBNtc+SA3R4necsu2VVinSD7+XY5PCCEzBFaWs42dtOEDIa2lMrgL0YBC01mDQ==} '@styled-system/grid@5.1.2': - resolution: - { - integrity: sha512-K3YiV1KyHHzgdNuNlaw8oW2ktMuGga99o1e/NAfTEi5Zsa7JXxzwEnVSDSBdJC+z6R8WYTCYRQC6bkVFcvdTeg==, - } + resolution: {integrity: sha512-K3YiV1KyHHzgdNuNlaw8oW2ktMuGga99o1e/NAfTEi5Zsa7JXxzwEnVSDSBdJC+z6R8WYTCYRQC6bkVFcvdTeg==} '@styled-system/layout@5.1.2': - resolution: - { - integrity: sha512-wUhkMBqSeacPFhoE9S6UF3fsMEKFv91gF4AdDWp0Aym1yeMPpqz9l9qS/6vjSsDPF7zOb5cOKC3tcKKOMuDCPw==, - } + resolution: {integrity: sha512-wUhkMBqSeacPFhoE9S6UF3fsMEKFv91gF4AdDWp0Aym1yeMPpqz9l9qS/6vjSsDPF7zOb5cOKC3tcKKOMuDCPw==} '@styled-system/position@5.1.2': - resolution: - { - integrity: sha512-60IZfMXEOOZe3l1mCu6sj/2NAyUmES2kR9Kzp7s2D3P4qKsZWxD1Se1+wJvevb+1TP+ZMkGPEYYXRyU8M1aF5A==, - } + resolution: {integrity: sha512-60IZfMXEOOZe3l1mCu6sj/2NAyUmES2kR9Kzp7s2D3P4qKsZWxD1Se1+wJvevb+1TP+ZMkGPEYYXRyU8M1aF5A==} '@styled-system/shadow@5.1.2': - resolution: - { - integrity: sha512-wqniqYb7XuZM7K7C0d1Euxc4eGtqEe/lvM0WjuAFsQVImiq6KGT7s7is+0bNI8O4Dwg27jyu4Lfqo/oIQXNzAg==, - } + resolution: {integrity: sha512-wqniqYb7XuZM7K7C0d1Euxc4eGtqEe/lvM0WjuAFsQVImiq6KGT7s7is+0bNI8O4Dwg27jyu4Lfqo/oIQXNzAg==} '@styled-system/space@5.1.2': - resolution: - { - integrity: sha512-+zzYpR8uvfhcAbaPXhH8QgDAV//flxqxSjHiS9cDFQQUSznXMQmxJegbhcdEF7/eNnJgHeIXv1jmny78kipgBA==, - } + resolution: {integrity: sha512-+zzYpR8uvfhcAbaPXhH8QgDAV//flxqxSjHiS9cDFQQUSznXMQmxJegbhcdEF7/eNnJgHeIXv1jmny78kipgBA==} '@styled-system/typography@5.1.2': - resolution: - { - integrity: sha512-BxbVUnN8N7hJ4aaPOd7wEsudeT7CxarR+2hns8XCX1zp0DFfbWw4xYa/olA0oQaqx7F1hzDg+eRaGzAJbF+jOg==, - } + resolution: {integrity: sha512-BxbVUnN8N7hJ4aaPOd7wEsudeT7CxarR+2hns8XCX1zp0DFfbWw4xYa/olA0oQaqx7F1hzDg+eRaGzAJbF+jOg==} '@styled-system/variant@5.1.5': - resolution: - { - integrity: sha512-Yn8hXAFoWIro8+Q5J8YJd/mP85Teiut3fsGVR9CAxwgNfIAiqlYxsk5iHU7VHJks/0KjL4ATSjmbtCDC/4l1qw==, - } + resolution: {integrity: sha512-Yn8hXAFoWIro8+Q5J8YJd/mP85Teiut3fsGVR9CAxwgNfIAiqlYxsk5iHU7VHJks/0KjL4ATSjmbtCDC/4l1qw==} '@swc/helpers@0.5.18': - resolution: - { - integrity: sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ==, - } + resolution: {integrity: sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ==} '@tanstack/query-core@5.90.19': - resolution: - { - integrity: sha512-GLW5sjPVIvH491VV1ufddnfldyVB+teCnpPIvweEfkpRx7CfUmUGhoh9cdcUKBh/KwVxk22aNEDxeTsvmyB/WA==, - } + resolution: {integrity: sha512-GLW5sjPVIvH491VV1ufddnfldyVB+teCnpPIvweEfkpRx7CfUmUGhoh9cdcUKBh/KwVxk22aNEDxeTsvmyB/WA==} '@tanstack/query-core@5.90.20': - resolution: - { - integrity: sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg==, - } + resolution: {integrity: sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg==} '@tanstack/react-query@5.90.19': - resolution: - { - integrity: sha512-qTZRZ4QyTzQc+M0IzrbKHxSeISUmRB3RPGmao5bT+sI6ayxSRhn0FXEnT5Hg3as8SBFcRosrXXRFB+yAcxVxJQ==, - } + resolution: {integrity: sha512-qTZRZ4QyTzQc+M0IzrbKHxSeISUmRB3RPGmao5bT+sI6ayxSRhn0FXEnT5Hg3as8SBFcRosrXXRFB+yAcxVxJQ==} peerDependencies: react: ^18 || ^19 '@tanstack/react-query@5.90.20': - resolution: - { - integrity: sha512-vXBxa+qeyveVO7OA0jX1z+DeyCA4JKnThKv411jd5SORpBKgkcVnYKCiBgECvADvniBX7tobwBmg01qq9JmMJw==, - } + resolution: {integrity: sha512-vXBxa+qeyveVO7OA0jX1z+DeyCA4JKnThKv411jd5SORpBKgkcVnYKCiBgECvADvniBX7tobwBmg01qq9JmMJw==} peerDependencies: react: ^18 || ^19 '@tanstack/react-virtual@3.13.18': - resolution: - { - integrity: sha512-dZkhyfahpvlaV0rIKnvQiVoWPyURppl6w4m9IwMDpuIjcJ1sD9YGWrt0wISvgU7ewACXx2Ct46WPgI6qAD4v6A==, - } + resolution: {integrity: sha512-dZkhyfahpvlaV0rIKnvQiVoWPyURppl6w4m9IwMDpuIjcJ1sD9YGWrt0wISvgU7ewACXx2Ct46WPgI6qAD4v6A==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 '@tanstack/virtual-core@3.13.18': - resolution: - { - integrity: sha512-Mx86Hqu1k39icq2Zusq+Ey2J6dDWTjDvEv43PJtRCoEYTLyfaPnxIQ6iy7YAOK0NV/qOEmZQ/uCufrppZxTgcg==, - } + resolution: {integrity: sha512-Mx86Hqu1k39icq2Zusq+Ey2J6dDWTjDvEv43PJtRCoEYTLyfaPnxIQ6iy7YAOK0NV/qOEmZQ/uCufrppZxTgcg==} '@testing-library/dom@7.31.2': - resolution: - { - integrity: sha512-3UqjCpey6HiTZT92vODYLPxTBWlM8ZOOjr3LX5F37/VRipW2M1kX6I/Cm4VXzteZqfGfagg8yXywpcOgQBlNsQ==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-3UqjCpey6HiTZT92vODYLPxTBWlM8ZOOjr3LX5F37/VRipW2M1kX6I/Cm4VXzteZqfGfagg8yXywpcOgQBlNsQ==} + engines: {node: '>=10'} '@testing-library/jest-dom@5.11.10': - resolution: - { - integrity: sha512-FuKiq5xuk44Fqm0000Z9w0hjOdwZRNzgx7xGGxQYepWFZy+OYUMOT/wPI4nLYXCaVltNVpU1W/qmD88wLWDsqQ==, - } - engines: { node: '>=8', npm: '>=6', yarn: '>=1' } + resolution: {integrity: sha512-FuKiq5xuk44Fqm0000Z9w0hjOdwZRNzgx7xGGxQYepWFZy+OYUMOT/wPI4nLYXCaVltNVpU1W/qmD88wLWDsqQ==} + engines: {node: '>=8', npm: '>=6', yarn: '>=1'} '@testing-library/react@11.2.5': - resolution: - { - integrity: sha512-yEx7oIa/UWLe2F2dqK0FtMF9sJWNXD+2PPtp39BvE0Kh9MJ9Kl0HrZAgEuhUJR+Lx8Di6Xz+rKwSdEPY2UV8ZQ==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-yEx7oIa/UWLe2F2dqK0FtMF9sJWNXD+2PPtp39BvE0Kh9MJ9Kl0HrZAgEuhUJR+Lx8Di6Xz+rKwSdEPY2UV8ZQ==} + engines: {node: '>=10'} peerDependencies: react: '*' react-dom: '*' '@tsconfig/node10@1.0.12': - resolution: - { - integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==, - } + resolution: {integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==} '@tsconfig/node12@1.0.11': - resolution: - { - integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==, - } + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} '@tsconfig/node14@1.0.3': - resolution: - { - integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==, - } + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} '@tsconfig/node16@1.0.4': - resolution: - { - integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==, - } + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} '@tsconfig/node20@20.1.9': - resolution: - { - integrity: sha512-IjlTv1RsvnPtUcjTqtVsZExKVq+KQx4g5pCP5tI7rAs6Xesl2qFwSz/tPDBC4JajkL/MlezBu3gPUwqRHl+RIg==, - } + resolution: {integrity: sha512-IjlTv1RsvnPtUcjTqtVsZExKVq+KQx4g5pCP5tI7rAs6Xesl2qFwSz/tPDBC4JajkL/MlezBu3gPUwqRHl+RIg==} '@tufjs/canonical-json@2.0.0': - resolution: - { - integrity: sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==} + engines: {node: ^16.14.0 || >=18.0.0} '@tufjs/models@2.0.1': - resolution: - { - integrity: sha512-92F7/SFyufn4DXsha9+QfKnN03JGqtMFMXgSHbZOo8JG59WkTni7UzAouNQDf7AuP9OAMxVOPQcqG3sB7w+kkg==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-92F7/SFyufn4DXsha9+QfKnN03JGqtMFMXgSHbZOo8JG59WkTni7UzAouNQDf7AuP9OAMxVOPQcqG3sB7w+kkg==} + engines: {node: ^16.14.0 || >=18.0.0} '@tybys/wasm-util@0.10.1': - resolution: - { - integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==, - } + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} '@tybys/wasm-util@0.9.0': - resolution: - { - integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==, - } + resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} '@types/accepts@1.3.7': - resolution: - { - integrity: sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==, - } + resolution: {integrity: sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==} '@types/aria-query@4.2.2': - resolution: - { - integrity: sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==, - } + resolution: {integrity: sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==} '@types/babel__core@7.20.5': - resolution: - { - integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==, - } + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} '@types/babel__generator@7.27.0': - resolution: - { - integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==, - } + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} '@types/babel__template@7.4.4': - resolution: - { - integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==, - } + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} '@types/babel__traverse@7.28.0': - resolution: - { - integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==, - } + resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} '@types/body-parser@1.19.6': - resolution: - { - integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==, - } + resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==} '@types/connect@3.4.38': - resolution: - { - integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==, - } + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} '@types/content-disposition@0.5.9': - resolution: - { - integrity: sha512-8uYXI3Gw35MhiVYhG3s295oihrxRyytcRHjSjqnqZVDDy/xcGBRny7+Xj1Wgfhv5QzRtN2hB2dVRBUX9XW3UcQ==, - } + resolution: {integrity: sha512-8uYXI3Gw35MhiVYhG3s295oihrxRyytcRHjSjqnqZVDDy/xcGBRny7+Xj1Wgfhv5QzRtN2hB2dVRBUX9XW3UcQ==} '@types/cookiejar@2.1.5': - resolution: - { - integrity: sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==, - } + resolution: {integrity: sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==} '@types/cookies@0.9.2': - resolution: - { - integrity: sha512-1AvkDdZM2dbyFybL4fxpuNCaWyv//0AwsuUk2DWeXyM1/5ZKm6W3z6mQi24RZ4l2ucY+bkSHzbDVpySqPGuV8A==, - } + resolution: {integrity: sha512-1AvkDdZM2dbyFybL4fxpuNCaWyv//0AwsuUk2DWeXyM1/5ZKm6W3z6mQi24RZ4l2ucY+bkSHzbDVpySqPGuV8A==} '@types/cors@2.8.19': - resolution: - { - integrity: sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==, - } + resolution: {integrity: sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==} '@types/d3-array@3.2.2': - resolution: - { - integrity: sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==, - } + resolution: {integrity: sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==} '@types/d3-axis@3.0.6': - resolution: - { - integrity: sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==, - } + resolution: {integrity: sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==} '@types/d3-brush@3.0.6': - resolution: - { - integrity: sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==, - } + resolution: {integrity: sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==} '@types/d3-chord@3.0.6': - resolution: - { - integrity: sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==, - } + resolution: {integrity: sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==} '@types/d3-color@3.1.3': - resolution: - { - integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==, - } + resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==} '@types/d3-contour@3.0.6': - resolution: - { - integrity: sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==, - } + resolution: {integrity: sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==} '@types/d3-delaunay@6.0.4': - resolution: - { - integrity: sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==, - } + resolution: {integrity: sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==} '@types/d3-dispatch@3.0.7': - resolution: - { - integrity: sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==, - } + resolution: {integrity: sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==} '@types/d3-drag@3.0.7': - resolution: - { - integrity: sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==, - } + resolution: {integrity: sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==} '@types/d3-dsv@3.0.7': - resolution: - { - integrity: sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==, - } + resolution: {integrity: sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==} '@types/d3-ease@3.0.2': - resolution: - { - integrity: sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==, - } + resolution: {integrity: sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==} '@types/d3-fetch@3.0.7': - resolution: - { - integrity: sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==, - } + resolution: {integrity: sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==} '@types/d3-force@3.0.10': - resolution: - { - integrity: sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==, - } + resolution: {integrity: sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==} '@types/d3-format@3.0.4': - resolution: - { - integrity: sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==, - } + resolution: {integrity: sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==} '@types/d3-geo@3.1.0': - resolution: - { - integrity: sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==, - } + resolution: {integrity: sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==} '@types/d3-hierarchy@3.1.7': - resolution: - { - integrity: sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==, - } + resolution: {integrity: sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==} '@types/d3-interpolate@3.0.4': - resolution: - { - integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==, - } + resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==} '@types/d3-path@3.1.1': - resolution: - { - integrity: sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==, - } + resolution: {integrity: sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==} '@types/d3-polygon@3.0.2': - resolution: - { - integrity: sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==, - } + resolution: {integrity: sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==} '@types/d3-quadtree@3.0.6': - resolution: - { - integrity: sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==, - } + resolution: {integrity: sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==} '@types/d3-random@3.0.3': - resolution: - { - integrity: sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==, - } + resolution: {integrity: sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==} '@types/d3-scale-chromatic@3.1.0': - resolution: - { - integrity: sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==, - } + resolution: {integrity: sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==} '@types/d3-scale@4.0.9': - resolution: - { - integrity: sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==, - } + resolution: {integrity: sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==} '@types/d3-selection@3.0.11': - resolution: - { - integrity: sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==, - } + resolution: {integrity: sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==} '@types/d3-shape@3.1.8': - resolution: - { - integrity: sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==, - } + resolution: {integrity: sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==} '@types/d3-time-format@4.0.3': - resolution: - { - integrity: sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==, - } + resolution: {integrity: sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==} '@types/d3-time@3.0.4': - resolution: - { - integrity: sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==, - } + resolution: {integrity: sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==} '@types/d3-timer@3.0.2': - resolution: - { - integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==, - } + resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==} '@types/d3-transition@3.0.9': - resolution: - { - integrity: sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==, - } + resolution: {integrity: sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==} '@types/d3-zoom@3.0.8': - resolution: - { - integrity: sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==, - } + resolution: {integrity: sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==} '@types/d3@7.4.3': - resolution: - { - integrity: sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==, - } + resolution: {integrity: sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==} '@types/estree@1.0.8': - resolution: - { - integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==, - } + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} '@types/express-serve-static-core@5.1.0': - resolution: - { - integrity: sha512-jnHMsrd0Mwa9Cf4IdOzbz543y4XJepXrbia2T4b6+spXC2We3t1y6K44D3mR8XMFSXMCf3/l7rCgddfx7UNVBA==, - } + resolution: {integrity: sha512-jnHMsrd0Mwa9Cf4IdOzbz543y4XJepXrbia2T4b6+spXC2We3t1y6K44D3mR8XMFSXMCf3/l7rCgddfx7UNVBA==} '@types/express@5.0.6': - resolution: - { - integrity: sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==, - } + resolution: {integrity: sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==} '@types/geojson@7946.0.16': - resolution: - { - integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==, - } + resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==} '@types/graphql-upload@8.0.12': - resolution: - { - integrity: sha512-M0ZPZqNUzKNB16q5woEzgG/Q8DjICV80K7JvDSRnDmDFfrRdfFX/n6PbmqAN7gCzECcHVnw1gk6N4Cg0FwxCqA==, - } + resolution: {integrity: sha512-M0ZPZqNUzKNB16q5woEzgG/Q8DjICV80K7JvDSRnDmDFfrRdfFX/n6PbmqAN7gCzECcHVnw1gk6N4Cg0FwxCqA==} '@types/http-assert@1.5.6': - resolution: - { - integrity: sha512-TTEwmtjgVbYAzZYWyeHPrrtWnfVkm8tQkP8P21uQifPgMRgjrow3XDEYqucuC8SKZJT7pUnhU/JymvjggxO9vw==, - } + resolution: {integrity: sha512-TTEwmtjgVbYAzZYWyeHPrrtWnfVkm8tQkP8P21uQifPgMRgjrow3XDEYqucuC8SKZJT7pUnhU/JymvjggxO9vw==} '@types/http-errors@2.0.5': - resolution: - { - integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==, - } + resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} '@types/interpret@1.1.4': - resolution: - { - integrity: sha512-r+tPKWHYqaxJOYA3Eik0mMi+SEREqOXLmsooRFmc6GHv7nWUDixFtKN+cegvsPlDcEZd9wxsdp041v2imQuvag==, - } + resolution: {integrity: sha512-r+tPKWHYqaxJOYA3Eik0mMi+SEREqOXLmsooRFmc6GHv7nWUDixFtKN+cegvsPlDcEZd9wxsdp041v2imQuvag==} '@types/istanbul-lib-coverage@2.0.6': - resolution: - { - integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==, - } + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} '@types/istanbul-lib-report@3.0.3': - resolution: - { - integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==, - } + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} '@types/istanbul-reports@3.0.4': - resolution: - { - integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==, - } + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} '@types/jest-in-case@1.0.9': - resolution: - { - integrity: sha512-tapHpzWGjCC/hxYJyzbJ/5ZV6rA2153Sve5lGJUAIA1Jzrphfp27TznAWfGeXf+d8TLN7zMujaC0UwNQwSJaQg==, - } + resolution: {integrity: sha512-tapHpzWGjCC/hxYJyzbJ/5ZV6rA2153Sve5lGJUAIA1Jzrphfp27TznAWfGeXf+d8TLN7zMujaC0UwNQwSJaQg==} '@types/jest@30.0.0': - resolution: - { - integrity: sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==, - } + resolution: {integrity: sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==} '@types/js-yaml@4.0.9': - resolution: - { - integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==, - } + resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==} '@types/json-schema@7.0.15': - resolution: - { - integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==, - } + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} '@types/keygrip@1.0.6': - resolution: - { - integrity: sha512-lZuNAY9xeJt7Bx4t4dx0rYCDqGPW8RXhQZK1td7d4H6E9zYbLoOtjBvfwdTKpsyxQI/2jv+armjX/RW+ZNpXOQ==, - } + resolution: {integrity: sha512-lZuNAY9xeJt7Bx4t4dx0rYCDqGPW8RXhQZK1td7d4H6E9zYbLoOtjBvfwdTKpsyxQI/2jv+armjX/RW+ZNpXOQ==} '@types/koa-compose@3.2.9': - resolution: - { - integrity: sha512-BroAZ9FTvPiCy0Pi8tjD1OfJ7bgU1gQf0eR6e1Vm+JJATy9eKOG3hQMFtMciMawiSOVnLMdmUOC46s7HBhSTsA==, - } + resolution: {integrity: sha512-BroAZ9FTvPiCy0Pi8tjD1OfJ7bgU1gQf0eR6e1Vm+JJATy9eKOG3hQMFtMciMawiSOVnLMdmUOC46s7HBhSTsA==} '@types/koa@3.0.1': - resolution: - { - integrity: sha512-VkB6WJUQSe0zBpR+Q7/YIUESGp5wPHcaXr0xueU5W0EOUWtlSbblsl+Kl31lyRQ63nIILh0e/7gXjQ09JXJIHw==, - } + resolution: {integrity: sha512-VkB6WJUQSe0zBpR+Q7/YIUESGp5wPHcaXr0xueU5W0EOUWtlSbblsl+Kl31lyRQ63nIILh0e/7gXjQ09JXJIHw==} '@types/methods@1.1.4': - resolution: - { - integrity: sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==, - } + resolution: {integrity: sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==} '@types/minimatch@3.0.5': - resolution: - { - integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==, - } + resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} '@types/minimist@1.2.5': - resolution: - { - integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==, - } + resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} '@types/node@18.19.130': - resolution: - { - integrity: sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==, - } + resolution: {integrity: sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==} '@types/node@20.19.27': - resolution: - { - integrity: sha512-N2clP5pJhB2YnZJ3PIHFk5RkygRX5WO/5f0WC08tp0wd+sv0rsJk3MqWn3CbNmT2J505a5336jaQj4ph1AdMug==, - } + resolution: {integrity: sha512-N2clP5pJhB2YnZJ3PIHFk5RkygRX5WO/5f0WC08tp0wd+sv0rsJk3MqWn3CbNmT2J505a5336jaQj4ph1AdMug==} '@types/node@22.19.11': - resolution: - { - integrity: sha512-BH7YwL6rA93ReqeQS1c4bsPpcfOmJasG+Fkr6Y59q83f9M1WcBRHR2vM+P9eOisYRcN3ujQoiZY8uk5W+1WL8w==, - } + resolution: {integrity: sha512-BH7YwL6rA93ReqeQS1c4bsPpcfOmJasG+Fkr6Y59q83f9M1WcBRHR2vM+P9eOisYRcN3ujQoiZY8uk5W+1WL8w==} '@types/nodemailer@7.0.5': - resolution: - { - integrity: sha512-7WtR4MFJUNN2UFy0NIowBRJswj5KXjXDhlZY43Hmots5eGu5q/dTeFd/I6GgJA/qj3RqO6dDy4SvfcV3fOVeIA==, - } + resolution: {integrity: sha512-7WtR4MFJUNN2UFy0NIowBRJswj5KXjXDhlZY43Hmots5eGu5q/dTeFd/I6GgJA/qj3RqO6dDy4SvfcV3fOVeIA==} '@types/normalize-package-data@2.4.4': - resolution: - { - integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==, - } + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} '@types/pg-copy-streams@1.2.5': - resolution: - { - integrity: sha512-7D6/GYW2uHIaVU6S/5omI+6RZnwlZBpLQDZAH83xX1rjxAOK0f6/deKyyUTewxqts145VIGn6XWYz1YGf50G5g==, - } + resolution: {integrity: sha512-7D6/GYW2uHIaVU6S/5omI+6RZnwlZBpLQDZAH83xX1rjxAOK0f6/deKyyUTewxqts145VIGn6XWYz1YGf50G5g==} '@types/pg@8.16.0': - resolution: - { - integrity: sha512-RmhMd/wD+CF8Dfo+cVIy3RR5cl8CyfXQ0tGgW6XBL8L4LM/UTEbNXYRbLwU6w+CgrKBNbrQWt4FUtTfaU5jSYQ==, - } + resolution: {integrity: sha512-RmhMd/wD+CF8Dfo+cVIy3RR5cl8CyfXQ0tGgW6XBL8L4LM/UTEbNXYRbLwU6w+CgrKBNbrQWt4FUtTfaU5jSYQ==} '@types/pluralize@0.0.33': - resolution: - { - integrity: sha512-JOqsl+ZoCpP4e8TDke9W79FDcSgPAR0l6pixx2JHkhnRjvShyYiAYw2LVsnA7K08Y6DeOnaU6ujmENO4os/cYg==, - } + resolution: {integrity: sha512-JOqsl+ZoCpP4e8TDke9W79FDcSgPAR0l6pixx2JHkhnRjvShyYiAYw2LVsnA7K08Y6DeOnaU6ujmENO4os/cYg==} '@types/qs@6.14.0': - resolution: - { - integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==, - } + resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==} '@types/range-parser@1.2.7': - resolution: - { - integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==, - } + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} '@types/react-dom@19.2.3': - resolution: - { - integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==, - } + resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} peerDependencies: '@types/react': ^19.2.0 '@types/react@19.2.13': - resolution: - { - integrity: sha512-KkiJeU6VbYbUOp5ITMIc7kBfqlYkKA5KhEHVrGMmUUMt7NeaZg65ojdPk+FtNrBAOXNVM5QM72jnADjM+XVRAQ==, - } + resolution: {integrity: sha512-KkiJeU6VbYbUOp5ITMIc7kBfqlYkKA5KhEHVrGMmUUMt7NeaZg65ojdPk+FtNrBAOXNVM5QM72jnADjM+XVRAQ==} '@types/react@19.2.8': - resolution: - { - integrity: sha512-3MbSL37jEchWZz2p2mjntRZtPt837ij10ApxKfgmXCTuHWagYg7iA5bqPw6C8BMPfwidlvfPI/fxOc42HLhcyg==, - } + resolution: {integrity: sha512-3MbSL37jEchWZz2p2mjntRZtPt837ij10ApxKfgmXCTuHWagYg7iA5bqPw6C8BMPfwidlvfPI/fxOc42HLhcyg==} '@types/request-ip@0.0.41': - resolution: - { - integrity: sha512-Qzz0PM2nSZej4lsLzzNfADIORZhhxO7PED0fXpg4FjXiHuJ/lMyUg+YFF5q8x9HPZH3Gl6N+NOM8QZjItNgGKg==, - } + resolution: {integrity: sha512-Qzz0PM2nSZej4lsLzzNfADIORZhhxO7PED0fXpg4FjXiHuJ/lMyUg+YFF5q8x9HPZH3Gl6N+NOM8QZjItNgGKg==} '@types/semver@7.7.1': - resolution: - { - integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==, - } + resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} '@types/send@1.2.1': - resolution: - { - integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==, - } + resolution: {integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==} '@types/serve-static@2.2.0': - resolution: - { - integrity: sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==, - } + resolution: {integrity: sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==} '@types/shelljs@0.8.17': - resolution: - { - integrity: sha512-IDksKYmQA2W9MkQjiyptbMmcQx+8+Ol6b7h6dPU5S05JyiQDSb/nZKnrMrZqGwgV6VkVdl6/SPCKPDlMRvqECg==, - } + resolution: {integrity: sha512-IDksKYmQA2W9MkQjiyptbMmcQx+8+Ol6b7h6dPU5S05JyiQDSb/nZKnrMrZqGwgV6VkVdl6/SPCKPDlMRvqECg==} '@types/smtp-server@3.5.12': - resolution: - { - integrity: sha512-IBemrqI6nzvbgwE41Lnd4v4Yf1Kc7F1UHjk1GFBLNhLcI/Zop1ggHQ8g7Y8QYc6jGVgzWQcsa0MBNcGnDY9UGw==, - } + resolution: {integrity: sha512-IBemrqI6nzvbgwE41Lnd4v4Yf1Kc7F1UHjk1GFBLNhLcI/Zop1ggHQ8g7Y8QYc6jGVgzWQcsa0MBNcGnDY9UGw==} '@types/stack-utils@2.0.3': - resolution: - { - integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==, - } + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} '@types/superagent@8.1.9': - resolution: - { - integrity: sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==, - } + resolution: {integrity: sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==} '@types/supertest@6.0.3': - resolution: - { - integrity: sha512-8WzXq62EXFhJ7QsH3Ocb/iKQ/Ty9ZVWnVzoTKc9tyyFRRF3a74Tk2+TLFgaFFw364Ere+npzHKEJ6ga2LzIL7w==, - } + resolution: {integrity: sha512-8WzXq62EXFhJ7QsH3Ocb/iKQ/Ty9ZVWnVzoTKc9tyyFRRF3a74Tk2+TLFgaFFw364Ere+npzHKEJ6ga2LzIL7w==} '@types/testing-library__jest-dom@5.14.9': - resolution: - { - integrity: sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw==, - } + resolution: {integrity: sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw==} '@types/trusted-types@2.0.7': - resolution: - { - integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==, - } + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} '@types/yargs-parser@21.0.3': - resolution: - { - integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==, - } + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} '@types/yargs@15.0.20': - resolution: - { - integrity: sha512-KIkX+/GgfFitlASYCGoSF+T4XRXhOubJLhkLVtSfsRTe9jWMmuM2g28zQ41BtPTG7TRBb2xHW+LCNVE9QR/vsg==, - } + resolution: {integrity: sha512-KIkX+/GgfFitlASYCGoSF+T4XRXhOubJLhkLVtSfsRTe9jWMmuM2g28zQ41BtPTG7TRBb2xHW+LCNVE9QR/vsg==} '@types/yargs@17.0.35': - resolution: - { - integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==, - } + resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} '@typescript-eslint/eslint-plugin@8.53.1': - resolution: - { - integrity: sha512-cFYYFZ+oQFi6hUnBTbLRXfTJiaQtYE3t4O692agbBl+2Zy+eqSKWtPjhPXJu1G7j4RLjKgeJPDdq3EqOwmX5Ag==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-cFYYFZ+oQFi6hUnBTbLRXfTJiaQtYE3t4O692agbBl+2Zy+eqSKWtPjhPXJu1G7j4RLjKgeJPDdq3EqOwmX5Ag==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: '@typescript-eslint/parser': ^8.53.1 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' '@typescript-eslint/parser@8.53.1': - resolution: - { - integrity: sha512-nm3cvFN9SqZGXjmw5bZ6cGmvJSyJPn0wU9gHAZZHDnZl2wF9PhHv78Xf06E0MaNk4zLVHL8hb2/c32XvyJOLQg==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-nm3cvFN9SqZGXjmw5bZ6cGmvJSyJPn0wU9gHAZZHDnZl2wF9PhHv78Xf06E0MaNk4zLVHL8hb2/c32XvyJOLQg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' '@typescript-eslint/project-service@8.53.1': - resolution: - { - integrity: sha512-WYC4FB5Ra0xidsmlPb+1SsnaSKPmS3gsjIARwbEkHkoWloQmuzcfypljaJcR78uyLA1h8sHdWWPHSLDI+MtNog==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-WYC4FB5Ra0xidsmlPb+1SsnaSKPmS3gsjIARwbEkHkoWloQmuzcfypljaJcR78uyLA1h8sHdWWPHSLDI+MtNog==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' '@typescript-eslint/scope-manager@8.53.1': - resolution: - { - integrity: sha512-Lu23yw1uJMFY8cUeq7JlrizAgeQvWugNQzJp8C3x8Eo5Jw5Q2ykMdiiTB9vBVOOUBysMzmRRmUfwFrZuI2C4SQ==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-Lu23yw1uJMFY8cUeq7JlrizAgeQvWugNQzJp8C3x8Eo5Jw5Q2ykMdiiTB9vBVOOUBysMzmRRmUfwFrZuI2C4SQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@typescript-eslint/tsconfig-utils@8.53.1': - resolution: - { - integrity: sha512-qfvLXS6F6b1y43pnf0pPbXJ+YoXIC7HKg0UGZ27uMIemKMKA6XH2DTxsEDdpdN29D+vHV07x/pnlPNVLhdhWiA==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-qfvLXS6F6b1y43pnf0pPbXJ+YoXIC7HKg0UGZ27uMIemKMKA6XH2DTxsEDdpdN29D+vHV07x/pnlPNVLhdhWiA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' '@typescript-eslint/type-utils@8.53.1': - resolution: - { - integrity: sha512-MOrdtNvyhy0rHyv0ENzub1d4wQYKb2NmIqG7qEqPWFW7Mpy2jzFC3pQ2yKDvirZB7jypm5uGjF2Qqs6OIqu47w==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-MOrdtNvyhy0rHyv0ENzub1d4wQYKb2NmIqG7qEqPWFW7Mpy2jzFC3pQ2yKDvirZB7jypm5uGjF2Qqs6OIqu47w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' '@typescript-eslint/types@8.53.1': - resolution: - { - integrity: sha512-jr/swrr2aRmUAUjW5/zQHbMaui//vQlsZcJKijZf3M26bnmLj8LyZUpj8/Rd6uzaek06OWsqdofN/Thenm5O8A==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-jr/swrr2aRmUAUjW5/zQHbMaui//vQlsZcJKijZf3M26bnmLj8LyZUpj8/Rd6uzaek06OWsqdofN/Thenm5O8A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@typescript-eslint/typescript-estree@8.53.1': - resolution: - { - integrity: sha512-RGlVipGhQAG4GxV1s34O91cxQ/vWiHJTDHbXRr0li2q/BGg3RR/7NM8QDWgkEgrwQYCvmJV9ichIwyoKCQ+DTg==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-RGlVipGhQAG4GxV1s34O91cxQ/vWiHJTDHbXRr0li2q/BGg3RR/7NM8QDWgkEgrwQYCvmJV9ichIwyoKCQ+DTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' '@typescript-eslint/utils@8.53.1': - resolution: - { - integrity: sha512-c4bMvGVWW4hv6JmDUEG7fSYlWOl3II2I4ylt0NM+seinYQlZMQIaKaXIIVJWt9Ofh6whrpM+EdDQXKXjNovvrg==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-c4bMvGVWW4hv6JmDUEG7fSYlWOl3II2I4ylt0NM+seinYQlZMQIaKaXIIVJWt9Ofh6whrpM+EdDQXKXjNovvrg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' '@typescript-eslint/visitor-keys@8.53.1': - resolution: - { - integrity: sha512-oy+wV7xDKFPRyNggmXuZQSBzvoLnpmJs+GhzRhPjrxl2b/jIlyjVokzm47CZCDUdXKr2zd7ZLodPfOBpOPyPlg==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-oy+wV7xDKFPRyNggmXuZQSBzvoLnpmJs+GhzRhPjrxl2b/jIlyjVokzm47CZCDUdXKr2zd7ZLodPfOBpOPyPlg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@ungap/structured-clone@1.3.0': - resolution: - { - integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==, - } + resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} '@unrs/resolver-binding-android-arm-eabi@1.11.1': - resolution: - { - integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==, - } + resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==} cpu: [arm] os: [android] '@unrs/resolver-binding-android-arm64@1.11.1': - resolution: - { - integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==, - } + resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==} cpu: [arm64] os: [android] '@unrs/resolver-binding-darwin-arm64@1.11.1': - resolution: - { - integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==, - } + resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==} cpu: [arm64] os: [darwin] '@unrs/resolver-binding-darwin-x64@1.11.1': - resolution: - { - integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==, - } + resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==} cpu: [x64] os: [darwin] '@unrs/resolver-binding-freebsd-x64@1.11.1': - resolution: - { - integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==, - } + resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==} cpu: [x64] os: [freebsd] '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': - resolution: - { - integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==, - } + resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==} cpu: [arm] os: [linux] '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': - resolution: - { - integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==, - } + resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==} cpu: [arm] os: [linux] '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': - resolution: - { - integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==, - } + resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==} cpu: [arm64] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-arm64-musl@1.11.1': - resolution: - { - integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==, - } + resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==} cpu: [arm64] os: [linux] - libc: [musl] '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': - resolution: - { - integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==, - } + resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==} cpu: [ppc64] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': - resolution: - { - integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==, - } + resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==} cpu: [riscv64] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': - resolution: - { - integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==, - } + resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==} cpu: [riscv64] os: [linux] - libc: [musl] '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': - resolution: - { - integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==, - } + resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==} cpu: [s390x] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-x64-gnu@1.11.1': - resolution: - { - integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==, - } + resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==} cpu: [x64] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-x64-musl@1.11.1': - resolution: - { - integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==, - } + resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==} cpu: [x64] os: [linux] - libc: [musl] '@unrs/resolver-binding-wasm32-wasi@1.11.1': - resolution: - { - integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==, - } - engines: { node: '>=14.0.0' } + resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==} + engines: {node: '>=14.0.0'} cpu: [wasm32] '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': - resolution: - { - integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==, - } + resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==} cpu: [arm64] os: [win32] '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': - resolution: - { - integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==, - } + resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==} cpu: [ia32] os: [win32] '@unrs/resolver-binding-win32-x64-msvc@1.11.1': - resolution: - { - integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==, - } + resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==} cpu: [x64] os: [win32] '@vitejs/plugin-react@4.7.0': - resolution: - { - integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==, - } - engines: { node: ^14.18.0 || >=16.0.0 } + resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==} + engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 '@yarnpkg/lockfile@1.1.0': - resolution: - { - integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==, - } + resolution: {integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==} '@yarnpkg/parsers@3.0.2': - resolution: - { - integrity: sha512-/HcYgtUSiJiot/XWGLOlGxPYUG65+/31V8oqk17vZLW1xlCoR4PampyePljOxY2n8/3jz9+tIFzICsyGujJZoA==, - } - engines: { node: '>=18.12.0' } + resolution: {integrity: sha512-/HcYgtUSiJiot/XWGLOlGxPYUG65+/31V8oqk17vZLW1xlCoR4PampyePljOxY2n8/3jz9+tIFzICsyGujJZoA==} + engines: {node: '>=18.12.0'} '@zkochan/js-yaml@0.0.7': - resolution: - { - integrity: sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==, - } + resolution: {integrity: sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==} hasBin: true JSONStream@1.3.5: - resolution: - { - integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==, - } + resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} hasBin: true abbrev@2.0.0: - resolution: - { - integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} accepts@2.0.0: - resolution: - { - integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==, - } - engines: { node: '>= 0.6' } + resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} + engines: {node: '>= 0.6'} acorn-jsx@5.3.2: - resolution: - { - integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==, - } + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 acorn-walk@8.3.4: - resolution: - { - integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==, - } - engines: { node: '>=0.4.0' } + resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} + engines: {node: '>=0.4.0'} acorn@8.15.0: - resolution: - { - integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==, - } - engines: { node: '>=0.4.0' } + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} hasBin: true add-stream@1.0.0: - resolution: - { - integrity: sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==, - } + resolution: {integrity: sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==} agent-base@7.1.4: - resolution: - { - integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==, - } - engines: { node: '>= 14' } + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} aggregate-error@3.1.0: - resolution: - { - integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} ajv@6.12.6: - resolution: - { - integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==, - } + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} ajv@7.2.4: - resolution: - { - integrity: sha512-nBeQgg/ZZA3u3SYxyaDvpvDtgZ/EZPF547ARgZBrG9Bhu1vKDwAIjtIf+sDtJUKa2zOcEbmRLBRSyMraS/Oy1A==, - } + resolution: {integrity: sha512-nBeQgg/ZZA3u3SYxyaDvpvDtgZ/EZPF547ARgZBrG9Bhu1vKDwAIjtIf+sDtJUKa2zOcEbmRLBRSyMraS/Oy1A==} ajv@8.17.1: - resolution: - { - integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==, - } + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} ansi-colors@4.1.3: - resolution: - { - integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} ansi-escapes@4.3.2: - resolution: - { - integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} ansi-regex@5.0.1: - resolution: - { - integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} ansi-regex@6.2.2: - resolution: - { - integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} ansi-styles@4.3.0: - resolution: - { - integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} ansi-styles@5.2.0: - resolution: - { - integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} ansi-styles@6.2.3: - resolution: - { - integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} anymatch@3.1.3: - resolution: - { - integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==, - } - engines: { node: '>= 8' } + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} appstash@0.3.0: - resolution: - { - integrity: sha512-F4rMrok4wQYDVitYMWbPQh2MBoKCj7GYzmI/Gw8zDeO2vDLmCmyzmbd0zAwplghB6X3VMGQw/NKcngIc8w6oTA==, - } + resolution: {integrity: sha512-F4rMrok4wQYDVitYMWbPQh2MBoKCj7GYzmI/Gw8zDeO2vDLmCmyzmbd0zAwplghB6X3VMGQw/NKcngIc8w6oTA==} appstash@0.3.1: - resolution: - { - integrity: sha512-6blvfn9slJQeA7oavIeJ8Wbj5/KCRKkWRsmL54+sgY/ZDPTZndRGTFGOpdARHx0MZzRRQSUPrt1pUaOXXy350A==, - } + resolution: {integrity: sha512-6blvfn9slJQeA7oavIeJ8Wbj5/KCRKkWRsmL54+sgY/ZDPTZndRGTFGOpdARHx0MZzRRQSUPrt1pUaOXXy350A==} aproba@2.0.0: - resolution: - { - integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==, - } + resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} arg@4.1.3: - resolution: - { - integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==, - } + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} argparse@1.0.10: - resolution: - { - integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==, - } + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} argparse@2.0.1: - resolution: - { - integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==, - } + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} aria-hidden@1.2.6: - resolution: - { - integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} + engines: {node: '>=10'} aria-query@4.2.2: - resolution: - { - integrity: sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==, - } - engines: { node: '>=6.0' } + resolution: {integrity: sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==} + engines: {node: '>=6.0'} array-differ@3.0.0: - resolution: - { - integrity: sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==} + engines: {node: '>=8'} array-ify@1.0.0: - resolution: - { - integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==, - } + resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} array-union@2.1.0: - resolution: - { - integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} arrify@1.0.1: - resolution: - { - integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} + engines: {node: '>=0.10.0'} arrify@2.0.1: - resolution: - { - integrity: sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==} + engines: {node: '>=8'} asap@2.0.6: - resolution: - { - integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==, - } + resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} async-retry@1.3.1: - resolution: - { - integrity: sha512-aiieFW/7h3hY0Bq5d+ktDBejxuwR78vRu9hDUdR8rNhSaQ29VzPL4AoIRG7D/c7tdenwOcKvgPM6tIxB3cB6HA==, - } + resolution: {integrity: sha512-aiieFW/7h3hY0Bq5d+ktDBejxuwR78vRu9hDUdR8rNhSaQ29VzPL4AoIRG7D/c7tdenwOcKvgPM6tIxB3cB6HA==} async@3.2.6: - resolution: - { - integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==, - } + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} asynckit@0.4.0: - resolution: - { - integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==, - } + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} atob@2.1.2: - resolution: - { - integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==, - } - engines: { node: '>= 4.5.0' } + resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} + engines: {node: '>= 4.5.0'} hasBin: true axios@1.13.2: - resolution: - { - integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==, - } + resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} babel-jest@30.2.0: - resolution: - { - integrity: sha512-0YiBEOxWqKkSQWL9nNGGEgndoeL0ZpWrbLMNL5u/Kaxrli3Eaxlt3ZtIDktEvXt4L/R9r3ODr2zKwGM/2BjxVw==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-0YiBEOxWqKkSQWL9nNGGEgndoeL0ZpWrbLMNL5u/Kaxrli3Eaxlt3ZtIDktEvXt4L/R9r3ODr2zKwGM/2BjxVw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} peerDependencies: '@babel/core': ^7.11.0 || ^8.0.0-0 babel-plugin-istanbul@7.0.1: - resolution: - { - integrity: sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==} + engines: {node: '>=12'} babel-plugin-jest-hoist@30.2.0: - resolution: - { - integrity: sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} babel-plugin-styled-components@2.1.4: - resolution: - { - integrity: sha512-Xgp9g+A/cG47sUyRwwYxGM4bR/jDRg5N6it/8+HxCnbT5XNKSKDT9xm4oag/osgqjC2It/vH0yXsomOG6k558g==, - } + resolution: {integrity: sha512-Xgp9g+A/cG47sUyRwwYxGM4bR/jDRg5N6it/8+HxCnbT5XNKSKDT9xm4oag/osgqjC2It/vH0yXsomOG6k558g==} peerDependencies: styled-components: '>= 2' babel-preset-current-node-syntax@1.2.0: - resolution: - { - integrity: sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==, - } + resolution: {integrity: sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==} peerDependencies: '@babel/core': ^7.0.0 || ^8.0.0-0 babel-preset-jest@30.2.0: - resolution: - { - integrity: sha512-US4Z3NOieAQumwFnYdUWKvUKh8+YSnS/gB3t6YBiz0bskpu7Pine8pPCheNxlPEW4wnUkma2a94YuW2q3guvCQ==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-US4Z3NOieAQumwFnYdUWKvUKh8+YSnS/gB3t6YBiz0bskpu7Pine8pPCheNxlPEW4wnUkma2a94YuW2q3guvCQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} peerDependencies: '@babel/core': ^7.11.0 || ^8.0.0-beta.1 babel-runtime@6.25.0: - resolution: - { - integrity: sha512-zeCYxDePWYAT/DfmQWIHsMSFW2vv45UIwIAMjGvQVsTd47RwsiRH0uK1yzyWZ7LDBKdhnGDPM6NYEO5CZyhPrg==, - } + resolution: {integrity: sha512-zeCYxDePWYAT/DfmQWIHsMSFW2vv45UIwIAMjGvQVsTd47RwsiRH0uK1yzyWZ7LDBKdhnGDPM6NYEO5CZyhPrg==} balanced-match@1.0.2: - resolution: - { - integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==, - } + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} base-64@1.0.0: - resolution: - { - integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==, - } + resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==} base32.js@0.1.0: - resolution: - { - integrity: sha512-n3TkB02ixgBOhTvANakDb4xaMXnYUVkNoRFJjQflcqMQhyEKxEHdj3E6N8t8sUQ0mjH/3/JxzlXuz3ul/J90pQ==, - } - engines: { node: '>=0.12.0' } + resolution: {integrity: sha512-n3TkB02ixgBOhTvANakDb4xaMXnYUVkNoRFJjQflcqMQhyEKxEHdj3E6N8t8sUQ0mjH/3/JxzlXuz3ul/J90pQ==} + engines: {node: '>=0.12.0'} base64-js@1.5.1: - resolution: - { - integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==, - } + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} baseline-browser-mapping@2.9.15: - resolution: - { - integrity: sha512-kX8h7K2srmDyYnXRIppo4AH/wYgzWVCs+eKr3RusRSQ5PvRYoEFmR/I0PbdTjKFAoKqp5+kbxnNTFO9jOfSVJg==, - } + resolution: {integrity: sha512-kX8h7K2srmDyYnXRIppo4AH/wYgzWVCs+eKr3RusRSQ5PvRYoEFmR/I0PbdTjKFAoKqp5+kbxnNTFO9jOfSVJg==} hasBin: true before-after-hook@2.2.3: - resolution: - { - integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==, - } + resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==} big-integer@1.6.52: - resolution: - { - integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==, - } - engines: { node: '>=0.6' } + resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} + engines: {node: '>=0.6'} bin-links@4.0.4: - resolution: - { - integrity: sha512-cMtq4W5ZsEwcutJrVId+a/tjt8GSbS+h0oNkdl6+6rBuEv8Ot33Bevj5KPm40t309zuhVic8NjpuL42QCiJWWA==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-cMtq4W5ZsEwcutJrVId+a/tjt8GSbS+h0oNkdl6+6rBuEv8Ot33Bevj5KPm40t309zuhVic8NjpuL42QCiJWWA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} binary-extensions@2.3.0: - resolution: - { - integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} bl@4.1.0: - resolution: - { - integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==, - } + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} body-parser@2.2.1: - resolution: - { - integrity: sha512-nfDwkulwiZYQIGwxdy0RUmowMhKcFVcYXUU7m4QlKYim1rUtg83xm2yjZ40QjDuc291AJjjeSc9b++AWHSgSHw==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-nfDwkulwiZYQIGwxdy0RUmowMhKcFVcYXUU7m4QlKYim1rUtg83xm2yjZ40QjDuc291AJjjeSc9b++AWHSgSHw==} + engines: {node: '>=18'} boolbase@1.0.0: - resolution: - { - integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==, - } + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} bowser@2.13.1: - resolution: - { - integrity: sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw==, - } + resolution: {integrity: sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw==} brace-expansion@1.1.12: - resolution: - { - integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==, - } + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} brace-expansion@2.0.2: - resolution: - { - integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==, - } + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} braces@3.0.3: - resolution: - { - integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} broadcast-channel@3.7.0: - resolution: - { - integrity: sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==, - } + resolution: {integrity: sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==} browserslist@4.28.1: - resolution: - { - integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==, - } - engines: { node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7 } + resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true bs-logger@0.2.6: - resolution: - { - integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==, - } - engines: { node: '>= 6' } + resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} + engines: {node: '>= 6'} bser@2.1.1: - resolution: - { - integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==, - } + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} buffer-equal-constant-time@1.0.1: - resolution: - { - integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==, - } + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} buffer-from@1.1.2: - resolution: - { - integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==, - } + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} buffer@5.6.0: - resolution: - { - integrity: sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==, - } + resolution: {integrity: sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==} buffer@5.7.1: - resolution: - { - integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==, - } + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} busboy@0.3.1: - resolution: - { - integrity: sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw==, - } - engines: { node: '>=4.5.0' } + resolution: {integrity: sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw==} + engines: {node: '>=4.5.0'} byte-size@8.1.1: - resolution: - { - integrity: sha512-tUkzZWK0M/qdoLEqikxBWe4kumyuwjl3HO6zHTr4yEI23EojPtLYXdG1+AQY7MN0cGyNDvEaJ8wiYQm6P2bPxg==, - } - engines: { node: '>=12.17' } + resolution: {integrity: sha512-tUkzZWK0M/qdoLEqikxBWe4kumyuwjl3HO6zHTr4yEI23EojPtLYXdG1+AQY7MN0cGyNDvEaJ8wiYQm6P2bPxg==} + engines: {node: '>=12.17'} bytes@3.1.2: - resolution: - { - integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==, - } - engines: { node: '>= 0.8' } + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} cacache@18.0.4: - resolution: - { - integrity: sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==} + engines: {node: ^16.14.0 || >=18.0.0} call-bind-apply-helpers@1.0.2: - resolution: - { - integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} call-bound@1.0.4: - resolution: - { - integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} callsites@3.1.0: - resolution: - { - integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} camel-case@3.0.0: - resolution: - { - integrity: sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==, - } + resolution: {integrity: sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==} camelcase-keys@6.2.2: - resolution: - { - integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} + engines: {node: '>=8'} camelcase@5.3.1: - resolution: - { - integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} camelcase@6.3.0: - resolution: - { - integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} camelize@1.0.1: - resolution: - { - integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==, - } + resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} caniuse-lite@1.0.30001765: - resolution: - { - integrity: sha512-LWcNtSyZrakjECqmpP4qdg0MMGdN368D7X8XvvAqOcqMv0RxnlqVKZl2V6/mBR68oYMxOZPLw/gO7DuisMHUvQ==, - } + resolution: {integrity: sha512-LWcNtSyZrakjECqmpP4qdg0MMGdN368D7X8XvvAqOcqMv0RxnlqVKZl2V6/mBR68oYMxOZPLw/gO7DuisMHUvQ==} case@1.6.3: - resolution: - { - integrity: sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==, - } - engines: { node: '>= 0.8.0' } + resolution: {integrity: sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==} + engines: {node: '>= 0.8.0'} chalk@3.0.0: - resolution: - { - integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} + engines: {node: '>=8'} chalk@4.1.0: - resolution: - { - integrity: sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==} + engines: {node: '>=10'} chalk@4.1.2: - resolution: - { - integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} char-regex@1.0.2: - resolution: - { - integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} chardet@2.1.1: - resolution: - { - integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==, - } + resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} cheerio-select@2.1.0: - resolution: - { - integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==, - } + resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} cheerio@1.0.0-rc.3: - resolution: - { - integrity: sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==, - } - engines: { node: '>= 0.6' } + resolution: {integrity: sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==} + engines: {node: '>= 0.6'} cheerio@1.1.2: - resolution: - { - integrity: sha512-IkxPpb5rS/d1IiLbHMgfPuS0FgiWTtFIm/Nj+2woXDLTZ7fOT2eqzgYbdMlLweqlHbsZjxEChoVK+7iph7jyQg==, - } - engines: { node: '>=20.18.1' } + resolution: {integrity: sha512-IkxPpb5rS/d1IiLbHMgfPuS0FgiWTtFIm/Nj+2woXDLTZ7fOT2eqzgYbdMlLweqlHbsZjxEChoVK+7iph7jyQg==} + engines: {node: '>=20.18.1'} chevrotain-allstar@0.3.1: - resolution: - { - integrity: sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==, - } + resolution: {integrity: sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==} peerDependencies: chevrotain: ^11.0.0 chevrotain@11.0.3: - resolution: - { - integrity: sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==, - } + resolution: {integrity: sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==} chokidar@3.6.0: - resolution: - { - integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==, - } - engines: { node: '>= 8.10.0' } + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} chownr@2.0.0: - resolution: - { - integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} ci-info@3.9.0: - resolution: - { - integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} ci-info@4.3.1: - resolution: - { - integrity: sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==} + engines: {node: '>=8'} cjs-module-lexer@2.2.0: - resolution: - { - integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==, - } + resolution: {integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==} clean-ansi@0.2.0: - resolution: - { - integrity: sha512-AX26I7oo87AIA4OixLOARtjeNdX85aKGI+HPJ7wQEnXkoC3ytbwIuPu3d5+cmDoh2j1I2pQsQa/z3/FNAR8vOQ==, - } + resolution: {integrity: sha512-AX26I7oo87AIA4OixLOARtjeNdX85aKGI+HPJ7wQEnXkoC3ytbwIuPu3d5+cmDoh2j1I2pQsQa/z3/FNAR8vOQ==} clean-css@4.2.4: - resolution: - { - integrity: sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==, - } - engines: { node: '>= 4.0' } + resolution: {integrity: sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==} + engines: {node: '>= 4.0'} clean-stack@2.2.0: - resolution: - { - integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} cli-cursor@3.1.0: - resolution: - { - integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} cli-spinners@2.6.1: - resolution: - { - integrity: sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==} + engines: {node: '>=6'} cli-spinners@2.9.2: - resolution: - { - integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} cli-width@3.0.0: - resolution: - { - integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==, - } - engines: { node: '>= 10' } + resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} + engines: {node: '>= 10'} cliui@6.0.0: - resolution: - { - integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==, - } + resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} cliui@7.0.4: - resolution: - { - integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==, - } + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} cliui@8.0.1: - resolution: - { - integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} clone-deep@4.0.1: - resolution: - { - integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} + engines: {node: '>=6'} clone@1.0.4: - resolution: - { - integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==, - } - engines: { node: '>=0.8' } + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} clsx@1.2.1: - resolution: - { - integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} + engines: {node: '>=6'} clsx@2.1.1: - resolution: - { - integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} cmd-shim@6.0.3: - resolution: - { - integrity: sha512-FMabTRlc5t5zjdenF6mS0MBeFZm0XqHqeOkcskKFb/LYCcRQ5fVgLOHVc4Lq9CqABd9zhjwPjMBCJvMCziSVtA==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-FMabTRlc5t5zjdenF6mS0MBeFZm0XqHqeOkcskKFb/LYCcRQ5fVgLOHVc4Lq9CqABd9zhjwPjMBCJvMCziSVtA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} co@4.6.0: - resolution: - { - integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==, - } - engines: { iojs: '>= 1.0.0', node: '>= 0.12.0' } + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} collect-v8-coverage@1.0.3: - resolution: - { - integrity: sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==, - } + resolution: {integrity: sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==} color-convert@2.0.1: - resolution: - { - integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==, - } - engines: { node: '>=7.0.0' } + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} color-name@1.1.4: - resolution: - { - integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==, - } + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} color-support@1.1.3: - resolution: - { - integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==, - } + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} hasBin: true columnify@1.6.0: - resolution: - { - integrity: sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==, - } - engines: { node: '>=8.0.0' } + resolution: {integrity: sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==} + engines: {node: '>=8.0.0'} combined-stream@1.0.8: - resolution: - { - integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==, - } - engines: { node: '>= 0.8' } + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} commander@10.0.1: - resolution: - { - integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==, - } - engines: { node: '>=14' } + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} commander@2.17.1: - resolution: - { - integrity: sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==, - } + resolution: {integrity: sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==} commander@2.19.0: - resolution: - { - integrity: sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==, - } + resolution: {integrity: sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==} commander@5.1.0: - resolution: - { - integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==, - } - engines: { node: '>= 6' } + resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==} + engines: {node: '>= 6'} commander@7.2.0: - resolution: - { - integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==, - } - engines: { node: '>= 10' } + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} commander@8.3.0: - resolution: - { - integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==, - } - engines: { node: '>= 12' } + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} common-ancestor-path@1.0.1: - resolution: - { - integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==, - } + resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==} compare-func@2.0.0: - resolution: - { - integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==, - } + resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} component-emitter@1.3.1: - resolution: - { - integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==, - } + resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} concat-map@0.0.1: - resolution: - { - integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==, - } + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} concat-stream@2.0.0: - resolution: - { - integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==, - } - engines: { '0': node >= 6.0 } + resolution: {integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==} + engines: {'0': node >= 6.0} confbox@0.1.8: - resolution: - { - integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==, - } + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} config-chain@1.1.13: - resolution: - { - integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==, - } + resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} console-control-strings@1.1.0: - resolution: - { - integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==, - } + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} content-disposition@1.0.1: - resolution: - { - integrity: sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==} + engines: {node: '>=18'} content-type@1.0.5: - resolution: - { - integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==, - } - engines: { node: '>= 0.6' } + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} conventional-changelog-angular@7.0.0: - resolution: - { - integrity: sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==, - } - engines: { node: '>=16' } + resolution: {integrity: sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==} + engines: {node: '>=16'} conventional-changelog-core@5.0.1: - resolution: - { - integrity: sha512-Rvi5pH+LvgsqGwZPZ3Cq/tz4ty7mjijhr3qR4m9IBXNbxGGYgTVVO+duXzz9aArmHxFtwZ+LRkrNIMDQzgoY4A==, - } - engines: { node: '>=14' } + resolution: {integrity: sha512-Rvi5pH+LvgsqGwZPZ3Cq/tz4ty7mjijhr3qR4m9IBXNbxGGYgTVVO+duXzz9aArmHxFtwZ+LRkrNIMDQzgoY4A==} + engines: {node: '>=14'} conventional-changelog-preset-loader@3.0.0: - resolution: - { - integrity: sha512-qy9XbdSLmVnwnvzEisjxdDiLA4OmV3o8db+Zdg4WiFw14fP3B6XNz98X0swPPpkTd/pc1K7+adKgEDM1JCUMiA==, - } - engines: { node: '>=14' } + resolution: {integrity: sha512-qy9XbdSLmVnwnvzEisjxdDiLA4OmV3o8db+Zdg4WiFw14fP3B6XNz98X0swPPpkTd/pc1K7+adKgEDM1JCUMiA==} + engines: {node: '>=14'} conventional-changelog-writer@6.0.1: - resolution: - { - integrity: sha512-359t9aHorPw+U+nHzUXHS5ZnPBOizRxfQsWT5ZDHBfvfxQOAik+yfuhKXG66CN5LEWPpMNnIMHUTCKeYNprvHQ==, - } - engines: { node: '>=14' } + resolution: {integrity: sha512-359t9aHorPw+U+nHzUXHS5ZnPBOizRxfQsWT5ZDHBfvfxQOAik+yfuhKXG66CN5LEWPpMNnIMHUTCKeYNprvHQ==} + engines: {node: '>=14'} hasBin: true conventional-commits-filter@3.0.0: - resolution: - { - integrity: sha512-1ymej8b5LouPx9Ox0Dw/qAO2dVdfpRFq28e5Y0jJEU8ZrLdy0vOSkkIInwmxErFGhg6SALro60ZrwYFVTUDo4Q==, - } - engines: { node: '>=14' } + resolution: {integrity: sha512-1ymej8b5LouPx9Ox0Dw/qAO2dVdfpRFq28e5Y0jJEU8ZrLdy0vOSkkIInwmxErFGhg6SALro60ZrwYFVTUDo4Q==} + engines: {node: '>=14'} conventional-commits-parser@4.0.0: - resolution: - { - integrity: sha512-WRv5j1FsVM5FISJkoYMR6tPk07fkKT0UodruX4je86V4owk451yjXAKzKAPOs9l7y59E2viHUS9eQ+dfUA9NSg==, - } - engines: { node: '>=14' } + resolution: {integrity: sha512-WRv5j1FsVM5FISJkoYMR6tPk07fkKT0UodruX4je86V4owk451yjXAKzKAPOs9l7y59E2viHUS9eQ+dfUA9NSg==} + engines: {node: '>=14'} hasBin: true conventional-recommended-bump@7.0.1: - resolution: - { - integrity: sha512-Ft79FF4SlOFvX4PkwFDRnaNiIVX7YbmqGU0RwccUaiGvgp3S0a8ipR2/Qxk31vclDNM+GSdJOVs2KrsUCjblVA==, - } - engines: { node: '>=14' } + resolution: {integrity: sha512-Ft79FF4SlOFvX4PkwFDRnaNiIVX7YbmqGU0RwccUaiGvgp3S0a8ipR2/Qxk31vclDNM+GSdJOVs2KrsUCjblVA==} + engines: {node: '>=14'} hasBin: true convert-source-map@2.0.0: - resolution: - { - integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==, - } + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} cookie-signature@1.2.2: - resolution: - { - integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==, - } - engines: { node: '>=6.6.0' } + resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} + engines: {node: '>=6.6.0'} cookie@0.7.2: - resolution: - { - integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==, - } - engines: { node: '>= 0.6' } + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} cookiejar@2.1.4: - resolution: - { - integrity: sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==, - } + resolution: {integrity: sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==} copyfiles@2.4.1: - resolution: - { - integrity: sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==, - } + resolution: {integrity: sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==} hasBin: true core-js-pure@3.47.0: - resolution: - { - integrity: sha512-BcxeDbzUrRnXGYIVAGFtcGQVNpFcUhVjr6W7F8XktvQW2iJP9e66GP6xdKotCRFlrxBvNIBrhwKteRXqMV86Nw==, - } + resolution: {integrity: sha512-BcxeDbzUrRnXGYIVAGFtcGQVNpFcUhVjr6W7F8XktvQW2iJP9e66GP6xdKotCRFlrxBvNIBrhwKteRXqMV86Nw==} core-js@2.6.12: - resolution: - { - integrity: sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==, - } + resolution: {integrity: sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==} deprecated: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js. core-util-is@1.0.3: - resolution: - { - integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==, - } + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} cors@2.8.5: - resolution: - { - integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==, - } - engines: { node: '>= 0.10' } + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} cose-base@1.0.3: - resolution: - { - integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==, - } + resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==} cose-base@2.2.0: - resolution: - { - integrity: sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==, - } + resolution: {integrity: sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==} cosmiconfig@9.0.0: - resolution: - { - integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==, - } - engines: { node: '>=14' } + resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + engines: {node: '>=14'} peerDependencies: typescript: '>=4.9.5' peerDependenciesMeta: @@ -8182,407 +5770,230 @@ packages: optional: true create-require@1.1.1: - resolution: - { - integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==, - } + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} cron-parser@4.9.0: - resolution: - { - integrity: sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==, - } - engines: { node: '>=12.0.0' } + resolution: {integrity: sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==} + engines: {node: '>=12.0.0'} cross-spawn@7.0.6: - resolution: - { - integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==, - } - engines: { node: '>= 8' } + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} css-color-keywords@1.0.0: - resolution: - { - integrity: sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==} + engines: {node: '>=4'} css-select@1.2.0: - resolution: - { - integrity: sha512-dUQOBoqdR7QwV90WysXPLXG5LO7nhYBgiWVfxF80DKPF8zx1t/pUd2FYy73emg3zrjtM6dzmYgbHKfV2rxiHQA==, - } + resolution: {integrity: sha512-dUQOBoqdR7QwV90WysXPLXG5LO7nhYBgiWVfxF80DKPF8zx1t/pUd2FYy73emg3zrjtM6dzmYgbHKfV2rxiHQA==} css-select@5.2.2: - resolution: - { - integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==, - } + resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} css-to-react-native@3.2.0: - resolution: - { - integrity: sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==, - } + resolution: {integrity: sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==} css-what@2.1.3: - resolution: - { - integrity: sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==, - } + resolution: {integrity: sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==} css-what@6.2.2: - resolution: - { - integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==, - } - engines: { node: '>= 6' } + resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} + engines: {node: '>= 6'} css.escape@1.5.1: - resolution: - { - integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==, - } + resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} css@3.0.0: - resolution: - { - integrity: sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==, - } + resolution: {integrity: sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==} cssesc@3.0.0: - resolution: - { - integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} hasBin: true csstype@3.2.3: - resolution: - { - integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==, - } + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} csv-parse@6.1.0: - resolution: - { - integrity: sha512-CEE+jwpgLn+MmtCpVcPtiCZpVtB6Z2OKPTr34pycYYoL7sxdOkXDdQ4lRiw6ioC0q6BLqhc6cKweCVvral8yhw==, - } + resolution: {integrity: sha512-CEE+jwpgLn+MmtCpVcPtiCZpVtB6Z2OKPTr34pycYYoL7sxdOkXDdQ4lRiw6ioC0q6BLqhc6cKweCVvral8yhw==} csv-parser@2.3.5: - resolution: - { - integrity: sha512-LCHolC4AlNwL+5EuD5LH2VVNKpD8QixZW2zzK1XmrVYUaslFY4c5BooERHOCIubG9iv/DAyFjs4x0HvWNZuyWg==, - } - engines: { node: '>= 8.16.0' } + resolution: {integrity: sha512-LCHolC4AlNwL+5EuD5LH2VVNKpD8QixZW2zzK1XmrVYUaslFY4c5BooERHOCIubG9iv/DAyFjs4x0HvWNZuyWg==} + engines: {node: '>= 8.16.0'} hasBin: true cytoscape-cose-bilkent@4.1.0: - resolution: - { - integrity: sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==, - } + resolution: {integrity: sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==} peerDependencies: cytoscape: ^3.2.0 cytoscape-fcose@2.2.0: - resolution: - { - integrity: sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==, - } + resolution: {integrity: sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==} peerDependencies: cytoscape: ^3.2.0 cytoscape@3.33.1: - resolution: - { - integrity: sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ==, - } - engines: { node: '>=0.10' } + resolution: {integrity: sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ==} + engines: {node: '>=0.10'} d3-array@2.12.1: - resolution: - { - integrity: sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==, - } + resolution: {integrity: sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==} d3-array@3.2.4: - resolution: - { - integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} + engines: {node: '>=12'} d3-axis@3.0.0: - resolution: - { - integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==} + engines: {node: '>=12'} d3-brush@3.0.0: - resolution: - { - integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==} + engines: {node: '>=12'} d3-chord@3.0.1: - resolution: - { - integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==} + engines: {node: '>=12'} d3-color@3.1.0: - resolution: - { - integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} + engines: {node: '>=12'} d3-contour@4.0.2: - resolution: - { - integrity: sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==} + engines: {node: '>=12'} d3-delaunay@6.0.4: - resolution: - { - integrity: sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==} + engines: {node: '>=12'} d3-dispatch@3.0.1: - resolution: - { - integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==} + engines: {node: '>=12'} d3-drag@3.0.0: - resolution: - { - integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==} + engines: {node: '>=12'} d3-dsv@3.0.1: - resolution: - { - integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==} + engines: {node: '>=12'} hasBin: true d3-ease@3.0.1: - resolution: - { - integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==} + engines: {node: '>=12'} d3-fetch@3.0.1: - resolution: - { - integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==} + engines: {node: '>=12'} d3-force@3.0.0: - resolution: - { - integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==} + engines: {node: '>=12'} d3-format@3.1.2: - resolution: - { - integrity: sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==} + engines: {node: '>=12'} d3-geo@3.1.1: - resolution: - { - integrity: sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==} + engines: {node: '>=12'} d3-hierarchy@3.1.2: - resolution: - { - integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==} + engines: {node: '>=12'} d3-interpolate@3.0.1: - resolution: - { - integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} + engines: {node: '>=12'} d3-path@1.0.9: - resolution: - { - integrity: sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==, - } + resolution: {integrity: sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==} d3-path@3.1.0: - resolution: - { - integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==} + engines: {node: '>=12'} d3-polygon@3.0.1: - resolution: - { - integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==} + engines: {node: '>=12'} d3-quadtree@3.0.1: - resolution: - { - integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==} + engines: {node: '>=12'} d3-random@3.0.1: - resolution: - { - integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==} + engines: {node: '>=12'} d3-sankey@0.12.3: - resolution: - { - integrity: sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==, - } + resolution: {integrity: sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==} d3-scale-chromatic@3.1.0: - resolution: - { - integrity: sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==} + engines: {node: '>=12'} d3-scale@4.0.2: - resolution: - { - integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==} + engines: {node: '>=12'} d3-selection@3.0.0: - resolution: - { - integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==} + engines: {node: '>=12'} d3-shape@1.3.7: - resolution: - { - integrity: sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==, - } + resolution: {integrity: sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==} d3-shape@3.2.0: - resolution: - { - integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==} + engines: {node: '>=12'} d3-time-format@4.1.0: - resolution: - { - integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==} + engines: {node: '>=12'} d3-time@3.1.0: - resolution: - { - integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==} + engines: {node: '>=12'} d3-timer@3.0.1: - resolution: - { - integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} + engines: {node: '>=12'} d3-transition@3.0.1: - resolution: - { - integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==} + engines: {node: '>=12'} peerDependencies: d3-selection: 2 - 3 d3-zoom@3.0.0: - resolution: - { - integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==} + engines: {node: '>=12'} d3@7.9.0: - resolution: - { - integrity: sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==} + engines: {node: '>=12'} dagre-d3-es@7.0.13: - resolution: - { - integrity: sha512-efEhnxpSuwpYOKRm/L5KbqoZmNNukHa/Flty4Wp62JRvgH2ojwVgPgdYyr4twpieZnyRDdIH7PY2mopX26+j2Q==, - } + resolution: {integrity: sha512-efEhnxpSuwpYOKRm/L5KbqoZmNNukHa/Flty4Wp62JRvgH2ojwVgPgdYyr4twpieZnyRDdIH7PY2mopX26+j2Q==} dargs@7.0.0: - resolution: - { - integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==} + engines: {node: '>=8'} dateformat@3.0.3: - resolution: - { - integrity: sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==, - } + resolution: {integrity: sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==} dayjs@1.11.19: - resolution: - { - integrity: sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==, - } + resolution: {integrity: sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==} debounce-promise@3.1.2: - resolution: - { - integrity: sha512-rZHcgBkbYavBeD9ej6sP56XfG53d51CD4dnaw989YX/nZ/ZJfgRx/9ePKmTNiUiyQvh4mtrMoS3OAWW+yoYtpg==, - } + resolution: {integrity: sha512-rZHcgBkbYavBeD9ej6sP56XfG53d51CD4dnaw989YX/nZ/ZJfgRx/9ePKmTNiUiyQvh4mtrMoS3OAWW+yoYtpg==} debug@4.4.3: - resolution: - { - integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==, - } - engines: { node: '>=6.0' } + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} peerDependencies: supports-color: '*' peerDependenciesMeta: @@ -8590,31 +6001,19 @@ packages: optional: true decamelize-keys@1.1.1: - resolution: - { - integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} + engines: {node: '>=0.10.0'} decamelize@1.2.0: - resolution: - { - integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} decode-uri-component@0.2.2: - resolution: - { - integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==, - } - engines: { node: '>=0.10' } + resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} + engines: {node: '>=0.10'} dedent@1.5.3: - resolution: - { - integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==, - } + resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} peerDependencies: babel-plugin-macros: ^3.1.0 peerDependenciesMeta: @@ -8622,10 +6021,7 @@ packages: optional: true dedent@1.7.1: - resolution: - { - integrity: sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==, - } + resolution: {integrity: sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==} peerDependencies: babel-plugin-macros: ^3.1.0 peerDependenciesMeta: @@ -8633,242 +6029,131 @@ packages: optional: true deep-is@0.1.4: - resolution: - { - integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==, - } + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} deepmerge@4.3.1: - resolution: - { - integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} defaults@1.0.4: - resolution: - { - integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==, - } + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} define-lazy-prop@2.0.0: - resolution: - { - integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} + engines: {node: '>=8'} delaunator@5.0.1: - resolution: - { - integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==, - } + resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==} delayed-stream@1.0.0: - resolution: - { - integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==, - } - engines: { node: '>=0.4.0' } + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} depd@1.1.2: - resolution: - { - integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==, - } - engines: { node: '>= 0.6' } + resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} + engines: {node: '>= 0.6'} depd@2.0.0: - resolution: - { - integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==, - } - engines: { node: '>= 0.8' } + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} deprecation@2.3.1: - resolution: - { - integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==, - } + resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} detect-indent@5.0.0: - resolution: - { - integrity: sha512-rlpvsxUtM0PQvy9iZe640/IWwWYyBsTApREbA1pHOpmOUIl9MkP/U4z7vTtg4Oaojvqhxt7sdufnT0EzGaR31g==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-rlpvsxUtM0PQvy9iZe640/IWwWYyBsTApREbA1pHOpmOUIl9MkP/U4z7vTtg4Oaojvqhxt7sdufnT0EzGaR31g==} + engines: {node: '>=4'} detect-newline@3.1.0: - resolution: - { - integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} detect-node-es@1.1.0: - resolution: - { - integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==, - } + resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} detect-node@2.1.0: - resolution: - { - integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==, - } + resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} dezalgo@1.0.4: - resolution: - { - integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==, - } + resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==} dicer@0.3.0: - resolution: - { - integrity: sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==, - } - engines: { node: '>=4.5.0' } + resolution: {integrity: sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==} + engines: {node: '>=4.5.0'} diff-sequences@29.6.3: - resolution: - { - integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==, - } - engines: { node: ^14.15.0 || ^16.10.0 || >=18.0.0 } + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} diff@4.0.2: - resolution: - { - integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==, - } - engines: { node: '>=0.3.1' } + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} dom-accessibility-api@0.5.16: - resolution: - { - integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==, - } + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} dom-serializer@0.1.1: - resolution: - { - integrity: sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==, - } + resolution: {integrity: sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==} dom-serializer@0.2.2: - resolution: - { - integrity: sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==, - } + resolution: {integrity: sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==} dom-serializer@1.4.1: - resolution: - { - integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==, - } + resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} dom-serializer@2.0.0: - resolution: - { - integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==, - } + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} domelementtype@1.3.1: - resolution: - { - integrity: sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==, - } + resolution: {integrity: sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==} domelementtype@2.3.0: - resolution: - { - integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==, - } + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} domhandler@2.4.2: - resolution: - { - integrity: sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==, - } + resolution: {integrity: sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==} domhandler@3.3.0: - resolution: - { - integrity: sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==, - } - engines: { node: '>= 4' } + resolution: {integrity: sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==} + engines: {node: '>= 4'} domhandler@4.3.1: - resolution: - { - integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==, - } - engines: { node: '>= 4' } + resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} + engines: {node: '>= 4'} domhandler@5.0.3: - resolution: - { - integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==, - } - engines: { node: '>= 4' } + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} dompurify@3.3.1: - resolution: - { - integrity: sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==, - } + resolution: {integrity: sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==} domutils@1.5.1: - resolution: - { - integrity: sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==, - } + resolution: {integrity: sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==} domutils@1.7.0: - resolution: - { - integrity: sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==, - } + resolution: {integrity: sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==} domutils@2.8.0: - resolution: - { - integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==, - } + resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} domutils@3.2.2: - resolution: - { - integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==, - } + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} dot-prop@5.3.0: - resolution: - { - integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} + engines: {node: '>=8'} dotenv-expand@11.0.7: - resolution: - { - integrity: sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==} + engines: {node: '>=12'} dotenv@16.4.7: - resolution: - { - integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} + engines: {node: '>=12'} drizzle-orm@0.45.1: - resolution: - { - integrity: sha512-Te0FOdKIistGNPMq2jscdqngBRfBpC8uMFVwqjf6gtTVJHIQ/dosgV/CLBU2N4ZJBsXL5savCba9b0YJskKdcA==, - } + resolution: {integrity: sha512-Te0FOdKIistGNPMq2jscdqngBRfBpC8uMFVwqjf6gtTVJHIQ/dosgV/CLBU2N4ZJBsXL5savCba9b0YJskKdcA==} peerDependencies: '@aws-sdk/client-rds-data': '>=3' '@cloudflare/workers-types': '>=4' @@ -8960,270 +6245,153 @@ packages: optional: true dunder-proto@1.0.1: - resolution: - { - integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} eastasianwidth@0.2.0: - resolution: - { - integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==, - } + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} ecdsa-sig-formatter@1.0.11: - resolution: - { - integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==, - } + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} editorconfig@1.0.4: - resolution: - { - integrity: sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==, - } - engines: { node: '>=14' } + resolution: {integrity: sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==} + engines: {node: '>=14'} hasBin: true ee-first@1.1.1: - resolution: - { - integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==, - } + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} ejs@3.1.10: - resolution: - { - integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} hasBin: true electron-to-chromium@1.5.267: - resolution: - { - integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==, - } + resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==} emittery@0.13.1: - resolution: - { - integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} + engines: {node: '>=12'} emoji-regex@8.0.0: - resolution: - { - integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==, - } + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} emoji-regex@9.2.2: - resolution: - { - integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==, - } + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} encodeurl@2.0.0: - resolution: - { - integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==, - } - engines: { node: '>= 0.8' } + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} encoding-sniffer@0.2.1: - resolution: - { - integrity: sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==, - } + resolution: {integrity: sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==} encoding@0.1.13: - resolution: - { - integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==, - } + resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} end-of-stream@1.4.5: - resolution: - { - integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==, - } + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} enquirer@2.3.6: - resolution: - { - integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==, - } - engines: { node: '>=8.6' } + resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} + engines: {node: '>=8.6'} entities@1.1.2: - resolution: - { - integrity: sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==, - } + resolution: {integrity: sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==} entities@2.2.0: - resolution: - { - integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==, - } + resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} entities@4.5.0: - resolution: - { - integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==, - } - engines: { node: '>=0.12' } + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} entities@6.0.1: - resolution: - { - integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==, - } - engines: { node: '>=0.12' } + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} env-paths@2.2.1: - resolution: - { - integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} envalid@8.1.1: - resolution: - { - integrity: sha512-vOUfHxAFFvkBjbVQbBfgnCO9d3GcNfMMTtVfgqSU2rQGMFEVqWy9GBuoSfHnwGu7EqR0/GeukQcL3KjFBaga9w==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-vOUfHxAFFvkBjbVQbBfgnCO9d3GcNfMMTtVfgqSU2rQGMFEVqWy9GBuoSfHnwGu7EqR0/GeukQcL3KjFBaga9w==} + engines: {node: '>=18'} envinfo@7.13.0: - resolution: - { - integrity: sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==} + engines: {node: '>=4'} hasBin: true err-code@2.0.3: - resolution: - { - integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==, - } + resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} error-ex@1.3.4: - resolution: - { - integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==, - } + resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} es-define-property@1.0.1: - resolution: - { - integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} es-errors@1.3.0: - resolution: - { - integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} es-object-atoms@1.1.1: - resolution: - { - integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} es-set-tostringtag@2.1.0: - resolution: - { - integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} esbuild@0.25.12: - resolution: - { - integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} + engines: {node: '>=18'} hasBin: true esbuild@0.27.2: - resolution: - { - integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} + engines: {node: '>=18'} hasBin: true escalade@3.2.0: - resolution: - { - integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} escape-goat@3.0.0: - resolution: - { - integrity: sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw==} + engines: {node: '>=10'} escape-html@1.0.3: - resolution: - { - integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==, - } + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} escape-string-regexp@1.0.5: - resolution: - { - integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==, - } - engines: { node: '>=0.8.0' } + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} escape-string-regexp@2.0.0: - resolution: - { - integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} escape-string-regexp@4.0.0: - resolution: - { - integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} eslint-config-prettier@10.1.8: - resolution: - { - integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==, - } + resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==} hasBin: true peerDependencies: eslint: '>=7.0.0' eslint-plugin-simple-import-sort@12.1.1: - resolution: - { - integrity: sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA==, - } + resolution: {integrity: sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA==} peerDependencies: eslint: '>=5.0.0' eslint-plugin-unused-imports@4.3.0: - resolution: - { - integrity: sha512-ZFBmXMGBYfHttdRtOG9nFFpmUvMtbHSjsKrS20vdWdbfiVYsO3yA2SGYy9i9XmZJDfMGBflZGBCm70SEnFQtOA==, - } + resolution: {integrity: sha512-ZFBmXMGBYfHttdRtOG9nFFpmUvMtbHSjsKrS20vdWdbfiVYsO3yA2SGYy9i9XmZJDfMGBflZGBCm70SEnFQtOA==} peerDependencies: '@typescript-eslint/eslint-plugin': ^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0 eslint: ^9.0.0 || ^8.0.0 @@ -9232,32 +6400,20 @@ packages: optional: true eslint-scope@8.4.0: - resolution: - { - integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} eslint-visitor-keys@3.4.3: - resolution: - { - integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} eslint-visitor-keys@4.2.1: - resolution: - { - integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} eslint@9.39.2: - resolution: - { - integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: jiti: '*' @@ -9266,177 +6422,99 @@ packages: optional: true espree@10.4.0: - resolution: - { - integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} esprima@4.0.1: - resolution: - { - integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} hasBin: true esquery@1.6.0: - resolution: - { - integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==, - } - engines: { node: '>=0.10' } + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} esrecurse@4.3.0: - resolution: - { - integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==, - } - engines: { node: '>=4.0' } + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} estraverse@5.3.0: - resolution: - { - integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==, - } - engines: { node: '>=4.0' } + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} esutils@2.0.3: - resolution: - { - integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} etag@1.8.1: - resolution: - { - integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==, - } - engines: { node: '>= 0.6' } + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} eventemitter3@4.0.7: - resolution: - { - integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==, - } + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} eventemitter3@5.0.4: - resolution: - { - integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==, - } + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} events@3.3.0: - resolution: - { - integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==, - } - engines: { node: '>=0.8.x' } + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} execa@5.0.0: - resolution: - { - integrity: sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==} + engines: {node: '>=10'} execa@5.1.1: - resolution: - { - integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} exit-x@0.2.2: - resolution: - { - integrity: sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==, - } - engines: { node: '>= 0.8.0' } + resolution: {integrity: sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==} + engines: {node: '>= 0.8.0'} expect@30.2.0: - resolution: - { - integrity: sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} exponential-backoff@3.1.3: - resolution: - { - integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==, - } + resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==} express@5.2.1: - resolution: - { - integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==, - } - engines: { node: '>= 18' } + resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} + engines: {node: '>= 18'} fast-deep-equal@3.1.3: - resolution: - { - integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==, - } + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} fast-glob@3.3.3: - resolution: - { - integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==, - } - engines: { node: '>=8.6.0' } + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} fast-json-stable-stringify@2.1.0: - resolution: - { - integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==, - } + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} fast-levenshtein@2.0.6: - resolution: - { - integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==, - } + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} fast-safe-stringify@2.1.1: - resolution: - { - integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==, - } + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} fast-uri@3.1.0: - resolution: - { - integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==, - } + resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} fast-xml-parser@5.2.5: - resolution: - { - integrity: sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==, - } + resolution: {integrity: sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==} hasBin: true fastq@1.20.1: - resolution: - { - integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==, - } + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} fb-watchman@2.0.2: - resolution: - { - integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==, - } + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} fdir@6.5.0: - resolution: - { - integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==, - } - engines: { node: '>=12.0.0' } + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} peerDependencies: picomatch: ^3 || ^4 peerDependenciesMeta: @@ -9444,98 +6522,56 @@ packages: optional: true figures@3.2.0: - resolution: - { - integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} + engines: {node: '>=8'} file-entry-cache@8.0.0: - resolution: - { - integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==, - } - engines: { node: '>=16.0.0' } + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} filelist@1.0.4: - resolution: - { - integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==, - } + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} fill-range@7.1.1: - resolution: - { - integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} finalhandler@2.1.1: - resolution: - { - integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==, - } - engines: { node: '>= 18.0.0' } + resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} + engines: {node: '>= 18.0.0'} find-and-require-package-json@0.9.0: - resolution: - { - integrity: sha512-e7+fnRvphmWHHgOdVQct5yLEmw38GD3wpX8CMONT/qn/BLK6F0ft/iPicNKJMX6U4GlTEFzreYbLf+FlCYh4lQ==, - } + resolution: {integrity: sha512-e7+fnRvphmWHHgOdVQct5yLEmw38GD3wpX8CMONT/qn/BLK6F0ft/iPicNKJMX6U4GlTEFzreYbLf+FlCYh4lQ==} find-and-require-package-json@0.9.1: - resolution: - { - integrity: sha512-jFpCL0XgjipSk109viUtfp+NyR/oW6a4Xus4tV3UYkmCbsjisEeZD1x5QnD1NDDK/hXas1WFs4yO13L4TPXWlQ==, - } + resolution: {integrity: sha512-jFpCL0XgjipSk109viUtfp+NyR/oW6a4Xus4tV3UYkmCbsjisEeZD1x5QnD1NDDK/hXas1WFs4yO13L4TPXWlQ==} find-up@2.1.0: - resolution: - { - integrity: sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==} + engines: {node: '>=4'} find-up@4.1.0: - resolution: - { - integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} find-up@5.0.0: - resolution: - { - integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} flat-cache@4.0.1: - resolution: - { - integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==, - } - engines: { node: '>=16' } + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} flat@5.0.2: - resolution: - { - integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==, - } + resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} hasBin: true flatted@3.3.3: - resolution: - { - integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==, - } + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} follow-redirects@1.15.11: - resolution: - { - integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==, - } - engines: { node: '>=4.0' } + resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + engines: {node: '>=4.0'} peerDependencies: debug: '*' peerDependenciesMeta: @@ -9543,38 +6579,23 @@ packages: optional: true foreground-child@3.3.1: - resolution: - { - integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==, - } - engines: { node: '>=14' } + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} form-data@4.0.5: - resolution: - { - integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==, - } - engines: { node: '>= 6' } + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} formidable@3.5.4: - resolution: - { - integrity: sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==, - } - engines: { node: '>=14.0.0' } + resolution: {integrity: sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==} + engines: {node: '>=14.0.0'} forwarded@0.2.0: - resolution: - { - integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==, - } - engines: { node: '>= 0.6' } + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} framer-motion@12.34.0: - resolution: - { - integrity: sha512-+/H49owhzkzQyxtn7nZeF4kdH++I2FWrESQ184Zbcw5cEqNHYkE5yxWxcTLSj5lNx3NWdbIRy5FHqUvetD8FWg==, - } + resolution: {integrity: sha512-+/H49owhzkzQyxtn7nZeF4kdH++I2FWrESQ184Zbcw5cEqNHYkE5yxWxcTLSj5lNx3NWdbIRy5FHqUvetD8FWg==} peerDependencies: '@emotion/is-prop-valid': '*' react: ^18.0.0 || ^19.0.0 @@ -9588,297 +6609,171 @@ packages: optional: true fresh@2.0.0: - resolution: - { - integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==, - } - engines: { node: '>= 0.8' } + resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} + engines: {node: '>= 0.8'} front-matter@4.0.2: - resolution: - { - integrity: sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==, - } + resolution: {integrity: sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==} fs-capacitor@6.2.0: - resolution: - { - integrity: sha512-nKcE1UduoSKX27NSZlg879LdQc94OtbOsEmKMN2MBNudXREvijRKx2GEBsTMTfws+BrbkJoEuynbGSVRSpauvw==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-nKcE1UduoSKX27NSZlg879LdQc94OtbOsEmKMN2MBNudXREvijRKx2GEBsTMTfws+BrbkJoEuynbGSVRSpauvw==} + engines: {node: '>=10'} fs-capacitor@8.0.0: - resolution: - { - integrity: sha512-+Lk6iSKajdGw+7XYxUkwIzreJ2G1JFlYOdnKJv5PzwFLVsoJYBpCuS7WPIUSNT1IbQaEWT1nhYU63Ud03DyzLA==, - } - engines: { node: ^14.17.0 || >=16.0.0 } + resolution: {integrity: sha512-+Lk6iSKajdGw+7XYxUkwIzreJ2G1JFlYOdnKJv5PzwFLVsoJYBpCuS7WPIUSNT1IbQaEWT1nhYU63Ud03DyzLA==} + engines: {node: ^14.17.0 || >=16.0.0} fs-constants@1.0.0: - resolution: - { - integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==, - } + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} fs-extra@11.3.3: - resolution: - { - integrity: sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==, - } - engines: { node: '>=14.14' } + resolution: {integrity: sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==} + engines: {node: '>=14.14'} fs-minipass@2.1.0: - resolution: - { - integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==, - } - engines: { node: '>= 8' } + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} fs-minipass@3.0.3: - resolution: - { - integrity: sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} fs.realpath@1.0.0: - resolution: - { - integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==, - } + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} fsevents@2.3.2: - resolution: - { - integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==, - } - engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 } + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] fsevents@2.3.3: - resolution: - { - integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==, - } - engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 } + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] function-bind@1.1.2: - resolution: - { - integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==, - } + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} genomic@5.3.0: - resolution: - { - integrity: sha512-59rZ++BMgR4/rbh/j55n0BCYAZI/KrP9l7IgxdOHT+HEMAADA6kGaPOhDBltekw2QpHOAUeOXoRiTvntM7b1Ug==, - } + resolution: {integrity: sha512-59rZ++BMgR4/rbh/j55n0BCYAZI/KrP9l7IgxdOHT+HEMAADA6kGaPOhDBltekw2QpHOAUeOXoRiTvntM7b1Ug==} gensync@1.0.0-beta.2: - resolution: - { - integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} get-caller-file@2.0.5: - resolution: - { - integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==, - } - engines: { node: 6.* || 8.* || >= 10.* } + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} get-intrinsic@1.3.0: - resolution: - { - integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} get-nonce@1.0.1: - resolution: - { - integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} + engines: {node: '>=6'} get-package-type@0.1.0: - resolution: - { - integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==, - } - engines: { node: '>=8.0.0' } + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} get-pkg-repo@4.2.1: - resolution: - { - integrity: sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==} + engines: {node: '>=6.9.0'} hasBin: true get-port@5.1.1: - resolution: - { - integrity: sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==} + engines: {node: '>=8'} get-proto@1.0.1: - resolution: - { - integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} get-stream@6.0.0: - resolution: - { - integrity: sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==} + engines: {node: '>=10'} get-stream@6.0.1: - resolution: - { - integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} get-tsconfig@4.13.0: - resolution: - { - integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==, - } + resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} get-value@3.0.1: - resolution: - { - integrity: sha512-mKZj9JLQrwMBtj5wxi6MH8Z5eSKaERpAwjg43dPtlGI1ZVEgH/qC7T8/6R2OBSUA+zzHBZgICsVJaEIV2tKTDA==, - } - engines: { node: '>=6.0' } + resolution: {integrity: sha512-mKZj9JLQrwMBtj5wxi6MH8Z5eSKaERpAwjg43dPtlGI1ZVEgH/qC7T8/6R2OBSUA+zzHBZgICsVJaEIV2tKTDA==} + engines: {node: '>=6.0'} git-raw-commits@3.0.0: - resolution: - { - integrity: sha512-b5OHmZ3vAgGrDn/X0kS+9qCfNKWe4K/jFnhwzVWWg0/k5eLa3060tZShrRg8Dja5kPc+YjS0Gc6y7cRr44Lpjw==, - } - engines: { node: '>=14' } + resolution: {integrity: sha512-b5OHmZ3vAgGrDn/X0kS+9qCfNKWe4K/jFnhwzVWWg0/k5eLa3060tZShrRg8Dja5kPc+YjS0Gc6y7cRr44Lpjw==} + engines: {node: '>=14'} hasBin: true git-remote-origin-url@2.0.0: - resolution: - { - integrity: sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw==} + engines: {node: '>=4'} git-semver-tags@5.0.1: - resolution: - { - integrity: sha512-hIvOeZwRbQ+7YEUmCkHqo8FOLQZCEn18yevLHADlFPZY02KJGsu5FZt9YW/lybfK2uhWFI7Qg/07LekJiTv7iA==, - } - engines: { node: '>=14' } + resolution: {integrity: sha512-hIvOeZwRbQ+7YEUmCkHqo8FOLQZCEn18yevLHADlFPZY02KJGsu5FZt9YW/lybfK2uhWFI7Qg/07LekJiTv7iA==} + engines: {node: '>=14'} hasBin: true git-up@7.0.0: - resolution: - { - integrity: sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==, - } + resolution: {integrity: sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==} git-url-parse@14.0.0: - resolution: - { - integrity: sha512-NnLweV+2A4nCvn4U/m2AoYu0pPKlsmhK9cknG7IMwsjFY1S2jxM+mAhsDxyxfCIGfGaD+dozsyX4b6vkYc83yQ==, - } + resolution: {integrity: sha512-NnLweV+2A4nCvn4U/m2AoYu0pPKlsmhK9cknG7IMwsjFY1S2jxM+mAhsDxyxfCIGfGaD+dozsyX4b6vkYc83yQ==} gitconfiglocal@1.0.0: - resolution: - { - integrity: sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ==, - } + resolution: {integrity: sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ==} glob-parent@5.1.2: - resolution: - { - integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==, - } - engines: { node: '>= 6' } + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} glob-parent@6.0.2: - resolution: - { - integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==, - } - engines: { node: '>=10.13.0' } + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} glob@10.5.0: - resolution: - { - integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==, - } + resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true glob@11.1.0: - resolution: - { - integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==} + engines: {node: 20 || >=22} deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true glob@13.0.0: - resolution: - { - integrity: sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==} + engines: {node: 20 || >=22} glob@7.2.3: - resolution: - { - integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==, - } + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me glob@9.3.5: - resolution: - { - integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==, - } - engines: { node: '>=16 || 14 >=14.17' } + resolution: {integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==} + engines: {node: '>=16 || 14 >=14.17'} deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me globals@14.0.0: - resolution: - { - integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} gopd@1.2.0: - resolution: - { - integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} graceful-fs@4.2.11: - resolution: - { - integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==, - } + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} grafast@1.0.0-rc.4: - resolution: - { - integrity: sha512-AdgPytJbuBQajHWpMfY+GPnJkVEzSMfF1lQW0eUnqbK+uGVjJZr+MfXk0DAZUbdvN+ac97Mlh/31UbP9tsQfIw==, - } - engines: { node: '>=22' } + resolution: {integrity: sha512-AdgPytJbuBQajHWpMfY+GPnJkVEzSMfF1lQW0eUnqbK+uGVjJZr+MfXk0DAZUbdvN+ac97Mlh/31UbP9tsQfIw==} + engines: {node: '>=22'} peerDependencies: '@envelop/core': ^5.0.0 graphql: ^16.9.0 @@ -9887,11 +6782,8 @@ packages: optional: true grafserv@1.0.0-rc.4: - resolution: - { - integrity: sha512-DmSDh0h8at9uaHQdY88bAJb/uaX9LaVcBoy4BgVJfqJ/uOPv7aCis3B/nVFNtVu0kEnkGvdVapy3X4dIx8M1QA==, - } - engines: { node: '>=22' } + resolution: {integrity: sha512-DmSDh0h8at9uaHQdY88bAJb/uaX9LaVcBoy4BgVJfqJ/uOPv7aCis3B/nVFNtVu0kEnkGvdVapy3X4dIx8M1QA==} + engines: {node: '>=22'} peerDependencies: '@envelop/core': ^5.0.0 '@whatwg-node/server': ^0.9.64 @@ -9914,11 +6806,8 @@ packages: optional: true graphile-build-pg@5.0.0-rc.4: - resolution: - { - integrity: sha512-iTEboezhdSrL0eOmht/9Q3D1aw/krjoa4sGtXrWx3D/XYZVH0XOySFFRYp2MXmZ8qnrPw1XBB8f/XVHovXRoIg==, - } - engines: { node: '>=22' } + resolution: {integrity: sha512-iTEboezhdSrL0eOmht/9Q3D1aw/krjoa4sGtXrWx3D/XYZVH0XOySFFRYp2MXmZ8qnrPw1XBB8f/XVHovXRoIg==} + engines: {node: '>=22'} peerDependencies: '@dataplan/pg': ^1.0.0-rc.4 grafast: ^1.0.0-rc.5 @@ -9933,29 +6822,20 @@ packages: optional: true graphile-build@5.0.0-rc.4: - resolution: - { - integrity: sha512-LOzqlccyOuYIK/+3239+FChTfDdysJBg1dB0oJrf5mHzxrcMCPFaUau+usgRRPrOYmBp4R9SJM75SnIQQqStMQ==, - } - engines: { node: '>=22' } + resolution: {integrity: sha512-LOzqlccyOuYIK/+3239+FChTfDdysJBg1dB0oJrf5mHzxrcMCPFaUau+usgRRPrOYmBp4R9SJM75SnIQQqStMQ==} + engines: {node: '>=22'} peerDependencies: grafast: ^1.0.0-rc.5 graphile-config: ^1.0.0-rc.4 graphql: ^16.9.0 graphile-config@1.0.0-rc.3: - resolution: - { - integrity: sha512-NDjAJOxxj3BQW4jqPohPe/lr2vya1Ou4/yno3QfDYIw7OwoR0G13HFa6kvfjMLHJkDpOBDcjDqxN65SME/sLxg==, - } - engines: { node: '>=22' } + resolution: {integrity: sha512-NDjAJOxxj3BQW4jqPohPe/lr2vya1Ou4/yno3QfDYIw7OwoR0G13HFa6kvfjMLHJkDpOBDcjDqxN65SME/sLxg==} + engines: {node: '>=22'} graphile-utils@5.0.0-rc.5: - resolution: - { - integrity: sha512-oXPLOU7N7Rc6wJoixIHtant2LITVoVMgUcytT8cp/KgpYJ7KHabiCHW90rBqaq9fy2+XaemTHEjpb+r2/3FzUw==, - } - engines: { node: '>=22' } + resolution: {integrity: sha512-oXPLOU7N7Rc6wJoixIHtant2LITVoVMgUcytT8cp/KgpYJ7KHabiCHW90rBqaq9fy2+XaemTHEjpb+r2/3FzUw==} + engines: {node: '>=22'} peerDependencies: '@dataplan/pg': ^1.0.0-rc.4 grafast: ^1.0.0-rc.6 @@ -9969,66 +6849,45 @@ packages: optional: true graphiql-explorer@0.9.0: - resolution: - { - integrity: sha512-fZC/wsuatqiQDO2otchxriFO0LaWIo/ovF/CQJ1yOudmY0P7pzDiP+l9CEHUiWbizk3e99x6DQG4XG1VxA+d6A==, - } + resolution: {integrity: sha512-fZC/wsuatqiQDO2otchxriFO0LaWIo/ovF/CQJ1yOudmY0P7pzDiP+l9CEHUiWbizk3e99x6DQG4XG1VxA+d6A==} peerDependencies: graphql: ^0.6.0 || ^0.7.0 || ^0.8.0-b || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 react: ^15.6.0 || ^16.0.0 react-dom: ^15.6.0 || ^16.0.0 graphiql@5.2.2: - resolution: - { - integrity: sha512-qYhw7e2QPLPEIdJXqlLa/XkZtEu2SVYyD71abOpPnrzmJzTdB+QsEswFIMg9u1WGkEtp/wi8epCsuKeA/chRcg==, - } + resolution: {integrity: sha512-qYhw7e2QPLPEIdJXqlLa/XkZtEu2SVYyD71abOpPnrzmJzTdB+QsEswFIMg9u1WGkEtp/wi8epCsuKeA/chRcg==} peerDependencies: graphql: ^15.5.0 || ^16.0.0 || ^17.0.0 react: ^18 || ^19 react-dom: ^18 || ^19 graphql-language-service@5.5.0: - resolution: - { - integrity: sha512-9EvWrLLkF6Y5e29/2cmFoAO6hBPPAZlCyjznmpR11iFtRydfkss+9m6x+htA8h7YznGam+TtJwS6JuwoWWgb2Q==, - } + resolution: {integrity: sha512-9EvWrLLkF6Y5e29/2cmFoAO6hBPPAZlCyjznmpR11iFtRydfkss+9m6x+htA8h7YznGam+TtJwS6JuwoWWgb2Q==} hasBin: true peerDependencies: graphql: ^15.5.0 || ^16.0.0 || ^17.0.0 graphql-request@7.4.0: - resolution: - { - integrity: sha512-xfr+zFb/QYbs4l4ty0dltqiXIp07U6sl+tOKAb0t50/EnQek6CVVBLjETXi+FghElytvgaAWtIOt3EV7zLzIAQ==, - } + resolution: {integrity: sha512-xfr+zFb/QYbs4l4ty0dltqiXIp07U6sl+tOKAb0t50/EnQek6CVVBLjETXi+FghElytvgaAWtIOt3EV7zLzIAQ==} peerDependencies: graphql: 14 - 16 graphql-tag@2.12.6: - resolution: - { - integrity: sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==} + engines: {node: '>=10'} peerDependencies: graphql: ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 graphql-upload@13.0.0: - resolution: - { - integrity: sha512-YKhx8m/uOtKu4Y1UzBFJhbBGJTlk7k4CydlUUiNrtxnwZv0WigbRHP+DVhRNKt7u7DXOtcKZeYJlGtnMXvreXA==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >= 16.0.0 } + resolution: {integrity: sha512-YKhx8m/uOtKu4Y1UzBFJhbBGJTlk7k4CydlUUiNrtxnwZv0WigbRHP+DVhRNKt7u7DXOtcKZeYJlGtnMXvreXA==} + engines: {node: ^12.22.0 || ^14.17.0 || >= 16.0.0} peerDependencies: graphql: 0.13.1 - 16 graphql-ws@6.0.7: - resolution: - { - integrity: sha512-yoLRW+KRlDmnnROdAu7sX77VNLC0bsFoZyGQJLy1cF+X/SkLg/fWkRGrEEYQK8o2cafJ2wmEaMqMEZB3U3DYDg==, - } - engines: { node: '>=20' } + resolution: {integrity: sha512-yoLRW+KRlDmnnROdAu7sX77VNLC0bsFoZyGQJLy1cF+X/SkLg/fWkRGrEEYQK8o2cafJ2wmEaMqMEZB3U3DYDg==} + engines: {node: '>=20'} peerDependencies: '@fastify/websocket': ^10 || ^11 crossws: ~0.3 @@ -10043,661 +6902,370 @@ packages: optional: true graphql@15.10.1: - resolution: - { - integrity: sha512-BL/Xd/T9baO6NFzoMpiMD7YUZ62R6viR5tp/MULVEnbYJXZA//kRNW7J0j1w/wXArgL0sCxhDfK5dczSKn3+cg==, - } - engines: { node: '>= 10.x' } + resolution: {integrity: sha512-BL/Xd/T9baO6NFzoMpiMD7YUZ62R6viR5tp/MULVEnbYJXZA//kRNW7J0j1w/wXArgL0sCxhDfK5dczSKn3+cg==} + engines: {node: '>= 10.x'} graphql@16.12.0: - resolution: - { - integrity: sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==, - } - engines: { node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0 } + resolution: {integrity: sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==} + engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} hachure-fill@0.5.2: - resolution: - { - integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==, - } + resolution: {integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==} handlebars@4.7.8: - resolution: - { - integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==, - } - engines: { node: '>=0.4.7' } + resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} + engines: {node: '>=0.4.7'} hasBin: true hard-rejection@2.1.0: - resolution: - { - integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} + engines: {node: '>=6'} has-flag@3.0.0: - resolution: - { - integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} has-flag@4.0.0: - resolution: - { - integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} has-symbols@1.1.0: - resolution: - { - integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} has-tostringtag@1.0.2: - resolution: - { - integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} has-unicode@2.0.1: - resolution: - { - integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==, - } + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} hasown@2.0.2: - resolution: - { - integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} he@1.2.0: - resolution: - { - integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==, - } + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true hoist-non-react-statics@3.3.2: - resolution: - { - integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==, - } + resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} hosted-git-info@2.8.9: - resolution: - { - integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==, - } + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} hosted-git-info@4.1.0: - resolution: - { - integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} + engines: {node: '>=10'} hosted-git-info@7.0.2: - resolution: - { - integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} + engines: {node: ^16.14.0 || >=18.0.0} html-escaper@2.0.2: - resolution: - { - integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==, - } + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} html-minifier@3.5.21: - resolution: - { - integrity: sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==} + engines: {node: '>=4'} hasBin: true htmlparser2@10.0.0: - resolution: - { - integrity: sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==, - } + resolution: {integrity: sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==} htmlparser2@3.10.1: - resolution: - { - integrity: sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==, - } + resolution: {integrity: sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==} htmlparser2@4.1.0: - resolution: - { - integrity: sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==, - } + resolution: {integrity: sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==} http-cache-semantics@4.2.0: - resolution: - { - integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==, - } + resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==} http-errors@1.8.1: - resolution: - { - integrity: sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==, - } - engines: { node: '>= 0.6' } + resolution: {integrity: sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==} + engines: {node: '>= 0.6'} http-errors@2.0.1: - resolution: - { - integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==, - } - engines: { node: '>= 0.8' } + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} + engines: {node: '>= 0.8'} http-proxy-agent@7.0.2: - resolution: - { - integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==, - } - engines: { node: '>= 14' } + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} http-proxy@1.18.1: - resolution: - { - integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==, - } - engines: { node: '>=8.0.0' } + resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} + engines: {node: '>=8.0.0'} https-proxy-agent@7.0.6: - resolution: - { - integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==, - } - engines: { node: '>= 14' } + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} human-signals@2.1.0: - resolution: - { - integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==, - } - engines: { node: '>=10.17.0' } + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} iconv-lite@0.6.3: - resolution: - { - integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} iconv-lite@0.7.1: - resolution: - { - integrity: sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==} + engines: {node: '>=0.10.0'} ieee754@1.2.1: - resolution: - { - integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==, - } + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} ignore-by-default@1.0.1: - resolution: - { - integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==, - } + resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} ignore-walk@6.0.5: - resolution: - { - integrity: sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} ignore@5.3.2: - resolution: - { - integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==, - } - engines: { node: '>= 4' } + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} ignore@7.0.5: - resolution: - { - integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==, - } - engines: { node: '>= 4' } + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} import-fresh@3.3.1: - resolution: - { - integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} import-local@3.1.0: - resolution: - { - integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} + engines: {node: '>=8'} hasBin: true import-local@3.2.0: - resolution: - { - integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} + engines: {node: '>=8'} hasBin: true imurmurhash@0.1.4: - resolution: - { - integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==, - } - engines: { node: '>=0.8.19' } + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} indent-string@4.0.0: - resolution: - { - integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} inflection@3.0.2: - resolution: - { - integrity: sha512-+Bg3+kg+J6JUWn8J6bzFmOWkTQ6L/NHfDRSYU+EVvuKHDxUDHAXgqixHfVlzuBQaPOTac8hn43aPhMNk6rMe3g==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-+Bg3+kg+J6JUWn8J6bzFmOWkTQ6L/NHfDRSYU+EVvuKHDxUDHAXgqixHfVlzuBQaPOTac8hn43aPhMNk6rMe3g==} + engines: {node: '>=18.0.0'} inflekt@0.3.1: - resolution: - { - integrity: sha512-z5jvjelE61KiWinkjlainPDROpO3u0NqlUsCoSTxrSV7yNhcnaIb71ckx3utm8GZ2wifjqGFyaqyYomSXEgMfQ==, - } + resolution: {integrity: sha512-z5jvjelE61KiWinkjlainPDROpO3u0NqlUsCoSTxrSV7yNhcnaIb71ckx3utm8GZ2wifjqGFyaqyYomSXEgMfQ==} inflight@1.0.6: - resolution: - { - integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==, - } + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. inherits@2.0.4: - resolution: - { - integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==, - } + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} ini@1.3.8: - resolution: - { - integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==, - } + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} ini@4.1.3: - resolution: - { - integrity: sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} init-package-json@6.0.3: - resolution: - { - integrity: sha512-Zfeb5ol+H+eqJWHTaGca9BovufyGeIfr4zaaBorPmJBMrJ+KBnN+kQx2ZtXdsotUTgldHmHQV44xvUWOUA7E2w==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-Zfeb5ol+H+eqJWHTaGca9BovufyGeIfr4zaaBorPmJBMrJ+KBnN+kQx2ZtXdsotUTgldHmHQV44xvUWOUA7E2w==} + engines: {node: ^16.14.0 || >=18.0.0} inquirer@8.2.7: - resolution: - { - integrity: sha512-UjOaSel/iddGZJ5xP/Eixh6dY1XghiBw4XK13rCCIJcJfyhhoul/7KhLLUGtebEj6GDYM6Vnx/mVsjx2L/mFIA==, - } - engines: { node: '>=12.0.0' } + resolution: {integrity: sha512-UjOaSel/iddGZJ5xP/Eixh6dY1XghiBw4XK13rCCIJcJfyhhoul/7KhLLUGtebEj6GDYM6Vnx/mVsjx2L/mFIA==} + engines: {node: '>=12.0.0'} inquirerer@4.4.0: - resolution: - { - integrity: sha512-zra0M4Oh+rzgr7PMJy9cNi/LbkJbtB6QRABou65nN6NTwb368/lMJ8ACHXozM7bw3+t5SOI0TP3gxKAyT0BCRw==, - } + resolution: {integrity: sha512-zra0M4Oh+rzgr7PMJy9cNi/LbkJbtB6QRABou65nN6NTwb368/lMJ8ACHXozM7bw3+t5SOI0TP3gxKAyT0BCRw==} inquirerer@4.5.0: - resolution: - { - integrity: sha512-ULWscyMV6Y/OH1XRODvunrQH1EO4r7q+UV/boWFiVIt9h2UZ7wa/Qc+ZpAqUaWynKUhDtY3UqZV4MVrRcEkmNg==, - } + resolution: {integrity: sha512-ULWscyMV6Y/OH1XRODvunrQH1EO4r7q+UV/boWFiVIt9h2UZ7wa/Qc+ZpAqUaWynKUhDtY3UqZV4MVrRcEkmNg==} inquirerer@4.5.1: - resolution: - { - integrity: sha512-/Cis0BNeqdgcXJt3loHKt7PbfawPG7fLTQHr29IfpOHCRaLACmf5737PAHakVU1rBflCNNMo4lpdso6t4FHpjg==, - } + resolution: {integrity: sha512-/Cis0BNeqdgcXJt3loHKt7PbfawPG7fLTQHr29IfpOHCRaLACmf5737PAHakVU1rBflCNNMo4lpdso6t4FHpjg==} internmap@1.0.1: - resolution: - { - integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==, - } + resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==} internmap@2.0.3: - resolution: - { - integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} + engines: {node: '>=12'} interpret@3.1.1: - resolution: - { - integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==, - } - engines: { node: '>=10.13.0' } + resolution: {integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==} + engines: {node: '>=10.13.0'} ip-address@10.1.0: - resolution: - { - integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==, - } - engines: { node: '>= 12' } + resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} + engines: {node: '>= 12'} ipaddr.js@1.9.1: - resolution: - { - integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==, - } - engines: { node: '>= 0.10' } + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} ipv6-normalize@1.0.1: - resolution: - { - integrity: sha512-Bm6H79i01DjgGTCWjUuCjJ6QDo1HB96PT/xCYuyJUP9WFbVDrLSbG4EZCvOCun2rNswZb0c3e4Jt/ws795esHA==, - } + resolution: {integrity: sha512-Bm6H79i01DjgGTCWjUuCjJ6QDo1HB96PT/xCYuyJUP9WFbVDrLSbG4EZCvOCun2rNswZb0c3e4Jt/ws795esHA==} is-arrayish@0.2.1: - resolution: - { - integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==, - } + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} is-binary-path@2.1.0: - resolution: - { - integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} is-ci@3.0.1: - resolution: - { - integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==, - } + resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} hasBin: true is-core-module@2.16.1: - resolution: - { - integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} is-docker@2.2.1: - resolution: - { - integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} hasBin: true is-extglob@2.1.1: - resolution: - { - integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} is-fullwidth-code-point@3.0.0: - resolution: - { - integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} is-generator-fn@2.1.0: - resolution: - { - integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} is-glob@4.0.3: - resolution: - { - integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} is-interactive@1.0.0: - resolution: - { - integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} is-lambda@1.0.1: - resolution: - { - integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==, - } + resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} is-number@7.0.0: - resolution: - { - integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==, - } - engines: { node: '>=0.12.0' } + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} is-obj@2.0.0: - resolution: - { - integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} + engines: {node: '>=8'} is-plain-obj@1.1.0: - resolution: - { - integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} + engines: {node: '>=0.10.0'} is-plain-object@2.0.4: - resolution: - { - integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} is-primitive@3.0.1: - resolution: - { - integrity: sha512-GljRxhWvlCNRfZyORiH77FwdFwGcMO620o37EOYC0ORWdq+WYNVqW0w2Juzew4M+L81l6/QS3t5gkkihyRqv9w==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-GljRxhWvlCNRfZyORiH77FwdFwGcMO620o37EOYC0ORWdq+WYNVqW0w2Juzew4M+L81l6/QS3t5gkkihyRqv9w==} + engines: {node: '>=0.10.0'} is-promise@4.0.0: - resolution: - { - integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==, - } + resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} is-ssh@1.4.1: - resolution: - { - integrity: sha512-JNeu1wQsHjyHgn9NcWTaXq6zWSR6hqE0++zhfZlkFBbScNkyvxCdeV8sRkSBaeLKxmbpR21brail63ACNxJ0Tg==, - } + resolution: {integrity: sha512-JNeu1wQsHjyHgn9NcWTaXq6zWSR6hqE0++zhfZlkFBbScNkyvxCdeV8sRkSBaeLKxmbpR21brail63ACNxJ0Tg==} is-stream@2.0.0: - resolution: - { - integrity: sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==} + engines: {node: '>=8'} is-stream@2.0.1: - resolution: - { - integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} is-text-path@1.0.1: - resolution: - { - integrity: sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==} + engines: {node: '>=0.10.0'} is-unicode-supported@0.1.0: - resolution: - { - integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} is-wsl@2.2.0: - resolution: - { - integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} isarray@0.0.1: - resolution: - { - integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==, - } + resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} isarray@1.0.0: - resolution: - { - integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==, - } + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} isexe@2.0.0: - resolution: - { - integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==, - } + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} isexe@3.1.1: - resolution: - { - integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==, - } - engines: { node: '>=16' } + resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==} + engines: {node: '>=16'} isobject@3.0.1: - resolution: - { - integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} istanbul-lib-coverage@3.2.2: - resolution: - { - integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} istanbul-lib-instrument@6.0.3: - resolution: - { - integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} + engines: {node: '>=10'} istanbul-lib-report@3.0.1: - resolution: - { - integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} istanbul-lib-source-maps@5.0.6: - resolution: - { - integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} + engines: {node: '>=10'} istanbul-reports@3.2.0: - resolution: - { - integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} + engines: {node: '>=8'} iterall@1.3.0: - resolution: - { - integrity: sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==, - } + resolution: {integrity: sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==} jackspeak@3.4.3: - resolution: - { - integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==, - } + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} jackspeak@4.2.3: - resolution: - { - integrity: sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==} + engines: {node: 20 || >=22} jake@10.9.4: - resolution: - { - integrity: sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==} + engines: {node: '>=10'} hasBin: true jest-changed-files@30.2.0: - resolution: - { - integrity: sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-circus@30.2.0: - resolution: - { - integrity: sha512-Fh0096NC3ZkFx05EP2OXCxJAREVxj1BcW/i6EWqqymcgYKWjyyDpral3fMxVcHXg6oZM7iULer9wGRFvfpl+Tg==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-Fh0096NC3ZkFx05EP2OXCxJAREVxj1BcW/i6EWqqymcgYKWjyyDpral3fMxVcHXg6oZM7iULer9wGRFvfpl+Tg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-cli@30.2.0: - resolution: - { - integrity: sha512-Os9ukIvADX/A9sLt6Zse3+nmHtHaE6hqOsjQtNiugFTbKRHYIYtZXNGNK9NChseXy7djFPjndX1tL0sCTlfpAA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-Os9ukIvADX/A9sLt6Zse3+nmHtHaE6hqOsjQtNiugFTbKRHYIYtZXNGNK9NChseXy7djFPjndX1tL0sCTlfpAA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 @@ -10706,11 +7274,8 @@ packages: optional: true jest-config@30.2.0: - resolution: - { - integrity: sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} peerDependencies: '@types/node': '*' esbuild-register: '>=3.4.0' @@ -10724,95 +7289,56 @@ packages: optional: true jest-diff@29.7.0: - resolution: - { - integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==, - } - engines: { node: ^14.15.0 || ^16.10.0 || >=18.0.0 } + resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} jest-diff@30.2.0: - resolution: - { - integrity: sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-docblock@30.2.0: - resolution: - { - integrity: sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-each@30.2.0: - resolution: - { - integrity: sha512-lpWlJlM7bCUf1mfmuqTA8+j2lNURW9eNafOy99knBM01i5CQeY5UH1vZjgT9071nDJac1M4XsbyI44oNOdhlDQ==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-lpWlJlM7bCUf1mfmuqTA8+j2lNURW9eNafOy99knBM01i5CQeY5UH1vZjgT9071nDJac1M4XsbyI44oNOdhlDQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-environment-node@30.2.0: - resolution: - { - integrity: sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-get-type@29.6.3: - resolution: - { - integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==, - } - engines: { node: ^14.15.0 || ^16.10.0 || >=18.0.0 } + resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} jest-haste-map@30.2.0: - resolution: - { - integrity: sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-in-case@1.0.2: - resolution: - { - integrity: sha512-2DE6Gdwnh5jkCYTePWoQinF+zne3lCADibXoYJEt8PS84JaRug0CyAOrEgzMxbzln3YcSY2PBeru7ct4tbflYA==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-2DE6Gdwnh5jkCYTePWoQinF+zne3lCADibXoYJEt8PS84JaRug0CyAOrEgzMxbzln3YcSY2PBeru7ct4tbflYA==} + engines: {node: '>=4'} jest-leak-detector@30.2.0: - resolution: - { - integrity: sha512-M6jKAjyzjHG0SrQgwhgZGy9hFazcudwCNovY/9HPIicmNSBuockPSedAP9vlPK6ONFJ1zfyH/M2/YYJxOz5cdQ==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-M6jKAjyzjHG0SrQgwhgZGy9hFazcudwCNovY/9HPIicmNSBuockPSedAP9vlPK6ONFJ1zfyH/M2/YYJxOz5cdQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-matcher-utils@30.2.0: - resolution: - { - integrity: sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-message-util@30.2.0: - resolution: - { - integrity: sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-mock@30.2.0: - resolution: - { - integrity: sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-pnp-resolver@1.2.3: - resolution: - { - integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} peerDependencies: jest-resolve: '*' peerDependenciesMeta: @@ -10820,81 +7346,48 @@ packages: optional: true jest-regex-util@30.0.1: - resolution: - { - integrity: sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-resolve-dependencies@30.2.0: - resolution: - { - integrity: sha512-xTOIGug/0RmIe3mmCqCT95yO0vj6JURrn1TKWlNbhiAefJRWINNPgwVkrVgt/YaerPzY3iItufd80v3lOrFJ2w==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-xTOIGug/0RmIe3mmCqCT95yO0vj6JURrn1TKWlNbhiAefJRWINNPgwVkrVgt/YaerPzY3iItufd80v3lOrFJ2w==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-resolve@30.2.0: - resolution: - { - integrity: sha512-TCrHSxPlx3tBY3hWNtRQKbtgLhsXa1WmbJEqBlTBrGafd5fiQFByy2GNCEoGR+Tns8d15GaL9cxEzKOO3GEb2A==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-TCrHSxPlx3tBY3hWNtRQKbtgLhsXa1WmbJEqBlTBrGafd5fiQFByy2GNCEoGR+Tns8d15GaL9cxEzKOO3GEb2A==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-runner@30.2.0: - resolution: - { - integrity: sha512-PqvZ2B2XEyPEbclp+gV6KO/F1FIFSbIwewRgmROCMBo/aZ6J1w8Qypoj2pEOcg3G2HzLlaP6VUtvwCI8dM3oqQ==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-PqvZ2B2XEyPEbclp+gV6KO/F1FIFSbIwewRgmROCMBo/aZ6J1w8Qypoj2pEOcg3G2HzLlaP6VUtvwCI8dM3oqQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-runtime@30.2.0: - resolution: - { - integrity: sha512-p1+GVX/PJqTucvsmERPMgCPvQJpFt4hFbM+VN3n8TMo47decMUcJbt+rgzwrEme0MQUA/R+1de2axftTHkKckg==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-p1+GVX/PJqTucvsmERPMgCPvQJpFt4hFbM+VN3n8TMo47decMUcJbt+rgzwrEme0MQUA/R+1de2axftTHkKckg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-snapshot@30.2.0: - resolution: - { - integrity: sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-util@30.2.0: - resolution: - { - integrity: sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-validate@30.2.0: - resolution: - { - integrity: sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-watcher@30.2.0: - resolution: - { - integrity: sha512-PYxa28dxJ9g777pGm/7PrbnMeA0Jr7osHP9bS7eJy9DuAjMgdGtxgf0uKMyoIsTWAkIbUW5hSDdJ3urmgXBqxg==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-PYxa28dxJ9g777pGm/7PrbnMeA0Jr7osHP9bS7eJy9DuAjMgdGtxgf0uKMyoIsTWAkIbUW5hSDdJ3urmgXBqxg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-worker@30.2.0: - resolution: - { - integrity: sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest@30.2.0: - resolution: - { - integrity: sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 @@ -10903,645 +7396,351 @@ packages: optional: true jiti@2.6.1: - resolution: - { - integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==, - } + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true js-beautify@1.15.4: - resolution: - { - integrity: sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==, - } - engines: { node: '>=14' } + resolution: {integrity: sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==} + engines: {node: '>=14'} hasBin: true js-cookie@3.0.5: - resolution: - { - integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==, - } - engines: { node: '>=14' } + resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} + engines: {node: '>=14'} js-sha3@0.8.0: - resolution: - { - integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==, - } + resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} js-tokens@4.0.0: - resolution: - { - integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==, - } + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} js-yaml@3.14.2: - resolution: - { - integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==, - } + resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} hasBin: true js-yaml@4.1.0: - resolution: - { - integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==, - } + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true js-yaml@4.1.1: - resolution: - { - integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==, - } + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true jsesc@3.1.0: - resolution: - { - integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} hasBin: true json-buffer@3.0.1: - resolution: - { - integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==, - } + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} json-parse-better-errors@1.0.2: - resolution: - { - integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==, - } + resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==} json-parse-even-better-errors@2.3.1: - resolution: - { - integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==, - } + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} json-parse-even-better-errors@3.0.2: - resolution: - { - integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} json-schema-traverse@0.4.1: - resolution: - { - integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==, - } + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} json-schema-traverse@1.0.0: - resolution: - { - integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==, - } + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} json-stable-stringify-without-jsonify@1.0.1: - resolution: - { - integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==, - } + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} json-stringify-nice@1.1.4: - resolution: - { - integrity: sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw==, - } + resolution: {integrity: sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw==} json-stringify-safe@5.0.1: - resolution: - { - integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==, - } + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} json5@2.2.3: - resolution: - { - integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} hasBin: true jsonc-parser@3.2.0: - resolution: - { - integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==, - } + resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} jsonc-parser@3.3.1: - resolution: - { - integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==, - } + resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} jsonfile@6.2.0: - resolution: - { - integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==, - } + resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} jsonparse@1.3.1: - resolution: - { - integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==, - } - engines: { '0': node >= 0.2.0 } + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} jsonwebtoken@9.0.3: - resolution: - { - integrity: sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==, - } - engines: { node: '>=12', npm: '>=6' } + resolution: {integrity: sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==} + engines: {node: '>=12', npm: '>=6'} juice@7.0.0: - resolution: - { - integrity: sha512-AjKQX31KKN+uJs+zaf+GW8mBO/f/0NqSh2moTMyvwBY+4/lXIYTU8D8I2h6BAV3Xnz6GGsbalUyFqbYMe+Vh+Q==, - } - engines: { node: '>=10.0.0' } + resolution: {integrity: sha512-AjKQX31KKN+uJs+zaf+GW8mBO/f/0NqSh2moTMyvwBY+4/lXIYTU8D8I2h6BAV3Xnz6GGsbalUyFqbYMe+Vh+Q==} + engines: {node: '>=10.0.0'} hasBin: true just-diff-apply@5.5.0: - resolution: - { - integrity: sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw==, - } + resolution: {integrity: sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw==} just-diff@6.0.2: - resolution: - { - integrity: sha512-S59eriX5u3/QhMNq3v/gm8Kd0w8OS6Tz2FS1NG4blv+z0MuQcBRJyFWjdovM0Rad4/P4aUPFtnkNjMjyMlMSYA==, - } + resolution: {integrity: sha512-S59eriX5u3/QhMNq3v/gm8Kd0w8OS6Tz2FS1NG4blv+z0MuQcBRJyFWjdovM0Rad4/P4aUPFtnkNjMjyMlMSYA==} jwa@2.0.1: - resolution: - { - integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==, - } + resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} jws@4.0.1: - resolution: - { - integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==, - } + resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==} katex@0.16.28: - resolution: - { - integrity: sha512-YHzO7721WbmAL6Ov1uzN/l5mY5WWWhJBSW+jq4tkfZfsxmo1hu6frS0EOswvjBUnWE6NtjEs48SFn5CQESRLZg==, - } + resolution: {integrity: sha512-YHzO7721WbmAL6Ov1uzN/l5mY5WWWhJBSW+jq4tkfZfsxmo1hu6frS0EOswvjBUnWE6NtjEs48SFn5CQESRLZg==} hasBin: true keyv@4.5.4: - resolution: - { - integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==, - } + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} khroma@2.1.0: - resolution: - { - integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==, - } + resolution: {integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==} kind-of@6.0.3: - resolution: - { - integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} komoji@0.8.0: - resolution: - { - integrity: sha512-+Ud4ubAJhhTWneLv8V/1OyrQMwrK7ZCHDY7QJJBjaypvTCM8+ECCfKWVZrYz5NIcswuBfiYsDNYJ5kxGUwsoOw==, - } + resolution: {integrity: sha512-+Ud4ubAJhhTWneLv8V/1OyrQMwrK7ZCHDY7QJJBjaypvTCM8+ECCfKWVZrYz5NIcswuBfiYsDNYJ5kxGUwsoOw==} langium@3.3.1: - resolution: - { - integrity: sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==, - } - engines: { node: '>=16.0.0' } + resolution: {integrity: sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==} + engines: {node: '>=16.0.0'} layout-base@1.0.2: - resolution: - { - integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==, - } + resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==} layout-base@2.0.1: - resolution: - { - integrity: sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==, - } + resolution: {integrity: sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==} lerna@8.2.4: - resolution: - { - integrity: sha512-0gaVWDIVT7fLfprfwpYcQajb7dBJv3EGavjG7zvJ+TmGx3/wovl5GklnSwM2/WeE0Z2wrIz7ndWhBcDUHVjOcQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-0gaVWDIVT7fLfprfwpYcQajb7dBJv3EGavjG7zvJ+TmGx3/wovl5GklnSwM2/WeE0Z2wrIz7ndWhBcDUHVjOcQ==} + engines: {node: '>=18.0.0'} hasBin: true leven@3.1.0: - resolution: - { - integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} levn@0.4.1: - resolution: - { - integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==, - } - engines: { node: '>= 0.8.0' } + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} libnpmaccess@8.0.6: - resolution: - { - integrity: sha512-uM8DHDEfYG6G5gVivVl+yQd4pH3uRclHC59lzIbSvy7b5FEwR+mU49Zq1jEyRtRFv7+M99mUW9S0wL/4laT4lw==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-uM8DHDEfYG6G5gVivVl+yQd4pH3uRclHC59lzIbSvy7b5FEwR+mU49Zq1jEyRtRFv7+M99mUW9S0wL/4laT4lw==} + engines: {node: ^16.14.0 || >=18.0.0} libnpmpublish@9.0.9: - resolution: - { - integrity: sha512-26zzwoBNAvX9AWOPiqqF6FG4HrSCPsHFkQm7nT+xU1ggAujL/eae81RnCv4CJ2In9q9fh10B88sYSzKCUh/Ghg==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-26zzwoBNAvX9AWOPiqqF6FG4HrSCPsHFkQm7nT+xU1ggAujL/eae81RnCv4CJ2In9q9fh10B88sYSzKCUh/Ghg==} + engines: {node: ^16.14.0 || >=18.0.0} libpg-query@17.7.3: - resolution: - { - integrity: sha512-lHKBvoWRsXt/9bJxpAeFxkLu0CA6tELusqy3o1z6/DwGXSETxhKJDaNlNdrNV8msvXDLBhpg/4RE/fKKs5rYFA==, - } + resolution: {integrity: sha512-lHKBvoWRsXt/9bJxpAeFxkLu0CA6tELusqy3o1z6/DwGXSETxhKJDaNlNdrNV8msvXDLBhpg/4RE/fKKs5rYFA==} lines-and-columns@1.2.4: - resolution: - { - integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==, - } + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} lines-and-columns@2.0.3: - resolution: - { - integrity: sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==, - } - engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + resolution: {integrity: sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} linkify-it@5.0.0: - resolution: - { - integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==, - } + resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} load-json-file@4.0.0: - resolution: - { - integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==} + engines: {node: '>=4'} load-json-file@6.2.0: - resolution: - { - integrity: sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ==} + engines: {node: '>=8'} locate-path@2.0.0: - resolution: - { - integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==} + engines: {node: '>=4'} locate-path@5.0.0: - resolution: - { - integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} locate-path@6.0.0: - resolution: - { - integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} lodash-es@4.17.21: - resolution: - { - integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==, - } + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} lodash-es@4.17.23: - resolution: - { - integrity: sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==, - } + resolution: {integrity: sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==} lodash.includes@4.3.0: - resolution: - { - integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==, - } + resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} lodash.isboolean@3.0.3: - resolution: - { - integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==, - } + resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} lodash.isinteger@4.0.4: - resolution: - { - integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==, - } + resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} lodash.ismatch@4.4.0: - resolution: - { - integrity: sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==, - } + resolution: {integrity: sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==} lodash.isnumber@3.0.3: - resolution: - { - integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==, - } + resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} lodash.isplainobject@4.0.6: - resolution: - { - integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==, - } + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} lodash.isstring@4.0.1: - resolution: - { - integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==, - } + resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} lodash.memoize@4.1.2: - resolution: - { - integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==, - } + resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} lodash.merge@4.6.2: - resolution: - { - integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==, - } + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} lodash.once@4.1.1: - resolution: - { - integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==, - } + resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} lodash@4.17.21: - resolution: - { - integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==, - } + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} lodash@4.17.23: - resolution: - { - integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==, - } + resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==} log-symbols@4.1.0: - resolution: - { - integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} long-timeout@0.1.1: - resolution: - { - integrity: sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==, - } + resolution: {integrity: sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==} long@5.3.2: - resolution: - { - integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==, - } + resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} loose-envify@1.4.0: - resolution: - { - integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==, - } + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true lower-case@1.1.4: - resolution: - { - integrity: sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==, - } + resolution: {integrity: sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==} lru-cache@10.4.3: - resolution: - { - integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==, - } + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} lru-cache@11.2.4: - resolution: - { - integrity: sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==} + engines: {node: 20 || >=22} lru-cache@5.1.1: - resolution: - { - integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==, - } + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} lru-cache@6.0.0: - resolution: - { - integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} luxon@3.7.2: - resolution: - { - integrity: sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==} + engines: {node: '>=12'} lz-string@1.5.0: - resolution: - { - integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==, - } + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true mailgun.js@10.4.0: - resolution: - { - integrity: sha512-YrdaZEAJwwjXGBTfZTNQ1LM7tmkdUaz2NpZEu7+zULcG4Wrlhd7cWSNZW0bxT3bP48k5N0mZWz8C2f9gc2+Geg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-YrdaZEAJwwjXGBTfZTNQ1LM7tmkdUaz2NpZEu7+zULcG4Wrlhd7cWSNZW0bxT3bP48k5N0mZWz8C2f9gc2+Geg==} + engines: {node: '>=18.0.0'} makage@0.1.12: - resolution: - { - integrity: sha512-R3bITl50Ts2GzoaErywe8n24Iu2qbvbNOqOyidjDjh6iqK0CAj2VzIk3xRS4z8Q4xDQzaJrcb2+dGDjqRj6ChA==, - } + resolution: {integrity: sha512-R3bITl50Ts2GzoaErywe8n24Iu2qbvbNOqOyidjDjh6iqK0CAj2VzIk3xRS4z8Q4xDQzaJrcb2+dGDjqRj6ChA==} hasBin: true make-dir@2.1.0: - resolution: - { - integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} + engines: {node: '>=6'} make-dir@4.0.0: - resolution: - { - integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} make-error@1.3.6: - resolution: - { - integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==, - } + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} make-fetch-happen@13.0.1: - resolution: - { - integrity: sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==} + engines: {node: ^16.14.0 || >=18.0.0} makeerror@1.0.12: - resolution: - { - integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==, - } + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} map-obj@1.0.1: - resolution: - { - integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} + engines: {node: '>=0.10.0'} map-obj@4.3.0: - resolution: - { - integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} + engines: {node: '>=8'} markdown-it@14.1.1: - resolution: - { - integrity: sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==, - } + resolution: {integrity: sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==} hasBin: true marked@16.4.2: - resolution: - { - integrity: sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==, - } - engines: { node: '>= 20' } + resolution: {integrity: sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==} + engines: {node: '>= 20'} hasBin: true match-sorter@6.3.4: - resolution: - { - integrity: sha512-jfZW7cWS5y/1xswZo8VBOdudUiSd9nifYRWphc9M5D/ee4w4AoXLgBEdRbgVaxbMuagBPeUC5y2Hi8DO6o9aDg==, - } + resolution: {integrity: sha512-jfZW7cWS5y/1xswZo8VBOdudUiSd9nifYRWphc9M5D/ee4w4AoXLgBEdRbgVaxbMuagBPeUC5y2Hi8DO6o9aDg==} math-intrinsics@1.1.0: - resolution: - { - integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} mdurl@2.0.0: - resolution: - { - integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==, - } + resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} media-typer@1.1.0: - resolution: - { - integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==, - } - engines: { node: '>= 0.8' } + resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} + engines: {node: '>= 0.8'} mensch@0.3.4: - resolution: - { - integrity: sha512-IAeFvcOnV9V0Yk+bFhYR07O3yNina9ANIN5MoXBKYJ/RLYPurd2d0yw14MDhpr9/momp0WofT1bPUh3hkzdi/g==, - } + resolution: {integrity: sha512-IAeFvcOnV9V0Yk+bFhYR07O3yNina9ANIN5MoXBKYJ/RLYPurd2d0yw14MDhpr9/momp0WofT1bPUh3hkzdi/g==} meow@8.1.2: - resolution: - { - integrity: sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==} + engines: {node: '>=10'} merge-descriptors@2.0.0: - resolution: - { - integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} + engines: {node: '>=18'} merge-stream@2.0.0: - resolution: - { - integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==, - } + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} merge2@1.4.1: - resolution: - { - integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==, - } - engines: { node: '>= 8' } + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} mermaid@11.12.2: - resolution: - { - integrity: sha512-n34QPDPEKmaeCG4WDMGy0OT6PSyxKCfy2pJgShP+Qow2KLrvWjclwbc3yXfSIf4BanqWEhQEpngWwNp/XhZt6w==, - } + resolution: {integrity: sha512-n34QPDPEKmaeCG4WDMGy0OT6PSyxKCfy2pJgShP+Qow2KLrvWjclwbc3yXfSIf4BanqWEhQEpngWwNp/XhZt6w==} meros@1.3.2: - resolution: - { - integrity: sha512-Q3mobPbvEx7XbwhnC1J1r60+5H6EZyNccdzSz0eGexJRwouUtTZxPVRGdqKtxlpD84ScK4+tIGldkqDtCKdI0A==, - } - engines: { node: '>=13' } + resolution: {integrity: sha512-Q3mobPbvEx7XbwhnC1J1r60+5H6EZyNccdzSz0eGexJRwouUtTZxPVRGdqKtxlpD84ScK4+tIGldkqDtCKdI0A==} + engines: {node: '>=13'} peerDependencies: '@types/node': '>=13' peerDependenciesMeta: @@ -11549,577 +7748,316 @@ packages: optional: true methods@1.1.2: - resolution: - { - integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==, - } - engines: { node: '>= 0.6' } + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} micromatch@4.0.8: - resolution: - { - integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==, - } - engines: { node: '>=8.6' } + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} microseconds@0.2.0: - resolution: - { - integrity: sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==, - } + resolution: {integrity: sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==} mime-db@1.52.0: - resolution: - { - integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==, - } - engines: { node: '>= 0.6' } + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} mime-db@1.54.0: - resolution: - { - integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==, - } - engines: { node: '>= 0.6' } + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} mime-types@2.1.35: - resolution: - { - integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==, - } - engines: { node: '>= 0.6' } + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} mime-types@3.0.2: - resolution: - { - integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} + engines: {node: '>=18'} mime@2.6.0: - resolution: - { - integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==, - } - engines: { node: '>=4.0.0' } + resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} + engines: {node: '>=4.0.0'} hasBin: true mimic-fn@2.1.0: - resolution: - { - integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} min-indent@1.0.1: - resolution: - { - integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} minimatch@10.1.1: - resolution: - { - integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==} + engines: {node: 20 || >=22} minimatch@10.1.2: - resolution: - { - integrity: sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==} + engines: {node: 20 || >=22} minimatch@3.0.5: - resolution: - { - integrity: sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==, - } + resolution: {integrity: sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==} minimatch@3.1.2: - resolution: - { - integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==, - } + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} minimatch@5.1.6: - resolution: - { - integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} minimatch@8.0.4: - resolution: - { - integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==, - } - engines: { node: '>=16 || 14 >=14.17' } + resolution: {integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==} + engines: {node: '>=16 || 14 >=14.17'} minimatch@9.0.1: - resolution: - { - integrity: sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==, - } - engines: { node: '>=16 || 14 >=14.17' } + resolution: {integrity: sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==} + engines: {node: '>=16 || 14 >=14.17'} minimatch@9.0.3: - resolution: - { - integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==, - } - engines: { node: '>=16 || 14 >=14.17' } + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} minimatch@9.0.5: - resolution: - { - integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==, - } - engines: { node: '>=16 || 14 >=14.17' } + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} minimist-options@4.1.0: - resolution: - { - integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==, - } - engines: { node: '>= 6' } + resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} + engines: {node: '>= 6'} minimist@1.2.8: - resolution: - { - integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==, - } + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} minipass-collect@2.0.1: - resolution: - { - integrity: sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==, - } - engines: { node: '>=16 || 14 >=14.17' } + resolution: {integrity: sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==} + engines: {node: '>=16 || 14 >=14.17'} minipass-fetch@3.0.5: - resolution: - { - integrity: sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} minipass-flush@1.0.5: - resolution: - { - integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==, - } - engines: { node: '>= 8' } + resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} + engines: {node: '>= 8'} minipass-pipeline@1.2.4: - resolution: - { - integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} + engines: {node: '>=8'} minipass-sized@1.0.3: - resolution: - { - integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} + engines: {node: '>=8'} minipass@3.3.6: - resolution: - { - integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} minipass@4.2.8: - resolution: - { - integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==} + engines: {node: '>=8'} minipass@5.0.0: - resolution: - { - integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} minipass@7.1.2: - resolution: - { - integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==, - } - engines: { node: '>=16 || 14 >=14.17' } + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} minizlib@2.1.2: - resolution: - { - integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==, - } - engines: { node: '>= 8' } + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} mjml-accordion@4.7.1: - resolution: - { - integrity: sha512-oYwC/CLOUWJ6pRt2saDHj/HytGOHO5B5lKNqUAhKPye5HFNZykKEV5ChmZ2NfGsGU+9BhQ7H5DaCafp4fDmPAg==, - } + resolution: {integrity: sha512-oYwC/CLOUWJ6pRt2saDHj/HytGOHO5B5lKNqUAhKPye5HFNZykKEV5ChmZ2NfGsGU+9BhQ7H5DaCafp4fDmPAg==} mjml-body@4.7.1: - resolution: - { - integrity: sha512-JCrkit+kjCfQyKuVyWSOonM2LGs/o3+63R9l2SleFeXf3+0CaKWaZr/Exzvaeo28c+1o3yRqXbJIpD22SEtJfQ==, - } + resolution: {integrity: sha512-JCrkit+kjCfQyKuVyWSOonM2LGs/o3+63R9l2SleFeXf3+0CaKWaZr/Exzvaeo28c+1o3yRqXbJIpD22SEtJfQ==} mjml-button@4.7.1: - resolution: - { - integrity: sha512-N3WkTMPOvKw2y6sakt1YfYDbOB8apumm1OApPG6J18CHcrX03BwhHPrdfu1JwlRNGwx4kCDdb6zNCGPwuZxkCg==, - } + resolution: {integrity: sha512-N3WkTMPOvKw2y6sakt1YfYDbOB8apumm1OApPG6J18CHcrX03BwhHPrdfu1JwlRNGwx4kCDdb6zNCGPwuZxkCg==} mjml-carousel@4.7.1: - resolution: - { - integrity: sha512-eH3rRyX23ES0BKOn+UUV39+yGNmZVApBVVV0A5znDaNWskCg6/g6ZhEHi4nkWpj+aP2lJKI0HX1nrMfJg0Mxhg==, - } + resolution: {integrity: sha512-eH3rRyX23ES0BKOn+UUV39+yGNmZVApBVVV0A5znDaNWskCg6/g6ZhEHi4nkWpj+aP2lJKI0HX1nrMfJg0Mxhg==} mjml-cli@4.7.1: - resolution: - { - integrity: sha512-xzCtJVKYVhGorvTmnbcMUfZlmJdBnu1UBD9A1H8UUBGMNE/Hs9QpHs9PLCMp8JR/uhSu15IgVjhFN0oSVndMRQ==, - } + resolution: {integrity: sha512-xzCtJVKYVhGorvTmnbcMUfZlmJdBnu1UBD9A1H8UUBGMNE/Hs9QpHs9PLCMp8JR/uhSu15IgVjhFN0oSVndMRQ==} hasBin: true mjml-column@4.7.1: - resolution: - { - integrity: sha512-CGw81TnGiuPR1GblLOez8xeoeAz1SEFjMpqapazjgXUuF5xUxg3qH55Wt4frpXe3VypeZWVYeumr6CwoNaPbKg==, - } + resolution: {integrity: sha512-CGw81TnGiuPR1GblLOez8xeoeAz1SEFjMpqapazjgXUuF5xUxg3qH55Wt4frpXe3VypeZWVYeumr6CwoNaPbKg==} mjml-core@4.7.1: - resolution: - { - integrity: sha512-AMACoq/h440m7SM86As8knW0bNQgjNIzsP/cMF6X9RO07GfszgbaWUq/XCaRNi+q8bWvBJSCXbngDJySVc5ALw==, - } + resolution: {integrity: sha512-AMACoq/h440m7SM86As8knW0bNQgjNIzsP/cMF6X9RO07GfszgbaWUq/XCaRNi+q8bWvBJSCXbngDJySVc5ALw==} mjml-divider@4.7.1: - resolution: - { - integrity: sha512-7+uCUJdqEr6w8AzpF8lhRheelYEgOwiK0KJGlAQN3LF+h2S1rTPEzEB67qL2x5cU+80kPlxtxoQWImDBy0vXqg==, - } + resolution: {integrity: sha512-7+uCUJdqEr6w8AzpF8lhRheelYEgOwiK0KJGlAQN3LF+h2S1rTPEzEB67qL2x5cU+80kPlxtxoQWImDBy0vXqg==} mjml-group@4.7.1: - resolution: - { - integrity: sha512-mAYdhocCzetdhPSws/9/sQ4hcz4kQPX2dNitQmbxNVwoMFYXjp/WcLEfGc5u13Ue7dPfcV6c9lB/Uu5o3NmRvw==, - } + resolution: {integrity: sha512-mAYdhocCzetdhPSws/9/sQ4hcz4kQPX2dNitQmbxNVwoMFYXjp/WcLEfGc5u13Ue7dPfcV6c9lB/Uu5o3NmRvw==} mjml-head-attributes@4.7.1: - resolution: - { - integrity: sha512-nB/bQ3I98Dvy/IkI4nqxTCnLonULkIKc8KrieRTrtPkUV3wskBzngpCgnjKvFPbHWiGlwjHDzcFJc7G0uWeqog==, - } + resolution: {integrity: sha512-nB/bQ3I98Dvy/IkI4nqxTCnLonULkIKc8KrieRTrtPkUV3wskBzngpCgnjKvFPbHWiGlwjHDzcFJc7G0uWeqog==} mjml-head-breakpoint@4.7.1: - resolution: - { - integrity: sha512-0KB5SweIWDvwHkn4VCUsEhCQgfY/0wkNUnSXNoftaRujv0NQFQfOOH4eINy0NZYfDfrE4WYe08z+olHprp+T2A==, - } + resolution: {integrity: sha512-0KB5SweIWDvwHkn4VCUsEhCQgfY/0wkNUnSXNoftaRujv0NQFQfOOH4eINy0NZYfDfrE4WYe08z+olHprp+T2A==} mjml-head-font@4.7.1: - resolution: - { - integrity: sha512-9YGzBcQ2htZ6j266fiLLfzcxqDEDLTvfKtypTjaeRb1w3N8S5wL+/zJA5ZjRL6r39Ij5ZPQSlSDC32KPiwhGkA==, - } + resolution: {integrity: sha512-9YGzBcQ2htZ6j266fiLLfzcxqDEDLTvfKtypTjaeRb1w3N8S5wL+/zJA5ZjRL6r39Ij5ZPQSlSDC32KPiwhGkA==} mjml-head-html-attributes@4.7.1: - resolution: - { - integrity: sha512-2TK2nGpq4rGaghbVx2UNm5TXeZ5BTGYEvtSPoYPNu02KRCj6tb+uedAgFXwJpX+ogRfIfPK50ih+9ZMoHwf2IQ==, - } + resolution: {integrity: sha512-2TK2nGpq4rGaghbVx2UNm5TXeZ5BTGYEvtSPoYPNu02KRCj6tb+uedAgFXwJpX+ogRfIfPK50ih+9ZMoHwf2IQ==} mjml-head-preview@4.7.1: - resolution: - { - integrity: sha512-UHlvvgldiPDODq/5zKMsmXgRb/ZyKygKDUVQSM5bm3HvpKXeyYxJZazcIGmlGICEqv1ced1WGINhCg72dSfN+Q==, - } + resolution: {integrity: sha512-UHlvvgldiPDODq/5zKMsmXgRb/ZyKygKDUVQSM5bm3HvpKXeyYxJZazcIGmlGICEqv1ced1WGINhCg72dSfN+Q==} mjml-head-style@4.7.1: - resolution: - { - integrity: sha512-8Gij99puN1SoOx5tGBjgkh4iCpI+zbwGBiB2Y8VwJrwXQxdJ1Qa902dQP5djoFFG39Bthii/48cS/d1bHigGPQ==, - } + resolution: {integrity: sha512-8Gij99puN1SoOx5tGBjgkh4iCpI+zbwGBiB2Y8VwJrwXQxdJ1Qa902dQP5djoFFG39Bthii/48cS/d1bHigGPQ==} mjml-head-title@4.7.1: - resolution: - { - integrity: sha512-vK3r+DApTXw2EoK/fh8dQOsO438Z7Ksy6iBIb7h04x33d4Z41r6+jtgxGXoKFXnjgr8MyLX5HZyyie5obW+hZg==, - } + resolution: {integrity: sha512-vK3r+DApTXw2EoK/fh8dQOsO438Z7Ksy6iBIb7h04x33d4Z41r6+jtgxGXoKFXnjgr8MyLX5HZyyie5obW+hZg==} mjml-head@4.7.1: - resolution: - { - integrity: sha512-jUcJ674CT1oT8NTQWTjQQBFZu4yklK0oppfGFJ1cq76ze3isMiyhSnGnOHw6FkjLnZtb3gXXaGKX7UZM+UMk/w==, - } + resolution: {integrity: sha512-jUcJ674CT1oT8NTQWTjQQBFZu4yklK0oppfGFJ1cq76ze3isMiyhSnGnOHw6FkjLnZtb3gXXaGKX7UZM+UMk/w==} mjml-hero@4.7.1: - resolution: - { - integrity: sha512-x+29V8zJAs8EV/eTtGbR921pCpitMQOAkyvNANW/3JLDTL2Oio1OYvGPVC3z1wOT9LKuRTxVzNHVt/bBw02CSQ==, - } + resolution: {integrity: sha512-x+29V8zJAs8EV/eTtGbR921pCpitMQOAkyvNANW/3JLDTL2Oio1OYvGPVC3z1wOT9LKuRTxVzNHVt/bBw02CSQ==} mjml-image@4.7.1: - resolution: - { - integrity: sha512-l3uRR2jaM0Bpz4ctdWuxQUFgg+ol6Nt+ODOrnHsGMwpmFOh4hTPTky6KaF0LCXxYmGbI0FoGBna+hVNnkBsQCA==, - } + resolution: {integrity: sha512-l3uRR2jaM0Bpz4ctdWuxQUFgg+ol6Nt+ODOrnHsGMwpmFOh4hTPTky6KaF0LCXxYmGbI0FoGBna+hVNnkBsQCA==} mjml-migrate@4.7.1: - resolution: - { - integrity: sha512-RgrJ9fHg6iRHC2H4pjRDWilBQ1eTH2jRu1ayDplbnepGoql83vLZaYaWc5Q+J+NsaNI16x+bgNB3fQdBiK+mng==, - } + resolution: {integrity: sha512-RgrJ9fHg6iRHC2H4pjRDWilBQ1eTH2jRu1ayDplbnepGoql83vLZaYaWc5Q+J+NsaNI16x+bgNB3fQdBiK+mng==} hasBin: true mjml-navbar@4.7.1: - resolution: - { - integrity: sha512-awdu8zT7xhS+9aCVunqtocUs8KA2xb+UhJ8UGbxVBpYbTNj3rCL9aWUXqWVwMk1la+3ypCkFuDuTl6dIoWPWlA==, - } + resolution: {integrity: sha512-awdu8zT7xhS+9aCVunqtocUs8KA2xb+UhJ8UGbxVBpYbTNj3rCL9aWUXqWVwMk1la+3ypCkFuDuTl6dIoWPWlA==} mjml-parser-xml@4.7.1: - resolution: - { - integrity: sha512-UWfuRpN45k3GUEv2yl8n5Uf98Tg6FyCsyRnqZGo83mgZzlJRDYTdKII9RjZM646/S8+Q8e9qxi3AsL00j6sZsQ==, - } + resolution: {integrity: sha512-UWfuRpN45k3GUEv2yl8n5Uf98Tg6FyCsyRnqZGo83mgZzlJRDYTdKII9RjZM646/S8+Q8e9qxi3AsL00j6sZsQ==} mjml-raw@4.7.1: - resolution: - { - integrity: sha512-mCQFEXINTkC8i7ydP1Km99e0FaZTeu79AoYnTBAILd4QO+RuD3n/PimBGrcGrOUex0JIKa2jyVQOcSCBuG4WpA==, - } + resolution: {integrity: sha512-mCQFEXINTkC8i7ydP1Km99e0FaZTeu79AoYnTBAILd4QO+RuD3n/PimBGrcGrOUex0JIKa2jyVQOcSCBuG4WpA==} mjml-react@1.0.59: - resolution: - { - integrity: sha512-W1ULnMlxJHE0kNpInu+u3CHr6+QcvhoLJ2ov93Pzt2A1wXAv4CJ9T/P5h/BhZn8vvCXgGizcwHv8sfANfQONVw==, - } + resolution: {integrity: sha512-W1ULnMlxJHE0kNpInu+u3CHr6+QcvhoLJ2ov93Pzt2A1wXAv4CJ9T/P5h/BhZn8vvCXgGizcwHv8sfANfQONVw==} peerDependencies: mjml: ^4.1.2 react: ^16.4.0 react-dom: ^16.4.0 mjml-section@4.7.1: - resolution: - { - integrity: sha512-PlhCMsl/bpFwwgQGUopi9OgOGWgRPpEJVKE8hk4He8GXzbfIuDj4DZ9QJSkwIoZ0fZtcgz11Wwb19i9BZcozVw==, - } + resolution: {integrity: sha512-PlhCMsl/bpFwwgQGUopi9OgOGWgRPpEJVKE8hk4He8GXzbfIuDj4DZ9QJSkwIoZ0fZtcgz11Wwb19i9BZcozVw==} mjml-social@4.7.1: - resolution: - { - integrity: sha512-tN/6V3m59izO9rqWpUokHxhwkk2GHkltzIlhI936hAJHh8hFyEO6+ZwQBZm738G00qgfICmQvX5FNq4upkCYjw==, - } + resolution: {integrity: sha512-tN/6V3m59izO9rqWpUokHxhwkk2GHkltzIlhI936hAJHh8hFyEO6+ZwQBZm738G00qgfICmQvX5FNq4upkCYjw==} mjml-spacer@4.7.1: - resolution: - { - integrity: sha512-gQu1+nA9YGnoolfNPvzfVe/RJ8WqS8ho0hthlhiLOC2RnEnmqH7HHSzCFXm4OeN0VgvDQsM7mfYQGl82O58Y+g==, - } + resolution: {integrity: sha512-gQu1+nA9YGnoolfNPvzfVe/RJ8WqS8ho0hthlhiLOC2RnEnmqH7HHSzCFXm4OeN0VgvDQsM7mfYQGl82O58Y+g==} mjml-table@4.7.1: - resolution: - { - integrity: sha512-rPkOtufMiVreb7I7vXk6rDm9i1DXncODnM5JJNhA9Z1dAQwXiz6V5904gAi2cEYfe0M2m0XQ8P5ZCtvqxGkfGA==, - } + resolution: {integrity: sha512-rPkOtufMiVreb7I7vXk6rDm9i1DXncODnM5JJNhA9Z1dAQwXiz6V5904gAi2cEYfe0M2m0XQ8P5ZCtvqxGkfGA==} mjml-text@4.7.1: - resolution: - { - integrity: sha512-hrjxbY59v6hu/Pn0NO+6TMlrdAlRa3M7GVALx/YWYV3hi59zjYfot8Au7Xq64XdcbcI4eiBVbP/AVr8w03HsOw==, - } + resolution: {integrity: sha512-hrjxbY59v6hu/Pn0NO+6TMlrdAlRa3M7GVALx/YWYV3hi59zjYfot8Au7Xq64XdcbcI4eiBVbP/AVr8w03HsOw==} mjml-validator@4.7.1: - resolution: - { - integrity: sha512-Qxubbz5WE182iLSTd/XRuezMr6UE7/u73grDCw0bTIcQsaTAIkWQn2tBI3jj0chWOw+sxwK2C6zPm9B0Cv7BGA==, - } + resolution: {integrity: sha512-Qxubbz5WE182iLSTd/XRuezMr6UE7/u73grDCw0bTIcQsaTAIkWQn2tBI3jj0chWOw+sxwK2C6zPm9B0Cv7BGA==} mjml-wrapper@4.7.1: - resolution: - { - integrity: sha512-6i+ZATUyqIO5YBnx+RFKZ3+6mg3iOCS/EdXGYZSonZ/EHqlt+RJa3fG2BB4dacXqAjghfl6Lk+bLoR47P3xYIQ==, - } + resolution: {integrity: sha512-6i+ZATUyqIO5YBnx+RFKZ3+6mg3iOCS/EdXGYZSonZ/EHqlt+RJa3fG2BB4dacXqAjghfl6Lk+bLoR47P3xYIQ==} mjml@4.7.1: - resolution: - { - integrity: sha512-nwMrmhTI+Aeh9Gav9LHX/i8k8yDi/QpX5h535BlT5oP4NaAUmyxP/UeYUn9yxtPcIzDlM5ullFnRv/71jyHpkQ==, - } + resolution: {integrity: sha512-nwMrmhTI+Aeh9Gav9LHX/i8k8yDi/QpX5h535BlT5oP4NaAUmyxP/UeYUn9yxtPcIzDlM5ullFnRv/71jyHpkQ==} hasBin: true mkdirp@1.0.4: - resolution: - { - integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} hasBin: true mlly@1.8.0: - resolution: - { - integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==, - } + resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==} mock-req@0.2.0: - resolution: - { - integrity: sha512-IUuwS0W5GjoPyjhuXPQJXpaHfHW7UYFRia8Cchm/xRuyDDclpSQdEoakt3krOpSYvgVlQsbnf0ePDsTRDfp7Dg==, - } + resolution: {integrity: sha512-IUuwS0W5GjoPyjhuXPQJXpaHfHW7UYFRia8Cchm/xRuyDDclpSQdEoakt3krOpSYvgVlQsbnf0ePDsTRDfp7Dg==} modify-values@1.0.1: - resolution: - { - integrity: sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==} + engines: {node: '>=0.10.0'} monaco-editor@0.52.2: - resolution: - { - integrity: sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==, - } + resolution: {integrity: sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==} monaco-graphql@1.7.3: - resolution: - { - integrity: sha512-6LAIcg/vT2NGLjHnT+5iIZONsZCaCuz2orbg7qD/u4Ry9R7rDotLh0HAzIF/yKdzEA5fTZC+TofSx2O+Zi+0ow==, - } + resolution: {integrity: sha512-6LAIcg/vT2NGLjHnT+5iIZONsZCaCuz2orbg7qD/u4Ry9R7rDotLh0HAzIF/yKdzEA5fTZC+TofSx2O+Zi+0ow==} peerDependencies: graphql: ^15.5.0 || ^16.0.0 || ^17.0.0 monaco-editor: '>= 0.20.0 < 0.53' prettier: ^2.8.0 || ^3.0.0 motion-dom@12.34.0: - resolution: - { - integrity: sha512-Lql3NuEcScRDxTAO6GgUsRHBZOWI/3fnMlkMcH5NftzcN37zJta+bpbMAV9px4Nj057TuvRooMK7QrzMCgtz6Q==, - } + resolution: {integrity: sha512-Lql3NuEcScRDxTAO6GgUsRHBZOWI/3fnMlkMcH5NftzcN37zJta+bpbMAV9px4Nj057TuvRooMK7QrzMCgtz6Q==} motion-utils@12.29.2: - resolution: - { - integrity: sha512-G3kc34H2cX2gI63RqU+cZq+zWRRPSsNIOjpdl9TN4AQwC4sgwYPl/Q/Obf/d53nOm569T0fYK+tcoSV50BWx8A==, - } + resolution: {integrity: sha512-G3kc34H2cX2gI63RqU+cZq+zWRRPSsNIOjpdl9TN4AQwC4sgwYPl/Q/Obf/d53nOm569T0fYK+tcoSV50BWx8A==} ms@2.1.3: - resolution: - { - integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==, - } + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} multimatch@5.0.0: - resolution: - { - integrity: sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==} + engines: {node: '>=10'} mute-stream@0.0.8: - resolution: - { - integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==, - } + resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} mute-stream@1.0.0: - resolution: - { - integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} nano-time@1.0.0: - resolution: - { - integrity: sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==, - } + resolution: {integrity: sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==} nanoid@3.3.11: - resolution: - { - integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==, - } - engines: { node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1 } + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true napi-postinstall@0.3.4: - resolution: - { - integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==, - } - engines: { node: ^12.20.0 || ^14.18.0 || >=16.0.0 } + resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} hasBin: true natural-compare@1.4.0: - resolution: - { - integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==, - } + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} negotiator@0.6.4: - resolution: - { - integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==, - } - engines: { node: '>= 0.6' } + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} negotiator@1.0.0: - resolution: - { - integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==, - } - engines: { node: '>= 0.6' } + resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} + engines: {node: '>= 0.6'} neo-async@2.6.2: - resolution: - { - integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==, - } + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} nested-obj@0.1.10: - resolution: - { - integrity: sha512-5V2kUPrBee/tmoS2p0IJ35BcaJuW1p1yXF5GP8JpXIkDoPbaYeYypAHizUeZkAUxcC7Rago7izWmEq7qa8+Mhw==, - } + resolution: {integrity: sha512-5V2kUPrBee/tmoS2p0IJ35BcaJuW1p1yXF5GP8JpXIkDoPbaYeYypAHizUeZkAUxcC7Rago7izWmEq7qa8+Mhw==} nested-obj@0.1.5: - resolution: - { - integrity: sha512-04Y7qDMlI8RbYTn0cJAKaw/mLrO9UmLj3xbrjTZKDfOn9f3b/RXEQFIIpveJlwn8KfPwdVFWLZUaL5gNuQ7G0w==, - } + resolution: {integrity: sha512-04Y7qDMlI8RbYTn0cJAKaw/mLrO9UmLj3xbrjTZKDfOn9f3b/RXEQFIIpveJlwn8KfPwdVFWLZUaL5gNuQ7G0w==} nested-obj@0.2.0: - resolution: - { - integrity: sha512-uPzih1V6f7yb563xUkFA/oainPdrlc0ojpV8OuRAg4qWK70TPt14D5hWuU3ta1eVacJQv+VVuMJRqFRyTgYZ0Q==, - } + resolution: {integrity: sha512-uPzih1V6f7yb563xUkFA/oainPdrlc0ojpV8OuRAg4qWK70TPt14D5hWuU3ta1eVacJQv+VVuMJRqFRyTgYZ0Q==} no-case@2.3.2: - resolution: - { - integrity: sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==, - } + resolution: {integrity: sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==} node-fetch@2.6.7: - resolution: - { - integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==, - } - engines: { node: 4.x || >=6.0.0 } + resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} + engines: {node: 4.x || >=6.0.0} peerDependencies: encoding: ^0.1.0 peerDependenciesMeta: @@ -12127,11 +8065,8 @@ packages: optional: true node-fetch@2.7.0: - resolution: - { - integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==, - } - engines: { node: 4.x || >=6.0.0 } + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} peerDependencies: encoding: ^0.1.0 peerDependenciesMeta: @@ -12139,180 +8074,102 @@ packages: optional: true node-gyp@10.3.1: - resolution: - { - integrity: sha512-Pp3nFHBThHzVtNY7U6JfPjvT/DTE8+o/4xKsLQtBoU+j2HLsGlhcfzflAoUreaJbNmYnX+LlLi0qjV8kpyO6xQ==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-Pp3nFHBThHzVtNY7U6JfPjvT/DTE8+o/4xKsLQtBoU+j2HLsGlhcfzflAoUreaJbNmYnX+LlLi0qjV8kpyO6xQ==} + engines: {node: ^16.14.0 || >=18.0.0} hasBin: true node-int64@0.4.0: - resolution: - { - integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==, - } + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} node-machine-id@1.1.12: - resolution: - { - integrity: sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==, - } + resolution: {integrity: sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==} node-releases@2.0.27: - resolution: - { - integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==, - } + resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} node-schedule@2.1.1: - resolution: - { - integrity: sha512-OXdegQq03OmXEjt2hZP33W2YPs/E5BcFQks46+G2gAxs4gHOIVD1u7EqlYLYSKsaIpyKCK9Gbk0ta1/gjRSMRQ==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-OXdegQq03OmXEjt2hZP33W2YPs/E5BcFQks46+G2gAxs4gHOIVD1u7EqlYLYSKsaIpyKCK9Gbk0ta1/gjRSMRQ==} + engines: {node: '>=6'} nodemailer@6.10.1: - resolution: - { - integrity: sha512-Z+iLaBGVaSjbIzQ4pX6XV41HrooLsQ10ZWPUehGmuantvzWoDVBnmsdUcOIDM1t+yPor5pDhVlDESgOMEGxhHA==, - } - engines: { node: '>=6.0.0' } + resolution: {integrity: sha512-Z+iLaBGVaSjbIzQ4pX6XV41HrooLsQ10ZWPUehGmuantvzWoDVBnmsdUcOIDM1t+yPor5pDhVlDESgOMEGxhHA==} + engines: {node: '>=6.0.0'} nodemailer@7.0.11: - resolution: - { - integrity: sha512-gnXhNRE0FNhD7wPSCGhdNh46Hs6nm+uTyg+Kq0cZukNQiYdnCsoQjodNP9BQVG9XrcK/v6/MgpAPBUFyzh9pvw==, - } - engines: { node: '>=6.0.0' } + resolution: {integrity: sha512-gnXhNRE0FNhD7wPSCGhdNh46Hs6nm+uTyg+Kq0cZukNQiYdnCsoQjodNP9BQVG9XrcK/v6/MgpAPBUFyzh9pvw==} + engines: {node: '>=6.0.0'} nodemon@3.1.11: - resolution: - { - integrity: sha512-is96t8F/1//UHAjNPHpbsNY46ELPpftGUoSVNXwUfMk/qdjSylYrWSu1XavVTBOn526kFiOR733ATgNBCQyH0g==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-is96t8F/1//UHAjNPHpbsNY46ELPpftGUoSVNXwUfMk/qdjSylYrWSu1XavVTBOn526kFiOR733ATgNBCQyH0g==} + engines: {node: '>=10'} hasBin: true noms@0.0.0: - resolution: - { - integrity: sha512-lNDU9VJaOPxUmXcLb+HQFeUgQQPtMI24Gt6hgfuMHRJgMRHMF/qZ4HJD3GDru4sSw9IQl2jPjAYnQrdIeLbwow==, - } + resolution: {integrity: sha512-lNDU9VJaOPxUmXcLb+HQFeUgQQPtMI24Gt6hgfuMHRJgMRHMF/qZ4HJD3GDru4sSw9IQl2jPjAYnQrdIeLbwow==} nopt@7.2.1: - resolution: - { - integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} hasBin: true normalize-package-data@2.5.0: - resolution: - { - integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==, - } + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} normalize-package-data@3.0.3: - resolution: - { - integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} + engines: {node: '>=10'} normalize-package-data@6.0.2: - resolution: - { - integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==} + engines: {node: ^16.14.0 || >=18.0.0} normalize-path@3.0.0: - resolution: - { - integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} npm-bundled@3.0.1: - resolution: - { - integrity: sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} npm-install-checks@6.3.0: - resolution: - { - integrity: sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} npm-normalize-package-bin@3.0.1: - resolution: - { - integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} npm-package-arg@11.0.2: - resolution: - { - integrity: sha512-IGN0IAwmhDJwy13Wc8k+4PEbTPhpJnMtfR53ZbOyjkvmEcLS4nCwp6mvMWjS5sUjeiW3mpx6cHmuhKEu9XmcQw==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-IGN0IAwmhDJwy13Wc8k+4PEbTPhpJnMtfR53ZbOyjkvmEcLS4nCwp6mvMWjS5sUjeiW3mpx6cHmuhKEu9XmcQw==} + engines: {node: ^16.14.0 || >=18.0.0} npm-packlist@8.0.2: - resolution: - { - integrity: sha512-shYrPFIS/JLP4oQmAwDyk5HcyysKW8/JLTEA32S0Z5TzvpaeeX2yMFfoK1fjEBnCBvVyIB/Jj/GBFdm0wsgzbA==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-shYrPFIS/JLP4oQmAwDyk5HcyysKW8/JLTEA32S0Z5TzvpaeeX2yMFfoK1fjEBnCBvVyIB/Jj/GBFdm0wsgzbA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} npm-pick-manifest@9.1.0: - resolution: - { - integrity: sha512-nkc+3pIIhqHVQr085X9d2JzPzLyjzQS96zbruppqC9aZRm/x8xx6xhI98gHtsfELP2bE+loHq8ZaHFHhe+NauA==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-nkc+3pIIhqHVQr085X9d2JzPzLyjzQS96zbruppqC9aZRm/x8xx6xhI98gHtsfELP2bE+loHq8ZaHFHhe+NauA==} + engines: {node: ^16.14.0 || >=18.0.0} npm-registry-fetch@17.1.0: - resolution: - { - integrity: sha512-5+bKQRH0J1xG1uZ1zMNvxW0VEyoNWgJpY9UDuluPFLKDfJ9u2JmmjmTJV1srBGQOROfdBMiVvnH2Zvpbm+xkVA==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-5+bKQRH0J1xG1uZ1zMNvxW0VEyoNWgJpY9UDuluPFLKDfJ9u2JmmjmTJV1srBGQOROfdBMiVvnH2Zvpbm+xkVA==} + engines: {node: ^16.14.0 || >=18.0.0} npm-run-path@4.0.1: - resolution: - { - integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} nth-check@1.0.2: - resolution: - { - integrity: sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==, - } + resolution: {integrity: sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==} nth-check@2.1.1: - resolution: - { - integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==, - } + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} nullthrows@1.1.1: - resolution: - { - integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==, - } + resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==} nx@20.8.3: - resolution: - { - integrity: sha512-8w815WSMWar3A/LFzwtmEY+E8cVW62lMiFuPDXje+C8O8hFndfvscP56QHNMn2Zdhz3q0+BZUe+se4Em1BKYdA==, - } + resolution: {integrity: sha512-8w815WSMWar3A/LFzwtmEY+E8cVW62lMiFuPDXje+C8O8hFndfvscP56QHNMn2Zdhz3q0+BZUe+se4Em1BKYdA==} hasBin: true peerDependencies: '@swc-node/register': ^1.8.0 @@ -12324,454 +8181,253 @@ packages: optional: true object-assign@4.1.1: - resolution: - { - integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} object-inspect@1.13.4: - resolution: - { - integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} object-path@0.11.8: - resolution: - { - integrity: sha512-YJjNZrlXJFM42wTBn6zgOJVar9KFJvzx6sTWDte8sWZF//cnjl0BxHNpfZx+ZffXX63A9q0b1zsFiBX4g4X5KA==, - } - engines: { node: '>= 10.12.0' } + resolution: {integrity: sha512-YJjNZrlXJFM42wTBn6zgOJVar9KFJvzx6sTWDte8sWZF//cnjl0BxHNpfZx+ZffXX63A9q0b1zsFiBX4g4X5KA==} + engines: {node: '>= 10.12.0'} oblivious-set@1.0.0: - resolution: - { - integrity: sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==, - } + resolution: {integrity: sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==} on-finished@2.4.1: - resolution: - { - integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==, - } - engines: { node: '>= 0.8' } + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} once@1.4.0: - resolution: - { - integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==, - } + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} onetime@5.1.2: - resolution: - { - integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} open@8.4.2: - resolution: - { - integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} + engines: {node: '>=12'} optionator@0.9.4: - resolution: - { - integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==, - } - engines: { node: '>= 0.8.0' } + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} ora@5.3.0: - resolution: - { - integrity: sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==} + engines: {node: '>=10'} ora@5.4.1: - resolution: - { - integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} oxfmt@0.26.0: - resolution: - { - integrity: sha512-UDD1wFNwfeorMm2ZY0xy1KRAAvJ5NjKBfbDmiMwGP7baEHTq65cYpC0aPP+BGHc8weXUbSZaK8MdGyvuRUvS4Q==, - } - engines: { node: ^20.19.0 || >=22.12.0 } + resolution: {integrity: sha512-UDD1wFNwfeorMm2ZY0xy1KRAAvJ5NjKBfbDmiMwGP7baEHTq65cYpC0aPP+BGHc8weXUbSZaK8MdGyvuRUvS4Q==} + engines: {node: ^20.19.0 || >=22.12.0} hasBin: true p-finally@1.0.0: - resolution: - { - integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} + engines: {node: '>=4'} p-limit@1.3.0: - resolution: - { - integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==} + engines: {node: '>=4'} p-limit@2.3.0: - resolution: - { - integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} p-limit@3.1.0: - resolution: - { - integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} p-locate@2.0.0: - resolution: - { - integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==} + engines: {node: '>=4'} p-locate@4.1.0: - resolution: - { - integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} p-locate@5.0.0: - resolution: - { - integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} p-map-series@2.1.0: - resolution: - { - integrity: sha512-RpYIIK1zXSNEOdwxcfe7FdvGcs7+y5n8rifMhMNWvaxRNMPINJHF5GDeuVxWqnfrcHPSCnp7Oo5yNXHId9Av2Q==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-RpYIIK1zXSNEOdwxcfe7FdvGcs7+y5n8rifMhMNWvaxRNMPINJHF5GDeuVxWqnfrcHPSCnp7Oo5yNXHId9Av2Q==} + engines: {node: '>=8'} p-map@4.0.0: - resolution: - { - integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} p-pipe@3.1.0: - resolution: - { - integrity: sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw==} + engines: {node: '>=8'} p-queue@6.6.2: - resolution: - { - integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==} + engines: {node: '>=8'} p-reduce@2.1.0: - resolution: - { - integrity: sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==} + engines: {node: '>=8'} p-timeout@3.2.0: - resolution: - { - integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} + engines: {node: '>=8'} p-try@1.0.0: - resolution: - { - integrity: sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==} + engines: {node: '>=4'} p-try@2.2.0: - resolution: - { - integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} p-waterfall@2.1.1: - resolution: - { - integrity: sha512-RRTnDb2TBG/epPRI2yYXsimO0v3BXC8Yd3ogr1545IaqKK17VGhbWVeGGN+XfCm/08OK8635nH31c8bATkHuSw==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-RRTnDb2TBG/epPRI2yYXsimO0v3BXC8Yd3ogr1545IaqKK17VGhbWVeGGN+XfCm/08OK8635nH31c8bATkHuSw==} + engines: {node: '>=8'} package-json-from-dist@1.0.1: - resolution: - { - integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==, - } + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} package-manager-detector@1.6.0: - resolution: - { - integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==, - } + resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==} pacote@18.0.6: - resolution: - { - integrity: sha512-+eK3G27SMwsB8kLIuj4h1FUhHtwiEUo21Tw8wNjmvdlpOEr613edv+8FUsTj/4F/VN5ywGE19X18N7CC2EJk6A==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-+eK3G27SMwsB8kLIuj4h1FUhHtwiEUo21Tw8wNjmvdlpOEr613edv+8FUsTj/4F/VN5ywGE19X18N7CC2EJk6A==} + engines: {node: ^16.14.0 || >=18.0.0} hasBin: true param-case@2.1.1: - resolution: - { - integrity: sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==, - } + resolution: {integrity: sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==} parent-module@1.0.1: - resolution: - { - integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} parse-conflict-json@3.0.1: - resolution: - { - integrity: sha512-01TvEktc68vwbJOtWZluyWeVGWjP+bZwXtPDMQVbBKzbJ/vZBif0L69KH1+cHv1SZ6e0FKLvjyHe8mqsIqYOmw==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-01TvEktc68vwbJOtWZluyWeVGWjP+bZwXtPDMQVbBKzbJ/vZBif0L69KH1+cHv1SZ6e0FKLvjyHe8mqsIqYOmw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} parse-json@4.0.0: - resolution: - { - integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==} + engines: {node: '>=4'} parse-json@5.2.0: - resolution: - { - integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} parse-package-name@1.0.0: - resolution: - { - integrity: sha512-kBeTUtcj+SkyfaW4+KBe0HtsloBJ/mKTPoxpVdA57GZiPerREsUWJOhVj9anXweFiJkm5y8FG1sxFZkZ0SN6wg==, - } + resolution: {integrity: sha512-kBeTUtcj+SkyfaW4+KBe0HtsloBJ/mKTPoxpVdA57GZiPerREsUWJOhVj9anXweFiJkm5y8FG1sxFZkZ0SN6wg==} parse-path@7.1.0: - resolution: - { - integrity: sha512-EuCycjZtfPcjWk7KTksnJ5xPMvWGA/6i4zrLYhRG0hGvC3GPU/jGUj3Cy+ZR0v30duV3e23R95T1lE2+lsndSw==, - } + resolution: {integrity: sha512-EuCycjZtfPcjWk7KTksnJ5xPMvWGA/6i4zrLYhRG0hGvC3GPU/jGUj3Cy+ZR0v30duV3e23R95T1lE2+lsndSw==} parse-url@8.1.0: - resolution: - { - integrity: sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==, - } + resolution: {integrity: sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==} parse5-htmlparser2-tree-adapter@7.1.0: - resolution: - { - integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==, - } + resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==} parse5-parser-stream@7.1.2: - resolution: - { - integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==, - } + resolution: {integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==} parse5@3.0.3: - resolution: - { - integrity: sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==, - } + resolution: {integrity: sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==} parse5@7.3.0: - resolution: - { - integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==, - } + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} parseurl@1.3.3: - resolution: - { - integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==, - } - engines: { node: '>= 0.8' } + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} path-data-parser@0.1.0: - resolution: - { - integrity: sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==, - } + resolution: {integrity: sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==} path-exists@3.0.0: - resolution: - { - integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} + engines: {node: '>=4'} path-exists@4.0.0: - resolution: - { - integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} path-is-absolute@1.0.1: - resolution: - { - integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} path-key@3.1.1: - resolution: - { - integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} path-parse@1.0.7: - resolution: - { - integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==, - } + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} path-scurry@1.11.1: - resolution: - { - integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==, - } - engines: { node: '>=16 || 14 >=14.18' } + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} path-scurry@2.0.1: - resolution: - { - integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==} + engines: {node: 20 || >=22} path-to-regexp@8.3.0: - resolution: - { - integrity: sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==, - } + resolution: {integrity: sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==} path-type@3.0.0: - resolution: - { - integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==} + engines: {node: '>=4'} pathe@2.0.3: - resolution: - { - integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==, - } + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} pg-cloudflare@1.3.0: - resolution: - { - integrity: sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==, - } + resolution: {integrity: sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==} pg-connection-string@2.10.0: - resolution: - { - integrity: sha512-ur/eoPKzDx2IjPaYyXS6Y8NSblxM7X64deV2ObV57vhjsWiwLvUD6meukAzogiOsu60GO8m/3Cb6FdJsWNjwXg==, - } + resolution: {integrity: sha512-ur/eoPKzDx2IjPaYyXS6Y8NSblxM7X64deV2ObV57vhjsWiwLvUD6meukAzogiOsu60GO8m/3Cb6FdJsWNjwXg==} pg-copy-streams@7.0.0: - resolution: - { - integrity: sha512-zBvnY6wtaBRE2ae2xXWOOGMaNVPkXh1vhypAkNSKgMdciJeTyIQAHZaEeRAxUjs/p1El5jgzYmwG5u871Zj3dQ==, - } + resolution: {integrity: sha512-zBvnY6wtaBRE2ae2xXWOOGMaNVPkXh1vhypAkNSKgMdciJeTyIQAHZaEeRAxUjs/p1El5jgzYmwG5u871Zj3dQ==} pg-int8@1.0.1: - resolution: - { - integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==, - } - engines: { node: '>=4.0.0' } + resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} + engines: {node: '>=4.0.0'} pg-introspection@1.0.0-rc.4: - resolution: - { - integrity: sha512-Cz5HZz4IbJN2wj9ow13dzco/HZ7UUi9qq0PYyjE4+hHgI8yxNLfXk9TqcJA+zgv7KR43QzGlx7yYcC25jTcFDw==, - } - engines: { node: '>=22' } + resolution: {integrity: sha512-Cz5HZz4IbJN2wj9ow13dzco/HZ7UUi9qq0PYyjE4+hHgI8yxNLfXk9TqcJA+zgv7KR43QzGlx7yYcC25jTcFDw==} + engines: {node: '>=22'} pg-pool@3.11.0: - resolution: - { - integrity: sha512-MJYfvHwtGp870aeusDh+hg9apvOe2zmpZJpyt+BMtzUWlVqbhFmMK6bOBXLBUPd7iRtIF9fZplDc7KrPN3PN7w==, - } + resolution: {integrity: sha512-MJYfvHwtGp870aeusDh+hg9apvOe2zmpZJpyt+BMtzUWlVqbhFmMK6bOBXLBUPd7iRtIF9fZplDc7KrPN3PN7w==} peerDependencies: pg: '>=8.0' pg-proto-parser@1.30.4: - resolution: - { - integrity: sha512-+9/n8zfYQVNRc8KGhxxNXO8NA5OKni01IPtit6+C3sLMtcRVVFCj4W0XtrEGFivNjz2qwUtFmRhG8OGMTxs6hg==, - } + resolution: {integrity: sha512-+9/n8zfYQVNRc8KGhxxNXO8NA5OKni01IPtit6+C3sLMtcRVVFCj4W0XtrEGFivNjz2qwUtFmRhG8OGMTxs6hg==} pg-protocol@1.10.3: - resolution: - { - integrity: sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==, - } + resolution: {integrity: sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==} pg-protocol@1.11.0: - resolution: - { - integrity: sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g==, - } + resolution: {integrity: sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g==} pg-sql2@5.0.0-rc.4: - resolution: - { - integrity: sha512-f8um4jNwumksk39zhkdps9jXeCkM3SY22gPjAcq45D/ZTIw2zWHMdsS6H5DE3XdeHy6pyGUzY0urmCgwuhiywg==, - } - engines: { node: '>=22' } + resolution: {integrity: sha512-f8um4jNwumksk39zhkdps9jXeCkM3SY22gPjAcq45D/ZTIw2zWHMdsS6H5DE3XdeHy6pyGUzY0urmCgwuhiywg==} + engines: {node: '>=22'} pg-types@2.2.0: - resolution: - { - integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} + engines: {node: '>=4'} pg@8.17.1: - resolution: - { - integrity: sha512-EIR+jXdYNSMOrpRp7g6WgQr7SaZNZfS7IzZIO0oTNEeibq956JxeD15t3Jk3zZH0KH8DmOIx38qJfQenoE8bXQ==, - } - engines: { node: '>= 16.0.0' } + resolution: {integrity: sha512-EIR+jXdYNSMOrpRp7g6WgQr7SaZNZfS7IzZIO0oTNEeibq956JxeD15t3Jk3zZH0KH8DmOIx38qJfQenoE8bXQ==} + engines: {node: '>= 16.0.0'} peerDependencies: pg-native: '>=3.0.1' peerDependenciesMeta: @@ -12779,165 +8435,93 @@ packages: optional: true pgpass@1.0.5: - resolution: - { - integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==, - } + resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==} pgsql-deparser@17.17.2: - resolution: - { - integrity: sha512-FCjqKY3Sdmce3VUd3CxCXF0kqaZ0s4a6yIMT5UJ9vETh0cF54A8Tpqjn0qBKaPUD8xqTKeLdS+SfiwjAC64wrA==, - } + resolution: {integrity: sha512-FCjqKY3Sdmce3VUd3CxCXF0kqaZ0s4a6yIMT5UJ9vETh0cF54A8Tpqjn0qBKaPUD8xqTKeLdS+SfiwjAC64wrA==} pgsql-parser@17.9.11: - resolution: - { - integrity: sha512-Bqp9uLvJK0Qht9PXzI6eC/Fn+lFRL+2eMvXss4D4qt7lxPLIHS8FMKYOHUQNTI3m6ylExSOdNXhx/DL5UGm3xg==, - } + resolution: {integrity: sha512-Bqp9uLvJK0Qht9PXzI6eC/Fn+lFRL+2eMvXss4D4qt7lxPLIHS8FMKYOHUQNTI3m6ylExSOdNXhx/DL5UGm3xg==} picocolors@1.1.1: - resolution: - { - integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==, - } + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} picomatch-browser@2.2.6: - resolution: - { - integrity: sha512-0ypsOQt9D4e3hziV8O4elD9uN0z/jtUEfxVRtNaAAtXIyUx9m/SzlO020i8YNL2aL/E6blOvvHQcin6HZlFy/w==, - } - engines: { node: '>=8.6' } + resolution: {integrity: sha512-0ypsOQt9D4e3hziV8O4elD9uN0z/jtUEfxVRtNaAAtXIyUx9m/SzlO020i8YNL2aL/E6blOvvHQcin6HZlFy/w==} + engines: {node: '>=8.6'} picomatch@2.3.1: - resolution: - { - integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==, - } - engines: { node: '>=8.6' } + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} picomatch@4.0.3: - resolution: - { - integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} pify@2.3.0: - resolution: - { - integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} pify@3.0.0: - resolution: - { - integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==} + engines: {node: '>=4'} pify@4.0.1: - resolution: - { - integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} pify@5.0.0: - resolution: - { - integrity: sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==} + engines: {node: '>=10'} pirates@4.0.7: - resolution: - { - integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==, - } - engines: { node: '>= 6' } + resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} + engines: {node: '>= 6'} pkg-dir@4.2.0: - resolution: - { - integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} pkg-types@1.3.1: - resolution: - { - integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==, - } + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} playwright-core@1.57.0: - resolution: - { - integrity: sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==} + engines: {node: '>=18'} hasBin: true playwright@1.57.0: - resolution: - { - integrity: sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==} + engines: {node: '>=18'} hasBin: true pluralize@7.0.0: - resolution: - { - integrity: sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==} + engines: {node: '>=4'} points-on-curve@0.2.0: - resolution: - { - integrity: sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==, - } + resolution: {integrity: sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==} points-on-path@0.2.1: - resolution: - { - integrity: sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==, - } + resolution: {integrity: sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==} postcss-selector-parser@6.1.2: - resolution: - { - integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} postcss-value-parser@4.2.0: - resolution: - { - integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==, - } + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} postcss@8.5.6: - resolution: - { - integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==, - } - engines: { node: ^10 || ^12 || >=14 } + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} postgraphile-plugin-connection-filter@3.0.0-rc.1: - resolution: - { - integrity: sha512-gVzLoY+OGAVhUWdcbtY4Hu2zSup8qZB+wlH54RgIa+tQSysWDDh5S3Opaz5uPwY6etcmzR5JjcApOmb1YYIzlA==, - } + resolution: {integrity: sha512-gVzLoY+OGAVhUWdcbtY4Hu2zSup8qZB+wlH54RgIa+tQSysWDDh5S3Opaz5uPwY6etcmzR5JjcApOmb1YYIzlA==} postgraphile@5.0.0-rc.6: - resolution: - { - integrity: sha512-iBEg8BejFUW1jCF2JXwbFSJ1B6AWHfHBuq+hCIQz6yTCmnuDToTBzuiX/icPq4n9RzBstuOn+nHZ/i8MVCbEpg==, - } - engines: { node: '>=22' } + resolution: {integrity: sha512-iBEg8BejFUW1jCF2JXwbFSJ1B6AWHfHBuq+hCIQz6yTCmnuDToTBzuiX/icPq4n9RzBstuOn+nHZ/i8MVCbEpg==} + engines: {node: '>=22'} hasBin: true peerDependencies: '@dataplan/json': 1.0.0-rc.4 @@ -12957,119 +8541,68 @@ packages: optional: true postgres-array@2.0.0: - resolution: - { - integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} + engines: {node: '>=4'} postgres-array@3.0.4: - resolution: - { - integrity: sha512-nAUSGfSDGOaOAEGwqsRY27GPOea7CNipJPOA7lPbdEpx5Kg3qzdP0AaWC5MlhTWV9s4hFX39nomVZ+C4tnGOJQ==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-nAUSGfSDGOaOAEGwqsRY27GPOea7CNipJPOA7lPbdEpx5Kg3qzdP0AaWC5MlhTWV9s4hFX39nomVZ+C4tnGOJQ==} + engines: {node: '>=12'} postgres-bytea@1.0.1: - resolution: - { - integrity: sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==} + engines: {node: '>=0.10.0'} postgres-date@1.0.7: - resolution: - { - integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==} + engines: {node: '>=0.10.0'} postgres-interval@1.2.0: - resolution: - { - integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} + engines: {node: '>=0.10.0'} postgres-range@1.1.4: - resolution: - { - integrity: sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==, - } + resolution: {integrity: sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==} prelude-ls@1.2.1: - resolution: - { - integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==, - } - engines: { node: '>= 0.8.0' } + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} prettier@3.8.0: - resolution: - { - integrity: sha512-yEPsovQfpxYfgWNhCfECjG5AQaO+K3dp6XERmOepyPDVqcJm+bjyCVO3pmU+nAPe0N5dDvekfGezt/EIiRe1TA==, - } - engines: { node: '>=14' } + resolution: {integrity: sha512-yEPsovQfpxYfgWNhCfECjG5AQaO+K3dp6XERmOepyPDVqcJm+bjyCVO3pmU+nAPe0N5dDvekfGezt/EIiRe1TA==} + engines: {node: '>=14'} hasBin: true pretty-format@26.6.2: - resolution: - { - integrity: sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==, - } - engines: { node: '>= 10' } + resolution: {integrity: sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==} + engines: {node: '>= 10'} pretty-format@29.7.0: - resolution: - { - integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==, - } - engines: { node: ^14.15.0 || ^16.10.0 || >=18.0.0 } + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} pretty-format@30.2.0: - resolution: - { - integrity: sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} proc-log@4.2.0: - resolution: - { - integrity: sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} process-nextick-args@2.0.1: - resolution: - { - integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==, - } + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} proggy@2.0.0: - resolution: - { - integrity: sha512-69agxLtnI8xBs9gUGqEnK26UfiexpHy+KUpBQWabiytQjnn5wFY8rklAi7GRfABIuPNnQ/ik48+LGLkYYJcy4A==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-69agxLtnI8xBs9gUGqEnK26UfiexpHy+KUpBQWabiytQjnn5wFY8rklAi7GRfABIuPNnQ/ik48+LGLkYYJcy4A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} promise-all-reject-late@1.0.1: - resolution: - { - integrity: sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==, - } + resolution: {integrity: sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==} promise-call-limit@3.0.2: - resolution: - { - integrity: sha512-mRPQO2T1QQVw11E7+UdCJu7S61eJVWknzml9sC1heAdj1jxl0fWMBypIt9ZOcLFf8FkG995ZD7RnVk7HH72fZw==, - } + resolution: {integrity: sha512-mRPQO2T1QQVw11E7+UdCJu7S61eJVWknzml9sC1heAdj1jxl0fWMBypIt9ZOcLFf8FkG995ZD7RnVk7HH72fZw==} promise-inflight@1.0.1: - resolution: - { - integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==, - } + resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} peerDependencies: bluebird: '*' peerDependenciesMeta: @@ -13077,164 +8610,92 @@ packages: optional: true promise-retry@2.0.1: - resolution: - { - integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} + engines: {node: '>=10'} promzard@1.0.2: - resolution: - { - integrity: sha512-2FPputGL+mP3jJ3UZg/Dl9YOkovB7DX0oOr+ck5QbZ5MtORtds8k/BZdn+02peDLI8/YWbmzx34k5fA+fHvCVQ==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-2FPputGL+mP3jJ3UZg/Dl9YOkovB7DX0oOr+ck5QbZ5MtORtds8k/BZdn+02peDLI8/YWbmzx34k5fA+fHvCVQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} proto-list@1.2.4: - resolution: - { - integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==, - } + resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} protocols@2.0.2: - resolution: - { - integrity: sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==, - } + resolution: {integrity: sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==} proxy-addr@2.0.7: - resolution: - { - integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==, - } - engines: { node: '>= 0.10' } + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} proxy-from-env@1.1.0: - resolution: - { - integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==, - } + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} pstree.remy@1.1.8: - resolution: - { - integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==, - } + resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==} punycode.js@2.3.1: - resolution: - { - integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} + engines: {node: '>=6'} punycode@2.3.1: - resolution: - { - integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} pure-rand@7.0.1: - resolution: - { - integrity: sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==, - } + resolution: {integrity: sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==} qs@6.14.0: - resolution: - { - integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==, - } - engines: { node: '>=0.6' } + resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} + engines: {node: '>=0.6'} qs@6.14.1: - resolution: - { - integrity: sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==, - } - engines: { node: '>=0.6' } + resolution: {integrity: sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==} + engines: {node: '>=0.6'} queue-microtask@1.2.3: - resolution: - { - integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==, - } + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} quick-lru@4.0.1: - resolution: - { - integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} + engines: {node: '>=8'} range-parser@1.2.1: - resolution: - { - integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==, - } - engines: { node: '>= 0.6' } + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} raw-body@3.0.2: - resolution: - { - integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==, - } - engines: { node: '>= 0.10' } + resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==} + engines: {node: '>= 0.10'} react-compiler-runtime@19.1.0-rc.1: - resolution: - { - integrity: sha512-wCt6g+cRh8g32QT18/9blfQHywGjYu+4FlEc3CW1mx3pPxYzZZl1y+VtqxRgnKKBCFLIGUYxog4j4rs5YS86hw==, - } + resolution: {integrity: sha512-wCt6g+cRh8g32QT18/9blfQHywGjYu+4FlEc3CW1mx3pPxYzZZl1y+VtqxRgnKKBCFLIGUYxog4j4rs5YS86hw==} peerDependencies: react: ^17.0.0 || ^18.0.0 || ^19.0.0 || ^0.0.0-experimental react-dom@19.2.3: - resolution: - { - integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==, - } + resolution: {integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==} peerDependencies: react: ^19.2.3 react-error-boundary@6.1.0: - resolution: - { - integrity: sha512-02k9WQ/mUhdbXir0tC1NiMesGzRPaCsJEWU/4bcFrbY1YMZOtHShtZP6zw0SJrBWA/31H0KT9/FgdL8+sPKgHA==, - } + resolution: {integrity: sha512-02k9WQ/mUhdbXir0tC1NiMesGzRPaCsJEWU/4bcFrbY1YMZOtHShtZP6zw0SJrBWA/31H0KT9/FgdL8+sPKgHA==} peerDependencies: react: ^18.0.0 || ^19.0.0 react-is@16.13.1: - resolution: - { - integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==, - } + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} react-is@17.0.2: - resolution: - { - integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==, - } + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} react-is@18.3.1: - resolution: - { - integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==, - } + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} react-is@19.2.4: - resolution: - { - integrity: sha512-W+EWGn2v0ApPKgKKCy/7s7WHXkboGcsrXE+2joLyVxkbyVQfO3MUEaUQDHoSmb8TFFrSKYa9mw64WZHNHSDzYA==, - } + resolution: {integrity: sha512-W+EWGn2v0ApPKgKKCy/7s7WHXkboGcsrXE+2joLyVxkbyVQfO3MUEaUQDHoSmb8TFFrSKYa9mw64WZHNHSDzYA==} react-query@3.39.3: - resolution: - { - integrity: sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g==, - } + resolution: {integrity: sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: '*' @@ -13246,18 +8707,12 @@ packages: optional: true react-refresh@0.17.0: - resolution: - { - integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} + engines: {node: '>=0.10.0'} react-remove-scroll-bar@2.3.8: - resolution: - { - integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} + engines: {node: '>=10'} peerDependencies: '@types/react': '*' react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -13266,11 +8721,8 @@ packages: optional: true react-remove-scroll@2.7.2: - resolution: - { - integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==} + engines: {node: '>=10'} peerDependencies: '@types/react': '*' react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc @@ -13279,11 +8731,8 @@ packages: optional: true react-style-singleton@2.2.3: - resolution: - { - integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} + engines: {node: '>=10'} peerDependencies: '@types/react': '*' react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc @@ -13292,252 +8741,144 @@ packages: optional: true react-test-renderer@19.2.3: - resolution: - { - integrity: sha512-TMR1LnSFiWZMJkCgNf5ATSvAheTT2NvKIwiVwdBPHxjBI7n/JbWd4gaZ16DVd9foAXdvDz+sB5yxZTwMjPRxpw==, - } + resolution: {integrity: sha512-TMR1LnSFiWZMJkCgNf5ATSvAheTT2NvKIwiVwdBPHxjBI7n/JbWd4gaZ16DVd9foAXdvDz+sB5yxZTwMjPRxpw==} peerDependencies: react: ^19.2.3 react@19.2.3: - resolution: - { - integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==} + engines: {node: '>=0.10.0'} read-cmd-shim@4.0.0: - resolution: - { - integrity: sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} read-package-json-fast@3.0.2: - resolution: - { - integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} read-pkg-up@3.0.0: - resolution: - { - integrity: sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==} + engines: {node: '>=4'} read-pkg-up@7.0.1: - resolution: - { - integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} read-pkg@3.0.0: - resolution: - { - integrity: sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==} + engines: {node: '>=4'} read-pkg@5.2.0: - resolution: - { - integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} read@3.0.1: - resolution: - { - integrity: sha512-SLBrDU/Srs/9EoWhU5GdbAoxG1GzpQHo/6qiGItaoLJ1thmYpcNIM1qISEUvyHBzfGlWIyd6p2DNi1oV1VmAuw==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-SLBrDU/Srs/9EoWhU5GdbAoxG1GzpQHo/6qiGItaoLJ1thmYpcNIM1qISEUvyHBzfGlWIyd6p2DNi1oV1VmAuw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} readable-stream@1.0.34: - resolution: - { - integrity: sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==, - } + resolution: {integrity: sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==} readable-stream@2.3.8: - resolution: - { - integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==, - } + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} readable-stream@3.6.2: - resolution: - { - integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==, - } - engines: { node: '>= 6' } + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} readdirp@3.6.0: - resolution: - { - integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==, - } - engines: { node: '>=8.10.0' } + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} redent@3.0.0: - resolution: - { - integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} regenerator-runtime@0.10.5: - resolution: - { - integrity: sha512-02YopEIhAgiBHWeoTiA8aitHDt8z6w+rQqNuIftlM+ZtvSl/brTouaU7DW6GO/cHtvxJvS4Hwv2ibKdxIRi24w==, - } + resolution: {integrity: sha512-02YopEIhAgiBHWeoTiA8aitHDt8z6w+rQqNuIftlM+ZtvSl/brTouaU7DW6GO/cHtvxJvS4Hwv2ibKdxIRi24w==} relateurl@0.2.7: - resolution: - { - integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==, - } - engines: { node: '>= 0.10' } + resolution: {integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==} + engines: {node: '>= 0.10'} remove-accents@0.5.0: - resolution: - { - integrity: sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==, - } + resolution: {integrity: sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==} request-ip@3.3.0: - resolution: - { - integrity: sha512-cA6Xh6e0fDBBBwH77SLJaJPBmD3nWVAcF9/XAcsrIHdjhFzFiB5aNQFytdjCGPezU3ROwrR11IddKAM08vohxA==, - } + resolution: {integrity: sha512-cA6Xh6e0fDBBBwH77SLJaJPBmD3nWVAcF9/XAcsrIHdjhFzFiB5aNQFytdjCGPezU3ROwrR11IddKAM08vohxA==} require-directory@2.1.1: - resolution: - { - integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} require-from-string@2.0.2: - resolution: - { - integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} require-main-filename@2.0.0: - resolution: - { - integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==, - } + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} requires-port@1.0.0: - resolution: - { - integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==, - } + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} resolve-cwd@3.0.0: - resolution: - { - integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} resolve-from@4.0.0: - resolution: - { - integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} resolve-from@5.0.0: - resolution: - { - integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} resolve-pkg-maps@1.0.0: - resolution: - { - integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==, - } + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} resolve.exports@2.0.3: - resolution: - { - integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==} + engines: {node: '>=10'} resolve@1.22.11: - resolution: - { - integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} + engines: {node: '>= 0.4'} hasBin: true restore-cursor@3.1.0: - resolution: - { - integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} retry@0.12.0: - resolution: - { - integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==, - } - engines: { node: '>= 4' } + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} reusify@1.1.0: - resolution: - { - integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==, - } - engines: { iojs: '>=1.0.0', node: '>=0.10.0' } + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} rimraf@3.0.2: - resolution: - { - integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==, - } + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true rimraf@4.4.1: - resolution: - { - integrity: sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==, - } - engines: { node: '>=14' } + resolution: {integrity: sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==} + engines: {node: '>=14'} hasBin: true rimraf@6.1.2: - resolution: - { - integrity: sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==} + engines: {node: 20 || >=22} hasBin: true robust-predicates@3.0.2: - resolution: - { - integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==, - } + resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} rollup-plugin-visualizer@6.0.5: - resolution: - { - integrity: sha512-9+HlNgKCVbJDs8tVtjQ43US12eqaiHyyiLMdBwQ7vSZPiHMysGNo2E88TAp1si5wx8NAoYriI2A5kuKfIakmJg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-9+HlNgKCVbJDs8tVtjQ43US12eqaiHyyiLMdBwQ7vSZPiHMysGNo2E88TAp1si5wx8NAoYriI2A5kuKfIakmJg==} + engines: {node: '>=18'} hasBin: true peerDependencies: rolldown: 1.x || ^1.0.0-beta @@ -13549,776 +8890,437 @@ packages: optional: true rollup@4.57.1: - resolution: - { - integrity: sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==, - } - engines: { node: '>=18.0.0', npm: '>=8.0.0' } + resolution: {integrity: sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true roughjs@4.6.6: - resolution: - { - integrity: sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==, - } + resolution: {integrity: sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==} router@2.2.0: - resolution: - { - integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==, - } - engines: { node: '>= 18' } + resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} + engines: {node: '>= 18'} run-async@2.4.1: - resolution: - { - integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==, - } - engines: { node: '>=0.12.0' } + resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} + engines: {node: '>=0.12.0'} run-parallel@1.2.0: - resolution: - { - integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==, - } + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} ruru-components@2.0.0-rc.4: - resolution: - { - integrity: sha512-P/+ISRxa8zgfp4dPiew7asaYtWKyJMpJu85BToSGKXvx/G5eff1b1LiVEj6Xd5gWBQnr3BDor/r8eZNKr6MBLA==, - } - engines: { node: '>=22' } + resolution: {integrity: sha512-P/+ISRxa8zgfp4dPiew7asaYtWKyJMpJu85BToSGKXvx/G5eff1b1LiVEj6Xd5gWBQnr3BDor/r8eZNKr6MBLA==} + engines: {node: '>=22'} peerDependencies: graphql: ^16.9.0 ruru@2.0.0-rc.4: - resolution: - { - integrity: sha512-MtirhxDUpeK3Z9etvwjicpGjMzloew18Skg/yfEV5lDnt5PrCdQDLi3fFqYNnqRO0NgEbbM7eo4utu3gUjYy9g==, - } - engines: { node: '>=22' } + resolution: {integrity: sha512-MtirhxDUpeK3Z9etvwjicpGjMzloew18Skg/yfEV5lDnt5PrCdQDLi3fFqYNnqRO0NgEbbM7eo4utu3gUjYy9g==} + engines: {node: '>=22'} hasBin: true peerDependencies: graphile-config: ^1.0.0-rc.3 graphql: ^16.9.0 rw@1.3.3: - resolution: - { - integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==, - } + resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} rxjs@7.8.2: - resolution: - { - integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==, - } + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} safe-buffer@5.1.2: - resolution: - { - integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==, - } + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} safe-buffer@5.2.1: - resolution: - { - integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==, - } + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} safer-buffer@2.1.2: - resolution: - { - integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==, - } + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} scheduler@0.27.0: - resolution: - { - integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==, - } + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} semver@5.7.2: - resolution: - { - integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==, - } + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true semver@6.3.1: - resolution: - { - integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==, - } + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true semver@7.7.3: - resolution: - { - integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} + engines: {node: '>=10'} hasBin: true semver@7.7.4: - resolution: - { - integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + engines: {node: '>=10'} hasBin: true send@1.2.1: - resolution: - { - integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==, - } - engines: { node: '>= 18' } + resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} + engines: {node: '>= 18'} serve-static@2.2.1: - resolution: - { - integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==, - } - engines: { node: '>= 18' } + resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} + engines: {node: '>= 18'} set-blocking@2.0.0: - resolution: - { - integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==, - } + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} set-value@4.1.0: - resolution: - { - integrity: sha512-zTEg4HL0RwVrqcWs3ztF+x1vkxfm0lP+MQQFPiMJTKVceBwEV0A569Ou8l9IYQG8jOZdMVI1hGsc0tmeD2o/Lw==, - } - engines: { node: '>=11.0' } + resolution: {integrity: sha512-zTEg4HL0RwVrqcWs3ztF+x1vkxfm0lP+MQQFPiMJTKVceBwEV0A569Ou8l9IYQG8jOZdMVI1hGsc0tmeD2o/Lw==} + engines: {node: '>=11.0'} setprototypeof@1.2.0: - resolution: - { - integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==, - } + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} shallow-clone@3.0.1: - resolution: - { - integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} + engines: {node: '>=8'} shallowequal@1.1.0: - resolution: - { - integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==, - } + resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} shebang-command@2.0.0: - resolution: - { - integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} shebang-regex@3.0.0: - resolution: - { - integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} shelljs@0.10.0: - resolution: - { - integrity: sha512-Jex+xw5Mg2qMZL3qnzXIfaxEtBaC4n7xifqaqtrZDdlheR70OGkydrPJWT0V1cA1k3nanC86x9FwAmQl6w3Klw==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-Jex+xw5Mg2qMZL3qnzXIfaxEtBaC4n7xifqaqtrZDdlheR70OGkydrPJWT0V1cA1k3nanC86x9FwAmQl6w3Klw==} + engines: {node: '>=18'} side-channel-list@1.0.0: - resolution: - { - integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} side-channel-map@1.0.1: - resolution: - { - integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} side-channel-weakmap@1.0.2: - resolution: - { - integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} side-channel@1.1.0: - resolution: - { - integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} signal-exit@3.0.7: - resolution: - { - integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==, - } + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} signal-exit@4.1.0: - resolution: - { - integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==, - } - engines: { node: '>=14' } + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} sigstore@2.3.1: - resolution: - { - integrity: sha512-8G+/XDU8wNsJOQS5ysDVO0Etg9/2uA5gR9l4ZwijjlwxBcrU6RPfwi2+jJmbP+Ap1Hlp/nVAaEO4Fj22/SL2gQ==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-8G+/XDU8wNsJOQS5ysDVO0Etg9/2uA5gR9l4ZwijjlwxBcrU6RPfwi2+jJmbP+Ap1Hlp/nVAaEO4Fj22/SL2gQ==} + engines: {node: ^16.14.0 || >=18.0.0} simple-update-notifier@2.0.0: - resolution: - { - integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} + engines: {node: '>=10'} slash@3.0.0: - resolution: - { - integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} slick@1.12.2: - resolution: - { - integrity: sha512-4qdtOGcBjral6YIBCWJ0ljFSKNLz9KkhbWtuGvUyRowl1kxfuE1x/Z/aJcaiilpb3do9bl5K7/1h9XC5wWpY/A==, - } + resolution: {integrity: sha512-4qdtOGcBjral6YIBCWJ0ljFSKNLz9KkhbWtuGvUyRowl1kxfuE1x/Z/aJcaiilpb3do9bl5K7/1h9XC5wWpY/A==} smart-buffer@4.2.0: - resolution: - { - integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==, - } - engines: { node: '>= 6.0.0', npm: '>= 3.0.0' } + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} smtp-server@3.18.0: - resolution: - { - integrity: sha512-xINTnh0H8JDAKOAGSnFX8mgXB/L4Oz8dG4P0EgKAzJEszngxEEx4vOys+yNpsUc6yIyTKS8m2BcIffq4Htma/w==, - } - engines: { node: '>=18.18.0' } + resolution: {integrity: sha512-xINTnh0H8JDAKOAGSnFX8mgXB/L4Oz8dG4P0EgKAzJEszngxEEx4vOys+yNpsUc6yIyTKS8m2BcIffq4Htma/w==} + engines: {node: '>=18.18.0'} socks-proxy-agent@8.0.5: - resolution: - { - integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==, - } - engines: { node: '>= 14' } + resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} + engines: {node: '>= 14'} socks@2.8.7: - resolution: - { - integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==, - } - engines: { node: '>= 10.0.0', npm: '>= 3.0.0' } + resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} sort-keys@2.0.0: - resolution: - { - integrity: sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==} + engines: {node: '>=4'} sorted-array-functions@1.3.0: - resolution: - { - integrity: sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==, - } + resolution: {integrity: sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==} source-map-js@1.2.1: - resolution: - { - integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} source-map-resolve@0.6.0: - resolution: - { - integrity: sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==, - } + resolution: {integrity: sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==} deprecated: See https://github.com/lydell/source-map-resolve#deprecated source-map-support@0.5.13: - resolution: - { - integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==, - } + resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} source-map@0.6.1: - resolution: - { - integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} source-map@0.7.6: - resolution: - { - integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==, - } - engines: { node: '>= 12' } + resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} + engines: {node: '>= 12'} spdx-correct@3.2.0: - resolution: - { - integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==, - } + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} spdx-exceptions@2.5.0: - resolution: - { - integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==, - } + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} spdx-expression-parse@3.0.1: - resolution: - { - integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==, - } + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} spdx-license-ids@3.0.22: - resolution: - { - integrity: sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==, - } + resolution: {integrity: sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==} split2@3.2.2: - resolution: - { - integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==, - } + resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==} split2@4.2.0: - resolution: - { - integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==, - } - engines: { node: '>= 10.x' } + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} split@1.0.1: - resolution: - { - integrity: sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==, - } + resolution: {integrity: sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==} sprintf-js@1.0.3: - resolution: - { - integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==, - } + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} ssri@10.0.6: - resolution: - { - integrity: sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} stack-utils@2.0.6: - resolution: - { - integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} statuses@1.5.0: - resolution: - { - integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==, - } - engines: { node: '>= 0.6' } + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} + engines: {node: '>= 0.6'} statuses@2.0.2: - resolution: - { - integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==, - } - engines: { node: '>= 0.8' } + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} stream-browserify@3.0.0: - resolution: - { - integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==, - } + resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} streamsearch@0.1.2: - resolution: - { - integrity: sha512-jos8u++JKm0ARcSUTAZXOVC0mSox7Bhn6sBgty73P1f3JGf7yG2clTbBNHUdde/kdvP2FESam+vM6l8jBrNxHA==, - } - engines: { node: '>=0.8.0' } + resolution: {integrity: sha512-jos8u++JKm0ARcSUTAZXOVC0mSox7Bhn6sBgty73P1f3JGf7yG2clTbBNHUdde/kdvP2FESam+vM6l8jBrNxHA==} + engines: {node: '>=0.8.0'} strfy-js@3.1.10: - resolution: - { - integrity: sha512-KQXNrvhnWpn4ya25WSG6EvJC6oqdeXlwMoitGl3qEJ2wnELV/sQO6uBy6CsIWTsVOMAt0B7/xvM40ucu5c8AuA==, - } + resolution: {integrity: sha512-KQXNrvhnWpn4ya25WSG6EvJC6oqdeXlwMoitGl3qEJ2wnELV/sQO6uBy6CsIWTsVOMAt0B7/xvM40ucu5c8AuA==} string-length@4.0.2: - resolution: - { - integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} string-width@4.2.3: - resolution: - { - integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} string-width@5.1.2: - resolution: - { - integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} string_decoder@0.10.31: - resolution: - { - integrity: sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==, - } + resolution: {integrity: sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==} string_decoder@1.1.1: - resolution: - { - integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==, - } + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} string_decoder@1.3.0: - resolution: - { - integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==, - } + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} strip-ansi@6.0.1: - resolution: - { - integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} strip-ansi@7.1.2: - resolution: - { - integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} + engines: {node: '>=12'} strip-bom@3.0.0: - resolution: - { - integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} strip-bom@4.0.0: - resolution: - { - integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} strip-final-newline@2.0.0: - resolution: - { - integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} strip-indent@3.0.0: - resolution: - { - integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} strip-json-comments@3.1.1: - resolution: - { - integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} strnum@2.1.2: - resolution: - { - integrity: sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ==, - } + resolution: {integrity: sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ==} styled-components@5.3.11: - resolution: - { - integrity: sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==} + engines: {node: '>=10'} peerDependencies: react: '>= 16.8.0' react-dom: '>= 16.8.0' react-is: '>= 16.8.0' styled-system@5.1.5: - resolution: - { - integrity: sha512-7VoD0o2R3RKzOzPK0jYrVnS8iJdfkKsQJNiLRDjikOpQVqQHns/DXWaPZOH4tIKkhAT7I6wIsy9FWTWh2X3q+A==, - } + resolution: {integrity: sha512-7VoD0o2R3RKzOzPK0jYrVnS8iJdfkKsQJNiLRDjikOpQVqQHns/DXWaPZOH4tIKkhAT7I6wIsy9FWTWh2X3q+A==} stylis@4.3.6: - resolution: - { - integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==, - } + resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==} superagent@10.3.0: - resolution: - { - integrity: sha512-B+4Ik7ROgVKrQsXTV0Jwp2u+PXYLSlqtDAhYnkkD+zn3yg8s/zjA2MeGayPoY/KICrbitwneDHrjSotxKL+0XQ==, - } - engines: { node: '>=14.18.0' } + resolution: {integrity: sha512-B+4Ik7ROgVKrQsXTV0Jwp2u+PXYLSlqtDAhYnkkD+zn3yg8s/zjA2MeGayPoY/KICrbitwneDHrjSotxKL+0XQ==} + engines: {node: '>=14.18.0'} supertest@7.2.2: - resolution: - { - integrity: sha512-oK8WG9diS3DlhdUkcFn4tkNIiIbBx9lI2ClF8K+b2/m8Eyv47LSawxUzZQSNKUrVb2KsqeTDCcjAAVPYaSLVTA==, - } - engines: { node: '>=14.18.0' } + resolution: {integrity: sha512-oK8WG9diS3DlhdUkcFn4tkNIiIbBx9lI2ClF8K+b2/m8Eyv47LSawxUzZQSNKUrVb2KsqeTDCcjAAVPYaSLVTA==} + engines: {node: '>=14.18.0'} supports-color@5.5.0: - resolution: - { - integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} supports-color@7.2.0: - resolution: - { - integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} supports-color@8.1.1: - resolution: - { - integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} supports-preserve-symlinks-flag@1.0.0: - resolution: - { - integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} synckit@0.11.12: - resolution: - { - integrity: sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==, - } - engines: { node: ^14.18.0 || >=16.0.0 } + resolution: {integrity: sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==} + engines: {node: ^14.18.0 || >=16.0.0} tabbable@6.4.0: - resolution: - { - integrity: sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==, - } + resolution: {integrity: sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==} tamedevil@0.1.0-rc.4: - resolution: - { - integrity: sha512-w6gmlfoKCBfOTjLzTVcUmEPuhWEes2lFZkC+y+KLsP3AUNiRZcyAgefosCaxOEehlHB6Rt4jRbFDSMBxQbGsug==, - } - engines: { node: '>=22' } + resolution: {integrity: sha512-w6gmlfoKCBfOTjLzTVcUmEPuhWEes2lFZkC+y+KLsP3AUNiRZcyAgefosCaxOEehlHB6Rt4jRbFDSMBxQbGsug==} + engines: {node: '>=22'} tar-stream@2.2.0: - resolution: - { - integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} tar@6.2.1: - resolution: - { - integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} + engines: {node: '>=10'} deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me temp-dir@1.0.0: - resolution: - { - integrity: sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==} + engines: {node: '>=4'} test-exclude@6.0.0: - resolution: - { - integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} text-extensions@1.9.0: - resolution: - { - integrity: sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==, - } - engines: { node: '>=0.10' } + resolution: {integrity: sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==} + engines: {node: '>=0.10'} through2@2.0.5: - resolution: - { - integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==, - } + resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} through2@3.0.2: - resolution: - { - integrity: sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==, - } + resolution: {integrity: sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==} through@2.3.8: - resolution: - { - integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==, - } + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} tinyexec@1.0.2: - resolution: - { - integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} + engines: {node: '>=18'} tinyglobby@0.2.12: - resolution: - { - integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==, - } - engines: { node: '>=12.0.0' } + resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} + engines: {node: '>=12.0.0'} tinyglobby@0.2.15: - resolution: - { - integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==, - } - engines: { node: '>=12.0.0' } + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} tinypool@2.0.0: - resolution: - { - integrity: sha512-/RX9RzeH2xU5ADE7n2Ykvmi9ED3FBGPAjw9u3zucrNNaEBIO0HPSYgL0NT7+3p147ojeSdaVu08F6hjpv31HJg==, - } - engines: { node: ^20.0.0 || >=22.0.0 } + resolution: {integrity: sha512-/RX9RzeH2xU5ADE7n2Ykvmi9ED3FBGPAjw9u3zucrNNaEBIO0HPSYgL0NT7+3p147ojeSdaVu08F6hjpv31HJg==} + engines: {node: ^20.0.0 || >=22.0.0} tmp@0.2.5: - resolution: - { - integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==, - } - engines: { node: '>=14.14' } + resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==} + engines: {node: '>=14.14'} tmpl@1.0.5: - resolution: - { - integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==, - } + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} to-regex-range@5.0.1: - resolution: - { - integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==, - } - engines: { node: '>=8.0' } + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} toidentifier@1.0.1: - resolution: - { - integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==, - } - engines: { node: '>=0.6' } + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} touch@3.1.1: - resolution: - { - integrity: sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==, - } + resolution: {integrity: sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==} hasBin: true tr46@0.0.3: - resolution: - { - integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==, - } + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} transliteration@2.6.1: - resolution: - { - integrity: sha512-hJ9BhrQAOnNTbpOr1MxsNjZISkn7ppvF5TKUeFmTE1mG4ZPD/XVxF0L0LUoIUCWmQyxH0gJpVtfYLAWf298U9w==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-hJ9BhrQAOnNTbpOr1MxsNjZISkn7ppvF5TKUeFmTE1mG4ZPD/XVxF0L0LUoIUCWmQyxH0gJpVtfYLAWf298U9w==} + engines: {node: '>=20.0.0'} hasBin: true treeverse@3.0.0: - resolution: - { - integrity: sha512-gcANaAnd2QDZFmHFEOF4k7uc1J/6a6z3DJMd/QwEyxLoKGiptJRwid582r7QIsFlFMIZ3SnxfS52S4hm2DHkuQ==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-gcANaAnd2QDZFmHFEOF4k7uc1J/6a6z3DJMd/QwEyxLoKGiptJRwid582r7QIsFlFMIZ3SnxfS52S4hm2DHkuQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} trim-newlines@3.0.1: - resolution: - { - integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} + engines: {node: '>=8'} ts-api-utils@2.4.0: - resolution: - { - integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==, - } - engines: { node: '>=18.12' } + resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==} + engines: {node: '>=18.12'} peerDependencies: typescript: '>=4.8.4' ts-dedent@2.2.0: - resolution: - { - integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==, - } - engines: { node: '>=6.10' } + resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} + engines: {node: '>=6.10'} ts-jest@29.4.6: - resolution: - { - integrity: sha512-fSpWtOO/1AjSNQguk43hb/JCo16oJDnMJf3CdEGNkqsEX3t0KX96xvyX1D7PfLCpVoKu4MfVrqUkFyblYoY4lA==, - } - engines: { node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0 } + resolution: {integrity: sha512-fSpWtOO/1AjSNQguk43hb/JCo16oJDnMJf3CdEGNkqsEX3t0KX96xvyX1D7PfLCpVoKu4MfVrqUkFyblYoY4lA==} + engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: '@babel/core': '>=7.0.0-beta.0 <8' @@ -14344,10 +9346,7 @@ packages: optional: true ts-node@10.9.2: - resolution: - { - integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==, - } + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} hasBin: true peerDependencies: '@swc/core': '>=1.2.50' @@ -14361,263 +9360,149 @@ packages: optional: true tsconfig-paths@4.2.0: - resolution: - { - integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} + engines: {node: '>=6'} tslib@2.8.1: - resolution: - { - integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==, - } + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} tsx@4.21.0: - resolution: - { - integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} + engines: {node: '>=18.0.0'} hasBin: true tuf-js@2.2.1: - resolution: - { - integrity: sha512-GwIJau9XaA8nLVbUXsN3IlFi7WmQ48gBUrl3FTkkL/XLu/POhBzfmX9hd33FNMX1qAsfl6ozO1iMmW9NC8YniA==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-GwIJau9XaA8nLVbUXsN3IlFi7WmQ48gBUrl3FTkkL/XLu/POhBzfmX9hd33FNMX1qAsfl6ozO1iMmW9NC8YniA==} + engines: {node: ^16.14.0 || >=18.0.0} type-check@0.4.0: - resolution: - { - integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==, - } - engines: { node: '>= 0.8.0' } + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} type-detect@4.0.8: - resolution: - { - integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} type-fest@0.18.1: - resolution: - { - integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==} + engines: {node: '>=10'} type-fest@0.21.3: - resolution: - { - integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} type-fest@0.4.1: - resolution: - { - integrity: sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw==} + engines: {node: '>=6'} type-fest@0.6.0: - resolution: - { - integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} type-fest@0.8.1: - resolution: - { - integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} type-fest@4.41.0: - resolution: - { - integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==, - } - engines: { node: '>=16' } + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} + engines: {node: '>=16'} type-is@2.0.1: - resolution: - { - integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==, - } - engines: { node: '>= 0.6' } + resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==} + engines: {node: '>= 0.6'} typedarray@0.0.6: - resolution: - { - integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==, - } + resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} typescript@5.9.3: - resolution: - { - integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==, - } - engines: { node: '>=14.17' } + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} hasBin: true uc.micro@2.1.0: - resolution: - { - integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==, - } + resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} ufo@1.6.3: - resolution: - { - integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==, - } + resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==} uglify-js@3.19.3: - resolution: - { - integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==, - } - engines: { node: '>=0.8.0' } + resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} + engines: {node: '>=0.8.0'} hasBin: true uglify-js@3.4.10: - resolution: - { - integrity: sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==, - } - engines: { node: '>=0.8.0' } + resolution: {integrity: sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==} + engines: {node: '>=0.8.0'} hasBin: true undefsafe@2.0.5: - resolution: - { - integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==, - } + resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} undici-types@5.26.5: - resolution: - { - integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==, - } + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} undici-types@6.21.0: - resolution: - { - integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==, - } + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} undici@7.16.0: - resolution: - { - integrity: sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==, - } - engines: { node: '>=20.18.1' } + resolution: {integrity: sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==} + engines: {node: '>=20.18.1'} undici@7.19.0: - resolution: - { - integrity: sha512-Heho1hJD81YChi+uS2RkSjcVO+EQLmLSyUlHyp7Y/wFbxQaGb4WXVKD073JytrjXJVkSZVzoE2MCSOKugFGtOQ==, - } - engines: { node: '>=20.18.1' } + resolution: {integrity: sha512-Heho1hJD81YChi+uS2RkSjcVO+EQLmLSyUlHyp7Y/wFbxQaGb4WXVKD073JytrjXJVkSZVzoE2MCSOKugFGtOQ==} + engines: {node: '>=20.18.1'} unique-filename@3.0.0: - resolution: - { - integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} unique-slug@4.0.0: - resolution: - { - integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} universal-user-agent@6.0.1: - resolution: - { - integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==, - } + resolution: {integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==} universalify@2.0.1: - resolution: - { - integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==, - } - engines: { node: '>= 10.0.0' } + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} unload@2.2.0: - resolution: - { - integrity: sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==, - } + resolution: {integrity: sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==} unpipe@1.0.0: - resolution: - { - integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==, - } - engines: { node: '>= 0.8' } + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} unrs-resolver@1.11.1: - resolution: - { - integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==, - } + resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} untildify@4.0.0: - resolution: - { - integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} + engines: {node: '>=8'} upath@2.0.1: - resolution: - { - integrity: sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==} + engines: {node: '>=4'} update-browserslist-db@1.2.3: - resolution: - { - integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==, - } + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' upper-case@1.1.3: - resolution: - { - integrity: sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==, - } + resolution: {integrity: sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==} uri-js@4.4.1: - resolution: - { - integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==, - } + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} url-join@4.0.1: - resolution: - { - integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==, - } + resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==} use-callback-ref@1.3.3: - resolution: - { - integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} + engines: {node: '>=10'} peerDependencies: '@types/react': '*' react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc @@ -14626,11 +9511,8 @@ packages: optional: true use-sidecar@1.1.3: - resolution: - { - integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} + engines: {node: '>=10'} peerDependencies: '@types/react': '*' react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc @@ -14639,79 +9521,46 @@ packages: optional: true use-sync-external-store@1.6.0: - resolution: - { - integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==, - } + resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 util-deprecate@1.0.2: - resolution: - { - integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==, - } + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} uuid@10.0.0: - resolution: - { - integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==, - } + resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} hasBin: true uuid@11.1.0: - resolution: - { - integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==, - } + resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} hasBin: true v8-compile-cache-lib@3.0.1: - resolution: - { - integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==, - } + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} v8-to-istanbul@9.3.0: - resolution: - { - integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==, - } - engines: { node: '>=10.12.0' } + resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} + engines: {node: '>=10.12.0'} valid-data-url@3.0.1: - resolution: - { - integrity: sha512-jOWVmzVceKlVVdwjNSenT4PbGghU0SBIizAev8ofZVgivk/TVHXSbNL8LP6M3spZvkR9/QolkyJavGSX5Cs0UA==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-jOWVmzVceKlVVdwjNSenT4PbGghU0SBIizAev8ofZVgivk/TVHXSbNL8LP6M3spZvkR9/QolkyJavGSX5Cs0UA==} + engines: {node: '>=10'} validate-npm-package-license@3.0.4: - resolution: - { - integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==, - } + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} validate-npm-package-name@5.0.1: - resolution: - { - integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} vary@1.1.2: - resolution: - { - integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==, - } - engines: { node: '>= 0.8' } + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} vite@6.4.1: - resolution: - { - integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==, - } - engines: { node: ^18.0.0 || ^20.0.0 || >=22.0.0 } + resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 @@ -14750,202 +9599,112 @@ packages: optional: true vscode-jsonrpc@8.2.0: - resolution: - { - integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==, - } - engines: { node: '>=14.0.0' } + resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==} + engines: {node: '>=14.0.0'} vscode-languageserver-protocol@3.17.5: - resolution: - { - integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==, - } + resolution: {integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==} vscode-languageserver-textdocument@1.0.12: - resolution: - { - integrity: sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==, - } + resolution: {integrity: sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==} vscode-languageserver-types@3.17.5: - resolution: - { - integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==, - } + resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==} vscode-languageserver@9.0.1: - resolution: - { - integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==, - } + resolution: {integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==} hasBin: true vscode-uri@3.0.8: - resolution: - { - integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==, - } + resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==} walk-up-path@3.0.1: - resolution: - { - integrity: sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==, - } + resolution: {integrity: sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==} walker@1.0.8: - resolution: - { - integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==, - } + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} warning@3.0.0: - resolution: - { - integrity: sha512-jMBt6pUrKn5I+OGgtQ4YZLdhIeJmObddh6CsibPxyQ5yPZm1XExSyzC1LCNX7BzhxWgiHmizBWJTHJIjMjTQYQ==, - } + resolution: {integrity: sha512-jMBt6pUrKn5I+OGgtQ4YZLdhIeJmObddh6CsibPxyQ5yPZm1XExSyzC1LCNX7BzhxWgiHmizBWJTHJIjMjTQYQ==} wcwidth@1.0.1: - resolution: - { - integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==, - } + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} web-resource-inliner@5.0.0: - resolution: - { - integrity: sha512-AIihwH+ZmdHfkJm7BjSXiEClVt4zUFqX4YlFAzjL13wLtDuUneSaFvDBTbdYRecs35SiU7iNKbMnN+++wVfb6A==, - } - engines: { node: '>=10.0.0' } + resolution: {integrity: sha512-AIihwH+ZmdHfkJm7BjSXiEClVt4zUFqX4YlFAzjL13wLtDuUneSaFvDBTbdYRecs35SiU7iNKbMnN+++wVfb6A==} + engines: {node: '>=10.0.0'} webidl-conversions@3.0.1: - resolution: - { - integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==, - } + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} whatwg-encoding@3.1.1: - resolution: - { - integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation whatwg-mimetype@4.0.0: - resolution: - { - integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} whatwg-url@5.0.0: - resolution: - { - integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==, - } + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} which-module@2.0.1: - resolution: - { - integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==, - } + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} which@2.0.2: - resolution: - { - integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==, - } - engines: { node: '>= 8' } + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} hasBin: true which@4.0.0: - resolution: - { - integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==, - } - engines: { node: ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==} + engines: {node: ^16.13.0 || >=18.0.0} hasBin: true wide-align@1.1.5: - resolution: - { - integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==, - } + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} word-wrap@1.2.5: - resolution: - { - integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} wordwrap@1.0.0: - resolution: - { - integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==, - } + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} wrap-ansi@6.2.0: - resolution: - { - integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} wrap-ansi@7.0.0: - resolution: - { - integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} wrap-ansi@8.1.0: - resolution: - { - integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} wrappy@1.0.2: - resolution: - { - integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==, - } + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} write-file-atomic@2.4.3: - resolution: - { - integrity: sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==, - } + resolution: {integrity: sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==} write-file-atomic@5.0.1: - resolution: - { - integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} write-json-file@3.2.0: - resolution: - { - integrity: sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==} + engines: {node: '>=6'} write-pkg@4.0.0: - resolution: - { - integrity: sha512-v2UQ+50TNf2rNHJ8NyWttfm/EJUBWMJcx6ZTYZr6Qp52uuegWw/lBkCtCbnYZEmPRNL61m+u67dAmGxo+HTULA==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-v2UQ+50TNf2rNHJ8NyWttfm/EJUBWMJcx6ZTYZr6Qp52uuegWw/lBkCtCbnYZEmPRNL61m+u67dAmGxo+HTULA==} + engines: {node: '>=8'} ws@8.19.0: - resolution: - { - integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==, - } - engines: { node: '>=10.0.0' } + resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==} + engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 utf-8-validate: '>=5.0.2' @@ -14956,119 +9715,68 @@ packages: optional: true xtend@4.0.2: - resolution: - { - integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==, - } - engines: { node: '>=0.4' } + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} y18n@4.0.3: - resolution: - { - integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==, - } + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} y18n@5.0.8: - resolution: - { - integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} yallist@3.1.1: - resolution: - { - integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==, - } + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} yallist@4.0.0: - resolution: - { - integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==, - } + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} yaml@2.8.2: - resolution: - { - integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==, - } - engines: { node: '>= 14.6' } + resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==} + engines: {node: '>= 14.6'} hasBin: true yanse@0.2.0: - resolution: - { - integrity: sha512-BN6WYjJRX3mw/LpEC4d2LAlLFFdoFKKYYbd9nvhTvbbEW+/mJJccBGy0DuvcYXg75Xed2ZT8euXtplfLKBfdHA==, - } + resolution: {integrity: sha512-BN6WYjJRX3mw/LpEC4d2LAlLFFdoFKKYYbd9nvhTvbbEW+/mJJccBGy0DuvcYXg75Xed2ZT8euXtplfLKBfdHA==} yanse@0.2.1: - resolution: - { - integrity: sha512-SMi3ZO1IqsvPLLXuy8LBCP1orqcjOT8VygiuyAlplaGeH2g+n4ZSSyWlA/BZjuUuN58TyOcz89mVkflSqIPxxQ==, - } + resolution: {integrity: sha512-SMi3ZO1IqsvPLLXuy8LBCP1orqcjOT8VygiuyAlplaGeH2g+n4ZSSyWlA/BZjuUuN58TyOcz89mVkflSqIPxxQ==} yargs-parser@18.1.3: - resolution: - { - integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} yargs-parser@20.2.9: - resolution: - { - integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} yargs-parser@21.1.1: - resolution: - { - integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} yargs@15.4.1: - resolution: - { - integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} + engines: {node: '>=8'} yargs@16.2.0: - resolution: - { - integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} yargs@17.7.2: - resolution: - { - integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} yn@3.1.1: - resolution: - { - integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} yocto-queue@0.1.0: - resolution: - { - integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} zustand@5.0.11: - resolution: - { - integrity: sha512-fdZY+dk7zn/vbWNCYmzZULHRrss0jx5pPFiOuMZ/5HJN6Yv3u+1Wswy/4MpZEkEGhtNH+pwxZB8OKgUBPzYAGg==, - } - engines: { node: '>=12.20.0' } + resolution: {integrity: sha512-fdZY+dk7zn/vbWNCYmzZULHRrss0jx5pPFiOuMZ/5HJN6Yv3u+1Wswy/4MpZEkEGhtNH+pwxZB8OKgUBPzYAGg==} + engines: {node: '>=12.20.0'} peerDependencies: '@types/react': '>=18.0.0' immer: '>=9.0.6' @@ -15085,6 +9793,7 @@ packages: optional: true snapshots: + '@0no-co/graphql.web@1.2.0(graphql@15.10.1)': optionalDependencies: graphql: 15.10.1 @@ -16486,7 +11195,7 @@ snapshots: '@graphiql/plugin-doc-explorer@0.4.1(@graphiql/react@0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)))(@types/react@19.2.13)(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3))': dependencies: - '@graphiql/react': 0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) + '@graphiql/react': 0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@20.19.27)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) '@headlessui/react': 2.2.9(react-dom@19.2.3(react@19.2.3))(react@19.2.3) graphql: 16.12.0 react: 19.2.3 @@ -16500,7 +11209,7 @@ snapshots: '@graphiql/plugin-explorer@5.1.1(@graphiql/react@0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)))(graphql@16.12.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: - '@graphiql/react': 0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) + '@graphiql/react': 0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@20.19.27)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) graphiql-explorer: 0.9.0(graphql@16.12.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) graphql: 16.12.0 react: 19.2.3 @@ -16508,8 +11217,8 @@ snapshots: '@graphiql/plugin-history@0.4.1(@graphiql/react@0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)))(@types/node@22.19.11)(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3))': dependencies: - '@graphiql/react': 0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) - '@graphiql/toolkit': 0.11.3(@types/node@22.19.11)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0) + '@graphiql/react': 0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@20.19.27)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) + '@graphiql/toolkit': 0.11.3(@types/node@20.19.27)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0) react: 19.2.3 react-compiler-runtime: 19.1.0-rc.1(react@19.2.3) react-dom: 19.2.3(react@19.2.3) @@ -16522,9 +11231,9 @@ snapshots: - immer - use-sync-external-store - '@graphiql/react@0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3))': + '@graphiql/react@0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@20.19.27)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3))': dependencies: - '@graphiql/toolkit': 0.11.3(@types/node@22.19.11)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0) + '@graphiql/toolkit': 0.11.3(@types/node@20.19.27)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0) '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@radix-ui/react-dropdown-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@radix-ui/react-tooltip': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -16553,11 +11262,11 @@ snapshots: - immer - use-sync-external-store - '@graphiql/toolkit@0.11.3(@types/node@22.19.11)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)': + '@graphiql/toolkit@0.11.3(@types/node@20.19.27)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)': dependencies: '@n1ru4l/push-pull-async-iterable-iterator': 3.2.0 graphql: 16.12.0 - meros: 1.3.2(@types/node@22.19.11) + meros: 1.3.2(@types/node@20.19.27) optionalDependencies: graphql-ws: 6.0.7(graphql@16.12.0)(ws@8.19.0) transitivePeerDependencies: @@ -20813,7 +15522,7 @@ snapshots: dependencies: '@graphiql/plugin-doc-explorer': 0.4.1(@graphiql/react@0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)))(@types/react@19.2.13)(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) '@graphiql/plugin-history': 0.4.1(@graphiql/react@0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)))(@types/node@22.19.11)(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) - '@graphiql/react': 0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) + '@graphiql/react': 0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@20.19.27)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) graphql: 16.12.0 react: 19.2.3 react-compiler-runtime: 19.1.0-rc.1(react@19.2.3) @@ -22013,9 +16722,9 @@ snapshots: ts-dedent: 2.2.0 uuid: 11.1.0 - meros@1.3.2(@types/node@22.19.11): + meros@1.3.2(@types/node@20.19.27): optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 20.19.27 methods@1.1.2: {} @@ -23437,8 +18146,8 @@ snapshots: '@graphiql/plugin-doc-explorer': 0.4.1(@graphiql/react@0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)))(@types/react@19.2.13)(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) '@graphiql/plugin-explorer': 5.1.1(@graphiql/react@0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)))(graphql@16.12.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@graphiql/plugin-history': 0.4.1(@graphiql/react@0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)))(@types/node@22.19.11)(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) - '@graphiql/react': 0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) - '@graphiql/toolkit': 0.11.3(@types/node@22.19.11)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0) + '@graphiql/react': 0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@20.19.27)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) + '@graphiql/toolkit': 0.11.3(@types/node@20.19.27)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0) '@types/node': 22.19.11 grafast: 1.0.0-rc.4(graphql@16.12.0) graphiql: 5.2.2(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) @@ -23951,24 +18660,6 @@ snapshots: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - ts-node@10.9.2(@types/node@22.19.11)(typescript@5.9.3): - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.12 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 22.19.11 - acorn: 8.15.0 - acorn-walk: 8.3.4 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 5.9.3 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - tsconfig-paths@4.2.0: dependencies: json5: 2.2.3 From 922c718c9bfb74f3a9c9fcbb9062f156ce830e92 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Tue, 17 Feb 2026 10:05:57 +0000 Subject: [PATCH 02/23] test(codegen): add CLI generator snapshot tests - Add cli-generator.test.ts with 13 tests covering all generated files - Snapshot executor, context, auth, table commands, custom commands, command map - Verify ORM method calls in table and custom commands - Verify appstash config-store usage in executor - Fix: runOrm now includes runCli so ORM is auto-enabled when CLI is enabled --- .../__snapshots__/cli-generator.test.ts.snap | 838 ++++++++++++++++++ .../__tests__/codegen/cli-generator.test.ts | 229 +++++ graphql/codegen/src/core/generate.ts | 4 +- 3 files changed, 1069 insertions(+), 2 deletions(-) create mode 100644 graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap create mode 100644 graphql/codegen/src/__tests__/codegen/cli-generator.test.ts diff --git a/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap b/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap new file mode 100644 index 000000000..092b8c18e --- /dev/null +++ b/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap @@ -0,0 +1,838 @@ +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing + +exports[`cli-generator generates commands.ts (command map) 1`] = ` +"/** + * CLI command map and entry point + * @generated by @constructive-io/graphql-codegen + * DO NOT EDIT - changes will be overwritten + */ +import { CLIOptions, Inquirerer, extractFirst } from "inquirerer"; +import contextCmd from "./commands/context"; +import authCmd from "./commands/auth"; +import carCmd from "./commands/car"; +import driverCmd from "./commands/driver"; +import currentUserCmd from "./commands/current-user"; +import loginCmd from "./commands/login"; +const createCommandMap = () => ({ + "context": contextCmd, + "auth": authCmd, + "car": carCmd, + "driver": driverCmd, + "current-user": currentUserCmd, + "login": loginCmd +}); +const usage = "\\nmyapp \\n\\nCommands:\\n context Manage API contexts\\n auth Manage authentication\\n car car CRUD operations\\n driver driver CRUD operations\\n current-user Get the currently authenticated user\\n login Authenticate a user\\n\\n --help, -h Show this help message\\n --version, -v Show version\\n"; +export const commands = async (argv: Partial>, prompter: Inquirerer, options: CLIOptions) => { + if (argv.help || argv.h) { + console.log(usage); + process.exit(0); + } + let { + first: command, + newArgv + } = extractFirst(argv); + const commandMap = createCommandMap(); + if (!command) { + const answer = await prompter.prompt(argv, [{ + type: "autocomplete", + name: "command", + message: "What do you want to do?", + options: Object.keys(commandMap) + }]); + command = answer.command; + } + const commandFn = commandMap[command]; + if (!commandFn) { + console.log(usage); + console.error(\`Unknown command: \${command}\`); + process.exit(1); + } + await commandFn(newArgv, prompter, options); + prompter.close(); + return argv; +};" +`; + +exports[`cli-generator generates commands/auth.ts 1`] = ` +"/** + * Authentication commands + * @generated by @constructive-io/graphql-codegen + * DO NOT EDIT - changes will be overwritten + */ +import { CLIOptions, Inquirerer, extractFirst } from "inquirerer"; +import { getStore } from "../executor"; +const usage = "\\nmyapp auth \\n\\nCommands:\\n set-token Set API token for the current context\\n status Show authentication status\\n logout Remove credentials for the current context\\n\\nOptions:\\n --context Specify context (defaults to current context)\\n\\n --help, -h Show this help message\\n"; +export default async (argv: Partial>, prompter: Inquirerer, _options: CLIOptions) => { + if (argv.help || argv.h) { + console.log(usage); + process.exit(0); + } + const store = getStore(); + const { + first: subcommand, + newArgv + } = extractFirst(argv); + if (!subcommand) { + const answer = await prompter.prompt(argv, [{ + type: "autocomplete", + name: "subcommand", + message: "What do you want to do?", + options: ["set-token", "status", "logout"] + }]); + return handleAuthSubcommand(answer.subcommand, newArgv, prompter, store); + } + return handleAuthSubcommand(subcommand, newArgv, prompter, store); +}; +async function handleAuthSubcommand(subcommand: string, argv: Partial>, prompter: Inquirerer, store: ReturnType) { + switch (subcommand) { + case "set-token": + return handleSetToken(argv, prompter, store); + case "status": + return handleStatus(store); + case "logout": + return handleLogout(argv, prompter, store); + default: + console.log(usage); + process.exit(1); + } +} +async function handleSetToken(argv: Partial>, prompter: Inquirerer, store: ReturnType) { + const current = store.getCurrentContext(); + if (!current) { + console.error("No active context. Run \\"context create\\" first."); + process.exit(1); + } + const { + first: token + } = extractFirst(argv); + let tokenValue = token; + if (!tokenValue) { + const answer = await prompter.prompt(argv, [{ + type: "password", + name: "token", + message: "API Token", + required: true + }]); + tokenValue = answer.token; + } + store.setCredentials(current.name, { + token: String.call(tokenValue || "").trim() + }); + console.log(\`Token saved for context: \${current.name}\`); +} +function handleStatus(store: ReturnType) { + const contexts = store.listContexts(); + const settings = store.loadSettings(); + if (contexts.length === 0) { + console.log("No contexts configured."); + return; + } + console.log("Authentication Status:"); + for (const ctx of contexts) { + const isCurrent = ctx.name === settings.currentContext; + const hasAuth = store.hasValidCredentials(ctx.name); + const marker = isCurrent ? "* " : " "; + const status = hasAuth ? "authenticated" : "no token"; + console.log(\`\${marker}\${ctx.name} [\${status}]\`); + } +} +async function handleLogout(argv: Partial>, prompter: Inquirerer, store: ReturnType) { + const current = store.getCurrentContext(); + if (!current) { + console.log("No active context."); + return; + } + const confirm = await prompter.prompt(argv, [{ + type: "confirm", + name: "confirm", + message: \`Remove credentials for "\${current.name}"?\`, + default: false + }]); + if (!confirm.confirm) { + return; + } + if (store.removeCredentials(current.name)) { + console.log(\`Credentials removed for: \${current.name}\`); + } else { + console.log(\`No credentials found for: \${current.name}\`); + } +}" +`; + +exports[`cli-generator generates commands/car.ts 1`] = ` +"/** + * CLI commands for Car + * @generated by @constructive-io/graphql-codegen + * DO NOT EDIT - changes will be overwritten + */ +import { CLIOptions, Inquirerer, extractFirst } from "inquirerer"; +import { getClient } from "../executor"; +const usage = "\\ncar \\n\\nCommands:\\n list List all car records\\n get Get a car by ID\\n create Create a new car\\n update Update an existing car\\n delete Delete a car\\n\\n --help, -h Show this help message\\n"; +export default async (argv: Partial>, prompter: Inquirerer, _options: CLIOptions) => { + if (argv.help || argv.h) { + console.log(usage); + process.exit(0); + } + const { + first: subcommand, + newArgv + } = extractFirst(argv); + if (!subcommand) { + const answer = await prompter.prompt(argv, [{ + type: "autocomplete", + name: "subcommand", + message: "What do you want to do?", + options: ["list", "get", "create", "update", "delete"] + }]); + return handleTableSubcommand(answer.subcommand, newArgv, prompter); + } + return handleTableSubcommand(subcommand, newArgv, prompter); +}; +async function handleTableSubcommand(subcommand: string, argv: Partial>, prompter: Inquirerer) { + switch (subcommand) { + case "list": + return handleList(argv, prompter); + case "get": + return handleGet(argv, prompter); + case "create": + return handleCreate(argv, prompter); + case "update": + return handleUpdate(argv, prompter); + case "delete": + return handleDelete(argv, prompter); + default: + console.log(usage); + process.exit(1); + } +} +async function handleList(_argv: Partial>, _prompter: Inquirerer) { + try { + const client = getClient(); + const result = await client.car.findMany({ + select: { + id: true, + make: true, + model: true, + year: true, + isElectric: true, + createdAt: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to list records."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleGet(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "id", + message: "id", + required: true + }]); + const client = getClient(); + const result = await client.car.findOne({ + id: answers.id, + select: { + id: true, + make: true, + model: true, + year: true, + isElectric: true, + createdAt: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Record not found."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleCreate(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "make", + message: "make", + required: true + }, { + type: "text", + name: "model", + message: "model", + required: true + }, { + type: "text", + name: "year", + message: "year", + required: true + }, { + type: "text", + name: "isElectric", + message: "isElectric", + required: true + }]); + const client = getClient(); + const result = await client.car.create({ + data: { + make: answers.make, + model: answers.model, + year: answers.year, + isElectric: answers.isElectric + }, + select: { + id: true, + make: true, + model: true, + year: true, + isElectric: true, + createdAt: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to create record."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleUpdate(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "id", + message: "id", + required: true + }, { + type: "text", + name: "make", + message: "make", + required: false + }, { + type: "text", + name: "model", + message: "model", + required: false + }, { + type: "text", + name: "year", + message: "year", + required: false + }, { + type: "text", + name: "isElectric", + message: "isElectric", + required: false + }]); + const client = getClient(); + const result = await client.car.update({ + id: answers.id, + data: { + make: answers.make, + model: answers.model, + year: answers.year, + isElectric: answers.isElectric + }, + select: { + id: true, + make: true, + model: true, + year: true, + isElectric: true, + createdAt: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to update record."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleDelete(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "id", + message: "id", + required: true + }]); + const client = getClient(); + const result = await client.car.delete({ + id: answers.id, + select: { + id: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to delete record."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +}" +`; + +exports[`cli-generator generates commands/context.ts 1`] = ` +"/** + * Context management commands + * @generated by @constructive-io/graphql-codegen + * DO NOT EDIT - changes will be overwritten + */ +import { CLIOptions, Inquirerer, extractFirst } from "inquirerer"; +import { getStore } from "../executor"; +const usage = "\\nmyapp context \\n\\nCommands:\\n create Create a new context\\n list List all contexts\\n use Set the active context\\n current Show current context\\n delete Delete a context\\n\\nCreate Options:\\n --endpoint GraphQL endpoint URL\\n\\n --help, -h Show this help message\\n"; +export default async (argv: Partial>, prompter: Inquirerer, _options: CLIOptions) => { + if (argv.help || argv.h) { + console.log(usage); + process.exit(0); + } + const store = getStore(); + const { + first: subcommand, + newArgv + } = extractFirst(argv); + if (!subcommand) { + const answer = await prompter.prompt(argv, [{ + type: "autocomplete", + name: "subcommand", + message: "What do you want to do?", + options: ["create", "list", "use", "current", "delete"] + }]); + return handleSubcommand(answer.subcommand, newArgv, prompter, store); + } + return handleSubcommand(subcommand, newArgv, prompter, store); +}; +async function handleSubcommand(subcommand: string, argv: Partial>, prompter: Inquirerer, store: ReturnType) { + switch (subcommand) { + case "create": + return handleCreate(argv, prompter, store); + case "list": + return handleList(store); + case "use": + return handleUse(argv, prompter, store); + case "current": + return handleCurrent(store); + case "delete": + return handleDelete(argv, prompter, store); + default: + console.log(usage); + process.exit(1); + } +} +async function handleCreate(argv: Partial>, prompter: Inquirerer, store: ReturnType) { + const { + first: name, + newArgv: restArgv + } = extractFirst(argv); + const answers = await prompter.prompt({ + name, + ...restArgv + }, [{ + type: "text", + name: "name", + message: "Context name", + required: true + }, { + type: "text", + name: "endpoint", + message: "GraphQL endpoint URL", + required: true + }]); + const contextName = answers.name; + const endpoint = answers.endpoint; + store.createContext(contextName, { + endpoint: endpoint + }); + const settings = store.loadSettings(); + if (!settings.currentContext) { + store.setCurrentContext(contextName); + } + console.log(\`Created context: \${contextName}\`); + console.log(\` Endpoint: \${endpoint}\`); +} +function handleList(store: ReturnType) { + const contexts = store.listContexts(); + const settings = store.loadSettings(); + if (contexts.length === 0) { + console.log("No contexts configured."); + return; + } + console.log("Contexts:"); + for (const ctx of contexts) { + const marker = ctx.name === settings.currentContext ? "* " : " "; + const authStatus = store.hasValidCredentials(ctx.name) ? "[authenticated]" : "[no token]"; + console.log(\`\${marker}\${ctx.name} \${authStatus}\`); + console.log(\` Endpoint: \${ctx.endpoint}\`); + } +} +async function handleUse(argv: Partial>, prompter: Inquirerer, store: ReturnType) { + const { + first: name + } = extractFirst(argv); + const contexts = store.listContexts(); + if (contexts.length === 0) { + console.log("No contexts configured."); + return; + } + let contextName = name; + if (!contextName) { + const answer = await prompter.prompt(argv, [{ + type: "autocomplete", + name: "name", + message: "Select context", + options: contexts.map(c => c.name) + }]); + contextName = answer.name; + } + if (store.setCurrentContext(contextName)) { + console.log(\`Switched to context: \${contextName}\`); + } else { + console.error(\`Context "\${contextName}" not found.\`); + process.exit(1); + } +} +function handleCurrent(store: ReturnType) { + const current = store.getCurrentContext(); + if (!current) { + console.log("No current context set."); + return; + } + console.log(\`Current context: \${current.name}\`); + console.log(\` Endpoint: \${current.endpoint}\`); + const hasAuth = store.hasValidCredentials(current.name); + console.log(\` Auth: \${hasAuth ? "authenticated" : "not authenticated"}\`); +} +async function handleDelete(argv: Partial>, prompter: Inquirerer, store: ReturnType) { + const { + first: name + } = extractFirst(argv); + const contexts = store.listContexts(); + if (contexts.length === 0) { + console.log("No contexts configured."); + return; + } + let contextName = name; + if (!contextName) { + const answer = await prompter.prompt(argv, [{ + type: "autocomplete", + name: "name", + message: "Select context to delete", + options: contexts.map(c => c.name) + }]); + contextName = answer.name; + } + if (store.deleteContext(contextName)) { + console.log(\`Deleted context: \${contextName}\`); + } else { + console.error(\`Context "\${contextName}" not found.\`); + process.exit(1); + } +}" +`; + +exports[`cli-generator generates commands/current-user.ts (custom query) 1`] = ` +"/** + * CLI command for query currentUser + * @generated by @constructive-io/graphql-codegen + * DO NOT EDIT - changes will be overwritten + */ +import { CLIOptions, Inquirerer } from "inquirerer"; +import { getClient } from "../executor"; +export default async (argv: Partial>, prompter: Inquirerer, _options: CLIOptions) => { + try { + if (argv.help || argv.h) { + console.log("current-user - Get the currently authenticated user\\n\\nUsage: current-user [OPTIONS]\\n"); + process.exit(0); + } + const client = getClient(); + const result = await client.query.currentUser({}).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed: currentUser"); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +};" +`; + +exports[`cli-generator generates commands/driver.ts 1`] = ` +"/** + * CLI commands for Driver + * @generated by @constructive-io/graphql-codegen + * DO NOT EDIT - changes will be overwritten + */ +import { CLIOptions, Inquirerer, extractFirst } from "inquirerer"; +import { getClient } from "../executor"; +const usage = "\\ndriver \\n\\nCommands:\\n list List all driver records\\n get Get a driver by ID\\n create Create a new driver\\n update Update an existing driver\\n delete Delete a driver\\n\\n --help, -h Show this help message\\n"; +export default async (argv: Partial>, prompter: Inquirerer, _options: CLIOptions) => { + if (argv.help || argv.h) { + console.log(usage); + process.exit(0); + } + const { + first: subcommand, + newArgv + } = extractFirst(argv); + if (!subcommand) { + const answer = await prompter.prompt(argv, [{ + type: "autocomplete", + name: "subcommand", + message: "What do you want to do?", + options: ["list", "get", "create", "update", "delete"] + }]); + return handleTableSubcommand(answer.subcommand, newArgv, prompter); + } + return handleTableSubcommand(subcommand, newArgv, prompter); +}; +async function handleTableSubcommand(subcommand: string, argv: Partial>, prompter: Inquirerer) { + switch (subcommand) { + case "list": + return handleList(argv, prompter); + case "get": + return handleGet(argv, prompter); + case "create": + return handleCreate(argv, prompter); + case "update": + return handleUpdate(argv, prompter); + case "delete": + return handleDelete(argv, prompter); + default: + console.log(usage); + process.exit(1); + } +} +async function handleList(_argv: Partial>, _prompter: Inquirerer) { + try { + const client = getClient(); + const result = await client.driver.findMany({ + select: { + id: true, + name: true, + licenseNumber: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to list records."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleGet(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "id", + message: "id", + required: true + }]); + const client = getClient(); + const result = await client.driver.findOne({ + id: answers.id, + select: { + id: true, + name: true, + licenseNumber: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Record not found."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleCreate(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "name", + message: "name", + required: true + }, { + type: "text", + name: "licenseNumber", + message: "licenseNumber", + required: true + }]); + const client = getClient(); + const result = await client.driver.create({ + data: { + name: answers.name, + licenseNumber: answers.licenseNumber + }, + select: { + id: true, + name: true, + licenseNumber: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to create record."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleUpdate(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "id", + message: "id", + required: true + }, { + type: "text", + name: "name", + message: "name", + required: false + }, { + type: "text", + name: "licenseNumber", + message: "licenseNumber", + required: false + }]); + const client = getClient(); + const result = await client.driver.update({ + id: answers.id, + data: { + name: answers.name, + licenseNumber: answers.licenseNumber + }, + select: { + id: true, + name: true, + licenseNumber: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to update record."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleDelete(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "id", + message: "id", + required: true + }]); + const client = getClient(); + const result = await client.driver.delete({ + id: answers.id, + select: { + id: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to delete record."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +}" +`; + +exports[`cli-generator generates commands/login.ts (custom mutation) 1`] = ` +"/** + * CLI command for mutation login + * @generated by @constructive-io/graphql-codegen + * DO NOT EDIT - changes will be overwritten + */ +import { CLIOptions, Inquirerer } from "inquirerer"; +import { getClient } from "../executor"; +export default async (argv: Partial>, prompter: Inquirerer, _options: CLIOptions) => { + try { + if (argv.help || argv.h) { + console.log("login - Authenticate a user\\n\\nUsage: login [OPTIONS]\\n"); + process.exit(0); + } + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "email", + message: "email", + required: true + }, { + type: "text", + name: "password", + message: "password", + required: true + }]); + const client = getClient(); + const result = await client.mutation.login(answers).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed: login"); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +};" +`; + +exports[`cli-generator generates executor.ts 1`] = ` +"/** + * Executor and config store for CLI + * @generated by @constructive-io/graphql-codegen + * DO NOT EDIT - changes will be overwritten + */ +import { createConfigStore } from "appstash"; +import { createClient } from "../orm"; +const store = createConfigStore("myapp"); +export const getStore = () => store; +export function getClient(contextName?: string) { + let ctx = null; + if (contextName) { + ctx = store.loadContext(contextName); + if (!ctx) { + throw new Error(\`Context "\${contextName}" not found.\`); + } + } else { + ctx = store.getCurrentContext(); + if (!ctx) { + throw new Error("No active context. Run \\"context create\\" or \\"context use\\" first."); + } + } + const headers = {}; + if (store.hasValidCredentials(ctx.name)) { + const creds = store.getCredentials(ctx.name); + if (creds?.token) { + headers.Authorization = \`Bearer \${creds.token}\`; + } + } + return createClient({ + endpoint: ctx.endpoint, + headers: headers + }); +}" +`; diff --git a/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts b/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts new file mode 100644 index 000000000..e6a251471 --- /dev/null +++ b/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts @@ -0,0 +1,229 @@ +import { generateCli } from '../../core/codegen/cli'; +import type { + CleanFieldType, + CleanOperation, + CleanRelations, + CleanTable, + CleanTypeRef, +} from '../../types/schema'; + +const fieldTypes = { + uuid: { gqlType: 'UUID', isArray: false } as CleanFieldType, + string: { gqlType: 'String', isArray: false } as CleanFieldType, + int: { gqlType: 'Int', isArray: false } as CleanFieldType, + boolean: { gqlType: 'Boolean', isArray: false } as CleanFieldType, + datetime: { gqlType: 'Datetime', isArray: false } as CleanFieldType, +}; + +const emptyRelations: CleanRelations = { + belongsTo: [], + hasOne: [], + hasMany: [], + manyToMany: [], +}; + +function createTable( + partial: Partial & { name: string }, +): CleanTable { + return { + name: partial.name, + fields: partial.fields ?? [], + relations: partial.relations ?? emptyRelations, + query: partial.query, + inflection: partial.inflection, + constraints: partial.constraints, + }; +} + +function createTypeRef( + kind: CleanTypeRef['kind'], + name: string | null, + ofType?: CleanTypeRef, +): CleanTypeRef { + return { kind, name, ofType }; +} + +const carTable = createTable({ + name: 'Car', + fields: [ + { name: 'id', type: fieldTypes.uuid }, + { name: 'make', type: fieldTypes.string }, + { name: 'model', type: fieldTypes.string }, + { name: 'year', type: fieldTypes.int }, + { name: 'isElectric', type: fieldTypes.boolean }, + { name: 'createdAt', type: fieldTypes.datetime }, + ], + query: { + all: 'cars', + one: 'car', + create: 'createCar', + update: 'updateCar', + delete: 'deleteCar', + }, +}); + +const driverTable = createTable({ + name: 'Driver', + fields: [ + { name: 'id', type: fieldTypes.uuid }, + { name: 'name', type: fieldTypes.string }, + { name: 'licenseNumber', type: fieldTypes.string }, + ], + query: { + all: 'drivers', + one: 'driver', + create: 'createDriver', + update: 'updateDriver', + delete: 'deleteDriver', + }, +}); + +const loginMutation: CleanOperation = { + name: 'login', + kind: 'mutation', + args: [ + { + name: 'email', + type: createTypeRef( + 'NON_NULL', + null, + createTypeRef('SCALAR', 'String'), + ), + }, + { + name: 'password', + type: createTypeRef( + 'NON_NULL', + null, + createTypeRef('SCALAR', 'String'), + ), + }, + ], + returnType: createTypeRef('OBJECT', 'LoginPayload'), + description: 'Authenticate a user', +}; + +const currentUserQuery: CleanOperation = { + name: 'currentUser', + kind: 'query', + args: [], + returnType: createTypeRef('OBJECT', 'User'), + description: 'Get the currently authenticated user', +}; + +describe('cli-generator', () => { + const result = generateCli({ + tables: [carTable, driverTable], + customOperations: { + queries: [currentUserQuery], + mutations: [loginMutation], + }, + config: { + cli: { toolName: 'myapp' }, + }, + }); + + it('returns correct stats', () => { + expect(result.stats).toEqual({ + tables: 2, + customQueries: 1, + customMutations: 1, + infraFiles: 3, + totalFiles: 8, + }); + }); + + it('generates executor.ts', () => { + const file = result.files.find((f) => f.fileName === 'executor.ts'); + expect(file).toBeDefined(); + expect(file!.content).toMatchSnapshot(); + }); + + it('generates commands/context.ts', () => { + const file = result.files.find( + (f) => f.fileName === 'commands/context.ts', + ); + expect(file).toBeDefined(); + expect(file!.content).toMatchSnapshot(); + }); + + it('generates commands/auth.ts', () => { + const file = result.files.find((f) => f.fileName === 'commands/auth.ts'); + expect(file).toBeDefined(); + expect(file!.content).toMatchSnapshot(); + }); + + it('generates commands/car.ts', () => { + const file = result.files.find((f) => f.fileName === 'commands/car.ts'); + expect(file).toBeDefined(); + expect(file!.content).toMatchSnapshot(); + }); + + it('generates commands/driver.ts', () => { + const file = result.files.find( + (f) => f.fileName === 'commands/driver.ts', + ); + expect(file).toBeDefined(); + expect(file!.content).toMatchSnapshot(); + }); + + it('generates commands/login.ts (custom mutation)', () => { + const file = result.files.find((f) => f.fileName === 'commands/login.ts'); + expect(file).toBeDefined(); + expect(file!.content).toMatchSnapshot(); + }); + + it('generates commands/current-user.ts (custom query)', () => { + const file = result.files.find( + (f) => f.fileName === 'commands/current-user.ts', + ); + expect(file).toBeDefined(); + expect(file!.content).toMatchSnapshot(); + }); + + it('generates commands.ts (command map)', () => { + const file = result.files.find((f) => f.fileName === 'commands.ts'); + expect(file).toBeDefined(); + expect(file!.content).toMatchSnapshot(); + }); + + it('uses ORM methods in table commands', () => { + const carFile = result.files.find( + (f) => f.fileName === 'commands/car.ts', + ); + expect(carFile!.content).toContain('getClient'); + expect(carFile!.content).toContain('.findMany('); + expect(carFile!.content).toContain('.execute()'); + expect(carFile!.content).toContain('JSON.stringify'); + }); + + it('uses ORM methods in custom commands', () => { + const loginFile = result.files.find( + (f) => f.fileName === 'commands/login.ts', + ); + expect(loginFile!.content).toContain('getClient'); + expect(loginFile!.content).toContain('.mutation.'); + expect(loginFile!.content).toContain('.execute()'); + }); + + it('uses appstash config-store in executor', () => { + const executor = result.files.find((f) => f.fileName === 'executor.ts'); + expect(executor!.content).toContain('createConfigStore'); + expect(executor!.content).toContain('"myapp"'); + expect(executor!.content).toContain('createClient'); + }); + + it('generates correct file names', () => { + const fileNames = result.files.map((f) => f.fileName).sort(); + expect(fileNames).toEqual([ + 'commands.ts', + 'commands/auth.ts', + 'commands/car.ts', + 'commands/context.ts', + 'commands/current-user.ts', + 'commands/driver.ts', + 'commands/login.ts', + 'executor.ts', + ]); + }); +}); diff --git a/graphql/codegen/src/core/generate.ts b/graphql/codegen/src/core/generate.ts index 3d4b22242..4a43c68e1 100644 --- a/graphql/codegen/src/core/generate.ts +++ b/graphql/codegen/src/core/generate.ts @@ -50,9 +50,9 @@ export async function generate( // ORM is always required when React Query is enabled (hooks delegate to ORM) // This handles minimist setting orm=false when --orm flag is absent const runReactQuery = config.reactQuery ?? false; - const runOrm = - runReactQuery || (options.orm !== undefined ? !!options.orm : false); const runCli = !!config.cli; + const runOrm = + runReactQuery || runCli || (options.orm !== undefined ? !!options.orm : false); if (!runReactQuery && !runOrm && !runCli) { return { From fde91f9fc7e60f60688da7186faa69084650666e Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Tue, 17 Feb 2026 10:14:45 +0000 Subject: [PATCH 03/23] feat(codegen): generate README.md and COMMANDS.md for CLI - Add docs-generator.ts that produces README.md (overview, setup, commands) and COMMANDS.md (man-page style reference with synopsis, options, examples) - Wire into CLI orchestrator so docs are always generated alongside commands - Update snapshot tests: 15 tests, 10 snapshots covering all generated files --- .../__snapshots__/cli-generator.test.ts.snap | 360 +++++++++++++++ .../__tests__/codegen/cli-generator.test.ts | 16 +- .../src/core/codegen/cli/docs-generator.ts | 417 ++++++++++++++++++ graphql/codegen/src/core/codegen/cli/index.ts | 11 + 4 files changed, 803 insertions(+), 1 deletion(-) create mode 100644 graphql/codegen/src/core/codegen/cli/docs-generator.ts diff --git a/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap b/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap index 092b8c18e..0d2f527d8 100644 --- a/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap +++ b/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap @@ -1,5 +1,365 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +exports[`cli-generator generates COMMANDS.md (man-page reference) 1`] = ` +"# myapp - Command Reference + +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT + +--- + +## context(1) + +### NAME + +context - manage API endpoint contexts + +### SYNOPSIS + + myapp context [options] + +### COMMANDS + +**create** \`\` \`--endpoint \` + + Create a named context pointing at a GraphQL endpoint. + Config stored at ~/.myapp/config/contexts/.json + +**list** + + List all configured contexts with auth status. + +**use** \`\` + + Set the active context for subsequent commands. + +**current** + + Display the currently active context and its endpoint. + +**delete** \`\` + + Remove a context and its configuration. + +--- + +## auth(1) + +### NAME + +auth - manage authentication tokens + +### SYNOPSIS + + myapp auth [options] + +### COMMANDS + +**set-token** \`\` \`[--context ]\` + + Store a bearer token for the current (or specified) context. + Credentials stored at ~/.myapp/config/credentials.json (mode 0600). + +**status** + + Show authentication status for all contexts. + +**logout** \`[--context ]\` + + Remove stored credentials for the current (or specified) context. + +--- + +## car(1) + +### NAME + +car - manage Car records + +### SYNOPSIS + + car [options] + +### COMMANDS + +**list** + + car list + +List all car records. Returns JSON array. + +Selected fields: id, make, model, year, isElectric, createdAt + +**get** + + car get --id + +Fetch a single car by its id. + +**create** + + car create --make --model --year --isElectric + +Create a new car. All fields are required. + + Options: + --make String (required) + --model String (required) + --year Int (required) + --isElectric Boolean (required) + +**update** + + car update --id [--make ] [--model ] [--year ] [--isElectric ] + +Update an existing car. Only provided fields are changed. + + Options: + --id UUID (required) + --make String + --model String + --year Int + --isElectric Boolean + +**delete** + + car delete --id + +Delete a car by its id. + +--- + +## driver(1) + +### NAME + +driver - manage Driver records + +### SYNOPSIS + + driver [options] + +### COMMANDS + +**list** + + driver list + +List all driver records. Returns JSON array. + +Selected fields: id, name, licenseNumber + +**get** + + driver get --id + +Fetch a single driver by its id. + +**create** + + driver create --name --licenseNumber + +Create a new driver. All fields are required. + + Options: + --name String (required) + --licenseNumber String (required) + +**update** + + driver update --id [--name ] [--licenseNumber ] + +Update an existing driver. Only provided fields are changed. + + Options: + --id UUID (required) + --name String + --licenseNumber String + +**delete** + + driver delete --id + +Delete a driver by its id. + +--- + +## current-user(1) + +### NAME + +current-user - Get the currently authenticated user + +### SYNOPSIS + + current-user + +### DESCRIPTION + +Get the currently authenticated user + +--- + +## login(1) + +### NAME + +login - Authenticate a user + +### SYNOPSIS + + login --email --password + +### DESCRIPTION + +Authenticate a user + +### OPTIONS + +**--email** String (required) + +**--password** String (required) + +--- +" +`; + +exports[`cli-generator generates README.md 1`] = ` +"# myapp CLI + +> Auto-generated CLI commands from GraphQL schema +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT + +## Setup + +\`\`\`bash +# Create a context pointing at your GraphQL endpoint +myapp context create production --endpoint https://api.example.com/graphql + +# Set the active context +myapp context use production + +# Authenticate +myapp auth set-token +\`\`\` + +## Commands + +| Command | Description | +|---------|-------------| +| \`context\` | Manage API contexts (endpoints) | +| \`auth\` | Manage authentication tokens | +| \`car\` | car CRUD operations | +| \`driver\` | driver CRUD operations | +| \`current-user\` | Get the currently authenticated user | +| \`login\` | Authenticate a user | + +## Infrastructure Commands + +### \`context\` + +Manage named API contexts (kubectl-style). + +| Subcommand | Description | +|------------|-------------| +| \`create --endpoint \` | Create a new context | +| \`list\` | List all contexts | +| \`use \` | Set the active context | +| \`current\` | Show current context | +| \`delete \` | Delete a context | + +Configuration is stored at \`~/.myapp/config/\`. + +### \`auth\` + +Manage authentication tokens per context. + +| Subcommand | Description | +|------------|-------------| +| \`set-token \` | Store bearer token for current context | +| \`status\` | Show auth status across all contexts | +| \`logout\` | Remove credentials for current context | + +## Table Commands + +### \`car\` + +CRUD operations for Car records. + +| Subcommand | Description | +|------------|-------------| +| \`list\` | List all car records | +| \`get\` | Get a car by id | +| \`create\` | Create a new car | +| \`update\` | Update an existing car | +| \`delete\` | Delete a car | + +**Fields:** + +| Field | Type | +|-------|------| +| \`id\` | UUID | +| \`make\` | String | +| \`model\` | String | +| \`year\` | Int | +| \`isElectric\` | Boolean | +| \`createdAt\` | Datetime | + +**Create fields:** \`make\`, \`model\`, \`year\`, \`isElectric\` + +### \`driver\` + +CRUD operations for Driver records. + +| Subcommand | Description | +|------------|-------------| +| \`list\` | List all driver records | +| \`get\` | Get a driver by id | +| \`create\` | Create a new driver | +| \`update\` | Update an existing driver | +| \`delete\` | Delete a driver | + +**Fields:** + +| Field | Type | +|-------|------| +| \`id\` | UUID | +| \`name\` | String | +| \`licenseNumber\` | String | + +**Create fields:** \`name\`, \`licenseNumber\` + +## Custom Operations + +### \`current-user\` + +Get the currently authenticated user + +- **Type:** query +- **Arguments:** none + +### \`login\` + +Authenticate a user + +- **Type:** mutation +- **Arguments:** + + | Argument | Type | + |----------|------| + | \`email\` | String (required) | + | \`password\` | String (required) | + +## Output + +All commands output JSON to stdout. Pipe to \`jq\` for formatting: + +\`\`\`bash +myapp car list | jq '.[]' +myapp car get --id | jq '.' +\`\`\` +" +`; + exports[`cli-generator generates commands.ts (command map) 1`] = ` "/** * CLI command map and entry point diff --git a/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts b/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts index e6a251471..01bd8a753 100644 --- a/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts +++ b/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts @@ -129,7 +129,7 @@ describe('cli-generator', () => { customQueries: 1, customMutations: 1, infraFiles: 3, - totalFiles: 8, + totalFiles: 10, }); }); @@ -187,6 +187,18 @@ describe('cli-generator', () => { expect(file!.content).toMatchSnapshot(); }); + it('generates README.md', () => { + const file = result.files.find((f) => f.fileName === 'README.md'); + expect(file).toBeDefined(); + expect(file!.content).toMatchSnapshot(); + }); + + it('generates COMMANDS.md (man-page reference)', () => { + const file = result.files.find((f) => f.fileName === 'COMMANDS.md'); + expect(file).toBeDefined(); + expect(file!.content).toMatchSnapshot(); + }); + it('uses ORM methods in table commands', () => { const carFile = result.files.find( (f) => f.fileName === 'commands/car.ts', @@ -216,6 +228,8 @@ describe('cli-generator', () => { it('generates correct file names', () => { const fileNames = result.files.map((f) => f.fileName).sort(); expect(fileNames).toEqual([ + 'COMMANDS.md', + 'README.md', 'commands.ts', 'commands/auth.ts', 'commands/car.ts', diff --git a/graphql/codegen/src/core/codegen/cli/docs-generator.ts b/graphql/codegen/src/core/codegen/cli/docs-generator.ts new file mode 100644 index 000000000..f9fda4c49 --- /dev/null +++ b/graphql/codegen/src/core/codegen/cli/docs-generator.ts @@ -0,0 +1,417 @@ +import { toKebabCase } from 'komoji'; + +import { + getScalarFields, + getTableNames, + getPrimaryKeyInfo, +} from '../utils'; +import type { CleanTable, CleanOperation } from '../../../types/schema'; +import type { GeneratedFile } from './executor-generator'; + +function formatArgType(arg: CleanOperation['args'][number]): string { + const t = arg.type; + if (t.kind === 'NON_NULL' && t.ofType) { + return `${formatTypeRef(t.ofType)} (required)`; + } + return formatTypeRef(t); +} + +function formatTypeRef(t: CleanOperation['args'][number]['type']): string { + if (t.kind === 'LIST' && t.ofType) { + return `[${formatTypeRef(t.ofType)}]`; + } + if (t.kind === 'NON_NULL' && t.ofType) { + return `${formatTypeRef(t.ofType)}!`; + } + return t.name ?? 'unknown'; +} + +function buildTableSection(table: CleanTable): string { + const { singularName } = getTableNames(table); + const kebab = toKebabCase(singularName); + const pk = getPrimaryKeyInfo(table)[0]; + const scalarFields = getScalarFields(table); + const editableFields = scalarFields.filter( + (f) => + f.name !== pk.name && + f.name !== 'nodeId' && + f.name !== 'createdAt' && + f.name !== 'updatedAt', + ); + + const lines: string[] = []; + + lines.push(`### \`${kebab}\``); + lines.push(''); + lines.push(`CRUD operations for ${table.name} records.`); + lines.push(''); + lines.push('| Subcommand | Description |'); + lines.push('|------------|-------------|'); + lines.push(`| \`list\` | List all ${singularName} records |`); + lines.push(`| \`get\` | Get a ${singularName} by ${pk.name} |`); + lines.push(`| \`create\` | Create a new ${singularName} |`); + lines.push(`| \`update\` | Update an existing ${singularName} |`); + lines.push(`| \`delete\` | Delete a ${singularName} |`); + lines.push(''); + + lines.push('**Fields:**'); + lines.push(''); + lines.push('| Field | Type |'); + lines.push('|-------|------|'); + for (const f of scalarFields) { + lines.push(`| \`${f.name}\` | ${f.type.gqlType} |`); + } + lines.push(''); + + lines.push(`**Create fields:** ${editableFields.map((f) => `\`${f.name}\``).join(', ')}`); + lines.push(''); + + return lines.join('\n'); +} + +function buildCustomOpSection(op: CleanOperation): string { + const kebab = toKebabCase(op.name); + const lines: string[] = []; + + lines.push(`### \`${kebab}\``); + lines.push(''); + lines.push(op.description || op.name); + lines.push(''); + lines.push(`- **Type:** ${op.kind}`); + + if (op.args.length > 0) { + lines.push('- **Arguments:**'); + lines.push(''); + lines.push(' | Argument | Type |'); + lines.push(' |----------|------|'); + for (const arg of op.args) { + lines.push(` | \`${arg.name}\` | ${formatArgType(arg)} |`); + } + lines.push(''); + } else { + lines.push('- **Arguments:** none'); + lines.push(''); + } + + return lines.join('\n'); +} + +function buildTableManPage(table: CleanTable): string { + const { singularName } = getTableNames(table); + const kebab = toKebabCase(singularName); + const pk = getPrimaryKeyInfo(table)[0]; + const scalarFields = getScalarFields(table); + const editableFields = scalarFields.filter( + (f) => + f.name !== pk.name && + f.name !== 'nodeId' && + f.name !== 'createdAt' && + f.name !== 'updatedAt', + ); + + const lines: string[] = []; + + lines.push(`## ${kebab}(1)`); + lines.push(''); + lines.push('### NAME'); + lines.push(''); + lines.push(`${kebab} - manage ${table.name} records`); + lines.push(''); + lines.push('### SYNOPSIS'); + lines.push(''); + lines.push(` ${kebab} [options]`); + lines.push(''); + lines.push('### COMMANDS'); + lines.push(''); + + lines.push('**list**'); + lines.push(''); + lines.push(` ${kebab} list`); + lines.push(''); + lines.push(`List all ${singularName} records. Returns JSON array.`); + lines.push(''); + lines.push(`Selected fields: ${scalarFields.map((f) => f.name).join(', ')}`); + lines.push(''); + + lines.push('**get**'); + lines.push(''); + lines.push(` ${kebab} get --${pk.name} `); + lines.push(''); + lines.push(`Fetch a single ${singularName} by its ${pk.name}.`); + lines.push(''); + + lines.push('**create**'); + lines.push(''); + const createFlags = editableFields.map((f) => `--${f.name} `).join(' '); + lines.push(` ${kebab} create ${createFlags}`); + lines.push(''); + lines.push(`Create a new ${singularName}. All fields are required.`); + lines.push(''); + lines.push(' Options:'); + for (const f of editableFields) { + lines.push(` --${f.name.padEnd(20)} ${f.type.gqlType} (required)`); + } + lines.push(''); + + lines.push('**update**'); + lines.push(''); + const updateFlags = editableFields.map((f) => `[--${f.name} ]`).join(' '); + lines.push(` ${kebab} update --${pk.name} ${updateFlags}`); + lines.push(''); + lines.push(`Update an existing ${singularName}. Only provided fields are changed.`); + lines.push(''); + lines.push(' Options:'); + lines.push(` --${pk.name.padEnd(20)} ${pk.gqlType} (required)`); + for (const f of editableFields) { + lines.push(` --${f.name.padEnd(20)} ${f.type.gqlType}`); + } + lines.push(''); + + lines.push('**delete**'); + lines.push(''); + lines.push(` ${kebab} delete --${pk.name} `); + lines.push(''); + lines.push(`Delete a ${singularName} by its ${pk.name}.`); + lines.push(''); + + return lines.join('\n'); +} + +function buildCustomOpManPage(op: CleanOperation): string { + const kebab = toKebabCase(op.name); + const lines: string[] = []; + + lines.push(`## ${kebab}(1)`); + lines.push(''); + lines.push('### NAME'); + lines.push(''); + lines.push(`${kebab} - ${op.description || op.name}`); + lines.push(''); + lines.push('### SYNOPSIS'); + lines.push(''); + + if (op.args.length > 0) { + const flags = op.args.map((a) => `--${a.name} `).join(' '); + lines.push(` ${kebab} ${flags}`); + } else { + lines.push(` ${kebab}`); + } + lines.push(''); + + lines.push('### DESCRIPTION'); + lines.push(''); + lines.push(op.description || `Execute the ${op.name} ${op.kind}.`); + lines.push(''); + + if (op.args.length > 0) { + lines.push('### OPTIONS'); + lines.push(''); + for (const arg of op.args) { + lines.push(`**--${arg.name}** ${formatArgType(arg)}`); + if (arg.description) { + lines.push(` ${arg.description}`); + } + lines.push(''); + } + } + + return lines.join('\n'); +} + +export function generateReadme( + tables: CleanTable[], + customOperations: CleanOperation[], + toolName: string, +): GeneratedFile { + const lines: string[] = []; + + lines.push(`# ${toolName} CLI`); + lines.push(''); + lines.push('> Auto-generated CLI commands from GraphQL schema'); + lines.push('> @generated by @constructive-io/graphql-codegen - DO NOT EDIT'); + lines.push(''); + lines.push('## Setup'); + lines.push(''); + lines.push('```bash'); + lines.push(`# Create a context pointing at your GraphQL endpoint`); + lines.push(`${toolName} context create production --endpoint https://api.example.com/graphql`); + lines.push(''); + lines.push(`# Set the active context`); + lines.push(`${toolName} context use production`); + lines.push(''); + lines.push(`# Authenticate`); + lines.push(`${toolName} auth set-token `); + lines.push('```'); + lines.push(''); + + lines.push('## Commands'); + lines.push(''); + lines.push('| Command | Description |'); + lines.push('|---------|-------------|'); + lines.push('| `context` | Manage API contexts (endpoints) |'); + lines.push('| `auth` | Manage authentication tokens |'); + for (const table of tables) { + const { singularName } = getTableNames(table); + const kebab = toKebabCase(singularName); + lines.push(`| \`${kebab}\` | ${singularName} CRUD operations |`); + } + for (const op of customOperations) { + const kebab = toKebabCase(op.name); + lines.push(`| \`${kebab}\` | ${op.description || op.name} |`); + } + lines.push(''); + + lines.push('## Infrastructure Commands'); + lines.push(''); + lines.push('### `context`'); + lines.push(''); + lines.push('Manage named API contexts (kubectl-style).'); + lines.push(''); + lines.push('| Subcommand | Description |'); + lines.push('|------------|-------------|'); + lines.push('| `create --endpoint ` | Create a new context |'); + lines.push('| `list` | List all contexts |'); + lines.push('| `use ` | Set the active context |'); + lines.push('| `current` | Show current context |'); + lines.push('| `delete ` | Delete a context |'); + lines.push(''); + lines.push(`Configuration is stored at \`~/.${toolName}/config/\`.`); + lines.push(''); + lines.push('### `auth`'); + lines.push(''); + lines.push('Manage authentication tokens per context.'); + lines.push(''); + lines.push('| Subcommand | Description |'); + lines.push('|------------|-------------|'); + lines.push('| `set-token ` | Store bearer token for current context |'); + lines.push('| `status` | Show auth status across all contexts |'); + lines.push('| `logout` | Remove credentials for current context |'); + lines.push(''); + + if (tables.length > 0) { + lines.push('## Table Commands'); + lines.push(''); + for (const table of tables) { + lines.push(buildTableSection(table)); + } + } + + if (customOperations.length > 0) { + lines.push('## Custom Operations'); + lines.push(''); + for (const op of customOperations) { + lines.push(buildCustomOpSection(op)); + } + } + + lines.push('## Output'); + lines.push(''); + lines.push('All commands output JSON to stdout. Pipe to `jq` for formatting:'); + lines.push(''); + lines.push('```bash'); + lines.push(`${toolName} car list | jq '.[]'`); + lines.push(`${toolName} car get --id | jq '.'`); + lines.push('```'); + lines.push(''); + + return { + fileName: 'README.md', + content: lines.join('\n'), + }; +} + +export function generateCommandReference( + tables: CleanTable[], + customOperations: CleanOperation[], + toolName: string, +): GeneratedFile { + const lines: string[] = []; + + lines.push(`# ${toolName} - Command Reference`); + lines.push(''); + lines.push('> @generated by @constructive-io/graphql-codegen - DO NOT EDIT'); + lines.push(''); + lines.push('---'); + lines.push(''); + + lines.push('## context(1)'); + lines.push(''); + lines.push('### NAME'); + lines.push(''); + lines.push('context - manage API endpoint contexts'); + lines.push(''); + lines.push('### SYNOPSIS'); + lines.push(''); + lines.push(` ${toolName} context [options]`); + lines.push(''); + lines.push('### COMMANDS'); + lines.push(''); + lines.push('**create** `` `--endpoint `'); + lines.push(''); + lines.push(' Create a named context pointing at a GraphQL endpoint.'); + lines.push(` Config stored at ~/.${toolName}/config/contexts/.json`); + lines.push(''); + lines.push('**list**'); + lines.push(''); + lines.push(' List all configured contexts with auth status.'); + lines.push(''); + lines.push('**use** ``'); + lines.push(''); + lines.push(' Set the active context for subsequent commands.'); + lines.push(''); + lines.push('**current**'); + lines.push(''); + lines.push(' Display the currently active context and its endpoint.'); + lines.push(''); + lines.push('**delete** ``'); + lines.push(''); + lines.push(' Remove a context and its configuration.'); + lines.push(''); + lines.push('---'); + lines.push(''); + + lines.push('## auth(1)'); + lines.push(''); + lines.push('### NAME'); + lines.push(''); + lines.push('auth - manage authentication tokens'); + lines.push(''); + lines.push('### SYNOPSIS'); + lines.push(''); + lines.push(` ${toolName} auth [options]`); + lines.push(''); + lines.push('### COMMANDS'); + lines.push(''); + lines.push('**set-token** `` `[--context ]`'); + lines.push(''); + lines.push(' Store a bearer token for the current (or specified) context.'); + lines.push(` Credentials stored at ~/.${toolName}/config/credentials.json (mode 0600).`); + lines.push(''); + lines.push('**status**'); + lines.push(''); + lines.push(' Show authentication status for all contexts.'); + lines.push(''); + lines.push('**logout** `[--context ]`'); + lines.push(''); + lines.push(' Remove stored credentials for the current (or specified) context.'); + lines.push(''); + lines.push('---'); + lines.push(''); + + for (const table of tables) { + lines.push(buildTableManPage(table)); + lines.push('---'); + lines.push(''); + } + + for (const op of customOperations) { + lines.push(buildCustomOpManPage(op)); + lines.push('---'); + lines.push(''); + } + + return { + fileName: 'COMMANDS.md', + content: lines.join('\n'), + }; +} diff --git a/graphql/codegen/src/core/codegen/cli/index.ts b/graphql/codegen/src/core/codegen/cli/index.ts index c38f6d3d4..a40e8effa 100644 --- a/graphql/codegen/src/core/codegen/cli/index.ts +++ b/graphql/codegen/src/core/codegen/cli/index.ts @@ -2,6 +2,7 @@ import type { GraphQLSDKConfigTarget } from '../../../types/config'; import type { CleanOperation, CleanTable } from '../../../types/schema'; import { generateCommandMap } from './command-map-generator'; import { generateCustomCommand } from './custom-command-generator'; +import { generateReadme, generateCommandReference } from './docs-generator'; import { generateExecutorFile } from './executor-generator'; import type { GeneratedFile } from './executor-generator'; import { generateAuthCommand, generateContextCommand } from './infra-generator'; @@ -68,6 +69,12 @@ export function generateCli(options: GenerateCliOptions): GenerateCliResult { ); files.push(commandMapFile); + const readmeFile = generateReadme(tables, allCustomOps, toolName); + files.push(readmeFile); + + const commandRefFile = generateCommandReference(tables, allCustomOps, toolName); + files.push(commandRefFile); + return { files, stats: { @@ -88,4 +95,8 @@ export { generateContextCommand, generateAuthCommand, } from './infra-generator'; +export { + generateReadme, + generateCommandReference, +} from './docs-generator'; export type { GeneratedFile } from './executor-generator'; From 1fe5255398d7dda4ed5ead956b29717357a737fb Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Tue, 17 Feb 2026 10:27:19 +0000 Subject: [PATCH 04/23] feat(codegen): add configurable docs generation (README, AGENTS.md, MCP, Skills) - Add DocsConfig interface: { readme, agents, mcp, skills } with boolean flags - Defaults: readme + agents on, mcp + skills opt-in. docs: true enables all. - generateAgentsDocs(): structured AGENTS.md for LLM consumption with TOOL sections, INPUT/OUTPUT schemas, WORKFLOWS, and ERROR HANDLING - generateMcpConfig(): mcp.json with typed inputSchema per command (JSON Schema) - generateSkills(): per-command .md skill files for agent systems - Wire into cli/index.ts orchestrator with config-driven conditional generation - 22 tests, 17 snapshots covering all formats and config combinations --- .../__snapshots__/cli-generator.test.ts.snap | 844 ++++++++++++++--- .../__tests__/codegen/cli-generator.test.ts | 126 ++- .../src/core/codegen/cli/docs-generator.ts | 863 +++++++++++++----- graphql/codegen/src/core/codegen/cli/index.ts | 39 +- graphql/codegen/src/types/config.ts | 44 + 5 files changed, 1551 insertions(+), 365 deletions(-) diff --git a/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap b/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap index 0d2f527d8..e008e1216 100644 --- a/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap +++ b/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap @@ -1,229 +1,837 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing -exports[`cli-generator generates COMMANDS.md (man-page reference) 1`] = ` -"# myapp - Command Reference +exports[`cli-generator docs: true (all formats) generates mcp.json 1`] = ` +"{ + "name": "myapp", + "version": "1.0.0", + "description": "MCP tool definitions for myapp CLI (auto-generated from GraphQL schema)", + "tools": [ + { + "name": "myapp_context_create", + "description": "Create a named API context pointing at a GraphQL endpoint", + "inputSchema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Context name" + }, + "endpoint": { + "type": "string", + "description": "GraphQL endpoint URL" + } + }, + "required": [ + "name", + "endpoint" + ] + } + }, + { + "name": "myapp_context_list", + "description": "List all configured API contexts", + "inputSchema": { + "type": "object", + "properties": {} + } + }, + { + "name": "myapp_context_use", + "description": "Set the active API context", + "inputSchema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Context name to activate" + } + }, + "required": [ + "name" + ] + } + }, + { + "name": "myapp_context_current", + "description": "Show the currently active API context", + "inputSchema": { + "type": "object", + "properties": {} + } + }, + { + "name": "myapp_context_delete", + "description": "Delete an API context", + "inputSchema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Context name to delete" + } + }, + "required": [ + "name" + ] + } + }, + { + "name": "myapp_auth_set_token", + "description": "Store a bearer token for the current context", + "inputSchema": { + "type": "object", + "properties": { + "token": { + "type": "string", + "description": "Bearer token value" + } + }, + "required": [ + "token" + ] + } + }, + { + "name": "myapp_auth_status", + "description": "Show authentication status for all contexts", + "inputSchema": { + "type": "object", + "properties": {} + } + }, + { + "name": "myapp_auth_logout", + "description": "Remove credentials for the current context", + "inputSchema": { + "type": "object", + "properties": {} + } + }, + { + "name": "myapp_car_list", + "description": "List all Car records", + "inputSchema": { + "type": "object", + "properties": {} + } + }, + { + "name": "myapp_car_get", + "description": "Get a single Car record by id", + "inputSchema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Car id" + } + }, + "required": [ + "id" + ] + } + }, + { + "name": "myapp_car_create", + "description": "Create a new Car record", + "inputSchema": { + "type": "object", + "properties": { + "make": { + "type": "string", + "description": "Car make" + }, + "model": { + "type": "string", + "description": "Car model" + }, + "year": { + "type": "integer", + "description": "Car year" + }, + "isElectric": { + "type": "boolean", + "description": "Car isElectric" + } + }, + "required": [ + "make", + "model", + "year", + "isElectric" + ] + } + }, + { + "name": "myapp_car_update", + "description": "Update an existing Car record", + "inputSchema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Car id" + }, + "make": { + "type": "string", + "description": "Car make" + }, + "model": { + "type": "string", + "description": "Car model" + }, + "year": { + "type": "integer", + "description": "Car year" + }, + "isElectric": { + "type": "boolean", + "description": "Car isElectric" + } + }, + "required": [ + "id" + ] + } + }, + { + "name": "myapp_car_delete", + "description": "Delete a Car record by id", + "inputSchema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Car id" + } + }, + "required": [ + "id" + ] + } + }, + { + "name": "myapp_car_fields", + "description": "List available fields for Car", + "inputSchema": { + "type": "object", + "properties": {} + }, + "_meta": { + "fields": [ + { + "name": "id", + "type": "UUID", + "editable": false, + "primaryKey": true + }, + { + "name": "make", + "type": "String", + "editable": true, + "primaryKey": false + }, + { + "name": "model", + "type": "String", + "editable": true, + "primaryKey": false + }, + { + "name": "year", + "type": "Int", + "editable": true, + "primaryKey": false + }, + { + "name": "isElectric", + "type": "Boolean", + "editable": true, + "primaryKey": false + }, + { + "name": "createdAt", + "type": "Datetime", + "editable": false, + "primaryKey": false + } + ] + } + }, + { + "name": "myapp_driver_list", + "description": "List all Driver records", + "inputSchema": { + "type": "object", + "properties": {} + } + }, + { + "name": "myapp_driver_get", + "description": "Get a single Driver record by id", + "inputSchema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Driver id" + } + }, + "required": [ + "id" + ] + } + }, + { + "name": "myapp_driver_create", + "description": "Create a new Driver record", + "inputSchema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Driver name" + }, + "licenseNumber": { + "type": "string", + "description": "Driver licenseNumber" + } + }, + "required": [ + "name", + "licenseNumber" + ] + } + }, + { + "name": "myapp_driver_update", + "description": "Update an existing Driver record", + "inputSchema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Driver id" + }, + "name": { + "type": "string", + "description": "Driver name" + }, + "licenseNumber": { + "type": "string", + "description": "Driver licenseNumber" + } + }, + "required": [ + "id" + ] + } + }, + { + "name": "myapp_driver_delete", + "description": "Delete a Driver record by id", + "inputSchema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Driver id" + } + }, + "required": [ + "id" + ] + } + }, + { + "name": "myapp_driver_fields", + "description": "List available fields for Driver", + "inputSchema": { + "type": "object", + "properties": {} + }, + "_meta": { + "fields": [ + { + "name": "id", + "type": "UUID", + "editable": false, + "primaryKey": true + }, + { + "name": "name", + "type": "String", + "editable": true, + "primaryKey": false + }, + { + "name": "licenseNumber", + "type": "String", + "editable": true, + "primaryKey": false + } + ] + } + }, + { + "name": "myapp_current-user", + "description": "Get the currently authenticated user", + "inputSchema": { + "type": "object", + "properties": {} + } + }, + { + "name": "myapp_login", + "description": "Authenticate a user", + "inputSchema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "email" + }, + "password": { + "type": "string", + "description": "password" + } + }, + "required": [ + "email", + "password" + ] + } + } + ] +} +" +`; + +exports[`cli-generator docs: true (all formats) generates skill files 1`] = ` +"# myapp-context > @generated by @constructive-io/graphql-codegen - DO NOT EDIT ---- +Manage API endpoint contexts for myapp -## context(1) +## Usage -### NAME +\`\`\`bash +myapp context create --endpoint +myapp context list +myapp context use +myapp context current +myapp context delete +\`\`\` -context - manage API endpoint contexts +## Examples -### SYNOPSIS +### Create and activate a context - myapp context [options] +\`\`\`bash +myapp context create production --endpoint https://api.example.com/graphql +myapp context use production +\`\`\` -### COMMANDS +### List all contexts -**create** \`\` \`--endpoint \` +\`\`\`bash +myapp context list +\`\`\` +" +`; - Create a named context pointing at a GraphQL endpoint. - Config stored at ~/.myapp/config/contexts/.json +exports[`cli-generator docs: true (all formats) generates skill files 2`] = ` +"# myapp-auth -**list** +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT - List all configured contexts with auth status. +Manage authentication tokens for myapp -**use** \`\` +## Usage - Set the active context for subsequent commands. +\`\`\`bash +myapp auth set-token +myapp auth status +myapp auth logout +\`\`\` -**current** +## Examples - Display the currently active context and its endpoint. +### Authenticate with a token -**delete** \`\` +\`\`\`bash +myapp auth set-token eyJhbGciOiJIUzI1NiIs... +\`\`\` - Remove a context and its configuration. +### Check auth status ---- +\`\`\`bash +myapp auth status +\`\`\` +" +`; -## auth(1) +exports[`cli-generator docs: true (all formats) generates skill files 3`] = ` +"# myapp-car -### NAME +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT -auth - manage authentication tokens +CRUD operations for Car records via myapp CLI -### SYNOPSIS +## Usage - myapp auth [options] +\`\`\`bash +myapp car list +myapp car get --id +myapp car create --make --model --year --isElectric +myapp car update --id [--make ] [--model ] [--year ] [--isElectric ] +myapp car delete --id +\`\`\` -### COMMANDS +## Examples -**set-token** \`\` \`[--context ]\` +### List all car records - Store a bearer token for the current (or specified) context. - Credentials stored at ~/.myapp/config/credentials.json (mode 0600). +\`\`\`bash +myapp car list +\`\`\` -**status** +### Create a car - Show authentication status for all contexts. +\`\`\`bash +myapp car create --make "value" --model "value" --year "value" --isElectric "value" +\`\`\` -**logout** \`[--context ]\` +### Get a car by id - Remove stored credentials for the current (or specified) context. +\`\`\`bash +myapp car get --id +\`\`\` ---- +### Update a car -## car(1) +\`\`\`bash +myapp car update --id --make "new-value" +\`\`\` -### NAME +### Delete a car -car - manage Car records +\`\`\`bash +myapp car delete --id +\`\`\` +" +`; -### SYNOPSIS +exports[`cli-generator docs: true (all formats) generates skill files 4`] = ` +"# myapp-driver - car [options] +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT -### COMMANDS +CRUD operations for Driver records via myapp CLI -**list** +## Usage - car list +\`\`\`bash +myapp driver list +myapp driver get --id +myapp driver create --name --licenseNumber +myapp driver update --id [--name ] [--licenseNumber ] +myapp driver delete --id +\`\`\` -List all car records. Returns JSON array. +## Examples -Selected fields: id, make, model, year, isElectric, createdAt +### List all driver records -**get** +\`\`\`bash +myapp driver list +\`\`\` - car get --id +### Create a driver -Fetch a single car by its id. +\`\`\`bash +myapp driver create --name "value" --licenseNumber "value" +\`\`\` -**create** +### Get a driver by id - car create --make --model --year --isElectric +\`\`\`bash +myapp driver get --id +\`\`\` -Create a new car. All fields are required. +### Update a driver - Options: - --make String (required) - --model String (required) - --year Int (required) - --isElectric Boolean (required) +\`\`\`bash +myapp driver update --id --name "new-value" +\`\`\` -**update** +### Delete a driver - car update --id [--make ] [--model ] [--year ] [--isElectric ] +\`\`\`bash +myapp driver delete --id +\`\`\` +" +`; -Update an existing car. Only provided fields are changed. +exports[`cli-generator docs: true (all formats) generates skill files 5`] = ` +"# myapp-current-user - Options: - --id UUID (required) - --make String - --model String - --year Int - --isElectric Boolean +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT -**delete** +Get the currently authenticated user - car delete --id +## Usage -Delete a car by its id. +\`\`\`bash +myapp current-user +\`\`\` ---- +## Examples -## driver(1) +### Run currentUser -### NAME +\`\`\`bash +myapp current-user +\`\`\` +" +`; -driver - manage Driver records +exports[`cli-generator docs: true (all formats) generates skill files 6`] = ` +"# myapp-login -### SYNOPSIS +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT - driver [options] +Authenticate a user -### COMMANDS +## Usage -**list** +\`\`\`bash +myapp login --email --password +\`\`\` - driver list +## Examples -List all driver records. Returns JSON array. +### Run login -Selected fields: id, name, licenseNumber +\`\`\`bash +myapp login --email --password +\`\`\` +" +`; -**get** +exports[`cli-generator generates AGENTS.md by default 1`] = ` +"# myapp CLI - Agent Reference - driver get --id +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT +> This document is structured for LLM/agent consumption. -Fetch a single driver by its id. +## OVERVIEW -**create** +\`myapp\` is a CLI tool for interacting with a GraphQL API. +All commands output JSON to stdout. All commands accept \`--help\` or \`-h\` for usage. +Configuration is stored at \`~/.myapp/config/\` via appstash. - driver create --name --licenseNumber +## PREREQUISITES -Create a new driver. All fields are required. +Before running any data commands, you must: - Options: - --name String (required) - --licenseNumber String (required) +1. Create a context: \`myapp context create --endpoint \` +2. Activate it: \`myapp context use \` +3. Authenticate: \`myapp auth set-token \` -**update** +## TOOLS - driver update --id [--name ] [--licenseNumber ] +### TOOL: context -Update an existing driver. Only provided fields are changed. +Manage named API endpoint contexts (like kubectl contexts). - Options: - --id UUID (required) - --name String - --licenseNumber String +\`\`\` +SUBCOMMANDS: + myapp context create --endpoint Create a new context + myapp context list List all contexts + myapp context use Set active context + myapp context current Show active context + myapp context delete Delete a context + +INPUT: + name: string (required) - Context identifier + endpoint: string (required for create) - GraphQL endpoint URL + +OUTPUT: JSON + create: { name, endpoint } + list: [{ name, endpoint, isCurrent, hasCredentials }] + use: { name, endpoint } + current: { name, endpoint } + delete: { deleted: name } +\`\`\` -**delete** +### TOOL: auth - driver delete --id +Manage authentication tokens per context. -Delete a driver by its id. +\`\`\` +SUBCOMMANDS: + myapp auth set-token Store bearer token for current context + myapp auth status Show auth status for all contexts + myapp auth logout Remove credentials for current context + +INPUT: + token: string (required for set-token) - Bearer token value + +OUTPUT: JSON + set-token: { context, status: "authenticated" } + status: [{ context, authenticated: boolean }] + logout: { context, status: "logged out" } +\`\`\` ---- +### TOOL: car -## current-user(1) +CRUD operations for Car records. -### NAME +\`\`\` +SUBCOMMANDS: + myapp car list List all records + myapp car get --id Get one record + myapp car create --make --model --year --isElectric + myapp car update --id [--make ] [--model ] [--year ] [--isElectric ] + myapp car delete --id Delete one record + +INPUT FIELDS: + id: UUID (primary key) + make: String + model: String + year: Int + isElectric: Boolean + createdAt: Datetime + +EDITABLE FIELDS (for create/update): + make: String + model: String + year: Int + isElectric: Boolean + +OUTPUT: JSON + list: [{ id, make, model, year, isElectric, createdAt }] + get: { id, make, model, year, isElectric, createdAt } + create: { id, make, model, year, isElectric, createdAt } + update: { id, make, model, year, isElectric, createdAt } + delete: { id } +\`\`\` -current-user - Get the currently authenticated user +### TOOL: driver -### SYNOPSIS +CRUD operations for Driver records. - current-user +\`\`\` +SUBCOMMANDS: + myapp driver list List all records + myapp driver get --id Get one record + myapp driver create --name --licenseNumber + myapp driver update --id [--name ] [--licenseNumber ] + myapp driver delete --id Delete one record + +INPUT FIELDS: + id: UUID (primary key) + name: String + licenseNumber: String + +EDITABLE FIELDS (for create/update): + name: String + licenseNumber: String + +OUTPUT: JSON + list: [{ id, name, licenseNumber }] + get: { id, name, licenseNumber } + create: { id, name, licenseNumber } + update: { id, name, licenseNumber } + delete: { id } +\`\`\` -### DESCRIPTION +### TOOL: current-user Get the currently authenticated user ---- +\`\`\` +TYPE: query +USAGE: myapp current-user + +INPUT: none + +OUTPUT: JSON +\`\`\` -## login(1) +### TOOL: login -### NAME +Authenticate a user -login - Authenticate a user +\`\`\` +TYPE: mutation +USAGE: myapp login --email --password -### SYNOPSIS +INPUT: + email: String (required) + password: String (required) - login --email --password +OUTPUT: JSON +\`\`\` -### DESCRIPTION +## WORKFLOWS -Authenticate a user +### Initial setup -### OPTIONS +\`\`\`bash +myapp context create dev --endpoint http://localhost:5000/graphql +myapp context use dev +myapp auth set-token eyJhbGciOiJIUzI1NiIs... +\`\`\` + +### CRUD workflow (car) + +\`\`\`bash +# List all +myapp car list + +# Create +myapp car create --make "value" --model "value" --year "value" --isElectric "value" + +# Get by id +myapp car get --id + +# Update +myapp car update --id --make "new-value" + +# Delete +myapp car delete --id +\`\`\` + +### Piping output + +\`\`\`bash +# Pretty print +myapp car list | jq '.' + +# Extract field +myapp car list | jq '.[].id' + +# Count results +myapp car list | jq 'length' +\`\`\` -**--email** String (required) +## ERROR HANDLING -**--password** String (required) +All errors are written to stderr. Exit codes: +- \`0\`: Success +- \`1\`: Error (auth failure, not found, validation error, network error) ---- +Common errors: +- "No active context": Run \`context use \` first +- "Not authenticated": Run \`auth set-token \` first +- "Record not found": The requested ID does not exist " `; -exports[`cli-generator generates README.md 1`] = ` +exports[`cli-generator generates README.md by default 1`] = ` "# myapp CLI > Auto-generated CLI commands from GraphQL schema diff --git a/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts b/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts index 01bd8a753..320d20151 100644 --- a/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts +++ b/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts @@ -133,6 +133,30 @@ describe('cli-generator', () => { }); }); + it('generates README.md by default', () => { + const file = result.files.find((f) => f.fileName === 'README.md'); + expect(file).toBeDefined(); + expect(file!.content).toMatchSnapshot(); + }); + + it('generates AGENTS.md by default', () => { + const file = result.files.find((f) => f.fileName === 'AGENTS.md'); + expect(file).toBeDefined(); + expect(file!.content).toMatchSnapshot(); + }); + + it('does not generate mcp.json by default', () => { + const file = result.files.find((f) => f.fileName === 'mcp.json'); + expect(file).toBeUndefined(); + }); + + it('does not generate skills by default', () => { + const skillFiles = result.files.filter((f) => + f.fileName.startsWith('skills/'), + ); + expect(skillFiles).toHaveLength(0); + }); + it('generates executor.ts', () => { const file = result.files.find((f) => f.fileName === 'executor.ts'); expect(file).toBeDefined(); @@ -187,17 +211,6 @@ describe('cli-generator', () => { expect(file!.content).toMatchSnapshot(); }); - it('generates README.md', () => { - const file = result.files.find((f) => f.fileName === 'README.md'); - expect(file).toBeDefined(); - expect(file!.content).toMatchSnapshot(); - }); - - it('generates COMMANDS.md (man-page reference)', () => { - const file = result.files.find((f) => f.fileName === 'COMMANDS.md'); - expect(file).toBeDefined(); - expect(file!.content).toMatchSnapshot(); - }); it('uses ORM methods in table commands', () => { const carFile = result.files.find( @@ -228,7 +241,52 @@ describe('cli-generator', () => { it('generates correct file names', () => { const fileNames = result.files.map((f) => f.fileName).sort(); expect(fileNames).toEqual([ - 'COMMANDS.md', + 'AGENTS.md', + 'README.md', + 'commands.ts', + 'commands/auth.ts', + 'commands/car.ts', + 'commands/context.ts', + 'commands/current-user.ts', + 'commands/driver.ts', + 'commands/login.ts', + 'executor.ts', + ]); + }); +}); + +describe('cli-generator docs: true (all formats)', () => { + const result = generateCli({ + tables: [carTable, driverTable], + customOperations: { + queries: [currentUserQuery], + mutations: [loginMutation], + }, + config: { + cli: { toolName: 'myapp', docs: true }, + }, + }); + + it('generates mcp.json', () => { + const file = result.files.find((f) => f.fileName === 'mcp.json'); + expect(file).toBeDefined(); + expect(file!.content).toMatchSnapshot(); + }); + + it('generates skill files', () => { + const skillFiles = result.files.filter((f) => + f.fileName.startsWith('skills/'), + ); + expect(skillFiles.length).toBeGreaterThan(0); + for (const sf of skillFiles) { + expect(sf.content).toMatchSnapshot(); + } + }); + + it('generates correct file names with all docs', () => { + const fileNames = result.files.map((f) => f.fileName).sort(); + expect(fileNames).toEqual([ + 'AGENTS.md', 'README.md', 'commands.ts', 'commands/auth.ts', @@ -238,6 +296,50 @@ describe('cli-generator', () => { 'commands/driver.ts', 'commands/login.ts', 'executor.ts', + 'mcp.json', + 'skills/auth.md', + 'skills/car.md', + 'skills/context.md', + 'skills/current-user.md', + 'skills/driver.md', + 'skills/login.md', ]); }); + + it('mcp.json has valid tool definitions', () => { + const file = result.files.find((f) => f.fileName === 'mcp.json'); + const parsed = JSON.parse(file!.content); + expect(parsed.name).toBe('myapp'); + expect(parsed.tools).toBeDefined(); + expect(parsed.tools.length).toBeGreaterThan(0); + for (const tool of parsed.tools) { + expect(tool.name).toBeDefined(); + expect(tool.description).toBeDefined(); + expect(tool.inputSchema).toBeDefined(); + } + }); +}); + +describe('cli-generator docs: false', () => { + const result = generateCli({ + tables: [carTable, driverTable], + customOperations: { + queries: [currentUserQuery], + mutations: [loginMutation], + }, + config: { + cli: { toolName: 'myapp', docs: false }, + }, + }); + + it('generates no doc files', () => { + const docFiles = result.files.filter( + (f) => + f.fileName === 'README.md' || + f.fileName === 'AGENTS.md' || + f.fileName === 'mcp.json' || + f.fileName.startsWith('skills/'), + ); + expect(docFiles).toHaveLength(0); + }); }); diff --git a/graphql/codegen/src/core/codegen/cli/docs-generator.ts b/graphql/codegen/src/core/codegen/cli/docs-generator.ts index f9fda4c49..41bece590 100644 --- a/graphql/codegen/src/core/codegen/cli/docs-generator.ts +++ b/graphql/codegen/src/core/codegen/cli/docs-generator.ts @@ -6,6 +6,7 @@ import { getPrimaryKeyInfo, } from '../utils'; import type { CleanTable, CleanOperation } from '../../../types/schema'; +import type { DocsConfig } from '../../../types/config'; import type { GeneratedFile } from './executor-generator'; function formatArgType(arg: CleanOperation['args'][number]): string { @@ -26,196 +27,48 @@ function formatTypeRef(t: CleanOperation['args'][number]['type']): string { return t.name ?? 'unknown'; } -function buildTableSection(table: CleanTable): string { - const { singularName } = getTableNames(table); - const kebab = toKebabCase(singularName); +function getEditableFields(table: CleanTable) { const pk = getPrimaryKeyInfo(table)[0]; - const scalarFields = getScalarFields(table); - const editableFields = scalarFields.filter( + return getScalarFields(table).filter( (f) => f.name !== pk.name && f.name !== 'nodeId' && f.name !== 'createdAt' && f.name !== 'updatedAt', ); - - const lines: string[] = []; - - lines.push(`### \`${kebab}\``); - lines.push(''); - lines.push(`CRUD operations for ${table.name} records.`); - lines.push(''); - lines.push('| Subcommand | Description |'); - lines.push('|------------|-------------|'); - lines.push(`| \`list\` | List all ${singularName} records |`); - lines.push(`| \`get\` | Get a ${singularName} by ${pk.name} |`); - lines.push(`| \`create\` | Create a new ${singularName} |`); - lines.push(`| \`update\` | Update an existing ${singularName} |`); - lines.push(`| \`delete\` | Delete a ${singularName} |`); - lines.push(''); - - lines.push('**Fields:**'); - lines.push(''); - lines.push('| Field | Type |'); - lines.push('|-------|------|'); - for (const f of scalarFields) { - lines.push(`| \`${f.name}\` | ${f.type.gqlType} |`); - } - lines.push(''); - - lines.push(`**Create fields:** ${editableFields.map((f) => `\`${f.name}\``).join(', ')}`); - lines.push(''); - - return lines.join('\n'); } -function buildCustomOpSection(op: CleanOperation): string { - const kebab = toKebabCase(op.name); - const lines: string[] = []; - - lines.push(`### \`${kebab}\``); - lines.push(''); - lines.push(op.description || op.name); - lines.push(''); - lines.push(`- **Type:** ${op.kind}`); - - if (op.args.length > 0) { - lines.push('- **Arguments:**'); - lines.push(''); - lines.push(' | Argument | Type |'); - lines.push(' |----------|------|'); - for (const arg of op.args) { - lines.push(` | \`${arg.name}\` | ${formatArgType(arg)} |`); - } - lines.push(''); - } else { - lines.push('- **Arguments:** none'); - lines.push(''); +function gqlTypeToJsonSchemaType(gqlType: string): string { + switch (gqlType) { + case 'Int': + return 'integer'; + case 'Float': + return 'number'; + case 'Boolean': + return 'boolean'; + default: + return 'string'; } - - return lines.join('\n'); } -function buildTableManPage(table: CleanTable): string { - const { singularName } = getTableNames(table); - const kebab = toKebabCase(singularName); - const pk = getPrimaryKeyInfo(table)[0]; - const scalarFields = getScalarFields(table); - const editableFields = scalarFields.filter( - (f) => - f.name !== pk.name && - f.name !== 'nodeId' && - f.name !== 'createdAt' && - f.name !== 'updatedAt', - ); - - const lines: string[] = []; - - lines.push(`## ${kebab}(1)`); - lines.push(''); - lines.push('### NAME'); - lines.push(''); - lines.push(`${kebab} - manage ${table.name} records`); - lines.push(''); - lines.push('### SYNOPSIS'); - lines.push(''); - lines.push(` ${kebab} [options]`); - lines.push(''); - lines.push('### COMMANDS'); - lines.push(''); - - lines.push('**list**'); - lines.push(''); - lines.push(` ${kebab} list`); - lines.push(''); - lines.push(`List all ${singularName} records. Returns JSON array.`); - lines.push(''); - lines.push(`Selected fields: ${scalarFields.map((f) => f.name).join(', ')}`); - lines.push(''); - - lines.push('**get**'); - lines.push(''); - lines.push(` ${kebab} get --${pk.name} `); - lines.push(''); - lines.push(`Fetch a single ${singularName} by its ${pk.name}.`); - lines.push(''); - - lines.push('**create**'); - lines.push(''); - const createFlags = editableFields.map((f) => `--${f.name} `).join(' '); - lines.push(` ${kebab} create ${createFlags}`); - lines.push(''); - lines.push(`Create a new ${singularName}. All fields are required.`); - lines.push(''); - lines.push(' Options:'); - for (const f of editableFields) { - lines.push(` --${f.name.padEnd(20)} ${f.type.gqlType} (required)`); +export function resolveDocsConfig( + docs: DocsConfig | boolean | undefined, +): DocsConfig { + if (docs === true) { + return { readme: true, agents: true, mcp: true, skills: true }; } - lines.push(''); - - lines.push('**update**'); - lines.push(''); - const updateFlags = editableFields.map((f) => `[--${f.name} ]`).join(' '); - lines.push(` ${kebab} update --${pk.name} ${updateFlags}`); - lines.push(''); - lines.push(`Update an existing ${singularName}. Only provided fields are changed.`); - lines.push(''); - lines.push(' Options:'); - lines.push(` --${pk.name.padEnd(20)} ${pk.gqlType} (required)`); - for (const f of editableFields) { - lines.push(` --${f.name.padEnd(20)} ${f.type.gqlType}`); - } - lines.push(''); - - lines.push('**delete**'); - lines.push(''); - lines.push(` ${kebab} delete --${pk.name} `); - lines.push(''); - lines.push(`Delete a ${singularName} by its ${pk.name}.`); - lines.push(''); - - return lines.join('\n'); -} - -function buildCustomOpManPage(op: CleanOperation): string { - const kebab = toKebabCase(op.name); - const lines: string[] = []; - - lines.push(`## ${kebab}(1)`); - lines.push(''); - lines.push('### NAME'); - lines.push(''); - lines.push(`${kebab} - ${op.description || op.name}`); - lines.push(''); - lines.push('### SYNOPSIS'); - lines.push(''); - - if (op.args.length > 0) { - const flags = op.args.map((a) => `--${a.name} `).join(' '); - lines.push(` ${kebab} ${flags}`); - } else { - lines.push(` ${kebab}`); + if (docs === false) { + return { readme: false, agents: false, mcp: false, skills: false }; } - lines.push(''); - - lines.push('### DESCRIPTION'); - lines.push(''); - lines.push(op.description || `Execute the ${op.name} ${op.kind}.`); - lines.push(''); - - if (op.args.length > 0) { - lines.push('### OPTIONS'); - lines.push(''); - for (const arg of op.args) { - lines.push(`**--${arg.name}** ${formatArgType(arg)}`); - if (arg.description) { - lines.push(` ${arg.description}`); - } - lines.push(''); - } + if (!docs) { + return { readme: true, agents: true, mcp: false, skills: false }; } - - return lines.join('\n'); + return { + readme: docs.readme ?? true, + agents: docs.agents ?? true, + mcp: docs.mcp ?? false, + skills: docs.skills ?? false, + }; } export function generateReadme( @@ -292,7 +145,34 @@ export function generateReadme( lines.push('## Table Commands'); lines.push(''); for (const table of tables) { - lines.push(buildTableSection(table)); + const { singularName } = getTableNames(table); + const kebab = toKebabCase(singularName); + const pk = getPrimaryKeyInfo(table)[0]; + const scalarFields = getScalarFields(table); + const editableFields = getEditableFields(table); + + lines.push(`### \`${kebab}\``); + lines.push(''); + lines.push(`CRUD operations for ${table.name} records.`); + lines.push(''); + lines.push('| Subcommand | Description |'); + lines.push('|------------|-------------|'); + lines.push(`| \`list\` | List all ${singularName} records |`); + lines.push(`| \`get\` | Get a ${singularName} by ${pk.name} |`); + lines.push(`| \`create\` | Create a new ${singularName} |`); + lines.push(`| \`update\` | Update an existing ${singularName} |`); + lines.push(`| \`delete\` | Delete a ${singularName} |`); + lines.push(''); + lines.push('**Fields:**'); + lines.push(''); + lines.push('| Field | Type |'); + lines.push('|-------|------|'); + for (const f of scalarFields) { + lines.push(`| \`${f.name}\` | ${f.type.gqlType} |`); + } + lines.push(''); + lines.push(`**Create fields:** ${editableFields.map((f) => `\`${f.name}\``).join(', ')}`); + lines.push(''); } } @@ -300,7 +180,24 @@ export function generateReadme( lines.push('## Custom Operations'); lines.push(''); for (const op of customOperations) { - lines.push(buildCustomOpSection(op)); + const kebab = toKebabCase(op.name); + lines.push(`### \`${kebab}\``); + lines.push(''); + lines.push(op.description || op.name); + lines.push(''); + lines.push(`- **Type:** ${op.kind}`); + if (op.args.length > 0) { + lines.push('- **Arguments:**'); + lines.push(''); + lines.push(' | Argument | Type |'); + lines.push(' |----------|------|'); + for (const arg of op.args) { + lines.push(` | \`${arg.name}\` | ${formatArgType(arg)} |`); + } + } else { + lines.push('- **Arguments:** none'); + } + lines.push(''); } } @@ -320,98 +217,608 @@ export function generateReadme( }; } -export function generateCommandReference( +export function generateAgentsDocs( tables: CleanTable[], customOperations: CleanOperation[], toolName: string, ): GeneratedFile { const lines: string[] = []; - lines.push(`# ${toolName} - Command Reference`); + lines.push(`# ${toolName} CLI - Agent Reference`); lines.push(''); lines.push('> @generated by @constructive-io/graphql-codegen - DO NOT EDIT'); - lines.push(''); - lines.push('---'); + lines.push('> This document is structured for LLM/agent consumption.'); lines.push(''); - lines.push('## context(1)'); + lines.push('## OVERVIEW'); lines.push(''); - lines.push('### NAME'); + lines.push(`\`${toolName}\` is a CLI tool for interacting with a GraphQL API.`); + lines.push('All commands output JSON to stdout. All commands accept `--help` or `-h` for usage.'); + lines.push(`Configuration is stored at \`~/.${toolName}/config/\` via appstash.`); lines.push(''); - lines.push('context - manage API endpoint contexts'); - lines.push(''); - lines.push('### SYNOPSIS'); - lines.push(''); - lines.push(` ${toolName} context [options]`); + + lines.push('## PREREQUISITES'); lines.push(''); - lines.push('### COMMANDS'); + lines.push('Before running any data commands, you must:'); lines.push(''); - lines.push('**create** `` `--endpoint `'); + lines.push(`1. Create a context: \`${toolName} context create --endpoint \``); + lines.push(`2. Activate it: \`${toolName} context use \``); + lines.push(`3. Authenticate: \`${toolName} auth set-token \``); lines.push(''); - lines.push(' Create a named context pointing at a GraphQL endpoint.'); - lines.push(` Config stored at ~/.${toolName}/config/contexts/.json`); + + lines.push('## TOOLS'); lines.push(''); - lines.push('**list**'); + + lines.push('### TOOL: context'); lines.push(''); - lines.push(' List all configured contexts with auth status.'); + lines.push('Manage named API endpoint contexts (like kubectl contexts).'); lines.push(''); - lines.push('**use** ``'); + lines.push('```'); + lines.push('SUBCOMMANDS:'); + lines.push(` ${toolName} context create --endpoint Create a new context`); + lines.push(` ${toolName} context list List all contexts`); + lines.push(` ${toolName} context use Set active context`); + lines.push(` ${toolName} context current Show active context`); + lines.push(` ${toolName} context delete Delete a context`); + lines.push(''); + lines.push('INPUT:'); + lines.push(' name: string (required) - Context identifier'); + lines.push(' endpoint: string (required for create) - GraphQL endpoint URL'); + lines.push(''); + lines.push('OUTPUT: JSON'); + lines.push(' create: { name, endpoint }'); + lines.push(' list: [{ name, endpoint, isCurrent, hasCredentials }]'); + lines.push(' use: { name, endpoint }'); + lines.push(' current: { name, endpoint }'); + lines.push(' delete: { deleted: name }'); + lines.push('```'); lines.push(''); - lines.push(' Set the active context for subsequent commands.'); + + lines.push('### TOOL: auth'); lines.push(''); - lines.push('**current**'); + lines.push('Manage authentication tokens per context.'); lines.push(''); - lines.push(' Display the currently active context and its endpoint.'); + lines.push('```'); + lines.push('SUBCOMMANDS:'); + lines.push(` ${toolName} auth set-token Store bearer token for current context`); + lines.push(` ${toolName} auth status Show auth status for all contexts`); + lines.push(` ${toolName} auth logout Remove credentials for current context`); + lines.push(''); + lines.push('INPUT:'); + lines.push(' token: string (required for set-token) - Bearer token value'); + lines.push(''); + lines.push('OUTPUT: JSON'); + lines.push(' set-token: { context, status: "authenticated" }'); + lines.push(' status: [{ context, authenticated: boolean }]'); + lines.push(' logout: { context, status: "logged out" }'); + lines.push('```'); lines.push(''); - lines.push('**delete** ``'); + + for (const table of tables) { + const { singularName } = getTableNames(table); + const kebab = toKebabCase(singularName); + const pk = getPrimaryKeyInfo(table)[0]; + const scalarFields = getScalarFields(table); + const editableFields = getEditableFields(table); + + lines.push(`### TOOL: ${kebab}`); + lines.push(''); + lines.push(`CRUD operations for ${table.name} records.`); + lines.push(''); + lines.push('```'); + lines.push('SUBCOMMANDS:'); + lines.push(` ${toolName} ${kebab} list List all records`); + lines.push(` ${toolName} ${kebab} get --${pk.name} Get one record`); + lines.push(` ${toolName} ${kebab} create ${editableFields.map((f) => `--${f.name} `).join(' ')}`); + lines.push(` ${toolName} ${kebab} update --${pk.name} ${editableFields.map((f) => `[--${f.name} ]`).join(' ')}`); + lines.push(` ${toolName} ${kebab} delete --${pk.name} Delete one record`); + lines.push(''); + lines.push('INPUT FIELDS:'); + for (const f of scalarFields) { + const isPk = f.name === pk.name; + lines.push(` ${f.name}: ${f.type.gqlType}${isPk ? ' (primary key)' : ''}`); + } + lines.push(''); + lines.push('EDITABLE FIELDS (for create/update):'); + for (const f of editableFields) { + lines.push(` ${f.name}: ${f.type.gqlType}`); + } + lines.push(''); + lines.push('OUTPUT: JSON'); + lines.push(` list: [{ ${scalarFields.map((f) => f.name).join(', ')} }]`); + lines.push(` get: { ${scalarFields.map((f) => f.name).join(', ')} }`); + lines.push(` create: { ${scalarFields.map((f) => f.name).join(', ')} }`); + lines.push(` update: { ${scalarFields.map((f) => f.name).join(', ')} }`); + lines.push(` delete: { ${pk.name} }`); + lines.push('```'); + lines.push(''); + } + + for (const op of customOperations) { + const kebab = toKebabCase(op.name); + + lines.push(`### TOOL: ${kebab}`); + lines.push(''); + lines.push(op.description || op.name); + lines.push(''); + lines.push('```'); + lines.push(`TYPE: ${op.kind}`); + if (op.args.length > 0) { + const flags = op.args.map((a) => `--${a.name} `).join(' '); + lines.push(`USAGE: ${toolName} ${kebab} ${flags}`); + lines.push(''); + lines.push('INPUT:'); + for (const arg of op.args) { + lines.push(` ${arg.name}: ${formatArgType(arg)}`); + } + } else { + lines.push(`USAGE: ${toolName} ${kebab}`); + lines.push(''); + lines.push('INPUT: none'); + } + lines.push(''); + lines.push('OUTPUT: JSON'); + lines.push('```'); + lines.push(''); + } + + lines.push('## WORKFLOWS'); lines.push(''); - lines.push(' Remove a context and its configuration.'); + lines.push('### Initial setup'); lines.push(''); - lines.push('---'); + lines.push('```bash'); + lines.push(`${toolName} context create dev --endpoint http://localhost:5000/graphql`); + lines.push(`${toolName} context use dev`); + lines.push(`${toolName} auth set-token eyJhbGciOiJIUzI1NiIs...`); + lines.push('```'); lines.push(''); - lines.push('## auth(1)'); + if (tables.length > 0) { + const firstTable = tables[0]; + const { singularName } = getTableNames(firstTable); + const kebab = toKebabCase(singularName); + const editableFields = getEditableFields(firstTable); + const pk = getPrimaryKeyInfo(firstTable)[0]; + + lines.push(`### CRUD workflow (${kebab})`); + lines.push(''); + lines.push('```bash'); + lines.push(`# List all`); + lines.push(`${toolName} ${kebab} list`); + lines.push(''); + lines.push(`# Create`); + lines.push(`${toolName} ${kebab} create ${editableFields.map((f) => `--${f.name} "value"`).join(' ')}`); + lines.push(''); + lines.push(`# Get by ${pk.name}`); + lines.push(`${toolName} ${kebab} get --${pk.name} `); + lines.push(''); + lines.push(`# Update`); + lines.push(`${toolName} ${kebab} update --${pk.name} --${editableFields[0]?.name || 'field'} "new-value"`); + lines.push(''); + lines.push(`# Delete`); + lines.push(`${toolName} ${kebab} delete --${pk.name} `); + lines.push('```'); + lines.push(''); + } + + lines.push('### Piping output'); lines.push(''); - lines.push('### NAME'); + lines.push('```bash'); + lines.push(`# Pretty print`); + lines.push(`${toolName} car list | jq '.'`); lines.push(''); - lines.push('auth - manage authentication tokens'); + lines.push(`# Extract field`); + lines.push(`${toolName} car list | jq '.[].id'`); lines.push(''); - lines.push('### SYNOPSIS'); + lines.push(`# Count results`); + lines.push(`${toolName} car list | jq 'length'`); + lines.push('```'); lines.push(''); - lines.push(` ${toolName} auth [options]`); + + lines.push('## ERROR HANDLING'); lines.push(''); - lines.push('### COMMANDS'); + lines.push('All errors are written to stderr. Exit codes:'); + lines.push('- `0`: Success'); + lines.push('- `1`: Error (auth failure, not found, validation error, network error)'); lines.push(''); - lines.push('**set-token** `` `[--context ]`'); + lines.push('Common errors:'); + lines.push('- "No active context": Run `context use ` first'); + lines.push('- "Not authenticated": Run `auth set-token ` first'); + lines.push('- "Record not found": The requested ID does not exist'); lines.push(''); - lines.push(' Store a bearer token for the current (or specified) context.'); - lines.push(` Credentials stored at ~/.${toolName}/config/credentials.json (mode 0600).`); + + return { + fileName: 'AGENTS.md', + content: lines.join('\n'), + }; +} + +export function generateMcpConfig( + tables: CleanTable[], + customOperations: CleanOperation[], + toolName: string, +): GeneratedFile { + const tools: Record[] = []; + + tools.push({ + name: `${toolName}_context_create`, + description: 'Create a named API context pointing at a GraphQL endpoint', + inputSchema: { + type: 'object', + properties: { + name: { type: 'string', description: 'Context name' }, + endpoint: { type: 'string', description: 'GraphQL endpoint URL' }, + }, + required: ['name', 'endpoint'], + }, + }); + + tools.push({ + name: `${toolName}_context_list`, + description: 'List all configured API contexts', + inputSchema: { type: 'object', properties: {} }, + }); + + tools.push({ + name: `${toolName}_context_use`, + description: 'Set the active API context', + inputSchema: { + type: 'object', + properties: { + name: { type: 'string', description: 'Context name to activate' }, + }, + required: ['name'], + }, + }); + + tools.push({ + name: `${toolName}_context_current`, + description: 'Show the currently active API context', + inputSchema: { type: 'object', properties: {} }, + }); + + tools.push({ + name: `${toolName}_context_delete`, + description: 'Delete an API context', + inputSchema: { + type: 'object', + properties: { + name: { type: 'string', description: 'Context name to delete' }, + }, + required: ['name'], + }, + }); + + tools.push({ + name: `${toolName}_auth_set_token`, + description: 'Store a bearer token for the current context', + inputSchema: { + type: 'object', + properties: { + token: { type: 'string', description: 'Bearer token value' }, + }, + required: ['token'], + }, + }); + + tools.push({ + name: `${toolName}_auth_status`, + description: 'Show authentication status for all contexts', + inputSchema: { type: 'object', properties: {} }, + }); + + tools.push({ + name: `${toolName}_auth_logout`, + description: 'Remove credentials for the current context', + inputSchema: { type: 'object', properties: {} }, + }); + + for (const table of tables) { + const { singularName } = getTableNames(table); + const kebab = toKebabCase(singularName); + const pk = getPrimaryKeyInfo(table)[0]; + const scalarFields = getScalarFields(table); + const editableFields = getEditableFields(table); + + tools.push({ + name: `${toolName}_${kebab}_list`, + description: `List all ${table.name} records`, + inputSchema: { type: 'object', properties: {} }, + }); + + tools.push({ + name: `${toolName}_${kebab}_get`, + description: `Get a single ${table.name} record by ${pk.name}`, + inputSchema: { + type: 'object', + properties: { + [pk.name]: { + type: gqlTypeToJsonSchemaType(pk.gqlType), + description: `${table.name} ${pk.name}`, + }, + }, + required: [pk.name], + }, + }); + + const createProps: Record = {}; + for (const f of editableFields) { + createProps[f.name] = { + type: gqlTypeToJsonSchemaType(f.type.gqlType), + description: `${table.name} ${f.name}`, + }; + } + tools.push({ + name: `${toolName}_${kebab}_create`, + description: `Create a new ${table.name} record`, + inputSchema: { + type: 'object', + properties: createProps, + required: editableFields.map((f) => f.name), + }, + }); + + const updateProps: Record = { + [pk.name]: { + type: gqlTypeToJsonSchemaType(pk.gqlType), + description: `${table.name} ${pk.name}`, + }, + }; + for (const f of editableFields) { + updateProps[f.name] = { + type: gqlTypeToJsonSchemaType(f.type.gqlType), + description: `${table.name} ${f.name}`, + }; + } + tools.push({ + name: `${toolName}_${kebab}_update`, + description: `Update an existing ${table.name} record`, + inputSchema: { + type: 'object', + properties: updateProps, + required: [pk.name], + }, + }); + + tools.push({ + name: `${toolName}_${kebab}_delete`, + description: `Delete a ${table.name} record by ${pk.name}`, + inputSchema: { + type: 'object', + properties: { + [pk.name]: { + type: gqlTypeToJsonSchemaType(pk.gqlType), + description: `${table.name} ${pk.name}`, + }, + }, + required: [pk.name], + }, + }); + + tools.push({ + name: `${toolName}_${kebab}_fields`, + description: `List available fields for ${table.name}`, + inputSchema: { type: 'object', properties: {} }, + _meta: { + fields: scalarFields.map((f) => ({ + name: f.name, + type: f.type.gqlType, + editable: editableFields.some((ef) => ef.name === f.name), + primaryKey: f.name === pk.name, + })), + }, + }); + } + + for (const op of customOperations) { + const kebab = toKebabCase(op.name); + const props: Record = {}; + const required: string[] = []; + + for (const arg of op.args) { + const isRequired = arg.type.kind === 'NON_NULL'; + const baseType = isRequired && arg.type.ofType ? arg.type.ofType : arg.type; + props[arg.name] = { + type: gqlTypeToJsonSchemaType(baseType.name ?? 'String'), + description: arg.description || arg.name, + }; + if (isRequired) { + required.push(arg.name); + } + } + + tools.push({ + name: `${toolName}_${kebab}`, + description: op.description || op.name, + inputSchema: { + type: 'object', + properties: props, + ...(required.length > 0 ? { required } : {}), + }, + }); + } + + const mcpConfig = { + name: toolName, + version: '1.0.0', + description: `MCP tool definitions for ${toolName} CLI (auto-generated from GraphQL schema)`, + tools, + }; + + return { + fileName: 'mcp.json', + content: JSON.stringify(mcpConfig, null, 2) + '\n', + }; +} + +export function generateSkills( + tables: CleanTable[], + customOperations: CleanOperation[], + toolName: string, +): GeneratedFile[] { + const files: GeneratedFile[] = []; + + files.push({ + fileName: 'skills/context.md', + content: buildSkillFile({ + name: `${toolName}-context`, + description: `Manage API endpoint contexts for ${toolName}`, + usage: [ + `${toolName} context create --endpoint `, + `${toolName} context list`, + `${toolName} context use `, + `${toolName} context current`, + `${toolName} context delete `, + ], + examples: [ + { + description: 'Create and activate a context', + commands: [ + `${toolName} context create production --endpoint https://api.example.com/graphql`, + `${toolName} context use production`, + ], + }, + { + description: 'List all contexts', + commands: [`${toolName} context list`], + }, + ], + }), + }); + + files.push({ + fileName: 'skills/auth.md', + content: buildSkillFile({ + name: `${toolName}-auth`, + description: `Manage authentication tokens for ${toolName}`, + usage: [ + `${toolName} auth set-token `, + `${toolName} auth status`, + `${toolName} auth logout`, + ], + examples: [ + { + description: 'Authenticate with a token', + commands: [`${toolName} auth set-token eyJhbGciOiJIUzI1NiIs...`], + }, + { + description: 'Check auth status', + commands: [`${toolName} auth status`], + }, + ], + }), + }); + + for (const table of tables) { + const { singularName } = getTableNames(table); + const kebab = toKebabCase(singularName); + const pk = getPrimaryKeyInfo(table)[0]; + const editableFields = getEditableFields(table); + + files.push({ + fileName: `skills/${kebab}.md`, + content: buildSkillFile({ + name: `${toolName}-${kebab}`, + description: `CRUD operations for ${table.name} records via ${toolName} CLI`, + usage: [ + `${toolName} ${kebab} list`, + `${toolName} ${kebab} get --${pk.name} `, + `${toolName} ${kebab} create ${editableFields.map((f) => `--${f.name} `).join(' ')}`, + `${toolName} ${kebab} update --${pk.name} ${editableFields.map((f) => `[--${f.name} ]`).join(' ')}`, + `${toolName} ${kebab} delete --${pk.name} `, + ], + examples: [ + { + description: `List all ${singularName} records`, + commands: [`${toolName} ${kebab} list`], + }, + { + description: `Create a ${singularName}`, + commands: [ + `${toolName} ${kebab} create ${editableFields.map((f) => `--${f.name} "value"`).join(' ')}`, + ], + }, + { + description: `Get a ${singularName} by ${pk.name}`, + commands: [`${toolName} ${kebab} get --${pk.name} `], + }, + { + description: `Update a ${singularName}`, + commands: [ + `${toolName} ${kebab} update --${pk.name} --${editableFields[0]?.name || 'field'} "new-value"`, + ], + }, + { + description: `Delete a ${singularName}`, + commands: [`${toolName} ${kebab} delete --${pk.name} `], + }, + ], + }), + }); + } + + for (const op of customOperations) { + const kebab = toKebabCase(op.name); + const usage = + op.args.length > 0 + ? `${toolName} ${kebab} ${op.args.map((a) => `--${a.name} `).join(' ')}` + : `${toolName} ${kebab}`; + + files.push({ + fileName: `skills/${kebab}.md`, + content: buildSkillFile({ + name: `${toolName}-${kebab}`, + description: op.description || `Execute the ${op.name} ${op.kind}`, + usage: [usage], + examples: [ + { + description: `Run ${op.name}`, + commands: [usage], + }, + ], + }), + }); + } + + return files; +} + +interface SkillDefinition { + name: string; + description: string; + usage: string[]; + examples: { description: string; commands: string[] }[]; +} + +function buildSkillFile(skill: SkillDefinition): string { + const lines: string[] = []; + + lines.push(`# ${skill.name}`); lines.push(''); - lines.push('**status**'); + lines.push(`> @generated by @constructive-io/graphql-codegen - DO NOT EDIT`); lines.push(''); - lines.push(' Show authentication status for all contexts.'); + lines.push(skill.description); lines.push(''); - lines.push('**logout** `[--context ]`'); + lines.push('## Usage'); lines.push(''); - lines.push(' Remove stored credentials for the current (or specified) context.'); + lines.push('```bash'); + for (const u of skill.usage) { + lines.push(u); + } + lines.push('```'); lines.push(''); - lines.push('---'); + lines.push('## Examples'); lines.push(''); - - for (const table of tables) { - lines.push(buildTableManPage(table)); - lines.push('---'); + for (const ex of skill.examples) { + lines.push(`### ${ex.description}`); lines.push(''); - } - - for (const op of customOperations) { - lines.push(buildCustomOpManPage(op)); - lines.push('---'); + lines.push('```bash'); + for (const cmd of ex.commands) { + lines.push(cmd); + } + lines.push('```'); lines.push(''); } - return { - fileName: 'COMMANDS.md', - content: lines.join('\n'), - }; + return lines.join('\n'); } diff --git a/graphql/codegen/src/core/codegen/cli/index.ts b/graphql/codegen/src/core/codegen/cli/index.ts index a40e8effa..85f3f0de4 100644 --- a/graphql/codegen/src/core/codegen/cli/index.ts +++ b/graphql/codegen/src/core/codegen/cli/index.ts @@ -1,8 +1,14 @@ -import type { GraphQLSDKConfigTarget } from '../../../types/config'; +import type { CliConfig, GraphQLSDKConfigTarget } from '../../../types/config'; import type { CleanOperation, CleanTable } from '../../../types/schema'; import { generateCommandMap } from './command-map-generator'; import { generateCustomCommand } from './custom-command-generator'; -import { generateReadme, generateCommandReference } from './docs-generator'; +import { + generateReadme, + generateAgentsDocs, + generateMcpConfig, + generateSkills, + resolveDocsConfig, +} from './docs-generator'; import { generateExecutorFile } from './executor-generator'; import type { GeneratedFile } from './executor-generator'; import { generateAuthCommand, generateContextCommand } from './infra-generator'; @@ -69,11 +75,27 @@ export function generateCli(options: GenerateCliOptions): GenerateCliResult { ); files.push(commandMapFile); - const readmeFile = generateReadme(tables, allCustomOps, toolName); - files.push(readmeFile); + const docsConfig = resolveDocsConfig( + typeof cliConfig === 'object' ? (cliConfig as CliConfig).docs : undefined, + ); + + if (docsConfig.readme) { + files.push(generateReadme(tables, allCustomOps, toolName)); + } + + if (docsConfig.agents) { + files.push(generateAgentsDocs(tables, allCustomOps, toolName)); + } - const commandRefFile = generateCommandReference(tables, allCustomOps, toolName); - files.push(commandRefFile); + if (docsConfig.mcp) { + files.push(generateMcpConfig(tables, allCustomOps, toolName)); + } + + if (docsConfig.skills) { + for (const skillFile of generateSkills(tables, allCustomOps, toolName)) { + files.push(skillFile); + } + } return { files, @@ -97,6 +119,9 @@ export { } from './infra-generator'; export { generateReadme, - generateCommandReference, + generateAgentsDocs, + generateMcpConfig, + generateSkills, + resolveDocsConfig, } from './docs-generator'; export type { GeneratedFile } from './executor-generator'; diff --git a/graphql/codegen/src/types/config.ts b/graphql/codegen/src/types/config.ts index 54f0a6a18..602846f59 100644 --- a/graphql/codegen/src/types/config.ts +++ b/graphql/codegen/src/types/config.ts @@ -136,6 +136,42 @@ export interface DbConfig { keepDb?: boolean; } +/** + * Documentation generation options for CLI + * Controls which doc formats are generated alongside CLI commands + */ +export interface DocsConfig { + /** + * Generate README.md — human-readable overview with setup, commands, examples + * @default true + */ + readme?: boolean; + + /** + * Generate AGENTS.md — structured markdown optimized for LLM consumption + * Includes: tool definitions, exact signatures, input/output schemas, + * workflow recipes, error handling, and machine-parseable sections + * @default true + */ + agents?: boolean; + + /** + * Generate mcp.json — MCP (Model Context Protocol) tool definitions + * Each CLI command becomes a tool with typed inputSchema (JSON Schema) + * Ready to plug into any MCP-compatible agent + * @default false + */ + mcp?: boolean; + + /** + * Generate skills/ directory — per-command .md skill files + * Each command gets its own skill file with description, usage, and examples + * Compatible with Devin and similar agent skill systems + * @default false + */ + skills?: boolean; +} + /** * CLI generation configuration */ @@ -145,6 +181,14 @@ export interface CliConfig { * @default derived from output directory name */ toolName?: string; + + /** + * Documentation generation options + * Controls which doc formats are generated alongside CLI commands + * Set to `true` to enable all formats, or configure individually + * @default { readme: true, agents: true, mcp: false, skills: false } + */ + docs?: DocsConfig | boolean; } /** From 0fb16ea4187d9fb2d88fb80401908c211ffcdd9a Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Tue, 17 Feb 2026 18:56:21 +0000 Subject: [PATCH 05/23] feat(codegen): add docs generation for ORM, React Query, and multi-target support - Move docs config to top-level GraphQLSDKConfigTarget (removed from CliConfig) - Create shared docs-utils.ts with common utilities - Add ORM docs generator (README, AGENTS.md, MCP tools, skills) - Add React Query hooks docs generator (README, AGENTS.md, MCP tools, skills) - Add per-target README and combined MCP config generators - Add root-root README for multi-target configs - Add generateMulti() to core for multi-target orchestration - Update CLI entry point to use core generateMulti() - Wire all docs generation into generate.ts - 32 tests, 31 snapshots covering all doc formats --- .../__snapshots__/cli-generator.test.ts.snap | 4277 +++++++++++------ .../__tests__/codegen/cli-generator.test.ts | 254 +- graphql/codegen/src/cli/index.ts | 20 +- .../src/core/codegen/cli/docs-generator.ts | 160 +- graphql/codegen/src/core/codegen/cli/index.ts | 36 +- .../codegen/src/core/codegen/docs-utils.ts | 121 + .../src/core/codegen/hooks-docs-generator.ts | 595 +++ .../src/core/codegen/orm/docs-generator.ts | 525 ++ .../src/core/codegen/target-docs-generator.ts | 170 + graphql/codegen/src/core/generate.ts | 182 +- graphql/codegen/src/types/config.ts | 21 +- 11 files changed, 4535 insertions(+), 1826 deletions(-) create mode 100644 graphql/codegen/src/core/codegen/docs-utils.ts create mode 100644 graphql/codegen/src/core/codegen/hooks-docs-generator.ts create mode 100644 graphql/codegen/src/core/codegen/orm/docs-generator.ts create mode 100644 graphql/codegen/src/core/codegen/target-docs-generator.ts diff --git a/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap b/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap index e008e1216..1456442a7 100644 --- a/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap +++ b/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap @@ -1,1806 +1,2983 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing -exports[`cli-generator docs: true (all formats) generates mcp.json 1`] = ` -"{ - "name": "myapp", - "version": "1.0.0", - "description": "MCP tool definitions for myapp CLI (auto-generated from GraphQL schema)", - "tools": [ - { - "name": "myapp_context_create", - "description": "Create a named API context pointing at a GraphQL endpoint", - "inputSchema": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Context name" - }, - "endpoint": { - "type": "string", - "description": "GraphQL endpoint URL" - } - }, - "required": [ - "name", - "endpoint" - ] - } - }, - { - "name": "myapp_context_list", - "description": "List all configured API contexts", - "inputSchema": { - "type": "object", - "properties": {} - } - }, - { - "name": "myapp_context_use", - "description": "Set the active API context", - "inputSchema": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Context name to activate" - } - }, - "required": [ - "name" - ] - } - }, - { - "name": "myapp_context_current", - "description": "Show the currently active API context", - "inputSchema": { - "type": "object", - "properties": {} - } - }, - { - "name": "myapp_context_delete", - "description": "Delete an API context", - "inputSchema": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Context name to delete" - } - }, - "required": [ - "name" - ] - } - }, - { - "name": "myapp_auth_set_token", - "description": "Store a bearer token for the current context", - "inputSchema": { - "type": "object", - "properties": { - "token": { - "type": "string", - "description": "Bearer token value" - } - }, - "required": [ - "token" - ] - } - }, - { - "name": "myapp_auth_status", - "description": "Show authentication status for all contexts", - "inputSchema": { - "type": "object", - "properties": {} - } - }, - { - "name": "myapp_auth_logout", - "description": "Remove credentials for the current context", - "inputSchema": { - "type": "object", - "properties": {} - } - }, - { - "name": "myapp_car_list", - "description": "List all Car records", - "inputSchema": { - "type": "object", - "properties": {} - } - }, - { - "name": "myapp_car_get", - "description": "Get a single Car record by id", - "inputSchema": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Car id" - } - }, - "required": [ - "id" - ] - } - }, - { - "name": "myapp_car_create", - "description": "Create a new Car record", - "inputSchema": { - "type": "object", - "properties": { - "make": { - "type": "string", - "description": "Car make" - }, - "model": { - "type": "string", - "description": "Car model" - }, - "year": { - "type": "integer", - "description": "Car year" - }, - "isElectric": { - "type": "boolean", - "description": "Car isElectric" - } - }, - "required": [ - "make", - "model", - "year", - "isElectric" - ] - } - }, - { - "name": "myapp_car_update", - "description": "Update an existing Car record", - "inputSchema": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Car id" - }, - "make": { - "type": "string", - "description": "Car make" - }, - "model": { - "type": "string", - "description": "Car model" - }, - "year": { - "type": "integer", - "description": "Car year" - }, - "isElectric": { - "type": "boolean", - "description": "Car isElectric" - } - }, - "required": [ - "id" - ] - } - }, - { - "name": "myapp_car_delete", - "description": "Delete a Car record by id", - "inputSchema": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Car id" - } - }, - "required": [ - "id" - ] - } - }, - { - "name": "myapp_car_fields", - "description": "List available fields for Car", - "inputSchema": { - "type": "object", - "properties": {} - }, - "_meta": { - "fields": [ - { - "name": "id", - "type": "UUID", - "editable": false, - "primaryKey": true - }, - { - "name": "make", - "type": "String", - "editable": true, - "primaryKey": false - }, - { - "name": "model", - "type": "String", - "editable": true, - "primaryKey": false - }, - { - "name": "year", - "type": "Int", - "editable": true, - "primaryKey": false - }, - { - "name": "isElectric", - "type": "Boolean", - "editable": true, - "primaryKey": false - }, - { - "name": "createdAt", - "type": "Datetime", - "editable": false, - "primaryKey": false - } - ] - } - }, - { - "name": "myapp_driver_list", - "description": "List all Driver records", - "inputSchema": { - "type": "object", - "properties": {} +exports[`cli docs generator generates CLI AGENTS.md 1`] = ` +"# myapp CLI - Agent Reference + +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT +> This document is structured for LLM/agent consumption. + +## OVERVIEW + +\`myapp\` is a CLI tool for interacting with a GraphQL API. +All commands output JSON to stdout. All commands accept \`--help\` or \`-h\` for usage. +Configuration is stored at \`~/.myapp/config/\` via appstash. + +## PREREQUISITES + +Before running any data commands, you must: + +1. Create a context: \`myapp context create --endpoint \` +2. Activate it: \`myapp context use \` +3. Authenticate: \`myapp auth set-token \` + +## TOOLS + +### TOOL: context + +Manage named API endpoint contexts (like kubectl contexts). + +\`\`\` +SUBCOMMANDS: + myapp context create --endpoint Create a new context + myapp context list List all contexts + myapp context use Set active context + myapp context current Show active context + myapp context delete Delete a context + +INPUT: + name: string (required) - Context identifier + endpoint: string (required for create) - GraphQL endpoint URL + +OUTPUT: JSON + create: { name, endpoint } + list: [{ name, endpoint, isCurrent, hasCredentials }] + use: { name, endpoint } + current: { name, endpoint } + delete: { deleted: name } +\`\`\` + +### TOOL: auth + +Manage authentication tokens per context. + +\`\`\` +SUBCOMMANDS: + myapp auth set-token Store bearer token for current context + myapp auth status Show auth status for all contexts + myapp auth logout Remove credentials for current context + +INPUT: + token: string (required for set-token) - Bearer token value + +OUTPUT: JSON + set-token: { context, status: "authenticated" } + status: [{ context, authenticated: boolean }] + logout: { context, status: "logged out" } +\`\`\` + +### TOOL: car + +CRUD operations for Car records. + +\`\`\` +SUBCOMMANDS: + myapp car list List all records + myapp car get --id Get one record + myapp car create --make --model --year --isElectric + myapp car update --id [--make ] [--model ] [--year ] [--isElectric ] + myapp car delete --id Delete one record + +INPUT FIELDS: + id: UUID (primary key) + make: String + model: String + year: Int + isElectric: Boolean + createdAt: Datetime + +EDITABLE FIELDS (for create/update): + make: String + model: String + year: Int + isElectric: Boolean + +OUTPUT: JSON + list: [{ id, make, model, year, isElectric, createdAt }] + get: { id, make, model, year, isElectric, createdAt } + create: { id, make, model, year, isElectric, createdAt } + update: { id, make, model, year, isElectric, createdAt } + delete: { id } +\`\`\` + +### TOOL: driver + +CRUD operations for Driver records. + +\`\`\` +SUBCOMMANDS: + myapp driver list List all records + myapp driver get --id Get one record + myapp driver create --name --licenseNumber + myapp driver update --id [--name ] [--licenseNumber ] + myapp driver delete --id Delete one record + +INPUT FIELDS: + id: UUID (primary key) + name: String + licenseNumber: String + +EDITABLE FIELDS (for create/update): + name: String + licenseNumber: String + +OUTPUT: JSON + list: [{ id, name, licenseNumber }] + get: { id, name, licenseNumber } + create: { id, name, licenseNumber } + update: { id, name, licenseNumber } + delete: { id } +\`\`\` + +### TOOL: current-user + +Get the currently authenticated user + +\`\`\` +TYPE: query +USAGE: myapp current-user + +INPUT: none + +OUTPUT: JSON +\`\`\` + +### TOOL: login + +Authenticate a user + +\`\`\` +TYPE: mutation +USAGE: myapp login --email --password + +INPUT: + email: String (required) + password: String (required) + +OUTPUT: JSON +\`\`\` + +## WORKFLOWS + +### Initial setup + +\`\`\`bash +myapp context create dev --endpoint http://localhost:5000/graphql +myapp context use dev +myapp auth set-token eyJhbGciOiJIUzI1NiIs... +\`\`\` + +### CRUD workflow (car) + +\`\`\`bash +# List all +myapp car list + +# Create +myapp car create --make "value" --model "value" --year "value" --isElectric "value" + +# Get by id +myapp car get --id + +# Update +myapp car update --id --make "new-value" + +# Delete +myapp car delete --id +\`\`\` + +### Piping output + +\`\`\`bash +# Pretty print +myapp car list | jq '.' + +# Extract field +myapp car list | jq '.[].id' + +# Count results +myapp car list | jq 'length' +\`\`\` + +## ERROR HANDLING + +All errors are written to stderr. Exit codes: +- \`0\`: Success +- \`1\`: Error (auth failure, not found, validation error, network error) + +Common errors: +- "No active context": Run \`context use \` first +- "Not authenticated": Run \`auth set-token \` first +- "Record not found": The requested ID does not exist +" +`; + +exports[`cli docs generator generates CLI README 1`] = ` +"# myapp CLI + +> Auto-generated CLI commands from GraphQL schema +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT + +## Setup + +\`\`\`bash +# Create a context pointing at your GraphQL endpoint +myapp context create production --endpoint https://api.example.com/graphql + +# Set the active context +myapp context use production + +# Authenticate +myapp auth set-token +\`\`\` + +## Commands + +| Command | Description | +|---------|-------------| +| \`context\` | Manage API contexts (endpoints) | +| \`auth\` | Manage authentication tokens | +| \`car\` | car CRUD operations | +| \`driver\` | driver CRUD operations | +| \`current-user\` | Get the currently authenticated user | +| \`login\` | Authenticate a user | + +## Infrastructure Commands + +### \`context\` + +Manage named API contexts (kubectl-style). + +| Subcommand | Description | +|------------|-------------| +| \`create --endpoint \` | Create a new context | +| \`list\` | List all contexts | +| \`use \` | Set the active context | +| \`current\` | Show current context | +| \`delete \` | Delete a context | + +Configuration is stored at \`~/.myapp/config/\`. + +### \`auth\` + +Manage authentication tokens per context. + +| Subcommand | Description | +|------------|-------------| +| \`set-token \` | Store bearer token for current context | +| \`status\` | Show auth status across all contexts | +| \`logout\` | Remove credentials for current context | + +## Table Commands + +### \`car\` + +CRUD operations for Car records. + +| Subcommand | Description | +|------------|-------------| +| \`list\` | List all car records | +| \`get\` | Get a car by id | +| \`create\` | Create a new car | +| \`update\` | Update an existing car | +| \`delete\` | Delete a car | + +**Fields:** + +| Field | Type | +|-------|------| +| \`id\` | UUID | +| \`make\` | String | +| \`model\` | String | +| \`year\` | Int | +| \`isElectric\` | Boolean | +| \`createdAt\` | Datetime | + +**Create fields:** \`make\`, \`model\`, \`year\`, \`isElectric\` + +### \`driver\` + +CRUD operations for Driver records. + +| Subcommand | Description | +|------------|-------------| +| \`list\` | List all driver records | +| \`get\` | Get a driver by id | +| \`create\` | Create a new driver | +| \`update\` | Update an existing driver | +| \`delete\` | Delete a driver | + +**Fields:** + +| Field | Type | +|-------|------| +| \`id\` | UUID | +| \`name\` | String | +| \`licenseNumber\` | String | + +**Create fields:** \`name\`, \`licenseNumber\` + +## Custom Operations + +### \`current-user\` + +Get the currently authenticated user + +- **Type:** query +- **Arguments:** none + +### \`login\` + +Authenticate a user + +- **Type:** mutation +- **Arguments:** + + | Argument | Type | + |----------|------| + | \`email\` | String (required) | + | \`password\` | String (required) | + +## Output + +All commands output JSON to stdout. Pipe to \`jq\` for formatting: + +\`\`\`bash +myapp car list | jq '.[]' +myapp car get --id | jq '.' +\`\`\` +" +`; + +exports[`cli docs generator generates CLI skill files 1`] = ` +"# myapp-context + +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT + +Manage API endpoint contexts for myapp + +## Usage + +\`\`\`bash +myapp context create --endpoint +myapp context list +myapp context use +myapp context current +myapp context delete +\`\`\` + +## Examples + +### Create and activate a context + +\`\`\`bash +myapp context create production --endpoint https://api.example.com/graphql +myapp context use production +\`\`\` + +### List all contexts + +\`\`\`bash +myapp context list +\`\`\` +" +`; + +exports[`cli docs generator generates CLI skill files 2`] = ` +"# myapp-auth + +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT + +Manage authentication tokens for myapp + +## Usage + +\`\`\`bash +myapp auth set-token +myapp auth status +myapp auth logout +\`\`\` + +## Examples + +### Authenticate with a token + +\`\`\`bash +myapp auth set-token eyJhbGciOiJIUzI1NiIs... +\`\`\` + +### Check auth status + +\`\`\`bash +myapp auth status +\`\`\` +" +`; + +exports[`cli docs generator generates CLI skill files 3`] = ` +"# myapp-car + +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT + +CRUD operations for Car records via myapp CLI + +## Usage + +\`\`\`bash +myapp car list +myapp car get --id +myapp car create --make --model --year --isElectric +myapp car update --id [--make ] [--model ] [--year ] [--isElectric ] +myapp car delete --id +\`\`\` + +## Examples + +### List all car records + +\`\`\`bash +myapp car list +\`\`\` + +### Create a car + +\`\`\`bash +myapp car create --make "value" --model "value" --year "value" --isElectric "value" +\`\`\` + +### Get a car by id + +\`\`\`bash +myapp car get --id +\`\`\` + +### Update a car + +\`\`\`bash +myapp car update --id --make "new-value" +\`\`\` + +### Delete a car + +\`\`\`bash +myapp car delete --id +\`\`\` +" +`; + +exports[`cli docs generator generates CLI skill files 4`] = ` +"# myapp-driver + +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT + +CRUD operations for Driver records via myapp CLI + +## Usage + +\`\`\`bash +myapp driver list +myapp driver get --id +myapp driver create --name --licenseNumber +myapp driver update --id [--name ] [--licenseNumber ] +myapp driver delete --id +\`\`\` + +## Examples + +### List all driver records + +\`\`\`bash +myapp driver list +\`\`\` + +### Create a driver + +\`\`\`bash +myapp driver create --name "value" --licenseNumber "value" +\`\`\` + +### Get a driver by id + +\`\`\`bash +myapp driver get --id +\`\`\` + +### Update a driver + +\`\`\`bash +myapp driver update --id --name "new-value" +\`\`\` + +### Delete a driver + +\`\`\`bash +myapp driver delete --id +\`\`\` +" +`; + +exports[`cli docs generator generates CLI skill files 5`] = ` +"# myapp-current-user + +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT + +Get the currently authenticated user + +## Usage + +\`\`\`bash +myapp current-user +\`\`\` + +## Examples + +### Run currentUser + +\`\`\`bash +myapp current-user +\`\`\` +" +`; + +exports[`cli docs generator generates CLI skill files 6`] = ` +"# myapp-login + +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT + +Authenticate a user + +## Usage + +\`\`\`bash +myapp login --email --password +\`\`\` + +## Examples + +### Run login + +\`\`\`bash +myapp login --email --password +\`\`\` +" +`; + +exports[`cli-generator generates commands.ts (command map) 1`] = ` +"/** + * CLI command map and entry point + * @generated by @constructive-io/graphql-codegen + * DO NOT EDIT - changes will be overwritten + */ +import { CLIOptions, Inquirerer, extractFirst } from "inquirerer"; +import contextCmd from "./commands/context"; +import authCmd from "./commands/auth"; +import carCmd from "./commands/car"; +import driverCmd from "./commands/driver"; +import currentUserCmd from "./commands/current-user"; +import loginCmd from "./commands/login"; +const createCommandMap = () => ({ + "context": contextCmd, + "auth": authCmd, + "car": carCmd, + "driver": driverCmd, + "current-user": currentUserCmd, + "login": loginCmd +}); +const usage = "\\nmyapp \\n\\nCommands:\\n context Manage API contexts\\n auth Manage authentication\\n car car CRUD operations\\n driver driver CRUD operations\\n current-user Get the currently authenticated user\\n login Authenticate a user\\n\\n --help, -h Show this help message\\n --version, -v Show version\\n"; +export const commands = async (argv: Partial>, prompter: Inquirerer, options: CLIOptions) => { + if (argv.help || argv.h) { + console.log(usage); + process.exit(0); + } + let { + first: command, + newArgv + } = extractFirst(argv); + const commandMap = createCommandMap(); + if (!command) { + const answer = await prompter.prompt(argv, [{ + type: "autocomplete", + name: "command", + message: "What do you want to do?", + options: Object.keys(commandMap) + }]); + command = answer.command; + } + const commandFn = commandMap[command]; + if (!commandFn) { + console.log(usage); + console.error(\`Unknown command: \${command}\`); + process.exit(1); + } + await commandFn(newArgv, prompter, options); + prompter.close(); + return argv; +};" +`; + +exports[`cli-generator generates commands/auth.ts 1`] = ` +"/** + * Authentication commands + * @generated by @constructive-io/graphql-codegen + * DO NOT EDIT - changes will be overwritten + */ +import { CLIOptions, Inquirerer, extractFirst } from "inquirerer"; +import { getStore } from "../executor"; +const usage = "\\nmyapp auth \\n\\nCommands:\\n set-token Set API token for the current context\\n status Show authentication status\\n logout Remove credentials for the current context\\n\\nOptions:\\n --context Specify context (defaults to current context)\\n\\n --help, -h Show this help message\\n"; +export default async (argv: Partial>, prompter: Inquirerer, _options: CLIOptions) => { + if (argv.help || argv.h) { + console.log(usage); + process.exit(0); + } + const store = getStore(); + const { + first: subcommand, + newArgv + } = extractFirst(argv); + if (!subcommand) { + const answer = await prompter.prompt(argv, [{ + type: "autocomplete", + name: "subcommand", + message: "What do you want to do?", + options: ["set-token", "status", "logout"] + }]); + return handleAuthSubcommand(answer.subcommand, newArgv, prompter, store); + } + return handleAuthSubcommand(subcommand, newArgv, prompter, store); +}; +async function handleAuthSubcommand(subcommand: string, argv: Partial>, prompter: Inquirerer, store: ReturnType) { + switch (subcommand) { + case "set-token": + return handleSetToken(argv, prompter, store); + case "status": + return handleStatus(store); + case "logout": + return handleLogout(argv, prompter, store); + default: + console.log(usage); + process.exit(1); + } +} +async function handleSetToken(argv: Partial>, prompter: Inquirerer, store: ReturnType) { + const current = store.getCurrentContext(); + if (!current) { + console.error("No active context. Run \\"context create\\" first."); + process.exit(1); + } + const { + first: token + } = extractFirst(argv); + let tokenValue = token; + if (!tokenValue) { + const answer = await prompter.prompt(argv, [{ + type: "password", + name: "token", + message: "API Token", + required: true + }]); + tokenValue = answer.token; + } + store.setCredentials(current.name, { + token: String.call(tokenValue || "").trim() + }); + console.log(\`Token saved for context: \${current.name}\`); +} +function handleStatus(store: ReturnType) { + const contexts = store.listContexts(); + const settings = store.loadSettings(); + if (contexts.length === 0) { + console.log("No contexts configured."); + return; + } + console.log("Authentication Status:"); + for (const ctx of contexts) { + const isCurrent = ctx.name === settings.currentContext; + const hasAuth = store.hasValidCredentials(ctx.name); + const marker = isCurrent ? "* " : " "; + const status = hasAuth ? "authenticated" : "no token"; + console.log(\`\${marker}\${ctx.name} [\${status}]\`); + } +} +async function handleLogout(argv: Partial>, prompter: Inquirerer, store: ReturnType) { + const current = store.getCurrentContext(); + if (!current) { + console.log("No active context."); + return; + } + const confirm = await prompter.prompt(argv, [{ + type: "confirm", + name: "confirm", + message: \`Remove credentials for "\${current.name}"?\`, + default: false + }]); + if (!confirm.confirm) { + return; + } + if (store.removeCredentials(current.name)) { + console.log(\`Credentials removed for: \${current.name}\`); + } else { + console.log(\`No credentials found for: \${current.name}\`); + } +}" +`; + +exports[`cli-generator generates commands/car.ts 1`] = ` +"/** + * CLI commands for Car + * @generated by @constructive-io/graphql-codegen + * DO NOT EDIT - changes will be overwritten + */ +import { CLIOptions, Inquirerer, extractFirst } from "inquirerer"; +import { getClient } from "../executor"; +const usage = "\\ncar \\n\\nCommands:\\n list List all car records\\n get Get a car by ID\\n create Create a new car\\n update Update an existing car\\n delete Delete a car\\n\\n --help, -h Show this help message\\n"; +export default async (argv: Partial>, prompter: Inquirerer, _options: CLIOptions) => { + if (argv.help || argv.h) { + console.log(usage); + process.exit(0); + } + const { + first: subcommand, + newArgv + } = extractFirst(argv); + if (!subcommand) { + const answer = await prompter.prompt(argv, [{ + type: "autocomplete", + name: "subcommand", + message: "What do you want to do?", + options: ["list", "get", "create", "update", "delete"] + }]); + return handleTableSubcommand(answer.subcommand, newArgv, prompter); + } + return handleTableSubcommand(subcommand, newArgv, prompter); +}; +async function handleTableSubcommand(subcommand: string, argv: Partial>, prompter: Inquirerer) { + switch (subcommand) { + case "list": + return handleList(argv, prompter); + case "get": + return handleGet(argv, prompter); + case "create": + return handleCreate(argv, prompter); + case "update": + return handleUpdate(argv, prompter); + case "delete": + return handleDelete(argv, prompter); + default: + console.log(usage); + process.exit(1); + } +} +async function handleList(_argv: Partial>, _prompter: Inquirerer) { + try { + const client = getClient(); + const result = await client.car.findMany({ + select: { + id: true, + make: true, + model: true, + year: true, + isElectric: true, + createdAt: true } - }, - { - "name": "myapp_driver_get", - "description": "Get a single Driver record by id", - "inputSchema": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Driver id" - } - }, - "required": [ - "id" - ] + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to list records."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleGet(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "id", + message: "id", + required: true + }]); + const client = getClient(); + const result = await client.car.findOne({ + id: answers.id, + select: { + id: true, + make: true, + model: true, + year: true, + isElectric: true, + createdAt: true } - }, - { - "name": "myapp_driver_create", - "description": "Create a new Driver record", - "inputSchema": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Driver name" - }, - "licenseNumber": { - "type": "string", - "description": "Driver licenseNumber" - } - }, - "required": [ - "name", - "licenseNumber" - ] + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Record not found."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleCreate(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "make", + message: "make", + required: true + }, { + type: "text", + name: "model", + message: "model", + required: true + }, { + type: "text", + name: "year", + message: "year", + required: true + }, { + type: "text", + name: "isElectric", + message: "isElectric", + required: true + }]); + const client = getClient(); + const result = await client.car.create({ + data: { + make: answers.make, + model: answers.model, + year: answers.year, + isElectric: answers.isElectric + }, + select: { + id: true, + make: true, + model: true, + year: true, + isElectric: true, + createdAt: true } - }, - { - "name": "myapp_driver_update", - "description": "Update an existing Driver record", - "inputSchema": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Driver id" - }, - "name": { - "type": "string", - "description": "Driver name" - }, - "licenseNumber": { - "type": "string", - "description": "Driver licenseNumber" - } - }, - "required": [ - "id" - ] + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to create record."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleUpdate(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "id", + message: "id", + required: true + }, { + type: "text", + name: "make", + message: "make", + required: false + }, { + type: "text", + name: "model", + message: "model", + required: false + }, { + type: "text", + name: "year", + message: "year", + required: false + }, { + type: "text", + name: "isElectric", + message: "isElectric", + required: false + }]); + const client = getClient(); + const result = await client.car.update({ + id: answers.id, + data: { + make: answers.make, + model: answers.model, + year: answers.year, + isElectric: answers.isElectric + }, + select: { + id: true, + make: true, + model: true, + year: true, + isElectric: true, + createdAt: true } - }, - { - "name": "myapp_driver_delete", - "description": "Delete a Driver record by id", - "inputSchema": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "Driver id" - } - }, - "required": [ - "id" - ] + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to update record."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleDelete(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "id", + message: "id", + required: true + }]); + const client = getClient(); + const result = await client.car.delete({ + id: answers.id, + select: { + id: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to delete record."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +}" +`; + +exports[`cli-generator generates commands/context.ts 1`] = ` +"/** + * Context management commands + * @generated by @constructive-io/graphql-codegen + * DO NOT EDIT - changes will be overwritten + */ +import { CLIOptions, Inquirerer, extractFirst } from "inquirerer"; +import { getStore } from "../executor"; +const usage = "\\nmyapp context \\n\\nCommands:\\n create Create a new context\\n list List all contexts\\n use Set the active context\\n current Show current context\\n delete Delete a context\\n\\nCreate Options:\\n --endpoint GraphQL endpoint URL\\n\\n --help, -h Show this help message\\n"; +export default async (argv: Partial>, prompter: Inquirerer, _options: CLIOptions) => { + if (argv.help || argv.h) { + console.log(usage); + process.exit(0); + } + const store = getStore(); + const { + first: subcommand, + newArgv + } = extractFirst(argv); + if (!subcommand) { + const answer = await prompter.prompt(argv, [{ + type: "autocomplete", + name: "subcommand", + message: "What do you want to do?", + options: ["create", "list", "use", "current", "delete"] + }]); + return handleSubcommand(answer.subcommand, newArgv, prompter, store); + } + return handleSubcommand(subcommand, newArgv, prompter, store); +}; +async function handleSubcommand(subcommand: string, argv: Partial>, prompter: Inquirerer, store: ReturnType) { + switch (subcommand) { + case "create": + return handleCreate(argv, prompter, store); + case "list": + return handleList(store); + case "use": + return handleUse(argv, prompter, store); + case "current": + return handleCurrent(store); + case "delete": + return handleDelete(argv, prompter, store); + default: + console.log(usage); + process.exit(1); + } +} +async function handleCreate(argv: Partial>, prompter: Inquirerer, store: ReturnType) { + const { + first: name, + newArgv: restArgv + } = extractFirst(argv); + const answers = await prompter.prompt({ + name, + ...restArgv + }, [{ + type: "text", + name: "name", + message: "Context name", + required: true + }, { + type: "text", + name: "endpoint", + message: "GraphQL endpoint URL", + required: true + }]); + const contextName = answers.name; + const endpoint = answers.endpoint; + store.createContext(contextName, { + endpoint: endpoint + }); + const settings = store.loadSettings(); + if (!settings.currentContext) { + store.setCurrentContext(contextName); + } + console.log(\`Created context: \${contextName}\`); + console.log(\` Endpoint: \${endpoint}\`); +} +function handleList(store: ReturnType) { + const contexts = store.listContexts(); + const settings = store.loadSettings(); + if (contexts.length === 0) { + console.log("No contexts configured."); + return; + } + console.log("Contexts:"); + for (const ctx of contexts) { + const marker = ctx.name === settings.currentContext ? "* " : " "; + const authStatus = store.hasValidCredentials(ctx.name) ? "[authenticated]" : "[no token]"; + console.log(\`\${marker}\${ctx.name} \${authStatus}\`); + console.log(\` Endpoint: \${ctx.endpoint}\`); + } +} +async function handleUse(argv: Partial>, prompter: Inquirerer, store: ReturnType) { + const { + first: name + } = extractFirst(argv); + const contexts = store.listContexts(); + if (contexts.length === 0) { + console.log("No contexts configured."); + return; + } + let contextName = name; + if (!contextName) { + const answer = await prompter.prompt(argv, [{ + type: "autocomplete", + name: "name", + message: "Select context", + options: contexts.map(c => c.name) + }]); + contextName = answer.name; + } + if (store.setCurrentContext(contextName)) { + console.log(\`Switched to context: \${contextName}\`); + } else { + console.error(\`Context "\${contextName}" not found.\`); + process.exit(1); + } +} +function handleCurrent(store: ReturnType) { + const current = store.getCurrentContext(); + if (!current) { + console.log("No current context set."); + return; + } + console.log(\`Current context: \${current.name}\`); + console.log(\` Endpoint: \${current.endpoint}\`); + const hasAuth = store.hasValidCredentials(current.name); + console.log(\` Auth: \${hasAuth ? "authenticated" : "not authenticated"}\`); +} +async function handleDelete(argv: Partial>, prompter: Inquirerer, store: ReturnType) { + const { + first: name + } = extractFirst(argv); + const contexts = store.listContexts(); + if (contexts.length === 0) { + console.log("No contexts configured."); + return; + } + let contextName = name; + if (!contextName) { + const answer = await prompter.prompt(argv, [{ + type: "autocomplete", + name: "name", + message: "Select context to delete", + options: contexts.map(c => c.name) + }]); + contextName = answer.name; + } + if (store.deleteContext(contextName)) { + console.log(\`Deleted context: \${contextName}\`); + } else { + console.error(\`Context "\${contextName}" not found.\`); + process.exit(1); + } +}" +`; + +exports[`cli-generator generates commands/current-user.ts (custom query) 1`] = ` +"/** + * CLI command for query currentUser + * @generated by @constructive-io/graphql-codegen + * DO NOT EDIT - changes will be overwritten + */ +import { CLIOptions, Inquirerer } from "inquirerer"; +import { getClient } from "../executor"; +export default async (argv: Partial>, prompter: Inquirerer, _options: CLIOptions) => { + try { + if (argv.help || argv.h) { + console.log("current-user - Get the currently authenticated user\\n\\nUsage: current-user [OPTIONS]\\n"); + process.exit(0); + } + const client = getClient(); + const result = await client.query.currentUser({}).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed: currentUser"); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +};" +`; + +exports[`cli-generator generates commands/driver.ts 1`] = ` +"/** + * CLI commands for Driver + * @generated by @constructive-io/graphql-codegen + * DO NOT EDIT - changes will be overwritten + */ +import { CLIOptions, Inquirerer, extractFirst } from "inquirerer"; +import { getClient } from "../executor"; +const usage = "\\ndriver \\n\\nCommands:\\n list List all driver records\\n get Get a driver by ID\\n create Create a new driver\\n update Update an existing driver\\n delete Delete a driver\\n\\n --help, -h Show this help message\\n"; +export default async (argv: Partial>, prompter: Inquirerer, _options: CLIOptions) => { + if (argv.help || argv.h) { + console.log(usage); + process.exit(0); + } + const { + first: subcommand, + newArgv + } = extractFirst(argv); + if (!subcommand) { + const answer = await prompter.prompt(argv, [{ + type: "autocomplete", + name: "subcommand", + message: "What do you want to do?", + options: ["list", "get", "create", "update", "delete"] + }]); + return handleTableSubcommand(answer.subcommand, newArgv, prompter); + } + return handleTableSubcommand(subcommand, newArgv, prompter); +}; +async function handleTableSubcommand(subcommand: string, argv: Partial>, prompter: Inquirerer) { + switch (subcommand) { + case "list": + return handleList(argv, prompter); + case "get": + return handleGet(argv, prompter); + case "create": + return handleCreate(argv, prompter); + case "update": + return handleUpdate(argv, prompter); + case "delete": + return handleDelete(argv, prompter); + default: + console.log(usage); + process.exit(1); + } +} +async function handleList(_argv: Partial>, _prompter: Inquirerer) { + try { + const client = getClient(); + const result = await client.driver.findMany({ + select: { + id: true, + name: true, + licenseNumber: true } - }, - { - "name": "myapp_driver_fields", - "description": "List available fields for Driver", - "inputSchema": { - "type": "object", - "properties": {} + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to list records."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleGet(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "id", + message: "id", + required: true + }]); + const client = getClient(); + const result = await client.driver.findOne({ + id: answers.id, + select: { + id: true, + name: true, + licenseNumber: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Record not found."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleCreate(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "name", + message: "name", + required: true + }, { + type: "text", + name: "licenseNumber", + message: "licenseNumber", + required: true + }]); + const client = getClient(); + const result = await client.driver.create({ + data: { + name: answers.name, + licenseNumber: answers.licenseNumber }, - "_meta": { - "fields": [ - { - "name": "id", - "type": "UUID", - "editable": false, - "primaryKey": true - }, - { - "name": "name", - "type": "String", - "editable": true, - "primaryKey": false - }, - { - "name": "licenseNumber", - "type": "String", - "editable": true, - "primaryKey": false - } - ] + select: { + id: true, + name: true, + licenseNumber: true } - }, - { - "name": "myapp_current-user", - "description": "Get the currently authenticated user", - "inputSchema": { - "type": "object", - "properties": {} + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to create record."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleUpdate(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "id", + message: "id", + required: true + }, { + type: "text", + name: "name", + message: "name", + required: false + }, { + type: "text", + name: "licenseNumber", + message: "licenseNumber", + required: false + }]); + const client = getClient(); + const result = await client.driver.update({ + id: answers.id, + data: { + name: answers.name, + licenseNumber: answers.licenseNumber + }, + select: { + id: true, + name: true, + licenseNumber: true } - }, - { - "name": "myapp_login", - "description": "Authenticate a user", - "inputSchema": { - "type": "object", - "properties": { - "email": { - "type": "string", - "description": "email" - }, - "password": { - "type": "string", - "description": "password" - } - }, - "required": [ - "email", - "password" - ] + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to update record."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleDelete(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "id", + message: "id", + required: true + }]); + const client = getClient(); + const result = await client.driver.delete({ + id: answers.id, + select: { + id: true } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to delete record."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +}" +`; + +exports[`cli-generator generates commands/login.ts (custom mutation) 1`] = ` +"/** + * CLI command for mutation login + * @generated by @constructive-io/graphql-codegen + * DO NOT EDIT - changes will be overwritten + */ +import { CLIOptions, Inquirerer } from "inquirerer"; +import { getClient } from "../executor"; +export default async (argv: Partial>, prompter: Inquirerer, _options: CLIOptions) => { + try { + if (argv.help || argv.h) { + console.log("login - Authenticate a user\\n\\nUsage: login [OPTIONS]\\n"); + process.exit(0); + } + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "email", + message: "email", + required: true + }, { + type: "text", + name: "password", + message: "password", + required: true + }]); + const client = getClient(); + const result = await client.mutation.login(answers).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed: login"); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +};" +`; + +exports[`cli-generator generates executor.ts 1`] = ` +"/** + * Executor and config store for CLI + * @generated by @constructive-io/graphql-codegen + * DO NOT EDIT - changes will be overwritten + */ +import { createConfigStore } from "appstash"; +import { createClient } from "../orm"; +const store = createConfigStore("myapp"); +export const getStore = () => store; +export function getClient(contextName?: string) { + let ctx = null; + if (contextName) { + ctx = store.loadContext(contextName); + if (!ctx) { + throw new Error(\`Context "\${contextName}" not found.\`); + } + } else { + ctx = store.getCurrentContext(); + if (!ctx) { + throw new Error("No active context. Run \\"context create\\" or \\"context use\\" first."); + } + } + const headers = {}; + if (store.hasValidCredentials(ctx.name)) { + const creds = store.getCredentials(ctx.name); + if (creds?.token) { + headers.Authorization = \`Bearer \${creds.token}\`; } - ] -} -" + } + return createClient({ + endpoint: ctx.endpoint, + headers: headers + }); +}" `; -exports[`cli-generator docs: true (all formats) generates skill files 1`] = ` -"# myapp-context +exports[`hooks docs generator generates hooks AGENTS.md 1`] = ` +"# React Query Hooks - Agent Reference > @generated by @constructive-io/graphql-codegen - DO NOT EDIT +> This document is structured for LLM/agent consumption. -Manage API endpoint contexts for myapp +## OVERVIEW -## Usage +React Query hooks wrapping ORM operations for data fetching and mutations. +All query hooks return \`UseQueryResult\`. All mutation hooks return \`UseMutationResult\`. -\`\`\`bash -myapp context create --endpoint -myapp context list -myapp context use -myapp context current -myapp context delete +## SETUP + +\`\`\`typescript +import { configure } from './hooks'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; + +configure({ endpoint: 'https://api.example.com/graphql' }); +const queryClient = new QueryClient(); +// Wrap app in \`\`\` -## Examples +## HOOKS -### Create and activate a context +### HOOK: useCarsQuery + +List all cars. -\`\`\`bash -myapp context create production --endpoint https://api.example.com/graphql -myapp context use production \`\`\` +TYPE: query +USAGE: useCarsQuery({ selection: { fields: { ... } } }) -### List all contexts +INPUT: + selection: { fields: Record } - Fields to select + +OUTPUT: UseQueryResult> +\`\`\` + +### HOOK: useCarQuery + +Get a single car by id. -\`\`\`bash -myapp context list \`\`\` -" -`; +TYPE: query +USAGE: useCarQuery({ id: '', selection: { fields: { ... } } }) -exports[`cli-generator docs: true (all formats) generates skill files 2`] = ` -"# myapp-auth +INPUT: + id: string (required) + selection: { fields: Record } - Fields to select + +OUTPUT: UseQueryResult<{ + id: string + make: string + model: string + year: number + isElectric: boolean + createdAt: string +}> +\`\`\` -> @generated by @constructive-io/graphql-codegen - DO NOT EDIT +### HOOK: useCreateCarMutation -Manage authentication tokens for myapp +Create a new car. -## Usage +\`\`\` +TYPE: mutation +USAGE: const { mutate } = useCreateCarMutation({ selection: { fields: { ... } } }) -\`\`\`bash -myapp auth set-token -myapp auth status -myapp auth logout +OUTPUT: UseMutationResult \`\`\` -## Examples +### HOOK: useUpdateCarMutation -### Authenticate with a token +Update an existing car. -\`\`\`bash -myapp auth set-token eyJhbGciOiJIUzI1NiIs... \`\`\` +TYPE: mutation +USAGE: const { mutate } = useUpdateCarMutation({ selection: { fields: { ... } } }) -### Check auth status +OUTPUT: UseMutationResult +\`\`\` + +### HOOK: useDeleteCarMutation + +Delete a car. -\`\`\`bash -myapp auth status \`\`\` -" -`; +TYPE: mutation +USAGE: const { mutate } = useDeleteCarMutation({}) -exports[`cli-generator docs: true (all formats) generates skill files 3`] = ` -"# myapp-car +OUTPUT: UseMutationResult +\`\`\` -> @generated by @constructive-io/graphql-codegen - DO NOT EDIT +### HOOK: useDriversQuery -CRUD operations for Car records via myapp CLI +List all drivers. -## Usage +\`\`\` +TYPE: query +USAGE: useDriversQuery({ selection: { fields: { ... } } }) -\`\`\`bash -myapp car list -myapp car get --id -myapp car create --make --model --year --isElectric -myapp car update --id [--make ] [--model ] [--year ] [--isElectric ] -myapp car delete --id +INPUT: + selection: { fields: Record } - Fields to select + +OUTPUT: UseQueryResult> \`\`\` -## Examples +### HOOK: useDriverQuery -### List all car records +Get a single driver by id. -\`\`\`bash -myapp car list \`\`\` +TYPE: query +USAGE: useDriverQuery({ id: '', selection: { fields: { ... } } }) -### Create a car +INPUT: + id: string (required) + selection: { fields: Record } - Fields to select + +OUTPUT: UseQueryResult<{ + id: string + name: string + licenseNumber: string +}> +\`\`\` + +### HOOK: useCreateDriverMutation + +Create a new driver. -\`\`\`bash -myapp car create --make "value" --model "value" --year "value" --isElectric "value" \`\`\` +TYPE: mutation +USAGE: const { mutate } = useCreateDriverMutation({ selection: { fields: { ... } } }) -### Get a car by id +OUTPUT: UseMutationResult +\`\`\` + +### HOOK: useUpdateDriverMutation + +Update an existing driver. -\`\`\`bash -myapp car get --id \`\`\` +TYPE: mutation +USAGE: const { mutate } = useUpdateDriverMutation({ selection: { fields: { ... } } }) -### Update a car +OUTPUT: UseMutationResult +\`\`\` + +### HOOK: useDeleteDriverMutation + +Delete a driver. -\`\`\`bash -myapp car update --id --make "new-value" \`\`\` +TYPE: mutation +USAGE: const { mutate } = useDeleteDriverMutation({}) -### Delete a car +OUTPUT: UseMutationResult +\`\`\` -\`\`\`bash -myapp car delete --id +## CUSTOM OPERATION HOOKS + +### HOOK: useCurrentUserQuery + +Get the currently authenticated user + +\`\`\` +TYPE: query +USAGE: useCurrentUserQuery() + +INPUT: none + +OUTPUT: UseQueryResult +\`\`\` + +### HOOK: useLoginMutation + +Authenticate a user + +\`\`\` +TYPE: mutation +USAGE: const { mutate } = useLoginMutation() + mutate({ email: , password: }) + +INPUT: + email: String (required) + password: String (required) + +OUTPUT: UseMutationResult \`\`\` " `; -exports[`cli-generator docs: true (all formats) generates skill files 4`] = ` -"# myapp-driver +exports[`hooks docs generator generates hooks README 1`] = ` +"# React Query Hooks +> Auto-generated React Query hooks from GraphQL schema > @generated by @constructive-io/graphql-codegen - DO NOT EDIT -CRUD operations for Driver records via myapp CLI +## Setup -## Usage +\`\`\`typescript +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { configure } from './hooks'; -\`\`\`bash -myapp driver list -myapp driver get --id -myapp driver create --name --licenseNumber -myapp driver update --id [--name ] [--licenseNumber ] -myapp driver delete --id +configure({ + endpoint: 'https://api.example.com/graphql', + headers: { Authorization: 'Bearer ' }, +}); + +const queryClient = new QueryClient(); + +function App() { + return ( + + + + ); +} \`\`\` -## Examples +## Hooks + +| Hook | Type | Description | +|------|------|-------------| +| \`useCarsQuery\` | Query | List all cars | +| \`useCarQuery\` | Query | Get one car | +| \`useCreateCarMutation\` | Mutation | Create a car | +| \`useUpdateCarMutation\` | Mutation | Update a car | +| \`useDeleteCarMutation\` | Mutation | Delete a car | +| \`useDriversQuery\` | Query | List all drivers | +| \`useDriverQuery\` | Query | Get one driver | +| \`useCreateDriverMutation\` | Mutation | Create a driver | +| \`useUpdateDriverMutation\` | Mutation | Update a driver | +| \`useDeleteDriverMutation\` | Mutation | Delete a driver | +| \`useCurrentUserQuery\` | Query | Get the currently authenticated user | +| \`useLoginMutation\` | Mutation | Authenticate a user | + +## Table Hooks + +### Car + +\`\`\`typescript +// List all cars +const { data, isLoading } = useCarsQuery({ + selection: { fields: { id: true, make: true, model: true, year: true, isElectric: true, createdAt: true } }, +}); -### List all driver records +// Get one car +const { data: item } = useCarQuery({ + id: '', + selection: { fields: { id: true, make: true, model: true, year: true, isElectric: true, createdAt: true } }, +}); -\`\`\`bash -myapp driver list +// Create a car +const { mutate: create } = useCreateCarMutation({ + selection: { fields: { id: true } }, +}); +create({ make: '', model: '', year: '', isElectric: '' }); \`\`\` -### Create a driver +### Driver -\`\`\`bash -myapp driver create --name "value" --licenseNumber "value" -\`\`\` +\`\`\`typescript +// List all drivers +const { data, isLoading } = useDriversQuery({ + selection: { fields: { id: true, name: true, licenseNumber: true } }, +}); -### Get a driver by id +// Get one driver +const { data: item } = useDriverQuery({ + id: '', + selection: { fields: { id: true, name: true, licenseNumber: true } }, +}); -\`\`\`bash -myapp driver get --id +// Create a driver +const { mutate: create } = useCreateDriverMutation({ + selection: { fields: { id: true } }, +}); +create({ name: '', licenseNumber: '' }); \`\`\` -### Update a driver +## Custom Operation Hooks -\`\`\`bash -myapp driver update --id --name "new-value" -\`\`\` +### \`useCurrentUserQuery\` -### Delete a driver +Get the currently authenticated user -\`\`\`bash -myapp driver delete --id -\`\`\` +- **Type:** query +- **Arguments:** none + +### \`useLoginMutation\` + +Authenticate a user + +- **Type:** mutation +- **Arguments:** + + | Argument | Type | + |----------|------| + | \`email\` | String (required) | + | \`password\` | String (required) | " `; -exports[`cli-generator docs: true (all formats) generates skill files 5`] = ` -"# myapp-current-user +exports[`hooks docs generator generates hooks skill files 1`] = ` +"# hooks-car > @generated by @constructive-io/graphql-codegen - DO NOT EDIT -Get the currently authenticated user +React Query hooks for Car data operations ## Usage -\`\`\`bash -myapp current-user +\`\`\`typescript +useCarsQuery({ selection: { fields: { id: true, make: true, model: true, year: true, isElectric: true, createdAt: true } } }) +useCarQuery({ id: '', selection: { fields: { id: true, make: true, model: true, year: true, isElectric: true, createdAt: true } } }) +useCreateCarMutation({ selection: { fields: { id: true } } }) +useUpdateCarMutation({ selection: { fields: { id: true } } }) +useDeleteCarMutation({}) \`\`\` ## Examples -### Run currentUser +### List all cars -\`\`\`bash -myapp current-user +\`\`\`typescript +const { data, isLoading } = useCarsQuery({ + selection: { fields: { id: true, make: true, model: true, year: true, isElectric: true, createdAt: true } }, +}); +\`\`\` + +### Create a car + +\`\`\`typescript +const { mutate } = useCreateCarMutation({ + selection: { fields: { id: true } }, +}); +mutate({ make: '', model: '', year: '', isElectric: '' }); \`\`\` " `; -exports[`cli-generator docs: true (all formats) generates skill files 6`] = ` -"# myapp-login +exports[`hooks docs generator generates hooks skill files 2`] = ` +"# hooks-driver > @generated by @constructive-io/graphql-codegen - DO NOT EDIT -Authenticate a user +React Query hooks for Driver data operations ## Usage -\`\`\`bash -myapp login --email --password +\`\`\`typescript +useDriversQuery({ selection: { fields: { id: true, name: true, licenseNumber: true } } }) +useDriverQuery({ id: '', selection: { fields: { id: true, name: true, licenseNumber: true } } }) +useCreateDriverMutation({ selection: { fields: { id: true } } }) +useUpdateDriverMutation({ selection: { fields: { id: true } } }) +useDeleteDriverMutation({}) \`\`\` ## Examples -### Run login +### List all drivers -\`\`\`bash -myapp login --email --password +\`\`\`typescript +const { data, isLoading } = useDriversQuery({ + selection: { fields: { id: true, name: true, licenseNumber: true } }, +}); +\`\`\` + +### Create a driver + +\`\`\`typescript +const { mutate } = useCreateDriverMutation({ + selection: { fields: { id: true } }, +}); +mutate({ name: '', licenseNumber: '' }); \`\`\` " `; -exports[`cli-generator generates AGENTS.md by default 1`] = ` -"# myapp CLI - Agent Reference +exports[`hooks docs generator generates hooks skill files 3`] = ` +"# hooks-currentUser > @generated by @constructive-io/graphql-codegen - DO NOT EDIT -> This document is structured for LLM/agent consumption. - -## OVERVIEW - -\`myapp\` is a CLI tool for interacting with a GraphQL API. -All commands output JSON to stdout. All commands accept \`--help\` or \`-h\` for usage. -Configuration is stored at \`~/.myapp/config/\` via appstash. - -## PREREQUISITES -Before running any data commands, you must: +Get the currently authenticated user -1. Create a context: \`myapp context create --endpoint \` -2. Activate it: \`myapp context use \` -3. Authenticate: \`myapp auth set-token \` +## Usage -## TOOLS +\`\`\`typescript +useCurrentUserQuery() +\`\`\` -### TOOL: context +## Examples -Manage named API endpoint contexts (like kubectl contexts). +### Use useCurrentUserQuery +\`\`\`typescript +const { data, isLoading } = useCurrentUserQuery(); \`\`\` -SUBCOMMANDS: - myapp context create --endpoint Create a new context - myapp context list List all contexts - myapp context use Set active context - myapp context current Show active context - myapp context delete Delete a context +" +`; -INPUT: - name: string (required) - Context identifier - endpoint: string (required for create) - GraphQL endpoint URL +exports[`hooks docs generator generates hooks skill files 4`] = ` +"# hooks-login -OUTPUT: JSON - create: { name, endpoint } - list: [{ name, endpoint, isCurrent, hasCredentials }] - use: { name, endpoint } - current: { name, endpoint } - delete: { deleted: name } -\`\`\` +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT -### TOOL: auth +Authenticate a user -Manage authentication tokens per context. +## Usage +\`\`\`typescript +const { mutate } = useLoginMutation(); mutate({ email: '', password: '' }); \`\`\` -SUBCOMMANDS: - myapp auth set-token Store bearer token for current context - myapp auth status Show auth status for all contexts - myapp auth logout Remove credentials for current context -INPUT: - token: string (required for set-token) - Bearer token value +## Examples -OUTPUT: JSON - set-token: { context, status: "authenticated" } - status: [{ context, authenticated: boolean }] - logout: { context, status: "logged out" } +### Use useLoginMutation + +\`\`\`typescript +const { mutate, isLoading } = useLoginMutation(); +mutate({ email: '', password: '' }); \`\`\` +" +`; -### TOOL: car +exports[`orm docs generator generates ORM AGENTS.md 1`] = ` +"# ORM Client - Agent Reference -CRUD operations for Car records. +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT +> This document is structured for LLM/agent consumption. -\`\`\` -SUBCOMMANDS: - myapp car list List all records - myapp car get --id Get one record - myapp car create --make --model --year --isElectric - myapp car update --id [--make ] [--model ] [--year ] [--isElectric ] - myapp car delete --id Delete one record +## OVERVIEW -INPUT FIELDS: - id: UUID (primary key) - make: String - model: String - year: Int - isElectric: Boolean - createdAt: Datetime +Prisma-like ORM client for interacting with a GraphQL API. +All methods return a query builder. Call \`.execute()\` to run the query. -EDITABLE FIELDS (for create/update): - make: String - model: String - year: Int - isElectric: Boolean +## SETUP -OUTPUT: JSON - list: [{ id, make, model, year, isElectric, createdAt }] - get: { id, make, model, year, isElectric, createdAt } - create: { id, make, model, year, isElectric, createdAt } - update: { id, make, model, year, isElectric, createdAt } - delete: { id } +\`\`\`typescript +import { createClient } from './orm'; + +const db = createClient({ + endpoint: 'https://api.example.com/graphql', + headers: { Authorization: 'Bearer ' }, +}); \`\`\` -### TOOL: driver +## MODELS -CRUD operations for Driver records. +### MODEL: car + +Access: \`db.car\` \`\`\` -SUBCOMMANDS: - myapp driver list List all records - myapp driver get --id Get one record - myapp driver create --name --licenseNumber - myapp driver update --id [--name ] [--licenseNumber ] - myapp driver delete --id Delete one record +METHODS: + db.car.findMany({ select, where?, orderBy?, first?, offset? }) + db.car.findOne({ where: { id }, select }) + db.car.create({ data: { make, model, year, isElectric }, select }) + db.car.update({ where: { id }, data, select }) + db.car.delete({ where: { id } }) + +FIELDS: + id: string (primary key) + make: string + model: string + year: number + isElectric: boolean + createdAt: string + +EDITABLE FIELDS: + make: string + model: string + year: number + isElectric: boolean + +OUTPUT: Promise + findMany: [{ id, make, model, year, isElectric, createdAt }] + findOne: { id, make, model, year, isElectric, createdAt } + create: { id, make, model, year, isElectric, createdAt } + update: { id, make, model, year, isElectric, createdAt } + delete: { id } +\`\`\` -INPUT FIELDS: - id: UUID (primary key) - name: String - licenseNumber: String +### MODEL: driver -EDITABLE FIELDS (for create/update): - name: String - licenseNumber: String +Access: \`db.driver\` -OUTPUT: JSON - list: [{ id, name, licenseNumber }] - get: { id, name, licenseNumber } - create: { id, name, licenseNumber } - update: { id, name, licenseNumber } - delete: { id } +\`\`\` +METHODS: + db.driver.findMany({ select, where?, orderBy?, first?, offset? }) + db.driver.findOne({ where: { id }, select }) + db.driver.create({ data: { name, licenseNumber }, select }) + db.driver.update({ where: { id }, data, select }) + db.driver.delete({ where: { id } }) + +FIELDS: + id: string (primary key) + name: string + licenseNumber: string + +EDITABLE FIELDS: + name: string + licenseNumber: string + +OUTPUT: Promise + findMany: [{ id, name, licenseNumber }] + findOne: { id, name, licenseNumber } + create: { id, name, licenseNumber } + update: { id, name, licenseNumber } + delete: { id } \`\`\` -### TOOL: current-user +## CUSTOM OPERATIONS + +### OPERATION: currentUser Get the currently authenticated user \`\`\` TYPE: query -USAGE: myapp current-user +ACCESS: db.query.currentUser +USAGE: db.query.currentUser().execute() INPUT: none -OUTPUT: JSON +OUTPUT: Promise \`\`\` -### TOOL: login +### OPERATION: login Authenticate a user \`\`\` TYPE: mutation -USAGE: myapp login --email --password +ACCESS: db.mutation.login +USAGE: db.mutation.login({ email: , password: }).execute() INPUT: email: String (required) password: String (required) -OUTPUT: JSON +OUTPUT: Promise \`\`\` -## WORKFLOWS +## PATTERNS -### Initial setup +\`\`\`typescript +// All methods require .execute() to run +const result = await db.modelName.findMany({ select: { id: true } }).execute(); -\`\`\`bash -myapp context create dev --endpoint http://localhost:5000/graphql -myapp context use dev -myapp auth set-token eyJhbGciOiJIUzI1NiIs... +// Select specific fields +const partial = await db.modelName.findMany({ select: { id: true, name: true } }).execute(); + +// Filter with where clause +const filtered = await db.modelName.findMany({ select: { id: true }, where: { name: 'test' } }).execute(); \`\`\` +" +`; -### CRUD workflow (car) +exports[`orm docs generator generates ORM README 1`] = ` +"# ORM Client -\`\`\`bash -# List all -myapp car list +> Auto-generated ORM client from GraphQL schema +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT -# Create -myapp car create --make "value" --model "value" --year "value" --isElectric "value" +## Setup -# Get by id -myapp car get --id +\`\`\`typescript +import { createClient } from './orm'; -# Update -myapp car update --id --make "new-value" +const db = createClient({ + endpoint: 'https://api.example.com/graphql', + headers: { Authorization: 'Bearer ' }, +}); +\`\`\` -# Delete -myapp car delete --id +## Models + +| Model | Operations | +|-------|------------| +| \`car\` | findMany, findOne, create, update, delete | +| \`driver\` | findMany, findOne, create, update, delete | + +## Table Operations + +### \`db.car\` + +CRUD operations for Car records. + +**Fields:** + +| Field | Type | Editable | +|-------|------|----------| +| \`id\` | UUID | No | +| \`make\` | String | Yes | +| \`model\` | String | Yes | +| \`year\` | Int | Yes | +| \`isElectric\` | Boolean | Yes | +| \`createdAt\` | Datetime | No | + +**Operations:** + +\`\`\`typescript +// List all car records +const items = await db.car.findMany({ select: { id: true, make: true, model: true, year: true, isElectric: true, createdAt: true } }).execute(); + +// Get one by id +const item = await db.car.findOne({ where: { id: '' }, select: { id: true, make: true, model: true, year: true, isElectric: true, createdAt: true } }).execute(); + +// Create +const created = await db.car.create({ data: { make: '', model: '', year: '', isElectric: '' }, select: { id: true } }).execute(); + +// Update +const updated = await db.car.update({ where: { id: '' }, data: { make: '' }, select: { id: true } }).execute(); + +// Delete +const deleted = await db.car.delete({ where: { id: '' } }).execute(); \`\`\` -### Piping output +### \`db.driver\` -\`\`\`bash -# Pretty print -myapp car list | jq '.' +CRUD operations for Driver records. -# Extract field -myapp car list | jq '.[].id' +**Fields:** -# Count results -myapp car list | jq 'length' +| Field | Type | Editable | +|-------|------|----------| +| \`id\` | UUID | No | +| \`name\` | String | Yes | +| \`licenseNumber\` | String | Yes | + +**Operations:** + +\`\`\`typescript +// List all driver records +const items = await db.driver.findMany({ select: { id: true, name: true, licenseNumber: true } }).execute(); + +// Get one by id +const item = await db.driver.findOne({ where: { id: '' }, select: { id: true, name: true, licenseNumber: true } }).execute(); + +// Create +const created = await db.driver.create({ data: { name: '', licenseNumber: '' }, select: { id: true } }).execute(); + +// Update +const updated = await db.driver.update({ where: { id: '' }, data: { name: '' }, select: { id: true } }).execute(); + +// Delete +const deleted = await db.driver.delete({ where: { id: '' } }).execute(); \`\`\` -## ERROR HANDLING +## Custom Operations -All errors are written to stderr. Exit codes: -- \`0\`: Success -- \`1\`: Error (auth failure, not found, validation error, network error) +### \`db.query.currentUser\` -Common errors: -- "No active context": Run \`context use \` first -- "Not authenticated": Run \`auth set-token \` first -- "Record not found": The requested ID does not exist -" -`; +Get the currently authenticated user -exports[`cli-generator generates README.md by default 1`] = ` -"# myapp CLI +- **Type:** query +- **Arguments:** none -> Auto-generated CLI commands from GraphQL schema -> @generated by @constructive-io/graphql-codegen - DO NOT EDIT +\`\`\`typescript +const result = await db.query.currentUser().execute(); +\`\`\` -## Setup +### \`db.mutation.login\` -\`\`\`bash -# Create a context pointing at your GraphQL endpoint -myapp context create production --endpoint https://api.example.com/graphql +Authenticate a user -# Set the active context -myapp context use production +- **Type:** mutation +- **Arguments:** -# Authenticate -myapp auth set-token + | Argument | Type | + |----------|------| + | \`email\` | String (required) | + | \`password\` | String (required) | + +\`\`\`typescript +const result = await db.mutation.login({ email: '', password: '' }).execute(); \`\`\` +" +`; -## Commands +exports[`orm docs generator generates ORM skill files 1`] = ` +"# orm-car -| Command | Description | -|---------|-------------| -| \`context\` | Manage API contexts (endpoints) | -| \`auth\` | Manage authentication tokens | -| \`car\` | car CRUD operations | -| \`driver\` | driver CRUD operations | -| \`current-user\` | Get the currently authenticated user | -| \`login\` | Authenticate a user | +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT -## Infrastructure Commands +ORM operations for Car records -### \`context\` +## Usage -Manage named API contexts (kubectl-style). +\`\`\`typescript +db.car.findMany({ select: { id: true } }).execute() +db.car.findOne({ where: { id: '' }, select: { id: true } }).execute() +db.car.create({ data: { make: '', model: '', year: '', isElectric: '' }, select: { id: true } }).execute() +db.car.update({ where: { id: '' }, data: { make: '' }, select: { id: true } }).execute() +db.car.delete({ where: { id: '' } }).execute() +\`\`\` -| Subcommand | Description | -|------------|-------------| -| \`create --endpoint \` | Create a new context | -| \`list\` | List all contexts | -| \`use \` | Set the active context | -| \`current\` | Show current context | -| \`delete \` | Delete a context | +## Examples -Configuration is stored at \`~/.myapp/config/\`. +### List all car records -### \`auth\` +\`\`\`typescript +const items = await db.car.findMany({ + select: { id: true, make: true } +}).execute(); +\`\`\` -Manage authentication tokens per context. +### Create a car -| Subcommand | Description | -|------------|-------------| -| \`set-token \` | Store bearer token for current context | -| \`status\` | Show auth status across all contexts | -| \`logout\` | Remove credentials for current context | +\`\`\`typescript +const item = await db.car.create({ + data: { make: 'value', model: 'value', year: 'value', isElectric: 'value' }, + select: { id: true } +}).execute(); +\`\`\` +" +`; -## Table Commands +exports[`orm docs generator generates ORM skill files 2`] = ` +"# orm-driver -### \`car\` +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT -CRUD operations for Car records. +ORM operations for Driver records -| Subcommand | Description | -|------------|-------------| -| \`list\` | List all car records | -| \`get\` | Get a car by id | -| \`create\` | Create a new car | -| \`update\` | Update an existing car | -| \`delete\` | Delete a car | +## Usage -**Fields:** +\`\`\`typescript +db.driver.findMany({ select: { id: true } }).execute() +db.driver.findOne({ where: { id: '' }, select: { id: true } }).execute() +db.driver.create({ data: { name: '', licenseNumber: '' }, select: { id: true } }).execute() +db.driver.update({ where: { id: '' }, data: { name: '' }, select: { id: true } }).execute() +db.driver.delete({ where: { id: '' } }).execute() +\`\`\` -| Field | Type | -|-------|------| -| \`id\` | UUID | -| \`make\` | String | -| \`model\` | String | -| \`year\` | Int | -| \`isElectric\` | Boolean | -| \`createdAt\` | Datetime | +## Examples -**Create fields:** \`make\`, \`model\`, \`year\`, \`isElectric\` +### List all driver records -### \`driver\` +\`\`\`typescript +const items = await db.driver.findMany({ + select: { id: true, name: true } +}).execute(); +\`\`\` -CRUD operations for Driver records. +### Create a driver -| Subcommand | Description | -|------------|-------------| -| \`list\` | List all driver records | -| \`get\` | Get a driver by id | -| \`create\` | Create a new driver | -| \`update\` | Update an existing driver | -| \`delete\` | Delete a driver | +\`\`\`typescript +const item = await db.driver.create({ + data: { name: 'value', licenseNumber: 'value' }, + select: { id: true } +}).execute(); +\`\`\` +" +`; -**Fields:** +exports[`orm docs generator generates ORM skill files 3`] = ` +"# orm-currentUser -| Field | Type | -|-------|------| -| \`id\` | UUID | -| \`name\` | String | -| \`licenseNumber\` | String | +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT + +Get the currently authenticated user + +## Usage -**Create fields:** \`name\`, \`licenseNumber\` +\`\`\`typescript +db.query.currentUser().execute() +\`\`\` -## Custom Operations +## Examples -### \`current-user\` +### Run currentUser -Get the currently authenticated user +\`\`\`typescript +const result = await db.query.currentUser().execute(); +\`\`\` +" +`; -- **Type:** query -- **Arguments:** none +exports[`orm docs generator generates ORM skill files 4`] = ` +"# orm-login -### \`login\` +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT Authenticate a user -- **Type:** mutation -- **Arguments:** +## Usage - | Argument | Type | - |----------|------| - | \`email\` | String (required) | - | \`password\` | String (required) | +\`\`\`typescript +db.mutation.login({ email: '', password: '' }).execute() +\`\`\` -## Output +## Examples -All commands output JSON to stdout. Pipe to \`jq\` for formatting: +### Run login -\`\`\`bash -myapp car list | jq '.[]' -myapp car get --id | jq '.' +\`\`\`typescript +const result = await db.mutation.login({ email: '', password: '' }).execute(); \`\`\` " `; -exports[`cli-generator generates commands.ts (command map) 1`] = ` -"/** - * CLI command map and entry point - * @generated by @constructive-io/graphql-codegen - * DO NOT EDIT - changes will be overwritten - */ -import { CLIOptions, Inquirerer, extractFirst } from "inquirerer"; -import contextCmd from "./commands/context"; -import authCmd from "./commands/auth"; -import carCmd from "./commands/car"; -import driverCmd from "./commands/driver"; -import currentUserCmd from "./commands/current-user"; -import loginCmd from "./commands/login"; -const createCommandMap = () => ({ - "context": contextCmd, - "auth": authCmd, - "car": carCmd, - "driver": driverCmd, - "current-user": currentUserCmd, - "login": loginCmd -}); -const usage = "\\nmyapp \\n\\nCommands:\\n context Manage API contexts\\n auth Manage authentication\\n car car CRUD operations\\n driver driver CRUD operations\\n current-user Get the currently authenticated user\\n login Authenticate a user\\n\\n --help, -h Show this help message\\n --version, -v Show version\\n"; -export const commands = async (argv: Partial>, prompter: Inquirerer, options: CLIOptions) => { - if (argv.help || argv.h) { - console.log(usage); - process.exit(0); - } - let { - first: command, - newArgv - } = extractFirst(argv); - const commandMap = createCommandMap(); - if (!command) { - const answer = await prompter.prompt(argv, [{ - type: "autocomplete", - name: "command", - message: "What do you want to do?", - options: Object.keys(commandMap) - }]); - command = answer.command; - } - const commandFn = commandMap[command]; - if (!commandFn) { - console.log(usage); - console.error(\`Unknown command: \${command}\`); - process.exit(1); - } - await commandFn(newArgv, prompter, options); - prompter.close(); - return argv; -};" -`; - -exports[`cli-generator generates commands/auth.ts 1`] = ` -"/** - * Authentication commands - * @generated by @constructive-io/graphql-codegen - * DO NOT EDIT - changes will be overwritten - */ -import { CLIOptions, Inquirerer, extractFirst } from "inquirerer"; -import { getStore } from "../executor"; -const usage = "\\nmyapp auth \\n\\nCommands:\\n set-token Set API token for the current context\\n status Show authentication status\\n logout Remove credentials for the current context\\n\\nOptions:\\n --context Specify context (defaults to current context)\\n\\n --help, -h Show this help message\\n"; -export default async (argv: Partial>, prompter: Inquirerer, _options: CLIOptions) => { - if (argv.help || argv.h) { - console.log(usage); - process.exit(0); - } - const store = getStore(); - const { - first: subcommand, - newArgv - } = extractFirst(argv); - if (!subcommand) { - const answer = await prompter.prompt(argv, [{ - type: "autocomplete", - name: "subcommand", - message: "What do you want to do?", - options: ["set-token", "status", "logout"] - }]); - return handleAuthSubcommand(answer.subcommand, newArgv, prompter, store); - } - return handleAuthSubcommand(subcommand, newArgv, prompter, store); -}; -async function handleAuthSubcommand(subcommand: string, argv: Partial>, prompter: Inquirerer, store: ReturnType) { - switch (subcommand) { - case "set-token": - return handleSetToken(argv, prompter, store); - case "status": - return handleStatus(store); - case "logout": - return handleLogout(argv, prompter, store); - default: - console.log(usage); - process.exit(1); - } -} -async function handleSetToken(argv: Partial>, prompter: Inquirerer, store: ReturnType) { - const current = store.getCurrentContext(); - if (!current) { - console.error("No active context. Run \\"context create\\" first."); - process.exit(1); - } - const { - first: token - } = extractFirst(argv); - let tokenValue = token; - if (!tokenValue) { - const answer = await prompter.prompt(argv, [{ - type: "password", - name: "token", - message: "API Token", - required: true - }]); - tokenValue = answer.token; - } - store.setCredentials(current.name, { - token: String.call(tokenValue || "").trim() - }); - console.log(\`Token saved for context: \${current.name}\`); -} -function handleStatus(store: ReturnType) { - const contexts = store.listContexts(); - const settings = store.loadSettings(); - if (contexts.length === 0) { - console.log("No contexts configured."); - return; - } - console.log("Authentication Status:"); - for (const ctx of contexts) { - const isCurrent = ctx.name === settings.currentContext; - const hasAuth = store.hasValidCredentials(ctx.name); - const marker = isCurrent ? "* " : " "; - const status = hasAuth ? "authenticated" : "no token"; - console.log(\`\${marker}\${ctx.name} [\${status}]\`); - } -} -async function handleLogout(argv: Partial>, prompter: Inquirerer, store: ReturnType) { - const current = store.getCurrentContext(); - if (!current) { - console.log("No active context."); - return; - } - const confirm = await prompter.prompt(argv, [{ - type: "confirm", - name: "confirm", - message: \`Remove credentials for "\${current.name}"?\`, - default: false - }]); - if (!confirm.confirm) { - return; - } - if (store.removeCredentials(current.name)) { - console.log(\`Credentials removed for: \${current.name}\`); - } else { - console.log(\`No credentials found for: \${current.name}\`); - } -}" -`; - -exports[`cli-generator generates commands/car.ts 1`] = ` -"/** - * CLI commands for Car - * @generated by @constructive-io/graphql-codegen - * DO NOT EDIT - changes will be overwritten - */ -import { CLIOptions, Inquirerer, extractFirst } from "inquirerer"; -import { getClient } from "../executor"; -const usage = "\\ncar \\n\\nCommands:\\n list List all car records\\n get Get a car by ID\\n create Create a new car\\n update Update an existing car\\n delete Delete a car\\n\\n --help, -h Show this help message\\n"; -export default async (argv: Partial>, prompter: Inquirerer, _options: CLIOptions) => { - if (argv.help || argv.h) { - console.log(usage); - process.exit(0); - } - const { - first: subcommand, - newArgv - } = extractFirst(argv); - if (!subcommand) { - const answer = await prompter.prompt(argv, [{ - type: "autocomplete", - name: "subcommand", - message: "What do you want to do?", - options: ["list", "get", "create", "update", "delete"] - }]); - return handleTableSubcommand(answer.subcommand, newArgv, prompter); - } - return handleTableSubcommand(subcommand, newArgv, prompter); -}; -async function handleTableSubcommand(subcommand: string, argv: Partial>, prompter: Inquirerer) { - switch (subcommand) { - case "list": - return handleList(argv, prompter); - case "get": - return handleGet(argv, prompter); - case "create": - return handleCreate(argv, prompter); - case "update": - return handleUpdate(argv, prompter); - case "delete": - return handleDelete(argv, prompter); - default: - console.log(usage); - process.exit(1); - } -} -async function handleList(_argv: Partial>, _prompter: Inquirerer) { - try { - const client = getClient(); - const result = await client.car.findMany({ - select: { - id: true, - make: true, - model: true, - year: true, - isElectric: true, - createdAt: true +exports[`target docs generator generates combined MCP config 1`] = ` +"{ + "name": "myapp", + "version": "1.0.0", + "description": "MCP tool definitions for myapp SDK (auto-generated from GraphQL schema)", + "tools": [ + { + "name": "myapp_context_create", + "description": "Create a named API context pointing at a GraphQL endpoint", + "inputSchema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Context name" + }, + "endpoint": { + "type": "string", + "description": "GraphQL endpoint URL" + } + }, + "required": [ + "name", + "endpoint" + ] + } + }, + { + "name": "myapp_context_list", + "description": "List all configured API contexts", + "inputSchema": { + "type": "object", + "properties": {} + } + }, + { + "name": "myapp_context_use", + "description": "Set the active API context", + "inputSchema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Context name to activate" + } + }, + "required": [ + "name" + ] + } + }, + { + "name": "myapp_context_current", + "description": "Show the currently active API context", + "inputSchema": { + "type": "object", + "properties": {} + } + }, + { + "name": "myapp_context_delete", + "description": "Delete an API context", + "inputSchema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Context name to delete" + } + }, + "required": [ + "name" + ] + } + }, + { + "name": "myapp_auth_set_token", + "description": "Store a bearer token for the current context", + "inputSchema": { + "type": "object", + "properties": { + "token": { + "type": "string", + "description": "Bearer token value" + } + }, + "required": [ + "token" + ] + } + }, + { + "name": "myapp_auth_status", + "description": "Show authentication status for all contexts", + "inputSchema": { + "type": "object", + "properties": {} + } + }, + { + "name": "myapp_auth_logout", + "description": "Remove credentials for the current context", + "inputSchema": { + "type": "object", + "properties": {} + } + }, + { + "name": "myapp_car_list", + "description": "List all Car records", + "inputSchema": { + "type": "object", + "properties": {} + } + }, + { + "name": "myapp_car_get", + "description": "Get a single Car record by id", + "inputSchema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Car id" + } + }, + "required": [ + "id" + ] + } + }, + { + "name": "myapp_car_create", + "description": "Create a new Car record", + "inputSchema": { + "type": "object", + "properties": { + "make": { + "type": "string", + "description": "Car make" + }, + "model": { + "type": "string", + "description": "Car model" + }, + "year": { + "type": "integer", + "description": "Car year" + }, + "isElectric": { + "type": "boolean", + "description": "Car isElectric" + } + }, + "required": [ + "make", + "model", + "year", + "isElectric" + ] + } + }, + { + "name": "myapp_car_update", + "description": "Update an existing Car record", + "inputSchema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Car id" + }, + "make": { + "type": "string", + "description": "Car make" + }, + "model": { + "type": "string", + "description": "Car model" + }, + "year": { + "type": "integer", + "description": "Car year" + }, + "isElectric": { + "type": "boolean", + "description": "Car isElectric" + } + }, + "required": [ + "id" + ] + } + }, + { + "name": "myapp_car_delete", + "description": "Delete a Car record by id", + "inputSchema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Car id" + } + }, + "required": [ + "id" + ] + } + }, + { + "name": "myapp_car_fields", + "description": "List available fields for Car", + "inputSchema": { + "type": "object", + "properties": {} + }, + "_meta": { + "fields": [ + { + "name": "id", + "type": "UUID", + "editable": false, + "primaryKey": true + }, + { + "name": "make", + "type": "String", + "editable": true, + "primaryKey": false + }, + { + "name": "model", + "type": "String", + "editable": true, + "primaryKey": false + }, + { + "name": "year", + "type": "Int", + "editable": true, + "primaryKey": false + }, + { + "name": "isElectric", + "type": "Boolean", + "editable": true, + "primaryKey": false + }, + { + "name": "createdAt", + "type": "Datetime", + "editable": false, + "primaryKey": false + } + ] + } + }, + { + "name": "myapp_driver_list", + "description": "List all Driver records", + "inputSchema": { + "type": "object", + "properties": {} + } + }, + { + "name": "myapp_driver_get", + "description": "Get a single Driver record by id", + "inputSchema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Driver id" + } + }, + "required": [ + "id" + ] } - }).execute(); - console.log(JSON.stringify(result, null, 2)); - } catch (error) { - console.error("Failed to list records."); - if (error instanceof Error) { - console.error(error.message); - } - process.exit(1); - } -} -async function handleGet(argv: Partial>, prompter: Inquirerer) { - try { - const answers = await prompter.prompt(argv, [{ - type: "text", - name: "id", - message: "id", - required: true - }]); - const client = getClient(); - const result = await client.car.findOne({ - id: answers.id, - select: { - id: true, - make: true, - model: true, - year: true, - isElectric: true, - createdAt: true + }, + { + "name": "myapp_driver_create", + "description": "Create a new Driver record", + "inputSchema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Driver name" + }, + "licenseNumber": { + "type": "string", + "description": "Driver licenseNumber" + } + }, + "required": [ + "name", + "licenseNumber" + ] } - }).execute(); - console.log(JSON.stringify(result, null, 2)); - } catch (error) { - console.error("Record not found."); - if (error instanceof Error) { - console.error(error.message); - } - process.exit(1); - } -} -async function handleCreate(argv: Partial>, prompter: Inquirerer) { - try { - const answers = await prompter.prompt(argv, [{ - type: "text", - name: "make", - message: "make", - required: true - }, { - type: "text", - name: "model", - message: "model", - required: true - }, { - type: "text", - name: "year", - message: "year", - required: true - }, { - type: "text", - name: "isElectric", - message: "isElectric", - required: true - }]); - const client = getClient(); - const result = await client.car.create({ - data: { - make: answers.make, - model: answers.model, - year: answers.year, - isElectric: answers.isElectric - }, - select: { - id: true, - make: true, - model: true, - year: true, - isElectric: true, - createdAt: true + }, + { + "name": "myapp_driver_update", + "description": "Update an existing Driver record", + "inputSchema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Driver id" + }, + "name": { + "type": "string", + "description": "Driver name" + }, + "licenseNumber": { + "type": "string", + "description": "Driver licenseNumber" + } + }, + "required": [ + "id" + ] } - }).execute(); - console.log(JSON.stringify(result, null, 2)); - } catch (error) { - console.error("Failed to create record."); - if (error instanceof Error) { - console.error(error.message); - } - process.exit(1); - } -} -async function handleUpdate(argv: Partial>, prompter: Inquirerer) { - try { - const answers = await prompter.prompt(argv, [{ - type: "text", - name: "id", - message: "id", - required: true - }, { - type: "text", - name: "make", - message: "make", - required: false - }, { - type: "text", - name: "model", - message: "model", - required: false - }, { - type: "text", - name: "year", - message: "year", - required: false - }, { - type: "text", - name: "isElectric", - message: "isElectric", - required: false - }]); - const client = getClient(); - const result = await client.car.update({ - id: answers.id, - data: { - make: answers.make, - model: answers.model, - year: answers.year, - isElectric: answers.isElectric + }, + { + "name": "myapp_driver_delete", + "description": "Delete a Driver record by id", + "inputSchema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Driver id" + } + }, + "required": [ + "id" + ] + } + }, + { + "name": "myapp_driver_fields", + "description": "List available fields for Driver", + "inputSchema": { + "type": "object", + "properties": {} }, - select: { - id: true, - make: true, - model: true, - year: true, - isElectric: true, - createdAt: true + "_meta": { + "fields": [ + { + "name": "id", + "type": "UUID", + "editable": false, + "primaryKey": true + }, + { + "name": "name", + "type": "String", + "editable": true, + "primaryKey": false + }, + { + "name": "licenseNumber", + "type": "String", + "editable": true, + "primaryKey": false + } + ] } - }).execute(); - console.log(JSON.stringify(result, null, 2)); - } catch (error) { - console.error("Failed to update record."); - if (error instanceof Error) { - console.error(error.message); - } - process.exit(1); - } -} -async function handleDelete(argv: Partial>, prompter: Inquirerer) { - try { - const answers = await prompter.prompt(argv, [{ - type: "text", - name: "id", - message: "id", - required: true - }]); - const client = getClient(); - const result = await client.car.delete({ - id: answers.id, - select: { - id: true + }, + { + "name": "myapp_current-user", + "description": "Get the currently authenticated user", + "inputSchema": { + "type": "object", + "properties": {} } - }).execute(); - console.log(JSON.stringify(result, null, 2)); - } catch (error) { - console.error("Failed to delete record."); - if (error instanceof Error) { - console.error(error.message); - } - process.exit(1); - } -}" -`; - -exports[`cli-generator generates commands/context.ts 1`] = ` -"/** - * Context management commands - * @generated by @constructive-io/graphql-codegen - * DO NOT EDIT - changes will be overwritten - */ -import { CLIOptions, Inquirerer, extractFirst } from "inquirerer"; -import { getStore } from "../executor"; -const usage = "\\nmyapp context \\n\\nCommands:\\n create Create a new context\\n list List all contexts\\n use Set the active context\\n current Show current context\\n delete Delete a context\\n\\nCreate Options:\\n --endpoint GraphQL endpoint URL\\n\\n --help, -h Show this help message\\n"; -export default async (argv: Partial>, prompter: Inquirerer, _options: CLIOptions) => { - if (argv.help || argv.h) { - console.log(usage); - process.exit(0); - } - const store = getStore(); - const { - first: subcommand, - newArgv - } = extractFirst(argv); - if (!subcommand) { - const answer = await prompter.prompt(argv, [{ - type: "autocomplete", - name: "subcommand", - message: "What do you want to do?", - options: ["create", "list", "use", "current", "delete"] - }]); - return handleSubcommand(answer.subcommand, newArgv, prompter, store); - } - return handleSubcommand(subcommand, newArgv, prompter, store); -}; -async function handleSubcommand(subcommand: string, argv: Partial>, prompter: Inquirerer, store: ReturnType) { - switch (subcommand) { - case "create": - return handleCreate(argv, prompter, store); - case "list": - return handleList(store); - case "use": - return handleUse(argv, prompter, store); - case "current": - return handleCurrent(store); - case "delete": - return handleDelete(argv, prompter, store); - default: - console.log(usage); - process.exit(1); - } -} -async function handleCreate(argv: Partial>, prompter: Inquirerer, store: ReturnType) { - const { - first: name, - newArgv: restArgv - } = extractFirst(argv); - const answers = await prompter.prompt({ - name, - ...restArgv - }, [{ - type: "text", - name: "name", - message: "Context name", - required: true - }, { - type: "text", - name: "endpoint", - message: "GraphQL endpoint URL", - required: true - }]); - const contextName = answers.name; - const endpoint = answers.endpoint; - store.createContext(contextName, { - endpoint: endpoint - }); - const settings = store.loadSettings(); - if (!settings.currentContext) { - store.setCurrentContext(contextName); - } - console.log(\`Created context: \${contextName}\`); - console.log(\` Endpoint: \${endpoint}\`); -} -function handleList(store: ReturnType) { - const contexts = store.listContexts(); - const settings = store.loadSettings(); - if (contexts.length === 0) { - console.log("No contexts configured."); - return; - } - console.log("Contexts:"); - for (const ctx of contexts) { - const marker = ctx.name === settings.currentContext ? "* " : " "; - const authStatus = store.hasValidCredentials(ctx.name) ? "[authenticated]" : "[no token]"; - console.log(\`\${marker}\${ctx.name} \${authStatus}\`); - console.log(\` Endpoint: \${ctx.endpoint}\`); - } -} -async function handleUse(argv: Partial>, prompter: Inquirerer, store: ReturnType) { - const { - first: name - } = extractFirst(argv); - const contexts = store.listContexts(); - if (contexts.length === 0) { - console.log("No contexts configured."); - return; - } - let contextName = name; - if (!contextName) { - const answer = await prompter.prompt(argv, [{ - type: "autocomplete", - name: "name", - message: "Select context", - options: contexts.map(c => c.name) - }]); - contextName = answer.name; - } - if (store.setCurrentContext(contextName)) { - console.log(\`Switched to context: \${contextName}\`); - } else { - console.error(\`Context "\${contextName}" not found.\`); - process.exit(1); - } -} -function handleCurrent(store: ReturnType) { - const current = store.getCurrentContext(); - if (!current) { - console.log("No current context set."); - return; - } - console.log(\`Current context: \${current.name}\`); - console.log(\` Endpoint: \${current.endpoint}\`); - const hasAuth = store.hasValidCredentials(current.name); - console.log(\` Auth: \${hasAuth ? "authenticated" : "not authenticated"}\`); -} -async function handleDelete(argv: Partial>, prompter: Inquirerer, store: ReturnType) { - const { - first: name - } = extractFirst(argv); - const contexts = store.listContexts(); - if (contexts.length === 0) { - console.log("No contexts configured."); - return; - } - let contextName = name; - if (!contextName) { - const answer = await prompter.prompt(argv, [{ - type: "autocomplete", - name: "name", - message: "Select context to delete", - options: contexts.map(c => c.name) - }]); - contextName = answer.name; - } - if (store.deleteContext(contextName)) { - console.log(\`Deleted context: \${contextName}\`); - } else { - console.error(\`Context "\${contextName}" not found.\`); - process.exit(1); - } -}" -`; - -exports[`cli-generator generates commands/current-user.ts (custom query) 1`] = ` -"/** - * CLI command for query currentUser - * @generated by @constructive-io/graphql-codegen - * DO NOT EDIT - changes will be overwritten - */ -import { CLIOptions, Inquirerer } from "inquirerer"; -import { getClient } from "../executor"; -export default async (argv: Partial>, prompter: Inquirerer, _options: CLIOptions) => { - try { - if (argv.help || argv.h) { - console.log("current-user - Get the currently authenticated user\\n\\nUsage: current-user [OPTIONS]\\n"); - process.exit(0); - } - const client = getClient(); - const result = await client.query.currentUser({}).execute(); - console.log(JSON.stringify(result, null, 2)); - } catch (error) { - console.error("Failed: currentUser"); - if (error instanceof Error) { - console.error(error.message); - } - process.exit(1); - } -};" -`; - -exports[`cli-generator generates commands/driver.ts 1`] = ` -"/** - * CLI commands for Driver - * @generated by @constructive-io/graphql-codegen - * DO NOT EDIT - changes will be overwritten - */ -import { CLIOptions, Inquirerer, extractFirst } from "inquirerer"; -import { getClient } from "../executor"; -const usage = "\\ndriver \\n\\nCommands:\\n list List all driver records\\n get Get a driver by ID\\n create Create a new driver\\n update Update an existing driver\\n delete Delete a driver\\n\\n --help, -h Show this help message\\n"; -export default async (argv: Partial>, prompter: Inquirerer, _options: CLIOptions) => { - if (argv.help || argv.h) { - console.log(usage); - process.exit(0); - } - const { - first: subcommand, - newArgv - } = extractFirst(argv); - if (!subcommand) { - const answer = await prompter.prompt(argv, [{ - type: "autocomplete", - name: "subcommand", - message: "What do you want to do?", - options: ["list", "get", "create", "update", "delete"] - }]); - return handleTableSubcommand(answer.subcommand, newArgv, prompter); - } - return handleTableSubcommand(subcommand, newArgv, prompter); -}; -async function handleTableSubcommand(subcommand: string, argv: Partial>, prompter: Inquirerer) { - switch (subcommand) { - case "list": - return handleList(argv, prompter); - case "get": - return handleGet(argv, prompter); - case "create": - return handleCreate(argv, prompter); - case "update": - return handleUpdate(argv, prompter); - case "delete": - return handleDelete(argv, prompter); - default: - console.log(usage); - process.exit(1); - } -} -async function handleList(_argv: Partial>, _prompter: Inquirerer) { - try { - const client = getClient(); - const result = await client.driver.findMany({ - select: { - id: true, - name: true, - licenseNumber: true + }, + { + "name": "myapp_login", + "description": "Authenticate a user", + "inputSchema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "email" + }, + "password": { + "type": "string", + "description": "password" + } + }, + "required": [ + "email", + "password" + ] } - }).execute(); - console.log(JSON.stringify(result, null, 2)); - } catch (error) { - console.error("Failed to list records."); - if (error instanceof Error) { - console.error(error.message); - } - process.exit(1); - } -} -async function handleGet(argv: Partial>, prompter: Inquirerer) { - try { - const answers = await prompter.prompt(argv, [{ - type: "text", - name: "id", - message: "id", - required: true - }]); - const client = getClient(); - const result = await client.driver.findOne({ - id: answers.id, - select: { - id: true, - name: true, - licenseNumber: true + }, + { + "name": "orm_car_findMany", + "description": "List all Car records via ORM", + "inputSchema": { + "type": "object", + "properties": { + "first": { + "type": "integer", + "description": "Limit number of results" + }, + "offset": { + "type": "integer", + "description": "Offset for pagination" + } + } } - }).execute(); - console.log(JSON.stringify(result, null, 2)); - } catch (error) { - console.error("Record not found."); - if (error instanceof Error) { - console.error(error.message); - } - process.exit(1); - } -} -async function handleCreate(argv: Partial>, prompter: Inquirerer) { - try { - const answers = await prompter.prompt(argv, [{ - type: "text", - name: "name", - message: "name", - required: true - }, { - type: "text", - name: "licenseNumber", - message: "licenseNumber", - required: true - }]); - const client = getClient(); - const result = await client.driver.create({ - data: { - name: answers.name, - licenseNumber: answers.licenseNumber + }, + { + "name": "orm_car_findOne", + "description": "Get a single Car record by id", + "inputSchema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Car id" + } + }, + "required": [ + "id" + ] + } + }, + { + "name": "orm_car_create", + "description": "Create a new Car record", + "inputSchema": { + "type": "object", + "properties": { + "make": { + "type": "string", + "description": "Car make" + }, + "model": { + "type": "string", + "description": "Car model" + }, + "year": { + "type": "integer", + "description": "Car year" + }, + "isElectric": { + "type": "boolean", + "description": "Car isElectric" + } + }, + "required": [ + "make", + "model", + "year", + "isElectric" + ] + } + }, + { + "name": "orm_car_update", + "description": "Update an existing Car record", + "inputSchema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Car id" + }, + "make": { + "type": "string", + "description": "Car make" + }, + "model": { + "type": "string", + "description": "Car model" + }, + "year": { + "type": "integer", + "description": "Car year" + }, + "isElectric": { + "type": "boolean", + "description": "Car isElectric" + } + }, + "required": [ + "id" + ] + } + }, + { + "name": "orm_car_delete", + "description": "Delete a Car record by id", + "inputSchema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Car id" + } + }, + "required": [ + "id" + ] }, - select: { - id: true, - name: true, - licenseNumber: true + "_meta": { + "fields": [ + { + "name": "id", + "type": "UUID", + "editable": false, + "primaryKey": true + }, + { + "name": "make", + "type": "String", + "editable": true, + "primaryKey": false + }, + { + "name": "model", + "type": "String", + "editable": true, + "primaryKey": false + }, + { + "name": "year", + "type": "Int", + "editable": true, + "primaryKey": false + }, + { + "name": "isElectric", + "type": "Boolean", + "editable": true, + "primaryKey": false + }, + { + "name": "createdAt", + "type": "Datetime", + "editable": false, + "primaryKey": false + } + ] + } + }, + { + "name": "orm_driver_findMany", + "description": "List all Driver records via ORM", + "inputSchema": { + "type": "object", + "properties": { + "first": { + "type": "integer", + "description": "Limit number of results" + }, + "offset": { + "type": "integer", + "description": "Offset for pagination" + } + } + } + }, + { + "name": "orm_driver_findOne", + "description": "Get a single Driver record by id", + "inputSchema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Driver id" + } + }, + "required": [ + "id" + ] + } + }, + { + "name": "orm_driver_create", + "description": "Create a new Driver record", + "inputSchema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Driver name" + }, + "licenseNumber": { + "type": "string", + "description": "Driver licenseNumber" + } + }, + "required": [ + "name", + "licenseNumber" + ] } - }).execute(); - console.log(JSON.stringify(result, null, 2)); - } catch (error) { - console.error("Failed to create record."); - if (error instanceof Error) { - console.error(error.message); - } - process.exit(1); - } -} -async function handleUpdate(argv: Partial>, prompter: Inquirerer) { - try { - const answers = await prompter.prompt(argv, [{ - type: "text", - name: "id", - message: "id", - required: true - }, { - type: "text", - name: "name", - message: "name", - required: false - }, { - type: "text", - name: "licenseNumber", - message: "licenseNumber", - required: false - }]); - const client = getClient(); - const result = await client.driver.update({ - id: answers.id, - data: { - name: answers.name, - licenseNumber: answers.licenseNumber + }, + { + "name": "orm_driver_update", + "description": "Update an existing Driver record", + "inputSchema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Driver id" + }, + "name": { + "type": "string", + "description": "Driver name" + }, + "licenseNumber": { + "type": "string", + "description": "Driver licenseNumber" + } + }, + "required": [ + "id" + ] + } + }, + { + "name": "orm_driver_delete", + "description": "Delete a Driver record by id", + "inputSchema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Driver id" + } + }, + "required": [ + "id" + ] }, - select: { - id: true, - name: true, - licenseNumber: true + "_meta": { + "fields": [ + { + "name": "id", + "type": "UUID", + "editable": false, + "primaryKey": true + }, + { + "name": "name", + "type": "String", + "editable": true, + "primaryKey": false + }, + { + "name": "licenseNumber", + "type": "String", + "editable": true, + "primaryKey": false + } + ] } - }).execute(); - console.log(JSON.stringify(result, null, 2)); - } catch (error) { - console.error("Failed to update record."); - if (error instanceof Error) { - console.error(error.message); - } - process.exit(1); - } -} -async function handleDelete(argv: Partial>, prompter: Inquirerer) { - try { - const answers = await prompter.prompt(argv, [{ - type: "text", - name: "id", - message: "id", - required: true - }]); - const client = getClient(); - const result = await client.driver.delete({ - id: answers.id, - select: { - id: true + }, + { + "name": "orm_query_currentUser", + "description": "Get the currently authenticated user", + "inputSchema": { + "type": "object", + "properties": {} + } + }, + { + "name": "orm_mutation_login", + "description": "Authenticate a user", + "inputSchema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "email" + }, + "password": { + "type": "string", + "description": "password" + } + }, + "required": [ + "email", + "password" + ] } - }).execute(); - console.log(JSON.stringify(result, null, 2)); - } catch (error) { - console.error("Failed to delete record."); - if (error instanceof Error) { - console.error(error.message); } - process.exit(1); - } -}" + ] +} +" `; -exports[`cli-generator generates commands/login.ts (custom mutation) 1`] = ` -"/** - * CLI command for mutation login - * @generated by @constructive-io/graphql-codegen - * DO NOT EDIT - changes will be overwritten - */ -import { CLIOptions, Inquirerer } from "inquirerer"; -import { getClient } from "../executor"; -export default async (argv: Partial>, prompter: Inquirerer, _options: CLIOptions) => { - try { - if (argv.help || argv.h) { - console.log("login - Authenticate a user\\n\\nUsage: login [OPTIONS]\\n"); - process.exit(0); - } - const answers = await prompter.prompt(argv, [{ - type: "text", - name: "email", - message: "email", - required: true - }, { - type: "text", - name: "password", - message: "password", - required: true - }]); - const client = getClient(); - const result = await client.mutation.login(answers).execute(); - console.log(JSON.stringify(result, null, 2)); - } catch (error) { - console.error("Failed: login"); - if (error instanceof Error) { - console.error(error.message); - } - process.exit(1); - } -};" +exports[`target docs generator generates per-target README 1`] = ` +"# Generated GraphQL SDK + +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT + +## Overview + +- **Tables:** 2 +- **Custom queries:** 1 +- **Custom mutations:** 1 + +**Generators:** ORM, React Query, CLI + +## Modules + +### ORM Client (\`./orm\`) + +Prisma-like ORM client for programmatic GraphQL access. + +\`\`\`typescript +import { createClient } from './orm'; + +const db = createClient({ + endpoint: 'https://api.example.com/graphql', +}); +\`\`\` + +See [orm/README.md](./orm/README.md) for full API reference. + +### React Query Hooks (\`./hooks\`) + +Type-safe React Query hooks for data fetching and mutations. + +\`\`\`typescript +import { configure } from './hooks'; +import { useCarsQuery } from './hooks'; + +configure({ endpoint: 'https://api.example.com/graphql' }); +\`\`\` + +See [hooks/README.md](./hooks/README.md) for full hook reference. + +### CLI Commands (\`./cli\`) + +inquirerer-based CLI commands for \`myapp\`. + +See [cli/README.md](./cli/README.md) for command reference. +" `; -exports[`cli-generator generates executor.ts 1`] = ` -"/** - * Executor and config store for CLI - * @generated by @constructive-io/graphql-codegen - * DO NOT EDIT - changes will be overwritten - */ -import { createConfigStore } from "appstash"; -import { createClient } from "../orm"; -const store = createConfigStore("myapp"); -export const getStore = () => store; -export function getClient(contextName?: string) { - let ctx = null; - if (contextName) { - ctx = store.loadContext(contextName); - if (!ctx) { - throw new Error(\`Context "\${contextName}" not found.\`); - } - } else { - ctx = store.getCurrentContext(); - if (!ctx) { - throw new Error("No active context. Run \\"context create\\" or \\"context use\\" first."); - } - } - const headers = {}; - if (store.hasValidCredentials(ctx.name)) { - const creds = store.getCredentials(ctx.name); - if (creds?.token) { - headers.Authorization = \`Bearer \${creds.token}\`; - } - } - return createClient({ - endpoint: ctx.endpoint, - headers: headers - }); -}" +exports[`target docs generator generates root-root README for multi-target 1`] = ` +"# GraphQL SDK + +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT + +## APIs + +| API | Endpoint | Generators | Docs | +|-----|----------|------------|------| +| auth | http://auth.localhost/graphql | ORM | [./generated/auth/README.md](./generated/auth/README.md) | +| app | http://app.localhost/graphql | ORM, React Query, CLI | [./generated/app/README.md](./generated/app/README.md) | +" `; diff --git a/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts b/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts index 320d20151..ab0d9eca2 100644 --- a/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts +++ b/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts @@ -1,4 +1,28 @@ import { generateCli } from '../../core/codegen/cli'; +import { + generateReadme as generateCliReadme, + generateAgentsDocs as generateCliAgentsDocs, + getCliMcpTools, + generateSkills as generateCliSkills, +} from '../../core/codegen/cli/docs-generator'; +import { resolveDocsConfig } from '../../core/codegen/docs-utils'; +import { + generateOrmReadme, + generateOrmAgentsDocs, + getOrmMcpTools, + generateOrmSkills, +} from '../../core/codegen/orm/docs-generator'; +import { + generateHooksReadme, + generateHooksAgentsDocs, + getHooksMcpTools, + generateHooksSkills, +} from '../../core/codegen/hooks-docs-generator'; +import { + generateTargetReadme, + generateCombinedMcpConfig, + generateRootRootReadme, +} from '../../core/codegen/target-docs-generator'; import type { CleanFieldType, CleanOperation, @@ -129,34 +153,10 @@ describe('cli-generator', () => { customQueries: 1, customMutations: 1, infraFiles: 3, - totalFiles: 10, + totalFiles: 8, }); }); - it('generates README.md by default', () => { - const file = result.files.find((f) => f.fileName === 'README.md'); - expect(file).toBeDefined(); - expect(file!.content).toMatchSnapshot(); - }); - - it('generates AGENTS.md by default', () => { - const file = result.files.find((f) => f.fileName === 'AGENTS.md'); - expect(file).toBeDefined(); - expect(file!.content).toMatchSnapshot(); - }); - - it('does not generate mcp.json by default', () => { - const file = result.files.find((f) => f.fileName === 'mcp.json'); - expect(file).toBeUndefined(); - }); - - it('does not generate skills by default', () => { - const skillFiles = result.files.filter((f) => - f.fileName.startsWith('skills/'), - ); - expect(skillFiles).toHaveLength(0); - }); - it('generates executor.ts', () => { const file = result.files.find((f) => f.fileName === 'executor.ts'); expect(file).toBeDefined(); @@ -241,8 +241,6 @@ describe('cli-generator', () => { it('generates correct file names', () => { const fileNames = result.files.map((f) => f.fileName).sort(); expect(fileNames).toEqual([ - 'AGENTS.md', - 'README.md', 'commands.ts', 'commands/auth.ts', 'commands/car.ts', @@ -255,91 +253,159 @@ describe('cli-generator', () => { }); }); -describe('cli-generator docs: true (all formats)', () => { - const result = generateCli({ - tables: [carTable, driverTable], - customOperations: { - queries: [currentUserQuery], - mutations: [loginMutation], - }, - config: { - cli: { toolName: 'myapp', docs: true }, - }, +const allCustomOps: CleanOperation[] = [currentUserQuery, loginMutation]; + +describe('cli docs generator', () => { + it('generates CLI README', () => { + const readme = generateCliReadme([carTable, driverTable], allCustomOps, 'myapp'); + expect(readme.fileName).toBe('README.md'); + expect(readme.content).toMatchSnapshot(); }); - it('generates mcp.json', () => { - const file = result.files.find((f) => f.fileName === 'mcp.json'); - expect(file).toBeDefined(); - expect(file!.content).toMatchSnapshot(); + it('generates CLI AGENTS.md', () => { + const agents = generateCliAgentsDocs([carTable, driverTable], allCustomOps, 'myapp'); + expect(agents.fileName).toBe('AGENTS.md'); + expect(agents.content).toMatchSnapshot(); }); - it('generates skill files', () => { - const skillFiles = result.files.filter((f) => - f.fileName.startsWith('skills/'), - ); - expect(skillFiles.length).toBeGreaterThan(0); - for (const sf of skillFiles) { + it('generates CLI MCP tools', () => { + const tools = getCliMcpTools([carTable, driverTable], allCustomOps, 'myapp'); + expect(tools.length).toBeGreaterThan(0); + for (const tool of tools) { + expect(tool.name).toBeDefined(); + expect(tool.description).toBeDefined(); + expect(tool.inputSchema).toBeDefined(); + } + }); + + it('generates CLI skill files', () => { + const skills = generateCliSkills([carTable, driverTable], allCustomOps, 'myapp'); + expect(skills.length).toBeGreaterThan(0); + for (const sf of skills) { expect(sf.content).toMatchSnapshot(); } }); +}); - it('generates correct file names with all docs', () => { - const fileNames = result.files.map((f) => f.fileName).sort(); - expect(fileNames).toEqual([ - 'AGENTS.md', - 'README.md', - 'commands.ts', - 'commands/auth.ts', - 'commands/car.ts', - 'commands/context.ts', - 'commands/current-user.ts', - 'commands/driver.ts', - 'commands/login.ts', - 'executor.ts', - 'mcp.json', - 'skills/auth.md', - 'skills/car.md', - 'skills/context.md', - 'skills/current-user.md', - 'skills/driver.md', - 'skills/login.md', - ]); +describe('orm docs generator', () => { + it('generates ORM README', () => { + const readme = generateOrmReadme([carTable, driverTable], allCustomOps); + expect(readme.fileName).toBe('README.md'); + expect(readme.content).toMatchSnapshot(); }); - it('mcp.json has valid tool definitions', () => { - const file = result.files.find((f) => f.fileName === 'mcp.json'); - const parsed = JSON.parse(file!.content); - expect(parsed.name).toBe('myapp'); - expect(parsed.tools).toBeDefined(); - expect(parsed.tools.length).toBeGreaterThan(0); - for (const tool of parsed.tools) { + it('generates ORM AGENTS.md', () => { + const agents = generateOrmAgentsDocs([carTable, driverTable], allCustomOps); + expect(agents.fileName).toBe('AGENTS.md'); + expect(agents.content).toMatchSnapshot(); + }); + + it('generates ORM MCP tools', () => { + const tools = getOrmMcpTools([carTable, driverTable], allCustomOps); + expect(tools.length).toBeGreaterThan(0); + for (const tool of tools) { expect(tool.name).toBeDefined(); expect(tool.description).toBeDefined(); expect(tool.inputSchema).toBeDefined(); } }); + + it('generates ORM skill files', () => { + const skills = generateOrmSkills([carTable, driverTable], allCustomOps); + expect(skills.length).toBeGreaterThan(0); + for (const sf of skills) { + expect(sf.content).toMatchSnapshot(); + } + }); }); -describe('cli-generator docs: false', () => { - const result = generateCli({ - tables: [carTable, driverTable], - customOperations: { - queries: [currentUserQuery], - mutations: [loginMutation], - }, - config: { - cli: { toolName: 'myapp', docs: false }, - }, +describe('hooks docs generator', () => { + it('generates hooks README', () => { + const readme = generateHooksReadme([carTable, driverTable], allCustomOps); + expect(readme.fileName).toBe('README.md'); + expect(readme.content).toMatchSnapshot(); }); - it('generates no doc files', () => { - const docFiles = result.files.filter( - (f) => - f.fileName === 'README.md' || - f.fileName === 'AGENTS.md' || - f.fileName === 'mcp.json' || - f.fileName.startsWith('skills/'), - ); - expect(docFiles).toHaveLength(0); + it('generates hooks AGENTS.md', () => { + const agents = generateHooksAgentsDocs([carTable, driverTable], allCustomOps); + expect(agents.fileName).toBe('AGENTS.md'); + expect(agents.content).toMatchSnapshot(); + }); + + it('generates hooks MCP tools', () => { + const tools = getHooksMcpTools([carTable, driverTable], allCustomOps); + expect(tools.length).toBeGreaterThan(0); + for (const tool of tools) { + expect(tool.name).toBeDefined(); + expect(tool.description).toBeDefined(); + expect(tool.inputSchema).toBeDefined(); + } + }); + + it('generates hooks skill files', () => { + const skills = generateHooksSkills([carTable, driverTable], allCustomOps); + expect(skills.length).toBeGreaterThan(0); + for (const sf of skills) { + expect(sf.content).toMatchSnapshot(); + } + }); +}); + +describe('target docs generator', () => { + it('generates per-target README', () => { + const readme = generateTargetReadme({ + hasOrm: true, + hasHooks: true, + hasCli: true, + tableCount: 2, + customQueryCount: 1, + customMutationCount: 1, + config: { cli: { toolName: 'myapp' } }, + }); + expect(readme.fileName).toBe('README.md'); + expect(readme.content).toMatchSnapshot(); + }); + + it('generates combined MCP config', () => { + const cliTools = getCliMcpTools([carTable, driverTable], allCustomOps, 'myapp'); + const ormTools = getOrmMcpTools([carTable, driverTable], allCustomOps); + const allTools = [...cliTools, ...ormTools]; + const mcp = generateCombinedMcpConfig(allTools, 'myapp'); + expect(mcp.fileName).toBe('mcp.json'); + const parsed = JSON.parse(mcp.content); + expect(parsed.name).toBe('myapp'); + expect(parsed.tools.length).toBe(allTools.length); + expect(mcp.content).toMatchSnapshot(); + }); + + it('generates root-root README for multi-target', () => { + const readme = generateRootRootReadme([ + { name: 'auth', output: './generated/auth', endpoint: 'http://auth.localhost/graphql', generators: ['ORM'] }, + { name: 'app', output: './generated/app', endpoint: 'http://app.localhost/graphql', generators: ['ORM', 'React Query', 'CLI'] }, + ]); + expect(readme.fileName).toBe('README.md'); + expect(readme.content).toMatchSnapshot(); + }); +}); + +describe('resolveDocsConfig', () => { + it('defaults to readme + agents', () => { + const config = resolveDocsConfig(undefined); + expect(config).toEqual({ readme: true, agents: true, mcp: false, skills: false }); + }); + + it('docs: true enables all', () => { + const config = resolveDocsConfig(true); + expect(config).toEqual({ readme: true, agents: true, mcp: true, skills: true }); + }); + + it('docs: false disables all', () => { + const config = resolveDocsConfig(false); + expect(config).toEqual({ readme: false, agents: false, mcp: false, skills: false }); + }); + + it('partial config fills defaults', () => { + const config = resolveDocsConfig({ mcp: true }); + expect(config).toEqual({ readme: true, agents: true, mcp: true, skills: false }); }); }); diff --git a/graphql/codegen/src/cli/index.ts b/graphql/codegen/src/cli/index.ts index 1a36a11e9..dec25073c 100644 --- a/graphql/codegen/src/cli/index.ts +++ b/graphql/codegen/src/cli/index.ts @@ -8,7 +8,7 @@ import { CLI, CLIOptions, getPackageJson, Inquirerer } from 'inquirerer'; import { findConfigFile, loadConfigFile } from '../core/config'; -import { generate } from '../core/generate'; +import { generate, generateMulti } from '../core/generate'; import { mergeConfig, type GraphQLSDKConfigTarget } from '../types/config'; import { buildDbConfig, @@ -96,7 +96,6 @@ export const commands = async ( if (isMulti) { const targets = config as Record; - const names = targetName ? [targetName] : Object.keys(targets); if (targetName && !targets[targetName]) { console.error( @@ -111,14 +110,19 @@ export const commands = async ( camelizeArgv(argv as Record), ), ); - let hasError = false; - for (const name of names) { + + const selectedTargets = targetName + ? { [targetName]: targets[targetName] } + : targets; + + const { results, hasError } = await generateMulti({ + configs: selectedTargets, + cliOverrides: cliOptions as Partial, + }); + + for (const { name, result } of results) { console.log(`\n[${name}]`); - const result = await generate( - mergeConfig(targets[name], cliOptions as GraphQLSDKConfigTarget), - ); printResult(result); - if (!result.success) hasError = true; } prompter.close(); diff --git a/graphql/codegen/src/core/codegen/cli/docs-generator.ts b/graphql/codegen/src/core/codegen/cli/docs-generator.ts index 41bece590..85a513e8f 100644 --- a/graphql/codegen/src/core/codegen/cli/docs-generator.ts +++ b/graphql/codegen/src/core/codegen/cli/docs-generator.ts @@ -1,81 +1,27 @@ import { toKebabCase } from 'komoji'; +import type { CleanTable, CleanOperation } from '../../../types/schema'; +import { + formatArgType, + getEditableFields, + gqlTypeToJsonSchemaType, + buildSkillFile, +} from '../docs-utils'; +import type { GeneratedDocFile, McpTool } from '../docs-utils'; import { getScalarFields, getTableNames, getPrimaryKeyInfo, } from '../utils'; -import type { CleanTable, CleanOperation } from '../../../types/schema'; -import type { DocsConfig } from '../../../types/config'; -import type { GeneratedFile } from './executor-generator'; - -function formatArgType(arg: CleanOperation['args'][number]): string { - const t = arg.type; - if (t.kind === 'NON_NULL' && t.ofType) { - return `${formatTypeRef(t.ofType)} (required)`; - } - return formatTypeRef(t); -} - -function formatTypeRef(t: CleanOperation['args'][number]['type']): string { - if (t.kind === 'LIST' && t.ofType) { - return `[${formatTypeRef(t.ofType)}]`; - } - if (t.kind === 'NON_NULL' && t.ofType) { - return `${formatTypeRef(t.ofType)}!`; - } - return t.name ?? 'unknown'; -} - -function getEditableFields(table: CleanTable) { - const pk = getPrimaryKeyInfo(table)[0]; - return getScalarFields(table).filter( - (f) => - f.name !== pk.name && - f.name !== 'nodeId' && - f.name !== 'createdAt' && - f.name !== 'updatedAt', - ); -} -function gqlTypeToJsonSchemaType(gqlType: string): string { - switch (gqlType) { - case 'Int': - return 'integer'; - case 'Float': - return 'number'; - case 'Boolean': - return 'boolean'; - default: - return 'string'; - } -} - -export function resolveDocsConfig( - docs: DocsConfig | boolean | undefined, -): DocsConfig { - if (docs === true) { - return { readme: true, agents: true, mcp: true, skills: true }; - } - if (docs === false) { - return { readme: false, agents: false, mcp: false, skills: false }; - } - if (!docs) { - return { readme: true, agents: true, mcp: false, skills: false }; - } - return { - readme: docs.readme ?? true, - agents: docs.agents ?? true, - mcp: docs.mcp ?? false, - skills: docs.skills ?? false, - }; -} +export { resolveDocsConfig } from '../docs-utils'; +export type { GeneratedDocFile, McpTool } from '../docs-utils'; export function generateReadme( tables: CleanTable[], customOperations: CleanOperation[], toolName: string, -): GeneratedFile { +): GeneratedDocFile { const lines: string[] = []; lines.push(`# ${toolName} CLI`); @@ -221,7 +167,7 @@ export function generateAgentsDocs( tables: CleanTable[], customOperations: CleanOperation[], toolName: string, -): GeneratedFile { +): GeneratedDocFile { const lines: string[] = []; lines.push(`# ${toolName} CLI - Agent Reference`); @@ -433,12 +379,12 @@ export function generateAgentsDocs( }; } -export function generateMcpConfig( +export function getCliMcpTools( tables: CleanTable[], customOperations: CleanOperation[], toolName: string, -): GeneratedFile { - const tools: Record[] = []; +): McpTool[] { + const tools: McpTool[] = []; tools.push({ name: `${toolName}_context_create`, @@ -638,25 +584,15 @@ export function generateMcpConfig( }); } - const mcpConfig = { - name: toolName, - version: '1.0.0', - description: `MCP tool definitions for ${toolName} CLI (auto-generated from GraphQL schema)`, - tools, - }; - - return { - fileName: 'mcp.json', - content: JSON.stringify(mcpConfig, null, 2) + '\n', - }; + return tools; } export function generateSkills( tables: CleanTable[], customOperations: CleanOperation[], toolName: string, -): GeneratedFile[] { - const files: GeneratedFile[] = []; +): GeneratedDocFile[] { + const files: GeneratedDocFile[] = []; files.push({ fileName: 'skills/context.md', @@ -673,14 +609,14 @@ export function generateSkills( examples: [ { description: 'Create and activate a context', - commands: [ + code: [ `${toolName} context create production --endpoint https://api.example.com/graphql`, `${toolName} context use production`, ], }, { description: 'List all contexts', - commands: [`${toolName} context list`], + code: [`${toolName} context list`], }, ], }), @@ -699,11 +635,11 @@ export function generateSkills( examples: [ { description: 'Authenticate with a token', - commands: [`${toolName} auth set-token eyJhbGciOiJIUzI1NiIs...`], + code: [`${toolName} auth set-token eyJhbGciOiJIUzI1NiIs...`], }, { description: 'Check auth status', - commands: [`${toolName} auth status`], + code: [`${toolName} auth status`], }, ], }), @@ -730,27 +666,27 @@ export function generateSkills( examples: [ { description: `List all ${singularName} records`, - commands: [`${toolName} ${kebab} list`], + code: [`${toolName} ${kebab} list`], }, { description: `Create a ${singularName}`, - commands: [ + code: [ `${toolName} ${kebab} create ${editableFields.map((f) => `--${f.name} "value"`).join(' ')}`, ], }, { description: `Get a ${singularName} by ${pk.name}`, - commands: [`${toolName} ${kebab} get --${pk.name} `], + code: [`${toolName} ${kebab} get --${pk.name} `], }, { description: `Update a ${singularName}`, - commands: [ + code: [ `${toolName} ${kebab} update --${pk.name} --${editableFields[0]?.name || 'field'} "new-value"`, ], }, { description: `Delete a ${singularName}`, - commands: [`${toolName} ${kebab} delete --${pk.name} `], + code: [`${toolName} ${kebab} delete --${pk.name} `], }, ], }), @@ -773,7 +709,7 @@ export function generateSkills( examples: [ { description: `Run ${op.name}`, - commands: [usage], + code: [usage], }, ], }), @@ -782,43 +718,3 @@ export function generateSkills( return files; } - -interface SkillDefinition { - name: string; - description: string; - usage: string[]; - examples: { description: string; commands: string[] }[]; -} - -function buildSkillFile(skill: SkillDefinition): string { - const lines: string[] = []; - - lines.push(`# ${skill.name}`); - lines.push(''); - lines.push(`> @generated by @constructive-io/graphql-codegen - DO NOT EDIT`); - lines.push(''); - lines.push(skill.description); - lines.push(''); - lines.push('## Usage'); - lines.push(''); - lines.push('```bash'); - for (const u of skill.usage) { - lines.push(u); - } - lines.push('```'); - lines.push(''); - lines.push('## Examples'); - lines.push(''); - for (const ex of skill.examples) { - lines.push(`### ${ex.description}`); - lines.push(''); - lines.push('```bash'); - for (const cmd of ex.commands) { - lines.push(cmd); - } - lines.push('```'); - lines.push(''); - } - - return lines.join('\n'); -} diff --git a/graphql/codegen/src/core/codegen/cli/index.ts b/graphql/codegen/src/core/codegen/cli/index.ts index 85f3f0de4..d64eeb5fe 100644 --- a/graphql/codegen/src/core/codegen/cli/index.ts +++ b/graphql/codegen/src/core/codegen/cli/index.ts @@ -1,14 +1,7 @@ -import type { CliConfig, GraphQLSDKConfigTarget } from '../../../types/config'; +import type { GraphQLSDKConfigTarget } from '../../../types/config'; import type { CleanOperation, CleanTable } from '../../../types/schema'; import { generateCommandMap } from './command-map-generator'; import { generateCustomCommand } from './custom-command-generator'; -import { - generateReadme, - generateAgentsDocs, - generateMcpConfig, - generateSkills, - resolveDocsConfig, -} from './docs-generator'; import { generateExecutorFile } from './executor-generator'; import type { GeneratedFile } from './executor-generator'; import { generateAuthCommand, generateContextCommand } from './infra-generator'; @@ -75,28 +68,6 @@ export function generateCli(options: GenerateCliOptions): GenerateCliResult { ); files.push(commandMapFile); - const docsConfig = resolveDocsConfig( - typeof cliConfig === 'object' ? (cliConfig as CliConfig).docs : undefined, - ); - - if (docsConfig.readme) { - files.push(generateReadme(tables, allCustomOps, toolName)); - } - - if (docsConfig.agents) { - files.push(generateAgentsDocs(tables, allCustomOps, toolName)); - } - - if (docsConfig.mcp) { - files.push(generateMcpConfig(tables, allCustomOps, toolName)); - } - - if (docsConfig.skills) { - for (const skillFile of generateSkills(tables, allCustomOps, toolName)) { - files.push(skillFile); - } - } - return { files, stats: { @@ -120,8 +91,9 @@ export { export { generateReadme, generateAgentsDocs, - generateMcpConfig, + getCliMcpTools, generateSkills, - resolveDocsConfig, } from './docs-generator'; +export { resolveDocsConfig } from '../docs-utils'; +export type { GeneratedDocFile, McpTool } from '../docs-utils'; export type { GeneratedFile } from './executor-generator'; diff --git a/graphql/codegen/src/core/codegen/docs-utils.ts b/graphql/codegen/src/core/codegen/docs-utils.ts new file mode 100644 index 000000000..2e5a7d4b6 --- /dev/null +++ b/graphql/codegen/src/core/codegen/docs-utils.ts @@ -0,0 +1,121 @@ +import type { DocsConfig } from '../../types/config'; +import type { CleanField, CleanOperation, CleanTable } from '../../types/schema'; +import { getScalarFields, getPrimaryKeyInfo } from './utils'; + +export interface GeneratedDocFile { + fileName: string; + content: string; +} + +export interface McpTool { + name: string; + description: string; + inputSchema: Record; + _meta?: Record; +} + +export interface SkillDefinition { + name: string; + description: string; + usage: string[]; + examples: { description: string; code: string[] }[]; + language?: string; +} + +export function resolveDocsConfig( + docs: DocsConfig | boolean | undefined, +): DocsConfig { + if (docs === true) { + return { readme: true, agents: true, mcp: true, skills: true }; + } + if (docs === false) { + return { readme: false, agents: false, mcp: false, skills: false }; + } + if (!docs) { + return { readme: true, agents: true, mcp: false, skills: false }; + } + return { + readme: docs.readme ?? true, + agents: docs.agents ?? true, + mcp: docs.mcp ?? false, + skills: docs.skills ?? false, + }; +} + +export function formatArgType(arg: CleanOperation['args'][number]): string { + const t = arg.type; + if (t.kind === 'NON_NULL' && t.ofType) { + return `${formatTypeRef(t.ofType)} (required)`; + } + return formatTypeRef(t); +} + +export function formatTypeRef( + t: CleanOperation['args'][number]['type'], +): string { + if (t.kind === 'LIST' && t.ofType) { + return `[${formatTypeRef(t.ofType)}]`; + } + if (t.kind === 'NON_NULL' && t.ofType) { + return `${formatTypeRef(t.ofType)}!`; + } + return t.name ?? 'unknown'; +} + +export function getEditableFields(table: CleanTable): CleanField[] { + const pk = getPrimaryKeyInfo(table)[0]; + return getScalarFields(table).filter( + (f) => + f.name !== pk.name && + f.name !== 'nodeId' && + f.name !== 'createdAt' && + f.name !== 'updatedAt', + ); +} + +export function gqlTypeToJsonSchemaType(gqlType: string): string { + switch (gqlType) { + case 'Int': + return 'integer'; + case 'Float': + return 'number'; + case 'Boolean': + return 'boolean'; + default: + return 'string'; + } +} + +export function buildSkillFile(skill: SkillDefinition): string { + const lang = skill.language ?? 'bash'; + const lines: string[] = []; + + lines.push(`# ${skill.name}`); + lines.push(''); + lines.push('> @generated by @constructive-io/graphql-codegen - DO NOT EDIT'); + lines.push(''); + lines.push(skill.description); + lines.push(''); + lines.push('## Usage'); + lines.push(''); + lines.push(`\`\`\`${lang}`); + for (const u of skill.usage) { + lines.push(u); + } + lines.push('```'); + lines.push(''); + lines.push('## Examples'); + lines.push(''); + for (const ex of skill.examples) { + lines.push(`### ${ex.description}`); + lines.push(''); + lines.push(`\`\`\`${lang}`); + for (const cmd of ex.code) { + lines.push(cmd); + } + lines.push('```'); + lines.push(''); + } + + return lines.join('\n'); +} diff --git a/graphql/codegen/src/core/codegen/hooks-docs-generator.ts b/graphql/codegen/src/core/codegen/hooks-docs-generator.ts new file mode 100644 index 000000000..12e6ffd5a --- /dev/null +++ b/graphql/codegen/src/core/codegen/hooks-docs-generator.ts @@ -0,0 +1,595 @@ +import type { CleanOperation, CleanTable } from '../../types/schema'; +import { + buildSkillFile, + formatArgType, + gqlTypeToJsonSchemaType, +} from './docs-utils'; +import type { GeneratedDocFile, McpTool } from './docs-utils'; +import { + getTableNames, + getScalarFields, + getPrimaryKeyInfo, + getListQueryHookName, + getSingleQueryHookName, + getCreateMutationHookName, + getUpdateMutationHookName, + getDeleteMutationHookName, + hasValidPrimaryKey, + ucFirst, + lcFirst, + fieldTypeToTs, +} from './utils'; + +function getCustomHookName(op: CleanOperation): string { + if (op.kind === 'query') { + return `use${ucFirst(op.name)}Query`; + } + return `use${ucFirst(op.name)}Mutation`; +} + +export function generateHooksReadme( + tables: CleanTable[], + customOperations: CleanOperation[], +): GeneratedDocFile { + const lines: string[] = []; + + lines.push('# React Query Hooks'); + lines.push(''); + lines.push('> Auto-generated React Query hooks from GraphQL schema'); + lines.push('> @generated by @constructive-io/graphql-codegen - DO NOT EDIT'); + lines.push(''); + lines.push('## Setup'); + lines.push(''); + lines.push('```typescript'); + lines.push("import { QueryClient, QueryClientProvider } from '@tanstack/react-query';"); + lines.push("import { configure } from './hooks';"); + lines.push(''); + lines.push('configure({'); + lines.push(" endpoint: 'https://api.example.com/graphql',"); + lines.push(" headers: { Authorization: 'Bearer ' },"); + lines.push('});'); + lines.push(''); + lines.push('const queryClient = new QueryClient();'); + lines.push(''); + lines.push('function App() {'); + lines.push(' return ('); + lines.push(' '); + lines.push(' '); + lines.push(' '); + lines.push(' );'); + lines.push('}'); + lines.push('```'); + lines.push(''); + + lines.push('## Hooks'); + lines.push(''); + lines.push('| Hook | Type | Description |'); + lines.push('|------|------|-------------|'); + for (const table of tables) { + const { singularName, pluralName } = getTableNames(table); + lines.push( + `| \`${getListQueryHookName(table)}\` | Query | List all ${pluralName} |`, + ); + if (hasValidPrimaryKey(table)) { + lines.push( + `| \`${getSingleQueryHookName(table)}\` | Query | Get one ${singularName} |`, + ); + } + lines.push( + `| \`${getCreateMutationHookName(table)}\` | Mutation | Create a ${singularName} |`, + ); + if (hasValidPrimaryKey(table)) { + lines.push( + `| \`${getUpdateMutationHookName(table)}\` | Mutation | Update a ${singularName} |`, + ); + lines.push( + `| \`${getDeleteMutationHookName(table)}\` | Mutation | Delete a ${singularName} |`, + ); + } + } + for (const op of customOperations) { + lines.push( + `| \`${getCustomHookName(op)}\` | ${ucFirst(op.kind)} | ${op.description || op.name} |`, + ); + } + lines.push(''); + + if (tables.length > 0) { + lines.push('## Table Hooks'); + lines.push(''); + for (const table of tables) { + const { singularName, pluralName } = getTableNames(table); + const pk = getPrimaryKeyInfo(table)[0]; + const scalarFields = getScalarFields(table); + + lines.push(`### ${table.name}`); + lines.push(''); + + lines.push('```typescript'); + lines.push(`// List all ${pluralName}`); + lines.push( + `const { data, isLoading } = ${getListQueryHookName(table)}({`, + ); + lines.push( + ` selection: { fields: { ${scalarFields.map((f) => `${f.name}: true`).join(', ')} } },`, + ); + lines.push('});'); + lines.push(''); + + if (hasValidPrimaryKey(table)) { + lines.push(`// Get one ${singularName}`); + lines.push( + `const { data: item } = ${getSingleQueryHookName(table)}({`, + ); + lines.push(` ${pk.name}: '',`); + lines.push( + ` selection: { fields: { ${scalarFields.map((f) => `${f.name}: true`).join(', ')} } },`, + ); + lines.push('});'); + lines.push(''); + } + + lines.push(`// Create a ${singularName}`); + lines.push( + `const { mutate: create } = ${getCreateMutationHookName(table)}({`, + ); + lines.push( + ` selection: { fields: { ${pk.name}: true } },`, + ); + lines.push('});'); + lines.push( + `create({ ${scalarFields.filter((f) => f.name !== pk.name && f.name !== 'nodeId' && f.name !== 'createdAt' && f.name !== 'updatedAt').map((f) => `${f.name}: ''`).join(', ')} });`, + ); + lines.push('```'); + lines.push(''); + } + } + + if (customOperations.length > 0) { + lines.push('## Custom Operation Hooks'); + lines.push(''); + for (const op of customOperations) { + const hookName = getCustomHookName(op); + lines.push(`### \`${hookName}\``); + lines.push(''); + lines.push(op.description || op.name); + lines.push(''); + lines.push(`- **Type:** ${op.kind}`); + if (op.args.length > 0) { + lines.push('- **Arguments:**'); + lines.push(''); + lines.push(' | Argument | Type |'); + lines.push(' |----------|------|'); + for (const arg of op.args) { + lines.push(` | \`${arg.name}\` | ${formatArgType(arg)} |`); + } + } else { + lines.push('- **Arguments:** none'); + } + lines.push(''); + } + } + + return { + fileName: 'README.md', + content: lines.join('\n'), + }; +} + +export function generateHooksAgentsDocs( + tables: CleanTable[], + customOperations: CleanOperation[], +): GeneratedDocFile { + const lines: string[] = []; + + lines.push('# React Query Hooks - Agent Reference'); + lines.push(''); + lines.push('> @generated by @constructive-io/graphql-codegen - DO NOT EDIT'); + lines.push('> This document is structured for LLM/agent consumption.'); + lines.push(''); + + lines.push('## OVERVIEW'); + lines.push(''); + lines.push( + 'React Query hooks wrapping ORM operations for data fetching and mutations.', + ); + lines.push( + 'All query hooks return `UseQueryResult`. All mutation hooks return `UseMutationResult`.', + ); + lines.push(''); + + lines.push('## SETUP'); + lines.push(''); + lines.push('```typescript'); + lines.push("import { configure } from './hooks';"); + lines.push("import { QueryClient, QueryClientProvider } from '@tanstack/react-query';"); + lines.push(''); + lines.push("configure({ endpoint: 'https://api.example.com/graphql' });"); + lines.push('const queryClient = new QueryClient();'); + lines.push('// Wrap app in '); + lines.push('```'); + lines.push(''); + + lines.push('## HOOKS'); + lines.push(''); + + for (const table of tables) { + const { singularName, pluralName } = getTableNames(table); + const pk = getPrimaryKeyInfo(table)[0]; + const scalarFields = getScalarFields(table); + + lines.push(`### HOOK: ${getListQueryHookName(table)}`); + lines.push(''); + lines.push(`List all ${pluralName}.`); + lines.push(''); + lines.push('```'); + lines.push(`TYPE: query`); + lines.push( + `USAGE: ${getListQueryHookName(table)}({ selection: { fields: { ... } } })`, + ); + lines.push(''); + lines.push('INPUT:'); + lines.push( + ' selection: { fields: Record } - Fields to select', + ); + lines.push(''); + lines.push('OUTPUT: UseQueryResult>'); + lines.push('```'); + lines.push(''); + + if (hasValidPrimaryKey(table)) { + lines.push(`### HOOK: ${getSingleQueryHookName(table)}`); + lines.push(''); + lines.push(`Get a single ${singularName} by ${pk.name}.`); + lines.push(''); + lines.push('```'); + lines.push(`TYPE: query`); + lines.push( + `USAGE: ${getSingleQueryHookName(table)}({ ${pk.name}: '', selection: { fields: { ... } } })`, + ); + lines.push(''); + lines.push('INPUT:'); + lines.push(` ${pk.name}: ${pk.tsType} (required)`); + lines.push( + ' selection: { fields: Record } - Fields to select', + ); + lines.push(''); + lines.push('OUTPUT: UseQueryResult<{'); + for (const f of scalarFields) { + lines.push(` ${f.name}: ${fieldTypeToTs(f.type)}`); + } + lines.push('}>'); + lines.push('```'); + lines.push(''); + } + + lines.push(`### HOOK: ${getCreateMutationHookName(table)}`); + lines.push(''); + lines.push(`Create a new ${singularName}.`); + lines.push(''); + lines.push('```'); + lines.push('TYPE: mutation'); + lines.push( + `USAGE: const { mutate } = ${getCreateMutationHookName(table)}({ selection: { fields: { ... } } })`, + ); + lines.push(''); + lines.push('OUTPUT: UseMutationResult'); + lines.push('```'); + lines.push(''); + + if (hasValidPrimaryKey(table)) { + lines.push(`### HOOK: ${getUpdateMutationHookName(table)}`); + lines.push(''); + lines.push(`Update an existing ${singularName}.`); + lines.push(''); + lines.push('```'); + lines.push('TYPE: mutation'); + lines.push( + `USAGE: const { mutate } = ${getUpdateMutationHookName(table)}({ selection: { fields: { ... } } })`, + ); + lines.push(''); + lines.push('OUTPUT: UseMutationResult'); + lines.push('```'); + lines.push(''); + + lines.push(`### HOOK: ${getDeleteMutationHookName(table)}`); + lines.push(''); + lines.push(`Delete a ${singularName}.`); + lines.push(''); + lines.push('```'); + lines.push('TYPE: mutation'); + lines.push( + `USAGE: const { mutate } = ${getDeleteMutationHookName(table)}({})`, + ); + lines.push(''); + lines.push('OUTPUT: UseMutationResult'); + lines.push('```'); + lines.push(''); + } + } + + if (customOperations.length > 0) { + lines.push('## CUSTOM OPERATION HOOKS'); + lines.push(''); + + for (const op of customOperations) { + const hookName = getCustomHookName(op); + + lines.push(`### HOOK: ${hookName}`); + lines.push(''); + lines.push(op.description || op.name); + lines.push(''); + lines.push('```'); + lines.push(`TYPE: ${op.kind}`); + if (op.args.length > 0) { + if (op.kind === 'mutation') { + lines.push(`USAGE: const { mutate } = ${hookName}()`); + lines.push( + ` mutate({ ${op.args.map((a) => `${a.name}: `).join(', ')} })`, + ); + } else { + lines.push( + `USAGE: ${hookName}({ ${op.args.map((a) => `${a.name}: `).join(', ')} })`, + ); + } + lines.push(''); + lines.push('INPUT:'); + for (const arg of op.args) { + lines.push(` ${arg.name}: ${formatArgType(arg)}`); + } + } else { + lines.push(`USAGE: ${hookName}()`); + lines.push(''); + lines.push('INPUT: none'); + } + lines.push(''); + lines.push( + `OUTPUT: ${op.kind === 'query' ? 'UseQueryResult' : 'UseMutationResult'}`, + ); + lines.push('```'); + lines.push(''); + } + } + + return { + fileName: 'AGENTS.md', + content: lines.join('\n'), + }; +} + +export function getHooksMcpTools( + tables: CleanTable[], + customOperations: CleanOperation[], +): McpTool[] { + const tools: McpTool[] = []; + + for (const table of tables) { + const { singularName, pluralName } = getTableNames(table); + const pk = getPrimaryKeyInfo(table)[0]; + const scalarFields = getScalarFields(table); + + tools.push({ + name: `hooks_${lcFirst(pluralName)}_query`, + description: `React Query hook to list all ${pluralName}`, + inputSchema: { + type: 'object', + properties: { + fields: { + type: 'object', + description: `Fields to select: { ${scalarFields.map((f) => f.name).join(', ')} }`, + }, + }, + }, + }); + + if (hasValidPrimaryKey(table)) { + tools.push({ + name: `hooks_${lcFirst(singularName)}_query`, + description: `React Query hook to get a single ${singularName} by ${pk.name}`, + inputSchema: { + type: 'object', + properties: { + [pk.name]: { + type: gqlTypeToJsonSchemaType(pk.gqlType), + description: `${table.name} ${pk.name}`, + }, + }, + required: [pk.name], + }, + }); + } + + tools.push({ + name: `hooks_create_${lcFirst(singularName)}_mutation`, + description: `React Query mutation hook to create a ${singularName}`, + inputSchema: { + type: 'object', + properties: Object.fromEntries( + scalarFields + .filter( + (f) => + f.name !== pk.name && + f.name !== 'nodeId' && + f.name !== 'createdAt' && + f.name !== 'updatedAt', + ) + .map((f) => [ + f.name, + { + type: gqlTypeToJsonSchemaType(f.type.gqlType), + description: `${table.name} ${f.name}`, + }, + ]), + ), + }, + }); + + if (hasValidPrimaryKey(table)) { + tools.push({ + name: `hooks_update_${lcFirst(singularName)}_mutation`, + description: `React Query mutation hook to update a ${singularName}`, + inputSchema: { + type: 'object', + properties: { + [pk.name]: { + type: gqlTypeToJsonSchemaType(pk.gqlType), + description: `${table.name} ${pk.name}`, + }, + }, + required: [pk.name], + }, + }); + + tools.push({ + name: `hooks_delete_${lcFirst(singularName)}_mutation`, + description: `React Query mutation hook to delete a ${singularName}`, + inputSchema: { + type: 'object', + properties: { + [pk.name]: { + type: gqlTypeToJsonSchemaType(pk.gqlType), + description: `${table.name} ${pk.name}`, + }, + }, + required: [pk.name], + }, + }); + } + } + + for (const op of customOperations) { + const hookName = getCustomHookName(op); + const props: Record = {}; + const required: string[] = []; + + for (const arg of op.args) { + const isRequired = arg.type.kind === 'NON_NULL'; + const baseType = + isRequired && arg.type.ofType ? arg.type.ofType : arg.type; + props[arg.name] = { + type: gqlTypeToJsonSchemaType(baseType.name ?? 'String'), + description: arg.description || arg.name, + }; + if (isRequired) { + required.push(arg.name); + } + } + + tools.push({ + name: `hooks_${hookName}`, + description: op.description || `${ucFirst(op.kind)} hook for ${op.name}`, + inputSchema: { + type: 'object', + properties: props, + ...(required.length > 0 ? { required } : {}), + }, + }); + } + + return tools; +} + +export function generateHooksSkills( + tables: CleanTable[], + customOperations: CleanOperation[], +): GeneratedDocFile[] { + const files: GeneratedDocFile[] = []; + + for (const table of tables) { + const { singularName, pluralName } = getTableNames(table); + const pk = getPrimaryKeyInfo(table)[0]; + const scalarFields = getScalarFields(table); + const selectFields = scalarFields + .map((f) => `${f.name}: true`) + .join(', '); + + files.push({ + fileName: `skills/${lcFirst(singularName)}.md`, + content: buildSkillFile({ + name: `hooks-${lcFirst(singularName)}`, + description: `React Query hooks for ${table.name} data operations`, + language: 'typescript', + usage: [ + `${getListQueryHookName(table)}({ selection: { fields: { ${selectFields} } } })`, + ...(hasValidPrimaryKey(table) + ? [ + `${getSingleQueryHookName(table)}({ ${pk.name}: '', selection: { fields: { ${selectFields} } } })`, + ] + : []), + `${getCreateMutationHookName(table)}({ selection: { fields: { ${pk.name}: true } } })`, + ...(hasValidPrimaryKey(table) + ? [ + `${getUpdateMutationHookName(table)}({ selection: { fields: { ${pk.name}: true } } })`, + `${getDeleteMutationHookName(table)}({})`, + ] + : []), + ], + examples: [ + { + description: `List all ${pluralName}`, + code: [ + `const { data, isLoading } = ${getListQueryHookName(table)}({`, + ` selection: { fields: { ${selectFields} } },`, + '});', + ], + }, + { + description: `Create a ${singularName}`, + code: [ + `const { mutate } = ${getCreateMutationHookName(table)}({`, + ` selection: { fields: { ${pk.name}: true } },`, + '});', + `mutate({ ${scalarFields.filter((f) => f.name !== pk.name && f.name !== 'nodeId' && f.name !== 'createdAt' && f.name !== 'updatedAt').map((f) => `${f.name}: ''`).join(', ')} });`, + ], + }, + ], + }), + }); + } + + for (const op of customOperations) { + const hookName = getCustomHookName(op); + const callArgs = + op.args.length > 0 + ? `{ ${op.args.map((a) => `${a.name}: ''`).join(', ')} }` + : ''; + + files.push({ + fileName: `skills/${op.name}.md`, + content: buildSkillFile({ + name: `hooks-${op.name}`, + description: + op.description || + `React Query ${op.kind} hook for ${op.name}`, + language: 'typescript', + usage: [ + op.kind === 'mutation' + ? `const { mutate } = ${hookName}(); mutate(${callArgs});` + : `${hookName}(${callArgs})`, + ], + examples: [ + { + description: `Use ${hookName}`, + code: + op.kind === 'mutation' + ? [ + `const { mutate, isLoading } = ${hookName}();`, + ...(callArgs + ? [`mutate(${callArgs});`] + : ['mutate();']), + ] + : [ + `const { data, isLoading } = ${hookName}(${callArgs});`, + ], + }, + ], + }), + }); + } + + return files; +} diff --git a/graphql/codegen/src/core/codegen/orm/docs-generator.ts b/graphql/codegen/src/core/codegen/orm/docs-generator.ts new file mode 100644 index 000000000..1389d6160 --- /dev/null +++ b/graphql/codegen/src/core/codegen/orm/docs-generator.ts @@ -0,0 +1,525 @@ +import type { CleanOperation, CleanTable } from '../../../types/schema'; +import { + buildSkillFile, + formatArgType, + getEditableFields, + gqlTypeToJsonSchemaType, +} from '../docs-utils'; +import type { GeneratedDocFile, McpTool } from '../docs-utils'; +import { + getScalarFields, + getTableNames, + getPrimaryKeyInfo, + lcFirst, + fieldTypeToTs, +} from '../utils'; + +export function generateOrmReadme( + tables: CleanTable[], + customOperations: CleanOperation[], +): GeneratedDocFile { + const lines: string[] = []; + + lines.push('# ORM Client'); + lines.push(''); + lines.push('> Auto-generated ORM client from GraphQL schema'); + lines.push('> @generated by @constructive-io/graphql-codegen - DO NOT EDIT'); + lines.push(''); + lines.push('## Setup'); + lines.push(''); + lines.push('```typescript'); + lines.push("import { createClient } from './orm';"); + lines.push(''); + lines.push('const db = createClient({'); + lines.push(" endpoint: 'https://api.example.com/graphql',"); + lines.push(" headers: { Authorization: 'Bearer ' },"); + lines.push('});'); + lines.push('```'); + lines.push(''); + + lines.push('## Models'); + lines.push(''); + lines.push('| Model | Operations |'); + lines.push('|-------|------------|'); + for (const table of tables) { + const { singularName } = getTableNames(table); + lines.push( + `| \`${singularName}\` | findMany, findOne, create, update, delete |`, + ); + } + lines.push(''); + + if (tables.length > 0) { + lines.push('## Table Operations'); + lines.push(''); + for (const table of tables) { + const { singularName } = getTableNames(table); + const pk = getPrimaryKeyInfo(table)[0]; + const scalarFields = getScalarFields(table); + const editableFields = getEditableFields(table); + + lines.push(`### \`db.${singularName}\``); + lines.push(''); + lines.push(`CRUD operations for ${table.name} records.`); + lines.push(''); + lines.push('**Fields:**'); + lines.push(''); + lines.push('| Field | Type | Editable |'); + lines.push('|-------|------|----------|'); + for (const f of scalarFields) { + const editable = editableFields.some((ef) => ef.name === f.name); + lines.push( + `| \`${f.name}\` | ${f.type.gqlType} | ${editable ? 'Yes' : 'No'} |`, + ); + } + lines.push(''); + + lines.push('**Operations:**'); + lines.push(''); + lines.push('```typescript'); + lines.push(`// List all ${singularName} records`); + lines.push( + `const items = await db.${singularName}.findMany({ select: { ${scalarFields.map((f) => `${f.name}: true`).join(', ')} } }).execute();`, + ); + lines.push(''); + lines.push(`// Get one by ${pk.name}`); + lines.push( + `const item = await db.${singularName}.findOne({ where: { ${pk.name}: '' }, select: { ${scalarFields.map((f) => `${f.name}: true`).join(', ')} } }).execute();`, + ); + lines.push(''); + lines.push(`// Create`); + lines.push( + `const created = await db.${singularName}.create({ data: { ${editableFields.map((f) => `${f.name}: ''`).join(', ')} }, select: { ${pk.name}: true } }).execute();`, + ); + lines.push(''); + lines.push(`// Update`); + lines.push( + `const updated = await db.${singularName}.update({ where: { ${pk.name}: '' }, data: { ${editableFields[0]?.name || 'field'}: '' }, select: { ${pk.name}: true } }).execute();`, + ); + lines.push(''); + lines.push(`// Delete`); + lines.push( + `const deleted = await db.${singularName}.delete({ where: { ${pk.name}: '' } }).execute();`, + ); + lines.push('```'); + lines.push(''); + } + } + + if (customOperations.length > 0) { + lines.push('## Custom Operations'); + lines.push(''); + for (const op of customOperations) { + const accessor = op.kind === 'query' ? 'query' : 'mutation'; + lines.push(`### \`db.${accessor}.${op.name}\``); + lines.push(''); + lines.push(op.description || op.name); + lines.push(''); + lines.push(`- **Type:** ${op.kind}`); + if (op.args.length > 0) { + lines.push('- **Arguments:**'); + lines.push(''); + lines.push(' | Argument | Type |'); + lines.push(' |----------|------|'); + for (const arg of op.args) { + lines.push(` | \`${arg.name}\` | ${formatArgType(arg)} |`); + } + lines.push(''); + lines.push('```typescript'); + lines.push( + `const result = await db.${accessor}.${op.name}({ ${op.args.map((a) => `${a.name}: ''`).join(', ')} }).execute();`, + ); + lines.push('```'); + } else { + lines.push('- **Arguments:** none'); + lines.push(''); + lines.push('```typescript'); + lines.push( + `const result = await db.${accessor}.${op.name}().execute();`, + ); + lines.push('```'); + } + lines.push(''); + } + } + + return { + fileName: 'README.md', + content: lines.join('\n'), + }; +} + +export function generateOrmAgentsDocs( + tables: CleanTable[], + customOperations: CleanOperation[], +): GeneratedDocFile { + const lines: string[] = []; + + lines.push('# ORM Client - Agent Reference'); + lines.push(''); + lines.push('> @generated by @constructive-io/graphql-codegen - DO NOT EDIT'); + lines.push('> This document is structured for LLM/agent consumption.'); + lines.push(''); + + lines.push('## OVERVIEW'); + lines.push(''); + lines.push( + 'Prisma-like ORM client for interacting with a GraphQL API.', + ); + lines.push( + 'All methods return a query builder. Call `.execute()` to run the query.', + ); + lines.push(''); + + lines.push('## SETUP'); + lines.push(''); + lines.push('```typescript'); + lines.push("import { createClient } from './orm';"); + lines.push(''); + lines.push('const db = createClient({'); + lines.push(" endpoint: 'https://api.example.com/graphql',"); + lines.push(" headers: { Authorization: 'Bearer ' },"); + lines.push('});'); + lines.push('```'); + lines.push(''); + + lines.push('## MODELS'); + lines.push(''); + + for (const table of tables) { + const { singularName } = getTableNames(table); + const pk = getPrimaryKeyInfo(table)[0]; + const scalarFields = getScalarFields(table); + const editableFields = getEditableFields(table); + + lines.push(`### MODEL: ${singularName}`); + lines.push(''); + lines.push(`Access: \`db.${singularName}\``); + lines.push(''); + lines.push('```'); + lines.push('METHODS:'); + lines.push( + ` db.${singularName}.findMany({ select, where?, orderBy?, first?, offset? })`, + ); + lines.push( + ` db.${singularName}.findOne({ where: { ${pk.name} }, select })`, + ); + lines.push( + ` db.${singularName}.create({ data: { ${editableFields.map((f) => f.name).join(', ')} }, select })`, + ); + lines.push( + ` db.${singularName}.update({ where: { ${pk.name} }, data, select })`, + ); + lines.push(` db.${singularName}.delete({ where: { ${pk.name} } })`); + lines.push(''); + lines.push('FIELDS:'); + for (const f of scalarFields) { + const isPk = f.name === pk.name; + lines.push( + ` ${f.name}: ${fieldTypeToTs(f.type)}${isPk ? ' (primary key)' : ''}`, + ); + } + lines.push(''); + lines.push('EDITABLE FIELDS:'); + for (const f of editableFields) { + lines.push(` ${f.name}: ${fieldTypeToTs(f.type)}`); + } + lines.push(''); + lines.push('OUTPUT: Promise'); + lines.push( + ` findMany: [{ ${scalarFields.map((f) => f.name).join(', ')} }]`, + ); + lines.push( + ` findOne: { ${scalarFields.map((f) => f.name).join(', ')} }`, + ); + lines.push( + ` create: { ${scalarFields.map((f) => f.name).join(', ')} }`, + ); + lines.push( + ` update: { ${scalarFields.map((f) => f.name).join(', ')} }`, + ); + lines.push(` delete: { ${pk.name} }`); + lines.push('```'); + lines.push(''); + } + + if (customOperations.length > 0) { + lines.push('## CUSTOM OPERATIONS'); + lines.push(''); + + for (const op of customOperations) { + const accessor = op.kind === 'query' ? 'query' : 'mutation'; + + lines.push(`### OPERATION: ${op.name}`); + lines.push(''); + lines.push(op.description || op.name); + lines.push(''); + lines.push('```'); + lines.push(`TYPE: ${op.kind}`); + lines.push(`ACCESS: db.${accessor}.${op.name}`); + if (op.args.length > 0) { + lines.push( + `USAGE: db.${accessor}.${op.name}({ ${op.args.map((a) => `${a.name}: `).join(', ')} }).execute()`, + ); + lines.push(''); + lines.push('INPUT:'); + for (const arg of op.args) { + lines.push(` ${arg.name}: ${formatArgType(arg)}`); + } + } else { + lines.push( + `USAGE: db.${accessor}.${op.name}().execute()`, + ); + lines.push(''); + lines.push('INPUT: none'); + } + lines.push(''); + lines.push('OUTPUT: Promise'); + lines.push('```'); + lines.push(''); + } + } + + lines.push('## PATTERNS'); + lines.push(''); + lines.push('```typescript'); + lines.push('// All methods require .execute() to run'); + lines.push( + 'const result = await db.modelName.findMany({ select: { id: true } }).execute();', + ); + lines.push(''); + lines.push('// Select specific fields'); + lines.push( + 'const partial = await db.modelName.findMany({ select: { id: true, name: true } }).execute();', + ); + lines.push(''); + lines.push('// Filter with where clause'); + lines.push( + "const filtered = await db.modelName.findMany({ select: { id: true }, where: { name: 'test' } }).execute();", + ); + lines.push('```'); + lines.push(''); + + return { + fileName: 'AGENTS.md', + content: lines.join('\n'), + }; +} + +export function getOrmMcpTools( + tables: CleanTable[], + customOperations: CleanOperation[], +): McpTool[] { + const tools: McpTool[] = []; + + for (const table of tables) { + const { singularName } = getTableNames(table); + const pk = getPrimaryKeyInfo(table)[0]; + const scalarFields = getScalarFields(table); + const editableFields = getEditableFields(table); + + tools.push({ + name: `orm_${lcFirst(singularName)}_findMany`, + description: `List all ${table.name} records via ORM`, + inputSchema: { + type: 'object', + properties: { + first: { + type: 'integer', + description: 'Limit number of results', + }, + offset: { + type: 'integer', + description: 'Offset for pagination', + }, + }, + }, + }); + + tools.push({ + name: `orm_${lcFirst(singularName)}_findOne`, + description: `Get a single ${table.name} record by ${pk.name}`, + inputSchema: { + type: 'object', + properties: { + [pk.name]: { + type: gqlTypeToJsonSchemaType(pk.gqlType), + description: `${table.name} ${pk.name}`, + }, + }, + required: [pk.name], + }, + }); + + const createProps: Record = {}; + for (const f of editableFields) { + createProps[f.name] = { + type: gqlTypeToJsonSchemaType(f.type.gqlType), + description: `${table.name} ${f.name}`, + }; + } + tools.push({ + name: `orm_${lcFirst(singularName)}_create`, + description: `Create a new ${table.name} record`, + inputSchema: { + type: 'object', + properties: createProps, + required: editableFields.map((f) => f.name), + }, + }); + + const updateProps: Record = { + [pk.name]: { + type: gqlTypeToJsonSchemaType(pk.gqlType), + description: `${table.name} ${pk.name}`, + }, + }; + for (const f of editableFields) { + updateProps[f.name] = { + type: gqlTypeToJsonSchemaType(f.type.gqlType), + description: `${table.name} ${f.name}`, + }; + } + tools.push({ + name: `orm_${lcFirst(singularName)}_update`, + description: `Update an existing ${table.name} record`, + inputSchema: { + type: 'object', + properties: updateProps, + required: [pk.name], + }, + }); + + tools.push({ + name: `orm_${lcFirst(singularName)}_delete`, + description: `Delete a ${table.name} record by ${pk.name}`, + inputSchema: { + type: 'object', + properties: { + [pk.name]: { + type: gqlTypeToJsonSchemaType(pk.gqlType), + description: `${table.name} ${pk.name}`, + }, + }, + required: [pk.name], + }, + _meta: { + fields: scalarFields.map((f) => ({ + name: f.name, + type: f.type.gqlType, + editable: editableFields.some((ef) => ef.name === f.name), + primaryKey: f.name === pk.name, + })), + }, + }); + } + + for (const op of customOperations) { + const accessor = op.kind === 'query' ? 'query' : 'mutation'; + const props: Record = {}; + const required: string[] = []; + + for (const arg of op.args) { + const isRequired = arg.type.kind === 'NON_NULL'; + const baseType = + isRequired && arg.type.ofType ? arg.type.ofType : arg.type; + props[arg.name] = { + type: gqlTypeToJsonSchemaType(baseType.name ?? 'String'), + description: arg.description || arg.name, + }; + if (isRequired) { + required.push(arg.name); + } + } + + tools.push({ + name: `orm_${accessor}_${op.name}`, + description: op.description || `Execute ${op.name} ${op.kind}`, + inputSchema: { + type: 'object', + properties: props, + ...(required.length > 0 ? { required } : {}), + }, + }); + } + + return tools; +} + +export function generateOrmSkills( + tables: CleanTable[], + customOperations: CleanOperation[], +): GeneratedDocFile[] { + const files: GeneratedDocFile[] = []; + + for (const table of tables) { + const { singularName } = getTableNames(table); + const pk = getPrimaryKeyInfo(table)[0]; + const editableFields = getEditableFields(table); + + files.push({ + fileName: `skills/${lcFirst(singularName)}.md`, + content: buildSkillFile({ + name: `orm-${lcFirst(singularName)}`, + description: `ORM operations for ${table.name} records`, + language: 'typescript', + usage: [ + `db.${lcFirst(singularName)}.findMany({ select: { id: true } }).execute()`, + `db.${lcFirst(singularName)}.findOne({ where: { ${pk.name}: '' }, select: { id: true } }).execute()`, + `db.${lcFirst(singularName)}.create({ data: { ${editableFields.map((f) => `${f.name}: ''`).join(', ')} }, select: { id: true } }).execute()`, + `db.${lcFirst(singularName)}.update({ where: { ${pk.name}: '' }, data: { ${editableFields[0]?.name || 'field'}: '' }, select: { id: true } }).execute()`, + `db.${lcFirst(singularName)}.delete({ where: { ${pk.name}: '' } }).execute()`, + ], + examples: [ + { + description: `List all ${singularName} records`, + code: [ + `const items = await db.${lcFirst(singularName)}.findMany({`, + ` select: { ${pk.name}: true, ${editableFields[0]?.name || 'name'}: true }`, + '}).execute();', + ], + }, + { + description: `Create a ${singularName}`, + code: [ + `const item = await db.${lcFirst(singularName)}.create({`, + ` data: { ${editableFields.map((f) => `${f.name}: 'value'`).join(', ')} },`, + ` select: { ${pk.name}: true }`, + '}).execute();', + ], + }, + ], + }), + }); + } + + for (const op of customOperations) { + const accessor = op.kind === 'query' ? 'query' : 'mutation'; + const callArgs = + op.args.length > 0 + ? `{ ${op.args.map((a) => `${a.name}: ''`).join(', ')} }` + : ''; + + files.push({ + fileName: `skills/${op.name}.md`, + content: buildSkillFile({ + name: `orm-${op.name}`, + description: op.description || `Execute the ${op.name} ${op.kind}`, + language: 'typescript', + usage: [ + `db.${accessor}.${op.name}(${callArgs}).execute()`, + ], + examples: [ + { + description: `Run ${op.name}`, + code: [ + `const result = await db.${accessor}.${op.name}(${callArgs}).execute();`, + ], + }, + ], + }), + }); + } + + return files; +} diff --git a/graphql/codegen/src/core/codegen/target-docs-generator.ts b/graphql/codegen/src/core/codegen/target-docs-generator.ts new file mode 100644 index 000000000..ab8b5d851 --- /dev/null +++ b/graphql/codegen/src/core/codegen/target-docs-generator.ts @@ -0,0 +1,170 @@ +import type { GraphQLSDKConfigTarget } from '../../types/config'; +import type { GeneratedDocFile, McpTool } from './docs-utils'; + +export interface TargetReadmeOptions { + hasOrm: boolean; + hasHooks: boolean; + hasCli: boolean; + tableCount: number; + customQueryCount: number; + customMutationCount: number; + config: GraphQLSDKConfigTarget; +} + +export function generateTargetReadme( + options: TargetReadmeOptions, +): GeneratedDocFile { + const { + hasOrm, + hasHooks, + hasCli, + tableCount, + customQueryCount, + customMutationCount, + config, + } = options; + const lines: string[] = []; + + lines.push('# Generated GraphQL SDK'); + lines.push(''); + lines.push('> @generated by @constructive-io/graphql-codegen - DO NOT EDIT'); + lines.push(''); + + lines.push('## Overview'); + lines.push(''); + lines.push(`- **Tables:** ${tableCount}`); + lines.push(`- **Custom queries:** ${customQueryCount}`); + lines.push(`- **Custom mutations:** ${customMutationCount}`); + lines.push(''); + + const generators: string[] = []; + if (hasOrm) generators.push('ORM'); + if (hasHooks) generators.push('React Query'); + if (hasCli) generators.push('CLI'); + lines.push(`**Generators:** ${generators.join(', ')}`); + lines.push(''); + + if (config.endpoint) { + lines.push(`**Endpoint:** \`${config.endpoint}\``); + lines.push(''); + } + + lines.push('## Modules'); + lines.push(''); + + if (hasOrm) { + lines.push('### ORM Client (`./orm`)'); + lines.push(''); + lines.push( + 'Prisma-like ORM client for programmatic GraphQL access.', + ); + lines.push(''); + lines.push('```typescript'); + lines.push("import { createClient } from './orm';"); + lines.push(''); + lines.push('const db = createClient({'); + lines.push(" endpoint: 'https://api.example.com/graphql',"); + lines.push('});'); + lines.push('```'); + lines.push(''); + lines.push( + 'See [orm/README.md](./orm/README.md) for full API reference.', + ); + lines.push(''); + } + + if (hasHooks) { + lines.push('### React Query Hooks (`./hooks`)'); + lines.push(''); + lines.push( + 'Type-safe React Query hooks for data fetching and mutations.', + ); + lines.push(''); + lines.push('```typescript'); + lines.push("import { configure } from './hooks';"); + lines.push("import { useCarsQuery } from './hooks';"); + lines.push(''); + lines.push("configure({ endpoint: 'https://api.example.com/graphql' });"); + lines.push('```'); + lines.push(''); + lines.push( + 'See [hooks/README.md](./hooks/README.md) for full hook reference.', + ); + lines.push(''); + } + + if (hasCli) { + const toolName = + typeof config.cli === 'object' && config.cli?.toolName + ? config.cli.toolName + : 'app'; + lines.push(`### CLI Commands (\`./cli\`)`); + lines.push(''); + lines.push( + `inquirerer-based CLI commands for \`${toolName}\`.`, + ); + lines.push(''); + lines.push( + 'See [cli/README.md](./cli/README.md) for command reference.', + ); + lines.push(''); + } + + return { + fileName: 'README.md', + content: lines.join('\n'), + }; +} + +export function generateCombinedMcpConfig( + tools: McpTool[], + name: string, +): GeneratedDocFile { + const mcpConfig = { + name, + version: '1.0.0', + description: `MCP tool definitions for ${name} SDK (auto-generated from GraphQL schema)`, + tools, + }; + + return { + fileName: 'mcp.json', + content: JSON.stringify(mcpConfig, null, 2) + '\n', + }; +} + +export interface RootRootReadmeTarget { + name: string; + output: string; + endpoint?: string; + generators: string[]; +} + +export function generateRootRootReadme( + targets: RootRootReadmeTarget[], +): GeneratedDocFile { + const lines: string[] = []; + + lines.push('# GraphQL SDK'); + lines.push(''); + lines.push('> @generated by @constructive-io/graphql-codegen - DO NOT EDIT'); + lines.push(''); + + lines.push('## APIs'); + lines.push(''); + lines.push('| API | Endpoint | Generators | Docs |'); + lines.push('|-----|----------|------------|------|'); + for (const target of targets) { + const endpoint = target.endpoint || '-'; + const gens = target.generators.join(', '); + lines.push( + `| ${target.name} | ${endpoint} | ${gens} | [${target.output}/README.md](${target.output}/README.md) |`, + ); + } + lines.push(''); + + return { + fileName: 'README.md', + content: lines.join('\n'), + }; +} diff --git a/graphql/codegen/src/core/generate.ts b/graphql/codegen/src/core/generate.ts index 4a43c68e1..3632dea72 100644 --- a/graphql/codegen/src/core/generate.ts +++ b/graphql/codegen/src/core/generate.ts @@ -8,11 +8,38 @@ import path from 'node:path'; import type { GraphQLSDKConfigTarget } from '../types/config'; import { getConfigOptions } from '../types/config'; +import type { CleanOperation } from '../types/schema'; import { generate as generateReactQueryFiles } from './codegen'; import { generateRootBarrel } from './codegen/barrel'; import { generateCli as generateCliFiles } from './codegen/cli'; +import { + generateReadme as generateCliReadme, + generateAgentsDocs as generateCliAgentsDocs, + getCliMcpTools, + generateSkills as generateCliSkills, +} from './codegen/cli/docs-generator'; +import { resolveDocsConfig } from './codegen/docs-utils'; +import type { McpTool } from './codegen/docs-utils'; +import { + generateHooksReadme, + generateHooksAgentsDocs, + getHooksMcpTools, + generateHooksSkills, +} from './codegen/hooks-docs-generator'; import { generateOrm as generateOrmFiles } from './codegen/orm'; +import { + generateOrmReadme, + generateOrmAgentsDocs, + getOrmMcpTools, + generateOrmSkills, +} from './codegen/orm/docs-generator'; import { generateSharedTypes } from './codegen/shared'; +import { + generateTargetReadme, + generateCombinedMcpConfig, + generateRootRootReadme, +} from './codegen/target-docs-generator'; +import type { RootRootReadmeTarget } from './codegen/target-docs-generator'; import { createSchemaSource, validateSourceOptions } from './introspect'; import { writeGeneratedFiles } from './output'; import { runCodegenPipeline, validateTablesFound } from './pipeline'; @@ -196,7 +223,6 @@ export async function generate( } // Generate barrel file at output root - // This re-exports from the appropriate subdirectories based on which generators are enabled const barrelContent = generateRootBarrel({ hasTypes: bothEnabled, hasHooks: runReactQuery, @@ -205,6 +231,99 @@ export async function generate( }); filesToWrite.push({ path: 'index.ts', content: barrelContent }); + // Generate docs for each enabled generator + const docsConfig = resolveDocsConfig(config.docs); + const allCustomOps: CleanOperation[] = [ + ...(customOperations.queries ?? []), + ...(customOperations.mutations ?? []), + ]; + const allMcpTools: McpTool[] = []; + + if (runOrm) { + if (docsConfig.readme) { + const readme = generateOrmReadme(tables, allCustomOps); + filesToWrite.push({ path: path.posix.join('orm', readme.fileName), content: readme.content }); + } + if (docsConfig.agents) { + const agents = generateOrmAgentsDocs(tables, allCustomOps); + filesToWrite.push({ path: path.posix.join('orm', agents.fileName), content: agents.content }); + } + if (docsConfig.mcp) { + allMcpTools.push(...getOrmMcpTools(tables, allCustomOps)); + } + if (docsConfig.skills) { + for (const skill of generateOrmSkills(tables, allCustomOps)) { + filesToWrite.push({ path: path.posix.join('orm', skill.fileName), content: skill.content }); + } + } + } + + if (runReactQuery) { + if (docsConfig.readme) { + const readme = generateHooksReadme(tables, allCustomOps); + filesToWrite.push({ path: path.posix.join('hooks', readme.fileName), content: readme.content }); + } + if (docsConfig.agents) { + const agents = generateHooksAgentsDocs(tables, allCustomOps); + filesToWrite.push({ path: path.posix.join('hooks', agents.fileName), content: agents.content }); + } + if (docsConfig.mcp) { + allMcpTools.push(...getHooksMcpTools(tables, allCustomOps)); + } + if (docsConfig.skills) { + for (const skill of generateHooksSkills(tables, allCustomOps)) { + filesToWrite.push({ path: path.posix.join('hooks', skill.fileName), content: skill.content }); + } + } + } + + if (runCli) { + const toolName = + typeof config.cli === 'object' && config.cli?.toolName + ? config.cli.toolName + : 'app'; + if (docsConfig.readme) { + const readme = generateCliReadme(tables, allCustomOps, toolName); + filesToWrite.push({ path: path.posix.join('cli', readme.fileName), content: readme.content }); + } + if (docsConfig.agents) { + const agents = generateCliAgentsDocs(tables, allCustomOps, toolName); + filesToWrite.push({ path: path.posix.join('cli', agents.fileName), content: agents.content }); + } + if (docsConfig.mcp) { + allMcpTools.push(...getCliMcpTools(tables, allCustomOps, toolName)); + } + if (docsConfig.skills) { + for (const skill of generateCliSkills(tables, allCustomOps, toolName)) { + filesToWrite.push({ path: path.posix.join('cli', skill.fileName), content: skill.content }); + } + } + } + + // Generate combined mcp.json at output root + if (docsConfig.mcp && allMcpTools.length > 0) { + const mcpName = + typeof config.cli === 'object' && config.cli?.toolName + ? config.cli.toolName + : 'graphql-sdk'; + const mcpFile = generateCombinedMcpConfig(allMcpTools, mcpName); + filesToWrite.push({ path: mcpFile.fileName, content: mcpFile.content }); + } + + // Generate per-target README at output root + if (docsConfig.readme) { + const targetReadme = generateTargetReadme({ + hasOrm: runOrm, + hasHooks: runReactQuery, + hasCli: runCli, + tableCount: tables.length, + customQueryCount: customOperations.queries.length, + customMutationCount: customOperations.mutations.length, + config, + }); + filesToWrite.push({ path: targetReadme.fileName, content: targetReadme.content }); + } + if (!options.dryRun) { const writeResult = await writeGeneratedFiles(filesToWrite, outputRoot, [], { pruneStaleFiles: true, @@ -238,3 +357,64 @@ export async function generate( filesWritten: allFilesWritten, }; } + +export interface GenerateMultiOptions { + configs: Record; + cliOverrides?: Partial; + verbose?: boolean; + dryRun?: boolean; +} + +export interface GenerateMultiResult { + results: Array<{ name: string; result: GenerateResult }>; + hasError: boolean; +} + +export async function generateMulti( + options: GenerateMultiOptions, +): Promise { + const { configs, cliOverrides, verbose, dryRun } = options; + const names = Object.keys(configs); + const results: Array<{ name: string; result: GenerateResult }> = []; + let hasError = false; + + const targetInfos: RootRootReadmeTarget[] = []; + + for (const name of names) { + const targetConfig = { + ...configs[name], + ...(cliOverrides ?? {}), + }; + const result = await generate({ ...targetConfig, verbose, dryRun }); + results.push({ name, result }); + if (!result.success) { + hasError = true; + } else { + const resolvedConfig = getConfigOptions(targetConfig); + const gens: string[] = []; + if (resolvedConfig.reactQuery) gens.push('React Query'); + if (resolvedConfig.orm || resolvedConfig.reactQuery || !!resolvedConfig.cli) gens.push('ORM'); + if (resolvedConfig.cli) gens.push('CLI'); + targetInfos.push({ + name, + output: resolvedConfig.output, + endpoint: resolvedConfig.endpoint || undefined, + generators: gens, + }); + } + } + + // Generate root-root README if multi-target + if (names.length > 1 && targetInfos.length > 0 && !dryRun) { + const rootReadme = generateRootRootReadme(targetInfos); + const { writeGeneratedFiles: writeFiles } = await import('./output'); + await writeFiles( + [{ path: rootReadme.fileName, content: rootReadme.content }], + '.', + [], + { pruneStaleFiles: false }, + ); + } + + return { results, hasError }; +} diff --git a/graphql/codegen/src/types/config.ts b/graphql/codegen/src/types/config.ts index 602846f59..de38149e7 100644 --- a/graphql/codegen/src/types/config.ts +++ b/graphql/codegen/src/types/config.ts @@ -137,8 +137,9 @@ export interface DbConfig { } /** - * Documentation generation options for CLI - * Controls which doc formats are generated alongside CLI commands + * Documentation generation options + * Controls which doc formats are generated alongside code for each generator target. + * Applied at the top level and affects all enabled generators (ORM, React Query, CLI). */ export interface DocsConfig { /** @@ -182,13 +183,6 @@ export interface CliConfig { */ toolName?: string; - /** - * Documentation generation options - * Controls which doc formats are generated alongside CLI commands - * Set to `true` to enable all formats, or configure individually - * @default { readme: true, agents: true, mcp: false, skills: false } - */ - docs?: DocsConfig | boolean; } /** @@ -321,6 +315,15 @@ export interface GraphQLSDKConfigTarget { */ cli?: CliConfig | boolean; + /** + * Documentation generation options + * Controls which doc formats are generated alongside code for each generator target. + * Applied globally to all enabled generators (ORM, React Query, CLI). + * Set to `true` to enable all formats, or configure individually. + * @default { readme: true, agents: true, mcp: false, skills: false } + */ + docs?: DocsConfig | boolean; + /** * Query key generation configuration * Controls how query keys are structured for cache management From 0b1500404867136d7375b832a6c051ffc9aac85a Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Tue, 17 Feb 2026 20:59:38 +0000 Subject: [PATCH 06/23] feat(codegen): add unified multi-target CLI architecture - Add InfraNames config to CliConfig for collision detection - Add multi-target executor generator with baked endpoints and target routing - Add target-prefixed table/custom command generators - Add multi-target command map generator with target:command namespacing - Add multi-target context command with per-target endpoint prompts - Add generateAuthCommandWithName for custom auth command naming - Add resolveInfraNames() for automatic collision detection (auth->credentials, context->env) - Add generateMultiTargetCli() orchestrator - Wire into generateMulti() with unifiedCli option - Add --save-token flag on auth target custom operations - Add snapshot tests for multi-target CLI (8 new snapshots) - Add unit tests for resolveInfraNames collision detection --- .../__snapshots__/cli-generator.test.ts.snap | 1037 +++++++++++++++++ .../__tests__/codegen/cli-generator.test.ts | 252 +++- .../core/codegen/cli/command-map-generator.ts | 341 ++++++ .../codegen/cli/custom-command-generator.ts | 97 +- .../core/codegen/cli/executor-generator.ts | 284 +++++ graphql/codegen/src/core/codegen/cli/index.ts | 149 ++- .../src/core/codegen/cli/infra-generator.ts | 746 ++++++++++++ .../codegen/cli/table-command-generator.ts | 43 +- graphql/codegen/src/core/generate.ts | 71 +- graphql/codegen/src/types/config.ts | 16 + 10 files changed, 3001 insertions(+), 35 deletions(-) diff --git a/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap b/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap index 1456442a7..0ade6cb03 100644 --- a/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap +++ b/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap @@ -1836,6 +1836,1043 @@ mutate({ email: '', password: '' }); " `; +exports[`multi-target cli generator generates credentials command (renamed from auth) 1`] = ` +"/** + * Authentication commands + * @generated by @constructive-io/graphql-codegen + * DO NOT EDIT - changes will be overwritten + */ +import { CLIOptions, Inquirerer, extractFirst } from "inquirerer"; +import { getStore } from "../executor"; +const usage = "\\nmyapp credentials \\n\\nCommands:\\n set-token Set API token for the current context\\n status Show authentication status\\n logout Remove credentials for the current context\\n\\nOptions:\\n --context Specify context (defaults to current context)\\n\\n --help, -h Show this help message\\n"; +export default async (argv: Partial>, prompter: Inquirerer, _options: CLIOptions) => { + if (argv.help || argv.h) { + console.log(usage); + process.exit(0); + } + const store = getStore(); + const { + first: subcommand, + newArgv + } = extractFirst(argv); + if (!subcommand) { + const answer = await prompter.prompt(argv, [{ + type: "autocomplete", + name: "subcommand", + message: "What do you want to do?", + options: ["set-token", "status", "logout"] + }]); + return handleAuthSubcommand(answer.subcommand, newArgv, prompter, store); + } + return handleAuthSubcommand(subcommand, newArgv, prompter, store); +}; +async function handleAuthSubcommand(subcommand: string, argv: Partial>, prompter: Inquirerer, store: ReturnType) { + switch (subcommand) { + case "set-token": + return handleSetToken(argv, prompter, store); + case "status": + return handleStatus(store); + case "logout": + return handleLogout(argv, prompter, store); + default: + console.log(usage); + process.exit(1); + } +} +async function handleSetToken(argv: Partial>, prompter: Inquirerer, store: ReturnType) { + const current = store.getCurrentContext(); + if (!current) { + console.error("No active context. Run \\"context create\\" first."); + process.exit(1); + } + const { + first: token + } = extractFirst(argv); + let tokenValue = token; + if (!tokenValue) { + const answer = await prompter.prompt(argv, [{ + type: "password", + name: "token", + message: "API Token", + required: true + }]); + tokenValue = answer.token; + } + store.setCredentials(current.name, { + token: String.call(tokenValue || "").trim() + }); + console.log(\`Token saved for context: \${current.name}\`); +} +function handleStatus(store: ReturnType) { + const contexts = store.listContexts(); + const settings = store.loadSettings(); + if (contexts.length === 0) { + console.log("No contexts configured."); + return; + } + console.log("Authentication Status:"); + for (const ctx of contexts) { + const isCurrent = ctx.name === settings.currentContext; + const hasAuth = store.hasValidCredentials(ctx.name); + const marker = isCurrent ? "* " : " "; + const status = hasAuth ? "authenticated" : "no token"; + console.log(\`\${marker}\${ctx.name} [\${status}]\`); + } +} +async function handleLogout(argv: Partial>, prompter: Inquirerer, store: ReturnType) { + const current = store.getCurrentContext(); + if (!current) { + console.log("No active context."); + return; + } + const confirm = await prompter.prompt(argv, [{ + type: "confirm", + name: "confirm", + message: \`Remove credentials for "\${current.name}"?\`, + default: false + }]); + if (!confirm.confirm) { + return; + } + if (store.removeCredentials(current.name)) { + console.log(\`Credentials removed for: \${current.name}\`); + } else { + console.log(\`No credentials found for: \${current.name}\`); + } +}" +`; + +exports[`multi-target cli generator generates multi-target command map 1`] = ` +"/** + * Multi-target CLI command map and entry point + * @generated by @constructive-io/graphql-codegen + * DO NOT EDIT - changes will be overwritten + */ +import { CLIOptions, Inquirerer, extractFirst } from "inquirerer"; +import contextCmd from "./commands/context"; +import credentialsCmd from "./commands/credentials"; +import authUserCmd from "./commands/auth/user"; +import authCurrentUserCmd from "./commands/auth/current-user"; +import authLoginCmd from "./commands/auth/login"; +import membersMemberCmd from "./commands/members/member"; +import appCarCmd from "./commands/app/car"; +const createCommandMap = () => ({ + "context": contextCmd, + "credentials": credentialsCmd, + "auth:user": authUserCmd, + "auth:current-user": authCurrentUserCmd, + "auth:login": authLoginCmd, + "members:member": membersMemberCmd, + "app:car": appCarCmd +}); +const usage = "\\nmyapp \\n\\nCommands:\\n context Manage API contexts\\n credentials Manage authentication\\n\\n auth:\\n auth:user user CRUD operations\\n auth:current-user Get the currently authenticated user\\n auth:login Authenticate a user\\n\\n members:\\n members:member member CRUD operations\\n\\n app:\\n app:car car CRUD operations\\n\\n --help, -h Show this help message\\n --version, -v Show version\\n"; +export const commands = async (argv: Partial>, prompter: Inquirerer, options: CLIOptions) => { + if (argv.help || argv.h) { + console.log(usage); + process.exit(0); + } + let { + first: command, + newArgv + } = extractFirst(argv); + const commandMap = createCommandMap(); + if (!command) { + const answer = await prompter.prompt(argv, [{ + type: "autocomplete", + name: "command", + message: "What do you want to do?", + options: Object.keys(commandMap) + }]); + command = answer.command; + } + const commandFn = commandMap[command]; + if (!commandFn) { + console.log(usage); + console.error(\`Unknown command: \${command}\`); + process.exit(1); + } + await commandFn(newArgv, prompter, options); + prompter.close(); + return argv; +};" +`; + +exports[`multi-target cli generator generates multi-target context command 1`] = ` +"/** + * Multi-target context management commands + * @generated by @constructive-io/graphql-codegen + * DO NOT EDIT - changes will be overwritten + */ +import { CLIOptions, Inquirerer, extractFirst } from "inquirerer"; +import { getStore } from "../executor"; +const usage = "\\nmyapp context \\n\\nCommands:\\n create Create a new context\\n list List all contexts\\n use Set the active context\\n current Show current context\\n delete Delete a context\\n\\nCreate Options:\\n --auth-endpoint auth endpoint (default: http://auth.localhost/graphql)\\n --members-endpoint members endpoint (default: http://members.localhost/graphql)\\n --app-endpoint app endpoint (default: http://app.localhost/graphql)\\n\\n --help, -h Show this help message\\n"; +export default async (argv: Partial>, prompter: Inquirerer, _options: CLIOptions) => { + if (argv.help || argv.h) { + console.log(usage); + process.exit(0); + } + const store = getStore(); + const { + first: subcommand, + newArgv + } = extractFirst(argv); + if (!subcommand) { + const answer = await prompter.prompt(argv, [{ + type: "autocomplete", + name: "subcommand", + message: "What do you want to do?", + options: ["create", "list", "use", "current", "delete"] + }]); + return handleSubcommand(answer.subcommand, newArgv, prompter, store); + } + return handleSubcommand(subcommand, newArgv, prompter, store); +}; +async function handleSubcommand(subcommand: string, argv: Partial>, prompter: Inquirerer, store: ReturnType) { + switch (subcommand) { + case "create": + return handleCreate(argv, prompter, store); + case "list": + return handleList(store); + case "use": + return handleUse(argv, prompter, store); + case "current": + return handleCurrent(store); + case "delete": + return handleDelete(argv, prompter, store); + default: + console.log(usage); + process.exit(1); + } +} +async function handleCreate(argv: Partial>, prompter: Inquirerer, store: ReturnType) { + const { + first: name, + newArgv: restArgv + } = extractFirst(argv); + const answers = await prompter.prompt({ + name, + ...restArgv + }, [{ + type: "text", + name: "name", + message: "Context name", + required: true + }, { + type: "text", + name: "authEndpoint", + message: "auth endpoint", + default: "http://auth.localhost/graphql" + }, { + type: "text", + name: "membersEndpoint", + message: "members endpoint", + default: "http://members.localhost/graphql" + }, { + type: "text", + name: "appEndpoint", + message: "app endpoint", + default: "http://app.localhost/graphql" + }]); + const contextName = answers.name; + const targets = { + "auth": { + endpoint: answers.authEndpoint + }, + "members": { + endpoint: answers.membersEndpoint + }, + "app": { + endpoint: answers.appEndpoint + } + }; + store.createContext(contextName, { + endpoint: answers.authEndpoint, + targets: targets + }); + const settings = store.loadSettings(); + if (!settings.currentContext) { + store.setCurrentContext(contextName); + } + console.log(\`Created context: \${contextName}\`); + console.log(\` auth: \${answers.authEndpoint}\`); + console.log(\` members: \${answers.membersEndpoint}\`); + console.log(\` app: \${answers.appEndpoint}\`); +} +function handleList(store: ReturnType) { + const contexts = store.listContexts(); + const settings = store.loadSettings(); + if (contexts.length === 0) { + console.log("No contexts configured."); + return; + } + console.log("Contexts:"); + for (const ctx of contexts) { + const marker = ctx.name === settings.currentContext ? "* " : " "; + const authStatus = store.hasValidCredentials(ctx.name) ? "[authenticated]" : "[no token]"; + console.log(\`\${marker}\${ctx.name} \${authStatus}\`); + console.log(\` Endpoint: \${ctx.endpoint}\`); + } +} +async function handleUse(argv: Partial>, prompter: Inquirerer, store: ReturnType) { + const { + first: name + } = extractFirst(argv); + const contexts = store.listContexts(); + if (contexts.length === 0) { + console.log("No contexts configured."); + return; + } + let contextName = name; + if (!contextName) { + const answer = await prompter.prompt(argv, [{ + type: "autocomplete", + name: "name", + message: "Select context", + options: contexts.map(c => c.name) + }]); + contextName = answer.name; + } + if (store.setCurrentContext(contextName)) { + console.log(\`Switched to context: \${contextName}\`); + } else { + console.error(\`Context "\${contextName}" not found.\`); + process.exit(1); + } +} +function handleCurrent(store: ReturnType) { + const current = store.getCurrentContext(); + if (!current) { + console.log("No current context set."); + return; + } + console.log(\`Current context: \${current.name}\`); + console.log(\` Endpoint: \${current.endpoint}\`); + const hasAuth = store.hasValidCredentials(current.name); + console.log(\` Auth: \${hasAuth ? "authenticated" : "not authenticated"}\`); +} +async function handleDelete(argv: Partial>, prompter: Inquirerer, store: ReturnType) { + const { + first: name + } = extractFirst(argv); + const contexts = store.listContexts(); + if (contexts.length === 0) { + console.log("No contexts configured."); + return; + } + let contextName = name; + if (!contextName) { + const answer = await prompter.prompt(argv, [{ + type: "autocomplete", + name: "name", + message: "Select context to delete", + options: contexts.map(c => c.name) + }]); + contextName = answer.name; + } + if (store.deleteContext(contextName)) { + console.log(\`Deleted context: \${contextName}\`); + } else { + console.error(\`Context "\${contextName}" not found.\`); + process.exit(1); + } +}" +`; + +exports[`multi-target cli generator generates multi-target executor 1`] = ` +"/** + * Multi-target executor and config store for CLI + * @generated by @constructive-io/graphql-codegen + * DO NOT EDIT - changes will be overwritten + */ +import { createConfigStore } from "appstash"; +import { createClient as createAuthClient } from "../../generated/auth/orm"; +import { createClient as createMembersClient } from "../../generated/members/orm"; +import { createClient as createAppClient } from "../../generated/app/orm"; +const store = createConfigStore("myapp"); +export const getStore = () => store; +const targetClients = { + "auth": createAuthClient, + "members": createMembersClient, + "app": createAppClient +}; +const defaultEndpoints = { + "auth": "http://auth.localhost/graphql", + "members": "http://members.localhost/graphql", + "app": "http://app.localhost/graphql" +}; +export const getTargetNames = () => Object.keys(targetClients); +export const getDefaultEndpoint = (targetName: string) => defaultEndpoints[targetName] || ""; +export function getClient(targetName: string, contextName?: string) { + const createFn = targetClients[targetName]; + if (!createFn) { + throw new Error(\`Unknown target: \${targetName}\`); + } + const headers = {}; + let endpoint = ""; + const ctx = contextName ? store.loadContext(contextName) : store.getCurrentContext(); + if (ctx) { + const resolved = store.getTargetEndpoint(targetName, ctx.name); + endpoint = resolved || defaultEndpoints[targetName] || ""; + if (store.hasValidCredentials(ctx.name)) { + const creds = store.getCredentials(ctx.name); + if (creds?.token) { + headers.Authorization = \`Bearer \${creds.token}\`; + } + } + } else { + endpoint = defaultEndpoints[targetName] || ""; + } + return createFn({ + endpoint: endpoint, + headers: headers + }); +}" +`; + +exports[`multi-target cli generator generates target-prefixed custom commands with save-token 1`] = ` +"/** + * CLI command for mutation login + * @generated by @constructive-io/graphql-codegen + * DO NOT EDIT - changes will be overwritten + */ +import { CLIOptions, Inquirerer } from "inquirerer"; +import { getClient, getStore } from "../../executor"; +export default async (argv: Partial>, prompter: Inquirerer, _options: CLIOptions) => { + try { + if (argv.help || argv.h) { + console.log("login - Authenticate a user\\n\\nUsage: login [OPTIONS]\\n"); + process.exit(0); + } + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "email", + message: "email", + required: true + }, { + type: "text", + name: "password", + message: "password", + required: true + }]); + const client = getClient("auth"); + const result = await client.mutation.login(answers).execute(); + if (argv.saveToken && result) { + const tokenValue = result.token || result.jwtToken || result.accessToken; + if (tokenValue) { + const s = getStore(); + const ctx = s.getCurrentContext(); + if (ctx) { + s.setCredentials(ctx.name, { + token: tokenValue + }); + console.log("Token saved to current context."); + } + } + } + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed: login"); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +};" +`; + +exports[`multi-target cli generator generates target-prefixed table commands 1`] = ` +"/** + * CLI commands for User + * @generated by @constructive-io/graphql-codegen + * DO NOT EDIT - changes will be overwritten + */ +import { CLIOptions, Inquirerer, extractFirst } from "inquirerer"; +import { getClient } from "../../executor"; +const usage = "\\nuser \\n\\nCommands:\\n list List all user records\\n get Get a user by ID\\n create Create a new user\\n update Update an existing user\\n delete Delete a user\\n\\n --help, -h Show this help message\\n"; +export default async (argv: Partial>, prompter: Inquirerer, _options: CLIOptions) => { + if (argv.help || argv.h) { + console.log(usage); + process.exit(0); + } + const { + first: subcommand, + newArgv + } = extractFirst(argv); + if (!subcommand) { + const answer = await prompter.prompt(argv, [{ + type: "autocomplete", + name: "subcommand", + message: "What do you want to do?", + options: ["list", "get", "create", "update", "delete"] + }]); + return handleTableSubcommand(answer.subcommand, newArgv, prompter); + } + return handleTableSubcommand(subcommand, newArgv, prompter); +}; +async function handleTableSubcommand(subcommand: string, argv: Partial>, prompter: Inquirerer) { + switch (subcommand) { + case "list": + return handleList(argv, prompter); + case "get": + return handleGet(argv, prompter); + case "create": + return handleCreate(argv, prompter); + case "update": + return handleUpdate(argv, prompter); + case "delete": + return handleDelete(argv, prompter); + default: + console.log(usage); + process.exit(1); + } +} +async function handleList(_argv: Partial>, _prompter: Inquirerer) { + try { + const client = getClient("auth"); + const result = await client.user.findMany({ + select: { + id: true, + email: true, + name: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to list records."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleGet(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "id", + message: "id", + required: true + }]); + const client = getClient("auth"); + const result = await client.user.findOne({ + id: answers.id, + select: { + id: true, + email: true, + name: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Record not found."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleCreate(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "email", + message: "email", + required: true + }, { + type: "text", + name: "name", + message: "name", + required: true + }]); + const client = getClient("auth"); + const result = await client.user.create({ + data: { + email: answers.email, + name: answers.name + }, + select: { + id: true, + email: true, + name: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to create record."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleUpdate(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "id", + message: "id", + required: true + }, { + type: "text", + name: "email", + message: "email", + required: false + }, { + type: "text", + name: "name", + message: "name", + required: false + }]); + const client = getClient("auth"); + const result = await client.user.update({ + id: answers.id, + data: { + email: answers.email, + name: answers.name + }, + select: { + id: true, + email: true, + name: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to update record."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleDelete(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "id", + message: "id", + required: true + }]); + const client = getClient("auth"); + const result = await client.user.delete({ + id: answers.id, + select: { + id: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to delete record."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +}" +`; + +exports[`multi-target cli generator generates target-prefixed table commands 2`] = ` +"/** + * CLI commands for Member + * @generated by @constructive-io/graphql-codegen + * DO NOT EDIT - changes will be overwritten + */ +import { CLIOptions, Inquirerer, extractFirst } from "inquirerer"; +import { getClient } from "../../executor"; +const usage = "\\nmember \\n\\nCommands:\\n list List all member records\\n get Get a member by ID\\n create Create a new member\\n update Update an existing member\\n delete Delete a member\\n\\n --help, -h Show this help message\\n"; +export default async (argv: Partial>, prompter: Inquirerer, _options: CLIOptions) => { + if (argv.help || argv.h) { + console.log(usage); + process.exit(0); + } + const { + first: subcommand, + newArgv + } = extractFirst(argv); + if (!subcommand) { + const answer = await prompter.prompt(argv, [{ + type: "autocomplete", + name: "subcommand", + message: "What do you want to do?", + options: ["list", "get", "create", "update", "delete"] + }]); + return handleTableSubcommand(answer.subcommand, newArgv, prompter); + } + return handleTableSubcommand(subcommand, newArgv, prompter); +}; +async function handleTableSubcommand(subcommand: string, argv: Partial>, prompter: Inquirerer) { + switch (subcommand) { + case "list": + return handleList(argv, prompter); + case "get": + return handleGet(argv, prompter); + case "create": + return handleCreate(argv, prompter); + case "update": + return handleUpdate(argv, prompter); + case "delete": + return handleDelete(argv, prompter); + default: + console.log(usage); + process.exit(1); + } +} +async function handleList(_argv: Partial>, _prompter: Inquirerer) { + try { + const client = getClient("members"); + const result = await client.member.findMany({ + select: { + id: true, + role: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to list records."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleGet(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "id", + message: "id", + required: true + }]); + const client = getClient("members"); + const result = await client.member.findOne({ + id: answers.id, + select: { + id: true, + role: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Record not found."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleCreate(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "role", + message: "role", + required: true + }]); + const client = getClient("members"); + const result = await client.member.create({ + data: { + role: answers.role + }, + select: { + id: true, + role: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to create record."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleUpdate(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "id", + message: "id", + required: true + }, { + type: "text", + name: "role", + message: "role", + required: false + }]); + const client = getClient("members"); + const result = await client.member.update({ + id: answers.id, + data: { + role: answers.role + }, + select: { + id: true, + role: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to update record."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleDelete(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "id", + message: "id", + required: true + }]); + const client = getClient("members"); + const result = await client.member.delete({ + id: answers.id, + select: { + id: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to delete record."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +}" +`; + +exports[`multi-target cli generator generates target-prefixed table commands 3`] = ` +"/** + * CLI commands for Car + * @generated by @constructive-io/graphql-codegen + * DO NOT EDIT - changes will be overwritten + */ +import { CLIOptions, Inquirerer, extractFirst } from "inquirerer"; +import { getClient } from "../../executor"; +const usage = "\\ncar \\n\\nCommands:\\n list List all car records\\n get Get a car by ID\\n create Create a new car\\n update Update an existing car\\n delete Delete a car\\n\\n --help, -h Show this help message\\n"; +export default async (argv: Partial>, prompter: Inquirerer, _options: CLIOptions) => { + if (argv.help || argv.h) { + console.log(usage); + process.exit(0); + } + const { + first: subcommand, + newArgv + } = extractFirst(argv); + if (!subcommand) { + const answer = await prompter.prompt(argv, [{ + type: "autocomplete", + name: "subcommand", + message: "What do you want to do?", + options: ["list", "get", "create", "update", "delete"] + }]); + return handleTableSubcommand(answer.subcommand, newArgv, prompter); + } + return handleTableSubcommand(subcommand, newArgv, prompter); +}; +async function handleTableSubcommand(subcommand: string, argv: Partial>, prompter: Inquirerer) { + switch (subcommand) { + case "list": + return handleList(argv, prompter); + case "get": + return handleGet(argv, prompter); + case "create": + return handleCreate(argv, prompter); + case "update": + return handleUpdate(argv, prompter); + case "delete": + return handleDelete(argv, prompter); + default: + console.log(usage); + process.exit(1); + } +} +async function handleList(_argv: Partial>, _prompter: Inquirerer) { + try { + const client = getClient("app"); + const result = await client.car.findMany({ + select: { + id: true, + make: true, + model: true, + year: true, + isElectric: true, + createdAt: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to list records."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleGet(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "id", + message: "id", + required: true + }]); + const client = getClient("app"); + const result = await client.car.findOne({ + id: answers.id, + select: { + id: true, + make: true, + model: true, + year: true, + isElectric: true, + createdAt: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Record not found."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleCreate(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "make", + message: "make", + required: true + }, { + type: "text", + name: "model", + message: "model", + required: true + }, { + type: "text", + name: "year", + message: "year", + required: true + }, { + type: "text", + name: "isElectric", + message: "isElectric", + required: true + }]); + const client = getClient("app"); + const result = await client.car.create({ + data: { + make: answers.make, + model: answers.model, + year: answers.year, + isElectric: answers.isElectric + }, + select: { + id: true, + make: true, + model: true, + year: true, + isElectric: true, + createdAt: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to create record."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleUpdate(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "id", + message: "id", + required: true + }, { + type: "text", + name: "make", + message: "make", + required: false + }, { + type: "text", + name: "model", + message: "model", + required: false + }, { + type: "text", + name: "year", + message: "year", + required: false + }, { + type: "text", + name: "isElectric", + message: "isElectric", + required: false + }]); + const client = getClient("app"); + const result = await client.car.update({ + id: answers.id, + data: { + make: answers.make, + model: answers.model, + year: answers.year, + isElectric: answers.isElectric + }, + select: { + id: true, + make: true, + model: true, + year: true, + isElectric: true, + createdAt: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to update record."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +} +async function handleDelete(argv: Partial>, prompter: Inquirerer) { + try { + const answers = await prompter.prompt(argv, [{ + type: "text", + name: "id", + message: "id", + required: true + }]); + const client = getClient("app"); + const result = await client.car.delete({ + id: answers.id, + select: { + id: true + } + }).execute(); + console.log(JSON.stringify(result, null, 2)); + } catch (error) { + console.error("Failed to delete record."); + if (error instanceof Error) { + console.error(error.message); + } + process.exit(1); + } +}" +`; + exports[`orm docs generator generates ORM AGENTS.md 1`] = ` "# ORM Client - Agent Reference diff --git a/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts b/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts index ab0d9eca2..4af63bd2c 100644 --- a/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts +++ b/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts @@ -1,4 +1,4 @@ -import { generateCli } from '../../core/codegen/cli'; +import { generateCli, generateMultiTargetCli, resolveInfraNames } from '../../core/codegen/cli'; import { generateReadme as generateCliReadme, generateAgentsDocs as generateCliAgentsDocs, @@ -409,3 +409,253 @@ describe('resolveDocsConfig', () => { expect(config).toEqual({ readme: true, agents: true, mcp: true, skills: false }); }); }); + +describe('resolveInfraNames', () => { + it('uses defaults when no collisions', () => { + expect(resolveInfraNames(['app', 'members'])).toEqual({ + auth: 'auth', + context: 'context', + }); + }); + + it('renames auth to credentials on collision', () => { + expect(resolveInfraNames(['auth', 'members', 'app'])).toEqual({ + auth: 'credentials', + context: 'context', + }); + }); + + it('renames context to env on collision', () => { + expect(resolveInfraNames(['context', 'app'])).toEqual({ + auth: 'auth', + context: 'env', + }); + }); + + it('renames both on collision', () => { + expect(resolveInfraNames(['auth', 'context', 'app'])).toEqual({ + auth: 'credentials', + context: 'env', + }); + }); + + it('respects user overrides even with collisions', () => { + expect( + resolveInfraNames(['auth', 'app'], { auth: 'auth' }), + ).toEqual({ + auth: 'auth', + context: 'context', + }); + }); + + it('uses user override names', () => { + expect( + resolveInfraNames(['app'], { auth: 'creds', context: 'profile' }), + ).toEqual({ + auth: 'creds', + context: 'profile', + }); + }); +}); + +const userTable = createTable({ + name: 'User', + fields: [ + { name: 'id', type: fieldTypes.uuid }, + { name: 'email', type: fieldTypes.string }, + { name: 'name', type: fieldTypes.string }, + ], + query: { + all: 'users', + one: 'user', + create: 'createUser', + update: 'updateUser', + delete: 'deleteUser', + }, +}); + +const memberTable = createTable({ + name: 'Member', + fields: [ + { name: 'id', type: fieldTypes.uuid }, + { name: 'role', type: fieldTypes.string }, + ], + query: { + all: 'members', + one: 'member', + create: 'createMember', + update: 'updateMember', + delete: 'deleteMember', + }, +}); + +describe('multi-target cli generator', () => { + const multiResult = generateMultiTargetCli({ + toolName: 'myapp', + targets: [ + { + name: 'auth', + endpoint: 'http://auth.localhost/graphql', + ormImportPath: '../../generated/auth/orm', + tables: [userTable], + customOperations: { + queries: [currentUserQuery], + mutations: [loginMutation], + }, + isAuthTarget: true, + }, + { + name: 'members', + endpoint: 'http://members.localhost/graphql', + ormImportPath: '../../generated/members/orm', + tables: [memberTable], + customOperations: { + queries: [], + mutations: [], + }, + }, + { + name: 'app', + endpoint: 'http://app.localhost/graphql', + ormImportPath: '../../generated/app/orm', + tables: [carTable], + customOperations: { + queries: [], + mutations: [], + }, + }, + ], + }); + + it('returns correct stats', () => { + expect(multiResult.stats).toEqual({ + tables: 3, + customQueries: 1, + customMutations: 1, + infraFiles: 3, + totalFiles: 9, + }); + }); + + it('auto-renames auth infra to credentials on collision', () => { + const fileNames = multiResult.files.map((f) => f.fileName).sort(); + expect(fileNames).toContain('commands/credentials.ts'); + expect(fileNames).not.toContain('commands/auth.ts'); + }); + + it('generates correct file names with target prefixes', () => { + const fileNames = multiResult.files.map((f) => f.fileName).sort(); + expect(fileNames).toEqual([ + 'commands.ts', + 'commands/app/car.ts', + 'commands/auth/current-user.ts', + 'commands/auth/login.ts', + 'commands/auth/user.ts', + 'commands/context.ts', + 'commands/credentials.ts', + 'commands/members/member.ts', + 'executor.ts', + ]); + }); + + it('generates multi-target executor', () => { + const file = multiResult.files.find((f) => f.fileName === 'executor.ts'); + expect(file).toBeDefined(); + expect(file!.content).toMatchSnapshot(); + }); + + it('generates multi-target context command', () => { + const file = multiResult.files.find( + (f) => f.fileName === 'commands/context.ts', + ); + expect(file).toBeDefined(); + expect(file!.content).toMatchSnapshot(); + }); + + it('generates credentials command (renamed from auth)', () => { + const file = multiResult.files.find( + (f) => f.fileName === 'commands/credentials.ts', + ); + expect(file).toBeDefined(); + expect(file!.content).toMatchSnapshot(); + }); + + it('generates target-prefixed table commands', () => { + const userFile = multiResult.files.find( + (f) => f.fileName === 'commands/auth/user.ts', + ); + expect(userFile).toBeDefined(); + expect(userFile!.content).toMatchSnapshot(); + + const memberFile = multiResult.files.find( + (f) => f.fileName === 'commands/members/member.ts', + ); + expect(memberFile).toBeDefined(); + expect(memberFile!.content).toMatchSnapshot(); + + const carFile = multiResult.files.find( + (f) => f.fileName === 'commands/app/car.ts', + ); + expect(carFile).toBeDefined(); + expect(carFile!.content).toMatchSnapshot(); + }); + + it('generates target-prefixed custom commands with save-token', () => { + const loginFile = multiResult.files.find( + (f) => f.fileName === 'commands/auth/login.ts', + ); + expect(loginFile).toBeDefined(); + expect(loginFile!.content).toContain('saveToken'); + expect(loginFile!.content).toMatchSnapshot(); + }); + + it('generates multi-target command map', () => { + const file = multiResult.files.find((f) => f.fileName === 'commands.ts'); + expect(file).toBeDefined(); + expect(file!.content).toContain('auth:user'); + expect(file!.content).toContain('auth:login'); + expect(file!.content).toContain('members:member'); + expect(file!.content).toContain('app:car'); + expect(file!.content).toContain('credentials'); + expect(file!.content).toContain('context'); + expect(file!.content).toMatchSnapshot(); + }); + + it('uses correct executor import path in target commands', () => { + const userFile = multiResult.files.find( + (f) => f.fileName === 'commands/auth/user.ts', + ); + expect(userFile!.content).toContain('../../executor'); + }); +}); + +describe('multi-target cli with custom infraNames', () => { + const result = generateMultiTargetCli({ + toolName: 'myapp', + infraNames: { auth: 'creds', context: 'profile' }, + targets: [ + { + name: 'auth', + endpoint: 'http://auth.localhost/graphql', + ormImportPath: '../../generated/auth/orm', + tables: [userTable], + customOperations: { queries: [], mutations: [] }, + }, + { + name: 'app', + endpoint: 'http://app.localhost/graphql', + ormImportPath: '../../generated/app/orm', + tables: [carTable], + customOperations: { queries: [], mutations: [] }, + }, + ], + }); + + it('uses custom infraNames from config', () => { + const fileNames = result.files.map((f) => f.fileName).sort(); + expect(fileNames).toContain('commands/creds.ts'); + expect(fileNames).toContain('commands/profile.ts'); + expect(fileNames).not.toContain('commands/auth.ts'); + expect(fileNames).not.toContain('commands/context.ts'); + }); +}); diff --git a/graphql/codegen/src/core/codegen/cli/command-map-generator.ts b/graphql/codegen/src/core/codegen/cli/command-map-generator.ts index e938e59f9..8a2991ab2 100644 --- a/graphql/codegen/src/core/codegen/cli/command-map-generator.ts +++ b/graphql/codegen/src/core/codegen/cli/command-map-generator.ts @@ -380,3 +380,344 @@ export function generateCommandMap( content: header + '\n' + code, }; } + +export interface MultiTargetCommandMapInput { + toolName: string; + infraNames: { auth: string; context: string }; + targets: Array<{ + name: string; + tables: CleanTable[]; + customOperations: CleanOperation[]; + }>; +} + +export function generateMultiTargetCommandMap( + input: MultiTargetCommandMapInput, +): GeneratedFile { + const { toolName, infraNames, targets } = input; + const statements: t.Statement[] = []; + + statements.push( + createNamedImportDeclaration('inquirerer', [ + 'CLIOptions', + 'Inquirerer', + 'extractFirst', + ]), + ); + + const commandEntries: { kebab: string; importName: string }[] = []; + + const contextImportName = `${infraNames.context}Cmd`; + commandEntries.push({ kebab: infraNames.context, importName: contextImportName }); + statements.push( + createImportDeclaration(`./commands/${infraNames.context}`, contextImportName), + ); + + const authImportName = `${infraNames.auth}Cmd`; + commandEntries.push({ kebab: infraNames.auth, importName: authImportName }); + statements.push( + createImportDeclaration(`./commands/${infraNames.auth}`, authImportName), + ); + + for (const target of targets) { + for (const table of target.tables) { + const { singularName } = getTableNames(table); + const kebab = toKebabCase(singularName); + const prefixedKebab = `${target.name}:${kebab}`; + const importName = `${target.name}${singularName[0].toUpperCase()}${singularName.slice(1)}Cmd`; + commandEntries.push({ kebab: prefixedKebab, importName }); + statements.push( + createImportDeclaration(`./commands/${target.name}/${kebab}`, importName), + ); + } + + for (const op of target.customOperations) { + const kebab = toKebabCase(op.name); + const prefixedKebab = `${target.name}:${kebab}`; + const importName = `${target.name}${op.name[0].toUpperCase()}${op.name.slice(1)}Cmd`; + commandEntries.push({ kebab: prefixedKebab, importName }); + statements.push( + createImportDeclaration(`./commands/${target.name}/${kebab}`, importName), + ); + } + } + + const mapProperties = commandEntries.map((entry) => + t.objectProperty( + t.stringLiteral(entry.kebab), + t.identifier(entry.importName), + ), + ); + + const createCommandMapFunc = t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('createCommandMap'), + t.arrowFunctionExpression( + [], + t.objectExpression(mapProperties), + ), + ), + ]); + statements.push(createCommandMapFunc); + + const usageLines = [ + '', + `${toolName} `, + '', + 'Commands:', + ` ${infraNames.context.padEnd(20)} Manage API contexts`, + ` ${infraNames.auth.padEnd(20)} Manage authentication`, + ]; + + for (const target of targets) { + usageLines.push(''); + usageLines.push(` ${target.name}:`); + for (const table of target.tables) { + const { singularName } = getTableNames(table); + const kebab = toKebabCase(singularName); + const cmd = `${target.name}:${kebab}`; + usageLines.push( + ` ${cmd.padEnd(22)} ${singularName} CRUD operations`, + ); + } + for (const op of target.customOperations) { + const kebab = toKebabCase(op.name); + const cmd = `${target.name}:${kebab}`; + usageLines.push( + ` ${cmd.padEnd(22)} ${op.description || op.name}`, + ); + } + } + + usageLines.push(''); + usageLines.push(' --help, -h Show this help message'); + usageLines.push(' --version, -v Show version'); + usageLines.push(''); + + statements.push( + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('usage'), + t.stringLiteral(usageLines.join('\n')), + ), + ]), + ); + + const argvParam = t.identifier('argv'); + argvParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('Partial'), + t.tsTypeParameterInstantiation([ + t.tsTypeReference( + t.identifier('Record'), + t.tsTypeParameterInstantiation([ + t.tsStringKeyword(), + t.tsUnknownKeyword(), + ]), + ), + ]), + ), + ); + const prompterParam = t.identifier('prompter'); + prompterParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('Inquirerer')), + ); + const optionsParam = t.identifier('options'); + optionsParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('CLIOptions')), + ); + + const commandsBody: t.Statement[] = [ + t.ifStatement( + t.logicalExpression( + '||', + t.memberExpression(t.identifier('argv'), t.identifier('help')), + t.memberExpression(t.identifier('argv'), t.identifier('h')), + ), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [t.identifier('usage')], + ), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('process'), + t.identifier('exit'), + ), + [t.numericLiteral(0)], + ), + ), + ]), + ), + t.variableDeclaration('let', [ + t.variableDeclarator( + t.objectPattern([ + t.objectProperty( + t.identifier('first'), + t.identifier('command'), + ), + t.objectProperty( + t.identifier('newArgv'), + t.identifier('newArgv'), + false, + true, + ), + ]), + t.callExpression(t.identifier('extractFirst'), [ + t.identifier('argv'), + ]), + ), + ]), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('commandMap'), + t.callExpression(t.identifier('createCommandMap'), []), + ), + ]), + t.ifStatement( + t.unaryExpression('!', t.identifier('command')), + t.blockStatement([ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('answer'), + t.awaitExpression( + t.callExpression( + t.memberExpression( + t.identifier('prompter'), + t.identifier('prompt'), + ), + [ + t.identifier('argv'), + t.arrayExpression([ + t.objectExpression([ + t.objectProperty( + t.identifier('type'), + t.stringLiteral('autocomplete'), + ), + t.objectProperty( + t.identifier('name'), + t.stringLiteral('command'), + ), + t.objectProperty( + t.identifier('message'), + t.stringLiteral('What do you want to do?'), + ), + t.objectProperty( + t.identifier('options'), + t.callExpression( + t.memberExpression( + t.identifier('Object'), + t.identifier('keys'), + ), + [t.identifier('commandMap')], + ), + ), + ]), + ]), + ], + ), + ), + ), + ]), + t.expressionStatement( + t.assignmentExpression( + '=', + t.identifier('command'), + t.memberExpression( + t.identifier('answer'), + t.identifier('command'), + ), + ), + ), + ]), + ), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('commandFn'), + t.memberExpression( + t.identifier('commandMap'), + t.identifier('command'), + true, + ), + ), + ]), + t.ifStatement( + t.unaryExpression('!', t.identifier('commandFn')), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [t.identifier('usage')], + ), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('console'), + t.identifier('error'), + ), + [ + t.templateLiteral( + [ + t.templateElement({ + raw: 'Unknown command: ', + cooked: 'Unknown command: ', + }), + t.templateElement({ raw: '', cooked: '' }, true), + ], + [t.identifier('command')], + ), + ], + ), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('process'), + t.identifier('exit'), + ), + [t.numericLiteral(1)], + ), + ), + ]), + ), + t.expressionStatement( + t.awaitExpression( + t.callExpression(t.identifier('commandFn'), [ + t.identifier('newArgv'), + t.identifier('prompter'), + t.identifier('options'), + ]), + ), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('prompter'), t.identifier('close')), + [], + ), + ), + t.returnStatement(t.identifier('argv')), + ]; + + const commandsFunc = t.arrowFunctionExpression( + [argvParam, prompterParam, optionsParam], + t.blockStatement(commandsBody), + true, + ); + + const commandsDecl = t.variableDeclaration('const', [ + t.variableDeclarator(t.identifier('commands'), commandsFunc), + ]); + statements.push(t.exportNamedDeclaration(commandsDecl)); + + const header = getGeneratedFileHeader('Multi-target CLI command map and entry point'); + const code = generateCode(statements); + + return { + fileName: 'commands.ts', + content: header + '\n' + code, + }; +} diff --git a/graphql/codegen/src/core/codegen/cli/custom-command-generator.ts b/graphql/codegen/src/core/codegen/cli/custom-command-generator.ts index a345e84f9..10005f6ae 100644 --- a/graphql/codegen/src/core/codegen/cli/custom-command-generator.ts +++ b/graphql/codegen/src/core/codegen/cli/custom-command-generator.ts @@ -123,16 +123,27 @@ function buildOrmCustomCall( ); } -export function generateCustomCommand(op: CleanOperation): GeneratedFile { +export interface CustomCommandOptions { + targetName?: string; + executorImportPath?: string; + saveToken?: boolean; +} + +export function generateCustomCommand(op: CleanOperation, options?: CustomCommandOptions): GeneratedFile { const commandName = toKebabCase(op.name); const opKind = op.kind === 'mutation' ? 'mutation' : 'query'; const statements: t.Statement[] = []; + const executorPath = options?.executorImportPath ?? '../executor'; + const imports = ['getClient']; + if (options?.saveToken) { + imports.push('getStore'); + } statements.push( createImportDeclaration('inquirerer', ['CLIOptions', 'Inquirerer']), ); statements.push( - createImportDeclaration('../executor', ['getClient']), + createImportDeclaration(executorPath, imports), ); const questionsArray = @@ -201,11 +212,14 @@ export function generateCustomCommand(op: CleanOperation): GeneratedFile { ); } + const getClientArgs: t.Expression[] = options?.targetName + ? [t.stringLiteral(options.targetName)] + : []; bodyStatements.push( t.variableDeclaration('const', [ t.variableDeclarator( t.identifier('client'), - t.callExpression(t.identifier('getClient'), []), + t.callExpression(t.identifier('getClient'), getClientArgs), ), ]), ); @@ -226,6 +240,79 @@ export function generateCustomCommand(op: CleanOperation): GeneratedFile { ]), ); + if (options?.saveToken) { + bodyStatements.push( + t.ifStatement( + t.logicalExpression( + '&&', + t.memberExpression(t.identifier('argv'), t.identifier('saveToken')), + t.identifier('result'), + ), + t.blockStatement([ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('tokenValue'), + t.logicalExpression( + '||', + t.memberExpression(t.identifier('result'), t.identifier('token'), false), + t.logicalExpression( + '||', + t.memberExpression(t.identifier('result'), t.identifier('jwtToken'), false), + t.memberExpression(t.identifier('result'), t.identifier('accessToken'), false), + ), + ), + ), + ]), + t.ifStatement( + t.identifier('tokenValue'), + t.blockStatement([ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('s'), + t.callExpression(t.identifier('getStore'), []), + ), + ]), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('ctx'), + t.callExpression( + t.memberExpression(t.identifier('s'), t.identifier('getCurrentContext')), + [], + ), + ), + ]), + t.ifStatement( + t.identifier('ctx'), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('s'), t.identifier('setCredentials')), + [ + t.memberExpression(t.identifier('ctx'), t.identifier('name')), + t.objectExpression([ + t.objectProperty( + t.identifier('token'), + t.identifier('tokenValue'), + ), + ]), + ], + ), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [t.stringLiteral('Token saved to current context.')], + ), + ), + ]), + ), + ]), + ), + ]), + ), + ); + } + bodyStatements.push(buildJsonLog(t.identifier('result'))); const tryBlock = t.tryStatement( @@ -249,7 +336,9 @@ export function generateCustomCommand(op: CleanOperation): GeneratedFile { const code = generateCode(statements); return { - fileName: `commands/${commandName}.ts`, + fileName: options?.targetName + ? `commands/${options.targetName}/${commandName}.ts` + : `commands/${commandName}.ts`, content: header + '\n' + code, }; } diff --git a/graphql/codegen/src/core/codegen/cli/executor-generator.ts b/graphql/codegen/src/core/codegen/cli/executor-generator.ts index d5d1183f9..e5a462f53 100644 --- a/graphql/codegen/src/core/codegen/cli/executor-generator.ts +++ b/graphql/codegen/src/core/codegen/cli/executor-generator.ts @@ -8,6 +8,12 @@ export interface GeneratedFile { content: string; } +export interface MultiTargetExecutorInput { + name: string; + endpoint: string; + ormImportPath: string; +} + function createImportDeclaration( moduleSpecifier: string, namedImports: string[], @@ -216,3 +222,281 @@ export function generateExecutorFile(toolName: string): GeneratedFile { content: header + '\n' + code, }; } + +export function generateMultiTargetExecutorFile( + toolName: string, + targets: MultiTargetExecutorInput[], +): GeneratedFile { + const statements: t.Statement[] = []; + + statements.push( + createImportDeclaration('appstash', ['createConfigStore']), + ); + + for (const target of targets) { + const aliasName = `create${target.name[0].toUpperCase()}${target.name.slice(1)}Client`; + const specifier = t.importSpecifier( + t.identifier(aliasName), + t.identifier('createClient'), + ); + statements.push( + t.importDeclaration([specifier], t.stringLiteral(target.ormImportPath)), + ); + } + + statements.push( + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('store'), + t.callExpression(t.identifier('createConfigStore'), [ + t.stringLiteral(toolName), + ]), + ), + ]), + ); + + const getStoreExport = t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('getStore'), + t.arrowFunctionExpression([], t.identifier('store')), + ), + ]); + statements.push(t.exportNamedDeclaration(getStoreExport)); + + const targetClientsProps = targets.map((target) => { + const aliasName = `create${target.name[0].toUpperCase()}${target.name.slice(1)}Client`; + return t.objectProperty( + t.stringLiteral(target.name), + t.identifier(aliasName), + ); + }); + const targetClientsDecl = t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('targetClients'), + t.objectExpression(targetClientsProps), + ), + ]); + statements.push(targetClientsDecl); + + const defaultEndpointProps = targets.map((target) => + t.objectProperty( + t.stringLiteral(target.name), + t.stringLiteral(target.endpoint), + ), + ); + const defaultEndpointsDecl = t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('defaultEndpoints'), + t.objectExpression(defaultEndpointProps), + ), + ]); + statements.push(defaultEndpointsDecl); + + const getTargetNamesFunc = t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('getTargetNames'), + t.arrowFunctionExpression( + [], + t.callExpression( + t.memberExpression(t.identifier('Object'), t.identifier('keys')), + [t.identifier('targetClients')], + ), + ), + ), + ]); + statements.push(t.exportNamedDeclaration(getTargetNamesFunc)); + + const getDefaultEndpointParam = t.identifier('targetName'); + getDefaultEndpointParam.typeAnnotation = t.tsTypeAnnotation(t.tsStringKeyword()); + const getDefaultEndpointFunc = t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('getDefaultEndpoint'), + t.arrowFunctionExpression( + [getDefaultEndpointParam], + t.logicalExpression( + '||', + t.memberExpression( + t.identifier('defaultEndpoints'), + t.identifier('targetName'), + true, + ), + t.stringLiteral(''), + ), + ), + ), + ]); + statements.push(t.exportNamedDeclaration(getDefaultEndpointFunc)); + + const targetNameParam = t.identifier('targetName'); + targetNameParam.typeAnnotation = t.tsTypeAnnotation(t.tsStringKeyword()); + const contextNameParam = t.identifier('contextName'); + contextNameParam.optional = true; + contextNameParam.typeAnnotation = t.tsTypeAnnotation(t.tsStringKeyword()); + + const getClientBody = t.blockStatement([ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('createFn'), + t.memberExpression( + t.identifier('targetClients'), + t.identifier('targetName'), + true, + ), + ), + ]), + t.ifStatement( + t.unaryExpression('!', t.identifier('createFn')), + t.blockStatement([ + t.throwStatement( + t.newExpression(t.identifier('Error'), [ + t.templateLiteral( + [ + t.templateElement({ raw: 'Unknown target: ', cooked: 'Unknown target: ' }), + t.templateElement({ raw: '', cooked: '' }, true), + ], + [t.identifier('targetName')], + ), + ]), + ), + ]), + ), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('headers'), + t.objectExpression([]), + ), + ]), + t.variableDeclaration('let', [ + t.variableDeclarator(t.identifier('endpoint'), t.stringLiteral('')), + ]), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('ctx'), + t.conditionalExpression( + t.identifier('contextName'), + t.callExpression( + t.memberExpression(t.identifier('store'), t.identifier('loadContext')), + [t.identifier('contextName')], + ), + t.callExpression( + t.memberExpression(t.identifier('store'), t.identifier('getCurrentContext')), + [], + ), + ), + ), + ]), + t.ifStatement( + t.identifier('ctx'), + t.blockStatement([ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('resolved'), + t.callExpression( + t.memberExpression(t.identifier('store'), t.identifier('getTargetEndpoint')), + [t.identifier('targetName'), t.memberExpression(t.identifier('ctx'), t.identifier('name'))], + ), + ), + ]), + t.expressionStatement( + t.assignmentExpression( + '=', + t.identifier('endpoint'), + t.logicalExpression( + '||', + t.identifier('resolved'), + t.logicalExpression( + '||', + t.memberExpression( + t.identifier('defaultEndpoints'), + t.identifier('targetName'), + true, + ), + t.stringLiteral(''), + ), + ), + ), + ), + t.ifStatement( + t.callExpression( + t.memberExpression(t.identifier('store'), t.identifier('hasValidCredentials')), + [t.memberExpression(t.identifier('ctx'), t.identifier('name'))], + ), + t.blockStatement([ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('creds'), + t.callExpression( + t.memberExpression(t.identifier('store'), t.identifier('getCredentials')), + [t.memberExpression(t.identifier('ctx'), t.identifier('name'))], + ), + ), + ]), + t.ifStatement( + t.optionalMemberExpression( + t.identifier('creds'), + t.identifier('token'), + false, + true, + ), + t.blockStatement([ + t.expressionStatement( + t.assignmentExpression( + '=', + t.memberExpression(t.identifier('headers'), t.identifier('Authorization')), + t.templateLiteral( + [ + t.templateElement({ raw: 'Bearer ', cooked: 'Bearer ' }), + t.templateElement({ raw: '', cooked: '' }, true), + ], + [t.memberExpression(t.identifier('creds'), t.identifier('token'))], + ), + ), + ), + ]), + ), + ]), + ), + ]), + t.blockStatement([ + t.expressionStatement( + t.assignmentExpression( + '=', + t.identifier('endpoint'), + t.logicalExpression( + '||', + t.memberExpression( + t.identifier('defaultEndpoints'), + t.identifier('targetName'), + true, + ), + t.stringLiteral(''), + ), + ), + ), + ]), + ), + t.returnStatement( + t.callExpression(t.identifier('createFn'), [ + t.objectExpression([ + t.objectProperty(t.identifier('endpoint'), t.identifier('endpoint')), + t.objectProperty(t.identifier('headers'), t.identifier('headers')), + ]), + ]), + ), + ]); + + const getClientFunc = t.functionDeclaration( + t.identifier('getClient'), + [targetNameParam, contextNameParam], + getClientBody, + ); + statements.push(t.exportNamedDeclaration(getClientFunc)); + + const header = getGeneratedFileHeader('Multi-target executor and config store for CLI'); + const code = generateCode(statements); + + return { + fileName: 'executor.ts', + content: header + '\n' + code, + }; +} diff --git a/graphql/codegen/src/core/codegen/cli/index.ts b/graphql/codegen/src/core/codegen/cli/index.ts index d64eeb5fe..e7ff52826 100644 --- a/graphql/codegen/src/core/codegen/cli/index.ts +++ b/graphql/codegen/src/core/codegen/cli/index.ts @@ -1,10 +1,15 @@ -import type { GraphQLSDKConfigTarget } from '../../../types/config'; +import type { GraphQLSDKConfigTarget, InfraNames } from '../../../types/config'; import type { CleanOperation, CleanTable } from '../../../types/schema'; -import { generateCommandMap } from './command-map-generator'; +import { generateCommandMap, generateMultiTargetCommandMap } from './command-map-generator'; import { generateCustomCommand } from './custom-command-generator'; -import { generateExecutorFile } from './executor-generator'; -import type { GeneratedFile } from './executor-generator'; -import { generateAuthCommand, generateContextCommand } from './infra-generator'; +import { generateExecutorFile, generateMultiTargetExecutorFile } from './executor-generator'; +import type { GeneratedFile, MultiTargetExecutorInput } from './executor-generator'; +import { + generateAuthCommand, + generateAuthCommandWithName, + generateContextCommand, + generateMultiTargetContextCommand, +} from './infra-generator'; import { generateTableCommand } from './table-command-generator'; export interface GenerateCliOptions { @@ -80,13 +85,141 @@ export function generateCli(options: GenerateCliOptions): GenerateCliResult { }; } -export { generateExecutorFile } from './executor-generator'; +export interface MultiTargetCliTarget { + name: string; + endpoint: string; + ormImportPath: string; + tables: CleanTable[]; + customOperations: { + queries: CleanOperation[]; + mutations: CleanOperation[]; + }; + isAuthTarget?: boolean; +} + +export interface GenerateMultiTargetCliOptions { + toolName: string; + infraNames?: InfraNames; + targets: MultiTargetCliTarget[]; +} + +export function resolveInfraNames( + targetNames: string[], + userOverrides?: InfraNames, +): { auth: string; context: string } { + let authName = userOverrides?.auth ?? 'auth'; + let contextName = userOverrides?.context ?? 'context'; + + if (targetNames.includes(authName) && !userOverrides?.auth) { + authName = 'credentials'; + } + if (targetNames.includes(contextName) && !userOverrides?.context) { + contextName = 'env'; + } + + return { auth: authName, context: contextName }; +} + +export function generateMultiTargetCli( + options: GenerateMultiTargetCliOptions, +): GenerateCliResult { + const { toolName, targets } = options; + const files: GeneratedFile[] = []; + + const targetNames = targets.map((t) => t.name); + const infraNames = resolveInfraNames(targetNames, options.infraNames); + + const executorInputs: MultiTargetExecutorInput[] = targets.map((t) => ({ + name: t.name, + endpoint: t.endpoint, + ormImportPath: t.ormImportPath, + })); + const executorFile = generateMultiTargetExecutorFile(toolName, executorInputs); + files.push(executorFile); + + const contextFile = generateMultiTargetContextCommand( + toolName, + infraNames.context, + targets.map((t) => ({ name: t.name, endpoint: t.endpoint })), + ); + files.push(contextFile); + + const authFile = generateAuthCommandWithName(toolName, infraNames.auth); + files.push(authFile); + + let totalTables = 0; + let totalQueries = 0; + let totalMutations = 0; + + const commandMapTargets: Array<{ + name: string; + tables: CleanTable[]; + customOperations: CleanOperation[]; + }> = []; + + for (const target of targets) { + const allOps: CleanOperation[] = [ + ...(target.customOperations?.queries ?? []), + ...(target.customOperations?.mutations ?? []), + ]; + + for (const table of target.tables) { + const tableFile = generateTableCommand(table, { + targetName: target.name, + executorImportPath: '../../executor', + }); + files.push(tableFile); + } + + for (const op of allOps) { + const isSaveToken = !!target.isAuthTarget && op.kind === 'mutation'; + const customFile = generateCustomCommand(op, { + targetName: target.name, + executorImportPath: '../../executor', + saveToken: isSaveToken, + }); + files.push(customFile); + } + + totalTables += target.tables.length; + totalQueries += target.customOperations?.queries?.length ?? 0; + totalMutations += target.customOperations?.mutations?.length ?? 0; + + commandMapTargets.push({ + name: target.name, + tables: target.tables, + customOperations: allOps, + }); + } + + const commandMapFile = generateMultiTargetCommandMap({ + toolName, + infraNames, + targets: commandMapTargets, + }); + files.push(commandMapFile); + + return { + files, + stats: { + tables: totalTables, + customQueries: totalQueries, + customMutations: totalMutations, + infraFiles: 3, + totalFiles: files.length, + }, + }; +} + +export { generateExecutorFile, generateMultiTargetExecutorFile } from './executor-generator'; export { generateTableCommand } from './table-command-generator'; export { generateCustomCommand } from './custom-command-generator'; -export { generateCommandMap } from './command-map-generator'; +export { generateCommandMap, generateMultiTargetCommandMap } from './command-map-generator'; export { generateContextCommand, generateAuthCommand, + generateMultiTargetContextCommand, + generateAuthCommandWithName, } from './infra-generator'; export { generateReadme, @@ -96,4 +229,4 @@ export { } from './docs-generator'; export { resolveDocsConfig } from '../docs-utils'; export type { GeneratedDocFile, McpTool } from '../docs-utils'; -export type { GeneratedFile } from './executor-generator'; +export type { GeneratedFile, MultiTargetExecutorInput } from './executor-generator'; diff --git a/graphql/codegen/src/core/codegen/cli/infra-generator.ts b/graphql/codegen/src/core/codegen/cli/infra-generator.ts index 9433169ad..d3610b5ce 100644 --- a/graphql/codegen/src/core/codegen/cli/infra-generator.ts +++ b/graphql/codegen/src/core/codegen/cli/infra-generator.ts @@ -2052,3 +2052,749 @@ function buildLogoutHandler(): t.FunctionDeclaration { ); return func; } + +export interface MultiTargetContextInput { + name: string; + endpoint: string; +} + +export function generateMultiTargetContextCommand( + toolName: string, + commandName: string, + targets: MultiTargetContextInput[], +): GeneratedFile { + const statements: t.Statement[] = []; + + statements.push( + createImportDeclaration('inquirerer', [ + 'CLIOptions', + 'Inquirerer', + 'extractFirst', + ]), + ); + statements.push( + createImportDeclaration('../executor', ['getStore']), + ); + + const usageStr = ` +${toolName} ${commandName} + +Commands: + create Create a new context + list List all contexts + use Set the active context + current Show current context + delete Delete a context + +Create Options: +${targets.map((tgt) => ` --${tgt.name}-endpoint ${tgt.name} endpoint (default: ${tgt.endpoint})`).join('\n')} + + --help, -h Show this help message +`; + + statements.push( + t.variableDeclaration('const', [ + t.variableDeclarator(t.identifier('usage'), t.stringLiteral(usageStr)), + ]), + ); + + const argvParam = t.identifier('argv'); + argvParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('Partial'), + t.tsTypeParameterInstantiation([ + t.tsTypeReference( + t.identifier('Record'), + t.tsTypeParameterInstantiation([ + t.tsStringKeyword(), + t.tsUnknownKeyword(), + ]), + ), + ]), + ), + ); + + const prompterParam = t.identifier('prompter'); + prompterParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('Inquirerer')), + ); + + const optionsParam = t.identifier('_options'); + optionsParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('CLIOptions')), + ); + + const mainBody: t.Statement[] = [ + t.ifStatement( + t.logicalExpression( + '||', + t.memberExpression(t.identifier('argv'), t.identifier('help')), + t.memberExpression(t.identifier('argv'), t.identifier('h')), + ), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [t.identifier('usage')], + ), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('process'), t.identifier('exit')), + [t.numericLiteral(0)], + ), + ), + ]), + ), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('store'), + t.callExpression(t.identifier('getStore'), []), + ), + ]), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.objectPattern([ + t.objectProperty( + t.identifier('first'), + t.identifier('subcommand'), + ), + t.objectProperty( + t.identifier('newArgv'), + t.identifier('newArgv'), + false, + true, + ), + ]), + t.callExpression(t.identifier('extractFirst'), [ + t.identifier('argv'), + ]), + ), + ]), + t.ifStatement( + t.unaryExpression('!', t.identifier('subcommand')), + t.blockStatement([ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('answer'), + t.awaitExpression( + t.callExpression( + t.memberExpression( + t.identifier('prompter'), + t.identifier('prompt'), + ), + [ + t.identifier('argv'), + t.arrayExpression([ + t.objectExpression([ + t.objectProperty( + t.identifier('type'), + t.stringLiteral('autocomplete'), + ), + t.objectProperty( + t.identifier('name'), + t.stringLiteral('subcommand'), + ), + t.objectProperty( + t.identifier('message'), + t.stringLiteral('What do you want to do?'), + ), + t.objectProperty( + t.identifier('options'), + t.arrayExpression([ + t.stringLiteral('create'), + t.stringLiteral('list'), + t.stringLiteral('use'), + t.stringLiteral('current'), + t.stringLiteral('delete'), + ]), + ), + ]), + ]), + ], + ), + ), + ), + ]), + t.returnStatement( + t.callExpression(t.identifier('handleSubcommand'), [ + t.memberExpression( + t.identifier('answer'), + t.identifier('subcommand'), + ), + t.identifier('newArgv'), + t.identifier('prompter'), + t.identifier('store'), + ]), + ), + ]), + ), + t.returnStatement( + t.callExpression(t.identifier('handleSubcommand'), [ + t.identifier('subcommand'), + t.identifier('newArgv'), + t.identifier('prompter'), + t.identifier('store'), + ]), + ), + ]; + + const mainExport = t.exportDefaultDeclaration( + t.arrowFunctionExpression( + [argvParam, prompterParam, optionsParam], + t.blockStatement(mainBody), + true, + ), + ); + statements.push(mainExport); + + const subcmdParam = t.identifier('subcommand'); + subcmdParam.typeAnnotation = t.tsTypeAnnotation(t.tsStringKeyword()); + const argvParam2 = t.identifier('argv'); + argvParam2.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('Partial'), + t.tsTypeParameterInstantiation([ + t.tsTypeReference( + t.identifier('Record'), + t.tsTypeParameterInstantiation([ + t.tsStringKeyword(), + t.tsUnknownKeyword(), + ]), + ), + ]), + ), + ); + const prompterParam2 = t.identifier('prompter'); + prompterParam2.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('Inquirerer')), + ); + const storeParam = t.identifier('store'); + storeParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('ReturnType'), + t.tsTypeParameterInstantiation([ + t.tsTypeQuery(t.identifier('getStore')), + ]), + ), + ); + + const handleSubcommandFunc = t.functionDeclaration( + t.identifier('handleSubcommand'), + [subcmdParam, argvParam2, prompterParam2, storeParam], + t.blockStatement([ + t.switchStatement(t.identifier('subcommand'), [ + buildSwitchCase('create', 'handleCreate', [ + t.identifier('argv'), + t.identifier('prompter'), + t.identifier('store'), + ]), + buildSwitchCase('list', 'handleList', [t.identifier('store')]), + buildSwitchCase('use', 'handleUse', [ + t.identifier('argv'), + t.identifier('prompter'), + t.identifier('store'), + ]), + buildSwitchCase('current', 'handleCurrent', [t.identifier('store')]), + buildSwitchCase('delete', 'handleDelete', [ + t.identifier('argv'), + t.identifier('prompter'), + t.identifier('store'), + ]), + buildDefaultSwitchCase('usage'), + ]), + ]), + false, + true, + ); + statements.push(handleSubcommandFunc); + + statements.push(buildMultiTargetCreateHandler(targets)); + statements.push(buildListHandler()); + statements.push(buildUseHandler()); + statements.push(buildCurrentHandler()); + statements.push(buildDeleteHandler()); + + const header = getGeneratedFileHeader('Multi-target context management commands'); + const code = generateCode(statements); + + return { + fileName: `commands/${commandName}.ts`, + content: header + '\n' + code, + }; +} + +function buildMultiTargetCreateHandler( + targets: MultiTargetContextInput[], +): t.FunctionDeclaration { + const argvParam = t.identifier('argv'); + argvParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('Partial'), + t.tsTypeParameterInstantiation([ + t.tsTypeReference( + t.identifier('Record'), + t.tsTypeParameterInstantiation([ + t.tsStringKeyword(), + t.tsUnknownKeyword(), + ]), + ), + ]), + ), + ); + const prompterParam = t.identifier('prompter'); + prompterParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('Inquirerer')), + ); + const storeParam = t.identifier('store'); + storeParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('ReturnType'), + t.tsTypeParameterInstantiation([ + t.tsTypeQuery(t.identifier('getStore')), + ]), + ), + ); + + const promptQuestions: t.Expression[] = [ + t.objectExpression([ + t.objectProperty(t.identifier('type'), t.stringLiteral('text')), + t.objectProperty(t.identifier('name'), t.stringLiteral('name')), + t.objectProperty(t.identifier('message'), t.stringLiteral('Context name')), + t.objectProperty(t.identifier('required'), t.booleanLiteral(true)), + ]), + ]; + + for (const target of targets) { + const fieldName = `${target.name}Endpoint`; + promptQuestions.push( + t.objectExpression([ + t.objectProperty(t.identifier('type'), t.stringLiteral('text')), + t.objectProperty(t.identifier('name'), t.stringLiteral(fieldName)), + t.objectProperty( + t.identifier('message'), + t.stringLiteral(`${target.name} endpoint`), + ), + t.objectProperty( + t.identifier('default'), + t.stringLiteral(target.endpoint), + ), + ]), + ); + } + + const targetsObjProps = targets.map((target) => { + const fieldName = `${target.name}Endpoint`; + return t.objectProperty( + t.stringLiteral(target.name), + t.objectExpression([ + t.objectProperty( + t.identifier('endpoint'), + t.memberExpression(t.identifier('answers'), t.identifier(fieldName)), + ), + ]), + ); + }); + + const body: t.Statement[] = [ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.objectPattern([ + t.objectProperty(t.identifier('first'), t.identifier('name')), + t.objectProperty( + t.identifier('newArgv'), + t.identifier('restArgv'), + ), + ]), + t.callExpression(t.identifier('extractFirst'), [ + t.identifier('argv'), + ]), + ), + ]), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('answers'), + t.awaitExpression( + t.callExpression( + t.memberExpression( + t.identifier('prompter'), + t.identifier('prompt'), + ), + [ + t.objectExpression([ + t.objectProperty( + t.identifier('name'), + t.identifier('name'), + false, + true, + ), + t.spreadElement(t.identifier('restArgv')), + ]), + t.arrayExpression(promptQuestions), + ], + ), + ), + ), + ]), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('contextName'), + t.memberExpression(t.identifier('answers'), t.identifier('name')), + ), + ]), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('targets'), + t.objectExpression(targetsObjProps), + ), + ]), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('store'), t.identifier('createContext')), + [ + t.identifier('contextName'), + t.objectExpression([ + t.objectProperty( + t.identifier('endpoint'), + t.memberExpression( + t.identifier('answers'), + t.identifier(`${targets[0].name}Endpoint`), + ), + ), + t.objectProperty( + t.identifier('targets'), + t.identifier('targets'), + ), + ]), + ], + ), + ), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('settings'), + t.callExpression( + t.memberExpression( + t.identifier('store'), + t.identifier('loadSettings'), + ), + [], + ), + ), + ]), + t.ifStatement( + t.unaryExpression( + '!', + t.memberExpression( + t.identifier('settings'), + t.identifier('currentContext'), + ), + ), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('store'), + t.identifier('setCurrentContext'), + ), + [t.identifier('contextName')], + ), + ), + ]), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [ + t.templateLiteral( + [ + t.templateElement({ raw: 'Created context: ', cooked: 'Created context: ' }), + t.templateElement({ raw: '', cooked: '' }, true), + ], + [t.identifier('contextName')], + ), + ], + ), + ), + ]; + + for (const target of targets) { + const fieldName = `${target.name}Endpoint`; + body.push( + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [ + t.templateLiteral( + [ + t.templateElement({ raw: ` ${target.name}: `, cooked: ` ${target.name}: ` }), + t.templateElement({ raw: '', cooked: '' }, true), + ], + [t.memberExpression(t.identifier('answers'), t.identifier(fieldName))], + ), + ], + ), + ), + ); + } + + const func = t.functionDeclaration( + t.identifier('handleCreate'), + [argvParam, prompterParam, storeParam], + t.blockStatement(body), + false, + true, + ); + return func; +} + +export function generateAuthCommandWithName( + toolName: string, + commandName: string, +): GeneratedFile { + const statements: t.Statement[] = []; + + statements.push( + createImportDeclaration('inquirerer', [ + 'CLIOptions', + 'Inquirerer', + 'extractFirst', + ]), + ); + statements.push( + createImportDeclaration('../executor', ['getStore']), + ); + + const usageStr = ` +${toolName} ${commandName} + +Commands: + set-token Set API token for the current context + status Show authentication status + logout Remove credentials for the current context + +Options: + --context Specify context (defaults to current context) + + --help, -h Show this help message +`; + + statements.push( + t.variableDeclaration('const', [ + t.variableDeclarator(t.identifier('usage'), t.stringLiteral(usageStr)), + ]), + ); + + const argvParam = t.identifier('argv'); + argvParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('Partial'), + t.tsTypeParameterInstantiation([ + t.tsTypeReference( + t.identifier('Record'), + t.tsTypeParameterInstantiation([ + t.tsStringKeyword(), + t.tsUnknownKeyword(), + ]), + ), + ]), + ), + ); + const prompterParam = t.identifier('prompter'); + prompterParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('Inquirerer')), + ); + const optionsParam = t.identifier('_options'); + optionsParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('CLIOptions')), + ); + + const mainBody: t.Statement[] = [ + t.ifStatement( + t.logicalExpression( + '||', + t.memberExpression(t.identifier('argv'), t.identifier('help')), + t.memberExpression(t.identifier('argv'), t.identifier('h')), + ), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('console'), t.identifier('log')), + [t.identifier('usage')], + ), + ), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('process'), t.identifier('exit')), + [t.numericLiteral(0)], + ), + ), + ]), + ), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('store'), + t.callExpression(t.identifier('getStore'), []), + ), + ]), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.objectPattern([ + t.objectProperty( + t.identifier('first'), + t.identifier('subcommand'), + ), + t.objectProperty( + t.identifier('newArgv'), + t.identifier('newArgv'), + false, + true, + ), + ]), + t.callExpression(t.identifier('extractFirst'), [ + t.identifier('argv'), + ]), + ), + ]), + t.ifStatement( + t.unaryExpression('!', t.identifier('subcommand')), + t.blockStatement([ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('answer'), + t.awaitExpression( + t.callExpression( + t.memberExpression( + t.identifier('prompter'), + t.identifier('prompt'), + ), + [ + t.identifier('argv'), + t.arrayExpression([ + t.objectExpression([ + t.objectProperty( + t.identifier('type'), + t.stringLiteral('autocomplete'), + ), + t.objectProperty( + t.identifier('name'), + t.stringLiteral('subcommand'), + ), + t.objectProperty( + t.identifier('message'), + t.stringLiteral('What do you want to do?'), + ), + t.objectProperty( + t.identifier('options'), + t.arrayExpression([ + t.stringLiteral('set-token'), + t.stringLiteral('status'), + t.stringLiteral('logout'), + ]), + ), + ]), + ]), + ], + ), + ), + ), + ]), + t.returnStatement( + t.callExpression(t.identifier('handleAuthSubcommand'), [ + t.memberExpression( + t.identifier('answer'), + t.identifier('subcommand'), + ), + t.identifier('newArgv'), + t.identifier('prompter'), + t.identifier('store'), + ]), + ), + ]), + ), + t.returnStatement( + t.callExpression(t.identifier('handleAuthSubcommand'), [ + t.identifier('subcommand'), + t.identifier('newArgv'), + t.identifier('prompter'), + t.identifier('store'), + ]), + ), + ]; + + statements.push( + t.exportDefaultDeclaration( + t.arrowFunctionExpression( + [argvParam, prompterParam, optionsParam], + t.blockStatement(mainBody), + true, + ), + ), + ); + + const subcmdParam = t.identifier('subcommand'); + subcmdParam.typeAnnotation = t.tsTypeAnnotation(t.tsStringKeyword()); + const argvParam2 = t.identifier('argv'); + argvParam2.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('Partial'), + t.tsTypeParameterInstantiation([ + t.tsTypeReference( + t.identifier('Record'), + t.tsTypeParameterInstantiation([ + t.tsStringKeyword(), + t.tsUnknownKeyword(), + ]), + ), + ]), + ), + ); + const prompterParam2 = t.identifier('prompter'); + prompterParam2.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('Inquirerer')), + ); + const storeParam = t.identifier('store'); + storeParam.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeReference( + t.identifier('ReturnType'), + t.tsTypeParameterInstantiation([ + t.tsTypeQuery(t.identifier('getStore')), + ]), + ), + ); + + const handleAuthSubcommandFunc = t.functionDeclaration( + t.identifier('handleAuthSubcommand'), + [subcmdParam, argvParam2, prompterParam2, storeParam], + t.blockStatement([ + t.switchStatement(t.identifier('subcommand'), [ + buildSwitchCase('set-token', 'handleSetToken', [ + t.identifier('argv'), + t.identifier('prompter'), + t.identifier('store'), + ]), + buildSwitchCase('status', 'handleStatus', [t.identifier('store')]), + buildSwitchCase('logout', 'handleLogout', [ + t.identifier('argv'), + t.identifier('prompter'), + t.identifier('store'), + ]), + buildDefaultSwitchCase('usage'), + ]), + ]), + false, + true, + ); + statements.push(handleAuthSubcommandFunc); + + statements.push(buildSetTokenHandler()); + statements.push(buildStatusHandler()); + statements.push(buildLogoutHandler()); + + const header = getGeneratedFileHeader('Authentication commands'); + const code = generateCode(statements); + + return { + fileName: `commands/${commandName}.ts`, + content: header + '\n' + code, + }; +} diff --git a/graphql/codegen/src/core/codegen/cli/table-command-generator.ts b/graphql/codegen/src/core/codegen/cli/table-command-generator.ts index 82d42d8e0..8a84ed5d0 100644 --- a/graphql/codegen/src/core/codegen/cli/table-command-generator.ts +++ b/graphql/codegen/src/core/codegen/cli/table-command-generator.ts @@ -120,11 +120,14 @@ function buildErrorCatch(errorMessage: string): t.CatchClause { ); } -function buildGetClientStatement(): t.VariableDeclaration { +function buildGetClientStatement(targetName?: string): t.VariableDeclaration { + const args: t.Expression[] = targetName + ? [t.stringLiteral(targetName)] + : []; return t.variableDeclaration('const', [ t.variableDeclarator( t.identifier('client'), - t.callExpression(t.identifier('getClient'), []), + t.callExpression(t.identifier('getClient'), args), ), ]); } @@ -180,12 +183,12 @@ function buildSubcommandSwitch( return t.switchStatement(t.identifier('subcommand'), cases); } -function buildListHandler(table: CleanTable): t.FunctionDeclaration { +function buildListHandler(table: CleanTable, targetName?: string): t.FunctionDeclaration { const { singularName } = getTableNames(table); const selectObj = buildSelectObject(table); const tryBody: t.Statement[] = [ - buildGetClientStatement(), + buildGetClientStatement(targetName), t.variableDeclaration('const', [ t.variableDeclarator( t.identifier('result'), @@ -224,7 +227,7 @@ function buildListHandler(table: CleanTable): t.FunctionDeclaration { ); } -function buildGetHandler(table: CleanTable): t.FunctionDeclaration { +function buildGetHandler(table: CleanTable, targetName?: string): t.FunctionDeclaration { const { singularName } = getTableNames(table); const pkFields = getPrimaryKeyInfo(table); const pk = pkFields[0]; @@ -260,7 +263,7 @@ function buildGetHandler(table: CleanTable): t.FunctionDeclaration { ), ), ]), - buildGetClientStatement(), + buildGetClientStatement(targetName), t.variableDeclaration('const', [ t.variableDeclarator( t.identifier('result'), @@ -294,6 +297,7 @@ function buildGetHandler(table: CleanTable): t.FunctionDeclaration { function buildMutationHandler( table: CleanTable, operation: 'create' | 'update' | 'delete', + targetName?: string, ): t.FunctionDeclaration { const { singularName } = getTableNames(table); const pkFields = getPrimaryKeyInfo(table); @@ -406,7 +410,7 @@ function buildMutationHandler( ), ), ]), - buildGetClientStatement(), + buildGetClientStatement(targetName), t.variableDeclaration('const', [ t.variableDeclarator( t.identifier('result'), @@ -441,10 +445,16 @@ function buildMutationHandler( ); } -export function generateTableCommand(table: CleanTable): GeneratedFile { +export interface TableCommandOptions { + targetName?: string; + executorImportPath?: string; +} + +export function generateTableCommand(table: CleanTable, options?: TableCommandOptions): GeneratedFile { const { singularName } = getTableNames(table); const commandName = toKebabCase(singularName); const statements: t.Statement[] = []; + const executorPath = options?.executorImportPath ?? '../executor'; statements.push( createImportDeclaration('inquirerer', [ @@ -454,7 +464,7 @@ export function generateTableCommand(table: CleanTable): GeneratedFile { ]), ); statements.push( - createImportDeclaration('../executor', ['getClient']), + createImportDeclaration(executorPath, ['getClient']), ); const subcommands = ['list', 'get', 'create', 'update', 'delete']; @@ -631,17 +641,20 @@ export function generateTableCommand(table: CleanTable): GeneratedFile { ), ); - statements.push(buildListHandler(table)); - statements.push(buildGetHandler(table)); - statements.push(buildMutationHandler(table, 'create')); - statements.push(buildMutationHandler(table, 'update')); - statements.push(buildMutationHandler(table, 'delete')); + const tn = options?.targetName; + statements.push(buildListHandler(table, tn)); + statements.push(buildGetHandler(table, tn)); + statements.push(buildMutationHandler(table, 'create', tn)); + statements.push(buildMutationHandler(table, 'update', tn)); + statements.push(buildMutationHandler(table, 'delete', tn)); const header = getGeneratedFileHeader(`CLI commands for ${table.name}`); const code = generateCode(statements); return { - fileName: `commands/${commandName}.ts`, + fileName: options?.targetName + ? `commands/${options.targetName}/${commandName}.ts` + : `commands/${commandName}.ts`, content: header + '\n' + code, }; } diff --git a/graphql/codegen/src/core/generate.ts b/graphql/codegen/src/core/generate.ts index 3632dea72..cfdeb8b0f 100644 --- a/graphql/codegen/src/core/generate.ts +++ b/graphql/codegen/src/core/generate.ts @@ -6,12 +6,13 @@ */ import path from 'node:path'; -import type { GraphQLSDKConfigTarget } from '../types/config'; +import type { CliConfig, GraphQLSDKConfigTarget } from '../types/config'; import { getConfigOptions } from '../types/config'; -import type { CleanOperation } from '../types/schema'; +import type { CleanOperation, CleanTable } from '../types/schema'; import { generate as generateReactQueryFiles } from './codegen'; import { generateRootBarrel } from './codegen/barrel'; -import { generateCli as generateCliFiles } from './codegen/cli'; +import { generateCli as generateCliFiles, generateMultiTargetCli } from './codegen/cli'; +import type { MultiTargetCliTarget } from './codegen/cli'; import { generateReadme as generateCliReadme, generateAgentsDocs as generateCliAgentsDocs, @@ -58,6 +59,13 @@ export interface GenerateResult { tables?: string[]; filesWritten?: string[]; errors?: string[]; + pipelineData?: { + tables: CleanTable[]; + customOperations: { + queries: CleanOperation[]; + mutations: CleanOperation[]; + }; + }; } /** @@ -66,8 +74,13 @@ export interface GenerateResult { * This is the primary entry point for programmatic usage. * For multiple configs, call this function in a loop. */ +export interface GenerateInternalOptions { + skipCli?: boolean; +} + export async function generate( options: GenerateOptions = {}, + internalOptions?: GenerateInternalOptions, ): Promise { // Apply defaults to get resolved config const config = getConfigOptions(options); @@ -77,9 +90,9 @@ export async function generate( // ORM is always required when React Query is enabled (hooks delegate to ORM) // This handles minimist setting orm=false when --orm flag is absent const runReactQuery = config.reactQuery ?? false; - const runCli = !!config.cli; + const runCli = internalOptions?.skipCli ? false : !!config.cli; const runOrm = - runReactQuery || runCli || (options.orm !== undefined ? !!options.orm : false); + runReactQuery || !!config.cli || (options.orm !== undefined ? !!options.orm : false); if (!runReactQuery && !runOrm && !runCli) { return { @@ -355,6 +368,13 @@ export async function generate( output: outputRoot, tables: tables.map((t) => t.name), filesWritten: allFilesWritten, + pipelineData: { + tables, + customOperations: { + queries: customOperations.queries, + mutations: customOperations.mutations, + }, + }, }; } @@ -363,6 +383,7 @@ export interface GenerateMultiOptions { cliOverrides?: Partial; verbose?: boolean; dryRun?: boolean; + unifiedCli?: CliConfig | boolean; } export interface GenerateMultiResult { @@ -373,19 +394,25 @@ export interface GenerateMultiResult { export async function generateMulti( options: GenerateMultiOptions, ): Promise { - const { configs, cliOverrides, verbose, dryRun } = options; + const { configs, cliOverrides, verbose, dryRun, unifiedCli } = options; const names = Object.keys(configs); const results: Array<{ name: string; result: GenerateResult }> = []; let hasError = false; const targetInfos: RootRootReadmeTarget[] = []; + const useUnifiedCli = !!unifiedCli && names.length > 1; + + const cliTargets: MultiTargetCliTarget[] = []; for (const name of names) { const targetConfig = { ...configs[name], ...(cliOverrides ?? {}), }; - const result = await generate({ ...targetConfig, verbose, dryRun }); + const result = await generate( + { ...targetConfig, verbose, dryRun }, + useUnifiedCli ? { skipCli: true } : undefined, + ); results.push({ name, result }); if (!result.success) { hasError = true; @@ -401,9 +428,39 @@ export async function generateMulti( endpoint: resolvedConfig.endpoint || undefined, generators: gens, }); + + if (useUnifiedCli && result.pipelineData) { + const isAuthTarget = name === 'auth'; + cliTargets.push({ + name, + endpoint: resolvedConfig.endpoint || '', + ormImportPath: `../../${resolvedConfig.output}/orm`, + tables: result.pipelineData.tables, + customOperations: result.pipelineData.customOperations, + isAuthTarget, + }); + } } } + if (useUnifiedCli && cliTargets.length > 0 && !dryRun) { + const cliConfig = typeof unifiedCli === 'object' ? unifiedCli : {}; + const toolName = cliConfig.toolName ?? 'app'; + const { files } = generateMultiTargetCli({ + toolName, + infraNames: cliConfig.infraNames, + targets: cliTargets, + }); + + const cliFilesToWrite = files.map((file) => ({ + path: path.posix.join('cli', file.fileName), + content: file.content, + })); + + const { writeGeneratedFiles: writeFiles } = await import('./output'); + await writeFiles(cliFilesToWrite, '.', [], { pruneStaleFiles: false }); + } + // Generate root-root README if multi-target if (names.length > 1 && targetInfos.length > 0 && !dryRun) { const rootReadme = generateRootRootReadme(targetInfos); diff --git a/graphql/codegen/src/types/config.ts b/graphql/codegen/src/types/config.ts index de38149e7..08482c805 100644 --- a/graphql/codegen/src/types/config.ts +++ b/graphql/codegen/src/types/config.ts @@ -173,6 +173,16 @@ export interface DocsConfig { skills?: boolean; } +/** + * Infrastructure command name overrides for collision handling. + * When a target name collides with a default infra command name, + * the infra command is auto-renamed. These allow user overrides. + */ +export interface InfraNames { + auth?: string; + context?: string; +} + /** * CLI generation configuration */ @@ -183,6 +193,12 @@ export interface CliConfig { */ toolName?: string; + /** + * Override infra command names (for collision handling) + * Defaults: auth -> 'auth' (renamed to 'credentials' on collision), + * context -> 'context' (renamed to 'env' on collision) + */ + infraNames?: InfraNames; } /** From 5288230b2dc1ee05a486daabd08f179c5582325d Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Tue, 17 Feb 2026 23:07:29 +0000 Subject: [PATCH 07/23] feat(codegen): add multi-target CLI docs generation (README, AGENTS.md, MCP, skills) --- .../__snapshots__/cli-generator.test.ts.snap | 1228 +++++++++++++++++ .../__tests__/codegen/cli-generator.test.ts | 87 ++ .../src/core/codegen/cli/docs-generator.ts | 838 +++++++++++ graphql/codegen/src/core/codegen/cli/index.ts | 5 + graphql/codegen/src/core/generate.ts | 51 + 5 files changed, 2209 insertions(+) diff --git a/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap b/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap index 0ade6cb03..cbdddfa8b 100644 --- a/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap +++ b/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap @@ -1836,6 +1836,1234 @@ mutate({ email: '', password: '' }); " `; +exports[`multi-target cli docs generates multi-target AGENTS.md 1`] = ` +"# myapp CLI - Agent Reference + +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT +> This document is structured for LLM/agent consumption. + +## OVERVIEW + +\`myapp\` is a unified multi-target CLI for interacting with multiple GraphQL APIs. +All commands output JSON to stdout. All commands accept \`--help\` or \`-h\` for usage. +Configuration is stored at \`~/.myapp/config/\` via appstash. + +TARGETS: + auth: http://auth.localhost/graphql + members: http://members.localhost/graphql + app: http://app.localhost/graphql + +COMMAND FORMAT: + myapp : [flags] Target-specific commands + myapp context [flags] Context management + myapp credentials [flags] Authentication + +## PREREQUISITES + +Before running any data commands, you must: + +1. Create a context: \`myapp context create \` + (prompts for per-target endpoints, defaults baked from config) +2. Activate it: \`myapp context use \` +3. Authenticate: \`myapp credentials set-token \` + +For local development, create a context accepting all defaults: + +\`\`\`bash +myapp context create local +myapp context use local +myapp credentials set-token +\`\`\` + +## TOOLS + +### TOOL: context + +Manage named API endpoint contexts. Each context stores per-target endpoint overrides. + +\`\`\` +SUBCOMMANDS: + myapp context create Create a new context + myapp context list List all contexts + myapp context use Set active context + myapp context current Show active context + myapp context delete Delete a context + +CREATE OPTIONS: + --auth-endpoint: string (default: http://auth.localhost/graphql) + --members-endpoint: string (default: http://members.localhost/graphql) + --app-endpoint: string (default: http://app.localhost/graphql) + +OUTPUT: JSON + create: { name, endpoint, targets } + list: [{ name, endpoint, isCurrent, hasCredentials }] + use: { name, endpoint } + current: { name, endpoint } + delete: { deleted: name } +\`\`\` + +### TOOL: credentials + +Manage authentication tokens per context. One shared token across all targets. + +\`\`\` +SUBCOMMANDS: + myapp credentials set-token Store bearer token for current context + myapp credentials status Show auth status for all contexts + myapp credentials logout Remove credentials for current context + +INPUT: + token: string (required for set-token) - Bearer token value + +OUTPUT: JSON + set-token: { context, status: "authenticated" } + status: [{ context, authenticated: boolean }] + logout: { context, status: "logged out" } +\`\`\` + +### TOOL: auth:user + +CRUD operations for User records (auth target). + +\`\`\` +SUBCOMMANDS: + myapp auth:user list List all records + myapp auth:user get --id Get one record + myapp auth:user create --email --name + myapp auth:user update --id [--email ] [--name ] + myapp auth:user delete --id Delete one record + +INPUT FIELDS: + id: UUID (primary key) + email: String + name: String + +EDITABLE FIELDS (for create/update): + email: String + name: String + +OUTPUT: JSON + list: [{ id, email, name }] + get: { id, email, name } + create: { id, email, name } + update: { id, email, name } + delete: { id } +\`\`\` + +### TOOL: auth:current-user + +Get the currently authenticated user + +\`\`\` +TYPE: query +USAGE: myapp auth:current-user + +INPUT: none + +OUTPUT: JSON +\`\`\` + +### TOOL: auth:login + +Authenticate a user + +\`\`\` +TYPE: mutation +USAGE: myapp auth:login --email --password + +INPUT: + email: String (required) + password: String (required) + +FLAGS: + --save-token: boolean - Auto-save returned token to credentials + +OUTPUT: JSON +\`\`\` + +### TOOL: members:member + +CRUD operations for Member records (members target). + +\`\`\` +SUBCOMMANDS: + myapp members:member list List all records + myapp members:member get --id Get one record + myapp members:member create --role + myapp members:member update --id [--role ] + myapp members:member delete --id Delete one record + +INPUT FIELDS: + id: UUID (primary key) + role: String + +EDITABLE FIELDS (for create/update): + role: String + +OUTPUT: JSON + list: [{ id, role }] + get: { id, role } + create: { id, role } + update: { id, role } + delete: { id } +\`\`\` + +### TOOL: app:car + +CRUD operations for Car records (app target). + +\`\`\` +SUBCOMMANDS: + myapp app:car list List all records + myapp app:car get --id Get one record + myapp app:car create --make --model --year --isElectric + myapp app:car update --id [--make ] [--model ] [--year ] [--isElectric ] + myapp app:car delete --id Delete one record + +INPUT FIELDS: + id: UUID (primary key) + make: String + model: String + year: Int + isElectric: Boolean + createdAt: Datetime + +EDITABLE FIELDS (for create/update): + make: String + model: String + year: Int + isElectric: Boolean + +OUTPUT: JSON + list: [{ id, make, model, year, isElectric, createdAt }] + get: { id, make, model, year, isElectric, createdAt } + create: { id, make, model, year, isElectric, createdAt } + update: { id, make, model, year, isElectric, createdAt } + delete: { id } +\`\`\` + +## WORKFLOWS + +### Initial setup + +\`\`\`bash +myapp context create dev +myapp context use dev +myapp credentials set-token eyJhbGciOiJIUzI1NiIs... +\`\`\` + +### Switch environment + +\`\`\`bash +myapp context create production \\ + --auth-endpoint https://auth.prod.example.com/graphql \\ + --members-endpoint https://members.prod.example.com/graphql \\ + --app-endpoint https://app.prod.example.com/graphql +myapp context use production +\`\`\` + +### CRUD workflow (auth:user) + +\`\`\`bash +myapp auth:user list +myapp auth:user create --email "value" --name "value" +myapp auth:user get --id +myapp auth:user update --id --email "new-value" +myapp auth:user delete --id +\`\`\` + +### Piping output + +\`\`\`bash +myapp auth:user list | jq '.' +myapp auth:user list | jq '.[].id' +myapp auth:user list | jq 'length' +\`\`\` + +## ERROR HANDLING + +All errors are written to stderr. Exit codes: +- \`0\`: Success +- \`1\`: Error (auth failure, not found, validation error, network error) + +Common errors: +- "No active context": Run \`context use \` first +- "Not authenticated": Run \`credentials set-token \` first +- "Unknown target": The target name is not recognized +- "Record not found": The requested ID does not exist +" +`; + +exports[`multi-target cli docs generates multi-target MCP tools 1`] = ` +[ + { + "description": "Create a named API context with per-target endpoint overrides", + "inputSchema": { + "properties": { + "app_endpoint": { + "description": "app GraphQL endpoint (default: http://app.localhost/graphql)", + "type": "string", + }, + "auth_endpoint": { + "description": "auth GraphQL endpoint (default: http://auth.localhost/graphql)", + "type": "string", + }, + "members_endpoint": { + "description": "members GraphQL endpoint (default: http://members.localhost/graphql)", + "type": "string", + }, + "name": { + "description": "Context name", + "type": "string", + }, + }, + "required": [ + "name", + ], + "type": "object", + }, + "name": "myapp_context_create", + }, + { + "description": "List all configured API contexts", + "inputSchema": { + "properties": {}, + "type": "object", + }, + "name": "myapp_context_list", + }, + { + "description": "Set the active API context (switches all targets at once)", + "inputSchema": { + "properties": { + "name": { + "description": "Context name to activate", + "type": "string", + }, + }, + "required": [ + "name", + ], + "type": "object", + }, + "name": "myapp_context_use", + }, + { + "description": "Show the currently active API context", + "inputSchema": { + "properties": {}, + "type": "object", + }, + "name": "myapp_context_current", + }, + { + "description": "Delete an API context", + "inputSchema": { + "properties": { + "name": { + "description": "Context name to delete", + "type": "string", + }, + }, + "required": [ + "name", + ], + "type": "object", + }, + "name": "myapp_context_delete", + }, + { + "description": "Store a bearer token for the current context (shared across all targets)", + "inputSchema": { + "properties": { + "token": { + "description": "Bearer token value", + "type": "string", + }, + }, + "required": [ + "token", + ], + "type": "object", + }, + "name": "myapp_credentials_set_token", + }, + { + "description": "Show authentication status for all contexts", + "inputSchema": { + "properties": {}, + "type": "object", + }, + "name": "myapp_credentials_status", + }, + { + "description": "Remove credentials for the current context", + "inputSchema": { + "properties": {}, + "type": "object", + }, + "name": "myapp_credentials_logout", + }, + { + "description": "List all User records (auth target)", + "inputSchema": { + "properties": {}, + "type": "object", + }, + "name": "myapp_auth_user_list", + }, + { + "description": "Get a single User record by id (auth target)", + "inputSchema": { + "properties": { + "id": { + "description": "User id", + "type": "string", + }, + }, + "required": [ + "id", + ], + "type": "object", + }, + "name": "myapp_auth_user_get", + }, + { + "description": "Create a new User record (auth target)", + "inputSchema": { + "properties": { + "email": { + "description": "User email", + "type": "string", + }, + "name": { + "description": "User name", + "type": "string", + }, + }, + "required": [ + "email", + "name", + ], + "type": "object", + }, + "name": "myapp_auth_user_create", + }, + { + "description": "Update an existing User record (auth target)", + "inputSchema": { + "properties": { + "email": { + "description": "User email", + "type": "string", + }, + "id": { + "description": "User id", + "type": "string", + }, + "name": { + "description": "User name", + "type": "string", + }, + }, + "required": [ + "id", + ], + "type": "object", + }, + "name": "myapp_auth_user_update", + }, + { + "description": "Delete a User record by id (auth target)", + "inputSchema": { + "properties": { + "id": { + "description": "User id", + "type": "string", + }, + }, + "required": [ + "id", + ], + "type": "object", + }, + "name": "myapp_auth_user_delete", + }, + { + "_meta": { + "fields": [ + { + "editable": false, + "name": "id", + "primaryKey": true, + "type": "UUID", + }, + { + "editable": true, + "name": "email", + "primaryKey": false, + "type": "String", + }, + { + "editable": true, + "name": "name", + "primaryKey": false, + "type": "String", + }, + ], + }, + "description": "List available fields for User (auth target)", + "inputSchema": { + "properties": {}, + "type": "object", + }, + "name": "myapp_auth_user_fields", + }, + { + "description": "Get the currently authenticated user (auth target)", + "inputSchema": { + "properties": {}, + "type": "object", + }, + "name": "myapp_auth_current-user", + }, + { + "description": "Authenticate a user (auth target)", + "inputSchema": { + "properties": { + "email": { + "description": "email", + "type": "string", + }, + "password": { + "description": "password", + "type": "string", + }, + "save_token": { + "description": "Auto-save returned token to credentials", + "type": "boolean", + }, + }, + "required": [ + "email", + "password", + ], + "type": "object", + }, + "name": "myapp_auth_login", + }, + { + "description": "List all Member records (members target)", + "inputSchema": { + "properties": {}, + "type": "object", + }, + "name": "myapp_members_member_list", + }, + { + "description": "Get a single Member record by id (members target)", + "inputSchema": { + "properties": { + "id": { + "description": "Member id", + "type": "string", + }, + }, + "required": [ + "id", + ], + "type": "object", + }, + "name": "myapp_members_member_get", + }, + { + "description": "Create a new Member record (members target)", + "inputSchema": { + "properties": { + "role": { + "description": "Member role", + "type": "string", + }, + }, + "required": [ + "role", + ], + "type": "object", + }, + "name": "myapp_members_member_create", + }, + { + "description": "Update an existing Member record (members target)", + "inputSchema": { + "properties": { + "id": { + "description": "Member id", + "type": "string", + }, + "role": { + "description": "Member role", + "type": "string", + }, + }, + "required": [ + "id", + ], + "type": "object", + }, + "name": "myapp_members_member_update", + }, + { + "description": "Delete a Member record by id (members target)", + "inputSchema": { + "properties": { + "id": { + "description": "Member id", + "type": "string", + }, + }, + "required": [ + "id", + ], + "type": "object", + }, + "name": "myapp_members_member_delete", + }, + { + "_meta": { + "fields": [ + { + "editable": false, + "name": "id", + "primaryKey": true, + "type": "UUID", + }, + { + "editable": true, + "name": "role", + "primaryKey": false, + "type": "String", + }, + ], + }, + "description": "List available fields for Member (members target)", + "inputSchema": { + "properties": {}, + "type": "object", + }, + "name": "myapp_members_member_fields", + }, + { + "description": "List all Car records (app target)", + "inputSchema": { + "properties": {}, + "type": "object", + }, + "name": "myapp_app_car_list", + }, + { + "description": "Get a single Car record by id (app target)", + "inputSchema": { + "properties": { + "id": { + "description": "Car id", + "type": "string", + }, + }, + "required": [ + "id", + ], + "type": "object", + }, + "name": "myapp_app_car_get", + }, + { + "description": "Create a new Car record (app target)", + "inputSchema": { + "properties": { + "isElectric": { + "description": "Car isElectric", + "type": "boolean", + }, + "make": { + "description": "Car make", + "type": "string", + }, + "model": { + "description": "Car model", + "type": "string", + }, + "year": { + "description": "Car year", + "type": "integer", + }, + }, + "required": [ + "make", + "model", + "year", + "isElectric", + ], + "type": "object", + }, + "name": "myapp_app_car_create", + }, + { + "description": "Update an existing Car record (app target)", + "inputSchema": { + "properties": { + "id": { + "description": "Car id", + "type": "string", + }, + "isElectric": { + "description": "Car isElectric", + "type": "boolean", + }, + "make": { + "description": "Car make", + "type": "string", + }, + "model": { + "description": "Car model", + "type": "string", + }, + "year": { + "description": "Car year", + "type": "integer", + }, + }, + "required": [ + "id", + ], + "type": "object", + }, + "name": "myapp_app_car_update", + }, + { + "description": "Delete a Car record by id (app target)", + "inputSchema": { + "properties": { + "id": { + "description": "Car id", + "type": "string", + }, + }, + "required": [ + "id", + ], + "type": "object", + }, + "name": "myapp_app_car_delete", + }, + { + "_meta": { + "fields": [ + { + "editable": false, + "name": "id", + "primaryKey": true, + "type": "UUID", + }, + { + "editable": true, + "name": "make", + "primaryKey": false, + "type": "String", + }, + { + "editable": true, + "name": "model", + "primaryKey": false, + "type": "String", + }, + { + "editable": true, + "name": "year", + "primaryKey": false, + "type": "Int", + }, + { + "editable": true, + "name": "isElectric", + "primaryKey": false, + "type": "Boolean", + }, + { + "editable": false, + "name": "createdAt", + "primaryKey": false, + "type": "Datetime", + }, + ], + }, + "description": "List available fields for Car (app target)", + "inputSchema": { + "properties": {}, + "type": "object", + }, + "name": "myapp_app_car_fields", + }, +] +`; + +exports[`multi-target cli docs generates multi-target README 1`] = ` +"# myapp CLI + +> Auto-generated unified multi-target CLI from GraphQL schemas +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT + +## Setup + +### Create a context + +A context stores per-target endpoint overrides for an environment (dev, staging, production). +Default endpoints are baked in from the codegen config, so local development works with zero configuration. + +\`\`\`bash +# Interactive - prompts for each target endpoint (defaults shown) +myapp context create local + +# Non-interactive +myapp context create production \\ + --auth-endpoint https://auth.prod.example.com/graphql \\ + --members-endpoint https://members.prod.example.com/graphql \\ + --app-endpoint https://app.prod.example.com/graphql +\`\`\` + +### Activate a context + +\`\`\`bash +myapp context use production +\`\`\` + +### Authenticate + +\`\`\`bash +myapp credentials set-token +\`\`\` + +Or authenticate via a login mutation (auto-saves token): + +\`\`\`bash +myapp auth:login --email --password --save-token +\`\`\` + +## API Targets + +| Target | Default Endpoint | Tables | Custom Operations | +|--------|-----------------|--------|-------------------| +| \`auth\` | http://auth.localhost/graphql | 1 | 2 | +| \`members\` | http://members.localhost/graphql | 1 | 0 | +| \`app\` | http://app.localhost/graphql | 1 | 0 | + +## Commands + +### Infrastructure + +| Command | Description | +|---------|-------------| +| \`context\` | Manage API contexts (per-target endpoints) | +| \`credentials\` | Manage authentication tokens | + +### auth + +| Command | Description | +|---------|-------------| +| \`auth:user\` | user CRUD operations | +| \`auth:current-user\` | Get the currently authenticated user | +| \`auth:login\` | Authenticate a user | + +### members + +| Command | Description | +|---------|-------------| +| \`members:member\` | member CRUD operations | + +### app + +| Command | Description | +|---------|-------------| +| \`app:car\` | car CRUD operations | + +## Infrastructure Commands + +### \`context\` + +Manage named API contexts (kubectl-style). Each context stores per-target endpoint overrides. + +| Subcommand | Description | +|------------|-------------| +| \`create \` | Create a new context (prompts for per-target endpoints) | +| \`list\` | List all contexts | +| \`use \` | Set the active context | +| \`current\` | Show current context | +| \`delete \` | Delete a context | + +Create options: + +- \`--auth-endpoint \` (default: http://auth.localhost/graphql) +- \`--members-endpoint \` (default: http://members.localhost/graphql) +- \`--app-endpoint \` (default: http://app.localhost/graphql) + +Configuration is stored at \`~/.myapp/config/\`. + +### \`credentials\` + +Manage authentication tokens per context. One shared token is used across all targets. + +| Subcommand | Description | +|------------|-------------| +| \`set-token \` | Store bearer token for current context | +| \`status\` | Show auth status across all contexts | +| \`logout\` | Remove credentials for current context | + +## auth Commands + +### \`auth:user\` + +CRUD operations for User records. + +| Subcommand | Description | +|------------|-------------| +| \`list\` | List all user records | +| \`get\` | Get a user by id | +| \`create\` | Create a new user | +| \`update\` | Update an existing user | +| \`delete\` | Delete a user | + +**Fields:** + +| Field | Type | +|-------|------| +| \`id\` | UUID | +| \`email\` | String | +| \`name\` | String | + +**Create fields:** \`email\`, \`name\` + +### \`auth:current-user\` + +Get the currently authenticated user + +- **Type:** query +- **Arguments:** none + +### \`auth:login\` + +Authenticate a user + +- **Type:** mutation +- **Arguments:** + + | Argument | Type | + |----------|------| + | \`email\` | String (required) | + | \`password\` | String (required) | +- **Flags:** \`--save-token\` auto-saves returned token to credentials + +## members Commands + +### \`members:member\` + +CRUD operations for Member records. + +| Subcommand | Description | +|------------|-------------| +| \`list\` | List all member records | +| \`get\` | Get a member by id | +| \`create\` | Create a new member | +| \`update\` | Update an existing member | +| \`delete\` | Delete a member | + +**Fields:** + +| Field | Type | +|-------|------| +| \`id\` | UUID | +| \`role\` | String | + +**Create fields:** \`role\` + +## app Commands + +### \`app:car\` + +CRUD operations for Car records. + +| Subcommand | Description | +|------------|-------------| +| \`list\` | List all car records | +| \`get\` | Get a car by id | +| \`create\` | Create a new car | +| \`update\` | Update an existing car | +| \`delete\` | Delete a car | + +**Fields:** + +| Field | Type | +|-------|------| +| \`id\` | UUID | +| \`make\` | String | +| \`model\` | String | +| \`year\` | Int | +| \`isElectric\` | Boolean | +| \`createdAt\` | Datetime | + +**Create fields:** \`make\`, \`model\`, \`year\`, \`isElectric\` + +## Output + +All commands output JSON to stdout. Pipe to \`jq\` for formatting: + +\`\`\`bash +myapp auth:user list | jq '.[]' +myapp auth:user get --id | jq '.' +\`\`\` +" +`; + +exports[`multi-target cli docs generates multi-target skills 1`] = ` +[ + { + "content": "# myapp-context + +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT + +Manage API endpoint contexts for myapp (multi-target: auth, members, app) + +## Usage + +\`\`\`bash +myapp context create +myapp context list +myapp context use +myapp context current +myapp context delete +\`\`\` + +## Examples + +### Create a context for local development (accept all defaults) + +\`\`\`bash +myapp context create local +myapp context use local +\`\`\` + +### Create a production context with custom endpoints + +\`\`\`bash +myapp context create production --auth-endpoint --members-endpoint --app-endpoint +myapp context use production +\`\`\` + +### List and switch contexts + +\`\`\`bash +myapp context list +myapp context use staging +\`\`\` +", + "fileName": "skills/context.md", + }, + { + "content": "# myapp-credentials + +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT + +Manage authentication tokens for myapp (shared across all targets) + +## Usage + +\`\`\`bash +myapp credentials set-token +myapp credentials status +myapp credentials logout +\`\`\` + +## Examples + +### Authenticate with a token + +\`\`\`bash +myapp credentials set-token eyJhbGciOiJIUzI1NiIs... +\`\`\` + +### Check auth status + +\`\`\`bash +myapp credentials status +\`\`\` +", + "fileName": "skills/credentials.md", + }, + { + "content": "# myapp-auth:user + +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT + +CRUD operations for User records via myapp CLI (auth target) + +## Usage + +\`\`\`bash +myapp auth:user list +myapp auth:user get --id +myapp auth:user create --email --name +myapp auth:user update --id [--email ] [--name ] +myapp auth:user delete --id +\`\`\` + +## Examples + +### List all user records + +\`\`\`bash +myapp auth:user list +\`\`\` + +### Create a user + +\`\`\`bash +myapp auth:user create --email "value" --name "value" +\`\`\` + +### Get a user by id + +\`\`\`bash +myapp auth:user get --id +\`\`\` +", + "fileName": "skills/auth-user.md", + }, + { + "content": "# myapp-auth:current-user + +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT + +Get the currently authenticated user (auth target) + +## Usage + +\`\`\`bash +myapp auth:current-user +\`\`\` + +## Examples + +### Run currentUser + +\`\`\`bash +myapp auth:current-user +\`\`\` +", + "fileName": "skills/auth-current-user.md", + }, + { + "content": "# myapp-auth:login + +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT + +Authenticate a user (auth target) + +## Usage + +\`\`\`bash +myapp auth:login --email --password +myapp auth:login --email --password --save-token +\`\`\` + +## Examples + +### Run login + +\`\`\`bash +myapp auth:login --email --password +\`\`\` +", + "fileName": "skills/auth-login.md", + }, + { + "content": "# myapp-members:member + +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT + +CRUD operations for Member records via myapp CLI (members target) + +## Usage + +\`\`\`bash +myapp members:member list +myapp members:member get --id +myapp members:member create --role +myapp members:member update --id [--role ] +myapp members:member delete --id +\`\`\` + +## Examples + +### List all member records + +\`\`\`bash +myapp members:member list +\`\`\` + +### Create a member + +\`\`\`bash +myapp members:member create --role "value" +\`\`\` + +### Get a member by id + +\`\`\`bash +myapp members:member get --id +\`\`\` +", + "fileName": "skills/members-member.md", + }, + { + "content": "# myapp-app:car + +> @generated by @constructive-io/graphql-codegen - DO NOT EDIT + +CRUD operations for Car records via myapp CLI (app target) + +## Usage + +\`\`\`bash +myapp app:car list +myapp app:car get --id +myapp app:car create --make --model --year --isElectric +myapp app:car update --id [--make ] [--model ] [--year ] [--isElectric ] +myapp app:car delete --id +\`\`\` + +## Examples + +### List all car records + +\`\`\`bash +myapp app:car list +\`\`\` + +### Create a car + +\`\`\`bash +myapp app:car create --make "value" --model "value" --year "value" --isElectric "value" +\`\`\` + +### Get a car by id + +\`\`\`bash +myapp app:car get --id +\`\`\` +", + "fileName": "skills/app-car.md", + }, +] +`; + exports[`multi-target cli generator generates credentials command (renamed from auth) 1`] = ` "/** * Authentication commands diff --git a/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts b/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts index 4af63bd2c..296ab336a 100644 --- a/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts +++ b/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts @@ -4,7 +4,12 @@ import { generateAgentsDocs as generateCliAgentsDocs, getCliMcpTools, generateSkills as generateCliSkills, + generateMultiTargetReadme, + generateMultiTargetAgentsDocs, + getMultiTargetCliMcpTools, + generateMultiTargetSkills, } from '../../core/codegen/cli/docs-generator'; +import type { MultiTargetDocsInput } from '../../core/codegen/cli/docs-generator'; import { resolveDocsConfig } from '../../core/codegen/docs-utils'; import { generateOrmReadme, @@ -629,6 +634,88 @@ describe('multi-target cli generator', () => { }); }); +describe('multi-target cli docs', () => { + const docsInput: MultiTargetDocsInput = { + toolName: 'myapp', + infraNames: { auth: 'credentials', context: 'context' }, + targets: [ + { + name: 'auth', + endpoint: 'http://auth.localhost/graphql', + tables: [userTable], + customOperations: [currentUserQuery, loginMutation], + isAuthTarget: true, + }, + { + name: 'members', + endpoint: 'http://members.localhost/graphql', + tables: [memberTable], + customOperations: [], + }, + { + name: 'app', + endpoint: 'http://app.localhost/graphql', + tables: [carTable], + customOperations: [], + }, + ], + }; + + it('generates multi-target README', () => { + const readme = generateMultiTargetReadme(docsInput); + expect(readme.fileName).toBe('README.md'); + expect(readme.content).toContain('myapp'); + expect(readme.content).toContain('auth:user'); + expect(readme.content).toContain('members:member'); + expect(readme.content).toContain('app:car'); + expect(readme.content).toContain('credentials'); + expect(readme.content).toContain('context'); + expect(readme.content).toMatchSnapshot(); + }); + + it('generates multi-target AGENTS.md', () => { + const agents = generateMultiTargetAgentsDocs(docsInput); + expect(agents.fileName).toBe('AGENTS.md'); + expect(agents.content).toContain('auth:user'); + expect(agents.content).toContain('members:member'); + expect(agents.content).toContain('app:car'); + expect(agents.content).toMatchSnapshot(); + }); + + it('generates multi-target MCP tools', () => { + const tools = getMultiTargetCliMcpTools(docsInput); + expect(tools.length).toBeGreaterThan(0); + const toolNames = tools.map((t) => t.name); + expect(toolNames).toContain('myapp_credentials_set_token'); + expect(toolNames).toContain('myapp_context_create'); + expect(toolNames.some((n) => n.includes('auth_user'))).toBe(true); + expect(toolNames.some((n) => n.includes('members_member'))).toBe(true); + expect(toolNames.some((n) => n.includes('app_car'))).toBe(true); + expect(tools).toMatchSnapshot(); + }); + + it('generates multi-target skills', () => { + const skills = generateMultiTargetSkills(docsInput); + expect(skills.length).toBeGreaterThan(0); + const fileNames = skills.map((s) => s.fileName); + expect(fileNames.some((n) => n.includes('auth-'))).toBe(true); + expect(fileNames.some((n) => n.includes('members-'))).toBe(true); + expect(fileNames.some((n) => n.includes('app-'))).toBe(true); + expect(skills).toMatchSnapshot(); + }); + + it('handles collision-renamed infra in docs', () => { + const collisionInput: MultiTargetDocsInput = { + toolName: 'myapp', + infraNames: { auth: 'credentials', context: 'env' }, + targets: docsInput.targets, + }; + const readme = generateMultiTargetReadme(collisionInput); + expect(readme.content).toContain('credentials'); + expect(readme.content).toContain('env'); + }); +}); + describe('multi-target cli with custom infraNames', () => { const result = generateMultiTargetCli({ toolName: 'myapp', diff --git a/graphql/codegen/src/core/codegen/cli/docs-generator.ts b/graphql/codegen/src/core/codegen/cli/docs-generator.ts index 85a513e8f..2e90c342c 100644 --- a/graphql/codegen/src/core/codegen/cli/docs-generator.ts +++ b/graphql/codegen/src/core/codegen/cli/docs-generator.ts @@ -718,3 +718,841 @@ export function generateSkills( return files; } + +export interface MultiTargetDocsInput { + toolName: string; + infraNames: { auth: string; context: string }; + targets: Array<{ + name: string; + endpoint: string; + tables: CleanTable[]; + customOperations: CleanOperation[]; + isAuthTarget?: boolean; + }>; +} + +export function generateMultiTargetReadme( + input: MultiTargetDocsInput, +): GeneratedDocFile { + const { toolName, infraNames, targets } = input; + const lines: string[] = []; + + lines.push(`# ${toolName} CLI`); + lines.push(''); + lines.push('> Auto-generated unified multi-target CLI from GraphQL schemas'); + lines.push('> @generated by @constructive-io/graphql-codegen - DO NOT EDIT'); + lines.push(''); + + lines.push('## Setup'); + lines.push(''); + lines.push('### Create a context'); + lines.push(''); + lines.push('A context stores per-target endpoint overrides for an environment (dev, staging, production).'); + lines.push('Default endpoints are baked in from the codegen config, so local development works with zero configuration.'); + lines.push(''); + lines.push('```bash'); + lines.push(`# Interactive - prompts for each target endpoint (defaults shown)`); + lines.push(`${toolName} ${infraNames.context} create local`); + lines.push(''); + lines.push(`# Non-interactive`); + lines.push(`${toolName} ${infraNames.context} create production \\`); + for (let i = 0; i < targets.length; i++) { + const tgt = targets[i]; + const continuation = i < targets.length - 1 ? ' \\' : ''; + lines.push(` --${tgt.name}-endpoint https://${tgt.name}.prod.example.com/graphql${continuation}`); + } + lines.push('```'); + lines.push(''); + lines.push('### Activate a context'); + lines.push(''); + lines.push('```bash'); + lines.push(`${toolName} ${infraNames.context} use production`); + lines.push('```'); + lines.push(''); + lines.push('### Authenticate'); + lines.push(''); + lines.push('```bash'); + lines.push(`${toolName} ${infraNames.auth} set-token `); + lines.push('```'); + lines.push(''); + + const authTarget = targets.find((t) => t.isAuthTarget); + if (authTarget) { + const authMutation = authTarget.customOperations.find( + (op) => op.kind === 'mutation' && /login|sign.?in|auth/i.test(op.name), + ); + if (authMutation) { + const kebab = toKebabCase(authMutation.name); + lines.push('Or authenticate via a login mutation (auto-saves token):'); + lines.push(''); + lines.push('```bash'); + const flags = authMutation.args.map((a) => `--${a.name} `).join(' '); + lines.push(`${toolName} ${authTarget.name}:${kebab} ${flags} --save-token`); + lines.push('```'); + lines.push(''); + } + } + + lines.push('## API Targets'); + lines.push(''); + lines.push('| Target | Default Endpoint | Tables | Custom Operations |'); + lines.push('|--------|-----------------|--------|-------------------|'); + for (const tgt of targets) { + lines.push(`| \`${tgt.name}\` | ${tgt.endpoint} | ${tgt.tables.length} | ${tgt.customOperations.length} |`); + } + lines.push(''); + + lines.push('## Commands'); + lines.push(''); + lines.push('### Infrastructure'); + lines.push(''); + lines.push('| Command | Description |'); + lines.push('|---------|-------------|'); + lines.push(`| \`${infraNames.context}\` | Manage API contexts (per-target endpoints) |`); + lines.push(`| \`${infraNames.auth}\` | Manage authentication tokens |`); + lines.push(''); + + for (const tgt of targets) { + lines.push(`### ${tgt.name}`); + lines.push(''); + lines.push('| Command | Description |'); + lines.push('|---------|-------------|'); + for (const table of tgt.tables) { + const { singularName } = getTableNames(table); + const kebab = toKebabCase(singularName); + lines.push(`| \`${tgt.name}:${kebab}\` | ${singularName} CRUD operations |`); + } + for (const op of tgt.customOperations) { + const kebab = toKebabCase(op.name); + lines.push(`| \`${tgt.name}:${kebab}\` | ${op.description || op.name} |`); + } + lines.push(''); + } + + lines.push('## Infrastructure Commands'); + lines.push(''); + lines.push(`### \`${infraNames.context}\``); + lines.push(''); + lines.push('Manage named API contexts (kubectl-style). Each context stores per-target endpoint overrides.'); + lines.push(''); + lines.push('| Subcommand | Description |'); + lines.push('|------------|-------------|'); + lines.push('| `create ` | Create a new context (prompts for per-target endpoints) |'); + lines.push('| `list` | List all contexts |'); + lines.push('| `use ` | Set the active context |'); + lines.push('| `current` | Show current context |'); + lines.push('| `delete ` | Delete a context |'); + lines.push(''); + lines.push('Create options:'); + lines.push(''); + for (const tgt of targets) { + lines.push(`- \`--${tgt.name}-endpoint \` (default: ${tgt.endpoint})`); + } + lines.push(''); + lines.push(`Configuration is stored at \`~/.${toolName}/config/\`.`); + lines.push(''); + + lines.push(`### \`${infraNames.auth}\``); + lines.push(''); + lines.push('Manage authentication tokens per context. One shared token is used across all targets.'); + lines.push(''); + lines.push('| Subcommand | Description |'); + lines.push('|------------|-------------|'); + lines.push('| `set-token ` | Store bearer token for current context |'); + lines.push('| `status` | Show auth status across all contexts |'); + lines.push('| `logout` | Remove credentials for current context |'); + lines.push(''); + + for (const tgt of targets) { + if (tgt.tables.length === 0 && tgt.customOperations.length === 0) continue; + lines.push(`## ${tgt.name} Commands`); + lines.push(''); + + for (const table of tgt.tables) { + const { singularName } = getTableNames(table); + const kebab = toKebabCase(singularName); + const pk = getPrimaryKeyInfo(table)[0]; + const scalarFields = getScalarFields(table); + const editableFields = getEditableFields(table); + + lines.push(`### \`${tgt.name}:${kebab}\``); + lines.push(''); + lines.push(`CRUD operations for ${table.name} records.`); + lines.push(''); + lines.push('| Subcommand | Description |'); + lines.push('|------------|-------------|'); + lines.push(`| \`list\` | List all ${singularName} records |`); + lines.push(`| \`get\` | Get a ${singularName} by ${pk.name} |`); + lines.push(`| \`create\` | Create a new ${singularName} |`); + lines.push(`| \`update\` | Update an existing ${singularName} |`); + lines.push(`| \`delete\` | Delete a ${singularName} |`); + lines.push(''); + lines.push('**Fields:**'); + lines.push(''); + lines.push('| Field | Type |'); + lines.push('|-------|------|'); + for (const f of scalarFields) { + lines.push(`| \`${f.name}\` | ${f.type.gqlType} |`); + } + lines.push(''); + lines.push(`**Create fields:** ${editableFields.map((f) => `\`${f.name}\``).join(', ')}`); + lines.push(''); + } + + for (const op of tgt.customOperations) { + const kebab = toKebabCase(op.name); + lines.push(`### \`${tgt.name}:${kebab}\``); + lines.push(''); + lines.push(op.description || op.name); + lines.push(''); + lines.push(`- **Type:** ${op.kind}`); + if (op.args.length > 0) { + lines.push('- **Arguments:**'); + lines.push(''); + lines.push(' | Argument | Type |'); + lines.push(' |----------|------|'); + for (const arg of op.args) { + lines.push(` | \`${arg.name}\` | ${formatArgType(arg)} |`); + } + } else { + lines.push('- **Arguments:** none'); + } + if (tgt.isAuthTarget && op.kind === 'mutation') { + lines.push(`- **Flags:** \`--save-token\` auto-saves returned token to credentials`); + } + lines.push(''); + } + } + + lines.push('## Output'); + lines.push(''); + lines.push('All commands output JSON to stdout. Pipe to `jq` for formatting:'); + lines.push(''); + lines.push('```bash'); + if (targets.length > 0 && targets[0].tables.length > 0) { + const tgt = targets[0]; + const kebab = toKebabCase(getTableNames(tgt.tables[0]).singularName); + lines.push(`${toolName} ${tgt.name}:${kebab} list | jq '.[]'`); + lines.push(`${toolName} ${tgt.name}:${kebab} get --id | jq '.'`); + } + lines.push('```'); + lines.push(''); + + return { + fileName: 'README.md', + content: lines.join('\n'), + }; +} + +export function generateMultiTargetAgentsDocs( + input: MultiTargetDocsInput, +): GeneratedDocFile { + const { toolName, infraNames, targets } = input; + const lines: string[] = []; + + lines.push(`# ${toolName} CLI - Agent Reference`); + lines.push(''); + lines.push('> @generated by @constructive-io/graphql-codegen - DO NOT EDIT'); + lines.push('> This document is structured for LLM/agent consumption.'); + lines.push(''); + + lines.push('## OVERVIEW'); + lines.push(''); + lines.push(`\`${toolName}\` is a unified multi-target CLI for interacting with multiple GraphQL APIs.`); + lines.push('All commands output JSON to stdout. All commands accept `--help` or `-h` for usage.'); + lines.push(`Configuration is stored at \`~/.${toolName}/config/\` via appstash.`); + lines.push(''); + lines.push('TARGETS:'); + for (const tgt of targets) { + lines.push(` ${tgt.name}: ${tgt.endpoint}`); + } + lines.push(''); + lines.push('COMMAND FORMAT:'); + lines.push(` ${toolName} : [flags] Target-specific commands`); + lines.push(` ${toolName} ${infraNames.context} [flags] Context management`); + lines.push(` ${toolName} ${infraNames.auth} [flags] Authentication`); + lines.push(''); + + lines.push('## PREREQUISITES'); + lines.push(''); + lines.push('Before running any data commands, you must:'); + lines.push(''); + lines.push(`1. Create a context: \`${toolName} ${infraNames.context} create \``); + lines.push(` (prompts for per-target endpoints, defaults baked from config)`); + lines.push(`2. Activate it: \`${toolName} ${infraNames.context} use \``); + lines.push(`3. Authenticate: \`${toolName} ${infraNames.auth} set-token \``); + lines.push(''); + lines.push('For local development, create a context accepting all defaults:'); + lines.push(''); + lines.push('```bash'); + lines.push(`${toolName} ${infraNames.context} create local`); + lines.push(`${toolName} ${infraNames.context} use local`); + lines.push(`${toolName} ${infraNames.auth} set-token `); + lines.push('```'); + lines.push(''); + + lines.push('## TOOLS'); + lines.push(''); + + lines.push(`### TOOL: ${infraNames.context}`); + lines.push(''); + lines.push('Manage named API endpoint contexts. Each context stores per-target endpoint overrides.'); + lines.push(''); + lines.push('```'); + lines.push('SUBCOMMANDS:'); + lines.push(` ${toolName} ${infraNames.context} create Create a new context`); + lines.push(` ${toolName} ${infraNames.context} list List all contexts`); + lines.push(` ${toolName} ${infraNames.context} use Set active context`); + lines.push(` ${toolName} ${infraNames.context} current Show active context`); + lines.push(` ${toolName} ${infraNames.context} delete Delete a context`); + lines.push(''); + lines.push('CREATE OPTIONS:'); + for (const tgt of targets) { + lines.push(` --${tgt.name}-endpoint: string (default: ${tgt.endpoint})`); + } + lines.push(''); + lines.push('OUTPUT: JSON'); + lines.push(' create: { name, endpoint, targets }'); + lines.push(' list: [{ name, endpoint, isCurrent, hasCredentials }]'); + lines.push(' use: { name, endpoint }'); + lines.push(' current: { name, endpoint }'); + lines.push(' delete: { deleted: name }'); + lines.push('```'); + lines.push(''); + + lines.push(`### TOOL: ${infraNames.auth}`); + lines.push(''); + lines.push('Manage authentication tokens per context. One shared token across all targets.'); + lines.push(''); + lines.push('```'); + lines.push('SUBCOMMANDS:'); + lines.push(` ${toolName} ${infraNames.auth} set-token Store bearer token for current context`); + lines.push(` ${toolName} ${infraNames.auth} status Show auth status for all contexts`); + lines.push(` ${toolName} ${infraNames.auth} logout Remove credentials for current context`); + lines.push(''); + lines.push('INPUT:'); + lines.push(' token: string (required for set-token) - Bearer token value'); + lines.push(''); + lines.push('OUTPUT: JSON'); + lines.push(' set-token: { context, status: "authenticated" }'); + lines.push(' status: [{ context, authenticated: boolean }]'); + lines.push(' logout: { context, status: "logged out" }'); + lines.push('```'); + lines.push(''); + + for (const tgt of targets) { + for (const table of tgt.tables) { + const { singularName } = getTableNames(table); + const kebab = toKebabCase(singularName); + const pk = getPrimaryKeyInfo(table)[0]; + const scalarFields = getScalarFields(table); + const editableFields = getEditableFields(table); + + lines.push(`### TOOL: ${tgt.name}:${kebab}`); + lines.push(''); + lines.push(`CRUD operations for ${table.name} records (${tgt.name} target).`); + lines.push(''); + lines.push('```'); + lines.push('SUBCOMMANDS:'); + lines.push(` ${toolName} ${tgt.name}:${kebab} list List all records`); + lines.push(` ${toolName} ${tgt.name}:${kebab} get --${pk.name} Get one record`); + lines.push(` ${toolName} ${tgt.name}:${kebab} create ${editableFields.map((f) => `--${f.name} `).join(' ')}`); + lines.push(` ${toolName} ${tgt.name}:${kebab} update --${pk.name} ${editableFields.map((f) => `[--${f.name} ]`).join(' ')}`); + lines.push(` ${toolName} ${tgt.name}:${kebab} delete --${pk.name} Delete one record`); + lines.push(''); + lines.push('INPUT FIELDS:'); + for (const f of scalarFields) { + const isPk = f.name === pk.name; + lines.push(` ${f.name}: ${f.type.gqlType}${isPk ? ' (primary key)' : ''}`); + } + lines.push(''); + lines.push('EDITABLE FIELDS (for create/update):'); + for (const f of editableFields) { + lines.push(` ${f.name}: ${f.type.gqlType}`); + } + lines.push(''); + lines.push('OUTPUT: JSON'); + lines.push(` list: [{ ${scalarFields.map((f) => f.name).join(', ')} }]`); + lines.push(` get: { ${scalarFields.map((f) => f.name).join(', ')} }`); + lines.push(` create: { ${scalarFields.map((f) => f.name).join(', ')} }`); + lines.push(` update: { ${scalarFields.map((f) => f.name).join(', ')} }`); + lines.push(` delete: { ${pk.name} }`); + lines.push('```'); + lines.push(''); + } + + for (const op of tgt.customOperations) { + const kebab = toKebabCase(op.name); + + lines.push(`### TOOL: ${tgt.name}:${kebab}`); + lines.push(''); + lines.push(op.description || op.name); + lines.push(''); + lines.push('```'); + lines.push(`TYPE: ${op.kind}`); + if (op.args.length > 0) { + const flags = op.args.map((a) => `--${a.name} `).join(' '); + lines.push(`USAGE: ${toolName} ${tgt.name}:${kebab} ${flags}`); + lines.push(''); + lines.push('INPUT:'); + for (const arg of op.args) { + lines.push(` ${arg.name}: ${formatArgType(arg)}`); + } + } else { + lines.push(`USAGE: ${toolName} ${tgt.name}:${kebab}`); + lines.push(''); + lines.push('INPUT: none'); + } + if (tgt.isAuthTarget && op.kind === 'mutation') { + lines.push(''); + lines.push('FLAGS:'); + lines.push(' --save-token: boolean - Auto-save returned token to credentials'); + } + lines.push(''); + lines.push('OUTPUT: JSON'); + lines.push('```'); + lines.push(''); + } + } + + lines.push('## WORKFLOWS'); + lines.push(''); + lines.push('### Initial setup'); + lines.push(''); + lines.push('```bash'); + lines.push(`${toolName} ${infraNames.context} create dev`); + lines.push(`${toolName} ${infraNames.context} use dev`); + lines.push(`${toolName} ${infraNames.auth} set-token eyJhbGciOiJIUzI1NiIs...`); + lines.push('```'); + lines.push(''); + + lines.push('### Switch environment'); + lines.push(''); + lines.push('```bash'); + lines.push(`${toolName} ${infraNames.context} create production \\`); + for (let i = 0; i < targets.length; i++) { + const tgt = targets[i]; + const continuation = i < targets.length - 1 ? ' \\' : ''; + lines.push(` --${tgt.name}-endpoint https://${tgt.name}.prod.example.com/graphql${continuation}`); + } + lines.push(`${toolName} ${infraNames.context} use production`); + lines.push('```'); + lines.push(''); + + if (targets.length > 0 && targets[0].tables.length > 0) { + const tgt = targets[0]; + const table = tgt.tables[0]; + const { singularName } = getTableNames(table); + const kebab = toKebabCase(singularName); + const editableFields = getEditableFields(table); + const pk = getPrimaryKeyInfo(table)[0]; + + lines.push(`### CRUD workflow (${tgt.name}:${kebab})`); + lines.push(''); + lines.push('```bash'); + lines.push(`${toolName} ${tgt.name}:${kebab} list`); + lines.push(`${toolName} ${tgt.name}:${kebab} create ${editableFields.map((f) => `--${f.name} "value"`).join(' ')}`); + lines.push(`${toolName} ${tgt.name}:${kebab} get --${pk.name} `); + lines.push(`${toolName} ${tgt.name}:${kebab} update --${pk.name} --${editableFields[0]?.name || 'field'} "new-value"`); + lines.push(`${toolName} ${tgt.name}:${kebab} delete --${pk.name} `); + lines.push('```'); + lines.push(''); + } + + lines.push('### Piping output'); + lines.push(''); + lines.push('```bash'); + if (targets.length > 0 && targets[0].tables.length > 0) { + const tgt = targets[0]; + const kebab = toKebabCase(getTableNames(tgt.tables[0]).singularName); + lines.push(`${toolName} ${tgt.name}:${kebab} list | jq '.'`); + lines.push(`${toolName} ${tgt.name}:${kebab} list | jq '.[].id'`); + lines.push(`${toolName} ${tgt.name}:${kebab} list | jq 'length'`); + } + lines.push('```'); + lines.push(''); + + lines.push('## ERROR HANDLING'); + lines.push(''); + lines.push('All errors are written to stderr. Exit codes:'); + lines.push('- `0`: Success'); + lines.push('- `1`: Error (auth failure, not found, validation error, network error)'); + lines.push(''); + lines.push('Common errors:'); + lines.push(`- "No active context": Run \`${infraNames.context} use \` first`); + lines.push(`- "Not authenticated": Run \`${infraNames.auth} set-token \` first`); + lines.push('- "Unknown target": The target name is not recognized'); + lines.push('- "Record not found": The requested ID does not exist'); + lines.push(''); + + return { + fileName: 'AGENTS.md', + content: lines.join('\n'), + }; +} + +export function getMultiTargetCliMcpTools( + input: MultiTargetDocsInput, +): McpTool[] { + const { toolName, infraNames, targets } = input; + const tools: McpTool[] = []; + + const contextEndpointProps: Record = { + name: { type: 'string', description: 'Context name' }, + }; + for (const tgt of targets) { + contextEndpointProps[`${tgt.name}_endpoint`] = { + type: 'string', + description: `${tgt.name} GraphQL endpoint (default: ${tgt.endpoint})`, + }; + } + tools.push({ + name: `${toolName}_${infraNames.context}_create`, + description: 'Create a named API context with per-target endpoint overrides', + inputSchema: { + type: 'object', + properties: contextEndpointProps, + required: ['name'], + }, + }); + + tools.push({ + name: `${toolName}_${infraNames.context}_list`, + description: 'List all configured API contexts', + inputSchema: { type: 'object', properties: {} }, + }); + + tools.push({ + name: `${toolName}_${infraNames.context}_use`, + description: 'Set the active API context (switches all targets at once)', + inputSchema: { + type: 'object', + properties: { + name: { type: 'string', description: 'Context name to activate' }, + }, + required: ['name'], + }, + }); + + tools.push({ + name: `${toolName}_${infraNames.context}_current`, + description: 'Show the currently active API context', + inputSchema: { type: 'object', properties: {} }, + }); + + tools.push({ + name: `${toolName}_${infraNames.context}_delete`, + description: 'Delete an API context', + inputSchema: { + type: 'object', + properties: { + name: { type: 'string', description: 'Context name to delete' }, + }, + required: ['name'], + }, + }); + + tools.push({ + name: `${toolName}_${infraNames.auth}_set_token`, + description: 'Store a bearer token for the current context (shared across all targets)', + inputSchema: { + type: 'object', + properties: { + token: { type: 'string', description: 'Bearer token value' }, + }, + required: ['token'], + }, + }); + + tools.push({ + name: `${toolName}_${infraNames.auth}_status`, + description: 'Show authentication status for all contexts', + inputSchema: { type: 'object', properties: {} }, + }); + + tools.push({ + name: `${toolName}_${infraNames.auth}_logout`, + description: 'Remove credentials for the current context', + inputSchema: { type: 'object', properties: {} }, + }); + + for (const tgt of targets) { + for (const table of tgt.tables) { + const { singularName } = getTableNames(table); + const kebab = toKebabCase(singularName); + const pk = getPrimaryKeyInfo(table)[0]; + const scalarFields = getScalarFields(table); + const editableFields = getEditableFields(table); + const prefix = `${toolName}_${tgt.name}_${kebab}`; + + tools.push({ + name: `${prefix}_list`, + description: `List all ${table.name} records (${tgt.name} target)`, + inputSchema: { type: 'object', properties: {} }, + }); + + tools.push({ + name: `${prefix}_get`, + description: `Get a single ${table.name} record by ${pk.name} (${tgt.name} target)`, + inputSchema: { + type: 'object', + properties: { + [pk.name]: { + type: gqlTypeToJsonSchemaType(pk.gqlType), + description: `${table.name} ${pk.name}`, + }, + }, + required: [pk.name], + }, + }); + + const createProps: Record = {}; + for (const f of editableFields) { + createProps[f.name] = { + type: gqlTypeToJsonSchemaType(f.type.gqlType), + description: `${table.name} ${f.name}`, + }; + } + tools.push({ + name: `${prefix}_create`, + description: `Create a new ${table.name} record (${tgt.name} target)`, + inputSchema: { + type: 'object', + properties: createProps, + required: editableFields.map((f) => f.name), + }, + }); + + const updateProps: Record = { + [pk.name]: { + type: gqlTypeToJsonSchemaType(pk.gqlType), + description: `${table.name} ${pk.name}`, + }, + }; + for (const f of editableFields) { + updateProps[f.name] = { + type: gqlTypeToJsonSchemaType(f.type.gqlType), + description: `${table.name} ${f.name}`, + }; + } + tools.push({ + name: `${prefix}_update`, + description: `Update an existing ${table.name} record (${tgt.name} target)`, + inputSchema: { + type: 'object', + properties: updateProps, + required: [pk.name], + }, + }); + + tools.push({ + name: `${prefix}_delete`, + description: `Delete a ${table.name} record by ${pk.name} (${tgt.name} target)`, + inputSchema: { + type: 'object', + properties: { + [pk.name]: { + type: gqlTypeToJsonSchemaType(pk.gqlType), + description: `${table.name} ${pk.name}`, + }, + }, + required: [pk.name], + }, + }); + + tools.push({ + name: `${prefix}_fields`, + description: `List available fields for ${table.name} (${tgt.name} target)`, + inputSchema: { type: 'object', properties: {} }, + _meta: { + fields: scalarFields.map((f) => ({ + name: f.name, + type: f.type.gqlType, + editable: editableFields.some((ef) => ef.name === f.name), + primaryKey: f.name === pk.name, + })), + }, + }); + } + + for (const op of tgt.customOperations) { + const kebab = toKebabCase(op.name); + const props: Record = {}; + const required: string[] = []; + + for (const arg of op.args) { + const isRequired = arg.type.kind === 'NON_NULL'; + const baseType = isRequired && arg.type.ofType ? arg.type.ofType : arg.type; + props[arg.name] = { + type: gqlTypeToJsonSchemaType(baseType.name ?? 'String'), + description: arg.description || arg.name, + }; + if (isRequired) { + required.push(arg.name); + } + } + + if (tgt.isAuthTarget && op.kind === 'mutation') { + props['save_token'] = { + type: 'boolean', + description: 'Auto-save returned token to credentials', + }; + } + + tools.push({ + name: `${toolName}_${tgt.name}_${kebab}`, + description: `${op.description || op.name} (${tgt.name} target)`, + inputSchema: { + type: 'object', + properties: props, + ...(required.length > 0 ? { required } : {}), + }, + }); + } + } + + return tools; +} + +export function generateMultiTargetSkills( + input: MultiTargetDocsInput, +): GeneratedDocFile[] { + const { toolName, infraNames, targets } = input; + const files: GeneratedDocFile[] = []; + + const contextUsage = [ + `${toolName} ${infraNames.context} create `, + `${toolName} ${infraNames.context} list`, + `${toolName} ${infraNames.context} use `, + `${toolName} ${infraNames.context} current`, + `${toolName} ${infraNames.context} delete `, + ]; + const contextCreateFlags = targets + .map((t) => `--${t.name}-endpoint `) + .join(' '); + files.push({ + fileName: `skills/${infraNames.context}.md`, + content: buildSkillFile({ + name: `${toolName}-${infraNames.context}`, + description: `Manage API endpoint contexts for ${toolName} (multi-target: ${targets.map((t) => t.name).join(', ')})`, + usage: contextUsage, + examples: [ + { + description: 'Create a context for local development (accept all defaults)', + code: [ + `${toolName} ${infraNames.context} create local`, + `${toolName} ${infraNames.context} use local`, + ], + }, + { + description: 'Create a production context with custom endpoints', + code: [ + `${toolName} ${infraNames.context} create production ${contextCreateFlags}`, + `${toolName} ${infraNames.context} use production`, + ], + }, + { + description: 'List and switch contexts', + code: [ + `${toolName} ${infraNames.context} list`, + `${toolName} ${infraNames.context} use staging`, + ], + }, + ], + }), + }); + + files.push({ + fileName: `skills/${infraNames.auth}.md`, + content: buildSkillFile({ + name: `${toolName}-${infraNames.auth}`, + description: `Manage authentication tokens for ${toolName} (shared across all targets)`, + usage: [ + `${toolName} ${infraNames.auth} set-token `, + `${toolName} ${infraNames.auth} status`, + `${toolName} ${infraNames.auth} logout`, + ], + examples: [ + { + description: 'Authenticate with a token', + code: [`${toolName} ${infraNames.auth} set-token eyJhbGciOiJIUzI1NiIs...`], + }, + { + description: 'Check auth status', + code: [`${toolName} ${infraNames.auth} status`], + }, + ], + }), + }); + + for (const tgt of targets) { + for (const table of tgt.tables) { + const { singularName } = getTableNames(table); + const kebab = toKebabCase(singularName); + const pk = getPrimaryKeyInfo(table)[0]; + const editableFields = getEditableFields(table); + const cmd = `${tgt.name}:${kebab}`; + + files.push({ + fileName: `skills/${tgt.name}-${kebab}.md`, + content: buildSkillFile({ + name: `${toolName}-${cmd}`, + description: `CRUD operations for ${table.name} records via ${toolName} CLI (${tgt.name} target)`, + usage: [ + `${toolName} ${cmd} list`, + `${toolName} ${cmd} get --${pk.name} `, + `${toolName} ${cmd} create ${editableFields.map((f) => `--${f.name} `).join(' ')}`, + `${toolName} ${cmd} update --${pk.name} ${editableFields.map((f) => `[--${f.name} ]`).join(' ')}`, + `${toolName} ${cmd} delete --${pk.name} `, + ], + examples: [ + { + description: `List all ${singularName} records`, + code: [`${toolName} ${cmd} list`], + }, + { + description: `Create a ${singularName}`, + code: [ + `${toolName} ${cmd} create ${editableFields.map((f) => `--${f.name} "value"`).join(' ')}`, + ], + }, + { + description: `Get a ${singularName} by ${pk.name}`, + code: [`${toolName} ${cmd} get --${pk.name} `], + }, + ], + }), + }); + } + + for (const op of tgt.customOperations) { + const kebab = toKebabCase(op.name); + const cmd = `${tgt.name}:${kebab}`; + const baseUsage = + op.args.length > 0 + ? `${toolName} ${cmd} ${op.args.map((a) => `--${a.name} `).join(' ')}` + : `${toolName} ${cmd}`; + const usageLines = [baseUsage]; + if (tgt.isAuthTarget && op.kind === 'mutation') { + usageLines.push(`${baseUsage} --save-token`); + } + + files.push({ + fileName: `skills/${tgt.name}-${kebab}.md`, + content: buildSkillFile({ + name: `${toolName}-${cmd}`, + description: `${op.description || `Execute the ${op.name} ${op.kind}`} (${tgt.name} target)`, + usage: usageLines, + examples: [ + { + description: `Run ${op.name}`, + code: [baseUsage], + }, + ], + }), + }); + } + } + + return files; +} diff --git a/graphql/codegen/src/core/codegen/cli/index.ts b/graphql/codegen/src/core/codegen/cli/index.ts index e7ff52826..a90877c48 100644 --- a/graphql/codegen/src/core/codegen/cli/index.ts +++ b/graphql/codegen/src/core/codegen/cli/index.ts @@ -226,7 +226,12 @@ export { generateAgentsDocs, getCliMcpTools, generateSkills, + generateMultiTargetReadme, + generateMultiTargetAgentsDocs, + getMultiTargetCliMcpTools, + generateMultiTargetSkills, } from './docs-generator'; +export type { MultiTargetDocsInput } from './docs-generator'; export { resolveDocsConfig } from '../docs-utils'; export type { GeneratedDocFile, McpTool } from '../docs-utils'; export type { GeneratedFile, MultiTargetExecutorInput } from './executor-generator'; diff --git a/graphql/codegen/src/core/generate.ts b/graphql/codegen/src/core/generate.ts index cfdeb8b0f..6b799eaa6 100644 --- a/graphql/codegen/src/core/generate.ts +++ b/graphql/codegen/src/core/generate.ts @@ -18,7 +18,12 @@ import { generateAgentsDocs as generateCliAgentsDocs, getCliMcpTools, generateSkills as generateCliSkills, + generateMultiTargetReadme, + generateMultiTargetAgentsDocs, + getMultiTargetCliMcpTools, + generateMultiTargetSkills, } from './codegen/cli/docs-generator'; +import type { MultiTargetDocsInput } from './codegen/cli/docs-generator'; import { resolveDocsConfig } from './codegen/docs-utils'; import type { McpTool } from './codegen/docs-utils'; import { @@ -457,6 +462,52 @@ export async function generateMulti( content: file.content, })); + const firstTargetDocsConfig = names.length > 0 && configs[names[0]]?.docs; + const docsConfig = resolveDocsConfig(firstTargetDocsConfig); + const { resolveInfraNames } = await import('./codegen/cli'); + const infraNames = resolveInfraNames( + cliTargets.map((t) => t.name), + cliConfig.infraNames, + ); + + const docsInput: MultiTargetDocsInput = { + toolName, + infraNames, + targets: cliTargets.map((t) => ({ + name: t.name, + endpoint: t.endpoint, + tables: t.tables, + customOperations: [ + ...(t.customOperations?.queries ?? []), + ...(t.customOperations?.mutations ?? []), + ], + isAuthTarget: t.isAuthTarget, + })), + }; + + const allMcpTools: McpTool[] = []; + + if (docsConfig.readme) { + const readme = generateMultiTargetReadme(docsInput); + cliFilesToWrite.push({ path: path.posix.join('cli', readme.fileName), content: readme.content }); + } + if (docsConfig.agents) { + const agents = generateMultiTargetAgentsDocs(docsInput); + cliFilesToWrite.push({ path: path.posix.join('cli', agents.fileName), content: agents.content }); + } + if (docsConfig.mcp) { + allMcpTools.push(...getMultiTargetCliMcpTools(docsInput)); + } + if (docsConfig.skills) { + for (const skill of generateMultiTargetSkills(docsInput)) { + cliFilesToWrite.push({ path: path.posix.join('cli', skill.fileName), content: skill.content }); + } + } + if (docsConfig.mcp && allMcpTools.length > 0) { + const mcpFile = generateCombinedMcpConfig(allMcpTools, toolName); + cliFilesToWrite.push({ path: path.posix.join('cli', mcpFile.fileName), content: mcpFile.content }); + } + const { writeGeneratedFiles: writeFiles } = await import('./output'); await writeFiles(cliFilesToWrite, '.', [], { pruneStaleFiles: false }); } From 1721182104c9db0a365112acdbcb67a55bbcedb1 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Tue, 17 Feb 2026 23:42:21 +0000 Subject: [PATCH 08/23] refactor(codegen): rename infraNames to builtinNames --- .../__tests__/codegen/cli-generator.test.ts | 26 ++-- .../core/codegen/cli/command-map-generator.ts | 20 +-- .../src/core/codegen/cli/docs-generator.ts | 132 +++++++++--------- graphql/codegen/src/core/codegen/cli/index.ts | 16 +-- graphql/codegen/src/core/generate.ts | 10 +- graphql/codegen/src/types/config.ts | 4 +- 6 files changed, 104 insertions(+), 104 deletions(-) diff --git a/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts b/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts index 296ab336a..47bc8f53b 100644 --- a/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts +++ b/graphql/codegen/src/__tests__/codegen/cli-generator.test.ts @@ -1,4 +1,4 @@ -import { generateCli, generateMultiTargetCli, resolveInfraNames } from '../../core/codegen/cli'; +import { generateCli, generateMultiTargetCli, resolveBuiltinNames } from '../../core/codegen/cli'; import { generateReadme as generateCliReadme, generateAgentsDocs as generateCliAgentsDocs, @@ -415,30 +415,30 @@ describe('resolveDocsConfig', () => { }); }); -describe('resolveInfraNames', () => { +describe('resolveBuiltinNames', () => { it('uses defaults when no collisions', () => { - expect(resolveInfraNames(['app', 'members'])).toEqual({ + expect(resolveBuiltinNames(['app', 'members'])).toEqual({ auth: 'auth', context: 'context', }); }); it('renames auth to credentials on collision', () => { - expect(resolveInfraNames(['auth', 'members', 'app'])).toEqual({ + expect(resolveBuiltinNames(['auth', 'members', 'app'])).toEqual({ auth: 'credentials', context: 'context', }); }); it('renames context to env on collision', () => { - expect(resolveInfraNames(['context', 'app'])).toEqual({ + expect(resolveBuiltinNames(['context', 'app'])).toEqual({ auth: 'auth', context: 'env', }); }); it('renames both on collision', () => { - expect(resolveInfraNames(['auth', 'context', 'app'])).toEqual({ + expect(resolveBuiltinNames(['auth', 'context', 'app'])).toEqual({ auth: 'credentials', context: 'env', }); @@ -446,7 +446,7 @@ describe('resolveInfraNames', () => { it('respects user overrides even with collisions', () => { expect( - resolveInfraNames(['auth', 'app'], { auth: 'auth' }), + resolveBuiltinNames(['auth', 'app'], { auth: 'auth' }), ).toEqual({ auth: 'auth', context: 'context', @@ -455,7 +455,7 @@ describe('resolveInfraNames', () => { it('uses user override names', () => { expect( - resolveInfraNames(['app'], { auth: 'creds', context: 'profile' }), + resolveBuiltinNames(['app'], { auth: 'creds', context: 'profile' }), ).toEqual({ auth: 'creds', context: 'profile', @@ -637,7 +637,7 @@ describe('multi-target cli generator', () => { describe('multi-target cli docs', () => { const docsInput: MultiTargetDocsInput = { toolName: 'myapp', - infraNames: { auth: 'credentials', context: 'context' }, + builtinNames: { auth: 'credentials', context: 'context' }, targets: [ { name: 'auth', @@ -707,7 +707,7 @@ describe('multi-target cli docs', () => { it('handles collision-renamed infra in docs', () => { const collisionInput: MultiTargetDocsInput = { toolName: 'myapp', - infraNames: { auth: 'credentials', context: 'env' }, + builtinNames: { auth: 'credentials', context: 'env' }, targets: docsInput.targets, }; const readme = generateMultiTargetReadme(collisionInput); @@ -716,10 +716,10 @@ describe('multi-target cli docs', () => { }); }); -describe('multi-target cli with custom infraNames', () => { +describe('multi-target cli with custom builtinNames', () => { const result = generateMultiTargetCli({ toolName: 'myapp', - infraNames: { auth: 'creds', context: 'profile' }, + builtinNames: { auth: 'creds', context: 'profile' }, targets: [ { name: 'auth', @@ -738,7 +738,7 @@ describe('multi-target cli with custom infraNames', () => { ], }); - it('uses custom infraNames from config', () => { + it('uses custom builtinNames from config', () => { const fileNames = result.files.map((f) => f.fileName).sort(); expect(fileNames).toContain('commands/creds.ts'); expect(fileNames).toContain('commands/profile.ts'); diff --git a/graphql/codegen/src/core/codegen/cli/command-map-generator.ts b/graphql/codegen/src/core/codegen/cli/command-map-generator.ts index 8a2991ab2..15f9ac71f 100644 --- a/graphql/codegen/src/core/codegen/cli/command-map-generator.ts +++ b/graphql/codegen/src/core/codegen/cli/command-map-generator.ts @@ -383,7 +383,7 @@ export function generateCommandMap( export interface MultiTargetCommandMapInput { toolName: string; - infraNames: { auth: string; context: string }; + builtinNames: { auth: string; context: string }; targets: Array<{ name: string; tables: CleanTable[]; @@ -394,7 +394,7 @@ export interface MultiTargetCommandMapInput { export function generateMultiTargetCommandMap( input: MultiTargetCommandMapInput, ): GeneratedFile { - const { toolName, infraNames, targets } = input; + const { toolName, builtinNames, targets } = input; const statements: t.Statement[] = []; statements.push( @@ -407,16 +407,16 @@ export function generateMultiTargetCommandMap( const commandEntries: { kebab: string; importName: string }[] = []; - const contextImportName = `${infraNames.context}Cmd`; - commandEntries.push({ kebab: infraNames.context, importName: contextImportName }); + const contextImportName = `${builtinNames.context}Cmd`; + commandEntries.push({ kebab: builtinNames.context, importName: contextImportName }); statements.push( - createImportDeclaration(`./commands/${infraNames.context}`, contextImportName), + createImportDeclaration(`./commands/${builtinNames.context}`, contextImportName), ); - const authImportName = `${infraNames.auth}Cmd`; - commandEntries.push({ kebab: infraNames.auth, importName: authImportName }); + const authImportName = `${builtinNames.auth}Cmd`; + commandEntries.push({ kebab: builtinNames.auth, importName: authImportName }); statements.push( - createImportDeclaration(`./commands/${infraNames.auth}`, authImportName), + createImportDeclaration(`./commands/${builtinNames.auth}`, authImportName), ); for (const target of targets) { @@ -465,8 +465,8 @@ export function generateMultiTargetCommandMap( `${toolName} `, '', 'Commands:', - ` ${infraNames.context.padEnd(20)} Manage API contexts`, - ` ${infraNames.auth.padEnd(20)} Manage authentication`, + ` ${builtinNames.context.padEnd(20)} Manage API contexts`, + ` ${builtinNames.auth.padEnd(20)} Manage authentication`, ]; for (const target of targets) { diff --git a/graphql/codegen/src/core/codegen/cli/docs-generator.ts b/graphql/codegen/src/core/codegen/cli/docs-generator.ts index 2e90c342c..c039e6c18 100644 --- a/graphql/codegen/src/core/codegen/cli/docs-generator.ts +++ b/graphql/codegen/src/core/codegen/cli/docs-generator.ts @@ -721,7 +721,7 @@ export function generateSkills( export interface MultiTargetDocsInput { toolName: string; - infraNames: { auth: string; context: string }; + builtinNames: { auth: string; context: string }; targets: Array<{ name: string; endpoint: string; @@ -734,7 +734,7 @@ export interface MultiTargetDocsInput { export function generateMultiTargetReadme( input: MultiTargetDocsInput, ): GeneratedDocFile { - const { toolName, infraNames, targets } = input; + const { toolName, builtinNames, targets } = input; const lines: string[] = []; lines.push(`# ${toolName} CLI`); @@ -752,10 +752,10 @@ export function generateMultiTargetReadme( lines.push(''); lines.push('```bash'); lines.push(`# Interactive - prompts for each target endpoint (defaults shown)`); - lines.push(`${toolName} ${infraNames.context} create local`); + lines.push(`${toolName} ${builtinNames.context} create local`); lines.push(''); lines.push(`# Non-interactive`); - lines.push(`${toolName} ${infraNames.context} create production \\`); + lines.push(`${toolName} ${builtinNames.context} create production \\`); for (let i = 0; i < targets.length; i++) { const tgt = targets[i]; const continuation = i < targets.length - 1 ? ' \\' : ''; @@ -766,13 +766,13 @@ export function generateMultiTargetReadme( lines.push('### Activate a context'); lines.push(''); lines.push('```bash'); - lines.push(`${toolName} ${infraNames.context} use production`); + lines.push(`${toolName} ${builtinNames.context} use production`); lines.push('```'); lines.push(''); lines.push('### Authenticate'); lines.push(''); lines.push('```bash'); - lines.push(`${toolName} ${infraNames.auth} set-token `); + lines.push(`${toolName} ${builtinNames.auth} set-token `); lines.push('```'); lines.push(''); @@ -808,8 +808,8 @@ export function generateMultiTargetReadme( lines.push(''); lines.push('| Command | Description |'); lines.push('|---------|-------------|'); - lines.push(`| \`${infraNames.context}\` | Manage API contexts (per-target endpoints) |`); - lines.push(`| \`${infraNames.auth}\` | Manage authentication tokens |`); + lines.push(`| \`${builtinNames.context}\` | Manage API contexts (per-target endpoints) |`); + lines.push(`| \`${builtinNames.auth}\` | Manage authentication tokens |`); lines.push(''); for (const tgt of targets) { @@ -831,7 +831,7 @@ export function generateMultiTargetReadme( lines.push('## Infrastructure Commands'); lines.push(''); - lines.push(`### \`${infraNames.context}\``); + lines.push(`### \`${builtinNames.context}\``); lines.push(''); lines.push('Manage named API contexts (kubectl-style). Each context stores per-target endpoint overrides.'); lines.push(''); @@ -852,7 +852,7 @@ export function generateMultiTargetReadme( lines.push(`Configuration is stored at \`~/.${toolName}/config/\`.`); lines.push(''); - lines.push(`### \`${infraNames.auth}\``); + lines.push(`### \`${builtinNames.auth}\``); lines.push(''); lines.push('Manage authentication tokens per context. One shared token is used across all targets.'); lines.push(''); @@ -947,7 +947,7 @@ export function generateMultiTargetReadme( export function generateMultiTargetAgentsDocs( input: MultiTargetDocsInput, ): GeneratedDocFile { - const { toolName, infraNames, targets } = input; + const { toolName, builtinNames, targets } = input; const lines: string[] = []; lines.push(`# ${toolName} CLI - Agent Reference`); @@ -969,42 +969,42 @@ export function generateMultiTargetAgentsDocs( lines.push(''); lines.push('COMMAND FORMAT:'); lines.push(` ${toolName} : [flags] Target-specific commands`); - lines.push(` ${toolName} ${infraNames.context} [flags] Context management`); - lines.push(` ${toolName} ${infraNames.auth} [flags] Authentication`); + lines.push(` ${toolName} ${builtinNames.context} [flags] Context management`); + lines.push(` ${toolName} ${builtinNames.auth} [flags] Authentication`); lines.push(''); lines.push('## PREREQUISITES'); lines.push(''); lines.push('Before running any data commands, you must:'); lines.push(''); - lines.push(`1. Create a context: \`${toolName} ${infraNames.context} create \``); + lines.push(`1. Create a context: \`${toolName} ${builtinNames.context} create \``); lines.push(` (prompts for per-target endpoints, defaults baked from config)`); - lines.push(`2. Activate it: \`${toolName} ${infraNames.context} use \``); - lines.push(`3. Authenticate: \`${toolName} ${infraNames.auth} set-token \``); + lines.push(`2. Activate it: \`${toolName} ${builtinNames.context} use \``); + lines.push(`3. Authenticate: \`${toolName} ${builtinNames.auth} set-token \``); lines.push(''); lines.push('For local development, create a context accepting all defaults:'); lines.push(''); lines.push('```bash'); - lines.push(`${toolName} ${infraNames.context} create local`); - lines.push(`${toolName} ${infraNames.context} use local`); - lines.push(`${toolName} ${infraNames.auth} set-token `); + lines.push(`${toolName} ${builtinNames.context} create local`); + lines.push(`${toolName} ${builtinNames.context} use local`); + lines.push(`${toolName} ${builtinNames.auth} set-token `); lines.push('```'); lines.push(''); lines.push('## TOOLS'); lines.push(''); - lines.push(`### TOOL: ${infraNames.context}`); + lines.push(`### TOOL: ${builtinNames.context}`); lines.push(''); lines.push('Manage named API endpoint contexts. Each context stores per-target endpoint overrides.'); lines.push(''); lines.push('```'); lines.push('SUBCOMMANDS:'); - lines.push(` ${toolName} ${infraNames.context} create Create a new context`); - lines.push(` ${toolName} ${infraNames.context} list List all contexts`); - lines.push(` ${toolName} ${infraNames.context} use Set active context`); - lines.push(` ${toolName} ${infraNames.context} current Show active context`); - lines.push(` ${toolName} ${infraNames.context} delete Delete a context`); + lines.push(` ${toolName} ${builtinNames.context} create Create a new context`); + lines.push(` ${toolName} ${builtinNames.context} list List all contexts`); + lines.push(` ${toolName} ${builtinNames.context} use Set active context`); + lines.push(` ${toolName} ${builtinNames.context} current Show active context`); + lines.push(` ${toolName} ${builtinNames.context} delete Delete a context`); lines.push(''); lines.push('CREATE OPTIONS:'); for (const tgt of targets) { @@ -1020,15 +1020,15 @@ export function generateMultiTargetAgentsDocs( lines.push('```'); lines.push(''); - lines.push(`### TOOL: ${infraNames.auth}`); + lines.push(`### TOOL: ${builtinNames.auth}`); lines.push(''); lines.push('Manage authentication tokens per context. One shared token across all targets.'); lines.push(''); lines.push('```'); lines.push('SUBCOMMANDS:'); - lines.push(` ${toolName} ${infraNames.auth} set-token Store bearer token for current context`); - lines.push(` ${toolName} ${infraNames.auth} status Show auth status for all contexts`); - lines.push(` ${toolName} ${infraNames.auth} logout Remove credentials for current context`); + lines.push(` ${toolName} ${builtinNames.auth} set-token Store bearer token for current context`); + lines.push(` ${toolName} ${builtinNames.auth} status Show auth status for all contexts`); + lines.push(` ${toolName} ${builtinNames.auth} logout Remove credentials for current context`); lines.push(''); lines.push('INPUT:'); lines.push(' token: string (required for set-token) - Bearer token value'); @@ -1120,22 +1120,22 @@ export function generateMultiTargetAgentsDocs( lines.push('### Initial setup'); lines.push(''); lines.push('```bash'); - lines.push(`${toolName} ${infraNames.context} create dev`); - lines.push(`${toolName} ${infraNames.context} use dev`); - lines.push(`${toolName} ${infraNames.auth} set-token eyJhbGciOiJIUzI1NiIs...`); + lines.push(`${toolName} ${builtinNames.context} create dev`); + lines.push(`${toolName} ${builtinNames.context} use dev`); + lines.push(`${toolName} ${builtinNames.auth} set-token eyJhbGciOiJIUzI1NiIs...`); lines.push('```'); lines.push(''); lines.push('### Switch environment'); lines.push(''); lines.push('```bash'); - lines.push(`${toolName} ${infraNames.context} create production \\`); + lines.push(`${toolName} ${builtinNames.context} create production \\`); for (let i = 0; i < targets.length; i++) { const tgt = targets[i]; const continuation = i < targets.length - 1 ? ' \\' : ''; lines.push(` --${tgt.name}-endpoint https://${tgt.name}.prod.example.com/graphql${continuation}`); } - lines.push(`${toolName} ${infraNames.context} use production`); + lines.push(`${toolName} ${builtinNames.context} use production`); lines.push('```'); lines.push(''); @@ -1179,8 +1179,8 @@ export function generateMultiTargetAgentsDocs( lines.push('- `1`: Error (auth failure, not found, validation error, network error)'); lines.push(''); lines.push('Common errors:'); - lines.push(`- "No active context": Run \`${infraNames.context} use \` first`); - lines.push(`- "Not authenticated": Run \`${infraNames.auth} set-token \` first`); + lines.push(`- "No active context": Run \`${builtinNames.context} use \` first`); + lines.push(`- "Not authenticated": Run \`${builtinNames.auth} set-token \` first`); lines.push('- "Unknown target": The target name is not recognized'); lines.push('- "Record not found": The requested ID does not exist'); lines.push(''); @@ -1194,7 +1194,7 @@ export function generateMultiTargetAgentsDocs( export function getMultiTargetCliMcpTools( input: MultiTargetDocsInput, ): McpTool[] { - const { toolName, infraNames, targets } = input; + const { toolName, builtinNames, targets } = input; const tools: McpTool[] = []; const contextEndpointProps: Record = { @@ -1207,7 +1207,7 @@ export function getMultiTargetCliMcpTools( }; } tools.push({ - name: `${toolName}_${infraNames.context}_create`, + name: `${toolName}_${builtinNames.context}_create`, description: 'Create a named API context with per-target endpoint overrides', inputSchema: { type: 'object', @@ -1217,13 +1217,13 @@ export function getMultiTargetCliMcpTools( }); tools.push({ - name: `${toolName}_${infraNames.context}_list`, + name: `${toolName}_${builtinNames.context}_list`, description: 'List all configured API contexts', inputSchema: { type: 'object', properties: {} }, }); tools.push({ - name: `${toolName}_${infraNames.context}_use`, + name: `${toolName}_${builtinNames.context}_use`, description: 'Set the active API context (switches all targets at once)', inputSchema: { type: 'object', @@ -1235,13 +1235,13 @@ export function getMultiTargetCliMcpTools( }); tools.push({ - name: `${toolName}_${infraNames.context}_current`, + name: `${toolName}_${builtinNames.context}_current`, description: 'Show the currently active API context', inputSchema: { type: 'object', properties: {} }, }); tools.push({ - name: `${toolName}_${infraNames.context}_delete`, + name: `${toolName}_${builtinNames.context}_delete`, description: 'Delete an API context', inputSchema: { type: 'object', @@ -1253,7 +1253,7 @@ export function getMultiTargetCliMcpTools( }); tools.push({ - name: `${toolName}_${infraNames.auth}_set_token`, + name: `${toolName}_${builtinNames.auth}_set_token`, description: 'Store a bearer token for the current context (shared across all targets)', inputSchema: { type: 'object', @@ -1265,13 +1265,13 @@ export function getMultiTargetCliMcpTools( }); tools.push({ - name: `${toolName}_${infraNames.auth}_status`, + name: `${toolName}_${builtinNames.auth}_status`, description: 'Show authentication status for all contexts', inputSchema: { type: 'object', properties: {} }, }); tools.push({ - name: `${toolName}_${infraNames.auth}_logout`, + name: `${toolName}_${builtinNames.auth}_logout`, description: 'Remove credentials for the current context', inputSchema: { type: 'object', properties: {} }, }); @@ -1417,45 +1417,45 @@ export function getMultiTargetCliMcpTools( export function generateMultiTargetSkills( input: MultiTargetDocsInput, ): GeneratedDocFile[] { - const { toolName, infraNames, targets } = input; + const { toolName, builtinNames, targets } = input; const files: GeneratedDocFile[] = []; const contextUsage = [ - `${toolName} ${infraNames.context} create `, - `${toolName} ${infraNames.context} list`, - `${toolName} ${infraNames.context} use `, - `${toolName} ${infraNames.context} current`, - `${toolName} ${infraNames.context} delete `, + `${toolName} ${builtinNames.context} create `, + `${toolName} ${builtinNames.context} list`, + `${toolName} ${builtinNames.context} use `, + `${toolName} ${builtinNames.context} current`, + `${toolName} ${builtinNames.context} delete `, ]; const contextCreateFlags = targets .map((t) => `--${t.name}-endpoint `) .join(' '); files.push({ - fileName: `skills/${infraNames.context}.md`, + fileName: `skills/${builtinNames.context}.md`, content: buildSkillFile({ - name: `${toolName}-${infraNames.context}`, + name: `${toolName}-${builtinNames.context}`, description: `Manage API endpoint contexts for ${toolName} (multi-target: ${targets.map((t) => t.name).join(', ')})`, usage: contextUsage, examples: [ { description: 'Create a context for local development (accept all defaults)', code: [ - `${toolName} ${infraNames.context} create local`, - `${toolName} ${infraNames.context} use local`, + `${toolName} ${builtinNames.context} create local`, + `${toolName} ${builtinNames.context} use local`, ], }, { description: 'Create a production context with custom endpoints', code: [ - `${toolName} ${infraNames.context} create production ${contextCreateFlags}`, - `${toolName} ${infraNames.context} use production`, + `${toolName} ${builtinNames.context} create production ${contextCreateFlags}`, + `${toolName} ${builtinNames.context} use production`, ], }, { description: 'List and switch contexts', code: [ - `${toolName} ${infraNames.context} list`, - `${toolName} ${infraNames.context} use staging`, + `${toolName} ${builtinNames.context} list`, + `${toolName} ${builtinNames.context} use staging`, ], }, ], @@ -1463,23 +1463,23 @@ export function generateMultiTargetSkills( }); files.push({ - fileName: `skills/${infraNames.auth}.md`, + fileName: `skills/${builtinNames.auth}.md`, content: buildSkillFile({ - name: `${toolName}-${infraNames.auth}`, + name: `${toolName}-${builtinNames.auth}`, description: `Manage authentication tokens for ${toolName} (shared across all targets)`, usage: [ - `${toolName} ${infraNames.auth} set-token `, - `${toolName} ${infraNames.auth} status`, - `${toolName} ${infraNames.auth} logout`, + `${toolName} ${builtinNames.auth} set-token `, + `${toolName} ${builtinNames.auth} status`, + `${toolName} ${builtinNames.auth} logout`, ], examples: [ { description: 'Authenticate with a token', - code: [`${toolName} ${infraNames.auth} set-token eyJhbGciOiJIUzI1NiIs...`], + code: [`${toolName} ${builtinNames.auth} set-token eyJhbGciOiJIUzI1NiIs...`], }, { description: 'Check auth status', - code: [`${toolName} ${infraNames.auth} status`], + code: [`${toolName} ${builtinNames.auth} status`], }, ], }), diff --git a/graphql/codegen/src/core/codegen/cli/index.ts b/graphql/codegen/src/core/codegen/cli/index.ts index a90877c48..fd4c696ac 100644 --- a/graphql/codegen/src/core/codegen/cli/index.ts +++ b/graphql/codegen/src/core/codegen/cli/index.ts @@ -1,4 +1,4 @@ -import type { GraphQLSDKConfigTarget, InfraNames } from '../../../types/config'; +import type { BuiltinNames, GraphQLSDKConfigTarget } from '../../../types/config'; import type { CleanOperation, CleanTable } from '../../../types/schema'; import { generateCommandMap, generateMultiTargetCommandMap } from './command-map-generator'; import { generateCustomCommand } from './custom-command-generator'; @@ -99,13 +99,13 @@ export interface MultiTargetCliTarget { export interface GenerateMultiTargetCliOptions { toolName: string; - infraNames?: InfraNames; + builtinNames?: BuiltinNames; targets: MultiTargetCliTarget[]; } -export function resolveInfraNames( +export function resolveBuiltinNames( targetNames: string[], - userOverrides?: InfraNames, + userOverrides?: BuiltinNames, ): { auth: string; context: string } { let authName = userOverrides?.auth ?? 'auth'; let contextName = userOverrides?.context ?? 'context'; @@ -127,7 +127,7 @@ export function generateMultiTargetCli( const files: GeneratedFile[] = []; const targetNames = targets.map((t) => t.name); - const infraNames = resolveInfraNames(targetNames, options.infraNames); + const builtinNames = resolveBuiltinNames(targetNames, options.builtinNames); const executorInputs: MultiTargetExecutorInput[] = targets.map((t) => ({ name: t.name, @@ -139,12 +139,12 @@ export function generateMultiTargetCli( const contextFile = generateMultiTargetContextCommand( toolName, - infraNames.context, + builtinNames.context, targets.map((t) => ({ name: t.name, endpoint: t.endpoint })), ); files.push(contextFile); - const authFile = generateAuthCommandWithName(toolName, infraNames.auth); + const authFile = generateAuthCommandWithName(toolName, builtinNames.auth); files.push(authFile); let totalTables = 0; @@ -194,7 +194,7 @@ export function generateMultiTargetCli( const commandMapFile = generateMultiTargetCommandMap({ toolName, - infraNames, + builtinNames, targets: commandMapTargets, }); files.push(commandMapFile); diff --git a/graphql/codegen/src/core/generate.ts b/graphql/codegen/src/core/generate.ts index 6b799eaa6..abb24ebb4 100644 --- a/graphql/codegen/src/core/generate.ts +++ b/graphql/codegen/src/core/generate.ts @@ -453,7 +453,7 @@ export async function generateMulti( const toolName = cliConfig.toolName ?? 'app'; const { files } = generateMultiTargetCli({ toolName, - infraNames: cliConfig.infraNames, + builtinNames: cliConfig.builtinNames, targets: cliTargets, }); @@ -464,15 +464,15 @@ export async function generateMulti( const firstTargetDocsConfig = names.length > 0 && configs[names[0]]?.docs; const docsConfig = resolveDocsConfig(firstTargetDocsConfig); - const { resolveInfraNames } = await import('./codegen/cli'); - const infraNames = resolveInfraNames( + const { resolveBuiltinNames } = await import('./codegen/cli'); + const builtinNames = resolveBuiltinNames( cliTargets.map((t) => t.name), - cliConfig.infraNames, + cliConfig.builtinNames, ); const docsInput: MultiTargetDocsInput = { toolName, - infraNames, + builtinNames, targets: cliTargets.map((t) => ({ name: t.name, endpoint: t.endpoint, diff --git a/graphql/codegen/src/types/config.ts b/graphql/codegen/src/types/config.ts index 08482c805..4dc7b946e 100644 --- a/graphql/codegen/src/types/config.ts +++ b/graphql/codegen/src/types/config.ts @@ -178,7 +178,7 @@ export interface DocsConfig { * When a target name collides with a default infra command name, * the infra command is auto-renamed. These allow user overrides. */ -export interface InfraNames { +export interface BuiltinNames { auth?: string; context?: string; } @@ -198,7 +198,7 @@ export interface CliConfig { * Defaults: auth -> 'auth' (renamed to 'credentials' on collision), * context -> 'context' (renamed to 'env' on collision) */ - infraNames?: InfraNames; + builtinNames?: BuiltinNames; } /** From ef638ade062520cd6ca9f9ffe11fd9196424536b Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Wed, 18 Feb 2026 07:50:38 +0000 Subject: [PATCH 09/23] fix(codegen): export generateMulti and fix multi-target executor import paths --- graphql/codegen/src/core/generate.ts | 2 +- graphql/codegen/src/index.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/graphql/codegen/src/core/generate.ts b/graphql/codegen/src/core/generate.ts index abb24ebb4..3dccf5b22 100644 --- a/graphql/codegen/src/core/generate.ts +++ b/graphql/codegen/src/core/generate.ts @@ -439,7 +439,7 @@ export async function generateMulti( cliTargets.push({ name, endpoint: resolvedConfig.endpoint || '', - ormImportPath: `../../${resolvedConfig.output}/orm`, + ormImportPath: `../${resolvedConfig.output.replace(/^\.\//, '')}/orm`, tables: result.pipelineData.tables, customOperations: result.pipelineData.customOperations, isAuthTarget, diff --git a/graphql/codegen/src/index.ts b/graphql/codegen/src/index.ts index 07ea53242..e1260dc59 100644 --- a/graphql/codegen/src/index.ts +++ b/graphql/codegen/src/index.ts @@ -22,8 +22,8 @@ export * from './client'; export { defineConfig } from './types/config'; // Main generate function (orchestrates the entire pipeline) -export type { GenerateOptions, GenerateResult } from './core/generate'; -export { generate } from './core/generate'; +export type { GenerateOptions, GenerateResult, GenerateMultiOptions, GenerateMultiResult } from './core/generate'; +export { generate, generateMulti } from './core/generate'; // Config utilities export { findConfigFile, loadConfigFile } from './core/config'; From d05e7632464ba6df3a5883127d3bae3eee0d388c Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Wed, 18 Feb 2026 09:56:13 +0000 Subject: [PATCH 10/23] feat(codegen): add shared PGPM ephemeral DB, multi-target cnc codegen, and export-schema command - Shared ephemeral DB: When multiple targets in generateMulti() share the same PGPM source, deploy once to a single ephemeral DB and reuse it across targets instead of creating N separate databases. Automatic teardown after all targets. - Multi-target cnc codegen: Add multi-target config detection to cnc codegen command, mirroring graphql-codegen CLI behavior. Supports --target flag. - Export schema from PGPM: New exportSchema()/exportSchemaSimple() functions and CLI commands (graphql-codegen export-schema, cnc export-schema) that deploy a PGPM module to an ephemeral DB, introspect via PostGraphile, and write .graphql schema files. No server required. Supports --api-names and --schemas flags. --- graphql/codegen/src/cli/index.ts | 79 ++++++++ graphql/codegen/src/core/export-schema.ts | 217 +++++++++++++++++++++ graphql/codegen/src/core/generate.ts | 126 +++++++++++- graphql/codegen/src/core/index.ts | 3 + graphql/codegen/src/index.ts | 9 + packages/cli/src/commands.ts | 2 + packages/cli/src/commands/codegen.ts | 51 ++++- packages/cli/src/commands/export-schema.ts | 91 +++++++++ 8 files changed, 575 insertions(+), 3 deletions(-) create mode 100644 graphql/codegen/src/core/export-schema.ts create mode 100644 packages/cli/src/commands/export-schema.ts diff --git a/graphql/codegen/src/cli/index.ts b/graphql/codegen/src/cli/index.ts index dec25073c..aab23773d 100644 --- a/graphql/codegen/src/cli/index.ts +++ b/graphql/codegen/src/cli/index.ts @@ -8,6 +8,7 @@ import { CLI, CLIOptions, getPackageJson, Inquirerer } from 'inquirerer'; import { findConfigFile, loadConfigFile } from '../core/config'; +import { exportSchemaSimple } from '../core/export-schema'; import { generate, generateMulti } from '../core/generate'; import { mergeConfig, type GraphQLSDKConfigTarget } from '../types/config'; import { @@ -26,6 +27,7 @@ graphql-codegen - GraphQL SDK generator for Constructive databases Usage: graphql-codegen [options] + graphql-codegen export-schema [options] Source Options (choose one): -c, --config Path to config file @@ -47,8 +49,78 @@ Generator Options: -h, --help Show this help message --version Show version number + +Export Schema (from PGPM module, no server required): + graphql-codegen export-schema --pgpm-module-path --api-names -o + graphql-codegen export-schema --pgpm-workspace-path --pgpm-module-name --api-names -o + --pgpm-module-path Path to PGPM module directory + --pgpm-workspace-path Path to PGPM workspace directory + --pgpm-module-name Module name within workspace + --keep-db Keep ephemeral database after export (debug) `; +async function handleExportSchema( + argv: Record, +): Promise { + const pgpmModulePath = argv['pgpm-module-path'] as string | undefined; + const pgpmWorkspacePath = argv['pgpm-workspace-path'] as string | undefined; + const pgpmModuleName = argv['pgpm-module-name'] as string | undefined; + const output = (argv.output || argv.o || '.') as string; + const filename = argv.filename as string | undefined; + const verbose = Boolean(argv.verbose || argv.v); + const keepDb = Boolean(argv['keep-db']); + + const rawSchemas = argv.schemas as string | undefined; + const rawApiNames = argv['api-names'] as string | undefined; + const schemas = rawSchemas + ? rawSchemas.split(',').map((s) => s.trim()).filter(Boolean) + : undefined; + const apiNames = rawApiNames + ? rawApiNames.split(',').map((s) => s.trim()).filter(Boolean) + : undefined; + + if (!pgpmModulePath && !(pgpmWorkspacePath && pgpmModuleName)) { + console.error( + 'x', + 'export-schema requires --pgpm-module-path or both --pgpm-workspace-path and --pgpm-module-name', + ); + process.exit(1); + } + + if (!schemas?.length && !apiNames?.length) { + console.error( + 'x', + 'export-schema requires --schemas or --api-names', + ); + process.exit(1); + } + + const pgpm = pgpmModulePath + ? { modulePath: pgpmModulePath } + : { workspacePath: pgpmWorkspacePath!, moduleName: pgpmModuleName! }; + + const result = await exportSchemaSimple({ + pgpm, + apiNames, + schemas, + output, + filename, + keepDb, + verbose, + }); + + if (result.success) { + console.log('[ok]', result.message); + for (const file of result.files ?? []) { + console.log(` ${file.target}: ${file.path} (schemas: ${file.schemas.join(', ')})`); + } + } else { + console.error('x', result.message); + result.errors?.forEach((e) => console.error(' -', e)); + process.exit(1); + } +} + export const commands = async ( argv: Record, prompter: Inquirerer, @@ -65,6 +137,13 @@ export const commands = async ( process.exit(0); } + const positionalArgs = (argv._ as string[]) ?? []; + if (positionalArgs.includes('export-schema')) { + await handleExportSchema(argv); + prompter.close(); + return argv; + } + const hasSourceFlags = Boolean( argv.endpoint || argv.e || diff --git a/graphql/codegen/src/core/export-schema.ts b/graphql/codegen/src/core/export-schema.ts new file mode 100644 index 000000000..ee77c0a4c --- /dev/null +++ b/graphql/codegen/src/core/export-schema.ts @@ -0,0 +1,217 @@ +import * as fs from 'node:fs'; +import * as path from 'node:path'; + +import { PgpmPackage } from '@pgpmjs/core'; +import { createEphemeralDb, type EphemeralDbResult } from 'pgsql-client'; +import { deployPgpm } from 'pgsql-seed'; + +import type { PgpmConfig } from '../types/config'; +import { buildSchemaSDLFromDatabase } from './database'; +import { resolveApiSchemas, validateServicesSchemas } from './introspect/source/api-schemas'; + +export interface ExportSchemaTarget { + apiNames?: string[]; + schemas?: string[]; + output: string; + filename?: string; +} + +export interface ExportSchemaOptions { + pgpm: PgpmConfig; + targets: ExportSchemaTarget[]; + keepDb?: boolean; + verbose?: boolean; +} + +export interface ExportSchemaResult { + success: boolean; + message: string; + files?: Array<{ target: string; path: string; schemas: string[] }>; + errors?: string[]; +} + +function resolveModulePath(pgpm: PgpmConfig): string { + if (pgpm.modulePath) return pgpm.modulePath; + if (pgpm.workspacePath && pgpm.moduleName) { + const workspace = new PgpmPackage(pgpm.workspacePath); + const moduleProject = workspace.getModuleProject(pgpm.moduleName); + const modulePath = moduleProject.getModulePath(); + if (!modulePath) { + throw new Error(`Module "${pgpm.moduleName}" not found in workspace`); + } + return modulePath; + } + throw new Error( + 'Invalid PGPM config: requires modulePath or both workspacePath and moduleName', + ); +} + +export async function exportSchema( + options: ExportSchemaOptions, +): Promise { + const { pgpm, targets, keepDb = false, verbose = false } = options; + + if (targets.length === 0) { + return { + success: false, + message: 'No export targets specified.', + }; + } + + let modulePath: string; + try { + modulePath = resolveModulePath(pgpm); + } catch (err) { + return { + success: false, + message: `Failed to resolve module path: ${err instanceof Error ? err.message : 'Unknown error'}`, + }; + } + + const pkg = new PgpmPackage(modulePath); + if (!pkg.isInModule()) { + return { + success: false, + message: `Not a valid PGPM module: ${modulePath}. Directory must contain pgpm.plan and .control files.`, + }; + } + + let ephemeralDb: EphemeralDbResult; + try { + ephemeralDb = createEphemeralDb({ + prefix: 'codegen_export_', + verbose, + }); + } catch (err) { + return { + success: false, + message: `Failed to create ephemeral database: ${err instanceof Error ? err.message : 'Unknown error'}`, + }; + } + + const { config: dbConfig, teardown } = ephemeralDb; + + try { + if (verbose) { + console.log(`Deploying PGPM module: ${modulePath}`); + } + await deployPgpm(dbConfig, modulePath, false); + + const { getPgPool } = await import('pg-cache'); + const pool = getPgPool(dbConfig); + + const exportedFiles: Array<{ + target: string; + path: string; + schemas: string[]; + }> = []; + const errors: string[] = []; + + for (const target of targets) { + const targetName = + target.apiNames?.join(',') || target.schemas?.join(',') || 'default'; + + try { + let schemas: string[]; + if (target.apiNames && target.apiNames.length > 0) { + const validation = await validateServicesSchemas(pool); + if (!validation.valid) { + errors.push(`[${targetName}] ${validation.error}`); + continue; + } + schemas = await resolveApiSchemas(pool, target.apiNames); + } else if (target.schemas && target.schemas.length > 0) { + schemas = target.schemas; + } else { + schemas = ['public']; + } + + if (verbose) { + console.log( + `[${targetName}] Introspecting schemas: ${schemas.join(', ')}`, + ); + } + + const sdl = await buildSchemaSDLFromDatabase({ + database: dbConfig.database, + schemas, + }); + + if (!sdl.trim()) { + errors.push(`[${targetName}] Introspection returned empty schema`); + continue; + } + + const outDir = path.resolve(target.output); + await fs.promises.mkdir(outDir, { recursive: true }); + + const filename = target.filename ?? 'schema.graphql'; + const filePath = path.join(outDir, filename); + await fs.promises.writeFile(filePath, sdl, 'utf-8'); + + exportedFiles.push({ + target: targetName, + path: filePath, + schemas, + }); + + if (verbose) { + console.log(`[${targetName}] Wrote ${filePath}`); + } + } catch (err) { + errors.push( + `[${targetName}] ${err instanceof Error ? err.message : 'Unknown error'}`, + ); + } + } + + if (exportedFiles.length === 0) { + return { + success: false, + message: 'No schema files exported.', + errors, + }; + } + + return { + success: true, + message: `Exported ${exportedFiles.length} schema file(s) from PGPM module.`, + files: exportedFiles, + errors: errors.length > 0 ? errors : undefined, + }; + } catch (err) { + return { + success: false, + message: `Failed to deploy PGPM module: ${err instanceof Error ? err.message : 'Unknown error'}`, + }; + } finally { + teardown({ keepDb }); + if (keepDb) { + console.log(`Kept ephemeral database: ${dbConfig.database}`); + } + } +} + +export interface ExportSchemaSimpleOptions { + pgpm: PgpmConfig; + apiNames?: string[]; + schemas?: string[]; + output: string; + filename?: string; + keepDb?: boolean; + verbose?: boolean; +} + +export async function exportSchemaSimple( + options: ExportSchemaSimpleOptions, +): Promise { + const { pgpm, apiNames, schemas, output, filename, keepDb, verbose } = + options; + + return exportSchema({ + pgpm, + targets: [{ apiNames, schemas, output, filename }], + keepDb, + verbose, + }); +} diff --git a/graphql/codegen/src/core/generate.ts b/graphql/codegen/src/core/generate.ts index 3dccf5b22..53fc4474f 100644 --- a/graphql/codegen/src/core/generate.ts +++ b/graphql/codegen/src/core/generate.ts @@ -6,7 +6,10 @@ */ import path from 'node:path'; -import type { CliConfig, GraphQLSDKConfigTarget } from '../types/config'; +import { createEphemeralDb, type EphemeralDbResult } from 'pgsql-client'; +import { deployPgpm } from 'pgsql-seed'; + +import type { CliConfig, DbConfig, GraphQLSDKConfigTarget, PgpmConfig } from '../types/config'; import { getConfigOptions } from '../types/config'; import type { CleanOperation, CleanTable } from '../types/schema'; import { generate as generateReactQueryFiles } from './codegen'; @@ -396,6 +399,114 @@ export interface GenerateMultiResult { hasError: boolean; } +interface SharedPgpmSource { + key: string; + ephemeralDb: EphemeralDbResult; + deployed: boolean; +} + +function getPgpmSourceKey(pgpm: PgpmConfig): string | null { + if (pgpm.modulePath) return `module:${path.resolve(pgpm.modulePath)}`; + if (pgpm.workspacePath && pgpm.moduleName) + return `workspace:${path.resolve(pgpm.workspacePath)}:${pgpm.moduleName}`; + return null; +} + +function getModulePathFromPgpm( + pgpm: PgpmConfig, +): string { + if (pgpm.modulePath) return pgpm.modulePath; + if (pgpm.workspacePath && pgpm.moduleName) { + const { PgpmPackage } = require('@pgpmjs/core') as typeof import('@pgpmjs/core'); + const workspace = new PgpmPackage(pgpm.workspacePath); + const moduleProject = workspace.getModuleProject(pgpm.moduleName); + const modulePath = moduleProject.getModulePath(); + if (!modulePath) { + throw new Error(`Module "${pgpm.moduleName}" not found in workspace`); + } + return modulePath; + } + throw new Error('Invalid PGPM config: requires modulePath or workspacePath+moduleName'); +} + +async function prepareSharedPgpmSources( + configs: Record, + cliOverrides?: Partial, +): Promise> { + const sharedSources = new Map(); + const pgpmTargetCount = new Map(); + + for (const name of Object.keys(configs)) { + const merged = { ...configs[name], ...(cliOverrides ?? {}) }; + const pgpm = merged.db?.pgpm; + if (!pgpm) continue; + const key = getPgpmSourceKey(pgpm); + if (!key) continue; + pgpmTargetCount.set(key, (pgpmTargetCount.get(key) ?? 0) + 1); + } + + for (const [key, count] of pgpmTargetCount) { + if (count < 2) continue; + + let pgpmConfig: PgpmConfig | undefined; + for (const name of Object.keys(configs)) { + const merged = { ...configs[name], ...(cliOverrides ?? {}) }; + const pgpm = merged.db?.pgpm; + if (pgpm && getPgpmSourceKey(pgpm) === key) { + pgpmConfig = pgpm; + break; + } + } + if (!pgpmConfig) continue; + + const ephemeralDb = createEphemeralDb({ + prefix: 'codegen_pgpm_shared_', + verbose: false, + }); + + const modulePath = getModulePathFromPgpm(pgpmConfig); + await deployPgpm(ephemeralDb.config, modulePath, false); + + sharedSources.set(key, { + key, + ephemeralDb, + deployed: true, + }); + + console.log( + `[multi-target] Shared PGPM source deployed once for ${count} targets: ${key}`, + ); + } + + return sharedSources; +} + +function applySharedPgpmDb( + config: GraphQLSDKConfigTarget, + sharedSources: Map, +): GraphQLSDKConfigTarget { + const pgpm = config.db?.pgpm; + if (!pgpm) return config; + + const key = getPgpmSourceKey(pgpm); + if (!key) return config; + + const shared = sharedSources.get(key); + if (!shared) return config; + + const sharedDbConfig: DbConfig = { + ...config.db, + pgpm: undefined, + config: shared.ephemeralDb.config, + keepDb: true, + }; + + return { + ...config, + db: sharedDbConfig, + }; +} + export async function generateMulti( options: GenerateMultiOptions, ): Promise { @@ -409,11 +520,15 @@ export async function generateMulti( const cliTargets: MultiTargetCliTarget[] = []; + const sharedSources = await prepareSharedPgpmSources(configs, cliOverrides); + + try { for (const name of names) { - const targetConfig = { + const baseConfig = { ...configs[name], ...(cliOverrides ?? {}), }; + const targetConfig = applySharedPgpmDb(baseConfig, sharedSources); const result = await generate( { ...targetConfig, verbose, dryRun }, useUnifiedCli ? { skipCli: true } : undefined, @@ -524,5 +639,12 @@ export async function generateMulti( ); } + } finally { + for (const shared of sharedSources.values()) { + const keepDb = Object.values(configs).some((c) => c.db?.keepDb); + shared.ephemeralDb.teardown({ keepDb }); + } + } + return { results, hasError }; } diff --git a/graphql/codegen/src/core/index.ts b/graphql/codegen/src/core/index.ts index 6b70c545d..93e0e9870 100644 --- a/graphql/codegen/src/core/index.ts +++ b/graphql/codegen/src/core/index.ts @@ -44,3 +44,6 @@ export * from './watch'; // Database schema utilities export * from './database'; + +// Schema export from PGPM modules +export * from './export-schema'; diff --git a/graphql/codegen/src/index.ts b/graphql/codegen/src/index.ts index e1260dc59..fa8309df0 100644 --- a/graphql/codegen/src/index.ts +++ b/graphql/codegen/src/index.ts @@ -54,3 +54,12 @@ export { buildSchemaFromDatabase, buildSchemaSDLFromDatabase, } from './core/database'; + +// Schema export from PGPM modules +export type { + ExportSchemaOptions, + ExportSchemaTarget, + ExportSchemaResult, + ExportSchemaSimpleOptions, +} from './core/export-schema'; +export { exportSchema, exportSchemaSimple } from './core/export-schema'; diff --git a/packages/cli/src/commands.ts b/packages/cli/src/commands.ts index f4d8392e7..183ac1cff 100644 --- a/packages/cli/src/commands.ts +++ b/packages/cli/src/commands.ts @@ -6,6 +6,7 @@ import codegen from './commands/codegen'; import context from './commands/context'; import execute from './commands/execute'; import explorer from './commands/explorer'; +import exportSchema from './commands/export-schema'; import getGraphqlSchema from './commands/get-graphql-schema'; import jobs from './commands/jobs'; import server from './commands/server'; @@ -17,6 +18,7 @@ const createCommandMap = (): Record => { explorer, 'get-graphql-schema': getGraphqlSchema, codegen, + 'export-schema': exportSchema, jobs, context, auth, diff --git a/packages/cli/src/commands/codegen.ts b/packages/cli/src/commands/codegen.ts index 58d47abe7..da6e40d32 100644 --- a/packages/cli/src/commands/codegen.ts +++ b/packages/cli/src/commands/codegen.ts @@ -1,11 +1,15 @@ import { CLIOptions, Inquirerer } from 'inquirerer'; import { generate, + generateMulti, findConfigFile, loadConfigFile, codegenQuestions, printResult, buildGenerateOptions, + buildDbConfig, + camelizeArgv, + normalizeCodegenListOptions, seedArgvFromConfig, hasResolvedCodegenSource, type GraphQLSDKConfigTarget, @@ -29,6 +33,7 @@ Generator Options: --react-query Generate React Query hooks (default) --orm Generate ORM client --output Output directory (default: codegen) + --target Target name (for multi-target configs) --authorization Authorization header value --dry-run Preview without writing files --verbose Verbose output @@ -60,7 +65,51 @@ export default async ( console.error('x', loaded.error); process.exit(1); } - fileConfig = loaded.config as GraphQLSDKConfigTarget; + + const config = loaded.config as Record; + const isMulti = !( + 'endpoint' in config || + 'schemaFile' in config || + 'db' in config + ); + + if (isMulti) { + const targets = config as Record; + const targetName = argv.target as string | undefined; + + if (targetName && !targets[targetName]) { + console.error( + 'x', + `Target "${targetName}" not found. Available: ${Object.keys(targets).join(', ')}`, + ); + process.exit(1); + } + + const cliOptions = buildDbConfig( + normalizeCodegenListOptions( + camelizeArgv(argv as Record), + ), + ); + + const selectedTargets = targetName + ? { [targetName]: targets[targetName] } + : targets; + + const { results, hasError } = await generateMulti({ + configs: selectedTargets, + cliOverrides: cliOptions as Partial, + }); + + for (const { name, result } of results) { + console.log(`\n[${name}]`); + printResult(result); + } + + if (hasError) process.exit(1); + return; + } + + fileConfig = config as GraphQLSDKConfigTarget; } const seeded = seedArgvFromConfig(argv as Record, fileConfig); diff --git a/packages/cli/src/commands/export-schema.ts b/packages/cli/src/commands/export-schema.ts new file mode 100644 index 000000000..757deff96 --- /dev/null +++ b/packages/cli/src/commands/export-schema.ts @@ -0,0 +1,91 @@ +import { CLIOptions, Inquirerer } from 'inquirerer'; +import { + exportSchemaSimple, + splitCommas, +} from '@constructive-io/graphql-codegen'; + +const usage = ` +Constructive Export Schema (from PGPM module, no server required): + + cnc export-schema [OPTIONS] + +PGPM Source (choose one): + --pgpm-module-path Path to PGPM module directory + --pgpm-workspace-path Path to PGPM workspace directory + --pgpm-module-name Module name within workspace + +Schema Selection (choose one): + --api-names Comma-separated API names + --schemas Comma-separated PostgreSQL schemas + +Output Options: + --output Output directory (default: current directory) + --filename Output filename (default: schema.graphql) + --keep-db Keep ephemeral database after export (debug) + --verbose Verbose output + + --help, -h Show this help message +`; + +export default async ( + argv: Partial>, + _prompter: Inquirerer, + _options: CLIOptions +) => { + if (argv.help || argv.h) { + console.log(usage); + process.exit(0); + } + + const pgpmModulePath = argv['pgpm-module-path'] as string | undefined; + const pgpmWorkspacePath = argv['pgpm-workspace-path'] as string | undefined; + const pgpmModuleName = argv['pgpm-module-name'] as string | undefined; + const output = (argv.output || '.') as string; + const filename = argv.filename as string | undefined; + const verbose = Boolean(argv.verbose); + const keepDb = Boolean(argv['keep-db']); + + const schemas = splitCommas(argv.schemas as string | undefined); + const apiNames = splitCommas(argv['api-names'] as string | undefined); + + if (!pgpmModulePath && !(pgpmWorkspacePath && pgpmModuleName)) { + console.error( + 'x', + 'export-schema requires --pgpm-module-path or both --pgpm-workspace-path and --pgpm-module-name', + ); + process.exit(1); + } + + if (!schemas?.length && !apiNames?.length) { + console.error( + 'x', + 'export-schema requires --schemas or --api-names', + ); + process.exit(1); + } + + const pgpm = pgpmModulePath + ? { modulePath: pgpmModulePath } + : { workspacePath: pgpmWorkspacePath!, moduleName: pgpmModuleName! }; + + const result = await exportSchemaSimple({ + pgpm, + apiNames, + schemas, + output, + filename, + keepDb, + verbose, + }); + + if (result.success) { + console.log('[ok]', result.message); + for (const file of result.files ?? []) { + console.log(` ${file.target}: ${file.path} (schemas: ${file.schemas.join(', ')})`); + } + } else { + console.error('x', result.message); + result.errors?.forEach((e) => console.error(' -', e)); + process.exit(1); + } +}; From b1396bcf0d238ae425c3a771ab07e460833a8c2f Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Wed, 18 Feb 2026 21:14:31 +0000 Subject: [PATCH 11/23] feat(codegen): apiNames auto-expansion to multi-target, --schema-only flag, remove redundant commands - Add expandApiNamesToMultiTarget(): when multiple apiNames are specified, auto-expand to multi-target (each API name = separate target = separate schema) - Add --schema-only flag to cnc codegen and graphql-codegen CLIs: exports GraphQL SDL instead of running full codegen pipeline - Remove redundant cnc get-graphql-schema command (use --schema-only instead) - Remove redundant cnc export-schema command (use --schema-only instead) - Remove server/scripts/codegen-schema.ts (use --schema-only instead) - Remove graphql/codegen/src/core/export-schema.ts module --- graphql/codegen/src/cli/index.ts | 112 +++------ graphql/codegen/src/core/export-schema.ts | 217 ------------------ graphql/codegen/src/core/generate.ts | 79 ++++++- graphql/codegen/src/core/index.ts | 3 - graphql/codegen/src/index.ts | 11 +- graphql/server/src/scripts/codegen-schema.ts | 105 --------- packages/cli/src/commands.ts | 4 - packages/cli/src/commands/codegen.ts | 26 ++- packages/cli/src/commands/export-schema.ts | 91 -------- .../cli/src/commands/get-graphql-schema.ts | 102 -------- 10 files changed, 129 insertions(+), 621 deletions(-) delete mode 100644 graphql/codegen/src/core/export-schema.ts delete mode 100644 graphql/server/src/scripts/codegen-schema.ts delete mode 100644 packages/cli/src/commands/export-schema.ts delete mode 100644 packages/cli/src/commands/get-graphql-schema.ts diff --git a/graphql/codegen/src/cli/index.ts b/graphql/codegen/src/cli/index.ts index aab23773d..776b3c357 100644 --- a/graphql/codegen/src/cli/index.ts +++ b/graphql/codegen/src/cli/index.ts @@ -8,9 +8,8 @@ import { CLI, CLIOptions, getPackageJson, Inquirerer } from 'inquirerer'; import { findConfigFile, loadConfigFile } from '../core/config'; -import { exportSchemaSimple } from '../core/export-schema'; -import { generate, generateMulti } from '../core/generate'; -import { mergeConfig, type GraphQLSDKConfigTarget } from '../types/config'; +import { expandApiNamesToMultiTarget, generate, generateMulti } from '../core/generate'; +import type { GraphQLSDKConfigTarget } from '../types/config'; import { buildDbConfig, buildGenerateOptions, @@ -27,7 +26,6 @@ graphql-codegen - GraphQL SDK generator for Constructive databases Usage: graphql-codegen [options] - graphql-codegen export-schema [options] Source Options (choose one): -c, --config Path to config file @@ -37,6 +35,7 @@ Source Options (choose one): Database Options: --schemas Comma-separated PostgreSQL schemas --api-names Comma-separated API names (mutually exclusive with --schemas) + Multiple apiNames auto-expand to multi-target (one schema per API). Generator Options: --react-query Generate React Query hooks @@ -47,80 +46,15 @@ Generator Options: --dry-run Preview without writing files -v, --verbose Show detailed output +Schema Export: + --schema-only Export GraphQL SDL instead of running full codegen. + Works with any source (endpoint, file, database, PGPM). + With multiple apiNames, writes one .graphql per API. + -h, --help Show this help message --version Show version number - -Export Schema (from PGPM module, no server required): - graphql-codegen export-schema --pgpm-module-path --api-names -o - graphql-codegen export-schema --pgpm-workspace-path --pgpm-module-name --api-names -o - --pgpm-module-path Path to PGPM module directory - --pgpm-workspace-path Path to PGPM workspace directory - --pgpm-module-name Module name within workspace - --keep-db Keep ephemeral database after export (debug) `; -async function handleExportSchema( - argv: Record, -): Promise { - const pgpmModulePath = argv['pgpm-module-path'] as string | undefined; - const pgpmWorkspacePath = argv['pgpm-workspace-path'] as string | undefined; - const pgpmModuleName = argv['pgpm-module-name'] as string | undefined; - const output = (argv.output || argv.o || '.') as string; - const filename = argv.filename as string | undefined; - const verbose = Boolean(argv.verbose || argv.v); - const keepDb = Boolean(argv['keep-db']); - - const rawSchemas = argv.schemas as string | undefined; - const rawApiNames = argv['api-names'] as string | undefined; - const schemas = rawSchemas - ? rawSchemas.split(',').map((s) => s.trim()).filter(Boolean) - : undefined; - const apiNames = rawApiNames - ? rawApiNames.split(',').map((s) => s.trim()).filter(Boolean) - : undefined; - - if (!pgpmModulePath && !(pgpmWorkspacePath && pgpmModuleName)) { - console.error( - 'x', - 'export-schema requires --pgpm-module-path or both --pgpm-workspace-path and --pgpm-module-name', - ); - process.exit(1); - } - - if (!schemas?.length && !apiNames?.length) { - console.error( - 'x', - 'export-schema requires --schemas or --api-names', - ); - process.exit(1); - } - - const pgpm = pgpmModulePath - ? { modulePath: pgpmModulePath } - : { workspacePath: pgpmWorkspacePath!, moduleName: pgpmModuleName! }; - - const result = await exportSchemaSimple({ - pgpm, - apiNames, - schemas, - output, - filename, - keepDb, - verbose, - }); - - if (result.success) { - console.log('[ok]', result.message); - for (const file of result.files ?? []) { - console.log(` ${file.target}: ${file.path} (schemas: ${file.schemas.join(', ')})`); - } - } else { - console.error('x', result.message); - result.errors?.forEach((e) => console.error(' -', e)); - process.exit(1); - } -} - export const commands = async ( argv: Record, prompter: Inquirerer, @@ -137,12 +71,7 @@ export const commands = async ( process.exit(0); } - const positionalArgs = (argv._ as string[]) ?? []; - if (positionalArgs.includes('export-schema')) { - await handleExportSchema(argv); - prompter.close(); - return argv; - } + const schemaOnly = Boolean(argv['schema-only']); const hasSourceFlags = Boolean( argv.endpoint || @@ -197,6 +126,7 @@ export const commands = async ( const { results, hasError } = await generateMulti({ configs: selectedTargets, cliOverrides: cliOptions as Partial, + schemaOnly, }); for (const { name, result } of results) { @@ -217,7 +147,23 @@ export const commands = async ( ? seeded : await prompter.prompt(seeded, codegenQuestions); const options = buildGenerateOptions(answers, fileConfig); - const result = await generate(options); + + const expanded = expandApiNamesToMultiTarget(options); + if (expanded) { + const { results, hasError } = await generateMulti({ + configs: expanded, + schemaOnly, + }); + for (const { name, result } of results) { + console.log(`\n[${name}]`); + printResult(result); + } + prompter.close(); + if (hasError) process.exit(1); + return argv; + } + + const result = await generate({ ...options, schemaOnly }); printResult(result); prompter.close(); return argv; @@ -235,6 +181,7 @@ export const options: Partial = { a: 'authorization', v: 'verbose', }, + boolean: ['schema-only'], string: [ 'config', 'endpoint', @@ -242,9 +189,6 @@ export const options: Partial = { 'output', 'target', 'authorization', - 'pgpm-module-path', - 'pgpm-workspace-path', - 'pgpm-module-name', 'schemas', 'api-names', ], diff --git a/graphql/codegen/src/core/export-schema.ts b/graphql/codegen/src/core/export-schema.ts deleted file mode 100644 index ee77c0a4c..000000000 --- a/graphql/codegen/src/core/export-schema.ts +++ /dev/null @@ -1,217 +0,0 @@ -import * as fs from 'node:fs'; -import * as path from 'node:path'; - -import { PgpmPackage } from '@pgpmjs/core'; -import { createEphemeralDb, type EphemeralDbResult } from 'pgsql-client'; -import { deployPgpm } from 'pgsql-seed'; - -import type { PgpmConfig } from '../types/config'; -import { buildSchemaSDLFromDatabase } from './database'; -import { resolveApiSchemas, validateServicesSchemas } from './introspect/source/api-schemas'; - -export interface ExportSchemaTarget { - apiNames?: string[]; - schemas?: string[]; - output: string; - filename?: string; -} - -export interface ExportSchemaOptions { - pgpm: PgpmConfig; - targets: ExportSchemaTarget[]; - keepDb?: boolean; - verbose?: boolean; -} - -export interface ExportSchemaResult { - success: boolean; - message: string; - files?: Array<{ target: string; path: string; schemas: string[] }>; - errors?: string[]; -} - -function resolveModulePath(pgpm: PgpmConfig): string { - if (pgpm.modulePath) return pgpm.modulePath; - if (pgpm.workspacePath && pgpm.moduleName) { - const workspace = new PgpmPackage(pgpm.workspacePath); - const moduleProject = workspace.getModuleProject(pgpm.moduleName); - const modulePath = moduleProject.getModulePath(); - if (!modulePath) { - throw new Error(`Module "${pgpm.moduleName}" not found in workspace`); - } - return modulePath; - } - throw new Error( - 'Invalid PGPM config: requires modulePath or both workspacePath and moduleName', - ); -} - -export async function exportSchema( - options: ExportSchemaOptions, -): Promise { - const { pgpm, targets, keepDb = false, verbose = false } = options; - - if (targets.length === 0) { - return { - success: false, - message: 'No export targets specified.', - }; - } - - let modulePath: string; - try { - modulePath = resolveModulePath(pgpm); - } catch (err) { - return { - success: false, - message: `Failed to resolve module path: ${err instanceof Error ? err.message : 'Unknown error'}`, - }; - } - - const pkg = new PgpmPackage(modulePath); - if (!pkg.isInModule()) { - return { - success: false, - message: `Not a valid PGPM module: ${modulePath}. Directory must contain pgpm.plan and .control files.`, - }; - } - - let ephemeralDb: EphemeralDbResult; - try { - ephemeralDb = createEphemeralDb({ - prefix: 'codegen_export_', - verbose, - }); - } catch (err) { - return { - success: false, - message: `Failed to create ephemeral database: ${err instanceof Error ? err.message : 'Unknown error'}`, - }; - } - - const { config: dbConfig, teardown } = ephemeralDb; - - try { - if (verbose) { - console.log(`Deploying PGPM module: ${modulePath}`); - } - await deployPgpm(dbConfig, modulePath, false); - - const { getPgPool } = await import('pg-cache'); - const pool = getPgPool(dbConfig); - - const exportedFiles: Array<{ - target: string; - path: string; - schemas: string[]; - }> = []; - const errors: string[] = []; - - for (const target of targets) { - const targetName = - target.apiNames?.join(',') || target.schemas?.join(',') || 'default'; - - try { - let schemas: string[]; - if (target.apiNames && target.apiNames.length > 0) { - const validation = await validateServicesSchemas(pool); - if (!validation.valid) { - errors.push(`[${targetName}] ${validation.error}`); - continue; - } - schemas = await resolveApiSchemas(pool, target.apiNames); - } else if (target.schemas && target.schemas.length > 0) { - schemas = target.schemas; - } else { - schemas = ['public']; - } - - if (verbose) { - console.log( - `[${targetName}] Introspecting schemas: ${schemas.join(', ')}`, - ); - } - - const sdl = await buildSchemaSDLFromDatabase({ - database: dbConfig.database, - schemas, - }); - - if (!sdl.trim()) { - errors.push(`[${targetName}] Introspection returned empty schema`); - continue; - } - - const outDir = path.resolve(target.output); - await fs.promises.mkdir(outDir, { recursive: true }); - - const filename = target.filename ?? 'schema.graphql'; - const filePath = path.join(outDir, filename); - await fs.promises.writeFile(filePath, sdl, 'utf-8'); - - exportedFiles.push({ - target: targetName, - path: filePath, - schemas, - }); - - if (verbose) { - console.log(`[${targetName}] Wrote ${filePath}`); - } - } catch (err) { - errors.push( - `[${targetName}] ${err instanceof Error ? err.message : 'Unknown error'}`, - ); - } - } - - if (exportedFiles.length === 0) { - return { - success: false, - message: 'No schema files exported.', - errors, - }; - } - - return { - success: true, - message: `Exported ${exportedFiles.length} schema file(s) from PGPM module.`, - files: exportedFiles, - errors: errors.length > 0 ? errors : undefined, - }; - } catch (err) { - return { - success: false, - message: `Failed to deploy PGPM module: ${err instanceof Error ? err.message : 'Unknown error'}`, - }; - } finally { - teardown({ keepDb }); - if (keepDb) { - console.log(`Kept ephemeral database: ${dbConfig.database}`); - } - } -} - -export interface ExportSchemaSimpleOptions { - pgpm: PgpmConfig; - apiNames?: string[]; - schemas?: string[]; - output: string; - filename?: string; - keepDb?: boolean; - verbose?: boolean; -} - -export async function exportSchemaSimple( - options: ExportSchemaSimpleOptions, -): Promise { - const { pgpm, apiNames, schemas, output, filename, keepDb, verbose } = - options; - - return exportSchema({ - pgpm, - targets: [{ apiNames, schemas, output, filename }], - keepDb, - verbose, - }); -} diff --git a/graphql/codegen/src/core/generate.ts b/graphql/codegen/src/core/generate.ts index 53fc4474f..6e56cdfec 100644 --- a/graphql/codegen/src/core/generate.ts +++ b/graphql/codegen/src/core/generate.ts @@ -4,8 +4,11 @@ * This is the primary entry point for programmatic usage. * The CLI is a thin wrapper around this function. */ +import * as fs from 'node:fs'; import path from 'node:path'; +import { buildClientSchema, printSchema } from 'graphql'; + import { createEphemeralDb, type EphemeralDbResult } from 'pgsql-client'; import { deployPgpm } from 'pgsql-seed'; @@ -58,6 +61,9 @@ export interface GenerateOptions extends GraphQLSDKConfigTarget { verbose?: boolean; dryRun?: boolean; skipCustomOperations?: boolean; + schemaOnly?: boolean; + schemaOnlyOutput?: string; + schemaOnlyFilename?: string; } export interface GenerateResult { @@ -102,7 +108,7 @@ export async function generate( const runOrm = runReactQuery || !!config.cli || (options.orm !== undefined ? !!options.orm : false); - if (!runReactQuery && !runOrm && !runCli) { + if (!options.schemaOnly && !runReactQuery && !runOrm && !runCli) { return { success: false, message: @@ -133,6 +139,42 @@ export async function generate( headers: config.headers, }); + if (options.schemaOnly) { + try { + console.log(`Fetching schema from ${source.describe()}...`); + const { introspection } = await source.fetch(); + const schema = buildClientSchema(introspection as any); + const sdl = printSchema(schema); + + if (!sdl.trim()) { + return { + success: false, + message: 'Schema introspection returned empty SDL.', + output: outputRoot, + }; + } + + const outDir = path.resolve(options.schemaOnlyOutput || outputRoot || '.'); + await fs.promises.mkdir(outDir, { recursive: true }); + const filename = options.schemaOnlyFilename || 'schema.graphql'; + const filePath = path.join(outDir, filename); + await fs.promises.writeFile(filePath, sdl, 'utf-8'); + + return { + success: true, + message: `Schema exported to ${filePath}`, + output: outDir, + filesWritten: [filePath], + }; + } catch (err) { + return { + success: false, + message: `Failed to export schema: ${err instanceof Error ? err.message : 'Unknown error'}`, + output: outputRoot, + }; + } + } + // Run pipeline let pipelineResult: Awaited>; try { @@ -386,11 +428,34 @@ export async function generate( }; } +export function expandApiNamesToMultiTarget( + config: GraphQLSDKConfigTarget, +): Record | null { + const apiNames = config.db?.apiNames; + if (!apiNames || apiNames.length <= 1) return null; + + const targets: Record = {}; + for (const apiName of apiNames) { + targets[apiName] = { + ...config, + db: { + ...config.db, + apiNames: [apiName], + }, + output: config.output + ? `${config.output}/${apiName}` + : `./generated/graphql/${apiName}`, + }; + } + return targets; +} + export interface GenerateMultiOptions { configs: Record; cliOverrides?: Partial; verbose?: boolean; dryRun?: boolean; + schemaOnly?: boolean; unifiedCli?: CliConfig | boolean; } @@ -510,13 +575,13 @@ function applySharedPgpmDb( export async function generateMulti( options: GenerateMultiOptions, ): Promise { - const { configs, cliOverrides, verbose, dryRun, unifiedCli } = options; + const { configs, cliOverrides, verbose, dryRun, schemaOnly, unifiedCli } = options; const names = Object.keys(configs); const results: Array<{ name: string; result: GenerateResult }> = []; let hasError = false; const targetInfos: RootRootReadmeTarget[] = []; - const useUnifiedCli = !!unifiedCli && names.length > 1; + const useUnifiedCli = !schemaOnly && !!unifiedCli && names.length > 1; const cliTargets: MultiTargetCliTarget[] = []; @@ -530,7 +595,13 @@ export async function generateMulti( }; const targetConfig = applySharedPgpmDb(baseConfig, sharedSources); const result = await generate( - { ...targetConfig, verbose, dryRun }, + { + ...targetConfig, + verbose, + dryRun, + schemaOnly, + schemaOnlyFilename: schemaOnly ? `${name}.graphql` : undefined, + }, useUnifiedCli ? { skipCli: true } : undefined, ); results.push({ name, result }); diff --git a/graphql/codegen/src/core/index.ts b/graphql/codegen/src/core/index.ts index 93e0e9870..6b70c545d 100644 --- a/graphql/codegen/src/core/index.ts +++ b/graphql/codegen/src/core/index.ts @@ -44,6 +44,3 @@ export * from './watch'; // Database schema utilities export * from './database'; - -// Schema export from PGPM modules -export * from './export-schema'; diff --git a/graphql/codegen/src/index.ts b/graphql/codegen/src/index.ts index fa8309df0..60d4cae31 100644 --- a/graphql/codegen/src/index.ts +++ b/graphql/codegen/src/index.ts @@ -23,7 +23,7 @@ export { defineConfig } from './types/config'; // Main generate function (orchestrates the entire pipeline) export type { GenerateOptions, GenerateResult, GenerateMultiOptions, GenerateMultiResult } from './core/generate'; -export { generate, generateMulti } from './core/generate'; +export { generate, generateMulti, expandApiNamesToMultiTarget } from './core/generate'; // Config utilities export { findConfigFile, loadConfigFile } from './core/config'; @@ -54,12 +54,3 @@ export { buildSchemaFromDatabase, buildSchemaSDLFromDatabase, } from './core/database'; - -// Schema export from PGPM modules -export type { - ExportSchemaOptions, - ExportSchemaTarget, - ExportSchemaResult, - ExportSchemaSimpleOptions, -} from './core/export-schema'; -export { exportSchema, exportSchemaSimple } from './core/export-schema'; diff --git a/graphql/server/src/scripts/codegen-schema.ts b/graphql/server/src/scripts/codegen-schema.ts deleted file mode 100644 index 24e74a7c6..000000000 --- a/graphql/server/src/scripts/codegen-schema.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { getEnvOptions } from '@constructive-io/graphql-env'; -import { Logger } from '@pgpmjs/logger'; -import { ConstructivePreset, makePgService } from 'graphile-settings'; -import { makeSchema } from 'graphile-build'; -import { buildConnectionString, getPgPool } from 'pg-cache'; -import { printSchema } from 'graphql'; -import { promises as fs } from 'node:fs'; -import path from 'node:path'; -import type { GraphileConfig } from 'graphile-config'; - -const log = new Logger('codegen-schema'); - -const getSchemaOutputPath = () => - process.env.CODEGEN_SCHEMA_OUT ?? - path.resolve(__dirname, '../../codegen/schema.graphql'); - -(async () => { - try { - const opts = getEnvOptions(); - const apiOpts = (opts as any).api || {}; - const metaSchemas = Array.isArray(apiOpts.metaSchemas) - ? apiOpts.metaSchemas - : []; - - let schemas: string[]; - let usingFallback = false; - - const dbName = - process.env.CODEGEN_DATABASE || process.env.PGDATABASE || 'constructive'; - const pgConfig = { ...opts.pg, database: dbName } as typeof opts.pg; - log.info(`Target database for codegen: ${dbName}`); - - if (metaSchemas.length) { - schemas = metaSchemas; - log.info(`Using meta schemas: ${schemas.join(', ')}`); - - const pool = getPgPool(pgConfig); - const checkResult = await pool.query( - `SELECT schema_name FROM information_schema.schemata - WHERE schema_name = ANY($1::text[]) - ORDER BY schema_name`, - [schemas] - ); - - const foundSchemas = checkResult.rows.map((r: any) => r.schema_name); - const missing = schemas.filter((s) => !foundSchemas.includes(s)); - - if (missing.length > 0) { - log.warn( - `Missing schemas: ${missing.join(', ')}. Falling back to 'public'.` - ); - schemas = ['public']; - usingFallback = true; - } - } else { - schemas = ['public']; - log.info('No meta schemas configured, using: public'); - usingFallback = true; - } - - if (usingFallback) { - log.warn( - 'Schema will be generated from public schema only. To generate full meta schema, ensure meta tables exist.' - ); - } - - const pool = getPgPool(pgConfig); - log.debug(`Connecting to database: ${dbName}`); - log.debug(`Connecting to host: ${opts.pg?.host || '(default)'}`); - - const dbInfo = await pool.query( - 'SELECT current_database() AS current_database, current_user AS current_user' - ); - log.info( - `Connected to database: ${dbInfo.rows[0]?.current_database} as user: ${dbInfo.rows[0]?.current_user}` - ); - - const connectionString = buildConnectionString( - pgConfig.user, pgConfig.password, pgConfig.host, pgConfig.port, dbName - ); - - // Create v5 preset with ConstructivePreset - const preset: GraphileConfig.Preset = { - extends: [ConstructivePreset], - pgServices: [ - makePgService({ - connectionString, - schemas, - }), - ], - }; - - const { schema: graphqlSchema } = await makeSchema(preset); - const sdl = printSchema(graphqlSchema); - - const outputPath = getSchemaOutputPath(); - await fs.mkdir(path.dirname(outputPath), { recursive: true }); - await fs.writeFile(outputPath, sdl, 'utf8'); - - log.success(`Schema written to ${outputPath}`); - } catch (error: any) { - log.error('Failed to write schema', error?.stack || error); - process.exitCode = 1; - } -})(); diff --git a/packages/cli/src/commands.ts b/packages/cli/src/commands.ts index 183ac1cff..12444bab0 100644 --- a/packages/cli/src/commands.ts +++ b/packages/cli/src/commands.ts @@ -6,8 +6,6 @@ import codegen from './commands/codegen'; import context from './commands/context'; import execute from './commands/execute'; import explorer from './commands/explorer'; -import exportSchema from './commands/export-schema'; -import getGraphqlSchema from './commands/get-graphql-schema'; import jobs from './commands/jobs'; import server from './commands/server'; import { usageText } from './utils'; @@ -16,9 +14,7 @@ const createCommandMap = (): Record => { return { server, explorer, - 'get-graphql-schema': getGraphqlSchema, codegen, - 'export-schema': exportSchema, jobs, context, auth, diff --git a/packages/cli/src/commands/codegen.ts b/packages/cli/src/commands/codegen.ts index da6e40d32..a1fa3808b 100644 --- a/packages/cli/src/commands/codegen.ts +++ b/packages/cli/src/commands/codegen.ts @@ -2,6 +2,7 @@ import { CLIOptions, Inquirerer } from 'inquirerer'; import { generate, generateMulti, + expandApiNamesToMultiTarget, findConfigFile, loadConfigFile, codegenQuestions, @@ -38,6 +39,11 @@ Generator Options: --dry-run Preview without writing files --verbose Verbose output +Schema Export: + --schema-only Export GraphQL SDL instead of running full codegen. + Works with any source (endpoint, file, database, PGPM). + With multiple apiNames, writes one .graphql per API. + --help, -h Show this help message `; @@ -51,6 +57,8 @@ export default async ( process.exit(0); } + const schemaOnly = Boolean(argv['schema-only']); + const hasSourceFlags = Boolean( argv.endpoint || argv['schema-file'] || argv.schemas || argv['api-names'] ); @@ -98,6 +106,7 @@ export default async ( const { results, hasError } = await generateMulti({ configs: selectedTargets, cliOverrides: cliOptions as Partial, + schemaOnly, }); for (const { name, result } of results) { @@ -117,6 +126,21 @@ export default async ( ? seeded : await prompter.prompt(seeded, codegenQuestions); const options = buildGenerateOptions(answers, fileConfig); - const result = await generate(options); + + const expanded = expandApiNamesToMultiTarget(options); + if (expanded) { + const { results, hasError } = await generateMulti({ + configs: expanded, + schemaOnly, + }); + for (const { name, result } of results) { + console.log(`\n[${name}]`); + printResult(result); + } + if (hasError) process.exit(1); + return; + } + + const result = await generate({ ...options, schemaOnly }); printResult(result); }; diff --git a/packages/cli/src/commands/export-schema.ts b/packages/cli/src/commands/export-schema.ts deleted file mode 100644 index 757deff96..000000000 --- a/packages/cli/src/commands/export-schema.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { CLIOptions, Inquirerer } from 'inquirerer'; -import { - exportSchemaSimple, - splitCommas, -} from '@constructive-io/graphql-codegen'; - -const usage = ` -Constructive Export Schema (from PGPM module, no server required): - - cnc export-schema [OPTIONS] - -PGPM Source (choose one): - --pgpm-module-path Path to PGPM module directory - --pgpm-workspace-path Path to PGPM workspace directory - --pgpm-module-name Module name within workspace - -Schema Selection (choose one): - --api-names Comma-separated API names - --schemas Comma-separated PostgreSQL schemas - -Output Options: - --output Output directory (default: current directory) - --filename Output filename (default: schema.graphql) - --keep-db Keep ephemeral database after export (debug) - --verbose Verbose output - - --help, -h Show this help message -`; - -export default async ( - argv: Partial>, - _prompter: Inquirerer, - _options: CLIOptions -) => { - if (argv.help || argv.h) { - console.log(usage); - process.exit(0); - } - - const pgpmModulePath = argv['pgpm-module-path'] as string | undefined; - const pgpmWorkspacePath = argv['pgpm-workspace-path'] as string | undefined; - const pgpmModuleName = argv['pgpm-module-name'] as string | undefined; - const output = (argv.output || '.') as string; - const filename = argv.filename as string | undefined; - const verbose = Boolean(argv.verbose); - const keepDb = Boolean(argv['keep-db']); - - const schemas = splitCommas(argv.schemas as string | undefined); - const apiNames = splitCommas(argv['api-names'] as string | undefined); - - if (!pgpmModulePath && !(pgpmWorkspacePath && pgpmModuleName)) { - console.error( - 'x', - 'export-schema requires --pgpm-module-path or both --pgpm-workspace-path and --pgpm-module-name', - ); - process.exit(1); - } - - if (!schemas?.length && !apiNames?.length) { - console.error( - 'x', - 'export-schema requires --schemas or --api-names', - ); - process.exit(1); - } - - const pgpm = pgpmModulePath - ? { modulePath: pgpmModulePath } - : { workspacePath: pgpmWorkspacePath!, moduleName: pgpmModuleName! }; - - const result = await exportSchemaSimple({ - pgpm, - apiNames, - schemas, - output, - filename, - keepDb, - verbose, - }); - - if (result.success) { - console.log('[ok]', result.message); - for (const file of result.files ?? []) { - console.log(` ${file.target}: ${file.path} (schemas: ${file.schemas.join(', ')})`); - } - } else { - console.error('x', result.message); - result.errors?.forEach((e) => console.error(' -', e)); - process.exit(1); - } -}; diff --git a/packages/cli/src/commands/get-graphql-schema.ts b/packages/cli/src/commands/get-graphql-schema.ts deleted file mode 100644 index f44cf2ee0..000000000 --- a/packages/cli/src/commands/get-graphql-schema.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { CLIOptions, Inquirerer, Question } from 'inquirerer'; -import { promises as fs } from 'fs'; -import { buildSchemaSDL, fetchEndpointSchemaSDL } from '@constructive-io/graphql-server'; - -const usage = ` -Constructive Get GraphQL Schema: - - cnc get-graphql-schema [OPTIONS] - -Source Options (choose one): - --endpoint GraphQL endpoint to fetch schema via introspection - --database Database name (default: constructive) - -Options: - --schemas Comma-separated schemas to include - --headerHost Host header to send with endpoint requests - --auth Authorization header value - --out Output file path (default: print to stdout) - - --help, -h Show this help message -`; - -const questions: Question[] = [ - { - name: 'endpoint', - message: 'GraphQL endpoint URL', - type: 'text', - required: false, - }, - { - name: 'database', - message: 'Database name', - type: 'text', - required: false, - }, - { - name: 'schemas', - message: 'Comma-separated schemas', - type: 'text', - required: false, - }, - { - name: 'out', - message: 'Output file path', - type: 'text', - required: false, - }, -]; - -export default async ( - argv: Partial>, - prompter: Inquirerer, - _options: CLIOptions -) => { - if (argv.help || argv.h) { - console.log(usage); - process.exit(0); - } - - const { - endpoint, - database, - schemas: schemasArg, - out, - } = await prompter.prompt(argv, questions); - - const schemas = String(schemasArg).split(',').map((s) => s.trim()).filter(Boolean); - - // Parse repeated --header values into headers object - const headerArg = argv.header as string | string[] | undefined; - const headerList = Array.isArray(headerArg) ? headerArg : headerArg ? [headerArg] : []; - const headers: Record = {}; - for (const h of headerList) { - const idx = typeof h === 'string' ? h.indexOf(':') : -1; - if (idx <= 0) continue; - const name = h.slice(0, idx).trim(); - const value = h.slice(idx + 1).trim(); - if (!name) continue; - headers[name] = value; - } - - let sdl: string; - if (endpoint) { - const opts: Record = {}; - if (argv.headerHost) opts.headerHost = argv.headerHost; - if (argv.auth) opts.auth = argv.auth; - if (Object.keys(headers).length) opts.headers = headers; - sdl = await (fetchEndpointSchemaSDL as (url: string, opts?: Record) => Promise)( - endpoint as string, - opts - ); - } else { - sdl = await buildSchemaSDL({ database: database as string, schemas }); - } - - if (out) { - await fs.writeFile(out as string, sdl, 'utf8'); - console.log(`Wrote schema SDL to ${out}`); - } else { - process.stdout.write(sdl + '\n'); - } -}; From 6f1eaad1403505246d17ab1e5ed1de4eddc0e8db Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Wed, 18 Feb 2026 21:19:41 +0000 Subject: [PATCH 12/23] fix(cli): update tests for removed get-graphql-schema and new expandApiNamesToMultiTarget export --- packages/cli/__tests__/codegen.test.ts | 2 + .../cli/__tests__/get-graphql-schema.test.ts | 162 ------------------ 2 files changed, 2 insertions(+), 162 deletions(-) delete mode 100644 packages/cli/__tests__/get-graphql-schema.test.ts diff --git a/packages/cli/__tests__/codegen.test.ts b/packages/cli/__tests__/codegen.test.ts index c61cdc34b..752127eb7 100644 --- a/packages/cli/__tests__/codegen.test.ts +++ b/packages/cli/__tests__/codegen.test.ts @@ -14,6 +14,8 @@ jest.mock('@constructive-io/graphql-codegen', () => { return { generate: jest.fn(async () => ({ success: true, message: 'Generated SDK', filesWritten: [] as string[] })), + generateMulti: jest.fn(async () => ({ results: [], hasError: false })), + expandApiNamesToMultiTarget: jest.fn(() => null), findConfigFile: jest.fn((): string | undefined => undefined), loadConfigFile: jest.fn(async () => ({ success: false, error: 'not found' })), splitCommas: splitCommasMock, diff --git a/packages/cli/__tests__/get-graphql-schema.test.ts b/packages/cli/__tests__/get-graphql-schema.test.ts deleted file mode 100644 index 587ddfa27..000000000 --- a/packages/cli/__tests__/get-graphql-schema.test.ts +++ /dev/null @@ -1,162 +0,0 @@ -import fs from 'fs'; -import os from 'os'; -import path from 'path'; -import runGetGraphqlSchema from '../src/commands/get-graphql-schema'; - -jest.mock('@constructive-io/graphql-server', () => ({ - buildSchemaSDL: jest.fn(async () => 'type Query { hello: String }\n'), - fetchEndpointSchemaSDL: jest.fn(async () => 'type Query { greeting: String }\n') -})); - -jest.setTimeout(15000); - -describe('cnc get-graphql-schema (mocked)', () => { - const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'constructive-cli-test-')); - const outDbFile = path.join(tempDir, 'schema.db.graphql'); - const outEndpointFile = path.join(tempDir, 'schema.endpoint.graphql'); - const outEndpointHeaderHostFile = path.join(tempDir, 'schema.endpoint.headerhost.graphql'); - const outEndpointAuthFile = path.join(tempDir, 'schema.endpoint.auth.graphql'); - const outEndpointHeadersFile = path.join(tempDir, 'schema.endpoint.headers.graphql'); - const outEndpointAuthAndHeaderFile = path.join(tempDir, 'schema.endpoint.auth_and_header.graphql'); - - const prompter: any = { - prompt: async (argv: any) => argv, - close: jest.fn() - }; - - afterAll(() => { - try { - fs.rmSync(tempDir, { recursive: true, force: true }); - } catch (_) { - // ignore - } - }); - - it('writes SDL to file when building from database', async () => { - const argv: any = { - _: ['get-graphql-schema'], - database: 'mockdb', - schemas: 'public', - out: outDbFile - }; - - await runGetGraphqlSchema(argv, prompter, {} as any); - - expect(fs.existsSync(outDbFile)).toBe(true); - const sdl = fs.readFileSync(outDbFile, 'utf8'); - expect(sdl).toContain('type Query'); - expect(sdl).toContain('hello'); - }); - - it('writes SDL to file when fetching from endpoint', async () => { - const argv: any = { - _: ['get-graphql-schema'], - endpoint: 'http://localhost:5555/graphql', - out: outEndpointFile - }; - - await runGetGraphqlSchema(argv, prompter, {} as any); - - expect(fs.existsSync(outEndpointFile)).toBe(true); - const sdl = fs.readFileSync(outEndpointFile, 'utf8'); - expect(sdl).toContain('type Query'); - expect(sdl).toContain('greeting'); - }); - - it('passes headerHost to fetchEndpointSchemaSDL when provided', async () => { - const argv: any = { - _: ['get-graphql-schema'], - endpoint: 'http://localhost:5555/graphql', - headerHost: 'meta8.localhost', - out: outEndpointHeaderHostFile - }; - - await runGetGraphqlSchema(argv, prompter, {} as any); - - // Verify file written - expect(fs.existsSync(outEndpointHeaderHostFile)).toBe(true); - const sdl = fs.readFileSync(outEndpointHeaderHostFile, 'utf8'); - expect(sdl).toContain('type Query'); - expect(sdl).toContain('greeting'); - - // Verify the mocked function received the headerHost argument - const server = jest.requireMock('@constructive-io/graphql-server') as any; - expect(server.fetchEndpointSchemaSDL).toHaveBeenCalled(); - const lastCall = server.fetchEndpointSchemaSDL.mock.calls[server.fetchEndpointSchemaSDL.mock.calls.length - 1]; - expect(lastCall[0]).toBe('http://localhost:5555/graphql'); - expect(lastCall[1]).toEqual({ headerHost: 'meta8.localhost' }); - }); - - it('passes auth to fetchEndpointSchemaSDL when provided', async () => { - const argv: any = { - _: ['get-graphql-schema'], - endpoint: 'http://localhost:5555/graphql', - auth: 'Bearer 123', - out: outEndpointAuthFile - }; - - await runGetGraphqlSchema(argv, prompter, {} as any); - - // Verify file written - expect(fs.existsSync(outEndpointAuthFile)).toBe(true); - const sdl = fs.readFileSync(outEndpointAuthFile, 'utf8'); - expect(sdl).toContain('type Query'); - expect(sdl).toContain('greeting'); - - // Verify the mocked function received the auth argument - const server = jest.requireMock('@constructive-io/graphql-server') as any; - expect(server.fetchEndpointSchemaSDL).toHaveBeenCalled(); - const lastCall = server.fetchEndpointSchemaSDL.mock.calls[server.fetchEndpointSchemaSDL.mock.calls.length - 1]; - expect(lastCall[0]).toBe('http://localhost:5555/graphql'); - expect(lastCall[1]).toEqual({ auth: 'Bearer 123' }); - }); - - it('passes repeated --header values to fetchEndpointSchemaSDL when provided', async () => { - const argv: any = { - _: ['get-graphql-schema'], - endpoint: 'http://localhost:5555/graphql', - header: ['X-Mode: fast', 'Authorization: Bearer ABC'], - out: outEndpointHeadersFile - }; - - await runGetGraphqlSchema(argv, prompter, {} as any); - - // Verify file written - expect(fs.existsSync(outEndpointHeadersFile)).toBe(true); - const sdl = fs.readFileSync(outEndpointHeadersFile, 'utf8'); - expect(sdl).toContain('type Query'); - expect(sdl).toContain('greeting'); - - // Verify the mocked function received the headers argument - const server = jest.requireMock('@constructive-io/graphql-server') as any; - expect(server.fetchEndpointSchemaSDL).toHaveBeenCalled(); - const lastCall = server.fetchEndpointSchemaSDL.mock.calls[server.fetchEndpointSchemaSDL.mock.calls.length - 1]; - expect(lastCall[0]).toBe('http://localhost:5555/graphql'); - expect(lastCall[1]).toEqual({ headers: { 'X-Mode': 'fast', Authorization: 'Bearer ABC' } }); - }); - - it('forwards both auth and header to fetchEndpointSchemaSDL', async () => { - const argv: any = { - _: ['get-graphql-schema'], - endpoint: 'http://localhost:5555/graphql', - auth: 'Bearer 123', - header: ['Authorization: Bearer override', 'X-Mode: fast'], - out: outEndpointAuthAndHeaderFile - }; - - await runGetGraphqlSchema(argv, prompter, {} as any); - - // Verify file written - expect(fs.existsSync(outEndpointAuthAndHeaderFile)).toBe(true); - const sdl = fs.readFileSync(outEndpointAuthAndHeaderFile, 'utf8'); - expect(sdl).toContain('type Query'); - expect(sdl).toContain('greeting'); - - // Verify the mocked function received both auth and headers - const server = jest.requireMock('@constructive-io/graphql-server') as any; - expect(server.fetchEndpointSchemaSDL).toHaveBeenCalled(); - const lastCall = server.fetchEndpointSchemaSDL.mock.calls[server.fetchEndpointSchemaSDL.mock.calls.length - 1]; - expect(lastCall[0]).toBe('http://localhost:5555/graphql'); - expect(lastCall[1]).toEqual({ auth: 'Bearer 123', headers: { Authorization: 'Bearer override', 'X-Mode': 'fast' } }); - }); -}); From 5a14718886e787128d05d1c5121dd4ef3e429139 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Wed, 18 Feb 2026 21:25:03 +0000 Subject: [PATCH 13/23] fix(cli): add explicit type annotations to test mock for strict TS --- packages/cli/__tests__/codegen.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cli/__tests__/codegen.test.ts b/packages/cli/__tests__/codegen.test.ts index 752127eb7..e0c5ecea2 100644 --- a/packages/cli/__tests__/codegen.test.ts +++ b/packages/cli/__tests__/codegen.test.ts @@ -14,8 +14,8 @@ jest.mock('@constructive-io/graphql-codegen', () => { return { generate: jest.fn(async () => ({ success: true, message: 'Generated SDK', filesWritten: [] as string[] })), - generateMulti: jest.fn(async () => ({ results: [], hasError: false })), - expandApiNamesToMultiTarget: jest.fn(() => null), + generateMulti: jest.fn(async (): Promise<{ results: { name: string; result: { success: boolean } }[]; hasError: boolean }> => ({ results: [], hasError: false })), + expandApiNamesToMultiTarget: jest.fn((): null => null), findConfigFile: jest.fn((): string | undefined => undefined), loadConfigFile: jest.fn(async () => ({ success: false, error: 'not found' })), splitCommas: splitCommasMock, From ddcc81d5e12033252780378681ec87b16599858a Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Wed, 18 Feb 2026 21:52:38 +0000 Subject: [PATCH 14/23] refactor(codegen): remove deprecations, unify camelizeArgv, clean up redundant wrappers - Undeprecate generators/index.ts (active v5 code, not legacy v4) - Undeprecate MetaObject/QueryBuilder exports in core/index.ts - Remove deprecated formatOutput() and its test (replaced by writeGeneratedFiles) - Remove buildSchemaSDLFromDatabase() wrapper, callers use buildSchemaSDL directly - Unify camelizeArgv: camelize once at top of each CLI handler, remove dual manual-kebab + later-camelize pattern --- .../__tests__/codegen/format-output.test.ts | 44 ------------------- graphql/codegen/src/cli/index.ts | 23 ++++------ graphql/codegen/src/core/database/index.ts | 21 --------- graphql/codegen/src/core/index.ts | 2 - .../src/core/introspect/source/database.ts | 5 ++- .../src/core/introspect/source/pgpm-module.ts | 5 ++- graphql/codegen/src/core/output/index.ts | 1 - graphql/codegen/src/core/output/writer.ts | 40 ----------------- graphql/codegen/src/generators/index.ts | 3 -- graphql/codegen/src/index.ts | 5 +-- packages/cli/src/commands/codegen.ts | 16 +++---- 11 files changed, 24 insertions(+), 141 deletions(-) delete mode 100644 graphql/codegen/src/__tests__/codegen/format-output.test.ts diff --git a/graphql/codegen/src/__tests__/codegen/format-output.test.ts b/graphql/codegen/src/__tests__/codegen/format-output.test.ts deleted file mode 100644 index 35169f7fb..000000000 --- a/graphql/codegen/src/__tests__/codegen/format-output.test.ts +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Test for formatOutput function - * Verifies that oxfmt formats generated code correctly - */ -import * as fs from 'node:fs'; -import * as os from 'node:os'; -import * as path from 'node:path'; - -import { formatOutput } from '../../core/output'; - -describe('formatOutput', () => { - let tempDir: string; - - beforeEach(() => { - tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'codegen-format-test-')); - }); - - afterEach(() => { - fs.rmSync(tempDir, { recursive: true, force: true }); - }); - - it('formats TypeScript files with oxfmt options', async () => { - // Write unformatted code (double quotes, missing semicolons) - const unformatted = `const x = "hello" -const obj = {a: 1,b: 2} -`; - fs.writeFileSync(path.join(tempDir, 'test.ts'), unformatted); - - const result = await formatOutput(tempDir); - - // If oxfmt is not available in test environment, skip the test - if (!result.success && result.error?.includes('oxfmt not available')) { - console.log('Skipping test: oxfmt not available in test environment'); - return; - } - - expect(result.success).toBe(true); - - // Verify formatting applied (single quotes, semicolons added) - const formatted = fs.readFileSync(path.join(tempDir, 'test.ts'), 'utf-8'); - expect(formatted).toContain("'hello'"); - expect(formatted).toContain(';'); - }); -}); diff --git a/graphql/codegen/src/cli/index.ts b/graphql/codegen/src/cli/index.ts index 776b3c357..df010b128 100644 --- a/graphql/codegen/src/cli/index.ts +++ b/graphql/codegen/src/cli/index.ts @@ -71,20 +71,17 @@ export const commands = async ( process.exit(0); } - const schemaOnly = Boolean(argv['schema-only']); + const args = camelizeArgv(argv as Record); + + const schemaOnly = Boolean(args.schemaOnly); const hasSourceFlags = Boolean( - argv.endpoint || - argv.e || - argv['schema-file'] || - argv.s || - argv.schemas || - argv['api-names'], + args.endpoint || args.schemaFile || args.schemas || args.apiNames ); - const explicitConfigPath = (argv.config || argv.c) as string | undefined; const configPath = - explicitConfigPath || (!hasSourceFlags ? findConfigFile() : undefined); - const targetName = (argv.target || argv.t) as string | undefined; + (args.config as string | undefined) || + (!hasSourceFlags ? findConfigFile() : undefined); + const targetName = args.target as string | undefined; let fileConfig: GraphQLSDKConfigTarget = {}; @@ -114,9 +111,7 @@ export const commands = async ( } const cliOptions = buildDbConfig( - normalizeCodegenListOptions( - camelizeArgv(argv as Record), - ), + normalizeCodegenListOptions(args), ); const selectedTargets = targetName @@ -142,7 +137,7 @@ export const commands = async ( fileConfig = config as GraphQLSDKConfigTarget; } - const seeded = seedArgvFromConfig(argv, fileConfig); + const seeded = seedArgvFromConfig(args, fileConfig); const answers = hasResolvedCodegenSource(seeded) ? seeded : await prompter.prompt(seeded, codegenQuestions); diff --git a/graphql/codegen/src/core/database/index.ts b/graphql/codegen/src/core/database/index.ts index 1b6cfae53..bc801c3f7 100644 --- a/graphql/codegen/src/core/database/index.ts +++ b/graphql/codegen/src/core/database/index.ts @@ -56,24 +56,3 @@ export async function buildSchemaFromDatabase( return { schemaPath, sdl }; } - -/** - * Build a GraphQL schema SDL string from a PostgreSQL database without writing to file. - * - * This is a convenience wrapper around buildSchemaSDL from graphql-server. - * - * @param options - Configuration options - * @returns The SDL content as a string - */ -export async function buildSchemaSDLFromDatabase(options: { - database: string; - schemas: string[]; -}): Promise { - const { database, schemas } = options; - - // PostGraphile v5 resolves role/settings via preset configuration. - return buildSchemaSDL({ - database, - schemas, - }); -} diff --git a/graphql/codegen/src/core/index.ts b/graphql/codegen/src/core/index.ts index 6b70c545d..3cae1c15c 100644 --- a/graphql/codegen/src/core/index.ts +++ b/graphql/codegen/src/core/index.ts @@ -17,11 +17,9 @@ export * from './ast'; export * from './custom-ast'; // Query builder -/** @deprecated Legacy v4 query builder — use v5 ORM codegen instead */ export { MetaObject, QueryBuilder } from './query-builder'; // Meta object utilities -/** @deprecated Legacy v4 meta-object utilities — v5 uses standard introspection */ export { convertFromMetaSchema, validateMetaObject } from './meta-object'; // Configuration loading and resolution diff --git a/graphql/codegen/src/core/introspect/source/database.ts b/graphql/codegen/src/core/introspect/source/database.ts index 5071fbe0b..de444a049 100644 --- a/graphql/codegen/src/core/introspect/source/database.ts +++ b/graphql/codegen/src/core/introspect/source/database.ts @@ -6,8 +6,9 @@ */ import { buildSchema, introspectionFromSchema } from 'graphql'; +import { buildSchemaSDL } from '@constructive-io/graphql-server'; + import type { IntrospectionQueryResponse } from '../../../types/introspection'; -import { buildSchemaSDLFromDatabase } from '../../database'; import { createDatabasePool, resolveApiSchemas, @@ -80,7 +81,7 @@ export class DatabaseSchemaSource implements SchemaSource { // Build SDL from database let sdl: string; try { - sdl = await buildSchemaSDLFromDatabase({ + sdl = await buildSchemaSDL({ database, schemas, }); diff --git a/graphql/codegen/src/core/introspect/source/pgpm-module.ts b/graphql/codegen/src/core/introspect/source/pgpm-module.ts index 2a02fa70b..1e827572b 100644 --- a/graphql/codegen/src/core/introspect/source/pgpm-module.ts +++ b/graphql/codegen/src/core/introspect/source/pgpm-module.ts @@ -13,8 +13,9 @@ import { getPgPool } from 'pg-cache'; import { createEphemeralDb, type EphemeralDbResult } from 'pgsql-client'; import { deployPgpm } from 'pgsql-seed'; +import { buildSchemaSDL } from '@constructive-io/graphql-server'; + import type { IntrospectionQueryResponse } from '../../../types/introspection'; -import { buildSchemaSDLFromDatabase } from '../../database'; import { resolveApiSchemas, validateServicesSchemas } from './api-schemas'; import type { SchemaSource, SchemaSourceResult } from './types'; import { SchemaSourceError } from './types'; @@ -199,7 +200,7 @@ export class PgpmModuleSchemaSource implements SchemaSource { // Build SDL from the deployed database let sdl: string; try { - sdl = await buildSchemaSDLFromDatabase({ + sdl = await buildSchemaSDL({ database: dbConfig.database, schemas, }); diff --git a/graphql/codegen/src/core/output/index.ts b/graphql/codegen/src/core/output/index.ts index d5047a2fc..e4cbae29b 100644 --- a/graphql/codegen/src/core/output/index.ts +++ b/graphql/codegen/src/core/output/index.ts @@ -3,7 +3,6 @@ */ export { - formatOutput, type GeneratedFile, writeGeneratedFiles, type WriteOptions, diff --git a/graphql/codegen/src/core/output/writer.ts b/graphql/codegen/src/core/output/writer.ts index 630a047d5..2f6de1a13 100644 --- a/graphql/codegen/src/core/output/writer.ts +++ b/graphql/codegen/src/core/output/writer.ts @@ -225,43 +225,3 @@ function findTsFiles(dir: string): string[] { return files; } - -/** - * Format generated files using oxfmt programmatically - * - * @deprecated Use writeGeneratedFiles with formatFiles option instead. - * This function is kept for backwards compatibility. - */ -export async function formatOutput( - outputDir: string, -): Promise<{ success: boolean; error?: string }> { - const formatFn = await getOxfmtFormat(); - if (!formatFn) { - return { - success: false, - error: 'oxfmt not available. Install it with: npm install oxfmt', - }; - } - - const absoluteOutputDir = path.resolve(outputDir); - - try { - // Find all .ts files in the output directory - const tsFiles = findTsFiles(absoluteOutputDir); - - for (const filePath of tsFiles) { - const content = fs.readFileSync(filePath, 'utf-8'); - const formatted = await formatFileContent( - path.basename(filePath), - content, - formatFn, - ); - fs.writeFileSync(filePath, formatted, 'utf-8'); - } - - return { success: true }; - } catch (err) { - const message = err instanceof Error ? err.message : String(err); - return { success: false, error: message }; - } -} diff --git a/graphql/codegen/src/generators/index.ts b/graphql/codegen/src/generators/index.ts index dd6e4a082..d4420dfee 100644 --- a/graphql/codegen/src/generators/index.ts +++ b/graphql/codegen/src/generators/index.ts @@ -1,8 +1,5 @@ /** * Query and mutation generator exports - * - * @deprecated Legacy v4 generators — use v5 ORM codegen pipeline instead. - * These are retained for backward compatibility with existing v4 consumers. */ // Field selector utilities diff --git a/graphql/codegen/src/index.ts b/graphql/codegen/src/index.ts index 60d4cae31..e5a9aa483 100644 --- a/graphql/codegen/src/index.ts +++ b/graphql/codegen/src/index.ts @@ -50,7 +50,4 @@ export type { BuildSchemaFromDatabaseOptions, BuildSchemaFromDatabaseResult, } from './core/database'; -export { - buildSchemaFromDatabase, - buildSchemaSDLFromDatabase, -} from './core/database'; +export { buildSchemaFromDatabase } from './core/database'; diff --git a/packages/cli/src/commands/codegen.ts b/packages/cli/src/commands/codegen.ts index a1fa3808b..4e422c1ae 100644 --- a/packages/cli/src/commands/codegen.ts +++ b/packages/cli/src/commands/codegen.ts @@ -57,12 +57,14 @@ export default async ( process.exit(0); } - const schemaOnly = Boolean(argv['schema-only']); + const args = camelizeArgv(argv as Record); + + const schemaOnly = Boolean(args.schemaOnly); const hasSourceFlags = Boolean( - argv.endpoint || argv['schema-file'] || argv.schemas || argv['api-names'] + args.endpoint || args.schemaFile || args.schemas || args.apiNames ); - const configPath = (argv.config as string | undefined) || + const configPath = (args.config as string | undefined) || (!hasSourceFlags ? findConfigFile() : undefined); let fileConfig: GraphQLSDKConfigTarget = {}; @@ -83,7 +85,7 @@ export default async ( if (isMulti) { const targets = config as Record; - const targetName = argv.target as string | undefined; + const targetName = args.target as string | undefined; if (targetName && !targets[targetName]) { console.error( @@ -94,9 +96,7 @@ export default async ( } const cliOptions = buildDbConfig( - normalizeCodegenListOptions( - camelizeArgv(argv as Record), - ), + normalizeCodegenListOptions(args), ); const selectedTargets = targetName @@ -121,7 +121,7 @@ export default async ( fileConfig = config as GraphQLSDKConfigTarget; } - const seeded = seedArgvFromConfig(argv as Record, fileConfig); + const seeded = seedArgvFromConfig(args, fileConfig); const answers = hasResolvedCodegenSource(seeded) ? seeded : await prompter.prompt(seeded, codegenQuestions); From 44097ee2fa72369eb12373f19429ed5f7ed4c859 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Wed, 18 Feb 2026 22:52:19 +0000 Subject: [PATCH 15/23] feat(codegen): add schemaDir multi-target expansion, unit tests, unify cnc codegen as thin wrapper - Add expandSchemaDirToMultiTarget(): auto-discovers *.graphql files in a directory, creates one target per file named by filename - Add schemaDir config option to GraphQLSDKConfigTarget - Add --schema-dir CLI flag to both graphql-codegen and cnc codegen - Extract shared runCodegenHandler() so cnc codegen delegates to it (no more duplicated logic) - Add 13 unit tests for expandApiNamesToMultiTarget and expandSchemaDirToMultiTarget - Remove pointless camelizeArgv mock from codegen.test.ts - Simplify codegen.test.ts to verify thin wrapper delegation --- .../__tests__/codegen/expand-targets.test.ts | 141 ++++++++++++++++++ graphql/codegen/src/cli/handler.ts | 122 +++++++++++++++ graphql/codegen/src/cli/index.ts | 106 +------------ graphql/codegen/src/core/generate.ts | 32 ++++ graphql/codegen/src/index.ts | 3 +- graphql/codegen/src/types/config.ts | 7 + packages/cli/__tests__/codegen.test.ts | 115 ++------------ packages/cli/src/commands/codegen.ts | 107 +------------ 8 files changed, 324 insertions(+), 309 deletions(-) create mode 100644 graphql/codegen/src/__tests__/codegen/expand-targets.test.ts create mode 100644 graphql/codegen/src/cli/handler.ts diff --git a/graphql/codegen/src/__tests__/codegen/expand-targets.test.ts b/graphql/codegen/src/__tests__/codegen/expand-targets.test.ts new file mode 100644 index 000000000..1dc7ee33c --- /dev/null +++ b/graphql/codegen/src/__tests__/codegen/expand-targets.test.ts @@ -0,0 +1,141 @@ +import * as fs from 'node:fs'; +import * as os from 'node:os'; +import * as path from 'node:path'; + +import { expandApiNamesToMultiTarget, expandSchemaDirToMultiTarget } from '../../core/generate'; + +describe('expandApiNamesToMultiTarget', () => { + it('returns null for no apiNames', () => { + expect(expandApiNamesToMultiTarget({})).toBeNull(); + }); + + it('returns null for empty apiNames', () => { + expect(expandApiNamesToMultiTarget({ db: { apiNames: [] } })).toBeNull(); + }); + + it('returns null for single apiName', () => { + expect( + expandApiNamesToMultiTarget({ db: { apiNames: ['app'] } }), + ).toBeNull(); + }); + + it('expands multiple apiNames into separate targets', () => { + const result = expandApiNamesToMultiTarget({ + db: { apiNames: ['app', 'admin'], pgpm: { workspacePath: '/ws', moduleName: 'mod' } }, + output: './generated', + orm: true, + reactQuery: true, + }); + + expect(result).not.toBeNull(); + expect(Object.keys(result!)).toEqual(['app', 'admin']); + + expect(result!.app.db?.apiNames).toEqual(['app']); + expect(result!.app.output).toBe('./generated/app'); + expect(result!.app.orm).toBe(true); + expect(result!.app.reactQuery).toBe(true); + expect(result!.app.db?.pgpm).toEqual({ workspacePath: '/ws', moduleName: 'mod' }); + + expect(result!.admin.db?.apiNames).toEqual(['admin']); + expect(result!.admin.output).toBe('./generated/admin'); + }); + + it('uses default output path when output is not specified', () => { + const result = expandApiNamesToMultiTarget({ + db: { apiNames: ['app', 'admin'] }, + }); + + expect(result!.app.output).toBe('./generated/graphql/app'); + expect(result!.admin.output).toBe('./generated/graphql/admin'); + }); + + it('preserves all other config properties', () => { + const result = expandApiNamesToMultiTarget({ + db: { apiNames: ['app', 'admin'], pgpm: { modulePath: '/mod' } }, + endpoint: 'http://example.com', + tables: { include: ['users'] }, + hooks: { queries: true }, + }); + + expect(result!.app.endpoint).toBe('http://example.com'); + expect(result!.app.tables).toEqual({ include: ['users'] }); + expect(result!.app.hooks).toEqual({ queries: true }); + }); +}); + +describe('expandSchemaDirToMultiTarget', () => { + let tempDir: string; + + beforeEach(() => { + tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'expand-schema-dir-')); + }); + + afterEach(() => { + fs.rmSync(tempDir, { recursive: true, force: true }); + }); + + it('returns null when schemaDir is not set', () => { + expect(expandSchemaDirToMultiTarget({})).toBeNull(); + }); + + it('returns null when directory does not exist', () => { + expect( + expandSchemaDirToMultiTarget({ schemaDir: '/nonexistent/path' }), + ).toBeNull(); + }); + + it('returns null when directory has no .graphql files', () => { + fs.writeFileSync(path.join(tempDir, 'readme.md'), 'hello'); + expect(expandSchemaDirToMultiTarget({ schemaDir: tempDir })).toBeNull(); + }); + + it('expands .graphql files into separate targets named by filename', () => { + fs.writeFileSync(path.join(tempDir, 'app.graphql'), 'type Query { hello: String }'); + fs.writeFileSync(path.join(tempDir, 'admin.graphql'), 'type Query { users: [User] }'); + + const result = expandSchemaDirToMultiTarget({ + schemaDir: tempDir, + output: './out', + orm: true, + }); + + expect(result).not.toBeNull(); + expect(Object.keys(result!).sort()).toEqual(['admin', 'app']); + + expect(result!.app.schemaFile).toBe(path.join(tempDir, 'app.graphql')); + expect(result!.app.output).toBe('./out/app'); + expect(result!.app.orm).toBe(true); + expect(result!.app.schemaDir).toBeUndefined(); + + expect(result!.admin.schemaFile).toBe(path.join(tempDir, 'admin.graphql')); + expect(result!.admin.output).toBe('./out/admin'); + }); + + it('uses default output path when output is not specified', () => { + fs.writeFileSync(path.join(tempDir, 'api.graphql'), 'type Query { ok: Boolean }'); + + const result = expandSchemaDirToMultiTarget({ schemaDir: tempDir }); + + expect(result!.api.output).toBe('./generated/graphql/api'); + }); + + it('ignores non-.graphql files', () => { + fs.writeFileSync(path.join(tempDir, 'app.graphql'), 'type Query { a: String }'); + fs.writeFileSync(path.join(tempDir, 'notes.txt'), 'not a schema'); + fs.writeFileSync(path.join(tempDir, 'data.json'), '{}'); + + const result = expandSchemaDirToMultiTarget({ schemaDir: tempDir }); + + expect(Object.keys(result!)).toEqual(['app']); + }); + + it('sorts targets alphabetically', () => { + fs.writeFileSync(path.join(tempDir, 'zebra.graphql'), 'type Query { z: String }'); + fs.writeFileSync(path.join(tempDir, 'alpha.graphql'), 'type Query { a: String }'); + fs.writeFileSync(path.join(tempDir, 'mid.graphql'), 'type Query { m: String }'); + + const result = expandSchemaDirToMultiTarget({ schemaDir: tempDir }); + + expect(Object.keys(result!)).toEqual(['alpha', 'mid', 'zebra']); + }); +}); diff --git a/graphql/codegen/src/cli/handler.ts b/graphql/codegen/src/cli/handler.ts new file mode 100644 index 000000000..110e5c259 --- /dev/null +++ b/graphql/codegen/src/cli/handler.ts @@ -0,0 +1,122 @@ +/** + * Shared codegen CLI handler + * + * Contains the core logic used by both `graphql-codegen` and `cnc codegen`. + * Both CLIs delegate to runCodegenHandler() after handling their own + * help/version flags. + */ +import type { Question } from 'inquirerer'; + +import { findConfigFile, loadConfigFile } from '../core/config'; +import { expandApiNamesToMultiTarget, expandSchemaDirToMultiTarget, generate, generateMulti } from '../core/generate'; +import type { GraphQLSDKConfigTarget } from '../types/config'; +import { + buildDbConfig, + buildGenerateOptions, + camelizeArgv, + codegenQuestions, + hasResolvedCodegenSource, + normalizeCodegenListOptions, + printResult, + seedArgvFromConfig, +} from './shared'; + +interface Prompter { + prompt(argv: Record, questions: Question[]): Promise>; +} + +export async function runCodegenHandler( + argv: Record, + prompter: Prompter, +): Promise { + const args = camelizeArgv(argv as Record); + + const schemaOnly = Boolean(args.schemaOnly); + + const hasSourceFlags = Boolean( + args.endpoint || args.schemaFile || args.schemaDir || args.schemas || args.apiNames + ); + const configPath = + (args.config as string | undefined) || + (!hasSourceFlags ? findConfigFile() : undefined); + const targetName = args.target as string | undefined; + + let fileConfig: GraphQLSDKConfigTarget = {}; + + if (configPath) { + const loaded = await loadConfigFile(configPath); + if (!loaded.success) { + console.error('x', loaded.error); + process.exit(1); + } + + const config = loaded.config as Record; + const isMulti = !( + 'endpoint' in config || + 'schemaFile' in config || + 'schemaDir' in config || + 'db' in config + ); + + if (isMulti) { + const targets = config as Record; + + if (targetName && !targets[targetName]) { + console.error( + 'x', + `Target "${targetName}" not found. Available: ${Object.keys(targets).join(', ')}`, + ); + process.exit(1); + } + + const cliOptions = buildDbConfig( + normalizeCodegenListOptions(args), + ); + + const selectedTargets = targetName + ? { [targetName]: targets[targetName] } + : targets; + + const { results, hasError } = await generateMulti({ + configs: selectedTargets, + cliOverrides: cliOptions as Partial, + schemaOnly, + }); + + for (const { name, result } of results) { + console.log(`\n[${name}]`); + printResult(result); + } + + if (hasError) process.exit(1); + return; + } + + fileConfig = config as GraphQLSDKConfigTarget; + } + + const seeded = seedArgvFromConfig(args, fileConfig); + const answers = hasResolvedCodegenSource(seeded) + ? seeded + : await prompter.prompt(seeded, codegenQuestions); + const options = buildGenerateOptions(answers, fileConfig); + + const expandedApi = expandApiNamesToMultiTarget(options); + const expandedDir = expandSchemaDirToMultiTarget(options); + const expanded = expandedApi || expandedDir; + if (expanded) { + const { results, hasError } = await generateMulti({ + configs: expanded, + schemaOnly, + }); + for (const { name, result } of results) { + console.log(`\n[${name}]`); + printResult(result); + } + if (hasError) process.exit(1); + return; + } + + const result = await generate({ ...options, schemaOnly }); + printResult(result); +} diff --git a/graphql/codegen/src/cli/index.ts b/graphql/codegen/src/cli/index.ts index df010b128..6f448a6ed 100644 --- a/graphql/codegen/src/cli/index.ts +++ b/graphql/codegen/src/cli/index.ts @@ -7,19 +7,7 @@ */ import { CLI, CLIOptions, getPackageJson, Inquirerer } from 'inquirerer'; -import { findConfigFile, loadConfigFile } from '../core/config'; -import { expandApiNamesToMultiTarget, generate, generateMulti } from '../core/generate'; -import type { GraphQLSDKConfigTarget } from '../types/config'; -import { - buildDbConfig, - buildGenerateOptions, - camelizeArgv, - codegenQuestions, - hasResolvedCodegenSource, - normalizeCodegenListOptions, - printResult, - seedArgvFromConfig, -} from './shared'; +import { runCodegenHandler } from './handler'; const usage = ` graphql-codegen - GraphQL SDK generator for Constructive databases @@ -31,6 +19,7 @@ Source Options (choose one): -c, --config Path to config file -e, --endpoint GraphQL endpoint URL -s, --schema-file Path to GraphQL schema file + --schema-dir Directory of .graphql files (auto-expands to multi-target) Database Options: --schemas Comma-separated PostgreSQL schemas @@ -71,95 +60,7 @@ export const commands = async ( process.exit(0); } - const args = camelizeArgv(argv as Record); - - const schemaOnly = Boolean(args.schemaOnly); - - const hasSourceFlags = Boolean( - args.endpoint || args.schemaFile || args.schemas || args.apiNames - ); - const configPath = - (args.config as string | undefined) || - (!hasSourceFlags ? findConfigFile() : undefined); - const targetName = args.target as string | undefined; - - let fileConfig: GraphQLSDKConfigTarget = {}; - - if (configPath) { - const loaded = await loadConfigFile(configPath); - if (!loaded.success) { - console.error('x', loaded.error); - process.exit(1); - } - - const config = loaded.config as Record; - const isMulti = !( - 'endpoint' in config || - 'schemaFile' in config || - 'db' in config - ); - - if (isMulti) { - const targets = config as Record; - - if (targetName && !targets[targetName]) { - console.error( - 'x', - `Target "${targetName}" not found. Available: ${Object.keys(targets).join(', ')}`, - ); - process.exit(1); - } - - const cliOptions = buildDbConfig( - normalizeCodegenListOptions(args), - ); - - const selectedTargets = targetName - ? { [targetName]: targets[targetName] } - : targets; - - const { results, hasError } = await generateMulti({ - configs: selectedTargets, - cliOverrides: cliOptions as Partial, - schemaOnly, - }); - - for (const { name, result } of results) { - console.log(`\n[${name}]`); - printResult(result); - } - - prompter.close(); - if (hasError) process.exit(1); - return argv; - } - - fileConfig = config as GraphQLSDKConfigTarget; - } - - const seeded = seedArgvFromConfig(args, fileConfig); - const answers = hasResolvedCodegenSource(seeded) - ? seeded - : await prompter.prompt(seeded, codegenQuestions); - const options = buildGenerateOptions(answers, fileConfig); - - const expanded = expandApiNamesToMultiTarget(options); - if (expanded) { - const { results, hasError } = await generateMulti({ - configs: expanded, - schemaOnly, - }); - for (const { name, result } of results) { - console.log(`\n[${name}]`); - printResult(result); - } - prompter.close(); - if (hasError) process.exit(1); - return argv; - } - - const result = await generate({ ...options, schemaOnly }); - printResult(result); + await runCodegenHandler(argv, prompter); prompter.close(); return argv; }; @@ -181,6 +82,7 @@ export const options: Partial = { 'config', 'endpoint', 'schema-file', + 'schema-dir', 'output', 'target', 'authorization', diff --git a/graphql/codegen/src/core/generate.ts b/graphql/codegen/src/core/generate.ts index 6e56cdfec..06d42c932 100644 --- a/graphql/codegen/src/core/generate.ts +++ b/graphql/codegen/src/core/generate.ts @@ -450,6 +450,38 @@ export function expandApiNamesToMultiTarget( return targets; } +export function expandSchemaDirToMultiTarget( + config: GraphQLSDKConfigTarget, +): Record | null { + const schemaDir = config.schemaDir; + if (!schemaDir) return null; + + const resolvedDir = path.resolve(schemaDir); + if (!fs.existsSync(resolvedDir) || !fs.statSync(resolvedDir).isDirectory()) { + return null; + } + + const graphqlFiles = fs.readdirSync(resolvedDir) + .filter((f) => f.endsWith('.graphql')) + .sort(); + + if (graphqlFiles.length === 0) return null; + + const targets: Record = {}; + for (const file of graphqlFiles) { + const name = path.basename(file, '.graphql'); + targets[name] = { + ...config, + schemaDir: undefined, + schemaFile: path.join(resolvedDir, file), + output: config.output + ? `${config.output}/${name}` + : `./generated/graphql/${name}`, + }; + } + return targets; +} + export interface GenerateMultiOptions { configs: Record; cliOverrides?: Partial; diff --git a/graphql/codegen/src/index.ts b/graphql/codegen/src/index.ts index e5a9aa483..56ea02d77 100644 --- a/graphql/codegen/src/index.ts +++ b/graphql/codegen/src/index.ts @@ -23,12 +23,13 @@ export { defineConfig } from './types/config'; // Main generate function (orchestrates the entire pipeline) export type { GenerateOptions, GenerateResult, GenerateMultiOptions, GenerateMultiResult } from './core/generate'; -export { generate, generateMulti, expandApiNamesToMultiTarget } from './core/generate'; +export { generate, generateMulti, expandApiNamesToMultiTarget, expandSchemaDirToMultiTarget } from './core/generate'; // Config utilities export { findConfigFile, loadConfigFile } from './core/config'; // CLI shared utilities (for packages/cli to import) +export { runCodegenHandler } from './cli/handler'; export type { CodegenAnswers } from './cli/shared'; export { buildDbConfig, diff --git a/graphql/codegen/src/types/config.ts b/graphql/codegen/src/types/config.ts index 4dc7b946e..0ca13a680 100644 --- a/graphql/codegen/src/types/config.ts +++ b/graphql/codegen/src/types/config.ts @@ -221,6 +221,13 @@ export interface GraphQLSDKConfigTarget { */ schemaFile?: string; + /** + * Path to a directory of .graphql schema files for multi-target generation. + * Each *.graphql file becomes its own target, named by the filename (without extension). + * e.g. schemas/app.graphql + schemas/admin.graphql → targets "app" and "admin" + */ + schemaDir?: string; + /** * Database configuration for direct database introspection or PGPM module * Use db.schemas or db.apiNames to specify which schemas to introspect diff --git a/packages/cli/__tests__/codegen.test.ts b/packages/cli/__tests__/codegen.test.ts index e0c5ecea2..49c6dbdcc 100644 --- a/packages/cli/__tests__/codegen.test.ts +++ b/packages/cli/__tests__/codegen.test.ts @@ -1,88 +1,15 @@ -import type { ParsedArgs, Question } from 'inquirerer' +import type { ParsedArgs } from 'inquirerer' import codegenCommand from '../src/commands/codegen' -const splitCommas = (input: string | undefined): string[] | undefined => { - if (!input) return undefined; - return input.split(',').map((s) => s.trim()).filter(Boolean); -}; +const mockRunCodegenHandler = jest.fn(async () => {}); -jest.mock('@constructive-io/graphql-codegen', () => { - const splitCommasMock = (input: string | undefined): string[] | undefined => { - if (!input) return undefined; - return input.split(',').map((s: string) => s.trim()).filter(Boolean); - }; +jest.mock('@constructive-io/graphql-codegen', () => ({ + runCodegenHandler: (...args: any[]) => mockRunCodegenHandler(...args), +})); - return { - generate: jest.fn(async () => ({ success: true, message: 'Generated SDK', filesWritten: [] as string[] })), - generateMulti: jest.fn(async (): Promise<{ results: { name: string; result: { success: boolean } }[]; hasError: boolean }> => ({ results: [], hasError: false })), - expandApiNamesToMultiTarget: jest.fn((): null => null), - findConfigFile: jest.fn((): string | undefined => undefined), - loadConfigFile: jest.fn(async () => ({ success: false, error: 'not found' })), - splitCommas: splitCommasMock, - codegenQuestions: [ - { name: 'endpoint', message: 'GraphQL endpoint URL', type: 'text', required: false }, - { name: 'schema-file', message: 'Path to GraphQL schema file', type: 'text', required: false }, - { name: 'output', message: 'Output directory', type: 'text', required: false, default: 'codegen', useDefault: true }, - { name: 'schemas', message: 'PostgreSQL schemas', type: 'text', required: false, sanitize: splitCommasMock }, - { name: 'api-names', message: 'API names', type: 'text', required: false, sanitize: splitCommasMock }, - { name: 'react-query', message: 'Generate React Query hooks?', type: 'confirm', required: false, default: false, useDefault: true }, - { name: 'orm', message: 'Generate ORM client?', type: 'confirm', required: false, default: false, useDefault: true }, - { name: 'authorization', message: 'Authorization header value', type: 'text', required: false }, - { name: 'dry-run', message: 'Preview without writing files?', type: 'confirm', required: false, default: false, useDefault: true }, - { name: 'verbose', message: 'Verbose output?', type: 'confirm', required: false, default: false, useDefault: true }, - ], - printResult: jest.fn((result: any) => { - if (result.success) { - console.log('[ok]', result.message); - } else { - console.error('x', result.message); - process.exit(1); - } - }), - camelizeArgv: jest.fn((argv: Record) => argv), - seedArgvFromConfig: jest.fn((argv: Record, _fileConfig: any) => argv), - hasResolvedCodegenSource: jest.fn((argv: Record) => { - const db = argv.db as Record | undefined; - return Boolean( - argv.endpoint || - argv['schema-file'] || - argv.schemas || - argv['api-names'] || - db?.schemas || - db?.apiNames - ); - }), - buildGenerateOptions: jest.fn((answers: Record, _fileConfig: any) => { - const { schemas, apiNames, ...rest } = answers; - const normalizedSchemas = Array.isArray(schemas) - ? schemas - : splitCommasMock(schemas as string | undefined); - const normalizedApiNames = Array.isArray(apiNames) - ? apiNames - : splitCommasMock(apiNames as string | undefined); - if (schemas || apiNames) { - return { ...rest, db: { schemas: normalizedSchemas, apiNames: normalizedApiNames } }; - } - return rest; - }), - }; -}) - -// Create a mock prompter that returns argv values and applies sanitize functions from questions const createMockPrompter = () => ({ - prompt: jest.fn(async (argv: any, questions: Question[]) => { - const result = { ...argv }; - // Apply sanitize functions from questions to simulate real prompter behavior - if (questions) { - for (const q of questions) { - if (q.sanitize && result[q.name] !== undefined) { - result[q.name] = q.sanitize(result[q.name], result); - } - } - } - return result; - }) -}) + prompt: jest.fn(async (argv: any) => argv), +}); describe('codegen command', () => { beforeEach(() => { @@ -100,14 +27,13 @@ describe('codegen command', () => { expect(spyLog).toHaveBeenCalled() const first = (spyLog.mock.calls[0]?.[0] as string) || '' expect(first).toContain('Constructive GraphQL Codegen') + expect(mockRunCodegenHandler).not.toHaveBeenCalled() spyLog.mockRestore() spyExit.mockRestore() }) - it('calls generate with endpoint flow options', async () => { - const { generate: mockGenerate } = require('@constructive-io/graphql-codegen') - + it('delegates to runCodegenHandler for endpoint flow', async () => { const argv: Partial = { endpoint: 'http://localhost:3000/graphql', authorization: 'Bearer testtoken', @@ -120,22 +46,10 @@ describe('codegen command', () => { await codegenCommand(argv, mockPrompter as any, {} as any) - expect(mockPrompter.prompt).not.toHaveBeenCalled() - expect(mockGenerate).toHaveBeenCalled() - const call = mockGenerate.mock.calls[0][0] - expect(call).toMatchObject({ - endpoint: 'http://localhost:3000/graphql', - output: 'graphql/codegen/dist', - authorization: 'Bearer testtoken', - verbose: true, - dryRun: true, - reactQuery: true - }) + expect(mockRunCodegenHandler).toHaveBeenCalledWith(argv, mockPrompter) }) - it('calls generate with db options when schemas provided', async () => { - const { generate: mockGenerate } = require('@constructive-io/graphql-codegen') - + it('delegates to runCodegenHandler for db options', async () => { const argv: Partial = { schemas: 'public,app', output: 'graphql/codegen/dist', @@ -145,11 +59,6 @@ describe('codegen command', () => { await codegenCommand(argv, mockPrompter as any, {} as any) - expect(mockPrompter.prompt).not.toHaveBeenCalled() - expect(mockGenerate).toHaveBeenCalled() - const call = mockGenerate.mock.calls[0][0] - expect(call.db).toEqual({ schemas: ['public', 'app'], apiNames: undefined }) - expect(call.output).toBe('graphql/codegen/dist') - expect(call.reactQuery).toBe(true) + expect(mockRunCodegenHandler).toHaveBeenCalledWith(argv, mockPrompter) }) }) diff --git a/packages/cli/src/commands/codegen.ts b/packages/cli/src/commands/codegen.ts index 4e422c1ae..a96649050 100644 --- a/packages/cli/src/commands/codegen.ts +++ b/packages/cli/src/commands/codegen.ts @@ -1,20 +1,5 @@ -import { CLIOptions, Inquirerer } from 'inquirerer'; -import { - generate, - generateMulti, - expandApiNamesToMultiTarget, - findConfigFile, - loadConfigFile, - codegenQuestions, - printResult, - buildGenerateOptions, - buildDbConfig, - camelizeArgv, - normalizeCodegenListOptions, - seedArgvFromConfig, - hasResolvedCodegenSource, - type GraphQLSDKConfigTarget, -} from '@constructive-io/graphql-codegen'; +import type { CLIOptions, Inquirerer } from 'inquirerer'; +import { runCodegenHandler } from '@constructive-io/graphql-codegen'; const usage = ` Constructive GraphQL Codegen: @@ -25,6 +10,7 @@ Source Options (choose one): --config Path to graphql-codegen config file --endpoint GraphQL endpoint URL --schema-file Path to GraphQL schema file + --schema-dir Directory of .graphql files (auto-expands to multi-target) Database Options: --schemas Comma-separated PostgreSQL schemas @@ -57,90 +43,5 @@ export default async ( process.exit(0); } - const args = camelizeArgv(argv as Record); - - const schemaOnly = Boolean(args.schemaOnly); - - const hasSourceFlags = Boolean( - args.endpoint || args.schemaFile || args.schemas || args.apiNames - ); - const configPath = (args.config as string | undefined) || - (!hasSourceFlags ? findConfigFile() : undefined); - - let fileConfig: GraphQLSDKConfigTarget = {}; - - if (configPath) { - const loaded = await loadConfigFile(configPath); - if (!loaded.success) { - console.error('x', loaded.error); - process.exit(1); - } - - const config = loaded.config as Record; - const isMulti = !( - 'endpoint' in config || - 'schemaFile' in config || - 'db' in config - ); - - if (isMulti) { - const targets = config as Record; - const targetName = args.target as string | undefined; - - if (targetName && !targets[targetName]) { - console.error( - 'x', - `Target "${targetName}" not found. Available: ${Object.keys(targets).join(', ')}`, - ); - process.exit(1); - } - - const cliOptions = buildDbConfig( - normalizeCodegenListOptions(args), - ); - - const selectedTargets = targetName - ? { [targetName]: targets[targetName] } - : targets; - - const { results, hasError } = await generateMulti({ - configs: selectedTargets, - cliOverrides: cliOptions as Partial, - schemaOnly, - }); - - for (const { name, result } of results) { - console.log(`\n[${name}]`); - printResult(result); - } - - if (hasError) process.exit(1); - return; - } - - fileConfig = config as GraphQLSDKConfigTarget; - } - - const seeded = seedArgvFromConfig(args, fileConfig); - const answers = hasResolvedCodegenSource(seeded) - ? seeded - : await prompter.prompt(seeded, codegenQuestions); - const options = buildGenerateOptions(answers, fileConfig); - - const expanded = expandApiNamesToMultiTarget(options); - if (expanded) { - const { results, hasError } = await generateMulti({ - configs: expanded, - schemaOnly, - }); - for (const { name, result } of results) { - console.log(`\n[${name}]`); - printResult(result); - } - if (hasError) process.exit(1); - return; - } - - const result = await generate({ ...options, schemaOnly }); - printResult(result); + await runCodegenHandler(argv as Record, prompter); }; From 4825be30bc2cc0a3b20d3e151203a55ce841f775 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Wed, 18 Feb 2026 22:57:00 +0000 Subject: [PATCH 16/23] fix(cli): fix spread argument type error in codegen test mock --- packages/cli/__tests__/codegen.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/__tests__/codegen.test.ts b/packages/cli/__tests__/codegen.test.ts index 49c6dbdcc..7445157f8 100644 --- a/packages/cli/__tests__/codegen.test.ts +++ b/packages/cli/__tests__/codegen.test.ts @@ -4,7 +4,7 @@ import codegenCommand from '../src/commands/codegen' const mockRunCodegenHandler = jest.fn(async () => {}); jest.mock('@constructive-io/graphql-codegen', () => ({ - runCodegenHandler: (...args: any[]) => mockRunCodegenHandler(...args), + runCodegenHandler: (argv: Record, prompter: unknown) => mockRunCodegenHandler(argv, prompter), })); const createMockPrompter = () => ({ From f7c988a6912ba207e7b1cfd268aa0ad6e3a5b55c Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Wed, 18 Feb 2026 23:01:41 +0000 Subject: [PATCH 17/23] fix(cli): type mock function parameters to fix TS2554 in CI --- packages/cli/__tests__/codegen.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/__tests__/codegen.test.ts b/packages/cli/__tests__/codegen.test.ts index 7445157f8..9282a8487 100644 --- a/packages/cli/__tests__/codegen.test.ts +++ b/packages/cli/__tests__/codegen.test.ts @@ -1,7 +1,7 @@ import type { ParsedArgs } from 'inquirerer' import codegenCommand from '../src/commands/codegen' -const mockRunCodegenHandler = jest.fn(async () => {}); +const mockRunCodegenHandler = jest.fn, [Record, unknown]>(); jest.mock('@constructive-io/graphql-codegen', () => ({ runCodegenHandler: (argv: Record, prompter: unknown) => mockRunCodegenHandler(argv, prompter), From 1fef68d15f223003375b4facdf519dfc71000d34 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Wed, 18 Feb 2026 23:22:04 +0000 Subject: [PATCH 18/23] ci: trigger CI run for latest changes From 458702780393dd4ca514e311d10f11143ee7a254 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Thu, 19 Feb 2026 00:00:57 +0000 Subject: [PATCH 19/23] feat: add graphile-schema package, README headers/footers, and --schema-only tests - Create graphile-schema package with buildSchemaSDL (pg-env/pg-cache, deepmerge) and fetchEndpointSchemaSDL - Update codegen imports from @constructive-io/graphql-server to graphile-schema - Add getReadmeHeader/getReadmeFooter to docs-utils.ts with Constructive logo and disclaimer - Update all 6 README generators to use header/footer - Add schema-only tests covering deleted get-graphql-schema scenarios - Update snapshot tests - Fix require('@pgpmjs/core') -> proper ES6 import in generate.ts --- graphile/graphile-schema/README.md | 97 ++++++++++++++ graphile/graphile-schema/jest.config.js | 18 +++ graphile/graphile-schema/package.json | 53 ++++++++ graphile/graphile-schema/src/build-schema.ts | 44 +++++++ .../src/fetch-endpoint-schema.ts | 80 ++++++++++++ graphile/graphile-schema/src/index.ts | 4 + graphile/graphile-schema/tsconfig.esm.json | 8 ++ graphile/graphile-schema/tsconfig.json | 10 ++ graphql/codegen/package.json | 2 +- .../__snapshots__/cli-generator.test.ts.snap | 88 ++++++++++++- .../src/__tests__/codegen/schema-only.test.ts | 87 +++++++++++++ .../src/core/codegen/cli/docs-generator.ts | 18 ++- .../codegen/src/core/codegen/docs-utils.ts | 33 +++++ .../src/core/codegen/hooks-docs-generator.ts | 10 +- .../src/core/codegen/orm/docs-generator.ts | 10 +- .../src/core/codegen/target-docs-generator.ts | 15 +-- graphql/codegen/src/core/database/index.ts | 2 +- graphql/codegen/src/core/generate.ts | 2 +- .../src/core/introspect/source/database.ts | 2 +- .../src/core/introspect/source/pgpm-module.ts | 2 +- graphql/server/package.json | 1 + graphql/server/src/schema.ts | 120 +----------------- pnpm-lock.yaml | 99 +++++++++++---- 23 files changed, 628 insertions(+), 177 deletions(-) create mode 100644 graphile/graphile-schema/README.md create mode 100644 graphile/graphile-schema/jest.config.js create mode 100644 graphile/graphile-schema/package.json create mode 100644 graphile/graphile-schema/src/build-schema.ts create mode 100644 graphile/graphile-schema/src/fetch-endpoint-schema.ts create mode 100644 graphile/graphile-schema/src/index.ts create mode 100644 graphile/graphile-schema/tsconfig.esm.json create mode 100644 graphile/graphile-schema/tsconfig.json create mode 100644 graphql/codegen/src/__tests__/codegen/schema-only.test.ts diff --git a/graphile/graphile-schema/README.md b/graphile/graphile-schema/README.md new file mode 100644 index 000000000..4049037ee --- /dev/null +++ b/graphile/graphile-schema/README.md @@ -0,0 +1,97 @@ +# graphile-schema + +

+ +

+ +

+ + + + + + + + + +

+ +Lightweight GraphQL SDL builder for PostgreSQL using PostGraphile v5. Build schemas directly from a database or fetch them from a running GraphQL endpoint — no server dependencies required. + +## Installation + +```bash +npm install graphile-schema +``` + +## Usage + +### Build SDL from a PostgreSQL Database + +```typescript +import { buildSchemaSDL } from 'graphile-schema'; + +const sdl = await buildSchemaSDL({ + database: 'mydb', + schemas: ['app_public'], +}); + +console.log(sdl); +``` + +### Fetch SDL from a GraphQL Endpoint + +```typescript +import { fetchEndpointSchemaSDL } from 'graphile-schema'; + +const sdl = await fetchEndpointSchemaSDL('https://api.example.com/graphql', { + auth: 'Bearer my-token', + headers: { 'X-Custom-Header': 'value' }, +}); + +console.log(sdl); +``` + +### With Custom Graphile Presets + +```typescript +import { buildSchemaSDL } from 'graphile-schema'; + +const sdl = await buildSchemaSDL({ + database: 'mydb', + schemas: ['app_public', 'app_private'], + graphile: { + extends: [MyCustomPreset], + schema: { pgSimplifyPatch: false }, + }, +}); +``` + +## API + +### `buildSchemaSDL(opts)` + +Builds a GraphQL SDL string directly from a PostgreSQL database using PostGraphile v5 introspection. + +| Option | Type | Description | +|--------|------|-------------| +| `database` | `string` | Database name (default: `'constructive'`) | +| `schemas` | `string[]` | PostgreSQL schemas to introspect | +| `graphile` | `Partial` | Optional Graphile preset overrides | + +### `fetchEndpointSchemaSDL(endpoint, opts?)` + +Fetches a GraphQL SDL string from a running GraphQL endpoint via introspection query. + +| Option | Type | Description | +|--------|------|-------------| +| `endpoint` | `string` | GraphQL endpoint URL | +| `opts.headerHost` | `string` | Override the `Host` header | +| `opts.auth` | `string` | `Authorization` header value | +| `opts.headers` | `Record` | Additional request headers | + +## Disclaimer + +AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED "AS IS", AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND. + +No developer or entity involved in creating this software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the code, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value. diff --git a/graphile/graphile-schema/jest.config.js b/graphile/graphile-schema/jest.config.js new file mode 100644 index 000000000..057a9420e --- /dev/null +++ b/graphile/graphile-schema/jest.config.js @@ -0,0 +1,18 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} */ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + transform: { + '^.+\\.tsx?$': [ + 'ts-jest', + { + babelConfig: false, + tsconfig: 'tsconfig.json', + }, + ], + }, + transformIgnorePatterns: [`/node_modules/*`], + testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$', + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], + modulePathIgnorePatterns: ['dist/*'] +}; diff --git a/graphile/graphile-schema/package.json b/graphile/graphile-schema/package.json new file mode 100644 index 000000000..029e7d136 --- /dev/null +++ b/graphile/graphile-schema/package.json @@ -0,0 +1,53 @@ +{ + "name": "graphile-schema", + "version": "1.0.0", + "author": "Constructive ", + "description": "Build GraphQL SDL from PostgreSQL databases using PostGraphile v5", + "main": "index.js", + "module": "esm/index.js", + "types": "index.d.ts", + "homepage": "https://github.com/constructive-io/constructive", + "license": "MIT", + "publishConfig": { + "access": "public", + "directory": "dist" + }, + "repository": { + "type": "git", + "url": "https://github.com/constructive-io/constructive" + }, + "bugs": { + "url": "https://github.com/constructive-io/constructive/issues" + }, + "scripts": { + "clean": "makage clean", + "prepack": "npm run build", + "build": "makage build", + "build:dev": "makage build --dev", + "lint": "eslint . --fix", + "test": "jest --passWithNoTests", + "test:watch": "jest --watch" + }, + "dependencies": { + "deepmerge": "^4.3.1", + "graphile-build": "^5.0.0-rc.3", + "graphile-config": "1.0.0-rc.3", + "graphile-settings": "workspace:^", + "graphql": "^16.9.0", + "pg-cache": "workspace:^", + "pg-env": "workspace:^" + }, + "devDependencies": { + "makage": "^0.1.10", + "ts-node": "^10.9.2" + }, + "keywords": [ + "graphile", + "schema", + "graphql", + "sdl", + "postgraphile", + "introspection", + "constructive" + ] +} diff --git a/graphile/graphile-schema/src/build-schema.ts b/graphile/graphile-schema/src/build-schema.ts new file mode 100644 index 000000000..34cf5b3ab --- /dev/null +++ b/graphile/graphile-schema/src/build-schema.ts @@ -0,0 +1,44 @@ +import deepmerge from 'deepmerge' +import { printSchema } from 'graphql' +import { ConstructivePreset, makePgService } from 'graphile-settings' +import { makeSchema } from 'graphile-build' +import { buildConnectionString } from 'pg-cache' +import { getPgEnvOptions } from 'pg-env' +import type { GraphileConfig } from 'graphile-config' + +export type BuildSchemaOptions = { + database?: string; + schemas: string[]; + graphile?: Partial; +}; + +export async function buildSchemaSDL(opts: BuildSchemaOptions): Promise { + const database = opts.database ?? 'constructive' + const schemas = Array.isArray(opts.schemas) ? opts.schemas : [] + + const config = getPgEnvOptions({ database }) + const connectionString = buildConnectionString( + config.user, + config.password, + config.host, + config.port, + config.database, + ) + + const basePreset: GraphileConfig.Preset = { + extends: [ConstructivePreset], + pgServices: [ + makePgService({ + connectionString, + schemas, + }), + ], + } + + const preset: GraphileConfig.Preset = opts.graphile + ? deepmerge(basePreset, opts.graphile) + : basePreset + + const { schema } = await makeSchema(preset) + return printSchema(schema) +} diff --git a/graphile/graphile-schema/src/fetch-endpoint-schema.ts b/graphile/graphile-schema/src/fetch-endpoint-schema.ts new file mode 100644 index 000000000..11a8d33b9 --- /dev/null +++ b/graphile/graphile-schema/src/fetch-endpoint-schema.ts @@ -0,0 +1,80 @@ +import { getIntrospectionQuery, buildClientSchema, printSchema } from 'graphql' +import * as http from 'node:http' +import * as https from 'node:https' + +export type FetchEndpointSchemaOptions = { + headerHost?: string; + headers?: Record; + auth?: string; +}; + +export async function fetchEndpointSchemaSDL(endpoint: string, opts?: FetchEndpointSchemaOptions): Promise { + const url = new URL(endpoint) + const requestUrl = url + + const introspectionQuery = getIntrospectionQuery({ descriptions: true }) + const postData = JSON.stringify({ + query: introspectionQuery, + variables: null, + operationName: 'IntrospectionQuery', + }) + + const headers: Record = { + 'Content-Type': 'application/json', + 'Content-Length': String(Buffer.byteLength(postData)), + } + if (opts?.headerHost) { + headers['Host'] = opts.headerHost + } + if (opts?.auth) { + headers['Authorization'] = opts.auth + } + if (opts?.headers) { + for (const [key, value] of Object.entries(opts.headers)) { + headers[key] = value + } + } + + const isHttps = requestUrl.protocol === 'https:' + const lib = isHttps ? https : http + + const responseData: string = await new Promise((resolve, reject) => { + const req = lib.request({ + hostname: requestUrl.hostname, + port: (requestUrl.port ? Number(requestUrl.port) : (isHttps ? 443 : 80)), + path: requestUrl.pathname, + method: 'POST', + headers, + }, (res) => { + let data = '' + res.on('data', (chunk) => { data += chunk }) + res.on('end', () => { + if (res.statusCode && res.statusCode >= 400) { + reject(new Error(`HTTP ${res.statusCode} – ${data}`)) + return + } + resolve(data) + }) + }) + req.on('error', (err) => reject(err)) + req.write(postData) + req.end() + }) + + let json: any + try { + json = JSON.parse(responseData) + } catch (e) { + throw new Error(`Failed to parse response: ${responseData}`) + } + + if (json.errors) { + throw new Error('Introspection returned errors') + } + if (!json.data) { + throw new Error('No data in introspection response') + } + + const schema = buildClientSchema(json.data as any) + return printSchema(schema) +} diff --git a/graphile/graphile-schema/src/index.ts b/graphile/graphile-schema/src/index.ts new file mode 100644 index 000000000..840b76710 --- /dev/null +++ b/graphile/graphile-schema/src/index.ts @@ -0,0 +1,4 @@ +export { buildSchemaSDL } from './build-schema'; +export type { BuildSchemaOptions } from './build-schema'; +export { fetchEndpointSchemaSDL } from './fetch-endpoint-schema'; +export type { FetchEndpointSchemaOptions } from './fetch-endpoint-schema'; diff --git a/graphile/graphile-schema/tsconfig.esm.json b/graphile/graphile-schema/tsconfig.esm.json new file mode 100644 index 000000000..d35ab5318 --- /dev/null +++ b/graphile/graphile-schema/tsconfig.esm.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "dist/esm", + "module": "ESNext", + "moduleResolution": "bundler" + } +} diff --git a/graphile/graphile-schema/tsconfig.json b/graphile/graphile-schema/tsconfig.json new file mode 100644 index 000000000..a54950429 --- /dev/null +++ b/graphile/graphile-schema/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "moduleResolution": "nodenext", + "module": "nodenext" + }, + "include": ["src/**/*"] +} diff --git a/graphql/codegen/package.json b/graphql/codegen/package.json index d55395a78..35d425b5f 100644 --- a/graphql/codegen/package.json +++ b/graphql/codegen/package.json @@ -56,7 +56,6 @@ "@0no-co/graphql.web": "^1.1.2", "@babel/generator": "^7.28.6", "@babel/types": "^7.28.6", - "@constructive-io/graphql-server": "workspace:^", "@constructive-io/graphql-types": "workspace:^", "@inquirerer/utils": "^3.2.3", "@pgpmjs/core": "workspace:^", @@ -64,6 +63,7 @@ "deepmerge": "^4.3.1", "find-and-require-package-json": "^0.9.0", "gql-ast": "workspace:^", + "graphile-schema": "workspace:^", "graphql": "^16.9.0", "inflekt": "^0.3.1", "inquirerer": "^4.4.0", diff --git a/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap b/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap index cbdddfa8b..280608677 100644 --- a/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap +++ b/graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap @@ -214,7 +214,10 @@ Common errors: exports[`cli docs generator generates CLI README 1`] = ` "# myapp CLI -> Auto-generated CLI commands from GraphQL schema +

+ +

+ > @generated by @constructive-io/graphql-codegen - DO NOT EDIT ## Setup @@ -345,6 +348,16 @@ All commands output JSON to stdout. Pipe to \`jq\` for formatting: myapp car list | jq '.[]' myapp car get --id | jq '.' \`\`\` + +--- + +Built by the [Constructive](https://constructive.io) team. + +## Disclaimer + +AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED "AS IS", AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND. + +No developer or entity involved in creating this software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the code, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value. " `; @@ -1604,7 +1617,10 @@ OUTPUT: UseMutationResult exports[`hooks docs generator generates hooks README 1`] = ` "# React Query Hooks -> Auto-generated React Query hooks from GraphQL schema +

+ +

+ > @generated by @constructive-io/graphql-codegen - DO NOT EDIT ## Setup @@ -1710,6 +1726,16 @@ Authenticate a user |----------|------| | \`email\` | String (required) | | \`password\` | String (required) | + +--- + +Built by the [Constructive](https://constructive.io) team. + +## Disclaimer + +AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED "AS IS", AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND. + +No developer or entity involved in creating this software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the code, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value. " `; @@ -2609,7 +2635,10 @@ exports[`multi-target cli docs generates multi-target MCP tools 1`] = ` exports[`multi-target cli docs generates multi-target README 1`] = ` "# myapp CLI -> Auto-generated unified multi-target CLI from GraphQL schemas +

+ +

+ > @generated by @constructive-io/graphql-codegen - DO NOT EDIT ## Setup @@ -2819,6 +2848,16 @@ All commands output JSON to stdout. Pipe to \`jq\` for formatting: myapp auth:user list | jq '.[]' myapp auth:user get --id | jq '.' \`\`\` + +--- + +Built by the [Constructive](https://constructive.io) team. + +## Disclaimer + +AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED "AS IS", AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND. + +No developer or entity involved in creating this software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the code, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value. " `; @@ -4238,7 +4277,10 @@ const filtered = await db.modelName.findMany({ select: { id: true }, where: { na exports[`orm docs generator generates ORM README 1`] = ` "# ORM Client -> Auto-generated ORM client from GraphQL schema +

+ +

+ > @generated by @constructive-io/graphql-codegen - DO NOT EDIT ## Setup @@ -4354,6 +4396,16 @@ Authenticate a user \`\`\`typescript const result = await db.mutation.login({ email: '', password: '' }).execute(); \`\`\` + +--- + +Built by the [Constructive](https://constructive.io) team. + +## Disclaimer + +AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED "AS IS", AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND. + +No developer or entity involved in creating this software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the code, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value. " `; @@ -5186,6 +5238,10 @@ exports[`target docs generator generates combined MCP config 1`] = ` exports[`target docs generator generates per-target README 1`] = ` "# Generated GraphQL SDK +

+ +

+ > @generated by @constructive-io/graphql-codegen - DO NOT EDIT ## Overview @@ -5230,12 +5286,26 @@ See [hooks/README.md](./hooks/README.md) for full hook reference. inquirerer-based CLI commands for \`myapp\`. See [cli/README.md](./cli/README.md) for command reference. + +--- + +Built by the [Constructive](https://constructive.io) team. + +## Disclaimer + +AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED "AS IS", AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND. + +No developer or entity involved in creating this software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the code, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value. " `; exports[`target docs generator generates root-root README for multi-target 1`] = ` "# GraphQL SDK +

+ +

+ > @generated by @constructive-io/graphql-codegen - DO NOT EDIT ## APIs @@ -5244,5 +5314,15 @@ exports[`target docs generator generates root-root README for multi-target 1`] = |-----|----------|------------|------| | auth | http://auth.localhost/graphql | ORM | [./generated/auth/README.md](./generated/auth/README.md) | | app | http://app.localhost/graphql | ORM, React Query, CLI | [./generated/app/README.md](./generated/app/README.md) | + +--- + +Built by the [Constructive](https://constructive.io) team. + +## Disclaimer + +AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED "AS IS", AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND. + +No developer or entity involved in creating this software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the code, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value. " `; diff --git a/graphql/codegen/src/__tests__/codegen/schema-only.test.ts b/graphql/codegen/src/__tests__/codegen/schema-only.test.ts new file mode 100644 index 000000000..7761e9a85 --- /dev/null +++ b/graphql/codegen/src/__tests__/codegen/schema-only.test.ts @@ -0,0 +1,87 @@ +import * as fs from 'node:fs'; +import * as os from 'node:os'; +import * as path from 'node:path'; + +import { generate } from '../../core/generate'; + +const EXAMPLE_SCHEMA = path.resolve( + __dirname, + '../../../examples/example.schema.graphql', +); + +describe('generate() with schemaOnly', () => { + let tempDir: string; + + beforeEach(() => { + tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'schema-only-test-')); + }); + + afterEach(() => { + fs.rmSync(tempDir, { recursive: true, force: true }); + }); + + it('writes SDL to file from schemaFile source', async () => { + const result = await generate({ + schemaFile: EXAMPLE_SCHEMA, + schemaOnly: true, + schemaOnlyOutput: tempDir, + }); + + expect(result.success).toBe(true); + expect(result.filesWritten).toHaveLength(1); + + const outFile = path.join(tempDir, 'schema.graphql'); + expect(fs.existsSync(outFile)).toBe(true); + + const sdl = fs.readFileSync(outFile, 'utf8'); + expect(sdl).toContain('type Query'); + expect(sdl).toContain('type User'); + }); + + it('uses custom filename when schemaOnlyFilename is set', async () => { + const result = await generate({ + schemaFile: EXAMPLE_SCHEMA, + schemaOnly: true, + schemaOnlyOutput: tempDir, + schemaOnlyFilename: 'app.graphql', + }); + + expect(result.success).toBe(true); + const outFile = path.join(tempDir, 'app.graphql'); + expect(fs.existsSync(outFile)).toBe(true); + }); + + it('succeeds without any generators enabled', async () => { + const result = await generate({ + schemaFile: EXAMPLE_SCHEMA, + schemaOnly: true, + schemaOnlyOutput: tempDir, + }); + + expect(result.success).toBe(true); + expect(result.message).toContain('Schema exported to'); + }); + + it('fails when no source is specified', async () => { + const result = await generate({ + schemaOnly: true, + schemaOnlyOutput: tempDir, + }); + + expect(result.success).toBe(false); + expect(result.message).toContain('No source specified'); + }); + + it('creates output directory if it does not exist', async () => { + const nestedDir = path.join(tempDir, 'nested', 'output'); + + const result = await generate({ + schemaFile: EXAMPLE_SCHEMA, + schemaOnly: true, + schemaOnlyOutput: nestedDir, + }); + + expect(result.success).toBe(true); + expect(fs.existsSync(path.join(nestedDir, 'schema.graphql'))).toBe(true); + }); +}); diff --git a/graphql/codegen/src/core/codegen/cli/docs-generator.ts b/graphql/codegen/src/core/codegen/cli/docs-generator.ts index c039e6c18..88f063d37 100644 --- a/graphql/codegen/src/core/codegen/cli/docs-generator.ts +++ b/graphql/codegen/src/core/codegen/cli/docs-generator.ts @@ -4,6 +4,8 @@ import type { CleanTable, CleanOperation } from '../../../types/schema'; import { formatArgType, getEditableFields, + getReadmeHeader, + getReadmeFooter, gqlTypeToJsonSchemaType, buildSkillFile, } from '../docs-utils'; @@ -24,11 +26,7 @@ export function generateReadme( ): GeneratedDocFile { const lines: string[] = []; - lines.push(`# ${toolName} CLI`); - lines.push(''); - lines.push('> Auto-generated CLI commands from GraphQL schema'); - lines.push('> @generated by @constructive-io/graphql-codegen - DO NOT EDIT'); - lines.push(''); + lines.push(...getReadmeHeader(`${toolName} CLI`)); lines.push('## Setup'); lines.push(''); lines.push('```bash'); @@ -157,6 +155,8 @@ export function generateReadme( lines.push('```'); lines.push(''); + lines.push(...getReadmeFooter()); + return { fileName: 'README.md', content: lines.join('\n'), @@ -737,11 +737,7 @@ export function generateMultiTargetReadme( const { toolName, builtinNames, targets } = input; const lines: string[] = []; - lines.push(`# ${toolName} CLI`); - lines.push(''); - lines.push('> Auto-generated unified multi-target CLI from GraphQL schemas'); - lines.push('> @generated by @constructive-io/graphql-codegen - DO NOT EDIT'); - lines.push(''); + lines.push(...getReadmeHeader(`${toolName} CLI`)); lines.push('## Setup'); lines.push(''); @@ -938,6 +934,8 @@ export function generateMultiTargetReadme( lines.push('```'); lines.push(''); + lines.push(...getReadmeFooter()); + return { fileName: 'README.md', content: lines.join('\n'), diff --git a/graphql/codegen/src/core/codegen/docs-utils.ts b/graphql/codegen/src/core/codegen/docs-utils.ts index 2e5a7d4b6..bab5c1d74 100644 --- a/graphql/codegen/src/core/codegen/docs-utils.ts +++ b/graphql/codegen/src/core/codegen/docs-utils.ts @@ -22,6 +22,39 @@ export interface SkillDefinition { language?: string; } +const CONSTRUCTIVE_LOGO_URL = + 'https://raw.githubusercontent.com/constructive-io/constructive/refs/heads/main/assets/outline-logo.svg'; + +const CONSTRUCTIVE_REPO = 'https://github.com/constructive-io/constructive'; + +export function getReadmeHeader(title: string): string[] { + return [ + `# ${title}`, + '', + '

', + ` `, + '

', + '', + `> @generated by @constructive-io/graphql-codegen - DO NOT EDIT`, + '', + ]; +} + +export function getReadmeFooter(): string[] { + return [ + '---', + '', + 'Built by the [Constructive](https://constructive.io) team.', + '', + '## Disclaimer', + '', + 'AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED "AS IS", AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND.', + '', + 'No developer or entity involved in creating this software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the code, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value.', + '', + ]; +} + export function resolveDocsConfig( docs: DocsConfig | boolean | undefined, ): DocsConfig { diff --git a/graphql/codegen/src/core/codegen/hooks-docs-generator.ts b/graphql/codegen/src/core/codegen/hooks-docs-generator.ts index 12e6ffd5a..4a7f93e45 100644 --- a/graphql/codegen/src/core/codegen/hooks-docs-generator.ts +++ b/graphql/codegen/src/core/codegen/hooks-docs-generator.ts @@ -2,6 +2,8 @@ import type { CleanOperation, CleanTable } from '../../types/schema'; import { buildSkillFile, formatArgType, + getReadmeHeader, + getReadmeFooter, gqlTypeToJsonSchemaType, } from './docs-utils'; import type { GeneratedDocFile, McpTool } from './docs-utils'; @@ -33,11 +35,7 @@ export function generateHooksReadme( ): GeneratedDocFile { const lines: string[] = []; - lines.push('# React Query Hooks'); - lines.push(''); - lines.push('> Auto-generated React Query hooks from GraphQL schema'); - lines.push('> @generated by @constructive-io/graphql-codegen - DO NOT EDIT'); - lines.push(''); + lines.push(...getReadmeHeader('React Query Hooks')); lines.push('## Setup'); lines.push(''); lines.push('```typescript'); @@ -170,6 +168,8 @@ export function generateHooksReadme( } } + lines.push(...getReadmeFooter()); + return { fileName: 'README.md', content: lines.join('\n'), diff --git a/graphql/codegen/src/core/codegen/orm/docs-generator.ts b/graphql/codegen/src/core/codegen/orm/docs-generator.ts index 1389d6160..950994c60 100644 --- a/graphql/codegen/src/core/codegen/orm/docs-generator.ts +++ b/graphql/codegen/src/core/codegen/orm/docs-generator.ts @@ -3,6 +3,8 @@ import { buildSkillFile, formatArgType, getEditableFields, + getReadmeHeader, + getReadmeFooter, gqlTypeToJsonSchemaType, } from '../docs-utils'; import type { GeneratedDocFile, McpTool } from '../docs-utils'; @@ -20,11 +22,7 @@ export function generateOrmReadme( ): GeneratedDocFile { const lines: string[] = []; - lines.push('# ORM Client'); - lines.push(''); - lines.push('> Auto-generated ORM client from GraphQL schema'); - lines.push('> @generated by @constructive-io/graphql-codegen - DO NOT EDIT'); - lines.push(''); + lines.push(...getReadmeHeader('ORM Client')); lines.push('## Setup'); lines.push(''); lines.push('```typescript'); @@ -143,6 +141,8 @@ export function generateOrmReadme( } } + lines.push(...getReadmeFooter()); + return { fileName: 'README.md', content: lines.join('\n'), diff --git a/graphql/codegen/src/core/codegen/target-docs-generator.ts b/graphql/codegen/src/core/codegen/target-docs-generator.ts index ab8b5d851..d5215b77d 100644 --- a/graphql/codegen/src/core/codegen/target-docs-generator.ts +++ b/graphql/codegen/src/core/codegen/target-docs-generator.ts @@ -1,4 +1,5 @@ import type { GraphQLSDKConfigTarget } from '../../types/config'; +import { getReadmeHeader, getReadmeFooter } from './docs-utils'; import type { GeneratedDocFile, McpTool } from './docs-utils'; export interface TargetReadmeOptions { @@ -25,10 +26,7 @@ export function generateTargetReadme( } = options; const lines: string[] = []; - lines.push('# Generated GraphQL SDK'); - lines.push(''); - lines.push('> @generated by @constructive-io/graphql-codegen - DO NOT EDIT'); - lines.push(''); + lines.push(...getReadmeHeader('Generated GraphQL SDK')); lines.push('## Overview'); lines.push(''); @@ -110,6 +108,8 @@ export function generateTargetReadme( lines.push(''); } + lines.push(...getReadmeFooter()); + return { fileName: 'README.md', content: lines.join('\n'), @@ -145,10 +145,7 @@ export function generateRootRootReadme( ): GeneratedDocFile { const lines: string[] = []; - lines.push('# GraphQL SDK'); - lines.push(''); - lines.push('> @generated by @constructive-io/graphql-codegen - DO NOT EDIT'); - lines.push(''); + lines.push(...getReadmeHeader('GraphQL SDK')); lines.push('## APIs'); lines.push(''); @@ -163,6 +160,8 @@ export function generateRootRootReadme( } lines.push(''); + lines.push(...getReadmeFooter()); + return { fileName: 'README.md', content: lines.join('\n'), diff --git a/graphql/codegen/src/core/database/index.ts b/graphql/codegen/src/core/database/index.ts index bc801c3f7..b078602f8 100644 --- a/graphql/codegen/src/core/database/index.ts +++ b/graphql/codegen/src/core/database/index.ts @@ -7,7 +7,7 @@ import * as fs from 'node:fs'; import * as path from 'node:path'; -import { buildSchemaSDL } from '@constructive-io/graphql-server'; +import { buildSchemaSDL } from 'graphile-schema'; export interface BuildSchemaFromDatabaseOptions { /** Database name */ diff --git a/graphql/codegen/src/core/generate.ts b/graphql/codegen/src/core/generate.ts index 06d42c932..034eb1ee2 100644 --- a/graphql/codegen/src/core/generate.ts +++ b/graphql/codegen/src/core/generate.ts @@ -9,6 +9,7 @@ import path from 'node:path'; import { buildClientSchema, printSchema } from 'graphql'; +import { PgpmPackage } from '@pgpmjs/core'; import { createEphemeralDb, type EphemeralDbResult } from 'pgsql-client'; import { deployPgpm } from 'pgsql-seed'; @@ -514,7 +515,6 @@ function getModulePathFromPgpm( ): string { if (pgpm.modulePath) return pgpm.modulePath; if (pgpm.workspacePath && pgpm.moduleName) { - const { PgpmPackage } = require('@pgpmjs/core') as typeof import('@pgpmjs/core'); const workspace = new PgpmPackage(pgpm.workspacePath); const moduleProject = workspace.getModuleProject(pgpm.moduleName); const modulePath = moduleProject.getModulePath(); diff --git a/graphql/codegen/src/core/introspect/source/database.ts b/graphql/codegen/src/core/introspect/source/database.ts index de444a049..851354483 100644 --- a/graphql/codegen/src/core/introspect/source/database.ts +++ b/graphql/codegen/src/core/introspect/source/database.ts @@ -6,7 +6,7 @@ */ import { buildSchema, introspectionFromSchema } from 'graphql'; -import { buildSchemaSDL } from '@constructive-io/graphql-server'; +import { buildSchemaSDL } from 'graphile-schema'; import type { IntrospectionQueryResponse } from '../../../types/introspection'; import { diff --git a/graphql/codegen/src/core/introspect/source/pgpm-module.ts b/graphql/codegen/src/core/introspect/source/pgpm-module.ts index 1e827572b..e268872a0 100644 --- a/graphql/codegen/src/core/introspect/source/pgpm-module.ts +++ b/graphql/codegen/src/core/introspect/source/pgpm-module.ts @@ -13,7 +13,7 @@ import { getPgPool } from 'pg-cache'; import { createEphemeralDb, type EphemeralDbResult } from 'pgsql-client'; import { deployPgpm } from 'pgsql-seed'; -import { buildSchemaSDL } from '@constructive-io/graphql-server'; +import { buildSchemaSDL } from 'graphile-schema'; import type { IntrospectionQueryResponse } from '../../../types/introspection'; import { resolveApiSchemas, validateServicesSchemas } from './api-schemas'; diff --git a/graphql/server/package.json b/graphql/server/package.json index c799f61a3..7b364047f 100644 --- a/graphql/server/package.json +++ b/graphql/server/package.json @@ -62,6 +62,7 @@ "graphile-build-pg": "^5.0.0-rc.3", "graphile-cache": "workspace:^", "graphile-config": "1.0.0-rc.3", + "graphile-schema": "workspace:^", "graphile-settings": "workspace:^", "graphql": "^16.9.0", "graphql-upload": "^13.0.0", diff --git a/graphql/server/src/schema.ts b/graphql/server/src/schema.ts index 29daf8305..a4dde745a 100644 --- a/graphql/server/src/schema.ts +++ b/graphql/server/src/schema.ts @@ -1,117 +1,3 @@ -import { printSchema, getIntrospectionQuery, buildClientSchema } from 'graphql' -import { ConstructivePreset, makePgService } from 'graphile-settings' -import { makeSchema } from 'graphile-build' -import { getPgPool } from 'pg-cache' -import type { GraphileConfig } from 'graphile-config' -import * as http from 'node:http' -import * as https from 'node:https' - -export type BuildSchemaOptions = { - database?: string; - schemas: string[]; - graphile?: Partial; -}; - -// Build GraphQL Schema SDL directly from Postgres using PostGraphile v5, without HTTP. -export async function buildSchemaSDL(opts: BuildSchemaOptions): Promise { - const database = opts.database ?? 'constructive' - const schemas = Array.isArray(opts.schemas) ? opts.schemas : [] - - // Get pool config for connection string - const pool = getPgPool({ database }) - const poolConfig = (pool as any).options || {} - const connectionString = `postgres://${poolConfig.user || 'postgres'}:${poolConfig.password || ''}@${poolConfig.host || 'localhost'}:${poolConfig.port || 5432}/${database}` - - // Build v5 preset - const preset: GraphileConfig.Preset = { - extends: [ - ConstructivePreset, - ...(opts.graphile?.extends ?? []), - ], - ...(opts.graphile?.disablePlugins && { disablePlugins: opts.graphile.disablePlugins }), - ...(opts.graphile?.plugins && { plugins: opts.graphile.plugins }), - ...(opts.graphile?.schema && { schema: opts.graphile.schema }), - pgServices: [ - makePgService({ - connectionString, - schemas, - }), - ], - } - - const { schema } = await makeSchema(preset) - return printSchema(schema) -} - -// Fetch GraphQL Schema SDL from a running GraphQL endpoint via introspection. -// This centralizes GraphQL client usage in the server package to avoid duplicating deps in the CLI. -export async function fetchEndpointSchemaSDL(endpoint: string, opts?: { headerHost?: string, headers?: Record, auth?: string }): Promise { - const url = new URL(endpoint) - const requestUrl = url - - const introspectionQuery = getIntrospectionQuery({ descriptions: true }) - const postData = JSON.stringify({ - query: introspectionQuery, - variables: null, - operationName: 'IntrospectionQuery', - }) - - const headers: Record = { - 'Content-Type': 'application/json', - 'Content-Length': String(Buffer.byteLength(postData)), - } - if (opts?.headerHost) { - headers['Host'] = opts.headerHost - } - if (opts?.auth) { - headers['Authorization'] = opts.auth - } - if (opts?.headers) { - for (const [key, value] of Object.entries(opts.headers)) { - headers[key] = value - } - } - - const isHttps = requestUrl.protocol === 'https:' - const lib = isHttps ? https : http - - const responseData: string = await new Promise((resolve, reject) => { - const req = lib.request({ - hostname: requestUrl.hostname, - port: (requestUrl.port ? Number(requestUrl.port) : (isHttps ? 443 : 80)), - path: requestUrl.pathname, - method: 'POST', - headers, - }, (res) => { - let data = '' - res.on('data', (chunk) => { data += chunk }) - res.on('end', () => { - if (res.statusCode && res.statusCode >= 400) { - reject(new Error(`HTTP ${res.statusCode} – ${data}`)) - return - } - resolve(data) - }) - }) - req.on('error', (err) => reject(err)) - req.write(postData) - req.end() - }) - - let json: any - try { - json = JSON.parse(responseData) - } catch (e) { - throw new Error(`Failed to parse response: ${responseData}`) - } - - if (json.errors) { - throw new Error('Introspection returned errors') - } - if (!json.data) { - throw new Error('No data in introspection response') - } - - const schema = buildClientSchema(json.data as any) - return printSchema(schema) -} +export { buildSchemaSDL, fetchEndpointSchemaSDL } from 'graphile-schema' +export type { BuildSchemaOptions } from 'graphile-schema' +export type { FetchEndpointSchemaOptions } from 'graphile-schema' diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ce9912cb8..8fb1ef619 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -215,7 +215,7 @@ importers: version: 3.1.11 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) + version: 10.9.2(@types/node@22.19.11)(typescript@5.9.3) publishDirectory: dist graphile/graphile-query: @@ -256,6 +256,38 @@ importers: version: link:../../postgres/pgsql-test/dist publishDirectory: dist + graphile/graphile-schema: + dependencies: + deepmerge: + specifier: ^4.3.1 + version: 4.3.1 + graphile-build: + specifier: ^5.0.0-rc.3 + version: 5.0.0-rc.4(grafast@1.0.0-rc.4(graphql@16.12.0))(graphile-config@1.0.0-rc.3)(graphql@16.12.0) + graphile-config: + specifier: 1.0.0-rc.3 + version: 1.0.0-rc.3 + graphile-settings: + specifier: workspace:^ + version: link:../graphile-settings/dist + graphql: + specifier: ^16.9.0 + version: 16.12.0 + pg-cache: + specifier: workspace:^ + version: link:../../postgres/pg-cache/dist + pg-env: + specifier: workspace:^ + version: link:../../postgres/pg-env/dist + devDependencies: + makage: + specifier: ^0.1.10 + version: 0.1.12 + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@22.19.11)(typescript@5.9.3) + publishDirectory: dist + graphile/graphile-search-plugin: dependencies: '@dataplan/pg': @@ -377,7 +409,7 @@ importers: version: 3.1.11 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) + version: 10.9.2(@types/node@22.19.11)(typescript@5.9.3) publishDirectory: dist graphile/graphile-test: @@ -488,9 +520,6 @@ importers: '@babel/types': specifier: ^7.28.6 version: 7.28.6 - '@constructive-io/graphql-server': - specifier: workspace:^ - version: link:../server/dist '@constructive-io/graphql-types': specifier: workspace:^ version: link:../types/dist @@ -512,6 +541,9 @@ importers: gql-ast: specifier: workspace:^ version: link:../gql-ast/dist + graphile-schema: + specifier: workspace:^ + version: link:../../graphile/graphile-schema/dist graphql: specifier: ^16.9.0 version: 16.12.0 @@ -648,7 +680,7 @@ importers: version: 3.1.11 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) + version: 10.9.2(@types/node@22.19.11)(typescript@5.9.3) publishDirectory: dist graphql/gql-ast: @@ -844,6 +876,9 @@ importers: graphile-config: specifier: 1.0.0-rc.3 version: 1.0.0-rc.3 + graphile-schema: + specifier: workspace:^ + version: link:../../graphile/graphile-schema/dist graphile-settings: specifier: workspace:^ version: link:../../graphile/graphile-settings/dist @@ -913,7 +948,7 @@ importers: version: 6.1.2 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) + version: 10.9.2(@types/node@22.19.11)(typescript@5.9.3) publishDirectory: dist graphql/server-test: @@ -1302,7 +1337,7 @@ importers: version: 7.2.2 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) + version: 10.9.2(@types/node@22.19.11)(typescript@5.9.3) publishDirectory: dist jobs/knative-job-worker: @@ -1589,7 +1624,7 @@ importers: version: 0.1.12 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) + version: 10.9.2(@types/node@22.19.11)(typescript@5.9.3) publishDirectory: dist packages/smtppostmaster: @@ -1618,7 +1653,7 @@ importers: version: 3.18.0 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) + version: 10.9.2(@types/node@22.19.11)(typescript@5.9.3) publishDirectory: dist packages/url-domains: @@ -11195,7 +11230,7 @@ snapshots: '@graphiql/plugin-doc-explorer@0.4.1(@graphiql/react@0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)))(@types/react@19.2.13)(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3))': dependencies: - '@graphiql/react': 0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@20.19.27)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) + '@graphiql/react': 0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) '@headlessui/react': 2.2.9(react-dom@19.2.3(react@19.2.3))(react@19.2.3) graphql: 16.12.0 react: 19.2.3 @@ -11209,7 +11244,7 @@ snapshots: '@graphiql/plugin-explorer@5.1.1(@graphiql/react@0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)))(graphql@16.12.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: - '@graphiql/react': 0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@20.19.27)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) + '@graphiql/react': 0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) graphiql-explorer: 0.9.0(graphql@16.12.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) graphql: 16.12.0 react: 19.2.3 @@ -11217,8 +11252,8 @@ snapshots: '@graphiql/plugin-history@0.4.1(@graphiql/react@0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)))(@types/node@22.19.11)(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3))': dependencies: - '@graphiql/react': 0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@20.19.27)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) - '@graphiql/toolkit': 0.11.3(@types/node@20.19.27)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0) + '@graphiql/react': 0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) + '@graphiql/toolkit': 0.11.3(@types/node@22.19.11)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0) react: 19.2.3 react-compiler-runtime: 19.1.0-rc.1(react@19.2.3) react-dom: 19.2.3(react@19.2.3) @@ -11231,9 +11266,9 @@ snapshots: - immer - use-sync-external-store - '@graphiql/react@0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@20.19.27)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3))': + '@graphiql/react@0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3))': dependencies: - '@graphiql/toolkit': 0.11.3(@types/node@20.19.27)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0) + '@graphiql/toolkit': 0.11.3(@types/node@22.19.11)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0) '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@radix-ui/react-dropdown-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@radix-ui/react-tooltip': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -11262,11 +11297,11 @@ snapshots: - immer - use-sync-external-store - '@graphiql/toolkit@0.11.3(@types/node@20.19.27)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)': + '@graphiql/toolkit@0.11.3(@types/node@22.19.11)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)': dependencies: '@n1ru4l/push-pull-async-iterable-iterator': 3.2.0 graphql: 16.12.0 - meros: 1.3.2(@types/node@20.19.27) + meros: 1.3.2(@types/node@22.19.11) optionalDependencies: graphql-ws: 6.0.7(graphql@16.12.0)(ws@8.19.0) transitivePeerDependencies: @@ -15522,7 +15557,7 @@ snapshots: dependencies: '@graphiql/plugin-doc-explorer': 0.4.1(@graphiql/react@0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)))(@types/react@19.2.13)(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) '@graphiql/plugin-history': 0.4.1(@graphiql/react@0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)))(@types/node@22.19.11)(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) - '@graphiql/react': 0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@20.19.27)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) + '@graphiql/react': 0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) graphql: 16.12.0 react: 19.2.3 react-compiler-runtime: 19.1.0-rc.1(react@19.2.3) @@ -16722,9 +16757,9 @@ snapshots: ts-dedent: 2.2.0 uuid: 11.1.0 - meros@1.3.2(@types/node@20.19.27): + meros@1.3.2(@types/node@22.19.11): optionalDependencies: - '@types/node': 20.19.27 + '@types/node': 22.19.11 methods@1.1.2: {} @@ -18146,8 +18181,8 @@ snapshots: '@graphiql/plugin-doc-explorer': 0.4.1(@graphiql/react@0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)))(@types/react@19.2.13)(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) '@graphiql/plugin-explorer': 5.1.1(@graphiql/react@0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)))(graphql@16.12.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@graphiql/plugin-history': 0.4.1(@graphiql/react@0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)))(@types/node@22.19.11)(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) - '@graphiql/react': 0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@20.19.27)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) - '@graphiql/toolkit': 0.11.3(@types/node@20.19.27)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0) + '@graphiql/react': 0.37.3(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-compiler-runtime@19.1.0-rc.1(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) + '@graphiql/toolkit': 0.11.3(@types/node@22.19.11)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0) '@types/node': 22.19.11 grafast: 1.0.0-rc.4(graphql@16.12.0) graphiql: 5.2.2(@emotion/is-prop-valid@1.4.0)(@types/node@22.19.11)(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(graphql-ws@6.0.7(graphql@16.12.0)(ws@8.19.0))(graphql@16.12.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) @@ -18660,6 +18695,24 @@ snapshots: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 + ts-node@10.9.2(@types/node@22.19.11)(typescript@5.9.3): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.12 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 22.19.11 + acorn: 8.15.0 + acorn-walk: 8.3.4 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.9.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + tsconfig-paths@4.2.0: dependencies: json5: 2.2.3 From bb1d268d01b243f01c37dc27c3c7515bf5f94a33 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Thu, 19 Feb 2026 00:12:27 +0000 Subject: [PATCH 20/23] docs: update stale references to get-graphql-schema, add graphile-schema tests - Remove codegen:schema script from server package.json (script file was deleted) - Update CLI README to document --schema-only instead of get-graphql-schema - Update CLI help text (display.ts) to remove get-graphql-schema reference - Update CLI AGENTS.md to reflect current command structure - Add 5 unit tests for fetchEndpointSchemaSDL in graphile-schema package (live HTTP server mock, error handling, custom headers/auth) --- .../__tests__/fetch-endpoint-schema.test.ts | 109 ++++++++++++++++++ graphql/server/package.json | 3 +- packages/cli/AGENTS.md | 12 +- packages/cli/README.md | 28 +++-- packages/cli/src/utils/display.ts | 3 +- 5 files changed, 134 insertions(+), 21 deletions(-) create mode 100644 graphile/graphile-schema/__tests__/fetch-endpoint-schema.test.ts diff --git a/graphile/graphile-schema/__tests__/fetch-endpoint-schema.test.ts b/graphile/graphile-schema/__tests__/fetch-endpoint-schema.test.ts new file mode 100644 index 000000000..c94afba81 --- /dev/null +++ b/graphile/graphile-schema/__tests__/fetch-endpoint-schema.test.ts @@ -0,0 +1,109 @@ +import * as http from 'node:http'; +import { getIntrospectionQuery, buildSchema, introspectionFromSchema } from 'graphql'; + +import { fetchEndpointSchemaSDL } from '../src/fetch-endpoint-schema'; + +const TEST_SDL = ` + type Query { + hello: String + version: Int + } +`; + +function createMockServer(handler: (req: http.IncomingMessage, res: http.ServerResponse) => void): Promise<{ server: http.Server; port: number }> { + return new Promise((resolve) => { + const server = http.createServer(handler); + server.listen(0, '127.0.0.1', () => { + const addr = server.address() as { port: number }; + resolve({ server, port: addr.port }); + }); + }); +} + +function introspectionHandler(_req: http.IncomingMessage, res: http.ServerResponse) { + const schema = buildSchema(TEST_SDL); + const introspection = introspectionFromSchema(schema); + res.writeHead(200, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ data: introspection })); +} + +describe('fetchEndpointSchemaSDL', () => { + let server: http.Server; + let port: number; + + beforeAll(async () => { + ({ server, port } = await createMockServer(introspectionHandler)); + }); + + afterAll(() => { + server.close(); + }); + + it('fetches and returns SDL from a live endpoint', async () => { + const sdl = await fetchEndpointSchemaSDL(`http://127.0.0.1:${port}/graphql`); + + expect(sdl).toContain('type Query'); + expect(sdl).toContain('hello'); + expect(sdl).toContain('version'); + }); + + it('throws on HTTP error responses', async () => { + const { server: errServer, port: errPort } = await createMockServer((_req, res) => { + res.writeHead(500); + res.end('Internal Server Error'); + }); + + await expect( + fetchEndpointSchemaSDL(`http://127.0.0.1:${errPort}/graphql`), + ).rejects.toThrow('HTTP 500'); + + errServer.close(); + }); + + it('throws on invalid JSON response', async () => { + const { server: badServer, port: badPort } = await createMockServer((_req, res) => { + res.writeHead(200, { 'Content-Type': 'text/html' }); + res.end('not json'); + }); + + await expect( + fetchEndpointSchemaSDL(`http://127.0.0.1:${badPort}/graphql`), + ).rejects.toThrow('Failed to parse response'); + + badServer.close(); + }); + + it('throws when introspection returns errors', async () => { + const { server: errServer, port: errPort } = await createMockServer((_req, res) => { + res.writeHead(200, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ errors: [{ message: 'Not allowed' }] })); + }); + + await expect( + fetchEndpointSchemaSDL(`http://127.0.0.1:${errPort}/graphql`), + ).rejects.toThrow('Introspection returned errors'); + + errServer.close(); + }); + + it('passes custom headers to the endpoint', async () => { + let receivedHeaders: http.IncomingHttpHeaders = {}; + + const { server: headerServer, port: headerPort } = await createMockServer((req, res) => { + receivedHeaders = req.headers; + introspectionHandler(req, res); + }); + + await fetchEndpointSchemaSDL(`http://127.0.0.1:${headerPort}/graphql`, { + auth: 'Bearer test-token', + headerHost: 'custom.host.io', + headers: { 'X-Custom': 'value123' }, + }); + + expect(receivedHeaders['authorization']).toBe('Bearer test-token'); + expect(receivedHeaders['host']).toBe('custom.host.io'); + expect(receivedHeaders['x-custom']).toBe('value123'); + + headerServer.close(); + }); +}); diff --git a/graphql/server/package.json b/graphql/server/package.json index 7b364047f..6ef2129ba 100644 --- a/graphql/server/package.json +++ b/graphql/server/package.json @@ -30,9 +30,8 @@ "test": "jest --passWithNoTests", "test:watch": "jest --watch", "bucket:create": "ts-node src/scripts/create-bucket.ts", - "codegen:schema": "ts-node src/scripts/codegen-schema.ts", "codegen:clean": "rimraf src/codegen/orm codegen/schema.graphql", - "codegen": "npm run codegen:clean && npm run codegen:schema && graphql-codegen generate-orm --schema codegen/schema.graphql --output src/codegen/orm" + "codegen": "npm run codegen:clean && graphql-codegen --schema-only --output codegen && graphql-codegen generate-orm --schema codegen/schema.graphql --output src/codegen/orm" }, "keywords": [ "server", diff --git a/packages/cli/AGENTS.md b/packages/cli/AGENTS.md index e22e6c7ea..23d63e7b8 100644 --- a/packages/cli/AGENTS.md +++ b/packages/cli/AGENTS.md @@ -3,7 +3,7 @@ The `@constructive-io/cli` package provides the user-facing CLI for the Constructive ecosystem. - **Binaries:** `constructive` (full) and `cnc` (shorthand) -- **What it covers:** Constructive GraphQL workflows only (server, explorer, schema tools, codegen) +- **What it covers:** Constructive GraphQL workflows only (server, explorer, codegen) **Note:** Database operations (init, add, deploy, revert, etc.) are handled by the separate `pgpm` CLI. Users should install both tools for the complete workflow. @@ -15,19 +15,19 @@ The `@constructive-io/cli` package provides the user-facing CLI for the Construc ## Commands -The CLI provides 4 GraphQL-focused commands: +The CLI provides GraphQL-focused commands: - `packages/cli/src/commands/server.ts` – start the Constructive GraphQL server - `packages/cli/src/commands/explorer.ts` – start the Constructive GraphQL explorer -- `packages/cli/src/commands/get-graphql-schema.ts` – emit schema SDL (DB build or endpoint introspection) -- `packages/cli/src/commands/codegen.ts` – run GraphQL codegen (`@constructive-io/graphql-codegen`) +- `packages/cli/src/commands/codegen.ts` – run GraphQL codegen (`@constructive-io/graphql-codegen`), including `--schema-only` for SDL export ## Debugging Tips - **Command routing:** `packages/cli/src/commands.ts` -- **Schema generation:** `packages/cli/src/commands/get-graphql-schema.ts` delegates schema building to `@constructive-io/graphql-server` +- **Codegen handler:** `packages/cli/src/commands/codegen.ts` delegates to `runCodegenHandler()` from `@constructive-io/graphql-codegen` +- **Schema building:** `graphile-schema` package provides `buildSchemaSDL` (from database) and `fetchEndpointSchemaSDL` (from endpoint) ## Tests -- `packages/cli/__tests__/*` covers the GraphQL commands (codegen, get-graphql-schema, cli) +- `packages/cli/__tests__/*` covers the GraphQL commands (codegen, cli) - Database/PGPM tests are located in `pgpm/cli/__tests__/` diff --git a/packages/cli/README.md b/packages/cli/README.md index 0e5e5e021..fb33e1ee0 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -95,27 +95,33 @@ cnc codegen --api-names my_api --output ./codegen --orm - `--dry-run` - Preview without writing files - `--verbose` - Verbose output -### `cnc get-graphql-schema` +### `cnc codegen --schema-only` -Fetch or build GraphQL schema SDL. +Export GraphQL schema SDL without running full code generation. Works with any source (endpoint, file, database, PGPM). ```bash # From database schemas -cnc get-graphql-schema --database mydb --schemas myapp,public --out ./schema.graphql +cnc codegen --schema-only --schemas myapp,public --output ./schemas # From running server -cnc get-graphql-schema --endpoint http://localhost:3000/graphql --out ./schema.graphql +cnc codegen --schema-only --endpoint http://localhost:3000/graphql --output ./schemas + +# From schema file (useful for converting/validating) +cnc codegen --schema-only --schema-file ./input.graphql --output ./schemas + +# From a directory of .graphql files (multi-target) +cnc codegen --schema-only --schema-dir ./schemas --output ./exported ``` **Options:** -- `--database ` - Database name (for programmatic builder) -- `--schemas ` - Comma-separated schemas to include (required unless using --endpoint) -- `--endpoint ` - GraphQL endpoint to fetch schema via introspection -- `--headerHost ` - Optional Host header for endpoint requests -- `--auth ` - Optional Authorization header value -- `--header "Name: Value"` - Optional HTTP header (repeatable) -- `--out ` - Output file path (prints to stdout if omitted) +- `--endpoint ` - GraphQL endpoint URL +- `--schema-file ` - Path to GraphQL schema file +- `--schemas ` - Comma-separated PostgreSQL schemas +- `--api-names ` - Comma-separated API names (multi-target when >1) +- `--schema-dir ` - Directory of .graphql files (auto-creates one target per file) +- `--output ` - Output directory (default: ./generated/graphql) +- `--authorization ` - Authorization header value ## Configuration diff --git a/packages/cli/src/utils/display.ts b/packages/cli/src/utils/display.ts index ed2571278..e84b4f988 100644 --- a/packages/cli/src/utils/display.ts +++ b/packages/cli/src/utils/display.ts @@ -10,7 +10,6 @@ export const usageText = ` Code Generation: codegen Generate TypeScript types and SDK from GraphQL schema - get-graphql-schema Fetch or build GraphQL schema SDL Jobs: jobs up Start combined server (jobs runtime) @@ -34,7 +33,7 @@ export const usageText = ` cnc server --port 8080 Start server on custom port cnc explorer Launch GraphiQL explorer cnc codegen --schema schema.graphql Generate types from schema - cnc get-graphql-schema --out schema.graphql Export schema SDL + cnc codegen --schema-only --out schema.graphql Export schema SDL cnc jobs up Start combined server (jobs runtime) # Execution Engine From c519f05a79f4293c68ba981dfa8cc4ae925169b4 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Thu, 19 Feb 2026 00:25:25 +0000 Subject: [PATCH 21/23] chore(server): remove dead codegen scripts, tsconfig excludes, rimraf dep - Remove codegen and codegen:clean scripts (no codegen dir/imports exist) - Remove src/codegen/**/* from tsconfig excludes (dir doesn't exist) - Remove Codegen section from README (server is runtime-only now) - Remove rimraf devDependency (only used by deleted codegen:clean) --- graphql/server/README.md | 4 ---- graphql/server/package.json | 5 +---- graphql/server/tsconfig.esm.json | 1 - graphql/server/tsconfig.json | 1 - pnpm-lock.yaml | 13 ------------- 5 files changed, 1 insertion(+), 23 deletions(-) diff --git a/graphql/server/README.md b/graphql/server/README.md index 3d07f2768..5a39463e5 100644 --- a/graphql/server/README.md +++ b/graphql/server/README.md @@ -118,10 +118,6 @@ Configuration is merged from defaults, config files, and env vars via `@construc Use `supertest` or your HTTP client of choice against `/graphql`. For RLS-aware tests, provide a `Bearer` token and ensure the API's auth function is available. -## Codegen - -For local codegen test, use `PORT=5555 API_ENABLE_META=true PGDATABASE=launchql pnpm dev` - ## Related Packages - `@constructive-io/graphql-env` - env parsing + defaults for GraphQL diff --git a/graphql/server/package.json b/graphql/server/package.json index 6ef2129ba..be28ec9ab 100644 --- a/graphql/server/package.json +++ b/graphql/server/package.json @@ -29,9 +29,7 @@ "lint": "eslint . --fix", "test": "jest --passWithNoTests", "test:watch": "jest --watch", - "bucket:create": "ts-node src/scripts/create-bucket.ts", - "codegen:clean": "rimraf src/codegen/orm codegen/schema.graphql", - "codegen": "npm run codegen:clean && graphql-codegen --schema-only --output codegen && graphql-codegen generate-orm --schema codegen/schema.graphql --output src/codegen/orm" + "bucket:create": "ts-node src/scripts/create-bucket.ts" }, "keywords": [ "server", @@ -85,7 +83,6 @@ "graphile-test": "workspace:*", "makage": "^0.1.10", "nodemon": "^3.1.10", - "rimraf": "^6.1.2", "ts-node": "^10.9.2" } } diff --git a/graphql/server/tsconfig.esm.json b/graphql/server/tsconfig.esm.json index b312f70fb..cda15ca65 100644 --- a/graphql/server/tsconfig.esm.json +++ b/graphql/server/tsconfig.esm.json @@ -12,7 +12,6 @@ "node_modules", "**/*.spec.*", "**/*.test.*", - "src/codegen/**/*", "src/plugins/**/*", "src/schema.ts", "src/scripts/**/*", diff --git a/graphql/server/tsconfig.json b/graphql/server/tsconfig.json index 52e1ca50f..e4cac2f6f 100644 --- a/graphql/server/tsconfig.json +++ b/graphql/server/tsconfig.json @@ -12,7 +12,6 @@ "node_modules", "**/*.spec.*", "**/*.test.*", - "src/codegen/**/*", "src/plugins/**/*", "src/schema.ts", "src/scripts/**/*", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8fb1ef619..6ea2b4231 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -943,9 +943,6 @@ importers: nodemon: specifier: ^3.1.10 version: 3.1.11 - rimraf: - specifier: ^6.1.2 - version: 6.1.2 ts-node: specifier: ^10.9.2 version: 10.9.2(@types/node@22.19.11)(typescript@5.9.3) @@ -8903,11 +8900,6 @@ packages: engines: {node: '>=14'} hasBin: true - rimraf@6.1.2: - resolution: {integrity: sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==} - engines: {node: 20 || >=22} - hasBin: true - robust-predicates@3.0.2: resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} @@ -18106,11 +18098,6 @@ snapshots: dependencies: glob: 9.3.5 - rimraf@6.1.2: - dependencies: - glob: 13.0.0 - package-json-from-dist: 1.0.1 - robust-predicates@3.0.2: {} rollup-plugin-visualizer@6.0.5(rollup@4.57.1): From 761c2747fad41b727f92c5cb101d1a276d6cff29 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Thu, 19 Feb 2026 00:33:40 +0000 Subject: [PATCH 22/23] refactor(server): remove backward-compat schema.ts re-export - Delete src/schema.ts (was just re-exporting from graphile-schema) - Remove export * from './schema' in index.ts - Remove graphile-schema dep from server (no longer needed) - Update server-test to import buildSchemaSDL from graphile-schema directly - Remove src/schema.ts from tsconfig excludes --- .../__tests__/schema-snapshot.test.ts | 2 +- graphql/server-test/package.json | 1 + graphql/server/package.json | 1 - graphql/server/src/index.ts | 1 - graphql/server/src/schema.ts | 3 --- graphql/server/tsconfig.esm.json | 1 - graphql/server/tsconfig.json | 1 - pnpm-lock.yaml | 20 +++++++++---------- 8 files changed, 12 insertions(+), 18 deletions(-) delete mode 100644 graphql/server/src/schema.ts diff --git a/graphql/server-test/__tests__/schema-snapshot.test.ts b/graphql/server-test/__tests__/schema-snapshot.test.ts index 54dd9fb26..a2b9b2c22 100644 --- a/graphql/server-test/__tests__/schema-snapshot.test.ts +++ b/graphql/server-test/__tests__/schema-snapshot.test.ts @@ -23,7 +23,7 @@ */ import path from 'path'; -import { buildSchemaSDL } from '@constructive-io/graphql-server'; +import { buildSchemaSDL } from 'graphile-schema'; import { getConnections, seed } from '../src'; jest.setTimeout(60000); diff --git a/graphql/server-test/package.json b/graphql/server-test/package.json index 4e268df1b..8ac2c6074 100644 --- a/graphql/server-test/package.json +++ b/graphql/server-test/package.json @@ -40,6 +40,7 @@ "@constructive-io/graphql-types": "workspace:^", "@pgpmjs/types": "workspace:^", "express": "^5.2.1", + "graphile-schema": "workspace:^", "graphql": "15.10.1", "pg": "^8.17.1", "pg-cache": "workspace:^", diff --git a/graphql/server/package.json b/graphql/server/package.json index be28ec9ab..6b2aedd38 100644 --- a/graphql/server/package.json +++ b/graphql/server/package.json @@ -59,7 +59,6 @@ "graphile-build-pg": "^5.0.0-rc.3", "graphile-cache": "workspace:^", "graphile-config": "1.0.0-rc.3", - "graphile-schema": "workspace:^", "graphile-settings": "workspace:^", "graphql": "^16.9.0", "graphql-upload": "^13.0.0", diff --git a/graphql/server/src/index.ts b/graphql/server/src/index.ts index 36b1118d4..803e7fe13 100644 --- a/graphql/server/src/index.ts +++ b/graphql/server/src/index.ts @@ -1,5 +1,4 @@ export * from './server'; -export * from './schema'; // Export options module - types, defaults, type guards, and utility functions export * from './options'; diff --git a/graphql/server/src/schema.ts b/graphql/server/src/schema.ts deleted file mode 100644 index a4dde745a..000000000 --- a/graphql/server/src/schema.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { buildSchemaSDL, fetchEndpointSchemaSDL } from 'graphile-schema' -export type { BuildSchemaOptions } from 'graphile-schema' -export type { FetchEndpointSchemaOptions } from 'graphile-schema' diff --git a/graphql/server/tsconfig.esm.json b/graphql/server/tsconfig.esm.json index cda15ca65..aef23b967 100644 --- a/graphql/server/tsconfig.esm.json +++ b/graphql/server/tsconfig.esm.json @@ -13,7 +13,6 @@ "**/*.spec.*", "**/*.test.*", "src/plugins/**/*", - "src/schema.ts", "src/scripts/**/*", "src/middleware/gql.ts" ] diff --git a/graphql/server/tsconfig.json b/graphql/server/tsconfig.json index e4cac2f6f..8bc5b231b 100644 --- a/graphql/server/tsconfig.json +++ b/graphql/server/tsconfig.json @@ -13,7 +13,6 @@ "**/*.spec.*", "**/*.test.*", "src/plugins/**/*", - "src/schema.ts", "src/scripts/**/*", "src/middleware/gql.ts" ] diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6ea2b4231..58af7d00e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -215,7 +215,7 @@ importers: version: 3.1.11 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@22.19.11)(typescript@5.9.3) + version: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) publishDirectory: dist graphile/graphile-query: @@ -285,7 +285,7 @@ importers: version: 0.1.12 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@22.19.11)(typescript@5.9.3) + version: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) publishDirectory: dist graphile/graphile-search-plugin: @@ -409,7 +409,7 @@ importers: version: 3.1.11 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@22.19.11)(typescript@5.9.3) + version: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) publishDirectory: dist graphile/graphile-test: @@ -680,7 +680,7 @@ importers: version: 3.1.11 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@22.19.11)(typescript@5.9.3) + version: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) publishDirectory: dist graphql/gql-ast: @@ -876,9 +876,6 @@ importers: graphile-config: specifier: 1.0.0-rc.3 version: 1.0.0-rc.3 - graphile-schema: - specifier: workspace:^ - version: link:../../graphile/graphile-schema/dist graphile-settings: specifier: workspace:^ version: link:../../graphile/graphile-settings/dist @@ -965,6 +962,9 @@ importers: express: specifier: ^5.2.1 version: 5.2.1 + graphile-schema: + specifier: workspace:^ + version: link:../../graphile/graphile-schema/dist graphql: specifier: 15.10.1 version: 15.10.1 @@ -1334,7 +1334,7 @@ importers: version: 7.2.2 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@22.19.11)(typescript@5.9.3) + version: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) publishDirectory: dist jobs/knative-job-worker: @@ -1621,7 +1621,7 @@ importers: version: 0.1.12 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@22.19.11)(typescript@5.9.3) + version: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) publishDirectory: dist packages/smtppostmaster: @@ -1650,7 +1650,7 @@ importers: version: 3.18.0 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@22.19.11)(typescript@5.9.3) + version: 10.9.2(@types/node@20.19.27)(typescript@5.9.3) publishDirectory: dist packages/url-domains: From c61e9171244469223847bcae67229f9f48935bad Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Thu, 19 Feb 2026 01:16:08 +0000 Subject: [PATCH 23/23] chore: remove --passWithNoTests from 41 packages that have tests Only packages with zero test files retain --passWithNoTests. --- graphile/graphile-authz/package.json | 2 +- graphile/graphile-query/package.json | 2 +- graphile/graphile-schema/package.json | 2 +- graphile/graphile-search-plugin/package.json | 2 +- graphile/graphile-settings/package.json | 2 +- graphile/graphile-test/package.json | 2 +- graphile/postgraphile-plugin-pgvector/package.json | 2 +- graphql/codegen/package.json | 2 +- graphql/env/package.json | 2 +- graphql/query/package.json | 2 +- graphql/server-test/package.json | 2 +- graphql/test/package.json | 2 +- jobs/knative-job-service/package.json | 2 +- jobs/knative-job-worker/package.json | 2 +- packages/12factor-env/package.json | 2 +- packages/cli/package.json | 2 +- packages/client/package.json | 2 +- packages/csrf/package.json | 2 +- packages/oauth/package.json | 2 +- packages/orm/package.json | 2 +- packages/postmaster/package.json | 2 +- packages/query-builder/package.json | 2 +- packages/smtppostmaster/package.json | 2 +- packages/url-domains/package.json | 2 +- pgpm/cli/package.json | 2 +- pgpm/core/package.json | 2 +- pgpm/env/package.json | 2 +- postgres/drizzle-orm-test/package.json | 2 +- postgres/introspectron/package.json | 2 +- postgres/pg-ast/package.json | 2 +- postgres/pg-codegen/package.json | 2 +- postgres/pgsql-test/package.json | 2 +- uploads/content-type-stream/package.json | 2 +- uploads/etag-hash/package.json | 2 +- uploads/etag-stream/package.json | 2 +- uploads/mime-bytes/package.json | 2 +- uploads/s3-streamer/package.json | 2 +- uploads/stream-to-etag/package.json | 2 +- uploads/upload-names/package.json | 2 +- uploads/uuid-hash/package.json | 2 +- uploads/uuid-stream/package.json | 2 +- 41 files changed, 41 insertions(+), 41 deletions(-) diff --git a/graphile/graphile-authz/package.json b/graphile/graphile-authz/package.json index 7319d4ab0..1e185811a 100644 --- a/graphile/graphile-authz/package.json +++ b/graphile/graphile-authz/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "devDependencies": { diff --git a/graphile/graphile-query/package.json b/graphile/graphile-query/package.json index 2a3c3675a..c03309d52 100644 --- a/graphile/graphile-query/package.json +++ b/graphile/graphile-query/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "dependencies": { diff --git a/graphile/graphile-schema/package.json b/graphile/graphile-schema/package.json index 029e7d136..f9ab9b29c 100644 --- a/graphile/graphile-schema/package.json +++ b/graphile/graphile-schema/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "dependencies": { diff --git a/graphile/graphile-search-plugin/package.json b/graphile/graphile-search-plugin/package.json index f28b2ce92..a1ba1cb13 100644 --- a/graphile/graphile-search-plugin/package.json +++ b/graphile/graphile-search-plugin/package.json @@ -14,7 +14,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "publishConfig": { diff --git a/graphile/graphile-settings/package.json b/graphile/graphile-settings/package.json index eed8207da..44a2f19ec 100644 --- a/graphile/graphile-settings/package.json +++ b/graphile/graphile-settings/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "dependencies": { diff --git a/graphile/graphile-test/package.json b/graphile/graphile-test/package.json index 08a8698f0..498bc554b 100644 --- a/graphile/graphile-test/package.json +++ b/graphile/graphile-test/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "devDependencies": { diff --git a/graphile/postgraphile-plugin-pgvector/package.json b/graphile/postgraphile-plugin-pgvector/package.json index 055ec5465..08fd62c69 100644 --- a/graphile/postgraphile-plugin-pgvector/package.json +++ b/graphile/postgraphile-plugin-pgvector/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "devDependencies": { diff --git a/graphql/codegen/package.json b/graphql/codegen/package.json index 35d425b5f..bc067f506 100644 --- a/graphql/codegen/package.json +++ b/graphql/codegen/package.json @@ -42,7 +42,7 @@ "lint": "eslint . --fix", "fmt": "oxfmt --write .", "fmt:check": "oxfmt --check .", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch", "example:codegen:sdk": "tsx src/cli/index.ts --config examples/multi-target.config.ts --react-query", "example:codegen:orm": "tsx src/cli/index.ts --config examples/multi-target.config.ts --orm", diff --git a/graphql/env/package.json b/graphql/env/package.json index 81a17e859..fed638503 100644 --- a/graphql/env/package.json +++ b/graphql/env/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "dependencies": { diff --git a/graphql/query/package.json b/graphql/query/package.json index 42db4e178..a9e232670 100644 --- a/graphql/query/package.json +++ b/graphql/query/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "dependencies": { diff --git a/graphql/server-test/package.json b/graphql/server-test/package.json index 8ac2c6074..5b2c51924 100644 --- a/graphql/server-test/package.json +++ b/graphql/server-test/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "devDependencies": { diff --git a/graphql/test/package.json b/graphql/test/package.json index 8121e6992..6f410339c 100644 --- a/graphql/test/package.json +++ b/graphql/test/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "devDependencies": { diff --git a/jobs/knative-job-service/package.json b/jobs/knative-job-service/package.json index 9c70f7004..f0eb42b1c 100644 --- a/jobs/knative-job-service/package.json +++ b/jobs/knative-job-service/package.json @@ -30,7 +30,7 @@ "build:dev": "makage build --dev", "start": "node dist/run.js", "dev": "ts-node --transpile-only src/run.ts", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch", "test:debug": "node --inspect node_modules/.bin/jest --runInBand" }, diff --git a/jobs/knative-job-worker/package.json b/jobs/knative-job-worker/package.json index 744a9f14e..af04c28f1 100644 --- a/jobs/knative-job-worker/package.json +++ b/jobs/knative-job-worker/package.json @@ -25,7 +25,7 @@ "url": "https://github.com/constructive-io/jobs" }, "scripts": { - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch", "test:debug": "node --inspect node_modules/.bin/jest --runInBand", "clean": "makage clean", diff --git a/packages/12factor-env/package.json b/packages/12factor-env/package.json index 8a08ddd98..5c47cb79f 100644 --- a/packages/12factor-env/package.json +++ b/packages/12factor-env/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "dependencies": { diff --git a/packages/cli/package.json b/packages/cli/package.json index 79d1b8206..4a694bfc9 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -30,7 +30,7 @@ "build:dev": "makage build --dev", "dev": "ts-node ./src/index.ts", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "devDependencies": { diff --git a/packages/client/package.json b/packages/client/package.json index 16e2628e4..5736d3dbd 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "keywords": [ diff --git a/packages/csrf/package.json b/packages/csrf/package.json index b6fc21623..9c0a976ce 100644 --- a/packages/csrf/package.json +++ b/packages/csrf/package.json @@ -16,7 +16,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "devDependencies": { diff --git a/packages/oauth/package.json b/packages/oauth/package.json index 79853417a..c0b790c2f 100644 --- a/packages/oauth/package.json +++ b/packages/oauth/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "dependencies": { diff --git a/packages/orm/package.json b/packages/orm/package.json index bc67ba1eb..38c228d34 100644 --- a/packages/orm/package.json +++ b/packages/orm/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "dependencies": { diff --git a/packages/postmaster/package.json b/packages/postmaster/package.json index 1439340c1..df18c4e7a 100644 --- a/packages/postmaster/package.json +++ b/packages/postmaster/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "dependencies": { diff --git a/packages/query-builder/package.json b/packages/query-builder/package.json index deb410970..1a01757a9 100644 --- a/packages/query-builder/package.json +++ b/packages/query-builder/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "keywords": [ diff --git a/packages/smtppostmaster/package.json b/packages/smtppostmaster/package.json index 167de79cc..774d36518 100644 --- a/packages/smtppostmaster/package.json +++ b/packages/smtppostmaster/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch", "test:send": "ts-node __tests__/test-send.ts", "test:send:dev": "ts-node __tests__/test-send.ts" diff --git a/packages/url-domains/package.json b/packages/url-domains/package.json index 080d496ac..6b8ebad06 100644 --- a/packages/url-domains/package.json +++ b/packages/url-domains/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "dependencies": { diff --git a/pgpm/cli/package.json b/pgpm/cli/package.json index 15c83edd1..1881560e2 100644 --- a/pgpm/cli/package.json +++ b/pgpm/cli/package.json @@ -29,7 +29,7 @@ "build:dev": "makage build --dev", "dev": "ts-node ./src/index.ts", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "devDependencies": { diff --git a/pgpm/core/package.json b/pgpm/core/package.json index bf29a02c2..34a7a12bd 100644 --- a/pgpm/core/package.json +++ b/pgpm/core/package.json @@ -28,7 +28,7 @@ "build": "makage build && npm run copy", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "keywords": [ diff --git a/pgpm/env/package.json b/pgpm/env/package.json index 185cd67a7..6d1b47f69 100644 --- a/pgpm/env/package.json +++ b/pgpm/env/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "dependencies": { diff --git a/postgres/drizzle-orm-test/package.json b/postgres/drizzle-orm-test/package.json index ce5316a62..4edb0fc2b 100644 --- a/postgres/drizzle-orm-test/package.json +++ b/postgres/drizzle-orm-test/package.json @@ -42,7 +42,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "devDependencies": { diff --git a/postgres/introspectron/package.json b/postgres/introspectron/package.json index f771c47ce..d28bf197f 100644 --- a/postgres/introspectron/package.json +++ b/postgres/introspectron/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "devDependencies": { diff --git a/postgres/pg-ast/package.json b/postgres/pg-ast/package.json index f8c067a1c..6bc08ac66 100644 --- a/postgres/pg-ast/package.json +++ b/postgres/pg-ast/package.json @@ -27,7 +27,7 @@ "build:dev": "makage build --dev", "build:proto": "ts-node scripts/pg-proto-parser", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "keywords": [ diff --git a/postgres/pg-codegen/package.json b/postgres/pg-codegen/package.json index 90f01c6cc..051370ca1 100644 --- a/postgres/pg-codegen/package.json +++ b/postgres/pg-codegen/package.json @@ -27,7 +27,7 @@ "build:dev": "makage build --dev", "dev": "ts-node ./src/index.ts", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "keywords": [ diff --git a/postgres/pgsql-test/package.json b/postgres/pgsql-test/package.json index b98969af7..38858957a 100644 --- a/postgres/pgsql-test/package.json +++ b/postgres/pgsql-test/package.json @@ -51,7 +51,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "devDependencies": { diff --git a/uploads/content-type-stream/package.json b/uploads/content-type-stream/package.json index f0c10cc00..319cf0b3f 100644 --- a/uploads/content-type-stream/package.json +++ b/uploads/content-type-stream/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "dependencies": { diff --git a/uploads/etag-hash/package.json b/uploads/etag-hash/package.json index ce68aebfd..fcef0319a 100644 --- a/uploads/etag-hash/package.json +++ b/uploads/etag-hash/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "keywords": [ diff --git a/uploads/etag-stream/package.json b/uploads/etag-stream/package.json index 85ed499ee..ea84aaa1e 100644 --- a/uploads/etag-stream/package.json +++ b/uploads/etag-stream/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "keywords": [ diff --git a/uploads/mime-bytes/package.json b/uploads/mime-bytes/package.json index d758bb1fa..ef9751d47 100644 --- a/uploads/mime-bytes/package.json +++ b/uploads/mime-bytes/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "keywords": [], diff --git a/uploads/s3-streamer/package.json b/uploads/s3-streamer/package.json index 5140b1a45..77d260bdf 100644 --- a/uploads/s3-streamer/package.json +++ b/uploads/s3-streamer/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "devDependencies": { diff --git a/uploads/stream-to-etag/package.json b/uploads/stream-to-etag/package.json index 9b121592e..b2801d994 100644 --- a/uploads/stream-to-etag/package.json +++ b/uploads/stream-to-etag/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "keywords": [ diff --git a/uploads/upload-names/package.json b/uploads/upload-names/package.json index 37f1be57c..d46a33244 100644 --- a/uploads/upload-names/package.json +++ b/uploads/upload-names/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "keywords": [], diff --git a/uploads/uuid-hash/package.json b/uploads/uuid-hash/package.json index 05b781810..43fa31ba3 100644 --- a/uploads/uuid-hash/package.json +++ b/uploads/uuid-hash/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "keywords": [ diff --git a/uploads/uuid-stream/package.json b/uploads/uuid-stream/package.json index f8d973b29..bd8351799 100644 --- a/uploads/uuid-stream/package.json +++ b/uploads/uuid-stream/package.json @@ -25,7 +25,7 @@ "build": "makage build", "build:dev": "makage build --dev", "lint": "eslint . --fix", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch" }, "keywords": [