From e26424494009d222e289fa7735475e016dbd720d Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 23 Jan 2026 04:48:31 +0000 Subject: [PATCH 01/23] refactor(graphql-codegen): separate concerns by moving business logic to core Move all business logic from cli/ to core/ directory structure: - Move cli/codegen/* to core/codegen/* (code generation) - Move cli/introspect/* to core/introspect/* (schema introspection) - Move cli/watch/* to core/watch/* (watch mode) - Move cli/commands/shared.ts to core/pipeline/ (codegen pipeline) - Create core/config/ with loader.ts and resolver.ts (config utilities) - Create core/output/ with writer.ts (file writing utilities) CLI commands are now thin wrappers that: - Handle user prompts and CLI arguments - Call core functions for business logic - Format and display output This improves separation of concerns and makes the core logic reusable outside of the CLI context. Update all test imports to reference new core/ paths. Update package.json copy:ts script for new file locations. --- graphql/codegen/package.json | 2 +- .../codegen/client-generator.test.ts | 2 +- .../__tests__/codegen/format-output.test.ts | 2 +- .../codegen/input-types-generator.test.ts | 2 +- .../__tests__/codegen/model-generator.test.ts | 2 +- .../codegen/query-keys-factory.test.ts | 6 +- .../codegen/react-query-hooks.test.ts | 12 +- .../codegen/react-query-optional.test.ts | 8 +- .../src/__tests__/codegen/scalars.test.ts | 2 +- .../codegen/schema-types-generator.test.ts | 2 +- .../src/__tests__/codegen/utils.test.ts | 2 +- .../__tests__/introspect/infer-tables.test.ts | 2 +- .../codegen/src/cli/commands/generate-orm.ts | 177 +--------- graphql/codegen/src/cli/commands/generate.ts | 313 +----------------- graphql/codegen/src/cli/commands/init.ts | 112 +------ graphql/codegen/src/cli/index.ts | 114 +------ .../src/{cli => core}/codegen/babel-ast.ts | 0 .../src/{cli => core}/codegen/barrel.ts | 0 .../src/{cli => core}/codegen/client.ts | 0 .../{cli => core}/codegen/custom-mutations.ts | 0 .../{cli => core}/codegen/custom-queries.ts | 0 .../src/{cli => core}/codegen/gql-ast.ts | 0 .../src/{cli => core}/codegen/index.ts | 0 .../src/{cli => core}/codegen/invalidation.ts | 0 .../{cli => core}/codegen/mutation-keys.ts | 0 .../src/{cli => core}/codegen/mutations.ts | 0 .../src/{cli => core}/codegen/orm/barrel.ts | 0 .../codegen/orm/client-generator.ts | 0 .../src/{cli => core}/codegen/orm/client.ts | 0 .../codegen/orm/custom-ops-generator.ts | 0 .../src/{cli => core}/codegen/orm/index.ts | 0 .../codegen/orm/input-types-generator.ts | 0 .../codegen/orm/model-generator.ts | 0 .../codegen/orm/query-builder.ts | 0 .../{cli => core}/codegen/orm/select-types.ts | 0 .../src/{cli => core}/codegen/queries.ts | 0 .../src/{cli => core}/codegen/query-keys.ts | 0 .../src/{cli => core}/codegen/scalars.ts | 0 .../{cli => core}/codegen/schema-gql-ast.ts | 0 .../codegen/schema-types-generator.ts | 0 .../{cli => core}/codegen/type-resolver.ts | 0 .../src/{cli => core}/codegen/types.ts | 0 .../src/{cli => core}/codegen/utils.ts | 0 graphql/codegen/src/core/config/index.ts | 18 + graphql/codegen/src/core/config/loader.ts | 112 +++++++ graphql/codegen/src/core/config/resolver.ts | 303 +++++++++++++++++ graphql/codegen/src/core/index.ts | 23 +- .../{cli => core}/introspect/fetch-schema.ts | 0 .../src/{cli => core}/introspect/index.ts | 0 .../{cli => core}/introspect/infer-tables.ts | 0 .../{cli => core}/introspect/schema-query.ts | 0 .../introspect/source/endpoint.ts | 0 .../{cli => core}/introspect/source/file.ts | 0 .../{cli => core}/introspect/source/index.ts | 0 .../{cli => core}/introspect/source/types.ts | 0 .../introspect/transform-schema.ts | 0 .../src/{cli => core}/introspect/transform.ts | 0 graphql/codegen/src/core/output/index.ts | 11 + graphql/codegen/src/core/output/writer.ts | 163 +++++++++ .../shared.ts => core/pipeline/index.ts} | 4 + .../codegen/src/{cli => core}/watch/cache.ts | 0 .../src/{cli => core}/watch/debounce.ts | 0 .../codegen/src/{cli => core}/watch/hash.ts | 0 .../codegen/src/{cli => core}/watch/index.ts | 0 .../src/{cli => core}/watch/orchestrator.ts | 76 +++-- .../codegen/src/{cli => core}/watch/poller.ts | 0 .../codegen/src/{cli => core}/watch/types.ts | 0 67 files changed, 748 insertions(+), 722 deletions(-) rename graphql/codegen/src/{cli => core}/codegen/babel-ast.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/barrel.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/client.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/custom-mutations.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/custom-queries.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/gql-ast.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/index.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/invalidation.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/mutation-keys.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/mutations.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/orm/barrel.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/orm/client-generator.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/orm/client.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/orm/custom-ops-generator.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/orm/index.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/orm/input-types-generator.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/orm/model-generator.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/orm/query-builder.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/orm/select-types.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/queries.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/query-keys.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/scalars.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/schema-gql-ast.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/schema-types-generator.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/type-resolver.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/types.ts (100%) rename graphql/codegen/src/{cli => core}/codegen/utils.ts (100%) create mode 100644 graphql/codegen/src/core/config/index.ts create mode 100644 graphql/codegen/src/core/config/loader.ts create mode 100644 graphql/codegen/src/core/config/resolver.ts rename graphql/codegen/src/{cli => core}/introspect/fetch-schema.ts (100%) rename graphql/codegen/src/{cli => core}/introspect/index.ts (100%) rename graphql/codegen/src/{cli => core}/introspect/infer-tables.ts (100%) rename graphql/codegen/src/{cli => core}/introspect/schema-query.ts (100%) rename graphql/codegen/src/{cli => core}/introspect/source/endpoint.ts (100%) rename graphql/codegen/src/{cli => core}/introspect/source/file.ts (100%) rename graphql/codegen/src/{cli => core}/introspect/source/index.ts (100%) rename graphql/codegen/src/{cli => core}/introspect/source/types.ts (100%) rename graphql/codegen/src/{cli => core}/introspect/transform-schema.ts (100%) rename graphql/codegen/src/{cli => core}/introspect/transform.ts (100%) create mode 100644 graphql/codegen/src/core/output/index.ts create mode 100644 graphql/codegen/src/core/output/writer.ts rename graphql/codegen/src/{cli/commands/shared.ts => core/pipeline/index.ts} (97%) rename graphql/codegen/src/{cli => core}/watch/cache.ts (100%) rename graphql/codegen/src/{cli => core}/watch/debounce.ts (100%) rename graphql/codegen/src/{cli => core}/watch/hash.ts (100%) rename graphql/codegen/src/{cli => core}/watch/index.ts (100%) rename graphql/codegen/src/{cli => core}/watch/orchestrator.ts (83%) rename graphql/codegen/src/{cli => core}/watch/poller.ts (100%) rename graphql/codegen/src/{cli => core}/watch/types.ts (100%) diff --git a/graphql/codegen/package.json b/graphql/codegen/package.json index 4aae42df7..907bb8a9a 100644 --- a/graphql/codegen/package.json +++ b/graphql/codegen/package.json @@ -35,7 +35,7 @@ "scripts": { "clean": "makage clean", "prepack": "npm run build", - "copy:ts": "makage copy src/cli/codegen/orm/query-builder.ts dist/cli/codegen/orm --flat", + "copy:ts": "makage copy src/core/codegen/orm/query-builder.ts dist/core/codegen/orm --flat", "build": "makage build && npm run copy:ts", "build:dev": "makage build --dev && npm run copy:ts", "dev": "ts-node ./src/index.ts", diff --git a/graphql/codegen/src/__tests__/codegen/client-generator.test.ts b/graphql/codegen/src/__tests__/codegen/client-generator.test.ts index f5b03828e..afcf275e4 100644 --- a/graphql/codegen/src/__tests__/codegen/client-generator.test.ts +++ b/graphql/codegen/src/__tests__/codegen/client-generator.test.ts @@ -8,7 +8,7 @@ import { generateQueryBuilderFile, generateSelectTypesFile, generateCreateClientFile, -} from '../../cli/codegen/orm/client-generator'; +} from '../../core/codegen/orm/client-generator'; import type { CleanTable, CleanFieldType, CleanRelations } from '../../types/schema'; // ============================================================================ diff --git a/graphql/codegen/src/__tests__/codegen/format-output.test.ts b/graphql/codegen/src/__tests__/codegen/format-output.test.ts index 1db9f0f30..d05d52671 100644 --- a/graphql/codegen/src/__tests__/codegen/format-output.test.ts +++ b/graphql/codegen/src/__tests__/codegen/format-output.test.ts @@ -5,7 +5,7 @@ import * as fs from 'node:fs'; import * as path from 'node:path'; import * as os from 'node:os'; -import { formatOutput } from '../../cli/commands/generate'; +import { formatOutput } from '../../core/output'; describe('formatOutput', () => { let tempDir: string; diff --git a/graphql/codegen/src/__tests__/codegen/input-types-generator.test.ts b/graphql/codegen/src/__tests__/codegen/input-types-generator.test.ts index 982ad96b4..d509456fa 100644 --- a/graphql/codegen/src/__tests__/codegen/input-types-generator.test.ts +++ b/graphql/codegen/src/__tests__/codegen/input-types-generator.test.ts @@ -6,7 +6,7 @@ * used to validate the AST-based migration produces equivalent results. */ // Jest globals - no import needed -import { generateInputTypesFile, collectInputTypeNames, collectPayloadTypeNames } from '../../cli/codegen/orm/input-types-generator'; +import { generateInputTypesFile, collectInputTypeNames, collectPayloadTypeNames } from '../../core/codegen/orm/input-types-generator'; import type { CleanTable, CleanFieldType, diff --git a/graphql/codegen/src/__tests__/codegen/model-generator.test.ts b/graphql/codegen/src/__tests__/codegen/model-generator.test.ts index 75d7e5991..1a27b9062 100644 --- a/graphql/codegen/src/__tests__/codegen/model-generator.test.ts +++ b/graphql/codegen/src/__tests__/codegen/model-generator.test.ts @@ -3,7 +3,7 @@ * * Tests the generated model classes with findMany, findFirst, create, update, delete methods. */ -import { generateModelFile } from '../../cli/codegen/orm/model-generator'; +import { generateModelFile } from '../../core/codegen/orm/model-generator'; import type { CleanTable, CleanFieldType, CleanRelations } from '../../types/schema'; // ============================================================================ diff --git a/graphql/codegen/src/__tests__/codegen/query-keys-factory.test.ts b/graphql/codegen/src/__tests__/codegen/query-keys-factory.test.ts index 177cc2dc1..eb2f37344 100644 --- a/graphql/codegen/src/__tests__/codegen/query-keys-factory.test.ts +++ b/graphql/codegen/src/__tests__/codegen/query-keys-factory.test.ts @@ -6,9 +6,9 @@ * - Mutation keys factory (mutation-keys.ts) * - Cache invalidation helpers (invalidation.ts) */ -import { generateQueryKeysFile } from '../../cli/codegen/query-keys'; -import { generateMutationKeysFile } from '../../cli/codegen/mutation-keys'; -import { generateInvalidationFile } from '../../cli/codegen/invalidation'; +import { generateQueryKeysFile } from '../../core/codegen/query-keys'; +import { generateMutationKeysFile } from '../../core/codegen/mutation-keys'; +import { generateInvalidationFile } from '../../core/codegen/invalidation'; import type { CleanTable, CleanFieldType, CleanRelations, CleanOperation, CleanTypeRef } from '../../types/schema'; import type { ResolvedQueryKeyConfig, EntityRelationship } from '../../types/config'; diff --git a/graphql/codegen/src/__tests__/codegen/react-query-hooks.test.ts b/graphql/codegen/src/__tests__/codegen/react-query-hooks.test.ts index 507ab13f4..d5e273df6 100644 --- a/graphql/codegen/src/__tests__/codegen/react-query-hooks.test.ts +++ b/graphql/codegen/src/__tests__/codegen/react-query-hooks.test.ts @@ -9,18 +9,18 @@ * - Schema types * - Barrel files */ -import { generateListQueryHook, generateSingleQueryHook } from '../../cli/codegen/queries'; -import { generateCreateMutationHook, generateUpdateMutationHook, generateDeleteMutationHook } from '../../cli/codegen/mutations'; -import { generateCustomQueryHook } from '../../cli/codegen/custom-queries'; -import { generateCustomMutationHook } from '../../cli/codegen/custom-mutations'; -import { generateSchemaTypesFile } from '../../cli/codegen/schema-types-generator'; +import { generateListQueryHook, generateSingleQueryHook } from '../../core/codegen/queries'; +import { generateCreateMutationHook, generateUpdateMutationHook, generateDeleteMutationHook } from '../../core/codegen/mutations'; +import { generateCustomQueryHook } from '../../core/codegen/custom-queries'; +import { generateCustomMutationHook } from '../../core/codegen/custom-mutations'; +import { generateSchemaTypesFile } from '../../core/codegen/schema-types-generator'; import { generateQueriesBarrel, generateMutationsBarrel, generateMainBarrel, generateCustomQueriesBarrel, generateCustomMutationsBarrel, -} from '../../cli/codegen/barrel'; +} from '../../core/codegen/barrel'; import type { CleanTable, CleanFieldType, diff --git a/graphql/codegen/src/__tests__/codegen/react-query-optional.test.ts b/graphql/codegen/src/__tests__/codegen/react-query-optional.test.ts index b36741fb1..cf21047a6 100644 --- a/graphql/codegen/src/__tests__/codegen/react-query-optional.test.ts +++ b/graphql/codegen/src/__tests__/codegen/react-query-optional.test.ts @@ -6,10 +6,10 @@ * - Mutation generators return null (since they require React Query) * - Standalone fetch functions are still generated for queries */ -import { generateListQueryHook, generateSingleQueryHook, generateAllQueryHooks } from '../../cli/codegen/queries'; -import { generateCreateMutationHook, generateUpdateMutationHook, generateDeleteMutationHook, generateAllMutationHooks } from '../../cli/codegen/mutations'; -import { generateCustomQueryHook, generateAllCustomQueryHooks } from '../../cli/codegen/custom-queries'; -import { generateCustomMutationHook, generateAllCustomMutationHooks } from '../../cli/codegen/custom-mutations'; +import { generateListQueryHook, generateSingleQueryHook, generateAllQueryHooks } from '../../core/codegen/queries'; +import { generateCreateMutationHook, generateUpdateMutationHook, generateDeleteMutationHook, generateAllMutationHooks } from '../../core/codegen/mutations'; +import { generateCustomQueryHook, generateAllCustomQueryHooks } from '../../core/codegen/custom-queries'; +import { generateCustomMutationHook, generateAllCustomMutationHooks } from '../../core/codegen/custom-mutations'; import type { CleanTable, CleanFieldType, CleanRelations, CleanOperation, CleanTypeRef, TypeRegistry } from '../../types/schema'; // ============================================================================ diff --git a/graphql/codegen/src/__tests__/codegen/scalars.test.ts b/graphql/codegen/src/__tests__/codegen/scalars.test.ts index 65c61adf5..27539d3f4 100644 --- a/graphql/codegen/src/__tests__/codegen/scalars.test.ts +++ b/graphql/codegen/src/__tests__/codegen/scalars.test.ts @@ -8,7 +8,7 @@ import { BASE_FILTER_TYPE_NAMES, scalarToTsType, scalarToFilterType, -} from '../../cli/codegen/scalars'; +} from '../../core/codegen/scalars'; describe('scalars', () => { describe('SCALAR_TS_MAP', () => { diff --git a/graphql/codegen/src/__tests__/codegen/schema-types-generator.test.ts b/graphql/codegen/src/__tests__/codegen/schema-types-generator.test.ts index b4b041a33..70fc56de2 100644 --- a/graphql/codegen/src/__tests__/codegen/schema-types-generator.test.ts +++ b/graphql/codegen/src/__tests__/codegen/schema-types-generator.test.ts @@ -1,7 +1,7 @@ /** * Snapshot tests for schema-types-generator */ -import { generateSchemaTypesFile } from '../../cli/codegen/schema-types-generator'; +import { generateSchemaTypesFile } from '../../core/codegen/schema-types-generator'; import type { TypeRegistry, ResolvedType } from '../../types/schema'; function createTypeRegistry(types: Array<[string, ResolvedType]>): TypeRegistry { diff --git a/graphql/codegen/src/__tests__/codegen/utils.test.ts b/graphql/codegen/src/__tests__/codegen/utils.test.ts index 5554bdbf6..62dbf33a0 100644 --- a/graphql/codegen/src/__tests__/codegen/utils.test.ts +++ b/graphql/codegen/src/__tests__/codegen/utils.test.ts @@ -13,7 +13,7 @@ import { gqlTypeToTs, getPrimaryKeyInfo, getGeneratedFileHeader, -} from '../../cli/codegen/utils'; +} from '../../core/codegen/utils'; import type { CleanTable, CleanRelations } from '../../types/schema'; const emptyRelations: CleanRelations = { diff --git a/graphql/codegen/src/__tests__/introspect/infer-tables.test.ts b/graphql/codegen/src/__tests__/introspect/infer-tables.test.ts index 375098263..af8828802 100644 --- a/graphql/codegen/src/__tests__/introspect/infer-tables.test.ts +++ b/graphql/codegen/src/__tests__/introspect/infer-tables.test.ts @@ -4,7 +4,7 @@ * These tests verify that we can correctly infer CleanTable[] metadata * from standard GraphQL introspection (without _meta query). */ -import { inferTablesFromIntrospection } from '../../cli/introspect/infer-tables'; +import { inferTablesFromIntrospection } from '../../core/introspect/infer-tables'; import type { IntrospectionQueryResponse, IntrospectionType, diff --git a/graphql/codegen/src/cli/commands/generate-orm.ts b/graphql/codegen/src/cli/commands/generate-orm.ts index 8c5b03e90..a329fa5a8 100644 --- a/graphql/codegen/src/cli/commands/generate-orm.ts +++ b/graphql/codegen/src/cli/commands/generate-orm.ts @@ -1,38 +1,23 @@ /** * Generate ORM command - generates Prisma-like ORM client from GraphQL schema * - * This command: - * 1. Fetches schema from endpoint or loads from file - * 2. Infers table metadata from introspection (replaces _meta) - * 3. Generates a Prisma-like ORM client with fluent API + * This is a thin CLI wrapper around the core generation functions. + * All business logic is in the core modules. */ - -import type { - GraphQLSDKConfig, - GraphQLSDKConfigTarget, - ResolvedTargetConfig, -} from '../../types/config'; -import { isMultiConfig, mergeConfig, resolveConfig } from '../../types/config'; +import type { ResolvedTargetConfig } from '../../types/config'; +import { + loadAndResolveConfig, + type ConfigOverrideOptions, +} from '../../core/config'; import { createSchemaSource, validateSourceOptions, -} from '../introspect/source'; -import { runCodegenPipeline, validateTablesFound } from './shared'; -import { findConfigFile, loadConfigFile } from './init'; -import { writeGeneratedFiles } from './generate'; -import { generateOrm as generateOrmFiles } from '../codegen/orm'; +} from '../../core/introspect'; +import { runCodegenPipeline, validateTablesFound } from '../../core/pipeline'; +import { generateOrm as generateOrmFiles } from '../../core/codegen/orm'; +import { writeGeneratedFiles } from '../../core/output'; -export interface GenerateOrmOptions { - /** Path to config file */ - config?: string; - /** Named target in a multi-target config */ - target?: string; - /** GraphQL endpoint URL (overrides config) */ - endpoint?: string; - /** Path to GraphQL schema file (.graphql) */ - schema?: string; - /** Output directory (overrides config) */ - output?: string; +export interface GenerateOrmOptions extends ConfigOverrideOptions { /** Authorization header */ authorization?: string; /** Verbose output */ @@ -76,7 +61,7 @@ export async function generateOrm( console.log('Loading configuration...'); } - const configResult = await loadConfig(options); + const configResult = await loadAndResolveConfig(options); if (!configResult.success) { return { success: false, @@ -280,139 +265,3 @@ async function generateOrmForTarget( filesWritten: writeResult.filesWritten, }; } - -interface LoadConfigResult { - success: boolean; - targets?: ResolvedTargetConfig[]; - isMulti?: boolean; - error?: string; -} - -function buildTargetOverrides( - options: GenerateOrmOptions -): GraphQLSDKConfigTarget { - const overrides: GraphQLSDKConfigTarget = {}; - - if (options.endpoint) { - overrides.endpoint = options.endpoint; - overrides.schema = undefined; - } - - if (options.schema) { - overrides.schema = options.schema; - overrides.endpoint = undefined; - } - - return overrides; -} - -async function loadConfig( - options: GenerateOrmOptions -): Promise { - if (options.endpoint && options.schema) { - return { - success: false, - error: 'Cannot use both --endpoint and --schema. Choose one source.', - }; - } - - // Find config file - let configPath = options.config; - if (!configPath) { - configPath = findConfigFile() ?? undefined; - } - - let baseConfig: GraphQLSDKConfig = {}; - - if (configPath) { - const loadResult = await loadConfigFile(configPath); - if (!loadResult.success) { - return { success: false, error: loadResult.error }; - } - baseConfig = loadResult.config; - } - - const overrides = buildTargetOverrides(options); - - if (isMultiConfig(baseConfig)) { - if (Object.keys(baseConfig.targets).length === 0) { - return { - success: false, - error: 'Config file defines no targets.', - }; - } - - if ( - !options.target && - (options.endpoint || options.schema || options.output) - ) { - return { - success: false, - error: - 'Multiple targets configured. Use --target with --endpoint, --schema, or --output.', - }; - } - - if (options.target && !baseConfig.targets[options.target]) { - return { - success: false, - error: `Target "${options.target}" not found in config file.`, - }; - } - - const selectedTargets = options.target - ? { [options.target]: baseConfig.targets[options.target] } - : baseConfig.targets; - const defaults = baseConfig.defaults ?? {}; - const resolvedTargets: ResolvedTargetConfig[] = []; - - for (const [name, target] of Object.entries(selectedTargets)) { - let mergedTarget = mergeConfig(defaults, target); - if (options.target && name === options.target) { - mergedTarget = mergeConfig(mergedTarget, overrides); - } - - if (!mergedTarget.endpoint && !mergedTarget.schema) { - return { - success: false, - error: `Target "${name}" is missing an endpoint or schema.`, - }; - } - - resolvedTargets.push({ - name, - config: resolveConfig(mergedTarget), - }); - } - - return { - success: true, - targets: resolvedTargets, - isMulti: true, - }; - } - - if (options.target) { - return { - success: false, - error: - 'Config file does not define targets. Remove --target to continue.', - }; - } - - const mergedConfig = mergeConfig(baseConfig, overrides); - - if (!mergedConfig.endpoint && !mergedConfig.schema) { - return { - success: false, - error: - 'No source specified. Use --endpoint or --schema, or create a config file with "graphql-codegen init".', - }; - } - - return { - success: true, - targets: [{ name: 'default', config: resolveConfig(mergedConfig) }], - isMulti: false, - }; -} diff --git a/graphql/codegen/src/cli/commands/generate.ts b/graphql/codegen/src/cli/commands/generate.ts index b6f035ca2..39b70d291 100644 --- a/graphql/codegen/src/cli/commands/generate.ts +++ b/graphql/codegen/src/cli/commands/generate.ts @@ -1,40 +1,23 @@ /** * Generate command - generates SDK from GraphQL schema * - * This command: - * 1. Fetches schema from endpoint or loads from file - * 2. Infers table metadata from introspection (replaces _meta) - * 3. Generates hooks for both table CRUD and custom operations + * This is a thin CLI wrapper around the core generation functions. + * All business logic is in the core modules. */ -import * as fs from 'node:fs'; -import * as path from 'node:path'; -import { execSync } from 'node:child_process'; - -import type { - GraphQLSDKConfig, - GraphQLSDKConfigTarget, - ResolvedTargetConfig, -} from '../../types/config'; -import { isMultiConfig, mergeConfig, resolveConfig } from '../../types/config'; +import type { ResolvedTargetConfig } from '../../types/config'; +import { + loadAndResolveConfig, + type ConfigOverrideOptions, +} from '../../core/config'; import { createSchemaSource, validateSourceOptions, -} from '../introspect/source'; -import { runCodegenPipeline, validateTablesFound } from './shared'; -import { findConfigFile, loadConfigFile } from './init'; -import { generate } from '../codegen'; +} from '../../core/introspect'; +import { runCodegenPipeline, validateTablesFound } from '../../core/pipeline'; +import { generate } from '../../core/codegen'; +import { writeGeneratedFiles } from '../../core/output'; -export interface GenerateOptions { - /** Path to config file */ - config?: string; - /** Named target in a multi-target config */ - target?: string; - /** GraphQL endpoint URL (overrides config) */ - endpoint?: string; - /** Path to GraphQL schema file (.graphql) */ - schema?: string; - /** Output directory (overrides config) */ - output?: string; +export interface GenerateOptions extends ConfigOverrideOptions { /** Authorization header */ authorization?: string; /** Verbose output */ @@ -78,7 +61,7 @@ export async function generateReactQuery( console.log('Loading configuration...'); } - const configResult = await loadConfig(options); + const configResult = await loadAndResolveConfig(options); if (!configResult.success) { return { success: false, @@ -281,273 +264,3 @@ async function generateForTarget( filesWritten: writeResult.filesWritten, }; } - -interface LoadConfigResult { - success: boolean; - targets?: ResolvedTargetConfig[]; - isMulti?: boolean; - error?: string; -} - -function buildTargetOverrides( - options: GenerateOptions -): GraphQLSDKConfigTarget { - const overrides: GraphQLSDKConfigTarget = {}; - - if (options.endpoint) { - overrides.endpoint = options.endpoint; - overrides.schema = undefined; - } - - if (options.schema) { - overrides.schema = options.schema; - overrides.endpoint = undefined; - } - - if (options.output) { - overrides.output = options.output; - } - - return overrides; -} - -async function loadConfig(options: GenerateOptions): Promise { - if (options.endpoint && options.schema) { - return { - success: false, - error: 'Cannot use both --endpoint and --schema. Choose one source.', - }; - } - - // Find config file - let configPath = options.config; - if (!configPath) { - configPath = findConfigFile() ?? undefined; - } - - let baseConfig: GraphQLSDKConfig = {}; - - if (configPath) { - const loadResult = await loadConfigFile(configPath); - if (!loadResult.success) { - return { success: false, error: loadResult.error }; - } - baseConfig = loadResult.config; - } - - const overrides = buildTargetOverrides(options); - - if (isMultiConfig(baseConfig)) { - if (Object.keys(baseConfig.targets).length === 0) { - return { - success: false, - error: 'Config file defines no targets.', - }; - } - - if ( - !options.target && - (options.endpoint || options.schema || options.output) - ) { - return { - success: false, - error: - 'Multiple targets configured. Use --target with --endpoint, --schema, or --output.', - }; - } - - if (options.target && !baseConfig.targets[options.target]) { - return { - success: false, - error: `Target "${options.target}" not found in config file.`, - }; - } - - const selectedTargets = options.target - ? { [options.target]: baseConfig.targets[options.target] } - : baseConfig.targets; - const defaults = baseConfig.defaults ?? {}; - const resolvedTargets: ResolvedTargetConfig[] = []; - - for (const [name, target] of Object.entries(selectedTargets)) { - let mergedTarget = mergeConfig(defaults, target); - if (options.target && name === options.target) { - mergedTarget = mergeConfig(mergedTarget, overrides); - } - - if (!mergedTarget.endpoint && !mergedTarget.schema) { - return { - success: false, - error: `Target "${name}" is missing an endpoint or schema.`, - }; - } - - resolvedTargets.push({ - name, - config: resolveConfig(mergedTarget), - }); - } - - return { - success: true, - targets: resolvedTargets, - isMulti: true, - }; - } - - if (options.target) { - return { - success: false, - error: - 'Config file does not define targets. Remove --target to continue.', - }; - } - - const mergedConfig = mergeConfig(baseConfig, overrides); - - if (!mergedConfig.endpoint && !mergedConfig.schema) { - return { - success: false, - error: - 'No source specified. Use --endpoint or --schema, or create a config file with "graphql-codegen init".', - }; - } - - return { - success: true, - targets: [{ name: 'default', config: resolveConfig(mergedConfig) }], - isMulti: false, - }; -} - -export interface GeneratedFile { - path: string; - content: string; -} - -export interface WriteResult { - success: boolean; - filesWritten?: string[]; - errors?: string[]; -} - -export interface WriteOptions { - showProgress?: boolean; -} - -export async function writeGeneratedFiles( - files: GeneratedFile[], - outputDir: string, - subdirs: string[], - options: WriteOptions = {} -): Promise { - const { showProgress = true } = options; - const errors: string[] = []; - const written: string[] = []; - const total = files.length; - const isTTY = process.stdout.isTTY; - - // Ensure output directory exists - try { - fs.mkdirSync(outputDir, { recursive: true }); - } catch (err) { - const message = err instanceof Error ? err.message : 'Unknown error'; - return { - success: false, - errors: [`Failed to create output directory: ${message}`], - }; - } - - // Create subdirectories - for (const subdir of subdirs) { - const subdirPath = path.join(outputDir, subdir); - try { - fs.mkdirSync(subdirPath, { recursive: true }); - } catch (err) { - const message = err instanceof Error ? err.message : 'Unknown error'; - errors.push(`Failed to create directory ${subdirPath}: ${message}`); - } - } - - if (errors.length > 0) { - return { success: false, errors }; - } - - for (let i = 0; i < files.length; i++) { - const file = files[i]; - const filePath = path.join(outputDir, file.path); - - // Show progress - if (showProgress) { - const progress = Math.round(((i + 1) / total) * 100); - if (isTTY) { - process.stdout.write( - `\rWriting files: ${i + 1}/${total} (${progress}%)` - ); - } else if (i % 100 === 0 || i === total - 1) { - // Non-TTY: periodic updates for CI/CD - console.log(`Writing files: ${i + 1}/${total}`); - } - } - - // Ensure parent directory exists - const parentDir = path.dirname(filePath); - try { - fs.mkdirSync(parentDir, { recursive: true }); - } catch { - // Ignore if already exists - } - - try { - fs.writeFileSync(filePath, file.content, 'utf-8'); - written.push(filePath); - } catch (err) { - const message = err instanceof Error ? err.message : 'Unknown error'; - errors.push(`Failed to write ${filePath}: ${message}`); - } - } - - // Clear progress line - if (showProgress && isTTY) { - process.stdout.write('\r' + ' '.repeat(40) + '\r'); - } - - // Format all generated files with prettier - if (errors.length === 0) { - if (showProgress) { - console.log('Formatting generated files...'); - } - const formatResult = formatOutput(outputDir); - if (!formatResult.success && showProgress) { - console.warn('Warning: Failed to format generated files:', formatResult.error); - } - } - - return { - success: errors.length === 0, - filesWritten: written, - errors: errors.length > 0 ? errors : undefined, - }; -} - -/** - * Format generated files using prettier - * Runs prettier on the output directory after all files are written - */ -export function formatOutput(outputDir: string): { success: boolean; error?: string } { - const absoluteOutputDir = path.resolve(outputDir); - - try { - execSync( - `npx prettier --write --single-quote --trailing-comma all --tab-width 2 --semi "${absoluteOutputDir}"`, - { - stdio: 'pipe', - encoding: '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/cli/commands/init.ts b/graphql/codegen/src/cli/commands/init.ts index e3a6497aa..eb61048de 100644 --- a/graphql/codegen/src/cli/commands/init.ts +++ b/graphql/codegen/src/cli/commands/init.ts @@ -1,9 +1,18 @@ /** * Init command - creates a new graphql-codegen configuration file + * + * This is a thin CLI wrapper. Config loading utilities are in core/config. */ import * as fs from 'node:fs'; import * as path from 'node:path'; -import { createJiti } from 'jiti'; + +import { + CONFIG_FILENAME, + findConfigFile, + loadConfigFile, +} from '../../core/config'; + +export { CONFIG_FILENAME, findConfigFile, loadConfigFile }; export interface InitOptions { /** Target directory for the config file */ @@ -16,9 +25,7 @@ export interface InitOptions { output?: string; } -const CONFIG_FILENAME = 'graphql-codegen.config.ts'; - -const CONFIG_TEMPLATE = `import { defineConfig } from '@constructive-io/graphql-codegen'; +const CONFIG_TEMPLATE= `import { defineConfig } from '@constructive-io/graphql-codegen'; export default defineConfig({ // GraphQL endpoint URL (PostGraphile with _meta plugin) @@ -112,100 +119,3 @@ export async function initCommand( }; } } - -/** - * Find the nearest config file by walking up directories - */ -export function findConfigFile( - startDir: string = process.cwd() -): string | null { - let currentDir = startDir; - - while (true) { - const configPath = path.join(currentDir, CONFIG_FILENAME); - if (fs.existsSync(configPath)) { - return configPath; - } - - const parentDir = path.dirname(currentDir); - if (parentDir === currentDir) { - // Reached root - return null; - } - currentDir = parentDir; - } -} - -/** - * Load and validate a config file - * - * Uses jiti to support TypeScript config files (.ts) in addition to - * JavaScript (.js, .mjs, .cjs) without requiring the user to have - * tsx or ts-node installed. - */ -export async function loadConfigFile(configPath: string): Promise<{ - success: boolean; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - config?: any; - error?: string; -}> { - const resolvedPath = path.resolve(configPath); - - if (!fs.existsSync(resolvedPath)) { - return { - success: false, - error: `Config file not found: ${resolvedPath}`, - }; - } - - try { - // Use jiti to load TypeScript/ESM config files seamlessly - // jiti handles .ts, .js, .mjs, .cjs and ESM/CJS interop - const jiti = createJiti(__filename, { - interopDefault: true, - debug: process.env.JITI_DEBUG === '1', - }); - - // jiti.import() with { default: true } returns mod?.default ?? mod - const config = await jiti.import(resolvedPath, { default: true }); - - if (!config || typeof config !== 'object') { - return { - success: false, - error: 'Config file must export a configuration object', - }; - } - - const hasEndpoint = 'endpoint' in config; - const hasSchema = 'schema' in config; - const hasTargets = 'targets' in config; - - if (!hasEndpoint && !hasSchema && !hasTargets) { - return { - success: false, - error: 'Config file must define "endpoint", "schema", or "targets".', - }; - } - - if (hasTargets) { - const targets = config.targets as unknown; - if (!targets || typeof targets !== 'object' || Array.isArray(targets)) { - return { - success: false, - error: 'Config file "targets" must be an object of named configs.', - }; - } - } - - return { - success: true, - config, - }; - } catch (err) { - const message = err instanceof Error ? err.message : 'Unknown error'; - return { - success: false, - error: `Failed to load config file: ${message}`, - }; - } -} diff --git a/graphql/codegen/src/cli/index.ts b/graphql/codegen/src/cli/index.ts index b765814a1..e14de13cb 100644 --- a/graphql/codegen/src/cli/index.ts +++ b/graphql/codegen/src/cli/index.ts @@ -5,18 +5,13 @@ import { CLI, CLIOptions, Inquirerer, ParsedArgs, cliExitWithError, extractFirst, getPackageJson } from 'inquirerer'; -import { initCommand, findConfigFile, loadConfigFile } from './commands/init'; +import { initCommand } from './commands/init'; import { generateReactQuery } from './commands/generate'; import { generateOrm } from './commands/generate-orm'; -import { startWatch } from './watch'; -import { - isMultiConfig, - mergeConfig, - resolveConfig, - type GraphQLSDKConfig, - type GraphQLSDKConfigTarget, - type ResolvedConfig, -} from '../types/config'; +import { loadWatchConfig } from '../core/config'; +import { startWatch } from '../core/watch'; +import { createSchemaSource, inferTablesFromIntrospection } from '../core/introspect'; +import type { ResolvedConfig } from '../types/config'; const usageText = ` graphql-codegen - CLI for generating GraphQL SDK from PostGraphile endpoints or schema files @@ -124,98 +119,6 @@ function formatDuration(ms: number): string { return `${(ms / 1000).toFixed(2)}s`; } -/** - * Load configuration for watch mode, merging CLI options with config file - */ -async function loadWatchConfig(options: { - config?: string; - target?: string; - endpoint?: string; - output?: string; - pollInterval?: number; - debounce?: number; - touch?: string; - clear?: boolean; -}): Promise { - let configPath = options.config; - if (!configPath) { - configPath = findConfigFile() ?? undefined; - } - - let baseConfig: GraphQLSDKConfig = {}; - - if (configPath) { - const loadResult = await loadConfigFile(configPath); - if (!loadResult.success) { - console.error('x', loadResult.error); - return null; - } - baseConfig = loadResult.config; - } - - if (isMultiConfig(baseConfig)) { - if (!options.target) { - console.error( - 'x Watch mode requires --target when using multiple targets.' - ); - return null; - } - - if (!baseConfig.targets[options.target]) { - console.error(`x Target "${options.target}" not found in config file.`); - return null; - } - } else if (options.target) { - console.error('x Config file does not define targets. Remove --target.'); - return null; - } - - const sourceOverrides: GraphQLSDKConfigTarget = {}; - if (options.endpoint) { - sourceOverrides.endpoint = options.endpoint; - sourceOverrides.schema = undefined; - } - - const watchOverrides: GraphQLSDKConfigTarget = { - watch: { - ...(options.pollInterval !== undefined && { - pollInterval: options.pollInterval, - }), - ...(options.debounce !== undefined && { debounce: options.debounce }), - ...(options.touch !== undefined && { touchFile: options.touch }), - ...(options.clear !== undefined && { clearScreen: options.clear }), - }, - }; - - let mergedTarget: GraphQLSDKConfigTarget; - - if (isMultiConfig(baseConfig)) { - const defaults = baseConfig.defaults ?? {}; - const targetConfig = baseConfig.targets[options.target!]; - mergedTarget = mergeConfig(defaults, targetConfig); - } else { - mergedTarget = baseConfig; - } - - mergedTarget = mergeConfig(mergedTarget, sourceOverrides); - mergedTarget = mergeConfig(mergedTarget, watchOverrides); - - if (!mergedTarget.endpoint) { - console.error( - 'x No endpoint specified. Watch mode only supports live endpoints.' - ); - return null; - } - - if (mergedTarget.schema) { - console.error( - 'x Watch mode is only supported with an endpoint, not schema.' - ); - return null; - } - - return resolveConfig(mergedTarget); -} /** * Init command handler @@ -308,6 +211,8 @@ async function handleGenerate(argv: Partial): Promise { configPath: config, target, outputDir: output, + generateReactQuery, + generateOrm, }); return; } @@ -440,6 +345,8 @@ async function handleGenerateOrm(argv: Partial): Promise { target, outputDir: output, skipCustomOperations, + generateReactQuery, + generateOrm, }); return; } @@ -549,9 +456,6 @@ async function handleIntrospect(argv: Partial): Promise { process.exit(1); } - const { createSchemaSource } = await import('./introspect/source'); - const { inferTablesFromIntrospection } = await import('./introspect/infer-tables'); - try { const source = createSchemaSource({ endpoint, diff --git a/graphql/codegen/src/cli/codegen/babel-ast.ts b/graphql/codegen/src/core/codegen/babel-ast.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/babel-ast.ts rename to graphql/codegen/src/core/codegen/babel-ast.ts diff --git a/graphql/codegen/src/cli/codegen/barrel.ts b/graphql/codegen/src/core/codegen/barrel.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/barrel.ts rename to graphql/codegen/src/core/codegen/barrel.ts diff --git a/graphql/codegen/src/cli/codegen/client.ts b/graphql/codegen/src/core/codegen/client.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/client.ts rename to graphql/codegen/src/core/codegen/client.ts diff --git a/graphql/codegen/src/cli/codegen/custom-mutations.ts b/graphql/codegen/src/core/codegen/custom-mutations.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/custom-mutations.ts rename to graphql/codegen/src/core/codegen/custom-mutations.ts diff --git a/graphql/codegen/src/cli/codegen/custom-queries.ts b/graphql/codegen/src/core/codegen/custom-queries.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/custom-queries.ts rename to graphql/codegen/src/core/codegen/custom-queries.ts diff --git a/graphql/codegen/src/cli/codegen/gql-ast.ts b/graphql/codegen/src/core/codegen/gql-ast.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/gql-ast.ts rename to graphql/codegen/src/core/codegen/gql-ast.ts diff --git a/graphql/codegen/src/cli/codegen/index.ts b/graphql/codegen/src/core/codegen/index.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/index.ts rename to graphql/codegen/src/core/codegen/index.ts diff --git a/graphql/codegen/src/cli/codegen/invalidation.ts b/graphql/codegen/src/core/codegen/invalidation.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/invalidation.ts rename to graphql/codegen/src/core/codegen/invalidation.ts diff --git a/graphql/codegen/src/cli/codegen/mutation-keys.ts b/graphql/codegen/src/core/codegen/mutation-keys.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/mutation-keys.ts rename to graphql/codegen/src/core/codegen/mutation-keys.ts diff --git a/graphql/codegen/src/cli/codegen/mutations.ts b/graphql/codegen/src/core/codegen/mutations.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/mutations.ts rename to graphql/codegen/src/core/codegen/mutations.ts diff --git a/graphql/codegen/src/cli/codegen/orm/barrel.ts b/graphql/codegen/src/core/codegen/orm/barrel.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/orm/barrel.ts rename to graphql/codegen/src/core/codegen/orm/barrel.ts diff --git a/graphql/codegen/src/cli/codegen/orm/client-generator.ts b/graphql/codegen/src/core/codegen/orm/client-generator.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/orm/client-generator.ts rename to graphql/codegen/src/core/codegen/orm/client-generator.ts diff --git a/graphql/codegen/src/cli/codegen/orm/client.ts b/graphql/codegen/src/core/codegen/orm/client.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/orm/client.ts rename to graphql/codegen/src/core/codegen/orm/client.ts diff --git a/graphql/codegen/src/cli/codegen/orm/custom-ops-generator.ts b/graphql/codegen/src/core/codegen/orm/custom-ops-generator.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/orm/custom-ops-generator.ts rename to graphql/codegen/src/core/codegen/orm/custom-ops-generator.ts diff --git a/graphql/codegen/src/cli/codegen/orm/index.ts b/graphql/codegen/src/core/codegen/orm/index.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/orm/index.ts rename to graphql/codegen/src/core/codegen/orm/index.ts diff --git a/graphql/codegen/src/cli/codegen/orm/input-types-generator.ts b/graphql/codegen/src/core/codegen/orm/input-types-generator.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/orm/input-types-generator.ts rename to graphql/codegen/src/core/codegen/orm/input-types-generator.ts diff --git a/graphql/codegen/src/cli/codegen/orm/model-generator.ts b/graphql/codegen/src/core/codegen/orm/model-generator.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/orm/model-generator.ts rename to graphql/codegen/src/core/codegen/orm/model-generator.ts diff --git a/graphql/codegen/src/cli/codegen/orm/query-builder.ts b/graphql/codegen/src/core/codegen/orm/query-builder.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/orm/query-builder.ts rename to graphql/codegen/src/core/codegen/orm/query-builder.ts diff --git a/graphql/codegen/src/cli/codegen/orm/select-types.ts b/graphql/codegen/src/core/codegen/orm/select-types.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/orm/select-types.ts rename to graphql/codegen/src/core/codegen/orm/select-types.ts diff --git a/graphql/codegen/src/cli/codegen/queries.ts b/graphql/codegen/src/core/codegen/queries.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/queries.ts rename to graphql/codegen/src/core/codegen/queries.ts diff --git a/graphql/codegen/src/cli/codegen/query-keys.ts b/graphql/codegen/src/core/codegen/query-keys.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/query-keys.ts rename to graphql/codegen/src/core/codegen/query-keys.ts diff --git a/graphql/codegen/src/cli/codegen/scalars.ts b/graphql/codegen/src/core/codegen/scalars.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/scalars.ts rename to graphql/codegen/src/core/codegen/scalars.ts diff --git a/graphql/codegen/src/cli/codegen/schema-gql-ast.ts b/graphql/codegen/src/core/codegen/schema-gql-ast.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/schema-gql-ast.ts rename to graphql/codegen/src/core/codegen/schema-gql-ast.ts diff --git a/graphql/codegen/src/cli/codegen/schema-types-generator.ts b/graphql/codegen/src/core/codegen/schema-types-generator.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/schema-types-generator.ts rename to graphql/codegen/src/core/codegen/schema-types-generator.ts diff --git a/graphql/codegen/src/cli/codegen/type-resolver.ts b/graphql/codegen/src/core/codegen/type-resolver.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/type-resolver.ts rename to graphql/codegen/src/core/codegen/type-resolver.ts diff --git a/graphql/codegen/src/cli/codegen/types.ts b/graphql/codegen/src/core/codegen/types.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/types.ts rename to graphql/codegen/src/core/codegen/types.ts diff --git a/graphql/codegen/src/cli/codegen/utils.ts b/graphql/codegen/src/core/codegen/utils.ts similarity index 100% rename from graphql/codegen/src/cli/codegen/utils.ts rename to graphql/codegen/src/core/codegen/utils.ts diff --git a/graphql/codegen/src/core/config/index.ts b/graphql/codegen/src/core/config/index.ts new file mode 100644 index 000000000..ef792ec1f --- /dev/null +++ b/graphql/codegen/src/core/config/index.ts @@ -0,0 +1,18 @@ +/** + * Configuration module exports + */ + +export { + CONFIG_FILENAME, + findConfigFile, + loadConfigFile, + type LoadConfigFileResult, +} from './loader'; + +export { + buildTargetOverrides, + loadAndResolveConfig, + loadWatchConfig, + type ConfigOverrideOptions, + type LoadConfigResult, +} from './resolver'; diff --git a/graphql/codegen/src/core/config/loader.ts b/graphql/codegen/src/core/config/loader.ts new file mode 100644 index 000000000..3ec07672c --- /dev/null +++ b/graphql/codegen/src/core/config/loader.ts @@ -0,0 +1,112 @@ +/** + * Configuration file loading utilities + * + * Pure functions for finding and loading graphql-codegen configuration files. + * These are core utilities that can be used programmatically or by the CLI. + */ +import * as fs from 'node:fs'; +import * as path from 'node:path'; +import { createJiti } from 'jiti'; + +export const CONFIG_FILENAME = 'graphql-codegen.config.ts'; + +/** + * Find the nearest config file by walking up directories + */ +export function findConfigFile( + startDir: string = process.cwd() +): string | null { + let currentDir = startDir; + + while (true) { + const configPath = path.join(currentDir, CONFIG_FILENAME); + if (fs.existsSync(configPath)) { + return configPath; + } + + const parentDir = path.dirname(currentDir); + if (parentDir === currentDir) { + // Reached root + return null; + } + currentDir = parentDir; + } +} + +export interface LoadConfigFileResult { + success: boolean; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + config?: any; + error?: string; +} + +/** + * Load and validate a config file + * + * Uses jiti to support TypeScript config files (.ts) in addition to + * JavaScript (.js, .mjs, .cjs) without requiring the user to have + * tsx or ts-node installed. + */ +export async function loadConfigFile( + configPath: string +): Promise { + const resolvedPath = path.resolve(configPath); + + if (!fs.existsSync(resolvedPath)) { + return { + success: false, + error: `Config file not found: ${resolvedPath}`, + }; + } + + try { + // Use jiti to load TypeScript/ESM config files seamlessly + // jiti handles .ts, .js, .mjs, .cjs and ESM/CJS interop + const jiti = createJiti(__filename, { + interopDefault: true, + debug: process.env.JITI_DEBUG === '1', + }); + + // jiti.import() with { default: true } returns mod?.default ?? mod + const config = await jiti.import(resolvedPath, { default: true }); + + if (!config || typeof config !== 'object') { + return { + success: false, + error: 'Config file must export a configuration object', + }; + } + + const hasEndpoint = 'endpoint' in config; + const hasSchema = 'schema' in config; + const hasTargets = 'targets' in config; + + if (!hasEndpoint && !hasSchema && !hasTargets) { + return { + success: false, + error: 'Config file must define "endpoint", "schema", or "targets".', + }; + } + + if (hasTargets) { + const targets = config.targets as unknown; + if (!targets || typeof targets !== 'object' || Array.isArray(targets)) { + return { + success: false, + error: 'Config file "targets" must be an object of named configs.', + }; + } + } + + return { + success: true, + config, + }; + } catch (err) { + const message = err instanceof Error ? err.message : 'Unknown error'; + return { + success: false, + error: `Failed to load config file: ${message}`, + }; + } +} diff --git a/graphql/codegen/src/core/config/resolver.ts b/graphql/codegen/src/core/config/resolver.ts new file mode 100644 index 000000000..ed116f9e6 --- /dev/null +++ b/graphql/codegen/src/core/config/resolver.ts @@ -0,0 +1,303 @@ +/** + * Configuration resolution utilities + * + * Functions for resolving and merging configuration from various sources + * (config file, CLI options, defaults) into a final resolved configuration. + */ +import type { + GraphQLSDKConfig, + GraphQLSDKConfigTarget, + GraphQLSDKMultiConfig, + ResolvedConfig, + ResolvedTargetConfig, +} from '../../types/config'; +import { isMultiConfig, mergeConfig, resolveConfig } from '../../types/config'; +import { findConfigFile, loadConfigFile } from './loader'; + +/** + * Options that can override config file settings + */ +export interface ConfigOverrideOptions { + /** Path to config file */ + config?: string; + /** Named target in a multi-target config */ + target?: string; + /** GraphQL endpoint URL (overrides config) */ + endpoint?: string; + /** Path to GraphQL schema file (.graphql) */ + schema?: string; + /** Output directory (overrides config) */ + output?: string; +} + +/** + * Result of loading and resolving configuration + */ +export interface LoadConfigResult { + success: boolean; + targets?: ResolvedTargetConfig[]; + isMulti?: boolean; + error?: string; +} + +/** + * Build target overrides from options + */ +export function buildTargetOverrides( + options: ConfigOverrideOptions +): GraphQLSDKConfigTarget { + const overrides: GraphQLSDKConfigTarget = {}; + + if (options.endpoint) { + overrides.endpoint = options.endpoint; + overrides.schema = undefined; + } + + if (options.schema) { + overrides.schema = options.schema; + overrides.endpoint = undefined; + } + + if (options.output) { + overrides.output = options.output; + } + + return overrides; +} + +/** + * Load and resolve configuration from file and/or options + * + * This is the main entry point for configuration loading. It: + * 1. Finds and loads the config file (if any) + * 2. Applies CLI option overrides + * 3. Resolves multi-target or single-target configurations + * 4. Returns fully resolved configuration ready for use + */ +export async function loadAndResolveConfig( + options: ConfigOverrideOptions +): Promise { + if (options.endpoint && options.schema) { + return { + success: false, + error: 'Cannot use both --endpoint and --schema. Choose one source.', + }; + } + + // Find config file + let configPath = options.config; + if (!configPath) { + configPath = findConfigFile() ?? undefined; + } + + let baseConfig: GraphQLSDKConfig = {}; + + if (configPath) { + const loadResult = await loadConfigFile(configPath); + if (!loadResult.success) { + return { success: false, error: loadResult.error }; + } + baseConfig = loadResult.config; + } + + const overrides = buildTargetOverrides(options); + + if (isMultiConfig(baseConfig)) { + return resolveMultiTargetConfig(baseConfig, options, overrides); + } + + return resolveSingleTargetConfig(baseConfig as GraphQLSDKConfigTarget, options, overrides); +} + +/** + * Resolve a multi-target configuration + */ +function resolveMultiTargetConfig( + baseConfig: GraphQLSDKMultiConfig, + options: ConfigOverrideOptions, + overrides: GraphQLSDKConfigTarget +): LoadConfigResult { + if (Object.keys(baseConfig.targets).length === 0) { + return { + success: false, + error: 'Config file defines no targets.', + }; + } + + if ( + !options.target && + (options.endpoint || options.schema || options.output) + ) { + return { + success: false, + error: + 'Multiple targets configured. Use --target with --endpoint, --schema, or --output.', + }; + } + + if (options.target && !baseConfig.targets[options.target]) { + return { + success: false, + error: `Target "${options.target}" not found in config file.`, + }; + } + + const selectedTargets = options.target + ? { [options.target]: baseConfig.targets[options.target] } + : baseConfig.targets; + const defaults = baseConfig.defaults ?? {}; + const resolvedTargets: ResolvedTargetConfig[] = []; + + for (const [name, target] of Object.entries(selectedTargets)) { + let mergedTarget = mergeConfig(defaults, target); + if (options.target && name === options.target) { + mergedTarget = mergeConfig(mergedTarget, overrides); + } + + if (!mergedTarget.endpoint && !mergedTarget.schema) { + return { + success: false, + error: `Target "${name}" is missing an endpoint or schema.`, + }; + } + + resolvedTargets.push({ + name, + config: resolveConfig(mergedTarget), + }); + } + + return { + success: true, + targets: resolvedTargets, + isMulti: true, + }; +} + +/** + * Resolve a single-target configuration + */ +function resolveSingleTargetConfig( + baseConfig: GraphQLSDKConfigTarget, + options: ConfigOverrideOptions, + overrides: GraphQLSDKConfigTarget +): LoadConfigResult { + if (options.target) { + return { + success: false, + error: + 'Config file does not define targets. Remove --target to continue.', + }; + } + + const mergedConfig = mergeConfig(baseConfig, overrides); + + if (!mergedConfig.endpoint && !mergedConfig.schema) { + return { + success: false, + error: + 'No source specified. Use --endpoint or --schema, or create a config file with "graphql-codegen init".', + }; + } + + return { + success: true, + targets: [{ name: 'default', config: resolveConfig(mergedConfig) }], + isMulti: false, + }; +} + +/** + * Build watch configuration from options + * + * Used by watch mode to resolve configuration with watch-specific overrides. + */ +export async function loadWatchConfig(options: { + config?: string; + target?: string; + endpoint?: string; + output?: string; + pollInterval?: number; + debounce?: number; + touch?: string; + clear?: boolean; +}): Promise { + let configPath = options.config; + if (!configPath) { + configPath = findConfigFile() ?? undefined; + } + + let baseConfig: GraphQLSDKConfig = {}; + + if (configPath) { + const loadResult = await loadConfigFile(configPath); + if (!loadResult.success) { + console.error('x', loadResult.error); + return null; + } + baseConfig = loadResult.config; + } + + if (isMultiConfig(baseConfig)) { + if (!options.target) { + console.error( + 'x Watch mode requires --target when using multiple targets.' + ); + return null; + } + + if (!baseConfig.targets[options.target]) { + console.error(`x Target "${options.target}" not found in config file.`); + return null; + } + } else if (options.target) { + console.error('x Config file does not define targets. Remove --target.'); + return null; + } + + const sourceOverrides: GraphQLSDKConfigTarget = {}; + if (options.endpoint) { + sourceOverrides.endpoint = options.endpoint; + sourceOverrides.schema = undefined; + } + + const watchOverrides: GraphQLSDKConfigTarget = { + watch: { + ...(options.pollInterval !== undefined && { + pollInterval: options.pollInterval, + }), + ...(options.debounce !== undefined && { debounce: options.debounce }), + ...(options.touch !== undefined && { touchFile: options.touch }), + ...(options.clear !== undefined && { clearScreen: options.clear }), + }, + }; + + let mergedTarget: GraphQLSDKConfigTarget; + + if (isMultiConfig(baseConfig)) { + const defaults = baseConfig.defaults ?? {}; + const targetConfig = baseConfig.targets[options.target!]; + mergedTarget = mergeConfig(defaults, targetConfig); + } else { + mergedTarget = baseConfig; + } + + mergedTarget = mergeConfig(mergedTarget, sourceOverrides); + mergedTarget = mergeConfig(mergedTarget, watchOverrides); + + if (!mergedTarget.endpoint) { + console.error( + 'x No endpoint specified. Watch mode only supports live endpoints.' + ); + return null; + } + + if (mergedTarget.schema) { + console.error( + 'x Watch mode is only supported with an endpoint, not schema.' + ); + return null; + } + + return resolveConfig(mergedTarget); +} diff --git a/graphql/codegen/src/core/index.ts b/graphql/codegen/src/core/index.ts index 5e6e782c0..a8a9b92e4 100644 --- a/graphql/codegen/src/core/index.ts +++ b/graphql/codegen/src/core/index.ts @@ -1,5 +1,8 @@ /** - * Core query building exports + * Core module exports + * + * This module contains all the core business logic for graphql-codegen. + * The CLI is a thin wrapper around these core functions. */ // Types @@ -14,3 +17,21 @@ export { QueryBuilder, MetaObject } from './query-builder'; // Meta object utilities export { validateMetaObject, convertFromMetaSchema } from './meta-object'; + +// Configuration loading and resolution +export * from './config'; + +// Code generation +export * from './codegen'; + +// Schema introspection +export * from './introspect'; + +// Codegen pipeline +export * from './pipeline'; + +// File output +export * from './output'; + +// Watch mode +export * from './watch'; diff --git a/graphql/codegen/src/cli/introspect/fetch-schema.ts b/graphql/codegen/src/core/introspect/fetch-schema.ts similarity index 100% rename from graphql/codegen/src/cli/introspect/fetch-schema.ts rename to graphql/codegen/src/core/introspect/fetch-schema.ts diff --git a/graphql/codegen/src/cli/introspect/index.ts b/graphql/codegen/src/core/introspect/index.ts similarity index 100% rename from graphql/codegen/src/cli/introspect/index.ts rename to graphql/codegen/src/core/introspect/index.ts diff --git a/graphql/codegen/src/cli/introspect/infer-tables.ts b/graphql/codegen/src/core/introspect/infer-tables.ts similarity index 100% rename from graphql/codegen/src/cli/introspect/infer-tables.ts rename to graphql/codegen/src/core/introspect/infer-tables.ts diff --git a/graphql/codegen/src/cli/introspect/schema-query.ts b/graphql/codegen/src/core/introspect/schema-query.ts similarity index 100% rename from graphql/codegen/src/cli/introspect/schema-query.ts rename to graphql/codegen/src/core/introspect/schema-query.ts diff --git a/graphql/codegen/src/cli/introspect/source/endpoint.ts b/graphql/codegen/src/core/introspect/source/endpoint.ts similarity index 100% rename from graphql/codegen/src/cli/introspect/source/endpoint.ts rename to graphql/codegen/src/core/introspect/source/endpoint.ts diff --git a/graphql/codegen/src/cli/introspect/source/file.ts b/graphql/codegen/src/core/introspect/source/file.ts similarity index 100% rename from graphql/codegen/src/cli/introspect/source/file.ts rename to graphql/codegen/src/core/introspect/source/file.ts diff --git a/graphql/codegen/src/cli/introspect/source/index.ts b/graphql/codegen/src/core/introspect/source/index.ts similarity index 100% rename from graphql/codegen/src/cli/introspect/source/index.ts rename to graphql/codegen/src/core/introspect/source/index.ts diff --git a/graphql/codegen/src/cli/introspect/source/types.ts b/graphql/codegen/src/core/introspect/source/types.ts similarity index 100% rename from graphql/codegen/src/cli/introspect/source/types.ts rename to graphql/codegen/src/core/introspect/source/types.ts diff --git a/graphql/codegen/src/cli/introspect/transform-schema.ts b/graphql/codegen/src/core/introspect/transform-schema.ts similarity index 100% rename from graphql/codegen/src/cli/introspect/transform-schema.ts rename to graphql/codegen/src/core/introspect/transform-schema.ts diff --git a/graphql/codegen/src/cli/introspect/transform.ts b/graphql/codegen/src/core/introspect/transform.ts similarity index 100% rename from graphql/codegen/src/cli/introspect/transform.ts rename to graphql/codegen/src/core/introspect/transform.ts diff --git a/graphql/codegen/src/core/output/index.ts b/graphql/codegen/src/core/output/index.ts new file mode 100644 index 000000000..3d6344d9c --- /dev/null +++ b/graphql/codegen/src/core/output/index.ts @@ -0,0 +1,11 @@ +/** + * Output module exports + */ + +export { + writeGeneratedFiles, + formatOutput, + type GeneratedFile, + type WriteResult, + type WriteOptions, +} from './writer'; diff --git a/graphql/codegen/src/core/output/writer.ts b/graphql/codegen/src/core/output/writer.ts new file mode 100644 index 000000000..ae7dd71b9 --- /dev/null +++ b/graphql/codegen/src/core/output/writer.ts @@ -0,0 +1,163 @@ +/** + * File writing utilities + * + * Pure functions for writing generated files to disk and formatting them. + * These are core utilities that can be used programmatically or by the CLI. + */ +import * as fs from 'node:fs'; +import * as path from 'node:path'; +import { execSync } from 'node:child_process'; + +import type { GeneratedFile } from '../codegen'; + +export type { GeneratedFile }; + +/** + * Result of writing files + */ +export interface WriteResult { + success: boolean; + filesWritten?: string[]; + errors?: string[]; +} + +/** + * Options for writing files + */ +export interface WriteOptions { + /** Show progress output (default: true) */ + showProgress?: boolean; + /** Format files with prettier after writing (default: true) */ + formatFiles?: boolean; +} + +/** + * Write generated files to disk + * + * @param files - Array of files to write + * @param outputDir - Base output directory + * @param subdirs - Subdirectories to create + * @param options - Write options + */ +export async function writeGeneratedFiles( + files: GeneratedFile[], + outputDir: string, + subdirs: string[], + options: WriteOptions = {} +): Promise { + const { showProgress = true, formatFiles = true } = options; + const errors: string[] = []; + const written: string[] = []; + const total = files.length; + const isTTY = process.stdout.isTTY; + + // Ensure output directory exists + try { + fs.mkdirSync(outputDir, { recursive: true }); + } catch (err) { + const message = err instanceof Error ? err.message : 'Unknown error'; + return { + success: false, + errors: [`Failed to create output directory: ${message}`], + }; + } + + // Create subdirectories + for (const subdir of subdirs) { + const subdirPath = path.join(outputDir, subdir); + try { + fs.mkdirSync(subdirPath, { recursive: true }); + } catch (err) { + const message = err instanceof Error ? err.message : 'Unknown error'; + errors.push(`Failed to create directory ${subdirPath}: ${message}`); + } + } + + if (errors.length > 0) { + return { success: false, errors }; + } + + for (let i = 0; i < files.length; i++) { + const file = files[i]; + const filePath = path.join(outputDir, file.path); + + // Show progress + if (showProgress) { + const progress = Math.round(((i + 1) / total) * 100); + if (isTTY) { + process.stdout.write( + `\rWriting files: ${i + 1}/${total} (${progress}%)` + ); + } else if (i % 100 === 0 || i === total - 1) { + // Non-TTY: periodic updates for CI/CD + console.log(`Writing files: ${i + 1}/${total}`); + } + } + + // Ensure parent directory exists + const parentDir = path.dirname(filePath); + try { + fs.mkdirSync(parentDir, { recursive: true }); + } catch { + // Ignore if already exists + } + + try { + fs.writeFileSync(filePath, file.content, 'utf-8'); + written.push(filePath); + } catch (err) { + const message = err instanceof Error ? err.message : 'Unknown error'; + errors.push(`Failed to write ${filePath}: ${message}`); + } + } + + // Clear progress line + if (showProgress && isTTY) { + process.stdout.write('\r' + ' '.repeat(40) + '\r'); + } + + // Format all generated files with prettier + if (formatFiles && errors.length === 0) { + if (showProgress) { + console.log('Formatting generated files...'); + } + const formatResult = formatOutput(outputDir); + if (!formatResult.success && showProgress) { + console.warn( + 'Warning: Failed to format generated files:', + formatResult.error + ); + } + } + + return { + success: errors.length === 0, + filesWritten: written, + errors: errors.length > 0 ? errors : undefined, + }; +} + +/** + * Format generated files using prettier + * + * Runs prettier on the output directory after all files are written. + */ +export function formatOutput( + outputDir: string +): { success: boolean; error?: string } { + const absoluteOutputDir = path.resolve(outputDir); + + try { + execSync( + `npx prettier --write --single-quote --trailing-comma all --tab-width 2 --semi "${absoluteOutputDir}"`, + { + stdio: 'pipe', + encoding: '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/cli/commands/shared.ts b/graphql/codegen/src/core/pipeline/index.ts similarity index 97% rename from graphql/codegen/src/cli/commands/shared.ts rename to graphql/codegen/src/core/pipeline/index.ts index 2defb6b24..c75d5011f 100644 --- a/graphql/codegen/src/cli/commands/shared.ts +++ b/graphql/codegen/src/core/pipeline/index.ts @@ -24,6 +24,10 @@ import { getCustomOperations, } from '../introspect/transform-schema'; +// Re-export for convenience +export type { SchemaSource } from '../introspect/source'; +export { createSchemaSource, validateSourceOptions } from '../introspect/source'; + // ============================================================================ // Pipeline Types // ============================================================================ diff --git a/graphql/codegen/src/cli/watch/cache.ts b/graphql/codegen/src/core/watch/cache.ts similarity index 100% rename from graphql/codegen/src/cli/watch/cache.ts rename to graphql/codegen/src/core/watch/cache.ts diff --git a/graphql/codegen/src/cli/watch/debounce.ts b/graphql/codegen/src/core/watch/debounce.ts similarity index 100% rename from graphql/codegen/src/cli/watch/debounce.ts rename to graphql/codegen/src/core/watch/debounce.ts diff --git a/graphql/codegen/src/cli/watch/hash.ts b/graphql/codegen/src/core/watch/hash.ts similarity index 100% rename from graphql/codegen/src/cli/watch/hash.ts rename to graphql/codegen/src/core/watch/hash.ts diff --git a/graphql/codegen/src/cli/watch/index.ts b/graphql/codegen/src/core/watch/index.ts similarity index 100% rename from graphql/codegen/src/cli/watch/index.ts rename to graphql/codegen/src/core/watch/index.ts diff --git a/graphql/codegen/src/cli/watch/orchestrator.ts b/graphql/codegen/src/core/watch/orchestrator.ts similarity index 83% rename from graphql/codegen/src/cli/watch/orchestrator.ts rename to graphql/codegen/src/core/watch/orchestrator.ts index 5c86db07c..83ea36fb0 100644 --- a/graphql/codegen/src/cli/watch/orchestrator.ts +++ b/graphql/codegen/src/core/watch/orchestrator.ts @@ -8,11 +8,28 @@ import type { ResolvedConfig } from '../../types/config'; import type { GeneratorType, WatchOptions, PollEvent } from './types'; import { SchemaPoller } from './poller'; import { debounce } from './debounce'; -import { generateReactQuery, type GenerateResult } from '../commands/generate'; -import { - generateOrm, - type GenerateOrmResult, -} from '../commands/generate-orm'; + +// These will be injected by the CLI layer to avoid circular dependencies +// The watch orchestrator doesn't need to know about the full generate commands +export interface GenerateFunction { + (options: { + config?: string; + target?: string; + endpoint?: string; + output?: string; + authorization?: string; + verbose?: boolean; + skipCustomOperations?: boolean; + }): Promise; +} + +export interface GenerateResult { + success: boolean; + message: string; + tables?: string[]; + filesWritten?: string[]; + errors?: string[]; +} export interface WatchOrchestratorOptions { config: ResolvedConfig; @@ -23,10 +40,14 @@ export interface WatchOrchestratorOptions { configPath?: string; /** Target name for multi-target configs */ target?: string; - /** Override output directory (for ORM) */ + /** Override output directory */ outputDir?: string; /** Skip custom operations flag */ skipCustomOperations?: boolean; + /** Generator function for React Query SDK */ + generateReactQuery: GenerateFunction; + /** Generator function for ORM client */ + generateOrm: GenerateFunction; } export interface WatchStatus { @@ -192,29 +213,26 @@ export class WatchOrchestrator { this.log('Regenerating...'); try { - let result: GenerateResult | GenerateOrmResult; - - if (this.options.generatorType === 'generate') { - result = await generateReactQuery({ - config: this.options.configPath, - target: this.options.target, - endpoint: this.options.config.endpoint, - output: this.options.outputDir ?? this.options.config.output, - authorization: this.options.authorization, - verbose: this.watchOptions.verbose, - skipCustomOperations: this.options.skipCustomOperations, - }); - } else { - result = await generateOrm({ - config: this.options.configPath, - target: this.options.target, - endpoint: this.options.config.endpoint, - output: this.options.outputDir ?? this.options.config.orm.output, - authorization: this.options.authorization, - verbose: this.watchOptions.verbose, - skipCustomOperations: this.options.skipCustomOperations, - }); - } + const generateFn = + this.options.generatorType === 'generate' + ? this.options.generateReactQuery + : this.options.generateOrm; + + const outputDir = + this.options.outputDir ?? + (this.options.generatorType === 'generate' + ? this.options.config.output + : this.options.config.orm.output); + + const result = await generateFn({ + config: this.options.configPath, + target: this.options.target, + endpoint: this.options.config.endpoint, + output: outputDir, + authorization: this.options.authorization, + verbose: this.watchOptions.verbose, + skipCustomOperations: this.options.skipCustomOperations, + }); const duration = Date.now() - startTime; diff --git a/graphql/codegen/src/cli/watch/poller.ts b/graphql/codegen/src/core/watch/poller.ts similarity index 100% rename from graphql/codegen/src/cli/watch/poller.ts rename to graphql/codegen/src/core/watch/poller.ts diff --git a/graphql/codegen/src/cli/watch/types.ts b/graphql/codegen/src/core/watch/types.ts similarity index 100% rename from graphql/codegen/src/cli/watch/types.ts rename to graphql/codegen/src/core/watch/types.ts From f5e9f7ccb95842d30e6934299b3b93e2124d36c2 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 23 Jan 2026 05:31:55 +0000 Subject: [PATCH 02/23] refactor(graphql-codegen): add database schema utilities and clean up CLI Phase 2 of separation of concerns: - Add @constructive-io/graphql-server as dependency to graphql-codegen - Remove @constructive-io/graphql-codegen devDependency from graphql-server (generated code is committed) - Create core/database module with buildSchemaFromDatabase function - Clean up packages/cli codegen.ts to use inquirerer pattern and import from graphql-codegen - Export buildSchemaFromDatabase and buildSchemaSDLFromDatabase from graphql-codegen This breaks the circular dependency by making it a one-way dependency: graphql-codegen -> graphql-server (no reverse dependency) --- graphql/codegen/package.json | 1 + graphql/codegen/src/core/database/index.ts | 79 + graphql/codegen/src/core/index.ts | 3 + graphql/codegen/src/index.ts | 10 + graphql/server/package.json | 1 - packages/cli/src/commands/codegen.ts | 233 +- pnpm-lock.yaml | 9677 +++++--------------- 7 files changed, 2736 insertions(+), 7268 deletions(-) create mode 100644 graphql/codegen/src/core/database/index.ts diff --git a/graphql/codegen/package.json b/graphql/codegen/package.json index 907bb8a9a..4fb11af43 100644 --- a/graphql/codegen/package.json +++ b/graphql/codegen/package.json @@ -56,6 +56,7 @@ "@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.0", "ajv": "^8.17.1", diff --git a/graphql/codegen/src/core/database/index.ts b/graphql/codegen/src/core/database/index.ts new file mode 100644 index 000000000..74c41cb03 --- /dev/null +++ b/graphql/codegen/src/core/database/index.ts @@ -0,0 +1,79 @@ +/** + * Database schema utilities + * + * Provides functions for building GraphQL schemas directly from PostgreSQL databases. + */ + +import * as fs from 'node:fs'; +import * as path from 'node:path'; +import { buildSchemaSDL } from '@constructive-io/graphql-server'; + +export interface BuildSchemaFromDatabaseOptions { + /** Database name */ + database: string; + /** PostgreSQL schemas to include */ + schemas: string[]; + /** Output directory for the schema file */ + outDir: string; + /** Optional filename (default: schema.graphql) */ + filename?: string; +} + +export interface BuildSchemaFromDatabaseResult { + /** Path to the generated schema file */ + schemaPath: string; + /** The SDL content */ + sdl: string; +} + +/** + * Build a GraphQL schema from a PostgreSQL database and write it to a file. + * + * This function introspects the database using PostGraphile and generates + * a GraphQL SDL file that can be used for code generation. + * + * @param options - Configuration options + * @returns The path to the generated schema file and the SDL content + */ +export async function buildSchemaFromDatabase( + options: BuildSchemaFromDatabaseOptions +): Promise { + const { database, schemas, outDir, filename = 'schema.graphql' } = options; + + // Ensure output directory exists + await fs.promises.mkdir(outDir, { recursive: true }); + + // Build schema SDL from database + const sdl = await buildSchemaSDL({ + database, + schemas, + graphile: { pgSettings: async () => ({ role: 'administrator' }) }, + }); + + // Write schema to file + const schemaPath = path.join(outDir, filename); + await fs.promises.writeFile(schemaPath, sdl, 'utf-8'); + + 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; + + return buildSchemaSDL({ + database, + schemas, + graphile: { pgSettings: async () => ({ role: 'administrator' }) }, + }); +} diff --git a/graphql/codegen/src/core/index.ts b/graphql/codegen/src/core/index.ts index a8a9b92e4..5d5be3db2 100644 --- a/graphql/codegen/src/core/index.ts +++ b/graphql/codegen/src/core/index.ts @@ -35,3 +35,6 @@ export * from './output'; // Watch mode export * from './watch'; + +// Database schema utilities +export * from './database'; diff --git a/graphql/codegen/src/index.ts b/graphql/codegen/src/index.ts index cd1db7b06..36314fd73 100644 --- a/graphql/codegen/src/index.ts +++ b/graphql/codegen/src/index.ts @@ -29,6 +29,16 @@ export { loadConfigFile, } from './cli/commands'; +// Database schema utilities (re-exported from core for convenience) +export { + buildSchemaFromDatabase, + buildSchemaSDLFromDatabase, +} from './core/database'; +export type { + BuildSchemaFromDatabaseOptions, + BuildSchemaFromDatabaseResult, +} from './core/database'; + export type { GenerateOptions, GenerateResult, diff --git a/graphql/server/package.json b/graphql/server/package.json index dc90a6b77..91abf4803 100644 --- a/graphql/server/package.json +++ b/graphql/server/package.json @@ -78,7 +78,6 @@ }, "devDependencies": { "@aws-sdk/client-s3": "^3.971.0", - "@constructive-io/graphql-codegen": "workspace:*", "@types/cors": "^2.8.17", "@types/express": "^5.0.6", "@types/graphql-upload": "^8.0.12", diff --git a/packages/cli/src/commands/codegen.ts b/packages/cli/src/commands/codegen.ts index dbd6a28aa..1731b5a00 100644 --- a/packages/cli/src/commands/codegen.ts +++ b/packages/cli/src/commands/codegen.ts @@ -1,11 +1,9 @@ -import { CLIOptions, Inquirerer, ParsedArgs } from 'inquirerer'; -import * as fs from 'node:fs'; -import * as path from 'node:path'; -import { buildSchemaSDL } from '@constructive-io/graphql-server'; +import { CLIOptions, Inquirerer, Question } from 'inquirerer'; import { generateReactQuery, generateOrm, findConfigFile, + buildSchemaFromDatabase, type GenerateResult, type GenerateTargetResult, type GenerateOrmResult, @@ -34,31 +32,83 @@ Options: --schemas Comma-separated schemas (required for DB mode) `; -interface CodegenOptions { - endpoint?: string; - config?: string; - target?: string; - output?: string; - auth?: string; - database?: string; - schemas?: string[]; - dryRun: boolean; - verbose: boolean; - orm: boolean; -} - -type SourceMode = - | { type: 'endpoint'; endpoint: string } - | { type: 'database'; database: string; schemas: string[] } - | { type: 'config'; configPath: string } - | { type: 'none' }; +const questions: Question[] = [ + { + name: 'endpoint', + message: 'GraphQL endpoint URL', + type: 'text', + required: false, + }, + { + name: 'config', + message: 'Path to config file', + type: 'text', + required: false, + }, + { + name: 'target', + message: 'Target name in config file', + type: 'text', + required: false, + }, + { + name: 'out', + message: 'Output directory', + type: 'text', + required: false, + default: 'codegen', + useDefault: true, + }, + { + name: 'auth', + message: 'Authorization header value', + type: 'text', + required: false, + }, + { + name: 'database', + message: 'Database name (for DB mode)', + type: 'text', + required: false, + }, + { + name: 'schemas', + message: 'Comma-separated schemas (for DB mode)', + type: 'text', + required: false, + }, + { + name: 'orm', + message: 'Generate ORM client instead of React Query hooks?', + type: 'confirm', + required: false, + default: false, + useDefault: true, + }, + { + name: 'dryRun', + 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, + }, +]; type AnyResult = GenerateResult | GenerateOrmResult; type AnyTargetResult = GenerateTargetResult | GenerateOrmTargetResult; export default async ( - argv: Partial, - _prompter: Inquirerer, + argv: Partial>, + prompter: Inquirerer, _options: CLIOptions ) => { if (argv.help || argv.h) { @@ -66,37 +116,76 @@ export default async ( process.exit(0); } - const opts = parseArgs(argv); - const mode = determineMode(opts); + // Handle CLI aliases and defaults + const normalizedArgv = { + ...argv, + dryRun: argv['dry-run'] || argv.dryRun, + verbose: argv.verbose || argv.v, + config: argv.config || findConfigFile() || undefined, + }; + + const answers: any = await prompter.prompt(normalizedArgv, questions); + const endpoint = answers.endpoint as string | undefined; + const config = answers.config as string | undefined; + const target = answers.target as string | undefined; + const out = answers.out as string | undefined; + const auth = answers.auth as string | undefined; + const database = answers.database as string | undefined; + const schemasArg = answers.schemas as string | undefined; + const orm = answers.orm as boolean | undefined; + const dryRun = answers.dryRun as boolean | undefined; + const verbose = answers.verbose as boolean | undefined; + + // Parse schemas from comma-separated string + const schemas = schemasArg + ? String(schemasArg).split(',').map((s: string) => s.trim()).filter(Boolean) + : []; + + // Determine output directory + const outDir = (out as string) || 'codegen'; + let schemaPath: string | undefined; + + // Build schema from database if schemas are provided + if (schemas.length > 0) { + const db = (database as string) || getEnvOptions().pg.database; + const result = await buildSchemaFromDatabase({ + database: db, + schemas, + outDir, + }); + schemaPath = result.schemaPath; + } - if (mode.type === 'none') { + // Validate that we have a source + if (!endpoint && !schemaPath && !config) { console.error( 'Error: No source specified. Use --endpoint, --config, or --schemas for database mode.' ); process.exit(1); } - // Build schema from database if needed - const outDir = opts.output || 'codegen'; - const schemaPath = - mode.type === 'database' - ? await buildSchemaFromDatabase(mode.database, mode.schemas, outDir) - : undefined; - - const commandOptions = { - config: opts.config, - target: opts.target, - endpoint: mode.type === 'endpoint' ? mode.endpoint : undefined, - schema: schemaPath, - output: opts.config ? opts.output : outDir, - authorization: opts.auth, - verbose: opts.verbose, - dryRun: opts.dryRun, - }; - - const result = opts.orm - ? await generateOrm(commandOptions) - : await generateReactQuery(commandOptions); + // Call core generate function + const result = orm + ? await generateOrm({ + config, + target, + endpoint: endpoint || undefined, + schema: schemaPath, + output: config ? out : outDir, + authorization: auth, + verbose, + dryRun, + }) + : await generateReactQuery({ + config, + target, + endpoint: endpoint || undefined, + schema: schemaPath, + output: config ? out : outDir, + authorization: auth, + verbose, + dryRun, + }); printResult(result); @@ -105,38 +194,6 @@ export default async ( } }; -function parseArgs(argv: Partial): CodegenOptions { - const schemasArg = (argv.schemas as string) || ''; - return { - endpoint: (argv.endpoint as string) || undefined, - config: (argv.config as string) || findConfigFile() || undefined, - target: (argv.target as string) || undefined, - output: (argv.out as string) || undefined, - auth: (argv.auth as string) || undefined, - database: (argv.database as string) || undefined, - schemas: schemasArg - ? schemasArg.split(',').map((s) => s.trim()).filter(Boolean) - : undefined, - dryRun: !!(argv['dry-run'] || argv.dryRun), - verbose: !!(argv.verbose || argv.v), - orm: !!argv.orm, - }; -} - -function determineMode(opts: CodegenOptions): SourceMode { - if (opts.endpoint) { - return { type: 'endpoint', endpoint: opts.endpoint }; - } - if (opts.schemas?.length) { - const database = opts.database || getEnvOptions().pg.database; - return { type: 'database', database, schemas: opts.schemas }; - } - if (opts.config) { - return { type: 'config', configPath: opts.config }; - } - return { type: 'none' }; -} - function printTargetResult(target: AnyTargetResult): void { const status = target.success ? '[ok]' : 'x'; console.log(`\n${status} ${target.message}`); @@ -173,19 +230,3 @@ function printResult(result: AnyResult): void { result.filesWritten?.forEach((f) => console.log(f)); } } - -async function buildSchemaFromDatabase( - database: string, - schemas: string[], - outDir: string -): Promise { - await fs.promises.mkdir(outDir, { recursive: true }); - const sdl = await buildSchemaSDL({ - database, - schemas, - graphile: { pgSettings: async () => ({ role: 'administrator' }) }, - }); - const schemaPath = path.join(outDir, 'schema.graphql'); - await fs.promises.writeFile(schemaPath, sdl, 'utf-8'); - return schemaPath; -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a3d6154c6..f4b0d8766 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,6 +7,7 @@ settings: packageExtensionsChecksum: sha256-x8B4zkJ4KLRX+yspUWxuggXWlz6zrBLSIh72pNhpPiE= importers: + .: devDependencies: '@jest/test-sequencer': @@ -726,6 +727,9 @@ 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 @@ -1095,9 +1099,6 @@ importers: '@aws-sdk/client-s3': specifier: ^3.971.0 version: 3.971.0 - '@constructive-io/graphql-codegen': - specifier: workspace:* - version: link:../codegen/dist '@types/cors': specifier: ^2.8.17 version: 2.8.19 @@ -2371,17 +2372,12 @@ importers: publishDirectory: dist packages: + 12factor-env@0.1.0: - resolution: - { - integrity: sha512-4SaHhlxwOSizIK5P/14r7V7HxcHmip1fpX2HEToV7NpLWVDkI+eb+nskkq5F0XzC5bq2vhzpIAHQwZVeEibZLg==, - } + resolution: {integrity: sha512-4SaHhlxwOSizIK5P/14r7V7HxcHmip1fpX2HEToV7NpLWVDkI+eb+nskkq5F0XzC5bq2vhzpIAHQwZVeEibZLg==} '@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: @@ -2389,399 +2385,228 @@ packages: optional: true '@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: @@ -2789,11 +2614,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: @@ -2801,806 +2623,494 @@ 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.5': - resolution: - { - integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==, - } - engines: { node: '>=6.0.0' } + resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} + engines: {node: '>=6.0.0'} hasBin: true '@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/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==} '@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'} '@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.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.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.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.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.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.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.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.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.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.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.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.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.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.27.2': - resolution: - { - integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==} + engines: {node: '>=18'} cpu: [ppc64] 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.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.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.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.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.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.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.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.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.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.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.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} '@graphile-contrib/pg-many-to-many@1.0.2': - resolution: - { - integrity: sha512-ChSaSU7/n99Crdlink62cCGqlEYmjUJKizz2Nx0tdGgqSMkf6KTk00D3ILGybScywMcJGjJE2cc6FXYIHVlxCg==, - } + resolution: {integrity: sha512-ChSaSU7/n99Crdlink62cCGqlEYmjUJKizz2Nx0tdGgqSMkf6KTk00D3ILGybScywMcJGjJE2cc6FXYIHVlxCg==} '@graphile-contrib/pg-simplify-inflector@6.1.0': - resolution: - { - integrity: sha512-3eI2FP4ulu/fxwkJBNXhR6XEzqVz4wJWFr4LfeyUNNArUtLFx0DpP6YdcARCYgwLExFcIQNE8fnul3JKiciYIw==, - } + resolution: {integrity: sha512-3eI2FP4ulu/fxwkJBNXhR6XEzqVz4wJWFr4LfeyUNNArUtLFx0DpP6YdcARCYgwLExFcIQNE8fnul3JKiciYIw==} '@graphile/lru@4.11.0': - resolution: - { - integrity: sha512-Fakuk190EAKxWSa9YQyr/87g8mvAv8HBvk6yPCPuIoA3bYXF7n6kl0XSqKjSd5VfjEqhtnzQ6zJGzDf1Gv/tJg==, - } - engines: { node: '>=8.6' } + resolution: {integrity: sha512-Fakuk190EAKxWSa9YQyr/87g8mvAv8HBvk6yPCPuIoA3bYXF7n6kl0XSqKjSd5VfjEqhtnzQ6zJGzDf1Gv/tJg==} + engines: {node: '>=8.6'} '@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 '@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'} '@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: @@ -3608,10 +3118,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: @@ -3619,65 +3126,38 @@ packages: optional: true '@inquirerer/utils@3.2.0': - resolution: - { - integrity: sha512-poeZdoOH/iDV9dG/J0apH92T5VOGiAgIp8me1yTK9wpEI2qGENyXXBmiYgcE2s+XMHuDr19R9d1UXE9ptaVneA==, - } + resolution: {integrity: sha512-poeZdoOH/iDV9dG/J0apH92T5VOGiAgIp8me1yTK9wpEI2qGENyXXBmiYgcE2s+XMHuDr19R9d1UXE9ptaVneA==} '@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/cliui@8.0.2': - resolution: - { - integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} '@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: @@ -3685,67 +3165,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: @@ -3753,3124 +3206,1747 @@ 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/postmaster@0.1.4': - resolution: - { - integrity: sha512-TIWqKLd0Lb15lLdzMYeBk43VGOM4G3wm4cLdN9KHKYG/yho+gt9P1Zs23OewJfb0a0rKyhNWYewdHbEJ6Y/sYQ==, - } + resolution: {integrity: sha512-TIWqKLd0Lb15lLdzMYeBk43VGOM4G3wm4cLdN9KHKYG/yho+gt9P1Zs23OewJfb0a0rKyhNWYewdHbEJ6Y/sYQ==} '@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'} '@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] '@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] '@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] '@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] '@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==} '@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==} '@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==} '@tanstack/query-core@5.90.19': - resolution: - { - integrity: sha512-GLW5sjPVIvH491VV1ufddnfldyVB+teCnpPIvweEfkpRx7CfUmUGhoh9cdcUKBh/KwVxk22aNEDxeTsvmyB/WA==, - } + resolution: {integrity: sha512-GLW5sjPVIvH491VV1ufddnfldyVB+teCnpPIvweEfkpRx7CfUmUGhoh9cdcUKBh/KwVxk22aNEDxeTsvmyB/WA==} '@tanstack/react-query@5.90.19': - resolution: - { - integrity: sha512-qTZRZ4QyTzQc+M0IzrbKHxSeISUmRB3RPGmao5bT+sI6ayxSRhn0FXEnT5Hg3as8SBFcRosrXXRFB+yAcxVxJQ==, - } + resolution: {integrity: sha512-qTZRZ4QyTzQc+M0IzrbKHxSeISUmRB3RPGmao5bT+sI6ayxSRhn0FXEnT5Hg3as8SBFcRosrXXRFB+yAcxVxJQ==} peerDependencies: react: ^18 || ^19 '@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==} '@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/accept-language-parser@1.5.8': - resolution: - { - integrity: sha512-6+dKdh9q/I8xDBnKQKddCBKaWBWLmJ97HTiSbAXVpL7LEgDfOkKF98UVCaZ5KJrtdN5Wa5ndXUiqD3XR9XGqWQ==, - } + resolution: {integrity: sha512-6+dKdh9q/I8xDBnKQKddCBKaWBWLmJ97HTiSbAXVpL7LEgDfOkKF98UVCaZ5KJrtdN5Wa5ndXUiqD3XR9XGqWQ==} '@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/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/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/json5@0.0.30': - resolution: - { - integrity: sha512-sqm9g7mHlPY/43fcSNrCYfOeX9zkTTK+euO5E6+CVijSMm5tTjkVdwdqRkY3ljjIAf8679vps5jKUoJBCLsMDA==, - } + resolution: {integrity: sha512-sqm9g7mHlPY/43fcSNrCYfOeX9zkTTK+euO5E6+CVijSMm5tTjkVdwdqRkY3ljjIAf8679vps5jKUoJBCLsMDA==} '@types/jsonwebtoken@9.0.10': - resolution: - { - integrity: sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==, - } + resolution: {integrity: sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==} '@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/ms@2.1.0': - resolution: - { - integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==, - } + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} '@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/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/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@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/ws@7.4.7': - resolution: - { - integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==, - } + resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==} '@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] '@unrs/resolver-binding-linux-arm64-musl@1.11.1': - resolution: - { - integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==, - } + resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==} cpu: [arm64] os: [linux] '@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] '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': - resolution: - { - integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==, - } + resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==} cpu: [riscv64] os: [linux] '@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] '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': - resolution: - { - integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==, - } + resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==} cpu: [s390x] os: [linux] '@unrs/resolver-binding-linux-x64-gnu@1.11.1': - resolution: - { - integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==, - } + resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==} cpu: [x64] os: [linux] '@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] '@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] '@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} accept-language-parser@1.5.0: - resolution: - { - integrity: sha512-QhyTbMLYo0BBGg1aWbeMG4ekWtds/31BrEU+DONOg/7ax23vxpL03Pb7/zBmha2v7vdD3AyzZVWBVGEZxKOXWw==, - } + resolution: {integrity: sha512-QhyTbMLYo0BBGg1aWbeMG4ekWtds/31BrEU+DONOg/7ax23vxpL03Pb7/zBmha2v7vdD3AyzZVWBVGEZxKOXWw==} 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@4.2.1: - resolution: - { - integrity: sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==, - } - engines: { node: '>= 4.0.0' } + resolution: {integrity: sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==} + engines: {node: '>= 4.0.0'} agent-base@4.3.0: - resolution: - { - integrity: sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==, - } - engines: { node: '>= 4.0.0' } + resolution: {integrity: sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==} + engines: {node: '>= 4.0.0'} 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@3.2.1: - resolution: - { - integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} 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==} 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-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==} asn1@0.2.6: - resolution: - { - integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==, - } + resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} assert-plus@1.0.0: - resolution: - { - integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==, - } - engines: { node: '>=0.8' } + resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} + engines: {node: '>=0.8'} ast-types@0.14.2: - resolution: - { - integrity: sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==} + engines: {node: '>=4'} async-retry@1.3.1: - resolution: - { - integrity: sha512-aiieFW/7h3hY0Bq5d+ktDBejxuwR78vRu9hDUdR8rNhSaQ29VzPL4AoIRG7D/c7tdenwOcKvgPM6tIxB3cB6HA==, - } + resolution: {integrity: sha512-aiieFW/7h3hY0Bq5d+ktDBejxuwR78vRu9hDUdR8rNhSaQ29VzPL4AoIRG7D/c7tdenwOcKvgPM6tIxB3cB6HA==} async@2.6.4: - resolution: - { - integrity: sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==, - } + resolution: {integrity: sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==} 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 aws-sign2@0.7.0: - resolution: - { - integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==, - } + resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==} aws4@1.13.2: - resolution: - { - integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==, - } + resolution: {integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==} 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==} backo2@1.0.2: - resolution: - { - integrity: sha512-zj6Z6M7Eq+PBZ7PQxl5NT665MvJdAkzp0f60nAJ+sLaSCBPMwVak5ZegFbgVCzFcCJTKFoMizvM5Ld7+JrRJHA==, - } + resolution: {integrity: sha512-zj6Z6M7Eq+PBZ7PQxl5NT665MvJdAkzp0f60nAJ+sLaSCBPMwVak5ZegFbgVCzFcCJTKFoMizvM5Ld7+JrRJHA==} balanced-match@1.0.2: - resolution: - { - integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==, - } + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 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 bcrypt-pbkdf@1.0.2: - resolution: - { - integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==, - } + resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} 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@1.19.0: - resolution: - { - integrity: sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==, - } - engines: { node: '>= 0.8' } + resolution: {integrity: sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==} + engines: {node: '>= 0.8'} 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.0: - resolution: - { - integrity: sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==, - } - engines: { node: '>= 0.8' } + resolution: {integrity: sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==} + engines: {node: '>= 0.8'} 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-bind@1.0.8: - resolution: - { - integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + 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'} caseless@0.12.0: - resolution: - { - integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==, - } + resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} chalk@2.4.2: - resolution: - { - integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} 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'} 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'} 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@1.9.3: - resolution: - { - integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==, - } + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} 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.3: - resolution: - { - integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==, - } + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} 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@2.20.3: - resolution: - { - integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==, - } + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} 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'} 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} 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.2: - resolution: - { - integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==, - } + resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} 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'} 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: @@ -6878,140 +4954,77 @@ 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@2.18.0: - resolution: - { - integrity: sha512-s4odpheTyydAbTBQepsqd2rNWGa2iV3cyo8g7zbI2QQYGLVsfbhmwukayS1XHppe02Oy1fg7mg6xoaraVJeEcg==, - } - engines: { node: '>=0.8' } + resolution: {integrity: sha512-s4odpheTyydAbTBQepsqd2rNWGa2iV3cyo8g7zbI2QQYGLVsfbhmwukayS1XHppe02Oy1fg7mg6xoaraVJeEcg==} + engines: {node: '>=0.8'} 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 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'} dashdash@1.14.1: - resolution: - { - integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==, - } - engines: { node: '>=0.10' } + resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==} + engines: {node: '>=0.10'} data-uri-to-buffer@1.2.0: - resolution: - { - integrity: sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==, - } + resolution: {integrity: sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==} dataloader@2.2.3: - resolution: - { - integrity: sha512-y2krtASINtPFS1rSDjacrFgn1dcUuoREVabwlOGOe4SdxenREqwjwjElAdwvbGM7kgZz9a3KVicWR7vcz8rnzA==, - } + resolution: {integrity: sha512-y2krtASINtPFS1rSDjacrFgn1dcUuoREVabwlOGOe4SdxenREqwjwjElAdwvbGM7kgZz9a3KVicWR7vcz8rnzA==} dateformat@3.0.3: - resolution: - { - integrity: sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==, - } + resolution: {integrity: sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==} debug@2.6.9: - resolution: - { - integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==, - } + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: supports-color: '*' peerDependenciesMeta: @@ -7019,10 +5032,7 @@ packages: optional: true debug@3.1.0: - resolution: - { - integrity: sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==, - } + resolution: {integrity: sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==} peerDependencies: supports-color: '*' peerDependenciesMeta: @@ -7030,10 +5040,7 @@ packages: optional: true debug@3.2.7: - resolution: - { - integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==, - } + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: supports-color: '*' peerDependenciesMeta: @@ -7041,11 +5048,8 @@ packages: optional: true 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: @@ -7053,31 +5057,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: @@ -7085,10 +5077,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: @@ -7096,251 +5085,137 @@ 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-data-property@1.1.4: - resolution: - { - integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} define-lazy-prop@2.0.0: - resolution: - { - integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} + engines: {node: '>=8'} define-properties@1.2.1: - resolution: - { - integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} degenerator@1.0.4: - resolution: - { - integrity: sha512-EMAC+riLSC64jKfOs1jp8J7M4ZXstUUwTdwFBEv6HOzL/Ae+eAzMKEK0nJnpof2fnw9IOjmE6u6qXFejVyk8AA==, - } + resolution: {integrity: sha512-EMAC+riLSC64jKfOs1jp8J7M4ZXstUUwTdwFBEv6HOzL/Ae+eAzMKEK0nJnpof2fnw9IOjmE6u6qXFejVyk8AA==} 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@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'} 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'} dotenv@8.6.0: - resolution: - { - integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} + engines: {node: '>=10'} 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' @@ -7432,295 +5307,166 @@ 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==} ecc-jsbn@0.1.2: - resolution: - { - integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==, - } + resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==} 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@6.0.2: - resolution: - { - integrity: sha512-ChJb9a5rjwZ/NkcXfBrzEl5cFZaGLg38N7MlWJkv5qsmSypX2WJe28LkoAWcklC60nKZXYKRlBbsjuJSjYw0Xg==, - } - engines: { node: '>=8.12' } + resolution: {integrity: sha512-ChJb9a5rjwZ/NkcXfBrzEl5cFZaGLg38N7MlWJkv5qsmSypX2WJe28LkoAWcklC60nKZXYKRlBbsjuJSjYw0Xg==} + engines: {node: '>=8.12'} 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'} es6-promise@4.2.8: - resolution: - { - integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==, - } + resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} es6-promisify@5.0.0: - resolution: - { - integrity: sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==, - } + resolution: {integrity: sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==} 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'} escodegen@1.14.3: - resolution: - { - integrity: sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==, - } - engines: { node: '>=4.0' } + resolution: {integrity: sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==} + engines: {node: '>=4.0'} hasBin: true 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 @@ -7729,32 +5475,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: '*' @@ -7763,205 +5497,115 @@ 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@3.1.3: - resolution: - { - integrity: sha512-AWwVMNxwhN8+NIPQzAQZCm7RkLC4RbM3B1OobMuyp3i+w73X57KCKaVIxaRZb+DYCojq7rspo+fmuQfAboyhFg==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-AWwVMNxwhN8+NIPQzAQZCm7RkLC4RbM3B1OobMuyp3i+w73X57KCKaVIxaRZb+DYCojq7rspo+fmuQfAboyhFg==} + engines: {node: '>=4'} hasBin: true 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@4.3.0: - resolution: - { - integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==, - } - engines: { node: '>=4.0' } + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + 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@3.1.2: - resolution: - { - integrity: sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==, - } + resolution: {integrity: sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==} eventemitter3@4.0.7: - resolution: - { - integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==, - } + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} 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'} extend@3.0.2: - resolution: - { - integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==, - } + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} extsprintf@1.3.0: - resolution: - { - integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==, - } - engines: { '0': node >=0.6.0 } + resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} + engines: {'0': node >=0.6.0} 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: @@ -7969,105 +5613,60 @@ 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'} file-uri-to-path@1.0.0: - resolution: - { - integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==, - } + resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} 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@1.3.2: - resolution: - { - integrity: sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==, - } - engines: { node: '>= 0.8' } + resolution: {integrity: sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==} + engines: {node: '>= 0.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-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: @@ -8075,1124 +5674,638 @@ packages: optional: true foreground-child@3.3.1: - resolution: - { - integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==, - } - engines: { node: '>=14' } + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} forever-agent@0.6.1: - resolution: - { - integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==, - } + resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} form-data@2.3.3: - resolution: - { - integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==, - } - engines: { node: '>= 0.12' } + resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==} + engines: {node: '>= 0.12'} form-data@2.5.5: - resolution: - { - integrity: sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A==, - } - engines: { node: '>= 0.12' } + resolution: {integrity: sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A==} + engines: {node: '>= 0.12'} 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'} 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] ftp@0.3.10: - resolution: - { - integrity: sha512-faFVML1aBx2UoDStmLwv2Wptt4vw5x03xxX172nhA5Y5HBshW5JweqQ2W4xL4dezQTG8inJsuYcpPHHU3X5OTQ==, - } - engines: { node: '>=0.8.0' } + resolution: {integrity: sha512-faFVML1aBx2UoDStmLwv2Wptt4vw5x03xxX172nhA5Y5HBshW5JweqQ2W4xL4dezQTG8inJsuYcpPHHU3X5OTQ==} + engines: {node: '>=0.8.0'} 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-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-uri@2.0.4: - resolution: - { - integrity: sha512-v7LT/s8kVjs+Tx0ykk1I+H/rbpzkHvuIq87LmeXptcf5sNWm9uQiwjNAt94SJPA1zOlCntmnOlJvVWKmzsxG8Q==, - } + resolution: {integrity: sha512-v7LT/s8kVjs+Tx0ykk1I+H/rbpzkHvuIq87LmeXptcf5sNWm9uQiwjNAt94SJPA1zOlCntmnOlJvVWKmzsxG8Q==} getpass@0.1.7: - resolution: - { - integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==, - } + resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} 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==} 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} 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: Glob versions prior to v9 are no longer supported 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'} 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==} graphile-build-pg@4.14.1: - resolution: - { - integrity: sha512-7DIVbcfMU5lXNkGnAeobqm29AvjFYw4/xOlKNQk3NE/mfFDcyPuXYboypmtxzglg1hGXkyONLYnas9vzL+SunQ==, - } - engines: { node: '>=8.6' } + resolution: {integrity: sha512-7DIVbcfMU5lXNkGnAeobqm29AvjFYw4/xOlKNQk3NE/mfFDcyPuXYboypmtxzglg1hGXkyONLYnas9vzL+SunQ==} + engines: {node: '>=8.6'} peerDependencies: pg: '>=6.1.0 <9' graphile-build@4.14.1: - resolution: - { - integrity: sha512-l/ylyMK0vl5LCOScpTsTedNZUqwBgafXS7RPDW1YiQofeioVtTDMdV9k3zRkXdMKtKqJsvOBvjXn64WGLaLInQ==, - } - engines: { node: '>=8.6' } + resolution: {integrity: sha512-l/ylyMK0vl5LCOScpTsTedNZUqwBgafXS7RPDW1YiQofeioVtTDMdV9k3zRkXdMKtKqJsvOBvjXn64WGLaLInQ==} + engines: {node: '>=8.6'} peerDependencies: graphql: '>=0.9 <0.14 || ^14.0.2 || ^15.4.0' graphile-utils@4.14.1: - resolution: - { - integrity: sha512-FgviZVKO3NS8va2inqUVQQFSnFLEG7FiH64BqSVRHSF8jwSXKcpx5NiRibErNvvIdnuzgVAXQ3W4jcXvMSx0Tg==, - } - engines: { node: '>=8.6' } + resolution: {integrity: sha512-FgviZVKO3NS8va2inqUVQQFSnFLEG7FiH64BqSVRHSF8jwSXKcpx5NiRibErNvvIdnuzgVAXQ3W4jcXvMSx0Tg==} + engines: {node: '>=8.6'} peerDependencies: graphile-build: ^4.5.0 graphile-build-pg: ^4.5.0 graphql-parse-resolve-info@4.14.1: - resolution: - { - integrity: sha512-WKHukfEuZamP1ZONR84b8iT+4sJgEhtXMDArm1jpXEsU2vTb5EgkCZ4Obfl+v09oNTKXm0CJjPfBUZ5jcJ2Ykg==, - } - engines: { node: '>=8.6' } + resolution: {integrity: sha512-WKHukfEuZamP1ZONR84b8iT+4sJgEhtXMDArm1jpXEsU2vTb5EgkCZ4Obfl+v09oNTKXm0CJjPfBUZ5jcJ2Ykg==} + engines: {node: '>=8.6'} peerDependencies: graphql: '>=0.9 <0.14 || ^14.0.2 || ^15.4.0 || ^16.3.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@5.16.2: - resolution: - { - integrity: sha512-E1uccsZxt/96jH/OwmLPuXMACILs76pKF2i3W861LpKBCYtGIyPQGtWLuBLkND4ox1KHns70e83PS4te50nvPQ==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-E1uccsZxt/96jH/OwmLPuXMACILs76pKF2i3W861LpKBCYtGIyPQGtWLuBLkND4ox1KHns70e83PS4te50nvPQ==} + engines: {node: '>=10'} peerDependencies: graphql: '>=0.11 <=16' 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'} 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 har-schema@2.0.0: - resolution: - { - integrity: sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==} + engines: {node: '>=4'} har-validator@5.1.5: - resolution: - { - integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==} + engines: {node: '>=6'} deprecated: this library is no longer supported 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-property-descriptors@1.0.2: - resolution: - { - integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==, - } + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} 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.7.2: - resolution: - { - integrity: sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==, - } - engines: { node: '>= 0.6' } + resolution: {integrity: sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==} + engines: {node: '>= 0.6'} 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@2.1.0: - resolution: - { - integrity: sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==, - } - engines: { node: '>= 4.5.0' } + resolution: {integrity: sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==} + engines: {node: '>= 4.5.0'} 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-signature@1.2.0: - resolution: - { - integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==, - } - engines: { node: '>=0.8', npm: '>=1.3.7' } + resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==} + engines: {node: '>=0.8', npm: '>=1.3.7'} https-proxy-agent@3.0.1: - resolution: - { - integrity: sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==, - } - engines: { node: '>= 4.5.0' } + resolution: {integrity: sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==} + engines: {node: '>= 4.5.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.4.24: - resolution: - { - integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.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@1.12.0: - resolution: - { - integrity: sha512-lRy4DxuIFWXlJU7ed8UiTJOSTqStqYdEb4CEbtXfNbkdj3nH1L+reUWiE10VWcJS2yR7tge8Z74pJjtBjNwj0w==, - } - engines: { '0': node >= 0.4.0 } + resolution: {integrity: sha512-lRy4DxuIFWXlJU7ed8UiTJOSTqStqYdEb4CEbtXfNbkdj3nH1L+reUWiE10VWcJS2yR7tge8Z74pJjtBjNwj0w==} + engines: {'0': node >= 0.4.0} inflection@1.3.8: - resolution: - { - integrity: sha512-xRvG6XhAkbneGO5BXP0uKyGkzmZ2bBbrFkx4ZVNx2TmsECbiq/pJapbbx/NECh+E85IfZwW5+IeVNJfkQgavag==, - } - engines: { '0': node >= 0.4.0 } + resolution: {integrity: sha512-xRvG6XhAkbneGO5BXP0uKyGkzmZ2bBbrFkx4ZVNx2TmsECbiq/pJapbbx/NECh+E85IfZwW5+IeVNJfkQgavag==} + engines: {'0': node >= 0.4.0} 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.0: - resolution: - { - integrity: sha512-YZRDExCvyQmOYld/oI62icM+V9d7wagwWmJ2+xgV0eAN2fkHR2PoHYDO/tW7BVwhi8viECFJiwdv8dPBSMDzHw==, - } + resolution: {integrity: sha512-YZRDExCvyQmOYld/oI62icM+V9d7wagwWmJ2+xgV0eAN2fkHR2PoHYDO/tW7BVwhi8viECFJiwdv8dPBSMDzHw==} 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.3: - resolution: - { - integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==, - } + resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} 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==} ip-address@10.1.0: - resolution: - { - integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==, - } - engines: { node: '>= 12' } + resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} + engines: {node: '>= 12'} ip@1.1.5: - resolution: - { - integrity: sha512-rBtCAQAJm8A110nbwn6YdveUnuZH3WrC36IwkRXxDnq53JvXA2NVQvB7IHyKomxK1MJ4VDNw3UtFDdXQ+AvLYA==, - } + resolution: {integrity: sha512-rBtCAQAJm8A110nbwn6YdveUnuZH3WrC36IwkRXxDnq53JvXA2NVQvB7IHyKomxK1MJ4VDNw3UtFDdXQ+AvLYA==} ip@1.1.9: - resolution: - { - integrity: sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==, - } + resolution: {integrity: sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==} 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-nan@1.3.2: - resolution: - { - integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} + engines: {node: '>= 0.4'} 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-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@1.1.0: - resolution: - { - integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} + engines: {node: '>=0.10.0'} 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-typedarray@1.0.0: - resolution: - { - integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==, - } + resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} 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'} isstream@0.1.2: - resolution: - { - integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==, - } + resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} 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.1.1: - resolution: - { - integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==} + 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 @@ -9201,11 +6314,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' @@ -9219,95 +6329,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: @@ -9315,81 +6386,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 @@ -9398,1137 +6436,618 @@ 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 jsbn@0.1.1: - resolution: - { - integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==, - } + resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} 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-schema@0.4.0: - resolution: - { - integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==, - } + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} 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==} 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'} jsprim@1.4.2: - resolution: - { - integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==, - } - engines: { node: '>=0.6.0' } + resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==} + engines: {node: '>=0.6.0'} 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==} keyv@4.5.4: - resolution: - { - integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==, - } + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} 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==} 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.3.0: - resolution: - { - integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==, - } - engines: { node: '>= 0.8.0' } + resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==} + engines: {node: '>= 0.8.0'} 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} 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.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==} 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@4.1.5: - resolution: - { - integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==, - } + resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} 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'} lz-string@1.5.0: - resolution: - { - integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==, - } + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true mailgun-js@0.22.0: - resolution: - { - integrity: sha512-a2alg5nuTZA9Psa1pSEIEsbxr1Zrmqx4VkgGCQ30xVh0kIH7Bu57AYILo+0v8QLSdXtCyLaS+KVmdCrQo0uWFA==, - } - engines: { node: '>=6.0.0' } + resolution: {integrity: sha512-a2alg5nuTZA9Psa1pSEIEsbxr1Zrmqx4VkgGCQ30xVh0kIH7Bu57AYILo+0v8QLSdXtCyLaS+KVmdCrQo0uWFA==} + engines: {node: '>=6.0.0'} deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. makage@0.1.10: - resolution: - { - integrity: sha512-IQKuRbHOrDgVNlydle+XRO5iMyaozBq4Bb9vhEzwxtvzyk08JkQo5qpfFRep0dSum53gECdX2gBoTmkWDHIfJA==, - } + resolution: {integrity: sha512-IQKuRbHOrDgVNlydle+XRO5iMyaozBq4Bb9vhEzwxtvzyk08JkQo5qpfFRep0dSum53gECdX2gBoTmkWDHIfJA==} 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'} 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'} meant@1.0.3: - resolution: - { - integrity: sha512-88ZRGcNxAq4EH38cQ4D85PM57pikCwS8Z99EWHODxN7KBY+UuPiqzRTtZzS8KTXO/ywSWbdjjJST2Hly/EQxLw==, - } + resolution: {integrity: sha512-88ZRGcNxAq4EH38cQ4D85PM57pikCwS8Z99EWHODxN7KBY+UuPiqzRTtZzS8KTXO/ywSWbdjjJST2Hly/EQxLw==} media-typer@0.3.0: - resolution: - { - integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==, - } - engines: { node: '>= 0.6' } + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} 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'} 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@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 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'} moment-timezone@0.5.48: - resolution: - { - integrity: sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==, - } + resolution: {integrity: sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==} moment@2.30.1: - resolution: - { - integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==, - } + resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} ms@2.0.0: - resolution: - { - integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==, - } + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} 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==} 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==} netmask@1.0.6: - resolution: - { - integrity: sha512-3DWDqAtIiPSkBXZyYEjwebfK56nrlQfRGt642fu8RPaL+ePu750+HCMHxjJCG3iEHq/0aeMvX6KIzlv7nuhfrA==, - } - engines: { node: '>= 0.4.0' } + resolution: {integrity: sha512-3DWDqAtIiPSkBXZyYEjwebfK56nrlQfRGt642fu8RPaL+ePu750+HCMHxjJCG3iEHq/0aeMvX6KIzlv7nuhfrA==} + engines: {node: '>= 0.4.0'} 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: @@ -10536,11 +7055,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: @@ -10548,173 +7064,98 @@ 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@1.3.2: - resolution: - { - integrity: sha512-GIND2pHMHiReSZSvS6dpZcDH7pGPGFfWBIEud6S00Q8zEIzAs9ommdyRK1ZbQt8y1LyZsJYZgPnyi7gpU2lcdw==, - } + resolution: {integrity: sha512-GIND2pHMHiReSZSvS6dpZcDH7pGPGFfWBIEud6S00Q8zEIzAs9ommdyRK1ZbQt8y1LyZsJYZgPnyi7gpU2lcdw==} 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==} 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 @@ -10726,487 +7167,271 @@ packages: optional: true oauth-sign@0.9.0: - resolution: - { - integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==, - } + resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==} 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-keys@1.1.1: - resolution: - { - integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + 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.3.0: - resolution: - { - integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==, - } - engines: { node: '>= 0.8' } + resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} + engines: {node: '>= 0.8'} 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.8.3: - resolution: - { - integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==, - } - engines: { node: '>= 0.8.0' } + resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} + engines: {node: '>= 0.8.0'} 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'} 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'} pac-proxy-agent@3.0.1: - resolution: - { - integrity: sha512-44DUg21G/liUZ48dJpUSjZnFfZro/0K5JTyFYLBcmh9+T6Ooi4/i4efwUiEy0+4oQusCBqWdhv16XohIj1GqnQ==, - } + resolution: {integrity: sha512-44DUg21G/liUZ48dJpUSjZnFfZro/0K5JTyFYLBcmh9+T6Ooi4/i4efwUiEy0+4oQusCBqWdhv16XohIj1GqnQ==} pac-resolver@3.0.0: - resolution: - { - integrity: sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==, - } + resolution: {integrity: sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==} package-json-from-dist@1.0.1: - resolution: - { - integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==, - } + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} 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-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-proxy@1.0.0: - resolution: - { - integrity: sha512-p9IuY9FRY1nU59RDW+tnLL6qMxmBnY03WGYxzy1FcqE5OMO5ggz7ahmOBH0JBS+9f95Yc7V5TZ+kHpTeFWaLQA==, - } + resolution: {integrity: sha512-p9IuY9FRY1nU59RDW+tnLL6qMxmBnY03WGYxzy1FcqE5OMO5ggz7ahmOBH0JBS+9f95Yc7V5TZ+kHpTeFWaLQA==} 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'} performance-now@2.1.0: - resolution: - { - integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==, - } + resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} 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-connection-string@2.9.1: - resolution: - { - integrity: sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w==, - } + resolution: {integrity: sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w==} 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-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@4.14.1: - resolution: - { - integrity: sha512-DvL0K9Pqz47EFq+BaQlGpzsXJnArKoAbxBxtHLy2/p3ey1X7ZwUF79UwFoDSTxQQCIbR4Z5D8CBI0nPfpw9Tmw==, - } - engines: { node: '>=8.6' } + resolution: {integrity: sha512-DvL0K9Pqz47EFq+BaQlGpzsXJnArKoAbxBxtHLy2/p3ey1X7ZwUF79UwFoDSTxQQCIbR4Z5D8CBI0nPfpw9Tmw==} + engines: {node: '>=8.6'} peerDependencies: pg: '>=6.1.0 <9' pg-tsquery@8.4.2: - resolution: - { - integrity: sha512-waJSlBIKE+shDhuDpuQglTH6dG5zakDhnrnxu8XB8V5c7yoDSuy4pOxY6t2dyoxTjaKMcMmlByJN7n9jx9eqMA==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-waJSlBIKE+shDhuDpuQglTH6dG5zakDhnrnxu8XB8V5c7yoDSuy4pOxY6t2dyoxTjaKMcMmlByJN7n9jx9eqMA==} + engines: {node: '>=10'} 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: @@ -11214,247 +7439,142 @@ 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@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'} 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'} 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==} postgraphile-core@4.14.1: - resolution: - { - integrity: sha512-3U6DAoGUmOikl9dVQhSJcw4cLeG0vQQnvEFw7MR0rvn125c1xdv6UBvamvX0pOzSfz5oBrFRQkZ2LvclAXKyBQ==, - } - engines: { node: '>=8.6' } + resolution: {integrity: sha512-3U6DAoGUmOikl9dVQhSJcw4cLeG0vQQnvEFw7MR0rvn125c1xdv6UBvamvX0pOzSfz5oBrFRQkZ2LvclAXKyBQ==} + engines: {node: '>=8.6'} peerDependencies: graphql: '>=0.9 <0.14 || ^14.0.2 || ^15.4.0' pg: '>=6.1.0 <9' postgraphile@4.14.1: - resolution: - { - integrity: sha512-4Rz//TtnjyZk6CbrcypWJNFRwXupHK+bHvaYaX2RrtxMJ2lTaoMDYOdEFESdo/POie3CAEbsC8ZBqb9eR/EyVw==, - } - engines: { node: '>=8.6' } + resolution: {integrity: sha512-4Rz//TtnjyZk6CbrcypWJNFRwXupHK+bHvaYaX2RrtxMJ2lTaoMDYOdEFESdo/POie3CAEbsC8ZBqb9eR/EyVw==} + engines: {node: '>=8.6'} hasBin: 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-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'} prelude-ls@1.1.2: - resolution: - { - integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==, - } - engines: { node: '>= 0.8.0' } + resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} + engines: {node: '>= 0.8.0'} 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: @@ -11462,196 +7582,109 @@ 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'} promisify-call@2.0.4: - resolution: - { - integrity: sha512-ZX68J1+1Pe0I8NC0P6Ji3fDDcJceVfpoygfDLgdb1fp5vW9IRlwSpDaxe1T5HgwchyHV2DsL/pWzWikUiWEbLQ==, - } - engines: { node: '>=4.0' } + resolution: {integrity: sha512-ZX68J1+1Pe0I8NC0P6Ji3fDDcJceVfpoygfDLgdb1fp5vW9IRlwSpDaxe1T5HgwchyHV2DsL/pWzWikUiWEbLQ==} + engines: {node: '>=4.0'} 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-agent@3.1.1: - resolution: - { - integrity: sha512-WudaR0eTsDx33O3EJE16PjBRZWcX8GqCEeERw1W3hZJgH/F2a46g7jty6UGty6NeJ4CKQy8ds2CJPMiyeqaTvw==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-WudaR0eTsDx33O3EJE16PjBRZWcX8GqCEeERw1W3hZJgH/F2a46g7jty6UGty6NeJ4CKQy8ds2CJPMiyeqaTvw==} + engines: {node: '>=6'} proxy-from-env@1.1.0: - resolution: - { - integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==, - } + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} pseudomap@1.0.2: - resolution: - { - integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==, - } + resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} psl@1.15.0: - resolution: - { - integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==, - } + resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} 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'} qs@6.5.3: - resolution: - { - integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==, - } - engines: { node: '>=0.6' } + resolution: {integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==} + engines: {node: '>=0.6'} qs@6.7.0: - resolution: - { - integrity: sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==, - } - engines: { node: '>=0.6' } + resolution: {integrity: sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==} + 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@2.4.0: - resolution: - { - integrity: sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==, - } - engines: { node: '>= 0.8' } + resolution: {integrity: sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==} + engines: {node: '>= 0.8'} raw-body@2.5.3: - resolution: - { - integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==, - } - engines: { node: '>= 0.8' } + resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==} + engines: {node: '>= 0.8'} raw-body@3.0.2: - resolution: - { - integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==, - } - engines: { node: '>= 0.10' } + resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==} + engines: {node: '>= 0.10'} 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-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-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: '*' @@ -11663,965 +7696,542 @@ packages: optional: true 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@1.1.14: - resolution: - { - integrity: sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==, - } + resolution: {integrity: sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==} 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==} request@2.88.2: - resolution: - { - integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==, - } - engines: { node: '>= 6' } + resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==} + engines: {node: '>= 6'} deprecated: request has been deprecated, see https://github.com/request/request/issues/3142 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==} 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 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==} 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 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-function-length@1.2.2: - resolution: - { - integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} setprototypeof@1.1.1: - resolution: - { - integrity: sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==, - } + resolution: {integrity: sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==} 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@4.0.2: - resolution: - { - integrity: sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==, - } - engines: { node: '>= 6' } + resolution: {integrity: sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==} + engines: {node: '>= 6'} 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.3.3: - resolution: - { - integrity: sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==, - } - engines: { node: '>= 6.0.0', npm: '>= 3.0.0' } + resolution: {integrity: sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} 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-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'} 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==} sshpk@1.18.0: - resolution: - { - integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==} + engines: {node: '>=0.10.0'} hasBin: true 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==} subscriptions-transport-ws@0.9.19: - resolution: - { - integrity: sha512-dxdemxFFB0ppCLg10FTtRqH/31FNRL1y1BQv8209MK5I4CwALb7iihQg+7p65lFcIl8MHatINWBLOqpgU4Kyyw==, - } + resolution: {integrity: sha512-dxdemxFFB0ppCLg10FTtRqH/31FNRL1y1BQv8209MK5I4CwALb7iihQg+7p65lFcIl8MHatINWBLOqpgU4Kyyw==} deprecated: The `subscriptions-transport-ws` package is no longer maintained. We recommend you use `graphql-ws` instead. For help migrating Apollo software to `graphql-ws`, see https://www.apollographql.com/docs/apollo-server/data/subscriptions/#switching-from-subscriptions-transport-ws For general help using `graphql-ws`, see https://github.com/enisdenjo/graphql-ws/blob/master/README.md peerDependencies: graphql: '>=0.10.0' 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'} symbol-observable@1.2.0: - resolution: - { - integrity: sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==} + engines: {node: '>=0.10.0'} 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} 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 exhorbitant 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==} thunkify@2.1.2: - resolution: - { - integrity: sha512-w9foI80XcGImrhMQ19pxunaEC5Rp2uzxZZg4XBAFRfiLOplk3F0l7wo+bO16vC2/nlQfR/mXZxcduo0MF2GWLg==, - } + resolution: {integrity: sha512-w9foI80XcGImrhMQ19pxunaEC5Rp2uzxZZg4XBAFRfiLOplk3F0l7wo+bO16vC2/nlQfR/mXZxcduo0MF2GWLg==} 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'} 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.0: - resolution: - { - integrity: sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==, - } - engines: { node: '>=0.6' } + resolution: {integrity: sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==} + engines: {node: '>=0.6'} 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 tough-cookie@2.5.0: - resolution: - { - integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==, - } - engines: { node: '>=0.8' } + resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==} + engines: {node: '>=0.8'} tr46@0.0.3: - resolution: - { - integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==, - } + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} 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-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' @@ -12647,10 +8257,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' @@ -12664,506 +8271,284 @@ 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==} tsscmp@1.0.6: - resolution: - { - integrity: sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==, - } - engines: { node: '>=0.6.x' } + resolution: {integrity: sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==} + engines: {node: '>=0.6.x'} 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} tunnel-agent@0.6.0: - resolution: - { - integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==, - } + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} tweetnacl@0.14.5: - resolution: - { - integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==, - } + resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} type-check@0.3.2: - resolution: - { - integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==, - } - engines: { node: '>= 0.8.0' } + resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} + engines: {node: '>= 0.8.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@1.6.18: - resolution: - { - integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==, - } - engines: { node: '>= 0.6' } + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} 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 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'} 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==} 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@3.4.0: - resolution: - { - integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==, - } + resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. 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} validator@13.15.26: - resolution: - { - integrity: sha512-spH26xU080ydGggxRyR1Yhcbgx+j3y5jbNXk/8L+iRvdIEQ4uTRH2Sgf2dokud6Q4oAtsbNvJ1Ft+9xmm6IZcA==, - } - engines: { node: '>= 0.10' } + resolution: {integrity: sha512-spH26xU080ydGggxRyR1Yhcbgx+j3y5jbNXk/8L+iRvdIEQ4uTRH2Sgf2dokud6Q4oAtsbNvJ1Ft+9xmm6IZcA==} + engines: {node: '>= 0.10'} 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'} verror@1.10.0: - resolution: - { - integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==, - } - engines: { '0': node >=0.6.0 } + resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} + engines: {'0': node >=0.6.0} 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==} with-callback@1.0.2: - resolution: - { - integrity: sha512-zaUhn7OWgikdqWlPYpZ4rTX/6IAV0czMVyd+C6QLVrif2tATF28CYUnHBmHs2a5EaZo7bB1+plBUPHto+HW8uA==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-zaUhn7OWgikdqWlPYpZ4rTX/6IAV0czMVyd+C6QLVrif2tATF28CYUnHBmHs2a5EaZo7bB1+plBUPHto+HW8uA==} + engines: {node: '>=4'} 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@7.5.10: - resolution: - { - integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==, - } - engines: { node: '>=8.3.0' } + resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} + engines: {node: '>=8.3.0'} peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ^5.0.2 @@ -13174,120 +8559,70 @@ packages: optional: true xregexp@2.0.0: - resolution: - { - integrity: sha512-xl/50/Cf32VsGq/1R8jJE5ajH1yMCQkpmoS10QbFZWl2Oor4H0Me64Pu2yxvsRWK3m6soJbmGfzSR7BYmDcWAA==, - } + resolution: {integrity: sha512-xl/50/Cf32VsGq/1R8jJE5ajH1yMCQkpmoS10QbFZWl2Oor4H0Me64Pu2yxvsRWK3m6soJbmGfzSR7BYmDcWAA==} 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@2.1.2: - resolution: - { - integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==, - } + resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} 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==} 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'} snapshots: + 12factor-env@0.1.0: dependencies: '@babel/runtime': 7.28.4 From be73198da8683cf360b5168af8d221b45a83216e Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 23 Jan 2026 05:44:18 +0000 Subject: [PATCH 03/23] test(cli): update codegen tests to use mock prompter The codegen command now uses prompter.prompt() for input handling, so tests need to provide a mock prompter that returns the argv values. --- packages/cli/__tests__/codegen.test.ts | 35 +++++++++++++++++++------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/packages/cli/__tests__/codegen.test.ts b/packages/cli/__tests__/codegen.test.ts index c396ffbe2..698084f16 100644 --- a/packages/cli/__tests__/codegen.test.ts +++ b/packages/cli/__tests__/codegen.test.ts @@ -6,10 +6,21 @@ jest.mock('@constructive-io/graphql-codegen/cli/commands/generate', () => ({ generateReactQuery: jest.fn(async () => ({ success: true, message: 'Generated SDK', filesWritten: [] as string[] })) })) -jest.mock('@constructive-io/graphql-server', () => ({ - buildSchemaSDL: jest.fn(async () => 'type Query { hello: String }\nschema { query: Query }') +jest.mock('@constructive-io/graphql-codegen', () => ({ + generateReactQuery: jest.fn(async () => ({ success: true, message: 'Generated SDK', filesWritten: [] as string[] })), + generateOrm: jest.fn(async () => ({ success: true, message: 'Generated ORM', filesWritten: [] as string[] })), + findConfigFile: jest.fn((): string | undefined => undefined), + buildSchemaFromDatabase: jest.fn(async ({ outDir }: { outDir: string }) => ({ + schemaPath: `${outDir}/schema.graphql`, + sdl: 'type Query { hello: String }\nschema { query: Query }' + })) })) +// Create a mock prompter that returns the argv values directly +const createMockPrompter = () => ({ + prompt: jest.fn(async (argv: any, _questions: any) => argv) +}) + describe('codegen command', () => { beforeEach(() => { jest.clearAllMocks() @@ -20,8 +31,9 @@ describe('codegen command', () => { const spyExit = jest.spyOn(process, 'exit').mockImplementation(((code?: number) => { throw new Error('exit:' + code) }) as any) const argv: Partial = { help: true } + const mockPrompter = createMockPrompter() - await expect(codegenCommand(argv, {} as any, {} as any)).rejects.toThrow('exit:0') + await expect(codegenCommand(argv, mockPrompter as any, {} as any)).rejects.toThrow('exit:0') expect(spyLog).toHaveBeenCalled() const first = (spyLog.mock.calls[0]?.[0] as string) || '' expect(first).toContain('Constructive GraphQL Codegen') @@ -31,6 +43,7 @@ describe('codegen command', () => { }) it('calls generateReactQuery with endpoint flow options', async () => { + const { generateReactQuery: mockGenerateReactQuery } = require('@constructive-io/graphql-codegen') const argv: Partial = { endpoint: 'http://localhost:3000/graphql', @@ -39,11 +52,12 @@ describe('codegen command', () => { verbose: true, 'dry-run': true } + const mockPrompter = createMockPrompter() - await codegenCommand(argv, {} as any, {} as any) + await codegenCommand(argv, mockPrompter as any, {} as any) - expect(generateReactQuery).toHaveBeenCalled() - const call = (generateReactQuery as jest.Mock).mock.calls[0][0] + expect(mockGenerateReactQuery).toHaveBeenCalled() + const call = mockGenerateReactQuery.mock.calls[0][0] expect(call).toMatchObject({ endpoint: 'http://localhost:3000/graphql', output: 'graphql/codegen/dist', @@ -54,17 +68,20 @@ describe('codegen command', () => { }) it('builds schema file and calls generateReactQuery with schema when DB options provided', async () => { + const { generateReactQuery: mockGenerateReactQuery, buildSchemaFromDatabase } = require('@constructive-io/graphql-codegen') const argv: Partial = { database: 'constructive_db', schemas: 'public', out: 'graphql/codegen/dist' } + const mockPrompter = createMockPrompter() - await codegenCommand(argv, {} as any, {} as any) + await codegenCommand(argv, mockPrompter as any, {} as any) - expect(generateReactQuery).toHaveBeenCalled() - const call = (generateReactQuery as jest.Mock).mock.calls[0][0] + expect(buildSchemaFromDatabase).toHaveBeenCalled() + expect(mockGenerateReactQuery).toHaveBeenCalled() + const call = mockGenerateReactQuery.mock.calls[0][0] expect(call.schema).toBe('graphql/codegen/dist/schema.graphql') expect(call.output).toBe('graphql/codegen/dist') expect(call.endpoint).toBeUndefined() From 2ac0112d2409d4370634f771a0521edc7202bfb5 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 23 Jan 2026 06:13:43 +0000 Subject: [PATCH 04/23] refactor(graphql-codegen): rename generator types and use switch statements - Rename 'generate' to 'react-query' for generator type (more specific naming) - Rename 'generate-orm' to 'orm' for generator type - Replace ternary operators with switch statements that throw on unknown cases - Improves code clarity and type safety --- graphql/codegen/src/cli/index.ts | 4 +- .../codegen/src/core/watch/orchestrator.ts | 40 ++++++++++++------- graphql/codegen/src/core/watch/types.ts | 2 +- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/graphql/codegen/src/cli/index.ts b/graphql/codegen/src/cli/index.ts index e14de13cb..6c7a4c868 100644 --- a/graphql/codegen/src/cli/index.ts +++ b/graphql/codegen/src/cli/index.ts @@ -205,7 +205,7 @@ async function handleGenerate(argv: Partial): Promise { await startWatch({ config: watchConfig, - generatorType: 'generate', + generatorType: 'react-query', verbose, authorization, configPath: config, @@ -338,7 +338,7 @@ async function handleGenerateOrm(argv: Partial): Promise { await startWatch({ config: watchConfig, - generatorType: 'generate-orm', + generatorType: 'orm', verbose, authorization, configPath: config, diff --git a/graphql/codegen/src/core/watch/orchestrator.ts b/graphql/codegen/src/core/watch/orchestrator.ts index 83ea36fb0..7e6f04fb6 100644 --- a/graphql/codegen/src/core/watch/orchestrator.ts +++ b/graphql/codegen/src/core/watch/orchestrator.ts @@ -213,16 +213,21 @@ export class WatchOrchestrator { this.log('Regenerating...'); try { - const generateFn = - this.options.generatorType === 'generate' - ? this.options.generateReactQuery - : this.options.generateOrm; - - const outputDir = - this.options.outputDir ?? - (this.options.generatorType === 'generate' - ? this.options.config.output - : this.options.config.orm.output); + let generateFn: GenerateFunction; + let outputDir: string | undefined; + + switch (this.options.generatorType) { + case 'react-query': + generateFn = this.options.generateReactQuery; + outputDir = this.options.outputDir ?? this.options.config.output; + break; + case 'orm': + generateFn = this.options.generateOrm; + outputDir = this.options.outputDir ?? this.options.config.orm.output; + break; + default: + throw new Error(`Unknown generator type: ${this.options.generatorType}`); + } const result = await generateFn({ config: this.options.configPath, @@ -278,10 +283,17 @@ export class WatchOrchestrator { } private logHeader(): void { - const generatorName = - this.options.generatorType === 'generate' - ? 'React Query hooks' - : 'ORM client'; + let generatorName: string; + switch (this.options.generatorType) { + case 'react-query': + generatorName = 'React Query hooks'; + break; + case 'orm': + generatorName = 'ORM client'; + break; + default: + throw new Error(`Unknown generator type: ${this.options.generatorType}`); + } console.log(`\n${'─'.repeat(50)}`); console.log(`graphql-codegen watch mode (${generatorName})`); console.log(`Endpoint: ${this.options.config.endpoint}`); diff --git a/graphql/codegen/src/core/watch/types.ts b/graphql/codegen/src/core/watch/types.ts index ae5f595d7..cc9d4bd5f 100644 --- a/graphql/codegen/src/core/watch/types.ts +++ b/graphql/codegen/src/core/watch/types.ts @@ -73,4 +73,4 @@ export interface PollEvent { /** * Generator type for watch mode */ -export type GeneratorType = 'generate' | 'generate-orm'; +export type GeneratorType = 'react-query' | 'orm'; From 2cb8113e59f6c55cf4354426cd1a3116a3521cea Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 23 Jan 2026 06:58:30 +0000 Subject: [PATCH 05/23] refactor(cli): replace ternary operator with switch statement in codegen command - Convert orm boolean check to explicit generatorType variable - Use switch statement with 'orm' and 'react-query' cases - Add throw for unknown generator type (defensive programming) - Extract output directory calculation to separate variable --- packages/cli/src/commands/codegen.ts | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/packages/cli/src/commands/codegen.ts b/packages/cli/src/commands/codegen.ts index 1731b5a00..6eaf7f606 100644 --- a/packages/cli/src/commands/codegen.ts +++ b/packages/cli/src/commands/codegen.ts @@ -164,28 +164,40 @@ export default async ( process.exit(1); } + // Determine generator type and output directory + const generatorType = orm ? 'orm' : 'react-query'; + const output = config ? out : outDir; + // Call core generate function - const result = orm - ? await generateOrm({ + let result: AnyResult; + switch (generatorType) { + case 'orm': + result = await generateOrm({ config, target, endpoint: endpoint || undefined, schema: schemaPath, - output: config ? out : outDir, + output, authorization: auth, verbose, dryRun, - }) - : await generateReactQuery({ + }); + break; + case 'react-query': + result = await generateReactQuery({ config, target, endpoint: endpoint || undefined, schema: schemaPath, - output: config ? out : outDir, + output, authorization: auth, verbose, dryRun, }); + break; + default: + throw new Error(`Unknown generator type: ${generatorType}`); + } printResult(result); From 3130c67bc5b57ebe5beecca8128e92aad9daeaa6 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 23 Jan 2026 07:41:12 +0000 Subject: [PATCH 06/23] feat(graphql-codegen): add single-step database generation support Extend generateReactQuery and generateOrm to accept database options directly, eliminating the need to call buildSchemaFromDatabase first. New usage: await generateReactQuery({ database: 'mydb', schemas: ['public'] }); await generateOrm({ database: 'mydb', schemas: ['public'] }); Changes: - Add DatabaseSchemaSource class for in-memory database introspection - Update createSchemaSource to detect and handle database mode - Update ConfigOverrideOptions to include database and schemas options - Update generateReactQuery and generateOrm to pass database options through - Add validateSourceOptions to check for exactly one source type --- .../codegen/src/cli/commands/generate-orm.ts | 18 ++- graphql/codegen/src/cli/commands/generate.ts | 18 ++- graphql/codegen/src/core/config/resolver.ts | 40 +++++-- .../src/core/introspect/source/database.ts | 103 ++++++++++++++++ .../src/core/introspect/source/index.ts | 112 ++++++++++++++---- 5 files changed, 255 insertions(+), 36 deletions(-) create mode 100644 graphql/codegen/src/core/introspect/source/database.ts diff --git a/graphql/codegen/src/cli/commands/generate-orm.ts b/graphql/codegen/src/cli/commands/generate-orm.ts index a329fa5a8..20fd53ca7 100644 --- a/graphql/codegen/src/cli/commands/generate-orm.ts +++ b/graphql/codegen/src/cli/commands/generate-orm.ts @@ -131,11 +131,20 @@ async function generateOrmForTarget( const formatMessage = (message: string) => isMultiTarget ? `Target "${target.name}": ${message}` : message; + // Extract database options if present (attached by config resolver for database mode) + const database = (config as any).database as string | undefined; + const schemas = (config as any).schemas as string[] | undefined; + if (isMultiTarget) { console.log(`\nTarget "${target.name}"`); - const sourceLabel = config.schema - ? `schema: ${config.schema}` - : `endpoint: ${config.endpoint}`; + let sourceLabel: string; + if (database) { + sourceLabel = `database: ${database} (schemas: ${(schemas ?? ['public']).join(', ')})`; + } else if (config.schema) { + sourceLabel = `schema: ${config.schema}`; + } else { + sourceLabel = `endpoint: ${config.endpoint}`; + } console.log(` Source: ${sourceLabel}`); console.log(` Output: ${outputDir}`); } @@ -144,6 +153,7 @@ async function generateOrmForTarget( const sourceValidation = validateSourceOptions({ endpoint: config.endpoint || undefined, schema: config.schema || undefined, + database, }); if (!sourceValidation.valid) { return { @@ -157,6 +167,8 @@ async function generateOrmForTarget( const source = createSchemaSource({ endpoint: config.endpoint || undefined, schema: config.schema || undefined, + database, + schemas, authorization: options.authorization || config.headers['Authorization'], headers: config.headers, }); diff --git a/graphql/codegen/src/cli/commands/generate.ts b/graphql/codegen/src/cli/commands/generate.ts index 39b70d291..fbb5ca171 100644 --- a/graphql/codegen/src/cli/commands/generate.ts +++ b/graphql/codegen/src/cli/commands/generate.ts @@ -130,11 +130,20 @@ async function generateForTarget( const formatMessage = (message: string) => isMultiTarget ? `Target "${target.name}": ${message}` : message; + // Extract database options if present (attached by config resolver for database mode) + const database = (config as any).database as string | undefined; + const schemas = (config as any).schemas as string[] | undefined; + if (isMultiTarget) { console.log(`\nTarget "${target.name}"`); - const sourceLabel = config.schema - ? `schema: ${config.schema}` - : `endpoint: ${config.endpoint}`; + let sourceLabel: string; + if (database) { + sourceLabel = `database: ${database} (schemas: ${(schemas ?? ['public']).join(', ')})`; + } else if (config.schema) { + sourceLabel = `schema: ${config.schema}`; + } else { + sourceLabel = `endpoint: ${config.endpoint}`; + } console.log(` Source: ${sourceLabel}`); console.log(` Output: ${config.output}`); } @@ -143,6 +152,7 @@ async function generateForTarget( const sourceValidation = validateSourceOptions({ endpoint: config.endpoint || undefined, schema: config.schema || undefined, + database, }); if (!sourceValidation.valid) { return { @@ -156,6 +166,8 @@ async function generateForTarget( const source = createSchemaSource({ endpoint: config.endpoint || undefined, schema: config.schema || undefined, + database, + schemas, authorization: options.authorization || config.headers['Authorization'], headers: config.headers, }); diff --git a/graphql/codegen/src/core/config/resolver.ts b/graphql/codegen/src/core/config/resolver.ts index ed116f9e6..29a3b3132 100644 --- a/graphql/codegen/src/core/config/resolver.ts +++ b/graphql/codegen/src/core/config/resolver.ts @@ -26,6 +26,10 @@ export interface ConfigOverrideOptions { endpoint?: string; /** Path to GraphQL schema file (.graphql) */ schema?: string; + /** Database name or connection string (for database introspection) */ + database?: string; + /** PostgreSQL schemas to include (for database mode) */ + schemas?: string[]; /** Output directory (overrides config) */ output?: string; } @@ -45,17 +49,26 @@ export interface LoadConfigResult { */ export function buildTargetOverrides( options: ConfigOverrideOptions -): GraphQLSDKConfigTarget { - const overrides: GraphQLSDKConfigTarget = {}; +): GraphQLSDKConfigTarget & { database?: string; schemas?: string[] } { + const overrides: GraphQLSDKConfigTarget & { database?: string; schemas?: string[] } = {}; if (options.endpoint) { overrides.endpoint = options.endpoint; overrides.schema = undefined; + overrides.database = undefined; } if (options.schema) { overrides.schema = options.schema; overrides.endpoint = undefined; + overrides.database = undefined; + } + + if (options.database) { + overrides.database = options.database; + overrides.schemas = options.schemas; + overrides.endpoint = undefined; + overrides.schema = undefined; } if (options.output) { @@ -77,10 +90,12 @@ export function buildTargetOverrides( export async function loadAndResolveConfig( options: ConfigOverrideOptions ): Promise { - if (options.endpoint && options.schema) { + // Validate that at most one source is specified + const sources = [options.endpoint, options.schema, options.database].filter(Boolean); + if (sources.length > 1) { return { success: false, - error: 'Cannot use both --endpoint and --schema. Choose one source.', + error: 'Multiple sources specified. Use only one of: endpoint, schema, or database.', }; } @@ -192,17 +207,28 @@ function resolveSingleTargetConfig( const mergedConfig = mergeConfig(baseConfig, overrides); - if (!mergedConfig.endpoint && !mergedConfig.schema) { + // Check if we have a source (endpoint, schema, or database) + const hasSource = mergedConfig.endpoint || mergedConfig.schema || (overrides as any).database; + if (!hasSource) { return { success: false, error: - 'No source specified. Use --endpoint or --schema, or create a config file with "graphql-codegen init".', + 'No source specified. Use --endpoint, --schema, or --database, or create a config file with "graphql-codegen init".', }; } + // For database mode, we need to pass the database info through to the resolved config + const resolvedConfig = resolveConfig(mergedConfig); + + // Attach database options if present (they're not part of the standard config type) + if ((overrides as any).database) { + (resolvedConfig as any).database = (overrides as any).database; + (resolvedConfig as any).schemas = (overrides as any).schemas; + } + return { success: true, - targets: [{ name: 'default', config: resolveConfig(mergedConfig) }], + targets: [{ name: 'default', config: resolvedConfig }], isMulti: false, }; } diff --git a/graphql/codegen/src/core/introspect/source/database.ts b/graphql/codegen/src/core/introspect/source/database.ts new file mode 100644 index 000000000..223633b20 --- /dev/null +++ b/graphql/codegen/src/core/introspect/source/database.ts @@ -0,0 +1,103 @@ +/** + * Database Schema Source + * + * Loads GraphQL schema directly from a PostgreSQL database using PostGraphile + * introspection and converts it to introspection format. + */ +import { buildSchema, introspectionFromSchema } from 'graphql'; +import type { SchemaSource, SchemaSourceResult } from './types'; +import { SchemaSourceError } from './types'; +import type { IntrospectionQueryResponse } from '../../../types/introspection'; +import { buildSchemaSDLFromDatabase } from '../../database'; + +export interface DatabaseSchemaSourceOptions { + /** + * Database name or connection string + * Can be a simple database name (uses PGHOST, PGPORT, PGUSER, PGPASSWORD env vars) + * or a full connection string (postgres://user:pass@host:port/dbname) + */ + database: string; + + /** + * PostgreSQL schemas to include in introspection + * @default ['public'] + */ + schemas?: string[]; +} + +/** + * Schema source that loads from a PostgreSQL database + * + * Uses PostGraphile to introspect the database and generate a GraphQL schema. + * The schema is built in-memory without writing to disk. + */ +export class DatabaseSchemaSource implements SchemaSource { + private readonly options: DatabaseSchemaSourceOptions; + + constructor(options: DatabaseSchemaSourceOptions) { + this.options = options; + } + + async fetch(): Promise { + const { database, schemas = ['public'] } = this.options; + + // Build SDL from database + let sdl: string; + try { + sdl = await buildSchemaSDLFromDatabase({ + database, + schemas, + }); + } catch (err) { + throw new SchemaSourceError( + `Failed to introspect database: ${err instanceof Error ? err.message : 'Unknown error'}`, + this.describe(), + err instanceof Error ? err : undefined + ); + } + + // Validate non-empty + if (!sdl.trim()) { + throw new SchemaSourceError( + 'Database introspection returned empty schema', + this.describe() + ); + } + + // Parse SDL to GraphQL schema + let schema; + try { + schema = buildSchema(sdl); + } catch (err) { + throw new SchemaSourceError( + `Invalid GraphQL SDL from database: ${err instanceof Error ? err.message : 'Unknown error'}`, + this.describe(), + err instanceof Error ? err : undefined + ); + } + + // Convert to introspection format + let introspectionResult; + try { + introspectionResult = introspectionFromSchema(schema); + } catch (err) { + throw new SchemaSourceError( + `Failed to generate introspection: ${err instanceof Error ? err.message : 'Unknown error'}`, + this.describe(), + err instanceof Error ? err : undefined + ); + } + + // Convert graphql-js introspection result to our mutable type + const introspection: IntrospectionQueryResponse = JSON.parse( + JSON.stringify(introspectionResult) + ) as IntrospectionQueryResponse; + + return { introspection }; + } + + describe(): string { + const { database, schemas = ['public'] } = this.options; + return `database: ${database} (schemas: ${schemas.join(', ')})`; + } +} diff --git a/graphql/codegen/src/core/introspect/source/index.ts b/graphql/codegen/src/core/introspect/source/index.ts index fee3433e3..2eec96fe8 100644 --- a/graphql/codegen/src/core/introspect/source/index.ts +++ b/graphql/codegen/src/core/introspect/source/index.ts @@ -4,14 +4,42 @@ * Provides a unified interface for loading GraphQL schemas from different sources: * - Live GraphQL endpoints (via introspection) * - Static .graphql schema files + * - PostgreSQL databases (via PostGraphile introspection) */ export * from './types'; export * from './endpoint'; export * from './file'; +export * from './database'; import type { SchemaSource } from './types'; import { EndpointSchemaSource } from './endpoint'; import { FileSchemaSource } from './file'; +import { DatabaseSchemaSource } from './database'; + +/** + * Options for endpoint-based schema source + */ +export interface EndpointSourceOptions { + endpoint: string; + authorization?: string; + headers?: Record; + timeout?: number; +} + +/** + * Options for file-based schema source + */ +export interface FileSourceOptions { + schema: string; +} + +/** + * Options for database-based schema source + */ +export interface DatabaseSourceOptions { + database: string; + schemas?: string[]; +} export interface CreateSchemaSourceOptions { /** @@ -24,6 +52,17 @@ export interface CreateSchemaSourceOptions { */ schema?: string; + /** + * Database name or connection string (for database introspection) + */ + database?: string; + + /** + * PostgreSQL schemas to include (for database mode) + * @default ['public'] + */ + schemas?: string[]; + /** * Optional authorization header for endpoint requests */ @@ -40,55 +79,82 @@ export interface CreateSchemaSourceOptions { timeout?: number; } +/** + * Detect which source mode is being used based on options + */ +export type SourceMode = 'endpoint' | 'schema' | 'database'; + +export function detectSourceMode(options: CreateSchemaSourceOptions): SourceMode | null { + if (options.endpoint) return 'endpoint'; + if (options.schema) return 'schema'; + if (options.database) return 'database'; + return null; +} + /** * Create a schema source based on configuration * + * Supports three modes: + * - endpoint: Introspect from a live GraphQL endpoint + * - schema: Load from a local .graphql file + * - database: Introspect directly from a PostgreSQL database + * * @param options - Source configuration * @returns Appropriate SchemaSource implementation - * @throws Error if neither endpoint nor schema is provided + * @throws Error if no valid source is provided */ export function createSchemaSource( options: CreateSchemaSourceOptions ): SchemaSource { - if (options.schema) { - return new FileSchemaSource({ - schemaPath: options.schema, - }); - } + const mode = detectSourceMode(options); - if (options.endpoint) { - return new EndpointSchemaSource({ - endpoint: options.endpoint, - authorization: options.authorization, - headers: options.headers, - timeout: options.timeout, - }); - } + switch (mode) { + case 'schema': + return new FileSchemaSource({ + schemaPath: options.schema!, + }); - throw new Error( - 'Either endpoint or schema must be provided. ' + - 'Use --endpoint for live introspection or --schema for a local file.' - ); + case 'endpoint': + return new EndpointSchemaSource({ + endpoint: options.endpoint!, + authorization: options.authorization, + headers: options.headers, + timeout: options.timeout, + }); + + case 'database': + return new DatabaseSchemaSource({ + database: options.database!, + schemas: options.schemas, + }); + + default: + throw new Error( + 'No source specified. Use one of: endpoint (URL), schema (file path), or database (name/connection string).' + ); + } } /** - * Validate that source options are valid (at least one source specified) + * Validate that source options are valid (exactly one source specified) */ export function validateSourceOptions(options: CreateSchemaSourceOptions): { valid: boolean; error?: string; } { - if (!options.endpoint && !options.schema) { + const sources = [options.endpoint, options.schema, options.database].filter(Boolean); + + if (sources.length === 0) { return { valid: false, - error: 'Either endpoint or schema must be provided', + error: 'No source specified. Use one of: endpoint, schema, or database.', }; } - if (options.endpoint && options.schema) { + if (sources.length > 1) { return { valid: false, - error: 'Cannot use both endpoint and schema. Choose one source.', + error: 'Multiple sources specified. Use only one of: endpoint, schema, or database.', }; } From d042f9c8a68b3636c1f3d92ad01803c9246f05b3 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 23 Jan 2026 09:05:52 +0000 Subject: [PATCH 07/23] feat(graphql-codegen): add PGPM module schema source support - Add ephemeral database utilities to pgsql-client (createEphemeralDb) - Add PgpmModuleSchemaSource class for introspecting PGPM modules - Support two input modes: pgpmModulePath and pgpmWorkspacePath + pgpmModuleName - Add keepDb option for debugging ephemeral databases - Update config resolver and generate commands to handle PGPM options - Add @pgpmjs/core, pgsql-client, and pgsql-seed dependencies to graphql-codegen --- graphql/codegen/package.json | 3 + .../codegen/src/cli/commands/generate-orm.ts | 19 +- graphql/codegen/src/cli/commands/generate.ts | 19 +- graphql/codegen/src/core/config/resolver.ts | 108 ++++++- .../src/core/introspect/source/index.ts | 108 ++++++- .../src/core/introspect/source/pgpm-module.ts | 268 ++++++++++++++++++ pnpm-lock.yaml | 9 + postgres/pgsql-client/src/ephemeral.ts | 165 +++++++++++ postgres/pgsql-client/src/index.ts | 1 + 9 files changed, 675 insertions(+), 25 deletions(-) create mode 100644 graphql/codegen/src/core/introspect/source/pgpm-module.ts create mode 100644 postgres/pgsql-client/src/ephemeral.ts diff --git a/graphql/codegen/package.json b/graphql/codegen/package.json index 4fb11af43..3b69ecd95 100644 --- a/graphql/codegen/package.json +++ b/graphql/codegen/package.json @@ -59,6 +59,7 @@ "@constructive-io/graphql-server": "workspace:^", "@constructive-io/graphql-types": "workspace:^", "@inquirerer/utils": "^3.2.0", + "@pgpmjs/core": "workspace:^", "ajv": "^8.17.1", "deepmerge": "^4.3.1", "find-and-require-package-json": "^0.9.0", @@ -67,6 +68,8 @@ "inflekt": "^0.3.0", "inquirerer": "^4.4.0", "jiti": "^2.6.1", + "pgsql-client": "workspace:^", + "pgsql-seed": "workspace:^", "prettier": "^3.7.4" }, "peerDependencies": { diff --git a/graphql/codegen/src/cli/commands/generate-orm.ts b/graphql/codegen/src/cli/commands/generate-orm.ts index 20fd53ca7..1a10cf06d 100644 --- a/graphql/codegen/src/cli/commands/generate-orm.ts +++ b/graphql/codegen/src/cli/commands/generate-orm.ts @@ -131,14 +131,22 @@ async function generateOrmForTarget( const formatMessage = (message: string) => isMultiTarget ? `Target "${target.name}": ${message}` : message; - // Extract database options if present (attached by config resolver for database mode) + // Extract extended options if present (attached by config resolver) const database = (config as any).database as string | undefined; const schemas = (config as any).schemas as string[] | undefined; + const pgpmModulePath = (config as any).pgpmModulePath as string | undefined; + const pgpmWorkspacePath = (config as any).pgpmWorkspacePath as string | undefined; + const pgpmModuleName = (config as any).pgpmModuleName as string | undefined; + const keepDb = (config as any).keepDb as boolean | undefined; if (isMultiTarget) { console.log(`\nTarget "${target.name}"`); let sourceLabel: string; - if (database) { + if (pgpmModulePath) { + sourceLabel = `pgpm module: ${pgpmModulePath} (schemas: ${(schemas ?? ['public']).join(', ')})`; + } else if (pgpmWorkspacePath && pgpmModuleName) { + sourceLabel = `pgpm workspace: ${pgpmWorkspacePath}, module: ${pgpmModuleName} (schemas: ${(schemas ?? ['public']).join(', ')})`; + } else if (database) { sourceLabel = `database: ${database} (schemas: ${(schemas ?? ['public']).join(', ')})`; } else if (config.schema) { sourceLabel = `schema: ${config.schema}`; @@ -154,6 +162,9 @@ async function generateOrmForTarget( endpoint: config.endpoint || undefined, schema: config.schema || undefined, database, + pgpmModulePath, + pgpmWorkspacePath, + pgpmModuleName, }); if (!sourceValidation.valid) { return { @@ -168,7 +179,11 @@ async function generateOrmForTarget( endpoint: config.endpoint || undefined, schema: config.schema || undefined, database, + pgpmModulePath, + pgpmWorkspacePath, + pgpmModuleName, schemas, + keepDb, authorization: options.authorization || config.headers['Authorization'], headers: config.headers, }); diff --git a/graphql/codegen/src/cli/commands/generate.ts b/graphql/codegen/src/cli/commands/generate.ts index fbb5ca171..addbc7db6 100644 --- a/graphql/codegen/src/cli/commands/generate.ts +++ b/graphql/codegen/src/cli/commands/generate.ts @@ -130,14 +130,22 @@ async function generateForTarget( const formatMessage = (message: string) => isMultiTarget ? `Target "${target.name}": ${message}` : message; - // Extract database options if present (attached by config resolver for database mode) + // Extract extended options if present (attached by config resolver) const database = (config as any).database as string | undefined; const schemas = (config as any).schemas as string[] | undefined; + const pgpmModulePath = (config as any).pgpmModulePath as string | undefined; + const pgpmWorkspacePath = (config as any).pgpmWorkspacePath as string | undefined; + const pgpmModuleName = (config as any).pgpmModuleName as string | undefined; + const keepDb = (config as any).keepDb as boolean | undefined; if (isMultiTarget) { console.log(`\nTarget "${target.name}"`); let sourceLabel: string; - if (database) { + if (pgpmModulePath) { + sourceLabel = `pgpm module: ${pgpmModulePath} (schemas: ${(schemas ?? ['public']).join(', ')})`; + } else if (pgpmWorkspacePath && pgpmModuleName) { + sourceLabel = `pgpm workspace: ${pgpmWorkspacePath}, module: ${pgpmModuleName} (schemas: ${(schemas ?? ['public']).join(', ')})`; + } else if (database) { sourceLabel = `database: ${database} (schemas: ${(schemas ?? ['public']).join(', ')})`; } else if (config.schema) { sourceLabel = `schema: ${config.schema}`; @@ -153,6 +161,9 @@ async function generateForTarget( endpoint: config.endpoint || undefined, schema: config.schema || undefined, database, + pgpmModulePath, + pgpmWorkspacePath, + pgpmModuleName, }); if (!sourceValidation.valid) { return { @@ -167,7 +178,11 @@ async function generateForTarget( endpoint: config.endpoint || undefined, schema: config.schema || undefined, database, + pgpmModulePath, + pgpmWorkspacePath, + pgpmModuleName, schemas, + keepDb, authorization: options.authorization || config.headers['Authorization'], headers: config.headers, }); diff --git a/graphql/codegen/src/core/config/resolver.ts b/graphql/codegen/src/core/config/resolver.ts index 29a3b3132..a42ef2151 100644 --- a/graphql/codegen/src/core/config/resolver.ts +++ b/graphql/codegen/src/core/config/resolver.ts @@ -28,8 +28,16 @@ export interface ConfigOverrideOptions { schema?: string; /** Database name or connection string (for database introspection) */ database?: string; - /** PostgreSQL schemas to include (for database mode) */ + /** Path to a PGPM module directory (for module introspection) */ + pgpmModulePath?: string; + /** Path to a PGPM workspace directory (used with pgpmModuleName) */ + pgpmWorkspacePath?: string; + /** Name of the module within the workspace (used with pgpmWorkspacePath) */ + pgpmModuleName?: string; + /** PostgreSQL schemas to include (for database and pgpm module modes) */ schemas?: string[]; + /** Keep the ephemeral database after introspection (for debugging, pgpm module mode only) */ + keepDb?: boolean; /** Output directory (overrides config) */ output?: string; } @@ -44,24 +52,42 @@ export interface LoadConfigResult { error?: string; } +/** + * Extended overrides type that includes database and PGPM module options + */ +export interface ExtendedTargetOverrides extends GraphQLSDKConfigTarget { + database?: string; + schemas?: string[]; + pgpmModulePath?: string; + pgpmWorkspacePath?: string; + pgpmModuleName?: string; + keepDb?: boolean; +} + /** * Build target overrides from options */ export function buildTargetOverrides( options: ConfigOverrideOptions -): GraphQLSDKConfigTarget & { database?: string; schemas?: string[] } { - const overrides: GraphQLSDKConfigTarget & { database?: string; schemas?: string[] } = {}; +): ExtendedTargetOverrides { + const overrides: ExtendedTargetOverrides = {}; if (options.endpoint) { overrides.endpoint = options.endpoint; overrides.schema = undefined; overrides.database = undefined; + overrides.pgpmModulePath = undefined; + overrides.pgpmWorkspacePath = undefined; + overrides.pgpmModuleName = undefined; } if (options.schema) { overrides.schema = options.schema; overrides.endpoint = undefined; overrides.database = undefined; + overrides.pgpmModulePath = undefined; + overrides.pgpmWorkspacePath = undefined; + overrides.pgpmModuleName = undefined; } if (options.database) { @@ -69,6 +95,31 @@ export function buildTargetOverrides( overrides.schemas = options.schemas; overrides.endpoint = undefined; overrides.schema = undefined; + overrides.pgpmModulePath = undefined; + overrides.pgpmWorkspacePath = undefined; + overrides.pgpmModuleName = undefined; + } + + if (options.pgpmModulePath) { + overrides.pgpmModulePath = options.pgpmModulePath; + overrides.schemas = options.schemas; + overrides.keepDb = options.keepDb; + overrides.endpoint = undefined; + overrides.schema = undefined; + overrides.database = undefined; + overrides.pgpmWorkspacePath = undefined; + overrides.pgpmModuleName = undefined; + } + + if (options.pgpmWorkspacePath && options.pgpmModuleName) { + overrides.pgpmWorkspacePath = options.pgpmWorkspacePath; + overrides.pgpmModuleName = options.pgpmModuleName; + overrides.schemas = options.schemas; + overrides.keepDb = options.keepDb; + overrides.endpoint = undefined; + overrides.schema = undefined; + overrides.database = undefined; + overrides.pgpmModulePath = undefined; } if (options.output) { @@ -90,12 +141,22 @@ export function buildTargetOverrides( export async function loadAndResolveConfig( options: ConfigOverrideOptions ): Promise { + // Check for pgpm workspace mode (requires both pgpmWorkspacePath and pgpmModuleName) + const hasPgpmWorkspace = options.pgpmWorkspacePath && options.pgpmModuleName; + // Validate that at most one source is specified - const sources = [options.endpoint, options.schema, options.database].filter(Boolean); + const sources = [ + options.endpoint, + options.schema, + options.database, + options.pgpmModulePath, + hasPgpmWorkspace, + ].filter(Boolean); if (sources.length > 1) { return { success: false, - error: 'Multiple sources specified. Use only one of: endpoint, schema, or database.', + error: + 'Multiple sources specified. Use only one of: endpoint, schema, database, pgpmModulePath, or pgpmWorkspacePath + pgpmModuleName.', }; } @@ -195,7 +256,7 @@ function resolveMultiTargetConfig( function resolveSingleTargetConfig( baseConfig: GraphQLSDKConfigTarget, options: ConfigOverrideOptions, - overrides: GraphQLSDKConfigTarget + overrides: ExtendedTargetOverrides ): LoadConfigResult { if (options.target) { return { @@ -207,23 +268,42 @@ function resolveSingleTargetConfig( const mergedConfig = mergeConfig(baseConfig, overrides); - // Check if we have a source (endpoint, schema, or database) - const hasSource = mergedConfig.endpoint || mergedConfig.schema || (overrides as any).database; + // Check if we have a source (endpoint, schema, database, or pgpm module) + const hasSource = + mergedConfig.endpoint || + mergedConfig.schema || + overrides.database || + overrides.pgpmModulePath || + (overrides.pgpmWorkspacePath && overrides.pgpmModuleName); + if (!hasSource) { return { success: false, error: - 'No source specified. Use --endpoint, --schema, or --database, or create a config file with "graphql-codegen init".', + 'No source specified. Use --endpoint, --schema, --database, --pgpmModulePath, or --pgpmWorkspacePath + --pgpmModuleName, or create a config file with "graphql-codegen init".', }; } // For database mode, we need to pass the database info through to the resolved config const resolvedConfig = resolveConfig(mergedConfig); - - // Attach database options if present (they're not part of the standard config type) - if ((overrides as any).database) { - (resolvedConfig as any).database = (overrides as any).database; - (resolvedConfig as any).schemas = (overrides as any).schemas; + + // Attach extended options if present (they're not part of the standard config type) + if (overrides.database) { + (resolvedConfig as any).database = overrides.database; + (resolvedConfig as any).schemas = overrides.schemas; + } + + if (overrides.pgpmModulePath) { + (resolvedConfig as any).pgpmModulePath = overrides.pgpmModulePath; + (resolvedConfig as any).schemas = overrides.schemas; + (resolvedConfig as any).keepDb = overrides.keepDb; + } + + if (overrides.pgpmWorkspacePath && overrides.pgpmModuleName) { + (resolvedConfig as any).pgpmWorkspacePath = overrides.pgpmWorkspacePath; + (resolvedConfig as any).pgpmModuleName = overrides.pgpmModuleName; + (resolvedConfig as any).schemas = overrides.schemas; + (resolvedConfig as any).keepDb = overrides.keepDb; } return { diff --git a/graphql/codegen/src/core/introspect/source/index.ts b/graphql/codegen/src/core/introspect/source/index.ts index 2eec96fe8..422174236 100644 --- a/graphql/codegen/src/core/introspect/source/index.ts +++ b/graphql/codegen/src/core/introspect/source/index.ts @@ -5,16 +5,23 @@ * - Live GraphQL endpoints (via introspection) * - Static .graphql schema files * - PostgreSQL databases (via PostGraphile introspection) + * - PGPM modules (via ephemeral database deployment) */ export * from './types'; export * from './endpoint'; export * from './file'; export * from './database'; +export * from './pgpm-module'; import type { SchemaSource } from './types'; import { EndpointSchemaSource } from './endpoint'; import { FileSchemaSource } from './file'; import { DatabaseSchemaSource } from './database'; +import { + PgpmModuleSchemaSource, + isPgpmModulePathOptions, + isPgpmWorkspaceOptions, +} from './pgpm-module'; /** * Options for endpoint-based schema source @@ -41,6 +48,25 @@ export interface DatabaseSourceOptions { schemas?: string[]; } +/** + * Options for PGPM module-based schema source (direct path) + */ +export interface PgpmModulePathSourceOptions { + pgpmModulePath: string; + schemas?: string[]; + keepDb?: boolean; +} + +/** + * Options for PGPM module-based schema source (workspace + module name) + */ +export interface PgpmWorkspaceSourceOptions { + pgpmWorkspacePath: string; + pgpmModuleName: string; + schemas?: string[]; + keepDb?: boolean; +} + export interface CreateSchemaSourceOptions { /** * GraphQL endpoint URL (for live introspection) @@ -58,11 +84,33 @@ export interface CreateSchemaSourceOptions { database?: string; /** - * PostgreSQL schemas to include (for database mode) + * Path to a PGPM module directory (for module introspection) + * Creates an ephemeral database, deploys the module, and introspects + */ + pgpmModulePath?: string; + + /** + * Path to a PGPM workspace directory (used with pgpmModuleName) + */ + pgpmWorkspacePath?: string; + + /** + * Name of the module within the workspace (used with pgpmWorkspacePath) + */ + pgpmModuleName?: string; + + /** + * PostgreSQL schemas to include (for database and pgpm module modes) * @default ['public'] */ schemas?: string[]; + /** + * Keep the ephemeral database after introspection (for debugging, pgpm module mode only) + * @default false + */ + keepDb?: boolean; + /** * Optional authorization header for endpoint requests */ @@ -82,22 +130,26 @@ export interface CreateSchemaSourceOptions { /** * Detect which source mode is being used based on options */ -export type SourceMode = 'endpoint' | 'schema' | 'database'; +export type SourceMode = 'endpoint' | 'schema' | 'database' | 'pgpm-module' | 'pgpm-workspace'; export function detectSourceMode(options: CreateSchemaSourceOptions): SourceMode | null { if (options.endpoint) return 'endpoint'; if (options.schema) return 'schema'; if (options.database) return 'database'; + if (options.pgpmModulePath) return 'pgpm-module'; + if (options.pgpmWorkspacePath && options.pgpmModuleName) return 'pgpm-workspace'; return null; } /** * Create a schema source based on configuration * - * Supports three modes: + * Supports five modes: * - endpoint: Introspect from a live GraphQL endpoint * - schema: Load from a local .graphql file * - database: Introspect directly from a PostgreSQL database + * - pgpm-module: Deploy a PGPM module to an ephemeral database and introspect + * - pgpm-workspace: Deploy a module from a PGPM workspace to an ephemeral database and introspect * * @param options - Source configuration * @returns Appropriate SchemaSource implementation @@ -128,9 +180,24 @@ export function createSchemaSource( schemas: options.schemas, }); + case 'pgpm-module': + return new PgpmModuleSchemaSource({ + pgpmModulePath: options.pgpmModulePath!, + schemas: options.schemas, + keepDb: options.keepDb, + }); + + case 'pgpm-workspace': + return new PgpmModuleSchemaSource({ + pgpmWorkspacePath: options.pgpmWorkspacePath!, + pgpmModuleName: options.pgpmModuleName!, + schemas: options.schemas, + keepDb: options.keepDb, + }); + default: throw new Error( - 'No source specified. Use one of: endpoint (URL), schema (file path), or database (name/connection string).' + 'No source specified. Use one of: endpoint (URL), schema (file path), database (name/connection string), pgpmModulePath (module directory), or pgpmWorkspacePath + pgpmModuleName.' ); } } @@ -142,19 +209,46 @@ export function validateSourceOptions(options: CreateSchemaSourceOptions): { valid: boolean; error?: string; } { - const sources = [options.endpoint, options.schema, options.database].filter(Boolean); + // Check for pgpm workspace mode (requires both pgpmWorkspacePath and pgpmModuleName) + const hasPgpmWorkspace = options.pgpmWorkspacePath && options.pgpmModuleName; + + // Count primary sources (pgpm workspace counts as one source) + const sources = [ + options.endpoint, + options.schema, + options.database, + options.pgpmModulePath, + hasPgpmWorkspace, + ].filter(Boolean); if (sources.length === 0) { return { valid: false, - error: 'No source specified. Use one of: endpoint, schema, or database.', + error: + 'No source specified. Use one of: endpoint, schema, database, pgpmModulePath, or pgpmWorkspacePath + pgpmModuleName.', }; } if (sources.length > 1) { return { valid: false, - error: 'Multiple sources specified. Use only one of: endpoint, schema, or database.', + error: + 'Multiple sources specified. Use only one of: endpoint, schema, database, pgpmModulePath, or pgpmWorkspacePath + pgpmModuleName.', + }; + } + + // Validate pgpm workspace mode has both required fields + if (options.pgpmWorkspacePath && !options.pgpmModuleName) { + return { + valid: false, + error: 'pgpmWorkspacePath requires pgpmModuleName to be specified.', + }; + } + + if (options.pgpmModuleName && !options.pgpmWorkspacePath) { + return { + valid: false, + error: 'pgpmModuleName requires pgpmWorkspacePath to be specified.', }; } diff --git a/graphql/codegen/src/core/introspect/source/pgpm-module.ts b/graphql/codegen/src/core/introspect/source/pgpm-module.ts new file mode 100644 index 000000000..5b12a2699 --- /dev/null +++ b/graphql/codegen/src/core/introspect/source/pgpm-module.ts @@ -0,0 +1,268 @@ +/** + * PGPM Module Schema Source + * + * Loads GraphQL schema from a PGPM module by: + * 1. Creating an ephemeral database + * 2. Deploying the module to the database + * 3. Introspecting the database with PostGraphile + * 4. Cleaning up the ephemeral database (unless keepDb is true) + */ +import { buildSchema, introspectionFromSchema } from 'graphql'; +import { PgpmPackage } from '@pgpmjs/core'; +import { createEphemeralDb, type EphemeralDbResult } from 'pgsql-client'; +import { deployPgpm } from 'pgsql-seed'; + +import type { SchemaSource, SchemaSourceResult } from './types'; +import { SchemaSourceError } from './types'; +import type { IntrospectionQueryResponse } from '../../../types/introspection'; +import { buildSchemaSDLFromDatabase } from '../../database'; + +/** + * Options for PGPM module schema source using direct module path + */ +export interface PgpmModulePathOptions { + /** + * Path to the PGPM module directory + * The directory should contain a pgpm.plan file and .control file + */ + pgpmModulePath: string; + + /** + * PostgreSQL schemas to include in introspection + * @default ['public'] + */ + schemas?: string[]; + + /** + * If true, keeps the ephemeral database after introspection (useful for debugging) + * @default false + */ + keepDb?: boolean; +} + +/** + * Options for PGPM module schema source using workspace + module name + */ +export interface PgpmWorkspaceOptions { + /** + * Path to the PGPM workspace directory + * The directory should contain a pgpm.config.yaml or similar workspace config + */ + pgpmWorkspacePath: string; + + /** + * Name of the module within the workspace + */ + pgpmModuleName: string; + + /** + * PostgreSQL schemas to include in introspection + * @default ['public'] + */ + schemas?: string[]; + + /** + * If true, keeps the ephemeral database after introspection (useful for debugging) + * @default false + */ + keepDb?: boolean; +} + +export type PgpmModuleSchemaSourceOptions = PgpmModulePathOptions | PgpmWorkspaceOptions; + +/** + * Type guard to check if options use direct module path + */ +export function isPgpmModulePathOptions( + options: PgpmModuleSchemaSourceOptions +): options is PgpmModulePathOptions { + return 'pgpmModulePath' in options; +} + +/** + * Type guard to check if options use workspace + module name + */ +export function isPgpmWorkspaceOptions( + options: PgpmModuleSchemaSourceOptions +): options is PgpmWorkspaceOptions { + return 'pgpmWorkspacePath' in options && 'pgpmModuleName' in options; +} + +/** + * Schema source that loads from a PGPM module + * + * Creates an ephemeral database, deploys the module, introspects the schema, + * and cleans up. Supports both direct module path and workspace + module name modes. + */ +export class PgpmModuleSchemaSource implements SchemaSource { + private readonly options: PgpmModuleSchemaSourceOptions; + private ephemeralDb: EphemeralDbResult | null = null; + + constructor(options: PgpmModuleSchemaSourceOptions) { + this.options = options; + } + + async fetch(): Promise { + const schemas = this.getSchemas(); + const keepDb = this.getKeepDb(); + + // Resolve the module path + let modulePath: string; + try { + modulePath = this.resolveModulePath(); + } catch (err) { + throw new SchemaSourceError( + `Failed to resolve module path: ${err instanceof Error ? err.message : 'Unknown error'}`, + this.describe(), + err instanceof Error ? err : undefined + ); + } + + // Validate the module exists + const pkg = new PgpmPackage(modulePath); + if (!pkg.isInModule()) { + throw new SchemaSourceError( + `Not a valid PGPM module: ${modulePath}. Directory must contain pgpm.plan and .control files.`, + this.describe() + ); + } + + // Create ephemeral database + try { + this.ephemeralDb = createEphemeralDb({ + prefix: 'codegen_pgpm_', + verbose: false, + }); + } catch (err) { + throw new SchemaSourceError( + `Failed to create ephemeral database: ${err instanceof Error ? err.message : 'Unknown error'}`, + this.describe(), + err instanceof Error ? err : undefined + ); + } + + const { config: dbConfig, teardown } = this.ephemeralDb; + + try { + // Deploy the module to the ephemeral database + try { + await deployPgpm(dbConfig, modulePath, false); + } catch (err) { + throw new SchemaSourceError( + `Failed to deploy PGPM module: ${err instanceof Error ? err.message : 'Unknown error'}`, + this.describe(), + err instanceof Error ? err : undefined + ); + } + + // Build SDL from the deployed database + let sdl: string; + try { + sdl = await buildSchemaSDLFromDatabase({ + database: dbConfig.database, + schemas, + }); + } catch (err) { + throw new SchemaSourceError( + `Failed to introspect database: ${err instanceof Error ? err.message : 'Unknown error'}`, + this.describe(), + err instanceof Error ? err : undefined + ); + } + + // Validate non-empty + if (!sdl.trim()) { + throw new SchemaSourceError( + 'Database introspection returned empty schema', + this.describe() + ); + } + + // Parse SDL to GraphQL schema + let schema; + try { + schema = buildSchema(sdl); + } catch (err) { + throw new SchemaSourceError( + `Invalid GraphQL SDL from database: ${err instanceof Error ? err.message : 'Unknown error'}`, + this.describe(), + err instanceof Error ? err : undefined + ); + } + + // Convert to introspection format + let introspectionResult; + try { + introspectionResult = introspectionFromSchema(schema); + } catch (err) { + throw new SchemaSourceError( + `Failed to generate introspection: ${err instanceof Error ? err.message : 'Unknown error'}`, + this.describe(), + err instanceof Error ? err : undefined + ); + } + + // Convert graphql-js introspection result to our mutable type + const introspection: IntrospectionQueryResponse = JSON.parse( + JSON.stringify(introspectionResult) + ) as IntrospectionQueryResponse; + + return { introspection }; + } finally { + // Clean up the ephemeral database + teardown({ keepDb }); + + if (keepDb) { + console.log(`[pgpm-module] Kept ephemeral database: ${dbConfig.database}`); + } + } + } + + describe(): string { + if (isPgpmModulePathOptions(this.options)) { + const schemas = this.options.schemas ?? ['public']; + return `pgpm module: ${this.options.pgpmModulePath} (schemas: ${schemas.join(', ')})`; + } else { + const schemas = this.options.schemas ?? ['public']; + return `pgpm workspace: ${this.options.pgpmWorkspacePath}, module: ${this.options.pgpmModuleName} (schemas: ${schemas.join(', ')})`; + } + } + + private resolveModulePath(): string { + if (isPgpmModulePathOptions(this.options)) { + return this.options.pgpmModulePath; + } + + // Workspace + module name mode + const { pgpmWorkspacePath, pgpmModuleName } = this.options; + const workspace = new PgpmPackage(pgpmWorkspacePath); + + if (!workspace.workspacePath) { + throw new Error(`Not a valid PGPM workspace: ${pgpmWorkspacePath}`); + } + + // Get the module from the workspace + const moduleProject = workspace.getModuleProject(pgpmModuleName); + const modulePath = moduleProject.getModulePath(); + + if (!modulePath) { + throw new Error(`Module "${pgpmModuleName}" not found in workspace`); + } + + return modulePath; + } + + private getSchemas(): string[] { + if (isPgpmModulePathOptions(this.options)) { + return this.options.schemas ?? ['public']; + } + return this.options.schemas ?? ['public']; + } + + private getKeepDb(): boolean { + if (isPgpmModulePathOptions(this.options)) { + return this.options.keepDb ?? false; + } + return this.options.keepDb ?? false; + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f4b0d8766..4d2ccc012 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -736,6 +736,9 @@ importers: '@inquirerer/utils': specifier: ^3.2.0 version: 3.2.0 + '@pgpmjs/core': + specifier: workspace:^ + version: link:../../pgpm/core/dist ajv: specifier: ^8.17.1 version: 8.17.1 @@ -760,6 +763,12 @@ importers: jiti: specifier: ^2.6.1 version: 2.6.1 + pgsql-client: + specifier: workspace:^ + version: link:../../postgres/pgsql-client/dist + pgsql-seed: + specifier: workspace:^ + version: link:../../postgres/pgsql-seed/dist prettier: specifier: ^3.7.4 version: 3.8.0 diff --git a/postgres/pgsql-client/src/ephemeral.ts b/postgres/pgsql-client/src/ephemeral.ts new file mode 100644 index 000000000..59a4df1a1 --- /dev/null +++ b/postgres/pgsql-client/src/ephemeral.ts @@ -0,0 +1,165 @@ +/** + * Ephemeral Database Utilities + * + * Provides utilities for creating and managing temporary PostgreSQL databases + * for testing, code generation, and other ephemeral use cases. + */ +import { randomUUID } from 'crypto'; +import { getPgEnvOptions, PgConfig } from 'pg-env'; + +import { DbAdmin } from './admin'; + +/** + * Options for creating an ephemeral database + */ +export interface EphemeralDbOptions { + /** + * Database name prefix (default: 'ephemeral_') + */ + prefix?: string; + + /** + * PostgreSQL extensions to install after creation + */ + extensions?: string[]; + + /** + * Base PostgreSQL configuration (host, port, user, password) + * If not provided, uses environment variables via pg-env + */ + baseConfig?: Partial; + + /** + * Enable verbose logging + */ + verbose?: boolean; +} + +/** + * Options for tearing down an ephemeral database + */ +export interface TeardownOptions { + /** + * If true, keeps the database instead of dropping it (useful for debugging) + */ + keepDb?: boolean; +} + +/** + * Result of creating an ephemeral database + */ +export interface EphemeralDbResult { + /** + * The name of the created database + */ + name: string; + + /** + * Full PostgreSQL configuration for connecting to the ephemeral database + */ + config: PgConfig; + + /** + * Database admin instance for additional operations + */ + admin: DbAdmin; + + /** + * Teardown function to clean up the ephemeral database + * Call this when done to drop the database (unless keepDb is true) + */ + teardown: (opts?: TeardownOptions) => void; +} + +/** + * Create an ephemeral (temporary) PostgreSQL database + * + * Creates a new database with a unique UUID-based name. The database + * can be used for testing, code generation, or other temporary purposes. + * + * @example + * ```typescript + * const { config, teardown } = createEphemeralDb(); + * + * // Use the database... + * const pool = new Pool(config); + * await pool.query('SELECT 1'); + * await pool.end(); + * + * // Clean up + * teardown(); + * + * // Or keep for debugging + * teardown({ keepDb: true }); + * ``` + */ +export function createEphemeralDb(options: EphemeralDbOptions = {}): EphemeralDbResult { + const { + prefix = 'ephemeral_', + extensions = [], + baseConfig = {}, + verbose = false, + } = options; + + // Generate unique database name + const dbName = `${prefix}${randomUUID().replace(/-/g, '_')}`; + + // Get base config from environment, merged with any provided config + const config: PgConfig = getPgEnvOptions({ + ...baseConfig, + database: dbName, + }); + + // Create admin instance for database operations + const admin = new DbAdmin(config, verbose); + + // Create the database + admin.create(dbName); + + // Install extensions if specified + if (extensions.length > 0) { + admin.installExtensions(extensions, dbName); + } + + // Create teardown function + const teardown = (opts: TeardownOptions = {}) => { + const { keepDb = false } = opts; + + if (keepDb) { + if (verbose) { + console.log(`[ephemeral-db] Keeping database: ${dbName}`); + } + return; + } + + try { + admin.drop(dbName); + if (verbose) { + console.log(`[ephemeral-db] Dropped database: ${dbName}`); + } + } catch (err) { + if (verbose) { + console.error(`[ephemeral-db] Failed to drop database ${dbName}:`, err); + } + } + }; + + return { + name: dbName, + config, + admin, + teardown, + }; +} + +/** + * Create an ephemeral database asynchronously + * + * Same as createEphemeralDb but returns a Promise for consistency + * with async workflows. + */ +export async function createEphemeralDbAsync( + options: EphemeralDbOptions = {} +): Promise { + return createEphemeralDb(options); +} diff --git a/postgres/pgsql-client/src/index.ts b/postgres/pgsql-client/src/index.ts index 7629d5920..5d9fa3bea 100644 --- a/postgres/pgsql-client/src/index.ts +++ b/postgres/pgsql-client/src/index.ts @@ -1,5 +1,6 @@ export * from './admin'; export * from './client'; export * from './context-utils'; +export * from './ephemeral'; export * from './roles'; export { streamSql } from './stream'; From b92509283038d945789fe0ddcf978c0e4c219b40 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 23 Jan 2026 09:34:10 +0000 Subject: [PATCH 08/23] feat(graphql-codegen): add apiNames support for automatic schema discovery - Add apiNames option to schema sources (mutually exclusive with schemas) - Create api-schemas.ts with utilities for resolving schemas from API names - Query services_public.api_schemas joined with services_public.apis and metaschema_public.schema - Validate services_public/metaschema_public schemas exist: - For database mode: validate at the beginning - For PGPM modes: validate after module deployment - Update config resolver to handle apiNames in ConfigOverrideOptions - Update generate.ts and generate-orm.ts to extract and pass apiNames - Add pg-cache and pg-env as dependencies --- graphql/codegen/package.json | 2 + .../codegen/src/cli/commands/generate-orm.ts | 13 +- graphql/codegen/src/cli/commands/generate.ts | 13 +- graphql/codegen/src/core/config/resolver.ts | 11 +- .../src/core/introspect/source/api-schemas.ts | 152 ++++++++++++++++++ .../src/core/introspect/source/database.ts | 42 ++++- .../src/core/introspect/source/index.ts | 37 ++++- .../src/core/introspect/source/pgpm-module.ts | 59 ++++++- pnpm-lock.yaml | 6 + 9 files changed, 320 insertions(+), 15 deletions(-) create mode 100644 graphql/codegen/src/core/introspect/source/api-schemas.ts diff --git a/graphql/codegen/package.json b/graphql/codegen/package.json index 3b69ecd95..fb13f745d 100644 --- a/graphql/codegen/package.json +++ b/graphql/codegen/package.json @@ -68,6 +68,8 @@ "inflekt": "^0.3.0", "inquirerer": "^4.4.0", "jiti": "^2.6.1", + "pg-cache": "workspace:^", + "pg-env": "workspace:^", "pgsql-client": "workspace:^", "pgsql-seed": "workspace:^", "prettier": "^3.7.4" diff --git a/graphql/codegen/src/cli/commands/generate-orm.ts b/graphql/codegen/src/cli/commands/generate-orm.ts index 1a10cf06d..576d0ac0d 100644 --- a/graphql/codegen/src/cli/commands/generate-orm.ts +++ b/graphql/codegen/src/cli/commands/generate-orm.ts @@ -134,6 +134,7 @@ async function generateOrmForTarget( // Extract extended options if present (attached by config resolver) const database = (config as any).database as string | undefined; const schemas = (config as any).schemas as string[] | undefined; + const apiNames = (config as any).apiNames as string[] | undefined; const pgpmModulePath = (config as any).pgpmModulePath as string | undefined; const pgpmWorkspacePath = (config as any).pgpmWorkspacePath as string | undefined; const pgpmModuleName = (config as any).pgpmModuleName as string | undefined; @@ -142,12 +143,15 @@ async function generateOrmForTarget( if (isMultiTarget) { console.log(`\nTarget "${target.name}"`); let sourceLabel: string; + const schemaInfo = apiNames && apiNames.length > 0 + ? `apiNames: ${apiNames.join(', ')}` + : `schemas: ${(schemas ?? ['public']).join(', ')}`; if (pgpmModulePath) { - sourceLabel = `pgpm module: ${pgpmModulePath} (schemas: ${(schemas ?? ['public']).join(', ')})`; + sourceLabel = `pgpm module: ${pgpmModulePath} (${schemaInfo})`; } else if (pgpmWorkspacePath && pgpmModuleName) { - sourceLabel = `pgpm workspace: ${pgpmWorkspacePath}, module: ${pgpmModuleName} (schemas: ${(schemas ?? ['public']).join(', ')})`; + sourceLabel = `pgpm workspace: ${pgpmWorkspacePath}, module: ${pgpmModuleName} (${schemaInfo})`; } else if (database) { - sourceLabel = `database: ${database} (schemas: ${(schemas ?? ['public']).join(', ')})`; + sourceLabel = `database: ${database} (${schemaInfo})`; } else if (config.schema) { sourceLabel = `schema: ${config.schema}`; } else { @@ -165,6 +169,8 @@ async function generateOrmForTarget( pgpmModulePath, pgpmWorkspacePath, pgpmModuleName, + schemas, + apiNames, }); if (!sourceValidation.valid) { return { @@ -183,6 +189,7 @@ async function generateOrmForTarget( pgpmWorkspacePath, pgpmModuleName, schemas, + apiNames, keepDb, authorization: options.authorization || config.headers['Authorization'], headers: config.headers, diff --git a/graphql/codegen/src/cli/commands/generate.ts b/graphql/codegen/src/cli/commands/generate.ts index addbc7db6..1bd6da45e 100644 --- a/graphql/codegen/src/cli/commands/generate.ts +++ b/graphql/codegen/src/cli/commands/generate.ts @@ -133,6 +133,7 @@ async function generateForTarget( // Extract extended options if present (attached by config resolver) const database = (config as any).database as string | undefined; const schemas = (config as any).schemas as string[] | undefined; + const apiNames = (config as any).apiNames as string[] | undefined; const pgpmModulePath = (config as any).pgpmModulePath as string | undefined; const pgpmWorkspacePath = (config as any).pgpmWorkspacePath as string | undefined; const pgpmModuleName = (config as any).pgpmModuleName as string | undefined; @@ -141,12 +142,15 @@ async function generateForTarget( if (isMultiTarget) { console.log(`\nTarget "${target.name}"`); let sourceLabel: string; + const schemaInfo = apiNames && apiNames.length > 0 + ? `apiNames: ${apiNames.join(', ')}` + : `schemas: ${(schemas ?? ['public']).join(', ')}`; if (pgpmModulePath) { - sourceLabel = `pgpm module: ${pgpmModulePath} (schemas: ${(schemas ?? ['public']).join(', ')})`; + sourceLabel = `pgpm module: ${pgpmModulePath} (${schemaInfo})`; } else if (pgpmWorkspacePath && pgpmModuleName) { - sourceLabel = `pgpm workspace: ${pgpmWorkspacePath}, module: ${pgpmModuleName} (schemas: ${(schemas ?? ['public']).join(', ')})`; + sourceLabel = `pgpm workspace: ${pgpmWorkspacePath}, module: ${pgpmModuleName} (${schemaInfo})`; } else if (database) { - sourceLabel = `database: ${database} (schemas: ${(schemas ?? ['public']).join(', ')})`; + sourceLabel = `database: ${database} (${schemaInfo})`; } else if (config.schema) { sourceLabel = `schema: ${config.schema}`; } else { @@ -164,6 +168,8 @@ async function generateForTarget( pgpmModulePath, pgpmWorkspacePath, pgpmModuleName, + schemas, + apiNames, }); if (!sourceValidation.valid) { return { @@ -182,6 +188,7 @@ async function generateForTarget( pgpmWorkspacePath, pgpmModuleName, schemas, + apiNames, keepDb, authorization: options.authorization || config.headers['Authorization'], headers: config.headers, diff --git a/graphql/codegen/src/core/config/resolver.ts b/graphql/codegen/src/core/config/resolver.ts index a42ef2151..1a0f2ee28 100644 --- a/graphql/codegen/src/core/config/resolver.ts +++ b/graphql/codegen/src/core/config/resolver.ts @@ -34,8 +34,10 @@ export interface ConfigOverrideOptions { pgpmWorkspacePath?: string; /** Name of the module within the workspace (used with pgpmWorkspacePath) */ pgpmModuleName?: string; - /** PostgreSQL schemas to include (for database and pgpm module modes) */ + /** PostgreSQL schemas to include (for database and pgpm module modes) - mutually exclusive with apiNames */ schemas?: string[]; + /** API names to resolve schemas from (for database and pgpm module modes) - mutually exclusive with schemas */ + apiNames?: string[]; /** Keep the ephemeral database after introspection (for debugging, pgpm module mode only) */ keepDb?: boolean; /** Output directory (overrides config) */ @@ -58,6 +60,7 @@ export interface LoadConfigResult { export interface ExtendedTargetOverrides extends GraphQLSDKConfigTarget { database?: string; schemas?: string[]; + apiNames?: string[]; pgpmModulePath?: string; pgpmWorkspacePath?: string; pgpmModuleName?: string; @@ -93,6 +96,7 @@ export function buildTargetOverrides( if (options.database) { overrides.database = options.database; overrides.schemas = options.schemas; + overrides.apiNames = options.apiNames; overrides.endpoint = undefined; overrides.schema = undefined; overrides.pgpmModulePath = undefined; @@ -103,6 +107,7 @@ export function buildTargetOverrides( if (options.pgpmModulePath) { overrides.pgpmModulePath = options.pgpmModulePath; overrides.schemas = options.schemas; + overrides.apiNames = options.apiNames; overrides.keepDb = options.keepDb; overrides.endpoint = undefined; overrides.schema = undefined; @@ -115,6 +120,7 @@ export function buildTargetOverrides( overrides.pgpmWorkspacePath = options.pgpmWorkspacePath; overrides.pgpmModuleName = options.pgpmModuleName; overrides.schemas = options.schemas; + overrides.apiNames = options.apiNames; overrides.keepDb = options.keepDb; overrides.endpoint = undefined; overrides.schema = undefined; @@ -291,11 +297,13 @@ function resolveSingleTargetConfig( if (overrides.database) { (resolvedConfig as any).database = overrides.database; (resolvedConfig as any).schemas = overrides.schemas; + (resolvedConfig as any).apiNames = overrides.apiNames; } if (overrides.pgpmModulePath) { (resolvedConfig as any).pgpmModulePath = overrides.pgpmModulePath; (resolvedConfig as any).schemas = overrides.schemas; + (resolvedConfig as any).apiNames = overrides.apiNames; (resolvedConfig as any).keepDb = overrides.keepDb; } @@ -303,6 +311,7 @@ function resolveSingleTargetConfig( (resolvedConfig as any).pgpmWorkspacePath = overrides.pgpmWorkspacePath; (resolvedConfig as any).pgpmModuleName = overrides.pgpmModuleName; (resolvedConfig as any).schemas = overrides.schemas; + (resolvedConfig as any).apiNames = overrides.apiNames; (resolvedConfig as any).keepDb = overrides.keepDb; } diff --git a/graphql/codegen/src/core/introspect/source/api-schemas.ts b/graphql/codegen/src/core/introspect/source/api-schemas.ts new file mode 100644 index 000000000..4ff79229f --- /dev/null +++ b/graphql/codegen/src/core/introspect/source/api-schemas.ts @@ -0,0 +1,152 @@ +/** + * API Schemas Resolution + * + * Utilities for resolving PostgreSQL schema names from API names + * by querying the services_public.api_schemas table. + */ +import { Pool } from 'pg'; +import { getPgPool } from 'pg-cache'; +import { getPgEnvOptions } from 'pg-env'; + +/** + * Result of validating services schema requirements + */ +export interface ServicesSchemaValidation { + valid: boolean; + error?: string; +} + +/** + * Validate that the required services schemas exist in the database + * + * Checks for: + * - services_public schema with apis and api_schemas tables + * - metaschema_public schema with schema table + * + * @param pool - Database connection pool + * @returns Validation result + */ +export async function validateServicesSchemas( + pool: Pool +): Promise { + try { + // Check for services_public.apis table + const apisCheck = await pool.query(` + SELECT 1 FROM information_schema.tables + WHERE table_schema = 'services_public' + AND table_name = 'apis' + `); + if (apisCheck.rows.length === 0) { + return { + valid: false, + error: 'services_public.apis table not found. The database must have the services schema deployed.', + }; + } + + // Check for services_public.api_schemas table + const apiSchemasCheck = await pool.query(` + SELECT 1 FROM information_schema.tables + WHERE table_schema = 'services_public' + AND table_name = 'api_schemas' + `); + if (apiSchemasCheck.rows.length === 0) { + return { + valid: false, + error: 'services_public.api_schemas table not found. The database must have the services schema deployed.', + }; + } + + // Check for metaschema_public.schema table + const metaschemaCheck = await pool.query(` + SELECT 1 FROM information_schema.tables + WHERE table_schema = 'metaschema_public' + AND table_name = 'schema' + `); + if (metaschemaCheck.rows.length === 0) { + return { + valid: false, + error: 'metaschema_public.schema table not found. The database must have the metaschema deployed.', + }; + } + + return { valid: true }; + } catch (err) { + return { + valid: false, + error: `Failed to validate services schemas: ${err instanceof Error ? err.message : 'Unknown error'}`, + }; + } +} + +/** + * Resolve schema names from API names by querying services_public.api_schemas + * + * Joins services_public.apis, services_public.api_schemas, and metaschema_public.schema + * to get the actual PostgreSQL schema names for the given API names. + * + * @param pool - Database connection pool + * @param apiNames - Array of API names to resolve + * @returns Array of PostgreSQL schema names + * @throws Error if validation fails or no schemas found + */ +export async function resolveApiSchemas( + pool: Pool, + apiNames: string[] +): Promise { + // First validate that the required schemas exist + const validation = await validateServicesSchemas(pool); + if (!validation.valid) { + throw new Error(validation.error); + } + + // Query to get schema names for the given API names + const result = await pool.query<{ schema_name: string }>( + ` + SELECT DISTINCT ms.schema_name + FROM services_public.api_schemas as_tbl + JOIN services_public.apis api ON api.id = as_tbl.api_id + JOIN metaschema_public.schema ms ON ms.id = as_tbl.schema_id + WHERE api.name = ANY($1) + ORDER BY ms.schema_name + `, + [apiNames] + ); + + if (result.rows.length === 0) { + throw new Error( + `No schemas found for API names: ${apiNames.join(', ')}. ` + + 'Ensure the APIs exist and have schemas assigned in services_public.api_schemas.' + ); + } + + return result.rows.map((row) => row.schema_name); +} + +/** + * Create a database pool for the given database name or connection string + * + * @param database - Database name or connection string + * @returns Database connection pool + */ +export function createDatabasePool(database: string): Pool { + // Check if it's a connection string or just a database name + const isConnectionString = database.startsWith('postgres://') || database.startsWith('postgresql://'); + + if (isConnectionString) { + // Parse connection string and extract database name + // Format: postgres://user:password@host:port/database + const url = new URL(database); + const dbName = url.pathname.slice(1); // Remove leading slash + return getPgPool({ + host: url.hostname, + port: parseInt(url.port || '5432', 10), + user: url.username, + password: url.password, + database: dbName, + }); + } + + // Use environment variables for connection, just override database name + const config = getPgEnvOptions({ database }); + return getPgPool(config); +} diff --git a/graphql/codegen/src/core/introspect/source/database.ts b/graphql/codegen/src/core/introspect/source/database.ts index 223633b20..4b77ea12e 100644 --- a/graphql/codegen/src/core/introspect/source/database.ts +++ b/graphql/codegen/src/core/introspect/source/database.ts @@ -9,6 +9,7 @@ import type { SchemaSource, SchemaSourceResult } from './types'; import { SchemaSourceError } from './types'; import type { IntrospectionQueryResponse } from '../../../types/introspection'; import { buildSchemaSDLFromDatabase } from '../../database'; +import { createDatabasePool, resolveApiSchemas, validateServicesSchemas } from './api-schemas'; export interface DatabaseSchemaSourceOptions { /** @@ -20,9 +21,16 @@ export interface DatabaseSchemaSourceOptions { /** * PostgreSQL schemas to include in introspection - * @default ['public'] + * Mutually exclusive with apiNames */ schemas?: string[]; + + /** + * API names to resolve schemas from + * Queries services_public.api_schemas to get schema names + * Mutually exclusive with schemas + */ + apiNames?: string[]; } /** @@ -39,7 +47,30 @@ export class DatabaseSchemaSource implements SchemaSource { } async fetch(): Promise { - const { database, schemas = ['public'] } = this.options; + const { database, apiNames } = this.options; + + // Resolve schemas - either from explicit schemas option or from apiNames + let schemas: string[]; + if (apiNames && apiNames.length > 0) { + // Validate services schemas exist at the beginning for database mode + const pool = createDatabasePool(database); + try { + const validation = await validateServicesSchemas(pool); + if (!validation.valid) { + throw new SchemaSourceError(validation.error!, this.describe()); + } + schemas = await resolveApiSchemas(pool, apiNames); + } catch (err) { + if (err instanceof SchemaSourceError) throw err; + throw new SchemaSourceError( + `Failed to resolve API schemas: ${err instanceof Error ? err.message : 'Unknown error'}`, + this.describe(), + err instanceof Error ? err : undefined + ); + } + } else { + schemas = this.options.schemas ?? ['public']; + } // Build SDL from database let sdl: string; @@ -97,7 +128,10 @@ export class DatabaseSchemaSource implements SchemaSource { } describe(): string { - const { database, schemas = ['public'] } = this.options; - return `database: ${database} (schemas: ${schemas.join(', ')})`; + const { database, schemas, apiNames } = this.options; + if (apiNames && apiNames.length > 0) { + return `database: ${database} (apiNames: ${apiNames.join(', ')})`; + } + return `database: ${database} (schemas: ${(schemas ?? ['public']).join(', ')})`; } } diff --git a/graphql/codegen/src/core/introspect/source/index.ts b/graphql/codegen/src/core/introspect/source/index.ts index 422174236..24a2f71d2 100644 --- a/graphql/codegen/src/core/introspect/source/index.ts +++ b/graphql/codegen/src/core/introspect/source/index.ts @@ -12,6 +12,7 @@ export * from './endpoint'; export * from './file'; export * from './database'; export * from './pgpm-module'; +export * from './api-schemas'; import type { SchemaSource } from './types'; import { EndpointSchemaSource } from './endpoint'; @@ -46,6 +47,7 @@ export interface FileSourceOptions { export interface DatabaseSourceOptions { database: string; schemas?: string[]; + apiNames?: string[]; } /** @@ -54,6 +56,7 @@ export interface DatabaseSourceOptions { export interface PgpmModulePathSourceOptions { pgpmModulePath: string; schemas?: string[]; + apiNames?: string[]; keepDb?: boolean; } @@ -64,6 +67,7 @@ export interface PgpmWorkspaceSourceOptions { pgpmWorkspacePath: string; pgpmModuleName: string; schemas?: string[]; + apiNames?: string[]; keepDb?: boolean; } @@ -101,10 +105,17 @@ export interface CreateSchemaSourceOptions { /** * PostgreSQL schemas to include (for database and pgpm module modes) - * @default ['public'] + * Mutually exclusive with apiNames - exactly one must be provided for database/pgpm modes */ schemas?: string[]; + /** + * API names to resolve schemas from (for database and pgpm module modes) + * Queries services_public.api_schemas to get schema names for the given APIs + * Mutually exclusive with schemas - exactly one must be provided for database/pgpm modes + */ + apiNames?: string[]; + /** * Keep the ephemeral database after introspection (for debugging, pgpm module mode only) * @default false @@ -178,12 +189,14 @@ export function createSchemaSource( return new DatabaseSchemaSource({ database: options.database!, schemas: options.schemas, + apiNames: options.apiNames, }); case 'pgpm-module': return new PgpmModuleSchemaSource({ pgpmModulePath: options.pgpmModulePath!, schemas: options.schemas, + apiNames: options.apiNames, keepDb: options.keepDb, }); @@ -192,6 +205,7 @@ export function createSchemaSource( pgpmWorkspacePath: options.pgpmWorkspacePath!, pgpmModuleName: options.pgpmModuleName!, schemas: options.schemas, + apiNames: options.apiNames, keepDb: options.keepDb, }); @@ -252,5 +266,26 @@ export function validateSourceOptions(options: CreateSchemaSourceOptions): { }; } + // For database and pgpm modes, validate schemas/apiNames mutual exclusivity + const isDatabaseOrPgpmMode = options.database || options.pgpmModulePath || hasPgpmWorkspace; + if (isDatabaseOrPgpmMode) { + const hasSchemas = options.schemas && options.schemas.length > 0; + const hasApiNames = options.apiNames && options.apiNames.length > 0; + + if (hasSchemas && hasApiNames) { + return { + valid: false, + error: 'Cannot specify both schemas and apiNames. Use one or the other.', + }; + } + + if (!hasSchemas && !hasApiNames) { + return { + valid: false, + error: 'Must specify either schemas or apiNames for database/pgpm modes.', + }; + } + } + return { valid: true }; } diff --git a/graphql/codegen/src/core/introspect/source/pgpm-module.ts b/graphql/codegen/src/core/introspect/source/pgpm-module.ts index 5b12a2699..a246d769f 100644 --- a/graphql/codegen/src/core/introspect/source/pgpm-module.ts +++ b/graphql/codegen/src/core/introspect/source/pgpm-module.ts @@ -11,11 +11,13 @@ import { buildSchema, introspectionFromSchema } from 'graphql'; import { PgpmPackage } from '@pgpmjs/core'; import { createEphemeralDb, type EphemeralDbResult } from 'pgsql-client'; import { deployPgpm } from 'pgsql-seed'; +import { getPgPool } from 'pg-cache'; import type { SchemaSource, SchemaSourceResult } from './types'; import { SchemaSourceError } from './types'; import type { IntrospectionQueryResponse } from '../../../types/introspection'; import { buildSchemaSDLFromDatabase } from '../../database'; +import { resolveApiSchemas, validateServicesSchemas } from './api-schemas'; /** * Options for PGPM module schema source using direct module path @@ -29,10 +31,17 @@ export interface PgpmModulePathOptions { /** * PostgreSQL schemas to include in introspection - * @default ['public'] + * Mutually exclusive with apiNames */ schemas?: string[]; + /** + * API names to resolve schemas from + * Queries services_public.api_schemas to get schema names + * Mutually exclusive with schemas + */ + apiNames?: string[]; + /** * If true, keeps the ephemeral database after introspection (useful for debugging) * @default false @@ -57,10 +66,17 @@ export interface PgpmWorkspaceOptions { /** * PostgreSQL schemas to include in introspection - * @default ['public'] + * Mutually exclusive with apiNames */ schemas?: string[]; + /** + * API names to resolve schemas from + * Queries services_public.api_schemas to get schema names + * Mutually exclusive with schemas + */ + apiNames?: string[]; + /** * If true, keeps the ephemeral database after introspection (useful for debugging) * @default false @@ -103,8 +119,8 @@ export class PgpmModuleSchemaSource implements SchemaSource { } async fetch(): Promise { - const schemas = this.getSchemas(); const keepDb = this.getKeepDb(); + const apiNames = this.getApiNames(); // Resolve the module path let modulePath: string; @@ -155,6 +171,29 @@ export class PgpmModuleSchemaSource implements SchemaSource { ); } + // Resolve schemas - either from explicit schemas option or from apiNames (after deployment) + let schemas: string[]; + if (apiNames && apiNames.length > 0) { + // For PGPM mode, validate services schemas AFTER migration + const pool = getPgPool(dbConfig); + try { + const validation = await validateServicesSchemas(pool); + if (!validation.valid) { + throw new SchemaSourceError(validation.error!, this.describe()); + } + schemas = await resolveApiSchemas(pool, apiNames); + } catch (err) { + if (err instanceof SchemaSourceError) throw err; + throw new SchemaSourceError( + `Failed to resolve API schemas: ${err instanceof Error ? err.message : 'Unknown error'}`, + this.describe(), + err instanceof Error ? err : undefined + ); + } + } else { + schemas = this.getSchemas(); + } + // Build SDL from the deployed database let sdl: string; try { @@ -219,10 +258,17 @@ export class PgpmModuleSchemaSource implements SchemaSource { } describe(): string { + const apiNames = this.getApiNames(); if (isPgpmModulePathOptions(this.options)) { + if (apiNames && apiNames.length > 0) { + return `pgpm module: ${this.options.pgpmModulePath} (apiNames: ${apiNames.join(', ')})`; + } const schemas = this.options.schemas ?? ['public']; return `pgpm module: ${this.options.pgpmModulePath} (schemas: ${schemas.join(', ')})`; } else { + if (apiNames && apiNames.length > 0) { + return `pgpm workspace: ${this.options.pgpmWorkspacePath}, module: ${this.options.pgpmModuleName} (apiNames: ${apiNames.join(', ')})`; + } const schemas = this.options.schemas ?? ['public']; return `pgpm workspace: ${this.options.pgpmWorkspacePath}, module: ${this.options.pgpmModuleName} (schemas: ${schemas.join(', ')})`; } @@ -259,6 +305,13 @@ export class PgpmModuleSchemaSource implements SchemaSource { return this.options.schemas ?? ['public']; } + private getApiNames(): string[] | undefined { + if (isPgpmModulePathOptions(this.options)) { + return this.options.apiNames; + } + return this.options.apiNames; + } + private getKeepDb(): boolean { if (isPgpmModulePathOptions(this.options)) { return this.options.keepDb ?? false; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2483df7c8..cda8350a4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -763,6 +763,12 @@ importers: jiti: specifier: ^2.6.1 version: 2.6.1 + pg-cache: + specifier: workspace:^ + version: link:../../postgres/pg-cache/dist + pg-env: + specifier: workspace:^ + version: link:../../postgres/pg-env/dist pgsql-client: specifier: workspace:^ version: link:../../postgres/pgsql-client/dist From 5a664841cae12ffab7fd2a33fdb8d887e75ea885 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 23 Jan 2026 10:19:45 +0000 Subject: [PATCH 09/23] feat(graphql-codegen): add unified generate function with --reactquery and --orm flags - Create unified generate() function that respects config.reactQuery.enabled and orm.enabled - Simplify CLI to use single 'generate' command with --reactquery and --orm flags - Remove old 'generate-orm' command (now unified into 'generate') - Add CLI support for new source options: --database, --pgpm-module-path, --pgpm-workspace-path, --pgpm-module-name - Add CLI support for schema options: --schemas, --api-names - Update help text with comprehensive documentation - Update README with new CLI usage examples - Update package.json example scripts --- graphql/codegen/README.md | 77 +-- graphql/codegen/package.json | 10 +- .../src/cli/commands/generate-unified.ts | 512 ++++++++++++++++++ graphql/codegen/src/cli/commands/index.ts | 9 +- graphql/codegen/src/cli/index.ts | 274 ++++------ graphql/codegen/src/index.ts | 4 +- 6 files changed, 671 insertions(+), 215 deletions(-) create mode 100644 graphql/codegen/src/cli/commands/generate-unified.ts diff --git a/graphql/codegen/README.md b/graphql/codegen/README.md index 100495d74..b307a2e23 100644 --- a/graphql/codegen/README.md +++ b/graphql/codegen/README.md @@ -12,7 +12,7 @@

-CLI-based GraphQL SDK generator for PostGraphile endpoints. Generate type-safe React Query hooks or a Prisma-like ORM client from your GraphQL schema. +GraphQL SDK generator for Constructive databases with React Query hooks. Generate type-safe React Query hooks or a Prisma-like ORM client from your GraphQL schema. ## Features @@ -79,11 +79,20 @@ export default defineConfig({ ### 2. Generate SDK ```bash -# Generate React Query hooks -npx graphql-sdk generate -e https://api.example.com/graphql -o ./generated/hooks +# Generate React Query hooks from an endpoint +npx graphql-sdk generate --endpoint https://api.example.com/graphql --output ./generated/hooks --reactquery -# Generate ORM client -npx graphql-sdk generate-orm -e https://api.example.com/graphql -o ./generated/orm +# Generate ORM client from an endpoint +npx graphql-sdk generate --endpoint https://api.example.com/graphql --output ./generated/orm --orm + +# Generate from a database directly +npx graphql-sdk generate --database postgres://localhost/mydb --schemas public,app_public --reactquery + +# Generate from a PGPM module +npx graphql-sdk generate --pgpm-module-path ./packages/my-module --schemas public --orm + +# Generate using apiNames for automatic schema discovery +npx graphql-sdk generate --database postgres://localhost/mydb --api-names my_api --reactquery --orm ``` ### 3. Use the Generated Code @@ -112,34 +121,40 @@ function CarList() { ### `graphql-sdk generate` -Generate React Query hooks from a PostGraphile endpoint. +Generate React Query hooks and/or ORM client from various sources. ```bash -Options: - -e, --endpoint GraphQL endpoint URL (overrides config) - -t, --target Target name in config file - -o, --output Output directory (default: ./generated/graphql) - -c, --config Path to config file - -a, --authorization Authorization header value - --dry-run Preview without writing files - --skip-custom-operations Only generate table CRUD hooks - -v, --verbose Show detailed output -``` - -### `graphql-sdk generate-orm` - -Generate Prisma-like ORM client from a PostGraphile endpoint. - -```bash -Options: - -e, --endpoint GraphQL endpoint URL - -t, --target Target name in config file - -o, --output Output directory (default: ./generated/orm) - -c, --config Path to config file - -a, --authorization Authorization header value - --skip-custom-operations Only generate table models - --dry-run Preview without writing files - -v, --verbose Show detailed output +Source Options (choose one): + -c, --config Path to config file (graphql-sdk.config.ts) + -e, --endpoint GraphQL endpoint URL + -s, --schema Path to GraphQL schema file + --database Database connection URL (postgres://...) + --pgpm-module-path Path to PGPM module directory + --pgpm-workspace-path Path to PGPM workspace (requires --pgpm-module-name) + --pgpm-module-name PGPM module name in workspace + +Schema Options (for database/pgpm modes): + --schemas Comma-separated list of schemas to introspect + --api-names Comma-separated API names for automatic schema discovery + (mutually exclusive with --schemas) + +Generator Options: + --reactquery Generate React Query hooks + --orm Generate ORM client + -t, --target Target name in config file + -o, --output Output directory + -a, --authorization Authorization header value + --skip-custom-operations Only generate table CRUD operations + --dry-run Preview without writing files + --keep-db Keep ephemeral database after generation (pgpm modes) + -v, --verbose Show detailed output + +Watch Mode Options: + -w, --watch Watch for schema changes and regenerate + --poll-interval Polling interval in milliseconds (default: 5000) + --debounce Debounce delay in milliseconds (default: 500) + --touch Touch file after regeneration + --no-clear Don't clear console on regeneration ``` ### `graphql-sdk init` diff --git a/graphql/codegen/package.json b/graphql/codegen/package.json index fb13f745d..59a882193 100644 --- a/graphql/codegen/package.json +++ b/graphql/codegen/package.json @@ -1,7 +1,7 @@ { "name": "@constructive-io/graphql-codegen", "version": "2.32.0", - "description": "CLI-based GraphQL SDK generator for PostGraphile endpoints with React Query hooks", + "description": "GraphQL SDK generator for Constructive databases with React Query hooks", "keywords": [ "graphql", "postgraphile", @@ -44,10 +44,10 @@ "fmt:check": "prettier --check .", "test": "jest --passWithNoTests", "test:watch": "jest --watch", - "example:codegen:sdk": "tsx src/cli/index.ts generate --config examples/multi-target.config.ts", - "example:codegen:orm": "tsx src/cli/index.ts generate-orm --config examples/multi-target.config.ts", - "example:codegen:sdk:schema": "node dist/cli/index.js generate --schema examples/example.schema.graphql --output examples/output/generated-sdk-schema", - "example:codegen:orm:schema": "node dist/cli/index.js generate-orm --schema examples/example.schema.graphql --output examples/output/generated-orm-schema", + "example:codegen:sdk": "tsx src/cli/index.ts generate --config examples/multi-target.config.ts --reactquery", + "example:codegen:orm": "tsx src/cli/index.ts generate --config examples/multi-target.config.ts --orm", + "example:codegen:sdk:schema": "node dist/cli/index.js generate --schema examples/example.schema.graphql --output examples/output/generated-sdk-schema --reactquery", + "example:codegen:orm:schema": "node dist/cli/index.js generate --schema examples/example.schema.graphql --output examples/output/generated-orm-schema --orm", "example:sdk": "tsx examples/react-hooks-sdk-test.tsx", "example:orm": "tsx examples/orm-sdk-test.ts", "example:sdk:typecheck": "tsc --noEmit --jsx react --esModuleInterop --skipLibCheck --moduleResolution node examples/react-hooks-sdk-test.tsx" diff --git a/graphql/codegen/src/cli/commands/generate-unified.ts b/graphql/codegen/src/cli/commands/generate-unified.ts new file mode 100644 index 000000000..51b683a7e --- /dev/null +++ b/graphql/codegen/src/cli/commands/generate-unified.ts @@ -0,0 +1,512 @@ +/** + * Unified generate command - generates SDK from GraphQL schema + * + * This is a thin CLI wrapper around the core generation functions. + * Supports generating React Query SDK, ORM client, or both based on config flags. + */ +import type { ResolvedTargetConfig, ResolvedConfig } from '../../types/config'; +import { + loadAndResolveConfig, + type ConfigOverrideOptions, +} from '../../core/config'; +import { + createSchemaSource, + validateSourceOptions, +} from '../../core/introspect'; +import { runCodegenPipeline, validateTablesFound } from '../../core/pipeline'; +import { generate as generateReactQueryFiles } from '../../core/codegen'; +import { generateOrm as generateOrmFiles } from '../../core/codegen/orm'; +import { writeGeneratedFiles } from '../../core/output'; +import type { CleanTable, CleanOperation, TypeRegistry } from '../../types/schema'; + +export type GeneratorType = 'react-query' | 'orm'; + +export interface GenerateOptions extends ConfigOverrideOptions { + /** Authorization header */ + authorization?: string; + /** Verbose output */ + verbose?: boolean; + /** Dry run - don't write files */ + dryRun?: boolean; + /** Skip custom operations (only generate table CRUD) */ + skipCustomOperations?: boolean; + /** Override: generate React Query SDK regardless of config */ + reactQuery?: boolean; + /** Override: generate ORM client regardless of config */ + orm?: boolean; +} + +export interface GenerateTargetResult { + name: string; + output: string; + generatorType: GeneratorType; + success: boolean; + message: string; + tables?: string[]; + customQueries?: string[]; + customMutations?: string[]; + filesWritten?: string[]; + errors?: string[]; +} + +export interface GenerateResult { + success: boolean; + message: string; + targets?: GenerateTargetResult[]; + tables?: string[]; + customQueries?: string[]; + customMutations?: string[]; + filesWritten?: string[]; + errors?: string[]; +} + +interface PipelineResult { + tables: CleanTable[]; + customOperations: { + queries: CleanOperation[]; + mutations: CleanOperation[]; + typeRegistry: TypeRegistry; + }; + stats: { + customQueries: number; + customMutations: number; + }; +} + +/** + * Unified generate function that respects config.reactQuery.enabled and config.orm.enabled + * + * Can generate React Query SDK, ORM client, or both based on configuration. + * Use the `reactQuery` and `orm` options to override config flags. + */ +export async function generate( + options: GenerateOptions = {} +): Promise { + if (options.verbose) { + console.log('Loading configuration...'); + } + + const configResult = await loadAndResolveConfig(options); + if (!configResult.success) { + return { + success: false, + message: configResult.error!, + }; + } + + const targets = configResult.targets ?? []; + if (targets.length === 0) { + return { + success: false, + message: 'No targets resolved from configuration.', + }; + } + + const isMultiTarget = configResult.isMulti ?? targets.length > 1; + const results: GenerateTargetResult[] = []; + + for (const target of targets) { + // Determine which generators to run based on config and options + const runReactQuery = options.reactQuery ?? target.config.reactQuery.enabled; + const runOrm = options.orm ?? target.config.orm.enabled; + + if (!runReactQuery && !runOrm) { + results.push({ + name: target.name, + output: target.config.output, + generatorType: 'react-query', + success: false, + message: `Target "${target.name}": No generators enabled. Set reactQuery.enabled or orm.enabled in config, or use --reactquery or --orm flags.`, + }); + continue; + } + + // Run pipeline once per target (shared between generators) + const pipelineResult = await runPipelineForTarget(target, options, isMultiTarget); + if (!pipelineResult.success) { + results.push({ + name: target.name, + output: target.config.output, + generatorType: 'react-query', + success: false, + message: pipelineResult.error!, + }); + continue; + } + + // Generate React Query SDK if enabled + if (runReactQuery) { + const result = await generateReactQueryForTarget( + target, + pipelineResult.data!, + options, + isMultiTarget + ); + results.push(result); + } + + // Generate ORM client if enabled + if (runOrm) { + const result = await generateOrmForTarget( + target, + pipelineResult.data!, + options, + isMultiTarget + ); + results.push(result); + } + } + + // Build summary + const successCount = results.filter((r) => r.success).length; + const failedCount = results.length - successCount; + + if (results.length === 1) { + const [result] = results; + return { + success: result.success, + message: result.message, + targets: results, + tables: result.tables, + customQueries: result.customQueries, + customMutations: result.customMutations, + filesWritten: result.filesWritten, + errors: result.errors, + }; + } + + const summaryMessage = + failedCount === 0 + ? `Generated ${results.length} outputs successfully.` + : `Generated ${successCount} of ${results.length} outputs.`; + + return { + success: failedCount === 0, + message: summaryMessage, + targets: results, + errors: + failedCount > 0 + ? results.flatMap((r) => r.errors ?? []) + : undefined, + }; +} + +/** + * Generate React Query SDK only (convenience wrapper) + */ +export async function generateReactQuery( + options: GenerateOptions = {} +): Promise { + return generate({ ...options, reactQuery: true, orm: false }); +} + +/** + * Generate ORM client only (convenience wrapper) + */ +export async function generateOrm( + options: GenerateOptions = {} +): Promise { + return generate({ ...options, reactQuery: false, orm: true }); +} + +// ============================================================================ +// Internal helpers +// ============================================================================ + +interface PipelineRunResult { + success: boolean; + error?: string; + data?: PipelineResult; +} + +async function runPipelineForTarget( + target: ResolvedTargetConfig, + options: GenerateOptions, + isMultiTarget: boolean +): Promise { + const config = target.config; + const prefix = isMultiTarget ? `[${target.name}] ` : ''; + const formatMessage = (message: string) => + isMultiTarget ? `Target "${target.name}": ${message}` : message; + + // Extract extended options if present (attached by config resolver) + const database = (config as any).database as string | undefined; + const schemas = (config as any).schemas as string[] | undefined; + const apiNames = (config as any).apiNames as string[] | undefined; + const pgpmModulePath = (config as any).pgpmModulePath as string | undefined; + const pgpmWorkspacePath = (config as any).pgpmWorkspacePath as string | undefined; + const pgpmModuleName = (config as any).pgpmModuleName as string | undefined; + const keepDb = (config as any).keepDb as boolean | undefined; + + if (isMultiTarget) { + console.log(`\nTarget "${target.name}"`); + let sourceLabel: string; + const schemaInfo = apiNames && apiNames.length > 0 + ? `apiNames: ${apiNames.join(', ')}` + : `schemas: ${(schemas ?? ['public']).join(', ')}`; + if (pgpmModulePath) { + sourceLabel = `pgpm module: ${pgpmModulePath} (${schemaInfo})`; + } else if (pgpmWorkspacePath && pgpmModuleName) { + sourceLabel = `pgpm workspace: ${pgpmWorkspacePath}, module: ${pgpmModuleName} (${schemaInfo})`; + } else if (database) { + sourceLabel = `database: ${database} (${schemaInfo})`; + } else if (config.schema) { + sourceLabel = `schema: ${config.schema}`; + } else { + sourceLabel = `endpoint: ${config.endpoint}`; + } + console.log(` Source: ${sourceLabel}`); + } + + // 1. Validate source + const sourceValidation = validateSourceOptions({ + endpoint: config.endpoint || undefined, + schema: config.schema || undefined, + database, + pgpmModulePath, + pgpmWorkspacePath, + pgpmModuleName, + schemas, + apiNames, + }); + if (!sourceValidation.valid) { + return { + success: false, + error: formatMessage(sourceValidation.error!), + }; + } + + const source = createSchemaSource({ + endpoint: config.endpoint || undefined, + schema: config.schema || undefined, + database, + pgpmModulePath, + pgpmWorkspacePath, + pgpmModuleName, + schemas, + apiNames, + keepDb, + authorization: options.authorization || config.headers['Authorization'], + headers: config.headers, + }); + + // 2. Run the codegen pipeline + let pipelineResult; + try { + console.log(`${prefix}Fetching schema...`); + pipelineResult = await runCodegenPipeline({ + source, + config, + verbose: options.verbose, + skipCustomOperations: options.skipCustomOperations, + }); + } catch (err) { + return { + success: false, + error: formatMessage( + `Failed to fetch schema: ${err instanceof Error ? err.message : 'Unknown error'}` + ), + }; + } + + const { tables, customOperations, stats } = pipelineResult; + + // 3. Validate tables found + const tablesValidation = validateTablesFound(tables); + if (!tablesValidation.valid) { + return { + success: false, + error: formatMessage(tablesValidation.error!), + }; + } + + return { + success: true, + data: { tables, customOperations, stats }, + }; +} + +async function generateReactQueryForTarget( + target: ResolvedTargetConfig, + pipelineResult: PipelineResult, + options: GenerateOptions, + isMultiTarget: boolean +): Promise { + const config = target.config; + const prefix = isMultiTarget ? `[${target.name}] ` : ''; + const log = options.verbose + ? (message: string) => console.log(`${prefix}${message}`) + : () => {}; + const formatMessage = (message: string) => + isMultiTarget ? `Target "${target.name}": ${message}` : message; + + const { tables, customOperations, stats } = pipelineResult; + + // Generate React Query SDK + console.log(`${prefix}Generating React Query SDK...`); + const { files: generatedFiles, stats: genStats } = generateReactQueryFiles({ + tables, + customOperations: { + queries: customOperations.queries, + mutations: customOperations.mutations, + typeRegistry: customOperations.typeRegistry, + }, + config, + }); + console.log(`${prefix}Generated ${genStats.totalFiles} files`); + + log(` ${genStats.queryHooks} table query hooks`); + log(` ${genStats.mutationHooks} table mutation hooks`); + log(` ${genStats.customQueryHooks} custom query hooks`); + log(` ${genStats.customMutationHooks} custom mutation hooks`); + + const customQueries = customOperations.queries.map((q) => q.name); + const customMutations = customOperations.mutations.map((m) => m.name); + + if (options.dryRun) { + return { + name: target.name, + output: config.output, + generatorType: 'react-query', + success: true, + message: formatMessage( + `Dry run complete. Would generate ${generatedFiles.length} files for ${tables.length} tables and ${stats.customQueries + stats.customMutations} custom operations.` + ), + tables: tables.map((t) => t.name), + customQueries, + customMutations, + filesWritten: generatedFiles.map((f) => f.path), + }; + } + + // Write files + log('Writing files...'); + console.log(`${prefix}Output: ${config.output}`); + const writeResult = await writeGeneratedFiles(generatedFiles, config.output, [ + 'queries', + 'mutations', + ]); + + if (!writeResult.success) { + return { + name: target.name, + output: config.output, + generatorType: 'react-query', + success: false, + message: formatMessage( + `Failed to write files: ${writeResult.errors?.join(', ')}` + ), + errors: writeResult.errors, + }; + } + + const totalOps = customQueries.length + customMutations.length; + const customOpsMsg = totalOps > 0 ? ` and ${totalOps} custom operations` : ''; + + return { + name: target.name, + output: config.output, + generatorType: 'react-query', + success: true, + message: formatMessage( + `Generated React Query SDK for ${tables.length} tables${customOpsMsg}. Files written to ${config.output}` + ), + tables: tables.map((t) => t.name), + customQueries, + customMutations, + filesWritten: writeResult.filesWritten, + }; +} + +async function generateOrmForTarget( + target: ResolvedTargetConfig, + pipelineResult: PipelineResult, + options: GenerateOptions, + isMultiTarget: boolean +): Promise { + const config = target.config; + const outputDir = options.output || config.orm.output; + const prefix = isMultiTarget ? `[${target.name}] ` : ''; + const log = options.verbose + ? (message: string) => console.log(`${prefix}${message}`) + : () => {}; + const formatMessage = (message: string) => + isMultiTarget ? `Target "${target.name}": ${message}` : message; + + const { tables, customOperations, stats } = pipelineResult; + + // Generate ORM client + console.log(`${prefix}Generating ORM client...`); + const { files: generatedFiles, stats: genStats } = generateOrmFiles({ + tables, + customOperations: { + queries: customOperations.queries, + mutations: customOperations.mutations, + typeRegistry: customOperations.typeRegistry, + }, + config, + }); + console.log(`${prefix}Generated ${genStats.totalFiles} files`); + + log(` ${genStats.tables} table models`); + log(` ${genStats.customQueries} custom query operations`); + log(` ${genStats.customMutations} custom mutation operations`); + + const customQueries = customOperations.queries.map((q) => q.name); + const customMutations = customOperations.mutations.map((m) => m.name); + + if (options.dryRun) { + return { + name: target.name, + output: outputDir, + generatorType: 'orm', + success: true, + message: formatMessage( + `Dry run complete. Would generate ${generatedFiles.length} files for ${tables.length} tables and ${stats.customQueries + stats.customMutations} custom operations.` + ), + tables: tables.map((t) => t.name), + customQueries, + customMutations, + filesWritten: generatedFiles.map((f) => f.path), + }; + } + + // Write files + log('Writing files...'); + console.log(`${prefix}Output: ${outputDir}`); + const writeResult = await writeGeneratedFiles(generatedFiles, outputDir, [ + 'models', + 'query', + 'mutation', + ]); + + if (!writeResult.success) { + return { + name: target.name, + output: outputDir, + generatorType: 'orm', + success: false, + message: formatMessage( + `Failed to write files: ${writeResult.errors?.join(', ')}` + ), + errors: writeResult.errors, + }; + } + + const totalOps = customQueries.length + customMutations.length; + const customOpsMsg = totalOps > 0 ? ` and ${totalOps} custom operations` : ''; + + return { + name: target.name, + output: outputDir, + generatorType: 'orm', + success: true, + message: formatMessage( + `Generated ORM client for ${tables.length} tables${customOpsMsg}. Files written to ${outputDir}` + ), + tables: tables.map((t) => t.name), + customQueries, + customMutations, + filesWritten: writeResult.filesWritten, + }; +} diff --git a/graphql/codegen/src/cli/commands/index.ts b/graphql/codegen/src/cli/commands/index.ts index bb15eb3a7..dee4025fa 100644 --- a/graphql/codegen/src/cli/commands/index.ts +++ b/graphql/codegen/src/cli/commands/index.ts @@ -5,8 +5,11 @@ export { initCommand, findConfigFile, loadConfigFile } from './init'; export type { InitOptions, InitResult } from './init'; -export { generateReactQuery } from './generate'; -export type { GenerateOptions, GenerateResult, GenerateTargetResult } from './generate'; +// Unified generate function (recommended) +export { generate, generateReactQuery, generateOrm } from './generate-unified'; +export type { GenerateOptions, GenerateResult, GenerateTargetResult, GeneratorType } from './generate-unified'; -export { generateOrm } from './generate-orm'; +// Legacy exports (deprecated - use unified generate instead) +export { generateReactQuery as generateReactQueryLegacy } from './generate'; +export { generateOrm as generateOrmLegacy } from './generate-orm'; export type { GenerateOrmOptions, GenerateOrmResult, GenerateOrmTargetResult } from './generate-orm'; diff --git a/graphql/codegen/src/cli/index.ts b/graphql/codegen/src/cli/index.ts index 6c7a4c868..592f2faa0 100644 --- a/graphql/codegen/src/cli/index.ts +++ b/graphql/codegen/src/cli/index.ts @@ -6,23 +6,21 @@ import { CLI, CLIOptions, Inquirerer, ParsedArgs, cliExitWithError, extractFirst, getPackageJson } from 'inquirerer'; import { initCommand } from './commands/init'; -import { generateReactQuery } from './commands/generate'; -import { generateOrm } from './commands/generate-orm'; +import { generate, generateReactQuery, generateOrm } from './commands/generate-unified'; import { loadWatchConfig } from '../core/config'; import { startWatch } from '../core/watch'; import { createSchemaSource, inferTablesFromIntrospection } from '../core/introspect'; import type { ResolvedConfig } from '../types/config'; const usageText = ` -graphql-codegen - CLI for generating GraphQL SDK from PostGraphile endpoints or schema files +graphql-codegen - GraphQL SDK generator for Constructive databases Usage: graphql-codegen [options] Commands: init Initialize a new graphql-codegen configuration file - generate Generate SDK from GraphQL endpoint or schema file - generate-orm Generate Prisma-like ORM client from GraphQL endpoint or schema file + generate Generate SDK from GraphQL endpoint, schema file, database, or PGPM module introspect Introspect a GraphQL endpoint or schema file and print table info Options: @@ -47,50 +45,49 @@ Options: `; const generateUsageText = ` -graphql-codegen generate - Generate SDK from GraphQL endpoint or schema file +graphql-codegen generate - Generate SDK from GraphQL endpoint, schema file, database, or PGPM module Usage: graphql-codegen generate [options] -Options: +Source Options (choose one): --config, -c Path to config file - --target, -t Target name in config file - --endpoint, -e GraphQL endpoint URL (overrides config) + --endpoint, -e GraphQL endpoint URL --schema, -s Path to GraphQL schema file (.graphql) - --output, -o Output directory (overrides config) - --authorization, -a
Authorization header value - --verbose, -v Verbose output - --dry-run Dry run - show what would be generated without writing files - --watch, -w Watch mode - poll endpoint for schema changes (in-memory) - --poll-interval Polling interval in milliseconds (default: 3000) - --debounce Debounce delay before regenerating (default: 800) - --touch File to touch on schema change - --no-clear Do not clear terminal on regeneration - --help, -h Show this help message -`; - -const generateOrmUsageText = ` -graphql-codegen generate-orm - Generate Prisma-like ORM client from GraphQL endpoint or schema file - -Usage: - graphql-codegen generate-orm [options] - -Options: - --config, -c Path to config file + --database Database name or connection string + --pgpm-module-path Path to PGPM module (creates ephemeral database) + --pgpm-workspace-path Path to PGPM workspace (use with --pgpm-module-name) + --pgpm-module-name Module name in workspace (use with --pgpm-workspace-path) + +Schema Options (for database/PGPM modes): + --schemas Comma-separated list of schemas to introspect (default: public) + --api-names Comma-separated list of API names (auto-resolves schemas from services_public.api_schemas) + +Generator Options: + --reactquery Generate React Query SDK (hooks + fetch functions) + --orm Generate Prisma-like ORM client --target, -t Target name in config file - --endpoint, -e GraphQL endpoint URL (overrides config) - --schema, -s Path to GraphQL schema file (.graphql) --output, -o Output directory (overrides config) --authorization, -a
Authorization header value - --verbose, -v Verbose output + --verbose Verbose output --dry-run Dry run - show what would be generated without writing files --skip-custom-operations Skip custom operations (only generate table CRUD) - --watch, -w Watch mode - poll endpoint for schema changes (in-memory) + --keep-db Keep ephemeral database after generation (for debugging) + +Watch Mode Options: + --watch, -w Watch mode - poll endpoint for schema changes --poll-interval Polling interval in milliseconds (default: 3000) --debounce Debounce delay before regenerating (default: 800) --touch File to touch on schema change --no-clear Do not clear terminal on regeneration + --help, -h Show this help message + +Examples: + graphql-codegen generate --endpoint http://localhost:5000/graphql --reactquery + graphql-codegen generate --database mydb --schemas public,app_public --orm + graphql-codegen generate --pgpm-module-path ./my-module --api-names my_api --reactquery --orm + graphql-codegen generate --config ./graphql-codegen.config.ts `; const introspectUsageText = ` @@ -147,7 +144,7 @@ async function handleInit(argv: Partial): Promise { } /** - * Generate command handler + * Generate command handler - unified handler for React Query SDK and ORM generation */ async function handleGenerate(argv: Partial): Promise { if (argv.help || argv.h) { @@ -157,14 +154,33 @@ async function handleGenerate(argv: Partial): Promise { const startTime = performance.now(); + // Source options const config = (argv.config as string) || (argv.c as string); const target = (argv.target as string) || (argv.t as string); const endpoint = (argv.endpoint as string) || (argv.e as string); const schema = (argv.schema as string) || (argv.s as string); + const database = argv.database as string | undefined; + 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; + + // Schema options + const schemasArg = argv.schemas as string | undefined; + const schemas = schemasArg ? schemasArg.split(',').map((s) => s.trim()) : undefined; + const apiNamesArg = argv['api-names'] as string | undefined; + const apiNames = apiNamesArg ? apiNamesArg.split(',').map((s) => s.trim()) : undefined; + + // Generator options + const reactQuery = !!argv.reactquery; + const orm = !!argv.orm; const output = (argv.output as string) || (argv.o as string); const authorization = (argv.authorization as string) || (argv.a as string); - const verbose = !!(argv.verbose || argv.v); + const verbose = !!argv.verbose; const dryRun = !!(argv['dry-run'] || argv.dryRun); + const skipCustomOperations = !!(argv['skip-custom-operations'] || argv.skipCustomOperations); + const keepDb = !!(argv['keep-db'] || argv.keepDb); + + // Watch options const watch = !!(argv.watch || argv.w); const pollInterval = argv['poll-interval'] !== undefined ? parseInt(argv['poll-interval'] as string, 10) @@ -175,151 +191,33 @@ async function handleGenerate(argv: Partial): Promise { const touch = argv.touch as string | undefined; const clear = argv.clear !== false; - if (endpoint && schema) { - console.error( - 'x Cannot use both --endpoint and --schema. Choose one source.' - ); + // Validate source options + const sourceCount = [endpoint, schema, database, pgpmModulePath, pgpmWorkspacePath].filter(Boolean).length; + if (sourceCount > 1 && !pgpmWorkspacePath) { + console.error('x Cannot use multiple source options. Choose one: --endpoint, --schema, --database, or --pgpm-module-path'); process.exit(1); } - if (watch) { - if (schema) { - console.error( - 'x Watch mode is only supported with --endpoint, not --schema.' - ); - process.exit(1); - } - const watchConfig = await loadWatchConfig({ - config, - target, - endpoint, - output, - pollInterval, - debounce, - touch, - clear, - }); - if (!watchConfig) { - process.exit(1); - } - - await startWatch({ - config: watchConfig, - generatorType: 'react-query', - verbose, - authorization, - configPath: config, - target, - outputDir: output, - generateReactQuery, - generateOrm, - }); - return; - } - - const result = await generateReactQuery({ - config, - target, - endpoint, - schema, - output, - authorization, - verbose, - dryRun, - }); - const duration = formatDuration(performance.now() - startTime); - - const targetResults = result.targets ?? []; - const hasNamedTargets = - targetResults.length > 0 && - (targetResults.length > 1 || targetResults[0]?.name !== 'default'); - - if (hasNamedTargets) { - console.log(result.success ? '[ok]' : 'x', result.message); - targetResults.forEach((t) => { - const status = t.success ? '[ok]' : 'x'; - console.log(`\n${status} ${t.message}`); - - if (t.tables && t.tables.length > 0) { - console.log(' Tables:'); - t.tables.forEach((table) => console.log(` - ${table}`)); - } - if (t.filesWritten && t.filesWritten.length > 0) { - console.log(' Files written:'); - t.filesWritten.forEach((file) => console.log(` - ${file}`)); - } - if (!t.success && t.errors) { - t.errors.forEach((error) => console.error(` - ${error}`)); - } - }); - - if (!result.success) { - process.exit(1); - } - return; - } - - if (result.success) { - console.log('[ok]', result.message, `(${duration})`); - if (result.tables && result.tables.length > 0) { - console.log('\nTables:'); - result.tables.forEach((t) => console.log(` - ${t}`)); - } - if (result.filesWritten && result.filesWritten.length > 0) { - console.log('\nFiles written:'); - result.filesWritten.forEach((f) => console.log(` - ${f}`)); - } - } else { - console.error('x', result.message, `(${duration})`); - if (result.errors) { - result.errors.forEach((e) => console.error(' -', e)); - } + // Validate pgpm workspace options + if (pgpmWorkspacePath && !pgpmModuleName) { + console.error('x --pgpm-workspace-path requires --pgpm-module-name'); process.exit(1); } -} - -/** - * Generate ORM command handler - */ -async function handleGenerateOrm(argv: Partial): Promise { - if (argv.help || argv.h) { - console.log(generateOrmUsageText); - process.exit(0); + if (pgpmModuleName && !pgpmWorkspacePath) { + console.error('x --pgpm-module-name requires --pgpm-workspace-path'); + process.exit(1); } - const startTime = performance.now(); - - const config = (argv.config as string) || (argv.c as string); - const target = (argv.target as string) || (argv.t as string); - const endpoint = (argv.endpoint as string) || (argv.e as string); - const schema = (argv.schema as string) || (argv.s as string); - const output = (argv.output as string) || (argv.o as string); - const authorization = (argv.authorization as string) || (argv.a as string); - const verbose = !!(argv.verbose || argv.v); - const dryRun = !!(argv['dry-run'] || argv.dryRun); - const skipCustomOperations = !!(argv['skip-custom-operations'] || argv.skipCustomOperations); - const watch = !!(argv.watch || argv.w); - const pollInterval = argv['poll-interval'] !== undefined - ? parseInt(argv['poll-interval'] as string, 10) - : undefined; - const debounce = argv.debounce !== undefined - ? parseInt(argv.debounce as string, 10) - : undefined; - const touch = argv.touch as string | undefined; - const clear = argv.clear !== false; - - if (endpoint && schema) { - console.error( - 'x Cannot use both --endpoint and --schema. Choose one source.' - ); + // Validate schema options + if (schemas && apiNames) { + console.error('x Cannot use both --schemas and --api-names. Choose one.'); process.exit(1); } + // Watch mode if (watch) { - if (schema) { - console.error( - 'x Watch mode is only supported with --endpoint, not --schema.' - ); + if (schema || database || pgpmModulePath || pgpmWorkspacePath) { + console.error('x Watch mode is only supported with --endpoint or --config.'); process.exit(1); } const watchConfig = await loadWatchConfig({ @@ -336,9 +234,10 @@ async function handleGenerateOrm(argv: Partial): Promise { process.exit(1); } + const generatorType = orm ? 'orm' : 'react-query'; await startWatch({ config: watchConfig, - generatorType: 'orm', + generatorType, verbose, authorization, configPath: config, @@ -351,26 +250,44 @@ async function handleGenerateOrm(argv: Partial): Promise { return; } - const result = await generateOrm({ + // Run generation + const result = await generate({ config, target, endpoint, schema, + database, + pgpmModulePath, + pgpmWorkspacePath, + pgpmModuleName, + schemas, + apiNames, output, authorization, verbose, dryRun, skipCustomOperations, + keepDb, + reactQuery, + orm, }); const duration = formatDuration(performance.now() - startTime); + // Print results + printGenerateResults(result, duration); +} + +/** + * Print generate results in a consistent format + */ +function printGenerateResults(result: Awaited>, duration: string): void { const targetResults = result.targets ?? []; const hasNamedTargets = targetResults.length > 0 && (targetResults.length > 1 || targetResults[0]?.name !== 'default'); if (hasNamedTargets) { - console.log(result.success ? '[ok]' : 'x', result.message); + console.log(result.success ? '[ok]' : 'x', result.message, `(${duration})`); targetResults.forEach((t) => { const status = t.success ? '[ok]' : 'x'; console.log(`\n${status} ${t.message}`); @@ -500,7 +417,6 @@ const createCommandMap = (): Record) => Promi return { init: handleInit, generate: handleGenerate, - 'generate-orm': handleGenerateOrm, introspect: handleIntrospect, }; }; @@ -576,8 +492,16 @@ export const options: Partial = { f: 'force', w: 'watch', }, - boolean: ['help', 'version', 'force', 'verbose', 'dry-run', 'watch', 'json', 'skip-custom-operations', 'clear'], - string: ['config', 'target', 'endpoint', 'schema', 'output', 'authorization', 'directory', 'touch', 'poll-interval', 'debounce'], + boolean: [ + 'help', 'version', 'force', 'verbose', 'dry-run', 'watch', 'json', + 'skip-custom-operations', 'clear', 'reactquery', 'orm', 'keep-db', + ], + string: [ + 'config', 'target', 'endpoint', 'schema', 'output', 'authorization', + 'directory', 'touch', 'poll-interval', 'debounce', 'database', + 'pgpm-module-path', 'pgpm-workspace-path', 'pgpm-module-name', + 'schemas', 'api-names', + ], default: { clear: true, }, diff --git a/graphql/codegen/src/index.ts b/graphql/codegen/src/index.ts index 36314fd73..4f5d8ebbc 100644 --- a/graphql/codegen/src/index.ts +++ b/graphql/codegen/src/index.ts @@ -1,7 +1,7 @@ /** * @constructive-io/graphql-codegen * - * CLI-based GraphQL SDK generator for PostGraphile endpoints. + * GraphQL SDK generator for Constructive databases. * Introspects via _meta query and generates typed queries, mutations, * and React Query v5 hooks. */ @@ -23,6 +23,7 @@ export { defineConfig } from './types/config'; // CLI command exports (for packages/cli consumption) export { + generate, generateReactQuery, generateOrm, findConfigFile, @@ -43,6 +44,7 @@ export type { GenerateOptions, GenerateResult, GenerateTargetResult, + GeneratorType, GenerateOrmOptions, GenerateOrmResult, GenerateOrmTargetResult, From b219348cc15fdff8c30cd19f21054601e14b7acd Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 23 Jan 2026 11:03:38 +0000 Subject: [PATCH 10/23] feat(graphql-codegen): add shared types pipeline and make generateReactQuery/generateOrm private - Create core/codegen/shared/ module for shared types generation - Update unified generate() to use shared types when both React Query and ORM are enabled - Add sharedTypesPath option to React Query SDK and ORM generators - Make generateReactQuery() and generateOrm() internal (not exported from package) - Update packages/cli to use unified generate() function - Export only generate() as the public API --- .../src/cli/commands/generate-unified.ts | 194 +++++++++++++++--- graphql/codegen/src/cli/commands/index.ts | 13 +- graphql/codegen/src/core/codegen/index.ts | 73 ++++--- graphql/codegen/src/core/codegen/orm/index.ts | 7 + .../codegen/src/core/codegen/shared/index.ts | 115 +++++++++++ graphql/codegen/src/index.ts | 3 +- packages/cli/src/commands/codegen.ts | 56 ++--- 7 files changed, 369 insertions(+), 92 deletions(-) create mode 100644 graphql/codegen/src/core/codegen/shared/index.ts diff --git a/graphql/codegen/src/cli/commands/generate-unified.ts b/graphql/codegen/src/cli/commands/generate-unified.ts index 51b683a7e..ee4a76a0b 100644 --- a/graphql/codegen/src/cli/commands/generate-unified.ts +++ b/graphql/codegen/src/cli/commands/generate-unified.ts @@ -1,10 +1,15 @@ /** * Unified generate command - generates SDK from GraphQL schema * - * This is a thin CLI wrapper around the core generation functions. - * Supports generating React Query SDK, ORM client, or both based on config flags. + * This module provides a single public generate() function that: + * 1. Runs introspection ONCE per target + * 2. Generates shared types ONCE (when both React Query and ORM are enabled) + * 3. Generates React Query SDK and/or ORM client based on config + * + * The internal generator functions are not exported from the package. */ -import type { ResolvedTargetConfig, ResolvedConfig } from '../../types/config'; +import path from 'path'; +import type { ResolvedTargetConfig } from '../../types/config'; import { loadAndResolveConfig, type ConfigOverrideOptions, @@ -16,10 +21,11 @@ import { import { runCodegenPipeline, validateTablesFound } from '../../core/pipeline'; import { generate as generateReactQueryFiles } from '../../core/codegen'; import { generateOrm as generateOrmFiles } from '../../core/codegen/orm'; +import { generateSharedTypes } from '../../core/codegen/shared'; import { writeGeneratedFiles } from '../../core/output'; import type { CleanTable, CleanOperation, TypeRegistry } from '../../types/schema'; -export type GeneratorType = 'react-query' | 'orm'; +export type GeneratorType = 'react-query' | 'orm' | 'shared'; export interface GenerateOptions extends ConfigOverrideOptions { /** Authorization header */ @@ -134,26 +140,40 @@ export async function generate( continue; } - // Generate React Query SDK if enabled - if (runReactQuery) { - const result = await generateReactQueryForTarget( - target, - pipelineResult.data!, - options, - isMultiTarget - ); - results.push(result); - } + const bothEnabled = runReactQuery && runOrm; - // Generate ORM client if enabled - if (runOrm) { - const result = await generateOrmForTarget( + // When both are enabled, use unified output structure with shared types + if (bothEnabled) { + const unifiedResults = await generateUnifiedOutput( target, pipelineResult.data!, options, isMultiTarget ); - results.push(result); + results.push(...unifiedResults); + } else { + // Single generator mode - use existing behavior + if (runReactQuery) { + const result = await generateReactQueryForTarget( + target, + pipelineResult.data!, + options, + isMultiTarget, + undefined // no shared types path + ); + results.push(result); + } + + if (runOrm) { + const result = await generateOrmForTarget( + target, + pipelineResult.data!, + options, + isMultiTarget, + undefined // no shared types path + ); + results.push(result); + } } } @@ -326,13 +346,128 @@ async function runPipelineForTarget( }; } -async function generateReactQueryForTarget( +/** + * Generate unified output when both React Query and ORM are enabled + * + * Output structure: + * {output}/ + * index.ts - Main barrel (re-exports shared + react-query + orm) + * types.ts - Shared entity types + * schema-types.ts - Shared schema types (enums, input types) + * react-query/ - React Query SDK + * orm/ - ORM client + */ +async function generateUnifiedOutput( target: ResolvedTargetConfig, pipelineResult: PipelineResult, options: GenerateOptions, isMultiTarget: boolean +): Promise { + const config = target.config; + const outputRoot = config.output; + const prefix = isMultiTarget ? `[${target.name}] ` : ''; + const formatMessage = (message: string) => + isMultiTarget ? `Target "${target.name}": ${message}` : message; + + const results: GenerateTargetResult[] = []; + const { tables, customOperations } = pipelineResult; + + // 1. Generate shared types to output root + console.log(`${prefix}Generating shared types...`); + const sharedResult = generateSharedTypes({ + tables, + customOperations: { + queries: customOperations.queries, + mutations: customOperations.mutations, + typeRegistry: customOperations.typeRegistry, + }, + config, + }); + + if (!options.dryRun) { + const writeResult = await writeGeneratedFiles(sharedResult.files, outputRoot, []); + if (!writeResult.success) { + results.push({ + name: target.name, + output: outputRoot, + generatorType: 'shared', + success: false, + message: formatMessage(`Failed to write shared types: ${writeResult.errors?.join(', ')}`), + errors: writeResult.errors, + }); + return results; + } + console.log(`${prefix}Shared types written to ${outputRoot}`); + } + + // 2. Generate React Query SDK to react-query/ subdirectory + const reactQueryResult = await generateReactQueryForTarget( + target, + pipelineResult, + options, + isMultiTarget, + '..' // import types from parent directory + ); + results.push(reactQueryResult); + + // 3. Generate ORM client to orm/ subdirectory + const ormResult = await generateOrmForTarget( + target, + pipelineResult, + options, + isMultiTarget, + '..' // import types from parent directory + ); + results.push(ormResult); + + // 4. Generate unified barrel export + if (!options.dryRun) { + const unifiedBarrel = generateUnifiedBarrel(sharedResult.hasSchemaTypes); + await writeGeneratedFiles([{ path: 'index.ts', content: unifiedBarrel }], outputRoot, []); + } + + return results; +} + +/** + * Generate the unified barrel export for the root output directory + */ +function generateUnifiedBarrel(hasSchemaTypes: boolean): string { + const lines = [ + '/**', + ' * Generated SDK - auto-generated, do not edit', + ' */', + '', + '// Shared types', + "export * from './types';", + ]; + + if (hasSchemaTypes) { + lines.push("export * from './schema-types';"); + } + + lines.push(''); + lines.push('// React Query SDK'); + lines.push("export * from './react-query';"); + lines.push(''); + lines.push('// ORM Client'); + lines.push("export * from './orm';"); + lines.push(''); + + return lines.join('\n'); +} + +async function generateReactQueryForTarget( + target: ResolvedTargetConfig, + pipelineResult: PipelineResult, + options: GenerateOptions, + isMultiTarget: boolean, + sharedTypesPath?: string ): Promise { const config = target.config; + const outputDir = sharedTypesPath + ? path.join(config.output, 'react-query') + : config.output; const prefix = isMultiTarget ? `[${target.name}] ` : ''; const log = options.verbose ? (message: string) => console.log(`${prefix}${message}`) @@ -352,6 +487,7 @@ async function generateReactQueryForTarget( typeRegistry: customOperations.typeRegistry, }, config, + sharedTypesPath, }); console.log(`${prefix}Generated ${genStats.totalFiles} files`); @@ -366,7 +502,7 @@ async function generateReactQueryForTarget( if (options.dryRun) { return { name: target.name, - output: config.output, + output: outputDir, generatorType: 'react-query', success: true, message: formatMessage( @@ -381,8 +517,8 @@ async function generateReactQueryForTarget( // Write files log('Writing files...'); - console.log(`${prefix}Output: ${config.output}`); - const writeResult = await writeGeneratedFiles(generatedFiles, config.output, [ + console.log(`${prefix}Output: ${outputDir}`); + const writeResult = await writeGeneratedFiles(generatedFiles, outputDir, [ 'queries', 'mutations', ]); @@ -390,7 +526,7 @@ async function generateReactQueryForTarget( if (!writeResult.success) { return { name: target.name, - output: config.output, + output: outputDir, generatorType: 'react-query', success: false, message: formatMessage( @@ -405,11 +541,11 @@ async function generateReactQueryForTarget( return { name: target.name, - output: config.output, + output: outputDir, generatorType: 'react-query', success: true, message: formatMessage( - `Generated React Query SDK for ${tables.length} tables${customOpsMsg}. Files written to ${config.output}` + `Generated React Query SDK for ${tables.length} tables${customOpsMsg}. Files written to ${outputDir}` ), tables: tables.map((t) => t.name), customQueries, @@ -422,10 +558,13 @@ async function generateOrmForTarget( target: ResolvedTargetConfig, pipelineResult: PipelineResult, options: GenerateOptions, - isMultiTarget: boolean + isMultiTarget: boolean, + sharedTypesPath?: string ): Promise { const config = target.config; - const outputDir = options.output || config.orm.output; + const outputDir = sharedTypesPath + ? path.join(config.output, 'orm') + : (options.output || config.orm.output); const prefix = isMultiTarget ? `[${target.name}] ` : ''; const log = options.verbose ? (message: string) => console.log(`${prefix}${message}`) @@ -445,6 +584,7 @@ async function generateOrmForTarget( typeRegistry: customOperations.typeRegistry, }, config, + sharedTypesPath, }); console.log(`${prefix}Generated ${genStats.totalFiles} files`); diff --git a/graphql/codegen/src/cli/commands/index.ts b/graphql/codegen/src/cli/commands/index.ts index dee4025fa..5b3afa9a4 100644 --- a/graphql/codegen/src/cli/commands/index.ts +++ b/graphql/codegen/src/cli/commands/index.ts @@ -1,12 +1,21 @@ /** * CLI commands exports + * + * Public API: + * - generate() - Unified generate function that respects config.reactQuery.enabled and config.orm.enabled + * - findConfigFile() - Find config file in directory + * - loadConfigFile() - Load and parse config file + * + * Internal (not exported from package): + * - generateReactQuery() - Convenience wrapper for generate({ reactQuery: true, orm: false }) + * - generateOrm() - Convenience wrapper for generate({ reactQuery: false, orm: true }) */ export { initCommand, findConfigFile, loadConfigFile } from './init'; export type { InitOptions, InitResult } from './init'; -// Unified generate function (recommended) -export { generate, generateReactQuery, generateOrm } from './generate-unified'; +// Unified generate function (public API) +export { generate } from './generate-unified'; export type { GenerateOptions, GenerateResult, GenerateTargetResult, GeneratorType } from './generate-unified'; // Legacy exports (deprecated - use unified generate instead) diff --git a/graphql/codegen/src/core/codegen/index.ts b/graphql/codegen/src/core/codegen/index.ts index 8778b7406..139ebc064 100644 --- a/graphql/codegen/src/core/codegen/index.ts +++ b/graphql/codegen/src/core/codegen/index.ts @@ -84,6 +84,13 @@ export interface GenerateOptions { }; /** Resolved configuration */ config: ResolvedConfig; + /** + * Path to shared types directory (relative import path). + * When provided, types.ts and schema-types.ts are NOT generated + * and imports reference the shared types location instead. + * Example: '..' means types are in parent directory + */ + sharedTypesPath?: string; } // ============================================================================ @@ -102,9 +109,12 @@ export function generateAllFiles( /** * Generate all SDK files with full support for custom operations + * + * When sharedTypesPath is provided, types.ts and schema-types.ts are NOT generated + * (they're expected to exist in the shared types directory). */ export function generate(options: GenerateOptions): GenerateResult { - const { tables, customOperations, config } = options; + const { tables, customOperations, config, sharedTypesPath } = options; const files: GeneratedFile[] = []; // Extract codegen options @@ -126,34 +136,51 @@ export function generate(options: GenerateOptions): GenerateResult { // Collect table type names for import path resolution const tableTypeNames = new Set(tables.map((t) => getTableNames(t).typeName)); - // 2. Generate schema-types.ts for custom operations (if any) - // NOTE: This must come BEFORE types.ts so that types.ts can import enum types + // When using shared types, skip generating types.ts and schema-types.ts + // They're already generated in the shared directory let hasSchemaTypes = false; let generatedEnumNames: string[] = []; - if (customOperations && customOperations.typeRegistry) { - const schemaTypesResult = generateSchemaTypesFile({ - typeRegistry: customOperations.typeRegistry, - tableTypeNames, - }); - // Only include if there's meaningful content - if (schemaTypesResult.content.split('\n').length > 10) { - files.push({ - path: 'schema-types.ts', - content: schemaTypesResult.content, + if (sharedTypesPath) { + // Using shared types - check if schema-types would be generated + if (customOperations && customOperations.typeRegistry) { + const schemaTypesResult = generateSchemaTypesFile({ + typeRegistry: customOperations.typeRegistry, + tableTypeNames, }); - hasSchemaTypes = true; - generatedEnumNames = schemaTypesResult.generatedEnums || []; + if (schemaTypesResult.content.split('\n').length > 10) { + hasSchemaTypes = true; + generatedEnumNames = schemaTypesResult.generatedEnums || []; + } } - } + } else { + // 2. Generate schema-types.ts for custom operations (if any) + // NOTE: This must come BEFORE types.ts so that types.ts can import enum types + if (customOperations && customOperations.typeRegistry) { + const schemaTypesResult = generateSchemaTypesFile({ + typeRegistry: customOperations.typeRegistry, + tableTypeNames, + }); - // 3. Generate types.ts (can now import enums from schema-types) - files.push({ - path: 'types.ts', - content: generateTypesFile(tables, { - enumsFromSchemaTypes: generatedEnumNames, - }), - }); + // Only include if there's meaningful content + if (schemaTypesResult.content.split('\n').length > 10) { + files.push({ + path: 'schema-types.ts', + content: schemaTypesResult.content, + }); + hasSchemaTypes = true; + generatedEnumNames = schemaTypesResult.generatedEnums || []; + } + } + + // 3. Generate types.ts (can now import enums from schema-types) + files.push({ + path: 'types.ts', + content: generateTypesFile(tables, { + enumsFromSchemaTypes: generatedEnumNames, + }), + }); + } // 3b. Generate centralized query keys (query-keys.ts) let hasQueryKeys = false; diff --git a/graphql/codegen/src/core/codegen/orm/index.ts b/graphql/codegen/src/core/codegen/orm/index.ts index c0c3955cb..919173248 100644 --- a/graphql/codegen/src/core/codegen/orm/index.ts +++ b/graphql/codegen/src/core/codegen/orm/index.ts @@ -33,6 +33,13 @@ export interface GenerateOrmOptions { typeRegistry?: TypeRegistry; }; config: ResolvedConfig; + /** + * Path to shared types directory (relative import path). + * When provided, entity types are imported from shared types + * instead of being generated in input-types.ts. + * Example: '..' means types are in parent directory + */ + sharedTypesPath?: string; } export interface GenerateOrmResult { diff --git a/graphql/codegen/src/core/codegen/shared/index.ts b/graphql/codegen/src/core/codegen/shared/index.ts new file mode 100644 index 000000000..ac7b247e5 --- /dev/null +++ b/graphql/codegen/src/core/codegen/shared/index.ts @@ -0,0 +1,115 @@ +/** + * Shared types generator + * + * Generates shared TypeScript types that can be imported by both + * React Query SDK and ORM client outputs. + * + * Output structure: + * shared/ + * index.ts - Barrel export + * types.ts - Entity interfaces + * schema-types.ts - Enums, input types, payload types + * filters.ts - Filter types (StringFilter, IntFilter, etc.) + */ +import type { CleanTable, CleanOperation, TypeRegistry } from '../../../types/schema'; +import type { ResolvedConfig } from '../../../types/config'; +import { generateTypesFile } from '../types'; +import { generateSchemaTypesFile } from '../schema-types-generator'; +import { getTableNames } from '../utils'; + +export interface GeneratedFile { + path: string; + content: string; +} + +export interface GenerateSharedOptions { + tables: CleanTable[]; + customOperations?: { + queries: CleanOperation[]; + mutations: CleanOperation[]; + typeRegistry: TypeRegistry; + }; + config: ResolvedConfig; +} + +export interface GenerateSharedResult { + files: GeneratedFile[]; + generatedEnumNames: string[]; + hasSchemaTypes: boolean; +} + +/** + * Generate shared types that can be imported by both React Query SDK and ORM client + */ +export function generateSharedTypes(options: GenerateSharedOptions): GenerateSharedResult { + const { tables, customOperations } = options; + const files: GeneratedFile[] = []; + + // Collect table type names for import path resolution + const tableTypeNames = new Set(tables.map((t) => getTableNames(t).typeName)); + + // 1. Generate schema-types.ts for custom operations (if any) + // NOTE: This must come BEFORE types.ts so that types.ts can import enum types + let hasSchemaTypes = false; + let generatedEnumNames: string[] = []; + if (customOperations && customOperations.typeRegistry) { + const schemaTypesResult = generateSchemaTypesFile({ + typeRegistry: customOperations.typeRegistry, + tableTypeNames, + }); + + // Only include if there's meaningful content + if (schemaTypesResult.content.split('\n').length > 10) { + files.push({ + path: 'schema-types.ts', + content: schemaTypesResult.content, + }); + hasSchemaTypes = true; + generatedEnumNames = schemaTypesResult.generatedEnums || []; + } + } + + // 2. Generate types.ts (entity interfaces and filter types) + files.push({ + path: 'types.ts', + content: generateTypesFile(tables, { + enumsFromSchemaTypes: generatedEnumNames, + }), + }); + + // 3. Generate barrel export (index.ts) + const barrelContent = generateSharedBarrel(hasSchemaTypes); + files.push({ + path: 'index.ts', + content: barrelContent, + }); + + return { + files, + generatedEnumNames, + hasSchemaTypes, + }; +} + +/** + * Generate the barrel export for shared types + */ +function generateSharedBarrel(hasSchemaTypes: boolean): string { + const lines = [ + '/**', + ' * Shared types - auto-generated, do not edit', + ' */', + '', + "export * from './types';", + ]; + + if (hasSchemaTypes) { + lines.push("export * from './schema-types';"); + } + + lines.push(''); + return lines.join('\n'); +} + +export { generateTypesFile } from '../types'; +export { generateSchemaTypesFile } from '../schema-types-generator'; diff --git a/graphql/codegen/src/index.ts b/graphql/codegen/src/index.ts index 4f5d8ebbc..83f7bc309 100644 --- a/graphql/codegen/src/index.ts +++ b/graphql/codegen/src/index.ts @@ -22,10 +22,9 @@ export * from './client'; export { defineConfig } from './types/config'; // CLI command exports (for packages/cli consumption) +// Note: generateReactQuery and generateOrm are internal - use generate() with config flags export { generate, - generateReactQuery, - generateOrm, findConfigFile, loadConfigFile, } from './cli/commands'; diff --git a/packages/cli/src/commands/codegen.ts b/packages/cli/src/commands/codegen.ts index 6eaf7f606..7538a6dae 100644 --- a/packages/cli/src/commands/codegen.ts +++ b/packages/cli/src/commands/codegen.ts @@ -1,13 +1,10 @@ import { CLIOptions, Inquirerer, Question } from 'inquirerer'; import { - generateReactQuery, - generateOrm, + generate, findConfigFile, buildSchemaFromDatabase, type GenerateResult, type GenerateTargetResult, - type GenerateOrmResult, - type GenerateOrmTargetResult, } from '@constructive-io/graphql-codegen'; import { getEnvOptions } from '@constructive-io/graphql-env'; @@ -103,8 +100,8 @@ const questions: Question[] = [ }, ]; -type AnyResult = GenerateResult | GenerateOrmResult; -type AnyTargetResult = GenerateTargetResult | GenerateOrmTargetResult; +type AnyResult = GenerateResult; +type AnyTargetResult = GenerateTargetResult; export default async ( argv: Partial>, @@ -164,40 +161,23 @@ export default async ( process.exit(1); } - // Determine generator type and output directory - const generatorType = orm ? 'orm' : 'react-query'; + // Determine output directory const output = config ? out : outDir; - // Call core generate function - let result: AnyResult; - switch (generatorType) { - case 'orm': - result = await generateOrm({ - config, - target, - endpoint: endpoint || undefined, - schema: schemaPath, - output, - authorization: auth, - verbose, - dryRun, - }); - break; - case 'react-query': - result = await generateReactQuery({ - config, - target, - endpoint: endpoint || undefined, - schema: schemaPath, - output, - authorization: auth, - verbose, - dryRun, - }); - break; - default: - throw new Error(`Unknown generator type: ${generatorType}`); - } + // Call unified generate function with appropriate flags + const result = await generate({ + config, + target, + endpoint: endpoint || undefined, + schema: schemaPath, + output, + authorization: auth, + verbose, + dryRun, + // Use flags to control which generators run + reactQuery: !orm, + orm: orm, + }); printResult(result); From 1d8eacbef66ce2ba19603afa87416c8c02553a4f Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 23 Jan 2026 11:17:04 +0000 Subject: [PATCH 11/23] test(cli): update codegen tests to use unified generate() function --- packages/cli/__tests__/codegen.test.ts | 32 +++++++++++++------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/cli/__tests__/codegen.test.ts b/packages/cli/__tests__/codegen.test.ts index 698084f16..31e42c73b 100644 --- a/packages/cli/__tests__/codegen.test.ts +++ b/packages/cli/__tests__/codegen.test.ts @@ -1,14 +1,8 @@ import type { ParsedArgs } from 'inquirerer' import codegenCommand from '../src/commands/codegen' -import { generateReactQuery } from '@constructive-io/graphql-codegen/cli/commands/generate' - -jest.mock('@constructive-io/graphql-codegen/cli/commands/generate', () => ({ - generateReactQuery: jest.fn(async () => ({ success: true, message: 'Generated SDK', filesWritten: [] as string[] })) -})) jest.mock('@constructive-io/graphql-codegen', () => ({ - generateReactQuery: jest.fn(async () => ({ success: true, message: 'Generated SDK', filesWritten: [] as string[] })), - generateOrm: jest.fn(async () => ({ success: true, message: 'Generated ORM', filesWritten: [] as string[] })), + generate: jest.fn(async () => ({ success: true, message: 'Generated SDK', filesWritten: [] as string[] })), findConfigFile: jest.fn((): string | undefined => undefined), buildSchemaFromDatabase: jest.fn(async ({ outDir }: { outDir: string }) => ({ schemaPath: `${outDir}/schema.graphql`, @@ -42,8 +36,8 @@ describe('codegen command', () => { spyExit.mockRestore() }) - it('calls generateReactQuery with endpoint flow options', async () => { - const { generateReactQuery: mockGenerateReactQuery } = require('@constructive-io/graphql-codegen') + it('calls generate with endpoint flow options', async () => { + const { generate: mockGenerate } = require('@constructive-io/graphql-codegen') const argv: Partial = { endpoint: 'http://localhost:3000/graphql', @@ -56,19 +50,22 @@ describe('codegen command', () => { await codegenCommand(argv, mockPrompter as any, {} as any) - expect(mockGenerateReactQuery).toHaveBeenCalled() - const call = mockGenerateReactQuery.mock.calls[0][0] + 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 + dryRun: true, + reactQuery: true }) + // orm is undefined when not set (defaults to false via !orm) + expect(call.orm).toBeFalsy() }) - it('builds schema file and calls generateReactQuery with schema when DB options provided', async () => { - const { generateReactQuery: mockGenerateReactQuery, buildSchemaFromDatabase } = require('@constructive-io/graphql-codegen') + it('builds schema file and calls generate with schema when DB options provided', async () => { + const { generate: mockGenerate, buildSchemaFromDatabase } = require('@constructive-io/graphql-codegen') const argv: Partial = { database: 'constructive_db', @@ -80,10 +77,13 @@ describe('codegen command', () => { await codegenCommand(argv, mockPrompter as any, {} as any) expect(buildSchemaFromDatabase).toHaveBeenCalled() - expect(mockGenerateReactQuery).toHaveBeenCalled() - const call = mockGenerateReactQuery.mock.calls[0][0] + expect(mockGenerate).toHaveBeenCalled() + const call = mockGenerate.mock.calls[0][0] expect(call.schema).toBe('graphql/codegen/dist/schema.graphql') expect(call.output).toBe('graphql/codegen/dist') expect(call.endpoint).toBeUndefined() + expect(call.reactQuery).toBe(true) + // orm is undefined when not set (defaults to false via !orm) + expect(call.orm).toBeFalsy() }) }) From 595f0eac484d23ea02cefb03351bd7751e4dc204 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 23 Jan 2026 12:23:50 +0000 Subject: [PATCH 12/23] refactor(graphql-codegen): add database/pgpm fields to config types and use Babel AST for barrel exports - Add database, pgpmModulePath, pgpmWorkspacePath, pgpmModuleName, schemas, apiNames, keepDb fields to GraphQLSDKConfigTarget and ResolvedConfig types - Remove all (config as any) type casts now that fields are first-class citizens - Simplify buildTargetOverrides by removing redundant undefined assignments (validation happens in loadAndResolveConfig) - Update generateSharedBarrel in shared/index.ts to use Babel AST instead of string concatenation - Update generateUnifiedBarrel in generate-unified.ts to use Babel AST instead of string concatenation - Update resolveMultiTargetConfig to check for all source types (database, pgpm, etc.) --- .../src/cli/commands/generate-unified.ts | 68 +++++++---- .../codegen/src/core/codegen/shared/index.ts | 36 ++++-- graphql/codegen/src/core/config/resolver.ts | 114 ++++++------------ graphql/codegen/src/types/config.ts | 95 ++++++++++++++- 4 files changed, 195 insertions(+), 118 deletions(-) diff --git a/graphql/codegen/src/cli/commands/generate-unified.ts b/graphql/codegen/src/cli/commands/generate-unified.ts index ee4a76a0b..85d3d6bbf 100644 --- a/graphql/codegen/src/cli/commands/generate-unified.ts +++ b/graphql/codegen/src/cli/commands/generate-unified.ts @@ -9,6 +9,8 @@ * The internal generator functions are not exported from the package. */ import path from 'path'; +import * as t from '@babel/types'; +import { generateCode, addJSDocComment } from '../../core/codegen/babel-ast'; import type { ResolvedTargetConfig } from '../../types/config'; import { loadAndResolveConfig, @@ -249,14 +251,14 @@ async function runPipelineForTarget( const formatMessage = (message: string) => isMultiTarget ? `Target "${target.name}": ${message}` : message; - // Extract extended options if present (attached by config resolver) - const database = (config as any).database as string | undefined; - const schemas = (config as any).schemas as string[] | undefined; - const apiNames = (config as any).apiNames as string[] | undefined; - const pgpmModulePath = (config as any).pgpmModulePath as string | undefined; - const pgpmWorkspacePath = (config as any).pgpmWorkspacePath as string | undefined; - const pgpmModuleName = (config as any).pgpmModuleName as string | undefined; - const keepDb = (config as any).keepDb as boolean | undefined; + // Extract source options from config (now first-class citizens in ResolvedConfig) + const database = config.database ?? undefined; + const schemas = config.schemas.length > 0 ? config.schemas : undefined; + const apiNames = config.apiNames.length > 0 ? config.apiNames : undefined; + const pgpmModulePath = config.pgpmModulePath ?? undefined; + const pgpmWorkspacePath = config.pgpmWorkspacePath ?? undefined; + const pgpmModuleName = config.pgpmModuleName ?? undefined; + const keepDb = config.keepDb; if (isMultiTarget) { console.log(`\nTarget "${target.name}"`); @@ -430,31 +432,45 @@ async function generateUnifiedOutput( } /** - * Generate the unified barrel export for the root output directory + * Helper to create export * from './module' statement + */ +function exportAllFrom(modulePath: string): t.ExportAllDeclaration { + return t.exportAllDeclaration(t.stringLiteral(modulePath)); +} + +/** + * Generate the unified barrel export for the root output directory using Babel AST */ function generateUnifiedBarrel(hasSchemaTypes: boolean): string { - const lines = [ - '/**', - ' * Generated SDK - auto-generated, do not edit', - ' */', - '', - '// Shared types', - "export * from './types';", - ]; + const statements: t.Statement[] = []; + + // Shared types + statements.push(exportAllFrom('./types')); if (hasSchemaTypes) { - lines.push("export * from './schema-types';"); + statements.push(exportAllFrom('./schema-types')); } - lines.push(''); - lines.push('// React Query SDK'); - lines.push("export * from './react-query';"); - lines.push(''); - lines.push('// ORM Client'); - lines.push("export * from './orm';"); - lines.push(''); + // React Query SDK + statements.push(exportAllFrom('./react-query')); + + // ORM Client + statements.push(exportAllFrom('./orm')); + + // Add file header as leading comment on first statement + if (statements.length > 0) { + addJSDocComment(statements[0], [ + 'Generated SDK - auto-generated, do not edit', + '@generated by @constructive-io/graphql-codegen', + '', + 'Exports:', + '- Shared types (types.ts, schema-types.ts)', + '- React Query SDK (react-query/)', + '- ORM Client (orm/)', + ]); + } - return lines.join('\n'); + return generateCode(statements); } async function generateReactQueryForTarget( diff --git a/graphql/codegen/src/core/codegen/shared/index.ts b/graphql/codegen/src/core/codegen/shared/index.ts index ac7b247e5..9a294d632 100644 --- a/graphql/codegen/src/core/codegen/shared/index.ts +++ b/graphql/codegen/src/core/codegen/shared/index.ts @@ -13,10 +13,19 @@ */ import type { CleanTable, CleanOperation, TypeRegistry } from '../../../types/schema'; import type { ResolvedConfig } from '../../../types/config'; +import * as t from '@babel/types'; +import { generateCode, addJSDocComment } from '../babel-ast'; import { generateTypesFile } from '../types'; import { generateSchemaTypesFile } from '../schema-types-generator'; import { getTableNames } from '../utils'; +/** + * Helper to create export * from './module' statement + */ +function exportAllFrom(modulePath: string): t.ExportAllDeclaration { + return t.exportAllDeclaration(t.stringLiteral(modulePath)); +} + export interface GeneratedFile { path: string; content: string; @@ -92,23 +101,28 @@ export function generateSharedTypes(options: GenerateSharedOptions): GenerateSha } /** - * Generate the barrel export for shared types + * Generate the barrel export for shared types using Babel AST */ function generateSharedBarrel(hasSchemaTypes: boolean): string { - const lines = [ - '/**', - ' * Shared types - auto-generated, do not edit', - ' */', - '', - "export * from './types';", - ]; + const statements: t.Statement[] = []; + // Export types + statements.push(exportAllFrom('./types')); + + // Export schema types if present if (hasSchemaTypes) { - lines.push("export * from './schema-types';"); + statements.push(exportAllFrom('./schema-types')); + } + + // Add file header as leading comment on first statement + if (statements.length > 0) { + addJSDocComment(statements[0], [ + 'Shared types - auto-generated, do not edit', + '@generated by @constructive-io/graphql-codegen', + ]); } - lines.push(''); - return lines.join('\n'); + return generateCode(statements); } export { generateTypesFile } from '../types'; diff --git a/graphql/codegen/src/core/config/resolver.ts b/graphql/codegen/src/core/config/resolver.ts index 1a0f2ee28..38230d9e4 100644 --- a/graphql/codegen/src/core/config/resolver.ts +++ b/graphql/codegen/src/core/config/resolver.ts @@ -55,77 +55,50 @@ export interface LoadConfigResult { } /** - * Extended overrides type that includes database and PGPM module options - */ -export interface ExtendedTargetOverrides extends GraphQLSDKConfigTarget { - database?: string; - schemas?: string[]; - apiNames?: string[]; - pgpmModulePath?: string; - pgpmWorkspacePath?: string; - pgpmModuleName?: string; - keepDb?: boolean; -} - -/** - * Build target overrides from options + * Build target overrides from CLI options + * + * Note: Validation that only one source is specified happens in loadAndResolveConfig, + * so we don't need to clear other source fields here. */ export function buildTargetOverrides( options: ConfigOverrideOptions -): ExtendedTargetOverrides { - const overrides: ExtendedTargetOverrides = {}; +): GraphQLSDKConfigTarget { + const overrides: GraphQLSDKConfigTarget = {}; if (options.endpoint) { overrides.endpoint = options.endpoint; - overrides.schema = undefined; - overrides.database = undefined; - overrides.pgpmModulePath = undefined; - overrides.pgpmWorkspacePath = undefined; - overrides.pgpmModuleName = undefined; } if (options.schema) { overrides.schema = options.schema; - overrides.endpoint = undefined; - overrides.database = undefined; - overrides.pgpmModulePath = undefined; - overrides.pgpmWorkspacePath = undefined; - overrides.pgpmModuleName = undefined; } if (options.database) { overrides.database = options.database; - overrides.schemas = options.schemas; - overrides.apiNames = options.apiNames; - overrides.endpoint = undefined; - overrides.schema = undefined; - overrides.pgpmModulePath = undefined; - overrides.pgpmWorkspacePath = undefined; - overrides.pgpmModuleName = undefined; } if (options.pgpmModulePath) { overrides.pgpmModulePath = options.pgpmModulePath; - overrides.schemas = options.schemas; - overrides.apiNames = options.apiNames; - overrides.keepDb = options.keepDb; - overrides.endpoint = undefined; - overrides.schema = undefined; - overrides.database = undefined; - overrides.pgpmWorkspacePath = undefined; - overrides.pgpmModuleName = undefined; } - if (options.pgpmWorkspacePath && options.pgpmModuleName) { + if (options.pgpmWorkspacePath) { overrides.pgpmWorkspacePath = options.pgpmWorkspacePath; + } + + if (options.pgpmModuleName) { overrides.pgpmModuleName = options.pgpmModuleName; + } + + if (options.schemas) { overrides.schemas = options.schemas; + } + + if (options.apiNames) { overrides.apiNames = options.apiNames; + } + + if (options.keepDb !== undefined) { overrides.keepDb = options.keepDb; - overrides.endpoint = undefined; - overrides.schema = undefined; - overrides.database = undefined; - overrides.pgpmModulePath = undefined; } if (options.output) { @@ -208,12 +181,13 @@ function resolveMultiTargetConfig( if ( !options.target && - (options.endpoint || options.schema || options.output) + (options.endpoint || options.schema || options.database || + options.pgpmModulePath || options.pgpmWorkspacePath || options.output) ) { return { success: false, error: - 'Multiple targets configured. Use --target with --endpoint, --schema, or --output.', + 'Multiple targets configured. Use --target with source or output overrides.', }; } @@ -236,10 +210,17 @@ function resolveMultiTargetConfig( mergedTarget = mergeConfig(mergedTarget, overrides); } - if (!mergedTarget.endpoint && !mergedTarget.schema) { + const hasSource = + mergedTarget.endpoint || + mergedTarget.schema || + mergedTarget.database || + mergedTarget.pgpmModulePath || + (mergedTarget.pgpmWorkspacePath && mergedTarget.pgpmModuleName); + + if (!hasSource) { return { success: false, - error: `Target "${name}" is missing an endpoint or schema.`, + error: `Target "${name}" is missing a source (endpoint, schema, database, or pgpm module).`, }; } @@ -262,7 +243,7 @@ function resolveMultiTargetConfig( function resolveSingleTargetConfig( baseConfig: GraphQLSDKConfigTarget, options: ConfigOverrideOptions, - overrides: ExtendedTargetOverrides + overrides: GraphQLSDKConfigTarget ): LoadConfigResult { if (options.target) { return { @@ -278,9 +259,9 @@ function resolveSingleTargetConfig( const hasSource = mergedConfig.endpoint || mergedConfig.schema || - overrides.database || - overrides.pgpmModulePath || - (overrides.pgpmWorkspacePath && overrides.pgpmModuleName); + mergedConfig.database || + mergedConfig.pgpmModulePath || + (mergedConfig.pgpmWorkspacePath && mergedConfig.pgpmModuleName); if (!hasSource) { return { @@ -290,31 +271,10 @@ function resolveSingleTargetConfig( }; } - // For database mode, we need to pass the database info through to the resolved config + // All source options are now first-class citizens in the config types, + // so resolveConfig handles them properly without any casts const resolvedConfig = resolveConfig(mergedConfig); - // Attach extended options if present (they're not part of the standard config type) - if (overrides.database) { - (resolvedConfig as any).database = overrides.database; - (resolvedConfig as any).schemas = overrides.schemas; - (resolvedConfig as any).apiNames = overrides.apiNames; - } - - if (overrides.pgpmModulePath) { - (resolvedConfig as any).pgpmModulePath = overrides.pgpmModulePath; - (resolvedConfig as any).schemas = overrides.schemas; - (resolvedConfig as any).apiNames = overrides.apiNames; - (resolvedConfig as any).keepDb = overrides.keepDb; - } - - if (overrides.pgpmWorkspacePath && overrides.pgpmModuleName) { - (resolvedConfig as any).pgpmWorkspacePath = overrides.pgpmWorkspacePath; - (resolvedConfig as any).pgpmModuleName = overrides.pgpmModuleName; - (resolvedConfig as any).schemas = overrides.schemas; - (resolvedConfig as any).apiNames = overrides.apiNames; - (resolvedConfig as any).keepDb = overrides.keepDb; - } - return { success: true, targets: [{ name: 'default', config: resolvedConfig }], diff --git a/graphql/codegen/src/types/config.ts b/graphql/codegen/src/types/config.ts index 0663eee61..80e4f1140 100644 --- a/graphql/codegen/src/types/config.ts +++ b/graphql/codegen/src/types/config.ts @@ -75,20 +75,72 @@ export interface QueryKeyConfig { /** * Target configuration for graphql-codegen * Represents a single schema source and output destination. + * + * Source options (choose one): + * - endpoint: GraphQL endpoint URL for live introspection + * - schema: Path to GraphQL schema file (.graphql) + * - database: Database name or connection string for direct introspection + * - pgpmModulePath: Path to PGPM module (creates ephemeral database) + * - pgpmWorkspacePath + pgpmModuleName: PGPM workspace mode */ export interface GraphQLSDKConfigTarget { /** * GraphQL endpoint URL for live introspection - * Either endpoint or schema must be provided */ endpoint?: string; /** * Path to GraphQL schema file (.graphql) for file-based generation - * Either endpoint or schema must be provided */ schema?: string; + /** + * Database name or connection string for direct database introspection + * Use with `schemas` or `apiNames` to specify which schemas to introspect + */ + database?: string; + + /** + * Path to a PGPM module directory + * Creates an ephemeral database, deploys the module, and introspects + * Use with `schemas` or `apiNames` to specify which schemas to introspect + */ + pgpmModulePath?: string; + + /** + * Path to a PGPM workspace directory + * Must be used together with `pgpmModuleName` + */ + pgpmWorkspacePath?: string; + + /** + * Name of the module within the PGPM workspace + * Must be used together with `pgpmWorkspacePath` + */ + pgpmModuleName?: string; + + /** + * PostgreSQL schemas to introspect (for database and PGPM modes) + * Mutually exclusive with `apiNames` + * @example ['public', 'app_public'] + */ + schemas?: string[]; + + /** + * API names to resolve schemas from (for database and PGPM modes) + * Queries services_public.api_schemas to automatically determine schemas + * Mutually exclusive with `schemas` + * @example ['my_api'] + */ + apiNames?: string[]; + + /** + * Keep the ephemeral database after introspection (for debugging) + * Only applies to PGPM module modes + * @default false + */ + keepDb?: boolean; + /** * Headers to include in introspection requests */ @@ -301,13 +353,41 @@ export interface ResolvedQueryKeyConfig { */ export interface ResolvedConfig { /** - * GraphQL endpoint URL (empty string if using schema file) + * GraphQL endpoint URL (empty string if using other source) */ endpoint: string; /** - * Path to GraphQL schema file (null if using endpoint) + * Path to GraphQL schema file (null if using other source) */ schema: string | null; + /** + * Database name or connection string (null if using other source) + */ + database: string | null; + /** + * Path to PGPM module (null if using other source) + */ + pgpmModulePath: string | null; + /** + * Path to PGPM workspace (null if using other source) + */ + pgpmWorkspacePath: string | null; + /** + * Module name within PGPM workspace (null if using other source) + */ + pgpmModuleName: string | null; + /** + * PostgreSQL schemas to introspect (for database and PGPM modes) + */ + schemas: string[]; + /** + * API names to resolve schemas from (for database and PGPM modes) + */ + apiNames: string[]; + /** + * Keep ephemeral database after introspection (for PGPM modes) + */ + keepDb: boolean; headers: Record; output: string; tables: { @@ -377,6 +457,13 @@ export const DEFAULT_QUERY_KEY_CONFIG: ResolvedQueryKeyConfig = { export const DEFAULT_CONFIG: ResolvedConfig = { endpoint: '', schema: null, + database: null, + pgpmModulePath: null, + pgpmWorkspacePath: null, + pgpmModuleName: null, + schemas: [], + apiNames: [], + keepDb: false, headers: {}, output: './generated/graphql', tables: { From 22a3bb21b6b7a7bff5b40579a80604c6737bfcbd Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 23 Jan 2026 13:00:20 +0000 Subject: [PATCH 13/23] refactor(graphql-codegen): simplify config types using single-type pattern - Delete ResolvedConfig, ResolvedWatchConfig, ResolvedQueryKeyConfig types - Use GraphQLSDKConfigTarget everywhere (single type with optional fields) - Delete buildTargetOverrides function - use destructuring inline - Create getConfigOptions function following pgpm/env pattern - Make ConfigOverrideOptions extend GraphQLSDKConfigTarget - Rename ResolvedTargetConfig to TargetConfig - Update all imports and usages to use new types - Remove (config as any) casts since config now has all fields - Rename reactQuery/orm options to enableReactQuery/enableOrm in GenerateOptions - Update tests to use QueryKeyConfig instead of ResolvedQueryKeyConfig --- .../codegen/query-keys-factory.test.ts | 4 +- .../__tests__/config/resolve-config.test.ts | 2 +- .../codegen/src/cli/commands/generate-orm.ts | 59 +++---- .../src/cli/commands/generate-unified.ts | 81 ++++----- graphql/codegen/src/cli/commands/generate.ts | 59 +++---- graphql/codegen/src/cli/index.ts | 6 +- graphql/codegen/src/core/codegen/index.ts | 10 +- .../codegen/src/core/codegen/invalidation.ts | 4 +- .../codegen/src/core/codegen/mutation-keys.ts | 4 +- graphql/codegen/src/core/codegen/orm/index.ts | 4 +- .../codegen/src/core/codegen/query-keys.ts | 4 +- .../codegen/src/core/codegen/shared/index.ts | 4 +- graphql/codegen/src/core/config/index.ts | 1 - graphql/codegen/src/core/config/resolver.ts | 155 +++++------------- graphql/codegen/src/core/pipeline/index.ts | 6 +- .../codegen/src/core/watch/orchestrator.ts | 4 +- graphql/codegen/src/types/config.ts | 146 +++-------------- graphql/codegen/src/types/index.ts | 6 +- 18 files changed, 176 insertions(+), 383 deletions(-) diff --git a/graphql/codegen/src/__tests__/codegen/query-keys-factory.test.ts b/graphql/codegen/src/__tests__/codegen/query-keys-factory.test.ts index eb2f37344..abc8484b9 100644 --- a/graphql/codegen/src/__tests__/codegen/query-keys-factory.test.ts +++ b/graphql/codegen/src/__tests__/codegen/query-keys-factory.test.ts @@ -10,7 +10,7 @@ import { generateQueryKeysFile } from '../../core/codegen/query-keys'; import { generateMutationKeysFile } from '../../core/codegen/mutation-keys'; import { generateInvalidationFile } from '../../core/codegen/invalidation'; import type { CleanTable, CleanFieldType, CleanRelations, CleanOperation, CleanTypeRef } from '../../types/schema'; -import type { ResolvedQueryKeyConfig, EntityRelationship } from '../../types/config'; +import type { QueryKeyConfig, EntityRelationship } from '../../types/config'; const fieldTypes = { uuid: { gqlType: 'UUID', isArray: false } as CleanFieldType, @@ -141,7 +141,7 @@ const fieldTable = createTable({ }, }); -const simpleConfig: ResolvedQueryKeyConfig = { +const simpleConfig: QueryKeyConfig = { style: 'hierarchical', relationships: {}, generateScopedKeys: true, diff --git a/graphql/codegen/src/__tests__/config/resolve-config.test.ts b/graphql/codegen/src/__tests__/config/resolve-config.test.ts index 984cc1a7e..92b74ed92 100644 --- a/graphql/codegen/src/__tests__/config/resolve-config.test.ts +++ b/graphql/codegen/src/__tests__/config/resolve-config.test.ts @@ -19,7 +19,7 @@ describe('config resolution', () => { const resolved = resolveConfig(config); expect(resolved.endpoint).toBe('https://api.example.com/graphql'); - expect(resolved.schema).toBeNull(); + expect(resolved.schema).toBeUndefined(); expect(resolved.output).toBe(DEFAULT_CONFIG.output); expect(resolved.tables.include).toEqual(DEFAULT_CONFIG.tables.include); expect(resolved.queries.exclude).toEqual(DEFAULT_CONFIG.queries.exclude); diff --git a/graphql/codegen/src/cli/commands/generate-orm.ts b/graphql/codegen/src/cli/commands/generate-orm.ts index 576d0ac0d..73dfc9d0a 100644 --- a/graphql/codegen/src/cli/commands/generate-orm.ts +++ b/graphql/codegen/src/cli/commands/generate-orm.ts @@ -4,7 +4,7 @@ * This is a thin CLI wrapper around the core generation functions. * All business logic is in the core modules. */ -import type { ResolvedTargetConfig } from '../../types/config'; +import type { TargetConfig } from '../../types/config'; import { loadAndResolveConfig, type ConfigOverrideOptions, @@ -118,7 +118,7 @@ export async function generateOrm( } async function generateOrmForTarget( - target: ResolvedTargetConfig, + target: TargetConfig, options: GenerateOrmOptions, isMultiTarget: boolean ): Promise { @@ -131,27 +131,18 @@ async function generateOrmForTarget( const formatMessage = (message: string) => isMultiTarget ? `Target "${target.name}": ${message}` : message; - // Extract extended options if present (attached by config resolver) - const database = (config as any).database as string | undefined; - const schemas = (config as any).schemas as string[] | undefined; - const apiNames = (config as any).apiNames as string[] | undefined; - const pgpmModulePath = (config as any).pgpmModulePath as string | undefined; - const pgpmWorkspacePath = (config as any).pgpmWorkspacePath as string | undefined; - const pgpmModuleName = (config as any).pgpmModuleName as string | undefined; - const keepDb = (config as any).keepDb as boolean | undefined; - if (isMultiTarget) { console.log(`\nTarget "${target.name}"`); let sourceLabel: string; - const schemaInfo = apiNames && apiNames.length > 0 - ? `apiNames: ${apiNames.join(', ')}` - : `schemas: ${(schemas ?? ['public']).join(', ')}`; - if (pgpmModulePath) { - sourceLabel = `pgpm module: ${pgpmModulePath} (${schemaInfo})`; - } else if (pgpmWorkspacePath && pgpmModuleName) { - sourceLabel = `pgpm workspace: ${pgpmWorkspacePath}, module: ${pgpmModuleName} (${schemaInfo})`; - } else if (database) { - sourceLabel = `database: ${database} (${schemaInfo})`; + const schemaInfo = config.apiNames && config.apiNames.length > 0 + ? `apiNames: ${config.apiNames.join(', ')}` + : `schemas: ${(config.schemas ?? ['public']).join(', ')}`; + if (config.pgpmModulePath) { + sourceLabel = `pgpm module: ${config.pgpmModulePath} (${schemaInfo})`; + } else if (config.pgpmWorkspacePath && config.pgpmModuleName) { + sourceLabel = `pgpm workspace: ${config.pgpmWorkspacePath}, module: ${config.pgpmModuleName} (${schemaInfo})`; + } else if (config.database) { + sourceLabel = `database: ${config.database} (${schemaInfo})`; } else if (config.schema) { sourceLabel = `schema: ${config.schema}`; } else { @@ -165,12 +156,12 @@ async function generateOrmForTarget( const sourceValidation = validateSourceOptions({ endpoint: config.endpoint || undefined, schema: config.schema || undefined, - database, - pgpmModulePath, - pgpmWorkspacePath, - pgpmModuleName, - schemas, - apiNames, + database: config.database, + pgpmModulePath: config.pgpmModulePath, + pgpmWorkspacePath: config.pgpmWorkspacePath, + pgpmModuleName: config.pgpmModuleName, + schemas: config.schemas, + apiNames: config.apiNames, }); if (!sourceValidation.valid) { return { @@ -184,14 +175,14 @@ async function generateOrmForTarget( const source = createSchemaSource({ endpoint: config.endpoint || undefined, schema: config.schema || undefined, - database, - pgpmModulePath, - pgpmWorkspacePath, - pgpmModuleName, - schemas, - apiNames, - keepDb, - authorization: options.authorization || config.headers['Authorization'], + database: config.database, + pgpmModulePath: config.pgpmModulePath, + pgpmWorkspacePath: config.pgpmWorkspacePath, + pgpmModuleName: config.pgpmModuleName, + schemas: config.schemas, + apiNames: config.apiNames, + keepDb: config.keepDb, + authorization: options.authorization || config.headers?.['Authorization'], headers: config.headers, }); diff --git a/graphql/codegen/src/cli/commands/generate-unified.ts b/graphql/codegen/src/cli/commands/generate-unified.ts index 85d3d6bbf..c7b537fbb 100644 --- a/graphql/codegen/src/cli/commands/generate-unified.ts +++ b/graphql/codegen/src/cli/commands/generate-unified.ts @@ -11,7 +11,7 @@ import path from 'path'; import * as t from '@babel/types'; import { generateCode, addJSDocComment } from '../../core/codegen/babel-ast'; -import type { ResolvedTargetConfig } from '../../types/config'; +import type { TargetConfig } from '../../types/config'; import { loadAndResolveConfig, type ConfigOverrideOptions, @@ -38,10 +38,10 @@ export interface GenerateOptions extends ConfigOverrideOptions { dryRun?: boolean; /** Skip custom operations (only generate table CRUD) */ skipCustomOperations?: boolean; - /** Override: generate React Query SDK regardless of config */ - reactQuery?: boolean; - /** Override: generate ORM client regardless of config */ - orm?: boolean; + /** Override: enable React Query SDK generation */ + enableReactQuery?: boolean; + /** Override: enable ORM client generation */ + enableOrm?: boolean; } export interface GenerateTargetResult { @@ -115,8 +115,8 @@ export async function generate( for (const target of targets) { // Determine which generators to run based on config and options - const runReactQuery = options.reactQuery ?? target.config.reactQuery.enabled; - const runOrm = options.orm ?? target.config.orm.enabled; + const runReactQuery = options.enableReactQuery ?? target.config.reactQuery?.enabled; + const runOrm = options.enableOrm ?? target.config.orm?.enabled; if (!runReactQuery && !runOrm) { results.push({ @@ -219,7 +219,7 @@ export async function generate( export async function generateReactQuery( options: GenerateOptions = {} ): Promise { - return generate({ ...options, reactQuery: true, orm: false }); + return generate({ ...options, enableReactQuery: true, enableOrm: false }); } /** @@ -228,7 +228,7 @@ export async function generateReactQuery( export async function generateOrm( options: GenerateOptions = {} ): Promise { - return generate({ ...options, reactQuery: false, orm: true }); + return generate({ ...options, enableReactQuery: false, enableOrm: true }); } // ============================================================================ @@ -242,7 +242,7 @@ interface PipelineRunResult { } async function runPipelineForTarget( - target: ResolvedTargetConfig, + target: TargetConfig, options: GenerateOptions, isMultiTarget: boolean ): Promise { @@ -251,27 +251,18 @@ async function runPipelineForTarget( const formatMessage = (message: string) => isMultiTarget ? `Target "${target.name}": ${message}` : message; - // Extract source options from config (now first-class citizens in ResolvedConfig) - const database = config.database ?? undefined; - const schemas = config.schemas.length > 0 ? config.schemas : undefined; - const apiNames = config.apiNames.length > 0 ? config.apiNames : undefined; - const pgpmModulePath = config.pgpmModulePath ?? undefined; - const pgpmWorkspacePath = config.pgpmWorkspacePath ?? undefined; - const pgpmModuleName = config.pgpmModuleName ?? undefined; - const keepDb = config.keepDb; - if (isMultiTarget) { console.log(`\nTarget "${target.name}"`); let sourceLabel: string; - const schemaInfo = apiNames && apiNames.length > 0 - ? `apiNames: ${apiNames.join(', ')}` - : `schemas: ${(schemas ?? ['public']).join(', ')}`; - if (pgpmModulePath) { - sourceLabel = `pgpm module: ${pgpmModulePath} (${schemaInfo})`; - } else if (pgpmWorkspacePath && pgpmModuleName) { - sourceLabel = `pgpm workspace: ${pgpmWorkspacePath}, module: ${pgpmModuleName} (${schemaInfo})`; - } else if (database) { - sourceLabel = `database: ${database} (${schemaInfo})`; + const schemaInfo = config.apiNames && config.apiNames.length > 0 + ? `apiNames: ${config.apiNames.join(', ')}` + : `schemas: ${(config.schemas ?? ['public']).join(', ')}`; + if (config.pgpmModulePath) { + sourceLabel = `pgpm module: ${config.pgpmModulePath} (${schemaInfo})`; + } else if (config.pgpmWorkspacePath && config.pgpmModuleName) { + sourceLabel = `pgpm workspace: ${config.pgpmWorkspacePath}, module: ${config.pgpmModuleName} (${schemaInfo})`; + } else if (config.database) { + sourceLabel = `database: ${config.database} (${schemaInfo})`; } else if (config.schema) { sourceLabel = `schema: ${config.schema}`; } else { @@ -284,12 +275,12 @@ async function runPipelineForTarget( const sourceValidation = validateSourceOptions({ endpoint: config.endpoint || undefined, schema: config.schema || undefined, - database, - pgpmModulePath, - pgpmWorkspacePath, - pgpmModuleName, - schemas, - apiNames, + database: config.database, + pgpmModulePath: config.pgpmModulePath, + pgpmWorkspacePath: config.pgpmWorkspacePath, + pgpmModuleName: config.pgpmModuleName, + schemas: config.schemas, + apiNames: config.apiNames, }); if (!sourceValidation.valid) { return { @@ -301,14 +292,14 @@ async function runPipelineForTarget( const source = createSchemaSource({ endpoint: config.endpoint || undefined, schema: config.schema || undefined, - database, - pgpmModulePath, - pgpmWorkspacePath, - pgpmModuleName, - schemas, - apiNames, - keepDb, - authorization: options.authorization || config.headers['Authorization'], + database: config.database, + pgpmModulePath: config.pgpmModulePath, + pgpmWorkspacePath: config.pgpmWorkspacePath, + pgpmModuleName: config.pgpmModuleName, + schemas: config.schemas, + apiNames: config.apiNames, + keepDb: config.keepDb, + authorization: options.authorization || config.headers?.['Authorization'], headers: config.headers, }); @@ -360,7 +351,7 @@ async function runPipelineForTarget( * orm/ - ORM client */ async function generateUnifiedOutput( - target: ResolvedTargetConfig, + target: TargetConfig, pipelineResult: PipelineResult, options: GenerateOptions, isMultiTarget: boolean @@ -474,7 +465,7 @@ function generateUnifiedBarrel(hasSchemaTypes: boolean): string { } async function generateReactQueryForTarget( - target: ResolvedTargetConfig, + target: TargetConfig, pipelineResult: PipelineResult, options: GenerateOptions, isMultiTarget: boolean, @@ -571,7 +562,7 @@ async function generateReactQueryForTarget( } async function generateOrmForTarget( - target: ResolvedTargetConfig, + target: TargetConfig, pipelineResult: PipelineResult, options: GenerateOptions, isMultiTarget: boolean, diff --git a/graphql/codegen/src/cli/commands/generate.ts b/graphql/codegen/src/cli/commands/generate.ts index 1bd6da45e..07f7f6ad6 100644 --- a/graphql/codegen/src/cli/commands/generate.ts +++ b/graphql/codegen/src/cli/commands/generate.ts @@ -4,7 +4,7 @@ * This is a thin CLI wrapper around the core generation functions. * All business logic is in the core modules. */ -import type { ResolvedTargetConfig } from '../../types/config'; +import type { TargetConfig } from '../../types/config'; import { loadAndResolveConfig, type ConfigOverrideOptions, @@ -118,7 +118,7 @@ export async function generateReactQuery( } async function generateForTarget( - target: ResolvedTargetConfig, + target: TargetConfig, options: GenerateOptions, isMultiTarget: boolean ): Promise { @@ -130,27 +130,18 @@ async function generateForTarget( const formatMessage = (message: string) => isMultiTarget ? `Target "${target.name}": ${message}` : message; - // Extract extended options if present (attached by config resolver) - const database = (config as any).database as string | undefined; - const schemas = (config as any).schemas as string[] | undefined; - const apiNames = (config as any).apiNames as string[] | undefined; - const pgpmModulePath = (config as any).pgpmModulePath as string | undefined; - const pgpmWorkspacePath = (config as any).pgpmWorkspacePath as string | undefined; - const pgpmModuleName = (config as any).pgpmModuleName as string | undefined; - const keepDb = (config as any).keepDb as boolean | undefined; - if (isMultiTarget) { console.log(`\nTarget "${target.name}"`); let sourceLabel: string; - const schemaInfo = apiNames && apiNames.length > 0 - ? `apiNames: ${apiNames.join(', ')}` - : `schemas: ${(schemas ?? ['public']).join(', ')}`; - if (pgpmModulePath) { - sourceLabel = `pgpm module: ${pgpmModulePath} (${schemaInfo})`; - } else if (pgpmWorkspacePath && pgpmModuleName) { - sourceLabel = `pgpm workspace: ${pgpmWorkspacePath}, module: ${pgpmModuleName} (${schemaInfo})`; - } else if (database) { - sourceLabel = `database: ${database} (${schemaInfo})`; + const schemaInfo = config.apiNames && config.apiNames.length > 0 + ? `apiNames: ${config.apiNames.join(', ')}` + : `schemas: ${(config.schemas ?? ['public']).join(', ')}`; + if (config.pgpmModulePath) { + sourceLabel = `pgpm module: ${config.pgpmModulePath} (${schemaInfo})`; + } else if (config.pgpmWorkspacePath && config.pgpmModuleName) { + sourceLabel = `pgpm workspace: ${config.pgpmWorkspacePath}, module: ${config.pgpmModuleName} (${schemaInfo})`; + } else if (config.database) { + sourceLabel = `database: ${config.database} (${schemaInfo})`; } else if (config.schema) { sourceLabel = `schema: ${config.schema}`; } else { @@ -164,12 +155,12 @@ async function generateForTarget( const sourceValidation = validateSourceOptions({ endpoint: config.endpoint || undefined, schema: config.schema || undefined, - database, - pgpmModulePath, - pgpmWorkspacePath, - pgpmModuleName, - schemas, - apiNames, + database: config.database, + pgpmModulePath: config.pgpmModulePath, + pgpmWorkspacePath: config.pgpmWorkspacePath, + pgpmModuleName: config.pgpmModuleName, + schemas: config.schemas, + apiNames: config.apiNames, }); if (!sourceValidation.valid) { return { @@ -183,14 +174,14 @@ async function generateForTarget( const source = createSchemaSource({ endpoint: config.endpoint || undefined, schema: config.schema || undefined, - database, - pgpmModulePath, - pgpmWorkspacePath, - pgpmModuleName, - schemas, - apiNames, - keepDb, - authorization: options.authorization || config.headers['Authorization'], + database: config.database, + pgpmModulePath: config.pgpmModulePath, + pgpmWorkspacePath: config.pgpmWorkspacePath, + pgpmModuleName: config.pgpmModuleName, + schemas: config.schemas, + apiNames: config.apiNames, + keepDb: config.keepDb, + authorization: options.authorization || config.headers?.['Authorization'], headers: config.headers, }); diff --git a/graphql/codegen/src/cli/index.ts b/graphql/codegen/src/cli/index.ts index 592f2faa0..0e196f6c3 100644 --- a/graphql/codegen/src/cli/index.ts +++ b/graphql/codegen/src/cli/index.ts @@ -10,7 +10,7 @@ import { generate, generateReactQuery, generateOrm } from './commands/generate-u import { loadWatchConfig } from '../core/config'; import { startWatch } from '../core/watch'; import { createSchemaSource, inferTablesFromIntrospection } from '../core/introspect'; -import type { ResolvedConfig } from '../types/config'; +import type { GraphQLSDKConfigTarget } from '../types/config'; const usageText = ` graphql-codegen - GraphQL SDK generator for Constructive databases @@ -268,8 +268,8 @@ async function handleGenerate(argv: Partial): Promise { dryRun, skipCustomOperations, keepDb, - reactQuery, - orm, + enableReactQuery: reactQuery, + enableOrm: orm, }); const duration = formatDuration(performance.now() - startTime); diff --git a/graphql/codegen/src/core/codegen/index.ts b/graphql/codegen/src/core/codegen/index.ts index 139ebc064..e5b7b5aa1 100644 --- a/graphql/codegen/src/core/codegen/index.ts +++ b/graphql/codegen/src/core/codegen/index.ts @@ -28,7 +28,7 @@ import type { CleanOperation, TypeRegistry, } from '../../types/schema'; -import type { ResolvedConfig, ResolvedQueryKeyConfig } from '../../types/config'; +import type { GraphQLSDKConfigTarget, QueryKeyConfig } from '../../types/config'; import { DEFAULT_QUERY_KEY_CONFIG } from '../../types/config'; import { generateClientFile } from './client'; @@ -82,8 +82,8 @@ export interface GenerateOptions { mutations: CleanOperation[]; typeRegistry: TypeRegistry; }; - /** Resolved configuration */ - config: ResolvedConfig; + /** Configuration */ + config: GraphQLSDKConfigTarget; /** * Path to shared types directory (relative import path). * When provided, types.ts and schema-types.ts are NOT generated @@ -102,7 +102,7 @@ export interface GenerateOptions { */ export function generateAllFiles( tables: CleanTable[], - config: ResolvedConfig + config: GraphQLSDKConfigTarget ): GenerateResult { return generate({ tables, config }); } @@ -123,7 +123,7 @@ export function generate(options: GenerateOptions): GenerateResult { const reactQueryEnabled = config.reactQuery.enabled; // Query key configuration (use defaults if not provided) - const queryKeyConfig: ResolvedQueryKeyConfig = config.queryKeys ?? DEFAULT_QUERY_KEY_CONFIG; + const queryKeyConfig: QueryKeyConfig = config.queryKeys ?? DEFAULT_QUERY_KEY_CONFIG; const useCentralizedKeys = queryKeyConfig.generateScopedKeys; const hasRelationships = Object.keys(queryKeyConfig.relationships).length > 0; diff --git a/graphql/codegen/src/core/codegen/invalidation.ts b/graphql/codegen/src/core/codegen/invalidation.ts index e7f07add6..96247303e 100644 --- a/graphql/codegen/src/core/codegen/invalidation.ts +++ b/graphql/codegen/src/core/codegen/invalidation.ts @@ -5,7 +5,7 @@ * for parent-child entity relationships. */ import type { CleanTable } from '../../types/schema'; -import type { ResolvedQueryKeyConfig, EntityRelationship } from '../../types/config'; +import type { QueryKeyConfig, EntityRelationship } from '../../types/config'; import { getTableNames, getGeneratedFileHeader, ucFirst, lcFirst } from './utils'; import * as t from '@babel/types'; import { @@ -18,7 +18,7 @@ import { export interface InvalidationGeneratorOptions { tables: CleanTable[]; - config: ResolvedQueryKeyConfig; + config: QueryKeyConfig; } export interface GeneratedInvalidationFile { diff --git a/graphql/codegen/src/core/codegen/mutation-keys.ts b/graphql/codegen/src/core/codegen/mutation-keys.ts index 657e1fb5a..431d84fe3 100644 --- a/graphql/codegen/src/core/codegen/mutation-keys.ts +++ b/graphql/codegen/src/core/codegen/mutation-keys.ts @@ -8,7 +8,7 @@ * - Tracking mutation state with useIsMutating */ import type { CleanTable, CleanOperation } from '../../types/schema'; -import type { ResolvedQueryKeyConfig, EntityRelationship } from '../../types/config'; +import type { QueryKeyConfig, EntityRelationship } from '../../types/config'; import { getTableNames, getGeneratedFileHeader, lcFirst } from './utils'; import * as t from '@babel/types'; import { @@ -22,7 +22,7 @@ import { export interface MutationKeyGeneratorOptions { tables: CleanTable[]; customMutations: CleanOperation[]; - config: ResolvedQueryKeyConfig; + config: QueryKeyConfig; } export interface GeneratedMutationKeysFile { diff --git a/graphql/codegen/src/core/codegen/orm/index.ts b/graphql/codegen/src/core/codegen/orm/index.ts index 919173248..e749e3ca6 100644 --- a/graphql/codegen/src/core/codegen/orm/index.ts +++ b/graphql/codegen/src/core/codegen/orm/index.ts @@ -5,7 +5,7 @@ * and produces the complete ORM client output. */ import type { CleanTable, CleanOperation, TypeRegistry } from '../../../types/schema'; -import type { ResolvedConfig } from '../../../types/config'; +import type { GraphQLSDKConfigTarget } from '../../../types/config'; import { generateOrmClientFile, generateQueryBuilderFile, @@ -32,7 +32,7 @@ export interface GenerateOrmOptions { mutations: CleanOperation[]; typeRegistry?: TypeRegistry; }; - config: ResolvedConfig; + config: GraphQLSDKConfigTarget; /** * Path to shared types directory (relative import path). * When provided, entity types are imported from shared types diff --git a/graphql/codegen/src/core/codegen/query-keys.ts b/graphql/codegen/src/core/codegen/query-keys.ts index ba32cff8c..791d4eec6 100644 --- a/graphql/codegen/src/core/codegen/query-keys.ts +++ b/graphql/codegen/src/core/codegen/query-keys.ts @@ -11,7 +11,7 @@ import * as t from '@babel/types'; import type { CleanTable, CleanOperation } from '../../types/schema'; -import type { ResolvedQueryKeyConfig, EntityRelationship } from '../../types/config'; +import type { QueryKeyConfig, EntityRelationship } from '../../types/config'; import { getTableNames, getGeneratedFileHeader, ucFirst, lcFirst } from './utils'; import { generateCode, @@ -25,7 +25,7 @@ import { export interface QueryKeyGeneratorOptions { tables: CleanTable[]; customQueries: CleanOperation[]; - config: ResolvedQueryKeyConfig; + config: QueryKeyConfig; } export interface GeneratedQueryKeysFile { diff --git a/graphql/codegen/src/core/codegen/shared/index.ts b/graphql/codegen/src/core/codegen/shared/index.ts index 9a294d632..ccf6819fe 100644 --- a/graphql/codegen/src/core/codegen/shared/index.ts +++ b/graphql/codegen/src/core/codegen/shared/index.ts @@ -12,7 +12,7 @@ * filters.ts - Filter types (StringFilter, IntFilter, etc.) */ import type { CleanTable, CleanOperation, TypeRegistry } from '../../../types/schema'; -import type { ResolvedConfig } from '../../../types/config'; +import type { GraphQLSDKConfigTarget } from '../../../types/config'; import * as t from '@babel/types'; import { generateCode, addJSDocComment } from '../babel-ast'; import { generateTypesFile } from '../types'; @@ -38,7 +38,7 @@ export interface GenerateSharedOptions { mutations: CleanOperation[]; typeRegistry: TypeRegistry; }; - config: ResolvedConfig; + config: GraphQLSDKConfigTarget; } export interface GenerateSharedResult { diff --git a/graphql/codegen/src/core/config/index.ts b/graphql/codegen/src/core/config/index.ts index ef792ec1f..239e5581b 100644 --- a/graphql/codegen/src/core/config/index.ts +++ b/graphql/codegen/src/core/config/index.ts @@ -10,7 +10,6 @@ export { } from './loader'; export { - buildTargetOverrides, loadAndResolveConfig, loadWatchConfig, type ConfigOverrideOptions, diff --git a/graphql/codegen/src/core/config/resolver.ts b/graphql/codegen/src/core/config/resolver.ts index 38230d9e4..b1ecd47ad 100644 --- a/graphql/codegen/src/core/config/resolver.ts +++ b/graphql/codegen/src/core/config/resolver.ts @@ -8,40 +8,20 @@ import type { GraphQLSDKConfig, GraphQLSDKConfigTarget, GraphQLSDKMultiConfig, - ResolvedConfig, - ResolvedTargetConfig, + TargetConfig, } from '../../types/config'; -import { isMultiConfig, mergeConfig, resolveConfig } from '../../types/config'; +import { isMultiConfig, mergeConfig, getConfigOptions } from '../../types/config'; import { findConfigFile, loadConfigFile } from './loader'; /** - * Options that can override config file settings + * CLI options that can override config file settings. + * Extends GraphQLSDKConfigTarget with CLI-specific fields. */ -export interface ConfigOverrideOptions { - /** Path to config file */ +export interface ConfigOverrideOptions extends GraphQLSDKConfigTarget { + /** Path to config file (CLI-only) */ config?: string; - /** Named target in a multi-target config */ + /** Named target in a multi-target config (CLI-only) */ target?: string; - /** GraphQL endpoint URL (overrides config) */ - endpoint?: string; - /** Path to GraphQL schema file (.graphql) */ - schema?: string; - /** Database name or connection string (for database introspection) */ - database?: string; - /** Path to a PGPM module directory (for module introspection) */ - pgpmModulePath?: string; - /** Path to a PGPM workspace directory (used with pgpmModuleName) */ - pgpmWorkspacePath?: string; - /** Name of the module within the workspace (used with pgpmWorkspacePath) */ - pgpmModuleName?: string; - /** PostgreSQL schemas to include (for database and pgpm module modes) - mutually exclusive with apiNames */ - schemas?: string[]; - /** API names to resolve schemas from (for database and pgpm module modes) - mutually exclusive with schemas */ - apiNames?: string[]; - /** Keep the ephemeral database after introspection (for debugging, pgpm module mode only) */ - keepDb?: boolean; - /** Output directory (overrides config) */ - output?: string; } /** @@ -49,65 +29,11 @@ export interface ConfigOverrideOptions { */ export interface LoadConfigResult { success: boolean; - targets?: ResolvedTargetConfig[]; + targets?: TargetConfig[]; isMulti?: boolean; error?: string; } -/** - * Build target overrides from CLI options - * - * Note: Validation that only one source is specified happens in loadAndResolveConfig, - * so we don't need to clear other source fields here. - */ -export function buildTargetOverrides( - options: ConfigOverrideOptions -): GraphQLSDKConfigTarget { - const overrides: GraphQLSDKConfigTarget = {}; - - if (options.endpoint) { - overrides.endpoint = options.endpoint; - } - - if (options.schema) { - overrides.schema = options.schema; - } - - if (options.database) { - overrides.database = options.database; - } - - if (options.pgpmModulePath) { - overrides.pgpmModulePath = options.pgpmModulePath; - } - - if (options.pgpmWorkspacePath) { - overrides.pgpmWorkspacePath = options.pgpmWorkspacePath; - } - - if (options.pgpmModuleName) { - overrides.pgpmModuleName = options.pgpmModuleName; - } - - if (options.schemas) { - overrides.schemas = options.schemas; - } - - if (options.apiNames) { - overrides.apiNames = options.apiNames; - } - - if (options.keepDb !== undefined) { - overrides.keepDb = options.keepDb; - } - - if (options.output) { - overrides.output = options.output; - } - - return overrides; -} - /** * Load and resolve configuration from file and/or options * @@ -120,15 +46,18 @@ export function buildTargetOverrides( export async function loadAndResolveConfig( options: ConfigOverrideOptions ): Promise { + // Destructure CLI-only fields, rest is config overrides + const { config: configPath, target: targetName, ...overrides } = options; + // Check for pgpm workspace mode (requires both pgpmWorkspacePath and pgpmModuleName) - const hasPgpmWorkspace = options.pgpmWorkspacePath && options.pgpmModuleName; + const hasPgpmWorkspace = overrides.pgpmWorkspacePath && overrides.pgpmModuleName; // Validate that at most one source is specified const sources = [ - options.endpoint, - options.schema, - options.database, - options.pgpmModulePath, + overrides.endpoint, + overrides.schema, + overrides.database, + overrides.pgpmModulePath, hasPgpmWorkspace, ].filter(Boolean); if (sources.length > 1) { @@ -140,28 +69,26 @@ export async function loadAndResolveConfig( } // Find config file - let configPath = options.config; - if (!configPath) { - configPath = findConfigFile() ?? undefined; + let resolvedConfigPath = configPath; + if (!resolvedConfigPath) { + resolvedConfigPath = findConfigFile() ?? undefined; } let baseConfig: GraphQLSDKConfig = {}; - if (configPath) { - const loadResult = await loadConfigFile(configPath); + if (resolvedConfigPath) { + const loadResult = await loadConfigFile(resolvedConfigPath); if (!loadResult.success) { return { success: false, error: loadResult.error }; } baseConfig = loadResult.config; } - const overrides = buildTargetOverrides(options); - if (isMultiConfig(baseConfig)) { - return resolveMultiTargetConfig(baseConfig, options, overrides); + return resolveMultiTargetConfig(baseConfig, targetName, overrides); } - return resolveSingleTargetConfig(baseConfig as GraphQLSDKConfigTarget, options, overrides); + return resolveSingleTargetConfig(baseConfig as GraphQLSDKConfigTarget, targetName, overrides); } /** @@ -169,7 +96,7 @@ export async function loadAndResolveConfig( */ function resolveMultiTargetConfig( baseConfig: GraphQLSDKMultiConfig, - options: ConfigOverrideOptions, + targetName: string | undefined, overrides: GraphQLSDKConfigTarget ): LoadConfigResult { if (Object.keys(baseConfig.targets).length === 0) { @@ -180,9 +107,9 @@ function resolveMultiTargetConfig( } if ( - !options.target && - (options.endpoint || options.schema || options.database || - options.pgpmModulePath || options.pgpmWorkspacePath || options.output) + !targetName && + (overrides.endpoint || overrides.schema || overrides.database || + overrides.pgpmModulePath || overrides.pgpmWorkspacePath || overrides.output) ) { return { success: false, @@ -191,22 +118,22 @@ function resolveMultiTargetConfig( }; } - if (options.target && !baseConfig.targets[options.target]) { + if (targetName && !baseConfig.targets[targetName]) { return { success: false, - error: `Target "${options.target}" not found in config file.`, + error: `Target "${targetName}" not found in config file.`, }; } - const selectedTargets = options.target - ? { [options.target]: baseConfig.targets[options.target] } + const selectedTargets = targetName + ? { [targetName]: baseConfig.targets[targetName] } : baseConfig.targets; const defaults = baseConfig.defaults ?? {}; - const resolvedTargets: ResolvedTargetConfig[] = []; + const resolvedTargets: TargetConfig[] = []; for (const [name, target] of Object.entries(selectedTargets)) { let mergedTarget = mergeConfig(defaults, target); - if (options.target && name === options.target) { + if (targetName && name === targetName) { mergedTarget = mergeConfig(mergedTarget, overrides); } @@ -226,7 +153,7 @@ function resolveMultiTargetConfig( resolvedTargets.push({ name, - config: resolveConfig(mergedTarget), + config: getConfigOptions(mergedTarget), }); } @@ -242,10 +169,10 @@ function resolveMultiTargetConfig( */ function resolveSingleTargetConfig( baseConfig: GraphQLSDKConfigTarget, - options: ConfigOverrideOptions, + targetName: string | undefined, overrides: GraphQLSDKConfigTarget ): LoadConfigResult { - if (options.target) { + if (targetName) { return { success: false, error: @@ -271,13 +198,9 @@ function resolveSingleTargetConfig( }; } - // All source options are now first-class citizens in the config types, - // so resolveConfig handles them properly without any casts - const resolvedConfig = resolveConfig(mergedConfig); - return { success: true, - targets: [{ name: 'default', config: resolvedConfig }], + targets: [{ name: 'default', config: getConfigOptions(mergedConfig) }], isMulti: false, }; } @@ -296,7 +219,7 @@ export async function loadWatchConfig(options: { debounce?: number; touch?: string; clear?: boolean; -}): Promise { +}): Promise { let configPath = options.config; if (!configPath) { configPath = findConfigFile() ?? undefined; @@ -374,5 +297,5 @@ export async function loadWatchConfig(options: { return null; } - return resolveConfig(mergedTarget); + return getConfigOptions(mergedTarget); } diff --git a/graphql/codegen/src/core/pipeline/index.ts b/graphql/codegen/src/core/pipeline/index.ts index c75d5011f..65aba4e21 100644 --- a/graphql/codegen/src/core/pipeline/index.ts +++ b/graphql/codegen/src/core/pipeline/index.ts @@ -8,7 +8,7 @@ * - Operation transformation * - Filtering */ -import type { ResolvedConfig } from '../../types/config'; +import type { GraphQLSDKConfigTarget } from '../../types/config'; import type { CleanTable, CleanOperation, @@ -39,9 +39,9 @@ export interface CodegenPipelineOptions { source: SchemaSource; /** - * Resolved configuration + * Configuration */ - config: ResolvedConfig; + config: GraphQLSDKConfigTarget; /** * Enable verbose logging diff --git a/graphql/codegen/src/core/watch/orchestrator.ts b/graphql/codegen/src/core/watch/orchestrator.ts index 7e6f04fb6..f73fbe413 100644 --- a/graphql/codegen/src/core/watch/orchestrator.ts +++ b/graphql/codegen/src/core/watch/orchestrator.ts @@ -4,7 +4,7 @@ * Coordinates schema polling, change detection, and code regeneration */ -import type { ResolvedConfig } from '../../types/config'; +import type { GraphQLSDKConfigTarget } from '../../types/config'; import type { GeneratorType, WatchOptions, PollEvent } from './types'; import { SchemaPoller } from './poller'; import { debounce } from './debounce'; @@ -32,7 +32,7 @@ export interface GenerateResult { } export interface WatchOrchestratorOptions { - config: ResolvedConfig; + config: GraphQLSDKConfigTarget; generatorType: GeneratorType; verbose: boolean; authorization?: string; diff --git a/graphql/codegen/src/types/config.ts b/graphql/codegen/src/types/config.ts index 80e4f1140..967d3e9a9 100644 --- a/graphql/codegen/src/types/config.ts +++ b/graphql/codegen/src/types/config.ts @@ -327,123 +327,20 @@ export interface WatchConfig { clearScreen?: boolean; } -/** - * Resolved watch configuration with defaults applied - */ -export interface ResolvedWatchConfig { - pollInterval: number; - debounce: number; - touchFile: string | null; - clearScreen: boolean; -} - -/** - * Resolved query key configuration with defaults applied - */ -export interface ResolvedQueryKeyConfig { - style: 'flat' | 'hierarchical'; - relationships: Record; - generateScopedKeys: boolean; - generateCascadeHelpers: boolean; - generateMutationKeys: boolean; -} - -/** - * Resolved configuration with defaults applied - */ -export interface ResolvedConfig { - /** - * GraphQL endpoint URL (empty string if using other source) - */ - endpoint: string; - /** - * Path to GraphQL schema file (null if using other source) - */ - schema: string | null; - /** - * Database name or connection string (null if using other source) - */ - database: string | null; - /** - * Path to PGPM module (null if using other source) - */ - pgpmModulePath: string | null; - /** - * Path to PGPM workspace (null if using other source) - */ - pgpmWorkspacePath: string | null; - /** - * Module name within PGPM workspace (null if using other source) - */ - pgpmModuleName: string | null; - /** - * PostgreSQL schemas to introspect (for database and PGPM modes) - */ - schemas: string[]; - /** - * API names to resolve schemas from (for database and PGPM modes) - */ - apiNames: string[]; - /** - * Keep ephemeral database after introspection (for PGPM modes) - */ - keepDb: boolean; - headers: Record; - output: string; - tables: { - include: string[]; - exclude: string[]; - systemExclude: string[]; - }; - queries: { - include: string[]; - exclude: string[]; - systemExclude: string[]; - }; - mutations: { - include: string[]; - exclude: string[]; - systemExclude: string[]; - }; - excludeFields: string[]; - hooks: { - queries: boolean; - mutations: boolean; - queryKeyPrefix: string; - }; - postgraphile: { - schema: string; - }; - codegen: { - maxFieldDepth: number; - skipQueryField: boolean; - }; - orm: { - enabled: boolean; - output: string; - useSharedTypes: boolean; - }; - reactQuery: { - enabled: boolean; - }; - queryKeys: ResolvedQueryKeyConfig; - watch: ResolvedWatchConfig; -} - /** * Default watch configuration values */ -export const DEFAULT_WATCH_CONFIG: ResolvedWatchConfig = { +export const DEFAULT_WATCH_CONFIG: WatchConfig = { pollInterval: 3000, debounce: 800, - touchFile: null, + touchFile: undefined, clearScreen: true, }; /** * Default query key configuration values */ -export const DEFAULT_QUERY_KEY_CONFIG: ResolvedQueryKeyConfig = { +export const DEFAULT_QUERY_KEY_CONFIG: QueryKeyConfig = { style: 'hierarchical', relationships: {}, generateScopedKeys: true, @@ -454,16 +351,8 @@ export const DEFAULT_QUERY_KEY_CONFIG: ResolvedQueryKeyConfig = { /** * Default configuration values */ -export const DEFAULT_CONFIG: ResolvedConfig = { +export const DEFAULT_CONFIG: GraphQLSDKConfigTarget = { endpoint: '', - schema: null, - database: null, - pgpmModulePath: null, - pgpmWorkspacePath: null, - pgpmModuleName: null, - schemas: [], - apiNames: [], - keepDb: false, headers: {}, output: './generated/graphql', tables: { @@ -515,11 +404,11 @@ export function defineConfig(config: GraphQLSDKConfig): GraphQLSDKConfig { } /** - * Resolved target configuration helper + * Target configuration with name (used after resolution) */ -export interface ResolvedTargetConfig { +export interface TargetConfig { name: string; - config: ResolvedConfig; + config: GraphQLSDKConfigTarget; } /** @@ -544,18 +433,27 @@ export function mergeConfig( return deepmerge(base, overrides, { arrayMerge: replaceArrays }); } +/** + * Get configuration options by merging defaults with user config. + * Similar to getEnvOptions pattern from @pgpmjs/env. + */ +export function getConfigOptions( + overrides: GraphQLSDKConfigTarget = {} +): GraphQLSDKConfigTarget { + return deepmerge(DEFAULT_CONFIG, overrides, { arrayMerge: replaceArrays }); +} + /** * Resolve configuration by applying defaults. - * Uses deepmerge with array replacement strategy. + * For single-target configs only - throws for multi-target configs. */ -export function resolveConfig(config: GraphQLSDKConfig): ResolvedConfig { +export function resolveConfig(config: GraphQLSDKConfig): GraphQLSDKConfigTarget { if (isMultiConfig(config)) { throw new Error( 'Multi-target config cannot be resolved with resolveConfig(). Use resolveConfigTargets().' ); } - - return deepmerge(DEFAULT_CONFIG, config, { arrayMerge: replaceArrays }) as ResolvedConfig; + return getConfigOptions(config); } /** @@ -563,11 +461,11 @@ export function resolveConfig(config: GraphQLSDKConfig): ResolvedConfig { */ export function resolveConfigTargets( config: GraphQLSDKMultiConfig -): ResolvedTargetConfig[] { +): TargetConfig[] { const defaults = config.defaults ?? {}; return Object.entries(config.targets).map(([name, target]) => ({ name, - config: resolveConfig(mergeConfig(defaults, target)), + config: getConfigOptions(mergeConfig(defaults, target)), })); } diff --git a/graphql/codegen/src/types/index.ts b/graphql/codegen/src/types/index.ts index 0498e391e..b88fafff7 100644 --- a/graphql/codegen/src/types/index.ts +++ b/graphql/codegen/src/types/index.ts @@ -53,13 +53,13 @@ export type { GraphQLSDKConfig, GraphQLSDKConfigTarget, GraphQLSDKMultiConfig, - ResolvedConfig, - ResolvedTargetConfig, + TargetConfig, } from './config'; export { defineConfig, - resolveConfig, + getConfigOptions, + mergeConfig, resolveConfigTargets, DEFAULT_CONFIG, } from './config'; From e33f55505bf46f133ab3d2e041412fe9dae9608b Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 23 Jan 2026 13:13:10 +0000 Subject: [PATCH 14/23] fix(cli): use enableReactQuery/enableOrm instead of reactQuery/orm in codegen command --- packages/cli/src/commands/codegen.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/commands/codegen.ts b/packages/cli/src/commands/codegen.ts index 7538a6dae..1c627649e 100644 --- a/packages/cli/src/commands/codegen.ts +++ b/packages/cli/src/commands/codegen.ts @@ -175,8 +175,8 @@ export default async ( verbose, dryRun, // Use flags to control which generators run - reactQuery: !orm, - orm: orm, + enableReactQuery: !orm, + enableOrm: orm, }); printResult(result); From 699fbbc4ea7ff692c7a21d87943b00c231f1e259 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 23 Jan 2026 13:25:27 +0000 Subject: [PATCH 15/23] test(cli): update codegen test to use enableReactQuery/enableOrm field names --- packages/cli/__tests__/codegen.test.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/cli/__tests__/codegen.test.ts b/packages/cli/__tests__/codegen.test.ts index 31e42c73b..060488e7d 100644 --- a/packages/cli/__tests__/codegen.test.ts +++ b/packages/cli/__tests__/codegen.test.ts @@ -58,10 +58,10 @@ describe('codegen command', () => { authorization: 'Bearer testtoken', verbose: true, dryRun: true, - reactQuery: true + enableReactQuery: true }) - // orm is undefined when not set (defaults to false via !orm) - expect(call.orm).toBeFalsy() + // enableOrm is undefined when not set (defaults to false via !orm) + expect(call.enableOrm).toBeFalsy() }) it('builds schema file and calls generate with schema when DB options provided', async () => { @@ -82,8 +82,8 @@ describe('codegen command', () => { expect(call.schema).toBe('graphql/codegen/dist/schema.graphql') expect(call.output).toBe('graphql/codegen/dist') expect(call.endpoint).toBeUndefined() - expect(call.reactQuery).toBe(true) - // orm is undefined when not set (defaults to false via !orm) - expect(call.orm).toBeFalsy() + expect(call.enableReactQuery).toBe(true) + // enableOrm is undefined when not set (defaults to false via !orm) + expect(call.enableOrm).toBeFalsy() }) }) From 6d9cd87ecd2e67e47d190faf44f270dbba333b93 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 23 Jan 2026 13:39:02 +0000 Subject: [PATCH 16/23] feat(graphql-codegen): add localhost DNS resolution for *.localhost endpoints during introspection This fixes DNS resolution issues on macOS where subdomains like api.localhost don't resolve automatically to 127.0.0.1 (unlike browsers which handle *.localhost). Uses undici Agent with custom DNS lookup to resolve *.localhost to 127.0.0.1 at codegen time only. The generated client code remains browser-compatible. --- graphql/codegen/package.json | 11 +-- .../src/core/introspect/fetch-schema.ts | 72 ++++++++++++++++--- pnpm-lock.yaml | 9 +++ 3 files changed, 78 insertions(+), 14 deletions(-) diff --git a/graphql/codegen/package.json b/graphql/codegen/package.json index 59a882193..96faf7e75 100644 --- a/graphql/codegen/package.json +++ b/graphql/codegen/package.json @@ -44,10 +44,10 @@ "fmt:check": "prettier --check .", "test": "jest --passWithNoTests", "test:watch": "jest --watch", - "example:codegen:sdk": "tsx src/cli/index.ts generate --config examples/multi-target.config.ts --reactquery", - "example:codegen:orm": "tsx src/cli/index.ts generate --config examples/multi-target.config.ts --orm", - "example:codegen:sdk:schema": "node dist/cli/index.js generate --schema examples/example.schema.graphql --output examples/output/generated-sdk-schema --reactquery", - "example:codegen:orm:schema": "node dist/cli/index.js generate --schema examples/example.schema.graphql --output examples/output/generated-orm-schema --orm", + "example:codegen:sdk": "tsx src/cli/index.ts generate --config examples/multi-target.config.ts --reactquery", + "example:codegen:orm": "tsx src/cli/index.ts generate --config examples/multi-target.config.ts --orm", + "example:codegen:sdk:schema": "node dist/cli/index.js generate --schema examples/example.schema.graphql --output examples/output/generated-sdk-schema --reactquery", + "example:codegen:orm:schema": "node dist/cli/index.js generate --schema examples/example.schema.graphql --output examples/output/generated-orm-schema --orm", "example:sdk": "tsx examples/react-hooks-sdk-test.tsx", "example:orm": "tsx examples/orm-sdk-test.ts", "example:sdk:typecheck": "tsc --noEmit --jsx react --esModuleInterop --skipLibCheck --moduleResolution node examples/react-hooks-sdk-test.tsx" @@ -72,7 +72,8 @@ "pg-env": "workspace:^", "pgsql-client": "workspace:^", "pgsql-seed": "workspace:^", - "prettier": "^3.7.4" + "prettier": "^3.7.4", + "undici": "^7.19.0" }, "peerDependencies": { "@tanstack/react-query": "^5.0.0", diff --git a/graphql/codegen/src/core/introspect/fetch-schema.ts b/graphql/codegen/src/core/introspect/fetch-schema.ts index 3002ac944..383552f78 100644 --- a/graphql/codegen/src/core/introspect/fetch-schema.ts +++ b/graphql/codegen/src/core/introspect/fetch-schema.ts @@ -1,9 +1,46 @@ /** * Fetch GraphQL schema introspection from an endpoint */ +import dns from 'node:dns'; +import { Agent } from 'undici'; import { SCHEMA_INTROSPECTION_QUERY } from './schema-query'; import type { IntrospectionQueryResponse } from '../../types/introspection'; +/** + * Check if a hostname is localhost or a localhost subdomain + */ +function isLocalhostHostname(hostname: string): boolean { + return hostname === 'localhost' || hostname.endsWith('.localhost'); +} + +/** + * Create an undici Agent that resolves *.localhost to 127.0.0.1 + * This fixes DNS resolution issues on macOS where subdomains like api.localhost + * don't resolve automatically (unlike browsers which handle *.localhost). + */ +function createLocalhostAgent(): Agent { + return new Agent({ + connect: { + lookup(hostname, opts, cb) { + if (isLocalhostHostname(hostname)) { + cb(null, '127.0.0.1', 4); + return; + } + dns.lookup(hostname, opts, cb); + }, + }, + }); +} + +let localhostAgent: Agent | null = null; + +function getLocalhostAgent(): Agent { + if (!localhostAgent) { + localhostAgent = createLocalhostAgent(); + } + return localhostAgent; +} + export interface FetchSchemaOptions { /** GraphQL endpoint URL */ endpoint: string; @@ -30,6 +67,10 @@ export async function fetchSchema( ): Promise { const { endpoint, authorization, headers = {}, timeout = 30000 } = options; + // Parse the endpoint URL to check for localhost + const url = new URL(endpoint); + const useLocalhostAgent = isLocalhostHostname(url.hostname); + // Build headers const requestHeaders: Record = { 'Content-Type': 'application/json', @@ -37,6 +78,11 @@ export async function fetchSchema( ...headers, }; + // Set Host header for localhost subdomains to preserve routing + if (useLocalhostAgent && url.hostname !== 'localhost') { + requestHeaders['Host'] = url.hostname; + } + if (authorization) { requestHeaders['Authorization'] = authorization; } @@ -45,16 +91,24 @@ export async function fetchSchema( const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), timeout); + // Build fetch options + const fetchOptions: RequestInit & { dispatcher?: Agent } = { + method: 'POST', + headers: requestHeaders, + body: JSON.stringify({ + query: SCHEMA_INTROSPECTION_QUERY, + variables: {}, + }), + signal: controller.signal, + }; + + // Use custom agent for localhost to fix DNS resolution on macOS + if (useLocalhostAgent) { + fetchOptions.dispatcher = getLocalhostAgent(); + } + try { - const response = await fetch(endpoint, { - method: 'POST', - headers: requestHeaders, - body: JSON.stringify({ - query: SCHEMA_INTROSPECTION_QUERY, - variables: {}, - }), - signal: controller.signal, - }); + const response = await fetch(endpoint, fetchOptions); clearTimeout(timeoutId); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cda8350a4..0d6f8f215 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -778,6 +778,9 @@ importers: prettier: specifier: ^3.7.4 version: 3.8.0 + undici: + specifier: ^7.19.0 + version: 7.19.0 devDependencies: '@tanstack/react-query': specifier: ^5.90.19 @@ -8252,6 +8255,10 @@ packages: 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'} + unique-filename@3.0.0: resolution: {integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -16104,6 +16111,8 @@ snapshots: undici@7.16.0: {} + undici@7.19.0: {} + unique-filename@3.0.0: dependencies: unique-slug: 4.0.0 From 467c7955081e4cdc485ff2f214a080976b607665 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 23 Jan 2026 14:45:49 +0000 Subject: [PATCH 17/23] refactor(graphql-codegen): rename --reactquery flag to --react-query Use kebab-case for CLI flag consistency with other flags like --dry-run, --keep-db, etc. --- graphql/codegen/README.md | 8 ++++---- graphql/codegen/package.json | 8 ++++---- graphql/codegen/src/cli/commands/generate-unified.ts | 2 +- graphql/codegen/src/cli/index.ts | 10 +++++----- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/graphql/codegen/README.md b/graphql/codegen/README.md index b307a2e23..b800c1b3c 100644 --- a/graphql/codegen/README.md +++ b/graphql/codegen/README.md @@ -80,19 +80,19 @@ export default defineConfig({ ```bash # Generate React Query hooks from an endpoint -npx graphql-sdk generate --endpoint https://api.example.com/graphql --output ./generated/hooks --reactquery +npx graphql-sdk generate --endpoint https://api.example.com/graphql --output ./generated/hooks --react-query # Generate ORM client from an endpoint npx graphql-sdk generate --endpoint https://api.example.com/graphql --output ./generated/orm --orm # Generate from a database directly -npx graphql-sdk generate --database postgres://localhost/mydb --schemas public,app_public --reactquery +npx graphql-sdk generate --database postgres://localhost/mydb --schemas public,app_public --react-query # Generate from a PGPM module npx graphql-sdk generate --pgpm-module-path ./packages/my-module --schemas public --orm # Generate using apiNames for automatic schema discovery -npx graphql-sdk generate --database postgres://localhost/mydb --api-names my_api --reactquery --orm +npx graphql-sdk generate --database postgres://localhost/mydb --api-names my_api --react-query --orm ``` ### 3. Use the Generated Code @@ -139,7 +139,7 @@ Schema Options (for database/pgpm modes): (mutually exclusive with --schemas) Generator Options: - --reactquery Generate React Query hooks + --react-query Generate React Query hooks --orm Generate ORM client -t, --target Target name in config file -o, --output Output directory diff --git a/graphql/codegen/package.json b/graphql/codegen/package.json index 96faf7e75..992d98741 100644 --- a/graphql/codegen/package.json +++ b/graphql/codegen/package.json @@ -44,10 +44,10 @@ "fmt:check": "prettier --check .", "test": "jest --passWithNoTests", "test:watch": "jest --watch", - "example:codegen:sdk": "tsx src/cli/index.ts generate --config examples/multi-target.config.ts --reactquery", - "example:codegen:orm": "tsx src/cli/index.ts generate --config examples/multi-target.config.ts --orm", - "example:codegen:sdk:schema": "node dist/cli/index.js generate --schema examples/example.schema.graphql --output examples/output/generated-sdk-schema --reactquery", - "example:codegen:orm:schema": "node dist/cli/index.js generate --schema examples/example.schema.graphql --output examples/output/generated-orm-schema --orm", + "example:codegen:sdk": "tsx src/cli/index.ts generate --config examples/multi-target.config.ts --react-query", + "example:codegen:orm": "tsx src/cli/index.ts generate --config examples/multi-target.config.ts --orm", + "example:codegen:sdk:schema": "node dist/cli/index.js generate --schema examples/example.schema.graphql --output examples/output/generated-sdk-schema --react-query", + "example:codegen:orm:schema": "node dist/cli/index.js generate --schema examples/example.schema.graphql --output examples/output/generated-orm-schema --orm", "example:sdk": "tsx examples/react-hooks-sdk-test.tsx", "example:orm": "tsx examples/orm-sdk-test.ts", "example:sdk:typecheck": "tsc --noEmit --jsx react --esModuleInterop --skipLibCheck --moduleResolution node examples/react-hooks-sdk-test.tsx" diff --git a/graphql/codegen/src/cli/commands/generate-unified.ts b/graphql/codegen/src/cli/commands/generate-unified.ts index c7b537fbb..80f894f0d 100644 --- a/graphql/codegen/src/cli/commands/generate-unified.ts +++ b/graphql/codegen/src/cli/commands/generate-unified.ts @@ -124,7 +124,7 @@ export async function generate( output: target.config.output, generatorType: 'react-query', success: false, - message: `Target "${target.name}": No generators enabled. Set reactQuery.enabled or orm.enabled in config, or use --reactquery or --orm flags.`, + message: `Target "${target.name}": No generators enabled. Set reactQuery.enabled or orm.enabled in config, or use --react-query or --orm flags.`, }); continue; } diff --git a/graphql/codegen/src/cli/index.ts b/graphql/codegen/src/cli/index.ts index 0e196f6c3..cc3e51c7b 100644 --- a/graphql/codegen/src/cli/index.ts +++ b/graphql/codegen/src/cli/index.ts @@ -64,7 +64,7 @@ Schema Options (for database/PGPM modes): --api-names Comma-separated list of API names (auto-resolves schemas from services_public.api_schemas) Generator Options: - --reactquery Generate React Query SDK (hooks + fetch functions) + --react-query Generate React Query SDK (hooks + fetch functions) --orm Generate Prisma-like ORM client --target, -t Target name in config file --output, -o Output directory (overrides config) @@ -84,9 +84,9 @@ Watch Mode Options: --help, -h Show this help message Examples: - graphql-codegen generate --endpoint http://localhost:5000/graphql --reactquery + graphql-codegen generate --endpoint http://localhost:5000/graphql --react-query graphql-codegen generate --database mydb --schemas public,app_public --orm - graphql-codegen generate --pgpm-module-path ./my-module --api-names my_api --reactquery --orm + graphql-codegen generate --pgpm-module-path ./my-module --api-names my_api --react-query --orm graphql-codegen generate --config ./graphql-codegen.config.ts `; @@ -171,7 +171,7 @@ async function handleGenerate(argv: Partial): Promise { const apiNames = apiNamesArg ? apiNamesArg.split(',').map((s) => s.trim()) : undefined; // Generator options - const reactQuery = !!argv.reactquery; + const reactQuery = !!argv['react-query']; const orm = !!argv.orm; const output = (argv.output as string) || (argv.o as string); const authorization = (argv.authorization as string) || (argv.a as string); @@ -494,7 +494,7 @@ export const options: Partial = { }, boolean: [ 'help', 'version', 'force', 'verbose', 'dry-run', 'watch', 'json', - 'skip-custom-operations', 'clear', 'reactquery', 'orm', 'keep-db', + 'skip-custom-operations', 'clear', 'react-query', 'orm', 'keep-db', ], string: [ 'config', 'target', 'endpoint', 'schema', 'output', 'authorization', From e86a68de2009122c44c59ace37110030bf4995cf Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 23 Jan 2026 15:02:38 +0000 Subject: [PATCH 18/23] docs(graphql-codegen): rewrite README with programmatic API as primary interface - Move programmatic API documentation to top (after installation) - Move CLI documentation to bottom as secondary interface - Remove legacy/backwards compatibility mentions and exports - Remove deprecation comments from code - Simplify barrel.ts by removing legacy boolean signature support - Clean up client-generator.ts comments - Update single-target.config.ts example comment --- graphql/codegen/README.md | 2073 +++-------------- .../codegen/examples/single-target.config.ts | 3 +- graphql/codegen/src/cli/commands/index.ts | 19 +- graphql/codegen/src/core/codegen/barrel.ts | 8 +- graphql/codegen/src/core/codegen/index.ts | 2 +- .../src/core/codegen/orm/client-generator.ts | 5 +- 6 files changed, 381 insertions(+), 1729 deletions(-) diff --git a/graphql/codegen/README.md b/graphql/codegen/README.md index b800c1b3c..2aee5f701 100644 --- a/graphql/codegen/README.md +++ b/graphql/codegen/README.md @@ -12,7 +12,7 @@

-GraphQL SDK generator for Constructive databases with React Query hooks. Generate type-safe React Query hooks or a Prisma-like ORM client from your GraphQL schema. +GraphQL SDK generator for Constructive databases. Generate type-safe React Query hooks or a Prisma-like ORM client from your GraphQL schema. ## Features @@ -24,29 +24,21 @@ GraphQL SDK generator for Constructive databases with React Query hooks. Generat - **Advanced Type Inference**: Const generics for narrowed return types based on select clauses - **Relation Support**: Typed nested selects for belongsTo, hasMany, and manyToMany relations - **Error Handling**: Discriminated unions with `.unwrap()`, `.unwrapOr()`, `.unwrapOrElse()` methods -- **AST-Based Generation**: Uses `ts-morph` for reliable code generation +- **AST-Based Generation**: Uses Babel for reliable code generation - **Configurable**: Filter tables, queries, and mutations with glob patterns - **Type-Safe**: Full TypeScript support with generated interfaces ## Table of Contents - [Installation](#installation) -- [Quick Start](#quick-start) -- [CLI Commands](#cli-commands) -- [Configuration](#configuration) +- [Programmatic API](#programmatic-api) - [React Query Hooks](#react-query-hooks) - [ORM Client](#orm-client) - - [Basic Usage](#basic-usage) - - [Select & Type Inference](#select--type-inference) - - [Relations](#relations) - - [Filtering & Ordering](#filtering--ordering) - - [Pagination](#pagination) - - [Error Handling](#error-handling) - - [Custom Operations](#custom-operations) +- [Configuration](#configuration) +- [CLI Commands](#cli-commands) - [Architecture](#architecture) - [Generated Types](#generated-types) - [Development](#development) -- [Roadmap](#roadmap) ## Installation @@ -54,233 +46,154 @@ GraphQL SDK generator for Constructive databases with React Query hooks. Generat pnpm add @constructive-io/graphql-codegen ``` -## Quick Start +## Programmatic API -### 1. Initialize Config (Optional) +The primary way to use this package is through the programmatic API. Import the `generate` function and call it with your configuration. -```bash -npx graphql-sdk init -``` - -Creates a `graphql-sdk.config.ts` file: +### Generate from Endpoint ```typescript -import { defineConfig } from '@constructive-io/graphql-codegen'; +import { generate } from '@constructive-io/graphql-codegen'; -export default defineConfig({ +// Generate React Query hooks from a GraphQL endpoint +await generate({ endpoint: 'https://api.example.com/graphql', - output: './generated/graphql', - headers: { - Authorization: 'Bearer ', - }, + output: './generated/hooks', + headers: { Authorization: 'Bearer ' }, + reactQuery: { enabled: true }, }); -``` - -### 2. Generate SDK -```bash -# Generate React Query hooks from an endpoint -npx graphql-sdk generate --endpoint https://api.example.com/graphql --output ./generated/hooks --react-query - -# Generate ORM client from an endpoint -npx graphql-sdk generate --endpoint https://api.example.com/graphql --output ./generated/orm --orm - -# Generate from a database directly -npx graphql-sdk generate --database postgres://localhost/mydb --schemas public,app_public --react-query - -# Generate from a PGPM module -npx graphql-sdk generate --pgpm-module-path ./packages/my-module --schemas public --orm +// Generate ORM client from a GraphQL endpoint +await generate({ + endpoint: 'https://api.example.com/graphql', + output: './generated/orm', + headers: { Authorization: 'Bearer ' }, + orm: { enabled: true }, +}); -# Generate using apiNames for automatic schema discovery -npx graphql-sdk generate --database postgres://localhost/mydb --api-names my_api --react-query --orm +// Generate both React Query hooks and ORM client +await generate({ + endpoint: 'https://api.example.com/graphql', + output: './generated', + reactQuery: { enabled: true }, + orm: { enabled: true, output: './generated/orm' }, +}); ``` -### 3. Use the Generated Code - -```typescript -// ORM Client -import { createClient } from './generated/orm'; +### Generate from Database -const db = createClient({ endpoint: 'https://api.example.com/graphql' }); +Connect directly to a PostgreSQL database to generate code: -const users = await db.user.findMany({ - select: { id: true, username: true }, - first: 10, -}).execute(); +```typescript +import { generate } from '@constructive-io/graphql-codegen'; -// React Query Hooks -import { useCarsQuery } from './generated/hooks'; +// Generate from database with explicit schemas +await generate({ + database: 'postgres://localhost/mydb', + schemas: ['public', 'app_public'], + output: './generated/hooks', + reactQuery: { enabled: true }, +}); -function CarList() { - const { data } = useCarsQuery({ first: 10 }); - return
    {data?.cars.nodes.map(car =>
  • {car.name}
  • )}
; -} +// Generate from database using API names for automatic schema discovery +await generate({ + database: 'postgres://localhost/mydb', + apiNames: ['my_api'], + output: './generated/orm', + orm: { enabled: true }, +}); ``` -## CLI Commands - -### `graphql-sdk generate` - -Generate React Query hooks and/or ORM client from various sources. - -```bash -Source Options (choose one): - -c, --config Path to config file (graphql-sdk.config.ts) - -e, --endpoint GraphQL endpoint URL - -s, --schema Path to GraphQL schema file - --database Database connection URL (postgres://...) - --pgpm-module-path Path to PGPM module directory - --pgpm-workspace-path Path to PGPM workspace (requires --pgpm-module-name) - --pgpm-module-name PGPM module name in workspace - -Schema Options (for database/pgpm modes): - --schemas Comma-separated list of schemas to introspect - --api-names Comma-separated API names for automatic schema discovery - (mutually exclusive with --schemas) - -Generator Options: - --react-query Generate React Query hooks - --orm Generate ORM client - -t, --target Target name in config file - -o, --output Output directory - -a, --authorization Authorization header value - --skip-custom-operations Only generate table CRUD operations - --dry-run Preview without writing files - --keep-db Keep ephemeral database after generation (pgpm modes) - -v, --verbose Show detailed output +### Generate from PGPM Module -Watch Mode Options: - -w, --watch Watch for schema changes and regenerate - --poll-interval Polling interval in milliseconds (default: 5000) - --debounce Debounce delay in milliseconds (default: 500) - --touch Touch file after regeneration - --no-clear Don't clear console on regeneration -``` +Generate code from a PGPM module path: -### `graphql-sdk init` +```typescript +import { generate } from '@constructive-io/graphql-codegen'; -Create a configuration file. +// Generate from a PGPM module directory +await generate({ + pgpmModulePath: './packages/my-module', + schemas: ['public'], + output: './generated/hooks', + reactQuery: { enabled: true }, +}); -```bash -Options: - -f, --format Config format: ts, js, json (default: ts) - -o, --output Output path for config file +// Generate from a PGPM workspace with module name +await generate({ + pgpmWorkspacePath: '/path/to/workspace', + pgpmModuleName: 'my-module', + schemas: ['public'], + output: './generated/orm', + orm: { enabled: true }, +}); ``` -### `graphql-sdk introspect` - -Inspect schema without generating code. - -```bash -Options: - -e, --endpoint GraphQL endpoint URL - --json Output as JSON - -v, --verbose Show detailed output -``` +### Configuration Options -## Configuration +The `generate` function accepts a configuration object with the following options: ```typescript interface GraphQLSDKConfigTarget { - // Required (choose one) - endpoint?: string; - schema?: string; + // Source (choose one) + endpoint?: string; // GraphQL endpoint URL + schema?: string; // Path to GraphQL schema file + database?: string; // Database connection URL + pgpmModulePath?: string; // Path to PGPM module directory + pgpmWorkspacePath?: string; // Path to PGPM workspace + pgpmModuleName?: string; // PGPM module name (with pgpmWorkspacePath) + + // Schema selection (for database/pgpm modes, choose one) + schemas?: string[]; // Explicit schema names + apiNames?: string[]; // API names for automatic schema discovery // Output - output?: string; // default: './generated/graphql' + output?: string; // Output directory (default: './generated/graphql') // Authentication - headers?: Record; + headers?: Record; // HTTP headers for endpoint requests + + // Generator flags + reactQuery?: { + enabled?: boolean; // Generate React Query hooks + }; + orm?: { + enabled?: boolean; // Generate ORM client + output?: string; // ORM output directory + }; // Table filtering (for CRUD operations from _meta) tables?: { - include?: string[]; // default: ['*'] - exclude?: string[]; // default: [] + include?: string[]; // Glob patterns (default: ['*']) + exclude?: string[]; // Glob patterns (default: []) }; // Query filtering (for ALL queries from __schema) queries?: { - include?: string[]; // default: ['*'] - exclude?: string[]; // default: ['_meta', 'query'] + include?: string[]; // Glob patterns (default: ['*']) + exclude?: string[]; // Glob patterns (default: ['_meta', 'query']) }; // Mutation filtering (for ALL mutations from __schema) mutations?: { - include?: string[]; // default: ['*'] - exclude?: string[]; // default: [] + include?: string[]; // Glob patterns (default: ['*']) + exclude?: string[]; // Glob patterns (default: []) }; // Code generation options codegen?: { - maxFieldDepth?: number; // default: 2 - skipQueryField?: boolean; // default: true + maxFieldDepth?: number; // Max depth for nested fields (default: 2) + skipQueryField?: boolean; // Skip 'query' field (default: true) }; - // ORM-specific config - orm?: { - output?: string; // default: './generated/orm' - useSharedTypes?: boolean; // default: true + // Query key generation + queryKeys?: { + generateScopedKeys?: boolean; // Generate scope-aware keys (default: true) + generateMutationKeys?: boolean; // Generate mutation keys (default: true) + generateCascadeHelpers?: boolean; // Generate invalidation helpers (default: true) + relationships?: Record; }; } - -interface GraphQLSDKMultiConfig { - defaults?: GraphQLSDKConfigTarget; - targets: Record; -} - -type GraphQLSDKConfig = GraphQLSDKConfigTarget | GraphQLSDKMultiConfig; -``` - -### Multi-target Configuration - -Configure multiple schema sources and outputs in one file: - -```typescript -export default defineConfig({ - defaults: { - headers: { Authorization: 'Bearer ' }, - }, - targets: { - public: { - endpoint: 'https://api.example.com/graphql', - output: './generated/public', - }, - admin: { - schema: './admin.schema.graphql', - output: './generated/admin', - }, - }, -}); -``` - -CLI behavior: - -- `graphql-codegen generate` runs all targets -- `graphql-codegen generate --target admin` runs a single target -- `--output` requires `--target` when multiple targets exist - -### Glob Patterns - -Filter patterns support wildcards: - -- `*` - matches any string -- `?` - matches single character - -Examples: - -```typescript -{ - tables: { - include: ['User', 'Product', 'Order*'], - exclude: ['*_archive', 'temp_*'], - }, - queries: { - exclude: ['_meta', 'query', '*Debug*'], - }, - mutations: { - include: ['create*', 'update*', 'delete*', 'login', 'register', 'logout'], - }, -} ``` ## React Query Hooks @@ -294,138 +207,74 @@ generated/hooks/ ├── index.ts # Main barrel export (configure, hooks, types) ├── client.ts # configure() and execute() functions ├── types.ts # Entity interfaces, filter types, enums -├── hooks.ts # All hooks re-exported ├── queries/ │ ├── index.ts # Query hooks barrel │ ├── useCarsQuery.ts # Table list query (findMany) │ ├── useCarQuery.ts # Table single item query (findOne) -│ ├── useCurrentUserQuery.ts # Custom query │ └── ... └── mutations/ ├── index.ts # Mutation hooks barrel ├── useCreateCarMutation.ts ├── useUpdateCarMutation.ts ├── useDeleteCarMutation.ts - ├── useLoginMutation.ts # Custom mutation └── ... ``` ### Setup & Configuration -#### 1. Configure the Client - Configure the GraphQL client once at your app's entry point: ```tsx -// App.tsx or main.tsx import { configure } from './generated/hooks'; -// Basic configuration -configure({ - endpoint: 'https://api.example.com/graphql', -}); - -// With authentication configure({ endpoint: 'https://api.example.com/graphql', headers: { Authorization: 'Bearer ', - 'X-Custom-Header': 'value', }, }); ``` -#### 2. Update Headers at Runtime - -```tsx -import { configure } from './generated/hooks'; - -// After login, update the authorization header -function handleLoginSuccess(token: string) { - configure({ - endpoint: 'https://api.example.com/graphql', - headers: { - Authorization: `Bearer ${token}`, - }, - }); -} -``` - ### Table Query Hooks For each table, two query hooks are generated: -#### List Query (`use{Table}sQuery`) - -Fetches multiple records with pagination, filtering, and ordering: - ```tsx -import { useCarsQuery } from './generated/hooks'; +import { useCarsQuery, useCarQuery } from './generated/hooks'; +// List query with filtering, pagination, and ordering function CarList() { - const { data, isLoading, isError, error, refetch, isFetching } = useCarsQuery( - { - // Pagination - first: 10, // First N records - // last: 10, // Last N records - // after: 'cursor', // Cursor-based pagination - // before: 'cursor', - // offset: 20, // Offset pagination - - // Filtering - filter: { - brand: { equalTo: 'Tesla' }, - price: { greaterThan: 50000 }, - }, - - // Ordering - orderBy: ['CREATED_AT_DESC', 'NAME_ASC'], - } - ); + const { data, isLoading, isError, error } = useCarsQuery({ + first: 10, + filter: { + brand: { equalTo: 'Tesla' }, + price: { greaterThan: 50000 }, + }, + orderBy: ['CREATED_AT_DESC'], + }); if (isLoading) return
Loading...
; if (isError) return
Error: {error.message}
; return ( -
-

Total: {data?.cars.totalCount}

-
    - {data?.cars.nodes.map((car) => ( -
  • - {car.brand} - ${car.price} -
  • - ))} -
- - {/* Pagination info */} - {data?.cars.pageInfo.hasNextPage && ( - - )} -
+
    + {data?.cars.nodes.map((car) => ( +
  • {car.brand} - ${car.price}
  • + ))} +
); } -``` - -#### Single Item Query (`use{Table}Query`) - -Fetches a single record by ID: - -```tsx -import { useCarQuery } from './generated/hooks'; +// Single item query by ID function CarDetails({ carId }: { carId: string }) { - const { data, isLoading, isError } = useCarQuery({ - id: carId, - }); + const { data, isLoading } = useCarQuery({ id: carId }); if (isLoading) return
Loading...
; - if (isError) return
Car not found
; return (

{data?.car?.brand}

Price: ${data?.car?.price}

-

Created: {data?.car?.createdAt}

); } @@ -435,840 +284,113 @@ function CarDetails({ carId }: { carId: string }) { For each table, three mutation hooks are generated: -#### Create Mutation (`useCreate{Table}Mutation`) - ```tsx -import { useCreateCarMutation } from './generated/hooks'; +import { + useCreateCarMutation, + useUpdateCarMutation, + useDeleteCarMutation, +} from './generated/hooks'; -function CreateCarForm() { +function CarForm() { const createCar = useCreateCarMutation({ onSuccess: (data) => { console.log('Created car:', data.createCar.car.id); - // Invalidate queries, redirect, show toast, etc. - }, - onError: (error) => { - console.error('Failed to create car:', error); - }, - }); - - const handleSubmit = (formData: { brand: string; price: number }) => { - createCar.mutate({ - input: { - car: { - brand: formData.brand, - price: formData.price, - }, - }, - }); - }; - - return ( -
{ - e.preventDefault(); - handleSubmit({ brand: 'Tesla', price: 80000 }); - }} - > - {/* form fields */} - - {createCar.isError &&

Error: {createCar.error.message}

} -
- ); -} -``` - -#### Update Mutation (`useUpdate{Table}Mutation`) - -```tsx -import { useUpdateCarMutation } from './generated/hooks'; - -function EditCarForm({ - carId, - currentBrand, -}: { - carId: string; - currentBrand: string; -}) { - const updateCar = useUpdateCarMutation({ - onSuccess: (data) => { - console.log('Updated car:', data.updateCar.car.brand); }, }); - const handleUpdate = (newBrand: string) => { - updateCar.mutate({ - input: { - id: carId, - patch: { - brand: newBrand, - }, - }, - }); - }; - return ( ); } ``` -#### Delete Mutation (`useDelete{Table}Mutation`) +### Custom Query and Mutation Hooks + +Custom queries and mutations from your schema get their own hooks: ```tsx -import { useDeleteCarMutation } from './generated/hooks'; +import { useCurrentUserQuery, useLoginMutation } from './generated/hooks'; -function DeleteCarButton({ carId }: { carId: string }) { - const deleteCar = useDeleteCarMutation({ - onSuccess: () => { - console.log('Car deleted'); - // Navigate away, refetch list, etc. +function UserProfile() { + const { data } = useCurrentUserQuery(); + return

Welcome, {data?.currentUser?.username}

; +} + +function LoginForm() { + const login = useLoginMutation({ + onSuccess: (data) => { + const token = data.login.apiToken?.accessToken; + if (token) localStorage.setItem('token', token); }, }); return ( - ); } ``` -### Custom Query Hooks +### Centralized Query Keys -Custom queries from your schema (like `currentUser`, `nodeById`, etc.) get their own hooks: +The codegen generates a centralized query key factory for type-safe cache management: ```tsx -import { useCurrentUserQuery, useNodeByIdQuery } from './generated/hooks'; +import { userKeys, invalidate } from './generated/hooks'; +import { useQueryClient } from '@tanstack/react-query'; -// Simple custom query -function UserProfile() { - const { data, isLoading } = useCurrentUserQuery(); +// Query key structure +userKeys.all; // ['user'] +userKeys.lists(); // ['user', 'list'] +userKeys.list({ first: 10 }); // ['user', 'list', { first: 10 }] +userKeys.details(); // ['user', 'detail'] +userKeys.detail('user-123'); // ['user', 'detail', 'user-123'] - if (isLoading) return
Loading...
; - if (!data?.currentUser) return
Not logged in
; +// Invalidation helpers +const queryClient = useQueryClient(); +invalidate.user.all(queryClient); +invalidate.user.lists(queryClient); +invalidate.user.detail(queryClient, userId); +``` - return ( -
-

Welcome, {data.currentUser.username}

-

Email: {data.currentUser.email}

-
- ); -} +## ORM Client -// Custom query with arguments -function NodeViewer({ nodeId }: { nodeId: string }) { - const { data } = useNodeByIdQuery({ - id: nodeId, - }); +The ORM client provides a Prisma-like fluent API for GraphQL operations without React dependencies. - return
{JSON.stringify(data?.node, null, 2)}
; -} +### Generated Output Structure + +``` +generated/orm/ +├── index.ts # createClient() factory + re-exports +├── client.ts # OrmClient class (GraphQL executor) +├── query-builder.ts # QueryBuilder with execute(), unwrap(), etc. +├── select-types.ts # Type utilities for select inference +├── input-types.ts # All generated types +├── models/ +│ ├── index.ts # Barrel export for all models +│ ├── user.ts # UserModel class +│ └── ... +├── query/ +│ └── index.ts # Custom query operations +└── mutation/ + └── index.ts # Custom mutation operations ``` -### Custom Mutation Hooks - -Custom mutations (like `login`, `register`, `logout`) get dedicated hooks: - -```tsx -import { - useLoginMutation, - useRegisterMutation, - useLogoutMutation, - useForgotPasswordMutation, -} from './generated/hooks'; - -// Login -function LoginForm() { - const login = useLoginMutation({ - onSuccess: (data) => { - const token = data.login.apiToken?.accessToken; - if (token) { - localStorage.setItem('token', token); - // Reconfigure client with new token - configure({ - endpoint: 'https://api.example.com/graphql', - headers: { Authorization: `Bearer ${token}` }, - }); - } - }, - onError: (error) => { - alert('Login failed: ' + error.message); - }, - }); - - const handleLogin = (email: string, password: string) => { - login.mutate({ - input: { email, password }, - }); - }; - - return ( -
{ - e.preventDefault(); - handleLogin('user@example.com', 'password'); - }} - > - {/* email and password inputs */} - -
- ); -} - -// Register -function RegisterForm() { - const register = useRegisterMutation({ - onSuccess: () => { - alert('Registration successful! Please check your email.'); - }, - }); - - const handleRegister = (data: { - email: string; - password: string; - username: string; - }) => { - register.mutate({ - input: { - email: data.email, - password: data.password, - username: data.username, - }, - }); - }; - - return ( - - ); -} - -// Logout -function LogoutButton() { - const logout = useLogoutMutation({ - onSuccess: () => { - localStorage.removeItem('token'); - window.location.href = '/login'; - }, - }); - - return ; -} - -// Forgot Password -function ForgotPasswordForm() { - const forgotPassword = useForgotPasswordMutation({ - onSuccess: () => { - alert('Password reset email sent!'); - }, - }); - - return ( - - ); -} -``` - -### Filtering - -All filter types from your PostGraphile schema are available: - -```tsx -// String filters -useCarsQuery({ - filter: { - brand: { - equalTo: 'Tesla', - notEqualTo: 'Ford', - in: ['Tesla', 'BMW', 'Mercedes'], - notIn: ['Unknown'], - contains: 'es', // LIKE '%es%' - startsWith: 'Tes', // LIKE 'Tes%' - endsWith: 'la', // LIKE '%la' - includesInsensitive: 'TESLA', // Case-insensitive - }, - }, -}); - -// Number filters -useProductsQuery({ - filter: { - price: { - equalTo: 100, - greaterThan: 50, - greaterThanOrEqualTo: 50, - lessThan: 200, - lessThanOrEqualTo: 200, - }, - }, -}); - -// Boolean filters -useUsersQuery({ - filter: { - isActive: { equalTo: true }, - isAdmin: { equalTo: false }, - }, -}); - -// Date/DateTime filters -useOrdersQuery({ - filter: { - createdAt: { - greaterThan: '2024-01-01T00:00:00Z', - lessThan: '2024-12-31T23:59:59Z', - }, - }, -}); - -// Null checks -useUsersQuery({ - filter: { - deletedAt: { isNull: true }, // Only non-deleted - }, -}); - -// Logical operators -useUsersQuery({ - filter: { - // AND (implicit) - isActive: { equalTo: true }, - role: { equalTo: 'ADMIN' }, - }, -}); - -useUsersQuery({ - filter: { - // OR - or: [{ role: { equalTo: 'ADMIN' } }, { role: { equalTo: 'MODERATOR' } }], - }, -}); - -useUsersQuery({ - filter: { - // Complex: active AND (admin OR moderator) - and: [ - { isActive: { equalTo: true } }, - { - or: [ - { role: { equalTo: 'ADMIN' } }, - { role: { equalTo: 'MODERATOR' } }, - ], - }, - ], - }, -}); - -useUsersQuery({ - filter: { - // NOT - not: { status: { equalTo: 'DELETED' } }, - }, -}); -``` - -### Ordering - -```tsx -// Single order -useCarsQuery({ - orderBy: ['CREATED_AT_DESC'], -}); - -// Multiple orders (fallback) -useCarsQuery({ - orderBy: ['BRAND_ASC', 'CREATED_AT_DESC'], -}); - -// Available OrderBy values per table: -// - PRIMARY_KEY_ASC / PRIMARY_KEY_DESC -// - NATURAL -// - {FIELD_NAME}_ASC / {FIELD_NAME}_DESC -``` - -### Pagination - -```tsx -// First N records -useCarsQuery({ first: 10 }); - -// Last N records -useCarsQuery({ last: 10 }); - -// Offset pagination -useCarsQuery({ first: 10, offset: 20 }); // Skip 20, take 10 - -// Cursor-based pagination -function PaginatedList() { - const [cursor, setCursor] = useState(null); - - const { data } = useCarsQuery({ - first: 10, - after: cursor, - }); - - return ( -
- {data?.cars.nodes.map((car) => ( -
{car.brand}
- ))} - - {data?.cars.pageInfo.hasNextPage && ( - - )} -
- ); -} - -// PageInfo structure -// { -// hasNextPage: boolean; -// hasPreviousPage: boolean; -// startCursor: string | null; -// endCursor: string | null; -// } -``` - -### React Query Options - -All hooks accept standard React Query options: - -```tsx -// Query hooks -useCarsQuery( - { first: 10 }, // Variables - { - // React Query options - enabled: isAuthenticated, // Conditional fetching - refetchInterval: 30000, // Poll every 30s - refetchOnWindowFocus: true, // Refetch on tab focus - staleTime: 5 * 60 * 1000, // Consider fresh for 5 min - gcTime: 30 * 60 * 1000, // Keep in cache for 30 min - retry: 3, // Retry failed requests - retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000), - placeholderData: previousData, // Show previous data while loading - select: (data) => data.cars.nodes, // Transform data - } -); - -// Mutation hooks -useCreateCarMutation({ - onSuccess: (data, variables, context) => { - console.log('Created:', data); - queryClient.invalidateQueries({ queryKey: ['cars'] }); - }, - onError: (error, variables, context) => { - console.error('Error:', error); - }, - onSettled: (data, error, variables, context) => { - console.log('Mutation completed'); - }, - onMutate: async (variables) => { - // Optimistic update - await queryClient.cancelQueries({ queryKey: ['cars'] }); - const previousCars = queryClient.getQueryData(['cars']); - queryClient.setQueryData(['cars'], (old) => ({ - ...old, - cars: { - ...old.cars, - nodes: [...old.cars.nodes, { id: 'temp', ...variables.input.car }], - }, - })); - return { previousCars }; - }, -}); -``` - -### Cache Invalidation - -```tsx -import { useQueryClient } from '@tanstack/react-query'; -import { useCreateCarMutation, useCarsQuery } from './generated/hooks'; - -function CreateCarWithInvalidation() { - const queryClient = useQueryClient(); - - const createCar = useCreateCarMutation({ - onSuccess: () => { - // Invalidate all car queries to refetch - queryClient.invalidateQueries({ queryKey: ['cars'] }); - - // Or invalidate specific queries - queryClient.invalidateQueries({ queryKey: ['cars', { first: 10 }] }); - }, - }); - - // ... -} -``` - -### Centralized Query Keys - -The codegen generates a centralized query key factory following the [lukemorales query-key-factory](https://tanstack.com/query/docs/framework/react/community/lukemorales-query-key-factory) pattern. This provides type-safe cache management with autocomplete support. - -#### Generated Files - -| File | Purpose | -| ------------------ | ------------------------------------------------------- | -| `query-keys.ts` | Query key factories for all entities | -| `mutation-keys.ts` | Mutation key factories for tracking in-flight mutations | -| `invalidation.ts` | Type-safe cache invalidation helpers | - -#### Using Query Keys - -```tsx -import { userKeys, invalidate } from './generated/hooks'; -import { useQueryClient } from '@tanstack/react-query'; - -// Query key structure -userKeys.all; // ['user'] -userKeys.lists(); // ['user', 'list'] -userKeys.list({ first: 10 }); // ['user', 'list', { first: 10 }] -userKeys.details(); // ['user', 'detail'] -userKeys.detail('user-123'); // ['user', 'detail', 'user-123'] - -// Granular cache invalidation -const queryClient = useQueryClient(); - -// Invalidate ALL user queries -queryClient.invalidateQueries({ queryKey: userKeys.all }); - -// Invalidate only list queries -queryClient.invalidateQueries({ queryKey: userKeys.lists() }); - -// Invalidate a specific user -queryClient.invalidateQueries({ queryKey: userKeys.detail(userId) }); -``` - -#### Invalidation Helpers - -Type-safe invalidation utilities: - -```tsx -import { invalidate, remove } from './generated/hooks'; - -// Invalidate queries (triggers refetch) -invalidate.user.all(queryClient); -invalidate.user.lists(queryClient); -invalidate.user.detail(queryClient, userId); - -// Remove from cache (for delete operations) -remove.user(queryClient, userId); -``` - -#### Mutation Key Tracking - -Track in-flight mutations with `useIsMutating`: - -```tsx -import { useIsMutating } from '@tanstack/react-query'; -import { userMutationKeys } from './generated/hooks'; - -function UserList() { - // Check if any user mutations are in progress - const isMutating = useIsMutating({ mutationKey: userMutationKeys.all }); - - // Check if a specific user is being deleted - const isDeleting = useIsMutating({ - mutationKey: userMutationKeys.delete(userId), - }); - - return ( -
- {isMutating > 0 && } - -
- ); -} -``` - -#### Optimistic Updates with Query Keys - -```tsx -import { useCreateUserMutation, userKeys } from './generated/hooks'; - -const createUser = useCreateUserMutation({ - onMutate: async (newUser) => { - // Cancel outgoing refetches - await queryClient.cancelQueries({ queryKey: userKeys.lists() }); - - // Snapshot previous value - const previous = queryClient.getQueryData(userKeys.list()); - - // Optimistically update cache - queryClient.setQueryData(userKeys.list(), (old) => ({ - ...old, - users: { - ...old.users, - nodes: [...old.users.nodes, { id: 'temp', ...newUser.input.user }], - }, - })); - - return { previous }; - }, - onError: (err, variables, context) => { - // Rollback on error - queryClient.setQueryData(userKeys.list(), context.previous); - }, - onSettled: () => { - // Refetch after mutation - queryClient.invalidateQueries({ queryKey: userKeys.lists() }); - }, -}); -``` - -#### Configuration - -Query key generation is enabled by default. Configure in your config file: - -```typescript -// graphql-sdk.config.ts -export default defineConfig({ - endpoint: 'https://api.example.com/graphql', - - queryKeys: { - // Generate scope-aware keys (default: true) - generateScopedKeys: true, - - // Generate mutation keys (default: true) - generateMutationKeys: true, - - // Generate invalidation helpers (default: true) - generateCascadeHelpers: true, - - // Define entity relationships for cascade invalidation - relationships: { - table: { parent: 'database', foreignKey: 'databaseId' }, - field: { parent: 'table', foreignKey: 'tableId' }, - }, - }, -}); -``` - -For detailed documentation on query key factory design and implementation, see [docs/QUERY-KEY-FACTORY.md](./docs/QUERY-KEY-FACTORY.md). - -### Prefetching - -```tsx -import { useQueryClient } from '@tanstack/react-query'; - -function CarListItem({ car }: { car: Car }) { - const queryClient = useQueryClient(); - - // Prefetch details on hover - const handleHover = () => { - queryClient.prefetchQuery({ - queryKey: ['car', { id: car.id }], - queryFn: () => execute(carQuery, { id: car.id }), - }); - }; - - return ( - - {car.brand} - - ); -} -``` - -### Type Exports - -All generated types are exported for use in your application: - -```tsx -import type { - // Entity types - Car, - User, - Product, - Order, - - // Filter types - CarFilter, - UserFilter, - StringFilter, - IntFilter, - UUIDFilter, - DatetimeFilter, - - // OrderBy types - CarsOrderBy, - UsersOrderBy, - - // Input types - CreateCarInput, - UpdateCarInput, - CarPatch, - LoginInput, - - // Payload types - LoginPayload, - CreateCarPayload, -} from './generated/hooks'; - -// Use in your components -interface CarListProps { - filter?: CarFilter; - orderBy?: CarsOrderBy[]; -} - -function CarList({ filter, orderBy }: CarListProps) { - const { data } = useCarsQuery({ filter, orderBy, first: 10 }); - // ... -} -``` - -### Error Handling - -```tsx -function CarList() { - const { data, isLoading, isError, error, failureCount } = useCarsQuery({ - first: 10, - }); - - if (isLoading) { - return
Loading...
; - } - - if (isError) { - // error is typed as Error - return ( -
-

Error: {error.message}

-

Failed {failureCount} times

- -
- ); - } - - return
{/* render data */}
; -} - -// Global error handling -const queryClient = new QueryClient({ - defaultOptions: { - queries: { - onError: (error) => { - console.error('Query error:', error); - // Show toast, log to monitoring, etc. - }, - }, - mutations: { - onError: (error) => { - console.error('Mutation error:', error); - }, - }, - }, -}); -``` - -### Generated Types Reference - -```typescript -// Query hook return type -type UseQueryResult = { - data: TData | undefined; - error: Error | null; - isLoading: boolean; - isFetching: boolean; - isError: boolean; - isSuccess: boolean; - refetch: () => Promise>; - // ... more React Query properties -}; - -// Mutation hook return type -type UseMutationResult = { - data: TData | undefined; - error: Error | null; - isLoading: boolean; // deprecated, use isPending - isPending: boolean; - isError: boolean; - isSuccess: boolean; - mutate: (variables: TVariables) => void; - mutateAsync: (variables: TVariables) => Promise; - reset: () => void; - // ... more React Query properties -}; - -// Connection result (for list queries) -interface CarsConnection { - nodes: Car[]; - totalCount: number; - pageInfo: PageInfo; -} - -interface PageInfo { - hasNextPage: boolean; - hasPreviousPage: boolean; - startCursor: string | null; - endCursor: string | null; -} -``` - ---- - -## ORM Client - -The ORM client provides a Prisma-like fluent API for GraphQL operations without React dependencies. - -### Generated Output Structure - -``` -generated/orm/ -├── index.ts # createClient() factory + re-exports -├── client.ts # OrmClient class (GraphQL executor) -├── query-builder.ts # QueryBuilder with execute(), unwrap(), etc. -├── select-types.ts # Type utilities for select inference -├── input-types.ts # All generated types (entities, filters, inputs, etc.) -├── types.ts # Re-exports from input-types -├── models/ -│ ├── index.ts # Barrel export for all models -│ ├── user.ts # UserModel class -│ ├── product.ts # ProductModel class -│ ├── order.ts # OrderModel class -│ └── ... -├── query/ -│ └── index.ts # Custom query operations (currentUser, etc.) -└── mutation/ - └── index.ts # Custom mutation operations (login, register, etc.) -``` - -### Basic Usage +### Basic Usage ```typescript import { createClient } from './generated/orm'; -// Create client instance const db = createClient({ endpoint: 'https://api.example.com/graphql', headers: { Authorization: 'Bearer ' }, @@ -1288,619 +410,287 @@ if (result.ok) { console.error(result.errors); } -// Find first matching user -const user = await db.user - .findFirst({ - select: { id: true, username: true }, - where: { username: { equalTo: 'john' } }, - }) - .execute(); - // Create a user const newUser = await db.user .create({ data: { username: 'john', email: 'john@example.com' }, select: { id: true, username: true }, }) - .execute(); - -// Update a user -const updated = await db.user - .update({ - where: { id: 'user-id' }, - data: { displayName: 'John Doe' }, - select: { id: true, displayName: true }, - }) - .execute(); - -// Delete a user -const deleted = await db.user - .delete({ - where: { id: 'user-id' }, - }) - .execute(); -``` - -### Select & Type Inference - -The ORM uses **const generics** to infer return types based on your select clause. Only the fields you select will be in the return type. - -```typescript -// Select specific fields - return type is narrowed -const users = await db.user - .findMany({ - select: { id: true, username: true }, // Only id and username - }) - .unwrap(); - -// TypeScript knows the exact shape: -// users.users.nodes[0] is { id: string; username: string | null } - -// If you try to access a field you didn't select, TypeScript will error: -// users.users.nodes[0].email // Error: Property 'email' does not exist - -// Without select, you get the full entity type -const allFields = await db.user.findMany({}).unwrap(); -// allFields.users.nodes[0] has all User fields -``` - -### Relations - -Relations are fully typed in Select types. The ORM supports all PostGraphile relation types: - -#### BelongsTo Relations (Single Entity) - -```typescript -// Order.customer is a belongsTo relation to User -const orders = await db.order - .findMany({ - select: { - id: true, - orderNumber: true, - // Nested select for belongsTo relation - customer: { - select: { id: true, username: true, displayName: true }, - }, - }, - }) - .unwrap(); - -// TypeScript knows: -// orders.orders.nodes[0].customer is { id: string; username: string | null; displayName: string | null } -``` - -#### HasMany Relations (Connection/Collection) - -```typescript -// Order.orderItems is a hasMany relation to OrderItem -const orders = await db.order - .findMany({ - select: { - id: true, - // HasMany with pagination and filtering - orderItems: { - select: { id: true, quantity: true, price: true }, - first: 10, // Pagination - filter: { quantity: { greaterThan: 0 } }, // Filtering - orderBy: ['QUANTITY_DESC'], // Ordering - }, - }, - }) - .unwrap(); - -// orders.orders.nodes[0].orderItems is a connection: -// { nodes: Array<{ id: string; quantity: number | null; price: number | null }>, totalCount: number, pageInfo: PageInfo } -``` - -#### ManyToMany Relations - -```typescript -// Order.productsByOrderItemOrderIdAndProductId is a manyToMany through OrderItem -const orders = await db.order - .findMany({ - select: { - id: true, - productsByOrderItemOrderIdAndProductId: { - select: { id: true, name: true, price: true }, - first: 5, - }, - }, - }) - .unwrap(); -``` - -#### Deeply Nested Relations - -```typescript -// Multiple levels of nesting -const products = await db.product - .findMany({ - select: { - id: true, - name: true, - // BelongsTo: Product -> User (seller) - seller: { - select: { - id: true, - username: true, - // Even deeper nesting if needed - }, - }, - // BelongsTo: Product -> Category - category: { - select: { id: true, name: true }, - }, - // HasMany: Product -> Review - reviews: { - select: { - id: true, - rating: true, - comment: true, - }, - first: 5, - orderBy: ['CREATED_AT_DESC'], - }, - }, - }) - .unwrap(); -``` - -### Filtering & Ordering - -#### Filter Types - -Each entity has a generated Filter type with field-specific operators: - -```typescript -// String filters -where: { - username: { - equalTo: 'john', - notEqualTo: 'jane', - in: ['john', 'jane', 'bob'], - notIn: ['admin'], - contains: 'oh', // LIKE '%oh%' - startsWith: 'j', // LIKE 'j%' - endsWith: 'n', // LIKE '%n' - includesInsensitive: 'OH', // Case-insensitive - } -} - -// Number filters (Int, Float, BigInt, BigFloat) -where: { - price: { - equalTo: 100, - greaterThan: 50, - greaterThanOrEqualTo: 50, - lessThan: 200, - lessThanOrEqualTo: 200, - in: [100, 200, 300], - } -} - -// Boolean filters -where: { - isActive: { equalTo: true } -} - -// UUID filters -where: { - id: { - equalTo: 'uuid-string', - in: ['uuid-1', 'uuid-2'], - } -} - -// DateTime filters -where: { - createdAt: { - greaterThan: '2024-01-01T00:00:00Z', - lessThan: '2024-12-31T23:59:59Z', - } -} - -// JSON filters -where: { - metadata: { - contains: { key: 'value' }, - containsKey: 'key', - containsAllKeys: ['key1', 'key2'], - } -} - -// Null checks (all filters) -where: { - deletedAt: { isNull: true } -} -``` - -#### Logical Operators - -```typescript -// AND (implicit - all conditions must match) -where: { - isActive: { equalTo: true }, - username: { startsWith: 'j' } -} - -// AND (explicit) -where: { - and: [ - { isActive: { equalTo: true } }, - { username: { startsWith: 'j' } } - ] -} - -// OR -where: { - or: [ - { status: { equalTo: 'ACTIVE' } }, - { status: { equalTo: 'PENDING' } } - ] -} - -// NOT -where: { - not: { status: { equalTo: 'DELETED' } } -} - -// Complex combinations -where: { - and: [ - { isActive: { equalTo: true } }, - { - or: [ - { role: { equalTo: 'ADMIN' } }, - { role: { equalTo: 'MODERATOR' } } - ] - } - ] -} -``` - -#### Ordering + .execute(); -```typescript -const users = await db.user - .findMany({ - select: { id: true, username: true, createdAt: true }, - orderBy: [ - 'CREATED_AT_DESC', // Newest first - 'USERNAME_ASC', // Then alphabetical - ], +// Update a user +const updated = await db.user + .update({ + where: { id: 'user-id' }, + data: { displayName: 'John Doe' }, + select: { id: true, displayName: true }, }) - .unwrap(); + .execute(); -// Available OrderBy values (generated per entity): -// - PRIMARY_KEY_ASC / PRIMARY_KEY_DESC -// - NATURAL -// - {FIELD_NAME}_ASC / {FIELD_NAME}_DESC +// Delete a user +const deleted = await db.user + .delete({ where: { id: 'user-id' } }) + .execute(); ``` -### Pagination +### Select & Type Inference -The ORM supports cursor-based and offset pagination: +The ORM uses const generics to infer return types based on your select clause: ```typescript -// First N records -const first10 = await db.user +const users = await db.user .findMany({ - select: { id: true }, - first: 10, + select: { id: true, username: true }, }) .unwrap(); -// Last N records -const last10 = await db.user - .findMany({ - select: { id: true }, - last: 10, - }) - .unwrap(); +// TypeScript knows the exact shape: +// users.users.nodes[0] is { id: string; username: string | null } -// Cursor-based pagination (after/before) -const page1 = await db.user - .findMany({ - select: { id: true }, - first: 10, - }) - .unwrap(); +// Accessing unselected fields is a compile error: +// users.users.nodes[0].email // Error: Property 'email' does not exist +``` + +### Relations -const endCursor = page1.users.pageInfo.endCursor; +Relations are fully typed in Select types: -const page2 = await db.user +```typescript +// BelongsTo relation +const orders = await db.order .findMany({ - select: { id: true }, - first: 10, - after: endCursor, // Get records after this cursor + select: { + id: true, + customer: { + select: { id: true, username: true }, + }, + }, }) .unwrap(); -// Offset pagination -const page3 = await db.user +// HasMany relation with pagination +const users = await db.user .findMany({ - select: { id: true }, - first: 10, - offset: 20, // Skip first 20 records + select: { + id: true, + orders: { + select: { id: true, total: true }, + first: 10, + orderBy: ['CREATED_AT_DESC'], + }, + }, }) .unwrap(); - -// PageInfo structure -// { -// hasNextPage: boolean; -// hasPreviousPage: boolean; -// startCursor: string | null; -// endCursor: string | null; -// } - -// Total count is always included -console.log(page1.users.totalCount); // Total matching records ``` ### Error Handling The ORM provides multiple ways to handle errors: -#### Discriminated Union (Recommended) - ```typescript -const result = await db.user - .findMany({ - select: { id: true }, - }) - .execute(); +// Discriminated union (recommended) +const result = await db.user.findMany({ select: { id: true } }).execute(); if (result.ok) { - // TypeScript knows result.data is non-null console.log(result.data.users.nodes); - // result.errors is undefined in this branch } else { - // TypeScript knows result.errors is non-null - console.error(result.errors[0].message); - // result.data is null in this branch + console.error(result.errors); } -``` - -#### `.unwrap()` - Throw on Error - -```typescript -import { GraphQLRequestError } from './generated/orm'; +// .unwrap() - throws on error try { - // Throws GraphQLRequestError if query fails - const data = await db.user - .findMany({ - select: { id: true }, - }) - .unwrap(); - - console.log(data.users.nodes); + const data = await db.user.findMany({ select: { id: true } }).unwrap(); } catch (error) { if (error instanceof GraphQLRequestError) { console.error('GraphQL errors:', error.errors); - console.error('Message:', error.message); } } -``` -#### `.unwrapOr()` - Default Value on Error - -```typescript -// Returns default value if query fails (no throwing) +// .unwrapOr() - returns default on error const data = await db.user - .findMany({ - select: { id: true }, - }) - .unwrapOr({ - users: { - nodes: [], - totalCount: 0, - pageInfo: { hasNextPage: false, hasPreviousPage: false }, - }, - }); - -// Always returns data (either real or default) -console.log(data.users.nodes); -``` + .findMany({ select: { id: true } }) + .unwrapOr({ users: { nodes: [], totalCount: 0, pageInfo: { hasNextPage: false, hasPreviousPage: false } } }); -#### `.unwrapOrElse()` - Callback on Error - -```typescript -// Call a function to handle errors and return fallback +// .unwrapOrElse() - callback on error const data = await db.user - .findMany({ - select: { id: true }, - }) + .findMany({ select: { id: true } }) .unwrapOrElse((errors) => { - // Log errors, send to monitoring, etc. - console.error('Query failed:', errors.map((e) => e.message).join(', ')); - - // Return fallback data - return { - users: { - nodes: [], - totalCount: 0, - pageInfo: { hasNextPage: false, hasPreviousPage: false }, - }, - }; + console.error('Query failed:', errors); + return { users: { nodes: [], totalCount: 0, pageInfo: { hasNextPage: false, hasPreviousPage: false } } }; }); ``` -#### Error Types +### Custom Operations + +Custom queries and mutations are available on `db.query` and `db.mutation`: ```typescript -interface GraphQLError { - message: string; - locations?: { line: number; column: number }[]; - path?: (string | number)[]; - extensions?: Record; -} +// Custom query +const currentUser = await db.query + .currentUser({ select: { id: true, username: true } }) + .unwrap(); -class GraphQLRequestError extends Error { - readonly errors: GraphQLError[]; - readonly data: unknown; // Partial data if available -} +// Custom mutation +const login = await db.mutation + .login( + { input: { email: 'user@example.com', password: 'secret' } }, + { select: { apiToken: { select: { accessToken: true } } } } + ) + .unwrap(); -type QueryResult = - | { ok: true; data: T; errors: undefined } - | { ok: false; data: null; errors: GraphQLError[] }; +console.log(login.login.apiToken?.accessToken); ``` -### Custom Operations +## Configuration -Custom queries and mutations (like `login`, `currentUser`, etc.) are available on `db.query` and `db.mutation`: +### Config File -#### Custom Queries +Create a `graphql-sdk.config.ts` file: ```typescript -// Query with select -const currentUser = await db.query - .currentUser({ - select: { id: true, username: true, email: true }, - }) - .unwrap(); - -// Query without select (returns full type) -const me = await db.query.currentUser({}).unwrap(); +import { defineConfig } from '@constructive-io/graphql-codegen'; -// Query with arguments -const node = await db.query - .nodeById( - { - id: 'some-node-id', - }, - { - select: { id: true }, - } - ) - .unwrap(); +export default defineConfig({ + endpoint: 'https://api.example.com/graphql', + output: './generated/graphql', + headers: { + Authorization: 'Bearer ', + }, + reactQuery: { enabled: true }, + orm: { enabled: true, output: './generated/orm' }, +}); ``` -#### Custom Mutations +### Multi-target Configuration + +Configure multiple schema sources and outputs: ```typescript -// Login mutation with typed select -const login = await db.mutation - .login( - { - input: { - email: 'user@example.com', - password: 'secret123', - }, +export default defineConfig({ + defaults: { + headers: { Authorization: 'Bearer ' }, + }, + targets: { + public: { + endpoint: 'https://api.example.com/graphql', + output: './generated/public', + reactQuery: { enabled: true }, }, - { - select: { - clientMutationId: true, - apiToken: { - select: { - accessToken: true, - accessTokenExpiresAt: true, - }, - }, - }, - } - ) - .unwrap(); + admin: { + schema: './admin.schema.graphql', + output: './generated/admin', + orm: { enabled: true }, + }, + }, +}); +``` -console.log(login.login.apiToken?.accessToken); +### Glob Patterns -// Register mutation -const register = await db.mutation - .register({ - input: { - email: 'new@example.com', - password: 'secret123', - username: 'newuser', - }, - }) - .unwrap(); +Filter patterns support wildcards: -// Logout mutation -await db.mutation - .logout({ - input: { clientMutationId: 'optional-id' }, - }) - .execute(); +```typescript +{ + tables: { + include: ['User', 'Product', 'Order*'], + exclude: ['*_archive', 'temp_*'], + }, + queries: { + exclude: ['_meta', 'query', '*Debug*'], + }, + mutations: { + include: ['create*', 'update*', 'delete*', 'login', 'register', 'logout'], + }, +} ``` -### Query Builder API +## CLI Commands -Every operation returns a `QueryBuilder` that can be inspected before execution: +The CLI provides a convenient way to run code generation from the command line. -```typescript -const query = db.user.findMany({ - select: { id: true, username: true }, - where: { isActive: { equalTo: true } }, - first: 10, -}); +### `graphql-sdk generate` + +Generate React Query hooks and/or ORM client from various sources. + +```bash +Source Options (choose one): + -c, --config Path to config file (graphql-sdk.config.ts) + -e, --endpoint GraphQL endpoint URL + -s, --schema Path to GraphQL schema file + --database Database connection URL (postgres://...) + --pgpm-module-path Path to PGPM module directory + --pgpm-workspace-path Path to PGPM workspace (requires --pgpm-module-name) + --pgpm-module-name PGPM module name in workspace + +Schema Options (for database/pgpm modes): + --schemas Comma-separated list of schemas to introspect + --api-names Comma-separated API names for automatic schema discovery + (mutually exclusive with --schemas) + +Generator Options: + --react-query Generate React Query hooks + --orm Generate ORM client + -t, --target Target name in config file + -o, --output Output directory + -a, --authorization Authorization header value + --skip-custom-operations Only generate table CRUD operations + --dry-run Preview without writing files + --keep-db Keep ephemeral database after generation (pgpm modes) + -v, --verbose Show detailed output -// Inspect the generated GraphQL -console.log(query.toGraphQL()); -// query UserQuery($where: UserFilter, $first: Int) { -// users(filter: $where, first: $first) { -// nodes { id username } -// totalCount -// pageInfo { hasNextPage hasPreviousPage startCursor endCursor } -// } -// } - -// Get variables -console.log(query.getVariables()); -// { where: { isActive: { equalTo: true } }, first: 10 } - -// Execute when ready -const result = await query.execute(); -// Or: const data = await query.unwrap(); +Watch Mode Options: + -w, --watch Watch for schema changes and regenerate + --poll-interval Polling interval in milliseconds (default: 5000) + --debounce Debounce delay in milliseconds (default: 500) + --touch Touch file after regeneration + --no-clear Don't clear console on regeneration ``` -### Client Configuration +Examples: -```typescript -import { createClient } from './generated/orm'; +```bash +# Generate React Query hooks from an endpoint +npx graphql-sdk generate --endpoint https://api.example.com/graphql --output ./generated/hooks --react-query -// Basic configuration -const db = createClient({ - endpoint: 'https://api.example.com/graphql', -}); +# Generate ORM client from an endpoint +npx graphql-sdk generate --endpoint https://api.example.com/graphql --output ./generated/orm --orm -// With authentication -const db = createClient({ - endpoint: 'https://api.example.com/graphql', - headers: { - Authorization: 'Bearer ', - 'X-Custom-Header': 'value', - }, -}); +# Generate from a database directly +npx graphql-sdk generate --database postgres://localhost/mydb --schemas public,app_public --react-query -// Update headers at runtime -db.setHeaders({ - Authorization: 'Bearer ', -}); +# Generate from a PGPM module +npx graphql-sdk generate --pgpm-module-path ./packages/my-module --schemas public --orm -// Get current endpoint -console.log(db.getEndpoint()); +# Generate using apiNames for automatic schema discovery +npx graphql-sdk generate --database postgres://localhost/mydb --api-names my_api --react-query --orm ``` ---- +### `graphql-sdk init` -## Architecture +Create a configuration file. -### How It Works +```bash +Options: + -f, --format Config format: ts, js, json (default: ts) + -o, --output Output path for config file +``` + +### `graphql-sdk introspect` + +Inspect schema without generating code. -1. **Fetch `_meta`**: Gets table metadata from PostGraphile's `_meta` query including: - - Table names and fields - - Relations (belongsTo, hasMany, manyToMany) - - Constraints (primary key, foreign key, unique) - - Inflection rules (query names, type names) +```bash +Options: + -e, --endpoint GraphQL endpoint URL + --json Output as JSON + -v, --verbose Show detailed output +``` -2. **Fetch `__schema`**: Gets full schema introspection for ALL operations: - - All queries (including custom ones like `currentUser`) - - All mutations (including custom ones like `login`, `register`) - - All types (entities, inputs, enums, scalars) +## Architecture -3. **Filter Operations**: Removes table CRUD from custom operations to avoid duplicates +### How It Works -4. **Generate Code**: Creates type-safe code using AST-based generation (`ts-morph`) +The codegen fetches `_meta` for table metadata (names, fields, relations, constraints) and `__schema` for full schema introspection (all queries, mutations, types). It then filters operations to avoid duplicates and generates type-safe code using Babel AST. ### Code Generation Pipeline @@ -1939,68 +729,16 @@ PostGraphile Endpoint └───────────────────┘ ``` -### Key Concepts - -#### Type Inference with Const Generics +### Type Inference with Const Generics The ORM uses TypeScript const generics to infer return types: ```typescript -// Model method signature findMany( args?: FindManyArgs ): QueryBuilder<{ users: ConnectionResult> }> - -// InferSelectResult maps select object to result type -type InferSelectResult = { - [K in keyof TSelect & keyof TEntity as TSelect[K] extends false | undefined - ? never - : K]: TSelect[K] extends true - ? TEntity[K] - : TSelect[K] extends { select: infer NestedSelect } - ? /* handle nested select */ - : TEntity[K]; -}; -``` - -#### Select Types with Relations - -Select types include relation fields with proper typing: - -```typescript -export type OrderSelect = { - // Scalar fields - id?: boolean; - orderNumber?: boolean; - status?: boolean; - - // BelongsTo relation - customer?: boolean | { select?: UserSelect }; - - // HasMany relation - orderItems?: - | boolean - | { - select?: OrderItemSelect; - first?: number; - filter?: OrderItemFilter; - orderBy?: OrderItemsOrderBy[]; - }; - - // ManyToMany relation - productsByOrderItemOrderIdAndProductId?: - | boolean - | { - select?: ProductSelect; - first?: number; - filter?: ProductFilter; - orderBy?: ProductsOrderBy[]; - }; -}; ``` ---- - ## Generated Types ### Entity Types @@ -2039,7 +777,6 @@ export interface StringFilter { contains?: string; startsWith?: string; endsWith?: string; - // ... more operators } ``` @@ -2075,35 +812,8 @@ export interface UpdateUserInput { id: string; patch: UserPatch; } - -export interface UserPatch { - username?: string | null; - email?: string | null; - displayName?: string | null; -} -``` - -### Payload Types (Custom Operations) - -```typescript -export interface LoginPayload { - clientMutationId?: string | null; - apiToken?: ApiToken | null; -} - -export interface ApiToken { - accessToken: string; - accessTokenExpiresAt?: string | null; -} - -export type LoginPayloadSelect = { - clientMutationId?: boolean; - apiToken?: boolean | { select?: ApiTokenSelect }; -}; ``` ---- - ## Development ```bash @@ -2116,27 +826,6 @@ pnpm build # Run in watch mode pnpm dev -# Test React Query hooks generation -node bin/graphql-sdk.js generate \ - -e http://public-0e394519.localhost:3000/graphql \ - -o ./output-rq \ - --verbose - -# Test ORM client generation -node bin/graphql-sdk.js generate-orm \ - -e http://public-0e394519.localhost:3000/graphql \ - -o ./output-orm \ - --verbose - -# Type check generated output -npx tsc --noEmit output-orm/*.ts output-orm/**/*.ts \ - --skipLibCheck --target ES2022 --module ESNext \ - --moduleResolution bundler --strict - -# Run example tests -npx tsx examples/test-orm.ts -npx tsx examples/type-inference-test.ts - # Type check pnpm lint:types @@ -2144,22 +833,6 @@ pnpm lint:types pnpm test ``` ---- - -## Roadmap - -- [x] **Relations**: Typed nested select with relation loading -- [x] **Type Inference**: Const generics for narrowed return types -- [x] **Error Handling**: Discriminated unions with unwrap methods -- [ ] **Aggregations**: Count, sum, avg operations -- [ ] **Batch Operations**: Bulk create/update/delete -- [ ] **Transactions**: Transaction support where available -- [ ] **Subscriptions**: Real-time subscription support -- [ ] **Custom Scalars**: Better handling of PostGraphile custom types -- [ ] **Query Caching**: Optional caching layer for ORM client -- [ ] **Middleware**: Request/response interceptors -- [ ] **Connection Pooling**: For high-throughput scenarios - ## Requirements - Node.js >= 18 diff --git a/graphql/codegen/examples/single-target.config.ts b/graphql/codegen/examples/single-target.config.ts index 9e7b858b3..063acb6f2 100644 --- a/graphql/codegen/examples/single-target.config.ts +++ b/graphql/codegen/examples/single-target.config.ts @@ -1,8 +1,7 @@ import { defineConfig } from '../src/types/config'; /** - * Single-target config (backward compatible format) - * Tests that the old config format without "targets" key still works. + * Single-target config */ export default defineConfig({ endpoint: 'http://api.localhost:3000/graphql', diff --git a/graphql/codegen/src/cli/commands/index.ts b/graphql/codegen/src/cli/commands/index.ts index 5b3afa9a4..770b650f2 100644 --- a/graphql/codegen/src/cli/commands/index.ts +++ b/graphql/codegen/src/cli/commands/index.ts @@ -1,24 +1,9 @@ /** * CLI commands exports - * - * Public API: - * - generate() - Unified generate function that respects config.reactQuery.enabled and config.orm.enabled - * - findConfigFile() - Find config file in directory - * - loadConfigFile() - Load and parse config file - * - * Internal (not exported from package): - * - generateReactQuery() - Convenience wrapper for generate({ reactQuery: true, orm: false }) - * - generateOrm() - Convenience wrapper for generate({ reactQuery: false, orm: true }) */ export { initCommand, findConfigFile, loadConfigFile } from './init'; export type { InitOptions, InitResult } from './init'; -// Unified generate function (public API) -export { generate } from './generate-unified'; -export type { GenerateOptions, GenerateResult, GenerateTargetResult, GeneratorType } from './generate-unified'; - -// Legacy exports (deprecated - use unified generate instead) -export { generateReactQuery as generateReactQueryLegacy } from './generate'; -export { generateOrm as generateOrmLegacy } from './generate-orm'; -export type { GenerateOrmOptions, GenerateOrmResult, GenerateOrmTargetResult } from './generate-orm'; +export { generate, generateReactQuery, generateOrm } from './generate-unified'; +export type { GenerateOptions, GenerateResult, GenerateTargetResult } from './generate-unified'; diff --git a/graphql/codegen/src/core/codegen/barrel.ts b/graphql/codegen/src/core/codegen/barrel.ts index 90a722b1a..fce2a9e3e 100644 --- a/graphql/codegen/src/core/codegen/barrel.ts +++ b/graphql/codegen/src/core/codegen/barrel.ts @@ -107,13 +107,9 @@ export interface MainBarrelOptions { export function generateMainBarrel( tables: CleanTable[], - options: MainBarrelOptions | boolean = {} + options: MainBarrelOptions = {} ): string { - // Support legacy signature where second arg was just hasSchemaTypes boolean - const opts: MainBarrelOptions = - typeof options === 'boolean' - ? { hasSchemaTypes: options, hasMutations: true } - : options; + const opts: MainBarrelOptions = options; const { hasSchemaTypes = false, diff --git a/graphql/codegen/src/core/codegen/index.ts b/graphql/codegen/src/core/codegen/index.ts index e5b7b5aa1..1e7a6e79f 100644 --- a/graphql/codegen/src/core/codegen/index.ts +++ b/graphql/codegen/src/core/codegen/index.ts @@ -98,7 +98,7 @@ export interface GenerateOptions { // ============================================================================ /** - * Generate all SDK files for tables only (legacy function signature) + * Generate all SDK files for tables only */ export function generateAllFiles( tables: CleanTable[], diff --git a/graphql/codegen/src/core/codegen/orm/client-generator.ts b/graphql/codegen/src/core/codegen/orm/client-generator.ts index ed50c6b72..7b658cb4a 100644 --- a/graphql/codegen/src/core/codegen/orm/client-generator.ts +++ b/graphql/codegen/src/core/codegen/orm/client-generator.ts @@ -460,11 +460,10 @@ export function generateCreateClientFile( // export * from './select-types'; statements.push(t.exportAllDeclaration(t.stringLiteral('./select-types'))); - // Re-export all models for backwards compatibility - // export * from './models'; + // Re-export all models statements.push(t.exportAllDeclaration(t.stringLiteral('./models'))); - // Re-export custom operations for backwards compatibility + // Re-export custom operations if (hasCustomQueries) { statements.push( t.exportNamedDeclaration( From 5b8ad1ab8b7a84ebd5ef49ed36a54c92ad101330 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 23 Jan 2026 15:13:52 +0000 Subject: [PATCH 19/23] fix(graphql-codegen): remove non-existent type exports from index.ts Remove GeneratorType, GenerateOrmOptions, GenerateOrmResult, and GenerateOrmTargetResult exports that were removed during legacy cleanup --- graphql/codegen/src/index.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/graphql/codegen/src/index.ts b/graphql/codegen/src/index.ts index 83f7bc309..5fbcccad5 100644 --- a/graphql/codegen/src/index.ts +++ b/graphql/codegen/src/index.ts @@ -43,10 +43,6 @@ export type { GenerateOptions, GenerateResult, GenerateTargetResult, - GeneratorType, - GenerateOrmOptions, - GenerateOrmResult, - GenerateOrmTargetResult, InitOptions, InitResult, } from './cli/commands'; From 65d2ff934af1fac0f32ac0735aeeaf6b5c3988f0 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 23 Jan 2026 16:21:57 +0000 Subject: [PATCH 20/23] refactor(graphql-codegen): restructure database/PGPM config with nested db object - Rename 'schema' to 'schemaFile' throughout codebase - Consolidate pgpmModulePath, pgpmWorkspacePath, pgpmModuleName into db.pgpm object - Move schemas, apiNames, keepDb into db object - Add db.config?: Partial with fallback to environment variables - Update CLI to use --schema-file flag and new db structure - Update all generate commands, introspection sources, and config resolver - Update README with new config structure examples - Update tests for new config structure --- graphql/codegen/README.md | 158 +++++++++++------ .../__tests__/config/resolve-config.test.ts | 6 +- .../codegen/src/cli/commands/generate-orm.ts | 46 ++--- .../src/cli/commands/generate-unified.ts | 106 +++++------ graphql/codegen/src/cli/commands/generate.ts | 43 ++--- graphql/codegen/src/cli/index.ts | 70 ++++---- graphql/codegen/src/core/codegen/index.ts | 2 +- graphql/codegen/src/core/codegen/orm/index.ts | 5 +- graphql/codegen/src/core/config/resolver.ts | 43 ++--- .../src/core/introspect/source/index.ts | 153 +++++++--------- .../codegen/src/core/watch/orchestrator.ts | 6 +- graphql/codegen/src/types/config.ts | 165 ++++++++++-------- packages/cli/__tests__/codegen.test.ts | 14 +- packages/cli/src/commands/codegen.ts | 6 +- 14 files changed, 420 insertions(+), 403 deletions(-) diff --git a/graphql/codegen/README.md b/graphql/codegen/README.md index 2aee5f701..349f36c41 100644 --- a/graphql/codegen/README.md +++ b/graphql/codegen/README.md @@ -58,25 +58,25 @@ import { generate } from '@constructive-io/graphql-codegen'; // Generate React Query hooks from a GraphQL endpoint await generate({ endpoint: 'https://api.example.com/graphql', - output: './generated/hooks', + output: './generated', headers: { Authorization: 'Bearer ' }, - reactQuery: { enabled: true }, + reactQuery: true, }); // Generate ORM client from a GraphQL endpoint await generate({ endpoint: 'https://api.example.com/graphql', - output: './generated/orm', + output: './generated', headers: { Authorization: 'Bearer ' }, - orm: { enabled: true }, + orm: true, }); // Generate both React Query hooks and ORM client await generate({ endpoint: 'https://api.example.com/graphql', output: './generated', - reactQuery: { enabled: true }, - orm: { enabled: true, output: './generated/orm' }, + reactQuery: true, + orm: true, }); ``` @@ -89,18 +89,35 @@ import { generate } from '@constructive-io/graphql-codegen'; // Generate from database with explicit schemas await generate({ - database: 'postgres://localhost/mydb', - schemas: ['public', 'app_public'], - output: './generated/hooks', - reactQuery: { enabled: true }, + db: { + schemas: ['public', 'app_public'], + }, + output: './generated', + reactQuery: true, }); // Generate from database using API names for automatic schema discovery await generate({ - database: 'postgres://localhost/mydb', - apiNames: ['my_api'], - output: './generated/orm', - orm: { enabled: true }, + db: { + apiNames: ['my_api'], + }, + output: './generated', + orm: true, +}); + +// Generate with explicit database config (overrides environment variables) +await generate({ + db: { + config: { + host: 'localhost', + port: 5432, + database: 'mydb', + user: 'postgres', + }, + schemas: ['public'], + }, + output: './generated', + reactQuery: true, }); ``` @@ -113,19 +130,36 @@ import { generate } from '@constructive-io/graphql-codegen'; // Generate from a PGPM module directory await generate({ - pgpmModulePath: './packages/my-module', - schemas: ['public'], - output: './generated/hooks', - reactQuery: { enabled: true }, + db: { + pgpm: { modulePath: './packages/my-module' }, + schemas: ['public'], + }, + output: './generated', + reactQuery: true, }); // Generate from a PGPM workspace with module name await generate({ - pgpmWorkspacePath: '/path/to/workspace', - pgpmModuleName: 'my-module', - schemas: ['public'], - output: './generated/orm', - orm: { enabled: true }, + db: { + pgpm: { + workspacePath: '/path/to/workspace', + moduleName: 'my-module', + }, + schemas: ['public'], + }, + output: './generated', + orm: true, +}); + +// Keep the ephemeral database after generation (for debugging) +await generate({ + db: { + pgpm: { modulePath: './packages/my-module' }, + schemas: ['public'], + keepDb: true, + }, + output: './generated', + reactQuery: true, }); ``` @@ -137,15 +171,8 @@ The `generate` function accepts a configuration object with the following option interface GraphQLSDKConfigTarget { // Source (choose one) endpoint?: string; // GraphQL endpoint URL - schema?: string; // Path to GraphQL schema file - database?: string; // Database connection URL - pgpmModulePath?: string; // Path to PGPM module directory - pgpmWorkspacePath?: string; // Path to PGPM workspace - pgpmModuleName?: string; // PGPM module name (with pgpmWorkspacePath) - - // Schema selection (for database/pgpm modes, choose one) - schemas?: string[]; // Explicit schema names - apiNames?: string[]; // API names for automatic schema discovery + schemaFile?: string; // Path to GraphQL schema file (.graphql) + db?: DbConfig; // Database configuration (see below) // Output output?: string; // Output directory (default: './generated/graphql') @@ -154,13 +181,8 @@ interface GraphQLSDKConfigTarget { headers?: Record; // HTTP headers for endpoint requests // Generator flags - reactQuery?: { - enabled?: boolean; // Generate React Query hooks - }; - orm?: { - enabled?: boolean; // Generate ORM client - output?: string; // ORM output directory - }; + reactQuery?: boolean; // Generate React Query hooks (output: {output}/hooks) + orm?: boolean; // Generate ORM client (output: {output}/orm) // Table filtering (for CRUD operations from _meta) tables?: { @@ -194,6 +216,26 @@ interface GraphQLSDKConfigTarget { relationships?: Record; }; } + +// Database configuration for direct database introspection or PGPM module +interface DbConfig { + // PostgreSQL connection config (falls back to PGHOST, PGPORT, etc. env vars) + config?: Partial; + + // PGPM module configuration for ephemeral database creation + pgpm?: { + modulePath?: string; // Path to PGPM module directory + workspacePath?: string; // Path to PGPM workspace (with moduleName) + moduleName?: string; // Module name within workspace + }; + + // Schema selection (choose one) + schemas?: string[]; // Explicit PostgreSQL schema names + apiNames?: string[]; // API names for automatic schema discovery + + // Debugging + keepDb?: boolean; // Keep ephemeral database after generation +} ``` ## React Query Hooks @@ -556,8 +598,8 @@ export default defineConfig({ headers: { Authorization: 'Bearer ', }, - reactQuery: { enabled: true }, - orm: { enabled: true, output: './generated/orm' }, + reactQuery: true, + orm: true, }); ``` @@ -574,12 +616,21 @@ export default defineConfig({ public: { endpoint: 'https://api.example.com/graphql', output: './generated/public', - reactQuery: { enabled: true }, + reactQuery: true, }, admin: { - schema: './admin.schema.graphql', + schemaFile: './admin.schema.graphql', output: './generated/admin', - orm: { enabled: true }, + orm: true, + }, + database: { + db: { + pgpm: { modulePath: './packages/my-module' }, + schemas: ['public'], + }, + output: './generated/db', + reactQuery: true, + orm: true, }, }, }); @@ -616,14 +667,13 @@ Generate React Query hooks and/or ORM client from various sources. Source Options (choose one): -c, --config Path to config file (graphql-sdk.config.ts) -e, --endpoint GraphQL endpoint URL - -s, --schema Path to GraphQL schema file - --database Database connection URL (postgres://...) + -s, --schema-file Path to GraphQL schema file (.graphql) --pgpm-module-path Path to PGPM module directory --pgpm-workspace-path Path to PGPM workspace (requires --pgpm-module-name) --pgpm-module-name PGPM module name in workspace -Schema Options (for database/pgpm modes): - --schemas Comma-separated list of schemas to introspect +Database Options (for pgpm modes): + --schemas Comma-separated list of PostgreSQL schemas to introspect --api-names Comma-separated API names for automatic schema discovery (mutually exclusive with --schemas) @@ -650,19 +700,19 @@ Examples: ```bash # Generate React Query hooks from an endpoint -npx graphql-sdk generate --endpoint https://api.example.com/graphql --output ./generated/hooks --react-query +npx graphql-sdk generate --endpoint https://api.example.com/graphql --output ./generated --react-query # Generate ORM client from an endpoint -npx graphql-sdk generate --endpoint https://api.example.com/graphql --output ./generated/orm --orm +npx graphql-sdk generate --endpoint https://api.example.com/graphql --output ./generated --orm -# Generate from a database directly -npx graphql-sdk generate --database postgres://localhost/mydb --schemas public,app_public --react-query +# Generate both React Query hooks and ORM client +npx graphql-sdk generate --endpoint https://api.example.com/graphql --output ./generated --react-query --orm # Generate from a PGPM module -npx graphql-sdk generate --pgpm-module-path ./packages/my-module --schemas public --orm +npx graphql-sdk generate --pgpm-module-path ./packages/my-module --schemas public --react-query # Generate using apiNames for automatic schema discovery -npx graphql-sdk generate --database postgres://localhost/mydb --api-names my_api --react-query --orm +npx graphql-sdk generate --pgpm-module-path ./packages/my-module --api-names my_api --react-query --orm ``` ### `graphql-sdk init` diff --git a/graphql/codegen/src/__tests__/config/resolve-config.test.ts b/graphql/codegen/src/__tests__/config/resolve-config.test.ts index 92b74ed92..1f81efffb 100644 --- a/graphql/codegen/src/__tests__/config/resolve-config.test.ts +++ b/graphql/codegen/src/__tests__/config/resolve-config.test.ts @@ -19,7 +19,7 @@ describe('config resolution', () => { const resolved = resolveConfig(config); expect(resolved.endpoint).toBe('https://api.example.com/graphql'); - expect(resolved.schema).toBeUndefined(); + expect(resolved.schemaFile).toBeUndefined(); expect(resolved.output).toBe(DEFAULT_CONFIG.output); expect(resolved.tables.include).toEqual(DEFAULT_CONFIG.tables.include); expect(resolved.queries.exclude).toEqual(DEFAULT_CONFIG.queries.exclude); @@ -77,7 +77,7 @@ describe('config resolution', () => { output: './generated/public', }, admin: { - schema: './admin.schema.graphql', + schemaFile: './admin.schema.graphql', output: './generated/admin', headers: { 'X-Admin': '1' }, }, @@ -103,7 +103,7 @@ describe('config resolution', () => { Authorization: 'Bearer token', 'X-Admin': '1', }); - expect(adminTarget?.config.schema).toBe('./admin.schema.graphql'); + expect(adminTarget?.config.schemaFile).toBe('./admin.schema.graphql'); }); it('detects multi-target configs', () => { diff --git a/graphql/codegen/src/cli/commands/generate-orm.ts b/graphql/codegen/src/cli/commands/generate-orm.ts index 73dfc9d0a..e71574388 100644 --- a/graphql/codegen/src/cli/commands/generate-orm.ts +++ b/graphql/codegen/src/cli/commands/generate-orm.ts @@ -123,7 +123,8 @@ async function generateOrmForTarget( isMultiTarget: boolean ): Promise { const config = target.config; - const outputDir = options.output || config.orm.output; + // Always use conventional subdirectory: {output}/orm + const outputDir = options.output || `${config.output}/orm`; const prefix = isMultiTarget ? `[${target.name}] ` : ''; const log = options.verbose ? (message: string) => console.log(`${prefix}${message}`) @@ -134,17 +135,19 @@ async function generateOrmForTarget( if (isMultiTarget) { console.log(`\nTarget "${target.name}"`); let sourceLabel: string; - const schemaInfo = config.apiNames && config.apiNames.length > 0 - ? `apiNames: ${config.apiNames.join(', ')}` - : `schemas: ${(config.schemas ?? ['public']).join(', ')}`; - if (config.pgpmModulePath) { - sourceLabel = `pgpm module: ${config.pgpmModulePath} (${schemaInfo})`; - } else if (config.pgpmWorkspacePath && config.pgpmModuleName) { - sourceLabel = `pgpm workspace: ${config.pgpmWorkspacePath}, module: ${config.pgpmModuleName} (${schemaInfo})`; - } else if (config.database) { - sourceLabel = `database: ${config.database} (${schemaInfo})`; - } else if (config.schema) { - sourceLabel = `schema: ${config.schema}`; + if (config.db) { + const schemaInfo = config.db.apiNames && config.db.apiNames.length > 0 + ? `apiNames: ${config.db.apiNames.join(', ')}` + : `schemas: ${(config.db.schemas ?? ['public']).join(', ')}`; + if (config.db.pgpm?.modulePath) { + sourceLabel = `pgpm module: ${config.db.pgpm.modulePath} (${schemaInfo})`; + } else if (config.db.pgpm?.workspacePath && config.db.pgpm?.moduleName) { + sourceLabel = `pgpm workspace: ${config.db.pgpm.workspacePath}, module: ${config.db.pgpm.moduleName} (${schemaInfo})`; + } else { + sourceLabel = `database (${schemaInfo})`; + } + } else if (config.schemaFile) { + sourceLabel = `schemaFile: ${config.schemaFile}`; } else { sourceLabel = `endpoint: ${config.endpoint}`; } @@ -155,13 +158,8 @@ async function generateOrmForTarget( // 1. Validate source const sourceValidation = validateSourceOptions({ endpoint: config.endpoint || undefined, - schema: config.schema || undefined, - database: config.database, - pgpmModulePath: config.pgpmModulePath, - pgpmWorkspacePath: config.pgpmWorkspacePath, - pgpmModuleName: config.pgpmModuleName, - schemas: config.schemas, - apiNames: config.apiNames, + schemaFile: config.schemaFile || undefined, + db: config.db, }); if (!sourceValidation.valid) { return { @@ -174,14 +172,8 @@ async function generateOrmForTarget( const source = createSchemaSource({ endpoint: config.endpoint || undefined, - schema: config.schema || undefined, - database: config.database, - pgpmModulePath: config.pgpmModulePath, - pgpmWorkspacePath: config.pgpmWorkspacePath, - pgpmModuleName: config.pgpmModuleName, - schemas: config.schemas, - apiNames: config.apiNames, - keepDb: config.keepDb, + schemaFile: config.schemaFile || undefined, + db: config.db, authorization: options.authorization || config.headers?.['Authorization'], headers: config.headers, }); diff --git a/graphql/codegen/src/cli/commands/generate-unified.ts b/graphql/codegen/src/cli/commands/generate-unified.ts index 80f894f0d..ad25b934e 100644 --- a/graphql/codegen/src/cli/commands/generate-unified.ts +++ b/graphql/codegen/src/cli/commands/generate-unified.ts @@ -11,11 +11,8 @@ import path from 'path'; import * as t from '@babel/types'; import { generateCode, addJSDocComment } from '../../core/codegen/babel-ast'; -import type { TargetConfig } from '../../types/config'; -import { - loadAndResolveConfig, - type ConfigOverrideOptions, -} from '../../core/config'; +import type { GraphQLSDKConfigTarget, TargetConfig } from '../../types/config'; +import { loadAndResolveConfig } from '../../core/config'; import { createSchemaSource, validateSourceOptions, @@ -29,19 +26,15 @@ import type { CleanTable, CleanOperation, TypeRegistry } from '../../types/schem export type GeneratorType = 'react-query' | 'orm' | 'shared'; -export interface GenerateOptions extends ConfigOverrideOptions { - /** Authorization header */ - authorization?: string; - /** Verbose output */ - verbose?: boolean; - /** Dry run - don't write files */ - dryRun?: boolean; - /** Skip custom operations (only generate table CRUD) */ - skipCustomOperations?: boolean; - /** Override: enable React Query SDK generation */ - enableReactQuery?: boolean; - /** Override: enable ORM client generation */ - enableOrm?: boolean; +/** + * Options for the generate() function. + * Extends GraphQLSDKConfigTarget with CLI-specific fields. + */ +export interface GenerateOptions extends GraphQLSDKConfigTarget { + /** Path to config file (CLI-only) */ + config?: string; + /** Named target in a multi-target config (CLI-only) */ + target?: string; } export interface GenerateTargetResult { @@ -82,10 +75,10 @@ interface PipelineResult { } /** - * Unified generate function that respects config.reactQuery.enabled and config.orm.enabled + * Unified generate function that respects config.reactQuery and config.orm * * Can generate React Query SDK, ORM client, or both based on configuration. - * Use the `reactQuery` and `orm` options to override config flags. + * Options override config values when provided. */ export async function generate( options: GenerateOptions = {} @@ -114,9 +107,9 @@ export async function generate( const results: GenerateTargetResult[] = []; for (const target of targets) { - // Determine which generators to run based on config and options - const runReactQuery = options.enableReactQuery ?? target.config.reactQuery?.enabled; - const runOrm = options.enableOrm ?? target.config.orm?.enabled; + // Determine which generators to run based on options (which override config) + const runReactQuery = options.reactQuery ?? target.config.reactQuery; + const runOrm = options.orm ?? target.config.orm; if (!runReactQuery && !runOrm) { results.push({ @@ -124,7 +117,7 @@ export async function generate( output: target.config.output, generatorType: 'react-query', success: false, - message: `Target "${target.name}": No generators enabled. Set reactQuery.enabled or orm.enabled in config, or use --react-query or --orm flags.`, + message: `Target "${target.name}": No generators enabled. Set reactQuery: true or orm: true in config, or use --react-query or --orm flags.`, }); continue; } @@ -219,7 +212,7 @@ export async function generate( export async function generateReactQuery( options: GenerateOptions = {} ): Promise { - return generate({ ...options, enableReactQuery: true, enableOrm: false }); + return generate({ ...options, reactQuery: true, orm: false }); } /** @@ -228,7 +221,7 @@ export async function generateReactQuery( export async function generateOrm( options: GenerateOptions = {} ): Promise { - return generate({ ...options, enableReactQuery: false, enableOrm: true }); + return generate({ ...options, reactQuery: false, orm: true }); } // ============================================================================ @@ -254,17 +247,19 @@ async function runPipelineForTarget( if (isMultiTarget) { console.log(`\nTarget "${target.name}"`); let sourceLabel: string; - const schemaInfo = config.apiNames && config.apiNames.length > 0 - ? `apiNames: ${config.apiNames.join(', ')}` - : `schemas: ${(config.schemas ?? ['public']).join(', ')}`; - if (config.pgpmModulePath) { - sourceLabel = `pgpm module: ${config.pgpmModulePath} (${schemaInfo})`; - } else if (config.pgpmWorkspacePath && config.pgpmModuleName) { - sourceLabel = `pgpm workspace: ${config.pgpmWorkspacePath}, module: ${config.pgpmModuleName} (${schemaInfo})`; - } else if (config.database) { - sourceLabel = `database: ${config.database} (${schemaInfo})`; - } else if (config.schema) { - sourceLabel = `schema: ${config.schema}`; + if (config.db) { + const schemaInfo = config.db.apiNames && config.db.apiNames.length > 0 + ? `apiNames: ${config.db.apiNames.join(', ')}` + : `schemas: ${(config.db.schemas ?? ['public']).join(', ')}`; + if (config.db.pgpm?.modulePath) { + sourceLabel = `pgpm module: ${config.db.pgpm.modulePath} (${schemaInfo})`; + } else if (config.db.pgpm?.workspacePath && config.db.pgpm?.moduleName) { + sourceLabel = `pgpm workspace: ${config.db.pgpm.workspacePath}, module: ${config.db.pgpm.moduleName} (${schemaInfo})`; + } else { + sourceLabel = `database (${schemaInfo})`; + } + } else if (config.schemaFile) { + sourceLabel = `schemaFile: ${config.schemaFile}`; } else { sourceLabel = `endpoint: ${config.endpoint}`; } @@ -274,13 +269,8 @@ async function runPipelineForTarget( // 1. Validate source const sourceValidation = validateSourceOptions({ endpoint: config.endpoint || undefined, - schema: config.schema || undefined, - database: config.database, - pgpmModulePath: config.pgpmModulePath, - pgpmWorkspacePath: config.pgpmWorkspacePath, - pgpmModuleName: config.pgpmModuleName, - schemas: config.schemas, - apiNames: config.apiNames, + schemaFile: config.schemaFile || undefined, + db: config.db, }); if (!sourceValidation.valid) { return { @@ -291,14 +281,8 @@ async function runPipelineForTarget( const source = createSchemaSource({ endpoint: config.endpoint || undefined, - schema: config.schema || undefined, - database: config.database, - pgpmModulePath: config.pgpmModulePath, - pgpmWorkspacePath: config.pgpmWorkspacePath, - pgpmModuleName: config.pgpmModuleName, - schemas: config.schemas, - apiNames: config.apiNames, - keepDb: config.keepDb, + schemaFile: config.schemaFile || undefined, + db: config.db, authorization: options.authorization || config.headers?.['Authorization'], headers: config.headers, }); @@ -344,10 +328,10 @@ async function runPipelineForTarget( * * Output structure: * {output}/ - * index.ts - Main barrel (re-exports shared + react-query + orm) + * index.ts - Main barrel (re-exports shared + hooks + orm) * types.ts - Shared entity types * schema-types.ts - Shared schema types (enums, input types) - * react-query/ - React Query SDK + * hooks/ - React Query hooks * orm/ - ORM client */ async function generateUnifiedOutput( @@ -442,8 +426,8 @@ function generateUnifiedBarrel(hasSchemaTypes: boolean): string { statements.push(exportAllFrom('./schema-types')); } - // React Query SDK - statements.push(exportAllFrom('./react-query')); + // React Query hooks + statements.push(exportAllFrom('./hooks')); // ORM Client statements.push(exportAllFrom('./orm')); @@ -456,7 +440,7 @@ function generateUnifiedBarrel(hasSchemaTypes: boolean): string { '', 'Exports:', '- Shared types (types.ts, schema-types.ts)', - '- React Query SDK (react-query/)', + '- React Query hooks (hooks/)', '- ORM Client (orm/)', ]); } @@ -472,9 +456,10 @@ async function generateReactQueryForTarget( sharedTypesPath?: string ): Promise { const config = target.config; + // Always use conventional subdirectory: {output}/hooks const outputDir = sharedTypesPath - ? path.join(config.output, 'react-query') - : config.output; + ? path.join(config.output, 'hooks') + : path.join(options.output || config.output, 'hooks'); const prefix = isMultiTarget ? `[${target.name}] ` : ''; const log = options.verbose ? (message: string) => console.log(`${prefix}${message}`) @@ -569,9 +554,10 @@ async function generateOrmForTarget( sharedTypesPath?: string ): Promise { const config = target.config; + // Always use conventional subdirectory: {output}/orm const outputDir = sharedTypesPath ? path.join(config.output, 'orm') - : (options.output || config.orm.output); + : path.join(options.output || config.output, 'orm'); const prefix = isMultiTarget ? `[${target.name}] ` : ''; const log = options.verbose ? (message: string) => console.log(`${prefix}${message}`) diff --git a/graphql/codegen/src/cli/commands/generate.ts b/graphql/codegen/src/cli/commands/generate.ts index 07f7f6ad6..8675bbe0d 100644 --- a/graphql/codegen/src/cli/commands/generate.ts +++ b/graphql/codegen/src/cli/commands/generate.ts @@ -133,17 +133,19 @@ async function generateForTarget( if (isMultiTarget) { console.log(`\nTarget "${target.name}"`); let sourceLabel: string; - const schemaInfo = config.apiNames && config.apiNames.length > 0 - ? `apiNames: ${config.apiNames.join(', ')}` - : `schemas: ${(config.schemas ?? ['public']).join(', ')}`; - if (config.pgpmModulePath) { - sourceLabel = `pgpm module: ${config.pgpmModulePath} (${schemaInfo})`; - } else if (config.pgpmWorkspacePath && config.pgpmModuleName) { - sourceLabel = `pgpm workspace: ${config.pgpmWorkspacePath}, module: ${config.pgpmModuleName} (${schemaInfo})`; - } else if (config.database) { - sourceLabel = `database: ${config.database} (${schemaInfo})`; - } else if (config.schema) { - sourceLabel = `schema: ${config.schema}`; + if (config.db) { + const schemaInfo = config.db.apiNames && config.db.apiNames.length > 0 + ? `apiNames: ${config.db.apiNames.join(', ')}` + : `schemas: ${(config.db.schemas ?? ['public']).join(', ')}`; + if (config.db.pgpm?.modulePath) { + sourceLabel = `pgpm module: ${config.db.pgpm.modulePath} (${schemaInfo})`; + } else if (config.db.pgpm?.workspacePath && config.db.pgpm?.moduleName) { + sourceLabel = `pgpm workspace: ${config.db.pgpm.workspacePath}, module: ${config.db.pgpm.moduleName} (${schemaInfo})`; + } else { + sourceLabel = `database (${schemaInfo})`; + } + } else if (config.schemaFile) { + sourceLabel = `schemaFile: ${config.schemaFile}`; } else { sourceLabel = `endpoint: ${config.endpoint}`; } @@ -154,13 +156,8 @@ async function generateForTarget( // 1. Validate source const sourceValidation = validateSourceOptions({ endpoint: config.endpoint || undefined, - schema: config.schema || undefined, - database: config.database, - pgpmModulePath: config.pgpmModulePath, - pgpmWorkspacePath: config.pgpmWorkspacePath, - pgpmModuleName: config.pgpmModuleName, - schemas: config.schemas, - apiNames: config.apiNames, + schemaFile: config.schemaFile || undefined, + db: config.db, }); if (!sourceValidation.valid) { return { @@ -173,14 +170,8 @@ async function generateForTarget( const source = createSchemaSource({ endpoint: config.endpoint || undefined, - schema: config.schema || undefined, - database: config.database, - pgpmModulePath: config.pgpmModulePath, - pgpmWorkspacePath: config.pgpmWorkspacePath, - pgpmModuleName: config.pgpmModuleName, - schemas: config.schemas, - apiNames: config.apiNames, - keepDb: config.keepDb, + schemaFile: config.schemaFile || undefined, + db: config.db, authorization: options.authorization || config.headers?.['Authorization'], headers: config.headers, }); diff --git a/graphql/codegen/src/cli/index.ts b/graphql/codegen/src/cli/index.ts index cc3e51c7b..210c36667 100644 --- a/graphql/codegen/src/cli/index.ts +++ b/graphql/codegen/src/cli/index.ts @@ -53,14 +53,13 @@ Usage: Source Options (choose one): --config, -c Path to config file --endpoint, -e GraphQL endpoint URL - --schema, -s Path to GraphQL schema file (.graphql) - --database Database name or connection string + --schema-file, -s Path to GraphQL schema file (.graphql) --pgpm-module-path Path to PGPM module (creates ephemeral database) --pgpm-workspace-path Path to PGPM workspace (use with --pgpm-module-name) --pgpm-module-name Module name in workspace (use with --pgpm-workspace-path) -Schema Options (for database/PGPM modes): - --schemas Comma-separated list of schemas to introspect (default: public) +Database Options (for database/PGPM modes): + --schemas Comma-separated list of PostgreSQL schemas to introspect --api-names Comma-separated list of API names (auto-resolves schemas from services_public.api_schemas) Generator Options: @@ -85,7 +84,7 @@ Watch Mode Options: Examples: graphql-codegen generate --endpoint http://localhost:5000/graphql --react-query - graphql-codegen generate --database mydb --schemas public,app_public --orm + graphql-codegen generate --pgpm-module-path ./my-module --schemas public --orm graphql-codegen generate --pgpm-module-path ./my-module --api-names my_api --react-query --orm graphql-codegen generate --config ./graphql-codegen.config.ts `; @@ -98,7 +97,7 @@ Usage: Options: --endpoint, -e GraphQL endpoint URL - --schema, -s Path to GraphQL schema file (.graphql) + --schema-file, -s Path to GraphQL schema file (.graphql) --authorization, -a
Authorization header value --json Output as JSON --help, -h Show this help message @@ -158,17 +157,17 @@ async function handleGenerate(argv: Partial): Promise { const config = (argv.config as string) || (argv.c as string); const target = (argv.target as string) || (argv.t as string); const endpoint = (argv.endpoint as string) || (argv.e as string); - const schema = (argv.schema as string) || (argv.s as string); - const database = argv.database as string | undefined; + const schemaFile = (argv['schema-file'] as string) || (argv.s as string); 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; - // Schema options + // Database options const schemasArg = argv.schemas as string | undefined; const schemas = schemasArg ? schemasArg.split(',').map((s) => s.trim()) : undefined; const apiNamesArg = argv['api-names'] as string | undefined; const apiNames = apiNamesArg ? apiNamesArg.split(',').map((s) => s.trim()) : undefined; + const keepDb = !!(argv['keep-db'] || argv.keepDb); // Generator options const reactQuery = !!argv['react-query']; @@ -178,7 +177,6 @@ async function handleGenerate(argv: Partial): Promise { const verbose = !!argv.verbose; const dryRun = !!(argv['dry-run'] || argv.dryRun); const skipCustomOperations = !!(argv['skip-custom-operations'] || argv.skipCustomOperations); - const keepDb = !!(argv['keep-db'] || argv.keepDb); // Watch options const watch = !!(argv.watch || argv.w); @@ -192,9 +190,9 @@ async function handleGenerate(argv: Partial): Promise { const clear = argv.clear !== false; // Validate source options - const sourceCount = [endpoint, schema, database, pgpmModulePath, pgpmWorkspacePath].filter(Boolean).length; + const sourceCount = [endpoint, schemaFile, pgpmModulePath, pgpmWorkspacePath].filter(Boolean).length; if (sourceCount > 1 && !pgpmWorkspacePath) { - console.error('x Cannot use multiple source options. Choose one: --endpoint, --schema, --database, or --pgpm-module-path'); + console.error('x Cannot use multiple source options. Choose one: --endpoint, --schema-file, or --pgpm-module-path'); process.exit(1); } @@ -208,7 +206,7 @@ async function handleGenerate(argv: Partial): Promise { process.exit(1); } - // Validate schema options + // Validate database options if (schemas && apiNames) { console.error('x Cannot use both --schemas and --api-names. Choose one.'); process.exit(1); @@ -216,7 +214,7 @@ async function handleGenerate(argv: Partial): Promise { // Watch mode if (watch) { - if (schema || database || pgpmModulePath || pgpmWorkspacePath) { + if (schemaFile || pgpmModulePath || pgpmWorkspacePath) { console.error('x Watch mode is only supported with --endpoint or --config.'); process.exit(1); } @@ -250,26 +248,32 @@ async function handleGenerate(argv: Partial): Promise { return; } + // Build db config if pgpm options are provided + const db = (pgpmModulePath || pgpmWorkspacePath) ? { + pgpm: { + modulePath: pgpmModulePath, + workspacePath: pgpmWorkspacePath, + moduleName: pgpmModuleName, + }, + schemas, + apiNames, + keepDb, + } : undefined; + // Run generation const result = await generate({ config, target, endpoint, - schema, - database, - pgpmModulePath, - pgpmWorkspacePath, - pgpmModuleName, - schemas, - apiNames, + schemaFile, + db, output, authorization, verbose, dryRun, skipCustomOperations, - keepDb, - enableReactQuery: reactQuery, - enableOrm: orm, + reactQuery, + orm, }); const duration = formatDuration(performance.now() - startTime); @@ -358,17 +362,17 @@ async function handleIntrospect(argv: Partial): Promise { const startTime = performance.now(); const endpoint = (argv.endpoint as string) || (argv.e as string); - const schema = (argv.schema as string) || (argv.s as string); + const schemaFile = (argv['schema-file'] as string) || (argv.s as string); const authorization = (argv.authorization as string) || (argv.a as string); const json = !!argv.json; - if (!endpoint && !schema) { - console.error('x Either --endpoint or --schema must be provided.'); + if (!endpoint && !schemaFile) { + console.error('x Either --endpoint or --schema-file must be provided.'); process.exit(1); } - if (endpoint && schema) { + if (endpoint && schemaFile) { console.error( - 'x Cannot use both --endpoint and --schema. Choose one source.' + 'x Cannot use both --endpoint and --schema-file. Choose one source.' ); process.exit(1); } @@ -376,7 +380,7 @@ async function handleIntrospect(argv: Partial): Promise { try { const source = createSchemaSource({ endpoint, - schema, + schemaFile, authorization, }); @@ -485,7 +489,7 @@ export const options: Partial = { c: 'config', t: 'target', e: 'endpoint', - s: 'schema', + s: 'schema-file', o: 'output', a: 'authorization', d: 'directory', @@ -497,8 +501,8 @@ export const options: Partial = { 'skip-custom-operations', 'clear', 'react-query', 'orm', 'keep-db', ], string: [ - 'config', 'target', 'endpoint', 'schema', 'output', 'authorization', - 'directory', 'touch', 'poll-interval', 'debounce', 'database', + 'config', 'target', 'endpoint', 'schema-file', 'output', 'authorization', + 'directory', 'touch', 'poll-interval', 'debounce', 'pgpm-module-path', 'pgpm-workspace-path', 'pgpm-module-name', 'schemas', 'api-names', ], diff --git a/graphql/codegen/src/core/codegen/index.ts b/graphql/codegen/src/core/codegen/index.ts index 1e7a6e79f..d300cd7ae 100644 --- a/graphql/codegen/src/core/codegen/index.ts +++ b/graphql/codegen/src/core/codegen/index.ts @@ -120,7 +120,7 @@ export function generate(options: GenerateOptions): GenerateResult { // Extract codegen options const maxDepth = config.codegen.maxFieldDepth; const skipQueryField = config.codegen.skipQueryField; - const reactQueryEnabled = config.reactQuery.enabled; + const reactQueryEnabled = config.reactQuery; // Query key configuration (use defaults if not provided) const queryKeyConfig: QueryKeyConfig = config.queryKeys ?? DEFAULT_QUERY_KEY_CONFIG; diff --git a/graphql/codegen/src/core/codegen/orm/index.ts b/graphql/codegen/src/core/codegen/orm/index.ts index e749e3ca6..c3e817946 100644 --- a/graphql/codegen/src/core/codegen/orm/index.ts +++ b/graphql/codegen/src/core/codegen/orm/index.ts @@ -56,10 +56,11 @@ export interface GenerateOrmResult { * Generate all ORM client files */ export function generateOrm(options: GenerateOrmOptions): GenerateOrmResult { - const { tables, customOperations, config } = options; + const { tables, customOperations, sharedTypesPath } = options; const files: GeneratedFile[] = []; - const useSharedTypes = config.orm.useSharedTypes; + // Use shared types when a sharedTypesPath is provided (unified output mode) + const useSharedTypes = !!sharedTypesPath; const hasCustomQueries = (customOperations?.queries.length ?? 0) > 0; const hasCustomMutations = (customOperations?.mutations.length ?? 0) > 0; const typeRegistry = customOperations?.typeRegistry; diff --git a/graphql/codegen/src/core/config/resolver.ts b/graphql/codegen/src/core/config/resolver.ts index b1ecd47ad..cbf7aa59e 100644 --- a/graphql/codegen/src/core/config/resolver.ts +++ b/graphql/codegen/src/core/config/resolver.ts @@ -14,8 +14,11 @@ import { isMultiConfig, mergeConfig, getConfigOptions } from '../../types/config import { findConfigFile, loadConfigFile } from './loader'; /** - * CLI options that can override config file settings. + * Options that can override config file settings. * Extends GraphQLSDKConfigTarget with CLI-specific fields. + * + * This is the same as GenerateOptions - both extend GraphQLSDKConfigTarget + * with config and target fields for CLI usage. */ export interface ConfigOverrideOptions extends GraphQLSDKConfigTarget { /** Path to config file (CLI-only) */ @@ -49,22 +52,17 @@ export async function loadAndResolveConfig( // Destructure CLI-only fields, rest is config overrides const { config: configPath, target: targetName, ...overrides } = options; - // Check for pgpm workspace mode (requires both pgpmWorkspacePath and pgpmModuleName) - const hasPgpmWorkspace = overrides.pgpmWorkspacePath && overrides.pgpmModuleName; - // Validate that at most one source is specified const sources = [ overrides.endpoint, - overrides.schema, - overrides.database, - overrides.pgpmModulePath, - hasPgpmWorkspace, + overrides.schemaFile, + overrides.db, ].filter(Boolean); if (sources.length > 1) { return { success: false, error: - 'Multiple sources specified. Use only one of: endpoint, schema, database, pgpmModulePath, or pgpmWorkspacePath + pgpmModuleName.', + 'Multiple sources specified. Use only one of: endpoint, schemaFile, or db.', }; } @@ -108,8 +106,7 @@ function resolveMultiTargetConfig( if ( !targetName && - (overrides.endpoint || overrides.schema || overrides.database || - overrides.pgpmModulePath || overrides.pgpmWorkspacePath || overrides.output) + (overrides.endpoint || overrides.schemaFile || overrides.db || overrides.output) ) { return { success: false, @@ -139,15 +136,13 @@ function resolveMultiTargetConfig( const hasSource = mergedTarget.endpoint || - mergedTarget.schema || - mergedTarget.database || - mergedTarget.pgpmModulePath || - (mergedTarget.pgpmWorkspacePath && mergedTarget.pgpmModuleName); + mergedTarget.schemaFile || + mergedTarget.db; if (!hasSource) { return { success: false, - error: `Target "${name}" is missing a source (endpoint, schema, database, or pgpm module).`, + error: `Target "${name}" is missing a source (endpoint, schemaFile, or db).`, }; } @@ -182,19 +177,17 @@ function resolveSingleTargetConfig( const mergedConfig = mergeConfig(baseConfig, overrides); - // Check if we have a source (endpoint, schema, database, or pgpm module) + // Check if we have a source (endpoint, schemaFile, or db) const hasSource = mergedConfig.endpoint || - mergedConfig.schema || - mergedConfig.database || - mergedConfig.pgpmModulePath || - (mergedConfig.pgpmWorkspacePath && mergedConfig.pgpmModuleName); + mergedConfig.schemaFile || + mergedConfig.db; if (!hasSource) { return { success: false, error: - 'No source specified. Use --endpoint, --schema, --database, --pgpmModulePath, or --pgpmWorkspacePath + --pgpmModuleName, or create a config file with "graphql-codegen init".', + 'No source specified. Use --endpoint, --schema-file, or --db, or create a config file with "graphql-codegen init".', }; } @@ -256,7 +249,7 @@ export async function loadWatchConfig(options: { const sourceOverrides: GraphQLSDKConfigTarget = {}; if (options.endpoint) { sourceOverrides.endpoint = options.endpoint; - sourceOverrides.schema = undefined; + sourceOverrides.schemaFile = undefined; } const watchOverrides: GraphQLSDKConfigTarget = { @@ -290,9 +283,9 @@ export async function loadWatchConfig(options: { return null; } - if (mergedTarget.schema) { + if (mergedTarget.schemaFile) { console.error( - 'x Watch mode is only supported with an endpoint, not schema.' + 'x Watch mode is only supported with an endpoint, not schemaFile.' ); return null; } diff --git a/graphql/codegen/src/core/introspect/source/index.ts b/graphql/codegen/src/core/introspect/source/index.ts index 24a2f71d2..9642201c0 100644 --- a/graphql/codegen/src/core/introspect/source/index.ts +++ b/graphql/codegen/src/core/introspect/source/index.ts @@ -15,6 +15,7 @@ export * from './pgpm-module'; export * from './api-schemas'; import type { SchemaSource } from './types'; +import type { DbConfig, PgpmConfig } from '../../../types/config'; import { EndpointSchemaSource } from './endpoint'; import { FileSchemaSource } from './file'; import { DatabaseSchemaSource } from './database'; @@ -38,7 +39,7 @@ export interface EndpointSourceOptions { * Options for file-based schema source */ export interface FileSourceOptions { - schema: string; + schemaFile: string; } /** @@ -80,47 +81,12 @@ export interface CreateSchemaSourceOptions { /** * Path to GraphQL schema file (.graphql) */ - schema?: string; + schemaFile?: string; /** - * Database name or connection string (for database introspection) + * Database configuration for direct database introspection or PGPM module */ - database?: string; - - /** - * Path to a PGPM module directory (for module introspection) - * Creates an ephemeral database, deploys the module, and introspects - */ - pgpmModulePath?: string; - - /** - * Path to a PGPM workspace directory (used with pgpmModuleName) - */ - pgpmWorkspacePath?: string; - - /** - * Name of the module within the workspace (used with pgpmWorkspacePath) - */ - pgpmModuleName?: string; - - /** - * PostgreSQL schemas to include (for database and pgpm module modes) - * Mutually exclusive with apiNames - exactly one must be provided for database/pgpm modes - */ - schemas?: string[]; - - /** - * API names to resolve schemas from (for database and pgpm module modes) - * Queries services_public.api_schemas to get schema names for the given APIs - * Mutually exclusive with schemas - exactly one must be provided for database/pgpm modes - */ - apiNames?: string[]; - - /** - * Keep the ephemeral database after introspection (for debugging, pgpm module mode only) - * @default false - */ - keepDb?: boolean; + db?: DbConfig; /** * Optional authorization header for endpoint requests @@ -141,14 +107,18 @@ export interface CreateSchemaSourceOptions { /** * Detect which source mode is being used based on options */ -export type SourceMode = 'endpoint' | 'schema' | 'database' | 'pgpm-module' | 'pgpm-workspace'; +export type SourceMode = 'endpoint' | 'schemaFile' | 'database' | 'pgpm-module' | 'pgpm-workspace'; export function detectSourceMode(options: CreateSchemaSourceOptions): SourceMode | null { if (options.endpoint) return 'endpoint'; - if (options.schema) return 'schema'; - if (options.database) return 'database'; - if (options.pgpmModulePath) return 'pgpm-module'; - if (options.pgpmWorkspacePath && options.pgpmModuleName) return 'pgpm-workspace'; + if (options.schemaFile) return 'schemaFile'; + if (options.db) { + // Check for PGPM modes first + if (options.db.pgpm?.modulePath) return 'pgpm-module'; + if (options.db.pgpm?.workspacePath && options.db.pgpm?.moduleName) return 'pgpm-workspace'; + // Default to database mode if db is specified without pgpm + return 'database'; + } return null; } @@ -157,7 +127,7 @@ export function detectSourceMode(options: CreateSchemaSourceOptions): SourceMode * * Supports five modes: * - endpoint: Introspect from a live GraphQL endpoint - * - schema: Load from a local .graphql file + * - schemaFile: Load from a local .graphql file * - database: Introspect directly from a PostgreSQL database * - pgpm-module: Deploy a PGPM module to an ephemeral database and introspect * - pgpm-workspace: Deploy a module from a PGPM workspace to an ephemeral database and introspect @@ -172,9 +142,9 @@ export function createSchemaSource( const mode = detectSourceMode(options); switch (mode) { - case 'schema': + case 'schemaFile': return new FileSchemaSource({ - schemaPath: options.schema!, + schemaPath: options.schemaFile!, }); case 'endpoint': @@ -186,32 +156,34 @@ export function createSchemaSource( }); case 'database': + // Database mode uses db.config for connection (falls back to env vars) + // and db.schemas or db.apiNames for schema selection return new DatabaseSchemaSource({ - database: options.database!, - schemas: options.schemas, - apiNames: options.apiNames, + database: options.db?.config?.database ?? '', + schemas: options.db?.schemas, + apiNames: options.db?.apiNames, }); case 'pgpm-module': return new PgpmModuleSchemaSource({ - pgpmModulePath: options.pgpmModulePath!, - schemas: options.schemas, - apiNames: options.apiNames, - keepDb: options.keepDb, + pgpmModulePath: options.db!.pgpm!.modulePath!, + schemas: options.db?.schemas, + apiNames: options.db?.apiNames, + keepDb: options.db?.keepDb, }); case 'pgpm-workspace': return new PgpmModuleSchemaSource({ - pgpmWorkspacePath: options.pgpmWorkspacePath!, - pgpmModuleName: options.pgpmModuleName!, - schemas: options.schemas, - apiNames: options.apiNames, - keepDb: options.keepDb, + pgpmWorkspacePath: options.db!.pgpm!.workspacePath!, + pgpmModuleName: options.db!.pgpm!.moduleName!, + schemas: options.db?.schemas, + apiNames: options.db?.apiNames, + keepDb: options.db?.keepDb, }); default: throw new Error( - 'No source specified. Use one of: endpoint (URL), schema (file path), database (name/connection string), pgpmModulePath (module directory), or pgpmWorkspacePath + pgpmModuleName.' + 'No source specified. Use one of: endpoint, schemaFile, or db (with optional pgpm for module deployment).' ); } } @@ -223,23 +195,18 @@ export function validateSourceOptions(options: CreateSchemaSourceOptions): { valid: boolean; error?: string; } { - // Check for pgpm workspace mode (requires both pgpmWorkspacePath and pgpmModuleName) - const hasPgpmWorkspace = options.pgpmWorkspacePath && options.pgpmModuleName; - - // Count primary sources (pgpm workspace counts as one source) + // Count primary sources const sources = [ options.endpoint, - options.schema, - options.database, - options.pgpmModulePath, - hasPgpmWorkspace, + options.schemaFile, + options.db, ].filter(Boolean); if (sources.length === 0) { return { valid: false, error: - 'No source specified. Use one of: endpoint, schema, database, pgpmModulePath, or pgpmWorkspacePath + pgpmModuleName.', + 'No source specified. Use one of: endpoint, schemaFile, or db.', }; } @@ -247,42 +214,52 @@ export function validateSourceOptions(options: CreateSchemaSourceOptions): { return { valid: false, error: - 'Multiple sources specified. Use only one of: endpoint, schema, database, pgpmModulePath, or pgpmWorkspacePath + pgpmModuleName.', + 'Multiple sources specified. Use only one of: endpoint, schemaFile, or db.', }; } // Validate pgpm workspace mode has both required fields - if (options.pgpmWorkspacePath && !options.pgpmModuleName) { - return { - valid: false, - error: 'pgpmWorkspacePath requires pgpmModuleName to be specified.', - }; - } + if (options.db?.pgpm) { + const pgpm = options.db.pgpm; + if (pgpm.workspacePath && !pgpm.moduleName) { + return { + valid: false, + error: 'db.pgpm.workspacePath requires db.pgpm.moduleName to be specified.', + }; + } - if (options.pgpmModuleName && !options.pgpmWorkspacePath) { - return { - valid: false, - error: 'pgpmModuleName requires pgpmWorkspacePath to be specified.', - }; + if (pgpm.moduleName && !pgpm.workspacePath) { + return { + valid: false, + error: 'db.pgpm.moduleName requires db.pgpm.workspacePath to be specified.', + }; + } + + // Must have either modulePath or workspacePath+moduleName + if (!pgpm.modulePath && !(pgpm.workspacePath && pgpm.moduleName)) { + return { + valid: false, + error: 'db.pgpm requires either modulePath or both workspacePath and moduleName.', + }; + } } - // For database and pgpm modes, validate schemas/apiNames mutual exclusivity - const isDatabaseOrPgpmMode = options.database || options.pgpmModulePath || hasPgpmWorkspace; - if (isDatabaseOrPgpmMode) { - const hasSchemas = options.schemas && options.schemas.length > 0; - const hasApiNames = options.apiNames && options.apiNames.length > 0; + // For database mode, validate schemas/apiNames mutual exclusivity + if (options.db) { + const hasSchemas = options.db.schemas && options.db.schemas.length > 0; + const hasApiNames = options.db.apiNames && options.db.apiNames.length > 0; if (hasSchemas && hasApiNames) { return { valid: false, - error: 'Cannot specify both schemas and apiNames. Use one or the other.', + error: 'Cannot specify both db.schemas and db.apiNames. Use one or the other.', }; } if (!hasSchemas && !hasApiNames) { return { valid: false, - error: 'Must specify either schemas or apiNames for database/pgpm modes.', + error: 'Must specify either db.schemas or db.apiNames for database mode.', }; } } diff --git a/graphql/codegen/src/core/watch/orchestrator.ts b/graphql/codegen/src/core/watch/orchestrator.ts index f73fbe413..c530c113e 100644 --- a/graphql/codegen/src/core/watch/orchestrator.ts +++ b/graphql/codegen/src/core/watch/orchestrator.ts @@ -219,11 +219,13 @@ export class WatchOrchestrator { switch (this.options.generatorType) { case 'react-query': generateFn = this.options.generateReactQuery; - outputDir = this.options.outputDir ?? this.options.config.output; + // React Query hooks go to {output}/hooks + outputDir = this.options.outputDir ?? `${this.options.config.output}/hooks`; break; case 'orm': generateFn = this.options.generateOrm; - outputDir = this.options.outputDir ?? this.options.config.orm.output; + // ORM client goes to {output}/orm + outputDir = this.options.outputDir ?? `${this.options.config.output}/orm`; break; default: throw new Error(`Unknown generator type: ${this.options.generatorType}`); diff --git a/graphql/codegen/src/types/config.ts b/graphql/codegen/src/types/config.ts index 967d3e9a9..f521943e2 100644 --- a/graphql/codegen/src/types/config.ts +++ b/graphql/codegen/src/types/config.ts @@ -3,6 +3,7 @@ */ import deepmerge from 'deepmerge'; +import type { PgConfig } from 'pg-env'; /** * Array merge strategy that replaces arrays (source wins over target). @@ -73,61 +74,54 @@ export interface QueryKeyConfig { } /** - * Target configuration for graphql-codegen - * Represents a single schema source and output destination. - * - * Source options (choose one): - * - endpoint: GraphQL endpoint URL for live introspection - * - schema: Path to GraphQL schema file (.graphql) - * - database: Database name or connection string for direct introspection - * - pgpmModulePath: Path to PGPM module (creates ephemeral database) - * - pgpmWorkspacePath + pgpmModuleName: PGPM workspace mode + * PGPM module configuration for ephemeral database creation */ -export interface GraphQLSDKConfigTarget { +export interface PgpmConfig { /** - * GraphQL endpoint URL for live introspection - */ - endpoint?: string; - - /** - * Path to GraphQL schema file (.graphql) for file-based generation + * Path to a PGPM module directory + * Creates an ephemeral database, deploys the module, and introspects */ - schema?: string; + modulePath?: string; /** - * Database name or connection string for direct database introspection - * Use with `schemas` or `apiNames` to specify which schemas to introspect + * Path to a PGPM workspace directory + * Must be used together with `moduleName` */ - database?: string; + workspacePath?: string; /** - * Path to a PGPM module directory - * Creates an ephemeral database, deploys the module, and introspects - * Use with `schemas` or `apiNames` to specify which schemas to introspect + * Name of the module within the PGPM workspace + * Must be used together with `workspacePath` */ - pgpmModulePath?: string; + moduleName?: string; +} +/** + * Database configuration for direct database introspection + */ +export interface DbConfig { /** - * Path to a PGPM workspace directory - * Must be used together with `pgpmModuleName` + * PostgreSQL connection configuration + * Falls back to environment variables (PGHOST, PGPORT, PGUSER, PGPASSWORD, PGDATABASE) + * via @pgpmjs/env when not specified */ - pgpmWorkspacePath?: string; + config?: Partial; /** - * Name of the module within the PGPM workspace - * Must be used together with `pgpmWorkspacePath` + * PGPM module configuration for ephemeral database creation + * When specified, creates an ephemeral database from the module */ - pgpmModuleName?: string; + pgpm?: PgpmConfig; /** - * PostgreSQL schemas to introspect (for database and PGPM modes) + * PostgreSQL schemas to introspect * Mutually exclusive with `apiNames` * @example ['public', 'app_public'] */ schemas?: string[]; /** - * API names to resolve schemas from (for database and PGPM modes) + * API names to resolve schemas from * Queries services_public.api_schemas to automatically determine schemas * Mutually exclusive with `schemas` * @example ['my_api'] @@ -136,10 +130,37 @@ export interface GraphQLSDKConfigTarget { /** * Keep the ephemeral database after introspection (for debugging) - * Only applies to PGPM module modes + * Only applies when using pgpm * @default false */ keepDb?: boolean; +} + +/** + * Target configuration for graphql-codegen + * Represents a single schema source and output destination. + * + * Source options (choose one): + * - endpoint: GraphQL endpoint URL for live introspection + * - schemaFile: Path to GraphQL schema file (.graphql) + * - db: Database configuration for direct introspection or PGPM module + */ +export interface GraphQLSDKConfigTarget { + /** + * GraphQL endpoint URL for live introspection + */ + endpoint?: string; + + /** + * Path to GraphQL schema file (.graphql) for file-based generation + */ + schemaFile?: string; + + /** + * Database configuration for direct database introspection or PGPM module + * Use db.schemas or db.apiNames to specify which schemas to introspect + */ + db?: DbConfig; /** * Headers to include in introspection requests @@ -226,40 +247,19 @@ export interface GraphQLSDKConfigTarget { }; /** - * ORM client generation options - * When set, generates a Prisma-like ORM client in addition to or instead of React Query hooks - */ - orm?: { - /** - * Whether to generate ORM client - * @default false - */ - enabled?: boolean; - /** - * Output directory for generated ORM client - * @default './generated/orm' - */ - output?: string; - /** - * Whether to import shared types from hooks output or generate standalone - * When true, ORM types.ts will re-export from ../graphql/types - * @default true - */ - useSharedTypes?: boolean; - }; + * Whether to generate ORM client + * When enabled, generates a Prisma-like ORM client to {output}/orm + * @default false + */ + orm?: boolean; /** - * React Query integration options - * Controls whether React Query hooks are generated + * Whether to generate React Query hooks + * When enabled, generates React Query hooks to {output}/hooks + * When false, only standalone fetch functions are generated (no React dependency) + * @default false */ - reactQuery?: { - /** - * Whether to generate React Query hooks (useQuery, useMutation) - * When false, only standalone fetch functions are generated (no React dependency) - * @default false - */ - enabled?: boolean; - }; + reactQuery?: boolean; /** * Query key generation configuration @@ -272,6 +272,33 @@ export interface GraphQLSDKConfigTarget { * When enabled via CLI --watch flag, the CLI will poll the endpoint for schema changes */ watch?: WatchConfig; + + // ============================================================================ + // Runtime options (used when calling generate() programmatically) + // ============================================================================ + + /** + * Authorization header value (convenience option, also available in headers) + */ + authorization?: string; + + /** + * Enable verbose output + * @default false + */ + verbose?: boolean; + + /** + * Dry run - don't write files, just show what would be generated + * @default false + */ + dryRun?: boolean; + + /** + * Skip custom operations (only generate table CRUD) + * @default false + */ + skipCustomOperations?: boolean; } /** @@ -383,14 +410,8 @@ export const DEFAULT_CONFIG: GraphQLSDKConfigTarget = { maxFieldDepth: 2, skipQueryField: true, }, - orm: { - enabled: false, - output: './generated/orm', - useSharedTypes: true, - }, - reactQuery: { - enabled: false, - }, + orm: false, + reactQuery: false, queryKeys: DEFAULT_QUERY_KEY_CONFIG, watch: DEFAULT_WATCH_CONFIG, }; diff --git a/packages/cli/__tests__/codegen.test.ts b/packages/cli/__tests__/codegen.test.ts index 060488e7d..b6ed7abd3 100644 --- a/packages/cli/__tests__/codegen.test.ts +++ b/packages/cli/__tests__/codegen.test.ts @@ -58,10 +58,10 @@ describe('codegen command', () => { authorization: 'Bearer testtoken', verbose: true, dryRun: true, - enableReactQuery: true + reactQuery: true }) - // enableOrm is undefined when not set (defaults to false via !orm) - expect(call.enableOrm).toBeFalsy() + // orm is undefined when not set (defaults to false via !orm) + expect(call.orm).toBeFalsy() }) it('builds schema file and calls generate with schema when DB options provided', async () => { @@ -79,11 +79,11 @@ describe('codegen command', () => { expect(buildSchemaFromDatabase).toHaveBeenCalled() expect(mockGenerate).toHaveBeenCalled() const call = mockGenerate.mock.calls[0][0] - expect(call.schema).toBe('graphql/codegen/dist/schema.graphql') + expect(call.schemaFile).toBe('graphql/codegen/dist/schema.graphql') expect(call.output).toBe('graphql/codegen/dist') expect(call.endpoint).toBeUndefined() - expect(call.enableReactQuery).toBe(true) - // enableOrm is undefined when not set (defaults to false via !orm) - expect(call.enableOrm).toBeFalsy() + expect(call.reactQuery).toBe(true) + // orm is undefined when not set (defaults to false via !orm) + expect(call.orm).toBeFalsy() }) }) diff --git a/packages/cli/src/commands/codegen.ts b/packages/cli/src/commands/codegen.ts index 1c627649e..1d9f197ed 100644 --- a/packages/cli/src/commands/codegen.ts +++ b/packages/cli/src/commands/codegen.ts @@ -169,14 +169,14 @@ export default async ( config, target, endpoint: endpoint || undefined, - schema: schemaPath, + schemaFile: schemaPath, output, authorization: auth, verbose, dryRun, // Use flags to control which generators run - enableReactQuery: !orm, - enableOrm: orm, + reactQuery: !orm, + orm: orm, }); printResult(result); From 22c14a4706b70dd4a40b4aa97820772d85ddfaf4 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 23 Jan 2026 22:32:04 +0000 Subject: [PATCH 21/23] refactor(graphql-codegen): simplify CLI to single file using inquirerer - Consolidate all CLI commands into a single src/cli/index.ts file - Remove separate command files (generate.ts, generate-orm.ts, generate-unified.ts, init.ts) - Use inquirerer pattern for clean CLI interface - Export generate() function and types from main index.ts - Update package.json scripts to use new CLI structure - Remove unused mock from packages/cli test --- graphql/codegen/package.json | 8 +- .../codegen/src/cli/commands/generate-orm.ts | 284 ------ .../src/cli/commands/generate-unified.ts | 645 -------------- graphql/codegen/src/cli/commands/generate.ts | 282 ------ graphql/codegen/src/cli/commands/index.ts | 9 - graphql/codegen/src/cli/commands/init.ts | 121 --- graphql/codegen/src/cli/index.ts | 810 +++++++++--------- graphql/codegen/src/index.ts | 19 +- packages/cli/__tests__/cli.test.ts | 6 - 9 files changed, 391 insertions(+), 1793 deletions(-) delete mode 100644 graphql/codegen/src/cli/commands/generate-orm.ts delete mode 100644 graphql/codegen/src/cli/commands/generate-unified.ts delete mode 100644 graphql/codegen/src/cli/commands/generate.ts delete mode 100644 graphql/codegen/src/cli/commands/index.ts delete mode 100644 graphql/codegen/src/cli/commands/init.ts diff --git a/graphql/codegen/package.json b/graphql/codegen/package.json index 992d98741..2692b7fb2 100644 --- a/graphql/codegen/package.json +++ b/graphql/codegen/package.json @@ -44,10 +44,10 @@ "fmt:check": "prettier --check .", "test": "jest --passWithNoTests", "test:watch": "jest --watch", - "example:codegen:sdk": "tsx src/cli/index.ts generate --config examples/multi-target.config.ts --react-query", - "example:codegen:orm": "tsx src/cli/index.ts generate --config examples/multi-target.config.ts --orm", - "example:codegen:sdk:schema": "node dist/cli/index.js generate --schema examples/example.schema.graphql --output examples/output/generated-sdk-schema --react-query", - "example:codegen:orm:schema": "node dist/cli/index.js generate --schema examples/example.schema.graphql --output examples/output/generated-orm-schema --orm", + "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", + "example:codegen:sdk:schema": "node dist/cli/index.js --schema-file examples/example.schema.graphql --output examples/output/generated-sdk-schema --react-query", + "example:codegen:orm:schema": "node dist/cli/index.js --schema-file examples/example.schema.graphql --output examples/output/generated-orm-schema --orm", "example:sdk": "tsx examples/react-hooks-sdk-test.tsx", "example:orm": "tsx examples/orm-sdk-test.ts", "example:sdk:typecheck": "tsc --noEmit --jsx react --esModuleInterop --skipLibCheck --moduleResolution node examples/react-hooks-sdk-test.tsx" diff --git a/graphql/codegen/src/cli/commands/generate-orm.ts b/graphql/codegen/src/cli/commands/generate-orm.ts deleted file mode 100644 index e71574388..000000000 --- a/graphql/codegen/src/cli/commands/generate-orm.ts +++ /dev/null @@ -1,284 +0,0 @@ -/** - * Generate ORM command - generates Prisma-like ORM client from GraphQL schema - * - * This is a thin CLI wrapper around the core generation functions. - * All business logic is in the core modules. - */ -import type { TargetConfig } from '../../types/config'; -import { - loadAndResolveConfig, - type ConfigOverrideOptions, -} from '../../core/config'; -import { - createSchemaSource, - validateSourceOptions, -} from '../../core/introspect'; -import { runCodegenPipeline, validateTablesFound } from '../../core/pipeline'; -import { generateOrm as generateOrmFiles } from '../../core/codegen/orm'; -import { writeGeneratedFiles } from '../../core/output'; - -export interface GenerateOrmOptions extends ConfigOverrideOptions { - /** Authorization header */ - authorization?: string; - /** Verbose output */ - verbose?: boolean; - /** Dry run - don't write files */ - dryRun?: boolean; - /** Skip custom operations (only generate table CRUD) */ - skipCustomOperations?: boolean; -} - -export interface GenerateOrmTargetResult { - name: string; - output: string; - success: boolean; - message: string; - tables?: string[]; - customQueries?: string[]; - customMutations?: string[]; - filesWritten?: string[]; - errors?: string[]; -} - -export interface GenerateOrmResult { - success: boolean; - message: string; - targets?: GenerateOrmTargetResult[]; - tables?: string[]; - customQueries?: string[]; - customMutations?: string[]; - filesWritten?: string[]; - errors?: string[]; -} - -/** - * Execute the generate-orm command (generates ORM client) - */ -export async function generateOrm( - options: GenerateOrmOptions = {} -): Promise { - if (options.verbose) { - console.log('Loading configuration...'); - } - - const configResult = await loadAndResolveConfig(options); - if (!configResult.success) { - return { - success: false, - message: configResult.error!, - }; - } - - const targets = configResult.targets ?? []; - if (targets.length === 0) { - return { - success: false, - message: 'No targets resolved from configuration.', - }; - } - - const isMultiTarget = configResult.isMulti ?? targets.length > 1; - const results: GenerateOrmTargetResult[] = []; - - for (const target of targets) { - const result = await generateOrmForTarget(target, options, isMultiTarget); - results.push(result); - } - - if (!isMultiTarget) { - const [result] = results; - return { - success: result.success, - message: result.message, - targets: results, - tables: result.tables, - customQueries: result.customQueries, - customMutations: result.customMutations, - filesWritten: result.filesWritten, - errors: result.errors, - }; - } - - const successCount = results.filter((result) => result.success).length; - const failedCount = results.length - successCount; - const summaryMessage = - failedCount === 0 - ? `Generated ORM clients for ${results.length} targets.` - : `Generated ORM clients for ${successCount} of ${results.length} targets.`; - - return { - success: failedCount === 0, - message: summaryMessage, - targets: results, - errors: - failedCount > 0 - ? results.flatMap((result) => result.errors ?? []) - : undefined, - }; -} - -async function generateOrmForTarget( - target: TargetConfig, - options: GenerateOrmOptions, - isMultiTarget: boolean -): Promise { - const config = target.config; - // Always use conventional subdirectory: {output}/orm - const outputDir = options.output || `${config.output}/orm`; - const prefix = isMultiTarget ? `[${target.name}] ` : ''; - const log = options.verbose - ? (message: string) => console.log(`${prefix}${message}`) - : () => {}; - const formatMessage = (message: string) => - isMultiTarget ? `Target "${target.name}": ${message}` : message; - - if (isMultiTarget) { - console.log(`\nTarget "${target.name}"`); - let sourceLabel: string; - if (config.db) { - const schemaInfo = config.db.apiNames && config.db.apiNames.length > 0 - ? `apiNames: ${config.db.apiNames.join(', ')}` - : `schemas: ${(config.db.schemas ?? ['public']).join(', ')}`; - if (config.db.pgpm?.modulePath) { - sourceLabel = `pgpm module: ${config.db.pgpm.modulePath} (${schemaInfo})`; - } else if (config.db.pgpm?.workspacePath && config.db.pgpm?.moduleName) { - sourceLabel = `pgpm workspace: ${config.db.pgpm.workspacePath}, module: ${config.db.pgpm.moduleName} (${schemaInfo})`; - } else { - sourceLabel = `database (${schemaInfo})`; - } - } else if (config.schemaFile) { - sourceLabel = `schemaFile: ${config.schemaFile}`; - } else { - sourceLabel = `endpoint: ${config.endpoint}`; - } - console.log(` Source: ${sourceLabel}`); - console.log(` Output: ${outputDir}`); - } - - // 1. Validate source - const sourceValidation = validateSourceOptions({ - endpoint: config.endpoint || undefined, - schemaFile: config.schemaFile || undefined, - db: config.db, - }); - if (!sourceValidation.valid) { - return { - name: target.name, - output: outputDir, - success: false, - message: formatMessage(sourceValidation.error!), - }; - } - - const source = createSchemaSource({ - endpoint: config.endpoint || undefined, - schemaFile: config.schemaFile || undefined, - db: config.db, - authorization: options.authorization || config.headers?.['Authorization'], - headers: config.headers, - }); - - // 2. Run the codegen pipeline - let pipelineResult; - try { - pipelineResult = await runCodegenPipeline({ - source, - config, - verbose: options.verbose, - skipCustomOperations: options.skipCustomOperations, - }); - } catch (err) { - return { - name: target.name, - output: outputDir, - success: false, - message: formatMessage( - `Failed to fetch schema: ${err instanceof Error ? err.message : 'Unknown error'}` - ), - }; - } - - const { tables, customOperations, stats } = pipelineResult; - - // 3. Validate tables found - const tablesValidation = validateTablesFound(tables); - if (!tablesValidation.valid) { - return { - name: target.name, - output: outputDir, - success: false, - message: formatMessage(tablesValidation.error!), - }; - } - - // 4. Generate ORM code - console.log(`${prefix}Generating code...`); - const { files: generatedFiles, stats: genStats } = generateOrmFiles({ - tables, - customOperations: { - queries: customOperations.queries, - mutations: customOperations.mutations, - typeRegistry: customOperations.typeRegistry, - }, - config, - }); - console.log(`${prefix}Generated ${genStats.totalFiles} files`); - - log(` ${genStats.tables} table models`); - log(` ${genStats.customQueries} custom query operations`); - log(` ${genStats.customMutations} custom mutation operations`); - - const customQueries = customOperations.queries.map((q) => q.name); - const customMutations = customOperations.mutations.map((m) => m.name); - - if (options.dryRun) { - return { - name: target.name, - output: outputDir, - success: true, - message: formatMessage( - `Dry run complete. Would generate ${generatedFiles.length} files for ${tables.length} tables and ${stats.customQueries + stats.customMutations} custom operations.` - ), - tables: tables.map((t) => t.name), - customQueries, - customMutations, - filesWritten: generatedFiles.map((f) => f.path), - }; - } - - // 5. Write files - log('Writing files...'); - const writeResult = await writeGeneratedFiles(generatedFiles, outputDir, [ - 'models', - 'query', - 'mutation', - ]); - - if (!writeResult.success) { - return { - name: target.name, - output: outputDir, - success: false, - message: formatMessage( - `Failed to write files: ${writeResult.errors?.join(', ')}` - ), - errors: writeResult.errors, - }; - } - - const totalOps = customQueries.length + customMutations.length; - const customOpsMsg = totalOps > 0 ? ` and ${totalOps} custom operations` : ''; - - return { - name: target.name, - output: outputDir, - success: true, - message: formatMessage( - `Generated ORM client for ${tables.length} tables${customOpsMsg}. Files written to ${outputDir}` - ), - tables: tables.map((t) => t.name), - customQueries, - customMutations, - filesWritten: writeResult.filesWritten, - }; -} diff --git a/graphql/codegen/src/cli/commands/generate-unified.ts b/graphql/codegen/src/cli/commands/generate-unified.ts deleted file mode 100644 index ad25b934e..000000000 --- a/graphql/codegen/src/cli/commands/generate-unified.ts +++ /dev/null @@ -1,645 +0,0 @@ -/** - * Unified generate command - generates SDK from GraphQL schema - * - * This module provides a single public generate() function that: - * 1. Runs introspection ONCE per target - * 2. Generates shared types ONCE (when both React Query and ORM are enabled) - * 3. Generates React Query SDK and/or ORM client based on config - * - * The internal generator functions are not exported from the package. - */ -import path from 'path'; -import * as t from '@babel/types'; -import { generateCode, addJSDocComment } from '../../core/codegen/babel-ast'; -import type { GraphQLSDKConfigTarget, TargetConfig } from '../../types/config'; -import { loadAndResolveConfig } from '../../core/config'; -import { - createSchemaSource, - validateSourceOptions, -} from '../../core/introspect'; -import { runCodegenPipeline, validateTablesFound } from '../../core/pipeline'; -import { generate as generateReactQueryFiles } from '../../core/codegen'; -import { generateOrm as generateOrmFiles } from '../../core/codegen/orm'; -import { generateSharedTypes } from '../../core/codegen/shared'; -import { writeGeneratedFiles } from '../../core/output'; -import type { CleanTable, CleanOperation, TypeRegistry } from '../../types/schema'; - -export type GeneratorType = 'react-query' | 'orm' | 'shared'; - -/** - * Options for the generate() function. - * Extends GraphQLSDKConfigTarget with CLI-specific fields. - */ -export interface GenerateOptions extends GraphQLSDKConfigTarget { - /** Path to config file (CLI-only) */ - config?: string; - /** Named target in a multi-target config (CLI-only) */ - target?: string; -} - -export interface GenerateTargetResult { - name: string; - output: string; - generatorType: GeneratorType; - success: boolean; - message: string; - tables?: string[]; - customQueries?: string[]; - customMutations?: string[]; - filesWritten?: string[]; - errors?: string[]; -} - -export interface GenerateResult { - success: boolean; - message: string; - targets?: GenerateTargetResult[]; - tables?: string[]; - customQueries?: string[]; - customMutations?: string[]; - filesWritten?: string[]; - errors?: string[]; -} - -interface PipelineResult { - tables: CleanTable[]; - customOperations: { - queries: CleanOperation[]; - mutations: CleanOperation[]; - typeRegistry: TypeRegistry; - }; - stats: { - customQueries: number; - customMutations: number; - }; -} - -/** - * Unified generate function that respects config.reactQuery and config.orm - * - * Can generate React Query SDK, ORM client, or both based on configuration. - * Options override config values when provided. - */ -export async function generate( - options: GenerateOptions = {} -): Promise { - if (options.verbose) { - console.log('Loading configuration...'); - } - - const configResult = await loadAndResolveConfig(options); - if (!configResult.success) { - return { - success: false, - message: configResult.error!, - }; - } - - const targets = configResult.targets ?? []; - if (targets.length === 0) { - return { - success: false, - message: 'No targets resolved from configuration.', - }; - } - - const isMultiTarget = configResult.isMulti ?? targets.length > 1; - const results: GenerateTargetResult[] = []; - - for (const target of targets) { - // Determine which generators to run based on options (which override config) - const runReactQuery = options.reactQuery ?? target.config.reactQuery; - const runOrm = options.orm ?? target.config.orm; - - if (!runReactQuery && !runOrm) { - results.push({ - name: target.name, - output: target.config.output, - generatorType: 'react-query', - success: false, - message: `Target "${target.name}": No generators enabled. Set reactQuery: true or orm: true in config, or use --react-query or --orm flags.`, - }); - continue; - } - - // Run pipeline once per target (shared between generators) - const pipelineResult = await runPipelineForTarget(target, options, isMultiTarget); - if (!pipelineResult.success) { - results.push({ - name: target.name, - output: target.config.output, - generatorType: 'react-query', - success: false, - message: pipelineResult.error!, - }); - continue; - } - - const bothEnabled = runReactQuery && runOrm; - - // When both are enabled, use unified output structure with shared types - if (bothEnabled) { - const unifiedResults = await generateUnifiedOutput( - target, - pipelineResult.data!, - options, - isMultiTarget - ); - results.push(...unifiedResults); - } else { - // Single generator mode - use existing behavior - if (runReactQuery) { - const result = await generateReactQueryForTarget( - target, - pipelineResult.data!, - options, - isMultiTarget, - undefined // no shared types path - ); - results.push(result); - } - - if (runOrm) { - const result = await generateOrmForTarget( - target, - pipelineResult.data!, - options, - isMultiTarget, - undefined // no shared types path - ); - results.push(result); - } - } - } - - // Build summary - const successCount = results.filter((r) => r.success).length; - const failedCount = results.length - successCount; - - if (results.length === 1) { - const [result] = results; - return { - success: result.success, - message: result.message, - targets: results, - tables: result.tables, - customQueries: result.customQueries, - customMutations: result.customMutations, - filesWritten: result.filesWritten, - errors: result.errors, - }; - } - - const summaryMessage = - failedCount === 0 - ? `Generated ${results.length} outputs successfully.` - : `Generated ${successCount} of ${results.length} outputs.`; - - return { - success: failedCount === 0, - message: summaryMessage, - targets: results, - errors: - failedCount > 0 - ? results.flatMap((r) => r.errors ?? []) - : undefined, - }; -} - -/** - * Generate React Query SDK only (convenience wrapper) - */ -export async function generateReactQuery( - options: GenerateOptions = {} -): Promise { - return generate({ ...options, reactQuery: true, orm: false }); -} - -/** - * Generate ORM client only (convenience wrapper) - */ -export async function generateOrm( - options: GenerateOptions = {} -): Promise { - return generate({ ...options, reactQuery: false, orm: true }); -} - -// ============================================================================ -// Internal helpers -// ============================================================================ - -interface PipelineRunResult { - success: boolean; - error?: string; - data?: PipelineResult; -} - -async function runPipelineForTarget( - target: TargetConfig, - options: GenerateOptions, - isMultiTarget: boolean -): Promise { - const config = target.config; - const prefix = isMultiTarget ? `[${target.name}] ` : ''; - const formatMessage = (message: string) => - isMultiTarget ? `Target "${target.name}": ${message}` : message; - - if (isMultiTarget) { - console.log(`\nTarget "${target.name}"`); - let sourceLabel: string; - if (config.db) { - const schemaInfo = config.db.apiNames && config.db.apiNames.length > 0 - ? `apiNames: ${config.db.apiNames.join(', ')}` - : `schemas: ${(config.db.schemas ?? ['public']).join(', ')}`; - if (config.db.pgpm?.modulePath) { - sourceLabel = `pgpm module: ${config.db.pgpm.modulePath} (${schemaInfo})`; - } else if (config.db.pgpm?.workspacePath && config.db.pgpm?.moduleName) { - sourceLabel = `pgpm workspace: ${config.db.pgpm.workspacePath}, module: ${config.db.pgpm.moduleName} (${schemaInfo})`; - } else { - sourceLabel = `database (${schemaInfo})`; - } - } else if (config.schemaFile) { - sourceLabel = `schemaFile: ${config.schemaFile}`; - } else { - sourceLabel = `endpoint: ${config.endpoint}`; - } - console.log(` Source: ${sourceLabel}`); - } - - // 1. Validate source - const sourceValidation = validateSourceOptions({ - endpoint: config.endpoint || undefined, - schemaFile: config.schemaFile || undefined, - db: config.db, - }); - if (!sourceValidation.valid) { - return { - success: false, - error: formatMessage(sourceValidation.error!), - }; - } - - const source = createSchemaSource({ - endpoint: config.endpoint || undefined, - schemaFile: config.schemaFile || undefined, - db: config.db, - authorization: options.authorization || config.headers?.['Authorization'], - headers: config.headers, - }); - - // 2. Run the codegen pipeline - let pipelineResult; - try { - console.log(`${prefix}Fetching schema...`); - pipelineResult = await runCodegenPipeline({ - source, - config, - verbose: options.verbose, - skipCustomOperations: options.skipCustomOperations, - }); - } catch (err) { - return { - success: false, - error: formatMessage( - `Failed to fetch schema: ${err instanceof Error ? err.message : 'Unknown error'}` - ), - }; - } - - const { tables, customOperations, stats } = pipelineResult; - - // 3. Validate tables found - const tablesValidation = validateTablesFound(tables); - if (!tablesValidation.valid) { - return { - success: false, - error: formatMessage(tablesValidation.error!), - }; - } - - return { - success: true, - data: { tables, customOperations, stats }, - }; -} - -/** - * Generate unified output when both React Query and ORM are enabled - * - * Output structure: - * {output}/ - * index.ts - Main barrel (re-exports shared + hooks + orm) - * types.ts - Shared entity types - * schema-types.ts - Shared schema types (enums, input types) - * hooks/ - React Query hooks - * orm/ - ORM client - */ -async function generateUnifiedOutput( - target: TargetConfig, - pipelineResult: PipelineResult, - options: GenerateOptions, - isMultiTarget: boolean -): Promise { - const config = target.config; - const outputRoot = config.output; - const prefix = isMultiTarget ? `[${target.name}] ` : ''; - const formatMessage = (message: string) => - isMultiTarget ? `Target "${target.name}": ${message}` : message; - - const results: GenerateTargetResult[] = []; - const { tables, customOperations } = pipelineResult; - - // 1. Generate shared types to output root - console.log(`${prefix}Generating shared types...`); - const sharedResult = generateSharedTypes({ - tables, - customOperations: { - queries: customOperations.queries, - mutations: customOperations.mutations, - typeRegistry: customOperations.typeRegistry, - }, - config, - }); - - if (!options.dryRun) { - const writeResult = await writeGeneratedFiles(sharedResult.files, outputRoot, []); - if (!writeResult.success) { - results.push({ - name: target.name, - output: outputRoot, - generatorType: 'shared', - success: false, - message: formatMessage(`Failed to write shared types: ${writeResult.errors?.join(', ')}`), - errors: writeResult.errors, - }); - return results; - } - console.log(`${prefix}Shared types written to ${outputRoot}`); - } - - // 2. Generate React Query SDK to react-query/ subdirectory - const reactQueryResult = await generateReactQueryForTarget( - target, - pipelineResult, - options, - isMultiTarget, - '..' // import types from parent directory - ); - results.push(reactQueryResult); - - // 3. Generate ORM client to orm/ subdirectory - const ormResult = await generateOrmForTarget( - target, - pipelineResult, - options, - isMultiTarget, - '..' // import types from parent directory - ); - results.push(ormResult); - - // 4. Generate unified barrel export - if (!options.dryRun) { - const unifiedBarrel = generateUnifiedBarrel(sharedResult.hasSchemaTypes); - await writeGeneratedFiles([{ path: 'index.ts', content: unifiedBarrel }], outputRoot, []); - } - - return results; -} - -/** - * Helper to create export * from './module' statement - */ -function exportAllFrom(modulePath: string): t.ExportAllDeclaration { - return t.exportAllDeclaration(t.stringLiteral(modulePath)); -} - -/** - * Generate the unified barrel export for the root output directory using Babel AST - */ -function generateUnifiedBarrel(hasSchemaTypes: boolean): string { - const statements: t.Statement[] = []; - - // Shared types - statements.push(exportAllFrom('./types')); - - if (hasSchemaTypes) { - statements.push(exportAllFrom('./schema-types')); - } - - // React Query hooks - statements.push(exportAllFrom('./hooks')); - - // ORM Client - statements.push(exportAllFrom('./orm')); - - // Add file header as leading comment on first statement - if (statements.length > 0) { - addJSDocComment(statements[0], [ - 'Generated SDK - auto-generated, do not edit', - '@generated by @constructive-io/graphql-codegen', - '', - 'Exports:', - '- Shared types (types.ts, schema-types.ts)', - '- React Query hooks (hooks/)', - '- ORM Client (orm/)', - ]); - } - - return generateCode(statements); -} - -async function generateReactQueryForTarget( - target: TargetConfig, - pipelineResult: PipelineResult, - options: GenerateOptions, - isMultiTarget: boolean, - sharedTypesPath?: string -): Promise { - const config = target.config; - // Always use conventional subdirectory: {output}/hooks - const outputDir = sharedTypesPath - ? path.join(config.output, 'hooks') - : path.join(options.output || config.output, 'hooks'); - const prefix = isMultiTarget ? `[${target.name}] ` : ''; - const log = options.verbose - ? (message: string) => console.log(`${prefix}${message}`) - : () => {}; - const formatMessage = (message: string) => - isMultiTarget ? `Target "${target.name}": ${message}` : message; - - const { tables, customOperations, stats } = pipelineResult; - - // Generate React Query SDK - console.log(`${prefix}Generating React Query SDK...`); - const { files: generatedFiles, stats: genStats } = generateReactQueryFiles({ - tables, - customOperations: { - queries: customOperations.queries, - mutations: customOperations.mutations, - typeRegistry: customOperations.typeRegistry, - }, - config, - sharedTypesPath, - }); - console.log(`${prefix}Generated ${genStats.totalFiles} files`); - - log(` ${genStats.queryHooks} table query hooks`); - log(` ${genStats.mutationHooks} table mutation hooks`); - log(` ${genStats.customQueryHooks} custom query hooks`); - log(` ${genStats.customMutationHooks} custom mutation hooks`); - - const customQueries = customOperations.queries.map((q) => q.name); - const customMutations = customOperations.mutations.map((m) => m.name); - - if (options.dryRun) { - return { - name: target.name, - output: outputDir, - generatorType: 'react-query', - success: true, - message: formatMessage( - `Dry run complete. Would generate ${generatedFiles.length} files for ${tables.length} tables and ${stats.customQueries + stats.customMutations} custom operations.` - ), - tables: tables.map((t) => t.name), - customQueries, - customMutations, - filesWritten: generatedFiles.map((f) => f.path), - }; - } - - // Write files - log('Writing files...'); - console.log(`${prefix}Output: ${outputDir}`); - const writeResult = await writeGeneratedFiles(generatedFiles, outputDir, [ - 'queries', - 'mutations', - ]); - - if (!writeResult.success) { - return { - name: target.name, - output: outputDir, - generatorType: 'react-query', - success: false, - message: formatMessage( - `Failed to write files: ${writeResult.errors?.join(', ')}` - ), - errors: writeResult.errors, - }; - } - - const totalOps = customQueries.length + customMutations.length; - const customOpsMsg = totalOps > 0 ? ` and ${totalOps} custom operations` : ''; - - return { - name: target.name, - output: outputDir, - generatorType: 'react-query', - success: true, - message: formatMessage( - `Generated React Query SDK for ${tables.length} tables${customOpsMsg}. Files written to ${outputDir}` - ), - tables: tables.map((t) => t.name), - customQueries, - customMutations, - filesWritten: writeResult.filesWritten, - }; -} - -async function generateOrmForTarget( - target: TargetConfig, - pipelineResult: PipelineResult, - options: GenerateOptions, - isMultiTarget: boolean, - sharedTypesPath?: string -): Promise { - const config = target.config; - // Always use conventional subdirectory: {output}/orm - const outputDir = sharedTypesPath - ? path.join(config.output, 'orm') - : path.join(options.output || config.output, 'orm'); - const prefix = isMultiTarget ? `[${target.name}] ` : ''; - const log = options.verbose - ? (message: string) => console.log(`${prefix}${message}`) - : () => {}; - const formatMessage = (message: string) => - isMultiTarget ? `Target "${target.name}": ${message}` : message; - - const { tables, customOperations, stats } = pipelineResult; - - // Generate ORM client - console.log(`${prefix}Generating ORM client...`); - const { files: generatedFiles, stats: genStats } = generateOrmFiles({ - tables, - customOperations: { - queries: customOperations.queries, - mutations: customOperations.mutations, - typeRegistry: customOperations.typeRegistry, - }, - config, - sharedTypesPath, - }); - console.log(`${prefix}Generated ${genStats.totalFiles} files`); - - log(` ${genStats.tables} table models`); - log(` ${genStats.customQueries} custom query operations`); - log(` ${genStats.customMutations} custom mutation operations`); - - const customQueries = customOperations.queries.map((q) => q.name); - const customMutations = customOperations.mutations.map((m) => m.name); - - if (options.dryRun) { - return { - name: target.name, - output: outputDir, - generatorType: 'orm', - success: true, - message: formatMessage( - `Dry run complete. Would generate ${generatedFiles.length} files for ${tables.length} tables and ${stats.customQueries + stats.customMutations} custom operations.` - ), - tables: tables.map((t) => t.name), - customQueries, - customMutations, - filesWritten: generatedFiles.map((f) => f.path), - }; - } - - // Write files - log('Writing files...'); - console.log(`${prefix}Output: ${outputDir}`); - const writeResult = await writeGeneratedFiles(generatedFiles, outputDir, [ - 'models', - 'query', - 'mutation', - ]); - - if (!writeResult.success) { - return { - name: target.name, - output: outputDir, - generatorType: 'orm', - success: false, - message: formatMessage( - `Failed to write files: ${writeResult.errors?.join(', ')}` - ), - errors: writeResult.errors, - }; - } - - const totalOps = customQueries.length + customMutations.length; - const customOpsMsg = totalOps > 0 ? ` and ${totalOps} custom operations` : ''; - - return { - name: target.name, - output: outputDir, - generatorType: 'orm', - success: true, - message: formatMessage( - `Generated ORM client for ${tables.length} tables${customOpsMsg}. Files written to ${outputDir}` - ), - tables: tables.map((t) => t.name), - customQueries, - customMutations, - filesWritten: writeResult.filesWritten, - }; -} diff --git a/graphql/codegen/src/cli/commands/generate.ts b/graphql/codegen/src/cli/commands/generate.ts deleted file mode 100644 index 8675bbe0d..000000000 --- a/graphql/codegen/src/cli/commands/generate.ts +++ /dev/null @@ -1,282 +0,0 @@ -/** - * Generate command - generates SDK from GraphQL schema - * - * This is a thin CLI wrapper around the core generation functions. - * All business logic is in the core modules. - */ -import type { TargetConfig } from '../../types/config'; -import { - loadAndResolveConfig, - type ConfigOverrideOptions, -} from '../../core/config'; -import { - createSchemaSource, - validateSourceOptions, -} from '../../core/introspect'; -import { runCodegenPipeline, validateTablesFound } from '../../core/pipeline'; -import { generate } from '../../core/codegen'; -import { writeGeneratedFiles } from '../../core/output'; - -export interface GenerateOptions extends ConfigOverrideOptions { - /** Authorization header */ - authorization?: string; - /** Verbose output */ - verbose?: boolean; - /** Dry run - don't write files */ - dryRun?: boolean; - /** Skip custom operations (only generate table CRUD) */ - skipCustomOperations?: boolean; -} - -export interface GenerateTargetResult { - name: string; - output: string; - success: boolean; - message: string; - tables?: string[]; - customQueries?: string[]; - customMutations?: string[]; - filesWritten?: string[]; - errors?: string[]; -} - -export interface GenerateResult { - success: boolean; - message: string; - targets?: GenerateTargetResult[]; - tables?: string[]; - customQueries?: string[]; - customMutations?: string[]; - filesWritten?: string[]; - errors?: string[]; -} - -/** - * Execute the generate command (generates React Query SDK) - */ -export async function generateReactQuery( - options: GenerateOptions = {} -): Promise { - if (options.verbose) { - console.log('Loading configuration...'); - } - - const configResult = await loadAndResolveConfig(options); - if (!configResult.success) { - return { - success: false, - message: configResult.error!, - }; - } - - const targets = configResult.targets ?? []; - if (targets.length === 0) { - return { - success: false, - message: 'No targets resolved from configuration.', - }; - } - - const isMultiTarget = configResult.isMulti ?? targets.length > 1; - const results: GenerateTargetResult[] = []; - - for (const target of targets) { - const result = await generateForTarget(target, options, isMultiTarget); - results.push(result); - } - - if (!isMultiTarget) { - const [result] = results; - return { - success: result.success, - message: result.message, - targets: results, - tables: result.tables, - customQueries: result.customQueries, - customMutations: result.customMutations, - filesWritten: result.filesWritten, - errors: result.errors, - }; - } - - const successCount = results.filter((result) => result.success).length; - const failedCount = results.length - successCount; - const summaryMessage = - failedCount === 0 - ? `Generated SDK for ${results.length} targets.` - : `Generated SDK for ${successCount} of ${results.length} targets.`; - - return { - success: failedCount === 0, - message: summaryMessage, - targets: results, - errors: - failedCount > 0 - ? results.flatMap((result) => result.errors ?? []) - : undefined, - }; -} - -async function generateForTarget( - target: TargetConfig, - options: GenerateOptions, - isMultiTarget: boolean -): Promise { - const config = target.config; - const prefix = isMultiTarget ? `[${target.name}] ` : ''; - const log = options.verbose - ? (message: string) => console.log(`${prefix}${message}`) - : () => {}; - const formatMessage = (message: string) => - isMultiTarget ? `Target "${target.name}": ${message}` : message; - - if (isMultiTarget) { - console.log(`\nTarget "${target.name}"`); - let sourceLabel: string; - if (config.db) { - const schemaInfo = config.db.apiNames && config.db.apiNames.length > 0 - ? `apiNames: ${config.db.apiNames.join(', ')}` - : `schemas: ${(config.db.schemas ?? ['public']).join(', ')}`; - if (config.db.pgpm?.modulePath) { - sourceLabel = `pgpm module: ${config.db.pgpm.modulePath} (${schemaInfo})`; - } else if (config.db.pgpm?.workspacePath && config.db.pgpm?.moduleName) { - sourceLabel = `pgpm workspace: ${config.db.pgpm.workspacePath}, module: ${config.db.pgpm.moduleName} (${schemaInfo})`; - } else { - sourceLabel = `database (${schemaInfo})`; - } - } else if (config.schemaFile) { - sourceLabel = `schemaFile: ${config.schemaFile}`; - } else { - sourceLabel = `endpoint: ${config.endpoint}`; - } - console.log(` Source: ${sourceLabel}`); - console.log(` Output: ${config.output}`); - } - - // 1. Validate source - const sourceValidation = validateSourceOptions({ - endpoint: config.endpoint || undefined, - schemaFile: config.schemaFile || undefined, - db: config.db, - }); - if (!sourceValidation.valid) { - return { - name: target.name, - output: config.output, - success: false, - message: formatMessage(sourceValidation.error!), - }; - } - - const source = createSchemaSource({ - endpoint: config.endpoint || undefined, - schemaFile: config.schemaFile || undefined, - db: config.db, - authorization: options.authorization || config.headers?.['Authorization'], - headers: config.headers, - }); - - // 2. Run the codegen pipeline - let pipelineResult; - try { - pipelineResult = await runCodegenPipeline({ - source, - config, - verbose: options.verbose, - skipCustomOperations: options.skipCustomOperations, - }); - } catch (err) { - return { - name: target.name, - output: config.output, - success: false, - message: formatMessage( - `Failed to fetch schema: ${err instanceof Error ? err.message : 'Unknown error'}` - ), - }; - } - - const { tables, customOperations, stats } = pipelineResult; - - // 3. Validate tables found - const tablesValidation = validateTablesFound(tables); - if (!tablesValidation.valid) { - return { - name: target.name, - output: config.output, - success: false, - message: formatMessage(tablesValidation.error!), - }; - } - - // 4. Generate code - console.log(`${prefix}Generating code...`); - const { files: generatedFiles, stats: genStats } = generate({ - tables, - customOperations: { - queries: customOperations.queries, - mutations: customOperations.mutations, - typeRegistry: customOperations.typeRegistry, - }, - config, - }); - console.log(`${prefix}Generated ${genStats.totalFiles} files`); - - log(` ${genStats.queryHooks} table query hooks`); - log(` ${genStats.mutationHooks} table mutation hooks`); - log(` ${genStats.customQueryHooks} custom query hooks`); - log(` ${genStats.customMutationHooks} custom mutation hooks`); - - const customQueries = customOperations.queries.map((q) => q.name); - const customMutations = customOperations.mutations.map((m) => m.name); - - if (options.dryRun) { - return { - name: target.name, - output: config.output, - success: true, - message: formatMessage( - `Dry run complete. Would generate ${generatedFiles.length} files for ${tables.length} tables and ${stats.customQueries + stats.customMutations} custom operations.` - ), - tables: tables.map((t) => t.name), - customQueries, - customMutations, - filesWritten: generatedFiles.map((f) => f.path), - }; - } - - // 5. Write files - log('Writing files...'); - const writeResult = await writeGeneratedFiles(generatedFiles, config.output, [ - 'queries', - 'mutations', - ]); - - if (!writeResult.success) { - return { - name: target.name, - output: config.output, - success: false, - message: formatMessage( - `Failed to write files: ${writeResult.errors?.join(', ')}` - ), - errors: writeResult.errors, - }; - } - - const totalOps = customQueries.length + customMutations.length; - const customOpsMsg = totalOps > 0 ? ` and ${totalOps} custom operations` : ''; - - return { - name: target.name, - output: config.output, - success: true, - message: formatMessage( - `Generated SDK for ${tables.length} tables${customOpsMsg}. Files written to ${config.output}` - ), - tables: tables.map((t) => t.name), - customQueries, - customMutations, - filesWritten: writeResult.filesWritten, - }; -} diff --git a/graphql/codegen/src/cli/commands/index.ts b/graphql/codegen/src/cli/commands/index.ts deleted file mode 100644 index 770b650f2..000000000 --- a/graphql/codegen/src/cli/commands/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * CLI commands exports - */ - -export { initCommand, findConfigFile, loadConfigFile } from './init'; -export type { InitOptions, InitResult } from './init'; - -export { generate, generateReactQuery, generateOrm } from './generate-unified'; -export type { GenerateOptions, GenerateResult, GenerateTargetResult } from './generate-unified'; diff --git a/graphql/codegen/src/cli/commands/init.ts b/graphql/codegen/src/cli/commands/init.ts deleted file mode 100644 index eb61048de..000000000 --- a/graphql/codegen/src/cli/commands/init.ts +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Init command - creates a new graphql-codegen configuration file - * - * This is a thin CLI wrapper. Config loading utilities are in core/config. - */ -import * as fs from 'node:fs'; -import * as path from 'node:path'; - -import { - CONFIG_FILENAME, - findConfigFile, - loadConfigFile, -} from '../../core/config'; - -export { CONFIG_FILENAME, findConfigFile, loadConfigFile }; - -export interface InitOptions { - /** Target directory for the config file */ - directory?: string; - /** Force overwrite existing config */ - force?: boolean; - /** GraphQL endpoint URL to pre-populate */ - endpoint?: string; - /** Output directory to pre-populate */ - output?: string; -} - -const CONFIG_TEMPLATE= `import { defineConfig } from '@constructive-io/graphql-codegen'; - -export default defineConfig({ - // GraphQL endpoint URL (PostGraphile with _meta plugin) - endpoint: '{{ENDPOINT}}', - - // Output directory for generated files - output: '{{OUTPUT}}', - - // Optional: Multi-target config (use instead of endpoint/output) - // defaults: { - // headers: { Authorization: 'Bearer YOUR_TOKEN' }, - // }, - // targets: { - // public: { endpoint: 'https://api.example.com/graphql', output: './generated/public' }, - // admin: { schema: './admin.schema.graphql', output: './generated/admin' }, - // }, - - // Optional: Tables to include/exclude (supports glob patterns) - // tables: { - // include: ['*'], - // exclude: ['_*', 'pg_*'], - // }, - - // Optional: Authorization header for authenticated endpoints - // headers: { - // Authorization: 'Bearer YOUR_TOKEN', - // }, - - // Optional: Watch mode settings (in-memory caching, no file I/O) - // watch: { - // pollInterval: 3000, // ms - // debounce: 800, // ms - // clearScreen: true, - // touchFile: '.trigger', // Optional: file to touch on change - // }, -}); -`; - -export interface InitResult { - success: boolean; - message: string; - configPath?: string; -} - -/** - * Execute the init command - */ -export async function initCommand( - options: InitOptions = {} -): Promise { - const { - directory = process.cwd(), - force = false, - endpoint = '', - output = './generated', - } = options; - - const configPath = path.join(directory, CONFIG_FILENAME); - - // Check if config already exists - if (fs.existsSync(configPath) && !force) { - return { - success: false, - message: `Configuration file already exists: ${configPath}\nUse --force to overwrite.`, - }; - } - - // Generate config content - const content = CONFIG_TEMPLATE.replace( - '{{ENDPOINT}}', - endpoint || 'http://localhost:5000/graphql' - ).replace('{{OUTPUT}}', output); - - try { - // Ensure directory exists - fs.mkdirSync(directory, { recursive: true }); - - // Write config file - fs.writeFileSync(configPath, content, 'utf-8'); - - return { - success: true, - message: `Created configuration file: ${configPath}`, - configPath, - }; - } catch (err) { - const message = err instanceof Error ? err.message : 'Unknown error'; - return { - success: false, - message: `Failed to create configuration file: ${message}`, - }; - } -} diff --git a/graphql/codegen/src/cli/index.ts b/graphql/codegen/src/cli/index.ts index 210c36667..ae5d67071 100644 --- a/graphql/codegen/src/cli/index.ts +++ b/graphql/codegen/src/cli/index.ts @@ -1,529 +1,483 @@ #!/usr/bin/env node /** * CLI entry point for graphql-codegen + * + * This is a thin wrapper around the core generate() function. + * All business logic is in the core modules. */ - -import { CLI, CLIOptions, Inquirerer, ParsedArgs, cliExitWithError, extractFirst, getPackageJson } from 'inquirerer'; - -import { initCommand } from './commands/init'; -import { generate, generateReactQuery, generateOrm } from './commands/generate-unified'; -import { loadWatchConfig } from '../core/config'; -import { startWatch } from '../core/watch'; -import { createSchemaSource, inferTablesFromIntrospection } from '../core/introspect'; -import type { GraphQLSDKConfigTarget } from '../types/config'; - -const usageText = ` +import path from 'path'; +import { CLI, CLIOptions, Inquirerer, Question, getPackageJson } from 'inquirerer'; + +import { loadAndResolveConfig, findConfigFile } from '../core/config'; +import { createSchemaSource, validateSourceOptions, inferTablesFromIntrospection } from '../core/introspect'; +import { runCodegenPipeline, validateTablesFound } from '../core/pipeline'; +import { generate as generateReactQueryFiles } from '../core/codegen'; +import { generateOrm as generateOrmFiles } from '../core/codegen/orm'; +import { generateSharedTypes } from '../core/codegen/shared'; +import { writeGeneratedFiles } from '../core/output'; +import type { GraphQLSDKConfigTarget, TargetConfig } from '../types/config'; + +const usage = ` graphql-codegen - GraphQL SDK generator for Constructive databases Usage: - graphql-codegen [options] - -Commands: - init Initialize a new graphql-codegen configuration file - generate Generate SDK from GraphQL endpoint, schema file, database, or PGPM module - introspect Introspect a GraphQL endpoint or schema file and print table info - -Options: - --help, -h Show this help message - --version, -v Show version number - -Run 'graphql-codegen --help' for more information on a command. -`; - -const initUsageText = ` -graphql-codegen init - Initialize a new graphql-codegen configuration file - -Usage: - graphql-codegen init [options] - -Options: - --directory, -d Target directory for the config file (default: .) - --force, -f Force overwrite existing config - --endpoint, -e GraphQL endpoint URL to pre-populate - --output, -o Output directory to pre-populate (default: ./generated) - --help, -h Show this help message -`; - -const generateUsageText = ` -graphql-codegen generate - Generate SDK from GraphQL endpoint, schema file, database, or PGPM module - -Usage: - graphql-codegen generate [options] + graphql-codegen [options] Source Options (choose one): - --config, -c Path to config file - --endpoint, -e GraphQL endpoint URL - --schema-file, -s Path to GraphQL schema file (.graphql) - --pgpm-module-path Path to PGPM module (creates ephemeral database) - --pgpm-workspace-path Path to PGPM workspace (use with --pgpm-module-name) - --pgpm-module-name Module name in workspace (use with --pgpm-workspace-path) + -c, --config Path to config file + -e, --endpoint GraphQL endpoint URL + -s, --schema-file Path to GraphQL schema file + --pgpm-module-path Path to PGPM module directory + --pgpm-workspace-path Path to PGPM workspace (requires --pgpm-module-name) + --pgpm-module-name PGPM module name in workspace -Database Options (for database/PGPM modes): - --schemas Comma-separated list of PostgreSQL schemas to introspect - --api-names Comma-separated list of API names (auto-resolves schemas from services_public.api_schemas) +Database Options: + --schemas Comma-separated PostgreSQL schemas + --api-names Comma-separated API names (mutually exclusive with --schemas) Generator Options: - --react-query Generate React Query SDK (hooks + fetch functions) - --orm Generate Prisma-like ORM client - --target, -t Target name in config file - --output, -o Output directory (overrides config) - --authorization, -a
Authorization header value - --verbose Verbose output - --dry-run Dry run - show what would be generated without writing files - --skip-custom-operations Skip custom operations (only generate table CRUD) - --keep-db Keep ephemeral database after generation (for debugging) - -Watch Mode Options: - --watch, -w Watch mode - poll endpoint for schema changes - --poll-interval Polling interval in milliseconds (default: 3000) - --debounce Debounce delay before regenerating (default: 800) - --touch File to touch on schema change - --no-clear Do not clear terminal on regeneration - - --help, -h Show this help message - -Examples: - graphql-codegen generate --endpoint http://localhost:5000/graphql --react-query - graphql-codegen generate --pgpm-module-path ./my-module --schemas public --orm - graphql-codegen generate --pgpm-module-path ./my-module --api-names my_api --react-query --orm - graphql-codegen generate --config ./graphql-codegen.config.ts + --react-query Generate React Query hooks + --orm Generate ORM client + -o, --output Output directory + -t, --target Target name in config file + -a, --authorization Authorization header value + --keep-db Keep ephemeral database after generation + --dry-run Preview without writing files + -v, --verbose Show detailed output + + -h, --help Show this help message + --version Show version number `; -const introspectUsageText = ` -graphql-codegen introspect - Introspect a GraphQL endpoint or schema file and print table info - -Usage: - graphql-codegen introspect [options] - -Options: - --endpoint, -e GraphQL endpoint URL - --schema-file, -s Path to GraphQL schema file (.graphql) - --authorization, -a
Authorization header value - --json Output as JSON - --help, -h Show this help message -`; +const questions: Question[] = [ + { + name: 'endpoint', + message: 'GraphQL endpoint URL', + type: 'text', + required: false, + }, + { + name: 'output', + message: 'Output directory', + type: 'text', + required: false, + default: './generated', + useDefault: true, + }, + { + name: 'reactQuery', + 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, + }, +]; + +export interface GenerateOptions extends GraphQLSDKConfigTarget { + config?: string; + target?: string; + authorization?: string; + verbose?: boolean; + dryRun?: boolean; + skipCustomOperations?: boolean; +} -/** - * Format duration in a human-readable way - * - Under 1 second: show milliseconds (e.g., "123ms") - * - Over 1 second: show seconds with 2 decimal places (e.g., "1.23s") - */ -function formatDuration(ms: number): string { - if (ms < 1000) { - return `${Math.round(ms)}ms`; - } - return `${(ms / 1000).toFixed(2)}s`; +export interface GenerateTargetResult { + name: string; + output: string; + success: boolean; + message: string; + tables?: string[]; + filesWritten?: string[]; + errors?: string[]; } +export interface GenerateResult { + success: boolean; + message: string; + targets?: GenerateTargetResult[]; + tables?: string[]; + filesWritten?: string[]; + errors?: string[]; +} /** - * Init command handler + * Main generate function - orchestrates the entire codegen pipeline */ -async function handleInit(argv: Partial): Promise { - if (argv.help || argv.h) { - console.log(initUsageText); - process.exit(0); +export async function generate(options: GenerateOptions = {}): Promise { + if (options.verbose) { + console.log('Loading configuration...'); } - const startTime = performance.now(); - const result = await initCommand({ - directory: (argv.directory as string) || (argv.d as string) || '.', - force: !!(argv.force || argv.f), - endpoint: (argv.endpoint as string) || (argv.e as string), - output: (argv.output as string) || (argv.o as string) || './generated', - }); - const duration = formatDuration(performance.now() - startTime); - - if (result.success) { - console.log('[ok]', result.message, `(${duration})`); - } else { - console.error('x', result.message, `(${duration})`); - process.exit(1); + const configResult = await loadAndResolveConfig(options); + if (!configResult.success) { + return { success: false, message: configResult.error! }; } -} -/** - * Generate command handler - unified handler for React Query SDK and ORM generation - */ -async function handleGenerate(argv: Partial): Promise { - if (argv.help || argv.h) { - console.log(generateUsageText); - process.exit(0); + const targets = configResult.targets ?? []; + if (targets.length === 0) { + return { success: false, message: 'No targets resolved from configuration.' }; } - const startTime = performance.now(); + const results: GenerateTargetResult[] = []; - // Source options - const config = (argv.config as string) || (argv.c as string); - const target = (argv.target as string) || (argv.t as string); - const endpoint = (argv.endpoint as string) || (argv.e as string); - const schemaFile = (argv['schema-file'] as string) || (argv.s as string); - 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; + for (const target of targets) { + const runReactQuery = options.reactQuery ?? target.config.reactQuery; + const runOrm = options.orm ?? target.config.orm; - // Database options - const schemasArg = argv.schemas as string | undefined; - const schemas = schemasArg ? schemasArg.split(',').map((s) => s.trim()) : undefined; - const apiNamesArg = argv['api-names'] as string | undefined; - const apiNames = apiNamesArg ? apiNamesArg.split(',').map((s) => s.trim()) : undefined; - const keepDb = !!(argv['keep-db'] || argv.keepDb); - - // Generator options - const reactQuery = !!argv['react-query']; - const orm = !!argv.orm; - const output = (argv.output as string) || (argv.o as string); - const authorization = (argv.authorization as string) || (argv.a as string); - const verbose = !!argv.verbose; - const dryRun = !!(argv['dry-run'] || argv.dryRun); - const skipCustomOperations = !!(argv['skip-custom-operations'] || argv.skipCustomOperations); - - // Watch options - const watch = !!(argv.watch || argv.w); - const pollInterval = argv['poll-interval'] !== undefined - ? parseInt(argv['poll-interval'] as string, 10) - : undefined; - const debounce = argv.debounce !== undefined - ? parseInt(argv.debounce as string, 10) - : undefined; - const touch = argv.touch as string | undefined; - const clear = argv.clear !== false; - - // Validate source options - const sourceCount = [endpoint, schemaFile, pgpmModulePath, pgpmWorkspacePath].filter(Boolean).length; - if (sourceCount > 1 && !pgpmWorkspacePath) { - console.error('x Cannot use multiple source options. Choose one: --endpoint, --schema-file, or --pgpm-module-path'); - process.exit(1); - } + if (!runReactQuery && !runOrm) { + results.push({ + name: target.name, + output: target.config.output, + success: false, + message: `Target "${target.name}": No generators enabled. Use --react-query or --orm.`, + }); + continue; + } - // Validate pgpm workspace options - if (pgpmWorkspacePath && !pgpmModuleName) { - console.error('x --pgpm-workspace-path requires --pgpm-module-name'); - process.exit(1); + const result = await generateForTarget(target, options, runReactQuery, runOrm); + results.push(result); } - if (pgpmModuleName && !pgpmWorkspacePath) { - console.error('x --pgpm-module-name requires --pgpm-workspace-path'); - process.exit(1); + + if (results.length === 1) { + const [result] = results; + return { + success: result.success, + message: result.message, + targets: results, + tables: result.tables, + filesWritten: result.filesWritten, + errors: result.errors, + }; } - // Validate database options - if (schemas && apiNames) { - console.error('x Cannot use both --schemas and --api-names. Choose one.'); - process.exit(1); + const successCount = results.filter((r) => r.success).length; + const failedCount = results.length - successCount; + + return { + success: failedCount === 0, + message: failedCount === 0 + ? `Generated ${results.length} outputs successfully.` + : `Generated ${successCount} of ${results.length} outputs.`, + targets: results, + errors: failedCount > 0 ? results.flatMap((r) => r.errors ?? []) : undefined, + }; +} + +async function generateForTarget( + target: TargetConfig, + options: GenerateOptions, + runReactQuery: boolean, + runOrm: boolean +): Promise { + const config = target.config; + const outputRoot = config.output; + + // Validate source + const sourceValidation = validateSourceOptions({ + endpoint: config.endpoint || undefined, + schemaFile: config.schemaFile || undefined, + db: config.db, + }); + if (!sourceValidation.valid) { + return { + name: target.name, + output: outputRoot, + success: false, + message: sourceValidation.error!, + }; } - // Watch mode - if (watch) { - if (schemaFile || pgpmModulePath || pgpmWorkspacePath) { - console.error('x Watch mode is only supported with --endpoint or --config.'); - process.exit(1); - } - const watchConfig = await loadWatchConfig({ - config, - target, - endpoint, - output, - pollInterval, - debounce, - touch, - clear, - }); - if (!watchConfig) { - process.exit(1); - } + const source = createSchemaSource({ + endpoint: config.endpoint || undefined, + schemaFile: config.schemaFile || undefined, + db: config.db, + authorization: options.authorization || config.headers?.['Authorization'], + headers: config.headers, + }); - const generatorType = orm ? 'orm' : 'react-query'; - await startWatch({ - config: watchConfig, - generatorType, - verbose, - authorization, - configPath: config, - target, - outputDir: output, - skipCustomOperations, - generateReactQuery, - generateOrm, + // Run pipeline + let pipelineResult; + try { + console.log(`Fetching schema from ${source.describe()}...`); + pipelineResult = await runCodegenPipeline({ + source, + config, + verbose: options.verbose, + skipCustomOperations: options.skipCustomOperations, }); - return; + } catch (err) { + return { + name: target.name, + output: outputRoot, + success: false, + message: `Failed to fetch schema: ${err instanceof Error ? err.message : 'Unknown error'}`, + }; } - // Build db config if pgpm options are provided - const db = (pgpmModulePath || pgpmWorkspacePath) ? { - pgpm: { - modulePath: pgpmModulePath, - workspacePath: pgpmWorkspacePath, - moduleName: pgpmModuleName, - }, - schemas, - apiNames, - keepDb, - } : undefined; - - // Run generation - const result = await generate({ - config, - target, - endpoint, - schemaFile, - db, - output, - authorization, - verbose, - dryRun, - skipCustomOperations, - reactQuery, - orm, - }); - const duration = formatDuration(performance.now() - startTime); + const { tables, customOperations } = pipelineResult; + + // Validate tables + const tablesValidation = validateTablesFound(tables); + if (!tablesValidation.valid) { + return { + name: target.name, + output: outputRoot, + success: false, + message: tablesValidation.error!, + }; + } - // Print results - printGenerateResults(result, duration); -} + const allFilesWritten: string[] = []; + const bothEnabled = runReactQuery && runOrm; + + // Generate shared types when both are enabled + if (bothEnabled) { + console.log('Generating shared types...'); + const sharedResult = generateSharedTypes({ + tables, + customOperations: { + queries: customOperations.queries, + mutations: customOperations.mutations, + typeRegistry: customOperations.typeRegistry, + }, + config, + }); -/** - * Print generate results in a consistent format - */ -function printGenerateResults(result: Awaited>, duration: string): void { - const targetResults = result.targets ?? []; - const hasNamedTargets = - targetResults.length > 0 && - (targetResults.length > 1 || targetResults[0]?.name !== 'default'); - - if (hasNamedTargets) { - console.log(result.success ? '[ok]' : 'x', result.message, `(${duration})`); - targetResults.forEach((t) => { - const status = t.success ? '[ok]' : 'x'; - console.log(`\n${status} ${t.message}`); - - if (t.tables && t.tables.length > 0) { - console.log(' Tables:'); - t.tables.forEach((table) => console.log(` - ${table}`)); - } - if (t.customQueries && t.customQueries.length > 0) { - console.log(' Custom Queries:'); - t.customQueries.forEach((query) => console.log(` - ${query}`)); - } - if (t.customMutations && t.customMutations.length > 0) { - console.log(' Custom Mutations:'); - t.customMutations.forEach((mutation) => console.log(` - ${mutation}`)); - } - if (t.filesWritten && t.filesWritten.length > 0) { - console.log(' Files written:'); - t.filesWritten.forEach((file) => console.log(` - ${file}`)); - } - if (!t.success && t.errors) { - t.errors.forEach((error) => console.error(` - ${error}`)); + if (!options.dryRun) { + const writeResult = await writeGeneratedFiles(sharedResult.files, outputRoot, []); + if (!writeResult.success) { + return { + name: target.name, + output: outputRoot, + success: false, + message: `Failed to write shared types: ${writeResult.errors?.join(', ')}`, + errors: writeResult.errors, + }; } + allFilesWritten.push(...(writeResult.filesWritten ?? [])); + } + } + + // Generate React Query hooks + if (runReactQuery) { + const hooksDir = bothEnabled ? path.join(outputRoot, 'hooks') : path.join(outputRoot, 'hooks'); + console.log('Generating React Query hooks...'); + const { files } = generateReactQueryFiles({ + tables, + customOperations: { + queries: customOperations.queries, + mutations: customOperations.mutations, + typeRegistry: customOperations.typeRegistry, + }, + config, + sharedTypesPath: bothEnabled ? '..' : undefined, }); - if (!result.success) { - process.exit(1); + if (!options.dryRun) { + const writeResult = await writeGeneratedFiles(files, hooksDir, ['queries', 'mutations']); + if (!writeResult.success) { + return { + name: target.name, + output: outputRoot, + success: false, + message: `Failed to write React Query hooks: ${writeResult.errors?.join(', ')}`, + errors: writeResult.errors, + }; + } + allFilesWritten.push(...(writeResult.filesWritten ?? [])); } - return; } - if (result.success) { - console.log('[ok]', result.message, `(${duration})`); - if (result.tables && result.tables.length > 0) { - console.log('\nTables:'); - result.tables.forEach((t) => console.log(` - ${t}`)); - } - if (result.customQueries && result.customQueries.length > 0) { - console.log('\nCustom Queries:'); - result.customQueries.forEach((q) => console.log(` - ${q}`)); - } - if (result.customMutations && result.customMutations.length > 0) { - console.log('\nCustom Mutations:'); - result.customMutations.forEach((m) => console.log(` - ${m}`)); - } - if (result.filesWritten && result.filesWritten.length > 0) { - console.log('\nFiles written:'); - result.filesWritten.forEach((f) => console.log(` - ${f}`)); - } - } else { - console.error('x', result.message, `(${duration})`); - if (result.errors) { - result.errors.forEach((e) => console.error(' -', e)); + // Generate ORM client + if (runOrm) { + const ormDir = bothEnabled ? path.join(outputRoot, 'orm') : path.join(outputRoot, 'orm'); + console.log('Generating ORM client...'); + const { files } = generateOrmFiles({ + tables, + customOperations: { + queries: customOperations.queries, + mutations: customOperations.mutations, + typeRegistry: customOperations.typeRegistry, + }, + config, + sharedTypesPath: bothEnabled ? '..' : undefined, + }); + + if (!options.dryRun) { + const writeResult = await writeGeneratedFiles(files, ormDir, ['models', 'query', 'mutation']); + if (!writeResult.success) { + return { + name: target.name, + output: outputRoot, + success: false, + message: `Failed to write ORM client: ${writeResult.errors?.join(', ')}`, + errors: writeResult.errors, + }; + } + allFilesWritten.push(...(writeResult.filesWritten ?? [])); } - process.exit(1); } -} -/** - * Introspect command handler + // Generate unified barrel when both are enabled + if (bothEnabled && !options.dryRun) { + const barrelContent = `/** + * Generated SDK - auto-generated, do not edit + * @generated by @constructive-io/graphql-codegen */ -async function handleIntrospect(argv: Partial): Promise { - if (argv.help || argv.h) { - console.log(introspectUsageText); - process.exit(0); +export * from './types'; +export * from './hooks'; +export * from './orm'; +`; + await writeGeneratedFiles([{ path: 'index.ts', content: barrelContent }], outputRoot, []); } - const startTime = performance.now(); - - const endpoint = (argv.endpoint as string) || (argv.e as string); - const schemaFile = (argv['schema-file'] as string) || (argv.s as string); - const authorization = (argv.authorization as string) || (argv.a as string); - const json = !!argv.json; + const generators = [runReactQuery && 'React Query', runOrm && 'ORM'].filter(Boolean).join(' and '); - if (!endpoint && !schemaFile) { - console.error('x Either --endpoint or --schema-file must be provided.'); - process.exit(1); - } - if (endpoint && schemaFile) { - console.error( - 'x Cannot use both --endpoint and --schema-file. Choose one source.' - ); - process.exit(1); - } + return { + name: target.name, + output: outputRoot, + success: true, + message: options.dryRun + ? `Dry run complete. Would generate ${generators} for ${tables.length} tables.` + : `Generated ${generators} for ${tables.length} tables. Files written to ${outputRoot}`, + tables: tables.map((t) => t.name), + filesWritten: allFilesWritten, + }; +} - try { - const source = createSchemaSource({ - endpoint, - schemaFile, - authorization, - }); +function printResult(result: GenerateResult): void { + const targets = result.targets ?? []; + const isMultiTarget = targets.length > 1 || (targets.length === 1 && targets[0]?.name !== 'default'); - console.log('Fetching schema from', source.describe(), '...'); - - const { introspection } = await source.fetch(); - const tables = inferTablesFromIntrospection(introspection); - const duration = formatDuration(performance.now() - startTime); - - if (json) { - console.log(JSON.stringify(tables, null, 2)); - } else { - console.log(`\n[ok] Found ${tables.length} tables (${duration}):\n`); - tables.forEach((table) => { - const fieldCount = table.fields.length; - const relationCount = - table.relations.belongsTo.length + - table.relations.hasOne.length + - table.relations.hasMany.length + - table.relations.manyToMany.length; - console.log( - ` ${table.name} (${fieldCount} fields, ${relationCount} relations)` - ); - }); + if (isMultiTarget) { + console.log(result.success ? '[ok]' : 'x', result.message); + for (const t of targets) { + console.log(`\n${t.success ? '[ok]' : 'x'} ${t.message}`); + if (t.tables?.length) { + console.log(' Tables:', t.tables.join(', ')); + } } - } catch (err) { - const duration = formatDuration(performance.now() - startTime); - console.error( - 'x Failed to introspect schema:', - err instanceof Error ? err.message : err, - `(${duration})` - ); - process.exit(1); + } else if (result.success) { + console.log('[ok]', result.message); + if (result.tables?.length) { + console.log('Tables:', result.tables.join(', ')); + } + } else { + console.error('x', result.message); + result.errors?.forEach((e) => console.error(' -', e)); } } -const createCommandMap = (): Record) => Promise> => { - return { - init: handleInit, - generate: handleGenerate, - introspect: handleIntrospect, - }; -}; - export const commands = async ( - argv: Partial, + argv: Record, prompter: Inquirerer, _options: CLIOptions -): Promise> => { - if (argv.version || argv.v) { +): Promise> => { + if (argv.version) { const pkg = getPackageJson(__dirname); console.log(pkg.version); process.exit(0); } - const { first: command, newArgv } = extractFirst(argv); - - if ((argv.help || argv.h) && !command) { - console.log(usageText); + if (argv.help || argv.h) { + console.log(usage); process.exit(0); } - if (command === 'help') { - console.log(usageText); - process.exit(0); - } + // Normalize CLI args + const normalizedArgv = { + ...argv, + config: argv.config || findConfigFile() || undefined, + output: argv.output || argv.o, + endpoint: argv.endpoint || argv.e, + schemaFile: argv['schema-file'] || argv.s, + authorization: argv.authorization || argv.a, + target: argv.target || argv.t, + reactQuery: argv['react-query'], + orm: argv.orm, + dryRun: argv['dry-run'], + verbose: argv.verbose || argv.v, + keepDb: argv['keep-db'], + }; - const commandMap = createCommandMap(); + const answers = await prompter.prompt(normalizedArgv, questions); - if (!command) { - const answer = await prompter.prompt(argv, [ - { - type: 'autocomplete', - name: 'command', - message: 'What do you want to do?', - options: Object.keys(commandMap), - }, - ]); - const selectedCommand = answer.command as string; - const commandFn = commandMap[selectedCommand]; - if (commandFn) { - await commandFn(newArgv); - } - prompter.close(); - return argv; - } + // Build db config if pgpm options provided + 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 schemasArg = argv.schemas as string | undefined; + const apiNamesArg = argv['api-names'] as string | undefined; - const commandFn = commandMap[command]; + const db = (pgpmModulePath || pgpmWorkspacePath) ? { + pgpm: { + modulePath: pgpmModulePath, + workspacePath: pgpmWorkspacePath, + moduleName: pgpmModuleName, + }, + schemas: schemasArg ? schemasArg.split(',').map((s) => s.trim()) : undefined, + apiNames: apiNamesArg ? apiNamesArg.split(',').map((s) => s.trim()) : undefined, + keepDb: !!normalizedArgv.keepDb, + } : undefined; + + const result = await generate({ + config: answers.config as string | undefined, + target: normalizedArgv.target as string | undefined, + endpoint: answers.endpoint as string | undefined, + schemaFile: normalizedArgv.schemaFile as string | undefined, + db, + output: answers.output as string | undefined, + authorization: normalizedArgv.authorization as string | undefined, + reactQuery: !!answers.reactQuery || !!normalizedArgv.reactQuery, + orm: !!answers.orm || !!normalizedArgv.orm, + dryRun: !!normalizedArgv.dryRun, + verbose: !!normalizedArgv.verbose, + }); + + printResult(result); - if (!commandFn) { - console.log(usageText); - await cliExitWithError(`Unknown command: ${command}`); + if (!result.success) { + process.exit(1); } - await commandFn(newArgv); prompter.close(); - return argv; }; export const options: Partial = { minimistOpts: { alias: { - v: 'version', h: 'help', c: 'config', - t: 'target', e: 'endpoint', s: 'schema-file', o: 'output', a: 'authorization', - d: 'directory', - f: 'force', - w: 'watch', + t: 'target', + v: 'verbose', }, boolean: [ - 'help', 'version', 'force', 'verbose', 'dry-run', 'watch', 'json', - 'skip-custom-operations', 'clear', 'react-query', 'orm', 'keep-db', + 'help', 'version', 'verbose', 'dry-run', 'react-query', 'orm', 'keep-db', ], string: [ - 'config', 'target', 'endpoint', 'schema-file', 'output', 'authorization', - 'directory', 'touch', 'poll-interval', 'debounce', + 'config', 'endpoint', 'schema-file', 'output', 'authorization', 'target', 'pgpm-module-path', 'pgpm-workspace-path', 'pgpm-module-name', 'schemas', 'api-names', ], - default: { - clear: true, - }, }, }; if (require.main === module) { - if (process.argv.includes('--version') || process.argv.includes('-v')) { - const pkg = getPackageJson(__dirname); - console.log(pkg.version); - process.exit(0); - } - - const app = new CLI(commands, options); - - app.run().then(() => { - }).catch((error) => { - console.error('Unexpected error:', error); - process.exit(1); - }); + const cli = new CLI(commands, options); + cli.run(); } diff --git a/graphql/codegen/src/index.ts b/graphql/codegen/src/index.ts index 5fbcccad5..d3cebe7c8 100644 --- a/graphql/codegen/src/index.ts +++ b/graphql/codegen/src/index.ts @@ -22,12 +22,11 @@ export * from './client'; export { defineConfig } from './types/config'; // CLI command exports (for packages/cli consumption) -// Note: generateReactQuery and generateOrm are internal - use generate() with config flags -export { - generate, - findConfigFile, - loadConfigFile, -} from './cli/commands'; +export { generate } from './cli'; +export type { GenerateOptions, GenerateResult, GenerateTargetResult } from './cli'; + +// Config utilities +export { findConfigFile, loadConfigFile } from './core/config'; // Database schema utilities (re-exported from core for convenience) export { @@ -38,11 +37,3 @@ export type { BuildSchemaFromDatabaseOptions, BuildSchemaFromDatabaseResult, } from './core/database'; - -export type { - GenerateOptions, - GenerateResult, - GenerateTargetResult, - InitOptions, - InitResult, -} from './cli/commands'; diff --git a/packages/cli/__tests__/cli.test.ts b/packages/cli/__tests__/cli.test.ts index 833dc89b7..83fc8ac0b 100644 --- a/packages/cli/__tests__/cli.test.ts +++ b/packages/cli/__tests__/cli.test.ts @@ -1,10 +1,4 @@ -jest.mock('@constructive-io/graphql-codegen/cli/commands/generate', () => ({ - generateCommand: async () => ({ success: true, message: 'ok' }) -})); import { Inquirerer, Question } from 'inquirerer'; -jest.mock('@constructive-io/graphql-codegen/cli/commands/generate', () => ({ - generateCommand: jest.fn(async () => ({ success: true, message: 'Generated SDK', filesWritten: [] as string[] })) -})) import { KEY_SEQUENCES, setupTests, TestEnvironment } from '../test-utils'; From 6e904c1d689610f14dede81979eb90ee7f5d2540 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 23 Jan 2026 23:00:57 +0000 Subject: [PATCH 22/23] refactor(cli): simplify codegen and get-graphql-schema commands using inquirerer pattern - Rewrite codegen.ts to use questions array and prompter.prompt() - Rewrite get-graphql-schema.ts to use questions array and prompter.prompt() - Remove manual arg parsing in favor of inquirerer handling - Update tests to match new simplified API - CLI commands now delegate all business logic to core functions --- packages/cli/__tests__/codegen.test.ts | 25 +- packages/cli/src/commands/codegen.ts | 216 +++++------------- .../cli/src/commands/get-graphql-schema.ts | 126 ++++++---- 3 files changed, 146 insertions(+), 221 deletions(-) diff --git a/packages/cli/__tests__/codegen.test.ts b/packages/cli/__tests__/codegen.test.ts index b6ed7abd3..0323a471c 100644 --- a/packages/cli/__tests__/codegen.test.ts +++ b/packages/cli/__tests__/codegen.test.ts @@ -4,10 +4,6 @@ import codegenCommand from '../src/commands/codegen' jest.mock('@constructive-io/graphql-codegen', () => ({ generate: jest.fn(async () => ({ success: true, message: 'Generated SDK', filesWritten: [] as string[] })), findConfigFile: jest.fn((): string | undefined => undefined), - buildSchemaFromDatabase: jest.fn(async ({ outDir }: { outDir: string }) => ({ - schemaPath: `${outDir}/schema.graphql`, - sdl: 'type Query { hello: String }\nschema { query: Query }' - })) })) // Create a mock prompter that returns the argv values directly @@ -44,7 +40,8 @@ describe('codegen command', () => { auth: 'Bearer testtoken', out: 'graphql/codegen/dist', verbose: true, - 'dry-run': true + dryRun: true, + reactQuery: true, } const mockPrompter = createMockPrompter() @@ -60,30 +57,24 @@ describe('codegen command', () => { dryRun: true, reactQuery: true }) - // orm is undefined when not set (defaults to false via !orm) - expect(call.orm).toBeFalsy() }) - it('builds schema file and calls generate with schema when DB options provided', async () => { - const { generate: mockGenerate, buildSchemaFromDatabase } = require('@constructive-io/graphql-codegen') + it('calls generate with db options when schemas provided', async () => { + const { generate: mockGenerate } = require('@constructive-io/graphql-codegen') const argv: Partial = { - database: 'constructive_db', - schemas: 'public', - out: 'graphql/codegen/dist' + schemas: 'public,app', + out: 'graphql/codegen/dist', + reactQuery: true, } const mockPrompter = createMockPrompter() await codegenCommand(argv, mockPrompter as any, {} as any) - expect(buildSchemaFromDatabase).toHaveBeenCalled() expect(mockGenerate).toHaveBeenCalled() const call = mockGenerate.mock.calls[0][0] - expect(call.schemaFile).toBe('graphql/codegen/dist/schema.graphql') + expect(call.db).toEqual({ schemas: ['public', 'app'], apiNames: undefined }) expect(call.output).toBe('graphql/codegen/dist') - expect(call.endpoint).toBeUndefined() expect(call.reactQuery).toBe(true) - // orm is undefined when not set (defaults to false via !orm) - expect(call.orm).toBeFalsy() }) }) diff --git a/packages/cli/src/commands/codegen.ts b/packages/cli/src/commands/codegen.ts index 1d9f197ed..343014899 100644 --- a/packages/cli/src/commands/codegen.ts +++ b/packages/cli/src/commands/codegen.ts @@ -1,41 +1,33 @@ import { CLIOptions, Inquirerer, Question } from 'inquirerer'; -import { - generate, - findConfigFile, - buildSchemaFromDatabase, - type GenerateResult, - type GenerateTargetResult, -} from '@constructive-io/graphql-codegen'; -import { getEnvOptions } from '@constructive-io/graphql-env'; +import { generate, findConfigFile } from '@constructive-io/graphql-codegen'; const usage = ` Constructive GraphQL Codegen: cnc codegen [OPTIONS] -Options: - --help, -h Show this help message +Source Options (choose one): --config Path to graphql-codegen config file - --target Target name in config file --endpoint GraphQL endpoint URL - --auth Authorization header value (e.g., "Bearer 123") - --out Output directory (default: codegen) - --dry-run Preview without writing files - -v, --verbose Verbose output + --schemaFile Path to GraphQL schema file + +Database Options: + --schemas Comma-separated PostgreSQL schemas + --apiNames Comma-separated API names - --orm Generate Prisma-like ORM client instead of React Query hooks +Generator Options: + --reactQuery Generate React Query hooks (default) + --orm Generate ORM client + --target Target name in config file + --out Output directory (default: codegen) + --auth Authorization header value + --dryRun Preview without writing files + --verbose Verbose output - --database Database override for DB mode (defaults to PGDATABASE) - --schemas Comma-separated schemas (required for DB mode) + --help, -h Show this help message `; const questions: Question[] = [ - { - name: 'endpoint', - message: 'GraphQL endpoint URL', - type: 'text', - required: false, - }, { name: 'config', message: 'Path to config file', @@ -43,8 +35,8 @@ const questions: Question[] = [ required: false, }, { - name: 'target', - message: 'Target name in config file', + name: 'endpoint', + message: 'GraphQL endpoint URL', type: 'text', required: false, }, @@ -57,42 +49,16 @@ const questions: Question[] = [ useDefault: true, }, { - name: 'auth', - message: 'Authorization header value', - type: 'text', - required: false, - }, - { - name: 'database', - message: 'Database name (for DB mode)', - type: 'text', - required: false, - }, - { - name: 'schemas', - message: 'Comma-separated schemas (for DB mode)', - type: 'text', - required: false, - }, - { - name: 'orm', - message: 'Generate ORM client instead of React Query hooks?', - type: 'confirm', - required: false, - default: false, - useDefault: true, - }, - { - name: 'dryRun', - message: 'Preview without writing files?', + name: 'reactQuery', + message: 'Generate React Query hooks?', type: 'confirm', required: false, - default: false, + default: true, useDefault: true, }, { - name: 'verbose', - message: 'Verbose output?', + name: 'orm', + message: 'Generate ORM client?', type: 'confirm', required: false, default: false, @@ -100,11 +66,8 @@ const questions: Question[] = [ }, ]; -type AnyResult = GenerateResult; -type AnyTargetResult = GenerateTargetResult; - export default async ( - argv: Partial>, + argv: Partial>, prompter: Inquirerer, _options: CLIOptions ) => { @@ -113,112 +76,49 @@ export default async ( process.exit(0); } - // Handle CLI aliases and defaults const normalizedArgv = { ...argv, - dryRun: argv['dry-run'] || argv.dryRun, - verbose: argv.verbose || argv.v, config: argv.config || findConfigFile() || undefined, + endpoint: argv.endpoint, + out: argv.out, + reactQuery: argv.reactQuery, + orm: argv.orm, }; - const answers: any = await prompter.prompt(normalizedArgv, questions); - const endpoint = answers.endpoint as string | undefined; - const config = answers.config as string | undefined; - const target = answers.target as string | undefined; - const out = answers.out as string | undefined; - const auth = answers.auth as string | undefined; - const database = answers.database as string | undefined; - const schemasArg = answers.schemas as string | undefined; - const orm = answers.orm as boolean | undefined; - const dryRun = answers.dryRun as boolean | undefined; - const verbose = answers.verbose as boolean | undefined; - - // Parse schemas from comma-separated string - const schemas = schemasArg - ? String(schemasArg).split(',').map((s: string) => s.trim()).filter(Boolean) - : []; - - // Determine output directory - const outDir = (out as string) || 'codegen'; - let schemaPath: string | undefined; - - // Build schema from database if schemas are provided - if (schemas.length > 0) { - const db = (database as string) || getEnvOptions().pg.database; - const result = await buildSchemaFromDatabase({ - database: db, - schemas, - outDir, - }); - schemaPath = result.schemaPath; - } - - // Validate that we have a source - if (!endpoint && !schemaPath && !config) { - console.error( - 'Error: No source specified. Use --endpoint, --config, or --schemas for database mode.' - ); - process.exit(1); - } - - // Determine output directory - const output = config ? out : outDir; + const { + config, + endpoint, + out, + reactQuery, + orm, + } = await prompter.prompt(normalizedArgv, questions); + + const schemasArg = argv.schemas as string | undefined; + const apiNamesArg = argv.apiNames as string | undefined; + const db = (schemasArg || apiNamesArg) ? { + schemas: schemasArg ? schemasArg.split(',').map((s) => s.trim()) : undefined, + apiNames: apiNamesArg ? apiNamesArg.split(',').map((s) => s.trim()) : undefined, + } : undefined; - // Call unified generate function with appropriate flags const result = await generate({ - config, - target, - endpoint: endpoint || undefined, - schemaFile: schemaPath, - output, - authorization: auth, - verbose, - dryRun, - // Use flags to control which generators run - reactQuery: !orm, - orm: orm, + config: config as string | undefined, + target: argv.target as string | undefined, + endpoint: endpoint as string | undefined, + schemaFile: argv.schemaFile as string | undefined, + db, + output: out as string | undefined, + authorization: argv.auth as string | undefined, + reactQuery: reactQuery as boolean, + orm: orm as boolean, + dryRun: !!argv.dryRun, + verbose: !!argv.verbose, }); - printResult(result); - - if (!result.success) { + if (result.success) { + console.log('[ok]', result.message); + } else { + console.error('x', result.message); + result.errors?.forEach((e) => console.error(' -', e)); process.exit(1); } }; - -function printTargetResult(target: AnyTargetResult): void { - const status = target.success ? '[ok]' : 'x'; - console.log(`\n${status} ${target.message}`); - - if (target.tables?.length) { - console.log(' Tables:'); - target.tables.forEach((t) => console.log(` - ${t}`)); - } - if (target.filesWritten?.length) { - console.log(' Files written:'); - target.filesWritten.forEach((f) => console.log(` - ${f}`)); - } - if (!target.success && target.errors?.length) { - target.errors.forEach((e) => console.error(` - ${e}`)); - } -} - -function printResult(result: AnyResult): void { - const targets = result.targets ?? []; - const isMultiTarget = - targets.length > 1 || (targets.length === 1 && targets[0]?.name !== 'default'); - - if (isMultiTarget) { - console.log(result.message); - targets.forEach(printTargetResult); - return; - } - - if (!result.success) { - console.error(result.message); - result.errors?.forEach((e) => console.error(' -', e)); - } else { - console.log(result.message); - result.filesWritten?.forEach((f) => console.log(f)); - } -} diff --git a/packages/cli/src/commands/get-graphql-schema.ts b/packages/cli/src/commands/get-graphql-schema.ts index 8916d7052..6645095a1 100644 --- a/packages/cli/src/commands/get-graphql-schema.ts +++ b/packages/cli/src/commands/get-graphql-schema.ts @@ -1,78 +1,112 @@ -import { CLIOptions, Inquirerer, ParsedArgs } from 'inquirerer' -import { promises as fs } from 'fs' -import { buildSchemaSDL, fetchEndpointSchemaSDL } from '@constructive-io/graphql-server' +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] -Options: - --help, -h Show this help message +Source Options (choose one): + --endpoint GraphQL endpoint to fetch schema via introspection --database Database name (default: constructive) + +Options: --schemas Comma-separated schemas to include - --endpoint GraphQL endpoint to fetch schema via introspection - --headerHost Optional Host header to send with endpoint requests - --auth Optional Authorization header value (e.g., "Bearer 123") - --header "Name: Value" Optional HTTP header; repeat to add multiple headers + --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 defaultSchemas = [ 'metaschema_public', 'metaschema_modules_public', - 'services_public' -] + 'services_public', +]; + +const questions: Question[] = [ + { + name: 'endpoint', + message: 'GraphQL endpoint URL', + type: 'text', + required: false, + }, + { + name: 'database', + message: 'Database name', + type: 'text', + required: false, + default: 'constructive', + useDefault: true, + }, + { + name: 'schemas', + message: 'Comma-separated schemas', + type: 'text', + required: false, + default: defaultSchemas.join(','), + useDefault: true, + }, + { + name: 'out', + message: 'Output file path', + type: 'text', + required: false, + }, +]; export default async ( - argv: Partial, + argv: Partial>, prompter: Inquirerer, _options: CLIOptions ) => { if (argv.help || argv.h) { - console.log(usage) - process.exit(0) + console.log(usage); + process.exit(0); } - const endpoint = (argv.endpoint as string) ?? '' - const headerHost = (argv.headerHost as string) ?? '' - const auth = (argv.auth as string) ?? '' - const database = (argv.database as string) ?? 'constructive' - const schemasArg = (argv.schemas as string) ?? defaultSchemas.join(',') - const out = (argv.out as string) ?? '' + const { + endpoint, + database, + schemas: schemasArg, + out, + } = await prompter.prompt(argv, questions); - const headerArg = argv.header as string | string[] | undefined - const headerList = Array.isArray(headerArg) ? headerArg : headerArg ? [headerArg] : [] - const headers: Record = {} + 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 + 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; } - const schemas = schemasArg.split(',').map(s => s.trim()).filter(Boolean) - - let sdl: string + let sdl: string; if (endpoint) { - const opts: any = {} - if (headerHost) opts.headerHost = headerHost - if (auth) opts.auth = auth - if (Object.keys(headers).length) opts.headers = headers - sdl = await (fetchEndpointSchemaSDL as any)(endpoint, opts) + 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 { - // The server package already depends on postgraphile and graphql, - // and exporting a reusable programmatic builder from there - // avoids adding new dependencies to cli and prevents duplication. - sdl = await buildSchemaSDL({ database, schemas }) + sdl = await buildSchemaSDL({ database: database as string, schemas }); } if (out) { - await fs.writeFile(out, sdl, 'utf8') - console.log(`Wrote schema SDL to ${out}`) + await fs.writeFile(out as string, sdl, 'utf8'); + console.log(`Wrote schema SDL to ${out}`); } else { - process.stdout.write(sdl + '\n') + process.stdout.write(sdl + '\n'); } -} +}; From d1a221a0abfa030bb3a28696520d35137f64bdef Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Fri, 23 Jan 2026 23:21:16 +0000 Subject: [PATCH 23/23] refactor(graphql-codegen): move generate orchestration to core, simplify CLI - Move generate() function from cli/index.ts to core/generate.ts - CLI is now a thin wrapper (~200 lines) that just parses args and calls core generate() - All business logic (config loading, introspection, file writing) is in core - Export generate() from core/index.ts and main index.ts --- graphql/codegen/src/cli/index.ts | 285 +------------------------- graphql/codegen/src/core/generate.ts | 289 +++++++++++++++++++++++++++ graphql/codegen/src/core/index.ts | 4 + graphql/codegen/src/index.ts | 6 +- 4 files changed, 299 insertions(+), 285 deletions(-) create mode 100644 graphql/codegen/src/core/generate.ts diff --git a/graphql/codegen/src/cli/index.ts b/graphql/codegen/src/cli/index.ts index ae5d67071..61a9360b8 100644 --- a/graphql/codegen/src/cli/index.ts +++ b/graphql/codegen/src/cli/index.ts @@ -5,17 +5,11 @@ * This is a thin wrapper around the core generate() function. * All business logic is in the core modules. */ -import path from 'path'; import { CLI, CLIOptions, Inquirerer, Question, getPackageJson } from 'inquirerer'; -import { loadAndResolveConfig, findConfigFile } from '../core/config'; -import { createSchemaSource, validateSourceOptions, inferTablesFromIntrospection } from '../core/introspect'; -import { runCodegenPipeline, validateTablesFound } from '../core/pipeline'; -import { generate as generateReactQueryFiles } from '../core/codegen'; -import { generateOrm as generateOrmFiles } from '../core/codegen/orm'; -import { generateSharedTypes } from '../core/codegen/shared'; -import { writeGeneratedFiles } from '../core/output'; -import type { GraphQLSDKConfigTarget, TargetConfig } from '../types/config'; +import { generate } from '../core/generate'; +import { findConfigFile } from '../core/config'; +import type { GenerateResult } from '../core/generate'; const usage = ` graphql-codegen - GraphQL SDK generator for Constructive databases @@ -82,279 +76,6 @@ const questions: Question[] = [ }, ]; -export interface GenerateOptions extends GraphQLSDKConfigTarget { - config?: string; - target?: string; - authorization?: string; - verbose?: boolean; - dryRun?: boolean; - skipCustomOperations?: boolean; -} - -export interface GenerateTargetResult { - name: string; - output: string; - success: boolean; - message: string; - tables?: string[]; - filesWritten?: string[]; - errors?: string[]; -} - -export interface GenerateResult { - success: boolean; - message: string; - targets?: GenerateTargetResult[]; - tables?: string[]; - filesWritten?: string[]; - errors?: string[]; -} - -/** - * Main generate function - orchestrates the entire codegen pipeline - */ -export async function generate(options: GenerateOptions = {}): Promise { - if (options.verbose) { - console.log('Loading configuration...'); - } - - const configResult = await loadAndResolveConfig(options); - if (!configResult.success) { - return { success: false, message: configResult.error! }; - } - - const targets = configResult.targets ?? []; - if (targets.length === 0) { - return { success: false, message: 'No targets resolved from configuration.' }; - } - - const results: GenerateTargetResult[] = []; - - for (const target of targets) { - const runReactQuery = options.reactQuery ?? target.config.reactQuery; - const runOrm = options.orm ?? target.config.orm; - - if (!runReactQuery && !runOrm) { - results.push({ - name: target.name, - output: target.config.output, - success: false, - message: `Target "${target.name}": No generators enabled. Use --react-query or --orm.`, - }); - continue; - } - - const result = await generateForTarget(target, options, runReactQuery, runOrm); - results.push(result); - } - - if (results.length === 1) { - const [result] = results; - return { - success: result.success, - message: result.message, - targets: results, - tables: result.tables, - filesWritten: result.filesWritten, - errors: result.errors, - }; - } - - const successCount = results.filter((r) => r.success).length; - const failedCount = results.length - successCount; - - return { - success: failedCount === 0, - message: failedCount === 0 - ? `Generated ${results.length} outputs successfully.` - : `Generated ${successCount} of ${results.length} outputs.`, - targets: results, - errors: failedCount > 0 ? results.flatMap((r) => r.errors ?? []) : undefined, - }; -} - -async function generateForTarget( - target: TargetConfig, - options: GenerateOptions, - runReactQuery: boolean, - runOrm: boolean -): Promise { - const config = target.config; - const outputRoot = config.output; - - // Validate source - const sourceValidation = validateSourceOptions({ - endpoint: config.endpoint || undefined, - schemaFile: config.schemaFile || undefined, - db: config.db, - }); - if (!sourceValidation.valid) { - return { - name: target.name, - output: outputRoot, - success: false, - message: sourceValidation.error!, - }; - } - - const source = createSchemaSource({ - endpoint: config.endpoint || undefined, - schemaFile: config.schemaFile || undefined, - db: config.db, - authorization: options.authorization || config.headers?.['Authorization'], - headers: config.headers, - }); - - // Run pipeline - let pipelineResult; - try { - console.log(`Fetching schema from ${source.describe()}...`); - pipelineResult = await runCodegenPipeline({ - source, - config, - verbose: options.verbose, - skipCustomOperations: options.skipCustomOperations, - }); - } catch (err) { - return { - name: target.name, - output: outputRoot, - success: false, - message: `Failed to fetch schema: ${err instanceof Error ? err.message : 'Unknown error'}`, - }; - } - - const { tables, customOperations } = pipelineResult; - - // Validate tables - const tablesValidation = validateTablesFound(tables); - if (!tablesValidation.valid) { - return { - name: target.name, - output: outputRoot, - success: false, - message: tablesValidation.error!, - }; - } - - const allFilesWritten: string[] = []; - const bothEnabled = runReactQuery && runOrm; - - // Generate shared types when both are enabled - if (bothEnabled) { - console.log('Generating shared types...'); - const sharedResult = generateSharedTypes({ - tables, - customOperations: { - queries: customOperations.queries, - mutations: customOperations.mutations, - typeRegistry: customOperations.typeRegistry, - }, - config, - }); - - if (!options.dryRun) { - const writeResult = await writeGeneratedFiles(sharedResult.files, outputRoot, []); - if (!writeResult.success) { - return { - name: target.name, - output: outputRoot, - success: false, - message: `Failed to write shared types: ${writeResult.errors?.join(', ')}`, - errors: writeResult.errors, - }; - } - allFilesWritten.push(...(writeResult.filesWritten ?? [])); - } - } - - // Generate React Query hooks - if (runReactQuery) { - const hooksDir = bothEnabled ? path.join(outputRoot, 'hooks') : path.join(outputRoot, 'hooks'); - console.log('Generating React Query hooks...'); - const { files } = generateReactQueryFiles({ - tables, - customOperations: { - queries: customOperations.queries, - mutations: customOperations.mutations, - typeRegistry: customOperations.typeRegistry, - }, - config, - sharedTypesPath: bothEnabled ? '..' : undefined, - }); - - if (!options.dryRun) { - const writeResult = await writeGeneratedFiles(files, hooksDir, ['queries', 'mutations']); - if (!writeResult.success) { - return { - name: target.name, - output: outputRoot, - success: false, - message: `Failed to write React Query hooks: ${writeResult.errors?.join(', ')}`, - errors: writeResult.errors, - }; - } - allFilesWritten.push(...(writeResult.filesWritten ?? [])); - } - } - - // Generate ORM client - if (runOrm) { - const ormDir = bothEnabled ? path.join(outputRoot, 'orm') : path.join(outputRoot, 'orm'); - console.log('Generating ORM client...'); - const { files } = generateOrmFiles({ - tables, - customOperations: { - queries: customOperations.queries, - mutations: customOperations.mutations, - typeRegistry: customOperations.typeRegistry, - }, - config, - sharedTypesPath: bothEnabled ? '..' : undefined, - }); - - if (!options.dryRun) { - const writeResult = await writeGeneratedFiles(files, ormDir, ['models', 'query', 'mutation']); - if (!writeResult.success) { - return { - name: target.name, - output: outputRoot, - success: false, - message: `Failed to write ORM client: ${writeResult.errors?.join(', ')}`, - errors: writeResult.errors, - }; - } - allFilesWritten.push(...(writeResult.filesWritten ?? [])); - } - } - - // Generate unified barrel when both are enabled - if (bothEnabled && !options.dryRun) { - const barrelContent = `/** - * Generated SDK - auto-generated, do not edit - * @generated by @constructive-io/graphql-codegen - */ -export * from './types'; -export * from './hooks'; -export * from './orm'; -`; - await writeGeneratedFiles([{ path: 'index.ts', content: barrelContent }], outputRoot, []); - } - - const generators = [runReactQuery && 'React Query', runOrm && 'ORM'].filter(Boolean).join(' and '); - - return { - name: target.name, - output: outputRoot, - success: true, - message: options.dryRun - ? `Dry run complete. Would generate ${generators} for ${tables.length} tables.` - : `Generated ${generators} for ${tables.length} tables. Files written to ${outputRoot}`, - tables: tables.map((t) => t.name), - filesWritten: allFilesWritten, - }; -} - function printResult(result: GenerateResult): void { const targets = result.targets ?? []; const isMultiTarget = targets.length > 1 || (targets.length === 1 && targets[0]?.name !== 'default'); diff --git a/graphql/codegen/src/core/generate.ts b/graphql/codegen/src/core/generate.ts new file mode 100644 index 000000000..408be6326 --- /dev/null +++ b/graphql/codegen/src/core/generate.ts @@ -0,0 +1,289 @@ +/** + * Main generate function - orchestrates the entire codegen pipeline + * + * This is the primary entry point for programmatic usage. + * The CLI is a thin wrapper around this function. + */ +import path from 'path'; + +import { loadAndResolveConfig } from './config'; +import { createSchemaSource, validateSourceOptions } from './introspect'; +import { runCodegenPipeline, validateTablesFound } from './pipeline'; +import { generate as generateReactQueryFiles } from './codegen'; +import { generateOrm as generateOrmFiles } from './codegen/orm'; +import { generateSharedTypes } from './codegen/shared'; +import { writeGeneratedFiles } from './output'; +import type { GraphQLSDKConfigTarget, TargetConfig } from '../types/config'; + +export interface GenerateOptions extends GraphQLSDKConfigTarget { + config?: string; + target?: string; + authorization?: string; + verbose?: boolean; + dryRun?: boolean; + skipCustomOperations?: boolean; +} + +export interface GenerateTargetResult { + name: string; + output: string; + success: boolean; + message: string; + tables?: string[]; + filesWritten?: string[]; + errors?: string[]; +} + +export interface GenerateResult { + success: boolean; + message: string; + targets?: GenerateTargetResult[]; + tables?: string[]; + filesWritten?: string[]; + errors?: string[]; +} + +/** + * Main generate function - orchestrates the entire codegen pipeline + */ +export async function generate(options: GenerateOptions = {}): Promise { + if (options.verbose) { + console.log('Loading configuration...'); + } + + const configResult = await loadAndResolveConfig(options); + if (!configResult.success) { + return { success: false, message: configResult.error! }; + } + + const targets = configResult.targets ?? []; + if (targets.length === 0) { + return { success: false, message: 'No targets resolved from configuration.' }; + } + + const results: GenerateTargetResult[] = []; + + for (const target of targets) { + const runReactQuery = options.reactQuery ?? target.config.reactQuery; + const runOrm = options.orm ?? target.config.orm; + + if (!runReactQuery && !runOrm) { + results.push({ + name: target.name, + output: target.config.output, + success: false, + message: `Target "${target.name}": No generators enabled. Use --react-query or --orm.`, + }); + continue; + } + + const result = await generateForTarget(target, options, runReactQuery, runOrm); + results.push(result); + } + + if (results.length === 1) { + const [result] = results; + return { + success: result.success, + message: result.message, + targets: results, + tables: result.tables, + filesWritten: result.filesWritten, + errors: result.errors, + }; + } + + const successCount = results.filter((r) => r.success).length; + const failedCount = results.length - successCount; + + return { + success: failedCount === 0, + message: failedCount === 0 + ? `Generated ${results.length} outputs successfully.` + : `Generated ${successCount} of ${results.length} outputs.`, + targets: results, + errors: failedCount > 0 ? results.flatMap((r) => r.errors ?? []) : undefined, + }; +} + +async function generateForTarget( + target: TargetConfig, + options: GenerateOptions, + runReactQuery: boolean, + runOrm: boolean +): Promise { + const config = target.config; + const outputRoot = config.output; + + // Validate source + const sourceValidation = validateSourceOptions({ + endpoint: config.endpoint || undefined, + schemaFile: config.schemaFile || undefined, + db: config.db, + }); + if (!sourceValidation.valid) { + return { + name: target.name, + output: outputRoot, + success: false, + message: sourceValidation.error!, + }; + } + + const source = createSchemaSource({ + endpoint: config.endpoint || undefined, + schemaFile: config.schemaFile || undefined, + db: config.db, + authorization: options.authorization || config.headers?.['Authorization'], + headers: config.headers, + }); + + // Run pipeline + let pipelineResult; + try { + console.log(`Fetching schema from ${source.describe()}...`); + pipelineResult = await runCodegenPipeline({ + source, + config, + verbose: options.verbose, + skipCustomOperations: options.skipCustomOperations, + }); + } catch (err) { + return { + name: target.name, + output: outputRoot, + success: false, + message: `Failed to fetch schema: ${err instanceof Error ? err.message : 'Unknown error'}`, + }; + } + + const { tables, customOperations } = pipelineResult; + + // Validate tables + const tablesValidation = validateTablesFound(tables); + if (!tablesValidation.valid) { + return { + name: target.name, + output: outputRoot, + success: false, + message: tablesValidation.error!, + }; + } + + const allFilesWritten: string[] = []; + const bothEnabled = runReactQuery && runOrm; + + // Generate shared types when both are enabled + if (bothEnabled) { + console.log('Generating shared types...'); + const sharedResult = generateSharedTypes({ + tables, + customOperations: { + queries: customOperations.queries, + mutations: customOperations.mutations, + typeRegistry: customOperations.typeRegistry, + }, + config, + }); + + if (!options.dryRun) { + const writeResult = await writeGeneratedFiles(sharedResult.files, outputRoot, []); + if (!writeResult.success) { + return { + name: target.name, + output: outputRoot, + success: false, + message: `Failed to write shared types: ${writeResult.errors?.join(', ')}`, + errors: writeResult.errors, + }; + } + allFilesWritten.push(...(writeResult.filesWritten ?? [])); + } + } + + // Generate React Query hooks + if (runReactQuery) { + const hooksDir = path.join(outputRoot, 'hooks'); + console.log('Generating React Query hooks...'); + const { files } = generateReactQueryFiles({ + tables, + customOperations: { + queries: customOperations.queries, + mutations: customOperations.mutations, + typeRegistry: customOperations.typeRegistry, + }, + config, + sharedTypesPath: bothEnabled ? '..' : undefined, + }); + + if (!options.dryRun) { + const writeResult = await writeGeneratedFiles(files, hooksDir, ['queries', 'mutations']); + if (!writeResult.success) { + return { + name: target.name, + output: outputRoot, + success: false, + message: `Failed to write React Query hooks: ${writeResult.errors?.join(', ')}`, + errors: writeResult.errors, + }; + } + allFilesWritten.push(...(writeResult.filesWritten ?? [])); + } + } + + // Generate ORM client + if (runOrm) { + const ormDir = path.join(outputRoot, 'orm'); + console.log('Generating ORM client...'); + const { files } = generateOrmFiles({ + tables, + customOperations: { + queries: customOperations.queries, + mutations: customOperations.mutations, + typeRegistry: customOperations.typeRegistry, + }, + config, + sharedTypesPath: bothEnabled ? '..' : undefined, + }); + + if (!options.dryRun) { + const writeResult = await writeGeneratedFiles(files, ormDir, ['models', 'query', 'mutation']); + if (!writeResult.success) { + return { + name: target.name, + output: outputRoot, + success: false, + message: `Failed to write ORM client: ${writeResult.errors?.join(', ')}`, + errors: writeResult.errors, + }; + } + allFilesWritten.push(...(writeResult.filesWritten ?? [])); + } + } + + // Generate unified barrel when both are enabled + if (bothEnabled && !options.dryRun) { + const barrelContent = `/** + * Generated SDK - auto-generated, do not edit + * @generated by @constructive-io/graphql-codegen + */ +export * from './types'; +export * from './hooks'; +export * from './orm'; +`; + await writeGeneratedFiles([{ path: 'index.ts', content: barrelContent }], outputRoot, []); + } + + const generators = [runReactQuery && 'React Query', runOrm && 'ORM'].filter(Boolean).join(' and '); + + return { + name: target.name, + output: outputRoot, + success: true, + message: options.dryRun + ? `Dry run complete. Would generate ${generators} for ${tables.length} tables.` + : `Generated ${generators} for ${tables.length} tables. Files written to ${outputRoot}`, + tables: tables.map((t) => t.name), + filesWritten: allFilesWritten, + }; +} diff --git a/graphql/codegen/src/core/index.ts b/graphql/codegen/src/core/index.ts index 5d5be3db2..5149bd636 100644 --- a/graphql/codegen/src/core/index.ts +++ b/graphql/codegen/src/core/index.ts @@ -5,6 +5,10 @@ * The CLI is a thin wrapper around these core functions. */ +// Main generate function (orchestrates the entire pipeline) +export { generate } from './generate'; +export type { GenerateOptions, GenerateResult, GenerateTargetResult } from './generate'; + // Types export * from './types'; diff --git a/graphql/codegen/src/index.ts b/graphql/codegen/src/index.ts index d3cebe7c8..f85898f2d 100644 --- a/graphql/codegen/src/index.ts +++ b/graphql/codegen/src/index.ts @@ -21,9 +21,9 @@ export * from './client'; // Config definition helper export { defineConfig } from './types/config'; -// CLI command exports (for packages/cli consumption) -export { generate } from './cli'; -export type { GenerateOptions, GenerateResult, GenerateTargetResult } from './cli'; +// Main generate function (orchestrates the entire pipeline) +export { generate } from './core/generate'; +export type { GenerateOptions, GenerateResult, GenerateTargetResult } from './core/generate'; // Config utilities export { findConfigFile, loadConfigFile } from './core/config';