diff --git a/.github/workflows/docker-launchql.yaml b/.github/workflows/docker-launchql.yaml index 13856efc6..abf4d3196 100644 --- a/.github/workflows/docker-launchql.yaml +++ b/.github/workflows/docker-launchql.yaml @@ -6,11 +6,17 @@ on: - main - v1 - release/* + paths-ignore: + - 'graphql/test-app/**' + - 'graphql/test-codegen-app/**' pull_request: branches: - main - v1 types: [opened, reopened, synchronize, ready_for_review] + paths-ignore: + - 'graphql/test-app/**' + - 'graphql/test-codegen-app/**' workflow_dispatch: {} concurrency: diff --git a/.github/workflows/notify-e2e.yml b/.github/workflows/notify-e2e.yml index e12a58c6a..7f9e6f3d6 100644 --- a/.github/workflows/notify-e2e.yml +++ b/.github/workflows/notify-e2e.yml @@ -6,6 +6,9 @@ name: Notify E2E Tests on: push: branches: [main] + paths-ignore: + - 'graphql/test-app/**' + - 'graphql/test-codegen-app/**' jobs: trigger-tests: diff --git a/.github/workflows/run-tests.yaml b/.github/workflows/run-tests.yaml index 3142fb930..015753008 100644 --- a/.github/workflows/run-tests.yaml +++ b/.github/workflows/run-tests.yaml @@ -4,10 +4,16 @@ on: branches: - main - v1 + paths-ignore: + - 'graphql/test-app/**' + - 'graphql/test-codegen-app/**' pull_request: branches: - main - v1 + paths-ignore: + - 'graphql/test-app/**' + - 'graphql/test-codegen-app/**' workflow_dispatch: workflow_call: @@ -190,7 +196,8 @@ jobs: run: pnpm install - name: build - run: pnpm run build + run: | + pnpm -r --filter '!@constructive-io/test-codegen-app' run build - name: seed app_user run: | diff --git a/CLAUDE.md b/CLAUDE.md index 907fe7cd1..776c240c3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -5,33 +5,22 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Build & Development Commands ```bash -# Install dependencies -pnpm install - -# Build all packages -pnpm build - -# Build all packages (dev mode - faster, no optimizations) -pnpm build:dev - -# Lint all packages (auto-fix enabled) -pnpm lint - -# Clean build artifacts -pnpm clean - -# Update dependencies interactively -pnpm deps +pnpm install # Install dependencies +pnpm build # Build all packages +pnpm build:dev # Build all packages (dev mode - faster, no optimizations) +pnpm lint # Lint all packages (auto-fix enabled) +pnpm clean # Clean build artifacts +pnpm deps # Update dependencies interactively (pnpm up -r -i -L) ``` ### Per-Package Commands -Navigate to any package directory (e.g., `cd pgpm/cli`) and run: +From any package directory (e.g., `cd pgpm/cli`): ```bash -pnpm build # Build the package +pnpm build # Build the package (uses makage) pnpm lint # Lint with auto-fix -pnpm test # Run tests +pnpm test # Run tests (Jest) pnpm test:watch # Run tests in watch mode pnpm dev # Run in development mode (where available) ``` @@ -41,54 +30,74 @@ pnpm dev # Run in development mode (where available) ```bash cd packages/cli pnpm test -- path/to/test.test.ts -# or with pattern matching: pnpm test -- --testNamePattern="test name pattern" ``` +### Publishing + +Lerna with independent versioning and conventional commits. Publishing only from `main` branch: + +```bash +npx lerna version # Bump versions +npx lerna publish # Publish to npm +``` + ## Project Architecture -This is a **pnpm monorepo** using Lerna for versioning/publishing. The workspace is organized into domain-specific directories: +A **pnpm monorepo** with Lerna for versioning. PostgreSQL-first framework: design your database schema, manage it with pgpm, and get a production-ready GraphQL API automatically via PostGraphile. + +### Data Flow + +``` +PostgreSQL (schema + RLS policies, managed by pgpm migrations) + ↓ +PostGraphile (graphql/server + graphile/* plugins) + ↓ +GraphQL Schema (auto-generated from database) + ↓ +graphql/codegen (--react-query mode OR --orm mode) + ↓ +React Query Hooks or Prisma-like ORM Client +``` -### Core Package Groups +### Workspace Groups | Directory | Purpose | |-----------|---------| -| `pgpm/` | PostgreSQL Package Manager - CLI, core engine, types | -| `graphql/` | GraphQL layer - server, codegen, React hooks, testing | -| `graphile/` | PostGraphile plugins - filters, i18n, meta-schema, PostGIS | -| `postgres/` | PostgreSQL utilities - introspection, testing, seeding, AST | -| `packages/` | Shared utilities - CLI, ORM, query builder | -| `uploads/` | File streaming - S3, ETags, content-type detection | -| `jobs/` | Job scheduling and worker infrastructure | +| `pgpm/` | PostgreSQL Package Manager - CLI (`pgpm`), core engine, types, env, logger | +| `graphql/` | GraphQL layer - server, codegen, query builder, explorer, AST utilities | +| `graphile/` | PostGraphile plugins - filters, i18n, meta-schema, PostGIS, search, uploads, settings | +| `postgres/` | PostgreSQL utilities - introspection, testing (pgsql-test), seeding, AST, query context | +| `packages/` | Shared utilities - CLI (`cnc`), ORM base, query builder, server utils, client | +| `uploads/` | File streaming - S3/MinIO, ETags, content-type detection, UUID hashing | +| `jobs/` | Knative job scheduling - worker, scheduler, service, functions | +| `functions/` | Knative cloud functions (e.g., send-email-link) | -### Key Packages +### Key Packages & CLIs -**pgpm (PostgreSQL Package Manager)** -- `pgpm/cli` - Main CLI tool (`pgpm` command) -- `pgpm/core` - Migration engine, dependency resolution, deployment +**`pgpm` CLI** (`pgpm/cli`) - PostgreSQL Package Manager. Commands: `init`, `add`, `deploy`, `revert`, `verify`, `plan`, `install`, `export`, `docker`, `dump`, `tag`. Manages SQL migrations in Sqitch-compatible format with dependency resolution. -**GraphQL Stack** -- `graphql/server` - Express + PostGraphile API server -- `graphql/codegen` - SDK generator (React Query hooks or Prisma-like ORM) -- `graphql/query` - Fluent GraphQL query builder +**`cnc` CLI** (`packages/cli`, binary: `cnc` or `constructive`) - Full dev toolkit. Commands: `server` (start PostGraphile), `explorer` (GraphiQL UI), `codegen` (generate SDK), `get-graphql-schema`, `jobs`, `context`, `auth`, `execute`. -**Testing Infrastructure** -- `postgres/pgsql-test` - Isolated PostgreSQL test environments with transaction rollback -- `graphile/graphile-test` - GraphQL testing utilities +**`graphql/codegen`** - Generates type-safe clients from GraphQL schema or endpoint: +- `--react-query` mode: TanStack Query v5 hooks with query key factories +- `--orm` mode: Prisma-like fluent API with `InferSelectResult` type inference, discriminated union error handling (`.unwrap()`, `.unwrapOr()`) +- Sources: GraphQL endpoint URL, .graphql schema file, or direct database introspection -### Testing Pattern +**`graphql/server`** - Express + PostGraphile. Supports multi-endpoint routing via subdomain/host detection (schema builder with app-public/auth/admin sub-endpoints). Uses `LISTEN/NOTIFY` for schema cache invalidation. -Tests use `pgsql-test` for database testing with per-test transaction rollback: +**`graphile/graphile-settings`** - Centralizes all PostGraphile plugin config: connection filters, full-text search, PostGIS, i18n, meta-schema, many-to-many, search, upload plugin. Single `getGraphileSettings(opts)` entry point. -```typescript -import { getConnections } from 'pgsql-test'; +**`packages/query-builder`** - Fluent SQL query builder for SELECT/INSERT/UPDATE/DELETE with JOINs, WHERE, GROUP BY. Schema-qualified tables. -let db, teardown; +### Testing Infrastructure -beforeAll(async () => { - ({ db, teardown } = await getConnections()); -}); +**`postgres/pgsql-test`** - Isolated PostgreSQL test environments with per-test transaction rollback: +```typescript +import { getConnections } from 'pgsql-test'; +let db, teardown; +beforeAll(async () => ({ db, teardown } = await getConnections())); beforeEach(() => db.beforeEach()); afterEach(() => db.afterEach()); afterAll(() => teardown()); @@ -100,26 +109,35 @@ test('example', async () => { }); ``` +**`graphile/graphile-test`** - GraphQL testing with PostGraphile snapshot support. + +### Job System + +Background jobs use Knative: jobs are added to `app_jobs.jobs` table → `knative-job-worker` polls and picks up → POSTs to Knative function URL → function executes (e.g., send email) → returns status. + ### Database Configuration -Tests require PostgreSQL. Standard PG environment variables: -- `PGHOST` (default: localhost) -- `PGPORT` (default: 5432) -- `PGUSER` (default: postgres) -- `PGPASSWORD` (default: password) +Tests require PostgreSQL. Standard PG env vars: +- `PGHOST` (default: localhost), `PGPORT` (default: 5432) +- `PGUSER` (default: postgres), `PGPASSWORD` (default: password) For S3/MinIO tests: `MINIO_ENDPOINT`, `AWS_ACCESS_KEY`, `AWS_SECRET_KEY`, `AWS_REGION` -### Build System +## Build System -- Uses `makage` for TypeScript compilation (handles both CJS and ESM output) -- Jest with ts-jest for testing -- ESLint with TypeScript support -- Each package has its own `tsconfig.json` extending root config +- **makage** compiles TypeScript to both CJS and ESM, outputs to `dist/` +- `makage build --dev` for faster dev builds +- Some packages use `copyfiles` for non-TS assets (SQL files, templates) +- Jest with `ts-jest` preset per-package (`jest.config.js` in each package) -### Code Conventions +## Code Conventions -- TypeScript with `strict: true` (but `strictNullChecks: false`) -- Target: ES2022, Module: CommonJS -- Packages publish to npm from `dist/` directory +- TypeScript with `strict: true` but `strictNullChecks: false` +- Target: ES2022, Module: CommonJS, ModuleResolution: node +- 2-space indent, single quotes, semicolons required, no trailing commas +- Imports auto-sorted by `simple-import-sort`, unused imports auto-removed +- `@typescript-eslint/no-explicit-any`: allowed (turned off) +- Unused var pattern: prefix with `_` (e.g., `_unused`) - Workspace dependencies use `workspace:^` protocol +- Packages publish from `dist/` directory +- GraphQL pinned to `15.10.1` via overrides diff --git a/graphql/codegen/AGENTS.md b/graphql/codegen/AGENTS.md new file mode 100644 index 000000000..8c0ab6a5f --- /dev/null +++ b/graphql/codegen/AGENTS.md @@ -0,0 +1,32 @@ +# Code Generation Rules + +## 1. Only AST-based code generation + +All per-schema/per-table code generation MUST use Babel AST (`@babel/types` + `generateCode()`). +Never use `lines.push()`, string concatenation, or template literals to build generated TypeScript code. + +Reference implementations: +- `src/core/codegen/orm/model-generator.ts` — per-table ORM model classes +- `src/core/codegen/orm/client-generator.ts` — createClient factory +- `src/core/codegen/orm/custom-ops-generator.ts` — custom query/mutation operations + +## 2. Never any string-based concatenation + +No `lines.push(...)`, no backtick template literals containing code, no string `+` operators +for building generated source files. If you find yourself writing `lines.push(\`import ...\`)`, +stop and use `t.importDeclaration(...)` instead. + +## 3. Giant templates must be actual files that get copied + +Static runtime code that does not vary per-schema belongs in `src/core/codegen/templates/` +as real `.ts` files. These are read at codegen time via `readTemplateFile()` and written +to the output directory with only the header replaced. + +This gives you: +- Syntax highlighting and IDE support while editing templates +- A clear boundary between "code that generates code" and "code that IS the output" + +Reference implementations: +- `src/core/codegen/templates/orm-client.ts` +- `src/core/codegen/templates/query-builder.ts` +- `src/core/codegen/templates/select-types.ts` diff --git a/graphql/codegen/examples/example.schema.graphql b/graphql/codegen/examples/example.schema.graphql new file mode 100644 index 000000000..1bba02d5c --- /dev/null +++ b/graphql/codegen/examples/example.schema.graphql @@ -0,0 +1,593 @@ +"""A universally unique identifier as defined by [RFC 4122](https://tools.ietf.org/html/rfc4122).""" +scalar UUID + +""" +A point in time as described by the [ISO +8601](https://en.wikipedia.org/wiki/ISO_8601) standard. May or may not include a timezone. +""" +scalar Datetime + +"""A location as described by the [GeoJSON](https://geojson.org/) format.""" +scalar JSON + +"""A string representing a cursor for pagination.""" +scalar Cursor + +"""The root query type.""" +type Query { + """Reads and enables pagination through a set of `User`.""" + users( + first: Int + last: Int + offset: Int + before: Cursor + after: Cursor + orderBy: [UsersOrderBy!] = [PRIMARY_KEY_ASC] + filter: UserFilter + condition: UserCondition + ): UsersConnection + + """Reads a single `User` using its globally unique `ID`.""" + user(id: UUID!): User + + """Reads and enables pagination through a set of `Post`.""" + posts( + first: Int + last: Int + offset: Int + before: Cursor + after: Cursor + orderBy: [PostsOrderBy!] = [PRIMARY_KEY_ASC] + filter: PostFilter + condition: PostCondition + ): PostsConnection + + """Reads a single `Post` using its globally unique `ID`.""" + post(id: UUID!): Post + + """Reads and enables pagination through a set of `Comment`.""" + comments( + first: Int + last: Int + offset: Int + before: Cursor + after: Cursor + orderBy: [CommentsOrderBy!] = [PRIMARY_KEY_ASC] + filter: CommentFilter + ): CommentsConnection + + """Reads a single `Comment` using its globally unique `ID`.""" + comment(id: UUID!): Comment + + """Reads and enables pagination through a set of `Tag`.""" + tags( + first: Int + last: Int + offset: Int + before: Cursor + after: Cursor + orderBy: [TagsOrderBy!] = [PRIMARY_KEY_ASC] + ): TagsConnection + + """The currently authenticated user.""" + currentUser: User + + """Search users by name or email.""" + searchUsers(query: String!): [User!] +} + +"""The root mutation type.""" +type Mutation { + """Creates a single `User`.""" + createUser(input: CreateUserInput!): CreateUserPayload + + """Updates a single `User` using its globally unique `ID`.""" + updateUser(input: UpdateUserInput!): UpdateUserPayload + + """Deletes a single `User` using its globally unique `ID`.""" + deleteUser(input: DeleteUserInput!): DeleteUserPayload + + """Creates a single `Post`.""" + createPost(input: CreatePostInput!): CreatePostPayload + + """Updates a single `Post` using its globally unique `ID`.""" + updatePost(input: UpdatePostInput!): UpdatePostPayload + + """Deletes a single `Post` using its globally unique `ID`.""" + deletePost(input: DeletePostInput!): DeletePostPayload + + """Creates a single `Comment`.""" + createComment(input: CreateCommentInput!): CreateCommentPayload + + """Updates a single `Comment` using its globally unique `ID`.""" + updateComment(input: UpdateCommentInput!): UpdateCommentPayload + + """Deletes a single `Comment` using its globally unique `ID`.""" + deleteComment(input: DeleteCommentInput!): DeleteCommentPayload + + """Creates a single `Tag`.""" + createTag(input: CreateTagInput!): CreateTagPayload + + """Authenticate a user and return a JWT token.""" + login(email: String!, password: String!): LoginPayload + + """Register a new user account.""" + register(username: String!, email: String!, password: String!): RegisterPayload +} + +# ============================================================================ +# Entity Types +# ============================================================================ + +type User { + id: UUID! + username: String! + email: String! + displayName: String + bio: String + role: UserRole! + isActive: Boolean! + createdAt: Datetime! + updatedAt: Datetime + + """Reads and enables pagination through a set of `Post`.""" + posts( + first: Int + last: Int + offset: Int + before: Cursor + after: Cursor + orderBy: [PostsOrderBy!] = [PRIMARY_KEY_ASC] + filter: PostFilter + ): PostsConnection! + + """Reads and enables pagination through a set of `Comment`.""" + comments( + first: Int + last: Int + offset: Int + before: Cursor + after: Cursor + ): CommentsConnection! +} + +type Post { + id: UUID! + title: String! + content: String + slug: String! + status: PostStatus! + authorId: UUID! + publishedAt: Datetime + createdAt: Datetime! + updatedAt: Datetime + + """Reads the `User` that authored this post.""" + author: User + + """Reads and enables pagination through a set of `Comment`.""" + comments( + first: Int + last: Int + offset: Int + before: Cursor + after: Cursor + ): CommentsConnection! + + """Reads and enables pagination through a set of `Tag`.""" + tags( + first: Int + last: Int + offset: Int + before: Cursor + after: Cursor + ): TagsConnection! +} + +type Comment { + id: UUID! + body: String! + postId: UUID! + authorId: UUID! + createdAt: Datetime! + updatedAt: Datetime + + """The post this comment belongs to.""" + post: Post + + """The user who authored this comment.""" + author: User +} + +type Tag { + id: UUID! + name: String! + slug: String! + createdAt: Datetime! +} + +# ============================================================================ +# Enums +# ============================================================================ + +enum UserRole { + ADMIN + EDITOR + USER + GUEST +} + +enum PostStatus { + DRAFT + PUBLISHED + ARCHIVED +} + +enum UsersOrderBy { + NATURAL + PRIMARY_KEY_ASC + PRIMARY_KEY_DESC + ID_ASC + ID_DESC + USERNAME_ASC + USERNAME_DESC + EMAIL_ASC + EMAIL_DESC + CREATED_AT_ASC + CREATED_AT_DESC +} + +enum PostsOrderBy { + NATURAL + PRIMARY_KEY_ASC + PRIMARY_KEY_DESC + ID_ASC + ID_DESC + TITLE_ASC + TITLE_DESC + CREATED_AT_ASC + CREATED_AT_DESC + PUBLISHED_AT_ASC + PUBLISHED_AT_DESC +} + +enum CommentsOrderBy { + NATURAL + PRIMARY_KEY_ASC + PRIMARY_KEY_DESC + ID_ASC + ID_DESC + CREATED_AT_ASC + CREATED_AT_DESC +} + +enum TagsOrderBy { + NATURAL + PRIMARY_KEY_ASC + PRIMARY_KEY_DESC + ID_ASC + ID_DESC + NAME_ASC + NAME_DESC +} + +# ============================================================================ +# Connection Types +# ============================================================================ + +type UsersConnection { + nodes: [User!]! + edges: [UsersEdge!]! + pageInfo: PageInfo! + totalCount: Int! +} + +type UsersEdge { + node: User! + cursor: Cursor! +} + +type PostsConnection { + nodes: [Post!]! + edges: [PostsEdge!]! + pageInfo: PageInfo! + totalCount: Int! +} + +type PostsEdge { + node: Post! + cursor: Cursor! +} + +type CommentsConnection { + nodes: [Comment!]! + edges: [CommentsEdge!]! + pageInfo: PageInfo! + totalCount: Int! +} + +type CommentsEdge { + node: Comment! + cursor: Cursor! +} + +type TagsConnection { + nodes: [Tag!]! + edges: [TagsEdge!]! + pageInfo: PageInfo! + totalCount: Int! +} + +type TagsEdge { + node: Tag! + cursor: Cursor! +} + +type PageInfo { + hasNextPage: Boolean! + hasPreviousPage: Boolean! + startCursor: Cursor + endCursor: Cursor +} + +# ============================================================================ +# Filter Types +# ============================================================================ + +input UserFilter { + id: UUIDFilter + username: StringFilter + email: StringFilter + role: UserRoleFilter + isActive: BooleanFilter + and: [UserFilter!] + or: [UserFilter!] + not: UserFilter +} + +input PostFilter { + id: UUIDFilter + title: StringFilter + status: PostStatusFilter + authorId: UUIDFilter + and: [PostFilter!] + or: [PostFilter!] + not: PostFilter +} + +input CommentFilter { + id: UUIDFilter + postId: UUIDFilter + authorId: UUIDFilter + and: [CommentFilter!] + or: [CommentFilter!] + not: CommentFilter +} + +input UUIDFilter { + equalTo: UUID + notEqualTo: UUID + in: [UUID!] + notIn: [UUID!] + isNull: Boolean +} + +input StringFilter { + equalTo: String + notEqualTo: String + in: [String!] + notIn: [String!] + includes: String + startsWith: String + endsWith: String + isNull: Boolean +} + +input BooleanFilter { + equalTo: Boolean + notEqualTo: Boolean + isNull: Boolean +} + +input UserRoleFilter { + equalTo: UserRole + notEqualTo: UserRole + in: [UserRole!] + notIn: [UserRole!] +} + +input PostStatusFilter { + equalTo: PostStatus + notEqualTo: PostStatus + in: [PostStatus!] + notIn: [PostStatus!] +} + +# ============================================================================ +# Condition Types +# ============================================================================ + +input UserCondition { + id: UUID + username: String + email: String +} + +input PostCondition { + id: UUID + title: String + authorId: UUID +} + +# ============================================================================ +# Mutation Input Types +# ============================================================================ + +input CreateUserInput { + clientMutationId: String + user: UserInput! +} + +input UserInput { + username: String! + email: String! + displayName: String + bio: String + role: UserRole +} + +input UpdateUserInput { + clientMutationId: String + id: UUID! + patch: UserPatch! +} + +input UserPatch { + username: String + email: String + displayName: String + bio: String + role: UserRole + isActive: Boolean +} + +input DeleteUserInput { + clientMutationId: String + id: UUID! +} + +input CreatePostInput { + clientMutationId: String + post: PostInput! +} + +input PostInput { + title: String! + content: String + slug: String! + status: PostStatus + authorId: UUID! +} + +input UpdatePostInput { + clientMutationId: String + id: UUID! + patch: PostPatch! +} + +input PostPatch { + title: String + content: String + slug: String + status: PostStatus + publishedAt: Datetime +} + +input DeletePostInput { + clientMutationId: String + id: UUID! +} + +input CreateCommentInput { + clientMutationId: String + comment: CommentInput! +} + +input CommentInput { + body: String! + postId: UUID! + authorId: UUID! +} + +input UpdateCommentInput { + clientMutationId: String + id: UUID! + patch: CommentPatch! +} + +input CommentPatch { + body: String +} + +input DeleteCommentInput { + clientMutationId: String + id: UUID! +} + +input CreateTagInput { + clientMutationId: String + tag: TagInput! +} + +input TagInput { + name: String! + slug: String! +} + +# ============================================================================ +# Mutation Payload Types +# ============================================================================ + +type CreateUserPayload { + clientMutationId: String + user: User +} + +type UpdateUserPayload { + clientMutationId: String + user: User +} + +type DeleteUserPayload { + clientMutationId: String + user: User +} + +type CreatePostPayload { + clientMutationId: String + post: Post +} + +type UpdatePostPayload { + clientMutationId: String + post: Post +} + +type DeletePostPayload { + clientMutationId: String + post: Post +} + +type CreateCommentPayload { + clientMutationId: String + comment: Comment +} + +type UpdateCommentPayload { + clientMutationId: String + comment: Comment +} + +type DeleteCommentPayload { + clientMutationId: String + comment: Comment +} + +type CreateTagPayload { + clientMutationId: String + tag: Tag +} + +# ============================================================================ +# Custom Operation Payload Types +# ============================================================================ + +type LoginPayload { + token: String! + user: User! +} + +type RegisterPayload { + token: String! + user: User! +} diff --git a/graphql/codegen/examples/multi-target.config.ts b/graphql/codegen/examples/multi-target.config.ts new file mode 100644 index 000000000..75f3628c0 --- /dev/null +++ b/graphql/codegen/examples/multi-target.config.ts @@ -0,0 +1,15 @@ +import type { GraphQLSDKConfigTarget } from '../src/types/config'; + +/** + * Multi-target example config for graphql-codegen + * + * Usage with CLI flags to select mode: + * tsx src/cli/index.ts --config examples/multi-target.config.ts --react-query + * tsx src/cli/index.ts --config examples/multi-target.config.ts --orm + */ +const config: GraphQLSDKConfigTarget = { + endpoint: 'http://api.localhost:3000/graphql', + output: './examples/output/generated-sdk-public', +}; + +export default config; diff --git a/graphql/codegen/jest.config.js b/graphql/codegen/jest.config.js index 86f911c5d..475aa4db7 100644 --- a/graphql/codegen/jest.config.js +++ b/graphql/codegen/jest.config.js @@ -7,9 +7,9 @@ module.exports = { 'ts-jest', { babelConfig: false, - tsconfig: 'tsconfig.json', - }, - ], + tsconfig: 'tsconfig.json' + } + ] }, transformIgnorePatterns: [`/node_modules/*`], testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$', diff --git a/graphql/codegen/src/__tests__/codegen/__snapshots__/client-generator.test.ts.snap b/graphql/codegen/src/__tests__/codegen/__snapshots__/client-generator.test.ts.snap index 11e9fad8f..df8457471 100644 --- a/graphql/codegen/src/__tests__/codegen/__snapshots__/client-generator.test.ts.snap +++ b/graphql/codegen/src/__tests__/codegen/__snapshots__/client-generator.test.ts.snap @@ -107,13 +107,13 @@ exports[`client-generator generateOrmClientFile generates OrmClient class with e import type { GraphQLAdapter, GraphQLError, - QueryResult, + QueryResult } from '@constructive-io/graphql-types'; export type { GraphQLAdapter, GraphQLError, - QueryResult, + QueryResult } from '@constructive-io/graphql-types'; /** @@ -139,19 +139,19 @@ export class FetchAdapter implements GraphQLAdapter { headers: { 'Content-Type': 'application/json', Accept: 'application/json', - ...this.headers, + ...this.headers }, body: JSON.stringify({ query: document, - variables: variables ?? {}, - }), + variables: variables ?? {} + }) }); if (!response.ok) { return { ok: false, data: null, - errors: [{ message: \`HTTP \${response.status}: \${response.statusText}\` }], + errors: [{ message: \`HTTP \${response.status}: \${response.statusText}\` }] }; } @@ -164,14 +164,14 @@ export class FetchAdapter implements GraphQLAdapter { return { ok: false, data: null, - errors: json.errors, + errors: json.errors }; } return { ok: true, data: json.data as T, - errors: undefined, + errors: undefined }; } @@ -301,23 +301,26 @@ export interface UpdateArgs { select?: TSelect; } -export interface DeleteArgs { +export type FindOneArgs< + TSelect, + TIdName extends string = 'id', + TId = string +> = { + select?: TSelect; +} & Record; + +export interface DeleteArgs { where: TWhere; + select?: TSelect; } /** * Recursively validates select objects, rejecting unknown keys. * - * This type ensures that users can only select fields that actually exist - * in the GraphQL schema. It returns \`never\` if any excess keys are found - * at any nesting level, causing a TypeScript compile error. - * - * Why this is needed: - * TypeScript's excess property checking has a quirk where it only catches - * invalid fields when they are the ONLY fields. When mixed with valid fields - * (e.g., \`{ id: true, invalidField: true }\`), the structural typing allows - * the excess property through. This type explicitly checks for and rejects - * such cases. + * NOTE: This type is intentionally NOT used in generated parameter positions + * (conditional types block IDE autocompletion). Parameters use \`S\` directly + * with \`S extends XxxSelect\` constraints, which provides full + * autocompletion via TypeScript's contextual typing. * * @example * // This will cause a type error because 'invalid' doesn't exist: @@ -334,15 +337,25 @@ export type DeepExact = T extends Shape ? { [K in keyof T]: K extends keyof Shape ? T[K] extends { select: infer NS } - ? Shape[K] extends { select?: infer ShapeNS } - ? { select: DeepExact> } - : T[K] + ? Extract extends { select?: infer ShapeNS } + ? DeepExact< + Omit & { select: DeepExact> }, + Extract + > + : never : T[K] : never; } : never : never; +/** + * Enforces exact select shape while keeping contextual typing on \`S extends XxxSelect\`. + * Use this as an intersection in overloads: + * \`{ select: S } & StrictSelect\`. + */ +export type StrictSelect = S extends DeepExact ? {} : never; + /** * Infer result type from select configuration */ diff --git a/graphql/codegen/src/__tests__/codegen/__snapshots__/input-types-generator.test.ts.snap b/graphql/codegen/src/__tests__/codegen/__snapshots__/input-types-generator.test.ts.snap index 523156dd3..816974a38 100644 --- a/graphql/codegen/src/__tests__/codegen/__snapshots__/input-types-generator.test.ts.snap +++ b/graphql/codegen/src/__tests__/codegen/__snapshots__/input-types-generator.test.ts.snap @@ -469,7 +469,17 @@ export interface UpdateCommentInput { export interface DeleteCommentInput { clientMutationId?: string; id: string; -}" +} +// ============ Connection Fields Map ============ +export const connectionFieldsMap = { + "User": { + "posts": "Post", + "comments": "Comment" + }, + "Post": { + "comments": "Comment" + } +} as Record>;" `; exports[`generateInputTypesFile generates complete types file for single table 1`] = ` @@ -785,7 +795,9 @@ export interface UpdateUserInput { export interface DeleteUserInput { clientMutationId?: string; id: string; -}" +} +// ============ Connection Fields Map ============ +export const connectionFieldsMap = {} as Record>;" `; exports[`generateInputTypesFile generates custom input types from TypeRegistry 1`] = ` @@ -1102,6 +1114,8 @@ export interface DeleteUserInput { clientMutationId?: string; id: string; } +// ============ Connection Fields Map ============ +export const connectionFieldsMap = {} as Record>; // ============ Custom Input Types (from schema) ============ export interface LoginInput { email: string; @@ -1430,6 +1444,8 @@ export interface DeleteUserInput { clientMutationId?: string; id: string; } +// ============ Connection Fields Map ============ +export const connectionFieldsMap = {} as Record>; // ============ Custom Input Types (from schema) ============ export interface LoginInput { email: string; @@ -1831,7 +1847,13 @@ export interface UpdateProfileInput { export interface DeleteProfileInput { clientMutationId?: string; id: string; -}" +} +// ============ Connection Fields Map ============ +export const connectionFieldsMap = { + "User": { + "posts": "Post" + } +} as Record>;" `; exports[`generateInputTypesFile generates types with manyToMany relations 1`] = ` @@ -2209,7 +2231,16 @@ export interface UpdateCategoryInput { export interface DeleteCategoryInput { clientMutationId?: string; id: string; -}" +} +// ============ Connection Fields Map ============ +export const connectionFieldsMap = { + "Post": { + "comments": "Comment" + }, + "Category": { + "posts": "Post" + } +} as Record>;" `; exports[`generateInputTypesFile handles empty tables array 1`] = ` @@ -2437,5 +2468,7 @@ export interface UUIDListFilter { anyLessThanOrEqualTo?: string; anyGreaterThan?: string; anyGreaterThanOrEqualTo?: string; -}" +} +// ============ Connection Fields Map ============ +export const connectionFieldsMap = {} as Record>;" `; diff --git a/graphql/codegen/src/__tests__/codegen/__snapshots__/model-generator.test.ts.snap b/graphql/codegen/src/__tests__/codegen/__snapshots__/model-generator.test.ts.snap index dc51d712f..4ed4ce22b 100644 --- a/graphql/codegen/src/__tests__/codegen/__snapshots__/model-generator.test.ts.snap +++ b/graphql/codegen/src/__tests__/codegen/__snapshots__/model-generator.test.ts.snap @@ -7,18 +7,30 @@ exports[`model-generator generates model with all CRUD methods 1`] = ` * DO NOT EDIT - changes will be overwritten */ import { OrmClient } from "../client"; -import { QueryBuilder, buildFindManyDocument, buildFindFirstDocument, buildCreateDocument, buildUpdateDocument, buildDeleteDocument } from "../query-builder"; -import type { ConnectionResult, FindManyArgs, FindFirstArgs, CreateArgs, UpdateArgs, DeleteArgs, InferSelectResult, DeepExact } from "../select-types"; +import { QueryBuilder, buildFindManyDocument, buildFindFirstDocument, buildFindOneDocument, buildCreateDocument, buildUpdateByPkDocument, buildDeleteByPkDocument } from "../query-builder"; +import type { ConnectionResult, FindManyArgs, FindFirstArgs, CreateArgs, UpdateArgs, DeleteArgs, InferSelectResult, StrictSelect } from "../select-types"; import type { User, UserWithRelations, UserSelect, UserFilter, UsersOrderBy, CreateUserInput, UpdateUserInput, UserPatch } from "../input-types"; +import { connectionFieldsMap } from "../input-types"; +const defaultSelect = { + id: true +} as const; export class UserModel { constructor(private client: OrmClient) {} - findMany(args?: FindManyArgs, UserFilter, UsersOrderBy>): QueryBuilder<{ + findMany(args: FindManyArgs & { + select: S; + } & StrictSelect): QueryBuilder<{ users: ConnectionResult>; - }> { + }>; + findMany(args?: Omit, "select"> & { + select?: undefined; + }): QueryBuilder<{ + users: ConnectionResult>; + }>; + findMany(args?: FindManyArgs) { const { document, variables - } = buildFindManyDocument("User", "users", args?.select, { + } = buildFindManyDocument("User", "users", args?.select ?? defaultSelect, { where: args?.where, orderBy: args?.orderBy as string[] | undefined, first: args?.first, @@ -26,7 +38,7 @@ export class UserModel { after: args?.after, before: args?.before, offset: args?.offset - }, "UserFilter", "UsersOrderBy"); + }, "UserFilter", "UsersOrderBy", connectionFieldsMap); return new QueryBuilder({ client: this.client, operation: "query", @@ -36,17 +48,27 @@ export class UserModel { variables }); } - findFirst(args?: FindFirstArgs, UserFilter>): QueryBuilder<{ + findFirst(args: FindFirstArgs & { + select: S; + } & StrictSelect): QueryBuilder<{ users: { nodes: InferSelectResult[]; }; - }> { + }>; + findFirst(args?: Omit, "select"> & { + select?: undefined; + }): QueryBuilder<{ + users: { + nodes: InferSelectResult[]; + }; + }>; + findFirst(args?: FindFirstArgs) { const { document, variables - } = buildFindFirstDocument("User", "users", args?.select, { + } = buildFindFirstDocument("User", "users", args?.select ?? defaultSelect, { where: args?.where - }, "UserFilter"); + }, "UserFilter", connectionFieldsMap); return new QueryBuilder({ client: this.client, operation: "query", @@ -56,15 +78,53 @@ export class UserModel { variables }); } - create(args: CreateArgs, CreateUserInput["user"]>): QueryBuilder<{ + findOne(args: { + id: string; + select: S; + } & StrictSelect): QueryBuilder<{ + user: InferSelectResult | null; + }>; + findOne(args: { + id: string; + }): QueryBuilder<{ + user: InferSelectResult | null; + }>; + findOne(args: { + id: string; + select?: UserSelect; + }) { + const { + document, + variables + } = buildFindOneDocument("User", "user", args.id, args.select ?? defaultSelect, "id", "UUID!", connectionFieldsMap); + return new QueryBuilder({ + client: this.client, + operation: "query", + operationName: "User", + fieldName: "user", + document, + variables + }); + } + create(args: CreateArgs & { + select: S; + } & StrictSelect): QueryBuilder<{ createUser: { user: InferSelectResult; }; - }> { + }>; + create(args: Omit, "select"> & { + select?: undefined; + }): QueryBuilder<{ + createUser: { + user: InferSelectResult; + }; + }>; + create(args: CreateArgs) { const { document, variables - } = buildCreateDocument("User", "createUser", "user", args.select, args.data, "CreateUserInput"); + } = buildCreateDocument("User", "createUser", "user", args.select ?? defaultSelect, args.data, "CreateUserInput", connectionFieldsMap); return new QueryBuilder({ client: this.client, operation: "mutation", @@ -74,17 +134,31 @@ export class UserModel { variables }); } - update(args: UpdateArgs, { + update(args: UpdateArgs): QueryBuilder<{ + }, UserPatch> & { + select: S; + } & StrictSelect): QueryBuilder<{ updateUser: { user: InferSelectResult; }; - }> { + }>; + update(args: Omit, "select"> & { + select?: undefined; + }): QueryBuilder<{ + updateUser: { + user: InferSelectResult; + }; + }>; + update(args: UpdateArgs) { const { document, variables - } = buildUpdateDocument("User", "updateUser", "user", args.select, args.where, args.data, "UpdateUserInput"); + } = buildUpdateByPkDocument("User", "updateUser", "user", args.select ?? defaultSelect, args.where.id, args.data, "UpdateUserInput", "id", connectionFieldsMap); return new QueryBuilder({ client: this.client, operation: "mutation", @@ -94,19 +168,31 @@ export class UserModel { variables }); } - delete(args: DeleteArgs<{ + delete(args: DeleteArgs<{ + id: string; + }, S> & { + select: S; + } & StrictSelect): QueryBuilder<{ + deleteUser: { + user: InferSelectResult; + }; + }>; + delete(args: Omit): QueryBuilder<{ + }, UserSelect>, "select"> & { + select?: undefined; + }): QueryBuilder<{ deleteUser: { - user: { - id: string; - }; + user: InferSelectResult; }; - }> { + }>; + delete(args: DeleteArgs<{ + id: string; + }, UserSelect>) { const { document, variables - } = buildDeleteDocument("User", "deleteUser", "user", args.where, "DeleteUserInput"); + } = buildDeleteByPkDocument("User", "deleteUser", "user", args.where.id, "DeleteUserInput", "id", args.select ?? defaultSelect, connectionFieldsMap); return new QueryBuilder({ client: this.client, operation: "mutation", @@ -126,18 +212,30 @@ exports[`model-generator generates model without update/delete when not availabl * DO NOT EDIT - changes will be overwritten */ import { OrmClient } from "../client"; -import { QueryBuilder, buildFindManyDocument, buildFindFirstDocument, buildCreateDocument, buildUpdateDocument, buildDeleteDocument } from "../query-builder"; -import type { ConnectionResult, FindManyArgs, FindFirstArgs, CreateArgs, UpdateArgs, DeleteArgs, InferSelectResult, DeepExact } from "../select-types"; +import { QueryBuilder, buildFindManyDocument, buildFindFirstDocument, buildFindOneDocument, buildCreateDocument, buildUpdateByPkDocument, buildDeleteByPkDocument } from "../query-builder"; +import type { ConnectionResult, FindManyArgs, FindFirstArgs, CreateArgs, UpdateArgs, DeleteArgs, InferSelectResult, StrictSelect } from "../select-types"; import type { AuditLog, AuditLogWithRelations, AuditLogSelect, AuditLogFilter, AuditLogsOrderBy, CreateAuditLogInput, UpdateAuditLogInput, AuditLogPatch } from "../input-types"; +import { connectionFieldsMap } from "../input-types"; +const defaultSelect = { + id: true +} as const; export class AuditLogModel { constructor(private client: OrmClient) {} - findMany(args?: FindManyArgs, AuditLogFilter, AuditLogsOrderBy>): QueryBuilder<{ + findMany(args: FindManyArgs & { + select: S; + } & StrictSelect): QueryBuilder<{ auditLogs: ConnectionResult>; - }> { + }>; + findMany(args?: Omit, "select"> & { + select?: undefined; + }): QueryBuilder<{ + auditLogs: ConnectionResult>; + }>; + findMany(args?: FindManyArgs) { const { document, variables - } = buildFindManyDocument("AuditLog", "auditLogs", args?.select, { + } = buildFindManyDocument("AuditLog", "auditLogs", args?.select ?? defaultSelect, { where: args?.where, orderBy: args?.orderBy as string[] | undefined, first: args?.first, @@ -145,7 +243,7 @@ export class AuditLogModel { after: args?.after, before: args?.before, offset: args?.offset - }, "AuditLogFilter", "AuditLogsOrderBy"); + }, "AuditLogFilter", "AuditLogsOrderBy", connectionFieldsMap); return new QueryBuilder({ client: this.client, operation: "query", @@ -155,17 +253,27 @@ export class AuditLogModel { variables }); } - findFirst(args?: FindFirstArgs, AuditLogFilter>): QueryBuilder<{ + findFirst(args: FindFirstArgs & { + select: S; + } & StrictSelect): QueryBuilder<{ auditLogs: { nodes: InferSelectResult[]; }; - }> { + }>; + findFirst(args?: Omit, "select"> & { + select?: undefined; + }): QueryBuilder<{ + auditLogs: { + nodes: InferSelectResult[]; + }; + }>; + findFirst(args?: FindFirstArgs) { const { document, variables - } = buildFindFirstDocument("AuditLog", "auditLogs", args?.select, { + } = buildFindFirstDocument("AuditLog", "auditLogs", args?.select ?? defaultSelect, { where: args?.where - }, "AuditLogFilter"); + }, "AuditLogFilter", connectionFieldsMap); return new QueryBuilder({ client: this.client, operation: "query", @@ -175,15 +283,53 @@ export class AuditLogModel { variables }); } - create(args: CreateArgs, CreateAuditLogInput["auditLog"]>): QueryBuilder<{ + findOne(args: { + id: string; + select: S; + } & StrictSelect): QueryBuilder<{ + auditLog: InferSelectResult | null; + }>; + findOne(args: { + id: string; + }): QueryBuilder<{ + auditLog: InferSelectResult | null; + }>; + findOne(args: { + id: string; + select?: AuditLogSelect; + }) { + const { + document, + variables + } = buildFindOneDocument("AuditLog", "auditLog", args.id, args.select ?? defaultSelect, "id", "UUID!", connectionFieldsMap); + return new QueryBuilder({ + client: this.client, + operation: "query", + operationName: "AuditLog", + fieldName: "auditLog", + document, + variables + }); + } + create(args: CreateArgs & { + select: S; + } & StrictSelect): QueryBuilder<{ createAuditLog: { auditLog: InferSelectResult; }; - }> { + }>; + create(args: Omit, "select"> & { + select?: undefined; + }): QueryBuilder<{ + createAuditLog: { + auditLog: InferSelectResult; + }; + }>; + create(args: CreateArgs) { const { document, variables - } = buildCreateDocument("AuditLog", "createAuditLog", "auditLog", args.select, args.data, "CreateAuditLogInput"); + } = buildCreateDocument("AuditLog", "createAuditLog", "auditLog", args.select ?? defaultSelect, args.data, "CreateAuditLogInput", connectionFieldsMap); return new QueryBuilder({ client: this.client, operation: "mutation", @@ -203,18 +349,30 @@ exports[`model-generator handles custom query/mutation names 1`] = ` * DO NOT EDIT - changes will be overwritten */ import { OrmClient } from "../client"; -import { QueryBuilder, buildFindManyDocument, buildFindFirstDocument, buildCreateDocument, buildUpdateDocument, buildDeleteDocument } from "../query-builder"; -import type { ConnectionResult, FindManyArgs, FindFirstArgs, CreateArgs, UpdateArgs, DeleteArgs, InferSelectResult, DeepExact } from "../select-types"; +import { QueryBuilder, buildFindManyDocument, buildFindFirstDocument, buildFindOneDocument, buildCreateDocument, buildUpdateByPkDocument, buildDeleteByPkDocument } from "../query-builder"; +import type { ConnectionResult, FindManyArgs, FindFirstArgs, CreateArgs, UpdateArgs, DeleteArgs, InferSelectResult, StrictSelect } from "../select-types"; import type { Organization, OrganizationWithRelations, OrganizationSelect, OrganizationFilter, OrganizationsOrderBy, CreateOrganizationInput, UpdateOrganizationInput, OrganizationPatch } from "../input-types"; +import { connectionFieldsMap } from "../input-types"; +const defaultSelect = { + id: true +} as const; export class OrganizationModel { constructor(private client: OrmClient) {} - findMany(args?: FindManyArgs, OrganizationFilter, OrganizationsOrderBy>): QueryBuilder<{ + findMany(args: FindManyArgs & { + select: S; + } & StrictSelect): QueryBuilder<{ allOrganizations: ConnectionResult>; - }> { + }>; + findMany(args?: Omit, "select"> & { + select?: undefined; + }): QueryBuilder<{ + allOrganizations: ConnectionResult>; + }>; + findMany(args?: FindManyArgs) { const { document, variables - } = buildFindManyDocument("Organization", "allOrganizations", args?.select, { + } = buildFindManyDocument("Organization", "allOrganizations", args?.select ?? defaultSelect, { where: args?.where, orderBy: args?.orderBy as string[] | undefined, first: args?.first, @@ -222,7 +380,7 @@ export class OrganizationModel { after: args?.after, before: args?.before, offset: args?.offset - }, "OrganizationFilter", "OrganizationsOrderBy"); + }, "OrganizationFilter", "OrganizationsOrderBy", connectionFieldsMap); return new QueryBuilder({ client: this.client, operation: "query", @@ -232,17 +390,27 @@ export class OrganizationModel { variables }); } - findFirst(args?: FindFirstArgs, OrganizationFilter>): QueryBuilder<{ + findFirst(args: FindFirstArgs & { + select: S; + } & StrictSelect): QueryBuilder<{ allOrganizations: { nodes: InferSelectResult[]; }; - }> { + }>; + findFirst(args?: Omit, "select"> & { + select?: undefined; + }): QueryBuilder<{ + allOrganizations: { + nodes: InferSelectResult[]; + }; + }>; + findFirst(args?: FindFirstArgs) { const { document, variables - } = buildFindFirstDocument("Organization", "allOrganizations", args?.select, { + } = buildFindFirstDocument("Organization", "allOrganizations", args?.select ?? defaultSelect, { where: args?.where - }, "OrganizationFilter"); + }, "OrganizationFilter", connectionFieldsMap); return new QueryBuilder({ client: this.client, operation: "query", @@ -252,15 +420,53 @@ export class OrganizationModel { variables }); } - create(args: CreateArgs, CreateOrganizationInput["organization"]>): QueryBuilder<{ + findOne(args: { + id: string; + select: S; + } & StrictSelect): QueryBuilder<{ + organizationById: InferSelectResult | null; + }>; + findOne(args: { + id: string; + }): QueryBuilder<{ + organizationById: InferSelectResult | null; + }>; + findOne(args: { + id: string; + select?: OrganizationSelect; + }) { + const { + document, + variables + } = buildFindOneDocument("Organization", "organizationById", args.id, args.select ?? defaultSelect, "id", "UUID!", connectionFieldsMap); + return new QueryBuilder({ + client: this.client, + operation: "query", + operationName: "Organization", + fieldName: "organizationById", + document, + variables + }); + } + create(args: CreateArgs & { + select: S; + } & StrictSelect): QueryBuilder<{ registerOrganization: { organization: InferSelectResult; }; - }> { + }>; + create(args: Omit, "select"> & { + select?: undefined; + }): QueryBuilder<{ + registerOrganization: { + organization: InferSelectResult; + }; + }>; + create(args: CreateArgs) { const { document, variables - } = buildCreateDocument("Organization", "registerOrganization", "organization", args.select, args.data, "CreateOrganizationInput"); + } = buildCreateDocument("Organization", "registerOrganization", "organization", args.select ?? defaultSelect, args.data, "CreateOrganizationInput", connectionFieldsMap); return new QueryBuilder({ client: this.client, operation: "mutation", @@ -270,17 +476,31 @@ export class OrganizationModel { variables }); } - update(args: UpdateArgs, { + update(args: UpdateArgs): QueryBuilder<{ + }, OrganizationPatch> & { + select: S; + } & StrictSelect): QueryBuilder<{ modifyOrganization: { organization: InferSelectResult; }; - }> { + }>; + update(args: Omit, "select"> & { + select?: undefined; + }): QueryBuilder<{ + modifyOrganization: { + organization: InferSelectResult; + }; + }>; + update(args: UpdateArgs) { const { document, variables - } = buildUpdateDocument("Organization", "modifyOrganization", "organization", args.select, args.where, args.data, "UpdateOrganizationInput"); + } = buildUpdateByPkDocument("Organization", "modifyOrganization", "organization", args.select ?? defaultSelect, args.where.id, args.data, "UpdateOrganizationInput", "id", connectionFieldsMap); return new QueryBuilder({ client: this.client, operation: "mutation", @@ -290,19 +510,31 @@ export class OrganizationModel { variables }); } - delete(args: DeleteArgs<{ + delete(args: DeleteArgs<{ id: string; - }>): QueryBuilder<{ + }, S> & { + select: S; + } & StrictSelect): QueryBuilder<{ removeOrganization: { - organization: { - id: string; - }; + organization: InferSelectResult; }; - }> { + }>; + delete(args: Omit, "select"> & { + select?: undefined; + }): QueryBuilder<{ + removeOrganization: { + organization: InferSelectResult; + }; + }>; + delete(args: DeleteArgs<{ + id: string; + }, OrganizationSelect>) { const { document, variables - } = buildDeleteDocument("Organization", "removeOrganization", "organization", args.where, "DeleteOrganizationInput"); + } = buildDeleteByPkDocument("Organization", "removeOrganization", "organization", args.where.id, "DeleteOrganizationInput", "id", args.select ?? defaultSelect, connectionFieldsMap); return new QueryBuilder({ client: this.client, operation: "mutation", diff --git a/graphql/codegen/src/__tests__/codegen/__snapshots__/query-builder.test.ts.snap b/graphql/codegen/src/__tests__/codegen/__snapshots__/query-builder.test.ts.snap new file mode 100644 index 000000000..f679d5605 --- /dev/null +++ b/graphql/codegen/src/__tests__/codegen/__snapshots__/query-builder.test.ts.snap @@ -0,0 +1,227 @@ +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing + +exports[`query-builder snapshots findMany document with filter and pagination 1`] = ` +"query UserQuery($where: UserFilter, $orderBy: [UsersOrderBy!], $first: Int) { + users(filter: $where, orderBy: $orderBy, first: $first) { + nodes { + id + name + email + } + totalCount + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + } +} +" +`; + +exports[`query-builder snapshots findMany document with nested connections via connectionFieldsMap 1`] = ` +"query UserQuery { + users { + nodes { + id + name + posts { + nodes { + id + title + } + totalCount + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + } + comments { + nodes { + id + } + totalCount + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + } + } + totalCount + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + } +} +" +`; + +exports[`query-builder snapshots findMany with deeply nested connections (3 levels) 1`] = ` +"query TestQuery { + users { + nodes { + id + posts { + nodes { + id + title + comments { + nodes { + id + body + } + totalCount + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + } + } + totalCount + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + } + } + totalCount + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + } +} +" +`; + +exports[`query-builder snapshots findMany with mixed connection and singular relations 1`] = ` +"query TestQuery { + users { + nodes { + id + name + profile { + bio + avatar + } + posts { + nodes { + id + title + } + totalCount + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + } + comments { + nodes { + id + body + } + totalCount + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + } + } + totalCount + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + } +} +" +`; + +exports[`query-builder snapshots findMany with nested connection fields 1`] = ` +"query TestQuery { + users { + nodes { + id + name + posts { + nodes { + id + title + body + } + totalCount + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + } + } + totalCount + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + } +} +" +`; + +exports[`query-builder snapshots findMany without connectionFieldsMap (no wrapping) 1`] = ` +"query TestQuery { + users { + nodes { + id + name + posts { + id + title + } + } + totalCount + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + } +} +" +`; + +exports[`query-builder snapshots mutation document 1`] = ` +"mutation CreateUserMutation($input: CreateUserInput!) { + createUser(input: $input) { + user { + id + name + email + } + } +} +" +`; diff --git a/graphql/codegen/src/__tests__/codegen/__snapshots__/react-query-hooks.test.ts.snap b/graphql/codegen/src/__tests__/codegen/__snapshots__/react-query-hooks.test.ts.snap index efafdb00e..68b86cdec 100644 --- a/graphql/codegen/src/__tests__/codegen/__snapshots__/react-query-hooks.test.ts.snap +++ b/graphql/codegen/src/__tests__/codegen/__snapshots__/react-query-hooks.test.ts.snap @@ -57,8 +57,6 @@ exports[`Barrel File Generators generateMainBarrel generates main barrel with al * \`\`\` */ export * from "./client"; -export * from "./types"; -export * from "./schema-types"; export * from "./query-keys"; export * from "./mutation-keys"; export * from "./invalidation"; @@ -97,7 +95,6 @@ exports[`Barrel File Generators generateMainBarrel generates main barrel without * \`\`\` */ export * from "./client"; -export * from "./types"; export * from "./queries"; export * from "./mutations";" `; @@ -133,8 +130,6 @@ exports[`Barrel File Generators generateMainBarrel generates main barrel without * \`\`\` */ export * from "./client"; -export * from "./types"; -export * from "./schema-types"; export * from "./queries";" `; @@ -193,32 +188,55 @@ exports[`Custom Mutation Hook Generators generateCustomMutationHook generates cu */ import { useMutation } from "@tanstack/react-query"; -import type { UseMutationOptions } from "@tanstack/react-query"; -import { execute } from "../client"; -import type { LoginPayload } from "../schema-types"; +import type { UseMutationOptions, UseMutationResult } from "@tanstack/react-query"; +import { getClient } from "../client"; +import { buildSelectionArgs } from "../selection"; +import type { SelectionConfig } from "../selection"; import { customMutationKeys } from "../mutation-keys"; -/** GraphQL mutation document */ -export const loginMutationDocument = \` -mutation LoginMutation($email: String!, $password: String!) { - login(email: $email, password: $password) { - token - } -} -\`; -export interface LoginMutationVariables { - email: string; - password: string; -} -export interface LoginMutationResult { - login: LoginPayload; -} -export function useLoginMutation(options?: Omit, 'mutationFn'>) { +import type { LoginVariables } from "../../orm/mutation"; +import type { LoginPayloadSelect, LoginPayload } from "../../orm/input-types"; +import type { InferSelectResult, StrictSelect } from "../../orm/select-types"; +export type { LoginVariables } from "../../orm/mutation"; +export type { LoginPayloadSelect } from "../../orm/input-types"; +const defaultSelect = { + token: true +} as const; +export function useLoginMutation(params: { + selection: ({ + fields: S; + } & StrictSelect); +} & Omit; +}, Error, LoginVariables>, "mutationFn">): UseMutationResult<{ + login: InferSelectResult; +}, Error, LoginVariables>; +export function useLoginMutation(params?: { + selection?: ({ + fields?: undefined; + }); +} & Omit; +}, Error, LoginVariables>, "mutationFn">): UseMutationResult<{ + login: InferSelectResult; +}, Error, LoginVariables>; +export function useLoginMutation(params?: { + selection?: SelectionConfig; +} & Omit, "mutationFn">) { + const args = buildSelectionArgs(params?.selection); + const { + selection: _selection, + ...mutationOptions + } = params ?? {}; + void _selection; return useMutation({ mutationKey: customMutationKeys.login(), - mutationFn: (variables: LoginMutationVariables) => execute(loginMutationDocument, variables), - ...options + mutationFn: (variables: LoginVariables) => getClient().mutation.login(variables, { + select: (args?.select ?? defaultSelect) as LoginPayloadSelect + }).unwrap(), + ...mutationOptions }); -}" +} +" `; exports[`Custom Mutation Hook Generators generateCustomMutationHook generates custom mutation hook with input object argument 1`] = ` @@ -229,31 +247,55 @@ exports[`Custom Mutation Hook Generators generateCustomMutationHook generates cu */ import { useMutation } from "@tanstack/react-query"; -import type { UseMutationOptions } from "@tanstack/react-query"; -import { execute } from "../client"; -import type { RegisterInput, RegisterPayload } from "../schema-types"; +import type { UseMutationOptions, UseMutationResult } from "@tanstack/react-query"; +import { getClient } from "../client"; +import { buildSelectionArgs } from "../selection"; +import type { SelectionConfig } from "../selection"; import { customMutationKeys } from "../mutation-keys"; -/** GraphQL mutation document */ -export const registerMutationDocument = \` -mutation RegisterMutation($input: RegisterInput!) { - register(input: $input) { - token - } -} -\`; -export interface RegisterMutationVariables { - input: RegisterInput; -} -export interface RegisterMutationResult { - register: RegisterPayload; -} -export function useRegisterMutation(options?: Omit, 'mutationFn'>) { +import type { RegisterVariables } from "../../orm/mutation"; +import type { RegisterPayloadSelect, RegisterPayload } from "../../orm/input-types"; +import type { InferSelectResult, StrictSelect } from "../../orm/select-types"; +export type { RegisterVariables } from "../../orm/mutation"; +export type { RegisterPayloadSelect } from "../../orm/input-types"; +const defaultSelect = { + token: true +} as const; +export function useRegisterMutation(params: { + selection: ({ + fields: S; + } & StrictSelect); +} & Omit; +}, Error, RegisterVariables>, "mutationFn">): UseMutationResult<{ + register: InferSelectResult; +}, Error, RegisterVariables>; +export function useRegisterMutation(params?: { + selection?: ({ + fields?: undefined; + }); +} & Omit; +}, Error, RegisterVariables>, "mutationFn">): UseMutationResult<{ + register: InferSelectResult; +}, Error, RegisterVariables>; +export function useRegisterMutation(params?: { + selection?: SelectionConfig; +} & Omit, "mutationFn">) { + const args = buildSelectionArgs(params?.selection); + const { + selection: _selection, + ...mutationOptions + } = params ?? {}; + void _selection; return useMutation({ mutationKey: customMutationKeys.register(), - mutationFn: (variables: RegisterMutationVariables) => execute(registerMutationDocument, variables), - ...options + mutationFn: (variables: RegisterVariables) => getClient().mutation.register(variables, { + select: (args?.select ?? defaultSelect) as RegisterPayloadSelect + }).unwrap(), + ...mutationOptions }); -}" +} +" `; exports[`Custom Mutation Hook Generators generateCustomMutationHook generates custom mutation hook without arguments 1`] = ` @@ -264,28 +306,53 @@ exports[`Custom Mutation Hook Generators generateCustomMutationHook generates cu */ import { useMutation } from "@tanstack/react-query"; -import type { UseMutationOptions } from "@tanstack/react-query"; -import { execute } from "../client"; -import type { LogoutPayload } from "../schema-types"; +import type { UseMutationOptions, UseMutationResult } from "@tanstack/react-query"; +import { getClient } from "../client"; +import { buildSelectionArgs } from "../selection"; +import type { SelectionConfig } from "../selection"; import { customMutationKeys } from "../mutation-keys"; -/** GraphQL mutation document */ -export const logoutMutationDocument = \` -mutation LogoutMutation { - logout { - success - } -} -\`; -export interface LogoutMutationResult { - logout: LogoutPayload; -} -export function useLogoutMutation(options?: Omit, 'mutationFn'>) { +import type { LogoutPayloadSelect, LogoutPayload } from "../../orm/input-types"; +import type { InferSelectResult, StrictSelect } from "../../orm/select-types"; +export type { LogoutPayloadSelect } from "../../orm/input-types"; +const defaultSelect = { + success: true +} as const; +export function useLogoutMutation(params: { + selection: ({ + fields: S; + } & StrictSelect); +} & Omit; +}, Error, void>, "mutationFn">): UseMutationResult<{ + logout: InferSelectResult; +}, Error, void>; +export function useLogoutMutation(params?: { + selection?: ({ + fields?: undefined; + }); +} & Omit; +}, Error, void>, "mutationFn">): UseMutationResult<{ + logout: InferSelectResult; +}, Error, void>; +export function useLogoutMutation(params?: { + selection?: SelectionConfig; +} & Omit, "mutationFn">) { + const args = buildSelectionArgs(params?.selection); + const { + selection: _selection, + ...mutationOptions + } = params ?? {}; + void _selection; return useMutation({ mutationKey: customMutationKeys.logout(), - mutationFn: () => execute(logoutMutationDocument), - ...options + mutationFn: () => getClient().mutation.logout({ + select: (args?.select ?? defaultSelect) as LogoutPayloadSelect + }).unwrap(), + ...mutationOptions }); -}" +} +" `; exports[`Custom Mutation Hook Generators generateCustomMutationHook generates custom mutation hook without centralized keys 1`] = ` @@ -296,30 +363,53 @@ exports[`Custom Mutation Hook Generators generateCustomMutationHook generates cu */ import { useMutation } from "@tanstack/react-query"; -import type { UseMutationOptions } from "@tanstack/react-query"; -import { execute } from "../client"; -import type { LoginPayload } from "../schema-types"; -/** GraphQL mutation document */ -export const loginMutationDocument = \` -mutation LoginMutation($email: String!, $password: String!) { - login(email: $email, password: $password) { - token - } -} -\`; -export interface LoginMutationVariables { - email: string; - password: string; -} -export interface LoginMutationResult { - login: LoginPayload; -} -export function useLoginMutation(options?: Omit, 'mutationFn'>) { +import type { UseMutationOptions, UseMutationResult } from "@tanstack/react-query"; +import { getClient } from "../client"; +import { buildSelectionArgs } from "../selection"; +import type { SelectionConfig } from "../selection"; +import type { LoginVariables } from "../../orm/mutation"; +import type { LoginPayloadSelect, LoginPayload } from "../../orm/input-types"; +import type { InferSelectResult, StrictSelect } from "../../orm/select-types"; +export type { LoginVariables } from "../../orm/mutation"; +export type { LoginPayloadSelect } from "../../orm/input-types"; +const defaultSelect = { + token: true +} as const; +export function useLoginMutation(params: { + selection: ({ + fields: S; + } & StrictSelect); +} & Omit; +}, Error, LoginVariables>, "mutationFn">): UseMutationResult<{ + login: InferSelectResult; +}, Error, LoginVariables>; +export function useLoginMutation(params?: { + selection?: ({ + fields?: undefined; + }); +} & Omit; +}, Error, LoginVariables>, "mutationFn">): UseMutationResult<{ + login: InferSelectResult; +}, Error, LoginVariables>; +export function useLoginMutation(params?: { + selection?: SelectionConfig; +} & Omit, "mutationFn">) { + const args = buildSelectionArgs(params?.selection); + const { + selection: _selection, + ...mutationOptions + } = params ?? {}; + void _selection; return useMutation({ - mutationFn: (variables: LoginMutationVariables) => execute(loginMutationDocument, variables), - ...options + mutationFn: (variables: LoginVariables) => getClient().mutation.login(variables, { + select: (args?.select ?? defaultSelect) as LoginPayloadSelect + }).unwrap(), + ...mutationOptions }); -}" +} +" `; exports[`Custom Query Hook Generators generateCustomQueryHook generates custom query hook with arguments 1`] = ` @@ -330,24 +420,19 @@ exports[`Custom Query Hook Generators generateCustomQueryHook generates custom q */ import { useQuery } from "@tanstack/react-query"; -import type { UseQueryOptions, QueryClient } from "@tanstack/react-query"; -import { execute } from "../client"; -import type { ExecuteOptions } from "../client"; -import type { User } from "../schema-types"; +import type { UseQueryOptions, UseQueryResult, QueryClient } from "@tanstack/react-query"; +import { getClient } from "../client"; +import { buildSelectionArgs } from "../selection"; +import type { SelectionConfig } from "../selection"; import { customQueryKeys } from "../query-keys"; -/** GraphQL query document */ -export const searchUsersQueryDocument = \` -query SearchUsersQuery($query: String!, $limit: Int) { - searchUsers(query: $query, limit: $limit) -} -\`; -export interface SearchUsersQueryVariables { - query: string; - limit?: number; -} -export interface SearchUsersQueryResult { - searchUsers: User[]; -} +import type { SearchUsersVariables } from "../../orm/query"; +import type { UserSelect, User } from "../../orm/input-types"; +import type { InferSelectResult, StrictSelect } from "../../orm/select-types"; +export type { SearchUsersVariables } from "../../orm/query"; +export type { UserSelect } from "../../orm/input-types"; +const defaultSelect = { + id: true +} as const; /** Query key factory - re-exported from query-keys.ts */ export const searchUsersQueryKey = customQueryKeys.searchUsers; /** @@ -362,12 +447,46 @@ export const searchUsersQueryKey = customQueryKeys.searchUsers; * } * \`\`\` */ -export function useSearchUsersQuery(variables: SearchUsersQueryVariables, options?: Omit, 'queryKey' | 'queryFn'>) { +export function useSearchUsersQuery[]; +}>(params: { + variables: SearchUsersVariables; + selection: ({ + fields: S; + } & StrictSelect); +} & Omit[]; +}, Error, TData>, "queryKey" | "queryFn">): UseQueryResult; +export function useSearchUsersQuery[]; +}>(params: { + variables: SearchUsersVariables; + selection?: ({ + fields?: undefined; + }); +} & Omit[]; +}, Error, TData>, "queryKey" | "queryFn">): UseQueryResult; +export function useSearchUsersQuery(params: { + variables: SearchUsersVariables; + selection?: SelectionConfig; +} & Omit, "queryKey" | "queryFn">) { + const variables = params?.variables; + const args = buildSelectionArgs(params?.selection); + const { + variables: _variables, + selection: _selection, + ...queryOptions + } = params ?? {}; + void _variables; + void _selection; return useQuery({ queryKey: searchUsersQueryKey(variables), - queryFn: () => execute(searchUsersQueryDocument, variables), - enabled: !!variables && options?.enabled !== false, - ...options + queryFn: () => getClient().query.searchUsers(variables!, { + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap(), + enabled: !!variables && params?.enabled !== false, + ...queryOptions }); } /** @@ -378,8 +497,31 @@ export function useSearchUsersQuery(variables: SearchUsersQueryVariables, option * const data = await fetchSearchUsersQuery({ query, limit }); * \`\`\` */ -export async function fetchSearchUsersQuery(variables: SearchUsersQueryVariables, options?: ExecuteOptions): Promise { - return execute(searchUsersQueryDocument, variables, options); +export async function fetchSearchUsersQuery(params: { + variables: SearchUsersVariables; + selection: ({ + fields: S; + } & StrictSelect); +}): Promise<{ + searchUsers: InferSelectResult[]; +}>; +export async function fetchSearchUsersQuery(params: { + variables: SearchUsersVariables; + selection?: ({ + fields?: undefined; + }); +}): Promise<{ + searchUsers: InferSelectResult[]; +}>; +export async function fetchSearchUsersQuery(params: { + variables: SearchUsersVariables; + selection?: SelectionConfig; +}) { + const variables = params?.variables; + const args = buildSelectionArgs(params?.selection); + return getClient().query.searchUsers(variables!, { + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap(); } /** * Prefetch searchUsers for SSR or cache warming @@ -389,12 +531,32 @@ export async function fetchSearchUsersQuery(variables: SearchUsersQueryVariables * await prefetchSearchUsersQuery(queryClient, { query, limit }); * \`\`\` */ -export async function prefetchSearchUsersQuery(queryClient: QueryClient, variables: SearchUsersQueryVariables, options?: ExecuteOptions): Promise { +export async function prefetchSearchUsersQuery(queryClient: QueryClient, params: { + variables: SearchUsersVariables; + selection: ({ + fields: S; + } & StrictSelect); +}): Promise; +export async function prefetchSearchUsersQuery(queryClient: QueryClient, params: { + variables: SearchUsersVariables; + selection?: ({ + fields?: undefined; + }); +}): Promise; +export async function prefetchSearchUsersQuery(queryClient: QueryClient, params: { + variables: SearchUsersVariables; + selection?: SelectionConfig; +}): void { + const variables = params?.variables; + const args = buildSelectionArgs(params?.selection); await queryClient.prefetchQuery({ queryKey: searchUsersQueryKey(variables), - queryFn: () => execute(searchUsersQueryDocument, variables, options) + queryFn: () => getClient().query.searchUsers(variables!, { + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap() }); -}" +} +" `; exports[`Custom Query Hook Generators generateCustomQueryHook generates custom query hook without arguments 1`] = ` @@ -405,20 +567,17 @@ exports[`Custom Query Hook Generators generateCustomQueryHook generates custom q */ import { useQuery } from "@tanstack/react-query"; -import type { UseQueryOptions, QueryClient } from "@tanstack/react-query"; -import { execute } from "../client"; -import type { ExecuteOptions } from "../client"; -import type { User } from "../schema-types"; +import type { UseQueryOptions, UseQueryResult, QueryClient } from "@tanstack/react-query"; +import { getClient } from "../client"; +import { buildSelectionArgs } from "../selection"; +import type { SelectionConfig } from "../selection"; import { customQueryKeys } from "../query-keys"; -/** GraphQL query document */ -export const currentUserQueryDocument = \` -query CurrentUserQuery { - currentUser -} -\`; -export interface CurrentUserQueryResult { - currentUser: User; -} +import type { UserSelect, User } from "../../orm/input-types"; +import type { InferSelectResult, StrictSelect } from "../../orm/select-types"; +export type { UserSelect } from "../../orm/input-types"; +const defaultSelect = { + id: true +} as const; /** Query key factory - re-exported from query-keys.ts */ export const currentUserQueryKey = customQueryKeys.currentUser; /** @@ -433,11 +592,39 @@ export const currentUserQueryKey = customQueryKeys.currentUser; * } * \`\`\` */ -export function useCurrentUserQuery(options?: Omit, 'queryKey' | 'queryFn'>) { +export function useCurrentUserQuery; +}>(params: { + selection: ({ + fields: S; + } & StrictSelect); +} & Omit; +}, Error, TData>, "queryKey" | "queryFn">): UseQueryResult; +export function useCurrentUserQuery; +}>(params?: { + selection?: ({ + fields?: undefined; + }); +} & Omit; +}, Error, TData>, "queryKey" | "queryFn">): UseQueryResult; +export function useCurrentUserQuery(params?: { + selection?: SelectionConfig; +} & Omit, "queryKey" | "queryFn">) { + const args = buildSelectionArgs(params?.selection); + const { + selection: _selection, + ...queryOptions + } = params ?? {}; + void _selection; return useQuery({ queryKey: currentUserQueryKey(), - queryFn: () => execute(currentUserQueryDocument), - ...options + queryFn: () => getClient().query.currentUser({ + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap(), + ...queryOptions }); } /** @@ -448,8 +635,27 @@ export function useCurrentUserQuery(options?: Omit { - return execute(currentUserQueryDocument, undefined, options); +export async function fetchCurrentUserQuery(params: { + selection: ({ + fields: S; + } & StrictSelect); +}): Promise<{ + currentUser: InferSelectResult; +}>; +export async function fetchCurrentUserQuery(params?: { + selection?: ({ + fields?: undefined; + }); +}): Promise<{ + currentUser: InferSelectResult; +}>; +export async function fetchCurrentUserQuery(params?: { + selection?: SelectionConfig; +}) { + const args = buildSelectionArgs(params?.selection); + return getClient().query.currentUser({ + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap(); } /** * Prefetch currentUser for SSR or cache warming @@ -459,12 +665,28 @@ export async function fetchCurrentUserQuery(options?: ExecuteOptions): Promise { +export async function prefetchCurrentUserQuery(queryClient: QueryClient, params: { + selection: ({ + fields: S; + } & StrictSelect); +}): Promise; +export async function prefetchCurrentUserQuery(queryClient: QueryClient, params?: { + selection?: ({ + fields?: undefined; + }); +}): Promise; +export async function prefetchCurrentUserQuery(queryClient: QueryClient, params?: { + selection?: SelectionConfig; +}): void { + const args = buildSelectionArgs(params?.selection); await queryClient.prefetchQuery({ queryKey: currentUserQueryKey(), - queryFn: () => execute(currentUserQueryDocument, undefined, options) + queryFn: () => getClient().query.currentUser({ + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap() }); -}" +} +" `; exports[`Custom Query Hook Generators generateCustomQueryHook generates custom query hook without centralized keys 1`] = ` @@ -475,19 +697,16 @@ exports[`Custom Query Hook Generators generateCustomQueryHook generates custom q */ import { useQuery } from "@tanstack/react-query"; -import type { UseQueryOptions, QueryClient } from "@tanstack/react-query"; -import { execute } from "../client"; -import type { ExecuteOptions } from "../client"; -import type { User } from "../schema-types"; -/** GraphQL query document */ -export const currentUserQueryDocument = \` -query CurrentUserQuery { - currentUser -} -\`; -export interface CurrentUserQueryResult { - currentUser: User; -} +import type { UseQueryOptions, UseQueryResult, QueryClient } from "@tanstack/react-query"; +import { getClient } from "../client"; +import { buildSelectionArgs } from "../selection"; +import type { SelectionConfig } from "../selection"; +import type { UserSelect, User } from "../../orm/input-types"; +import type { InferSelectResult, StrictSelect } from "../../orm/select-types"; +export type { UserSelect } from "../../orm/input-types"; +const defaultSelect = { + id: true +} as const; /** Query key factory for caching */ export const currentUserQueryKey = () => ["currentUser"] as const; /** @@ -502,11 +721,39 @@ export const currentUserQueryKey = () => ["currentUser"] as const; * } * \`\`\` */ -export function useCurrentUserQuery(options?: Omit, 'queryKey' | 'queryFn'>) { +export function useCurrentUserQuery; +}>(params: { + selection: ({ + fields: S; + } & StrictSelect); +} & Omit; +}, Error, TData>, "queryKey" | "queryFn">): UseQueryResult; +export function useCurrentUserQuery; +}>(params?: { + selection?: ({ + fields?: undefined; + }); +} & Omit; +}, Error, TData>, "queryKey" | "queryFn">): UseQueryResult; +export function useCurrentUserQuery(params?: { + selection?: SelectionConfig; +} & Omit, "queryKey" | "queryFn">) { + const args = buildSelectionArgs(params?.selection); + const { + selection: _selection, + ...queryOptions + } = params ?? {}; + void _selection; return useQuery({ queryKey: currentUserQueryKey(), - queryFn: () => execute(currentUserQueryDocument), - ...options + queryFn: () => getClient().query.currentUser({ + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap(), + ...queryOptions }); } /** @@ -517,8 +764,27 @@ export function useCurrentUserQuery(options?: Omit { - return execute(currentUserQueryDocument, undefined, options); +export async function fetchCurrentUserQuery(params: { + selection: ({ + fields: S; + } & StrictSelect); +}): Promise<{ + currentUser: InferSelectResult; +}>; +export async function fetchCurrentUserQuery(params?: { + selection?: ({ + fields?: undefined; + }); +}): Promise<{ + currentUser: InferSelectResult; +}>; +export async function fetchCurrentUserQuery(params?: { + selection?: SelectionConfig; +}) { + const args = buildSelectionArgs(params?.selection); + return getClient().query.currentUser({ + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap(); } /** * Prefetch currentUser for SSR or cache warming @@ -528,12 +794,28 @@ export async function fetchCurrentUserQuery(options?: ExecuteOptions): Promise { +export async function prefetchCurrentUserQuery(queryClient: QueryClient, params: { + selection: ({ + fields: S; + } & StrictSelect); +}): Promise; +export async function prefetchCurrentUserQuery(queryClient: QueryClient, params?: { + selection?: ({ + fields?: undefined; + }); +}): Promise; +export async function prefetchCurrentUserQuery(queryClient: QueryClient, params?: { + selection?: SelectionConfig; +}): void { + const args = buildSelectionArgs(params?.selection); await queryClient.prefetchQuery({ queryKey: currentUserQueryKey(), - queryFn: () => execute(currentUserQueryDocument, undefined, options) + queryFn: () => getClient().query.currentUser({ + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap() }); -}" +} +" `; exports[`Mutation Hook Generators generateCreateMutationHook generates create mutation hook for simple table 1`] = ` @@ -544,68 +826,81 @@ exports[`Mutation Hook Generators generateCreateMutationHook generates create mu */ import { useMutation, useQueryClient } from "@tanstack/react-query"; -import type { UseMutationOptions } from "@tanstack/react-query"; -import { execute } from "../client"; -import type { User } from "../types"; +import type { UseMutationOptions, UseMutationResult } from "@tanstack/react-query"; +import { getClient } from "../client"; +import { buildSelectionArgs } from "../selection"; +import type { SelectionConfig } from "../selection"; import { userKeys } from "../query-keys"; import { userMutationKeys } from "../mutation-keys"; -export type { User } from "../types"; -export const createUserMutationDocument = \` -mutation CreateUserMutation($input: CreateUserInput!) { - createUser(input: $input) { - user { - id - email - name - createdAt - } - } -} -\`; -/** Input type for creating a User */ -interface UserCreateInput { - email?: string | null; - name?: string | null; -} -export interface CreateUserMutationVariables { - input: { - user: UserCreateInput; - }; -} -export interface CreateUserMutationResult { - createUser: { - user: User; - }; -} +import type { UserSelect, UserWithRelations, CreateUserInput } from "../../orm/input-types"; +import type { InferSelectResult, StrictSelect } from "../../orm/select-types"; +export type { UserSelect, UserWithRelations, CreateUserInput } from "../../orm/input-types"; +const defaultSelect = { + id: true +} as const; /** * Mutation hook for creating a User * * @example * \`\`\`tsx - * const { mutate, isPending } = useCreateUserMutation(); - * - * mutate({ - * input: { - * user: { - * // ... fields - * }, - * }, + * const { mutate, isPending } = useCreateUserMutation({ + * selection: { fields: { id: true, name: true } }, * }); + * + * mutate({ name: 'New item' }); * \`\`\` */ -export function useCreateUserMutation(options?: Omit, 'mutationFn'>) { +export function useCreateUserMutation(params: { + selection: ({ + fields: S; + } & StrictSelect); +} & Omit; + }; +}, Error, CreateUserInput["user"]>, "mutationFn">): UseMutationResult<{ + createUser: { + user: InferSelectResult; + }; +}, Error, CreateUserInput["user"]>; +export function useCreateUserMutation(params?: { + selection?: ({ + fields?: undefined; + }); +} & Omit; + }; +}, Error, CreateUserInput["user"]>, "mutationFn">): UseMutationResult<{ + createUser: { + user: InferSelectResult; + }; +}, Error, CreateUserInput["user"]>; +export function useCreateUserMutation(params?: { + selection?: SelectionConfig; +} & Omit, "mutationFn">) { + const args = buildSelectionArgs(params?.selection); + const { + selection: _selection, + ...mutationOptions + } = params ?? {}; + void _selection; const queryClient = useQueryClient(); return useMutation({ mutationKey: userMutationKeys.create(), - mutationFn: (variables: CreateUserMutationVariables) => execute(createUserMutationDocument, variables), + mutationFn: (data: CreateUserInput["user"]) => getClient().user.create({ + data, + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap(), onSuccess: () => { queryClient.invalidateQueries({ queryKey: userKeys.lists() }); }, - ...options + ...mutationOptions }); -}" +} +" `; exports[`Mutation Hook Generators generateCreateMutationHook generates create mutation hook for table with relationships 1`] = ` @@ -616,73 +911,81 @@ exports[`Mutation Hook Generators generateCreateMutationHook generates create mu */ import { useMutation, useQueryClient } from "@tanstack/react-query"; -import type { UseMutationOptions } from "@tanstack/react-query"; -import { execute } from "../client"; -import type { Post } from "../types"; +import type { UseMutationOptions, UseMutationResult } from "@tanstack/react-query"; +import { getClient } from "../client"; +import { buildSelectionArgs } from "../selection"; +import type { SelectionConfig } from "../selection"; import { postKeys } from "../query-keys"; -import type { PostScope } from "../query-keys"; import { postMutationKeys } from "../mutation-keys"; -export type { Post } from "../types"; -export const createPostMutationDocument = \` -mutation CreatePostMutation($input: CreatePostInput!) { - createPost(input: $input) { - post { - id - title - content - authorId - published - createdAt - } - } -} -\`; -/** Input type for creating a Post */ -interface PostCreateInput { - title?: string | null; - content?: string | null; - authorId?: string | null; - published?: boolean | null; -} -export interface CreatePostMutationVariables { - input: { - post: PostCreateInput; - }; -} -export interface CreatePostMutationResult { - createPost: { - post: Post; - }; -} +import type { PostSelect, PostWithRelations, CreatePostInput } from "../../orm/input-types"; +import type { InferSelectResult, StrictSelect } from "../../orm/select-types"; +export type { PostSelect, PostWithRelations, CreatePostInput } from "../../orm/input-types"; +const defaultSelect = { + id: true +} as const; /** * Mutation hook for creating a Post * * @example * \`\`\`tsx - * const { mutate, isPending } = useCreatePostMutation(); - * - * mutate({ - * input: { - * post: { - * // ... fields - * }, - * }, + * const { mutate, isPending } = useCreatePostMutation({ + * selection: { fields: { id: true, name: true } }, * }); + * + * mutate({ name: 'New item' }); * \`\`\` */ -export function useCreatePostMutation(options?: Omit, 'mutationFn'>) { +export function useCreatePostMutation(params: { + selection: ({ + fields: S; + } & StrictSelect); +} & Omit; + }; +}, Error, CreatePostInput["post"]>, "mutationFn">): UseMutationResult<{ + createPost: { + post: InferSelectResult; + }; +}, Error, CreatePostInput["post"]>; +export function useCreatePostMutation(params?: { + selection?: ({ + fields?: undefined; + }); +} & Omit; + }; +}, Error, CreatePostInput["post"]>, "mutationFn">): UseMutationResult<{ + createPost: { + post: InferSelectResult; + }; +}, Error, CreatePostInput["post"]>; +export function useCreatePostMutation(params?: { + selection?: SelectionConfig; +} & Omit, "mutationFn">) { + const args = buildSelectionArgs(params?.selection); + const { + selection: _selection, + ...mutationOptions + } = params ?? {}; + void _selection; const queryClient = useQueryClient(); return useMutation({ mutationKey: postMutationKeys.create(), - mutationFn: (variables: CreatePostMutationVariables) => execute(createPostMutationDocument, variables), + mutationFn: (data: CreatePostInput["post"]) => getClient().post.create({ + data, + select: (args?.select ?? defaultSelect) as PostSelect + }).unwrap(), onSuccess: () => { queryClient.invalidateQueries({ queryKey: postKeys.lists() }); }, - ...options + ...mutationOptions }); -}" +} +" `; exports[`Mutation Hook Generators generateCreateMutationHook generates create mutation hook without centralized keys 1`] = ` @@ -693,65 +996,78 @@ exports[`Mutation Hook Generators generateCreateMutationHook generates create mu */ import { useMutation, useQueryClient } from "@tanstack/react-query"; -import type { UseMutationOptions } from "@tanstack/react-query"; -import { execute } from "../client"; -import type { User } from "../types"; -export type { User } from "../types"; -export const createUserMutationDocument = \` -mutation CreateUserMutation($input: CreateUserInput!) { - createUser(input: $input) { - user { - id - email - name - createdAt - } - } -} -\`; -/** Input type for creating a User */ -interface UserCreateInput { - email?: string | null; - name?: string | null; -} -export interface CreateUserMutationVariables { - input: { - user: UserCreateInput; - }; -} -export interface CreateUserMutationResult { - createUser: { - user: User; - }; -} +import type { UseMutationOptions, UseMutationResult } from "@tanstack/react-query"; +import { getClient } from "../client"; +import { buildSelectionArgs } from "../selection"; +import type { SelectionConfig } from "../selection"; +import type { UserSelect, UserWithRelations, CreateUserInput } from "../../orm/input-types"; +import type { InferSelectResult, StrictSelect } from "../../orm/select-types"; +export type { UserSelect, UserWithRelations, CreateUserInput } from "../../orm/input-types"; +const defaultSelect = { + id: true +} as const; /** * Mutation hook for creating a User * * @example * \`\`\`tsx - * const { mutate, isPending } = useCreateUserMutation(); - * - * mutate({ - * input: { - * user: { - * // ... fields - * }, - * }, + * const { mutate, isPending } = useCreateUserMutation({ + * selection: { fields: { id: true, name: true } }, * }); + * + * mutate({ name: 'New item' }); * \`\`\` */ -export function useCreateUserMutation(options?: Omit, 'mutationFn'>) { +export function useCreateUserMutation(params: { + selection: ({ + fields: S; + } & StrictSelect); +} & Omit; + }; +}, Error, CreateUserInput["user"]>, "mutationFn">): UseMutationResult<{ + createUser: { + user: InferSelectResult; + }; +}, Error, CreateUserInput["user"]>; +export function useCreateUserMutation(params?: { + selection?: ({ + fields?: undefined; + }); +} & Omit; + }; +}, Error, CreateUserInput["user"]>, "mutationFn">): UseMutationResult<{ + createUser: { + user: InferSelectResult; + }; +}, Error, CreateUserInput["user"]>; +export function useCreateUserMutation(params?: { + selection?: SelectionConfig; +} & Omit, "mutationFn">) { + const args = buildSelectionArgs(params?.selection); + const { + selection: _selection, + ...mutationOptions + } = params ?? {}; + void _selection; const queryClient = useQueryClient(); return useMutation({ - mutationFn: (variables: CreateUserMutationVariables) => execute(createUserMutationDocument, variables), + mutationFn: (data: CreateUserInput["user"]) => getClient().user.create({ + data, + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap(), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["user", "list"] }); }, - ...options + ...mutationOptions }); -}" +} +" `; exports[`Mutation Hook Generators generateDeleteMutationHook generates delete mutation hook for simple table 1`] = ` @@ -762,57 +1078,100 @@ exports[`Mutation Hook Generators generateDeleteMutationHook generates delete mu */ import { useMutation, useQueryClient } from "@tanstack/react-query"; -import type { UseMutationOptions } from "@tanstack/react-query"; -import { execute } from "../client"; +import type { UseMutationOptions, UseMutationResult } from "@tanstack/react-query"; +import { getClient } from "../client"; +import { buildSelectionArgs } from "../selection"; +import type { SelectionConfig } from "../selection"; import { userKeys } from "../query-keys"; import { userMutationKeys } from "../mutation-keys"; -export const deleteUserMutationDocument = \` -mutation DeleteUserMutation($input: DeleteUserInput!) { - deleteUser(input: $input) { - clientMutationId - } -} -\`; -export interface DeleteUserMutationVariables { - input: { - id: string; - }; -} -export interface DeleteUserMutationResult { - deleteUser: { - clientMutationId: string | null; - }; -} +import type { UserSelect, UserWithRelations } from "../../orm/input-types"; +import type { InferSelectResult, StrictSelect } from "../../orm/select-types"; +export type { UserSelect, UserWithRelations } from "../../orm/input-types"; +const defaultSelect = { + id: true +} as const; /** * Mutation hook for deleting a User * * @example * \`\`\`tsx - * const { mutate, isPending } = useDeleteUserMutation(); - * - * mutate({ - * input: { - * id: 'value-to-delete', - * }, + * const { mutate, isPending } = useDeleteUserMutation({ + * selection: { fields: { id: true } }, * }); + * + * mutate({ id: 'value-to-delete' }); * \`\`\` */ -export function useDeleteUserMutation(options?: Omit, 'mutationFn'>) { +export function useDeleteUserMutation(params: { + selection: ({ + fields: S; + } & StrictSelect); +} & Omit; + }; +}, Error, { + id: string; +}>, "mutationFn">): UseMutationResult<{ + deleteUser: { + user: InferSelectResult; + }; +}, Error, { + id: string; +}>; +export function useDeleteUserMutation(params?: { + selection?: ({ + fields?: undefined; + }); +} & Omit; + }; +}, Error, { + id: string; +}>, "mutationFn">): UseMutationResult<{ + deleteUser: { + user: InferSelectResult; + }; +}, Error, { + id: string; +}>; +export function useDeleteUserMutation(params?: { + selection?: SelectionConfig; +} & Omit, "mutationFn">) { + const args = buildSelectionArgs(params?.selection); + const { + selection: _selection, + ...mutationOptions + } = params ?? {}; + void _selection; const queryClient = useQueryClient(); return useMutation({ mutationKey: userMutationKeys.all, - mutationFn: (variables: DeleteUserMutationVariables) => execute(deleteUserMutationDocument, variables), + mutationFn: ({ + id + }: { + id: string; + }) => getClient().user.delete({ + where: { + id + }, + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap(), onSuccess: (_, variables) => { queryClient.removeQueries({ - queryKey: userKeys.detail(variables.input.id) + queryKey: userKeys.detail(variables.id) }); queryClient.invalidateQueries({ queryKey: userKeys.lists() }); }, - ...options + ...mutationOptions }); -}" +} +" `; exports[`Mutation Hook Generators generateDeleteMutationHook generates delete mutation hook for table with relationships 1`] = ` @@ -823,58 +1182,100 @@ exports[`Mutation Hook Generators generateDeleteMutationHook generates delete mu */ import { useMutation, useQueryClient } from "@tanstack/react-query"; -import type { UseMutationOptions } from "@tanstack/react-query"; -import { execute } from "../client"; +import type { UseMutationOptions, UseMutationResult } from "@tanstack/react-query"; +import { getClient } from "../client"; +import { buildSelectionArgs } from "../selection"; +import type { SelectionConfig } from "../selection"; import { postKeys } from "../query-keys"; -import type { PostScope } from "../query-keys"; import { postMutationKeys } from "../mutation-keys"; -export const deletePostMutationDocument = \` -mutation DeletePostMutation($input: DeletePostInput!) { - deletePost(input: $input) { - clientMutationId - } -} -\`; -export interface DeletePostMutationVariables { - input: { - id: string; - }; -} -export interface DeletePostMutationResult { - deletePost: { - clientMutationId: string | null; - }; -} +import type { PostSelect, PostWithRelations } from "../../orm/input-types"; +import type { InferSelectResult, StrictSelect } from "../../orm/select-types"; +export type { PostSelect, PostWithRelations } from "../../orm/input-types"; +const defaultSelect = { + id: true +} as const; /** * Mutation hook for deleting a Post * * @example * \`\`\`tsx - * const { mutate, isPending } = useDeletePostMutation(); - * - * mutate({ - * input: { - * id: 'value-to-delete', - * }, + * const { mutate, isPending } = useDeletePostMutation({ + * selection: { fields: { id: true } }, * }); + * + * mutate({ id: 'value-to-delete' }); * \`\`\` */ -export function useDeletePostMutation(options?: Omit, 'mutationFn'>) { +export function useDeletePostMutation(params: { + selection: ({ + fields: S; + } & StrictSelect); +} & Omit; + }; +}, Error, { + id: string; +}>, "mutationFn">): UseMutationResult<{ + deletePost: { + post: InferSelectResult; + }; +}, Error, { + id: string; +}>; +export function useDeletePostMutation(params?: { + selection?: ({ + fields?: undefined; + }); +} & Omit; + }; +}, Error, { + id: string; +}>, "mutationFn">): UseMutationResult<{ + deletePost: { + post: InferSelectResult; + }; +}, Error, { + id: string; +}>; +export function useDeletePostMutation(params?: { + selection?: SelectionConfig; +} & Omit, "mutationFn">) { + const args = buildSelectionArgs(params?.selection); + const { + selection: _selection, + ...mutationOptions + } = params ?? {}; + void _selection; const queryClient = useQueryClient(); return useMutation({ mutationKey: postMutationKeys.all, - mutationFn: (variables: DeletePostMutationVariables) => execute(deletePostMutationDocument, variables), + mutationFn: ({ + id + }: { + id: string; + }) => getClient().post.delete({ + where: { + id + }, + select: (args?.select ?? defaultSelect) as PostSelect + }).unwrap(), onSuccess: (_, variables) => { queryClient.removeQueries({ - queryKey: postKeys.detail(variables.input.id) + queryKey: postKeys.detail(variables.id) }); queryClient.invalidateQueries({ queryKey: postKeys.lists() }); }, - ...options + ...mutationOptions }); -}" +} +" `; exports[`Mutation Hook Generators generateDeleteMutationHook generates delete mutation hook without centralized keys 1`] = ` @@ -885,54 +1286,97 @@ exports[`Mutation Hook Generators generateDeleteMutationHook generates delete mu */ import { useMutation, useQueryClient } from "@tanstack/react-query"; -import type { UseMutationOptions } from "@tanstack/react-query"; -import { execute } from "../client"; -export const deleteUserMutationDocument = \` -mutation DeleteUserMutation($input: DeleteUserInput!) { - deleteUser(input: $input) { - clientMutationId - } -} -\`; -export interface DeleteUserMutationVariables { - input: { - id: string; - }; -} -export interface DeleteUserMutationResult { - deleteUser: { - clientMutationId: string | null; - }; -} +import type { UseMutationOptions, UseMutationResult } from "@tanstack/react-query"; +import { getClient } from "../client"; +import { buildSelectionArgs } from "../selection"; +import type { SelectionConfig } from "../selection"; +import type { UserSelect, UserWithRelations } from "../../orm/input-types"; +import type { InferSelectResult, StrictSelect } from "../../orm/select-types"; +export type { UserSelect, UserWithRelations } from "../../orm/input-types"; +const defaultSelect = { + id: true +} as const; /** * Mutation hook for deleting a User * * @example * \`\`\`tsx - * const { mutate, isPending } = useDeleteUserMutation(); - * - * mutate({ - * input: { - * id: 'value-to-delete', - * }, + * const { mutate, isPending } = useDeleteUserMutation({ + * selection: { fields: { id: true } }, * }); + * + * mutate({ id: 'value-to-delete' }); * \`\`\` */ -export function useDeleteUserMutation(options?: Omit, 'mutationFn'>) { +export function useDeleteUserMutation(params: { + selection: ({ + fields: S; + } & StrictSelect); +} & Omit; + }; +}, Error, { + id: string; +}>, "mutationFn">): UseMutationResult<{ + deleteUser: { + user: InferSelectResult; + }; +}, Error, { + id: string; +}>; +export function useDeleteUserMutation(params?: { + selection?: ({ + fields?: undefined; + }); +} & Omit; + }; +}, Error, { + id: string; +}>, "mutationFn">): UseMutationResult<{ + deleteUser: { + user: InferSelectResult; + }; +}, Error, { + id: string; +}>; +export function useDeleteUserMutation(params?: { + selection?: SelectionConfig; +} & Omit, "mutationFn">) { + const args = buildSelectionArgs(params?.selection); + const { + selection: _selection, + ...mutationOptions + } = params ?? {}; + void _selection; const queryClient = useQueryClient(); return useMutation({ - mutationFn: (variables: DeleteUserMutationVariables) => execute(deleteUserMutationDocument, variables), + mutationFn: ({ + id + }: { + id: string; + }) => getClient().user.delete({ + where: { + id + }, + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap(), onSuccess: (_, variables) => { queryClient.removeQueries({ - queryKey: ["user", "detail", variables.input.id] + queryKey: ["user", "detail", variables.id] }); queryClient.invalidateQueries({ queryKey: ["user", "list"] }); }, - ...options + ...mutationOptions }); -}" +} +" `; exports[`Mutation Hook Generators generateUpdateMutationHook generates update mutation hook for simple table 1`] = ` @@ -943,74 +1387,108 @@ exports[`Mutation Hook Generators generateUpdateMutationHook generates update mu */ import { useMutation, useQueryClient } from "@tanstack/react-query"; -import type { UseMutationOptions } from "@tanstack/react-query"; -import { execute } from "../client"; -import type { User } from "../types"; +import type { UseMutationOptions, UseMutationResult } from "@tanstack/react-query"; +import { getClient } from "../client"; +import { buildSelectionArgs } from "../selection"; +import type { SelectionConfig } from "../selection"; import { userKeys } from "../query-keys"; import { userMutationKeys } from "../mutation-keys"; -export type { User } from "../types"; -export const updateUserMutationDocument = \` -mutation UpdateUserMutation($input: UpdateUserInput!) { - updateUser(input: $input) { - user { - id - email - name - createdAt - } - } -} -\`; -/** Patch type for updating a User - all fields optional */ -interface UserPatch { - email?: string | null; - name?: string | null; - createdAt?: string | null; -} -export interface UpdateUserMutationVariables { - input: { - id: string; - patch: UserPatch; - }; -} -export interface UpdateUserMutationResult { - updateUser: { - user: User; - }; -} +import type { UserSelect, UserWithRelations, UserPatch } from "../../orm/input-types"; +import type { InferSelectResult, StrictSelect } from "../../orm/select-types"; +export type { UserSelect, UserWithRelations, UserPatch } from "../../orm/input-types"; +const defaultSelect = { + id: true +} as const; /** * Mutation hook for updating a User * * @example * \`\`\`tsx - * const { mutate, isPending } = useUpdateUserMutation(); - * - * mutate({ - * input: { - * id: 'value-here', - * patch: { - * // ... fields to update - * }, - * }, + * const { mutate, isPending } = useUpdateUserMutation({ + * selection: { fields: { id: true, name: true } }, * }); + * + * mutate({ id: 'value-here', patch: { name: 'Updated' } }); * \`\`\` */ -export function useUpdateUserMutation(options?: Omit, 'mutationFn'>) { +export function useUpdateUserMutation(params: { + selection: ({ + fields: S; + } & StrictSelect); +} & Omit; + }; +}, Error, { + id: string; + patch: UserPatch; +}>, "mutationFn">): UseMutationResult<{ + updateUser: { + user: InferSelectResult; + }; +}, Error, { + id: string; + patch: UserPatch; +}>; +export function useUpdateUserMutation(params?: { + selection?: ({ + fields?: undefined; + }); +} & Omit; + }; +}, Error, { + id: string; + patch: UserPatch; +}>, "mutationFn">): UseMutationResult<{ + updateUser: { + user: InferSelectResult; + }; +}, Error, { + id: string; + patch: UserPatch; +}>; +export function useUpdateUserMutation(params?: { + selection?: SelectionConfig; +} & Omit, "mutationFn">) { + const args = buildSelectionArgs(params?.selection); + const { + selection: _selection, + ...mutationOptions + } = params ?? {}; + void _selection; const queryClient = useQueryClient(); return useMutation({ mutationKey: userMutationKeys.all, - mutationFn: (variables: UpdateUserMutationVariables) => execute(updateUserMutationDocument, variables), + mutationFn: ({ + id, + patch + }: { + id: string; + patch: UserPatch; + }) => getClient().user.update({ + where: { + id + }, + data: patch, + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap(), onSuccess: (_, variables) => { queryClient.invalidateQueries({ - queryKey: userKeys.detail(variables.input.id) + queryKey: userKeys.detail(variables.id) }); queryClient.invalidateQueries({ queryKey: userKeys.lists() }); }, - ...options + ...mutationOptions }); -}" +} +" `; exports[`Mutation Hook Generators generateUpdateMutationHook generates update mutation hook for table with relationships 1`] = ` @@ -1021,79 +1499,108 @@ exports[`Mutation Hook Generators generateUpdateMutationHook generates update mu */ import { useMutation, useQueryClient } from "@tanstack/react-query"; -import type { UseMutationOptions } from "@tanstack/react-query"; -import { execute } from "../client"; -import type { Post } from "../types"; +import type { UseMutationOptions, UseMutationResult } from "@tanstack/react-query"; +import { getClient } from "../client"; +import { buildSelectionArgs } from "../selection"; +import type { SelectionConfig } from "../selection"; import { postKeys } from "../query-keys"; -import type { PostScope } from "../query-keys"; import { postMutationKeys } from "../mutation-keys"; -export type { Post } from "../types"; -export const updatePostMutationDocument = \` -mutation UpdatePostMutation($input: UpdatePostInput!) { - updatePost(input: $input) { - post { - id - title - content - authorId - published - createdAt - } - } -} -\`; -/** Patch type for updating a Post - all fields optional */ -interface PostPatch { - title?: string | null; - content?: string | null; - authorId?: string | null; - published?: boolean | null; - createdAt?: string | null; -} -export interface UpdatePostMutationVariables { - input: { - id: string; - patch: PostPatch; - }; -} -export interface UpdatePostMutationResult { - updatePost: { - post: Post; - }; -} +import type { PostSelect, PostWithRelations, PostPatch } from "../../orm/input-types"; +import type { InferSelectResult, StrictSelect } from "../../orm/select-types"; +export type { PostSelect, PostWithRelations, PostPatch } from "../../orm/input-types"; +const defaultSelect = { + id: true +} as const; /** * Mutation hook for updating a Post * * @example * \`\`\`tsx - * const { mutate, isPending } = useUpdatePostMutation(); - * - * mutate({ - * input: { - * id: 'value-here', - * patch: { - * // ... fields to update - * }, - * }, + * const { mutate, isPending } = useUpdatePostMutation({ + * selection: { fields: { id: true, name: true } }, * }); + * + * mutate({ id: 'value-here', patch: { name: 'Updated' } }); * \`\`\` */ -export function useUpdatePostMutation(options?: Omit, 'mutationFn'>) { +export function useUpdatePostMutation(params: { + selection: ({ + fields: S; + } & StrictSelect); +} & Omit; + }; +}, Error, { + id: string; + patch: PostPatch; +}>, "mutationFn">): UseMutationResult<{ + updatePost: { + post: InferSelectResult; + }; +}, Error, { + id: string; + patch: PostPatch; +}>; +export function useUpdatePostMutation(params?: { + selection?: ({ + fields?: undefined; + }); +} & Omit; + }; +}, Error, { + id: string; + patch: PostPatch; +}>, "mutationFn">): UseMutationResult<{ + updatePost: { + post: InferSelectResult; + }; +}, Error, { + id: string; + patch: PostPatch; +}>; +export function useUpdatePostMutation(params?: { + selection?: SelectionConfig; +} & Omit, "mutationFn">) { + const args = buildSelectionArgs(params?.selection); + const { + selection: _selection, + ...mutationOptions + } = params ?? {}; + void _selection; const queryClient = useQueryClient(); return useMutation({ mutationKey: postMutationKeys.all, - mutationFn: (variables: UpdatePostMutationVariables) => execute(updatePostMutationDocument, variables), + mutationFn: ({ + id, + patch + }: { + id: string; + patch: PostPatch; + }) => getClient().post.update({ + where: { + id + }, + data: patch, + select: (args?.select ?? defaultSelect) as PostSelect + }).unwrap(), onSuccess: (_, variables) => { queryClient.invalidateQueries({ - queryKey: postKeys.detail(variables.input.id) + queryKey: postKeys.detail(variables.id) }); queryClient.invalidateQueries({ queryKey: postKeys.lists() }); }, - ...options + ...mutationOptions }); -}" +} +" `; exports[`Mutation Hook Generators generateUpdateMutationHook generates update mutation hook without centralized keys 1`] = ` @@ -1104,71 +1611,105 @@ exports[`Mutation Hook Generators generateUpdateMutationHook generates update mu */ import { useMutation, useQueryClient } from "@tanstack/react-query"; -import type { UseMutationOptions } from "@tanstack/react-query"; -import { execute } from "../client"; -import type { User } from "../types"; -export type { User } from "../types"; -export const updateUserMutationDocument = \` -mutation UpdateUserMutation($input: UpdateUserInput!) { - updateUser(input: $input) { - user { - id - email - name - createdAt - } - } -} -\`; -/** Patch type for updating a User - all fields optional */ -interface UserPatch { - email?: string | null; - name?: string | null; - createdAt?: string | null; -} -export interface UpdateUserMutationVariables { - input: { - id: string; - patch: UserPatch; - }; -} -export interface UpdateUserMutationResult { - updateUser: { - user: User; - }; -} +import type { UseMutationOptions, UseMutationResult } from "@tanstack/react-query"; +import { getClient } from "../client"; +import { buildSelectionArgs } from "../selection"; +import type { SelectionConfig } from "../selection"; +import type { UserSelect, UserWithRelations, UserPatch } from "../../orm/input-types"; +import type { InferSelectResult, StrictSelect } from "../../orm/select-types"; +export type { UserSelect, UserWithRelations, UserPatch } from "../../orm/input-types"; +const defaultSelect = { + id: true +} as const; /** * Mutation hook for updating a User * * @example * \`\`\`tsx - * const { mutate, isPending } = useUpdateUserMutation(); - * - * mutate({ - * input: { - * id: 'value-here', - * patch: { - * // ... fields to update - * }, - * }, + * const { mutate, isPending } = useUpdateUserMutation({ + * selection: { fields: { id: true, name: true } }, * }); + * + * mutate({ id: 'value-here', patch: { name: 'Updated' } }); * \`\`\` */ -export function useUpdateUserMutation(options?: Omit, 'mutationFn'>) { +export function useUpdateUserMutation(params: { + selection: ({ + fields: S; + } & StrictSelect); +} & Omit; + }; +}, Error, { + id: string; + patch: UserPatch; +}>, "mutationFn">): UseMutationResult<{ + updateUser: { + user: InferSelectResult; + }; +}, Error, { + id: string; + patch: UserPatch; +}>; +export function useUpdateUserMutation(params?: { + selection?: ({ + fields?: undefined; + }); +} & Omit; + }; +}, Error, { + id: string; + patch: UserPatch; +}>, "mutationFn">): UseMutationResult<{ + updateUser: { + user: InferSelectResult; + }; +}, Error, { + id: string; + patch: UserPatch; +}>; +export function useUpdateUserMutation(params?: { + selection?: SelectionConfig; +} & Omit, "mutationFn">) { + const args = buildSelectionArgs(params?.selection); + const { + selection: _selection, + ...mutationOptions + } = params ?? {}; + void _selection; const queryClient = useQueryClient(); return useMutation({ - mutationFn: (variables: UpdateUserMutationVariables) => execute(updateUserMutationDocument, variables), + mutationFn: ({ + id, + patch + }: { + id: string; + patch: UserPatch; + }) => getClient().user.update({ + where: { + id + }, + data: patch, + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap(), onSuccess: (_, variables) => { queryClient.invalidateQueries({ - queryKey: ["user", "detail", variables.input.id] + queryKey: ["user", "detail", variables.id] }); queryClient.invalidateQueries({ queryKey: ["user", "list"] }); }, - ...options + ...mutationOptions }); -}" +} +" `; exports[`Query Hook Generators generateListQueryHook generates list query hook for simple table 1`] = ` @@ -1179,78 +1720,17 @@ exports[`Query Hook Generators generateListQueryHook generates list query hook f */ import { useQuery } from "@tanstack/react-query"; -import type { UseQueryOptions, QueryClient } from "@tanstack/react-query"; -import { execute } from "../client"; -import type { ExecuteOptions } from "../client"; -import type { User, UUIDFilter, StringFilter, DatetimeFilter } from "../types"; +import type { UseQueryOptions, UseQueryResult, QueryClient } from "@tanstack/react-query"; +import { getClient } from "../client"; +import { buildListSelectionArgs } from "../selection"; +import type { ListSelectionConfig } from "../selection"; import { userKeys } from "../query-keys"; -export type { User } from "../types"; -export const usersQueryDocument = \` -query UsersQuery($first: Int, $last: Int, $offset: Int, $before: Cursor, $after: Cursor, $filter: UserFilter, $condition: UserCondition, $orderBy: [UsersOrderBy!]) { - users( - first: $first - last: $last - offset: $offset - before: $before - after: $after - filter: $filter - condition: $condition - orderBy: $orderBy - ) { - totalCount - nodes { - id - email - name - createdAt - } - pageInfo { - hasNextPage - hasPreviousPage - startCursor - endCursor - } - } -} -\`; -interface UserFilter { - id?: UUIDFilter; - email?: StringFilter; - name?: StringFilter; - createdAt?: DatetimeFilter; - and?: UserFilter[]; - or?: UserFilter[]; - not?: UserFilter; -} -interface UserCondition { - id?: string; - email?: string; - name?: string; - createdAt?: string; -} -type UsersOrderBy = "ID_ASC" | "ID_DESC" | "EMAIL_ASC" | "EMAIL_DESC" | "NAME_ASC" | "NAME_DESC" | "CREATED_AT_ASC" | "CREATED_AT_DESC" | "NATURAL" | "PRIMARY_KEY_ASC" | "PRIMARY_KEY_DESC"; -export interface UsersQueryVariables { - first?: number; - last?: number; - offset?: number; - before?: string; - after?: string; - filter?: UserFilter; - condition?: UserCondition; - orderBy?: UsersOrderBy[]; -} -export interface UsersQueryResult { - users: { - totalCount: number; - nodes: User[]; - pageInfo: { - hasNextPage: boolean; - hasPreviousPage: boolean; - startCursor: string | null; - endCursor: string | null; - }; - }; -} +import type { UserSelect, UserWithRelations, UserFilter, UsersOrderBy } from "../../orm/input-types"; +import type { FindManyArgs, InferSelectResult, ConnectionResult, StrictSelect } from "../../orm/select-types"; +export type { UserSelect, UserWithRelations, UserFilter, UsersOrderBy } from "../../orm/input-types"; +const defaultSelect = { + id: true +} as const; /** Query key factory - re-exported from query-keys.ts */ export const usersQueryKey = userKeys.list; /** @@ -1259,17 +1739,50 @@ export const usersQueryKey = userKeys.list; * @example * \`\`\`tsx * const { data, isLoading } = useUsersQuery({ - * first: 10, - * filter: { name: { equalTo: "example" } }, - * orderBy: ['CREATED_AT_DESC'], + * selection: { + * fields: { id: true, name: true }, + * where: { name: { equalTo: "example" } }, + * orderBy: ['CREATED_AT_DESC'], + * first: 10, + * }, * }); * \`\`\` */ -export function useUsersQuery(variables?: UsersQueryVariables, options?: Omit, 'queryKey' | 'queryFn'>) { +export function useUsersQuery>; +}>(params: { + selection: { + fields: S; + } & Omit, "fields"> & StrictSelect; +} & Omit>; +}, Error, TData>, "queryKey" | "queryFn">): UseQueryResult; +export function useUsersQuery>; +}>(params?: { + selection?: Omit, "fields"> & { + fields?: undefined; + }; +} & Omit>; +}, Error, TData>, "queryKey" | "queryFn">): UseQueryResult; +export function useUsersQuery(params?: { + selection?: ListSelectionConfig; +} & Omit, "queryKey" | "queryFn">) { + const selection = params?.selection; + const args = buildListSelectionArgs(selection); + const { + selection: _selection, + ...queryOptions + } = params ?? {}; + void _selection; return useQuery({ - queryKey: userKeys.list(variables), - queryFn: () => execute(usersQueryDocument, variables), - ...options + queryKey: userKeys.list(args), + queryFn: () => getClient().user.findMany({ + ...(args ?? {}), + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap(), + ...queryOptions }); } /** @@ -1277,33 +1790,68 @@ export function useUsersQuery(variables?: UsersQueryVariables, options?: Omit fetchUsersQuery(variables), + * const data = await fetchUsersQuery({ + * selection: { + * fields: { id: true }, + * first: 10, + * }, * }); * \`\`\` */ -export async function fetchUsersQuery(variables?: UsersQueryVariables, options?: ExecuteOptions): Promise { - return execute(usersQueryDocument, variables, options); +export async function fetchUsersQuery(params: { + selection: { + fields: S; + } & Omit, "fields"> & StrictSelect; +}): Promise<{ + users: ConnectionResult>; +}>; +export async function fetchUsersQuery(params?: { + selection?: Omit, "fields"> & { + fields?: undefined; + }; +}): Promise<{ + users: ConnectionResult>; +}>; +export async function fetchUsersQuery(params?: { + selection?: ListSelectionConfig; +}) { + const args = buildListSelectionArgs(selection); + return getClient().user.findMany({ + ...(args ?? {}), + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap(); } /** * Prefetch User list for SSR or cache warming * * @example * \`\`\`ts - * await prefetchUsersQuery(queryClient, { first: 10 }); + * await prefetchUsersQuery(queryClient, { selection: { first: 10 } }); * \`\`\` */ -export async function prefetchUsersQuery(queryClient: QueryClient, variables?: UsersQueryVariables, options?: ExecuteOptions): Promise { +export async function prefetchUsersQuery(queryClient: QueryClient, params: { + selection: { + fields: S; + } & Omit, "fields"> & StrictSelect; +}): Promise; +export async function prefetchUsersQuery(queryClient: QueryClient, params?: { + selection?: Omit, "fields"> & { + fields?: undefined; + }; +}): Promise; +export async function prefetchUsersQuery(queryClient: QueryClient, params?: { + selection?: ListSelectionConfig; +}): void { + const args = buildListSelectionArgs(selection); await queryClient.prefetchQuery({ - queryKey: userKeys.list(variables), - queryFn: () => execute(usersQueryDocument, variables, options) + queryKey: userKeys.list(args), + queryFn: () => getClient().user.findMany({ + ...(args ?? {}), + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap() }); -}" +} +" `; exports[`Query Hook Generators generateListQueryHook generates list query hook for table with relationships 1`] = ` @@ -1314,85 +1862,18 @@ exports[`Query Hook Generators generateListQueryHook generates list query hook f */ import { useQuery } from "@tanstack/react-query"; -import type { UseQueryOptions, QueryClient } from "@tanstack/react-query"; -import { execute } from "../client"; -import type { ExecuteOptions } from "../client"; -import type { Post, UUIDFilter, StringFilter, BooleanFilter, DatetimeFilter } from "../types"; +import type { UseQueryOptions, UseQueryResult, QueryClient } from "@tanstack/react-query"; +import { getClient } from "../client"; +import { buildListSelectionArgs } from "../selection"; +import type { ListSelectionConfig } from "../selection"; import { postKeys } from "../query-keys"; import type { PostScope } from "../query-keys"; -export type { Post } from "../types"; -export const postsQueryDocument = \` -query PostsQuery($first: Int, $last: Int, $offset: Int, $before: Cursor, $after: Cursor, $filter: PostFilter, $condition: PostCondition, $orderBy: [PostsOrderBy!]) { - posts( - first: $first - last: $last - offset: $offset - before: $before - after: $after - filter: $filter - condition: $condition - orderBy: $orderBy - ) { - totalCount - nodes { - id - title - content - authorId - published - createdAt - } - pageInfo { - hasNextPage - hasPreviousPage - startCursor - endCursor - } - } -} -\`; -interface PostFilter { - id?: UUIDFilter; - title?: StringFilter; - content?: StringFilter; - authorId?: UUIDFilter; - published?: BooleanFilter; - createdAt?: DatetimeFilter; - and?: PostFilter[]; - or?: PostFilter[]; - not?: PostFilter; -} -interface PostCondition { - id?: string; - title?: string; - content?: string; - authorId?: string; - published?: boolean; - createdAt?: string; -} -type PostsOrderBy = "ID_ASC" | "ID_DESC" | "TITLE_ASC" | "TITLE_DESC" | "CONTENT_ASC" | "CONTENT_DESC" | "AUTHOR_ID_ASC" | "AUTHOR_ID_DESC" | "PUBLISHED_ASC" | "PUBLISHED_DESC" | "CREATED_AT_ASC" | "CREATED_AT_DESC" | "NATURAL" | "PRIMARY_KEY_ASC" | "PRIMARY_KEY_DESC"; -export interface PostsQueryVariables { - first?: number; - last?: number; - offset?: number; - before?: string; - after?: string; - filter?: PostFilter; - condition?: PostCondition; - orderBy?: PostsOrderBy[]; -} -export interface PostsQueryResult { - posts: { - totalCount: number; - nodes: Post[]; - pageInfo: { - hasNextPage: boolean; - hasPreviousPage: boolean; - startCursor: string | null; - endCursor: string | null; - }; - }; -} +import type { PostSelect, PostWithRelations, PostFilter, PostsOrderBy } from "../../orm/input-types"; +import type { FindManyArgs, InferSelectResult, ConnectionResult, StrictSelect } from "../../orm/select-types"; +export type { PostSelect, PostWithRelations, PostFilter, PostsOrderBy } from "../../orm/input-types"; +const defaultSelect = { + id: true +} as const; /** Query key factory - re-exported from query-keys.ts */ export const postsQueryKey = postKeys.list; /** @@ -1401,28 +1882,64 @@ export const postsQueryKey = postKeys.list; * @example * \`\`\`tsx * const { data, isLoading } = usePostsQuery({ - * first: 10, - * filter: { name: { equalTo: "example" } }, - * orderBy: ['CREATED_AT_DESC'], + * selection: { + * fields: { id: true, name: true }, + * where: { name: { equalTo: "example" } }, + * orderBy: ['CREATED_AT_DESC'], + * first: 10, + * }, * }); * \`\`\` * * @example With scope for hierarchical cache invalidation * \`\`\`tsx - * const { data } = usePostsQuery( - * { first: 10 }, - * { scope: { parentId: 'parent-id' } } - * ); + * const { data } = usePostsQuery({ + * selection: { first: 10 }, + * scope: { parentId: 'parent-id' }, + * }); * \`\`\` */ -export function usePostsQuery(variables?: PostsQueryVariables, options?: Omit, 'queryKey' | 'queryFn'> & { scope?: PostScope }) { +export function usePostsQuery>; +}>(params: { + selection: { + fields: S; + } & Omit, "fields"> & StrictSelect; +} & Omit>; +}, Error, TData>, "queryKey" | "queryFn"> & { + scope?: PostScope; +}): UseQueryResult; +export function usePostsQuery>; +}>(params?: { + selection?: Omit, "fields"> & { + fields?: undefined; + }; +} & Omit>; +}, Error, TData>, "queryKey" | "queryFn"> & { + scope?: PostScope; +}): UseQueryResult; +export function usePostsQuery(params?: { + selection?: ListSelectionConfig; +} & Omit, "queryKey" | "queryFn"> & { + scope?: PostScope; +}) { + const selection = params?.selection; + const args = buildListSelectionArgs(selection); const { scope, + selection: _selection, ...queryOptions - } = options ?? {}; + } = params ?? {}; + void _selection; return useQuery({ - queryKey: postKeys.list(variables, scope), - queryFn: () => execute(postsQueryDocument, variables), + queryKey: postKeys.list(args, scope), + queryFn: () => getClient().post.findMany({ + ...(args ?? {}), + select: (args?.select ?? defaultSelect) as PostSelect + }).unwrap(), ...queryOptions }); } @@ -1431,33 +1948,74 @@ export function usePostsQuery(variables?: PostsQueryVariables, options?: Omit fetchPostsQuery(variables), + * const data = await fetchPostsQuery({ + * selection: { + * fields: { id: true }, + * first: 10, + * }, * }); * \`\`\` */ -export async function fetchPostsQuery(variables?: PostsQueryVariables, options?: ExecuteOptions): Promise { - return execute(postsQueryDocument, variables, options); +export async function fetchPostsQuery(params: { + selection: { + fields: S; + } & Omit, "fields"> & StrictSelect; +}): Promise<{ + posts: ConnectionResult>; +}>; +export async function fetchPostsQuery(params?: { + selection?: Omit, "fields"> & { + fields?: undefined; + }; +}): Promise<{ + posts: ConnectionResult>; +}>; +export async function fetchPostsQuery(params?: { + selection?: ListSelectionConfig; +}) { + const args = buildListSelectionArgs(selection); + return getClient().post.findMany({ + ...(args ?? {}), + select: (args?.select ?? defaultSelect) as PostSelect + }).unwrap(); } /** * Prefetch Post list for SSR or cache warming * * @example * \`\`\`ts - * await prefetchPostsQuery(queryClient, { first: 10 }); + * await prefetchPostsQuery(queryClient, { selection: { first: 10 } }); * \`\`\` */ -export async function prefetchPostsQuery(queryClient: QueryClient, variables?: PostsQueryVariables, scope?: PostScope, options?: ExecuteOptions): Promise { +export async function prefetchPostsQuery(queryClient: QueryClient, params: { + selection: { + fields: S; + } & Omit, "fields"> & StrictSelect; +} & { + scope?: PostScope; +}): Promise; +export async function prefetchPostsQuery(queryClient: QueryClient, params?: { + selection?: Omit, "fields"> & { + fields?: undefined; + }; +} & { + scope?: PostScope; +}): Promise; +export async function prefetchPostsQuery(queryClient: QueryClient, params?: { + selection?: ListSelectionConfig; +} & { + scope?: PostScope; +}): void { + const args = buildListSelectionArgs(selection); await queryClient.prefetchQuery({ - queryKey: postKeys.list(variables, scope), - queryFn: () => execute(postsQueryDocument, variables, options) + queryKey: postKeys.list(args, params?.scope), + queryFn: () => getClient().post.findMany({ + ...(args ?? {}), + select: (args?.select ?? defaultSelect) as PostSelect + }).unwrap() }); -}" +} +" `; exports[`Query Hook Generators generateListQueryHook generates list query hook without centralized keys 1`] = ` @@ -1468,95 +2026,67 @@ exports[`Query Hook Generators generateListQueryHook generates list query hook w */ import { useQuery } from "@tanstack/react-query"; -import type { UseQueryOptions, QueryClient } from "@tanstack/react-query"; -import { execute } from "../client"; -import type { ExecuteOptions } from "../client"; -import type { User, UUIDFilter, StringFilter, DatetimeFilter } from "../types"; -export type { User } from "../types"; -export const usersQueryDocument = \` -query UsersQuery($first: Int, $last: Int, $offset: Int, $before: Cursor, $after: Cursor, $filter: UserFilter, $condition: UserCondition, $orderBy: [UsersOrderBy!]) { - users( - first: $first - last: $last - offset: $offset - before: $before - after: $after - filter: $filter - condition: $condition - orderBy: $orderBy - ) { - totalCount - nodes { - id - email - name - createdAt - } - pageInfo { - hasNextPage - hasPreviousPage - startCursor - endCursor - } - } -} -\`; -interface UserFilter { - id?: UUIDFilter; - email?: StringFilter; - name?: StringFilter; - createdAt?: DatetimeFilter; - and?: UserFilter[]; - or?: UserFilter[]; - not?: UserFilter; -} -interface UserCondition { - id?: string; - email?: string; - name?: string; - createdAt?: string; -} -type UsersOrderBy = "ID_ASC" | "ID_DESC" | "EMAIL_ASC" | "EMAIL_DESC" | "NAME_ASC" | "NAME_DESC" | "CREATED_AT_ASC" | "CREATED_AT_DESC" | "NATURAL" | "PRIMARY_KEY_ASC" | "PRIMARY_KEY_DESC"; -export interface UsersQueryVariables { - first?: number; - last?: number; - offset?: number; - before?: string; - after?: string; - filter?: UserFilter; - condition?: UserCondition; - orderBy?: UsersOrderBy[]; -} -export interface UsersQueryResult { - users: { - totalCount: number; - nodes: User[]; - pageInfo: { - hasNextPage: boolean; - hasPreviousPage: boolean; - startCursor: string | null; - endCursor: string | null; - }; - }; -} -export const usersQueryKey = (variables?: UsersQueryVariables) => ["user", "list", variables] as const; +import type { UseQueryOptions, UseQueryResult, QueryClient } from "@tanstack/react-query"; +import { getClient } from "../client"; +import { buildListSelectionArgs } from "../selection"; +import type { ListSelectionConfig } from "../selection"; +import type { UserSelect, UserWithRelations, UserFilter, UsersOrderBy } from "../../orm/input-types"; +import type { FindManyArgs, InferSelectResult, ConnectionResult, StrictSelect } from "../../orm/select-types"; +export type { UserSelect, UserWithRelations, UserFilter, UsersOrderBy } from "../../orm/input-types"; +const defaultSelect = { + id: true +} as const; +export const usersQueryKey = (variables?: FindManyArgs) => ["user", "list", variables] as const; /** * Query hook for fetching User list * * @example * \`\`\`tsx * const { data, isLoading } = useUsersQuery({ - * first: 10, - * filter: { name: { equalTo: "example" } }, - * orderBy: ['CREATED_AT_DESC'], + * selection: { + * fields: { id: true, name: true }, + * where: { name: { equalTo: "example" } }, + * orderBy: ['CREATED_AT_DESC'], + * first: 10, + * }, * }); * \`\`\` */ -export function useUsersQuery(variables?: UsersQueryVariables, options?: Omit, 'queryKey' | 'queryFn'>) { +export function useUsersQuery>; +}>(params: { + selection: { + fields: S; + } & Omit, "fields"> & StrictSelect; +} & Omit>; +}, Error, TData>, "queryKey" | "queryFn">): UseQueryResult; +export function useUsersQuery>; +}>(params?: { + selection?: Omit, "fields"> & { + fields?: undefined; + }; +} & Omit>; +}, Error, TData>, "queryKey" | "queryFn">): UseQueryResult; +export function useUsersQuery(params?: { + selection?: ListSelectionConfig; +} & Omit, "queryKey" | "queryFn">) { + const selection = params?.selection; + const args = buildListSelectionArgs(selection); + const { + selection: _selection, + ...queryOptions + } = params ?? {}; + void _selection; return useQuery({ - queryKey: usersQueryKey(variables), - queryFn: () => execute(usersQueryDocument, variables), - ...options + queryKey: usersQueryKey(args), + queryFn: () => getClient().user.findMany({ + ...(args ?? {}), + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap(), + ...queryOptions }); } /** @@ -1564,33 +2094,68 @@ export function useUsersQuery(variables?: UsersQueryVariables, options?: Omit fetchUsersQuery(variables), + * const data = await fetchUsersQuery({ + * selection: { + * fields: { id: true }, + * first: 10, + * }, * }); * \`\`\` */ -export async function fetchUsersQuery(variables?: UsersQueryVariables, options?: ExecuteOptions): Promise { - return execute(usersQueryDocument, variables, options); +export async function fetchUsersQuery(params: { + selection: { + fields: S; + } & Omit, "fields"> & StrictSelect; +}): Promise<{ + users: ConnectionResult>; +}>; +export async function fetchUsersQuery(params?: { + selection?: Omit, "fields"> & { + fields?: undefined; + }; +}): Promise<{ + users: ConnectionResult>; +}>; +export async function fetchUsersQuery(params?: { + selection?: ListSelectionConfig; +}) { + const args = buildListSelectionArgs(selection); + return getClient().user.findMany({ + ...(args ?? {}), + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap(); } /** * Prefetch User list for SSR or cache warming * * @example * \`\`\`ts - * await prefetchUsersQuery(queryClient, { first: 10 }); + * await prefetchUsersQuery(queryClient, { selection: { first: 10 } }); * \`\`\` */ -export async function prefetchUsersQuery(queryClient: QueryClient, variables?: UsersQueryVariables, options?: ExecuteOptions): Promise { +export async function prefetchUsersQuery(queryClient: QueryClient, params: { + selection: { + fields: S; + } & Omit, "fields"> & StrictSelect; +}): Promise; +export async function prefetchUsersQuery(queryClient: QueryClient, params?: { + selection?: Omit, "fields"> & { + fields?: undefined; + }; +}): Promise; +export async function prefetchUsersQuery(queryClient: QueryClient, params?: { + selection?: ListSelectionConfig; +}): void { + const args = buildListSelectionArgs(selection); await queryClient.prefetchQuery({ - queryKey: usersQueryKey(variables), - queryFn: () => execute(usersQueryDocument, variables, options) + queryKey: usersQueryKey(args), + queryFn: () => getClient().user.findMany({ + ...(args ?? {}), + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap() }); -}" +} +" `; exports[`Query Hook Generators generateSingleQueryHook generates single query hook for simple table 1`] = ` @@ -1601,28 +2166,17 @@ exports[`Query Hook Generators generateSingleQueryHook generates single query ho */ import { useQuery } from "@tanstack/react-query"; -import type { UseQueryOptions, QueryClient } from "@tanstack/react-query"; -import { execute } from "../client"; -import type { ExecuteOptions } from "../client"; -import type { User } from "../types"; +import type { UseQueryOptions, UseQueryResult, QueryClient } from "@tanstack/react-query"; +import { getClient } from "../client"; +import { buildSelectionArgs } from "../selection"; +import type { SelectionConfig } from "../selection"; import { userKeys } from "../query-keys"; -export type { User } from "../types"; -export const userQueryDocument = \` -query UserQuery($id: UUID!) { - user(id: $id) { - id - email - name - createdAt - } -} -\`; -export interface UserQueryVariables { - id: string; -} -export interface UserQueryResult { - user: User | null; -} +import type { UserSelect, UserWithRelations } from "../../orm/input-types"; +import type { InferSelectResult, StrictSelect } from "../../orm/select-types"; +export type { UserSelect, UserWithRelations } from "../../orm/input-types"; +const defaultSelect = { + id: true +} as const; /** Query key factory - re-exported from query-keys.ts */ export const userQueryKey = userKeys.detail; /** @@ -1630,14 +2184,50 @@ export const userQueryKey = userKeys.detail; * * @example * \`\`\`tsx - * const { data, isLoading } = useUserQuery({ id: 'some-id' }); + * const { data, isLoading } = useUserQuery({ + * id: 'some-id', + * selection: { fields: { id: true, name: true } }, + * }); * \`\`\` */ -export function useUserQuery(variables: UserQueryVariables, options?: Omit, 'queryKey' | 'queryFn'>) { +export function useUserQuery | null; +}>(params: { + id: string; + selection: { + fields: S; + } & StrictSelect; +} & Omit | null; +}, Error, TData>, "queryKey" | "queryFn">): UseQueryResult; +export function useUserQuery | null; +}>(params: { + id: string; + selection?: { + fields?: undefined; + }; +} & Omit | null; +}, Error, TData>, "queryKey" | "queryFn">): UseQueryResult; +export function useUserQuery(params: { + id: string; + selection?: SelectionConfig; +} & Omit, "queryKey" | "queryFn">) { + const args = buildSelectionArgs(params.selection); + const { + selection: _selection, + ...queryOptions + } = params ?? {}; + void _selection; return useQuery({ - queryKey: userKeys.detail(variables.id), - queryFn: () => execute(userQueryDocument, variables), - ...options + queryKey: userKeys.detail(params.id), + queryFn: () => getClient().user.findOne({ + id: params.id, + ...(args ?? {}), + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap(), + ...queryOptions }); } /** @@ -1645,11 +2235,38 @@ export function useUserQuery(variables: UserQueryVariables, options?: Omit { - return execute(userQueryDocument, variables, options); +export async function fetchUserQuery(params: { + id: string; + selection: { + fields: S; + } & StrictSelect; +}): Promise<{ + user: InferSelectResult | null; +}>; +export async function fetchUserQuery(params: { + id: string; + selection?: { + fields?: undefined; + }; +}): Promise<{ + user: InferSelectResult | null; +}>; +export async function fetchUserQuery(params: { + id: string; + selection?: SelectionConfig; +}) { + const args = buildSelectionArgs(params.selection); + return getClient().user.findOne({ + id: params.id, + ...(args ?? {}), + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap(); } /** * Prefetch a single User for SSR or cache warming @@ -1659,12 +2276,33 @@ export async function fetchUserQuery(variables: UserQueryVariables, options?: Ex * await prefetchUserQuery(queryClient, { id: 'some-id' }); * \`\`\` */ -export async function prefetchUserQuery(queryClient: QueryClient, variables: UserQueryVariables, options?: ExecuteOptions): Promise { +export async function prefetchUserQuery(queryClient: QueryClient, params: { + id: string; + selection: { + fields: S; + } & StrictSelect; +}): Promise; +export async function prefetchUserQuery(queryClient: QueryClient, params: { + id: string; + selection?: { + fields?: undefined; + }; +}): Promise; +export async function prefetchUserQuery(queryClient: QueryClient, params: { + id: string; + selection?: SelectionConfig; +}): void { + const args = buildSelectionArgs(params.selection); await queryClient.prefetchQuery({ - queryKey: userKeys.detail(variables.id), - queryFn: () => execute(userQueryDocument, variables, options) + queryKey: userKeys.detail(params.id), + queryFn: () => getClient().user.findOne({ + id: params.id, + ...(args ?? {}), + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap() }); -}" +} +" `; exports[`Query Hook Generators generateSingleQueryHook generates single query hook for table with relationships 1`] = ` @@ -1675,31 +2313,18 @@ exports[`Query Hook Generators generateSingleQueryHook generates single query ho */ import { useQuery } from "@tanstack/react-query"; -import type { UseQueryOptions, QueryClient } from "@tanstack/react-query"; -import { execute } from "../client"; -import type { ExecuteOptions } from "../client"; -import type { Post } from "../types"; +import type { UseQueryOptions, UseQueryResult, QueryClient } from "@tanstack/react-query"; +import { getClient } from "../client"; +import { buildSelectionArgs } from "../selection"; +import type { SelectionConfig } from "../selection"; import { postKeys } from "../query-keys"; import type { PostScope } from "../query-keys"; -export type { Post } from "../types"; -export const postQueryDocument = \` -query PostQuery($id: UUID!) { - post(id: $id) { - id - title - content - authorId - published - createdAt - } -} -\`; -export interface PostQueryVariables { - id: string; -} -export interface PostQueryResult { - post: Post | null; -} +import type { PostSelect, PostWithRelations } from "../../orm/input-types"; +import type { InferSelectResult, StrictSelect } from "../../orm/select-types"; +export type { PostSelect, PostWithRelations } from "../../orm/input-types"; +const defaultSelect = { + id: true +} as const; /** Query key factory - re-exported from query-keys.ts */ export const postQueryKey = postKeys.detail; /** @@ -1707,25 +2332,64 @@ export const postQueryKey = postKeys.detail; * * @example * \`\`\`tsx - * const { data, isLoading } = usePostQuery({ id: 'some-id' }); + * const { data, isLoading } = usePostQuery({ + * id: 'some-id', + * selection: { fields: { id: true, name: true } }, + * }); * \`\`\` * * @example With scope for hierarchical cache invalidation * \`\`\`tsx - * const { data } = usePostQuery( - * { id: 'some-id' }, - * { scope: { parentId: 'parent-id' } } - * ); + * const { data } = usePostQuery({ + * id: 'some-id', + * scope: { parentId: 'parent-id' }, + * }); * \`\`\` */ -export function usePostQuery(variables: PostQueryVariables, options?: Omit, 'queryKey' | 'queryFn'> & { scope?: PostScope }) { +export function usePostQuery | null; +}>(params: { + id: string; + selection: { + fields: S; + } & StrictSelect; +} & Omit | null; +}, Error, TData>, "queryKey" | "queryFn"> & { + scope?: PostScope; +}): UseQueryResult; +export function usePostQuery | null; +}>(params: { + id: string; + selection?: { + fields?: undefined; + }; +} & Omit | null; +}, Error, TData>, "queryKey" | "queryFn"> & { + scope?: PostScope; +}): UseQueryResult; +export function usePostQuery(params: { + id: string; + selection?: SelectionConfig; +} & Omit, "queryKey" | "queryFn"> & { + scope?: PostScope; +}) { + const args = buildSelectionArgs(params.selection); const { scope, + selection: _selection, ...queryOptions - } = options ?? {}; + } = params ?? {}; + void _selection; return useQuery({ - queryKey: postKeys.detail(variables.id, scope), - queryFn: () => execute(postQueryDocument, variables), + queryKey: postKeys.detail(params.id, scope), + queryFn: () => getClient().post.findOne({ + id: params.id, + ...(args ?? {}), + select: (args?.select ?? defaultSelect) as PostSelect + }).unwrap(), ...queryOptions }); } @@ -1734,11 +2398,38 @@ export function usePostQuery(variables: PostQueryVariables, options?: Omit { - return execute(postQueryDocument, variables, options); +export async function fetchPostQuery(params: { + id: string; + selection: { + fields: S; + } & StrictSelect; +}): Promise<{ + post: InferSelectResult | null; +}>; +export async function fetchPostQuery(params: { + id: string; + selection?: { + fields?: undefined; + }; +}): Promise<{ + post: InferSelectResult | null; +}>; +export async function fetchPostQuery(params: { + id: string; + selection?: SelectionConfig; +}) { + const args = buildSelectionArgs(params.selection); + return getClient().post.findOne({ + id: params.id, + ...(args ?? {}), + select: (args?.select ?? defaultSelect) as PostSelect + }).unwrap(); } /** * Prefetch a single Post for SSR or cache warming @@ -1748,12 +2439,39 @@ export async function fetchPostQuery(variables: PostQueryVariables, options?: Ex * await prefetchPostQuery(queryClient, { id: 'some-id' }); * \`\`\` */ -export async function prefetchPostQuery(queryClient: QueryClient, variables: PostQueryVariables, scope?: PostScope, options?: ExecuteOptions): Promise { +export async function prefetchPostQuery(queryClient: QueryClient, params: { + id: string; + selection: { + fields: S; + } & StrictSelect; +} & { + scope?: PostScope; +}): Promise; +export async function prefetchPostQuery(queryClient: QueryClient, params: { + id: string; + selection?: { + fields?: undefined; + }; +} & { + scope?: PostScope; +}): Promise; +export async function prefetchPostQuery(queryClient: QueryClient, params: { + id: string; + selection?: SelectionConfig; +} & { + scope?: PostScope; +}): void { + const args = buildSelectionArgs(params.selection); await queryClient.prefetchQuery({ - queryKey: postKeys.detail(variables.id, scope), - queryFn: () => execute(postQueryDocument, variables, options) + queryKey: postKeys.detail(params.id, params?.scope), + queryFn: () => getClient().post.findOne({ + id: params.id, + ...(args ?? {}), + select: (args?.select ?? defaultSelect) as PostSelect + }).unwrap() }); -}" +} +" `; exports[`Query Hook Generators generateSingleQueryHook generates single query hook without centralized keys 1`] = ` @@ -1764,41 +2482,66 @@ exports[`Query Hook Generators generateSingleQueryHook generates single query ho */ import { useQuery } from "@tanstack/react-query"; -import type { UseQueryOptions, QueryClient } from "@tanstack/react-query"; -import { execute } from "../client"; -import type { ExecuteOptions } from "../client"; -import type { User } from "../types"; -export type { User } from "../types"; -export const userQueryDocument = \` -query UserQuery($id: UUID!) { - user(id: $id) { - id - email - name - createdAt - } -} -\`; -export interface UserQueryVariables { - id: string; -} -export interface UserQueryResult { - user: User | null; -} +import type { UseQueryOptions, UseQueryResult, QueryClient } from "@tanstack/react-query"; +import { getClient } from "../client"; +import { buildSelectionArgs } from "../selection"; +import type { SelectionConfig } from "../selection"; +import type { UserSelect, UserWithRelations } from "../../orm/input-types"; +import type { InferSelectResult, StrictSelect } from "../../orm/select-types"; +export type { UserSelect, UserWithRelations } from "../../orm/input-types"; +const defaultSelect = { + id: true +} as const; export const userQueryKey = (id: string) => ["user", "detail", id] as const; /** * Query hook for fetching a single User * * @example * \`\`\`tsx - * const { data, isLoading } = useUserQuery({ id: 'some-id' }); + * const { data, isLoading } = useUserQuery({ + * id: 'some-id', + * selection: { fields: { id: true, name: true } }, + * }); * \`\`\` */ -export function useUserQuery(variables: UserQueryVariables, options?: Omit, 'queryKey' | 'queryFn'>) { +export function useUserQuery | null; +}>(params: { + id: string; + selection: { + fields: S; + } & StrictSelect; +} & Omit | null; +}, Error, TData>, "queryKey" | "queryFn">): UseQueryResult; +export function useUserQuery | null; +}>(params: { + id: string; + selection?: { + fields?: undefined; + }; +} & Omit | null; +}, Error, TData>, "queryKey" | "queryFn">): UseQueryResult; +export function useUserQuery(params: { + id: string; + selection?: SelectionConfig; +} & Omit, "queryKey" | "queryFn">) { + const args = buildSelectionArgs(params.selection); + const { + selection: _selection, + ...queryOptions + } = params ?? {}; + void _selection; return useQuery({ - queryKey: userQueryKey(variables.id), - queryFn: () => execute(userQueryDocument, variables), - ...options + queryKey: userQueryKey(params.id), + queryFn: () => getClient().user.findOne({ + id: params.id, + ...(args ?? {}), + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap(), + ...queryOptions }); } /** @@ -1806,11 +2549,38 @@ export function useUserQuery(variables: UserQueryVariables, options?: Omit { - return execute(userQueryDocument, variables, options); +export async function fetchUserQuery(params: { + id: string; + selection: { + fields: S; + } & StrictSelect; +}): Promise<{ + user: InferSelectResult | null; +}>; +export async function fetchUserQuery(params: { + id: string; + selection?: { + fields?: undefined; + }; +}): Promise<{ + user: InferSelectResult | null; +}>; +export async function fetchUserQuery(params: { + id: string; + selection?: SelectionConfig; +}) { + const args = buildSelectionArgs(params.selection); + return getClient().user.findOne({ + id: params.id, + ...(args ?? {}), + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap(); } /** * Prefetch a single User for SSR or cache warming @@ -1820,12 +2590,33 @@ export async function fetchUserQuery(variables: UserQueryVariables, options?: Ex * await prefetchUserQuery(queryClient, { id: 'some-id' }); * \`\`\` */ -export async function prefetchUserQuery(queryClient: QueryClient, variables: UserQueryVariables, options?: ExecuteOptions): Promise { +export async function prefetchUserQuery(queryClient: QueryClient, params: { + id: string; + selection: { + fields: S; + } & StrictSelect; +}): Promise; +export async function prefetchUserQuery(queryClient: QueryClient, params: { + id: string; + selection?: { + fields?: undefined; + }; +}): Promise; +export async function prefetchUserQuery(queryClient: QueryClient, params: { + id: string; + selection?: SelectionConfig; +}): void { + const args = buildSelectionArgs(params.selection); await queryClient.prefetchQuery({ - queryKey: userQueryKey(variables.id), - queryFn: () => execute(userQueryDocument, variables, options) + queryKey: userQueryKey(params.id), + queryFn: () => getClient().user.findOne({ + id: params.id, + ...(args ?? {}), + select: (args?.select ?? defaultSelect) as UserSelect + }).unwrap() }); -}" +} +" `; exports[`Schema Types Generator generateSchemaTypesFile generates schema types file with empty table types 1`] = ` diff --git a/graphql/codegen/src/__tests__/codegen/client-generator.test.ts b/graphql/codegen/src/__tests__/codegen/client-generator.test.ts index afcf275e4..3bd0fbc02 100644 --- a/graphql/codegen/src/__tests__/codegen/client-generator.test.ts +++ b/graphql/codegen/src/__tests__/codegen/client-generator.test.ts @@ -4,12 +4,12 @@ * Tests the generated ORM client files: client.ts, query-builder.ts, select-types.ts, index.ts */ import { + generateCreateClientFile, generateOrmClientFile, generateQueryBuilderFile, - generateSelectTypesFile, - generateCreateClientFile, + generateSelectTypesFile } from '../../core/codegen/orm/client-generator'; -import type { CleanTable, CleanFieldType, CleanRelations } from '../../types/schema'; +import type { CleanFieldType, CleanRelations,CleanTable } from '../../types/schema'; // ============================================================================ // Test Fixtures @@ -17,14 +17,14 @@ import type { CleanTable, CleanFieldType, CleanRelations } from '../../types/sch const fieldTypes = { uuid: { gqlType: 'UUID', isArray: false } as CleanFieldType, - string: { gqlType: 'String', isArray: false } as CleanFieldType, + string: { gqlType: 'String', isArray: false } as CleanFieldType }; const emptyRelations: CleanRelations = { belongsTo: [], hasOne: [], hasMany: [], - manyToMany: [], + manyToMany: [] }; function createTable(partial: Partial & { name: string }): CleanTable { @@ -34,7 +34,7 @@ function createTable(partial: Partial & { name: string }): CleanTabl relations: partial.relations ?? emptyRelations, query: partial.query, inflection: partial.inflection, - constraints: partial.constraints, + constraints: partial.constraints }; } @@ -91,13 +91,13 @@ describe('client-generator', () => { createTable({ name: 'User', fields: [{ name: 'id', type: fieldTypes.uuid }], - query: { all: 'users', one: 'user', create: 'createUser', update: 'updateUser', delete: 'deleteUser' }, + query: { all: 'users', one: 'user', create: 'createUser', update: 'updateUser', delete: 'deleteUser' } }), createTable({ name: 'Post', fields: [{ name: 'id', type: fieldTypes.uuid }], - query: { all: 'posts', one: 'post', create: 'createPost', update: 'updatePost', delete: 'deletePost' }, - }), + query: { all: 'posts', one: 'post', create: 'createPost', update: 'updatePost', delete: 'deletePost' } + }) ]; const result = generateCreateClientFile(tables, false, false); @@ -114,8 +114,8 @@ describe('client-generator', () => { createTable({ name: 'User', fields: [{ name: 'id', type: fieldTypes.uuid }], - query: { all: 'users', one: 'user', create: 'createUser', update: 'updateUser', delete: 'deleteUser' }, - }), + query: { all: 'users', one: 'user', create: 'createUser', update: 'updateUser', delete: 'deleteUser' } + }) ]; const result = generateCreateClientFile(tables, true, true); @@ -123,8 +123,8 @@ describe('client-generator', () => { expect(result.content).toMatchSnapshot(); expect(result.content).toContain('createQueryOperations'); expect(result.content).toContain('createMutationOperations'); - expect(result.content).toContain("query: createQueryOperations(client)"); - expect(result.content).toContain("mutation: createMutationOperations(client)"); + expect(result.content).toContain('query: createQueryOperations(client)'); + expect(result.content).toContain('mutation: createMutationOperations(client)'); }); }); }); diff --git a/graphql/codegen/src/__tests__/codegen/format-output.test.ts b/graphql/codegen/src/__tests__/codegen/format-output.test.ts index bb8b87099..35169f7fb 100644 --- a/graphql/codegen/src/__tests__/codegen/format-output.test.ts +++ b/graphql/codegen/src/__tests__/codegen/format-output.test.ts @@ -3,8 +3,9 @@ * Verifies that oxfmt formats generated code correctly */ import * as fs from 'node:fs'; -import * as path from 'node:path'; import * as os from 'node:os'; +import * as path from 'node:path'; + import { formatOutput } from '../../core/output'; describe('formatOutput', () => { 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 d509456fa..241a7ae69 100644 --- a/graphql/codegen/src/__tests__/codegen/input-types-generator.test.ts +++ b/graphql/codegen/src/__tests__/codegen/input-types-generator.test.ts @@ -6,15 +6,15 @@ * used to validate the AST-based migration produces equivalent results. */ // Jest globals - no import needed -import { generateInputTypesFile, collectInputTypeNames, collectPayloadTypeNames } from '../../core/codegen/orm/input-types-generator'; +import { collectInputTypeNames, collectPayloadTypeNames,generateInputTypesFile } from '../../core/codegen/orm/input-types-generator'; import type { - CleanTable, + CleanArgument, CleanFieldType, CleanRelations, - TypeRegistry, - ResolvedType, - CleanArgument, + CleanTable, CleanTypeRef, + ResolvedType, + TypeRegistry } from '../../types/schema'; // ============================================================================ @@ -32,7 +32,7 @@ const fieldTypes = { json: { gqlType: 'JSON', isArray: false } as CleanFieldType, bigint: { gqlType: 'BigInt', isArray: false } as CleanFieldType, stringArray: { gqlType: 'String', isArray: true } as CleanFieldType, - intArray: { gqlType: 'Int', isArray: true } as CleanFieldType, + intArray: { gqlType: 'Int', isArray: true } as CleanFieldType }; // ============================================================================ @@ -43,7 +43,7 @@ const emptyRelations: CleanRelations = { belongsTo: [], hasOne: [], hasMany: [], - manyToMany: [], + manyToMany: [] }; function createTable(partial: Partial & { name: string }): CleanTable { @@ -53,7 +53,7 @@ function createTable(partial: Partial & { name: string }): CleanTabl relations: partial.relations ?? emptyRelations, query: partial.query, inflection: partial.inflection, - constraints: partial.constraints, + constraints: partial.constraints }; } @@ -89,15 +89,15 @@ const userTable = createTable({ { name: 'age', type: fieldTypes.int }, { name: 'isActive', type: fieldTypes.boolean }, { name: 'createdAt', type: fieldTypes.datetime }, - { name: 'metadata', type: fieldTypes.json }, + { name: 'metadata', type: fieldTypes.json } ], query: { all: 'users', one: 'user', create: 'createUser', update: 'updateUser', - delete: 'deleteUser', - }, + delete: 'deleteUser' + } }); /** @@ -111,7 +111,7 @@ const postTable = createTable({ { name: 'content', type: fieldTypes.string }, { name: 'authorId', type: fieldTypes.uuid }, { name: 'publishedAt', type: fieldTypes.datetime }, - { name: 'tags', type: fieldTypes.stringArray }, + { name: 'tags', type: fieldTypes.stringArray } ], relations: { belongsTo: [ @@ -120,8 +120,8 @@ const postTable = createTable({ isUnique: false, referencesTable: 'User', type: null, - keys: [{ name: 'authorId', type: fieldTypes.uuid }], - }, + keys: [{ name: 'authorId', type: fieldTypes.uuid }] + } ], hasOne: [], hasMany: [ @@ -130,18 +130,18 @@ const postTable = createTable({ isUnique: false, referencedByTable: 'Comment', type: null, - keys: [], - }, + keys: [] + } ], - manyToMany: [], + manyToMany: [] }, query: { all: 'posts', one: 'post', create: 'createPost', update: 'updatePost', - delete: 'deletePost', - }, + delete: 'deletePost' + } }); /** @@ -154,7 +154,7 @@ const commentTable = createTable({ { name: 'body', type: fieldTypes.string }, { name: 'postId', type: fieldTypes.uuid }, { name: 'authorId', type: fieldTypes.uuid }, - { name: 'createdAt', type: fieldTypes.datetime }, + { name: 'createdAt', type: fieldTypes.datetime } ], relations: { belongsTo: [ @@ -163,27 +163,27 @@ const commentTable = createTable({ isUnique: false, referencesTable: 'Post', type: null, - keys: [], + keys: [] }, { fieldName: 'author', isUnique: false, referencesTable: 'User', type: null, - keys: [], - }, + keys: [] + } ], hasOne: [], hasMany: [], - manyToMany: [], + manyToMany: [] }, query: { all: 'comments', one: 'comment', create: 'createComment', update: 'updateComment', - delete: 'deleteComment', - }, + delete: 'deleteComment' + } }); /** @@ -200,18 +200,18 @@ const userTableWithRelations = createTable({ isUnique: false, referencedByTable: 'Post', type: null, - keys: [], + keys: [] }, { fieldName: 'comments', isUnique: false, referencedByTable: 'Comment', type: null, - keys: [], - }, + keys: [] + } ], - manyToMany: [], - }, + manyToMany: [] + } }); /** @@ -222,7 +222,7 @@ const categoryTable = createTable({ fields: [ { name: 'id', type: fieldTypes.uuid }, { name: 'name', type: fieldTypes.string }, - { name: 'slug', type: fieldTypes.string }, + { name: 'slug', type: fieldTypes.string } ], relations: { belongsTo: [], @@ -233,17 +233,17 @@ const categoryTable = createTable({ fieldName: 'posts', rightTable: 'Post', junctionTable: 'PostCategory', - type: null, - }, - ], + type: null + } + ] }, query: { all: 'categories', one: 'category', create: 'createCategory', update: 'updateCategory', - delete: 'deleteCategory', - }, + delete: 'deleteCategory' + } }); /** @@ -255,7 +255,7 @@ const profileTable = createTable({ { name: 'id', type: fieldTypes.uuid }, { name: 'bio', type: fieldTypes.string }, { name: 'userId', type: fieldTypes.uuid }, - { name: 'avatarUrl', type: fieldTypes.string }, + { name: 'avatarUrl', type: fieldTypes.string } ], relations: { belongsTo: [ @@ -264,20 +264,20 @@ const profileTable = createTable({ isUnique: true, referencesTable: 'User', type: null, - keys: [], - }, + keys: [] + } ], hasOne: [], hasMany: [], - manyToMany: [], + manyToMany: [] }, query: { all: 'profiles', one: 'profile', create: 'createProfile', update: 'updateProfile', - delete: 'deleteProfile', - }, + delete: 'deleteProfile' + } }); // User with hasOne to profile @@ -291,8 +291,8 @@ const userTableWithProfile = createTable({ isUnique: true, referencedByTable: 'Profile', type: null, - keys: [], - }, + keys: [] + } ], hasMany: [ { @@ -300,11 +300,11 @@ const userTableWithProfile = createTable({ isUnique: false, referencedByTable: 'Post', type: null, - keys: [], - }, + keys: [] + } ], - manyToMany: [], - }, + manyToMany: [] + } }); // ============================================================================ @@ -318,8 +318,8 @@ const sampleTypeRegistry = createTypeRegistry({ inputFields: [ { name: 'email', type: createNonNull(createTypeRef('SCALAR', 'String')) }, { name: 'password', type: createNonNull(createTypeRef('SCALAR', 'String')) }, - { name: 'rememberMe', type: createTypeRef('SCALAR', 'Boolean') }, - ], + { name: 'rememberMe', type: createTypeRef('SCALAR', 'Boolean') } + ] }, RegisterInput: { kind: 'INPUT_OBJECT', @@ -327,13 +327,13 @@ const sampleTypeRegistry = createTypeRegistry({ inputFields: [ { name: 'email', type: createNonNull(createTypeRef('SCALAR', 'String')) }, { name: 'password', type: createNonNull(createTypeRef('SCALAR', 'String')) }, - { name: 'name', type: createTypeRef('SCALAR', 'String') }, - ], + { name: 'name', type: createTypeRef('SCALAR', 'String') } + ] }, UserRole: { kind: 'ENUM', name: 'UserRole', - enumValues: ['ADMIN', 'USER', 'GUEST'], + enumValues: ['ADMIN', 'USER', 'GUEST'] }, LoginPayload: { kind: 'OBJECT', @@ -341,9 +341,9 @@ const sampleTypeRegistry = createTypeRegistry({ fields: [ { name: 'token', type: createTypeRef('SCALAR', 'String') }, { name: 'user', type: createTypeRef('OBJECT', 'User') }, - { name: 'expiresAt', type: createTypeRef('SCALAR', 'Datetime') }, - ], - }, + { name: 'expiresAt', type: createTypeRef('SCALAR', 'Datetime') } + ] + } }); // ============================================================================ @@ -646,14 +646,14 @@ describe('collectInputTypeNames', () => { const operations = [ { args: [ - { name: 'input', type: createNonNull(createTypeRef('INPUT_OBJECT', 'LoginInput')) }, - ] as CleanArgument[], + { name: 'input', type: createNonNull(createTypeRef('INPUT_OBJECT', 'LoginInput')) } + ] as CleanArgument[] }, { args: [ - { name: 'data', type: createTypeRef('INPUT_OBJECT', 'RegisterInput') }, - ] as CleanArgument[], - }, + { name: 'data', type: createTypeRef('INPUT_OBJECT', 'RegisterInput') } + ] as CleanArgument[] + } ]; const result = collectInputTypeNames(operations); @@ -666,9 +666,9 @@ describe('collectInputTypeNames', () => { const operations = [ { args: [ - { name: 'filter', type: createTypeRef('INPUT_OBJECT', 'UserFilter') }, - ] as CleanArgument[], - }, + { name: 'filter', type: createTypeRef('INPUT_OBJECT', 'UserFilter') } + ] as CleanArgument[] + } ]; const result = collectInputTypeNames(operations); @@ -681,7 +681,7 @@ describe('collectPayloadTypeNames', () => { it('collects Payload type names from operations', () => { const operations = [ { returnType: createTypeRef('OBJECT', 'LoginPayload') }, - { returnType: createTypeRef('OBJECT', 'RegisterPayload') }, + { returnType: createTypeRef('OBJECT', 'RegisterPayload') } ]; const result = collectPayloadTypeNames(operations); @@ -690,14 +690,14 @@ describe('collectPayloadTypeNames', () => { expect(result.has('RegisterPayload')).toBe(true); }); - it('excludes Connection types', () => { + it('includes Connection types', () => { const operations = [ - { returnType: createTypeRef('OBJECT', 'UsersConnection') }, + { returnType: createTypeRef('OBJECT', 'UsersConnection') } ]; const result = collectPayloadTypeNames(operations); - expect(result.has('UsersConnection')).toBe(false); + expect(result.has('UsersConnection')).toBe(true); }); }); @@ -717,7 +717,7 @@ describe('edge cases', () => { it('handles table with only id field', () => { const minimalTable = createTable({ name: 'Minimal', - fields: [{ name: 'id', type: fieldTypes.uuid }], + fields: [{ name: 'id', type: fieldTypes.uuid }] }); const result = generateInputTypesFile(new Map(), new Set(), [minimalTable]); diff --git a/graphql/codegen/src/__tests__/codegen/model-generator.test.ts b/graphql/codegen/src/__tests__/codegen/model-generator.test.ts index 1a27b9062..86de98981 100644 --- a/graphql/codegen/src/__tests__/codegen/model-generator.test.ts +++ b/graphql/codegen/src/__tests__/codegen/model-generator.test.ts @@ -4,7 +4,7 @@ * Tests the generated model classes with findMany, findFirst, create, update, delete methods. */ import { generateModelFile } from '../../core/codegen/orm/model-generator'; -import type { CleanTable, CleanFieldType, CleanRelations } from '../../types/schema'; +import type { CleanFieldType, CleanRelations,CleanTable } from '../../types/schema'; // ============================================================================ // Test Fixtures @@ -15,14 +15,14 @@ const fieldTypes = { string: { gqlType: 'String', isArray: false } as CleanFieldType, int: { gqlType: 'Int', isArray: false } as CleanFieldType, boolean: { gqlType: 'Boolean', isArray: false } as CleanFieldType, - datetime: { gqlType: 'Datetime', isArray: false } as CleanFieldType, + datetime: { gqlType: 'Datetime', isArray: false } as CleanFieldType }; const emptyRelations: CleanRelations = { belongsTo: [], hasOne: [], hasMany: [], - manyToMany: [], + manyToMany: [] }; function createTable(partial: Partial & { name: string }): CleanTable { @@ -32,7 +32,7 @@ function createTable(partial: Partial & { name: string }): CleanTabl relations: partial.relations ?? emptyRelations, query: partial.query, inflection: partial.inflection, - constraints: partial.constraints, + constraints: partial.constraints }; } @@ -49,15 +49,15 @@ describe('model-generator', () => { { name: 'email', type: fieldTypes.string }, { name: 'name', type: fieldTypes.string }, { name: 'isActive', type: fieldTypes.boolean }, - { name: 'createdAt', type: fieldTypes.datetime }, + { name: 'createdAt', type: fieldTypes.datetime } ], query: { all: 'users', one: 'user', create: 'createUser', update: 'updateUser', - delete: 'deleteUser', - }, + delete: 'deleteUser' + } }); const result = generateModelFile(table, false); @@ -73,15 +73,15 @@ describe('model-generator', () => { fields: [ { name: 'id', type: fieldTypes.uuid }, { name: 'action', type: fieldTypes.string }, - { name: 'timestamp', type: fieldTypes.datetime }, + { name: 'timestamp', type: fieldTypes.datetime } ], query: { all: 'auditLogs', one: 'auditLog', create: 'createAuditLog', update: undefined, - delete: undefined, - }, + delete: undefined + } }); const result = generateModelFile(table, false); @@ -99,15 +99,15 @@ describe('model-generator', () => { name: 'Organization', fields: [ { name: 'id', type: fieldTypes.uuid }, - { name: 'name', type: fieldTypes.string }, + { name: 'name', type: fieldTypes.string } ], query: { all: 'allOrganizations', one: 'organizationById', create: 'registerOrganization', update: 'modifyOrganization', - delete: 'removeOrganization', - }, + delete: 'removeOrganization' + } }); const result = generateModelFile(table, false); @@ -125,15 +125,15 @@ describe('model-generator', () => { fields: [ { name: 'id', type: fieldTypes.uuid }, { name: 'name', type: fieldTypes.string }, - { name: 'price', type: fieldTypes.int }, + { name: 'price', type: fieldTypes.int } ], query: { all: 'products', one: 'product', create: 'createProduct', update: 'updateProduct', - delete: 'deleteProduct', - }, + delete: 'deleteProduct' + } }); const result = generateModelFile(table, false); diff --git a/graphql/codegen/src/__tests__/codegen/query-builder.test.ts b/graphql/codegen/src/__tests__/codegen/query-builder.test.ts index b91c420fc..3cd47be84 100644 --- a/graphql/codegen/src/__tests__/codegen/query-builder.test.ts +++ b/graphql/codegen/src/__tests__/codegen/query-builder.test.ts @@ -5,8 +5,8 @@ * Functions are re-implemented here to avoid ./client import issues. */ import * as t from 'gql-ast'; -import { parseType, print } from 'graphql'; import type { ArgumentNode, FieldNode, VariableDefinitionNode } from 'graphql'; +import { parseType, print } from 'graphql'; // ============================================================================ // Core functions from query-builder.ts (re-implemented for testing) @@ -16,7 +16,7 @@ function buildConnectionSelections(nodeSelections: FieldNode[]): FieldNode[] { return [ t.field({ name: 'nodes', - selectionSet: t.selectionSet({ selections: nodeSelections }), + selectionSet: t.selectionSet({ selections: nodeSelections }) }), t.field({ name: 'totalCount' }), t.field({ @@ -26,10 +26,10 @@ function buildConnectionSelections(nodeSelections: FieldNode[]): FieldNode[] { t.field({ name: 'hasNextPage' }), t.field({ name: 'hasPreviousPage' }), t.field({ name: 'startCursor' }), - t.field({ name: 'endCursor' }), - ], - }), - }), + t.field({ name: 'endCursor' }) + ] + }) + }) ]; } @@ -43,32 +43,67 @@ function addVariable( definitions.push( t.variableDefinition({ variable: t.variable({ name: spec.varName }), - type: parseType(spec.typeName), + type: parseType(spec.typeName) }) ); args.push( t.argument({ name: spec.argName ?? spec.varName, - value: t.variable({ name: spec.varName }), + value: t.variable({ name: spec.varName }) }) ); variables[spec.varName] = spec.value; } -function buildSelections(select: Record | undefined): FieldNode[] { +function buildSelections( + select: Record | undefined, + connectionFieldsMap?: Record>, + entityType?: string +): FieldNode[] { if (!select) return []; const fields: FieldNode[] = []; + const entityConnections = entityType ? connectionFieldsMap?.[entityType] : undefined; + for (const [key, value] of Object.entries(select)) { + if (value === false || value === undefined) continue; if (value === true) { fields.push(t.field({ name: key })); - } else if (value && typeof value === 'object' && 'select' in value) { - const nested = value as { select: Record }; - fields.push( - t.field({ - name: key, - selectionSet: t.selectionSet({ selections: buildSelections(nested.select) }), - }) - ); + continue; + } + if (typeof value === 'object' && value !== null) { + const nested = value as { + select?: Record; + first?: number; + filter?: Record; + connection?: boolean; + }; + if (nested.select) { + const relatedEntityType = entityConnections?.[key]; + const nestedSelections = buildSelections(nested.select, connectionFieldsMap, relatedEntityType); + const isConnection = + nested.connection === true || + nested.first !== undefined || + nested.filter !== undefined || + relatedEntityType !== undefined; + + if (isConnection) { + fields.push( + t.field({ + name: key, + selectionSet: t.selectionSet({ + selections: buildConnectionSelections(nestedSelections) + }) + }) + ); + } else { + fields.push( + t.field({ + name: key, + selectionSet: t.selectionSet({ selections: nestedSelections }) + }) + ); + } + } } } return fields; @@ -80,10 +115,11 @@ function buildFindManyDocument( select: TSelect, args: { where?: TWhere; first?: number; orderBy?: string[] }, filterTypeName: string, - orderByTypeName: string + orderByTypeName: string, + connectionFieldsMap?: Record> ): { document: string; variables: Record } { const selections = select - ? buildSelections(select as Record) + ? buildSelections(select as Record, connectionFieldsMap, operationName) : [t.field({ name: 'id' })]; const variableDefinitions: VariableDefinitionNode[] = []; const queryArgs: ArgumentNode[] = []; @@ -104,12 +140,12 @@ function buildFindManyDocument( t.field({ name: queryField, args: queryArgs.length ? queryArgs : undefined, - selectionSet: t.selectionSet({ selections: buildConnectionSelections(selections) }), - }), - ], - }), - }), - ], + selectionSet: t.selectionSet({ selections: buildConnectionSelections(selections) }) + }) + ] + }) + }) + ] }); return { document: print(document), variables }; } @@ -130,8 +166,8 @@ function buildMutationDocument( variableDefinitions: [ t.variableDefinition({ variable: t.variable({ name: 'input' }), - type: parseType(inputTypeName + '!'), - }), + type: parseType(inputTypeName + '!') + }) ], selectionSet: t.selectionSet({ selections: [ @@ -142,15 +178,15 @@ function buildMutationDocument( selections: [ t.field({ name: entityField, - selectionSet: t.selectionSet({ selections }), - }), - ], - }), - }), - ], - }), - }), - ], + selectionSet: t.selectionSet({ selections }) + }) + ] + }) + }) + ] + }) + }) + ] }) ); } @@ -166,7 +202,7 @@ describe('query-builder', () => { id: true, name: true, ignored: false, - profile: { select: { bio: true } }, + profile: { select: { bio: true } } }); expect(result).toHaveLength(3); @@ -175,6 +211,155 @@ describe('query-builder', () => { expect(result[2].name.value).toBe('profile'); expect(result[2].selectionSet?.selections).toHaveLength(1); }); + + it('wraps connection fields in nodes when connectionFieldsMap is provided', () => { + const connectionFieldsMap = { + User: { posts: 'Post', comments: 'Comment' } + }; + + const result = buildSelections( + { id: true, posts: { select: { id: true, title: true } } }, + connectionFieldsMap, + 'User' + ); + + expect(result).toHaveLength(2); + expect(result[0].name.value).toBe('id'); + expect(result[1].name.value).toBe('posts'); + // Should be wrapped in connection structure: nodes, totalCount, pageInfo + const postsSelections = result[1].selectionSet?.selections as FieldNode[]; + expect(postsSelections).toHaveLength(3); + expect(postsSelections[0].name.value).toBe('nodes'); + expect(postsSelections[1].name.value).toBe('totalCount'); + expect(postsSelections[2].name.value).toBe('pageInfo'); + // nodes should contain the actual fields + const nodesSelections = postsSelections[0].selectionSet?.selections as FieldNode[]; + expect(nodesSelections).toHaveLength(2); + expect(nodesSelections[0].name.value).toBe('id'); + expect(nodesSelections[1].name.value).toBe('title'); + }); + + it('does not wrap singular relations in nodes', () => { + const connectionFieldsMap = { + Post: { comments: 'Comment' } + }; + + const result = buildSelections( + { id: true, author: { select: { id: true, name: true } } }, + connectionFieldsMap, + 'Post' + ); + + expect(result).toHaveLength(2); + expect(result[1].name.value).toBe('author'); + // author is NOT in connectionFieldsMap for Post → should NOT be wrapped + const authorSelections = result[1].selectionSet?.selections as FieldNode[]; + expect(authorSelections).toHaveLength(2); + expect(authorSelections[0].name.value).toBe('id'); + expect(authorSelections[1].name.value).toBe('name'); + }); + + it('handles deeply nested connections recursively', () => { + const connectionFieldsMap = { + User: { posts: 'Post' }, + Post: { comments: 'Comment' } + }; + + const result = buildSelections( + { + id: true, + posts: { + select: { + id: true, + comments: { select: { id: true, body: true } } + } + } + }, + connectionFieldsMap, + 'User' + ); + + // posts should be wrapped (User.posts is a connection) + const postsSelections = result[1].selectionSet?.selections as FieldNode[]; + expect(postsSelections[0].name.value).toBe('nodes'); + + // Inside nodes, comments should also be wrapped (Post.comments is a connection) + const nodesFields = postsSelections[0].selectionSet?.selections as FieldNode[]; + const commentsField = nodesFields.find((f) => f.name.value === 'comments')!; + const commentsSelections = commentsField.selectionSet?.selections as FieldNode[]; + expect(commentsSelections[0].name.value).toBe('nodes'); + expect(commentsSelections[1].name.value).toBe('totalCount'); + expect(commentsSelections[2].name.value).toBe('pageInfo'); + }); + + it('works without connectionFieldsMap (backward compat)', () => { + const result = buildSelections({ + id: true, + posts: { select: { id: true } } + }); + + expect(result).toHaveLength(2); + expect(result[1].name.value).toBe('posts'); + // Without map, posts is NOT treated as a connection + const postsSelections = result[1].selectionSet?.selections as FieldNode[]; + expect(postsSelections).toHaveLength(1); + expect(postsSelections[0].name.value).toBe('id'); + }); + + it('still wraps when first/filter provided even without connectionFieldsMap', () => { + const result = buildSelections({ + id: true, + posts: { select: { id: true }, first: 10 } + }); + + expect(result).toHaveLength(2); + const postsSelections = result[1].selectionSet?.selections as FieldNode[]; + expect(postsSelections[0].name.value).toBe('nodes'); + expect(postsSelections[1].name.value).toBe('totalCount'); + }); + + it('handles mixed connection and singular relations on same entity', () => { + const connectionFieldsMap = { + Post: { comments: 'Comment' } + }; + + const result = buildSelections( + { + id: true, + author: { select: { id: true } }, + comments: { select: { id: true, body: true } } + }, + connectionFieldsMap, + 'Post' + ); + + expect(result).toHaveLength(3); + // author = singular → no wrapping + const authorSelections = result[1].selectionSet?.selections as FieldNode[]; + expect(authorSelections[0].name.value).toBe('id'); + + // comments = connection → wrapped + const commentsSelections = result[2].selectionSet?.selections as FieldNode[]; + expect(commentsSelections[0].name.value).toBe('nodes'); + expect(commentsSelections[1].name.value).toBe('totalCount'); + }); + + it('handles entity not in connectionFieldsMap gracefully', () => { + const connectionFieldsMap = { + User: { posts: 'Post' } + }; + + // Comment is not in the map — all nested fields should be singular + const result = buildSelections( + { id: true, author: { select: { id: true } } }, + connectionFieldsMap, + 'Comment' + ); + + expect(result).toHaveLength(2); + const authorSelections = result[1].selectionSet?.selections as FieldNode[]; + expect(authorSelections[0].name.value).toBe('id'); + }); }); describe('buildFindManyDocument', () => { @@ -199,7 +384,7 @@ describe('query-builder', () => { expect(variables).toEqual({ where: { status: { equalTo: 'active' } }, first: 10, - orderBy: ['NAME_ASC'], + orderBy: ['NAME_ASC'] }); }); }); @@ -222,4 +407,140 @@ describe('query-builder', () => { expect(document).toContain('name'); }); }); + + // ========================================================================== + // Snapshot Tests — GraphQL Document Output + // ========================================================================== + + describe('snapshots', () => { + const connectionFieldsMap = { + User: { posts: 'Post', comments: 'Comment' }, + Post: { comments: 'Comment', tags: 'Tag' } + }; + + /** Helper: build a query document and print it for snapshotting */ + function buildQuerySnapshot( + select: Record, + map?: Record> + ): string { + const selections = buildSelections(select, map, 'User'); + const doc = t.document({ + definitions: [ + t.operationDefinition({ + operation: 'query', + name: 'TestQuery', + selectionSet: t.selectionSet({ + selections: [ + t.field({ + name: 'users', + selectionSet: t.selectionSet({ + selections: buildConnectionSelections(selections) + }) + }) + ] + }) + }) + ] + }); + return print(doc); + } + + it('findMany with nested connection fields', () => { + const document = buildQuerySnapshot( + { + id: true, + name: true, + posts: { select: { id: true, title: true, body: true } } + }, + connectionFieldsMap + ); + expect(document).toMatchSnapshot(); + }); + + it('findMany with deeply nested connections (3 levels)', () => { + const document = buildQuerySnapshot( + { + id: true, + posts: { + select: { + id: true, + title: true, + comments: { + select: { id: true, body: true } + } + } + } + }, + connectionFieldsMap + ); + expect(document).toMatchSnapshot(); + }); + + it('findMany with mixed connection and singular relations', () => { + const document = buildQuerySnapshot( + { + id: true, + name: true, + profile: { select: { bio: true, avatar: true } }, + posts: { select: { id: true, title: true } }, + comments: { select: { id: true, body: true } } + }, + connectionFieldsMap + ); + expect(document).toMatchSnapshot(); + }); + + it('findMany without connectionFieldsMap (no wrapping)', () => { + const document = buildQuerySnapshot( + { + id: true, + name: true, + posts: { select: { id: true, title: true } } + } + // no connectionFieldsMap + ); + expect(document).toMatchSnapshot(); + }); + + it('findMany document with filter and pagination', () => { + const { document } = buildFindManyDocument( + 'User', + 'users', + { id: true, name: true, email: true }, + { where: { name: { equalTo: 'test' } }, first: 25, orderBy: ['NAME_ASC', 'CREATED_AT_DESC'] }, + 'UserFilter', + 'UsersOrderBy' + ); + expect(document).toMatchSnapshot(); + }); + + it('mutation document', () => { + const document = buildMutationDocument( + 'CreateUser', + 'createUser', + 'user', + [t.field({ name: 'id' }), t.field({ name: 'name' }), t.field({ name: 'email' })], + 'CreateUserInput' + ); + expect(document).toMatchSnapshot(); + }); + + it('findMany document with nested connections via connectionFieldsMap', () => { + const { document } = buildFindManyDocument( + 'User', + 'users', + { + id: true, + name: true, + posts: { select: { id: true, title: true } }, + comments: { select: { id: true } } + }, + {}, + 'UserFilter', + 'UsersOrderBy', + connectionFieldsMap + ); + expect(document).toMatchSnapshot(); + }); + }); }); 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 abc8484b9..ad96c2697 100644 --- a/graphql/codegen/src/__tests__/codegen/query-keys-factory.test.ts +++ b/graphql/codegen/src/__tests__/codegen/query-keys-factory.test.ts @@ -6,24 +6,24 @@ * - Mutation keys factory (mutation-keys.ts) * - Cache invalidation helpers (invalidation.ts) */ -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 { QueryKeyConfig, EntityRelationship } from '../../types/config'; +import { generateMutationKeysFile } from '../../core/codegen/mutation-keys'; +import { generateQueryKeysFile } from '../../core/codegen/query-keys'; +import type { EntityRelationship,QueryKeyConfig } from '../../types/config'; +import type { CleanFieldType, CleanOperation, CleanRelations, CleanTable, CleanTypeRef } from '../../types/schema'; const fieldTypes = { uuid: { gqlType: 'UUID', isArray: false } as CleanFieldType, string: { gqlType: 'String', isArray: false } as CleanFieldType, int: { gqlType: 'Int', isArray: false } as CleanFieldType, - datetime: { gqlType: 'Datetime', isArray: false } as CleanFieldType, + datetime: { gqlType: 'Datetime', isArray: false } as CleanFieldType }; const emptyRelations: CleanRelations = { belongsTo: [], hasOne: [], hasMany: [], - manyToMany: [], + manyToMany: [] }; function createTable(partial: Partial & { name: string }): CleanTable { @@ -33,7 +33,7 @@ function createTable(partial: Partial & { name: string }): CleanTabl relations: partial.relations ?? emptyRelations, query: partial.query, inflection: partial.inflection, - constraints: partial.constraints, + constraints: partial.constraints }; } @@ -47,15 +47,15 @@ const simpleUserTable = createTable({ { name: 'id', type: fieldTypes.uuid }, { name: 'email', type: fieldTypes.string }, { name: 'name', type: fieldTypes.string }, - { name: 'createdAt', type: fieldTypes.datetime }, + { name: 'createdAt', type: fieldTypes.datetime } ], query: { all: 'users', one: 'user', create: 'createUser', update: 'updateUser', - delete: 'deleteUser', - }, + delete: 'deleteUser' + } }); const postTable = createTable({ @@ -65,15 +65,15 @@ const postTable = createTable({ { name: 'title', type: fieldTypes.string }, { name: 'content', type: fieldTypes.string }, { name: 'authorId', type: fieldTypes.uuid }, - { name: 'createdAt', type: fieldTypes.datetime }, + { name: 'createdAt', type: fieldTypes.datetime } ], query: { all: 'posts', one: 'post', create: 'createPost', update: 'updatePost', - delete: 'deletePost', - }, + delete: 'deletePost' + } }); const organizationTable = createTable({ @@ -81,15 +81,15 @@ const organizationTable = createTable({ fields: [ { name: 'id', type: fieldTypes.uuid }, { name: 'name', type: fieldTypes.string }, - { name: 'slug', type: fieldTypes.string }, + { name: 'slug', type: fieldTypes.string } ], query: { all: 'organizations', one: 'organization', create: 'createOrganization', update: 'updateOrganization', - delete: 'deleteOrganization', - }, + delete: 'deleteOrganization' + } }); const databaseTable = createTable({ @@ -97,15 +97,15 @@ const databaseTable = createTable({ fields: [ { name: 'id', type: fieldTypes.uuid }, { name: 'name', type: fieldTypes.string }, - { name: 'organizationId', type: fieldTypes.uuid }, + { name: 'organizationId', type: fieldTypes.uuid } ], query: { all: 'databases', one: 'database', create: 'createDatabase', update: 'updateDatabase', - delete: 'deleteDatabase', - }, + delete: 'deleteDatabase' + } }); const tableEntityTable = createTable({ @@ -113,15 +113,15 @@ const tableEntityTable = createTable({ fields: [ { name: 'id', type: fieldTypes.uuid }, { name: 'name', type: fieldTypes.string }, - { name: 'databaseId', type: fieldTypes.uuid }, + { name: 'databaseId', type: fieldTypes.uuid } ], query: { all: 'tables', one: 'table', create: 'createTable', update: 'updateTable', - delete: 'deleteTable', - }, + delete: 'deleteTable' + } }); const fieldTable = createTable({ @@ -130,15 +130,15 @@ const fieldTable = createTable({ { name: 'id', type: fieldTypes.uuid }, { name: 'name', type: fieldTypes.string }, { name: 'tableId', type: fieldTypes.uuid }, - { name: 'type', type: fieldTypes.string }, + { name: 'type', type: fieldTypes.string } ], query: { all: 'fields', one: 'field', create: 'createField', update: 'updateField', - delete: 'deleteField', - }, + delete: 'deleteField' + } }); const simpleConfig: QueryKeyConfig = { @@ -146,17 +146,17 @@ const simpleConfig: QueryKeyConfig = { relationships: {}, generateScopedKeys: true, generateCascadeHelpers: true, - generateMutationKeys: true, + generateMutationKeys: true }; const simpleRelationships: Record = { - post: { parent: 'User', foreignKey: 'authorId' }, + post: { parent: 'User', foreignKey: 'authorId' } }; const hierarchicalRelationships: Record = { database: { parent: 'Organization', foreignKey: 'organizationId' }, table: { parent: 'Database', foreignKey: 'databaseId', ancestors: ['organization'] }, - field: { parent: 'Table', foreignKey: 'tableId', ancestors: ['database', 'organization'] }, + field: { parent: 'Table', foreignKey: 'tableId', ancestors: ['database', 'organization'] } }; const sampleCustomQueries: CleanOperation[] = [ @@ -165,18 +165,18 @@ const sampleCustomQueries: CleanOperation[] = [ kind: 'query', args: [], returnType: createTypeRef('OBJECT', 'User'), - description: 'Get the current authenticated user', + description: 'Get the current authenticated user' }, { name: 'searchUsers', kind: 'query', args: [ { name: 'query', type: createTypeRef('NON_NULL', null, createTypeRef('SCALAR', 'String')) }, - { name: 'limit', type: createTypeRef('SCALAR', 'Int') }, + { name: 'limit', type: createTypeRef('SCALAR', 'Int') } ], returnType: createTypeRef('LIST', null, createTypeRef('OBJECT', 'User')), - description: 'Search users by name or email', - }, + description: 'Search users by name or email' + } ]; const sampleCustomMutations: CleanOperation[] = [ @@ -185,18 +185,18 @@ const sampleCustomMutations: CleanOperation[] = [ kind: 'mutation', args: [ { name: 'email', type: createTypeRef('NON_NULL', null, createTypeRef('SCALAR', 'String')) }, - { name: 'password', type: createTypeRef('NON_NULL', null, createTypeRef('SCALAR', 'String')) }, + { name: 'password', type: createTypeRef('NON_NULL', null, createTypeRef('SCALAR', 'String')) } ], returnType: createTypeRef('OBJECT', 'LoginPayload'), - description: 'Authenticate user', + description: 'Authenticate user' }, { name: 'logout', kind: 'mutation', args: [], returnType: createTypeRef('OBJECT', 'LogoutPayload'), - description: 'Log out current user', - }, + description: 'Log out current user' + } ]; describe('generateQueryKeysFile', () => { @@ -204,7 +204,7 @@ describe('generateQueryKeysFile', () => { const result = generateQueryKeysFile({ tables: [simpleUserTable], customQueries: [], - config: simpleConfig, + config: simpleConfig }); expect(result.fileName).toBe('query-keys.ts'); expect(result.content).toMatchSnapshot(); @@ -214,7 +214,7 @@ describe('generateQueryKeysFile', () => { const result = generateQueryKeysFile({ tables: [simpleUserTable, postTable], customQueries: [], - config: simpleConfig, + config: simpleConfig }); expect(result.content).toMatchSnapshot(); }); @@ -225,8 +225,8 @@ describe('generateQueryKeysFile', () => { customQueries: [], config: { ...simpleConfig, - relationships: simpleRelationships, - }, + relationships: simpleRelationships + } }); expect(result.content).toMatchSnapshot(); }); @@ -237,8 +237,8 @@ describe('generateQueryKeysFile', () => { customQueries: [], config: { ...simpleConfig, - relationships: hierarchicalRelationships, - }, + relationships: hierarchicalRelationships + } }); expect(result.content).toMatchSnapshot(); }); @@ -247,7 +247,7 @@ describe('generateQueryKeysFile', () => { const result = generateQueryKeysFile({ tables: [simpleUserTable], customQueries: sampleCustomQueries, - config: simpleConfig, + config: simpleConfig }); expect(result.content).toMatchSnapshot(); }); @@ -259,8 +259,8 @@ describe('generateQueryKeysFile', () => { config: { ...simpleConfig, relationships: simpleRelationships, - generateScopedKeys: false, - }, + generateScopedKeys: false + } }); expect(result.content).toMatchSnapshot(); }); @@ -271,7 +271,7 @@ describe('generateMutationKeysFile', () => { const result = generateMutationKeysFile({ tables: [simpleUserTable], customMutations: [], - config: simpleConfig, + config: simpleConfig }); expect(result.fileName).toBe('mutation-keys.ts'); expect(result.content).toMatchSnapshot(); @@ -281,7 +281,7 @@ describe('generateMutationKeysFile', () => { const result = generateMutationKeysFile({ tables: [simpleUserTable, postTable], customMutations: [], - config: simpleConfig, + config: simpleConfig }); expect(result.content).toMatchSnapshot(); }); @@ -292,8 +292,8 @@ describe('generateMutationKeysFile', () => { customMutations: [], config: { ...simpleConfig, - relationships: simpleRelationships, - }, + relationships: simpleRelationships + } }); expect(result.content).toMatchSnapshot(); }); @@ -302,7 +302,7 @@ describe('generateMutationKeysFile', () => { const result = generateMutationKeysFile({ tables: [simpleUserTable], customMutations: sampleCustomMutations, - config: simpleConfig, + config: simpleConfig }); expect(result.content).toMatchSnapshot(); }); @@ -313,8 +313,8 @@ describe('generateMutationKeysFile', () => { customMutations: [], config: { ...simpleConfig, - relationships: hierarchicalRelationships, - }, + relationships: hierarchicalRelationships + } }); expect(result.content).toMatchSnapshot(); }); @@ -324,7 +324,7 @@ describe('generateInvalidationFile', () => { it('generates invalidation helpers for a single table without relationships', () => { const result = generateInvalidationFile({ tables: [simpleUserTable], - config: simpleConfig, + config: simpleConfig }); expect(result.fileName).toBe('invalidation.ts'); expect(result.content).toMatchSnapshot(); @@ -333,7 +333,7 @@ describe('generateInvalidationFile', () => { it('generates invalidation helpers for multiple tables', () => { const result = generateInvalidationFile({ tables: [simpleUserTable, postTable], - config: simpleConfig, + config: simpleConfig }); expect(result.content).toMatchSnapshot(); }); @@ -343,8 +343,8 @@ describe('generateInvalidationFile', () => { tables: [simpleUserTable, postTable], config: { ...simpleConfig, - relationships: simpleRelationships, - }, + relationships: simpleRelationships + } }); expect(result.content).toMatchSnapshot(); }); @@ -354,8 +354,8 @@ describe('generateInvalidationFile', () => { tables: [organizationTable, databaseTable, tableEntityTable, fieldTable], config: { ...simpleConfig, - relationships: hierarchicalRelationships, - }, + relationships: hierarchicalRelationships + } }); expect(result.content).toMatchSnapshot(); }); @@ -366,8 +366,8 @@ describe('generateInvalidationFile', () => { config: { ...simpleConfig, relationships: simpleRelationships, - generateCascadeHelpers: false, - }, + generateCascadeHelpers: false + } }); expect(result.content).toMatchSnapshot(); }); 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 d5e273df6..a8a187295 100644 --- a/graphql/codegen/src/__tests__/codegen/react-query-hooks.test.ts +++ b/graphql/codegen/src/__tests__/codegen/react-query-hooks.test.ts @@ -9,26 +9,26 @@ * - Schema types * - Barrel files */ -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, + generateCustomQueriesBarrel, + generateMainBarrel, + generateMutationsBarrel, + generateQueriesBarrel } from '../../core/codegen/barrel'; +import { generateCustomMutationHook } from '../../core/codegen/custom-mutations'; +import { generateCustomQueryHook } from '../../core/codegen/custom-queries'; +import { generateCreateMutationHook, generateDeleteMutationHook,generateUpdateMutationHook } from '../../core/codegen/mutations'; +import { generateListQueryHook, generateSingleQueryHook } from '../../core/codegen/queries'; +import { generateSchemaTypesFile } from '../../core/codegen/schema-types-generator'; import type { - CleanTable, CleanFieldType, - CleanRelations, CleanOperation, + CleanRelations, + CleanTable, CleanTypeRef, - TypeRegistry, ResolvedType, + TypeRegistry } from '../../types/schema'; const fieldTypes = { @@ -36,14 +36,14 @@ const fieldTypes = { string: { gqlType: 'String', isArray: false } as CleanFieldType, int: { gqlType: 'Int', isArray: false } as CleanFieldType, datetime: { gqlType: 'Datetime', isArray: false } as CleanFieldType, - boolean: { gqlType: 'Boolean', isArray: false } as CleanFieldType, + boolean: { gqlType: 'Boolean', isArray: false } as CleanFieldType }; const emptyRelations: CleanRelations = { belongsTo: [], hasOne: [], hasMany: [], - manyToMany: [], + manyToMany: [] }; function createTable(partial: Partial & { name: string }): CleanTable { @@ -53,7 +53,7 @@ function createTable(partial: Partial & { name: string }): CleanTabl relations: partial.relations ?? emptyRelations, query: partial.query, inflection: partial.inflection, - constraints: partial.constraints, + constraints: partial.constraints }; } @@ -67,15 +67,15 @@ const simpleUserTable = createTable({ { name: 'id', type: fieldTypes.uuid }, { name: 'email', type: fieldTypes.string }, { name: 'name', type: fieldTypes.string }, - { name: 'createdAt', type: fieldTypes.datetime }, + { name: 'createdAt', type: fieldTypes.datetime } ], query: { all: 'users', one: 'user', create: 'createUser', update: 'updateUser', - delete: 'deleteUser', - }, + delete: 'deleteUser' + } }); const postTable = createTable({ @@ -86,15 +86,15 @@ const postTable = createTable({ { name: 'content', type: fieldTypes.string }, { name: 'authorId', type: fieldTypes.uuid }, { name: 'published', type: fieldTypes.boolean }, - { name: 'createdAt', type: fieldTypes.datetime }, + { name: 'createdAt', type: fieldTypes.datetime } ], query: { all: 'posts', one: 'post', create: 'createPost', update: 'updatePost', - delete: 'deletePost', - }, + delete: 'deletePost' + } }); const simpleCustomQueries: CleanOperation[] = [ @@ -103,18 +103,18 @@ const simpleCustomQueries: CleanOperation[] = [ kind: 'query', args: [], returnType: createTypeRef('OBJECT', 'User'), - description: 'Get the current authenticated user', + description: 'Get the current authenticated user' }, { name: 'searchUsers', kind: 'query', args: [ { name: 'query', type: createTypeRef('NON_NULL', null, createTypeRef('SCALAR', 'String')) }, - { name: 'limit', type: createTypeRef('SCALAR', 'Int') }, + { name: 'limit', type: createTypeRef('SCALAR', 'Int') } ], returnType: createTypeRef('LIST', null, createTypeRef('OBJECT', 'User')), - description: 'Search users by name or email', - }, + description: 'Search users by name or email' + } ]; const simpleCustomMutations: CleanOperation[] = [ @@ -123,27 +123,27 @@ const simpleCustomMutations: CleanOperation[] = [ kind: 'mutation', args: [ { name: 'email', type: createTypeRef('NON_NULL', null, createTypeRef('SCALAR', 'String')) }, - { name: 'password', type: createTypeRef('NON_NULL', null, createTypeRef('SCALAR', 'String')) }, + { name: 'password', type: createTypeRef('NON_NULL', null, createTypeRef('SCALAR', 'String')) } ], returnType: createTypeRef('OBJECT', 'LoginPayload'), - description: 'Authenticate user', + description: 'Authenticate user' }, { name: 'logout', kind: 'mutation', args: [], returnType: createTypeRef('OBJECT', 'LogoutPayload'), - description: 'Log out current user', + description: 'Log out current user' }, { name: 'register', kind: 'mutation', args: [ - { name: 'input', type: createTypeRef('NON_NULL', null, createTypeRef('INPUT_OBJECT', 'RegisterInput')) }, + { name: 'input', type: createTypeRef('NON_NULL', null, createTypeRef('INPUT_OBJECT', 'RegisterInput')) } ], returnType: createTypeRef('OBJECT', 'RegisterPayload'), - description: 'Register a new user', - }, + description: 'Register a new user' + } ]; function createTypeRegistry(): TypeRegistry { @@ -154,16 +154,16 @@ function createTypeRegistry(): TypeRegistry { name: 'LoginPayload', fields: [ { name: 'token', type: createTypeRef('SCALAR', 'String') }, - { name: 'user', type: createTypeRef('OBJECT', 'User') }, - ], + { name: 'user', type: createTypeRef('OBJECT', 'User') } + ] } as ResolvedType); registry.set('LogoutPayload', { kind: 'OBJECT', name: 'LogoutPayload', fields: [ - { name: 'success', type: createTypeRef('SCALAR', 'Boolean') }, - ], + { name: 'success', type: createTypeRef('SCALAR', 'Boolean') } + ] } as ResolvedType); registry.set('RegisterPayload', { @@ -171,8 +171,8 @@ function createTypeRegistry(): TypeRegistry { name: 'RegisterPayload', fields: [ { name: 'token', type: createTypeRef('SCALAR', 'String') }, - { name: 'user', type: createTypeRef('OBJECT', 'User') }, - ], + { name: 'user', type: createTypeRef('OBJECT', 'User') } + ] } as ResolvedType); registry.set('RegisterInput', { @@ -181,22 +181,22 @@ function createTypeRegistry(): TypeRegistry { inputFields: [ { name: 'email', type: createTypeRef('NON_NULL', null, createTypeRef('SCALAR', 'String')) }, { name: 'password', type: createTypeRef('NON_NULL', null, createTypeRef('SCALAR', 'String')) }, - { name: 'name', type: createTypeRef('SCALAR', 'String') }, - ], + { name: 'name', type: createTypeRef('SCALAR', 'String') } + ] } as ResolvedType); registry.set('UserRole', { kind: 'ENUM', name: 'UserRole', - enumValues: ['ADMIN', 'USER', 'GUEST'], + enumValues: ['ADMIN', 'USER', 'GUEST'] } as ResolvedType); registry.set('Query', { kind: 'OBJECT', name: 'Query', fields: [ - { name: 'currentUser', type: createTypeRef('OBJECT', 'User') }, - ], + { name: 'currentUser', type: createTypeRef('OBJECT', 'User') } + ] } as ResolvedType); registry.set('Mutation', { @@ -205,8 +205,8 @@ function createTypeRegistry(): TypeRegistry { fields: [ { name: 'login', type: createTypeRef('OBJECT', 'LoginPayload') }, { name: 'logout', type: createTypeRef('OBJECT', 'LogoutPayload') }, - { name: 'register', type: createTypeRef('OBJECT', 'RegisterPayload') }, - ], + { name: 'register', type: createTypeRef('OBJECT', 'RegisterPayload') } + ] } as ResolvedType); return registry; @@ -217,7 +217,7 @@ describe('Query Hook Generators', () => { it('generates list query hook for simple table', () => { const result = generateListQueryHook(simpleUserTable, { reactQueryEnabled: true, - useCentralizedKeys: true, + useCentralizedKeys: true }); expect(result).not.toBeNull(); expect(result.fileName).toBe('useUsersQuery.ts'); @@ -227,7 +227,7 @@ describe('Query Hook Generators', () => { it('generates list query hook without centralized keys', () => { const result = generateListQueryHook(simpleUserTable, { reactQueryEnabled: true, - useCentralizedKeys: false, + useCentralizedKeys: false }); expect(result).not.toBeNull(); expect(result.content).toMatchSnapshot(); @@ -237,7 +237,7 @@ describe('Query Hook Generators', () => { const result = generateListQueryHook(postTable, { reactQueryEnabled: true, useCentralizedKeys: true, - hasRelationships: true, + hasRelationships: true }); expect(result).not.toBeNull(); expect(result.content).toMatchSnapshot(); @@ -248,7 +248,7 @@ describe('Query Hook Generators', () => { it('generates single query hook for simple table', () => { const result = generateSingleQueryHook(simpleUserTable, { reactQueryEnabled: true, - useCentralizedKeys: true, + useCentralizedKeys: true }); expect(result).not.toBeNull(); expect(result.fileName).toBe('useUserQuery.ts'); @@ -258,7 +258,7 @@ describe('Query Hook Generators', () => { it('generates single query hook without centralized keys', () => { const result = generateSingleQueryHook(simpleUserTable, { reactQueryEnabled: true, - useCentralizedKeys: false, + useCentralizedKeys: false }); expect(result).not.toBeNull(); expect(result.content).toMatchSnapshot(); @@ -268,7 +268,7 @@ describe('Query Hook Generators', () => { const result = generateSingleQueryHook(postTable, { reactQueryEnabled: true, useCentralizedKeys: true, - hasRelationships: true, + hasRelationships: true }); expect(result).not.toBeNull(); expect(result.content).toMatchSnapshot(); @@ -281,7 +281,7 @@ describe('Mutation Hook Generators', () => { it('generates create mutation hook for simple table', () => { const result = generateCreateMutationHook(simpleUserTable, { reactQueryEnabled: true, - useCentralizedKeys: true, + useCentralizedKeys: true }); expect(result).not.toBeNull(); expect(result!.fileName).toBe('useCreateUserMutation.ts'); @@ -291,7 +291,7 @@ describe('Mutation Hook Generators', () => { it('generates create mutation hook without centralized keys', () => { const result = generateCreateMutationHook(simpleUserTable, { reactQueryEnabled: true, - useCentralizedKeys: false, + useCentralizedKeys: false }); expect(result).not.toBeNull(); expect(result!.content).toMatchSnapshot(); @@ -300,8 +300,7 @@ describe('Mutation Hook Generators', () => { it('generates create mutation hook for table with relationships', () => { const result = generateCreateMutationHook(postTable, { reactQueryEnabled: true, - useCentralizedKeys: true, - hasRelationships: true, + useCentralizedKeys: true }); expect(result).not.toBeNull(); expect(result!.content).toMatchSnapshot(); @@ -312,7 +311,7 @@ describe('Mutation Hook Generators', () => { it('generates update mutation hook for simple table', () => { const result = generateUpdateMutationHook(simpleUserTable, { reactQueryEnabled: true, - useCentralizedKeys: true, + useCentralizedKeys: true }); expect(result).not.toBeNull(); expect(result!.fileName).toBe('useUpdateUserMutation.ts'); @@ -322,7 +321,7 @@ describe('Mutation Hook Generators', () => { it('generates update mutation hook without centralized keys', () => { const result = generateUpdateMutationHook(simpleUserTable, { reactQueryEnabled: true, - useCentralizedKeys: false, + useCentralizedKeys: false }); expect(result).not.toBeNull(); expect(result!.content).toMatchSnapshot(); @@ -331,8 +330,7 @@ describe('Mutation Hook Generators', () => { it('generates update mutation hook for table with relationships', () => { const result = generateUpdateMutationHook(postTable, { reactQueryEnabled: true, - useCentralizedKeys: true, - hasRelationships: true, + useCentralizedKeys: true }); expect(result).not.toBeNull(); expect(result!.content).toMatchSnapshot(); @@ -343,7 +341,7 @@ describe('Mutation Hook Generators', () => { it('generates delete mutation hook for simple table', () => { const result = generateDeleteMutationHook(simpleUserTable, { reactQueryEnabled: true, - useCentralizedKeys: true, + useCentralizedKeys: true }); expect(result).not.toBeNull(); expect(result!.fileName).toBe('useDeleteUserMutation.ts'); @@ -353,7 +351,7 @@ describe('Mutation Hook Generators', () => { it('generates delete mutation hook without centralized keys', () => { const result = generateDeleteMutationHook(simpleUserTable, { reactQueryEnabled: true, - useCentralizedKeys: false, + useCentralizedKeys: false }); expect(result).not.toBeNull(); expect(result!.content).toMatchSnapshot(); @@ -362,8 +360,7 @@ describe('Mutation Hook Generators', () => { it('generates delete mutation hook for table with relationships', () => { const result = generateDeleteMutationHook(postTable, { reactQueryEnabled: true, - useCentralizedKeys: true, - hasRelationships: true, + useCentralizedKeys: true }); expect(result).not.toBeNull(); expect(result!.content).toMatchSnapshot(); @@ -377,7 +374,7 @@ describe('Custom Query Hook Generators', () => { const result = generateCustomQueryHook({ operation: simpleCustomQueries[0], typeRegistry: createTypeRegistry(), - useCentralizedKeys: true, + useCentralizedKeys: true }); expect(result).not.toBeNull(); expect(result!.fileName).toBe('useCurrentUserQuery.ts'); @@ -388,7 +385,7 @@ describe('Custom Query Hook Generators', () => { const result = generateCustomQueryHook({ operation: simpleCustomQueries[1], typeRegistry: createTypeRegistry(), - useCentralizedKeys: true, + useCentralizedKeys: true }); expect(result).not.toBeNull(); expect(result!.fileName).toBe('useSearchUsersQuery.ts'); @@ -399,7 +396,7 @@ describe('Custom Query Hook Generators', () => { const result = generateCustomQueryHook({ operation: simpleCustomQueries[0], typeRegistry: createTypeRegistry(), - useCentralizedKeys: false, + useCentralizedKeys: false }); expect(result).not.toBeNull(); expect(result!.content).toMatchSnapshot(); @@ -413,7 +410,7 @@ describe('Custom Mutation Hook Generators', () => { const result = generateCustomMutationHook({ operation: simpleCustomMutations[0], typeRegistry: createTypeRegistry(), - useCentralizedKeys: true, + useCentralizedKeys: true }); expect(result).not.toBeNull(); expect(result!.fileName).toBe('useLoginMutation.ts'); @@ -424,7 +421,7 @@ describe('Custom Mutation Hook Generators', () => { const result = generateCustomMutationHook({ operation: simpleCustomMutations[1], typeRegistry: createTypeRegistry(), - useCentralizedKeys: true, + useCentralizedKeys: true }); expect(result).not.toBeNull(); expect(result!.fileName).toBe('useLogoutMutation.ts'); @@ -435,7 +432,7 @@ describe('Custom Mutation Hook Generators', () => { const result = generateCustomMutationHook({ operation: simpleCustomMutations[2], typeRegistry: createTypeRegistry(), - useCentralizedKeys: true, + useCentralizedKeys: true }); expect(result).not.toBeNull(); expect(result!.fileName).toBe('useRegisterMutation.ts'); @@ -446,7 +443,7 @@ describe('Custom Mutation Hook Generators', () => { const result = generateCustomMutationHook({ operation: simpleCustomMutations[0], typeRegistry: createTypeRegistry(), - useCentralizedKeys: false, + useCentralizedKeys: false }); expect(result).not.toBeNull(); expect(result!.content).toMatchSnapshot(); @@ -459,7 +456,7 @@ describe('Schema Types Generator', () => { it('generates schema types file with enums and input objects', () => { const result = generateSchemaTypesFile({ typeRegistry: createTypeRegistry(), - tableTypeNames: new Set(['User', 'Post']), + tableTypeNames: new Set(['User', 'Post']) }); expect(result.fileName).toBe('schema-types.ts'); expect(result.content).toMatchSnapshot(); @@ -468,7 +465,7 @@ describe('Schema Types Generator', () => { it('generates schema types file with empty table types', () => { const result = generateSchemaTypesFile({ typeRegistry: createTypeRegistry(), - tableTypeNames: new Set(), + tableTypeNames: new Set() }); expect(result.content).toMatchSnapshot(); }); @@ -503,27 +500,24 @@ describe('Barrel File Generators', () => { describe('generateMainBarrel', () => { it('generates main barrel with all options enabled', () => { const result = generateMainBarrel([simpleUserTable, postTable], { - hasSchemaTypes: true, hasMutations: true, hasQueryKeys: true, hasMutationKeys: true, - hasInvalidation: true, + hasInvalidation: true }); expect(result).toMatchSnapshot(); }); it('generates main barrel without custom operations', () => { const result = generateMainBarrel([simpleUserTable], { - hasSchemaTypes: false, - hasMutations: true, + hasMutations: true }); expect(result).toMatchSnapshot(); }); it('generates main barrel without mutations', () => { const result = generateMainBarrel([simpleUserTable, postTable], { - hasSchemaTypes: true, - hasMutations: false, + hasMutations: false }); expect(result).toMatchSnapshot(); }); 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 cf21047a6..93143400f 100644 --- a/graphql/codegen/src/__tests__/codegen/react-query-optional.test.ts +++ b/graphql/codegen/src/__tests__/codegen/react-query-optional.test.ts @@ -6,11 +6,11 @@ * - Mutation generators return null (since they require React Query) * - Standalone fetch functions are still generated for queries */ -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'; +import { generateAllCustomMutationHooks,generateCustomMutationHook } from '../../core/codegen/custom-mutations'; +import { generateAllCustomQueryHooks,generateCustomQueryHook } from '../../core/codegen/custom-queries'; +import { generateAllMutationHooks,generateCreateMutationHook, generateDeleteMutationHook, generateUpdateMutationHook } from '../../core/codegen/mutations'; +import { generateAllQueryHooks,generateListQueryHook, generateSingleQueryHook } from '../../core/codegen/queries'; +import type { CleanFieldType, CleanOperation, CleanRelations, CleanTable, CleanTypeRef, TypeRegistry } from '../../types/schema'; // ============================================================================ // Test Fixtures @@ -20,14 +20,14 @@ const fieldTypes = { uuid: { gqlType: 'UUID', isArray: false } as CleanFieldType, string: { gqlType: 'String', isArray: false } as CleanFieldType, int: { gqlType: 'Int', isArray: false } as CleanFieldType, - datetime: { gqlType: 'Datetime', isArray: false } as CleanFieldType, + datetime: { gqlType: 'Datetime', isArray: false } as CleanFieldType }; const emptyRelations: CleanRelations = { belongsTo: [], hasOne: [], hasMany: [], - manyToMany: [], + manyToMany: [] }; function createTable(partial: Partial & { name: string }): CleanTable { @@ -37,7 +37,7 @@ function createTable(partial: Partial & { name: string }): CleanTabl relations: partial.relations ?? emptyRelations, query: partial.query, inflection: partial.inflection, - constraints: partial.constraints, + constraints: partial.constraints }; } @@ -47,15 +47,15 @@ const userTable = createTable({ { name: 'id', type: fieldTypes.uuid }, { name: 'email', type: fieldTypes.string }, { name: 'name', type: fieldTypes.string }, - { name: 'createdAt', type: fieldTypes.datetime }, + { name: 'createdAt', type: fieldTypes.datetime } ], query: { all: 'users', one: 'user', create: 'createUser', update: 'updateUser', - delete: 'deleteUser', - }, + delete: 'deleteUser' + } }); function createTypeRef(kind: CleanTypeRef['kind'], name: string | null, ofType?: CleanTypeRef): CleanTypeRef { @@ -67,7 +67,7 @@ const sampleQueryOperation: CleanOperation = { kind: 'query', args: [], returnType: createTypeRef('OBJECT', 'User'), - description: 'Get the current authenticated user', + description: 'Get the current authenticated user' }; const sampleMutationOperation: CleanOperation = { @@ -75,10 +75,10 @@ const sampleMutationOperation: CleanOperation = { kind: 'mutation', args: [ { name: 'email', type: createTypeRef('NON_NULL', null, createTypeRef('SCALAR', 'String')) }, - { name: 'password', type: createTypeRef('NON_NULL', null, createTypeRef('SCALAR', 'String')) }, + { name: 'password', type: createTypeRef('NON_NULL', null, createTypeRef('SCALAR', 'String')) } ], returnType: createTypeRef('OBJECT', 'LoginPayload'), - description: 'Authenticate user', + description: 'Authenticate user' }; const emptyTypeRegistry: TypeRegistry = new Map(); @@ -111,9 +111,9 @@ describe('Query generators with reactQueryEnabled: false', () => { expect(result.content).toContain('export async function fetchUsersQuery'); }); - it('should still include GraphQL document when disabled', () => { + it('should still include ORM client imports when disabled', () => { const result = generateListQueryHook(userTable, { reactQueryEnabled: false }); - expect(result.content).toContain('usersQueryDocument'); + expect(result.content).toContain('getClient'); }); it('should still include query key factory when disabled', () => { @@ -251,7 +251,7 @@ describe('Custom query generators with reactQueryEnabled: false', () => { const result = generateCustomQueryHook({ operation: sampleQueryOperation, typeRegistry: emptyTypeRegistry, - reactQueryEnabled: false, + reactQueryEnabled: false }); expect(result.content).not.toContain('@tanstack/react-query'); expect(result.content).not.toContain('useQuery'); @@ -261,7 +261,7 @@ describe('Custom query generators with reactQueryEnabled: false', () => { const result = generateCustomQueryHook({ operation: sampleQueryOperation, typeRegistry: emptyTypeRegistry, - reactQueryEnabled: false, + reactQueryEnabled: false }); expect(result.content).not.toContain('export function useCurrentUserQuery'); }); @@ -270,7 +270,7 @@ describe('Custom query generators with reactQueryEnabled: false', () => { const result = generateCustomQueryHook({ operation: sampleQueryOperation, typeRegistry: emptyTypeRegistry, - reactQueryEnabled: false, + reactQueryEnabled: false }); expect(result.content).toContain('export async function fetchCurrentUserQuery'); }); @@ -281,7 +281,7 @@ describe('Custom query generators with reactQueryEnabled: false', () => { const results = generateAllCustomQueryHooks({ operations: [sampleQueryOperation], typeRegistry: emptyTypeRegistry, - reactQueryEnabled: false, + reactQueryEnabled: false }); expect(results.length).toBe(1); expect(results[0].content).not.toContain('@tanstack/react-query'); @@ -299,7 +299,7 @@ describe('Custom mutation generators with reactQueryEnabled: false', () => { const result = generateCustomMutationHook({ operation: sampleMutationOperation, typeRegistry: emptyTypeRegistry, - reactQueryEnabled: false, + reactQueryEnabled: false }); expect(result).toBeNull(); }); @@ -310,7 +310,7 @@ describe('Custom mutation generators with reactQueryEnabled: false', () => { const results = generateAllCustomMutationHooks({ operations: [sampleMutationOperation], typeRegistry: emptyTypeRegistry, - reactQueryEnabled: false, + reactQueryEnabled: false }); expect(results).toEqual([]); }); @@ -326,7 +326,7 @@ describe('Custom mutation generators with reactQueryEnabled: true (default)', () it('should return mutation file by default', () => { const result = generateCustomMutationHook({ operation: sampleMutationOperation, - typeRegistry: emptyTypeRegistry, + typeRegistry: emptyTypeRegistry }); expect(result).not.toBeNull(); expect(result!.content).toContain('useMutation'); diff --git a/graphql/codegen/src/__tests__/codegen/scalars.test.ts b/graphql/codegen/src/__tests__/codegen/scalars.test.ts index 27539d3f4..7c81ae5c9 100644 --- a/graphql/codegen/src/__tests__/codegen/scalars.test.ts +++ b/graphql/codegen/src/__tests__/codegen/scalars.test.ts @@ -2,12 +2,12 @@ * Tests for scalar mappings */ import { - SCALAR_TS_MAP, + BASE_FILTER_TYPE_NAMES, SCALAR_FILTER_MAP, SCALAR_NAMES, - BASE_FILTER_TYPE_NAMES, - scalarToTsType, + SCALAR_TS_MAP, scalarToFilterType, + scalarToTsType } from '../../core/codegen/scalars'; describe('scalars', () => { 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 70fc56de2..526013226 100644 --- a/graphql/codegen/src/__tests__/codegen/schema-types-generator.test.ts +++ b/graphql/codegen/src/__tests__/codegen/schema-types-generator.test.ts @@ -2,7 +2,7 @@ * Snapshot tests for schema-types-generator */ import { generateSchemaTypesFile } from '../../core/codegen/schema-types-generator'; -import type { TypeRegistry, ResolvedType } from '../../types/schema'; +import type { ResolvedType,TypeRegistry } from '../../types/schema'; function createTypeRegistry(types: Array<[string, ResolvedType]>): TypeRegistry { return new Map(types); @@ -12,12 +12,12 @@ describe('schema-types-generator', () => { it('generates enum types as string unions', () => { const registry = createTypeRegistry([ ['Status', { kind: 'ENUM', name: 'Status', enumValues: ['ACTIVE', 'INACTIVE', 'PENDING'] }], - ['Priority', { kind: 'ENUM', name: 'Priority', enumValues: ['LOW', 'MEDIUM', 'HIGH'] }], + ['Priority', { kind: 'ENUM', name: 'Priority', enumValues: ['LOW', 'MEDIUM', 'HIGH'] }] ]); const result = generateSchemaTypesFile({ typeRegistry: registry, - tableTypeNames: new Set(), + tableTypeNames: new Set() }); expect(result.content).toMatchSnapshot(); @@ -34,9 +34,9 @@ describe('schema-types-generator', () => { inputFields: [ { name: 'email', type: { kind: 'NON_NULL', name: null, ofType: { kind: 'SCALAR', name: 'String' } } }, { name: 'name', type: { kind: 'SCALAR', name: 'String' } }, - { name: 'age', type: { kind: 'SCALAR', name: 'Int' } }, - ], - }, + { name: 'age', type: { kind: 'SCALAR', name: 'Int' } } + ] + } ], [ 'UpdateUserInput', @@ -45,15 +45,15 @@ describe('schema-types-generator', () => { name: 'UpdateUserInput', inputFields: [ { name: 'id', type: { kind: 'NON_NULL', name: null, ofType: { kind: 'SCALAR', name: 'UUID' } } }, - { name: 'name', type: { kind: 'SCALAR', name: 'String' } }, - ], - }, - ], + { name: 'name', type: { kind: 'SCALAR', name: 'String' } } + ] + } + ] ]); const result = generateSchemaTypesFile({ typeRegistry: registry, - tableTypeNames: new Set(), + tableTypeNames: new Set() }); expect(result.content).toMatchSnapshot(); @@ -61,12 +61,12 @@ describe('schema-types-generator', () => { it('generates union types', () => { const registry = createTypeRegistry([ - ['SearchResult', { kind: 'UNION', name: 'SearchResult', possibleTypes: ['User', 'Post', 'Comment'] }], + ['SearchResult', { kind: 'UNION', name: 'SearchResult', possibleTypes: ['User', 'Post', 'Comment'] }] ]); const result = generateSchemaTypesFile({ typeRegistry: registry, - tableTypeNames: new Set(), + tableTypeNames: new Set() }); expect(result.content).toMatchSnapshot(); @@ -80,9 +80,9 @@ describe('schema-types-generator', () => { kind: 'OBJECT', name: 'Mutation', fields: [ - { name: 'login', type: { kind: 'OBJECT', name: 'LoginPayload' } }, - ], - }, + { name: 'login', type: { kind: 'OBJECT', name: 'LoginPayload' } } + ] + } ], [ 'LoginPayload', @@ -92,15 +92,15 @@ describe('schema-types-generator', () => { fields: [ { name: 'token', type: { kind: 'NON_NULL', name: null, ofType: { kind: 'SCALAR', name: 'String' } } }, { name: 'refreshToken', type: { kind: 'SCALAR', name: 'String' } }, - { name: 'user', type: { kind: 'OBJECT', name: 'User' } }, - ], - }, - ], + { name: 'user', type: { kind: 'OBJECT', name: 'User' } } + ] + } + ] ]); const result = generateSchemaTypesFile({ typeRegistry: registry, - tableTypeNames: new Set(['User']), + tableTypeNames: new Set(['User']) }); expect(result.content).toMatchSnapshot(); @@ -111,12 +111,12 @@ describe('schema-types-generator', () => { const registry = createTypeRegistry([ ['User', { kind: 'ENUM', name: 'User', enumValues: ['ADMIN'] }], ['String', { kind: 'ENUM', name: 'String', enumValues: ['A'] }], - ['CustomEnum', { kind: 'ENUM', name: 'CustomEnum', enumValues: ['VALUE_A', 'VALUE_B'] }], + ['CustomEnum', { kind: 'ENUM', name: 'CustomEnum', enumValues: ['VALUE_A', 'VALUE_B'] }] ]); const result = generateSchemaTypesFile({ typeRegistry: registry, - tableTypeNames: new Set(['User']), + tableTypeNames: new Set(['User']) }); expect(result.content).toMatchSnapshot(); diff --git a/graphql/codegen/src/__tests__/codegen/utils.test.ts b/graphql/codegen/src/__tests__/codegen/utils.test.ts index 62dbf33a0..38f9f066d 100644 --- a/graphql/codegen/src/__tests__/codegen/utils.test.ts +++ b/graphql/codegen/src/__tests__/codegen/utils.test.ts @@ -2,25 +2,25 @@ * Tests for codegen utility functions */ import { + getFilterTypeName, + getGeneratedFileHeader, + getOrderByTypeName, + getPrimaryKeyInfo, + getTableNames, + gqlTypeToTs, lcFirst, - ucFirst, toCamelCase, toPascalCase, toScreamingSnake, - getTableNames, - getFilterTypeName, - getOrderByTypeName, - gqlTypeToTs, - getPrimaryKeyInfo, - getGeneratedFileHeader, + ucFirst } from '../../core/codegen/utils'; -import type { CleanTable, CleanRelations } from '../../types/schema'; +import type { CleanRelations,CleanTable } from '../../types/schema'; const emptyRelations: CleanRelations = { belongsTo: [], hasOne: [], hasMany: [], - manyToMany: [], + manyToMany: [] }; // Use any for test fixture overrides to avoid strict type requirements @@ -29,7 +29,7 @@ function createTable(name: string, overrides: Record = {}): Cle name, fields: [], relations: emptyRelations, - ...overrides, + ...overrides } as CleanTable; } @@ -78,7 +78,7 @@ describe('utils', () => { it('uses inflection overrides when provided', () => { const result = getTableNames( createTable('Person', { - inflection: { tableFieldName: 'individual', allRows: 'people' }, + inflection: { tableFieldName: 'individual', allRows: 'people' } }) ); expect(result.singularName).toBe('individual'); @@ -88,7 +88,7 @@ describe('utils', () => { it('uses query.all for plural name', () => { const result = getTableNames( createTable('Child', { - query: { all: 'children', one: 'child', create: 'createChild', update: 'updateChild', delete: 'deleteChild' }, + query: { all: 'children', one: 'child', create: 'createChild', update: 'updateChild', delete: 'deleteChild' } }) ); expect(result.pluralName).toBe('children'); @@ -138,8 +138,8 @@ describe('utils', () => { it('extracts PK from constraints', () => { const table = createTable('User', { constraints: { - primaryKey: [{ name: 'users_pkey', fields: [{ name: 'id', type: { gqlType: 'UUID', isArray: false } }] }], - }, + primaryKey: [{ name: 'users_pkey', fields: [{ name: 'id', type: { gqlType: 'UUID', isArray: false } }] }] + } }); const result = getPrimaryKeyInfo(table); expect(result).toEqual([{ name: 'id', gqlType: 'UUID', tsType: 'string' }]); @@ -147,7 +147,7 @@ describe('utils', () => { it('falls back to id field', () => { const table = createTable('User', { - fields: [{ name: 'id', type: { gqlType: 'UUID', isArray: false } }], + fields: [{ name: 'id', type: { gqlType: 'UUID', isArray: false } }] }); const result = getPrimaryKeyInfo(table); expect(result).toEqual([{ name: 'id', gqlType: 'UUID', tsType: 'string' }]); @@ -161,11 +161,11 @@ describe('utils', () => { name: 'user_roles_pkey', fields: [ { name: 'userId', type: { gqlType: 'UUID', isArray: false } }, - { name: 'roleId', type: { gqlType: 'UUID', isArray: false } }, - ], - }, - ], - }, + { name: 'roleId', type: { gqlType: 'UUID', isArray: false } } + ] + } + ] + } }); const result = getPrimaryKeyInfo(table); expect(result).toHaveLength(2); diff --git a/graphql/codegen/src/__tests__/config/resolve-config.test.ts b/graphql/codegen/src/__tests__/config/resolve-config.test.ts index e7e879345..c3d5cd162 100644 --- a/graphql/codegen/src/__tests__/config/resolve-config.test.ts +++ b/graphql/codegen/src/__tests__/config/resolve-config.test.ts @@ -1,16 +1,16 @@ import type { - GraphQLSDKConfigTarget, + GraphQLSDKConfigTarget } from '../../types/config'; import { - mergeConfig, - getConfigOptions, DEFAULT_CONFIG, + getConfigOptions, + mergeConfig } from '../../types/config'; describe('config resolution', () => { it('resolves config with defaults', () => { const config: GraphQLSDKConfigTarget = { - endpoint: 'https://api.example.com/graphql', + endpoint: 'https://api.example.com/graphql' }; const resolved = getConfigOptions(config); @@ -29,9 +29,9 @@ describe('config resolution', () => { tables: { include: ['User'] }, queryKeys: { relationships: { - database: { parent: 'organization', foreignKey: 'organizationId' }, - }, - }, + database: { parent: 'organization', foreignKey: 'organizationId' } + } + } }; const overrides: GraphQLSDKConfigTarget = { @@ -40,9 +40,9 @@ describe('config resolution', () => { tables: { exclude: ['_internal'] }, queryKeys: { relationships: { - table: { parent: 'database', foreignKey: 'databaseId' }, - }, - }, + table: { parent: 'database', foreignKey: 'databaseId' } + } + } }; const merged = mergeConfig(base, overrides); @@ -50,15 +50,15 @@ describe('config resolution', () => { expect(merged.output).toBe('./generated/custom'); expect(merged.headers).toEqual({ Authorization: 'Bearer base', - 'X-Custom': '1', + 'X-Custom': '1' }); expect(merged.tables).toEqual({ include: ['User'], - exclude: ['_internal'], + exclude: ['_internal'] }); expect(merged.queryKeys?.relationships).toEqual({ database: { parent: 'organization', foreignKey: 'organizationId' }, - table: { parent: 'database', foreignKey: 'databaseId' }, + table: { parent: 'database', foreignKey: 'databaseId' } }); }); }); diff --git a/graphql/codegen/src/__tests__/introspect/infer-tables.test.ts b/graphql/codegen/src/__tests__/introspect/infer-tables.test.ts index af8828802..80091abed 100644 --- a/graphql/codegen/src/__tests__/introspect/infer-tables.test.ts +++ b/graphql/codegen/src/__tests__/introspect/infer-tables.test.ts @@ -6,12 +6,12 @@ */ import { inferTablesFromIntrospection } from '../../core/introspect/infer-tables'; import type { - IntrospectionQueryResponse, - IntrospectionType, - IntrospectionTypeRef, + IntrospectionEnumValue, IntrospectionField, IntrospectionInputValue, - IntrospectionEnumValue, + IntrospectionQueryResponse, + IntrospectionType, + IntrospectionTypeRef } from '../../types/introspection'; // ============================================================================ @@ -99,19 +99,19 @@ function createIntrospection( name: a.name, type: a.type, description: null, - defaultValue: null, + defaultValue: null }) ), deprecationReason: null, description: null, - isDeprecated: false, + isDeprecated: false }); const makeInputField = (f: InputFieldDef): IntrospectionInputValue => ({ name: f.name, type: f.type, description: null, - defaultValue: null, + defaultValue: null }); // Add Query and Mutation types @@ -124,21 +124,21 @@ function createIntrospection( enumValues: null, interfaces: [], possibleTypes: null, - description: null, + description: null }, ...(mutationFields.length > 0 ? [ - { - name: 'Mutation', - kind: 'OBJECT' as const, - fields: mutationFields.map(makeField), - inputFields: null, - enumValues: null, - interfaces: [], - possibleTypes: null, - description: null, - }, - ] + { + name: 'Mutation', + kind: 'OBJECT' as const, + fields: mutationFields.map(makeField), + inputFields: null, + enumValues: null, + interfaces: [], + possibleTypes: null, + description: null + } + ] : []), ...types.map( (t): IntrospectionType => ({ @@ -152,19 +152,19 @@ function createIntrospection( enumValues: t.kind === 'ENUM' ? (t.enumValues ?? []).map( - (v): IntrospectionEnumValue => ({ - name: v, - deprecationReason: null, - description: null, - isDeprecated: false, - }) - ) + (v): IntrospectionEnumValue => ({ + name: v, + deprecationReason: null, + description: null, + isDeprecated: false + }) + ) : null, interfaces: [], possibleTypes: null, - description: null, + description: null }) - ), + ) ]; return { @@ -173,8 +173,8 @@ function createIntrospection( mutationType: mutationFields.length > 0 ? { name: 'Mutation' } : null, subscriptionType: null, types: allTypes, - directives: [], - }, + directives: [] + } }; } @@ -192,8 +192,8 @@ describe('Entity Detection', () => { kind: 'OBJECT', fields: [ { name: 'id', type: nonNull(scalar('UUID')) }, - { name: 'email', type: scalar('String') }, - ], + { name: 'email', type: scalar('String') } + ] }, // UsersConnection type (indicates User is an entity) { @@ -201,15 +201,15 @@ describe('Entity Detection', () => { kind: 'OBJECT', fields: [ { name: 'nodes', type: list(object('User')) }, - { name: 'pageInfo', type: nonNull(object('PageInfo')) }, - ], + { name: 'pageInfo', type: nonNull(object('PageInfo')) } + ] }, // PageInfo (builtin, should be ignored) - { name: 'PageInfo', kind: 'OBJECT', fields: [] }, + { name: 'PageInfo', kind: 'OBJECT', fields: [] } ], [ // Query for users - { name: 'users', type: object('UsersConnection') }, + { name: 'users', type: object('UsersConnection') } ] ); @@ -225,26 +225,26 @@ describe('Entity Detection', () => { { name: 'User', kind: 'OBJECT', - fields: [{ name: 'id', type: nonNull(scalar('UUID')) }], + fields: [{ name: 'id', type: nonNull(scalar('UUID')) }] }, { name: 'UsersConnection', kind: 'OBJECT', fields: [] }, { name: 'Post', kind: 'OBJECT', - fields: [{ name: 'id', type: nonNull(scalar('UUID')) }], + fields: [{ name: 'id', type: nonNull(scalar('UUID')) }] }, { name: 'PostsConnection', kind: 'OBJECT', fields: [] }, { name: 'Comment', kind: 'OBJECT', - fields: [{ name: 'id', type: nonNull(scalar('UUID')) }], + fields: [{ name: 'id', type: nonNull(scalar('UUID')) }] }, - { name: 'CommentsConnection', kind: 'OBJECT', fields: [] }, + { name: 'CommentsConnection', kind: 'OBJECT', fields: [] } ], [ { name: 'users', type: object('UsersConnection') }, { name: 'posts', type: object('PostsConnection') }, - { name: 'comments', type: object('CommentsConnection') }, + { name: 'comments', type: object('CommentsConnection') } ] ); @@ -261,15 +261,15 @@ describe('Entity Detection', () => { { name: 'User', kind: 'OBJECT', - fields: [{ name: 'id', type: nonNull(scalar('UUID')) }], + fields: [{ name: 'id', type: nonNull(scalar('UUID')) }] }, { name: 'UsersConnection', kind: 'OBJECT', fields: [] }, // Does not have Connection (should be ignored) { name: 'AuditLog', kind: 'OBJECT', - fields: [{ name: 'id', type: nonNull(scalar('UUID')) }], - }, + fields: [{ name: 'id', type: nonNull(scalar('UUID')) }] + } ], [{ name: 'users', type: object('UsersConnection') }] ); @@ -297,10 +297,10 @@ describe('Field Extraction', () => { { name: 'email', type: scalar('String') }, { name: 'age', type: scalar('Int') }, { name: 'isActive', type: scalar('Boolean') }, - { name: 'metadata', type: scalar('JSON') }, - ], + { name: 'metadata', type: scalar('JSON') } + ] }, - { name: 'UsersConnection', kind: 'OBJECT', fields: [] }, + { name: 'UsersConnection', kind: 'OBJECT', fields: [] } ], [{ name: 'users', type: object('UsersConnection') }] ); @@ -314,7 +314,7 @@ describe('Field Extraction', () => { 'email', 'age', 'isActive', - 'metadata', + 'metadata' ]); expect(fields.find((f) => f.name === 'id')?.type.gqlType).toBe('UUID'); expect(fields.find((f) => f.name === 'email')?.type.gqlType).toBe('String'); @@ -328,10 +328,10 @@ describe('Field Extraction', () => { kind: 'OBJECT', fields: [ { name: 'id', type: nonNull(scalar('UUID')) }, - { name: 'tags', type: list(scalar('String')) }, - ], + { name: 'tags', type: list(scalar('String')) } + ] }, - { name: 'PostsConnection', kind: 'OBJECT', fields: [] }, + { name: 'PostsConnection', kind: 'OBJECT', fields: [] } ], [{ name: 'posts', type: object('PostsConnection') }] ); @@ -354,27 +354,27 @@ describe('Field Extraction', () => { { name: 'id', type: nonNull(scalar('UUID')) }, { name: 'title', type: scalar('String') }, { name: 'author', type: object('User') }, // belongsTo relation - { name: 'comments', type: object('CommentsConnection') }, // hasMany relation - ], + { name: 'comments', type: object('CommentsConnection') } // hasMany relation + ] }, { name: 'PostsConnection', kind: 'OBJECT', fields: [] }, { name: 'User', kind: 'OBJECT', - fields: [{ name: 'id', type: nonNull(scalar('UUID')) }], + fields: [{ name: 'id', type: nonNull(scalar('UUID')) }] }, { name: 'UsersConnection', kind: 'OBJECT', fields: [] }, { name: 'Comment', kind: 'OBJECT', - fields: [{ name: 'id', type: nonNull(scalar('UUID')) }], + fields: [{ name: 'id', type: nonNull(scalar('UUID')) }] }, - { name: 'CommentsConnection', kind: 'OBJECT', fields: [] }, + { name: 'CommentsConnection', kind: 'OBJECT', fields: [] } ], [ { name: 'posts', type: object('PostsConnection') }, { name: 'users', type: object('UsersConnection') }, - { name: 'comments', type: object('CommentsConnection') }, + { name: 'comments', type: object('CommentsConnection') } ] ); @@ -402,20 +402,20 @@ describe('Relation Inference', () => { kind: 'OBJECT', fields: [ { name: 'id', type: nonNull(scalar('UUID')) }, - { name: 'author', type: object('User') }, - ], + { name: 'author', type: object('User') } + ] }, { name: 'PostsConnection', kind: 'OBJECT', fields: [] }, { name: 'User', kind: 'OBJECT', - fields: [{ name: 'id', type: nonNull(scalar('UUID')) }], + fields: [{ name: 'id', type: nonNull(scalar('UUID')) }] }, - { name: 'UsersConnection', kind: 'OBJECT', fields: [] }, + { name: 'UsersConnection', kind: 'OBJECT', fields: [] } ], [ { name: 'posts', type: object('PostsConnection') }, - { name: 'users', type: object('UsersConnection') }, + { name: 'users', type: object('UsersConnection') } ] ); @@ -435,20 +435,20 @@ describe('Relation Inference', () => { kind: 'OBJECT', fields: [ { name: 'id', type: nonNull(scalar('UUID')) }, - { name: 'posts', type: object('PostsConnection') }, - ], + { name: 'posts', type: object('PostsConnection') } + ] }, { name: 'UsersConnection', kind: 'OBJECT', fields: [] }, { name: 'Post', kind: 'OBJECT', - fields: [{ name: 'id', type: nonNull(scalar('UUID')) }], + fields: [{ name: 'id', type: nonNull(scalar('UUID')) }] }, - { name: 'PostsConnection', kind: 'OBJECT', fields: [] }, + { name: 'PostsConnection', kind: 'OBJECT', fields: [] } ], [ { name: 'users', type: object('UsersConnection') }, - { name: 'posts', type: object('PostsConnection') }, + { name: 'posts', type: object('PostsConnection') } ] ); @@ -471,21 +471,21 @@ describe('Relation Inference', () => { // ManyToMany pattern: {entities}By{JunctionTable}{Keys} { name: 'productsByProductCategoryProductIdAndCategoryId', - type: object('ProductsConnection'), - }, - ], + type: object('ProductsConnection') + } + ] }, { name: 'CategoriesConnection', kind: 'OBJECT', fields: [] }, { name: 'Product', kind: 'OBJECT', - fields: [{ name: 'id', type: nonNull(scalar('UUID')) }], + fields: [{ name: 'id', type: nonNull(scalar('UUID')) }] }, - { name: 'ProductsConnection', kind: 'OBJECT', fields: [] }, + { name: 'ProductsConnection', kind: 'OBJECT', fields: [] } ], [ { name: 'categories', type: object('CategoriesConnection') }, - { name: 'products', type: object('ProductsConnection') }, + { name: 'products', type: object('ProductsConnection') } ] ); @@ -511,9 +511,9 @@ describe('Query Operation Matching', () => { { name: 'User', kind: 'OBJECT', - fields: [{ name: 'id', type: nonNull(scalar('UUID')) }], + fields: [{ name: 'id', type: nonNull(scalar('UUID')) }] }, - { name: 'UsersConnection', kind: 'OBJECT', fields: [] }, + { name: 'UsersConnection', kind: 'OBJECT', fields: [] } ], [{ name: 'allUsers', type: object('UsersConnection') }] ); @@ -529,17 +529,17 @@ describe('Query Operation Matching', () => { { name: 'User', kind: 'OBJECT', - fields: [{ name: 'id', type: nonNull(scalar('UUID')) }], + fields: [{ name: 'id', type: nonNull(scalar('UUID')) }] }, - { name: 'UsersConnection', kind: 'OBJECT', fields: [] }, + { name: 'UsersConnection', kind: 'OBJECT', fields: [] } ], [ { name: 'users', type: object('UsersConnection') }, { name: 'user', type: object('User'), - args: [{ name: 'id', type: nonNull(scalar('UUID')) }], - }, + args: [{ name: 'id', type: nonNull(scalar('UUID')) }] + } ] ); @@ -554,12 +554,12 @@ describe('Query Operation Matching', () => { { name: 'User', kind: 'OBJECT', - fields: [{ name: 'id', type: nonNull(scalar('UUID')) }], + fields: [{ name: 'id', type: nonNull(scalar('UUID')) }] }, - { name: 'UsersConnection', kind: 'OBJECT', fields: [] }, + { name: 'UsersConnection', kind: 'OBJECT', fields: [] } ], [ - { name: 'users', type: object('UsersConnection') }, + { name: 'users', type: object('UsersConnection') } // No single user query ] ); @@ -579,10 +579,10 @@ describe('Mutation Operation Matching', () => { { name: 'User', kind: 'OBJECT', - fields: [{ name: 'id', type: nonNull(scalar('UUID')) }], + fields: [{ name: 'id', type: nonNull(scalar('UUID')) }] }, { name: 'UsersConnection', kind: 'OBJECT', fields: [] }, - { name: 'CreateUserPayload', kind: 'OBJECT', fields: [] }, + { name: 'CreateUserPayload', kind: 'OBJECT', fields: [] } ], [{ name: 'users', type: object('UsersConnection') }], [ @@ -590,9 +590,9 @@ describe('Mutation Operation Matching', () => { name: 'createUser', type: object('CreateUserPayload'), args: [ - { name: 'input', type: nonNull(inputObject('CreateUserInput')) }, - ], - }, + { name: 'input', type: nonNull(inputObject('CreateUserInput')) } + ] + } ] ); @@ -607,11 +607,11 @@ describe('Mutation Operation Matching', () => { { name: 'User', kind: 'OBJECT', - fields: [{ name: 'id', type: nonNull(scalar('UUID')) }], + fields: [{ name: 'id', type: nonNull(scalar('UUID')) }] }, { name: 'UsersConnection', kind: 'OBJECT', fields: [] }, { name: 'UpdateUserPayload', kind: 'OBJECT', fields: [] }, - { name: 'DeleteUserPayload', kind: 'OBJECT', fields: [] }, + { name: 'DeleteUserPayload', kind: 'OBJECT', fields: [] } ], [{ name: 'users', type: object('UsersConnection') }], [ @@ -619,16 +619,16 @@ describe('Mutation Operation Matching', () => { name: 'updateUser', type: object('UpdateUserPayload'), args: [ - { name: 'input', type: nonNull(inputObject('UpdateUserInput')) }, - ], + { name: 'input', type: nonNull(inputObject('UpdateUserInput')) } + ] }, { name: 'deleteUser', type: object('DeleteUserPayload'), args: [ - { name: 'input', type: nonNull(inputObject('DeleteUserInput')) }, - ], - }, + { name: 'input', type: nonNull(inputObject('DeleteUserInput')) } + ] + } ] ); @@ -644,15 +644,15 @@ describe('Mutation Operation Matching', () => { { name: 'User', kind: 'OBJECT', - fields: [{ name: 'id', type: nonNull(scalar('UUID')) }], + fields: [{ name: 'id', type: nonNull(scalar('UUID')) }] }, { name: 'UsersConnection', kind: 'OBJECT', fields: [] }, - { name: 'UpdateUserPayload', kind: 'OBJECT', fields: [] }, + { name: 'UpdateUserPayload', kind: 'OBJECT', fields: [] } ], [{ name: 'users', type: object('UsersConnection') }], [ { name: 'updateUserById', type: object('UpdateUserPayload') }, - { name: 'updateUser', type: object('UpdateUserPayload') }, + { name: 'updateUser', type: object('UpdateUserPayload') } ] ); @@ -673,9 +673,9 @@ describe('Constraint Inference', () => { { name: 'User', kind: 'OBJECT', - fields: [{ name: 'id', type: nonNull(scalar('UUID')) }], + fields: [{ name: 'id', type: nonNull(scalar('UUID')) }] }, - { name: 'UsersConnection', kind: 'OBJECT', fields: [] }, + { name: 'UsersConnection', kind: 'OBJECT', fields: [] } ], [{ name: 'users', type: object('UsersConnection') }] ); @@ -692,14 +692,14 @@ describe('Constraint Inference', () => { { name: 'User', kind: 'OBJECT', - fields: [{ name: 'userId', type: nonNull(scalar('UUID')) }], + fields: [{ name: 'userId', type: nonNull(scalar('UUID')) }] }, { name: 'UsersConnection', kind: 'OBJECT', fields: [] }, { name: 'UpdateUserInput', kind: 'INPUT_OBJECT', - inputFields: [{ name: 'id', type: nonNull(scalar('UUID')) }], - }, + inputFields: [{ name: 'id', type: nonNull(scalar('UUID')) }] + } ], [{ name: 'users', type: object('UsersConnection') }], [{ name: 'updateUser', type: object('UpdateUserPayload') }] @@ -723,12 +723,12 @@ describe('Inflection Building', () => { { name: 'User', kind: 'OBJECT', - fields: [{ name: 'id', type: nonNull(scalar('UUID')) }], + fields: [{ name: 'id', type: nonNull(scalar('UUID')) }] }, { name: 'UsersConnection', kind: 'OBJECT', fields: [] }, { name: 'UserFilter', kind: 'INPUT_OBJECT', inputFields: [] }, { name: 'UserPatch', kind: 'INPUT_OBJECT', inputFields: [] }, - { name: 'UpdateUserPayload', kind: 'OBJECT', fields: [] }, + { name: 'UpdateUserPayload', kind: 'OBJECT', fields: [] } ], [{ name: 'users', type: object('UsersConnection') }] ); @@ -750,9 +750,9 @@ describe('Inflection Building', () => { { name: 'User', kind: 'OBJECT', - fields: [{ name: 'id', type: nonNull(scalar('UUID')) }], + fields: [{ name: 'id', type: nonNull(scalar('UUID')) }] }, - { name: 'UsersConnection', kind: 'OBJECT', fields: [] }, + { name: 'UsersConnection', kind: 'OBJECT', fields: [] } // No UserFilter, UserPatch, or UpdateUserPayload ], [{ name: 'users', type: object('UsersConnection') }] @@ -776,7 +776,7 @@ describe('Edge Cases', () => { const introspection = createIntrospection( [ // Only built-in types, no entities - { name: 'PageInfo', kind: 'OBJECT', fields: [] }, + { name: 'PageInfo', kind: 'OBJECT', fields: [] } ], [] ); @@ -793,9 +793,9 @@ describe('Edge Cases', () => { { name: 'Orphan', kind: 'OBJECT', - fields: [{ name: 'id', type: nonNull(scalar('UUID')) }], + fields: [{ name: 'id', type: nonNull(scalar('UUID')) }] }, - { name: 'OrphansConnection', kind: 'OBJECT', fields: [] }, + { name: 'OrphansConnection', kind: 'OBJECT', fields: [] } ], [] // No query fields ); @@ -814,8 +814,8 @@ describe('Edge Cases', () => { kind: 'OBJECT', fields: [ { name: 'id', type: nonNull(scalar('UUID')) }, - { name: 'posts', type: object('PostsConnection') }, - ], + { name: 'posts', type: object('PostsConnection') } + ] }, { name: 'UsersConnection', kind: 'OBJECT', fields: [] }, { @@ -823,14 +823,14 @@ describe('Edge Cases', () => { kind: 'OBJECT', fields: [ { name: 'id', type: nonNull(scalar('UUID')) }, - { name: 'author', type: object('User') }, - ], + { name: 'author', type: object('User') } + ] }, - { name: 'PostsConnection', kind: 'OBJECT', fields: [] }, + { name: 'PostsConnection', kind: 'OBJECT', fields: [] } ], [ { name: 'users', type: object('UsersConnection') }, - { name: 'posts', type: object('PostsConnection') }, + { name: 'posts', type: object('PostsConnection') } ] ); @@ -852,9 +852,9 @@ describe('Edge Cases', () => { { name: 'Person', kind: 'OBJECT', - fields: [{ name: 'id', type: nonNull(scalar('UUID')) }], + fields: [{ name: 'id', type: nonNull(scalar('UUID')) }] }, - { name: 'PeopleConnection', kind: 'OBJECT', fields: [] }, + { name: 'PeopleConnection', kind: 'OBJECT', fields: [] } ], [{ name: 'people', type: object('PeopleConnection') }] ); @@ -875,15 +875,15 @@ describe('Edge Cases', () => { fields: [ { name: 'id', type: nonNull(scalar('UUID')) }, { name: 'street', type: scalar('String') }, - { name: 'city', type: scalar('String') }, - ], + { name: 'city', type: scalar('String') } + ] }, { name: 'AddressesConnection', kind: 'OBJECT', fields: [] }, { name: 'AddressesOrderBy', kind: 'ENUM', - enumValues: ['ID_ASC', 'ID_DESC'], - }, + enumValues: ['ID_ASC', 'ID_DESC'] + } ], [{ name: 'addresses', type: object('AddressesConnection') }] ); @@ -903,10 +903,10 @@ describe('Edge Cases', () => { { name: 'Category', kind: 'OBJECT', - fields: [{ name: 'id', type: nonNull(scalar('UUID')) }], + fields: [{ name: 'id', type: nonNull(scalar('UUID')) }] }, { name: 'CategoriesConnection', kind: 'OBJECT', fields: [] }, - { name: 'CategoriesOrderBy', kind: 'ENUM', enumValues: ['ID_ASC'] }, + { name: 'CategoriesOrderBy', kind: 'ENUM', enumValues: ['ID_ASC'] } ], [{ name: 'categories', type: object('CategoriesConnection') }] ); @@ -923,11 +923,11 @@ describe('Edge Cases', () => { { name: 'Status', kind: 'OBJECT', - fields: [{ name: 'id', type: nonNull(scalar('UUID')) }], + fields: [{ name: 'id', type: nonNull(scalar('UUID')) }] }, { name: 'StatusesConnection', kind: 'OBJECT', fields: [] }, // Schema has the actual OrderBy enum - { name: 'StatusesOrderBy', kind: 'ENUM', enumValues: ['ID_ASC'] }, + { name: 'StatusesOrderBy', kind: 'ENUM', enumValues: ['ID_ASC'] } ], [{ name: 'statuses', type: object('StatusesConnection') }] ); diff --git a/graphql/codegen/src/cli/index.ts b/graphql/codegen/src/cli/index.ts index 5ef53ee8c..cfea02a20 100644 --- a/graphql/codegen/src/cli/index.ts +++ b/graphql/codegen/src/cli/index.ts @@ -5,12 +5,19 @@ * This is a thin wrapper around the core generate() function. * All business logic is in the core modules. */ -import { CLI, CLIOptions, Inquirerer, getPackageJson } from 'inquirerer'; +import { CLI, CLIOptions, getPackageJson, Inquirerer } from 'inquirerer'; -import { generate } from '../core/generate'; import { findConfigFile, loadConfigFile } from '../core/config'; +import { generate } from '../core/generate'; import type { GraphQLSDKConfigTarget } from '../types/config'; -import { camelizeArgv, codegenQuestions, printResult, type CodegenAnswers } from './shared'; +import { + buildDbConfig, + buildGenerateOptions, + camelizeArgv, + codegenQuestions, + printResult, + seedArgvFromConfig +} from './shared'; const usage = ` graphql-codegen - GraphQL SDK generator for Constructive databases @@ -33,8 +40,6 @@ Generator Options: -o, --output Output directory -t, --target Target name (for multi-target configs) -a, --authorization Authorization header value - --browser-compatible Generate browser-compatible code (default: true) - Set to false for Node.js with localhost DNS fix --dry-run Preview without writing files -v, --verbose Show detailed output @@ -58,10 +63,16 @@ export const commands = async ( process.exit(0); } - const configPath = (argv.config || argv.c || findConfigFile()) as string | undefined; + const hasSourceFlags = Boolean( + argv.endpoint || argv.e || argv['schema-file'] || argv.s || + argv.schemas || argv['api-names'] + ); + const explicitConfigPath = (argv.config || argv.c) as string | undefined; + const configPath = explicitConfigPath || (!hasSourceFlags ? findConfigFile() : undefined); const targetName = (argv.target || argv.t) as string | undefined; - // If config file exists, load and run + let fileConfig: GraphQLSDKConfigTarget = {}; + if (configPath) { const loaded = await loadConfigFile(configPath); if (!loaded.success) { @@ -70,12 +81,9 @@ export const commands = async ( } const config = loaded.config as Record; - - // Check if it's a multi-target config (no source fields at top level) const isMulti = !('endpoint' in config || 'schemaFile' in config || 'db' in config); if (isMulti) { - // Multi-target: simple for loop over targets const targets = config as Record; const names = targetName ? [targetName] : Object.keys(targets); @@ -84,10 +92,11 @@ export const commands = async ( process.exit(1); } + const cliOptions = buildDbConfig(camelizeArgv(argv as Record)); let hasError = false; for (const name of names) { console.log(`\n[${name}]`); - const result = await generate(targets[name]); + const result = await generate({ ...targets[name], ...cliOptions } as GraphQLSDKConfigTarget); printResult(result); if (!result.success) hasError = true; } @@ -97,39 +106,13 @@ export const commands = async ( return argv; } - // Single config - const result = await generate(config as GraphQLSDKConfigTarget); - printResult(result); - if (!result.success) process.exit(1); - prompter.close(); - return argv; + fileConfig = config as GraphQLSDKConfigTarget; } - // No config file - prompt for options using shared questions - const answers = await prompter.prompt(argv as CodegenAnswers, codegenQuestions); - - // Convert kebab-case CLI args to camelCase for internal use - const camelized = camelizeArgv(answers) as CodegenAnswers; - - // Build db config if schemas or apiNames provided - const db = (camelized.schemas || camelized.apiNames) ? { - schemas: camelized.schemas, - apiNames: camelized.apiNames, - } : undefined; - - const result = await generate({ - endpoint: camelized.endpoint, - schemaFile: camelized.schemaFile, - db, - output: camelized.output, - authorization: camelized.authorization, - reactQuery: camelized.reactQuery, - orm: camelized.orm, - browserCompatible: camelized.browserCompatible, - dryRun: camelized.dryRun, - verbose: camelized.verbose, - }); - + const seeded = seedArgvFromConfig(argv, fileConfig); + const answers = await prompter.prompt(seeded, codegenQuestions); + const options = buildGenerateOptions(answers, fileConfig); + const result = await generate(options); printResult(result); prompter.close(); return argv; @@ -145,17 +128,17 @@ export const options: Partial = { o: 'output', t: 'target', a: 'authorization', - v: 'verbose', + v: 'verbose' }, boolean: [ - 'help', 'version', 'verbose', 'dry-run', 'react-query', 'orm', 'keep-db', 'browser-compatible', + 'help', 'version', 'verbose', 'dry-run', 'react-query', 'orm', 'keep-db' ], string: [ 'config', 'endpoint', 'schema-file', 'output', 'target', 'authorization', 'pgpm-module-path', 'pgpm-workspace-path', 'pgpm-module-name', - 'schemas', 'api-names', - ], - }, + 'schemas', 'api-names' + ] + } }; if (require.main === module) { diff --git a/graphql/codegen/src/cli/shared.ts b/graphql/codegen/src/cli/shared.ts index f147b9fa8..26370919b 100644 --- a/graphql/codegen/src/cli/shared.ts +++ b/graphql/codegen/src/cli/shared.ts @@ -1,26 +1,21 @@ /** * Shared CLI utilities for graphql-codegen * - * These are exported so that packages/cli can use the same questions - * and types, ensuring consistency between the two CLIs. + * These are exported so that packages/cli can use the same questions, + * types, and transform utilities, ensuring consistency between the two CLIs. */ -import type { Question } from 'inquirerer'; -import type { GenerateResult } from '../core/generate'; import { camelize } from 'inflekt'; import { inflektTree } from 'inflekt/transform-keys'; +import type { Question } from 'inquirerer'; + +import type { GenerateResult } from '../core/generate'; +import type { GraphQLSDKConfigTarget } from '../types/config'; -/** - * Sanitize function that splits comma-separated strings into arrays - */ export const splitCommas = (input: string | undefined): string[] | undefined => { if (!input) return undefined; return input.split(',').map((s) => s.trim()).filter(Boolean); }; -/** - * Interface for codegen CLI answers - * CLI accepts kebab-case arguments, converted to camelCase for internal use - */ export interface CodegenAnswers { endpoint?: string; schemaFile?: string; @@ -29,27 +24,23 @@ export interface CodegenAnswers { apiNames?: string[]; reactQuery?: boolean; orm?: boolean; - browserCompatible?: boolean; authorization?: string; dryRun?: boolean; verbose?: boolean; } -/** - * Questions for the codegen CLI - */ export const codegenQuestions: Question[] = [ { name: 'endpoint', message: 'GraphQL endpoint URL', type: 'text', - required: false, + required: false }, { name: 'schema-file', message: 'Path to GraphQL schema file', type: 'text', - required: false, + required: false }, { name: 'output', @@ -57,21 +48,21 @@ export const codegenQuestions: Question[] = [ type: 'text', required: false, default: 'codegen', - useDefault: true, + useDefault: true }, { name: 'schemas', message: 'PostgreSQL schemas (comma-separated)', type: 'text', required: false, - sanitize: splitCommas, + sanitize: splitCommas }, { name: 'api-names', message: 'API names (comma-separated)', type: 'text', required: false, - sanitize: splitCommas, + sanitize: splitCommas }, { name: 'react-query', @@ -79,7 +70,7 @@ export const codegenQuestions: Question[] = [ type: 'confirm', required: false, default: false, - useDefault: true, + useDefault: true }, { name: 'orm', @@ -87,21 +78,13 @@ export const codegenQuestions: Question[] = [ type: 'confirm', required: false, default: false, - useDefault: true, - }, - { - name: 'browser-compatible', - message: 'Generate browser-compatible code?', - type: 'confirm', - required: false, - default: true, - useDefault: true, + useDefault: true }, { name: 'authorization', message: 'Authorization header value', type: 'text', - required: false, + required: false }, { name: 'dry-run', @@ -109,7 +92,7 @@ export const codegenQuestions: Question[] = [ type: 'confirm', required: false, default: false, - useDefault: true, + useDefault: true }, { name: 'verbose', @@ -117,13 +100,10 @@ export const codegenQuestions: Question[] = [ type: 'confirm', required: false, default: false, - useDefault: true, - }, + useDefault: true + } ]; -/** - * Print the result of a generate operation - */ export function printResult(result: GenerateResult): void { if (result.success) { console.log('[ok]', result.message); @@ -137,15 +117,69 @@ export function printResult(result: GenerateResult): void { } } +// ============================================================================ +// Key transform utilities +// ============================================================================ + const isTopLevel = (_key: string, path: string[]) => path.length === 0; -export const camelizeArgv = (argv: Record) => +const skipNonTopLevel = (key: string, path: string[]) => + !isTopLevel(key, path) || key === '_' || key.startsWith('_'); + +export const camelizeArgv = (argv: Record): Record => inflektTree(argv, (key) => { - // inflection.camelize expects underscores, so replace hyphens first const underscored = key.replace(/-/g, '_'); return camelize(underscored, true); - }, { - skip: (key, path) => - !isTopLevel(key, path) || - key === '_' || - key.startsWith('_') + }, { skip: skipNonTopLevel }); + +export const hyphenateKeys = (obj: Record): Record => + inflektTree(obj, (key) => key.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase()), { + skip: skipNonTopLevel }); + +// ============================================================================ +// Config <-> CLI shape transforms +// ============================================================================ + +export function filterDefined(obj: Record): Record { + return Object.fromEntries( + Object.entries(obj).filter(([, v]) => v !== undefined && v !== null) + ); +} + +export function flattenDbFields(config: Record): Record { + const { db, ...rest } = config; + if (db && typeof db === 'object') { + const dbObj = db as Record; + const schemas = Array.isArray(dbObj.schemas) ? dbObj.schemas.join(',') : dbObj.schemas; + const apiNames = Array.isArray(dbObj.apiNames) ? dbObj.apiNames.join(',') : dbObj.apiNames; + return { ...rest, schemas, apiNames }; + } + return rest; +} + +export function buildDbConfig(options: Record): Record { + const { schemas, apiNames, ...rest } = options; + if (schemas || apiNames) { + return { ...rest, db: { schemas, apiNames } }; + } + return rest; +} + +export function seedArgvFromConfig( + argv: Record, + fileConfig: GraphQLSDKConfigTarget +): Record { + const flat = flattenDbFields(fileConfig as Record); + const hyphenated = hyphenateKeys(flat); + const defined = filterDefined(hyphenated); + return { ...defined, ...argv }; +} + +export function buildGenerateOptions( + answers: Record, + fileConfig: GraphQLSDKConfigTarget = {} +): GraphQLSDKConfigTarget { + const camelized = camelizeArgv(answers); + const withDb = buildDbConfig(camelized); + return { ...fileConfig, ...withDb } as GraphQLSDKConfigTarget; +} diff --git a/graphql/codegen/src/client/error.ts b/graphql/codegen/src/client/error.ts index d879712de..368094f84 100644 --- a/graphql/codegen/src/client/error.ts +++ b/graphql/codegen/src/client/error.ts @@ -43,7 +43,7 @@ export const DataErrorType = { EXCLUSION_VIOLATION: 'EXCLUSION_VIOLATION', // Generic errors - UNKNOWN_ERROR: 'UNKNOWN_ERROR', + UNKNOWN_ERROR: 'UNKNOWN_ERROR' } as const; export type DataErrorType = (typeof DataErrorType)[keyof typeof DataErrorType]; @@ -91,36 +91,36 @@ export class DataError extends Error { getUserMessage(): string { switch (this.type) { - case DataErrorType.NETWORK_ERROR: - return 'Network error. Please check your connection and try again.'; - case DataErrorType.TIMEOUT_ERROR: - return 'Request timed out. Please try again.'; - case DataErrorType.UNAUTHORIZED: - return 'You are not authorized. Please log in and try again.'; - case DataErrorType.FORBIDDEN: - return 'You do not have permission to access this resource.'; - case DataErrorType.VALIDATION_FAILED: - return 'Validation failed. Please check your input and try again.'; - case DataErrorType.REQUIRED_FIELD_MISSING: - return this.fieldName - ? `The field "${this.fieldName}" is required.` - : 'A required field is missing.'; - case DataErrorType.UNIQUE_VIOLATION: - return this.fieldName - ? `A record with this ${this.fieldName} already exists.` - : 'A record with this value already exists.'; - case DataErrorType.FOREIGN_KEY_VIOLATION: - return 'This record references a record that does not exist.'; - case DataErrorType.NOT_NULL_VIOLATION: - return this.fieldName - ? `The field "${this.fieldName}" cannot be empty.` - : 'A required field cannot be empty.'; - case DataErrorType.CHECK_VIOLATION: - return this.fieldName - ? `The value for "${this.fieldName}" is not valid.` - : 'The value does not meet the required constraints.'; - default: - return this.message || 'An unexpected error occurred.'; + case DataErrorType.NETWORK_ERROR: + return 'Network error. Please check your connection and try again.'; + case DataErrorType.TIMEOUT_ERROR: + return 'Request timed out. Please try again.'; + case DataErrorType.UNAUTHORIZED: + return 'You are not authorized. Please log in and try again.'; + case DataErrorType.FORBIDDEN: + return 'You do not have permission to access this resource.'; + case DataErrorType.VALIDATION_FAILED: + return 'Validation failed. Please check your input and try again.'; + case DataErrorType.REQUIRED_FIELD_MISSING: + return this.fieldName + ? `The field "${this.fieldName}" is required.` + : 'A required field is missing.'; + case DataErrorType.UNIQUE_VIOLATION: + return this.fieldName + ? `A record with this ${this.fieldName} already exists.` + : 'A record with this value already exists.'; + case DataErrorType.FOREIGN_KEY_VIOLATION: + return 'This record references a record that does not exist.'; + case DataErrorType.NOT_NULL_VIOLATION: + return this.fieldName + ? `The field "${this.fieldName}" cannot be empty.` + : 'A required field cannot be empty.'; + case DataErrorType.CHECK_VIOLATION: + return this.fieldName + ? `The value for "${this.fieldName}" is not valid.` + : 'The value does not meet the required constraints.'; + default: + return this.message || 'An unexpected error occurred.'; } } @@ -148,7 +148,7 @@ export const PG_ERROR_CODES = { DATETIME_FIELD_OVERFLOW: '22008', UNDEFINED_TABLE: '42P01', UNDEFINED_COLUMN: '42703', - INSUFFICIENT_PRIVILEGE: '42501', + INSUFFICIENT_PRIVILEGE: '42501' } as const; // ============================================================================ @@ -187,7 +187,7 @@ export const createError = { new DataError(DataErrorType.NOT_NULL_VIOLATION, message, { fieldName, constraint, code: '23502' }), unknown: (originalError: Error) => - new DataError(DataErrorType.UNKNOWN_ERROR, originalError.message, { originalError }), + new DataError(DataErrorType.UNKNOWN_ERROR, originalError.message, { originalError }) }; // ============================================================================ @@ -293,7 +293,7 @@ export function parseGraphQLError(error: unknown): DataError { code: extCode, fieldName, constraint, - context: gqlError.extensions, + context: gqlError.extensions }); } @@ -303,7 +303,7 @@ export function parseGraphQLError(error: unknown): DataError { code: extCode, fieldName, constraint, - context: gqlError.extensions, + context: gqlError.extensions }); } diff --git a/graphql/codegen/src/client/execute.ts b/graphql/codegen/src/client/execute.ts index 6f59e7cec..1c4441acf 100644 --- a/graphql/codegen/src/client/execute.ts +++ b/graphql/codegen/src/client/execute.ts @@ -5,8 +5,8 @@ import type { DocumentNode } from 'graphql'; import { print } from 'graphql'; +import { createError, type DataError,parseGraphQLError } from './error'; import { TypedDocumentString } from './typed-document'; -import { createError, parseGraphQLError, type DataError } from './error'; // ============================================================================ // Types @@ -69,7 +69,7 @@ export async function execute( endpoint: string, document: TDocument, variables?: VariablesOf, - options: ExecuteOptions = {}, + options: ExecuteOptions = {} ): Promise> { const { headers = {}, timeout = 30000, signal } = options; @@ -88,13 +88,13 @@ export async function execute( headers: { 'Content-Type': 'application/json', Accept: 'application/graphql-response+json, application/json', - ...headers, + ...headers }, body: JSON.stringify({ query: documentToString(document), - ...(variables !== undefined && { variables }), + ...(variables !== undefined && { variables }) }), - signal: combinedSignal, + signal: combinedSignal }); clearTimeout(timeoutId); @@ -182,12 +182,12 @@ export function createGraphQLClient(options: GraphQLClientOptions) { async execute( document: TDocument, variables?: VariablesOf, - options: ExecuteOptions = {}, + options: ExecuteOptions = {} ): Promise> { return execute(endpoint, document, variables, { headers: { ...defaultHeaders, ...options.headers }, timeout: options.timeout ?? defaultTimeout, - signal: options.signal, + signal: options.signal }); }, @@ -196,7 +196,7 @@ export function createGraphQLClient(options: GraphQLClientOptions) { */ getEndpoint(): string { return endpoint; - }, + } }; } diff --git a/graphql/codegen/src/client/index.ts b/graphql/codegen/src/client/index.ts index 53b0bb352..2ec241259 100644 --- a/graphql/codegen/src/client/index.ts +++ b/graphql/codegen/src/client/index.ts @@ -2,24 +2,22 @@ * Client exports */ -export { TypedDocumentString, type DocumentTypeDecoration } from './typed-document'; - export { - DataError, - DataErrorType, createError, - parseGraphQLError, - isDataError, - PG_ERROR_CODES, + DataError, type DataErrorOptions, + DataErrorType, type GraphQLError, + isDataError, + parseGraphQLError, + PG_ERROR_CODES } from './error'; - export { - execute, createGraphQLClient, + execute, type ExecuteOptions, - type GraphQLClientOptions, type GraphQLClient, - type GraphQLResponse, + type GraphQLClientOptions, + type GraphQLResponse } from './execute'; +export { type DocumentTypeDecoration,TypedDocumentString } from './typed-document'; diff --git a/graphql/codegen/src/client/typed-document.ts b/graphql/codegen/src/client/typed-document.ts index ca3f895a4..95350ad96 100644 --- a/graphql/codegen/src/client/typed-document.ts +++ b/graphql/codegen/src/client/typed-document.ts @@ -33,7 +33,7 @@ export class TypedDocumentString this.value = value; this.__meta__ = { hash: this.generateHash(value), - ...meta, + ...meta }; } diff --git a/graphql/codegen/src/core/ast.ts b/graphql/codegen/src/core/ast.ts index d7903bd09..7c3b95db7 100644 --- a/graphql/codegen/src/core/ast.ts +++ b/graphql/codegen/src/core/ast.ts @@ -5,19 +5,18 @@ import type { FieldNode, TypeNode, ValueNode, - VariableDefinitionNode, + VariableDefinitionNode } from 'graphql'; import { camelize, singularize } from 'inflekt'; - import { getCustomAst } from './custom-ast'; import type { ASTFunctionParams, - QueryFieldSelection, MutationASTParams, NestedProperties, ObjectArrayItem, - QueryProperty, + QueryFieldSelection, + QueryProperty } from './types'; const NON_MUTABLE_PROPS = ['createdAt', 'createdBy', 'updatedAt', 'updatedBy']; @@ -32,7 +31,7 @@ const objectToArray = ( isNotNull: obj[k].isNotNull, isArray: obj[k].isArray, isArrayNotNull: obj[k].isArrayNotNull, - properties: obj[k].properties, + properties: obj[k].properties })); interface CreateGqlMutationParams { @@ -52,32 +51,32 @@ const createGqlMutation = ({ selections, variableDefinitions, modelName, - useModel = true, + useModel = true }: CreateGqlMutationParams): DocumentNode => { const opSel: FieldNode[] = !modelName ? [ - t.field({ - name: operationName, - args: selectArgs, - selectionSet: t.selectionSet({ selections }), - }), - ] + t.field({ + name: operationName, + args: selectArgs, + selectionSet: t.selectionSet({ selections }) + }) + ] : [ - t.field({ - name: operationName, - args: selectArgs, - selectionSet: t.selectionSet({ - selections: useModel - ? [ - t.field({ - name: modelName, - selectionSet: t.selectionSet({ selections }), - }), - ] - : selections, - }), - }), - ]; + t.field({ + name: operationName, + args: selectArgs, + selectionSet: t.selectionSet({ + selections: useModel + ? [ + t.field({ + name: modelName, + selectionSet: t.selectionSet({ selections }) + }) + ] + : selections + }) + }) + ]; return t.document({ definitions: [ @@ -85,16 +84,16 @@ const createGqlMutation = ({ operation: 'mutation', name: mutationName, variableDefinitions, - selectionSet: t.selectionSet({ selections: opSel }), - }), - ], + selectionSet: t.selectionSet({ selections: opSel }) + }) + ] }); }; export const getAll = ({ queryName, operationName, - selection, + selection }: ASTFunctionParams): DocumentNode => { const selections = getSelections(selection); @@ -104,15 +103,15 @@ export const getAll = ({ selectionSet: t.selectionSet({ selections: [ t.field({ - name: 'totalCount', + name: 'totalCount' }), t.field({ name: 'nodes', - selectionSet: t.selectionSet({ selections }), - }), - ], - }), - }), + selectionSet: t.selectionSet({ selections }) + }) + ] + }) + }) ]; const ast = t.document({ @@ -120,9 +119,9 @@ export const getAll = ({ t.operationDefinition({ operation: 'query', name: queryName, - selectionSet: t.selectionSet({ selections: opSel }), - }), - ], + selectionSet: t.selectionSet({ selections: opSel }) + }) + ] }); return ast; @@ -131,7 +130,7 @@ export const getAll = ({ export const getCount = ({ queryName, operationName, - query, + query }: Omit): DocumentNode => { const Singular = query.model; const Filter = `${Singular}Filter`; @@ -140,17 +139,17 @@ export const getCount = ({ const variableDefinitions: VariableDefinitionNode[] = [ t.variableDefinition({ variable: t.variable({ name: 'condition' }), - type: t.namedType({ type: Condition }), + type: t.namedType({ type: Condition }) }), t.variableDefinition({ variable: t.variable({ name: 'filter' }), - type: t.namedType({ type: Filter }), - }), + type: t.namedType({ type: Filter }) + }) ]; const args: ArgumentNode[] = [ t.argument({ name: 'condition', value: t.variable({ name: 'condition' }) }), - t.argument({ name: 'filter', value: t.variable({ name: 'filter' }) }), + t.argument({ name: 'filter', value: t.variable({ name: 'filter' }) }) ]; // PostGraphile supports totalCount through connections @@ -161,11 +160,11 @@ export const getCount = ({ selectionSet: t.selectionSet({ selections: [ t.field({ - name: 'totalCount', - }), - ], - }), - }), + name: 'totalCount' + }) + ] + }) + }) ]; const ast = t.document({ @@ -174,9 +173,9 @@ export const getCount = ({ operation: 'query', name: queryName, variableDefinitions, - selectionSet: t.selectionSet({ selections: opSel }), - }), - ], + selectionSet: t.selectionSet({ selections: opSel }) + }) + ] }); return ast; @@ -187,7 +186,7 @@ export const getMany = ({ queryName, operationName, query, - selection, + selection }: ASTFunctionParams): DocumentNode => { const Singular = query.model; const Plural = @@ -200,38 +199,38 @@ export const getMany = ({ const variableDefinitions: VariableDefinitionNode[] = [ t.variableDefinition({ variable: t.variable({ name: 'first' }), - type: t.namedType({ type: 'Int' }), + type: t.namedType({ type: 'Int' }) }), t.variableDefinition({ variable: t.variable({ name: 'last' }), - type: t.namedType({ type: 'Int' }), + type: t.namedType({ type: 'Int' }) }), t.variableDefinition({ variable: t.variable({ name: 'after' }), - type: t.namedType({ type: 'Cursor' }), + type: t.namedType({ type: 'Cursor' }) }), t.variableDefinition({ variable: t.variable({ name: 'before' }), - type: t.namedType({ type: 'Cursor' }), + type: t.namedType({ type: 'Cursor' }) }), t.variableDefinition({ variable: t.variable({ name: 'offset' }), - type: t.namedType({ type: 'Int' }), + type: t.namedType({ type: 'Int' }) }), t.variableDefinition({ variable: t.variable({ name: 'condition' }), - type: t.namedType({ type: Condition }), + type: t.namedType({ type: Condition }) }), t.variableDefinition({ variable: t.variable({ name: 'filter' }), - type: t.namedType({ type: Filter }), + type: t.namedType({ type: Filter }) }), t.variableDefinition({ variable: t.variable({ name: 'orderBy' }), type: t.listType({ - type: t.nonNullType({ type: t.namedType({ type: OrderBy }) }), - }), - }), + type: t.nonNullType({ type: t.namedType({ type: OrderBy }) }) + }) + }) ]; const args: ArgumentNode[] = [ @@ -242,44 +241,44 @@ export const getMany = ({ t.argument({ name: 'before', value: t.variable({ name: 'before' }) }), t.argument({ name: 'condition', - value: t.variable({ name: 'condition' }), + value: t.variable({ name: 'condition' }) }), t.argument({ name: 'filter', value: t.variable({ name: 'filter' }) }), - t.argument({ name: 'orderBy', value: t.variable({ name: 'orderBy' }) }), + t.argument({ name: 'orderBy', value: t.variable({ name: 'orderBy' }) }) ]; const pageInfoFields: FieldNode[] = [ t.field({ name: 'hasNextPage' }), t.field({ name: 'hasPreviousPage' }), t.field({ name: 'endCursor' }), - t.field({ name: 'startCursor' }), + t.field({ name: 'startCursor' }) ]; const dataField: FieldNode = builder?._edges ? t.field({ - name: 'edges', - selectionSet: t.selectionSet({ - selections: [ - t.field({ name: 'cursor' }), - t.field({ - name: 'node', - selectionSet: t.selectionSet({ selections }), - }), - ], - }), + name: 'edges', + selectionSet: t.selectionSet({ + selections: [ + t.field({ name: 'cursor' }), + t.field({ + name: 'node', + selectionSet: t.selectionSet({ selections }) + }) + ] }) + }) : t.field({ - name: 'nodes', - selectionSet: t.selectionSet({ selections }), - }); + name: 'nodes', + selectionSet: t.selectionSet({ selections }) + }); const connectionFields: FieldNode[] = [ t.field({ name: 'totalCount' }), t.field({ name: 'pageInfo', - selectionSet: t.selectionSet({ selections: pageInfoFields }), + selectionSet: t.selectionSet({ selections: pageInfoFields }) }), - dataField, + dataField ]; const ast = t.document({ @@ -293,12 +292,12 @@ export const getMany = ({ t.field({ name: operationName, args, - selectionSet: t.selectionSet({ selections: connectionFields }), - }), - ], - }), - }), - ], + selectionSet: t.selectionSet({ selections: connectionFields }) + }) + ] + }) + }) + ] }); return ast; @@ -308,7 +307,7 @@ export const getOne = ({ queryName, operationName, query, - selection, + selection }: ASTFunctionParams): DocumentNode => { const variableDefinitions: VariableDefinitionNode[] = Object.keys( query.properties @@ -321,7 +320,7 @@ export const getOne = ({ type: fieldType, isNotNull, isArray, - isArrayNotNull, + isArrayNotNull } = field; let type: TypeNode = t.namedType({ type: fieldType }); if (isNotNull) type = t.nonNullType({ type }); @@ -331,7 +330,7 @@ export const getOne = ({ } return t.variableDefinition({ variable: t.variable({ name: fieldName }), - type, + type }); }); @@ -342,7 +341,7 @@ export const getOne = ({ .map((field) => { return t.argument({ name: field.name, - value: t.variable({ name: field.name }), + value: t.variable({ name: field.name }) }); }); @@ -352,8 +351,8 @@ export const getOne = ({ t.field({ name: operationName, args: selectArgs, - selectionSet: t.selectionSet({ selections }), - }), + selectionSet: t.selectionSet({ selections }) + }) ]; const ast = t.document({ @@ -362,9 +361,9 @@ export const getOne = ({ operation: 'query', name: queryName, variableDefinitions, - selectionSet: t.selectionSet({ selections: opSel }), - }), - ], + selectionSet: t.selectionSet({ selections: opSel }) + }) + ] }); return ast; }; @@ -373,7 +372,7 @@ export const createOne = ({ mutationName, operationName, mutation, - selection, + selection }: MutationASTParams): DocumentNode => { if (!mutation.properties?.input?.properties) { throw new Error(`No input field for mutation: ${mutationName}`); @@ -412,14 +411,14 @@ export const createOne = ({ fields: attrs.map((field) => t.objectField({ name: field.name, - value: t.variable({ name: field.name }), + value: t.variable({ name: field.name }) }) - ), - }), - }), - ], - }), - }), + ) + }) + }) + ] + }) + }) ]; const selections = selection @@ -432,7 +431,7 @@ export const createOne = ({ selectArgs, selections, variableDefinitions, - modelName, + modelName }); return ast; @@ -442,7 +441,7 @@ export const patchOne = ({ mutationName, operationName, mutation, - selection, + selection }: MutationASTParams): DocumentNode => { if (!mutation.properties?.input?.properties) { throw new Error(`No input field for mutation: ${mutationName}`); @@ -479,7 +478,7 @@ export const patchOne = ({ ...patchByAttrs.map((field) => t.objectField({ name: field.name, - value: t.variable({ name: field.name }), + value: t.variable({ name: field.name }) }) ), t.objectField({ @@ -490,14 +489,14 @@ export const patchOne = ({ .map((field) => t.objectField({ name: field.name, - value: t.variable({ name: field.name }), + value: t.variable({ name: field.name }) }) - ), - }), - }), - ], - }), - }), + ) + }) + }) + ] + }) + }) ]; const selections = selection @@ -510,7 +509,7 @@ export const patchOne = ({ selectArgs, selections, variableDefinitions, - modelName, + modelName }); return ast; @@ -519,7 +518,7 @@ export const patchOne = ({ export const deleteOne = ({ mutationName, operationName, - mutation, + mutation }: Omit): DocumentNode => { if (!mutation.properties?.input?.properties) { throw new Error(`No input field for mutation: ${mutationName}`); @@ -548,7 +547,7 @@ export const deleteOne = ({ } return t.variableDefinition({ variable: t.variable({ name: fieldName }), - type, + type }); } ); @@ -560,11 +559,11 @@ export const deleteOne = ({ fields: deleteAttrs.map((f) => t.objectField({ name: f.name, - value: t.variable({ name: f.name }), + value: t.variable({ name: f.name }) }) - ), - }), - }), + ) + }) + }) ]; // so we can support column select grants plugin @@ -576,7 +575,7 @@ export const deleteOne = ({ selections, useModel: false, variableDefinitions, - modelName, + modelName }); return ast; @@ -614,7 +613,7 @@ export function getSelections(selection: QueryFieldSelection[] = []): FieldNode[ const [argName, argValue] = variable; const argAst = t.argument({ name: argName, - value: getComplexValueAst(argValue), + value: getComplexValueAst(argValue) }); return argAst ? [...acc, argAst] : acc; }, @@ -627,19 +626,19 @@ export function getSelections(selection: QueryFieldSelection[] = []): FieldNode[ const selectionSet = isBelongTo ? t.selectionSet({ selections: subSelections }) : t.selectionSet({ - selections: [ - t.field({ name: 'totalCount' }), - t.field({ - name: 'nodes', - selectionSet: t.selectionSet({ selections: subSelections }), - }), - ], - }); + selections: [ + t.field({ name: 'totalCount' }), + t.field({ + name: 'nodes', + selectionSet: t.selectionSet({ selections: subSelections }) + }) + ] + }); return t.field({ name, args, - selectionSet, + selectionSet }); } else { return selectionAst(selectionDefn); @@ -670,7 +669,7 @@ function getComplexValueAst(value: unknown): ValueNode { // Handle arrays if (Array.isArray(value)) { return t.listValue({ - values: value.map((item) => getComplexValueAst(item)), + values: value.map((item) => getComplexValueAst(item)) }); } @@ -681,9 +680,9 @@ function getComplexValueAst(value: unknown): ValueNode { fields: Object.entries(obj).map(([key, val]) => t.objectField({ name: key, - value: getComplexValueAst(val), + value: getComplexValueAst(val) }) - ), + ) }); } @@ -699,7 +698,7 @@ function getCreateVariablesAst( type: fieldType, isNotNull, isArray, - isArrayNotNull, + isArrayNotNull } = field; let type: TypeNode = t.namedType({ type: fieldType }); if (isNotNull) type = t.nonNullType({ type }); @@ -709,7 +708,7 @@ function getCreateVariablesAst( } return t.variableDefinition({ variable: t.variable({ name: fieldName }), - type, + type }); }); } @@ -730,14 +729,14 @@ function getUpdateVariablesAst( } return t.variableDefinition({ variable: t.variable({ name: fieldName }), - type, + type }); }); const patcherVariables: VariableDefinitionNode[] = patchers.map((patcher) => { return t.variableDefinition({ variable: t.variable({ name: patcher }), - type: t.nonNullType({ type: t.namedType({ type: 'String' }) }), + type: t.nonNullType({ type: t.namedType({ type: 'String' }) }) }); }); diff --git a/graphql/codegen/src/core/codegen/babel-ast.ts b/graphql/codegen/src/core/codegen/babel-ast.ts index 9a189b2f7..0b981d4de 100644 --- a/graphql/codegen/src/core/codegen/babel-ast.ts +++ b/graphql/codegen/src/core/codegen/babel-ast.ts @@ -9,7 +9,7 @@ import generate from '@babel/generator'; import * as t from '@babel/types'; // Re-export for convenience -export { t, generate }; +export { generate,t }; /** * Generate code from an array of statements @@ -29,7 +29,7 @@ export const commentBlock = (value: string): t.CommentBlock => { value, start: null, end: null, - loc: null, + loc: null }; }; @@ -42,7 +42,7 @@ export const commentLine = (value: string): t.CommentLine => { value, start: null, end: null, - loc: null, + loc: null }; }; diff --git a/graphql/codegen/src/core/codegen/barrel.ts b/graphql/codegen/src/core/codegen/barrel.ts index 25d5a6fa6..dc11a6843 100644 --- a/graphql/codegen/src/core/codegen/barrel.ts +++ b/graphql/codegen/src/core/codegen/barrel.ts @@ -3,18 +3,19 @@ * * Using Babel AST for generating barrel (index.ts) files with re-exports. */ -import type { CleanTable } from '../../types/schema'; import * as t from '@babel/types'; -import { generateCode, addJSDocComment } from './babel-ast'; + +import type { CleanTable } from '../../types/schema'; +import { addJSDocComment,generateCode } from './babel-ast'; +import { getOperationHookName } from './type-resolver'; import { + getCreateMutationHookName, + getDeleteMutationHookName, getListQueryHookName, getSingleQueryHookName, - getCreateMutationHookName, getUpdateMutationHookName, - getDeleteMutationHookName, - hasValidPrimaryKey, + hasValidPrimaryKey } from './utils'; -import { getOperationHookName } from './type-resolver'; /** * Helper to create export * from './module' statement @@ -46,7 +47,7 @@ export function generateQueriesBarrel(tables: CleanTable[]): string { addJSDocComment(statements[0], [ 'Query hooks barrel export', '@generated by @constructive-io/graphql-codegen', - 'DO NOT EDIT - changes will be overwritten', + 'DO NOT EDIT - changes will be overwritten' ]); } @@ -62,16 +63,16 @@ export function generateMutationsBarrel(tables: CleanTable[]): string { // Export all mutation hooks for (const table of tables) { const createHookName = getCreateMutationHookName(table); - const updateHookName = getUpdateMutationHookName(table); - const deleteHookName = getDeleteMutationHookName(table); statements.push(exportAllFrom(`./${createHookName}`)); - // Only add update/delete if they exist - if (table.query?.update !== null) { + // Only add update/delete if they exist AND table has valid PK + if (table.query?.update !== null && hasValidPrimaryKey(table)) { + const updateHookName = getUpdateMutationHookName(table); statements.push(exportAllFrom(`./${updateHookName}`)); } - if (table.query?.delete !== null) { + if (table.query?.delete !== null && hasValidPrimaryKey(table)) { + const deleteHookName = getDeleteMutationHookName(table); statements.push(exportAllFrom(`./${deleteHookName}`)); } } @@ -81,7 +82,7 @@ export function generateMutationsBarrel(tables: CleanTable[]): string { addJSDocComment(statements[0], [ 'Mutation hooks barrel export', '@generated by @constructive-io/graphql-codegen', - 'DO NOT EDIT - changes will be overwritten', + 'DO NOT EDIT - changes will be overwritten' ]); } @@ -95,7 +96,6 @@ export function generateMutationsBarrel(tables: CleanTable[]): string { * @param hasSchemaTypes - Whether schema-types.ts was generated */ export interface MainBarrelOptions { - hasSchemaTypes?: boolean; hasMutations?: boolean; /** Whether query-keys.ts was generated */ hasQueryKeys?: boolean; @@ -112,27 +112,18 @@ export function generateMainBarrel( const opts: MainBarrelOptions = options; const { - hasSchemaTypes = false, hasMutations = true, hasQueryKeys = false, hasMutationKeys = false, - hasInvalidation = false, + hasInvalidation = false } = opts; const tableNames = tables.map((tbl) => tbl.name).join(', '); const statements: t.Statement[] = []; - // Client configuration + // Client configuration (ORM wrapper with configure/getClient) statements.push(exportAllFrom('./client')); - // Entity and filter types - statements.push(exportAllFrom('./types')); - - // Schema types (input, payload, enum types) - if (hasSchemaTypes) { - statements.push(exportAllFrom('./schema-types')); - } - // Centralized query keys (for cache management) if (hasQueryKeys) { statements.push(exportAllFrom('./query-keys')); @@ -185,7 +176,7 @@ export function generateMainBarrel( ' const { mutate } = useCreateCarMutation();', ' // ...', '}', - '```', + '```' ]); } @@ -224,7 +215,7 @@ export function generateRootBarrel(options: RootBarrelOptions = {}): string { if (statements.length > 0) { addJSDocComment(statements[0], [ 'Generated SDK - auto-generated, do not edit', - '@generated by @constructive-io/graphql-codegen', + '@generated by @constructive-io/graphql-codegen' ]); } @@ -277,7 +268,7 @@ export function generateCustomQueriesBarrel( addJSDocComment(statements[0], [ 'Query hooks barrel export', '@generated by @constructive-io/graphql-codegen', - 'DO NOT EDIT - changes will be overwritten', + 'DO NOT EDIT - changes will be overwritten' ]); } @@ -302,15 +293,15 @@ export function generateCustomMutationsBarrel( exportedHooks.add(createHookName); } - // Only add update/delete if they exist - if (table.query?.update !== null) { + // Only add update/delete if they exist AND table has valid PK + if (table.query?.update !== null && hasValidPrimaryKey(table)) { const updateHookName = getUpdateMutationHookName(table); if (!exportedHooks.has(updateHookName)) { statements.push(exportAllFrom(`./${updateHookName}`)); exportedHooks.add(updateHookName); } } - if (table.query?.delete !== null) { + if (table.query?.delete !== null && hasValidPrimaryKey(table)) { const deleteHookName = getDeleteMutationHookName(table); if (!exportedHooks.has(deleteHookName)) { statements.push(exportAllFrom(`./${deleteHookName}`)); @@ -333,7 +324,7 @@ export function generateCustomMutationsBarrel( addJSDocComment(statements[0], [ 'Mutation hooks barrel export', '@generated by @constructive-io/graphql-codegen', - 'DO NOT EDIT - changes will be overwritten', + 'DO NOT EDIT - changes will be overwritten' ]); } diff --git a/graphql/codegen/src/core/codegen/client.ts b/graphql/codegen/src/core/codegen/client.ts index 809c6f513..ed5727e96 100644 --- a/graphql/codegen/src/core/codegen/client.ts +++ b/graphql/codegen/src/core/codegen/client.ts @@ -1,74 +1,39 @@ /** - * Client generator - generates client.ts with configure() and execute() + * Client generator - generates client.ts as ORM client wrapper * - * Reads from template files in the templates/ directory for proper type checking. + * Uses template-copy pattern: reads hooks-client.ts from templates/ + * and writes it to the output directory with a generated file header. */ import * as fs from 'fs'; import * as path from 'path'; -import { getGeneratedFileHeader } from './utils'; -export interface GenerateClientFileOptions { - /** - * Generate browser-compatible code using native fetch - * When true (default), uses native W3C fetch API - * When false, uses undici fetch with dispatcher support for localhost DNS resolution - * @default true - */ - browserCompatible?: boolean; -} +import { getGeneratedFileHeader } from './utils'; -/** - * Find a template file path. - * Templates are at ./templates/ relative to this file in both src/ and dist/. - */ function findTemplateFile(templateName: string): string { const templatePath = path.join(__dirname, 'templates', templateName); - if (fs.existsSync(templatePath)) { return templatePath; } - throw new Error( - `Could not find template file: ${templateName}. ` + - `Searched in: ${templatePath}` + `Could not find template file: ${templateName}. Searched in: ${templatePath}` ); } -/** - * Read a template file and replace the header with generated file header - */ function readTemplateFile(templateName: string, description: string): string { const templatePath = findTemplateFile(templateName); let content = fs.readFileSync(templatePath, 'utf-8'); - - // Replace the source file header comment with the generated file header - // Match the header pattern used in template files const headerPattern = /\/\*\*[\s\S]*?\* NOTE: This file is read at codegen time and written to output\.[\s\S]*?\*\/\n*/; - content = content.replace( headerPattern, getGeneratedFileHeader(description) + '\n' ); - return content; } /** - * Generate client.ts content - * @param options - Generation options + * Generate client.ts content - ORM client wrapper with configure/getClient */ -export function generateClientFile( - options: GenerateClientFileOptions = {} -): string { - const { browserCompatible = true } = options; - - const templateName = browserCompatible - ? 'client.browser.ts' - : 'client.node.ts'; - - return readTemplateFile( - templateName, - 'GraphQL client configuration and execution' - ); +export function generateClientFile(): string { + return readTemplateFile('hooks-client.ts', 'ORM client wrapper for React Query hooks'); } diff --git a/graphql/codegen/src/core/codegen/custom-mutations.ts b/graphql/codegen/src/core/codegen/custom-mutations.ts index 2d9a10aef..e5ceab809 100644 --- a/graphql/codegen/src/core/codegen/custom-mutations.ts +++ b/graphql/codegen/src/core/codegen/custom-mutations.ts @@ -1,35 +1,63 @@ /** - * Custom mutation hook generators for non-table operations + * Custom mutation hook generators for non-table operations (Babel AST-based) * * Generates hooks for operations discovered via schema introspection * that are NOT table CRUD operations (e.g., login, register, etc.) * + * Delegates to ORM custom mutation operations: + * getClient().mutation.operationName(args, { select }).unwrap() + * * Output structure: * mutations/ * useLoginMutation.ts * useRegisterMutation.ts * ... */ +import * as t from '@babel/types'; + import type { CleanOperation, - CleanArgument, - TypeRegistry, + TypeRegistry } from '../../types/schema'; -import * as t from '@babel/types'; -import { generateCode, addJSDocComment, typedParam, createTypedCallExpression } from './babel-ast'; -import { buildCustomMutationString } from './schema-gql-ast'; +import { asConst } from './babel-ast'; +import { + buildDefaultSelectExpr, + buildSelectionArgsCall, + callExpr, + constDecl, + createFunctionParam, + createImportDeclaration, + createSTypeParam, + createTypeReExport, + customSelectResultTypeLiteral, + destructureParamsWithSelection, + exportDeclareFunction, + exportFunction, + generateHookFileCode, + getClientCustomCallUnwrap, + objectProp, + omitType, + returnUseMutation, + selectionConfigType, + spreadObj, + sRef, + typeofRef, + typeRef, + useMutationOptionsType, + useMutationResultType, + voidStatement +} from './hooks-ast'; +import { + getSelectTypeName +} from './select-helpers'; import { - typeRefToTsType, - isTypeRequired, - getOperationHookName, - getOperationFileName, - getOperationVariablesTypeName, - getOperationResultTypeName, - getDocumentConstName, createTypeTracker, - type TypeTracker, + getOperationFileName, + getOperationHookName, + getTypeBaseName, + typeRefToTsType } from './type-resolver'; -import { getGeneratedFileHeader } from './utils'; +import { ucFirst } from './utils'; export interface GeneratedCustomMutationFile { fileName: string; @@ -47,25 +75,6 @@ export interface GenerateCustomMutationHookOptions { useCentralizedKeys?: boolean; } -interface VariablesProp { - name: string; - type: string; - optional: boolean; - docs?: string[]; -} - -function generateVariablesProperties( - args: CleanArgument[], - tracker?: TypeTracker -): VariablesProp[] { - return args.map((arg) => ({ - name: arg.name, - type: typeRefToTsType(arg.type, tracker), - optional: !isTypeRequired(arg.type), - docs: arg.description ? [arg.description] : undefined, - })); -} - export function generateCustomMutationHook( options: GenerateCustomMutationHookOptions ): GeneratedCustomMutationFile | null { @@ -90,210 +99,256 @@ function generateCustomMutationHookInternal( const { operation, typeRegistry, - maxDepth = 2, - skipQueryField = true, tableTypeNames, - useCentralizedKeys = true, + useCentralizedKeys = true } = options; const hookName = getOperationHookName(operation.name, 'mutation'); const fileName = getOperationFileName(operation.name, 'mutation'); - const variablesTypeName = getOperationVariablesTypeName(operation.name, 'mutation'); - const resultTypeName = getOperationResultTypeName(operation.name, 'mutation'); - const documentConstName = getDocumentConstName(operation.name, 'mutation'); + const varTypeName = `${ucFirst(operation.name)}Variables`; const tracker = createTypeTracker({ tableTypeNames }); - const mutationDocument = buildCustomMutationString({ - operation, - typeRegistry, - maxDepth, - skipQueryField, - }); + const hasArgs = operation.args.length > 0; + + typeRefToTsType(operation.returnType, tracker); + for (const arg of operation.args) { + typeRefToTsType(arg.type, tracker); + } + + const selectTypeName = getSelectTypeName(operation.returnType); + const payloadTypeName = getTypeBaseName(operation.returnType); + const hasSelect = !!selectTypeName && !!payloadTypeName; const statements: t.Statement[] = []; - const variablesProps = - operation.args.length > 0 - ? generateVariablesProperties(operation.args, tracker) - : []; - - const resultType = typeRefToTsType(operation.returnType, tracker); - - const schemaTypes = tracker.getImportableTypes(); - const tableTypes = tracker.getTableTypes(); - - const reactQueryImport = t.importDeclaration( - [t.importSpecifier(t.identifier('useMutation'), t.identifier('useMutation'))], - t.stringLiteral('@tanstack/react-query') - ); - statements.push(reactQueryImport); - - const reactQueryTypeImport = t.importDeclaration( - [t.importSpecifier(t.identifier('UseMutationOptions'), t.identifier('UseMutationOptions'))], - t.stringLiteral('@tanstack/react-query') - ); - reactQueryTypeImport.importKind = 'type'; - statements.push(reactQueryTypeImport); - - const clientImport = t.importDeclaration( - [t.importSpecifier(t.identifier('execute'), t.identifier('execute'))], - t.stringLiteral('../client') - ); - statements.push(clientImport); - - if (tableTypes.length > 0) { - const typesImport = t.importDeclaration( - tableTypes.map((tt) => t.importSpecifier(t.identifier(tt), t.identifier(tt))), - t.stringLiteral('../types') - ); - typesImport.importKind = 'type'; - statements.push(typesImport); - } + // Imports + statements.push(createImportDeclaration('@tanstack/react-query', ['useMutation'])); + statements.push(createImportDeclaration('@tanstack/react-query', ['UseMutationOptions', 'UseMutationResult'], true)); + statements.push(createImportDeclaration('../client', ['getClient'])); + statements.push(createImportDeclaration('../selection', ['buildSelectionArgs'])); + statements.push(createImportDeclaration('../selection', ['SelectionConfig'], true)); - if (schemaTypes.length > 0) { - const schemaTypesImport = t.importDeclaration( - schemaTypes.map((st) => t.importSpecifier(t.identifier(st), t.identifier(st))), - t.stringLiteral('../schema-types') - ); - schemaTypesImport.importKind = 'type'; - statements.push(schemaTypesImport); + if (useCentralizedKeys) { + statements.push(createImportDeclaration('../mutation-keys', ['customMutationKeys'])); } - if (useCentralizedKeys) { - const mutationKeyImport = t.importDeclaration( - [t.importSpecifier(t.identifier('customMutationKeys'), t.identifier('customMutationKeys'))], - t.stringLiteral('../mutation-keys') - ); - statements.push(mutationKeyImport); + if (hasArgs) { + statements.push(createImportDeclaration('../../orm/mutation', [varTypeName], true)); } - const mutationDocConst = t.variableDeclaration('const', [ - t.variableDeclarator( - t.identifier(documentConstName), - t.templateLiteral( - [t.templateElement({ raw: '\n' + mutationDocument, cooked: '\n' + mutationDocument }, true)], - [] - ) - ), - ]); - const mutationDocExport = t.exportNamedDeclaration(mutationDocConst); - addJSDocComment(mutationDocExport, ['GraphQL mutation document']); - statements.push(mutationDocExport); - - if (operation.args.length > 0) { - const variablesInterfaceProps = variablesProps.map((vp) => { - const prop = t.tsPropertySignature( - t.identifier(vp.name), - t.tsTypeAnnotation(t.tsTypeReference(t.identifier(vp.type))) - ); - prop.optional = vp.optional; - return prop; - }); - const variablesInterface = t.tsInterfaceDeclaration( - t.identifier(variablesTypeName), - null, - null, - t.tsInterfaceBody(variablesInterfaceProps) - ); - statements.push(t.exportNamedDeclaration(variablesInterface)); + const inputTypeImports: string[] = []; + if (hasSelect) { + inputTypeImports.push(selectTypeName!); + inputTypeImports.push(payloadTypeName!); + } else { + for (const refType of tracker.referencedTypes) { + if (!inputTypeImports.includes(refType)) { + inputTypeImports.push(refType); + } + } + } + if (inputTypeImports.length > 0) { + statements.push(createImportDeclaration('../../orm/input-types', inputTypeImports, true)); } - const resultInterfaceBody = t.tsInterfaceBody([ - t.tsPropertySignature( - t.identifier(operation.name), - t.tsTypeAnnotation(t.tsTypeReference(t.identifier(resultType))) - ), - ]); - const resultInterface = t.tsInterfaceDeclaration( - t.identifier(resultTypeName), - null, - null, - resultInterfaceBody - ); - statements.push(t.exportNamedDeclaration(resultInterface)); + if (hasSelect) { + statements.push(createImportDeclaration('../../orm/select-types', ['InferSelectResult', 'StrictSelect'], true)); + } - const hasArgs = operation.args.length > 0; + // Re-exports + if (hasArgs) { + statements.push(createTypeReExport([varTypeName], '../../orm/mutation')); + } + if (hasSelect) { + statements.push(createTypeReExport([selectTypeName!], '../../orm/input-types')); + } - const hookBodyStatements: t.Statement[] = []; - const mutationOptions: (t.ObjectProperty | t.SpreadElement)[] = []; + // Default select + if (hasSelect) { + statements.push(constDecl('defaultSelect', asConst(buildDefaultSelectExpr(payloadTypeName!, typeRegistry)))); + } - if (useCentralizedKeys) { - mutationOptions.push( - t.objectProperty( - t.identifier('mutationKey'), - t.callExpression( - t.memberExpression(t.identifier('customMutationKeys'), t.identifier(operation.name)), - [] + // Hook + if (hasSelect) { + const mutationVarType: t.TSType = hasArgs ? typeRef(varTypeName) : t.tsVoidKeyword(); + + const selectedResultType = (sel: t.TSType) => + customSelectResultTypeLiteral(operation.name, operation.returnType, payloadTypeName!, sel); + + // Overload 1: with selection.fields + const o1ParamType = t.tsIntersectionType([ + t.tsTypeLiteral([ + t.tsPropertySignature( + t.identifier('selection'), + t.tsTypeAnnotation( + t.tsParenthesizedType( + t.tsIntersectionType([ + t.tsTypeLiteral([ + t.tsPropertySignature(t.identifier('fields'), t.tsTypeAnnotation(sRef())) + ]), + typeRef('StrictSelect', [sRef(), typeRef(selectTypeName!)]) + ]) + ) + ) ) + ]), + useMutationOptionsType(selectedResultType(sRef()), mutationVarType) + ]); + statements.push( + exportDeclareFunction( + hookName, + createSTypeParam(selectTypeName!), + [createFunctionParam('params', o1ParamType)], + useMutationResultType(selectedResultType(sRef()), mutationVarType) ) ); - } - if (hasArgs) { - mutationOptions.push( - t.objectProperty( - t.identifier('mutationFn'), - t.arrowFunctionExpression( - [typedParam('variables', t.tsTypeReference(t.identifier(variablesTypeName)))], - createTypedCallExpression( - t.identifier('execute'), - [t.identifier(documentConstName), t.identifier('variables')], - [ - t.tsTypeReference(t.identifier(resultTypeName)), - t.tsTypeReference(t.identifier(variablesTypeName)), - ] - ) - ) + // Overload 2: without selection.fields + const o2SelectionProp = (() => { + const innerFieldsProp = t.tsPropertySignature( + t.identifier('fields'), + t.tsTypeAnnotation(t.tsUndefinedKeyword()) + ); + innerFieldsProp.optional = true; + const selProp = t.tsPropertySignature( + t.identifier('selection'), + t.tsTypeAnnotation(t.tsParenthesizedType(t.tsTypeLiteral([innerFieldsProp]))) + ); + selProp.optional = true; + return selProp; + })(); + const o2ParamType = t.tsIntersectionType([ + t.tsTypeLiteral([o2SelectionProp]), + useMutationOptionsType(selectedResultType(typeofRef('defaultSelect')), mutationVarType) + ]); + statements.push( + exportDeclareFunction( + hookName, + null, + [createFunctionParam('params', o2ParamType, true)], + useMutationResultType(selectedResultType(typeofRef('defaultSelect')), mutationVarType) ) ); - } else { - mutationOptions.push( - t.objectProperty( - t.identifier('mutationFn'), - t.arrowFunctionExpression( - [], - createTypedCallExpression( - t.identifier('execute'), - [t.identifier(documentConstName)], - [t.tsTypeReference(t.identifier(resultTypeName))] - ) + + // Implementation + const implSelProp = t.tsPropertySignature( + t.identifier('selection'), + t.tsTypeAnnotation(selectionConfigType(typeRef(selectTypeName!))) + ); + implSelProp.optional = true; + const implParamType = t.tsIntersectionType([ + t.tsTypeLiteral([implSelProp]), + omitType( + typeRef('UseMutationOptions', [t.tsAnyKeyword(), typeRef('Error'), mutationVarType]), + ['mutationFn'] + ) + ]); + + const body: t.Statement[] = []; + body.push(buildSelectionArgsCall(selectTypeName!)); + body.push(destructureParamsWithSelection('mutationOptions')); + body.push(voidStatement('_selection')); + + const mutationKeyExpr = useCentralizedKeys + ? callExpr( + t.memberExpression(t.identifier('customMutationKeys'), t.identifier(operation.name)), + [] + ) + : undefined; + + const selectExpr = t.tsAsExpression( + t.parenthesizedExpression( + t.logicalExpression( + '??', + t.optionalMemberExpression(t.identifier('args'), t.identifier('select'), false, true), + t.identifier('defaultSelect') ) + ), + typeRef(selectTypeName!) + ); + const selectObj = t.objectExpression([objectProp('select', selectExpr)]); + + let mutationFnExpr: t.Expression; + if (hasArgs) { + const variablesParam = createFunctionParam('variables', typeRef(varTypeName)); + mutationFnExpr = t.arrowFunctionExpression( + [variablesParam], + getClientCustomCallUnwrap('mutation', operation.name, [t.identifier('variables')], selectObj) + ); + } else { + mutationFnExpr = t.arrowFunctionExpression( + [], + getClientCustomCallUnwrap('mutation', operation.name, [], selectObj) + ); + } + + body.push( + returnUseMutation( + mutationFnExpr, + [spreadObj(t.identifier('mutationOptions'))], + mutationKeyExpr ) ); - } - mutationOptions.push(t.spreadElement(t.identifier('options'))); + statements.push(exportFunction(hookName, null, [createFunctionParam('params', implParamType, true)], body)); + } else { + // Without select: simple hook (scalar return type) + const resultTypeStr = typeRefToTsType(operation.returnType, tracker); + const resultTypeLiteral = t.tsTypeLiteral([ + t.tsPropertySignature( + t.identifier(operation.name), + t.tsTypeAnnotation(typeRef(resultTypeStr)) + ) + ]); + const mutationVarType: t.TSType = hasArgs ? typeRef(varTypeName) : t.tsVoidKeyword(); - hookBodyStatements.push( - t.returnStatement( - t.callExpression(t.identifier('useMutation'), [t.objectExpression(mutationOptions)]) - ) - ); + const optionsType = omitType( + typeRef('UseMutationOptions', [resultTypeLiteral, typeRef('Error'), mutationVarType]), + ['mutationFn'] + ); - const optionsType = hasArgs - ? `Omit, 'mutationFn'>` - : `Omit, 'mutationFn'>`; + const body: t.Statement[] = []; + body.push(constDecl('mutationOptions', t.logicalExpression('??', t.identifier('params'), t.objectExpression([])))); - const optionsParam = t.identifier('options'); - optionsParam.optional = true; - optionsParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier(optionsType))); + const mutationKeyExpr = useCentralizedKeys + ? callExpr( + t.memberExpression(t.identifier('customMutationKeys'), t.identifier(operation.name)), + [] + ) + : undefined; + + let mutationFnExpr: t.Expression; + if (hasArgs) { + const variablesParam = createFunctionParam('variables', typeRef(varTypeName)); + mutationFnExpr = t.arrowFunctionExpression( + [variablesParam], + getClientCustomCallUnwrap('mutation', operation.name, [t.identifier('variables')]) + ); + } else { + mutationFnExpr = t.arrowFunctionExpression( + [], + getClientCustomCallUnwrap('mutation', operation.name, []) + ); + } - const hookFunc = t.functionDeclaration( - t.identifier(hookName), - [optionsParam], - t.blockStatement(hookBodyStatements) - ); - const hookExport = t.exportNamedDeclaration(hookFunc); - statements.push(hookExport); + body.push( + returnUseMutation( + mutationFnExpr, + [spreadObj(t.identifier('mutationOptions'))], + mutationKeyExpr + ) + ); + + statements.push(exportFunction(hookName, null, [createFunctionParam('params', optionsType, true)], body)); + } - const code = generateCode(statements); - const content = getGeneratedFileHeader(`Custom mutation hook for ${operation.name}`) + '\n\n' + code; + const content = generateHookFileCode(`Custom mutation hook for ${operation.name}`, statements); return { fileName, content, - operationName: operation.name, + operationName: operation.name }; } @@ -317,7 +372,7 @@ export function generateAllCustomMutationHooks( skipQueryField = true, reactQueryEnabled = true, tableTypeNames, - useCentralizedKeys = true, + useCentralizedKeys = true } = options; return operations @@ -330,7 +385,7 @@ export function generateAllCustomMutationHooks( skipQueryField, reactQueryEnabled, tableTypeNames, - useCentralizedKeys, + useCentralizedKeys }) ) .filter((result): result is GeneratedCustomMutationFile => result !== null); diff --git a/graphql/codegen/src/core/codegen/custom-queries.ts b/graphql/codegen/src/core/codegen/custom-queries.ts index daefb0eb0..b94eb1747 100644 --- a/graphql/codegen/src/core/codegen/custom-queries.ts +++ b/graphql/codegen/src/core/codegen/custom-queries.ts @@ -1,36 +1,71 @@ /** - * Custom query hook generators for non-table operations + * Custom query hook generators for non-table operations (Babel AST-based) * * Generates hooks for operations discovered via schema introspection * that are NOT table CRUD operations (e.g., currentUser, nodeById, etc.) * + * Delegates to ORM custom query operations: + * getClient().query.operationName(args, { select }).unwrap() + * * Output structure: * queries/ * useCurrentUserQuery.ts * useNodeQuery.ts * ... */ +import * as t from '@babel/types'; + import type { CleanOperation, - CleanArgument, - TypeRegistry, + TypeRegistry } from '../../types/schema'; -import * as t from '@babel/types'; -import { generateCode, addJSDocComment, typedParam, createTypedCallExpression } from './babel-ast'; -import { buildCustomQueryString } from './schema-gql-ast'; +import { asConst } from './babel-ast'; import { - typeRefToTsType, - isTypeRequired, - getOperationHookName, + addJSDocComment, + buildDefaultSelectExpr, + buildSelectionArgsCall, + callExpr, + constDecl, + createFunctionParam, + createImportDeclaration, + createSAndTDataTypeParams, + createSTypeParam, + createTDataTypeParam, + createTypeReExport, + customSelectResultTypeLiteral, + destructureParamsWithSelection, + exportAsyncDeclareFunction, + exportAsyncFunction, + exportDeclareFunction, + exportFunction, + generateHookFileCode, + getClientCustomCallUnwrap, + objectProp, + omitType, + returnUseQuery, + selectionConfigType, + spreadObj, + sRef, + typeofRef, + typeRef, + useQueryOptionsImplType, + useQueryOptionsType, + voidStatement, + wrapInferSelectResultType +} from './hooks-ast'; +import { + getSelectTypeName +} from './select-helpers'; +import { + createTypeTracker, getOperationFileName, - getOperationVariablesTypeName, - getOperationResultTypeName, - getDocumentConstName, + getOperationHookName, getQueryKeyName, - createTypeTracker, - type TypeTracker, + getTypeBaseName, + isTypeRequired, + typeRefToTsType } from './type-resolver'; -import { ucFirst, getGeneratedFileHeader } from './utils'; +import { ucFirst } from './utils'; export interface GeneratedCustomQueryFile { fileName: string; @@ -48,497 +83,620 @@ export interface GenerateCustomQueryHookOptions { useCentralizedKeys?: boolean; } -interface VariablesProp { - name: string; - type: string; - optional: boolean; - docs?: string[]; -} - -function generateVariablesProperties( - args: CleanArgument[], - tracker?: TypeTracker -): VariablesProp[] { - return args.map((arg) => ({ - name: arg.name, - type: typeRefToTsType(arg.type, tracker), - optional: !isTypeRequired(arg.type), - docs: arg.description ? [arg.description] : undefined, - })); -} - export function generateCustomQueryHook( options: GenerateCustomQueryHookOptions ): GeneratedCustomQueryFile { const { operation, typeRegistry, - maxDepth = 2, - skipQueryField = true, reactQueryEnabled = true, tableTypeNames, - useCentralizedKeys = true, + useCentralizedKeys = true } = options; const hookName = getOperationHookName(operation.name, 'query'); const fileName = getOperationFileName(operation.name, 'query'); - const variablesTypeName = getOperationVariablesTypeName(operation.name, 'query'); - const resultTypeName = getOperationResultTypeName(operation.name, 'query'); - const documentConstName = getDocumentConstName(operation.name, 'query'); const queryKeyName = getQueryKeyName(operation.name); + const varTypeName = `${ucFirst(operation.name)}Variables`; const tracker = createTypeTracker({ tableTypeNames }); - const queryDocument = buildCustomQueryString({ - operation, - typeRegistry, - maxDepth, - skipQueryField, - }); - - const statements: t.Statement[] = []; - - const variablesProps = - operation.args.length > 0 - ? generateVariablesProperties(operation.args, tracker) - : []; + const hasArgs = operation.args.length > 0; + const hasRequiredArgs = operation.args.some((arg) => isTypeRequired(arg.type)); const resultType = typeRefToTsType(operation.returnType, tracker); + for (const arg of operation.args) { + typeRefToTsType(arg.type, tracker); + } - const schemaTypes = tracker.getImportableTypes(); - const tableTypes = tracker.getTableTypes(); + const selectTypeName = getSelectTypeName(operation.returnType); + const payloadTypeName = getTypeBaseName(operation.returnType); + const hasSelect = !!selectTypeName && !!payloadTypeName; + const statements: t.Statement[] = []; + + // Imports if (reactQueryEnabled) { - const reactQueryImport = t.importDeclaration( - [t.importSpecifier(t.identifier('useQuery'), t.identifier('useQuery'))], - t.stringLiteral('@tanstack/react-query') - ); - statements.push(reactQueryImport); - const reactQueryTypeImport = t.importDeclaration( - [ - t.importSpecifier(t.identifier('UseQueryOptions'), t.identifier('UseQueryOptions')), - t.importSpecifier(t.identifier('QueryClient'), t.identifier('QueryClient')), - ], - t.stringLiteral('@tanstack/react-query') - ); - reactQueryTypeImport.importKind = 'type'; - statements.push(reactQueryTypeImport); + statements.push(createImportDeclaration('@tanstack/react-query', ['useQuery'])); + statements.push(createImportDeclaration('@tanstack/react-query', ['UseQueryOptions', 'UseQueryResult', 'QueryClient'], true)); } - const clientImport = t.importDeclaration( - [t.importSpecifier(t.identifier('execute'), t.identifier('execute'))], - t.stringLiteral('../client') - ); - statements.push(clientImport); - const clientTypeImport = t.importDeclaration( - [t.importSpecifier(t.identifier('ExecuteOptions'), t.identifier('ExecuteOptions'))], - t.stringLiteral('../client') - ); - clientTypeImport.importKind = 'type'; - statements.push(clientTypeImport); + statements.push(createImportDeclaration('../client', ['getClient'])); + statements.push(createImportDeclaration('../selection', ['buildSelectionArgs'])); + statements.push(createImportDeclaration('../selection', ['SelectionConfig'], true)); - if (tableTypes.length > 0) { - const typesImport = t.importDeclaration( - tableTypes.map((tt) => t.importSpecifier(t.identifier(tt), t.identifier(tt))), - t.stringLiteral('../types') - ); - typesImport.importKind = 'type'; - statements.push(typesImport); + if (useCentralizedKeys) { + statements.push(createImportDeclaration('../query-keys', ['customQueryKeys'])); } - if (schemaTypes.length > 0) { - const schemaTypesImport = t.importDeclaration( - schemaTypes.map((st) => t.importSpecifier(t.identifier(st), t.identifier(st))), - t.stringLiteral('../schema-types') - ); - schemaTypesImport.importKind = 'type'; - statements.push(schemaTypesImport); + if (hasArgs) { + statements.push(createImportDeclaration('../../orm/query', [varTypeName], true)); } - if (useCentralizedKeys) { - const queryKeyImport = t.importDeclaration( - [t.importSpecifier(t.identifier('customQueryKeys'), t.identifier('customQueryKeys'))], - t.stringLiteral('../query-keys') - ); - statements.push(queryKeyImport); + const inputTypeImports: string[] = []; + if (hasSelect) { + inputTypeImports.push(selectTypeName!); + inputTypeImports.push(payloadTypeName!); + } else { + const baseName = getTypeBaseName(operation.returnType); + if (baseName && !tracker.referencedTypes.has('__skip__')) { + for (const refType of tracker.referencedTypes) { + if (!inputTypeImports.includes(refType)) { + inputTypeImports.push(refType); + } + } + } + } + if (inputTypeImports.length > 0) { + statements.push(createImportDeclaration('../../orm/input-types', inputTypeImports, true)); } - const queryDocConst = t.variableDeclaration('const', [ - t.variableDeclarator( - t.identifier(documentConstName), - t.templateLiteral( - [t.templateElement({ raw: '\n' + queryDocument, cooked: '\n' + queryDocument }, true)], - [] - ) - ), - ]); - const queryDocExport = t.exportNamedDeclaration(queryDocConst); - addJSDocComment(queryDocExport, ['GraphQL query document']); - statements.push(queryDocExport); - - if (operation.args.length > 0) { - const variablesInterfaceProps = variablesProps.map((vp) => { - const prop = t.tsPropertySignature( - t.identifier(vp.name), - t.tsTypeAnnotation(t.tsTypeReference(t.identifier(vp.type))) - ); - prop.optional = vp.optional; - return prop; - }); - const variablesInterface = t.tsInterfaceDeclaration( - t.identifier(variablesTypeName), - null, - null, - t.tsInterfaceBody(variablesInterfaceProps) - ); - statements.push(t.exportNamedDeclaration(variablesInterface)); + if (hasSelect) { + statements.push(createImportDeclaration('../../orm/select-types', ['InferSelectResult', 'StrictSelect'], true)); } - const resultInterfaceBody = t.tsInterfaceBody([ - t.tsPropertySignature( - t.identifier(operation.name), - t.tsTypeAnnotation(t.tsTypeReference(t.identifier(resultType))) - ), - ]); - const resultInterface = t.tsInterfaceDeclaration( - t.identifier(resultTypeName), - null, - null, - resultInterfaceBody - ); - statements.push(t.exportNamedDeclaration(resultInterface)); + // Re-exports + if (hasArgs) { + statements.push(createTypeReExport([varTypeName], '../../orm/query')); + } + if (hasSelect) { + statements.push(createTypeReExport([selectTypeName!], '../../orm/input-types')); + } + + // Default select + if (hasSelect) { + statements.push(constDecl('defaultSelect', asConst(buildDefaultSelectExpr(payloadTypeName!, typeRegistry)))); + } + // Query key if (useCentralizedKeys) { - const queryKeyConst = t.variableDeclaration('const', [ - t.variableDeclarator( - t.identifier(queryKeyName), - t.memberExpression(t.identifier('customQueryKeys'), t.identifier(operation.name)) - ), - ]); - const queryKeyExport = t.exportNamedDeclaration(queryKeyConst); - addJSDocComment(queryKeyExport, ['Query key factory - re-exported from query-keys.ts']); - statements.push(queryKeyExport); - } else if (operation.args.length > 0) { - const queryKeyArrow = t.arrowFunctionExpression( - [typedParam('variables', t.tsTypeReference(t.identifier(variablesTypeName)), true)], - t.tsAsExpression( - t.arrayExpression([t.stringLiteral(operation.name), t.identifier('variables')]), - t.tsTypeReference(t.identifier('const')) - ) + const keyDecl = t.exportNamedDeclaration( + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier(queryKeyName), + t.memberExpression(t.identifier('customQueryKeys'), t.identifier(operation.name)) + ) + ]) ); - const queryKeyConst = t.variableDeclaration('const', [ - t.variableDeclarator(t.identifier(queryKeyName), queryKeyArrow), - ]); - const queryKeyExport = t.exportNamedDeclaration(queryKeyConst); - addJSDocComment(queryKeyExport, ['Query key factory for caching']); - statements.push(queryKeyExport); + addJSDocComment(keyDecl, ['Query key factory - re-exported from query-keys.ts']); + statements.push(keyDecl); + } else if (hasArgs) { + const keyFn = t.arrowFunctionExpression( + [createFunctionParam('variables', typeRef(varTypeName), true)], + asConst(t.arrayExpression([t.stringLiteral(operation.name), t.identifier('variables')])) + ); + const keyDecl = t.exportNamedDeclaration( + t.variableDeclaration('const', [t.variableDeclarator(t.identifier(queryKeyName), keyFn)]) + ); + addJSDocComment(keyDecl, ['Query key factory for caching']); + statements.push(keyDecl); } else { - const queryKeyArrow = t.arrowFunctionExpression( + const keyFn = t.arrowFunctionExpression( [], - t.tsAsExpression( - t.arrayExpression([t.stringLiteral(operation.name)]), - t.tsTypeReference(t.identifier('const')) - ) + asConst(t.arrayExpression([t.stringLiteral(operation.name)])) ); - const queryKeyConst = t.variableDeclaration('const', [ - t.variableDeclarator(t.identifier(queryKeyName), queryKeyArrow), - ]); - const queryKeyExport = t.exportNamedDeclaration(queryKeyConst); - addJSDocComment(queryKeyExport, ['Query key factory for caching']); - statements.push(queryKeyExport); + const keyDecl = t.exportNamedDeclaration( + t.variableDeclaration('const', [t.variableDeclarator(t.identifier(queryKeyName), keyFn)]) + ); + addJSDocComment(keyDecl, ['Query key factory for caching']); + statements.push(keyDecl); } - if (reactQueryEnabled) { - const hasArgs = operation.args.length > 0; - const hasRequiredArgs = operation.args.some((arg) => isTypeRequired(arg.type)); + // Helper to build select fallback expression + const buildSelectFallback = () => t.tsAsExpression( + t.parenthesizedExpression( + t.logicalExpression( + '??', + t.optionalMemberExpression(t.identifier('args'), t.identifier('select'), false, true), + t.identifier('defaultSelect') + ) + ), + typeRef(selectTypeName!) + ); - const hookBodyStatements: t.Statement[] = []; - const useQueryOptions: (t.ObjectProperty | t.SpreadElement)[] = []; + // Helper to build query key call expression + const buildQueryKeyCall = (withVars: boolean) => { + if (useCentralizedKeys) { + return withVars + ? callExpr(t.identifier(queryKeyName), [t.identifier('variables')]) + : callExpr(t.identifier(queryKeyName), []); + } + return withVars + ? callExpr(t.identifier(queryKeyName), [t.identifier('variables')]) + : callExpr(t.identifier(queryKeyName), []); + }; - if (hasArgs) { - useQueryOptions.push( - t.objectProperty( - t.identifier('queryKey'), - t.callExpression(t.identifier(queryKeyName), [t.identifier('variables')]) - ) + // Helper to build the fields+StrictSelect intersection type + const fieldsSelectionType = (s: t.TSType) => t.tsParenthesizedType( + t.tsIntersectionType([ + t.tsTypeLiteral([t.tsPropertySignature(t.identifier('fields'), t.tsTypeAnnotation(s))]), + typeRef('StrictSelect', [s, typeRef(selectTypeName!)]) + ]) + ); + + // Helper for { fields?: undefined } + const noFieldsType = () => { + const fp = t.tsPropertySignature(t.identifier('fields'), t.tsTypeAnnotation(t.tsUndefinedKeyword())); + fp.optional = true; + return t.tsParenthesizedType(t.tsTypeLiteral([fp])); + }; + + const selectedResultType = (sel: t.TSType) => + customSelectResultTypeLiteral(operation.name, operation.returnType, payloadTypeName!, sel); + + // Hook + if (reactQueryEnabled) { + const description = operation.description || `Query hook for ${operation.name}`; + const argNames = operation.args.map((a) => a.name).join(', '); + const exampleCall = hasArgs ? `${hookName}({ ${argNames} })` : `${hookName}()`; + + if (hasSelect) { + // Overload 1: with selection.fields + const o1Props: t.TSPropertySignature[] = []; + if (hasArgs) { + const varType = hasRequiredArgs + ? typeRef(varTypeName) + : t.tsUnionType([typeRef(varTypeName), t.tsUndefinedKeyword()]); + o1Props.push(t.tsPropertySignature(t.identifier('variables'), t.tsTypeAnnotation(varType))); + } + o1Props.push(t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(fieldsSelectionType(sRef())))); + const o1ParamType = t.tsIntersectionType([ + t.tsTypeLiteral(o1Props), + omitType(typeRef('UseQueryOptions', [selectedResultType(sRef()), typeRef('Error'), typeRef('TData')]), ['queryKey', 'queryFn']) + ]); + const o1 = exportDeclareFunction( + hookName, + createSAndTDataTypeParams(selectTypeName!, selectedResultType(sRef())), + [createFunctionParam('params', o1ParamType)], + typeRef('UseQueryResult', [typeRef('TData')]) ); - useQueryOptions.push( - t.objectProperty( - t.identifier('queryFn'), - t.arrowFunctionExpression( - [], - createTypedCallExpression( - t.identifier('execute'), - [t.identifier(documentConstName), t.identifier('variables')], - [ - t.tsTypeReference(t.identifier(resultTypeName)), - t.tsTypeReference(t.identifier(variablesTypeName)), - ] - ) - ) + addJSDocComment(o1, [ + description, + '', + '@example', + '```tsx', + `const { data, isLoading } = ${exampleCall};`, + '', + `if (data?.${operation.name}) {`, + ` console.log(data.${operation.name});`, + '}', + '```' + ]); + statements.push(o1); + + // Overload 2: without fields + const o2Props: t.TSPropertySignature[] = []; + if (hasArgs) { + const varProp = t.tsPropertySignature(t.identifier('variables'), t.tsTypeAnnotation(typeRef(varTypeName))); + if (!hasRequiredArgs) varProp.optional = true; + o2Props.push(varProp); + } + const selProp = t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(noFieldsType())); + selProp.optional = true; + o2Props.push(selProp); + const o2ParamType = t.tsIntersectionType([ + t.tsTypeLiteral(o2Props), + omitType(typeRef('UseQueryOptions', [selectedResultType(typeofRef('defaultSelect')), typeRef('Error'), typeRef('TData')]), ['queryKey', 'queryFn']) + ]); + const o2Param = createFunctionParam('params', o2ParamType, !hasRequiredArgs); + statements.push( + exportDeclareFunction( + hookName, + createTDataTypeParam(selectedResultType(typeofRef('defaultSelect'))), + [o2Param], + typeRef('UseQueryResult', [typeRef('TData')]) ) ); - if (hasRequiredArgs) { - useQueryOptions.push( - t.objectProperty( - t.identifier('enabled'), - t.logicalExpression( - '&&', - t.unaryExpression('!', t.unaryExpression('!', t.identifier('variables'))), - t.binaryExpression( - '!==', - t.optionalMemberExpression( - t.identifier('options'), - t.identifier('enabled'), - false, - true - ), - t.booleanLiteral(false) - ) - ) - ) - ); + + // Implementation + const implProps: t.TSPropertySignature[] = []; + if (hasArgs) { + const varProp = t.tsPropertySignature(t.identifier('variables'), t.tsTypeAnnotation(typeRef(varTypeName))); + if (!hasRequiredArgs) varProp.optional = true; + implProps.push(varProp); } - } else { - useQueryOptions.push( - t.objectProperty( - t.identifier('queryKey'), - t.callExpression(t.identifier(queryKeyName), []) - ) + const implSelProp = t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(selectionConfigType(typeRef(selectTypeName!)))); + implSelProp.optional = true; + implProps.push(implSelProp); + const implParamType = t.tsIntersectionType([ + t.tsTypeLiteral(implProps), + useQueryOptionsImplType() + ]); + const implParam = createFunctionParam('params', implParamType, !hasRequiredArgs); + + const body: t.Statement[] = []; + if (hasArgs) { + body.push(constDecl('variables', t.optionalMemberExpression(t.identifier('params'), t.identifier('variables'), false, true))); + } + body.push(buildSelectionArgsCall(selectTypeName!)); + + if (hasArgs) { + const destructPattern = t.objectPattern([ + t.objectProperty(t.identifier('variables'), t.identifier('_variables'), false, false), + t.objectProperty(t.identifier('selection'), t.identifier('_selection'), false, false), + t.restElement(t.identifier('queryOptions')) + ]); + body.push(t.variableDeclaration('const', [ + t.variableDeclarator(destructPattern, t.logicalExpression('??', t.identifier('params'), t.objectExpression([]))) + ])); + body.push(voidStatement('_variables')); + body.push(voidStatement('_selection')); + } else { + body.push(destructureParamsWithSelection('queryOptions')); + body.push(voidStatement('_selection')); + } + + const selectObj = t.objectExpression([objectProp('select', buildSelectFallback())]); + const queryFnArgs = hasArgs + ? [hasRequiredArgs ? t.tsNonNullExpression(t.identifier('variables')) : t.identifier('variables'), selectObj] + : [selectObj]; + const queryFnExpr = t.arrowFunctionExpression( + [], + getClientCustomCallUnwrap('query', operation.name, queryFnArgs as t.Expression[]) ); - useQueryOptions.push( - t.objectProperty( - t.identifier('queryFn'), - t.arrowFunctionExpression( - [], - createTypedCallExpression( - t.identifier('execute'), - [t.identifier(documentConstName)], - [t.tsTypeReference(t.identifier(resultTypeName))] - ) + + const extraProps: (t.ObjectProperty | t.SpreadElement)[] = []; + const enabledExpr = hasRequiredArgs + ? t.logicalExpression( + '&&', + t.unaryExpression('!', t.unaryExpression('!', t.identifier('variables'))), + t.binaryExpression( + '!==', + t.optionalMemberExpression(t.identifier('params'), t.identifier('enabled'), false, true), + t.booleanLiteral(false) ) ) + : undefined; + extraProps.push(spreadObj(t.identifier('queryOptions'))); + + body.push(returnUseQuery(buildQueryKeyCall(hasArgs), queryFnExpr, extraProps, enabledExpr)); + statements.push(exportFunction(hookName, null, [implParam], body)); + } else { + // Without select: simple hook (scalar return type) + const resultTypeLiteral = t.tsTypeLiteral([ + t.tsPropertySignature(t.identifier(operation.name), t.tsTypeAnnotation(typeRef(resultType))) + ]); + + const optType = omitType( + typeRef('UseQueryOptions', [resultTypeLiteral, typeRef('Error'), typeRef('TData')]), + ['queryKey', 'queryFn'] + ); + + let paramType: t.TSType; + if (hasArgs) { + const varProp = t.tsPropertySignature(t.identifier('variables'), t.tsTypeAnnotation(typeRef(varTypeName))); + if (!hasRequiredArgs) varProp.optional = true; + paramType = t.tsIntersectionType([t.tsTypeLiteral([varProp]), optType]); + } else { + paramType = optType; + } + + const implParam = createFunctionParam('params', paramType, !hasRequiredArgs); + const hookDecl = exportDeclareFunction( + hookName, + createTDataTypeParam(resultTypeLiteral), + [implParam], + typeRef('UseQueryResult', [typeRef('TData')]) + ); + addJSDocComment(hookDecl, [ + description, + '', + '@example', + '```tsx', + `const { data, isLoading } = ${exampleCall};`, + '', + `if (data?.${operation.name}) {`, + ` console.log(data.${operation.name});`, + '}', + '```' + ]); + + const body: t.Statement[] = []; + if (hasArgs) { + body.push(constDecl('variables', t.optionalMemberExpression(t.identifier('params'), t.identifier('variables'), false, true))); + const destructPattern = t.objectPattern([ + t.objectProperty(t.identifier('variables'), t.identifier('_variables'), false, false), + t.restElement(t.identifier('queryOptions')) + ]); + body.push(t.variableDeclaration('const', [ + t.variableDeclarator(destructPattern, t.logicalExpression('??', t.identifier('params'), t.objectExpression([]))) + ])); + body.push(voidStatement('_variables')); + } else { + body.push(constDecl('queryOptions', t.logicalExpression('??', t.identifier('params'), t.objectExpression([])))); + } + + const queryFnArgs = hasArgs + ? [hasRequiredArgs ? t.tsNonNullExpression(t.identifier('variables')) : t.identifier('variables')] + : []; + const queryFnExpr = t.arrowFunctionExpression( + [], + getClientCustomCallUnwrap('query', operation.name, queryFnArgs as t.Expression[]) ); + + const enabledExpr = hasRequiredArgs + ? t.logicalExpression( + '&&', + t.unaryExpression('!', t.unaryExpression('!', t.identifier('variables'))), + t.binaryExpression('!==', t.optionalMemberExpression(t.identifier('params'), t.identifier('enabled'), false, true), t.booleanLiteral(false)) + ) + : undefined; + + body.push(returnUseQuery(buildQueryKeyCall(hasArgs), queryFnExpr, [spreadObj(t.identifier('queryOptions'))], enabledExpr)); + + // We need the implementation version (not declare), with return type + statements.push(hookDecl); + statements.push(exportFunction(hookName, null, [implParam], body, typeRef('UseQueryResult', [typeRef('TData')]))); } - useQueryOptions.push(t.spreadElement(t.identifier('options'))); + } - hookBodyStatements.push( - t.returnStatement( - t.callExpression(t.identifier('useQuery'), [t.objectExpression(useQueryOptions)]) - ) - ); + // Fetch function (non-hook) + const fetchFnName = `fetch${ucFirst(operation.name)}Query`; + const fetchArgNames = operation.args.map((a) => a.name).join(', '); + const fetchExampleCall = hasArgs ? `${fetchFnName}({ ${fetchArgNames} })` : `${fetchFnName}()`; - const hookParams: t.Identifier[] = []; + if (hasSelect) { + // Overload 1: with fields + const f1Props: t.TSPropertySignature[] = []; if (hasArgs) { - hookParams.push( - typedParam('variables', t.tsTypeReference(t.identifier(variablesTypeName)), !hasRequiredArgs) - ); + const varType = hasRequiredArgs ? typeRef(varTypeName) : t.tsUnionType([typeRef(varTypeName), t.tsUndefinedKeyword()]); + f1Props.push(t.tsPropertySignature(t.identifier('variables'), t.tsTypeAnnotation(varType))); } - const optionsTypeStr = `Omit, 'queryKey' | 'queryFn'>`; - const optionsParam = t.identifier('options'); - optionsParam.optional = true; - optionsParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier(optionsTypeStr))); - hookParams.push(optionsParam); - - const hookFunc = t.functionDeclaration( - t.identifier(hookName), - hookParams, - t.blockStatement(hookBodyStatements) + f1Props.push(t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(fieldsSelectionType(sRef())))); + const f1Decl = exportAsyncDeclareFunction( + fetchFnName, + createSTypeParam(selectTypeName!), + [createFunctionParam('params', t.tsTypeLiteral(f1Props))], + typeRef('Promise', [selectedResultType(sRef())]) ); - const hookExport = t.exportNamedDeclaration(hookFunc); - - const description = operation.description || `Query hook for ${operation.name}`; - const argNames = operation.args.map((a) => a.name).join(', '); - const exampleCall = hasArgs ? `${hookName}({ ${argNames} })` : `${hookName}()`; - addJSDocComment(hookExport, [ - description, + addJSDocComment(f1Decl, [ + `Fetch ${operation.name} without React hooks`, '', '@example', - '```tsx', - `const { data, isLoading } = ${exampleCall};`, - '', - `if (data?.${operation.name}) {`, - ` console.log(data.${operation.name});`, - '}', - '```', + '```ts', + `const data = await ${fetchExampleCall};`, + '```' ]); - statements.push(hookExport); - } - - const fetchFnName = `fetch${ucFirst(operation.name)}Query`; - const hasArgs = operation.args.length > 0; - const hasRequiredArgs = operation.args.some((arg) => isTypeRequired(arg.type)); + statements.push(f1Decl); - const fetchBodyStatements: t.Statement[] = []; - if (hasArgs) { - fetchBodyStatements.push( - t.returnStatement( - createTypedCallExpression( - t.identifier('execute'), - [t.identifier(documentConstName), t.identifier('variables'), t.identifier('options')], - [ - t.tsTypeReference(t.identifier(resultTypeName)), - t.tsTypeReference(t.identifier(variablesTypeName)), - ] - ) - ) - ); - } else { - fetchBodyStatements.push( - t.returnStatement( - createTypedCallExpression( - t.identifier('execute'), - [t.identifier(documentConstName), t.identifier('undefined'), t.identifier('options')], - [t.tsTypeReference(t.identifier(resultTypeName))] - ) + // Overload 2: without fields + const f2Props: t.TSPropertySignature[] = []; + if (hasArgs) { + const varProp = t.tsPropertySignature(t.identifier('variables'), t.tsTypeAnnotation(typeRef(varTypeName))); + if (!hasRequiredArgs) varProp.optional = true; + f2Props.push(varProp); + } + const f2SelProp = t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(noFieldsType())); + f2SelProp.optional = true; + f2Props.push(f2SelProp); + statements.push( + exportAsyncDeclareFunction( + fetchFnName, + null, + [createFunctionParam('params', t.tsTypeLiteral(f2Props), !hasRequiredArgs)], + typeRef('Promise', [selectedResultType(typeofRef('defaultSelect'))]) ) ); - } - const fetchParams: t.Identifier[] = []; - if (hasArgs) { - fetchParams.push( - typedParam('variables', t.tsTypeReference(t.identifier(variablesTypeName)), !hasRequiredArgs) - ); - } - fetchParams.push(typedParam('options', t.tsTypeReference(t.identifier('ExecuteOptions')), true)); + // Implementation + const fImplProps: t.TSPropertySignature[] = []; + if (hasArgs) { + const varProp = t.tsPropertySignature(t.identifier('variables'), t.tsTypeAnnotation(typeRef(varTypeName))); + if (!hasRequiredArgs) varProp.optional = true; + fImplProps.push(varProp); + } + const fImplSelProp = t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(selectionConfigType(typeRef(selectTypeName!)))); + fImplSelProp.optional = true; + fImplProps.push(fImplSelProp); - const fetchFunc = t.functionDeclaration( - t.identifier(fetchFnName), - fetchParams, - t.blockStatement(fetchBodyStatements) - ); - fetchFunc.async = true; - fetchFunc.returnType = t.tsTypeAnnotation( - t.tsTypeReference( - t.identifier('Promise'), - t.tsTypeParameterInstantiation([t.tsTypeReference(t.identifier(resultTypeName))]) - ) - ); - const fetchExport = t.exportNamedDeclaration(fetchFunc); - - const argNames = operation.args.map((a) => a.name).join(', '); - const fetchExampleCall = hasArgs ? `${fetchFnName}({ ${argNames} })` : `${fetchFnName}()`; - addJSDocComment(fetchExport, [ - `Fetch ${operation.name} without React hooks`, - '', - '@example', - '```ts', - `const data = await ${fetchExampleCall};`, - '```', - ]); - statements.push(fetchExport); + const fBody: t.Statement[] = []; + if (hasArgs) { + fBody.push(constDecl('variables', t.optionalMemberExpression(t.identifier('params'), t.identifier('variables'), false, true))); + } + fBody.push(buildSelectionArgsCall(selectTypeName!)); + const selectObj = t.objectExpression([objectProp('select', buildSelectFallback())]); + const fCallArgs = hasArgs + ? [hasRequiredArgs ? t.tsNonNullExpression(t.identifier('variables')) : t.identifier('variables'), selectObj] + : [selectObj]; + fBody.push(t.returnStatement(getClientCustomCallUnwrap('query', operation.name, fCallArgs as t.Expression[]))); + statements.push(exportAsyncFunction(fetchFnName, null, [createFunctionParam('params', t.tsTypeLiteral(fImplProps), !hasRequiredArgs)], fBody)); + } else { + const fBody: t.Statement[] = []; + if (hasArgs) { + const fProps: t.TSPropertySignature[] = []; + const varProp = t.tsPropertySignature(t.identifier('variables'), t.tsTypeAnnotation(typeRef(varTypeName))); + if (!hasRequiredArgs) varProp.optional = true; + fProps.push(varProp); + fBody.push(constDecl('variables', t.optionalMemberExpression(t.identifier('params'), t.identifier('variables'), false, true))); + const fCallArgs = hasRequiredArgs ? [t.tsNonNullExpression(t.identifier('variables'))] : [t.identifier('variables')]; + fBody.push(t.returnStatement(getClientCustomCallUnwrap('query', operation.name, fCallArgs as t.Expression[]))); + const fDecl = exportAsyncFunction(fetchFnName, null, [createFunctionParam('params', t.tsTypeLiteral(fProps), !hasRequiredArgs)], fBody); + addJSDocComment(fDecl, [ + `Fetch ${operation.name} without React hooks`, + '', + '@example', + '```ts', + `const data = await ${fetchExampleCall};`, + '```' + ]); + statements.push(fDecl); + } else { + fBody.push(t.returnStatement(getClientCustomCallUnwrap('query', operation.name, []))); + const fDecl = exportAsyncFunction(fetchFnName, null, [], fBody); + addJSDocComment(fDecl, [ + `Fetch ${operation.name} without React hooks`, + '', + '@example', + '```ts', + `const data = await ${fetchExampleCall};`, + '```' + ]); + statements.push(fDecl); + } + } + // Prefetch function if (reactQueryEnabled) { const prefetchFnName = `prefetch${ucFirst(operation.name)}Query`; + const prefetchArgNames = operation.args.map((a) => a.name).join(', '); + const prefetchExampleCall = hasArgs + ? `${prefetchFnName}(queryClient, { ${prefetchArgNames} })` + : `${prefetchFnName}(queryClient)`; - const prefetchBodyStatements: t.Statement[] = []; - const prefetchQueryOptions: t.ObjectProperty[] = []; - - if (hasArgs) { - prefetchQueryOptions.push( - t.objectProperty( - t.identifier('queryKey'), - t.callExpression(t.identifier(queryKeyName), [t.identifier('variables')]) - ) + if (hasSelect) { + // Overload 1: with fields + const p1Props: t.TSPropertySignature[] = []; + if (hasArgs) { + const varType = hasRequiredArgs ? typeRef(varTypeName) : t.tsUnionType([typeRef(varTypeName), t.tsUndefinedKeyword()]); + p1Props.push(t.tsPropertySignature(t.identifier('variables'), t.tsTypeAnnotation(varType))); + } + p1Props.push(t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(fieldsSelectionType(sRef())))); + const p1Decl = exportAsyncDeclareFunction( + prefetchFnName, + createSTypeParam(selectTypeName!), + [createFunctionParam('queryClient', typeRef('QueryClient')), createFunctionParam('params', t.tsTypeLiteral(p1Props))], + typeRef('Promise', [t.tsVoidKeyword()]) ); - prefetchQueryOptions.push( - t.objectProperty( - t.identifier('queryFn'), - t.arrowFunctionExpression( - [], - createTypedCallExpression( - t.identifier('execute'), - [t.identifier(documentConstName), t.identifier('variables'), t.identifier('options')], - [ - t.tsTypeReference(t.identifier(resultTypeName)), - t.tsTypeReference(t.identifier(variablesTypeName)), - ] - ) - ) + addJSDocComment(p1Decl, [ + `Prefetch ${operation.name} for SSR or cache warming`, + '', + '@example', + '```ts', + `await ${prefetchExampleCall};`, + '```' + ]); + statements.push(p1Decl); + + // Overload 2: without fields + const p2Props: t.TSPropertySignature[] = []; + if (hasArgs) { + const varProp = t.tsPropertySignature(t.identifier('variables'), t.tsTypeAnnotation(typeRef(varTypeName))); + if (!hasRequiredArgs) varProp.optional = true; + p2Props.push(varProp); + } + const p2SelProp = t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(noFieldsType())); + p2SelProp.optional = true; + p2Props.push(p2SelProp); + statements.push( + exportAsyncDeclareFunction( + prefetchFnName, + null, + [createFunctionParam('queryClient', typeRef('QueryClient')), createFunctionParam('params', t.tsTypeLiteral(p2Props), !hasRequiredArgs)], + typeRef('Promise', [t.tsVoidKeyword()]) ) ); - } else { - prefetchQueryOptions.push( - t.objectProperty( - t.identifier('queryKey'), - t.callExpression(t.identifier(queryKeyName), []) - ) + + // Implementation + const pImplProps: t.TSPropertySignature[] = []; + if (hasArgs) { + const varProp = t.tsPropertySignature(t.identifier('variables'), t.tsTypeAnnotation(typeRef(varTypeName))); + if (!hasRequiredArgs) varProp.optional = true; + pImplProps.push(varProp); + } + const pImplSelProp = t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(selectionConfigType(typeRef(selectTypeName!)))); + pImplSelProp.optional = true; + pImplProps.push(pImplSelProp); + + const pBody: t.Statement[] = []; + if (hasArgs) { + pBody.push(constDecl('variables', t.optionalMemberExpression(t.identifier('params'), t.identifier('variables'), false, true))); + } + pBody.push(buildSelectionArgsCall(selectTypeName!)); + const selectObj = t.objectExpression([objectProp('select', buildSelectFallback())]); + const pCallArgs = hasArgs + ? [hasRequiredArgs ? t.tsNonNullExpression(t.identifier('variables')) : t.identifier('variables'), selectObj] + : [selectObj]; + const prefetchQueryCall = callExpr( + t.memberExpression(t.identifier('queryClient'), t.identifier('prefetchQuery')), + [t.objectExpression([ + objectProp('queryKey', buildQueryKeyCall(hasArgs)), + objectProp('queryFn', t.arrowFunctionExpression([], getClientCustomCallUnwrap('query', operation.name, pCallArgs as t.Expression[]))) + ])] ); - prefetchQueryOptions.push( - t.objectProperty( - t.identifier('queryFn'), - t.arrowFunctionExpression( - [], - createTypedCallExpression( - t.identifier('execute'), - [t.identifier(documentConstName), t.identifier('undefined'), t.identifier('options')], - [t.tsTypeReference(t.identifier(resultTypeName))] - ) - ) + pBody.push(t.expressionStatement(t.awaitExpression(prefetchQueryCall))); + statements.push( + exportAsyncFunction( + prefetchFnName, + null, + [createFunctionParam('queryClient', typeRef('QueryClient')), createFunctionParam('params', t.tsTypeLiteral(pImplProps), !hasRequiredArgs)], + pBody, + t.tsVoidKeyword() ) ); - } - - prefetchBodyStatements.push( - t.expressionStatement( - t.awaitExpression( - t.callExpression( - t.memberExpression(t.identifier('queryClient'), t.identifier('prefetchQuery')), - [t.objectExpression(prefetchQueryOptions)] - ) - ) - ) - ); + } else { + // Without select + const pBody: t.Statement[] = []; + const pParams: t.Identifier[] = [createFunctionParam('queryClient', typeRef('QueryClient'))]; + + if (hasArgs) { + const pProps: t.TSPropertySignature[] = []; + const varProp = t.tsPropertySignature(t.identifier('variables'), t.tsTypeAnnotation(typeRef(varTypeName))); + if (!hasRequiredArgs) varProp.optional = true; + pProps.push(varProp); + pParams.push(createFunctionParam('params', t.tsTypeLiteral(pProps), !hasRequiredArgs)); + pBody.push(constDecl('variables', t.optionalMemberExpression(t.identifier('params'), t.identifier('variables'), false, true))); + const pCallArgs = hasRequiredArgs ? [t.tsNonNullExpression(t.identifier('variables'))] : [t.identifier('variables')]; + const prefetchQueryCall = callExpr( + t.memberExpression(t.identifier('queryClient'), t.identifier('prefetchQuery')), + [t.objectExpression([ + objectProp('queryKey', buildQueryKeyCall(true)), + objectProp('queryFn', t.arrowFunctionExpression([], getClientCustomCallUnwrap('query', operation.name, pCallArgs as t.Expression[]))) + ])] + ); + pBody.push(t.expressionStatement(t.awaitExpression(prefetchQueryCall))); + } else { + const prefetchQueryCall = callExpr( + t.memberExpression(t.identifier('queryClient'), t.identifier('prefetchQuery')), + [t.objectExpression([ + objectProp('queryKey', buildQueryKeyCall(false)), + objectProp('queryFn', t.arrowFunctionExpression([], getClientCustomCallUnwrap('query', operation.name, []))) + ])] + ); + pBody.push(t.expressionStatement(t.awaitExpression(prefetchQueryCall))); + } - const prefetchParams: t.Identifier[] = [ - typedParam('queryClient', t.tsTypeReference(t.identifier('QueryClient'))), - ]; - if (hasArgs) { - prefetchParams.push( - typedParam('variables', t.tsTypeReference(t.identifier(variablesTypeName)), !hasRequiredArgs) - ); + const pDecl = exportAsyncFunction(prefetchFnName, null, pParams, pBody, t.tsVoidKeyword()); + addJSDocComment(pDecl, [ + `Prefetch ${operation.name} for SSR or cache warming`, + '', + '@example', + '```ts', + `await ${prefetchExampleCall};`, + '```' + ]); + statements.push(pDecl); } - prefetchParams.push(typedParam('options', t.tsTypeReference(t.identifier('ExecuteOptions')), true)); - - const prefetchFunc = t.functionDeclaration( - t.identifier(prefetchFnName), - prefetchParams, - t.blockStatement(prefetchBodyStatements) - ); - prefetchFunc.async = true; - prefetchFunc.returnType = t.tsTypeAnnotation( - t.tsTypeReference( - t.identifier('Promise'), - t.tsTypeParameterInstantiation([t.tsVoidKeyword()]) - ) - ); - const prefetchExport = t.exportNamedDeclaration(prefetchFunc); - - const prefetchExampleCall = hasArgs - ? `${prefetchFnName}(queryClient, { ${argNames} })` - : `${prefetchFnName}(queryClient)`; - addJSDocComment(prefetchExport, [ - `Prefetch ${operation.name} for SSR or cache warming`, - '', - '@example', - '```ts', - `await ${prefetchExampleCall};`, - '```', - ]); - statements.push(prefetchExport); } - const code = generateCode(statements); const headerText = reactQueryEnabled ? `Custom query hook for ${operation.name}` : `Custom query functions for ${operation.name}`; - const content = getGeneratedFileHeader(headerText) + '\n\n' + code; + const content = generateHookFileCode(headerText, statements); return { fileName, content, - operationName: operation.name, + operationName: operation.name }; } @@ -562,7 +720,7 @@ export function generateAllCustomQueryHooks( skipQueryField = true, reactQueryEnabled = true, tableTypeNames, - useCentralizedKeys = true, + useCentralizedKeys = true } = options; return operations @@ -575,7 +733,7 @@ export function generateAllCustomQueryHooks( skipQueryField, reactQueryEnabled, tableTypeNames, - useCentralizedKeys, + useCentralizedKeys }) ); } diff --git a/graphql/codegen/src/core/codegen/gql-ast.ts b/graphql/codegen/src/core/codegen/gql-ast.ts deleted file mode 100644 index 612db24a0..000000000 --- a/graphql/codegen/src/core/codegen/gql-ast.ts +++ /dev/null @@ -1,405 +0,0 @@ -/** - * GraphQL AST builders using gql-ast - * - * Provides utilities for generating GraphQL queries and mutations via AST - * instead of string concatenation. - */ -import * as t from 'gql-ast'; -import { print } from 'graphql'; -import type { - DocumentNode, - FieldNode, - ArgumentNode, - VariableDefinitionNode, -} from 'graphql'; -import type { CleanTable, CleanField } from '../../types/schema'; -import { - getTableNames, - getAllRowsQueryName, - getSingleRowQueryName, - getCreateMutationName, - getUpdateMutationName, - getDeleteMutationName, - getFilterTypeName, - getConditionTypeName, - getOrderByTypeName, - getScalarFields, - getPrimaryKeyInfo, - ucFirst, -} from './utils'; - - - -// ============================================================================ -// Field selection builders -// ============================================================================ - -/** - * Create field selections from CleanField array - */ -function createFieldSelections(fields: CleanField[]): FieldNode[] { - return fields.map((field) => t.field({ name: field.name })); -} - -/** - * Create pageInfo selection - */ -function createPageInfoSelection(): FieldNode { - return t.field({ - name: 'pageInfo', - selectionSet: t.selectionSet({ - selections: [ - t.field({ name: 'hasNextPage' }), - t.field({ name: 'hasPreviousPage' }), - t.field({ name: 'startCursor' }), - t.field({ name: 'endCursor' }), - ], - }), - }); -} - -// ============================================================================ -// List query builder -// ============================================================================ - -export interface ListQueryConfig { - table: CleanTable; -} - -/** - * Build a list query AST for a table - */ -export function buildListQueryAST(config: ListQueryConfig): DocumentNode { - const { table } = config; - const queryName = getAllRowsQueryName(table); - const filterType = getFilterTypeName(table); - const conditionType = getConditionTypeName(table); - const orderByType = getOrderByTypeName(table); - const scalarFields = getScalarFields(table); - - // Variable definitions - all pagination arguments from PostGraphile - const variableDefinitions: VariableDefinitionNode[] = [ - t.variableDefinition({ - variable: t.variable({ name: 'first' }), - type: t.namedType({ type: 'Int' }), - }), - t.variableDefinition({ - variable: t.variable({ name: 'last' }), - type: t.namedType({ type: 'Int' }), - }), - t.variableDefinition({ - variable: t.variable({ name: 'offset' }), - type: t.namedType({ type: 'Int' }), - }), - t.variableDefinition({ - variable: t.variable({ name: 'before' }), - type: t.namedType({ type: 'Cursor' }), - }), - t.variableDefinition({ - variable: t.variable({ name: 'after' }), - type: t.namedType({ type: 'Cursor' }), - }), - t.variableDefinition({ - variable: t.variable({ name: 'filter' }), - type: t.namedType({ type: filterType }), - }), - t.variableDefinition({ - variable: t.variable({ name: 'condition' }), - type: t.namedType({ type: conditionType }), - }), - t.variableDefinition({ - variable: t.variable({ name: 'orderBy' }), - type: t.listType({ - type: t.nonNullType({ type: t.namedType({ type: orderByType }) }), - }), - }), - ]; - - // Query arguments - const args: ArgumentNode[] = [ - t.argument({ name: 'first', value: t.variable({ name: 'first' }) }), - t.argument({ name: 'last', value: t.variable({ name: 'last' }) }), - t.argument({ name: 'offset', value: t.variable({ name: 'offset' }) }), - t.argument({ name: 'before', value: t.variable({ name: 'before' }) }), - t.argument({ name: 'after', value: t.variable({ name: 'after' }) }), - t.argument({ name: 'filter', value: t.variable({ name: 'filter' }) }), - t.argument({ name: 'condition', value: t.variable({ name: 'condition' }) }), - t.argument({ name: 'orderBy', value: t.variable({ name: 'orderBy' }) }), - ]; - - // Field selections - const fieldSelections = createFieldSelections(scalarFields); - - // Connection fields - const connectionFields: FieldNode[] = [ - t.field({ name: 'totalCount' }), - t.field({ - name: 'nodes', - selectionSet: t.selectionSet({ selections: fieldSelections }), - }), - createPageInfoSelection(), - ]; - - return t.document({ - definitions: [ - t.operationDefinition({ - operation: 'query', - name: `${ucFirst(queryName)}Query`, - variableDefinitions, - selectionSet: t.selectionSet({ - selections: [ - t.field({ - name: queryName, - args, - selectionSet: t.selectionSet({ selections: connectionFields }), - }), - ], - }), - }), - ], - }); -} - -// ============================================================================ -// Single item query builder -// ============================================================================ - -export interface SingleQueryConfig { - table: CleanTable; -} - -/** - * Build a single item query AST for a table - */ -export function buildSingleQueryAST(config: SingleQueryConfig): DocumentNode { - const { table } = config; - const queryName = getSingleRowQueryName(table); - const scalarFields = getScalarFields(table); - - // Get primary key info dynamically from table constraints - const pkFields = getPrimaryKeyInfo(table); - // For simplicity, use first PK field (most common case) - const pkField = pkFields[0]; - - // Variable definitions - use dynamic PK field name and type - const variableDefinitions: VariableDefinitionNode[] = [ - t.variableDefinition({ - variable: t.variable({ name: pkField.name }), - type: t.nonNullType({ type: t.namedType({ type: pkField.gqlType }) }), - }), - ]; - - // Query arguments - use dynamic PK field name - const args: ArgumentNode[] = [ - t.argument({ name: pkField.name, value: t.variable({ name: pkField.name }) }), - ]; - - // Field selections - const fieldSelections = createFieldSelections(scalarFields); - - return t.document({ - definitions: [ - t.operationDefinition({ - operation: 'query', - name: `${ucFirst(queryName)}Query`, - variableDefinitions, - selectionSet: t.selectionSet({ - selections: [ - t.field({ - name: queryName, - args, - selectionSet: t.selectionSet({ selections: fieldSelections }), - }), - ], - }), - }), - ], - }); -} - -// ============================================================================ -// Create mutation builder -// ============================================================================ - -export interface CreateMutationConfig { - table: CleanTable; -} - -/** - * Build a create mutation AST for a table - */ -export function buildCreateMutationAST(config: CreateMutationConfig): DocumentNode { - const { table } = config; - const { typeName, singularName } = getTableNames(table); - const mutationName = getCreateMutationName(table); - const inputTypeName = `Create${typeName}Input`; - const scalarFields = getScalarFields(table); - - // Variable definitions - const variableDefinitions: VariableDefinitionNode[] = [ - t.variableDefinition({ - variable: t.variable({ name: 'input' }), - type: t.nonNullType({ type: t.namedType({ type: inputTypeName }) }), - }), - ]; - - // Mutation arguments - const args: ArgumentNode[] = [ - t.argument({ name: 'input', value: t.variable({ name: 'input' }) }), - ]; - - // Field selections - const fieldSelections = createFieldSelections(scalarFields); - - return t.document({ - definitions: [ - t.operationDefinition({ - operation: 'mutation', - name: `${ucFirst(mutationName)}Mutation`, - variableDefinitions, - selectionSet: t.selectionSet({ - selections: [ - t.field({ - name: mutationName, - args, - selectionSet: t.selectionSet({ - selections: [ - t.field({ - name: singularName, - selectionSet: t.selectionSet({ selections: fieldSelections }), - }), - ], - }), - }), - ], - }), - }), - ], - }); -} - -// ============================================================================ -// Update mutation builder -// ============================================================================ - -export interface UpdateMutationConfig { - table: CleanTable; -} - -/** - * Build an update mutation AST for a table - */ -export function buildUpdateMutationAST(config: UpdateMutationConfig): DocumentNode { - const { table } = config; - const { typeName, singularName } = getTableNames(table); - const mutationName = getUpdateMutationName(table); - const inputTypeName = `Update${typeName}Input`; - const scalarFields = getScalarFields(table); - - // Variable definitions - const variableDefinitions: VariableDefinitionNode[] = [ - t.variableDefinition({ - variable: t.variable({ name: 'input' }), - type: t.nonNullType({ type: t.namedType({ type: inputTypeName }) }), - }), - ]; - - // Mutation arguments - const args: ArgumentNode[] = [ - t.argument({ name: 'input', value: t.variable({ name: 'input' }) }), - ]; - - // Field selections - const fieldSelections = createFieldSelections(scalarFields); - - return t.document({ - definitions: [ - t.operationDefinition({ - operation: 'mutation', - name: `${ucFirst(mutationName)}Mutation`, - variableDefinitions, - selectionSet: t.selectionSet({ - selections: [ - t.field({ - name: mutationName, - args, - selectionSet: t.selectionSet({ - selections: [ - t.field({ - name: singularName, - selectionSet: t.selectionSet({ selections: fieldSelections }), - }), - ], - }), - }), - ], - }), - }), - ], - }); -} - -// ============================================================================ -// Delete mutation builder -// ============================================================================ - -export interface DeleteMutationConfig { - table: CleanTable; -} - -/** - * Build a delete mutation AST for a table - */ -export function buildDeleteMutationAST(config: DeleteMutationConfig): DocumentNode { - const { table } = config; - const { typeName } = getTableNames(table); - const mutationName = getDeleteMutationName(table); - const inputTypeName = `Delete${typeName}Input`; - - // Variable definitions - const variableDefinitions: VariableDefinitionNode[] = [ - t.variableDefinition({ - variable: t.variable({ name: 'input' }), - type: t.nonNullType({ type: t.namedType({ type: inputTypeName }) }), - }), - ]; - - // Mutation arguments - const args: ArgumentNode[] = [ - t.argument({ name: 'input', value: t.variable({ name: 'input' }) }), - ]; - - return t.document({ - definitions: [ - t.operationDefinition({ - operation: 'mutation', - name: `${ucFirst(mutationName)}Mutation`, - variableDefinitions, - selectionSet: t.selectionSet({ - selections: [ - t.field({ - name: mutationName, - args, - selectionSet: t.selectionSet({ - selections: [ - t.field({ name: 'clientMutationId' }), - ], - }), - }), - ], - }), - }), - ], - }); -} - -// ============================================================================ -// Print utilities -// ============================================================================ - -/** - * Print AST to GraphQL string - */ -export function printGraphQL(ast: DocumentNode): string { - return print(ast); -} diff --git a/graphql/codegen/src/core/codegen/hooks-ast.ts b/graphql/codegen/src/core/codegen/hooks-ast.ts new file mode 100644 index 000000000..6b3782f43 --- /dev/null +++ b/graphql/codegen/src/core/codegen/hooks-ast.ts @@ -0,0 +1,874 @@ +/** + * Shared Babel AST helpers for React Query hook generators + * + * Provides reusable AST-building functions for the common patterns + * used across queries.ts, mutations.ts, custom-queries.ts, and custom-mutations.ts. + */ +import * as t from '@babel/types'; + +import type { CleanArgument, TypeRegistry } from '../../types/schema'; +import { commentBlock, generateCode } from './babel-ast'; +import { getTypeBaseName, scalarToTsType } from './type-resolver'; +import { getGeneratedFileHeader } from './utils'; + +// ============================================================================ +// Import helpers +// ============================================================================ + +export function createImportDeclaration( + moduleSpecifier: string, + namedImports: string[], + typeOnly: boolean = false +): t.ImportDeclaration { + const specifiers = namedImports.map((name) => + t.importSpecifier(t.identifier(name), t.identifier(name)) + ); + const decl = t.importDeclaration(specifiers, t.stringLiteral(moduleSpecifier)); + decl.importKind = typeOnly ? 'type' : 'value'; + return decl; +} + +export function createTypeReExport( + names: string[], + moduleSpecifier: string +): t.ExportNamedDeclaration { + const specifiers = names.map((name) => + t.exportSpecifier(t.identifier(name), t.identifier(name)) + ); + const decl = t.exportNamedDeclaration(null, specifiers, t.stringLiteral(moduleSpecifier)); + decl.exportKind = 'type'; + return decl; +} + +// ============================================================================ +// Type reference helpers +// ============================================================================ + +export function typeRef(name: string, params?: t.TSType[]): t.TSTypeReference { + return t.tsTypeReference( + t.identifier(name), + params ? t.tsTypeParameterInstantiation(params) : undefined + ); +} + +export function sRef(): t.TSTypeReference { + return typeRef('S'); +} + +export function typeofRef(name: string): t.TSTypeQuery { + return t.tsTypeQuery(t.identifier(name)); +} + +export function stringLiteralType(value: string): t.TSLiteralType { + return t.tsLiteralType(t.stringLiteral(value)); +} + +// ============================================================================ +// Complex type builders +// ============================================================================ + +export function inferSelectResultType( + entityTypeName: string, + selectType: t.TSType +): t.TSTypeReference { + return typeRef('InferSelectResult', [typeRef(entityTypeName), selectType]); +} + +export function connectionResultType( + entityTypeName: string, + selectType: t.TSType +): t.TSTypeReference { + return typeRef('ConnectionResult', [inferSelectResultType(entityTypeName, selectType)]); +} + +export function typeLiteralWithProps( + props: Array<{ name: string; type: t.TSType; optional?: boolean }> +): t.TSTypeLiteral { + return t.tsTypeLiteral( + props.map((p) => { + const prop = t.tsPropertySignature( + t.identifier(p.name), + t.tsTypeAnnotation(p.type) + ); + if (p.optional) { + prop.optional = true; + } + return prop; + }) + ); +} + +export function queryResultType( + queryName: string, + innerType: t.TSType +): t.TSTypeLiteral { + return typeLiteralWithProps([{ name: queryName, type: innerType }]); +} + +export function listQueryResultType( + queryName: string, + entityTypeName: string, + selectType: t.TSType +): t.TSTypeLiteral { + return queryResultType(queryName, connectionResultType(entityTypeName, selectType)); +} + +export function singleQueryResultType( + queryName: string, + entityTypeName: string, + selectType: t.TSType, + nullable: boolean = true +): t.TSTypeLiteral { + const resultType = inferSelectResultType(entityTypeName, selectType); + const innerType = nullable + ? t.tsUnionType([resultType, t.tsNullKeyword()]) + : resultType; + return queryResultType(queryName, innerType); +} + +export function mutationResultType( + mutationName: string, + entityField: string, + entityTypeName: string, + selectType: t.TSType +): t.TSTypeLiteral { + return queryResultType( + mutationName, + typeLiteralWithProps([{ + name: entityField, + type: inferSelectResultType(entityTypeName, selectType) + }]) + ); +} + +export function omitType(baseType: t.TSType, keys: string[]): t.TSTypeReference { + const keyType = keys.length === 1 + ? stringLiteralType(keys[0]) + : t.tsUnionType(keys.map(stringLiteralType)); + return typeRef('Omit', [baseType, keyType]); +} + +export function listSelectionConfigType( + selectType: t.TSType, + filterTypeName: string, + orderByTypeName: string +): t.TSTypeReference { + return typeRef('ListSelectionConfig', [ + selectType, + typeRef(filterTypeName), + typeRef(orderByTypeName) + ]); +} + +export function selectionConfigType(selectType: t.TSType): t.TSTypeReference { + return typeRef('SelectionConfig', [selectType]); +} + +export function strictSelectType( + selectType: t.TSType, + shapeTypeName: string +): t.TSTypeReference { + return typeRef('StrictSelect', [selectType, typeRef(shapeTypeName)]); +} + +export function withFieldsSelectionType( + selectType: t.TSType, + selectTypeName: string +): t.TSIntersectionType { + return t.tsIntersectionType([ + typeLiteralWithProps([{ name: 'fields', type: selectType }]), + strictSelectType(selectType, selectTypeName) + ]); +} + +export function withFieldsListSelectionType( + selectType: t.TSType, + selectTypeName: string, + filterTypeName: string, + orderByTypeName: string +): t.TSIntersectionType { + return t.tsIntersectionType([ + typeLiteralWithProps([{ name: 'fields', type: selectType }]), + omitType( + listSelectionConfigType(selectType, filterTypeName, orderByTypeName), + ['fields'] + ), + strictSelectType(selectType, selectTypeName) + ]); +} + +export function withoutFieldsSelectionType(): t.TSTypeLiteral { + return typeLiteralWithProps([{ + name: 'fields', + type: t.tsUndefinedKeyword(), + optional: true + }]); +} + +export function withoutFieldsListSelectionType( + selectTypeName: string, + filterTypeName: string, + orderByTypeName: string +): t.TSIntersectionType { + return t.tsIntersectionType([ + omitType( + listSelectionConfigType(typeRef(selectTypeName), filterTypeName, orderByTypeName), + ['fields'] + ), + withoutFieldsSelectionType() + ]); +} + +export function useQueryOptionsType( + queryDataType: t.TSType, + dataType: t.TSType, + extraProps?: t.TSType +): t.TSType { + const base = omitType( + typeRef('UseQueryOptions', [queryDataType, typeRef('Error'), dataType]), + ['queryKey', 'queryFn'] + ); + if (extraProps) { + return t.tsIntersectionType([base, extraProps]); + } + return base; +} + +export function useQueryOptionsImplType(extraProps?: t.TSType): t.TSType { + const base = omitType( + typeRef('UseQueryOptions', [ + t.tsAnyKeyword(), + typeRef('Error'), + t.tsAnyKeyword(), + t.tsAnyKeyword() + ]), + ['queryKey', 'queryFn'] + ); + if (extraProps) { + return t.tsIntersectionType([base, extraProps]); + } + return base; +} + +export function useMutationOptionsType( + resultType: t.TSType, + varType: t.TSType +): t.TSTypeReference { + return omitType( + typeRef('UseMutationOptions', [resultType, typeRef('Error'), varType]), + ['mutationFn'] + ); +} + +export function useMutationResultType( + resultType: t.TSType, + varType: t.TSType +): t.TSTypeReference { + return typeRef('UseMutationResult', [resultType, typeRef('Error'), varType]); +} + +// ============================================================================ +// Type parameter helpers +// ============================================================================ + +export function createSTypeParam(constraintName: string): t.TSTypeParameterDeclaration { + const param = t.tsTypeParameter(typeRef(constraintName), null, 'S'); + return t.tsTypeParameterDeclaration([param]); +} + +export function createSAndTDataTypeParams( + constraintName: string, + defaultDataType: t.TSType +): t.TSTypeParameterDeclaration { + const sParam = t.tsTypeParameter(typeRef(constraintName), null, 'S'); + const tDataParam = t.tsTypeParameter(null, defaultDataType, 'TData'); + return t.tsTypeParameterDeclaration([sParam, tDataParam]); +} + +export function createTDataTypeParam(defaultType: t.TSType): t.TSTypeParameterDeclaration { + const param = t.tsTypeParameter(null, defaultType, 'TData'); + return t.tsTypeParameterDeclaration([param]); +} + +// ============================================================================ +// Function declaration helpers +// ============================================================================ + +export function createFunctionParam( + name: string, + typeAnnotation: t.TSType, + optional: boolean = false +): t.Identifier { + const param = t.identifier(name); + param.typeAnnotation = t.tsTypeAnnotation(typeAnnotation); + param.optional = optional; + return param; +} + +export function exportDeclareFunction( + name: string, + typeParameters: t.TSTypeParameterDeclaration | null, + params: t.Identifier[], + returnType: t.TSType +): t.ExportNamedDeclaration { + const func = t.tsDeclareFunction( + t.identifier(name), + typeParameters, + params, + t.tsTypeAnnotation(returnType) + ); + return t.exportNamedDeclaration(func); +} + +export function exportFunction( + name: string, + typeParameters: t.TSTypeParameterDeclaration | null, + params: t.Identifier[], + body: t.Statement[], + returnType?: t.TSType +): t.ExportNamedDeclaration { + const func = t.functionDeclaration( + t.identifier(name), + params, + t.blockStatement(body) + ); + func.typeParameters = typeParameters; + if (returnType) { + func.returnType = t.tsTypeAnnotation(returnType); + } + return t.exportNamedDeclaration(func); +} + +export function exportAsyncFunction( + name: string, + typeParameters: t.TSTypeParameterDeclaration | null, + params: t.Identifier[], + body: t.Statement[], + returnType?: t.TSType +): t.ExportNamedDeclaration { + const func = t.functionDeclaration( + t.identifier(name), + params, + t.blockStatement(body) + ); + func.async = true; + func.typeParameters = typeParameters; + if (returnType) { + func.returnType = t.tsTypeAnnotation(returnType); + } + return t.exportNamedDeclaration(func); +} + +export function exportAsyncDeclareFunction( + name: string, + typeParameters: t.TSTypeParameterDeclaration | null, + params: t.Identifier[], + returnType: t.TSType +): t.ExportNamedDeclaration { + const func = t.tsDeclareFunction( + t.identifier(name), + typeParameters, + params, + t.tsTypeAnnotation(returnType) + ); + func.async = true; + return t.exportNamedDeclaration(func); +} + +// ============================================================================ +// Expression helpers +// ============================================================================ + +export function callExpr( + callee: string | t.Expression, + args: (t.Expression | t.SpreadElement)[] +): t.CallExpression { + const calleeExpr = typeof callee === 'string' ? t.identifier(callee) : callee; + return t.callExpression(calleeExpr, args); +} + +export function memberExpr(obj: string, prop: string): t.MemberExpression { + return t.memberExpression(t.identifier(obj), t.identifier(prop)); +} + +export function optionalMemberExpr(obj: string, prop: string): t.OptionalMemberExpression { + return t.optionalMemberExpression(t.identifier(obj), t.identifier(prop), false, true); +} + +export function arrowFn( + params: t.Identifier[], + body: t.Expression | t.BlockStatement +): t.ArrowFunctionExpression { + return t.arrowFunctionExpression(params, body); +} + +export function awaitExpr(expr: t.Expression): t.AwaitExpression { + return t.awaitExpression(expr); +} + +export function spreadObj(expr: t.Expression): t.SpreadElement { + return t.spreadElement(expr); +} + +export function objectProp( + key: string, + value: t.Expression, + shorthand: boolean = false +): t.ObjectProperty { + return t.objectProperty(t.identifier(key), value, false, shorthand); +} + +export function shorthandProp(name: string): t.ObjectProperty { + return t.objectProperty(t.identifier(name), t.identifier(name), false, true); +} + +export function constDecl(name: string, init: t.Expression): t.VariableDeclaration { + return t.variableDeclaration('const', [ + t.variableDeclarator(t.identifier(name), init) + ]); +} + +export function asConstExpr(expr: t.Expression): t.TSAsExpression { + return t.tsAsExpression(expr, t.tsTypeReference(t.identifier('const'))); +} + +export function asTypeExpr(expr: t.Expression, typeName: string): t.TSAsExpression { + return t.tsAsExpression(expr, typeRef(typeName)); +} + +// ============================================================================ +// Statement helpers +// ============================================================================ + +export function voidStatement(name: string): t.ExpressionStatement { + return t.expressionStatement(t.unaryExpression('void', t.identifier(name))); +} + +export function returnUseQuery( + queryKeyExpr: t.Expression, + queryFnExpr: t.Expression, + extraProps?: Array, + enabledExpr?: t.Expression +): t.ReturnStatement { + const props: Array = [ + objectProp('queryKey', queryKeyExpr), + objectProp('queryFn', queryFnExpr) + ]; + if (enabledExpr) { + props.push(objectProp('enabled', enabledExpr)); + } + if (extraProps) { + props.push(...extraProps); + } + return t.returnStatement( + callExpr('useQuery', [t.objectExpression(props)]) + ); +} + +export function returnUseMutation( + mutationFnExpr: t.Expression, + extraProps: Array, + mutationKeyExpr?: t.Expression +): t.ReturnStatement { + const props: Array = []; + if (mutationKeyExpr) { + props.push(objectProp('mutationKey', mutationKeyExpr)); + } + props.push(objectProp('mutationFn', mutationFnExpr)); + props.push(...extraProps); + return t.returnStatement( + callExpr('useMutation', [t.objectExpression(props)]) + ); +} + +// ============================================================================ +// Destructuring helpers +// ============================================================================ + +export function destructureWithRest( + source: t.Expression, + keys: string[], + restName: string +): t.VariableDeclaration { + const properties = keys.map((key) => + t.objectProperty(t.identifier(key), t.identifier(`_${key}`), false, false) + ); + const pattern = t.objectPattern([ + ...properties, + t.restElement(t.identifier(restName)) + ]); + return constDecl(restName, t.identifier('__placeholder__')); +} + +export function destructureParamsWithSelection( + restName: string, + extraKeys: string[] = [] +): t.VariableDeclaration { + const properties: (t.ObjectProperty | t.RestElement)[] = []; + for (const key of extraKeys) { + properties.push( + t.objectProperty(t.identifier(key), t.identifier(key), false, true) + ); + } + properties.push( + t.objectProperty(t.identifier('selection'), t.identifier('_selection'), false, false) + ); + properties.push(t.restElement(t.identifier(restName))); + + const pattern = t.objectPattern(properties); + return t.variableDeclaration('const', [ + t.variableDeclarator( + pattern, + t.logicalExpression('??', t.identifier('params'), t.objectExpression([])) + ) + ]); +} + +export function destructureParamsWithSelectionAndScope( + restName: string +): t.VariableDeclaration { + const pattern = t.objectPattern([ + t.objectProperty(t.identifier('scope'), t.identifier('scope'), false, true), + t.objectProperty(t.identifier('selection'), t.identifier('_selection'), false, false), + t.restElement(t.identifier(restName)) + ]); + return t.variableDeclaration('const', [ + t.variableDeclarator( + pattern, + t.logicalExpression('??', t.identifier('params'), t.objectExpression([])) + ) + ]); +} + +// ============================================================================ +// JSDoc comment helpers +// ============================================================================ + +export function addJSDocComment(node: T, lines: string[]): T { + const text = lines.length === 1 + ? `* ${lines[0]} ` + : `*\n${lines.map((line) => ` * ${line}`).join('\n')}\n `; + if (!node.leadingComments) { + node.leadingComments = []; + } + node.leadingComments.push(commentBlock(text)); + return node; +} + +export function addLineComment(node: T, text: string): T { + if (!node.leadingComments) { + node.leadingComments = []; + } + node.leadingComments.push({ + type: 'CommentLine', + value: ` ${text}`, + start: null, + end: null, + loc: null + }); + return node; +} + +// ============================================================================ +// ORM client call builders +// ============================================================================ + +export function getClientCall( + modelName: string, + method: string, + args: t.Expression +): t.CallExpression { + return t.callExpression( + t.memberExpression( + t.memberExpression( + callExpr('getClient', []), + t.identifier(modelName) + ), + t.identifier(method) + ), + [args] + ); +} + +export function getClientCallUnwrap( + modelName: string, + method: string, + args: t.Expression +): t.CallExpression { + return t.callExpression( + t.memberExpression( + getClientCall(modelName, method, args), + t.identifier('unwrap') + ), + [] + ); +} + +export function getClientCustomCall( + operationType: 'query' | 'mutation', + operationName: string, + args: t.Expression[], + optionsArg?: t.Expression +): t.CallExpression { + const callArgs = optionsArg ? [...args, optionsArg] : args; + return t.callExpression( + t.memberExpression( + t.memberExpression( + callExpr('getClient', []), + t.identifier(operationType) + ), + t.identifier(operationName) + ), + callArgs + ); +} + +export function getClientCustomCallUnwrap( + operationType: 'query' | 'mutation', + operationName: string, + args: t.Expression[], + optionsArg?: t.Expression +): t.CallExpression { + return t.callExpression( + t.memberExpression( + getClientCustomCall(operationType, operationName, args, optionsArg), + t.identifier('unwrap') + ), + [] + ); +} + +// ============================================================================ +// Select/args expression builders +// ============================================================================ + +export function buildSelectFallbackExpr( + argsIdent: string, + defaultSelectIdent: string, + selectTypeName: string +): t.TSAsExpression { + return t.tsAsExpression( + t.parenthesizedExpression( + t.logicalExpression( + '??', + t.optionalMemberExpression( + t.identifier(argsIdent), + t.identifier('select'), + false, + true + ), + t.identifier(defaultSelectIdent) + ) + ), + typeRef(selectTypeName) + ); +} + +export function buildFindManyCallExpr( + singularName: string, + argsIdent: string, + selectTypeName: string, + defaultSelectIdent: string = 'defaultSelect' +): t.CallExpression { + const spreadArgs = t.parenthesizedExpression( + t.logicalExpression('??', t.identifier(argsIdent), t.objectExpression([])) + ); + return getClientCallUnwrap( + singularName, + 'findMany', + t.objectExpression([ + t.spreadElement(spreadArgs), + objectProp('select', buildSelectFallbackExpr(argsIdent, defaultSelectIdent, selectTypeName)) + ]) + ); +} + +export function buildFindOneCallExpr( + singularName: string, + pkFieldName: string, + argsIdent: string, + selectTypeName: string, + paramsIdent: string = 'params', + defaultSelectIdent: string = 'defaultSelect' +): t.CallExpression { + return getClientCallUnwrap( + singularName, + 'findOne', + t.objectExpression([ + objectProp( + pkFieldName, + t.memberExpression(t.identifier(paramsIdent), t.identifier(pkFieldName)) + ), + t.spreadElement( + t.parenthesizedExpression( + t.logicalExpression('??', t.identifier(argsIdent), t.objectExpression([])) + ) + ), + objectProp('select', buildSelectFallbackExpr(argsIdent, defaultSelectIdent, selectTypeName)) + ]) + ); +} + +// ============================================================================ +// Code generation +// ============================================================================ + +export function generateHookFileCode( + headerDescription: string, + statements: t.Statement[] +): string { + const header = getGeneratedFileHeader(headerDescription); + const code = generateCode(statements); + return header + '\n\n' + code + '\n'; +} + +// ============================================================================ +// Scope type helper +// ============================================================================ + +export function scopeTypeLiteral(scopeTypeName: string): t.TSTypeLiteral { + return typeLiteralWithProps([{ + name: 'scope', + type: typeRef(scopeTypeName), + optional: true + }]); +} + +// ============================================================================ +// Type conversion helpers (GraphQL -> AST) +// ============================================================================ + +const NON_SELECT_TYPES_AST = new Set([ + 'String', 'Int', 'Float', 'Boolean', 'ID', + 'BigFloat', 'BigInt', 'Cursor', 'Date', 'Datetime', + 'JSON', 'UUID', 'Uuid', 'Time', + 'Query', 'Mutation' +]); + +export function wrapInferSelectResultType( + typeRefNode: CleanArgument['type'], + payloadTypeName: string, + selectType: t.TSType +): t.TSType { + if (typeRefNode.kind === 'NON_NULL' && typeRefNode.ofType) { + return wrapInferSelectResultType( + typeRefNode.ofType as CleanArgument['type'], + payloadTypeName, + selectType + ); + } + if (typeRefNode.kind === 'LIST' && typeRefNode.ofType) { + return t.tsArrayType( + wrapInferSelectResultType( + typeRefNode.ofType as CleanArgument['type'], + payloadTypeName, + selectType + ) + ); + } + return inferSelectResultType(payloadTypeName, selectType); +} + +export function typeRefToTsTypeAST( + typeRefNode: CleanArgument['type'] +): t.TSType { + if (typeRefNode.kind === 'NON_NULL' && typeRefNode.ofType) { + return typeRefToTsTypeAST(typeRefNode.ofType as CleanArgument['type']); + } + if (typeRefNode.kind === 'LIST' && typeRefNode.ofType) { + return t.tsArrayType(typeRefToTsTypeAST(typeRefNode.ofType as CleanArgument['type'])); + } + if (typeRefNode.kind === 'SCALAR') { + const tsType = scalarToTsType(typeRefNode.name ?? 'unknown'); + if (tsType === 'string') return t.tsStringKeyword(); + if (tsType === 'number') return t.tsNumberKeyword(); + if (tsType === 'boolean') return t.tsBooleanKeyword(); + return t.tsUnknownKeyword(); + } + return typeRef(typeRefNode.name ?? 'unknown'); +} + +export function buildDefaultSelectExpr( + typeName: string, + typeRegistry: TypeRegistry, + depth: number = 0 +): t.ObjectExpression { + const resolved = typeRegistry.get(typeName); + const fields = resolved?.fields ?? []; + + if (depth > 3 || fields.length === 0) { + const fieldName = fields.length > 0 ? fields[0].name : 'id'; + return t.objectExpression([objectProp(fieldName, t.booleanLiteral(true))]); + } + + const idLike = fields.find((f) => f.name === 'id' || f.name === 'nodeId'); + if (idLike) return t.objectExpression([objectProp(idLike.name, t.booleanLiteral(true))]); + + const scalarField = fields.find((f) => { + const baseName = getTypeBaseName(f.type); + if (!baseName) return false; + if (NON_SELECT_TYPES_AST.has(baseName)) return true; + return typeRegistry.get(baseName)?.kind === 'ENUM'; + }); + if (scalarField) return t.objectExpression([objectProp(scalarField.name, t.booleanLiteral(true))]); + + const first = fields[0]; + const firstBase = getTypeBaseName(first.type); + if ( + !firstBase || + NON_SELECT_TYPES_AST.has(firstBase) || + typeRegistry.get(firstBase)?.kind === 'ENUM' + ) { + return t.objectExpression([objectProp(first.name, t.booleanLiteral(true))]); + } + + const nested = buildDefaultSelectExpr(firstBase, typeRegistry, depth + 1); + return t.objectExpression([ + objectProp(first.name, t.objectExpression([objectProp('select', nested)])) + ]); +} + +export function buildSelectionArgsCall( + selectTypeName: string +): t.VariableDeclaration { + const call = t.callExpression(t.identifier('buildSelectionArgs'), [ + t.optionalMemberExpression( + t.identifier('params'), + t.identifier('selection'), + false, + true + ) + ]); + // @ts-ignore - Babel types support typeParameters on CallExpression for TS + call.typeParameters = t.tsTypeParameterInstantiation([typeRef(selectTypeName)]); + return constDecl('args', call); +} + +export function buildListSelectionArgsCall( + selectTypeName: string, + filterTypeName: string, + orderByTypeName: string +): t.VariableDeclaration { + const call = t.callExpression(t.identifier('buildListSelectionArgs'), [ + t.identifier('selection') + ]); + // @ts-ignore - Babel types support typeParameters on CallExpression for TS + call.typeParameters = t.tsTypeParameterInstantiation([ + typeRef(selectTypeName), + typeRef(filterTypeName), + typeRef(orderByTypeName) + ]); + return constDecl('args', call); +} + +export function customSelectResultTypeLiteral( + opName: string, + returnType: CleanArgument['type'], + payloadTypeName: string, + selectType: t.TSType +): t.TSTypeLiteral { + return typeLiteralWithProps([{ + name: opName, + type: wrapInferSelectResultType(returnType, payloadTypeName, selectType) + }]); +} diff --git a/graphql/codegen/src/core/codegen/index.ts b/graphql/codegen/src/core/codegen/index.ts index 407e10527..57e75750f 100644 --- a/graphql/codegen/src/core/codegen/index.ts +++ b/graphql/codegen/src/core/codegen/index.ts @@ -2,52 +2,49 @@ * Code generation orchestrator * * Coordinates all code generators to produce the complete SDK output. + * Hooks delegate to ORM model methods - types are imported from ORM's input-types.ts. * * Output structure: * generated/ * index.ts - Main barrel export - * client.ts - GraphQL client with configure() and execute() - * types.ts - Entity interfaces and filter types + * client.ts - ORM client wrapper (configure/getClient) * queries/ * index.ts - Query hooks barrel - * useCarsQuery.ts - List query hook (table-based) - * useCarQuery.ts - Single item query hook (table-based) - * useCurrentUserQuery.ts - Custom query hook + * useCarsQuery.ts - List query hook -> ORM findMany + * useCarQuery.ts - Single item query hook -> ORM findOne + * useCurrentUserQuery.ts - Custom query hook -> ORM query.xxx * ... * mutations/ * index.ts - Mutation hooks barrel - * useCreateCarMutation.ts - Table-based CRUD - * useUpdateCarMutation.ts - * useDeleteCarMutation.ts - * useLoginMutation.ts - Custom mutation - * useRegisterMutation.ts + * useCreateCarMutation.ts - -> ORM create + * useUpdateCarMutation.ts - -> ORM update + * useDeleteCarMutation.ts - -> ORM delete + * useLoginMutation.ts - Custom mutation -> ORM mutation.xxx * ... */ +import type { GraphQLSDKConfigTarget, QueryKeyConfig } from '../../types/config'; +import { DEFAULT_QUERY_KEY_CONFIG } from '../../types/config'; import type { - CleanTable, CleanOperation, - TypeRegistry, + CleanTable, + TypeRegistry } from '../../types/schema'; -import type { GraphQLSDKConfigTarget, QueryKeyConfig } from '../../types/config'; -import { DEFAULT_QUERY_KEY_CONFIG } from '../../types/config'; - -import { generateClientFile } from './client'; -import { generateTypesFile } from './types'; -import { generateSchemaTypesFile } from './schema-types-generator'; -import { generateAllQueryHooks } from './queries'; -import { generateAllMutationHooks } from './mutations'; -import { generateAllCustomQueryHooks } from './custom-queries'; -import { generateAllCustomMutationHooks } from './custom-mutations'; -import { generateQueryKeysFile } from './query-keys'; -import { generateMutationKeysFile } from './mutation-keys'; -import { generateInvalidationFile } from './invalidation'; import { - generateQueriesBarrel, - generateMutationsBarrel, - generateMainBarrel, - generateCustomQueriesBarrel, generateCustomMutationsBarrel, + generateCustomQueriesBarrel, + generateMainBarrel, + generateMutationsBarrel, + generateQueriesBarrel } from './barrel'; +import { generateClientFile } from './client'; +import { generateAllCustomMutationHooks } from './custom-mutations'; +import { generateAllCustomQueryHooks } from './custom-queries'; +import { generateInvalidationFile } from './invalidation'; +import { generateMutationKeysFile } from './mutation-keys'; +import { generateAllMutationHooks } from './mutations'; +import { generateAllQueryHooks } from './queries'; +import { generateQueryKeysFile } from './query-keys'; +import { generateSelectionFile } from './selection'; import { getTableNames } from './utils'; // ============================================================================ @@ -114,7 +111,7 @@ export function generateAllFiles( * (they're expected to exist in the shared types directory). */ export function generate(options: GenerateOptions): GenerateResult { - const { tables, customOperations, config, sharedTypesPath } = options; + const { tables, customOperations, config } = options; const files: GeneratedFile[] = []; // Extract codegen options @@ -127,62 +124,24 @@ export function generate(options: GenerateOptions): GenerateResult { const useCentralizedKeys = queryKeyConfig.generateScopedKeys; const hasRelationships = Object.keys(queryKeyConfig.relationships).length > 0; - // 1. Generate client.ts + // 1. Generate client.ts (ORM client wrapper) files.push({ path: 'client.ts', - content: generateClientFile({ - browserCompatible: config.browserCompatible ?? true, - }), + content: generateClientFile() + }); + + // 1b. Generate selection.ts (shared selection adapters for hooks) + files.push({ + path: 'selection.ts', + content: generateSelectionFile() }); // Collect table type names for import path resolution const tableTypeNames = new Set(tables.map((t) => getTableNames(t).typeName)); - // 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 (sharedTypesPath) { - // Using shared types - check if schema-types would be generated - if (customOperations && customOperations.typeRegistry) { - const schemaTypesResult = generateSchemaTypesFile({ - typeRegistry: customOperations.typeRegistry, - tableTypeNames, - }); - 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, - }); - - // 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, - }), - }); - } + // NOTE: types.ts and schema-types.ts are no longer generated here. + // Hooks now import types directly from the ORM's input-types.ts, + // which serves as the single source of truth for all types. // 3b. Generate centralized query keys (query-keys.ts) let hasQueryKeys = false; @@ -190,11 +149,11 @@ export function generate(options: GenerateOptions): GenerateResult { const queryKeysResult = generateQueryKeysFile({ tables, customQueries: customOperations?.queries ?? [], - config: queryKeyConfig, + config: queryKeyConfig }); files.push({ path: queryKeysResult.fileName, - content: queryKeysResult.content, + content: queryKeysResult.content }); hasQueryKeys = true; } @@ -205,11 +164,11 @@ export function generate(options: GenerateOptions): GenerateResult { const mutationKeysResult = generateMutationKeysFile({ tables, customMutations: customOperations?.mutations ?? [], - config: queryKeyConfig, + config: queryKeyConfig }); files.push({ path: mutationKeysResult.fileName, - content: mutationKeysResult.content, + content: mutationKeysResult.content }); hasMutationKeys = true; } @@ -219,11 +178,11 @@ export function generate(options: GenerateOptions): GenerateResult { if (useCentralizedKeys && queryKeyConfig.generateCascadeHelpers) { const invalidationResult = generateInvalidationFile({ tables, - config: queryKeyConfig, + config: queryKeyConfig }); files.push({ path: invalidationResult.fileName, - content: invalidationResult.content, + content: invalidationResult.content }); hasInvalidation = true; } @@ -232,12 +191,12 @@ export function generate(options: GenerateOptions): GenerateResult { const queryHooks = generateAllQueryHooks(tables, { reactQueryEnabled, useCentralizedKeys, - hasRelationships, + hasRelationships }); for (const hook of queryHooks) { files.push({ path: `queries/${hook.fileName}`, - content: hook.content, + content: hook.content }); } @@ -255,13 +214,13 @@ export function generate(options: GenerateOptions): GenerateResult { skipQueryField, reactQueryEnabled, tableTypeNames, - useCentralizedKeys, + useCentralizedKeys }); for (const hook of customQueryHooks) { files.push({ path: `queries/${hook.fileName}`, - content: hook.content, + content: hook.content }); } } @@ -272,24 +231,21 @@ export function generate(options: GenerateOptions): GenerateResult { content: customQueryHooks.length > 0 ? generateCustomQueriesBarrel( - tables, - customQueryHooks.map((h) => h.operationName) - ) - : generateQueriesBarrel(tables), + tables, + customQueryHooks.map((h) => h.operationName) + ) + : generateQueriesBarrel(tables) }); // 6. Generate table-based mutation hooks (mutations/*.ts) const mutationHooks = generateAllMutationHooks(tables, { reactQueryEnabled, - enumsFromSchemaTypes: generatedEnumNames, - useCentralizedKeys, - hasRelationships, - tableTypeNames, + useCentralizedKeys }); for (const hook of mutationHooks) { files.push({ path: `mutations/${hook.fileName}`, - content: hook.content, + content: hook.content }); } @@ -307,13 +263,13 @@ export function generate(options: GenerateOptions): GenerateResult { skipQueryField, reactQueryEnabled, tableTypeNames, - useCentralizedKeys, + useCentralizedKeys }); for (const hook of customMutationHooks) { files.push({ path: `mutations/${hook.fileName}`, - content: hook.content, + content: hook.content }); } } @@ -328,23 +284,23 @@ export function generate(options: GenerateOptions): GenerateResult { content: customMutationHooks.length > 0 ? generateCustomMutationsBarrel( - tables, - customMutationHooks.map((h) => h.operationName) - ) - : generateMutationsBarrel(tables), + tables, + customMutationHooks.map((h) => h.operationName) + ) + : generateMutationsBarrel(tables) }); } - // 9. Generate main index.ts barrel (with schema-types if present) + // 9. Generate main index.ts barrel + // No longer includes types.ts or schema-types.ts - hooks import from ORM directly files.push({ path: 'index.ts', content: generateMainBarrel(tables, { - hasSchemaTypes, hasMutations, hasQueryKeys, hasMutationKeys, - hasInvalidation, - }), + hasInvalidation + }) }); return { @@ -355,8 +311,8 @@ export function generate(options: GenerateOptions): GenerateResult { mutationHooks: mutationHooks.length, customQueryHooks: customQueryHooks.length, customMutationHooks: customMutationHooks.length, - totalFiles: files.length, - }, + totalFiles: files.length + } }; } @@ -364,34 +320,33 @@ export function generate(options: GenerateOptions): GenerateResult { // Re-exports for convenience // ============================================================================ +export { + generateCustomMutationsBarrel, + generateCustomQueriesBarrel, + generateMainBarrel, + generateMutationsBarrel, + generateQueriesBarrel +} from './barrel'; export { generateClientFile } from './client'; -export { generateTypesFile } from './types'; export { - generateAllQueryHooks, - generateListQueryHook, - generateSingleQueryHook, -} from './queries'; + generateAllCustomMutationHooks, + generateCustomMutationHook +} from './custom-mutations'; +export { + generateAllCustomQueryHooks, + generateCustomQueryHook +} from './custom-queries'; +export { generateInvalidationFile } from './invalidation'; +export { generateMutationKeysFile } from './mutation-keys'; export { generateAllMutationHooks, generateCreateMutationHook, - generateUpdateMutationHook, generateDeleteMutationHook, + generateUpdateMutationHook } from './mutations'; export { - generateAllCustomQueryHooks, - generateCustomQueryHook, -} from './custom-queries'; -export { - generateAllCustomMutationHooks, - generateCustomMutationHook, -} from './custom-mutations'; -export { - generateQueriesBarrel, - generateMutationsBarrel, - generateMainBarrel, - generateCustomQueriesBarrel, - generateCustomMutationsBarrel, -} from './barrel'; + generateAllQueryHooks, + generateListQueryHook, + generateSingleQueryHook +} from './queries'; export { generateQueryKeysFile } from './query-keys'; -export { generateMutationKeysFile } from './mutation-keys'; -export { generateInvalidationFile } from './invalidation'; diff --git a/graphql/codegen/src/core/codegen/invalidation.ts b/graphql/codegen/src/core/codegen/invalidation.ts index 96247303e..ef9a5bf4b 100644 --- a/graphql/codegen/src/core/codegen/invalidation.ts +++ b/graphql/codegen/src/core/codegen/invalidation.ts @@ -4,17 +4,18 @@ * Generates type-safe cache invalidation utilities with cascade support * for parent-child entity relationships. */ -import type { CleanTable } from '../../types/schema'; -import type { QueryKeyConfig, EntityRelationship } from '../../types/config'; -import { getTableNames, getGeneratedFileHeader, ucFirst, lcFirst } from './utils'; import * as t from '@babel/types'; + +import type { EntityRelationship,QueryKeyConfig } from '../../types/config'; +import type { CleanTable } from '../../types/schema'; import { - generateCode, addJSDocComment, - asConst, - typedParam, addLineComment, + asConst, + generateCode, + typedParam } from './babel-ast'; +import { getGeneratedFileHeader, getTableNames, lcFirst,ucFirst } from './utils'; export interface InvalidationGeneratorOptions { tables: CleanTable[]; @@ -247,7 +248,7 @@ function buildEntityInvalidateProperty( const withChildrenProp = t.objectProperty(t.identifier('withChildren'), withChildrenArrowFn); addJSDocComment(withChildrenProp, [ `Invalidate ${singularName} and all child entities`, - `Cascades to: ${descendants.join(', ')}`, + `Cascades to: ${descendants.join(', ')}` ]); innerProperties.push(withChildrenProp); } @@ -397,7 +398,7 @@ export function generateInvalidationFile( 'invalidate.user.lists(queryClient);', '', '// Invalidate specific user', - 'invalidate.user.detail(queryClient, userId);', + 'invalidate.user.detail(queryClient, userId);' ]; if (generateCascadeHelpers && Object.keys(relationships).length > 0) { invalidateDocLines.push(''); @@ -426,7 +427,7 @@ export function generateInvalidationFile( 'Remove queries from cache (for delete operations)', '', 'Use these when an entity is deleted to remove it from cache', - 'instead of just invalidating (which would trigger a refetch).', + 'instead of just invalidating (which would trigger a refetch).' ]); statements.push(removeDecl); @@ -484,6 +485,6 @@ ${description} return { fileName: 'invalidation.ts', - content, + content }; } diff --git a/graphql/codegen/src/core/codegen/mutation-keys.ts b/graphql/codegen/src/core/codegen/mutation-keys.ts index 431d84fe3..5816e3ee1 100644 --- a/graphql/codegen/src/core/codegen/mutation-keys.ts +++ b/graphql/codegen/src/core/codegen/mutation-keys.ts @@ -7,17 +7,18 @@ * - Mutation deduplication * - Tracking mutation state with useIsMutating */ -import type { CleanTable, CleanOperation } from '../../types/schema'; -import type { QueryKeyConfig, EntityRelationship } from '../../types/config'; -import { getTableNames, getGeneratedFileHeader, lcFirst } from './utils'; import * as t from '@babel/types'; + +import type { EntityRelationship,QueryKeyConfig } from '../../types/config'; +import type { CleanOperation,CleanTable } from '../../types/schema'; import { - generateCode, addJSDocComment, asConst, constArray, - typedParam, + generateCode, + typedParam } from './babel-ast'; +import { getGeneratedFileHeader, getTableNames, lcFirst } from './utils'; export interface MutationKeyGeneratorOptions { tables: CleanTable[]; @@ -75,12 +76,12 @@ function generateEntityMutationKeysDeclaration( false, true ) - ]), + ]) ]), constArray([ t.stringLiteral('mutation'), t.stringLiteral(entityKey), - t.stringLiteral('create'), + t.stringLiteral('create') ]) ) ); @@ -92,7 +93,7 @@ function generateEntityMutationKeysDeclaration( constArray([ t.stringLiteral('mutation'), t.stringLiteral(entityKey), - t.stringLiteral('create'), + t.stringLiteral('create') ]) ); @@ -108,7 +109,7 @@ function generateEntityMutationKeysDeclaration( t.stringLiteral('mutation'), t.stringLiteral(entityKey), t.stringLiteral('update'), - t.identifier('id'), + t.identifier('id') ]) ); const updateProp = t.objectProperty(t.identifier('update'), updateArrowFn); @@ -122,7 +123,7 @@ function generateEntityMutationKeysDeclaration( t.stringLiteral('mutation'), t.stringLiteral(entityKey), t.stringLiteral('delete'), - t.identifier('id'), + t.identifier('id') ]) ); const deleteProp = t.objectProperty(t.identifier('delete'), deleteArrowFn); @@ -166,7 +167,7 @@ function generateCustomMutationKeysDeclaration( constArray([ t.stringLiteral('mutation'), t.stringLiteral(op.name), - t.identifier('identifier'), + t.identifier('identifier') ]), constArray([t.stringLiteral('mutation'), t.stringLiteral(op.name)]) ) @@ -243,7 +244,7 @@ function generateUnifiedMutationStoreDeclaration( '', '// Check if a specific user is being updated', 'const isUpdating = useIsMutating({ mutationKey: mutationKeys.user.update(userId) });', - '```', + '```' ]); return decl; @@ -335,6 +336,6 @@ ${description} return { fileName: 'mutation-keys.ts', - content, + content }; } diff --git a/graphql/codegen/src/core/codegen/mutations.ts b/graphql/codegen/src/core/codegen/mutations.ts index 0a3a75227..1edbbe07a 100644 --- a/graphql/codegen/src/core/codegen/mutations.ts +++ b/graphql/codegen/src/core/codegen/mutations.ts @@ -1,51 +1,62 @@ /** - * Mutation hook generators using Babel AST-based code generation + * Mutation hook generators - delegates to ORM model methods (Babel AST-based) * * Output structure: * mutations/ - * useCreateCarMutation.ts - * useUpdateCarMutation.ts - * useDeleteCarMutation.ts + * useCreateCarMutation.ts -> ORM create + * useUpdateCarMutation.ts -> ORM update + * useDeleteCarMutation.ts -> ORM delete */ -import type { CleanTable } from '../../types/schema'; import * as t from '@babel/types'; -import { generateCode, addJSDocComment, typedParam, createTypedCallExpression } from './babel-ast'; + +import type { CleanTable } from '../../types/schema'; +import { asConst } from './babel-ast'; import { - buildCreateMutationAST, - buildUpdateMutationAST, - buildDeleteMutationAST, - printGraphQL, -} from './gql-ast'; + addJSDocComment, + buildSelectionArgsCall, + callExpr, + constDecl, + createFunctionParam, + createImportDeclaration, + createSTypeParam, + createTypeReExport, + destructureParamsWithSelection, + exportDeclareFunction, + exportFunction, + generateHookFileCode, + getClientCallUnwrap, + inferSelectResultType, + objectProp, + omitType, + returnUseMutation, + selectionConfigType, + shorthandProp, + spreadObj, + sRef, + typeofRef, + typeRef, + typeLiteralWithProps, + useMutationOptionsType, + useMutationResultType, + voidStatement +} from './hooks-ast'; import { - getTableNames, - getCreateMutationHookName, - getUpdateMutationHookName, - getDeleteMutationHookName, getCreateMutationFileName, - getUpdateMutationFileName, - getDeleteMutationFileName, + getCreateMutationHookName, getCreateMutationName, - getUpdateMutationName, + getDefaultSelectFieldName, + getDeleteMutationFileName, + getDeleteMutationHookName, getDeleteMutationName, - getScalarFields, getPrimaryKeyInfo, - fieldTypeToTs, - ucFirst, - lcFirst, - getGeneratedFileHeader, + getTableNames, + getUpdateMutationFileName, + getUpdateMutationHookName, + getUpdateMutationName, + hasValidPrimaryKey, + lcFirst } from './utils'; -function isAutoGeneratedField(fieldName: string, pkFieldNames: Set): boolean { - const name = fieldName.toLowerCase(); - if (pkFieldNames.has(fieldName)) return true; - const timestampPatterns = [ - 'createdat', 'created_at', 'createddate', 'created_date', - 'updatedat', 'updated_at', 'updateddate', 'updated_date', - 'deletedat', 'deleted_at', - ]; - return timestampPatterns.includes(name); -} - export interface GeneratedMutationFile { fileName: string; content: string; @@ -53,11 +64,50 @@ export interface GeneratedMutationFile { export interface MutationGeneratorOptions { reactQueryEnabled?: boolean; - enumsFromSchemaTypes?: string[]; useCentralizedKeys?: boolean; - hasRelationships?: boolean; - /** All table type names for determining which types to import from types.ts vs schema-types.ts */ - tableTypeNames?: Set; +} + +function buildMutationResultType( + mutationName: string, + singularName: string, + relationTypeName: string, + selectType: t.TSType +): t.TSTypeLiteral { + return typeLiteralWithProps([{ + name: mutationName, + type: typeLiteralWithProps([{ + name: singularName, + type: inferSelectResultType(relationTypeName, selectType) + }]) + }]); +} + +function buildSelectFallback(selectTypeName: string): t.TSAsExpression { + return t.tsAsExpression( + t.parenthesizedExpression( + t.logicalExpression( + '??', + t.optionalMemberExpression(t.identifier('args'), t.identifier('select'), false, true), + t.identifier('defaultSelect') + ) + ), + typeRef(selectTypeName) + ); +} + +function buildFieldsSelectionType(s: t.TSType, selectTypeName: string): t.TSParenthesizedType { + return t.tsParenthesizedType( + t.tsIntersectionType([ + t.tsTypeLiteral([t.tsPropertySignature(t.identifier('fields'), t.tsTypeAnnotation(s))]), + typeRef('StrictSelect', [s, typeRef(selectTypeName)]) + ]) + ); +} + +function buildNoFieldsType(): t.TSParenthesizedType { + const fp = t.tsPropertySignature(t.identifier('fields'), t.tsTypeAnnotation(t.tsUndefinedKeyword())); + fp.optional = true; + return t.tsParenthesizedType(t.tsTypeLiteral([fp])); } export function generateCreateMutationHook( @@ -66,293 +116,156 @@ export function generateCreateMutationHook( ): GeneratedMutationFile | null { const { reactQueryEnabled = true, - enumsFromSchemaTypes = [], - useCentralizedKeys = true, - hasRelationships = false, - tableTypeNames = new Set(), + useCentralizedKeys = true } = options; - if (!reactQueryEnabled) { - return null; - } + if (!reactQueryEnabled) return null; - const enumSet = new Set(enumsFromSchemaTypes); const { typeName, singularName } = getTableNames(table); const hookName = getCreateMutationHookName(table); + const mutationName = getCreateMutationName(table); const keysName = `${lcFirst(typeName)}Keys`; const mutationKeysName = `${lcFirst(typeName)}MutationKeys`; - const scopeTypeName = `${typeName}Scope`; - const mutationName = getCreateMutationName(table); - const scalarFields = getScalarFields(table); - - const pkFieldNames = new Set(getPrimaryKeyInfo(table).map((pk) => pk.name)); - - const usedEnums = new Set(); - const usedTableTypes = new Set(); - for (const field of scalarFields) { - const cleanType = field.type.gqlType.replace(/!/g, ''); - if (enumSet.has(cleanType)) { - usedEnums.add(cleanType); - } else if (tableTypeNames.has(cleanType) && cleanType !== typeName) { - // Track table types used in scalar fields (excluding the main type which is already imported) - usedTableTypes.add(cleanType); - } - } - - const mutationAST = buildCreateMutationAST({ table }); - const mutationDocument = printGraphQL(mutationAST); + const selectTypeName = `${typeName}Select`; + const relationTypeName = `${typeName}WithRelations`; + const createInputTypeName = `Create${typeName}Input`; + const defaultFieldName = getDefaultSelectFieldName(table); const statements: t.Statement[] = []; - const reactQueryImport = t.importDeclaration( - [ - t.importSpecifier(t.identifier('useMutation'), t.identifier('useMutation')), - t.importSpecifier(t.identifier('useQueryClient'), t.identifier('useQueryClient')), - ], - t.stringLiteral('@tanstack/react-query') - ); - statements.push(reactQueryImport); + // Imports + statements.push(createImportDeclaration('@tanstack/react-query', ['useMutation', 'useQueryClient'])); + statements.push(createImportDeclaration('@tanstack/react-query', ['UseMutationOptions', 'UseMutationResult'], true)); + statements.push(createImportDeclaration('../client', ['getClient'])); + statements.push(createImportDeclaration('../selection', ['buildSelectionArgs'])); + statements.push(createImportDeclaration('../selection', ['SelectionConfig'], true)); - const reactQueryTypeImport = t.importDeclaration( - [t.importSpecifier(t.identifier('UseMutationOptions'), t.identifier('UseMutationOptions'))], - t.stringLiteral('@tanstack/react-query') - ); - reactQueryTypeImport.importKind = 'type'; - statements.push(reactQueryTypeImport); + if (useCentralizedKeys) { + statements.push(createImportDeclaration('../query-keys', [keysName])); + statements.push(createImportDeclaration('../mutation-keys', [mutationKeysName])); + } - const clientImport = t.importDeclaration( - [t.importSpecifier(t.identifier('execute'), t.identifier('execute'))], - t.stringLiteral('../client') - ); - statements.push(clientImport); + statements.push(createImportDeclaration('../../orm/input-types', [selectTypeName, relationTypeName, createInputTypeName], true)); + statements.push(createImportDeclaration('../../orm/select-types', ['InferSelectResult', 'StrictSelect'], true)); - // Import the main type and any other table types used in scalar fields - const allTypesToImport = [typeName, ...Array.from(usedTableTypes)].sort(); - const typesImport = t.importDeclaration( - allTypesToImport.map((t_) => t.importSpecifier(t.identifier(t_), t.identifier(t_))), - t.stringLiteral('../types') - ); - typesImport.importKind = 'type'; - statements.push(typesImport); - - if (usedEnums.size > 0) { - const enumImport = t.importDeclaration( - Array.from(usedEnums).sort().map((e) => t.importSpecifier(t.identifier(e), t.identifier(e))), - t.stringLiteral('../schema-types') - ); - enumImport.importKind = 'type'; - statements.push(enumImport); - } + // Re-exports + statements.push(createTypeReExport([selectTypeName, relationTypeName, createInputTypeName], '../../orm/input-types')); - if (useCentralizedKeys) { - const queryKeyImport = t.importDeclaration( - [t.importSpecifier(t.identifier(keysName), t.identifier(keysName))], - t.stringLiteral('../query-keys') - ); - statements.push(queryKeyImport); - if (hasRelationships) { - const scopeTypeImport = t.importDeclaration( - [t.importSpecifier(t.identifier(scopeTypeName), t.identifier(scopeTypeName))], - t.stringLiteral('../query-keys') - ); - scopeTypeImport.importKind = 'type'; - statements.push(scopeTypeImport); - } - const mutationKeyImport = t.importDeclaration( - [t.importSpecifier(t.identifier(mutationKeysName), t.identifier(mutationKeysName))], - t.stringLiteral('../mutation-keys') - ); - statements.push(mutationKeyImport); - } + // Default select + statements.push(constDecl('defaultSelect', asConst(t.objectExpression([objectProp(defaultFieldName, t.booleanLiteral(true))])))); - const reExportDecl = t.exportNamedDeclaration( - null, - [t.exportSpecifier(t.identifier(typeName), t.identifier(typeName))], - t.stringLiteral('../types') + // Variable type: CreateTypeName['singularName'] + const createVarType = t.tsIndexedAccessType( + typeRef(createInputTypeName), + t.tsLiteralType(t.stringLiteral(singularName)) ); - reExportDecl.exportKind = 'type'; - statements.push(reExportDecl); - - const mutationDocConst = t.variableDeclaration('const', [ - t.variableDeclarator( - t.identifier(`${mutationName}MutationDocument`), - t.templateLiteral( - [t.templateElement({ raw: '\n' + mutationDocument, cooked: '\n' + mutationDocument }, true)], - [] - ) - ), + + const resultType = (sel: t.TSType) => buildMutationResultType(mutationName, singularName, relationTypeName, sel); + + // Overload 1: with fields + const o1ParamType = t.tsIntersectionType([ + t.tsTypeLiteral([ + t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(buildFieldsSelectionType(sRef(), selectTypeName))) + ]), + useMutationOptionsType(resultType(sRef()), createVarType) ]); - statements.push(t.exportNamedDeclaration(mutationDocConst)); - - const inputFields = scalarFields - .filter((f) => !isAutoGeneratedField(f.name, pkFieldNames)) - .map((f) => { - const prop = t.tsPropertySignature( - t.identifier(f.name), - t.tsTypeAnnotation( - t.tsUnionType([ - t.tsTypeReference(t.identifier(fieldTypeToTs(f.type))), - t.tsNullKeyword(), - ]) - ) - ); - prop.optional = true; - return prop; - }); - - const createInputInterface = t.tsInterfaceDeclaration( - t.identifier(`${typeName}CreateInput`), - null, - null, - t.tsInterfaceBody(inputFields) + const o1 = exportDeclareFunction( + hookName, + createSTypeParam(selectTypeName), + [createFunctionParam('params', o1ParamType)], + useMutationResultType(resultType(sRef()), createVarType) ); - addJSDocComment(createInputInterface, [`Input type for creating a ${typeName}`]); - statements.push(createInputInterface); - - const variablesInterfaceBody = t.tsInterfaceBody([ - t.tsPropertySignature( - t.identifier('input'), - t.tsTypeAnnotation( - t.tsTypeLiteral([ - t.tsPropertySignature( - t.identifier(lcFirst(typeName)), - t.tsTypeAnnotation(t.tsTypeReference(t.identifier(`${typeName}CreateInput`))) - ), - ]) - ) - ), + addJSDocComment(o1, [ + `Mutation hook for creating a ${typeName}`, + '', + '@example', + '```tsx', + `const { mutate, isPending } = ${hookName}({`, + ' selection: { fields: { id: true, name: true } },', + '});', + '', + "mutate({ name: 'New item' });", + '```' ]); - const variablesInterface = t.tsInterfaceDeclaration( - t.identifier(`${ucFirst(mutationName)}MutationVariables`), - null, - null, - variablesInterfaceBody - ); - statements.push(t.exportNamedDeclaration(variablesInterface)); - - const resultInterfaceBody = t.tsInterfaceBody([ - t.tsPropertySignature( - t.identifier(mutationName), - t.tsTypeAnnotation( - t.tsTypeLiteral([ - t.tsPropertySignature( - t.identifier(singularName), - t.tsTypeAnnotation(t.tsTypeReference(t.identifier(typeName))) - ), - ]) - ) - ), + statements.push(o1); + + // Overload 2: without fields + const o2SelProp = t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(buildNoFieldsType())); + o2SelProp.optional = true; + const o2ParamType = t.tsIntersectionType([ + t.tsTypeLiteral([o2SelProp]), + useMutationOptionsType(resultType(typeofRef('defaultSelect')), createVarType) ]); - const resultInterface = t.tsInterfaceDeclaration( - t.identifier(`${ucFirst(mutationName)}MutationResult`), - null, - null, - resultInterfaceBody - ); - statements.push(t.exportNamedDeclaration(resultInterface)); - - const hookBodyStatements: t.Statement[] = []; - hookBodyStatements.push( - t.variableDeclaration('const', [ - t.variableDeclarator( - t.identifier('queryClient'), - t.callExpression(t.identifier('useQueryClient'), []) - ), - ]) + statements.push( + exportDeclareFunction( + hookName, + null, + [createFunctionParam('params', o2ParamType, true)], + useMutationResultType(resultType(typeofRef('defaultSelect')), createVarType) + ) ); - const mutationOptions: (t.ObjectProperty | t.SpreadElement)[] = []; - if (useCentralizedKeys) { - mutationOptions.push( - t.objectProperty( - t.identifier('mutationKey'), - t.callExpression( - t.memberExpression(t.identifier(mutationKeysName), t.identifier('create')), - [] - ) - ) - ); - } - mutationOptions.push( - t.objectProperty( - t.identifier('mutationFn'), - t.arrowFunctionExpression( - [typedParam('variables', t.tsTypeReference(t.identifier(`${ucFirst(mutationName)}MutationVariables`)))], - createTypedCallExpression( - t.identifier('execute'), - [t.identifier(`${mutationName}MutationDocument`), t.identifier('variables')], - [ - t.tsTypeReference(t.identifier(`${ucFirst(mutationName)}MutationResult`)), - t.tsTypeReference(t.identifier(`${ucFirst(mutationName)}MutationVariables`)), - ] - ) - ) - ) - ); + // Implementation + const implSelProp = t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(selectionConfigType(typeRef(selectTypeName)))); + implSelProp.optional = true; + const implParamType = t.tsIntersectionType([ + t.tsTypeLiteral([implSelProp]), + omitType(typeRef('UseMutationOptions', [t.tsAnyKeyword(), typeRef('Error'), createVarType]), ['mutationFn']) + ]); - const invalidateQueryKey = useCentralizedKeys - ? t.callExpression(t.memberExpression(t.identifier(keysName), t.identifier('lists')), []) + const body: t.Statement[] = []; + body.push(buildSelectionArgsCall(selectTypeName)); + body.push(destructureParamsWithSelection('mutationOptions')); + body.push(voidStatement('_selection')); + body.push(constDecl('queryClient', callExpr('useQueryClient', []))); + + const mutationKeyExpr = useCentralizedKeys + ? callExpr(t.memberExpression(t.identifier(mutationKeysName), t.identifier('create')), []) + : undefined; + + // mutationFn: (data: CreateInput['singular']) => getClient().singular.create({ data, select: ... }).unwrap() + const dataParam = createFunctionParam('data', createVarType); + const mutationFnExpr = t.arrowFunctionExpression( + [dataParam], + getClientCallUnwrap(singularName, 'create', t.objectExpression([ + shorthandProp('data'), + objectProp('select', buildSelectFallback(selectTypeName)) + ])) + ); + + // onSuccess: invalidate lists + const listKeyExpr = useCentralizedKeys + ? callExpr(t.memberExpression(t.identifier(keysName), t.identifier('lists')), []) : t.arrayExpression([t.stringLiteral(typeName.toLowerCase()), t.stringLiteral('list')]); - mutationOptions.push( - t.objectProperty( - t.identifier('onSuccess'), - t.arrowFunctionExpression( - [], - t.blockStatement([ - t.expressionStatement( - t.callExpression( - t.memberExpression(t.identifier('queryClient'), t.identifier('invalidateQueries')), - [t.objectExpression([t.objectProperty(t.identifier('queryKey'), invalidateQueryKey)])] - ) - ), - ]) + const onSuccessFn = t.arrowFunctionExpression( + [], + t.blockStatement([ + t.expressionStatement( + callExpr( + t.memberExpression(t.identifier('queryClient'), t.identifier('invalidateQueries')), + [t.objectExpression([objectProp('queryKey', listKeyExpr)])] + ) ) - ) + ]) ); - mutationOptions.push(t.spreadElement(t.identifier('options'))); - hookBodyStatements.push( - t.returnStatement( - t.callExpression(t.identifier('useMutation'), [t.objectExpression(mutationOptions)]) + body.push( + returnUseMutation( + mutationFnExpr, + [ + objectProp('onSuccess', onSuccessFn), + spreadObj(t.identifier('mutationOptions')) + ], + mutationKeyExpr ) ); - const optionsTypeStr = `Omit, 'mutationFn'>`; - const optionsParam = t.identifier('options'); - optionsParam.optional = true; - optionsParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier(optionsTypeStr))); - - const hookFunc = t.functionDeclaration( - t.identifier(hookName), - [optionsParam], - t.blockStatement(hookBodyStatements) - ); - const hookExport = t.exportNamedDeclaration(hookFunc); - addJSDocComment(hookExport, [ - `Mutation hook for creating a ${typeName}`, - '', - '@example', - '```tsx', - `const { mutate, isPending } = ${hookName}();`, - '', - 'mutate({', - ' input: {', - ` ${lcFirst(typeName)}: {`, - ' // ... fields', - ' },', - ' },', - '});', - '```', - ]); - statements.push(hookExport); - - const code = generateCode(statements); - const content = getGeneratedFileHeader(`Create mutation hook for ${typeName}`) + '\n\n' + code; + statements.push(exportFunction(hookName, null, [createFunctionParam('params', implParamType, true)], body)); return { fileName: getCreateMutationFileName(table), - content, + content: generateHookFileCode(`Create mutation hook for ${typeName}`, statements) }; } @@ -362,321 +275,181 @@ export function generateUpdateMutationHook( ): GeneratedMutationFile | null { const { reactQueryEnabled = true, - enumsFromSchemaTypes = [], - useCentralizedKeys = true, - hasRelationships = false, - tableTypeNames = new Set(), + useCentralizedKeys = true } = options; - if (!reactQueryEnabled) { - return null; - } - - if (table.query?.update === null) { - return null; - } + if (!reactQueryEnabled) return null; + if (table.query?.update === null) return null; + if (!hasValidPrimaryKey(table)) return null; - const enumSet = new Set(enumsFromSchemaTypes); const { typeName, singularName } = getTableNames(table); const hookName = getUpdateMutationHookName(table); const mutationName = getUpdateMutationName(table); - const scalarFields = getScalarFields(table); const keysName = `${lcFirst(typeName)}Keys`; const mutationKeysName = `${lcFirst(typeName)}MutationKeys`; - const scopeTypeName = `${typeName}Scope`; + const selectTypeName = `${typeName}Select`; + const relationTypeName = `${typeName}WithRelations`; + const patchTypeName = `${typeName}Patch`; const pkFields = getPrimaryKeyInfo(table); const pkField = pkFields[0]; - const pkFieldNames = new Set(pkFields.map((pk) => pk.name)); - - const usedEnums = new Set(); - const usedTableTypes = new Set(); - for (const field of scalarFields) { - const cleanType = field.type.gqlType.replace(/!/g, ''); - if (enumSet.has(cleanType)) { - usedEnums.add(cleanType); - } else if (tableTypeNames.has(cleanType) && cleanType !== typeName) { - usedTableTypes.add(cleanType); - } - } - const mutationAST = buildUpdateMutationAST({ table }); - const mutationDocument = printGraphQL(mutationAST); + const pkTsType = pkField.tsType === 'string' ? t.tsStringKeyword() : t.tsNumberKeyword(); const statements: t.Statement[] = []; - const reactQueryImport = t.importDeclaration( - [ - t.importSpecifier(t.identifier('useMutation'), t.identifier('useMutation')), - t.importSpecifier(t.identifier('useQueryClient'), t.identifier('useQueryClient')), - ], - t.stringLiteral('@tanstack/react-query') - ); - statements.push(reactQueryImport); + // Imports + statements.push(createImportDeclaration('@tanstack/react-query', ['useMutation', 'useQueryClient'])); + statements.push(createImportDeclaration('@tanstack/react-query', ['UseMutationOptions', 'UseMutationResult'], true)); + statements.push(createImportDeclaration('../client', ['getClient'])); + statements.push(createImportDeclaration('../selection', ['buildSelectionArgs'])); + statements.push(createImportDeclaration('../selection', ['SelectionConfig'], true)); - const reactQueryTypeImport = t.importDeclaration( - [t.importSpecifier(t.identifier('UseMutationOptions'), t.identifier('UseMutationOptions'))], - t.stringLiteral('@tanstack/react-query') - ); - reactQueryTypeImport.importKind = 'type'; - statements.push(reactQueryTypeImport); + if (useCentralizedKeys) { + statements.push(createImportDeclaration('../query-keys', [keysName])); + statements.push(createImportDeclaration('../mutation-keys', [mutationKeysName])); + } - const clientImport = t.importDeclaration( - [t.importSpecifier(t.identifier('execute'), t.identifier('execute'))], - t.stringLiteral('../client') - ); - statements.push(clientImport); + statements.push(createImportDeclaration('../../orm/input-types', [selectTypeName, relationTypeName, patchTypeName], true)); + statements.push(createImportDeclaration('../../orm/select-types', ['InferSelectResult', 'StrictSelect'], true)); - // Import the main type and any other table types used in scalar fields - const allTypesToImportUpdate = [typeName, ...Array.from(usedTableTypes)].sort(); - const typesImport = t.importDeclaration( - allTypesToImportUpdate.map((t_) => t.importSpecifier(t.identifier(t_), t.identifier(t_))), - t.stringLiteral('../types') - ); - typesImport.importKind = 'type'; - statements.push(typesImport); - - if (usedEnums.size > 0) { - const enumImport = t.importDeclaration( - Array.from(usedEnums).sort().map((e) => t.importSpecifier(t.identifier(e), t.identifier(e))), - t.stringLiteral('../schema-types') - ); - enumImport.importKind = 'type'; - statements.push(enumImport); - } + // Re-exports + statements.push(createTypeReExport([selectTypeName, relationTypeName, patchTypeName], '../../orm/input-types')); - if (useCentralizedKeys) { - const queryKeyImport = t.importDeclaration( - [t.importSpecifier(t.identifier(keysName), t.identifier(keysName))], - t.stringLiteral('../query-keys') - ); - statements.push(queryKeyImport); - if (hasRelationships) { - const scopeTypeImport = t.importDeclaration( - [t.importSpecifier(t.identifier(scopeTypeName), t.identifier(scopeTypeName))], - t.stringLiteral('../query-keys') - ); - scopeTypeImport.importKind = 'type'; - statements.push(scopeTypeImport); - } - const mutationKeyImport = t.importDeclaration( - [t.importSpecifier(t.identifier(mutationKeysName), t.identifier(mutationKeysName))], - t.stringLiteral('../mutation-keys') - ); - statements.push(mutationKeyImport); - } + // Default select + statements.push(constDecl('defaultSelect', asConst(t.objectExpression([objectProp(pkField.name, t.booleanLiteral(true))])))); - const reExportDecl = t.exportNamedDeclaration( - null, - [t.exportSpecifier(t.identifier(typeName), t.identifier(typeName))], - t.stringLiteral('../types') - ); - reExportDecl.exportKind = 'type'; - statements.push(reExportDecl); - - const mutationDocConst = t.variableDeclaration('const', [ - t.variableDeclarator( - t.identifier(`${mutationName}MutationDocument`), - t.templateLiteral( - [t.templateElement({ raw: '\n' + mutationDocument, cooked: '\n' + mutationDocument }, true)], - [] - ) - ), + // Variable type: { pkField: type; patch: PatchType } + const updateVarType = t.tsTypeLiteral([ + t.tsPropertySignature(t.identifier(pkField.name), t.tsTypeAnnotation(pkTsType)), + t.tsPropertySignature(t.identifier('patch'), t.tsTypeAnnotation(typeRef(patchTypeName))) ]); - statements.push(t.exportNamedDeclaration(mutationDocConst)); - - const patchFields = scalarFields - .filter((f) => !pkFieldNames.has(f.name)) - .map((f) => { - const prop = t.tsPropertySignature( - t.identifier(f.name), - t.tsTypeAnnotation( - t.tsUnionType([ - t.tsTypeReference(t.identifier(fieldTypeToTs(f.type))), - t.tsNullKeyword(), - ]) - ) - ); - prop.optional = true; - return prop; - }); - - const patchInterface = t.tsInterfaceDeclaration( - t.identifier(`${typeName}Patch`), - null, - null, - t.tsInterfaceBody(patchFields) - ); - addJSDocComment(patchInterface, [`Patch type for updating a ${typeName} - all fields optional`]); - statements.push(patchInterface); - - const pkTypeAnnotation = - pkField.tsType === 'string' - ? t.tsStringKeyword() - : pkField.tsType === 'number' - ? t.tsNumberKeyword() - : t.tsTypeReference(t.identifier(pkField.tsType)); - - const variablesInterfaceBody = t.tsInterfaceBody([ - t.tsPropertySignature( - t.identifier('input'), - t.tsTypeAnnotation( - t.tsTypeLiteral([ - t.tsPropertySignature(t.identifier(pkField.name), t.tsTypeAnnotation(pkTypeAnnotation)), - t.tsPropertySignature( - t.identifier('patch'), - t.tsTypeAnnotation(t.tsTypeReference(t.identifier(`${typeName}Patch`))) - ), - ]) - ) - ), + + const resultType = (sel: t.TSType) => buildMutationResultType(mutationName, singularName, relationTypeName, sel); + + // Overload 1: with fields + const o1ParamType = t.tsIntersectionType([ + t.tsTypeLiteral([ + t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(buildFieldsSelectionType(sRef(), selectTypeName))) + ]), + useMutationOptionsType(resultType(sRef()), updateVarType) ]); - const variablesInterface = t.tsInterfaceDeclaration( - t.identifier(`${ucFirst(mutationName)}MutationVariables`), - null, - null, - variablesInterfaceBody + const o1 = exportDeclareFunction( + hookName, + createSTypeParam(selectTypeName), + [createFunctionParam('params', o1ParamType)], + useMutationResultType(resultType(sRef()), updateVarType) ); - statements.push(t.exportNamedDeclaration(variablesInterface)); - - const resultInterfaceBody = t.tsInterfaceBody([ - t.tsPropertySignature( - t.identifier(mutationName), - t.tsTypeAnnotation( - t.tsTypeLiteral([ - t.tsPropertySignature( - t.identifier(singularName), - t.tsTypeAnnotation(t.tsTypeReference(t.identifier(typeName))) - ), - ]) - ) - ), + addJSDocComment(o1, [ + `Mutation hook for updating a ${typeName}`, + '', + '@example', + '```tsx', + `const { mutate, isPending } = ${hookName}({`, + ' selection: { fields: { id: true, name: true } },', + '});', + '', + `mutate({ ${pkField.name}: 'value-here', patch: { name: 'Updated' } });`, + '```' ]); - const resultInterface = t.tsInterfaceDeclaration( - t.identifier(`${ucFirst(mutationName)}MutationResult`), - null, - null, - resultInterfaceBody - ); - statements.push(t.exportNamedDeclaration(resultInterface)); - - const hookBodyStatements: t.Statement[] = []; - hookBodyStatements.push( - t.variableDeclaration('const', [ - t.variableDeclarator( - t.identifier('queryClient'), - t.callExpression(t.identifier('useQueryClient'), []) - ), - ]) - ); - - const mutationOptions: (t.ObjectProperty | t.SpreadElement)[] = []; - if (useCentralizedKeys) { - mutationOptions.push( - t.objectProperty( - t.identifier('mutationKey'), - t.memberExpression(t.identifier(mutationKeysName), t.identifier('all')) - ) - ); - } - mutationOptions.push( - t.objectProperty( - t.identifier('mutationFn'), - t.arrowFunctionExpression( - [typedParam('variables', t.tsTypeReference(t.identifier(`${ucFirst(mutationName)}MutationVariables`)))], - createTypedCallExpression( - t.identifier('execute'), - [t.identifier(`${mutationName}MutationDocument`), t.identifier('variables')], - [ - t.tsTypeReference(t.identifier(`${ucFirst(mutationName)}MutationResult`)), - t.tsTypeReference(t.identifier(`${ucFirst(mutationName)}MutationVariables`)), - ] - ) - ) + statements.push(o1); + + // Overload 2: without fields + const o2SelProp = t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(buildNoFieldsType())); + o2SelProp.optional = true; + const o2ParamType = t.tsIntersectionType([ + t.tsTypeLiteral([o2SelProp]), + useMutationOptionsType(resultType(typeofRef('defaultSelect')), updateVarType) + ]); + statements.push( + exportDeclareFunction( + hookName, + null, + [createFunctionParam('params', o2ParamType, true)], + useMutationResultType(resultType(typeofRef('defaultSelect')), updateVarType) ) ); - const detailQueryKey = useCentralizedKeys - ? t.callExpression( - t.memberExpression(t.identifier(keysName), t.identifier('detail')), - [t.memberExpression(t.memberExpression(t.identifier('variables'), t.identifier('input')), t.identifier(pkField.name))] - ) - : t.arrayExpression([ - t.stringLiteral(typeName.toLowerCase()), - t.stringLiteral('detail'), - t.memberExpression(t.memberExpression(t.identifier('variables'), t.identifier('input')), t.identifier(pkField.name)), - ]); - - const listQueryKey = useCentralizedKeys - ? t.callExpression(t.memberExpression(t.identifier(keysName), t.identifier('lists')), []) + // Implementation + const implSelProp = t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(selectionConfigType(typeRef(selectTypeName)))); + implSelProp.optional = true; + const implParamType = t.tsIntersectionType([ + t.tsTypeLiteral([implSelProp]), + omitType(typeRef('UseMutationOptions', [t.tsAnyKeyword(), typeRef('Error'), updateVarType]), ['mutationFn']) + ]); + + const body: t.Statement[] = []; + body.push(buildSelectionArgsCall(selectTypeName)); + body.push(destructureParamsWithSelection('mutationOptions')); + body.push(voidStatement('_selection')); + body.push(constDecl('queryClient', callExpr('useQueryClient', []))); + + const mutationKeyExpr = useCentralizedKeys + ? t.memberExpression(t.identifier(mutationKeysName), t.identifier('all')) + : undefined; + + // mutationFn: ({ pkField, patch }: { pkField: type; patch: PatchType }) => + // getClient().singular.update({ where: { pkField }, data: patch, select: ... }).unwrap() + const destructParam = t.objectPattern([ + shorthandProp(pkField.name), + shorthandProp('patch') + ]); + destructParam.typeAnnotation = t.tsTypeAnnotation(updateVarType); + const mutationFnExpr = t.arrowFunctionExpression( + [destructParam], + getClientCallUnwrap(singularName, 'update', t.objectExpression([ + objectProp('where', t.objectExpression([shorthandProp(pkField.name)])), + objectProp('data', t.identifier('patch')), + objectProp('select', buildSelectFallback(selectTypeName)) + ])) + ); + + // onSuccess: invalidate detail and lists + const detailKeyExpr = useCentralizedKeys + ? callExpr(t.memberExpression(t.identifier(keysName), t.identifier('detail')), [ + t.memberExpression(t.identifier('variables'), t.identifier(pkField.name)) + ]) + : t.arrayExpression([t.stringLiteral(typeName.toLowerCase()), t.stringLiteral('detail'), t.memberExpression(t.identifier('variables'), t.identifier(pkField.name))]); + const listKeyExpr = useCentralizedKeys + ? callExpr(t.memberExpression(t.identifier(keysName), t.identifier('lists')), []) : t.arrayExpression([t.stringLiteral(typeName.toLowerCase()), t.stringLiteral('list')]); - mutationOptions.push( - t.objectProperty( - t.identifier('onSuccess'), - t.arrowFunctionExpression( - [t.identifier('_'), t.identifier('variables')], - t.blockStatement([ - t.expressionStatement( - t.callExpression( - t.memberExpression(t.identifier('queryClient'), t.identifier('invalidateQueries')), - [t.objectExpression([t.objectProperty(t.identifier('queryKey'), detailQueryKey)])] - ) - ), - t.expressionStatement( - t.callExpression( - t.memberExpression(t.identifier('queryClient'), t.identifier('invalidateQueries')), - [t.objectExpression([t.objectProperty(t.identifier('queryKey'), listQueryKey)])] - ) - ), - ]) + const onSuccessParam = t.identifier('_'); + const variablesParam = t.identifier('variables'); + const onSuccessFn = t.arrowFunctionExpression( + [onSuccessParam, variablesParam], + t.blockStatement([ + t.expressionStatement( + callExpr( + t.memberExpression(t.identifier('queryClient'), t.identifier('invalidateQueries')), + [t.objectExpression([objectProp('queryKey', detailKeyExpr)])] + ) + ), + t.expressionStatement( + callExpr( + t.memberExpression(t.identifier('queryClient'), t.identifier('invalidateQueries')), + [t.objectExpression([objectProp('queryKey', listKeyExpr)])] + ) ) - ) + ]) ); - mutationOptions.push(t.spreadElement(t.identifier('options'))); - hookBodyStatements.push( - t.returnStatement( - t.callExpression(t.identifier('useMutation'), [t.objectExpression(mutationOptions)]) + body.push( + returnUseMutation( + mutationFnExpr, + [ + objectProp('onSuccess', onSuccessFn), + spreadObj(t.identifier('mutationOptions')) + ], + mutationKeyExpr ) ); - const optionsTypeStr = `Omit, 'mutationFn'>`; - const optionsParam = t.identifier('options'); - optionsParam.optional = true; - optionsParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier(optionsTypeStr))); - - const hookFunc = t.functionDeclaration( - t.identifier(hookName), - [optionsParam], - t.blockStatement(hookBodyStatements) - ); - const hookExport = t.exportNamedDeclaration(hookFunc); - addJSDocComment(hookExport, [ - `Mutation hook for updating a ${typeName}`, - '', - '@example', - '```tsx', - `const { mutate, isPending } = ${hookName}();`, - '', - 'mutate({', - ' input: {', - ` ${pkField.name}: ${pkField.tsType === 'string' ? "'value-here'" : '123'},`, - ' patch: {', - ' // ... fields to update', - ' },', - ' },', - '});', - '```', - ]); - statements.push(hookExport); - - const code = generateCode(statements); - const content = getGeneratedFileHeader(`Update mutation hook for ${typeName}`) + '\n\n' + code; + statements.push(exportFunction(hookName, null, [createFunctionParam('params', implParamType, true)], body)); return { fileName: getUpdateMutationFileName(table), - content, + content: generateHookFileCode(`Update mutation hook for ${typeName}`, statements) }; } @@ -686,245 +459,173 @@ export function generateDeleteMutationHook( ): GeneratedMutationFile | null { const { reactQueryEnabled = true, - useCentralizedKeys = true, - hasRelationships = false, + useCentralizedKeys = true } = options; - if (!reactQueryEnabled) { - return null; - } - - if (table.query?.delete === null) { - return null; - } + if (!reactQueryEnabled) return null; + if (table.query?.delete === null) return null; + if (!hasValidPrimaryKey(table)) return null; - const { typeName } = getTableNames(table); + const { typeName, singularName } = getTableNames(table); const hookName = getDeleteMutationHookName(table); const mutationName = getDeleteMutationName(table); const keysName = `${lcFirst(typeName)}Keys`; const mutationKeysName = `${lcFirst(typeName)}MutationKeys`; - const scopeTypeName = `${typeName}Scope`; + const selectTypeName = `${typeName}Select`; + const relationTypeName = `${typeName}WithRelations`; const pkFields = getPrimaryKeyInfo(table); const pkField = pkFields[0]; - const mutationAST = buildDeleteMutationAST({ table }); - const mutationDocument = printGraphQL(mutationAST); + const pkTsType = pkField.tsType === 'string' ? t.tsStringKeyword() : t.tsNumberKeyword(); const statements: t.Statement[] = []; - const reactQueryImport = t.importDeclaration( - [ - t.importSpecifier(t.identifier('useMutation'), t.identifier('useMutation')), - t.importSpecifier(t.identifier('useQueryClient'), t.identifier('useQueryClient')), - ], - t.stringLiteral('@tanstack/react-query') - ); - statements.push(reactQueryImport); - - const reactQueryTypeImport = t.importDeclaration( - [t.importSpecifier(t.identifier('UseMutationOptions'), t.identifier('UseMutationOptions'))], - t.stringLiteral('@tanstack/react-query') - ); - reactQueryTypeImport.importKind = 'type'; - statements.push(reactQueryTypeImport); - - const clientImport = t.importDeclaration( - [t.importSpecifier(t.identifier('execute'), t.identifier('execute'))], - t.stringLiteral('../client') - ); - statements.push(clientImport); + // Imports + statements.push(createImportDeclaration('@tanstack/react-query', ['useMutation', 'useQueryClient'])); + statements.push(createImportDeclaration('@tanstack/react-query', ['UseMutationOptions', 'UseMutationResult'], true)); + statements.push(createImportDeclaration('../client', ['getClient'])); + statements.push(createImportDeclaration('../selection', ['buildSelectionArgs'])); + statements.push(createImportDeclaration('../selection', ['SelectionConfig'], true)); if (useCentralizedKeys) { - const queryKeyImport = t.importDeclaration( - [t.importSpecifier(t.identifier(keysName), t.identifier(keysName))], - t.stringLiteral('../query-keys') - ); - statements.push(queryKeyImport); - if (hasRelationships) { - const scopeTypeImport = t.importDeclaration( - [t.importSpecifier(t.identifier(scopeTypeName), t.identifier(scopeTypeName))], - t.stringLiteral('../query-keys') - ); - scopeTypeImport.importKind = 'type'; - statements.push(scopeTypeImport); - } - const mutationKeyImport = t.importDeclaration( - [t.importSpecifier(t.identifier(mutationKeysName), t.identifier(mutationKeysName))], - t.stringLiteral('../mutation-keys') - ); - statements.push(mutationKeyImport); + statements.push(createImportDeclaration('../query-keys', [keysName])); + statements.push(createImportDeclaration('../mutation-keys', [mutationKeysName])); } - const mutationDocConst = t.variableDeclaration('const', [ - t.variableDeclarator( - t.identifier(`${mutationName}MutationDocument`), - t.templateLiteral( - [t.templateElement({ raw: '\n' + mutationDocument, cooked: '\n' + mutationDocument }, true)], - [] - ) - ), - ]); - statements.push(t.exportNamedDeclaration(mutationDocConst)); - - const pkTypeAnnotation = - pkField.tsType === 'string' - ? t.tsStringKeyword() - : pkField.tsType === 'number' - ? t.tsNumberKeyword() - : t.tsTypeReference(t.identifier(pkField.tsType)); - - const variablesInterfaceBody = t.tsInterfaceBody([ - t.tsPropertySignature( - t.identifier('input'), - t.tsTypeAnnotation( - t.tsTypeLiteral([ - t.tsPropertySignature(t.identifier(pkField.name), t.tsTypeAnnotation(pkTypeAnnotation)), - ]) - ) - ), + statements.push(createImportDeclaration('../../orm/input-types', [selectTypeName, relationTypeName], true)); + statements.push(createImportDeclaration('../../orm/select-types', ['InferSelectResult', 'StrictSelect'], true)); + + // Re-exports + statements.push(createTypeReExport([selectTypeName, relationTypeName], '../../orm/input-types')); + + // Default select + statements.push(constDecl('defaultSelect', asConst(t.objectExpression([objectProp(pkField.name, t.booleanLiteral(true))])))); + + // Variable type: { pkField: type } + const deleteVarType = t.tsTypeLiteral([ + t.tsPropertySignature(t.identifier(pkField.name), t.tsTypeAnnotation(pkTsType)) ]); - const variablesInterface = t.tsInterfaceDeclaration( - t.identifier(`${ucFirst(mutationName)}MutationVariables`), - null, - null, - variablesInterfaceBody - ); - statements.push(t.exportNamedDeclaration(variablesInterface)); - const clientMutationIdProp = t.tsPropertySignature( - t.identifier('clientMutationId'), - t.tsTypeAnnotation(t.tsUnionType([t.tsStringKeyword(), t.tsNullKeyword()])) - ); + const resultType = (sel: t.TSType) => buildMutationResultType(mutationName, singularName, relationTypeName, sel); - const resultInterfaceBody = t.tsInterfaceBody([ - t.tsPropertySignature( - t.identifier(mutationName), - t.tsTypeAnnotation(t.tsTypeLiteral([clientMutationIdProp])) - ), + // Overload 1: with fields + const o1ParamType = t.tsIntersectionType([ + t.tsTypeLiteral([ + t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(buildFieldsSelectionType(sRef(), selectTypeName))) + ]), + useMutationOptionsType(resultType(sRef()), deleteVarType) ]); - const resultInterface = t.tsInterfaceDeclaration( - t.identifier(`${ucFirst(mutationName)}MutationResult`), - null, - null, - resultInterfaceBody + const o1 = exportDeclareFunction( + hookName, + createSTypeParam(selectTypeName), + [createFunctionParam('params', o1ParamType)], + useMutationResultType(resultType(sRef()), deleteVarType) ); - statements.push(t.exportNamedDeclaration(resultInterface)); - - const hookBodyStatements: t.Statement[] = []; - hookBodyStatements.push( - t.variableDeclaration('const', [ - t.variableDeclarator( - t.identifier('queryClient'), - t.callExpression(t.identifier('useQueryClient'), []) - ), - ]) - ); - - const mutationOptions: (t.ObjectProperty | t.SpreadElement)[] = []; - if (useCentralizedKeys) { - mutationOptions.push( - t.objectProperty( - t.identifier('mutationKey'), - t.memberExpression(t.identifier(mutationKeysName), t.identifier('all')) - ) - ); - } - mutationOptions.push( - t.objectProperty( - t.identifier('mutationFn'), - t.arrowFunctionExpression( - [typedParam('variables', t.tsTypeReference(t.identifier(`${ucFirst(mutationName)}MutationVariables`)))], - createTypedCallExpression( - t.identifier('execute'), - [t.identifier(`${mutationName}MutationDocument`), t.identifier('variables')], - [ - t.tsTypeReference(t.identifier(`${ucFirst(mutationName)}MutationResult`)), - t.tsTypeReference(t.identifier(`${ucFirst(mutationName)}MutationVariables`)), - ] - ) - ) + addJSDocComment(o1, [ + `Mutation hook for deleting a ${typeName}`, + '', + '@example', + '```tsx', + `const { mutate, isPending } = ${hookName}({`, + ' selection: { fields: { id: true } },', + '});', + '', + `mutate({ ${pkField.name}: ${pkField.tsType === 'string' ? "'value-to-delete'" : '123'} });`, + '```' + ]); + statements.push(o1); + + // Overload 2: without fields + const o2SelProp = t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(buildNoFieldsType())); + o2SelProp.optional = true; + const o2ParamType = t.tsIntersectionType([ + t.tsTypeLiteral([o2SelProp]), + useMutationOptionsType(resultType(typeofRef('defaultSelect')), deleteVarType) + ]); + statements.push( + exportDeclareFunction( + hookName, + null, + [createFunctionParam('params', o2ParamType, true)], + useMutationResultType(resultType(typeofRef('defaultSelect')), deleteVarType) ) ); - const detailQueryKey = useCentralizedKeys - ? t.callExpression( - t.memberExpression(t.identifier(keysName), t.identifier('detail')), - [t.memberExpression(t.memberExpression(t.identifier('variables'), t.identifier('input')), t.identifier(pkField.name))] - ) - : t.arrayExpression([ - t.stringLiteral(typeName.toLowerCase()), - t.stringLiteral('detail'), - t.memberExpression(t.memberExpression(t.identifier('variables'), t.identifier('input')), t.identifier(pkField.name)), - ]); - - const listQueryKey = useCentralizedKeys - ? t.callExpression(t.memberExpression(t.identifier(keysName), t.identifier('lists')), []) + // Implementation + const implSelProp = t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(selectionConfigType(typeRef(selectTypeName)))); + implSelProp.optional = true; + const implParamType = t.tsIntersectionType([ + t.tsTypeLiteral([implSelProp]), + omitType(typeRef('UseMutationOptions', [t.tsAnyKeyword(), typeRef('Error'), deleteVarType]), ['mutationFn']) + ]); + + const body: t.Statement[] = []; + body.push(buildSelectionArgsCall(selectTypeName)); + body.push(destructureParamsWithSelection('mutationOptions')); + body.push(voidStatement('_selection')); + body.push(constDecl('queryClient', callExpr('useQueryClient', []))); + + const mutationKeyExpr = useCentralizedKeys + ? t.memberExpression(t.identifier(mutationKeysName), t.identifier('all')) + : undefined; + + // mutationFn: ({ pkField }: { pkField: type }) => + // getClient().singular.delete({ where: { pkField }, select: ... }).unwrap() + const destructParam = t.objectPattern([shorthandProp(pkField.name)]); + destructParam.typeAnnotation = t.tsTypeAnnotation(deleteVarType); + const mutationFnExpr = t.arrowFunctionExpression( + [destructParam], + getClientCallUnwrap(singularName, 'delete', t.objectExpression([ + objectProp('where', t.objectExpression([shorthandProp(pkField.name)])), + objectProp('select', buildSelectFallback(selectTypeName)) + ])) + ); + + // onSuccess: remove detail, invalidate lists + const detailKeyExpr = useCentralizedKeys + ? callExpr(t.memberExpression(t.identifier(keysName), t.identifier('detail')), [ + t.memberExpression(t.identifier('variables'), t.identifier(pkField.name)) + ]) + : t.arrayExpression([t.stringLiteral(typeName.toLowerCase()), t.stringLiteral('detail'), t.memberExpression(t.identifier('variables'), t.identifier(pkField.name))]); + const listKeyExpr = useCentralizedKeys + ? callExpr(t.memberExpression(t.identifier(keysName), t.identifier('lists')), []) : t.arrayExpression([t.stringLiteral(typeName.toLowerCase()), t.stringLiteral('list')]); - mutationOptions.push( - t.objectProperty( - t.identifier('onSuccess'), - t.arrowFunctionExpression( - [t.identifier('_'), t.identifier('variables')], - t.blockStatement([ - t.expressionStatement( - t.callExpression( - t.memberExpression(t.identifier('queryClient'), t.identifier('removeQueries')), - [t.objectExpression([t.objectProperty(t.identifier('queryKey'), detailQueryKey)])] - ) - ), - t.expressionStatement( - t.callExpression( - t.memberExpression(t.identifier('queryClient'), t.identifier('invalidateQueries')), - [t.objectExpression([t.objectProperty(t.identifier('queryKey'), listQueryKey)])] - ) - ), - ]) + const onSuccessFn = t.arrowFunctionExpression( + [t.identifier('_'), t.identifier('variables')], + t.blockStatement([ + t.expressionStatement( + callExpr( + t.memberExpression(t.identifier('queryClient'), t.identifier('removeQueries')), + [t.objectExpression([objectProp('queryKey', detailKeyExpr)])] + ) + ), + t.expressionStatement( + callExpr( + t.memberExpression(t.identifier('queryClient'), t.identifier('invalidateQueries')), + [t.objectExpression([objectProp('queryKey', listKeyExpr)])] + ) ) - ) + ]) ); - mutationOptions.push(t.spreadElement(t.identifier('options'))); - hookBodyStatements.push( - t.returnStatement( - t.callExpression(t.identifier('useMutation'), [t.objectExpression(mutationOptions)]) + body.push( + returnUseMutation( + mutationFnExpr, + [ + objectProp('onSuccess', onSuccessFn), + spreadObj(t.identifier('mutationOptions')) + ], + mutationKeyExpr ) ); - const optionsTypeStr = `Omit, 'mutationFn'>`; - const optionsParam = t.identifier('options'); - optionsParam.optional = true; - optionsParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier(optionsTypeStr))); - - const hookFunc = t.functionDeclaration( - t.identifier(hookName), - [optionsParam], - t.blockStatement(hookBodyStatements) - ); - const hookExport = t.exportNamedDeclaration(hookFunc); - addJSDocComment(hookExport, [ - `Mutation hook for deleting a ${typeName}`, - '', - '@example', - '```tsx', - `const { mutate, isPending } = ${hookName}();`, - '', - 'mutate({', - ' input: {', - ` ${pkField.name}: ${pkField.tsType === 'string' ? "'value-to-delete'" : '123'},`, - ' },', - '});', - '```', - ]); - statements.push(hookExport); - - const code = generateCode(statements); - const content = getGeneratedFileHeader(`Delete mutation hook for ${typeName}`) + '\n\n' + code; + statements.push(exportFunction(hookName, null, [createFunctionParam('params', implParamType, true)], body)); return { fileName: getDeleteMutationFileName(table), - content, + content: generateHookFileCode(`Delete mutation hook for ${typeName}`, statements) }; } diff --git a/graphql/codegen/src/core/codegen/orm/barrel.ts b/graphql/codegen/src/core/codegen/orm/barrel.ts index fda3b5b15..b1a9e63a0 100644 --- a/graphql/codegen/src/core/codegen/orm/barrel.ts +++ b/graphql/codegen/src/core/codegen/orm/barrel.ts @@ -3,10 +3,11 @@ * * Generates index.ts files that re-export all models and operations. */ -import type { CleanTable } from '../../../types/schema'; import * as t from '@babel/types'; + +import type { CleanTable } from '../../../types/schema'; import { generateCode } from '../babel-ast'; -import { getTableNames, lcFirst, getGeneratedFileHeader } from '../utils'; +import { getGeneratedFileHeader,getTableNames, lcFirst } from '../utils'; export interface GeneratedBarrelFile { fileName: string; @@ -41,7 +42,7 @@ export function generateModelsBarrel(tables: CleanTable[]): GeneratedBarrelFile return { fileName: 'models/index.ts', - content: header + '\n' + code, + content: header + '\n' + code }; } @@ -62,6 +63,6 @@ export * from './input-types'; return { fileName: 'types.ts', - content, + content }; } diff --git a/graphql/codegen/src/core/codegen/orm/client-generator.ts b/graphql/codegen/src/core/codegen/orm/client-generator.ts index 765d95807..293f0be52 100644 --- a/graphql/codegen/src/core/codegen/orm/client-generator.ts +++ b/graphql/codegen/src/core/codegen/orm/client-generator.ts @@ -3,13 +3,14 @@ * * Generates the createClient() factory function and main client file. */ -import type { CleanTable } from '../../../types/schema'; import * as t from '@babel/types'; -import { generateCode, commentBlock } from '../babel-ast'; -import { getTableNames, lcFirst, getGeneratedFileHeader } from '../utils'; import * as fs from 'fs'; import * as path from 'path'; +import type { CleanTable } from '../../../types/schema'; +import { commentBlock,generateCode } from '../babel-ast'; +import { getGeneratedFileHeader,getTableNames, lcFirst } from '../utils'; + export interface GeneratedClientFile { fileName: string; content: string; @@ -61,7 +62,7 @@ function readTemplateFile(templateName: string, description: string): string { export function generateOrmClientFile(): GeneratedClientFile { return { fileName: 'client.ts', - content: readTemplateFile('orm-client.ts', 'ORM Client - Runtime GraphQL executor'), + content: readTemplateFile('orm-client.ts', 'ORM Client - Runtime GraphQL executor') }; } @@ -76,7 +77,7 @@ export function generateQueryBuilderFile(): GeneratedClientFile { content: readTemplateFile( 'query-builder.ts', 'Query Builder - Builds and executes GraphQL operations' - ), + ) }; } @@ -88,7 +89,7 @@ export function generateQueryBuilderFile(): GeneratedClientFile { export function generateSelectTypesFile(): GeneratedClientFile { return { fileName: 'select-types.ts', - content: readTemplateFile('select-types.ts', 'Type utilities for select inference'), + content: readTemplateFile('select-types.ts', 'Type utilities for select inference') }; } @@ -167,7 +168,7 @@ export function generateCreateClientFile( t.exportSpecifier( t.identifier('GraphQLAdapter'), t.identifier('GraphQLAdapter') - ), + ) ], t.stringLiteral('./client') ); @@ -182,7 +183,7 @@ export function generateCreateClientFile( t.exportSpecifier( t.identifier('GraphQLRequestError'), t.identifier('GraphQLRequestError') - ), + ) ], t.stringLiteral('./client') ) @@ -196,7 +197,7 @@ export function generateCreateClientFile( t.exportSpecifier( t.identifier('QueryBuilder'), t.identifier('QueryBuilder') - ), + ) ], t.stringLiteral('./query-builder') ) @@ -217,7 +218,7 @@ export function generateCreateClientFile( t.exportSpecifier( t.identifier('createQueryOperations'), t.identifier('createQueryOperations') - ), + ) ], t.stringLiteral('./query') ) @@ -231,7 +232,7 @@ export function generateCreateClientFile( t.exportSpecifier( t.identifier('createMutationOperations'), t.identifier('createMutationOperations') - ), + ) ], t.stringLiteral('./mutation') ) @@ -257,7 +258,7 @@ export function generateCreateClientFile( t.objectProperty( t.identifier('query'), t.callExpression(t.identifier('createQueryOperations'), [ - t.identifier('client'), + t.identifier('client') ]) ) ); @@ -268,7 +269,7 @@ export function generateCreateClientFile( t.objectProperty( t.identifier('mutation'), t.callExpression(t.identifier('createMutationOperations'), [ - t.identifier('client'), + t.identifier('client') ]) ) ); @@ -279,7 +280,7 @@ export function generateCreateClientFile( t.variableDeclarator( t.identifier('client'), t.newExpression(t.identifier('OrmClient'), [t.identifier('config')]) - ), + ) ]); const returnStmt = t.returnStatement(t.objectExpression(returnProperties)); @@ -329,6 +330,6 @@ export function generateCreateClientFile( return { fileName: 'index.ts', - content: header + '\n' + code, + content: header + '\n' + code }; } diff --git a/graphql/codegen/src/core/codegen/orm/client.ts b/graphql/codegen/src/core/codegen/orm/client.ts index f7e233531..d217115f0 100644 --- a/graphql/codegen/src/core/codegen/orm/client.ts +++ b/graphql/codegen/src/core/codegen/orm/client.ts @@ -54,19 +54,19 @@ export class FetchAdapter implements GraphQLAdapter { headers: { 'Content-Type': 'application/json', Accept: 'application/json', - ...this.headers, + ...this.headers }, body: JSON.stringify({ query: document, - variables: variables ?? {}, - }), + variables: variables ?? {} + }) }); if (!response.ok) { return { ok: false, data: null, - errors: [{ message: `HTTP ${response.status}: ${response.statusText}` }], + errors: [{ message: `HTTP ${response.status}: ${response.statusText}` }] }; } @@ -79,14 +79,14 @@ export class FetchAdapter implements GraphQLAdapter { return { ok: false, data: null, - errors: json.errors, + errors: json.errors }; } return { ok: true, data: json.data as T, - errors: undefined, + errors: undefined }; } diff --git a/graphql/codegen/src/core/codegen/orm/custom-ops-generator.ts b/graphql/codegen/src/core/codegen/orm/custom-ops-generator.ts index 0e7a55cb0..5fbcf5f26 100644 --- a/graphql/codegen/src/core/codegen/orm/custom-ops-generator.ts +++ b/graphql/codegen/src/core/codegen/orm/custom-ops-generator.ts @@ -4,16 +4,17 @@ * Generates db.query.* and db.mutation.* namespaces for non-table operations * like login, register, currentUser, etc. */ -import type { CleanOperation, CleanArgument } from '../../../types/schema'; import * as t from '@babel/types'; -import { generateCode } from '../babel-ast'; -import { ucFirst, getGeneratedFileHeader } from '../utils'; + +import type { CleanArgument, CleanOperation, TypeRegistry } from '../../../types/schema'; +import { asConst, generateCode } from '../babel-ast'; +import { NON_SELECT_TYPES, getSelectTypeName } from '../select-helpers'; import { - typeRefToTsType, - isTypeRequired, getTypeBaseName, + isTypeRequired, + typeRefToTsType } from '../type-resolver'; -import { SCALAR_NAMES } from '../scalars'; +import { getGeneratedFileHeader,ucFirst } from '../utils'; export interface GeneratedCustomOpsFile { fileName: string; @@ -45,13 +46,6 @@ function collectInputTypeNamesFromOps(operations: CleanOperation[]): string[] { return Array.from(inputTypes); } -// Types that don't need Select types -const NON_SELECT_TYPES = new Set([ - ...SCALAR_NAMES, - 'Query', - 'Mutation', -]); - /** * Collect all payload/return type names from operations (for Select types) * Filters out scalar types @@ -66,8 +60,6 @@ function collectPayloadTypeNamesFromOps( if ( baseName && !baseName.endsWith('Connection') && - baseName !== 'Query' && - baseName !== 'Mutation' && !NON_SELECT_TYPES.has(baseName) ) { payloadTypes.add(baseName); @@ -78,21 +70,26 @@ function collectPayloadTypeNamesFromOps( } /** - * Get the Select type name for a return type - * Returns null for scalar types, Connection types (no select needed) + * Collect Connection and other non-scalar return type names that need importing + * (for typing QueryBuilder results on scalar/Connection operations) */ -function getSelectTypeName(returnType: CleanArgument['type']): string | null { - const baseName = getTypeBaseName(returnType); - if ( - baseName && - !NON_SELECT_TYPES.has(baseName) && - baseName !== 'Query' && - baseName !== 'Mutation' && - !baseName.endsWith('Connection') - ) { - return `${baseName}Select`; +function collectRawReturnTypeNames( + operations: CleanOperation[] +): string[] { + const types = new Set(); + + for (const op of operations) { + const baseName = getTypeBaseName(op.returnType); + if ( + baseName && + !NON_SELECT_TYPES.has(baseName) && + baseName.endsWith('Connection') + ) { + types.add(baseName); + } } - return null; + + return Array.from(types); } function createImportDeclaration( @@ -153,15 +150,106 @@ function parseTypeAnnotation(typeStr: string): t.TSType { return t.tsTypeReference(t.identifier(typeStr)); } +function buildSelectedResultTsType( + typeRef: CleanArgument['type'], + payloadTypeName: string +): t.TSType { + if (typeRef.kind === 'NON_NULL' && typeRef.ofType) { + return buildSelectedResultTsType(typeRef.ofType as CleanArgument['type'], payloadTypeName); + } + + if (typeRef.kind === 'LIST' && typeRef.ofType) { + return t.tsArrayType( + buildSelectedResultTsType(typeRef.ofType as CleanArgument['type'], payloadTypeName) + ); + } + + return t.tsTypeReference( + t.identifier('InferSelectResult'), + t.tsTypeParameterInstantiation([ + t.tsTypeReference(t.identifier(payloadTypeName)), + t.tsTypeReference(t.identifier('S')) + ]) + ); +} + +function buildDefaultSelectExpression( + typeName: string, + typeRegistry: TypeRegistry, + depth: number = 0 +): t.Expression { + const resolved = typeRegistry.get(typeName); + const fields = resolved?.fields ?? []; + + if (depth > 3 || fields.length === 0) { + // Use first field if available, otherwise fallback to 'id' + const fallbackName = fields.length > 0 ? fields[0].name : 'id'; + return t.objectExpression([t.objectProperty(t.identifier(fallbackName), t.booleanLiteral(true))]); + } + + // Prefer id-like fields + const idLike = fields.find((f) => f.name === 'id' || f.name === 'nodeId'); + if (idLike) { + return t.objectExpression([ + t.objectProperty(t.identifier(idLike.name), t.booleanLiteral(true)) + ]); + } + + // Prefer scalar/enum fields + const scalarField = fields.find((f) => { + const baseName = getTypeBaseName(f.type); + if (!baseName) return false; + if (NON_SELECT_TYPES.has(baseName)) return true; + const baseResolved = typeRegistry.get(baseName); + return baseResolved?.kind === 'ENUM'; + }); + + if (scalarField) { + return t.objectExpression([ + t.objectProperty(t.identifier(scalarField.name), t.booleanLiteral(true)) + ]); + } + + // Fallback: first field (ensure valid selection for object fields) + const first = fields[0]; + + const firstBaseName = getTypeBaseName(first.type); + if (!firstBaseName || NON_SELECT_TYPES.has(firstBaseName)) { + return t.objectExpression([ + t.objectProperty(t.identifier(first.name), t.booleanLiteral(true)) + ]); + } + + const nestedResolved = typeRegistry.get(firstBaseName); + if (nestedResolved?.kind === 'ENUM') { + return t.objectExpression([ + t.objectProperty(t.identifier(first.name), t.booleanLiteral(true)) + ]); + } + + return t.objectExpression([ + t.objectProperty( + t.identifier(first.name), + t.objectExpression([ + t.objectProperty( + t.identifier('select'), + buildDefaultSelectExpression(firstBaseName, typeRegistry, depth + 1) + ) + ]) + ) + ]); +} + function buildOperationMethod( op: CleanOperation, - operationType: 'query' | 'mutation' + operationType: 'query' | 'mutation', + defaultSelectIdent?: t.Identifier ): t.ObjectProperty { const hasArgs = op.args.length > 0; const varTypeName = `${ucFirst(op.name)}Variables`; const varDefs = op.args.map((arg) => ({ name: arg.name, - type: formatGraphQLType(arg.type), + type: formatGraphQLType(arg.type) })); const selectTypeName = getSelectTypeName(op.returnType); @@ -179,26 +267,21 @@ function buildOperationMethod( const optionsParam = t.identifier('options'); optionsParam.optional = true; if (selectTypeName) { - // Use DeepExact to enforce strict field validation - // This catches invalid fields even when mixed with valid ones + const selectProp = t.tsPropertySignature( + t.identifier('select'), + t.tsTypeAnnotation(t.tsTypeReference(t.identifier('S'))) + ); + selectProp.optional = false; optionsParam.typeAnnotation = t.tsTypeAnnotation( - t.tsTypeLiteral([ - (() => { - const prop = t.tsPropertySignature( - t.identifier('select'), - t.tsTypeAnnotation( - t.tsTypeReference( - t.identifier('DeepExact'), - t.tsTypeParameterInstantiation([ - t.tsTypeReference(t.identifier('S')), - t.tsTypeReference(t.identifier(selectTypeName)), - ]) - ) - ) - ); - prop.optional = true; - return prop; - })(), + t.tsIntersectionType([ + t.tsTypeLiteral([selectProp]), + t.tsTypeReference( + t.identifier('StrictSelect'), + t.tsTypeParameterInstantiation([ + t.tsTypeReference(t.identifier('S')), + t.tsTypeReference(t.identifier(selectTypeName)) + ]) + ) ]) ); } else { @@ -216,13 +299,24 @@ function buildOperationMethod( ); prop.optional = true; return prop; - })(), + })() ]) ); } params.push(optionsParam); // Build the QueryBuilder call + const selectExpr = defaultSelectIdent + ? t.logicalExpression( + '??', + t.optionalMemberExpression(t.identifier('options'), t.identifier('select'), false, true), + defaultSelectIdent + ) + : t.optionalMemberExpression(t.identifier('options'), t.identifier('select'), false, true); + const entityTypeExpr = selectTypeName && payloadTypeName + ? t.stringLiteral(payloadTypeName) + : t.identifier('undefined'); + const queryBuilderArgs = t.objectExpression([ t.objectProperty(t.identifier('client'), t.identifier('client'), false, true), t.objectProperty(t.identifier('operation'), t.stringLiteral(operationType)), @@ -233,39 +327,47 @@ function buildOperationMethod( t.stringLiteral(operationType), t.stringLiteral(ucFirst(op.name)), t.stringLiteral(op.name), - t.optionalMemberExpression(t.identifier('options'), t.identifier('select'), false, true), + selectExpr, hasArgs ? t.identifier('args') : t.identifier('undefined'), t.arrayExpression( varDefs.map((v) => t.objectExpression([ t.objectProperty(t.identifier('name'), t.stringLiteral(v.name)), - t.objectProperty(t.identifier('type'), t.stringLiteral(v.type)), + t.objectProperty(t.identifier('type'), t.stringLiteral(v.type)) ]) ) ), + t.identifier('connectionFieldsMap'), + entityTypeExpr ]) - ), + ) ]); const newExpr = t.newExpression(t.identifier('QueryBuilder'), [queryBuilderArgs]); - // Add type parameter if we have a select type + // Add type parameter to QueryBuilder for typed .unwrap() results if (selectTypeName && payloadTypeName) { + // Select-based type: use InferSelectResult (newExpr as any).typeParameters = t.tsTypeParameterInstantiation([ t.tsTypeLiteral([ t.tsPropertySignature( t.identifier(op.name), t.tsTypeAnnotation( - t.tsTypeReference( - t.identifier('InferSelectResult'), - t.tsTypeParameterInstantiation([ - t.tsTypeReference(t.identifier(payloadTypeName)), - t.tsTypeReference(t.identifier('S')), - ]) - ) + buildSelectedResultTsType(op.returnType, payloadTypeName) ) - ), - ]), + ) + ]) + ]); + } else { + // Scalar/Connection type: use raw TS type directly + const rawTsType = typeRefToTsType(op.returnType); + (newExpr as any).typeParameters = t.tsTypeParameterInstantiation([ + t.tsTypeLiteral([ + t.tsPropertySignature( + t.identifier(op.name), + t.tsTypeAnnotation(parseTypeAnnotation(rawTsType)) + ) + ]) ]); } @@ -273,12 +375,14 @@ function buildOperationMethod( // Add type parameters to arrow function if we have a select type if (selectTypeName) { + const defaultType = defaultSelectIdent + ? t.tsTypeQuery(defaultSelectIdent) + : null; const typeParam = t.tsTypeParameter( t.tsTypeReference(t.identifier(selectTypeName)), - null, + defaultType, 'S' ); - (typeParam as any).const = true; arrowFunc.typeParameters = t.tsTypeParameterDeclaration([typeParam]); } @@ -289,7 +393,8 @@ function buildOperationMethod( * Generate the query/index.ts file for custom query operations */ export function generateCustomQueryOpsFile( - operations: CleanOperation[] + operations: CleanOperation[], + typeRegistry: TypeRegistry ): GeneratedCustomOpsFile { const statements: t.Statement[] = []; @@ -297,16 +402,18 @@ export function generateCustomQueryOpsFile( const inputTypeNames = collectInputTypeNamesFromOps(operations); const payloadTypeNames = collectPayloadTypeNamesFromOps(operations); const selectTypeNames = payloadTypeNames.map((p) => `${p}Select`); - const allTypeImports = [...new Set([...inputTypeNames, ...payloadTypeNames, ...selectTypeNames])]; + const rawReturnTypeNames = collectRawReturnTypeNames(operations); + const allTypeImports = [...new Set([...inputTypeNames, ...payloadTypeNames, ...selectTypeNames, ...rawReturnTypeNames])]; // Add imports statements.push(createImportDeclaration('../client', ['OrmClient'])); statements.push(createImportDeclaration('../query-builder', ['QueryBuilder', 'buildCustomDocument'])); - statements.push(createImportDeclaration('../select-types', ['InferSelectResult', 'DeepExact'], true)); + statements.push(createImportDeclaration('../select-types', ['InferSelectResult', 'StrictSelect'], true)); if (allTypeImports.length > 0) { statements.push(createImportDeclaration('../input-types', allTypeImports, true)); } + statements.push(createImportDeclaration('../input-types', ['connectionFieldsMap'])); // Generate variable interfaces for (const op of operations) { @@ -314,8 +421,29 @@ export function generateCustomQueryOpsFile( if (varInterface) statements.push(varInterface); } + // Default selects (avoid invalid documents when select is omitted) + const defaultSelectIdentsByOpName = new Map(); + for (const op of operations) { + const selectTypeName = getSelectTypeName(op.returnType); + const payloadTypeName = getTypeBaseName(op.returnType); + if (!selectTypeName || !payloadTypeName) continue; + + const ident = t.identifier(`${op.name}DefaultSelect`); + defaultSelectIdentsByOpName.set(op.name, ident); + statements.push( + t.variableDeclaration('const', [ + t.variableDeclarator( + ident, + asConst(buildDefaultSelectExpression(payloadTypeName, typeRegistry)) + ) + ]) + ); + } + // Generate factory function - const operationProperties = operations.map((op) => buildOperationMethod(op, 'query')); + const operationProperties = operations.map((op) => + buildOperationMethod(op, 'query', defaultSelectIdentsByOpName.get(op.name)) + ); const returnObj = t.objectExpression(operationProperties); const returnStmt = t.returnStatement(returnObj); @@ -335,7 +463,7 @@ export function generateCustomQueryOpsFile( return { fileName: 'query/index.ts', - content: header + '\n' + code, + content: header + '\n' + code }; } @@ -343,7 +471,8 @@ export function generateCustomQueryOpsFile( * Generate the mutation/index.ts file for custom mutation operations */ export function generateCustomMutationOpsFile( - operations: CleanOperation[] + operations: CleanOperation[], + typeRegistry: TypeRegistry ): GeneratedCustomOpsFile { const statements: t.Statement[] = []; @@ -351,16 +480,18 @@ export function generateCustomMutationOpsFile( const inputTypeNames = collectInputTypeNamesFromOps(operations); const payloadTypeNames = collectPayloadTypeNamesFromOps(operations); const selectTypeNames = payloadTypeNames.map((p) => `${p}Select`); - const allTypeImports = [...new Set([...inputTypeNames, ...payloadTypeNames, ...selectTypeNames])]; + const rawReturnTypeNames = collectRawReturnTypeNames(operations); + const allTypeImports = [...new Set([...inputTypeNames, ...payloadTypeNames, ...selectTypeNames, ...rawReturnTypeNames])]; // Add imports statements.push(createImportDeclaration('../client', ['OrmClient'])); statements.push(createImportDeclaration('../query-builder', ['QueryBuilder', 'buildCustomDocument'])); - statements.push(createImportDeclaration('../select-types', ['InferSelectResult', 'DeepExact'], true)); + statements.push(createImportDeclaration('../select-types', ['InferSelectResult', 'StrictSelect'], true)); if (allTypeImports.length > 0) { statements.push(createImportDeclaration('../input-types', allTypeImports, true)); } + statements.push(createImportDeclaration('../input-types', ['connectionFieldsMap'])); // Generate variable interfaces for (const op of operations) { @@ -368,8 +499,29 @@ export function generateCustomMutationOpsFile( if (varInterface) statements.push(varInterface); } + // Default selects (avoid invalid documents when select is omitted) + const defaultSelectIdentsByOpName = new Map(); + for (const op of operations) { + const selectTypeName = getSelectTypeName(op.returnType); + const payloadTypeName = getTypeBaseName(op.returnType); + if (!selectTypeName || !payloadTypeName) continue; + + const ident = t.identifier(`${op.name}DefaultSelect`); + defaultSelectIdentsByOpName.set(op.name, ident); + statements.push( + t.variableDeclaration('const', [ + t.variableDeclarator( + ident, + asConst(buildDefaultSelectExpression(payloadTypeName, typeRegistry)) + ) + ]) + ); + } + // Generate factory function - const operationProperties = operations.map((op) => buildOperationMethod(op, 'mutation')); + const operationProperties = operations.map((op) => + buildOperationMethod(op, 'mutation', defaultSelectIdentsByOpName.get(op.name)) + ); const returnObj = t.objectExpression(operationProperties); const returnStmt = t.returnStatement(returnObj); @@ -389,7 +541,7 @@ export function generateCustomMutationOpsFile( return { fileName: 'mutation/index.ts', - content: header + '\n' + code, + content: header + '\n' + code }; } diff --git a/graphql/codegen/src/core/codegen/orm/index.ts b/graphql/codegen/src/core/codegen/orm/index.ts index 099826959..afeff9380 100644 --- a/graphql/codegen/src/core/codegen/orm/index.ts +++ b/graphql/codegen/src/core/codegen/orm/index.ts @@ -4,21 +4,21 @@ * Main entry point for ORM code generation. Coordinates all generators * and produces the complete ORM client output. */ -import type { CleanTable, CleanOperation, TypeRegistry } from '../../../types/schema'; import type { GraphQLSDKConfigTarget } from '../../../types/config'; +import type { CleanOperation, CleanTable, TypeRegistry } from '../../../types/schema'; +import { generateModelsBarrel, generateTypesBarrel } from './barrel'; import { + generateCreateClientFile, generateOrmClientFile, generateQueryBuilderFile, - generateSelectTypesFile, - generateCreateClientFile, + generateSelectTypesFile } from './client-generator'; -import { generateAllModelFiles } from './model-generator'; import { - generateCustomQueryOpsFile, generateCustomMutationOpsFile, + generateCustomQueryOpsFile } from './custom-ops-generator'; -import { generateModelsBarrel, generateTypesBarrel } from './barrel'; -import { generateInputTypesFile, collectInputTypeNames, collectPayloadTypeNames } from './input-types-generator'; +import { collectInputTypeNames, collectPayloadTypeNames,generateInputTypesFile } from './input-types-generator'; +import { generateAllModelFiles } from './model-generator'; export interface GeneratedFile { path: string; @@ -80,7 +80,7 @@ export function generateOrm(options: GenerateOrmOptions): GenerateOrmResult { for (const modelFile of modelFiles) { files.push({ path: `models/${modelFile.fileName}`, - content: modelFile.content, + content: modelFile.content }); } @@ -93,7 +93,7 @@ export function generateOrm(options: GenerateOrmOptions): GenerateOrmResult { if (tables.length > 0 || (typeRegistry && (hasCustomQueries || hasCustomMutations))) { const allOps = [ ...(customOperations?.queries ?? []), - ...(customOperations?.mutations ?? []), + ...(customOperations?.mutations ?? []) ]; const usedInputTypes = collectInputTypeNames(allOps); const usedPayloadTypes = collectPayloadTypeNames(allOps); @@ -106,7 +106,7 @@ export function generateOrm(options: GenerateOrmOptions): GenerateOrmResult { const crudPayloadTypes = [ `Create${typeName}Payload`, `Update${typeName}Payload`, - `Delete${typeName}Payload`, + `Delete${typeName}Payload` ]; for (const payloadType of crudPayloadTypes) { if (typeRegistry.has(payloadType)) { @@ -127,12 +127,18 @@ export function generateOrm(options: GenerateOrmOptions): GenerateOrmResult { // 5. Generate custom operations (if any) if (hasCustomQueries && customOperations?.queries) { - const queryOpsFile = generateCustomQueryOpsFile(customOperations.queries); + const queryOpsFile = generateCustomQueryOpsFile( + customOperations.queries, + typeRegistry ?? new Map() + ); files.push({ path: queryOpsFile.fileName, content: queryOpsFile.content }); } if (hasCustomMutations && customOperations?.mutations) { - const mutationOpsFile = generateCustomMutationOpsFile(customOperations.mutations); + const mutationOpsFile = generateCustomMutationOpsFile( + customOperations.mutations, + typeRegistry ?? new Map() + ); files.push({ path: mutationOpsFile.fileName, content: mutationOpsFile.content }); } @@ -150,17 +156,17 @@ export function generateOrm(options: GenerateOrmOptions): GenerateOrmResult { tables: tables.length, customQueries: customOperations?.queries.length ?? 0, customMutations: customOperations?.mutations.length ?? 0, - totalFiles: files.length, - }, + totalFiles: files.length + } }; } // Re-export generators for direct use +export { generateModelsBarrel, generateTypesBarrel } from './barrel'; export { generateOrmClientFile, generateQueryBuilderFile, - generateSelectTypesFile, + generateSelectTypesFile } from './client-generator'; -export { generateModelFile, generateAllModelFiles } from './model-generator'; -export { generateCustomQueryOpsFile, generateCustomMutationOpsFile } from './custom-ops-generator'; -export { generateModelsBarrel, generateTypesBarrel } from './barrel'; +export { generateCustomMutationOpsFile,generateCustomQueryOpsFile } from './custom-ops-generator'; +export { generateAllModelFiles,generateModelFile } from './model-generator'; diff --git a/graphql/codegen/src/core/codegen/orm/input-types-generator.ts b/graphql/codegen/src/core/codegen/orm/input-types-generator.ts index ca7154c57..b4cb1bfe4 100644 --- a/graphql/codegen/src/core/codegen/orm/input-types-generator.ts +++ b/graphql/codegen/src/core/codegen/orm/input-types-generator.ts @@ -10,24 +10,26 @@ * * Uses Babel AST for robust code generation. */ +import * as t from '@babel/types'; +import { pluralize } from 'inflekt'; + import type { - TypeRegistry, CleanArgument, CleanTable, + TypeRegistry } from '../../../types/schema'; -import * as t from '@babel/types'; -import { generateCode, addLineComment } from '../babel-ast'; +import { addLineComment,generateCode } from '../babel-ast'; +import { scalarToFilterType,scalarToTsType } from '../scalars'; +import { getTypeBaseName } from '../type-resolver'; import { - getTableNames, - getFilterTypeName, getConditionTypeName, - getOrderByTypeName, - isRelationField, + getFilterTypeName, getGeneratedFileHeader, + getOrderByTypeName, + getPrimaryKeyInfo, + getTableNames, + isRelationField } from '../utils'; -import { pluralize } from 'inflekt'; -import { getTypeBaseName } from '../type-resolver'; -import { scalarToTsType, scalarToFilterType } from '../scalars'; export interface GeneratedInputTypesFile { fileName: string; @@ -43,7 +45,7 @@ const EXCLUDED_MUTATION_FIELDS = [ 'id', 'createdAt', 'updatedAt', - 'nodeId', + 'nodeId' ] as const; // ============================================================================ @@ -54,7 +56,7 @@ const EXCLUDED_MUTATION_FIELDS = [ * Overrides for input-type generation */ const INPUT_SCALAR_OVERRIDES: Record = { - JSON: 'Record', + JSON: 'Record' }; /** @@ -63,7 +65,7 @@ const INPUT_SCALAR_OVERRIDES: Record = { function scalarToInputTs(scalar: string): string { return scalarToTsType(scalar, { unknownScalar: 'name', - overrides: INPUT_SCALAR_OVERRIDES, + overrides: INPUT_SCALAR_OVERRIDES }); } @@ -132,18 +134,18 @@ function parseTypeString(typeStr: string): t.TSType { // Handle primitive types switch (typeStr) { - case 'string': - return t.tsStringKeyword(); - case 'number': - return t.tsNumberKeyword(); - case 'boolean': - return t.tsBooleanKeyword(); - case 'null': - return t.tsNullKeyword(); - case 'unknown': - return t.tsUnknownKeyword(); - default: - return t.tsTypeReference(t.identifier(typeStr)); + case 'string': + return t.tsStringKeyword(); + case 'number': + return t.tsNumberKeyword(); + case 'boolean': + return t.tsBooleanKeyword(); + case 'null': + return t.tsNullKeyword(); + case 'unknown': + return t.tsUnknownKeyword(); + default: + return t.tsTypeReference(t.identifier(typeStr)); } } @@ -256,72 +258,72 @@ const SCALAR_FILTER_CONFIGS: ScalarFilterConfig[] = [ { name: 'StringFilter', tsType: 'string', - operators: ['equality', 'distinct', 'inArray', 'comparison', 'string'], + operators: ['equality', 'distinct', 'inArray', 'comparison', 'string'] }, { name: 'IntFilter', tsType: 'number', - operators: ['equality', 'distinct', 'inArray', 'comparison'], + operators: ['equality', 'distinct', 'inArray', 'comparison'] }, { name: 'FloatFilter', tsType: 'number', - operators: ['equality', 'distinct', 'inArray', 'comparison'], + operators: ['equality', 'distinct', 'inArray', 'comparison'] }, { name: 'BooleanFilter', tsType: 'boolean', operators: ['equality'] }, { name: 'UUIDFilter', tsType: 'string', - operators: ['equality', 'distinct', 'inArray'], + operators: ['equality', 'distinct', 'inArray'] }, { name: 'DatetimeFilter', tsType: 'string', - operators: ['equality', 'distinct', 'inArray', 'comparison'], + operators: ['equality', 'distinct', 'inArray', 'comparison'] }, { name: 'DateFilter', tsType: 'string', - operators: ['equality', 'distinct', 'inArray', 'comparison'], + operators: ['equality', 'distinct', 'inArray', 'comparison'] }, { name: 'JSONFilter', tsType: 'Record', - operators: ['equality', 'distinct', 'json'], + operators: ['equality', 'distinct', 'json'] }, { name: 'BigIntFilter', tsType: 'string', - operators: ['equality', 'distinct', 'inArray', 'comparison'], + operators: ['equality', 'distinct', 'inArray', 'comparison'] }, { name: 'BigFloatFilter', tsType: 'string', - operators: ['equality', 'distinct', 'inArray', 'comparison'], + operators: ['equality', 'distinct', 'inArray', 'comparison'] }, { name: 'BitStringFilter', tsType: 'string', operators: ['equality'] }, { name: 'InternetAddressFilter', tsType: 'string', - operators: ['equality', 'distinct', 'inArray', 'comparison', 'inet'], + operators: ['equality', 'distinct', 'inArray', 'comparison', 'inet'] }, { name: 'FullTextFilter', tsType: 'string', operators: ['fulltext'] }, // List filters (for array fields like string[], int[], uuid[]) { name: 'StringListFilter', tsType: 'string[]', - operators: ['equality', 'distinct', 'comparison', 'listArray'], + operators: ['equality', 'distinct', 'comparison', 'listArray'] }, { name: 'IntListFilter', tsType: 'number[]', - operators: ['equality', 'distinct', 'comparison', 'listArray'], + operators: ['equality', 'distinct', 'comparison', 'listArray'] }, { name: 'UUIDListFilter', tsType: 'string[]', - operators: ['equality', 'distinct', 'comparison', 'listArray'], - }, + operators: ['equality', 'distinct', 'comparison', 'listArray'] + } ]; /** @@ -542,7 +544,7 @@ function buildEntityProperties(table: CleanTable): InterfaceProperty[] { properties.push({ name: field.name, type: isNullable ? `${tsType} | null` : tsType, - optional: isNullable, + optional: isNullable }); } @@ -582,13 +584,13 @@ function generateRelationHelperTypes(): t.Statement[] { const connectionResultProps: t.TSPropertySignature[] = [ createPropertySignature('nodes', 'T[]', false), createPropertySignature('totalCount', 'number', false), - createPropertySignature('pageInfo', 'PageInfo', false), + createPropertySignature('pageInfo', 'PageInfo', false) ]; const connectionResultBody = t.tsInterfaceBody(connectionResultProps); const connectionResultDecl = t.tsInterfaceDeclaration( t.identifier('ConnectionResult'), t.tsTypeParameterDeclaration([ - t.tsTypeParameter(null, null, 'T'), + t.tsTypeParameter(null, null, 'T') ]), null, connectionResultBody @@ -601,7 +603,7 @@ function generateRelationHelperTypes(): t.Statement[] { { name: 'hasNextPage', type: 'boolean', optional: false }, { name: 'hasPreviousPage', type: 'boolean', optional: false }, { name: 'startCursor', type: 'string | null', optional: true }, - { name: 'endCursor', type: 'string | null', optional: true }, + { name: 'endCursor', type: 'string | null', optional: true } ]) ); @@ -663,7 +665,7 @@ function buildEntityRelationProperties( properties.push({ name: relation.fieldName, type: `${relatedTypeName} | null`, - optional: true, + optional: true }); } @@ -676,7 +678,7 @@ function buildEntityRelationProperties( properties.push({ name: relation.fieldName, type: `${relatedTypeName} | null`, - optional: true, + optional: true }); } @@ -689,7 +691,7 @@ function buildEntityRelationProperties( properties.push({ name: relation.fieldName, type: `ConnectionResult<${relatedTypeName}>`, - optional: true, + optional: true }); } @@ -702,7 +704,7 @@ function buildEntityRelationProperties( properties.push({ name: relation.fieldName, type: `ConnectionResult<${relatedTypeName}>`, - optional: true, + optional: true }); } @@ -803,8 +805,8 @@ function buildSelectTypeLiteral( ); selectProp.optional = true; return selectProp; - })(), - ]), + })() + ]) ]) ) ); @@ -869,8 +871,8 @@ function buildSelectTypeLiteral( ); p.optional = true; return p; - })(), - ]), + })() + ]) ]) ) ); @@ -932,8 +934,8 @@ function buildSelectTypeLiteral( ); p.optional = true; return p; - })(), - ]), + })() + ]) ]) ) ); @@ -964,8 +966,8 @@ function buildSelectTypeLiteral( ); selectProp.optional = true; return selectProp; - })(), - ]), + })() + ]) ]) ) ); @@ -1077,7 +1079,7 @@ function buildTableConditionProperties(table: CleanTable): InterfaceProperty[] { properties.push({ name: field.name, type: `${tsType} | null`, - optional: true, + optional: true }); } @@ -1214,7 +1216,7 @@ function buildCreateInputInterface(table: CleanTable): t.ExportNamedDeclaration t.tsPropertySignature( t.identifier(singularName), t.tsTypeAnnotation(nestedObjectType) - ), + ) ]; const body = t.tsInterfaceBody(mainProps); @@ -1249,7 +1251,7 @@ function buildPatchProperties(table: CleanTable): InterfaceProperty[] { properties.push({ name: field.name, type: `${tsType} | null`, - optional: true, + optional: true }); } @@ -1264,6 +1266,11 @@ function generateCrudInputTypes(table: CleanTable): t.Statement[] { const { typeName } = getTableNames(table); const patchName = `${typeName}Patch`; + const pkFields = getPrimaryKeyInfo(table); + const pkField = pkFields[0]; + const pkFieldName = pkField?.name ?? 'id'; + const pkFieldTsType = pkField?.tsType ?? 'string'; + // Create input statements.push(buildCreateInputInterface(table)); @@ -1276,8 +1283,8 @@ function generateCrudInputTypes(table: CleanTable): t.Statement[] { statements.push( createExportedInterface(`Update${typeName}Input`, [ { name: 'clientMutationId', type: 'string', optional: true }, - { name: 'id', type: 'string', optional: false }, - { name: 'patch', type: patchName, optional: false }, + { name: pkFieldName, type: pkFieldTsType, optional: false }, + { name: 'patch', type: patchName, optional: false } ]) ); @@ -1285,7 +1292,7 @@ function generateCrudInputTypes(table: CleanTable): t.Statement[] { statements.push( createExportedInterface(`Delete${typeName}Input`, [ { name: 'clientMutationId', type: 'string', optional: true }, - { name: 'id', type: 'string', optional: false }, + { name: pkFieldName, type: pkFieldTsType, optional: false } ]) ); @@ -1456,10 +1463,7 @@ export function collectPayloadTypeNames( for (const op of operations) { const baseName = getTypeBaseName(op.returnType); - if ( - baseName && - (baseName.endsWith('Payload') || !baseName.endsWith('Connection')) - ) { + if (baseName) { payloadTypes.add(baseName); } } @@ -1494,7 +1498,7 @@ function generatePayloadTypes( 'BigFloat', 'Cursor', 'Query', - 'Mutation', + 'Mutation' ]); // Process all types - no artificial limit @@ -1524,7 +1528,7 @@ function generatePayloadTypes( interfaceProps.push({ name: field.name, type: isNullable ? `${tsType} | null` : tsType, - optional: isNullable, + optional: isNullable }); // Follow nested OBJECT types @@ -1563,8 +1567,8 @@ function generatePayloadTypes( ); p.optional = true; return p; - })(), - ]), + })() + ]) ]); } else { propType = t.tsBooleanKeyword(); @@ -1592,6 +1596,90 @@ function generatePayloadTypes( return statements; } +// ============================================================================ +// Connection Fields Map Generator +// ============================================================================ + +/** + * Generate a runtime map of entity type → { fieldName: relatedTypeName } + * for all hasMany and manyToMany relations. Used by buildSelections() + * to detect connection fields that need `nodes { ... }` wrapping. + */ +function generateConnectionFieldsMap( + tables: CleanTable[], + tableByName: Map +): t.Statement[] { + const properties: t.ObjectProperty[] = []; + + for (const table of tables) { + const { typeName } = getTableNames(table); + const fieldEntries: t.ObjectProperty[] = []; + + for (const relation of table.relations.hasMany) { + if (!relation.fieldName) continue; + const relatedTypeName = getRelatedTypeName( + relation.referencedByTable, + tableByName + ); + fieldEntries.push( + t.objectProperty( + t.stringLiteral(relation.fieldName), + t.stringLiteral(relatedTypeName) + ) + ); + } + + for (const relation of table.relations.manyToMany) { + if (!relation.fieldName) continue; + const relatedTypeName = getRelatedTypeName( + relation.rightTable, + tableByName + ); + fieldEntries.push( + t.objectProperty( + t.stringLiteral(relation.fieldName), + t.stringLiteral(relatedTypeName) + ) + ); + } + + if (fieldEntries.length > 0) { + properties.push( + t.objectProperty( + t.stringLiteral(typeName), + t.objectExpression(fieldEntries) + ) + ); + } + } + + const decl = t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('connectionFieldsMap'), + t.tsAsExpression( + t.objectExpression(properties), + t.tsTypeReference( + t.identifier('Record'), + t.tsTypeParameterInstantiation([ + t.tsStringKeyword(), + t.tsTypeReference( + t.identifier('Record'), + t.tsTypeParameterInstantiation([ + t.tsStringKeyword(), + t.tsStringKeyword() + ]) + ) + ]) + ) + ) + ) + ]); + + const statements: t.Statement[] = [t.exportNamedDeclaration(decl)]; + addSectionComment(statements, 'Connection Fields Map'); + return statements; +} + // ============================================================================ // Main Generator (AST-based) // ============================================================================ @@ -1606,39 +1694,44 @@ export function generateInputTypesFile( usedPayloadTypes?: Set ): GeneratedInputTypesFile { const statements: t.Statement[] = []; + const tablesList = tables ?? []; + const hasTables = tablesList.length > 0; + const tableByName = new Map(tablesList.map((table) => [table.name, table])); // 1. Scalar filter types statements.push(...generateScalarFilterTypes()); // 2. Enum types used by table fields - if (tables && tables.length > 0) { - const enumTypes = collectEnumTypesFromTables(tables, typeRegistry); + if (hasTables) { + const enumTypes = collectEnumTypesFromTables(tablesList, typeRegistry); statements.push(...generateEnumTypes(typeRegistry, enumTypes)); } // 3. Entity and relation types (if tables provided) - if (tables && tables.length > 0) { - const tableByName = new Map(tables.map((table) => [table.name, table])); - - statements.push(...generateEntityTypes(tables)); + if (hasTables) { + statements.push(...generateEntityTypes(tablesList)); statements.push(...generateRelationHelperTypes()); - statements.push(...generateEntityRelationTypes(tables, tableByName)); - statements.push(...generateEntityWithRelations(tables)); - statements.push(...generateEntitySelectTypes(tables, tableByName)); + statements.push(...generateEntityRelationTypes(tablesList, tableByName)); + statements.push(...generateEntityWithRelations(tablesList)); + statements.push(...generateEntitySelectTypes(tablesList, tableByName)); // 4. Table filter types - statements.push(...generateTableFilterTypes(tables)); + statements.push(...generateTableFilterTypes(tablesList)); // 4b. Table condition types (simple equality filter) - statements.push(...generateTableConditionTypes(tables)); + statements.push(...generateTableConditionTypes(tablesList)); // 5. OrderBy types - statements.push(...generateOrderByTypes(tables)); + statements.push(...generateOrderByTypes(tablesList)); // 6. CRUD input types - statements.push(...generateAllCrudInputTypes(tables)); + statements.push(...generateAllCrudInputTypes(tablesList)); } + // 6b. Connection fields map (runtime metadata for buildSelections) + // Always emit this export so generated model/custom-op imports stay valid. + statements.push(...generateConnectionFieldsMap(tablesList, tableByName)); + // 7. Custom input types from TypeRegistry const tableCrudTypes = tables ? buildTableCrudTypeNames(tables) : undefined; statements.push( @@ -1669,6 +1762,6 @@ export function generateInputTypesFile( return { fileName: 'input-types.ts', - content: header + '\n' + code, + content: header + '\n' + code }; } diff --git a/graphql/codegen/src/core/codegen/orm/model-generator.ts b/graphql/codegen/src/core/codegen/orm/model-generator.ts index 0498688b4..67f8a29a5 100644 --- a/graphql/codegen/src/core/codegen/orm/model-generator.ts +++ b/graphql/codegen/src/core/codegen/orm/model-generator.ts @@ -2,16 +2,21 @@ * Model class generator for ORM client (Babel AST-based) * * Generates per-table model classes with findMany, findFirst, create, update, delete methods. + * Each method uses function overloads for IDE autocompletion of select objects. */ -import type { CleanTable } from '../../../types/schema'; import * as t from '@babel/types'; -import { generateCode } from '../babel-ast'; + +import type { CleanTable } from '../../../types/schema'; +import { asConst, generateCode } from '../babel-ast'; import { - getTableNames, - getOrderByTypeName, + getDefaultSelectFieldName, getFilterTypeName, - lcFirst, getGeneratedFileHeader, + getOrderByTypeName, + getPrimaryKeyInfo, + getTableNames, + hasValidPrimaryKey, + lcFirst } from '../utils'; export interface GeneratedModelFile { @@ -45,10 +50,10 @@ function buildMethodBody( t.variableDeclarator( t.objectPattern([ t.objectProperty(t.identifier('document'), t.identifier('document'), false, true), - t.objectProperty(t.identifier('variables'), t.identifier('variables'), false, true), + t.objectProperty(t.identifier('variables'), t.identifier('variables'), false, true) ]), t.callExpression(t.identifier(builderFn), args) - ), + ) ]); const returnStmt = t.returnStatement( @@ -59,8 +64,8 @@ function buildMethodBody( t.objectProperty(t.identifier('operationName'), t.stringLiteral(typeName)), t.objectProperty(t.identifier('fieldName'), t.stringLiteral(fieldName)), t.objectProperty(t.identifier('document'), t.identifier('document'), false, true), - t.objectProperty(t.identifier('variables'), t.identifier('variables'), false, true), - ]), + t.objectProperty(t.identifier('variables'), t.identifier('variables'), false, true) + ]) ]) ); @@ -80,16 +85,86 @@ function createClassMethod( return method; } -function createConstTypeParam(constraintTypeName: string): t.TSTypeParameterDeclaration { +function createDeclareMethod( + name: string, + typeParameters: t.TSTypeParameterDeclaration | null, + params: (t.Identifier | t.TSParameterProperty)[], + returnType: t.TSTypeAnnotation +): t.TSDeclareMethod { + const method = t.tsDeclareMethod( + null, + t.identifier(name), + typeParameters, + params, + returnType + ); + return method; +} + +function createTypeParam( + constraintTypeName: string, + defaultType?: t.TSType +): t.TSTypeParameterDeclaration { const param = t.tsTypeParameter( t.tsTypeReference(t.identifier(constraintTypeName)), - null, + defaultType ?? null, 'S' ); - (param as any).const = true; return t.tsTypeParameterDeclaration([param]); } +function tsTypeFromPrimitive(typeName: string): t.TSType { + if (typeName === 'string') return t.tsStringKeyword(); + if (typeName === 'number') return t.tsNumberKeyword(); + if (typeName === 'boolean') return t.tsBooleanKeyword(); + return t.tsTypeReference(t.identifier(typeName)); +} + +/** Build a required `select: S` property for overload signatures */ +function requiredSelectProp(): t.TSPropertySignature { + const prop = t.tsPropertySignature( + t.identifier('select'), + t.tsTypeAnnotation(t.tsTypeReference(t.identifier('S'))) + ); + prop.optional = false; + return prop; +} + +/** Build an optional `select?: undefined` prop to forbid select in fallback overloads */ +function optionalUndefinedSelectProp(): t.TSPropertySignature { + const prop = t.tsPropertySignature( + t.identifier('select'), + t.tsTypeAnnotation(t.tsUndefinedKeyword()) + ); + prop.optional = true; + return prop; +} + +/** Build `StrictSelect` type reference for overload intersections */ +function strictSelectGuard(selectTypeName: string): t.TSType { + return t.tsTypeReference( + t.identifier('StrictSelect'), + t.tsTypeParameterInstantiation([ + t.tsTypeReference(t.identifier('S')), + t.tsTypeReference(t.identifier(selectTypeName)) + ]) + ); +} + +/** Build `Omit & { select?: undefined }` for fallback overloads */ +function withoutSelect(argsType: t.TSType): t.TSType { + return t.tsIntersectionType([ + t.tsTypeReference( + t.identifier('Omit'), + t.tsTypeParameterInstantiation([ + argsType, + t.tsLiteralType(t.stringLiteral('select')) + ]) + ), + t.tsTypeLiteral([optionalUndefinedSelectProp()]) + ]); +} + export function generateModelFile( table: CleanTable, _useSharedTypes: boolean @@ -109,6 +184,11 @@ export function generateModelFile( const deleteInputTypeName = `Delete${typeName}Input`; const patchTypeName = `${typeName}Patch`; + const pkFields = getPrimaryKeyInfo(table); + const pkField = pkFields[0]; + const defaultSelectIdent = t.identifier('defaultSelect'); + const defaultSelectFieldName = getDefaultSelectFieldName(table); + const pluralQueryName = table.query?.all ?? pluralName; const createMutationName = table.query?.create ?? `create${typeName}`; const updateMutationName = table.query?.update; @@ -118,17 +198,32 @@ export function generateModelFile( statements.push(createImportDeclaration('../client', ['OrmClient'])); statements.push(createImportDeclaration('../query-builder', [ - 'QueryBuilder', 'buildFindManyDocument', 'buildFindFirstDocument', - 'buildCreateDocument', 'buildUpdateDocument', 'buildDeleteDocument', + 'QueryBuilder', 'buildFindManyDocument', 'buildFindFirstDocument', 'buildFindOneDocument', + 'buildCreateDocument', 'buildUpdateByPkDocument', 'buildDeleteByPkDocument' ])); statements.push(createImportDeclaration('../select-types', [ 'ConnectionResult', 'FindManyArgs', 'FindFirstArgs', 'CreateArgs', - 'UpdateArgs', 'DeleteArgs', 'InferSelectResult', 'DeepExact', + 'UpdateArgs', 'DeleteArgs', 'InferSelectResult', 'StrictSelect' ], true)); statements.push(createImportDeclaration('../input-types', [ typeName, relationTypeName, selectTypeName, whereTypeName, orderByTypeName, - createInputTypeName, updateInputTypeName, patchTypeName, + createInputTypeName, updateInputTypeName, patchTypeName ], true)); + statements.push(createImportDeclaration('../input-types', ['connectionFieldsMap'])); + + // Default select (ensures valid GraphQL selection + sound TS return types) + statements.push( + t.variableDeclaration('const', [ + t.variableDeclarator( + defaultSelectIdent, + asConst( + t.objectExpression([ + t.objectProperty(t.identifier(defaultSelectFieldName), t.booleanLiteral(true)) + ]) + ) + ) + ]) + ); const classBody: t.ClassBody['body'] = []; @@ -139,206 +234,421 @@ export function generateModelFile( paramProp.accessibility = 'private'; classBody.push(t.classMethod('constructor', t.identifier('constructor'), [paramProp], t.blockStatement([]))); - // findMany method - // Use DeepExact to enforce strict field validation - const findManyParam = t.identifier('args'); - findManyParam.optional = true; - findManyParam.typeAnnotation = t.tsTypeAnnotation( - t.tsTypeReference(t.identifier('FindManyArgs'), t.tsTypeParameterInstantiation([ - t.tsTypeReference(t.identifier('DeepExact'), t.tsTypeParameterInstantiation([ - t.tsTypeReference(t.identifier('S')), - t.tsTypeReference(t.identifier(selectTypeName)), - ])), - t.tsTypeReference(t.identifier(whereTypeName)), - t.tsTypeReference(t.identifier(orderByTypeName)), - ])) - ); - const findManyReturnType = t.tsTypeAnnotation( - t.tsTypeReference(t.identifier('QueryBuilder'), t.tsTypeParameterInstantiation([ - t.tsTypeLiteral([ - t.tsPropertySignature(t.identifier(pluralQueryName), t.tsTypeAnnotation( - t.tsTypeReference(t.identifier('ConnectionResult'), t.tsTypeParameterInstantiation([ - t.tsTypeReference(t.identifier('InferSelectResult'), t.tsTypeParameterInstantiation([ - t.tsTypeReference(t.identifier(relationTypeName)), - t.tsTypeReference(t.identifier('S')), - ])), - ])) + // Reusable type reference factories + const sRef = () => t.tsTypeReference(t.identifier('S')); + const defaultRef = () => t.tsTypeQuery(defaultSelectIdent); + const selectRef = () => t.tsTypeReference(t.identifier(selectTypeName)); + const pkTsType = () => tsTypeFromPrimitive(pkField.tsType); + + // ── findMany ─────────────────────────────────────────────────────────── + { + const argsType = (sel: t.TSType) => + t.tsTypeReference(t.identifier('FindManyArgs'), t.tsTypeParameterInstantiation([ + sel, + t.tsTypeReference(t.identifier(whereTypeName)), + t.tsTypeReference(t.identifier(orderByTypeName)) + ])); + const retType = (sel: t.TSType) => + t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('QueryBuilder'), t.tsTypeParameterInstantiation([ + t.tsTypeLiteral([ + t.tsPropertySignature(t.identifier(pluralQueryName), t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('ConnectionResult'), t.tsTypeParameterInstantiation([ + t.tsTypeReference(t.identifier('InferSelectResult'), t.tsTypeParameterInstantiation([ + t.tsTypeReference(t.identifier(relationTypeName)), + sel + ])) + ])) + )) + ]) + ])) + ); + + // Overload 1: with select (autocompletion) + const o1Param = t.identifier('args'); + o1Param.typeAnnotation = t.tsTypeAnnotation( + t.tsIntersectionType([ + argsType(sRef()), + t.tsTypeLiteral([requiredSelectProp()]), + strictSelectGuard(selectTypeName) + ]) + ); + classBody.push(createDeclareMethod('findMany', createTypeParam(selectTypeName), [o1Param], retType(sRef()))); + + // Overload 2: without select (default) + const o2Param = t.identifier('args'); + o2Param.optional = true; + o2Param.typeAnnotation = t.tsTypeAnnotation(withoutSelect(argsType(selectRef()))); + classBody.push(createDeclareMethod('findMany', null, [o2Param], retType(defaultRef()))); + + // Implementation + const implParam = t.identifier('args'); + implParam.optional = true; + implParam.typeAnnotation = t.tsTypeAnnotation(argsType(selectRef())); + const selectExpr = t.logicalExpression('??', + t.optionalMemberExpression(t.identifier('args'), t.identifier('select'), false, true), + defaultSelectIdent); + const bodyArgs = [ + t.stringLiteral(typeName), + t.stringLiteral(pluralQueryName), + selectExpr, + t.objectExpression([ + t.objectProperty(t.identifier('where'), t.optionalMemberExpression(t.identifier('args'), t.identifier('where'), false, true)), + t.objectProperty(t.identifier('orderBy'), t.tsAsExpression( + t.optionalMemberExpression(t.identifier('args'), t.identifier('orderBy'), false, true), + t.tsUnionType([t.tsArrayType(t.tsStringKeyword()), t.tsUndefinedKeyword()]) )), + t.objectProperty(t.identifier('first'), t.optionalMemberExpression(t.identifier('args'), t.identifier('first'), false, true)), + t.objectProperty(t.identifier('last'), t.optionalMemberExpression(t.identifier('args'), t.identifier('last'), false, true)), + t.objectProperty(t.identifier('after'), t.optionalMemberExpression(t.identifier('args'), t.identifier('after'), false, true)), + t.objectProperty(t.identifier('before'), t.optionalMemberExpression(t.identifier('args'), t.identifier('before'), false, true)), + t.objectProperty(t.identifier('offset'), t.optionalMemberExpression(t.identifier('args'), t.identifier('offset'), false, true)) ]), - ])) - ); - const findManyArgs = [ - t.stringLiteral(typeName), - t.stringLiteral(pluralQueryName), - t.optionalMemberExpression(t.identifier('args'), t.identifier('select'), false, true), - t.objectExpression([ - t.objectProperty(t.identifier('where'), t.optionalMemberExpression(t.identifier('args'), t.identifier('where'), false, true)), - t.objectProperty(t.identifier('orderBy'), t.tsAsExpression( - t.optionalMemberExpression(t.identifier('args'), t.identifier('orderBy'), false, true), - t.tsUnionType([t.tsArrayType(t.tsStringKeyword()), t.tsUndefinedKeyword()]) - )), - t.objectProperty(t.identifier('first'), t.optionalMemberExpression(t.identifier('args'), t.identifier('first'), false, true)), - t.objectProperty(t.identifier('last'), t.optionalMemberExpression(t.identifier('args'), t.identifier('last'), false, true)), - t.objectProperty(t.identifier('after'), t.optionalMemberExpression(t.identifier('args'), t.identifier('after'), false, true)), - t.objectProperty(t.identifier('before'), t.optionalMemberExpression(t.identifier('args'), t.identifier('before'), false, true)), - t.objectProperty(t.identifier('offset'), t.optionalMemberExpression(t.identifier('args'), t.identifier('offset'), false, true)), - ]), - t.stringLiteral(whereTypeName), - t.stringLiteral(orderByTypeName), - ]; - classBody.push(createClassMethod('findMany', createConstTypeParam(selectTypeName), [findManyParam], findManyReturnType, - buildMethodBody('buildFindManyDocument', findManyArgs, 'query', typeName, pluralQueryName))); - - // findFirst method - const findFirstParam = t.identifier('args'); - findFirstParam.optional = true; - findFirstParam.typeAnnotation = t.tsTypeAnnotation( - t.tsTypeReference(t.identifier('FindFirstArgs'), t.tsTypeParameterInstantiation([ - t.tsTypeReference(t.identifier('DeepExact'), t.tsTypeParameterInstantiation([ - t.tsTypeReference(t.identifier('S')), - t.tsTypeReference(t.identifier(selectTypeName)), - ])), - t.tsTypeReference(t.identifier(whereTypeName)), - ])) - ); - const findFirstReturnType = t.tsTypeAnnotation( - t.tsTypeReference(t.identifier('QueryBuilder'), t.tsTypeParameterInstantiation([ - t.tsTypeLiteral([ - t.tsPropertySignature(t.identifier(pluralQueryName), t.tsTypeAnnotation( + t.stringLiteral(whereTypeName), + t.stringLiteral(orderByTypeName), + t.identifier('connectionFieldsMap') + ]; + classBody.push(createClassMethod('findMany', null, [implParam], null, + buildMethodBody('buildFindManyDocument', bodyArgs, 'query', typeName, pluralQueryName))); + } + + // ── findFirst ────────────────────────────────────────────────────────── + { + const argsType = (sel: t.TSType) => + t.tsTypeReference(t.identifier('FindFirstArgs'), t.tsTypeParameterInstantiation([ + sel, + t.tsTypeReference(t.identifier(whereTypeName)) + ])); + const retType = (sel: t.TSType) => + t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('QueryBuilder'), t.tsTypeParameterInstantiation([ t.tsTypeLiteral([ - t.tsPropertySignature(t.identifier('nodes'), t.tsTypeAnnotation( - t.tsArrayType(t.tsTypeReference(t.identifier('InferSelectResult'), t.tsTypeParameterInstantiation([ - t.tsTypeReference(t.identifier(relationTypeName)), - t.tsTypeReference(t.identifier('S')), - ]))) - )), + t.tsPropertySignature(t.identifier(pluralQueryName), t.tsTypeAnnotation( + t.tsTypeLiteral([ + t.tsPropertySignature(t.identifier('nodes'), t.tsTypeAnnotation( + t.tsArrayType(t.tsTypeReference(t.identifier('InferSelectResult'), t.tsTypeParameterInstantiation([ + t.tsTypeReference(t.identifier(relationTypeName)), + sel + ]))) + )) + ]) + )) ]) - )), + ])) + ); + + // Overload 1: with select (autocompletion) + const o1Param = t.identifier('args'); + o1Param.typeAnnotation = t.tsTypeAnnotation( + t.tsIntersectionType([ + argsType(sRef()), + t.tsTypeLiteral([requiredSelectProp()]), + strictSelectGuard(selectTypeName) + ]) + ); + classBody.push(createDeclareMethod('findFirst', createTypeParam(selectTypeName), [o1Param], retType(sRef()))); + + // Overload 2: without select (default) + const o2Param = t.identifier('args'); + o2Param.optional = true; + o2Param.typeAnnotation = t.tsTypeAnnotation(withoutSelect(argsType(selectRef()))); + classBody.push(createDeclareMethod('findFirst', null, [o2Param], retType(defaultRef()))); + + // Implementation + const implParam = t.identifier('args'); + implParam.optional = true; + implParam.typeAnnotation = t.tsTypeAnnotation(argsType(selectRef())); + const selectExpr = t.logicalExpression('??', + t.optionalMemberExpression(t.identifier('args'), t.identifier('select'), false, true), + defaultSelectIdent); + const bodyArgs = [ + t.stringLiteral(typeName), + t.stringLiteral(pluralQueryName), + selectExpr, + t.objectExpression([ + t.objectProperty(t.identifier('where'), t.optionalMemberExpression(t.identifier('args'), t.identifier('where'), false, true)) ]), - ])) - ); - const findFirstArgs = [ - t.stringLiteral(typeName), - t.stringLiteral(pluralQueryName), - t.optionalMemberExpression(t.identifier('args'), t.identifier('select'), false, true), - t.objectExpression([ - t.objectProperty(t.identifier('where'), t.optionalMemberExpression(t.identifier('args'), t.identifier('where'), false, true)), - ]), - t.stringLiteral(whereTypeName), - ]; - classBody.push(createClassMethod('findFirst', createConstTypeParam(selectTypeName), [findFirstParam], findFirstReturnType, - buildMethodBody('buildFindFirstDocument', findFirstArgs, 'query', typeName, pluralQueryName))); - - // create method - const createParam = t.identifier('args'); - createParam.typeAnnotation = t.tsTypeAnnotation( - t.tsTypeReference(t.identifier('CreateArgs'), t.tsTypeParameterInstantiation([ - t.tsTypeReference(t.identifier('DeepExact'), t.tsTypeParameterInstantiation([ - t.tsTypeReference(t.identifier('S')), - t.tsTypeReference(t.identifier(selectTypeName)), - ])), - t.tsIndexedAccessType(t.tsTypeReference(t.identifier(createInputTypeName)), t.tsLiteralType(t.stringLiteral(singularName))), - ])) - ); - const createReturnType = t.tsTypeAnnotation( - t.tsTypeReference(t.identifier('QueryBuilder'), t.tsTypeParameterInstantiation([ + t.stringLiteral(whereTypeName), + t.identifier('connectionFieldsMap') + ]; + classBody.push(createClassMethod('findFirst', null, [implParam], null, + buildMethodBody('buildFindFirstDocument', bodyArgs, 'query', typeName, pluralQueryName))); + } + + // ── findOne ──────────────────────────────────────────────────────────── + const singleQueryName = table.query?.one; + if (singleQueryName && hasValidPrimaryKey(table)) { + const pkGqlType = pkField.gqlType.replace(/!/g, '') + '!'; + + const retType = (sel: t.TSType) => + t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('QueryBuilder'), t.tsTypeParameterInstantiation([ + t.tsTypeLiteral([ + t.tsPropertySignature(t.identifier(singleQueryName), t.tsTypeAnnotation( + t.tsUnionType([ + t.tsTypeReference(t.identifier('InferSelectResult'), t.tsTypeParameterInstantiation([ + t.tsTypeReference(t.identifier(relationTypeName)), + sel + ])), + t.tsNullKeyword() + ]) + )) + ]) + ])) + ); + + const pkProp = () => { + const prop = t.tsPropertySignature(t.identifier(pkField.name), t.tsTypeAnnotation(pkTsType())); + prop.optional = false; + return prop; + }; + + // Overload 1: with select (autocompletion) + const o1Param = t.identifier('args'); + o1Param.typeAnnotation = t.tsTypeAnnotation( + t.tsIntersectionType([ + t.tsTypeLiteral([pkProp(), requiredSelectProp()]), + strictSelectGuard(selectTypeName) + ]) + ); + classBody.push(createDeclareMethod('findOne', createTypeParam(selectTypeName), [o1Param], retType(sRef()))); + + // Overload 2: without select (default) + const o2Param = t.identifier('args'); + o2Param.typeAnnotation = t.tsTypeAnnotation( + t.tsTypeLiteral([pkProp()]) + ); + classBody.push(createDeclareMethod('findOne', null, [o2Param], retType(defaultRef()))); + + // Implementation + const implParam = t.identifier('args'); + implParam.typeAnnotation = t.tsTypeAnnotation( t.tsTypeLiteral([ - t.tsPropertySignature(t.identifier(createMutationName), t.tsTypeAnnotation( + pkProp(), + (() => { + const prop = t.tsPropertySignature( + t.identifier('select'), + t.tsTypeAnnotation(t.tsTypeReference(t.identifier(selectTypeName))) + ); + prop.optional = true; + return prop; + })() + ]) + ); + const selectExpr = t.logicalExpression('??', + t.memberExpression(t.identifier('args'), t.identifier('select')), + defaultSelectIdent); + const bodyArgs = [ + t.stringLiteral(typeName), + t.stringLiteral(singleQueryName), + t.memberExpression(t.identifier('args'), t.identifier(pkField.name)), + selectExpr, + t.stringLiteral(pkField.name), + t.stringLiteral(pkGqlType), + t.identifier('connectionFieldsMap') + ]; + classBody.push(createClassMethod('findOne', null, [implParam], null, + buildMethodBody('buildFindOneDocument', bodyArgs, 'query', typeName, singleQueryName))); + } + + // ── create ───────────────────────────────────────────────────────────── + { + const dataType = () => t.tsIndexedAccessType( + t.tsTypeReference(t.identifier(createInputTypeName)), + t.tsLiteralType(t.stringLiteral(singularName)) + ); + const argsType = (sel: t.TSType) => + t.tsTypeReference(t.identifier('CreateArgs'), t.tsTypeParameterInstantiation([sel, dataType()])); + const retType = (sel: t.TSType) => + t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('QueryBuilder'), t.tsTypeParameterInstantiation([ t.tsTypeLiteral([ - t.tsPropertySignature(t.identifier(entityLower), t.tsTypeAnnotation( - t.tsTypeReference(t.identifier('InferSelectResult'), t.tsTypeParameterInstantiation([ - t.tsTypeReference(t.identifier(relationTypeName)), - t.tsTypeReference(t.identifier('S')), - ])) - )), + t.tsPropertySignature(t.identifier(createMutationName), t.tsTypeAnnotation( + t.tsTypeLiteral([ + t.tsPropertySignature(t.identifier(entityLower), t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('InferSelectResult'), t.tsTypeParameterInstantiation([ + t.tsTypeReference(t.identifier(relationTypeName)), + sel + ])) + )) + ]) + )) ]) - )), - ]), - ])) - ); - const createArgs = [ - t.stringLiteral(typeName), - t.stringLiteral(createMutationName), - t.stringLiteral(entityLower), - t.memberExpression(t.identifier('args'), t.identifier('select')), - t.memberExpression(t.identifier('args'), t.identifier('data')), - t.stringLiteral(createInputTypeName), - ]; - classBody.push(createClassMethod('create', createConstTypeParam(selectTypeName), [createParam], createReturnType, - buildMethodBody('buildCreateDocument', createArgs, 'mutation', typeName, createMutationName))); - - // update method (if available) + ])) + ); + + // Overload 1: with select (autocompletion) + const o1Param = t.identifier('args'); + o1Param.typeAnnotation = t.tsTypeAnnotation( + t.tsIntersectionType([ + argsType(sRef()), + t.tsTypeLiteral([requiredSelectProp()]), + strictSelectGuard(selectTypeName) + ]) + ); + classBody.push(createDeclareMethod('create', createTypeParam(selectTypeName), [o1Param], retType(sRef()))); + + // Overload 2: without select (default) + const o2Param = t.identifier('args'); + o2Param.typeAnnotation = t.tsTypeAnnotation(withoutSelect(argsType(selectRef()))); + classBody.push(createDeclareMethod('create', null, [o2Param], retType(defaultRef()))); + + // Implementation + const implParam = t.identifier('args'); + implParam.typeAnnotation = t.tsTypeAnnotation(argsType(selectRef())); + const selectExpr = t.logicalExpression('??', + t.memberExpression(t.identifier('args'), t.identifier('select')), + defaultSelectIdent); + const bodyArgs = [ + t.stringLiteral(typeName), + t.stringLiteral(createMutationName), + t.stringLiteral(entityLower), + selectExpr, + t.memberExpression(t.identifier('args'), t.identifier('data')), + t.stringLiteral(createInputTypeName), + t.identifier('connectionFieldsMap') + ]; + classBody.push(createClassMethod('create', null, [implParam], null, + buildMethodBody('buildCreateDocument', bodyArgs, 'mutation', typeName, createMutationName))); + } + + // ── update ───────────────────────────────────────────────────────────── if (updateMutationName) { - const updateParam = t.identifier('args'); - updateParam.typeAnnotation = t.tsTypeAnnotation( + const whereLiteral = () => t.tsTypeLiteral([ + (() => { + const prop = t.tsPropertySignature(t.identifier(pkField.name), t.tsTypeAnnotation(pkTsType())); + prop.optional = false; + return prop; + })() + ]); + const argsType = (sel: t.TSType) => t.tsTypeReference(t.identifier('UpdateArgs'), t.tsTypeParameterInstantiation([ - t.tsTypeReference(t.identifier('DeepExact'), t.tsTypeParameterInstantiation([ - t.tsTypeReference(t.identifier('S')), - t.tsTypeReference(t.identifier(selectTypeName)), - ])), - t.tsTypeLiteral([t.tsPropertySignature(t.identifier('id'), t.tsTypeAnnotation(t.tsStringKeyword()))]), - t.tsTypeReference(t.identifier(patchTypeName)), - ])) - ); - const updateReturnType = t.tsTypeAnnotation( - t.tsTypeReference(t.identifier('QueryBuilder'), t.tsTypeParameterInstantiation([ - t.tsTypeLiteral([ - t.tsPropertySignature(t.identifier(updateMutationName), t.tsTypeAnnotation( - t.tsTypeLiteral([ - t.tsPropertySignature(t.identifier(entityLower), t.tsTypeAnnotation( - t.tsTypeReference(t.identifier('InferSelectResult'), t.tsTypeParameterInstantiation([ - t.tsTypeReference(t.identifier(relationTypeName)), - t.tsTypeReference(t.identifier('S')), - ])) - )), - ]) - )), - ]), - ])) + sel, whereLiteral(), t.tsTypeReference(t.identifier(patchTypeName)) + ])); + const retType = (sel: t.TSType) => + t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('QueryBuilder'), t.tsTypeParameterInstantiation([ + t.tsTypeLiteral([ + t.tsPropertySignature(t.identifier(updateMutationName), t.tsTypeAnnotation( + t.tsTypeLiteral([ + t.tsPropertySignature(t.identifier(entityLower), t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('InferSelectResult'), t.tsTypeParameterInstantiation([ + t.tsTypeReference(t.identifier(relationTypeName)), + sel + ])) + )) + ]) + )) + ]) + ])) + ); + + // Overload 1: with select (autocompletion) + const o1Param = t.identifier('args'); + o1Param.typeAnnotation = t.tsTypeAnnotation( + t.tsIntersectionType([ + argsType(sRef()), + t.tsTypeLiteral([requiredSelectProp()]), + strictSelectGuard(selectTypeName) + ]) ); - const updateArgs = [ + classBody.push(createDeclareMethod('update', createTypeParam(selectTypeName), [o1Param], retType(sRef()))); + + // Overload 2: without select (default) + const o2Param = t.identifier('args'); + o2Param.typeAnnotation = t.tsTypeAnnotation(withoutSelect(argsType(selectRef()))); + classBody.push(createDeclareMethod('update', null, [o2Param], retType(defaultRef()))); + + // Implementation + const implParam = t.identifier('args'); + implParam.typeAnnotation = t.tsTypeAnnotation(argsType(selectRef())); + const selectExpr = t.logicalExpression('??', + t.memberExpression(t.identifier('args'), t.identifier('select')), + defaultSelectIdent); + const bodyArgs = [ t.stringLiteral(typeName), t.stringLiteral(updateMutationName), t.stringLiteral(entityLower), - t.memberExpression(t.identifier('args'), t.identifier('select')), - t.memberExpression(t.identifier('args'), t.identifier('where')), + selectExpr, + t.memberExpression( + t.memberExpression(t.identifier('args'), t.identifier('where')), + t.identifier(pkField.name) + ), t.memberExpression(t.identifier('args'), t.identifier('data')), t.stringLiteral(updateInputTypeName), + t.stringLiteral(pkField.name), + t.identifier('connectionFieldsMap') ]; - classBody.push(createClassMethod('update', createConstTypeParam(selectTypeName), [updateParam], updateReturnType, - buildMethodBody('buildUpdateDocument', updateArgs, 'mutation', typeName, updateMutationName))); + classBody.push(createClassMethod('update', null, [implParam], null, + buildMethodBody('buildUpdateByPkDocument', bodyArgs, 'mutation', typeName, updateMutationName))); } - // delete method (if available) + // ── delete ───────────────────────────────────────────────────────────── if (deleteMutationName) { - const deleteParam = t.identifier('args'); - deleteParam.typeAnnotation = t.tsTypeAnnotation( - t.tsTypeReference(t.identifier('DeleteArgs'), t.tsTypeParameterInstantiation([ - t.tsTypeLiteral([t.tsPropertySignature(t.identifier('id'), t.tsTypeAnnotation(t.tsStringKeyword()))]), - ])) - ); - const deleteReturnType = t.tsTypeAnnotation( - t.tsTypeReference(t.identifier('QueryBuilder'), t.tsTypeParameterInstantiation([ - t.tsTypeLiteral([ - t.tsPropertySignature(t.identifier(deleteMutationName), t.tsTypeAnnotation( - t.tsTypeLiteral([ - t.tsPropertySignature(t.identifier(entityLower), t.tsTypeAnnotation( - t.tsTypeLiteral([t.tsPropertySignature(t.identifier('id'), t.tsTypeAnnotation(t.tsStringKeyword()))]) - )), - ]) - )), - ]), - ])) + const whereLiteral = () => t.tsTypeLiteral([ + (() => { + const prop = t.tsPropertySignature(t.identifier(pkField.name), t.tsTypeAnnotation(pkTsType())); + prop.optional = false; + return prop; + })() + ]); + const argsType = (sel: t.TSType) => + t.tsTypeReference(t.identifier('DeleteArgs'), t.tsTypeParameterInstantiation([whereLiteral(), sel])); + const retType = (sel: t.TSType) => + t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('QueryBuilder'), t.tsTypeParameterInstantiation([ + t.tsTypeLiteral([ + t.tsPropertySignature(t.identifier(deleteMutationName), t.tsTypeAnnotation( + t.tsTypeLiteral([ + t.tsPropertySignature(t.identifier(entityLower), t.tsTypeAnnotation( + t.tsTypeReference(t.identifier('InferSelectResult'), t.tsTypeParameterInstantiation([ + t.tsTypeReference(t.identifier(relationTypeName)), + sel + ])) + )) + ]) + )) + ]) + ])) + ); + + // Overload 1: with select (autocompletion) + const o1Param = t.identifier('args'); + o1Param.typeAnnotation = t.tsTypeAnnotation( + t.tsIntersectionType([ + argsType(sRef()), + t.tsTypeLiteral([requiredSelectProp()]), + strictSelectGuard(selectTypeName) + ]) ); - const deleteArgs = [ + classBody.push(createDeclareMethod('delete', createTypeParam(selectTypeName), [o1Param], retType(sRef()))); + + // Overload 2: without select (default) + const o2Param = t.identifier('args'); + o2Param.typeAnnotation = t.tsTypeAnnotation(withoutSelect(argsType(selectRef()))); + classBody.push(createDeclareMethod('delete', null, [o2Param], retType(defaultRef()))); + + // Implementation + const implParam = t.identifier('args'); + implParam.typeAnnotation = t.tsTypeAnnotation(argsType(selectRef())); + const selectExpr = t.logicalExpression('??', + t.memberExpression(t.identifier('args'), t.identifier('select')), + defaultSelectIdent); + const bodyArgs = [ t.stringLiteral(typeName), t.stringLiteral(deleteMutationName), t.stringLiteral(entityLower), - t.memberExpression(t.identifier('args'), t.identifier('where')), + t.memberExpression( + t.memberExpression(t.identifier('args'), t.identifier('where')), + t.identifier(pkField.name) + ), t.stringLiteral(deleteInputTypeName), + t.stringLiteral(pkField.name), + selectExpr, + t.identifier('connectionFieldsMap') ]; - classBody.push(createClassMethod('delete', null, [deleteParam], deleteReturnType, - buildMethodBody('buildDeleteDocument', deleteArgs, 'mutation', typeName, deleteMutationName))); + classBody.push(createClassMethod('delete', null, [implParam], null, + buildMethodBody('buildDeleteByPkDocument', bodyArgs, 'mutation', typeName, deleteMutationName))); } const classDecl = t.classDeclaration(t.identifier(modelName), null, t.classBody(classBody)); diff --git a/graphql/codegen/src/core/codegen/orm/select-types.ts b/graphql/codegen/src/core/codegen/orm/select-types.ts index 973b216c3..446a4b642 100644 --- a/graphql/codegen/src/core/codegen/orm/select-types.ts +++ b/graphql/codegen/src/core/codegen/orm/select-types.ts @@ -53,16 +53,10 @@ export interface NestedSelectConfig { /** * Recursively validates select objects, rejecting unknown keys. * - * This type ensures that users can only select fields that actually exist - * in the GraphQL schema. It returns `never` if any excess keys are found - * at any nesting level, causing a TypeScript compile error. - * - * Why this is needed: - * TypeScript's excess property checking has a quirk where it only catches - * invalid fields when they are the ONLY fields. When mixed with valid fields - * (e.g., `{ id: true, invalidField: true }`), the structural typing allows - * the excess property through. This type explicitly checks for and rejects - * such cases. + * NOTE: This type is intentionally NOT used in generated parameter positions + * (conditional types block IDE autocompletion). Parameters use `S` directly + * with `S extends XxxSelect` constraints, which provides full + * autocompletion via TypeScript's contextual typing. * * @example * // This will cause a type error because 'invalid' doesn't exist: @@ -79,15 +73,25 @@ export type DeepExact = T extends Shape ? { [K in keyof T]: K extends keyof Shape ? T[K] extends { select: infer NS } - ? Shape[K] extends { select?: infer ShapeNS } - ? { select: DeepExact> } - : T[K] + ? Extract extends { select?: infer ShapeNS } + ? DeepExact< + Omit & { select: DeepExact> }, + Extract + > + : never : T[K] : never; } : never : never; +/** + * Enforces exact select shape while keeping contextual typing on `S extends XxxSelect`. + * Use this as an intersection in overloads: + * `{ select: S } & StrictSelect`. + */ +export type StrictSelect = S extends DeepExact ? {} : never; + /** * Infers the result type from a select configuration * @@ -202,8 +206,9 @@ export interface UpdateArgs { /** * Arguments for delete operations */ -export interface DeleteArgs { +export interface DeleteArgs { where: TWhere; + select?: TSelect; } /** diff --git a/graphql/codegen/src/core/codegen/queries.ts b/graphql/codegen/src/core/codegen/queries.ts index 55852c339..38e4e5395 100644 --- a/graphql/codegen/src/core/codegen/queries.ts +++ b/graphql/codegen/src/core/codegen/queries.ts @@ -1,39 +1,75 @@ /** - * Query hook generators using Babel AST-based code generation + * Query hook generators - delegates to ORM model methods (Babel AST-based) * * Output structure: * queries/ - * useCarsQuery.ts - List query hook - * useCarQuery.ts - Single item query hook + * useCarsQuery.ts - List query hook -> ORM findMany + * useCarQuery.ts - Single item query hook -> ORM findOne */ -import type { CleanTable } from '../../types/schema'; import * as t from '@babel/types'; -import { generateCode, addJSDocComment, typedParam, createTypedCallExpression } from './babel-ast'; + +import type { CleanTable } from '../../types/schema'; +import { asConst } from './babel-ast'; import { - buildListQueryAST, - buildSingleQueryAST, - printGraphQL, -} from './gql-ast'; + addJSDocComment, + buildFindManyCallExpr, + buildFindOneCallExpr, + buildListSelectionArgsCall, + buildSelectionArgsCall, + buildSelectFallbackExpr, + callExpr, + connectionResultType, + constDecl, + createFunctionParam, + createImportDeclaration, + createSAndTDataTypeParams, + createSTypeParam, + createTDataTypeParam, + createTypeReExport, + destructureParamsWithSelection, + destructureParamsWithSelectionAndScope, + exportAsyncDeclareFunction, + exportAsyncFunction, + exportDeclareFunction, + exportFunction, + generateHookFileCode, + inferSelectResultType, + listQueryResultType, + listSelectionConfigType, + objectProp, + omitType, + returnUseQuery, + scopeTypeLiteral, + selectionConfigType, + singleQueryResultType, + spreadObj, + sRef, + typeofRef, + typeRef, + typeLiteralWithProps, + useQueryOptionsType, + useQueryOptionsImplType, + voidStatement, + withFieldsListSelectionType, + withFieldsSelectionType, + withoutFieldsListSelectionType, + withoutFieldsSelectionType +} from './hooks-ast'; import { - getTableNames, - getListQueryHookName, - getSingleQueryHookName, - getListQueryFileName, - getSingleQueryFileName, getAllRowsQueryName, - getSingleRowQueryName, + getDefaultSelectFieldName, getFilterTypeName, - getConditionTypeName, + getListQueryFileName, + getListQueryHookName, getOrderByTypeName, - getScalarFields, - getScalarFilterType, getPrimaryKeyInfo, + getSingleQueryFileName, + getSingleQueryHookName, + getSingleRowQueryName, + getTableNames, hasValidPrimaryKey, - fieldTypeToTs, - toScreamingSnake, - ucFirst, lcFirst, - getGeneratedFileHeader, + ucFirst } from './utils'; export interface GeneratedQueryFile { @@ -47,55 +83,6 @@ export interface QueryGeneratorOptions { hasRelationships?: boolean; } -function createUnionType(values: string[]): t.TSUnionType { - return t.tsUnionType(values.map((v) => t.tsLiteralType(t.stringLiteral(v)))); -} - -function createFilterInterfaceDeclaration( - name: string, - fieldFilters: Array<{ fieldName: string; filterType: string }>, - isExported: boolean = true -): t.Statement { - const properties: t.TSPropertySignature[] = []; - for (const filter of fieldFilters) { - const prop = t.tsPropertySignature( - t.identifier(filter.fieldName), - t.tsTypeAnnotation(t.tsTypeReference(t.identifier(filter.filterType))) - ); - prop.optional = true; - properties.push(prop); - } - const andProp = t.tsPropertySignature( - t.identifier('and'), - t.tsTypeAnnotation(t.tsArrayType(t.tsTypeReference(t.identifier(name)))) - ); - andProp.optional = true; - properties.push(andProp); - const orProp = t.tsPropertySignature( - t.identifier('or'), - t.tsTypeAnnotation(t.tsArrayType(t.tsTypeReference(t.identifier(name)))) - ); - orProp.optional = true; - properties.push(orProp); - const notProp = t.tsPropertySignature( - t.identifier('not'), - t.tsTypeAnnotation(t.tsTypeReference(t.identifier(name))) - ); - notProp.optional = true; - properties.push(notProp); - const body = t.tsInterfaceBody(properties); - const interfaceDecl = t.tsInterfaceDeclaration( - t.identifier(name), - null, - null, - body - ); - if (isExported) { - return t.exportNamedDeclaration(interfaceDecl); - } - return interfaceDecl; -} - export function generateListQueryHook( table: CleanTable, options: QueryGeneratorOptions = {} @@ -103,742 +90,357 @@ export function generateListQueryHook( const { reactQueryEnabled = true, useCentralizedKeys = true, - hasRelationships = false, + hasRelationships = false } = options; - const { typeName, pluralName } = getTableNames(table); + const { typeName, pluralName, singularName } = getTableNames(table); const hookName = getListQueryHookName(table); const queryName = getAllRowsQueryName(table); const filterTypeName = getFilterTypeName(table); - const conditionTypeName = getConditionTypeName(table); const orderByTypeName = getOrderByTypeName(table); - const scalarFields = getScalarFields(table); const keysName = `${lcFirst(typeName)}Keys`; const scopeTypeName = `${typeName}Scope`; + const selectTypeName = `${typeName}Select`; + const relationTypeName = `${typeName}WithRelations`; + const defaultFieldName = getDefaultSelectFieldName(table); - const queryAST = buildListQueryAST({ table }); - const queryDocument = printGraphQL(queryAST); + const listResultTypeAST = (sel: t.TSType) => listQueryResultType(queryName, relationTypeName, sel); const statements: t.Statement[] = []; - const filterTypesUsed = new Set(); - for (const field of scalarFields) { - const filterType = getScalarFilterType(field.type.gqlType, field.type.isArray); - if (filterType) { - filterTypesUsed.add(filterType); - } - } - + // Imports if (reactQueryEnabled) { - const reactQueryImport = t.importDeclaration( - [t.importSpecifier(t.identifier('useQuery'), t.identifier('useQuery'))], - t.stringLiteral('@tanstack/react-query') - ); - statements.push(reactQueryImport); - const reactQueryTypeImport = t.importDeclaration( - [ - t.importSpecifier( - t.identifier('UseQueryOptions'), - t.identifier('UseQueryOptions') - ), - t.importSpecifier( - t.identifier('QueryClient'), - t.identifier('QueryClient') - ), - ], - t.stringLiteral('@tanstack/react-query') - ); - reactQueryTypeImport.importKind = 'type'; - statements.push(reactQueryTypeImport); + statements.push(createImportDeclaration('@tanstack/react-query', ['useQuery'])); + statements.push(createImportDeclaration('@tanstack/react-query', ['UseQueryOptions', 'UseQueryResult', 'QueryClient'], true)); } - - const clientImport = t.importDeclaration( - [t.importSpecifier(t.identifier('execute'), t.identifier('execute'))], - t.stringLiteral('../client') - ); - statements.push(clientImport); - const clientTypeImport = t.importDeclaration( - [ - t.importSpecifier( - t.identifier('ExecuteOptions'), - t.identifier('ExecuteOptions') - ), - ], - t.stringLiteral('../client') - ); - clientTypeImport.importKind = 'type'; - statements.push(clientTypeImport); - - const typesImport = t.importDeclaration( - [ - t.importSpecifier(t.identifier(typeName), t.identifier(typeName)), - ...Array.from(filterTypesUsed).map((ft) => - t.importSpecifier(t.identifier(ft), t.identifier(ft)) - ), - ], - t.stringLiteral('../types') - ); - typesImport.importKind = 'type'; - statements.push(typesImport); + statements.push(createImportDeclaration('../client', ['getClient'])); + statements.push(createImportDeclaration('../selection', ['buildListSelectionArgs'])); + statements.push(createImportDeclaration('../selection', ['ListSelectionConfig'], true)); if (useCentralizedKeys) { - const queryKeyImport = t.importDeclaration( - [t.importSpecifier(t.identifier(keysName), t.identifier(keysName))], - t.stringLiteral('../query-keys') - ); - statements.push(queryKeyImport); + statements.push(createImportDeclaration('../query-keys', [keysName])); if (hasRelationships) { - const scopeTypeImport = t.importDeclaration( - [ - t.importSpecifier( - t.identifier(scopeTypeName), - t.identifier(scopeTypeName) - ), - ], - t.stringLiteral('../query-keys') - ); - scopeTypeImport.importKind = 'type'; - statements.push(scopeTypeImport); + statements.push(createImportDeclaration('../query-keys', [scopeTypeName], true)); } } - const reExportDecl = t.exportNamedDeclaration( - null, - [t.exportSpecifier(t.identifier(typeName), t.identifier(typeName))], - t.stringLiteral('../types') - ); - reExportDecl.exportKind = 'type'; - statements.push(reExportDecl); - - const queryDocConst = t.variableDeclaration('const', [ - t.variableDeclarator( - t.identifier(`${queryName}QueryDocument`), - t.templateLiteral( - [ - t.templateElement( - { raw: '\n' + queryDocument, cooked: '\n' + queryDocument }, - true - ), - ], - [] - ) - ), - ]); - statements.push(t.exportNamedDeclaration(queryDocConst)); - - const fieldFilters = scalarFields - .map((field) => { - const filterType = getScalarFilterType(field.type.gqlType, field.type.isArray); - return filterType ? { fieldName: field.name, filterType } : null; - }) - .filter((f): f is { fieldName: string; filterType: string } => f !== null); - - statements.push( - createFilterInterfaceDeclaration(filterTypeName, fieldFilters, false) - ); + statements.push(createImportDeclaration('../../orm/input-types', [selectTypeName, relationTypeName, filterTypeName, orderByTypeName], true)); + statements.push(createImportDeclaration('../../orm/select-types', ['FindManyArgs', 'InferSelectResult', 'ConnectionResult', 'StrictSelect'], true)); - // Generate Condition interface (simple equality filter with scalar types) - // Track non-primitive types (enums) that need to be imported - const enumTypesUsed = new Set(); - const conditionProperties: t.TSPropertySignature[] = scalarFields.map( - (field) => { - const tsType = fieldTypeToTs(field.type); - const isPrimitive = - tsType === 'string' || - tsType === 'number' || - tsType === 'boolean' || - tsType === 'unknown' || - tsType.endsWith('[]'); - let typeAnnotation: t.TSType; - if (field.type.isArray) { - const baseType = tsType.replace('[]', ''); - const isBasePrimitive = - baseType === 'string' || - baseType === 'number' || - baseType === 'boolean' || - baseType === 'unknown'; - if (!isBasePrimitive) { - enumTypesUsed.add(baseType); - } - typeAnnotation = t.tsArrayType( - baseType === 'string' - ? t.tsStringKeyword() - : baseType === 'number' - ? t.tsNumberKeyword() - : baseType === 'boolean' - ? t.tsBooleanKeyword() - : t.tsTypeReference(t.identifier(baseType)) - ); - } else { - if (!isPrimitive) { - enumTypesUsed.add(tsType); - } - typeAnnotation = - tsType === 'string' - ? t.tsStringKeyword() - : tsType === 'number' - ? t.tsNumberKeyword() - : tsType === 'boolean' - ? t.tsBooleanKeyword() - : t.tsTypeReference(t.identifier(tsType)); - } - const prop = t.tsPropertySignature( - t.identifier(field.name), - t.tsTypeAnnotation(typeAnnotation) - ); - prop.optional = true; - return prop; - } - ); + // Re-exports + statements.push(createTypeReExport([selectTypeName, relationTypeName, filterTypeName, orderByTypeName], '../../orm/input-types')); - // Add import for enum types if any are used - if (enumTypesUsed.size > 0) { - const schemaTypesImport = t.importDeclaration( - Array.from(enumTypesUsed).map((et) => - t.importSpecifier(t.identifier(et), t.identifier(et)) - ), - t.stringLiteral('../schema-types') - ); - schemaTypesImport.importKind = 'type'; - statements.push(schemaTypesImport); - } - - const conditionInterface = t.tsInterfaceDeclaration( - t.identifier(conditionTypeName), - null, - null, - t.tsInterfaceBody(conditionProperties) - ); - statements.push(conditionInterface); - - const orderByValues = [ - ...scalarFields.flatMap((f) => [ - `${toScreamingSnake(f.name)}_ASC`, - `${toScreamingSnake(f.name)}_DESC`, - ]), - 'NATURAL', - 'PRIMARY_KEY_ASC', - 'PRIMARY_KEY_DESC', - ]; - const orderByTypeAlias = t.tsTypeAliasDeclaration( - t.identifier(orderByTypeName), - null, - createUnionType(orderByValues) - ); - statements.push(orderByTypeAlias); - - const variablesInterfaceBody = t.tsInterfaceBody([ - (() => { - const p = t.tsPropertySignature( - t.identifier('first'), - t.tsTypeAnnotation(t.tsNumberKeyword()) - ); - p.optional = true; - return p; - })(), - (() => { - const p = t.tsPropertySignature( - t.identifier('last'), - t.tsTypeAnnotation(t.tsNumberKeyword()) - ); - p.optional = true; - return p; - })(), - (() => { - const p = t.tsPropertySignature( - t.identifier('offset'), - t.tsTypeAnnotation(t.tsNumberKeyword()) - ); - p.optional = true; - return p; - })(), - (() => { - const p = t.tsPropertySignature( - t.identifier('before'), - t.tsTypeAnnotation(t.tsStringKeyword()) - ); - p.optional = true; - return p; - })(), - (() => { - const p = t.tsPropertySignature( - t.identifier('after'), - t.tsTypeAnnotation(t.tsStringKeyword()) - ); - p.optional = true; - return p; - })(), - (() => { - const p = t.tsPropertySignature( - t.identifier('filter'), - t.tsTypeAnnotation(t.tsTypeReference(t.identifier(filterTypeName))) - ); - p.optional = true; - return p; - })(), - (() => { - const p = t.tsPropertySignature( - t.identifier('condition'), - t.tsTypeAnnotation(t.tsTypeReference(t.identifier(conditionTypeName))) - ); - p.optional = true; - return p; - })(), - (() => { - const p = t.tsPropertySignature( - t.identifier('orderBy'), - t.tsTypeAnnotation( - t.tsArrayType(t.tsTypeReference(t.identifier(orderByTypeName))) - ) - ); - p.optional = true; - return p; - })(), - ]); - const variablesInterface = t.tsInterfaceDeclaration( - t.identifier(`${ucFirst(pluralName)}QueryVariables`), - null, - null, - variablesInterfaceBody - ); - statements.push(t.exportNamedDeclaration(variablesInterface)); - - const pageInfoType = t.tsTypeLiteral([ - t.tsPropertySignature( - t.identifier('hasNextPage'), - t.tsTypeAnnotation(t.tsBooleanKeyword()) - ), - t.tsPropertySignature( - t.identifier('hasPreviousPage'), - t.tsTypeAnnotation(t.tsBooleanKeyword()) - ), - t.tsPropertySignature( - t.identifier('startCursor'), - t.tsTypeAnnotation( - t.tsUnionType([t.tsStringKeyword(), t.tsNullKeyword()]) - ) - ), - t.tsPropertySignature( - t.identifier('endCursor'), - t.tsTypeAnnotation( - t.tsUnionType([t.tsStringKeyword(), t.tsNullKeyword()]) - ) - ), - ]); - const resultType = t.tsTypeLiteral([ - t.tsPropertySignature( - t.identifier('totalCount'), - t.tsTypeAnnotation(t.tsNumberKeyword()) - ), - t.tsPropertySignature( - t.identifier('nodes'), - t.tsTypeAnnotation( - t.tsArrayType(t.tsTypeReference(t.identifier(typeName))) - ) - ), - t.tsPropertySignature( - t.identifier('pageInfo'), - t.tsTypeAnnotation(pageInfoType) - ), - ]); - const resultInterfaceBody = t.tsInterfaceBody([ - t.tsPropertySignature( - t.identifier(queryName), - t.tsTypeAnnotation(resultType) - ), - ]); - const resultInterface = t.tsInterfaceDeclaration( - t.identifier(`${ucFirst(pluralName)}QueryResult`), - null, - null, - resultInterfaceBody - ); - statements.push(t.exportNamedDeclaration(resultInterface)); + // Default select + statements.push(constDecl('defaultSelect', asConst(t.objectExpression([objectProp(defaultFieldName, t.booleanLiteral(true))])))); + // Query key if (useCentralizedKeys) { - const queryKeyConst = t.variableDeclaration('const', [ - t.variableDeclarator( - t.identifier(`${queryName}QueryKey`), - t.memberExpression(t.identifier(keysName), t.identifier('list')) - ), - ]); - const queryKeyExport = t.exportNamedDeclaration(queryKeyConst); - addJSDocComment(queryKeyExport, [ - 'Query key factory - re-exported from query-keys.ts', - ]); - statements.push(queryKeyExport); + const keyDecl = t.exportNamedDeclaration( + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier(`${queryName}QueryKey`), + t.memberExpression(t.identifier(keysName), t.identifier('list')) + ) + ]) + ); + addJSDocComment(keyDecl, ['Query key factory - re-exported from query-keys.ts']); + statements.push(keyDecl); } else { - const queryKeyArrow = t.arrowFunctionExpression( - [ - typedParam( - 'variables', - t.tsTypeReference( - t.identifier(`${ucFirst(pluralName)}QueryVariables`) - ), - true - ), - ], - t.tsAsExpression( - t.arrayExpression([ - t.stringLiteral(typeName.toLowerCase()), - t.stringLiteral('list'), - t.identifier('variables'), - ]), - t.tsTypeReference(t.identifier('const')) - ) + const keyFn = t.arrowFunctionExpression( + [createFunctionParam('variables', typeRef('FindManyArgs', [t.tsUnknownKeyword(), typeRef(filterTypeName), typeRef(orderByTypeName)]), true)], + asConst(t.arrayExpression([t.stringLiteral(typeName.toLowerCase()), t.stringLiteral('list'), t.identifier('variables')])) ); - const queryKeyConst = t.variableDeclaration('const', [ - t.variableDeclarator( - t.identifier(`${queryName}QueryKey`), - queryKeyArrow - ), - ]); - statements.push(t.exportNamedDeclaration(queryKeyConst)); + statements.push(t.exportNamedDeclaration( + t.variableDeclaration('const', [t.variableDeclarator(t.identifier(`${queryName}QueryKey`), keyFn)]) + )); } - if (reactQueryEnabled) { - const hookBodyStatements: t.Statement[] = []; - if (hasRelationships && useCentralizedKeys) { - hookBodyStatements.push( - t.variableDeclaration('const', [ - t.variableDeclarator( - t.objectPattern([ - t.objectProperty( - t.identifier('scope'), - t.identifier('scope'), - false, - true - ), - t.restElement(t.identifier('queryOptions')), - ]), - t.logicalExpression( - '??', - t.identifier('options'), - t.objectExpression([]) - ) - ), - ]) - ); - hookBodyStatements.push( - t.returnStatement( - t.callExpression(t.identifier('useQuery'), [ - t.objectExpression([ - t.objectProperty( - t.identifier('queryKey'), - t.callExpression( - t.memberExpression( - t.identifier(keysName), - t.identifier('list') - ), - [t.identifier('variables'), t.identifier('scope')] - ) - ), - t.objectProperty( - t.identifier('queryFn'), - t.arrowFunctionExpression( - [], - createTypedCallExpression( - t.identifier('execute'), - [t.identifier(`${queryName}QueryDocument`), t.identifier('variables')], - [ - t.tsTypeReference(t.identifier(`${ucFirst(pluralName)}QueryResult`)), - t.tsTypeReference(t.identifier(`${ucFirst(pluralName)}QueryVariables`)), - ] - ) - ) - ), - t.spreadElement(t.identifier('queryOptions')), - ]), - ]) - ) - ); - } else if (useCentralizedKeys) { - hookBodyStatements.push( - t.returnStatement( - t.callExpression(t.identifier('useQuery'), [ - t.objectExpression([ - t.objectProperty( - t.identifier('queryKey'), - t.callExpression( - t.memberExpression( - t.identifier(keysName), - t.identifier('list') - ), - [t.identifier('variables')] - ) - ), - t.objectProperty( - t.identifier('queryFn'), - t.arrowFunctionExpression( - [], - createTypedCallExpression( - t.identifier('execute'), - [t.identifier(`${queryName}QueryDocument`), t.identifier('variables')], - [ - t.tsTypeReference(t.identifier(`${ucFirst(pluralName)}QueryResult`)), - t.tsTypeReference(t.identifier(`${ucFirst(pluralName)}QueryVariables`)), - ] - ) - ) - ), - t.spreadElement(t.identifier('options')), - ]), - ]) - ) - ); - } else { - hookBodyStatements.push( - t.returnStatement( - t.callExpression(t.identifier('useQuery'), [ - t.objectExpression([ - t.objectProperty( - t.identifier('queryKey'), - t.callExpression(t.identifier(`${queryName}QueryKey`), [ - t.identifier('variables'), - ]) - ), - t.objectProperty( - t.identifier('queryFn'), - t.arrowFunctionExpression( - [], - createTypedCallExpression( - t.identifier('execute'), - [t.identifier(`${queryName}QueryDocument`), t.identifier('variables')], - [ - t.tsTypeReference(t.identifier(`${ucFirst(pluralName)}QueryResult`)), - t.tsTypeReference(t.identifier(`${ucFirst(pluralName)}QueryVariables`)), - ] - ) - ) - ), - t.spreadElement(t.identifier('options')), - ]), - ]) - ) - ); + // Helper for query key call + const buildListQueryKey = (argsExpr: t.Expression, scopeExpr?: t.Expression) => { + if (useCentralizedKeys) { + const args = [argsExpr]; + if (scopeExpr) args.push(scopeExpr); + return callExpr(t.memberExpression(t.identifier(keysName), t.identifier('list')), args); } + return callExpr(t.identifier(`${queryName}QueryKey`), [argsExpr]); + }; - const hookParams: t.Identifier[] = [ - typedParam( - 'variables', - t.tsTypeReference(t.identifier(`${ucFirst(pluralName)}QueryVariables`)), - true - ), - ]; - let optionsTypeStr: string; + // Helper for findMany queryFn + const buildFindManyFn = () => t.arrowFunctionExpression( + [], + buildFindManyCallExpr(singularName, 'args', selectTypeName) + ); + + // Options type builder with optional scope + const buildOptionsType = (queryDataType: t.TSType, dataType: t.TSType) => { + const base = omitType( + typeRef('UseQueryOptions', [queryDataType, typeRef('Error'), dataType]), + ['queryKey', 'queryFn'] + ); if (hasRelationships && useCentralizedKeys) { - optionsTypeStr = `Omit, 'queryKey' | 'queryFn'> & { scope?: ${scopeTypeName} }`; - } else { - optionsTypeStr = `Omit, 'queryKey' | 'queryFn'>`; + return t.tsIntersectionType([base, scopeTypeLiteral(scopeTypeName)]); } - const optionsParam = t.identifier('options'); - optionsParam.optional = true; - optionsParam.typeAnnotation = t.tsTypeAnnotation( - t.tsTypeReference(t.identifier(optionsTypeStr)) - ); - hookParams.push(optionsParam); + return base; + }; - const hookFunc = t.functionDeclaration( - t.identifier(hookName), - hookParams, - t.blockStatement(hookBodyStatements) - ); - const hookExport = t.exportNamedDeclaration(hookFunc); + // Hook + if (reactQueryEnabled) { const docLines = [ `Query hook for fetching ${typeName} list`, '', '@example', '```tsx', `const { data, isLoading } = ${hookName}({`, - ' first: 10,', - ' filter: { name: { equalTo: "example" } },', - " orderBy: ['CREATED_AT_DESC'],", + ' selection: {', + ' fields: { id: true, name: true },', + ' where: { name: { equalTo: "example" } },', + " orderBy: ['CREATED_AT_DESC'],", + ' first: 10,', + ' },', '});', - '```', + '```' ]; if (hasRelationships && useCentralizedKeys) { docLines.push(''); docLines.push('@example With scope for hierarchical cache invalidation'); docLines.push('```tsx'); - docLines.push(`const { data } = ${hookName}(`); - docLines.push(' { first: 10 },'); - docLines.push(" { scope: { parentId: 'parent-id' } }"); - docLines.push(');'); + docLines.push(`const { data } = ${hookName}({`); + docLines.push(' selection: { first: 10 },'); + docLines.push(" scope: { parentId: 'parent-id' },"); + docLines.push('});'); docLines.push('```'); } - addJSDocComment(hookExport, docLines); - statements.push(hookExport); - } - const fetchFuncBody = t.blockStatement([ - t.returnStatement( - createTypedCallExpression( - t.identifier('execute'), - [t.identifier(`${queryName}QueryDocument`), t.identifier('variables'), t.identifier('options')], - [ - t.tsTypeReference(t.identifier(`${ucFirst(pluralName)}QueryResult`)), - t.tsTypeReference(t.identifier(`${ucFirst(pluralName)}QueryVariables`)), - ] - ) - ), - ]); - const fetchFunc = t.functionDeclaration( - t.identifier(`fetch${ucFirst(pluralName)}Query`), - [ - typedParam( - 'variables', - t.tsTypeReference(t.identifier(`${ucFirst(pluralName)}QueryVariables`)), - true - ), - typedParam( - 'options', - t.tsTypeReference(t.identifier('ExecuteOptions')), - true - ), - ], - fetchFuncBody - ); - fetchFunc.async = true; - fetchFunc.returnType = t.tsTypeAnnotation( - t.tsTypeReference( - t.identifier('Promise'), - t.tsTypeParameterInstantiation([ - t.tsTypeReference(t.identifier(`${ucFirst(pluralName)}QueryResult`)), - ]) - ) - ); - const fetchExport = t.exportNamedDeclaration(fetchFunc); - addJSDocComment(fetchExport, [ - `Fetch ${typeName} list without React hooks`, - '', - '@example', - '```ts', - '// Direct fetch', - `const data = await fetch${ucFirst(pluralName)}Query({ first: 10 });`, - '', - '// With QueryClient', - 'const data = await queryClient.fetchQuery({', - ` queryKey: ${queryName}QueryKey(variables),`, - ` queryFn: () => fetch${ucFirst(pluralName)}Query(variables),`, - '});', - '```', - ]); - statements.push(fetchExport); - - if (reactQueryEnabled) { - const prefetchParams: t.Identifier[] = [ - typedParam( - 'queryClient', - t.tsTypeReference(t.identifier('QueryClient')) - ), - typedParam( - 'variables', - t.tsTypeReference(t.identifier(`${ucFirst(pluralName)}QueryVariables`)), - true - ), - ]; - if (hasRelationships && useCentralizedKeys) { - prefetchParams.push( - typedParam( - 'scope', - t.tsTypeReference(t.identifier(scopeTypeName)), - true + // Overload 1: with fields + const o1ParamType = t.tsIntersectionType([ + t.tsTypeLiteral([ + t.tsPropertySignature( + t.identifier('selection'), + t.tsTypeAnnotation(withFieldsListSelectionType(sRef(), selectTypeName, filterTypeName, orderByTypeName)) ) - ); - } - prefetchParams.push( - typedParam( - 'options', - t.tsTypeReference(t.identifier('ExecuteOptions')), - true + ]), + buildOptionsType(listResultTypeAST(sRef()), typeRef('TData')) + ]); + const o1 = exportDeclareFunction( + hookName, + createSAndTDataTypeParams(selectTypeName, listResultTypeAST(sRef())), + [createFunctionParam('params', o1ParamType)], + typeRef('UseQueryResult', [typeRef('TData')]) + ); + addJSDocComment(o1, docLines); + statements.push(o1); + + // Overload 2: without fields + const o2SelProp = t.tsPropertySignature( + t.identifier('selection'), + t.tsTypeAnnotation(withoutFieldsListSelectionType(selectTypeName, filterTypeName, orderByTypeName)) + ); + o2SelProp.optional = true; + const o2ParamType = t.tsIntersectionType([ + t.tsTypeLiteral([o2SelProp]), + buildOptionsType(listResultTypeAST(typeofRef('defaultSelect')), typeRef('TData')) + ]); + statements.push( + exportDeclareFunction( + hookName, + createTDataTypeParam(listResultTypeAST(typeofRef('defaultSelect'))), + [createFunctionParam('params', o2ParamType, true)], + typeRef('UseQueryResult', [typeRef('TData')]) ) ); - let prefetchQueryKeyExpr: t.Expression; + // Implementation + const implSelProp = t.tsPropertySignature( + t.identifier('selection'), + t.tsTypeAnnotation(listSelectionConfigType(typeRef(selectTypeName), filterTypeName, orderByTypeName)) + ); + implSelProp.optional = true; + const implOptionsType = (() => { + const base = useQueryOptionsImplType(); + if (hasRelationships && useCentralizedKeys) { + return t.tsIntersectionType([base, scopeTypeLiteral(scopeTypeName)]); + } + return base; + })(); + const implParamType = t.tsIntersectionType([ + t.tsTypeLiteral([implSelProp]), + implOptionsType + ]); + + const body: t.Statement[] = []; + body.push(constDecl('selection', t.optionalMemberExpression(t.identifier('params'), t.identifier('selection'), false, true))); + body.push(buildListSelectionArgsCall(selectTypeName, filterTypeName, orderByTypeName)); + if (hasRelationships && useCentralizedKeys) { - prefetchQueryKeyExpr = t.callExpression( - t.memberExpression(t.identifier(keysName), t.identifier('list')), - [t.identifier('variables'), t.identifier('scope')] - ); - } else if (useCentralizedKeys) { - prefetchQueryKeyExpr = t.callExpression( - t.memberExpression(t.identifier(keysName), t.identifier('list')), - [t.identifier('variables')] - ); + body.push(destructureParamsWithSelectionAndScope('queryOptions')); + body.push(voidStatement('_selection')); + body.push(returnUseQuery( + buildListQueryKey(t.identifier('args'), t.identifier('scope')), + buildFindManyFn(), + [spreadObj(t.identifier('queryOptions'))] + )); } else { - prefetchQueryKeyExpr = t.callExpression( - t.identifier(`${queryName}QueryKey`), - [t.identifier('variables')] - ); + body.push(destructureParamsWithSelection('queryOptions')); + body.push(voidStatement('_selection')); + body.push(returnUseQuery( + buildListQueryKey(t.identifier('args')), + buildFindManyFn(), + [spreadObj(t.identifier('queryOptions'))] + )); } - const prefetchFuncBody = t.blockStatement([ - t.expressionStatement( - t.awaitExpression( - t.callExpression( - t.memberExpression( - t.identifier('queryClient'), - t.identifier('prefetchQuery') - ), - [ - t.objectExpression([ - t.objectProperty( - t.identifier('queryKey'), - prefetchQueryKeyExpr - ), - t.objectProperty( - t.identifier('queryFn'), - t.arrowFunctionExpression( - [], - createTypedCallExpression( - t.identifier('execute'), - [t.identifier(`${queryName}QueryDocument`), t.identifier('variables'), t.identifier('options')], - [ - t.tsTypeReference(t.identifier(`${ucFirst(pluralName)}QueryResult`)), - t.tsTypeReference(t.identifier(`${ucFirst(pluralName)}QueryVariables`)), - ] - ) - ) - ), - ]), - ] - ) - ) - ), + statements.push(exportFunction(hookName, null, [createFunctionParam('params', implParamType, true)], body)); + } + + // Fetch function + const fetchFnName = `fetch${ucFirst(pluralName)}Query`; + { + // Overload 1: with fields + const f1ParamType = t.tsTypeLiteral([ + t.tsPropertySignature( + t.identifier('selection'), + t.tsTypeAnnotation(withFieldsListSelectionType(sRef(), selectTypeName, filterTypeName, orderByTypeName)) + ) ]); + const f1Decl = exportAsyncDeclareFunction( + fetchFnName, + createSTypeParam(selectTypeName), + [createFunctionParam('params', f1ParamType)], + typeRef('Promise', [listResultTypeAST(sRef())]) + ); + addJSDocComment(f1Decl, [ + `Fetch ${typeName} list without React hooks`, + '', + '@example', + '```ts', + `const data = await ${fetchFnName}({`, + ' selection: {', + ' fields: { id: true },', + ' first: 10,', + ' },', + '});', + '```' + ]); + statements.push(f1Decl); + + // Overload 2: without fields + const f2SelProp = t.tsPropertySignature( + t.identifier('selection'), + t.tsTypeAnnotation(withoutFieldsListSelectionType(selectTypeName, filterTypeName, orderByTypeName)) + ); + f2SelProp.optional = true; + statements.push( + exportAsyncDeclareFunction( + fetchFnName, + null, + [createFunctionParam('params', t.tsTypeLiteral([f2SelProp]), true)], + typeRef('Promise', [listResultTypeAST(typeofRef('defaultSelect'))]) + ) + ); - const prefetchFunc = t.functionDeclaration( - t.identifier(`prefetch${ucFirst(pluralName)}Query`), - prefetchParams, - prefetchFuncBody + // Implementation + const fImplSelProp = t.tsPropertySignature( + t.identifier('selection'), + t.tsTypeAnnotation(listSelectionConfigType(typeRef(selectTypeName), filterTypeName, orderByTypeName)) ); - prefetchFunc.async = true; - prefetchFunc.returnType = t.tsTypeAnnotation( - t.tsTypeReference( - t.identifier('Promise'), - t.tsTypeParameterInstantiation([t.tsVoidKeyword()]) + fImplSelProp.optional = true; + const fBody: t.Statement[] = []; + fBody.push(buildListSelectionArgsCall(selectTypeName, filterTypeName, orderByTypeName)); + fBody.push(t.returnStatement(buildFindManyCallExpr(singularName, 'args', selectTypeName))); + statements.push(exportAsyncFunction(fetchFnName, null, [createFunctionParam('params', t.tsTypeLiteral([fImplSelProp]), true)], fBody)); + } + + // Prefetch function + if (reactQueryEnabled) { + const prefetchFnName = `prefetch${ucFirst(pluralName)}Query`; + + // Overload 1: with fields + const p1Params: t.TSPropertySignature[] = [ + t.tsPropertySignature( + t.identifier('selection'), + t.tsTypeAnnotation(withFieldsListSelectionType(sRef(), selectTypeName, filterTypeName, orderByTypeName)) ) + ]; + const p1ParamType = hasRelationships && useCentralizedKeys + ? t.tsIntersectionType([t.tsTypeLiteral(p1Params), scopeTypeLiteral(scopeTypeName)]) + : t.tsTypeLiteral(p1Params); + const p1Decl = exportAsyncDeclareFunction( + prefetchFnName, + createSTypeParam(selectTypeName), + [createFunctionParam('queryClient', typeRef('QueryClient')), createFunctionParam('params', p1ParamType)], + typeRef('Promise', [t.tsVoidKeyword()]) ); - const prefetchExport = t.exportNamedDeclaration(prefetchFunc); - addJSDocComment(prefetchExport, [ + addJSDocComment(p1Decl, [ `Prefetch ${typeName} list for SSR or cache warming`, '', '@example', '```ts', - `await prefetch${ucFirst(pluralName)}Query(queryClient, { first: 10 });`, - '```', + `await ${prefetchFnName}(queryClient, { selection: { first: 10 } });`, + '```' ]); - statements.push(prefetchExport); + statements.push(p1Decl); + + // Overload 2: without fields + const p2SelProp = t.tsPropertySignature( + t.identifier('selection'), + t.tsTypeAnnotation(withoutFieldsListSelectionType(selectTypeName, filterTypeName, orderByTypeName)) + ); + p2SelProp.optional = true; + const p2ParamType = hasRelationships && useCentralizedKeys + ? t.tsIntersectionType([t.tsTypeLiteral([p2SelProp]), scopeTypeLiteral(scopeTypeName)]) + : t.tsTypeLiteral([p2SelProp]); + statements.push( + exportAsyncDeclareFunction( + prefetchFnName, + null, + [createFunctionParam('queryClient', typeRef('QueryClient')), createFunctionParam('params', p2ParamType, true)], + typeRef('Promise', [t.tsVoidKeyword()]) + ) + ); + + // Implementation + const pImplSelProp = t.tsPropertySignature( + t.identifier('selection'), + t.tsTypeAnnotation(listSelectionConfigType(typeRef(selectTypeName), filterTypeName, orderByTypeName)) + ); + pImplSelProp.optional = true; + const pImplParamType = hasRelationships && useCentralizedKeys + ? t.tsIntersectionType([t.tsTypeLiteral([pImplSelProp]), scopeTypeLiteral(scopeTypeName)]) + : t.tsTypeLiteral([pImplSelProp]); + + const pBody: t.Statement[] = []; + pBody.push(buildListSelectionArgsCall(selectTypeName, filterTypeName, orderByTypeName)); + + const queryKeyExpr = hasRelationships && useCentralizedKeys + ? buildListQueryKey(t.identifier('args'), t.optionalMemberExpression(t.identifier('params'), t.identifier('scope'), false, true)) + : buildListQueryKey(t.identifier('args')); + + const prefetchCall = callExpr( + t.memberExpression(t.identifier('queryClient'), t.identifier('prefetchQuery')), + [t.objectExpression([ + objectProp('queryKey', queryKeyExpr), + objectProp('queryFn', buildFindManyFn()) + ])] + ); + pBody.push(t.expressionStatement(t.awaitExpression(prefetchCall))); + + statements.push( + exportAsyncFunction( + prefetchFnName, + null, + [createFunctionParam('queryClient', typeRef('QueryClient')), createFunctionParam('params', pImplParamType, true)], + pBody, + t.tsVoidKeyword() + ) + ); } - const code = generateCode(statements); const headerText = reactQueryEnabled ? `List query hook for ${typeName}` : `List query functions for ${typeName}`; - const content = getGeneratedFileHeader(headerText) + '\n\n' + code; return { fileName: getListQueryFileName(table), - content, + content: generateHookFileCode(headerText, statements) }; } @@ -846,544 +448,402 @@ export function generateSingleQueryHook( table: CleanTable, options: QueryGeneratorOptions = {} ): GeneratedQueryFile | null { - // Skip tables with composite keys - they are handled as custom queries - if (!hasValidPrimaryKey(table)) { - return null; - } + if (!hasValidPrimaryKey(table)) return null; const { reactQueryEnabled = true, useCentralizedKeys = true, - hasRelationships = false, + hasRelationships = false } = options; const { typeName, singularName } = getTableNames(table); const hookName = getSingleQueryHookName(table); const queryName = getSingleRowQueryName(table); const keysName = `${lcFirst(typeName)}Keys`; const scopeTypeName = `${typeName}Scope`; + const selectTypeName = `${typeName}Select`; + const relationTypeName = `${typeName}WithRelations`; const pkFields = getPrimaryKeyInfo(table); const pkField = pkFields[0]; - const pkName = pkField.name; - const pkTsType = pkField.tsType; + const pkFieldName = pkField?.name ?? 'id'; + const pkFieldTsType = pkField?.tsType ?? 'string'; + const defaultFieldName = getDefaultSelectFieldName(table); - const queryAST = buildSingleQueryAST({ table }); - const queryDocument = printGraphQL(queryAST); + const pkTsType: t.TSType = pkFieldTsType === 'string' ? t.tsStringKeyword() : t.tsNumberKeyword(); + const singleResultTypeAST = (sel: t.TSType) => singleQueryResultType(queryName, relationTypeName, sel); const statements: t.Statement[] = []; + // Imports if (reactQueryEnabled) { - const reactQueryImport = t.importDeclaration( - [t.importSpecifier(t.identifier('useQuery'), t.identifier('useQuery'))], - t.stringLiteral('@tanstack/react-query') - ); - statements.push(reactQueryImport); - const reactQueryTypeImport = t.importDeclaration( - [ - t.importSpecifier( - t.identifier('UseQueryOptions'), - t.identifier('UseQueryOptions') - ), - t.importSpecifier( - t.identifier('QueryClient'), - t.identifier('QueryClient') - ), - ], - t.stringLiteral('@tanstack/react-query') - ); - reactQueryTypeImport.importKind = 'type'; - statements.push(reactQueryTypeImport); + statements.push(createImportDeclaration('@tanstack/react-query', ['useQuery'])); + statements.push(createImportDeclaration('@tanstack/react-query', ['UseQueryOptions', 'UseQueryResult', 'QueryClient'], true)); } - - const clientImport = t.importDeclaration( - [t.importSpecifier(t.identifier('execute'), t.identifier('execute'))], - t.stringLiteral('../client') - ); - statements.push(clientImport); - const clientTypeImport = t.importDeclaration( - [ - t.importSpecifier( - t.identifier('ExecuteOptions'), - t.identifier('ExecuteOptions') - ), - ], - t.stringLiteral('../client') - ); - clientTypeImport.importKind = 'type'; - statements.push(clientTypeImport); - - const typesImport = t.importDeclaration( - [t.importSpecifier(t.identifier(typeName), t.identifier(typeName))], - t.stringLiteral('../types') - ); - typesImport.importKind = 'type'; - statements.push(typesImport); + statements.push(createImportDeclaration('../client', ['getClient'])); + statements.push(createImportDeclaration('../selection', ['buildSelectionArgs'])); + statements.push(createImportDeclaration('../selection', ['SelectionConfig'], true)); if (useCentralizedKeys) { - const queryKeyImport = t.importDeclaration( - [t.importSpecifier(t.identifier(keysName), t.identifier(keysName))], - t.stringLiteral('../query-keys') - ); - statements.push(queryKeyImport); + statements.push(createImportDeclaration('../query-keys', [keysName])); if (hasRelationships) { - const scopeTypeImport = t.importDeclaration( - [ - t.importSpecifier( - t.identifier(scopeTypeName), - t.identifier(scopeTypeName) - ), - ], - t.stringLiteral('../query-keys') - ); - scopeTypeImport.importKind = 'type'; - statements.push(scopeTypeImport); + statements.push(createImportDeclaration('../query-keys', [scopeTypeName], true)); } } - const reExportDecl = t.exportNamedDeclaration( - null, - [t.exportSpecifier(t.identifier(typeName), t.identifier(typeName))], - t.stringLiteral('../types') - ); - reExportDecl.exportKind = 'type'; - statements.push(reExportDecl); - - const queryDocConst = t.variableDeclaration('const', [ - t.variableDeclarator( - t.identifier(`${queryName}QueryDocument`), - t.templateLiteral( - [ - t.templateElement( - { raw: '\n' + queryDocument, cooked: '\n' + queryDocument }, - true - ), - ], - [] - ) - ), - ]); - statements.push(t.exportNamedDeclaration(queryDocConst)); - - const pkTypeAnnotation = - pkTsType === 'string' - ? t.tsStringKeyword() - : pkTsType === 'number' - ? t.tsNumberKeyword() - : t.tsTypeReference(t.identifier(pkTsType)); - - const variablesInterfaceBody = t.tsInterfaceBody([ - t.tsPropertySignature( - t.identifier(pkName), - t.tsTypeAnnotation(pkTypeAnnotation) - ), - ]); - const variablesInterface = t.tsInterfaceDeclaration( - t.identifier(`${ucFirst(singularName)}QueryVariables`), - null, - null, - variablesInterfaceBody - ); - statements.push(t.exportNamedDeclaration(variablesInterface)); - - const resultInterfaceBody = t.tsInterfaceBody([ - t.tsPropertySignature( - t.identifier(queryName), - t.tsTypeAnnotation( - t.tsUnionType([ - t.tsTypeReference(t.identifier(typeName)), - t.tsNullKeyword(), - ]) - ) - ), - ]); - const resultInterface = t.tsInterfaceDeclaration( - t.identifier(`${ucFirst(singularName)}QueryResult`), - null, - null, - resultInterfaceBody - ); - statements.push(t.exportNamedDeclaration(resultInterface)); + statements.push(createImportDeclaration('../../orm/input-types', [selectTypeName, relationTypeName], true)); + statements.push(createImportDeclaration('../../orm/select-types', ['InferSelectResult', 'StrictSelect'], true)); + // Re-exports + statements.push(createTypeReExport([selectTypeName, relationTypeName], '../../orm/input-types')); + + // Default select + statements.push(constDecl('defaultSelect', asConst(t.objectExpression([objectProp(defaultFieldName, t.booleanLiteral(true))])))); + + // Query key if (useCentralizedKeys) { - const queryKeyConst = t.variableDeclaration('const', [ - t.variableDeclarator( - t.identifier(`${queryName}QueryKey`), - t.memberExpression(t.identifier(keysName), t.identifier('detail')) - ), - ]); - const queryKeyExport = t.exportNamedDeclaration(queryKeyConst); - addJSDocComment(queryKeyExport, [ - 'Query key factory - re-exported from query-keys.ts', - ]); - statements.push(queryKeyExport); + const keyDecl = t.exportNamedDeclaration( + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier(`${queryName}QueryKey`), + t.memberExpression(t.identifier(keysName), t.identifier('detail')) + ) + ]) + ); + addJSDocComment(keyDecl, ['Query key factory - re-exported from query-keys.ts']); + statements.push(keyDecl); } else { - const queryKeyArrow = t.arrowFunctionExpression( - [typedParam(pkName, pkTypeAnnotation)], - t.tsAsExpression( - t.arrayExpression([ - t.stringLiteral(typeName.toLowerCase()), - t.stringLiteral('detail'), - t.identifier(pkName), - ]), - t.tsTypeReference(t.identifier('const')) - ) + const keyFn = t.arrowFunctionExpression( + [createFunctionParam('id', pkTsType)], + asConst(t.arrayExpression([t.stringLiteral(typeName.toLowerCase()), t.stringLiteral('detail'), t.identifier('id')])) ); - const queryKeyConst = t.variableDeclaration('const', [ - t.variableDeclarator( - t.identifier(`${queryName}QueryKey`), - queryKeyArrow - ), - ]); - statements.push(t.exportNamedDeclaration(queryKeyConst)); + statements.push(t.exportNamedDeclaration( + t.variableDeclaration('const', [t.variableDeclarator(t.identifier(`${queryName}QueryKey`), keyFn)]) + )); } - if (reactQueryEnabled) { - const hookBodyStatements: t.Statement[] = []; - if (hasRelationships && useCentralizedKeys) { - hookBodyStatements.push( - t.variableDeclaration('const', [ - t.variableDeclarator( - t.objectPattern([ - t.objectProperty( - t.identifier('scope'), - t.identifier('scope'), - false, - true - ), - t.restElement(t.identifier('queryOptions')), - ]), - t.logicalExpression( - '??', - t.identifier('options'), - t.objectExpression([]) - ) - ), - ]) - ); - hookBodyStatements.push( - t.returnStatement( - t.callExpression(t.identifier('useQuery'), [ - t.objectExpression([ - t.objectProperty( - t.identifier('queryKey'), - t.callExpression( - t.memberExpression( - t.identifier(keysName), - t.identifier('detail') - ), - [ - t.memberExpression( - t.identifier('variables'), - t.identifier(pkName) - ), - t.identifier('scope'), - ] - ) - ), - t.objectProperty( - t.identifier('queryFn'), - t.arrowFunctionExpression( - [], - createTypedCallExpression( - t.identifier('execute'), - [t.identifier(`${queryName}QueryDocument`), t.identifier('variables')], - [ - t.tsTypeReference(t.identifier(`${ucFirst(singularName)}QueryResult`)), - t.tsTypeReference(t.identifier(`${ucFirst(singularName)}QueryVariables`)), - ] - ) - ) - ), - t.spreadElement(t.identifier('queryOptions')), - ]), - ]) - ) - ); - } else if (useCentralizedKeys) { - hookBodyStatements.push( - t.returnStatement( - t.callExpression(t.identifier('useQuery'), [ - t.objectExpression([ - t.objectProperty( - t.identifier('queryKey'), - t.callExpression( - t.memberExpression( - t.identifier(keysName), - t.identifier('detail') - ), - [ - t.memberExpression( - t.identifier('variables'), - t.identifier(pkName) - ), - ] - ) - ), - t.objectProperty( - t.identifier('queryFn'), - t.arrowFunctionExpression( - [], - createTypedCallExpression( - t.identifier('execute'), - [t.identifier(`${queryName}QueryDocument`), t.identifier('variables')], - [ - t.tsTypeReference(t.identifier(`${ucFirst(singularName)}QueryResult`)), - t.tsTypeReference(t.identifier(`${ucFirst(singularName)}QueryVariables`)), - ] - ) - ) - ), - t.spreadElement(t.identifier('options')), - ]), - ]) - ) - ); - } else { - hookBodyStatements.push( - t.returnStatement( - t.callExpression(t.identifier('useQuery'), [ - t.objectExpression([ - t.objectProperty( - t.identifier('queryKey'), - t.callExpression(t.identifier(`${queryName}QueryKey`), [ - t.memberExpression( - t.identifier('variables'), - t.identifier(pkName) - ), - ]) - ), - t.objectProperty( - t.identifier('queryFn'), - t.arrowFunctionExpression( - [], - createTypedCallExpression( - t.identifier('execute'), - [t.identifier(`${queryName}QueryDocument`), t.identifier('variables')], - [ - t.tsTypeReference(t.identifier(`${ucFirst(singularName)}QueryResult`)), - t.tsTypeReference(t.identifier(`${ucFirst(singularName)}QueryVariables`)), - ] - ) - ) - ), - t.spreadElement(t.identifier('options')), - ]), - ]) - ) - ); + // Helper for query key call + const buildDetailQueryKey = (pkExpr: t.Expression, scopeExpr?: t.Expression) => { + if (useCentralizedKeys) { + const args = [pkExpr]; + if (scopeExpr) args.push(scopeExpr); + return callExpr(t.memberExpression(t.identifier(keysName), t.identifier('detail')), args); } + return callExpr(t.identifier(`${queryName}QueryKey`), [pkExpr]); + }; - const hookParams: t.Identifier[] = [ - typedParam( - 'variables', - t.tsTypeReference(t.identifier(`${ucFirst(singularName)}QueryVariables`)) - ), - ]; - let optionsTypeStr: string; + // Helper for findOne queryFn + const buildFindOneFn = () => t.arrowFunctionExpression( + [], + buildFindOneCallExpr(singularName, pkFieldName, 'args', selectTypeName) + ); + + // Options type builder with optional scope + const buildSingleOptionsType = (queryDataType: t.TSType, dataType: t.TSType) => { + const base = omitType( + typeRef('UseQueryOptions', [queryDataType, typeRef('Error'), dataType]), + ['queryKey', 'queryFn'] + ); if (hasRelationships && useCentralizedKeys) { - optionsTypeStr = `Omit, 'queryKey' | 'queryFn'> & { scope?: ${scopeTypeName} }`; - } else { - optionsTypeStr = `Omit, 'queryKey' | 'queryFn'>`; + return t.tsIntersectionType([base, scopeTypeLiteral(scopeTypeName)]); } - const optionsParam = t.identifier('options'); - optionsParam.optional = true; - optionsParam.typeAnnotation = t.tsTypeAnnotation( - t.tsTypeReference(t.identifier(optionsTypeStr)) - ); - hookParams.push(optionsParam); + return base; + }; - const hookFunc = t.functionDeclaration( - t.identifier(hookName), - hookParams, - t.blockStatement(hookBodyStatements) - ); - const hookExport = t.exportNamedDeclaration(hookFunc); + // Hook + if (reactQueryEnabled) { const docLines = [ `Query hook for fetching a single ${typeName}`, '', '@example', '```tsx', - `const { data, isLoading } = ${hookName}({ ${pkName}: 'some-id' });`, - '```', + `const { data, isLoading } = ${hookName}({`, + ` ${pkFieldName}: 'some-id',`, + ' selection: { fields: { id: true, name: true } },', + '});', + '```' ]; if (hasRelationships && useCentralizedKeys) { docLines.push(''); docLines.push('@example With scope for hierarchical cache invalidation'); docLines.push('```tsx'); - docLines.push(`const { data } = ${hookName}(`); - docLines.push(` { ${pkName}: 'some-id' },`); - docLines.push(" { scope: { parentId: 'parent-id' } }"); - docLines.push(');'); + docLines.push(`const { data } = ${hookName}({`); + docLines.push(` ${pkFieldName}: 'some-id',`); + docLines.push(" scope: { parentId: 'parent-id' },"); + docLines.push('});'); docLines.push('```'); } - addJSDocComment(hookExport, docLines); - statements.push(hookExport); - } - const fetchFuncBody = t.blockStatement([ - t.returnStatement( - createTypedCallExpression( - t.identifier('execute'), - [t.identifier(`${queryName}QueryDocument`), t.identifier('variables'), t.identifier('options')], - [ - t.tsTypeReference(t.identifier(`${ucFirst(singularName)}QueryResult`)), - t.tsTypeReference(t.identifier(`${ucFirst(singularName)}QueryVariables`)), - ] + // Overload 1: with fields + const o1Props = [ + t.tsPropertySignature(t.identifier(pkFieldName), t.tsTypeAnnotation(pkTsType)), + t.tsPropertySignature( + t.identifier('selection'), + t.tsTypeAnnotation(withFieldsSelectionType(sRef(), selectTypeName)) ) - ), - ]); - const fetchFunc = t.functionDeclaration( - t.identifier(`fetch${ucFirst(singularName)}Query`), - [ - typedParam( - 'variables', - t.tsTypeReference(t.identifier(`${ucFirst(singularName)}QueryVariables`)) - ), - typedParam( - 'options', - t.tsTypeReference(t.identifier('ExecuteOptions')), - true - ), - ], - fetchFuncBody - ); - fetchFunc.async = true; - fetchFunc.returnType = t.tsTypeAnnotation( - t.tsTypeReference( - t.identifier('Promise'), - t.tsTypeParameterInstantiation([ - t.tsTypeReference(t.identifier(`${ucFirst(singularName)}QueryResult`)), - ]) - ) - ); - const fetchExport = t.exportNamedDeclaration(fetchFunc); - addJSDocComment(fetchExport, [ - `Fetch a single ${typeName} without React hooks`, - '', - '@example', - '```ts', - `const data = await fetch${ucFirst(singularName)}Query({ ${pkName}: 'some-id' });`, - '```', - ]); - statements.push(fetchExport); + ]; + const o1ParamType = t.tsIntersectionType([ + t.tsTypeLiteral(o1Props), + buildSingleOptionsType(singleResultTypeAST(sRef()), typeRef('TData')) + ]); + const o1 = exportDeclareFunction( + hookName, + createSAndTDataTypeParams(selectTypeName, singleResultTypeAST(sRef())), + [createFunctionParam('params', o1ParamType)], + typeRef('UseQueryResult', [typeRef('TData')]) + ); + addJSDocComment(o1, docLines); + statements.push(o1); - if (reactQueryEnabled) { - const prefetchParams: t.Identifier[] = [ - typedParam( - 'queryClient', - t.tsTypeReference(t.identifier('QueryClient')) - ), - typedParam( - 'variables', - t.tsTypeReference(t.identifier(`${ucFirst(singularName)}QueryVariables`)) - ), + // Overload 2: without fields + const o2SelProp = t.tsPropertySignature( + t.identifier('selection'), + t.tsTypeAnnotation(withoutFieldsSelectionType()) + ); + o2SelProp.optional = true; + const o2Props = [ + t.tsPropertySignature(t.identifier(pkFieldName), t.tsTypeAnnotation(pkTsType)), + o2SelProp ]; - if (hasRelationships && useCentralizedKeys) { - prefetchParams.push( - typedParam( - 'scope', - t.tsTypeReference(t.identifier(scopeTypeName)), - true - ) - ); - } - prefetchParams.push( - typedParam( - 'options', - t.tsTypeReference(t.identifier('ExecuteOptions')), - true + const o2ParamType = t.tsIntersectionType([ + t.tsTypeLiteral(o2Props), + buildSingleOptionsType(singleResultTypeAST(typeofRef('defaultSelect')), typeRef('TData')) + ]); + statements.push( + exportDeclareFunction( + hookName, + createTDataTypeParam(singleResultTypeAST(typeofRef('defaultSelect'))), + [createFunctionParam('params', o2ParamType)], + typeRef('UseQueryResult', [typeRef('TData')]) ) ); - let prefetchQueryKeyExpr: t.Expression; + // Implementation + const implSelProp = t.tsPropertySignature( + t.identifier('selection'), + t.tsTypeAnnotation(selectionConfigType(typeRef(selectTypeName))) + ); + implSelProp.optional = true; + const implProps = [ + t.tsPropertySignature(t.identifier(pkFieldName), t.tsTypeAnnotation(pkTsType)), + implSelProp + ]; + const implOptionsType = (() => { + const base = useQueryOptionsImplType(); + if (hasRelationships && useCentralizedKeys) { + return t.tsIntersectionType([base, scopeTypeLiteral(scopeTypeName)]); + } + return base; + })(); + const implParamType = t.tsIntersectionType([ + t.tsTypeLiteral(implProps), + implOptionsType + ]); + + const body: t.Statement[] = []; + // const args = buildSelectionArgs(params.selection); + const argsCall = t.callExpression(t.identifier('buildSelectionArgs'), [ + t.memberExpression(t.identifier('params'), t.identifier('selection')) + ]); + // @ts-ignore + argsCall.typeParameters = t.tsTypeParameterInstantiation([typeRef(selectTypeName)]); + body.push(constDecl('args', argsCall)); + + const pkMemberExpr = t.memberExpression(t.identifier('params'), t.identifier(pkFieldName)); + if (hasRelationships && useCentralizedKeys) { - prefetchQueryKeyExpr = t.callExpression( - t.memberExpression(t.identifier(keysName), t.identifier('detail')), - [ - t.memberExpression(t.identifier('variables'), t.identifier(pkName)), - t.identifier('scope'), - ] - ); - } else if (useCentralizedKeys) { - prefetchQueryKeyExpr = t.callExpression( - t.memberExpression(t.identifier(keysName), t.identifier('detail')), - [t.memberExpression(t.identifier('variables'), t.identifier(pkName))] - ); + body.push(destructureParamsWithSelectionAndScope('queryOptions')); + body.push(voidStatement('_selection')); + body.push(returnUseQuery( + buildDetailQueryKey(pkMemberExpr, t.identifier('scope')), + buildFindOneFn(), + [spreadObj(t.identifier('queryOptions'))] + )); } else { - prefetchQueryKeyExpr = t.callExpression( - t.identifier(`${queryName}QueryKey`), - [t.memberExpression(t.identifier('variables'), t.identifier(pkName))] - ); + body.push(destructureParamsWithSelection('queryOptions')); + body.push(voidStatement('_selection')); + body.push(returnUseQuery( + buildDetailQueryKey(pkMemberExpr), + buildFindOneFn(), + [spreadObj(t.identifier('queryOptions'))] + )); } - const prefetchFuncBody = t.blockStatement([ - t.expressionStatement( - t.awaitExpression( - t.callExpression( - t.memberExpression( - t.identifier('queryClient'), - t.identifier('prefetchQuery') - ), - [ - t.objectExpression([ - t.objectProperty( - t.identifier('queryKey'), - prefetchQueryKeyExpr - ), - t.objectProperty( - t.identifier('queryFn'), - t.arrowFunctionExpression( - [], - createTypedCallExpression( - t.identifier('execute'), - [t.identifier(`${queryName}QueryDocument`), t.identifier('variables'), t.identifier('options')], - [ - t.tsTypeReference(t.identifier(`${ucFirst(singularName)}QueryResult`)), - t.tsTypeReference(t.identifier(`${ucFirst(singularName)}QueryVariables`)), - ] - ) - ) - ), - ]), - ] - ) - ) - ), + statements.push(exportFunction(hookName, null, [createFunctionParam('params', implParamType)], body)); + } + + // Fetch function + const fetchFnName = `fetch${ucFirst(singularName)}Query`; + { + // Overload 1: with fields + const f1Props = [ + t.tsPropertySignature(t.identifier(pkFieldName), t.tsTypeAnnotation(pkTsType)), + t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(withFieldsSelectionType(sRef(), selectTypeName))) + ]; + const f1Decl = exportAsyncDeclareFunction( + fetchFnName, + createSTypeParam(selectTypeName), + [createFunctionParam('params', t.tsTypeLiteral(f1Props))], + typeRef('Promise', [singleResultTypeAST(sRef())]) + ); + addJSDocComment(f1Decl, [ + `Fetch a single ${typeName} without React hooks`, + '', + '@example', + '```ts', + `const data = await ${fetchFnName}({`, + ` ${pkFieldName}: 'some-id',`, + ' selection: { fields: { id: true } },', + '});', + '```' ]); + statements.push(f1Decl); - const prefetchFunc = t.functionDeclaration( - t.identifier(`prefetch${ucFirst(singularName)}Query`), - prefetchParams, - prefetchFuncBody + // Overload 2: without fields + const f2SelProp = t.tsPropertySignature( + t.identifier('selection'), + t.tsTypeAnnotation(withoutFieldsSelectionType()) ); - prefetchFunc.async = true; - prefetchFunc.returnType = t.tsTypeAnnotation( - t.tsTypeReference( - t.identifier('Promise'), - t.tsTypeParameterInstantiation([t.tsVoidKeyword()]) + f2SelProp.optional = true; + const f2Props = [ + t.tsPropertySignature(t.identifier(pkFieldName), t.tsTypeAnnotation(pkTsType)), + f2SelProp + ]; + statements.push( + exportAsyncDeclareFunction( + fetchFnName, + null, + [createFunctionParam('params', t.tsTypeLiteral(f2Props))], + typeRef('Promise', [singleResultTypeAST(typeofRef('defaultSelect'))]) ) ); - const prefetchExport = t.exportNamedDeclaration(prefetchFunc); - addJSDocComment(prefetchExport, [ + + // Implementation + const fImplSelProp = t.tsPropertySignature( + t.identifier('selection'), + t.tsTypeAnnotation(selectionConfigType(typeRef(selectTypeName))) + ); + fImplSelProp.optional = true; + const fImplProps = [ + t.tsPropertySignature(t.identifier(pkFieldName), t.tsTypeAnnotation(pkTsType)), + fImplSelProp + ]; + const fBody: t.Statement[] = []; + const fArgsCall = t.callExpression(t.identifier('buildSelectionArgs'), [ + t.memberExpression(t.identifier('params'), t.identifier('selection')) + ]); + // @ts-ignore + fArgsCall.typeParameters = t.tsTypeParameterInstantiation([typeRef(selectTypeName)]); + fBody.push(constDecl('args', fArgsCall)); + fBody.push(t.returnStatement(buildFindOneCallExpr(singularName, pkFieldName, 'args', selectTypeName))); + statements.push(exportAsyncFunction(fetchFnName, null, [createFunctionParam('params', t.tsTypeLiteral(fImplProps))], fBody)); + } + + // Prefetch function + if (reactQueryEnabled) { + const prefetchFnName = `prefetch${ucFirst(singularName)}Query`; + + // Overload 1: with fields + const p1Props: t.TSPropertySignature[] = [ + t.tsPropertySignature(t.identifier(pkFieldName), t.tsTypeAnnotation(pkTsType)), + t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(withFieldsSelectionType(sRef(), selectTypeName))) + ]; + const p1ParamType = hasRelationships && useCentralizedKeys + ? t.tsIntersectionType([t.tsTypeLiteral(p1Props), scopeTypeLiteral(scopeTypeName)]) + : t.tsTypeLiteral(p1Props); + const p1Decl = exportAsyncDeclareFunction( + prefetchFnName, + createSTypeParam(selectTypeName), + [createFunctionParam('queryClient', typeRef('QueryClient')), createFunctionParam('params', p1ParamType)], + typeRef('Promise', [t.tsVoidKeyword()]) + ); + addJSDocComment(p1Decl, [ `Prefetch a single ${typeName} for SSR or cache warming`, '', '@example', '```ts', - `await prefetch${ucFirst(singularName)}Query(queryClient, { ${pkName}: 'some-id' });`, - '```', + `await ${prefetchFnName}(queryClient, { ${pkFieldName}: 'some-id' });`, + '```' ]); - statements.push(prefetchExport); + statements.push(p1Decl); + + // Overload 2: without fields + const p2SelProp = t.tsPropertySignature( + t.identifier('selection'), + t.tsTypeAnnotation(withoutFieldsSelectionType()) + ); + p2SelProp.optional = true; + const p2Props: t.TSPropertySignature[] = [ + t.tsPropertySignature(t.identifier(pkFieldName), t.tsTypeAnnotation(pkTsType)), + p2SelProp + ]; + const p2ParamType = hasRelationships && useCentralizedKeys + ? t.tsIntersectionType([t.tsTypeLiteral(p2Props), scopeTypeLiteral(scopeTypeName)]) + : t.tsTypeLiteral(p2Props); + statements.push( + exportAsyncDeclareFunction( + prefetchFnName, + null, + [createFunctionParam('queryClient', typeRef('QueryClient')), createFunctionParam('params', p2ParamType)], + typeRef('Promise', [t.tsVoidKeyword()]) + ) + ); + + // Implementation + const pImplSelProp = t.tsPropertySignature( + t.identifier('selection'), + t.tsTypeAnnotation(selectionConfigType(typeRef(selectTypeName))) + ); + pImplSelProp.optional = true; + const pImplProps: t.TSPropertySignature[] = [ + t.tsPropertySignature(t.identifier(pkFieldName), t.tsTypeAnnotation(pkTsType)), + pImplSelProp + ]; + const pImplParamType = hasRelationships && useCentralizedKeys + ? t.tsIntersectionType([t.tsTypeLiteral(pImplProps), scopeTypeLiteral(scopeTypeName)]) + : t.tsTypeLiteral(pImplProps); + + const pBody: t.Statement[] = []; + const pArgsCall = t.callExpression(t.identifier('buildSelectionArgs'), [ + t.memberExpression(t.identifier('params'), t.identifier('selection')) + ]); + // @ts-ignore + pArgsCall.typeParameters = t.tsTypeParameterInstantiation([typeRef(selectTypeName)]); + pBody.push(constDecl('args', pArgsCall)); + + const queryKeyExpr = hasRelationships && useCentralizedKeys + ? buildDetailQueryKey( + t.memberExpression(t.identifier('params'), t.identifier(pkFieldName)), + t.optionalMemberExpression(t.identifier('params'), t.identifier('scope'), false, true) + ) + : buildDetailQueryKey(t.memberExpression(t.identifier('params'), t.identifier(pkFieldName))); + + const prefetchCall = callExpr( + t.memberExpression(t.identifier('queryClient'), t.identifier('prefetchQuery')), + [t.objectExpression([ + objectProp('queryKey', queryKeyExpr), + objectProp('queryFn', buildFindOneFn()) + ])] + ); + pBody.push(t.expressionStatement(t.awaitExpression(prefetchCall))); + + statements.push( + exportAsyncFunction( + prefetchFnName, + null, + [createFunctionParam('queryClient', typeRef('QueryClient')), createFunctionParam('params', pImplParamType)], + pBody, + t.tsVoidKeyword() + ) + ); } - const code = generateCode(statements); const headerText = reactQueryEnabled ? `Single item query hook for ${typeName}` : `Single item query functions for ${typeName}`; - const content = getGeneratedFileHeader(headerText) + '\n\n' + code; return { fileName: getSingleQueryFileName(table), - content, + content: generateHookFileCode(headerText, statements) }; } diff --git a/graphql/codegen/src/core/codegen/query-keys.ts b/graphql/codegen/src/core/codegen/query-keys.ts index 791d4eec6..b9c09c468 100644 --- a/graphql/codegen/src/core/codegen/query-keys.ts +++ b/graphql/codegen/src/core/codegen/query-keys.ts @@ -10,17 +10,17 @@ */ import * as t from '@babel/types'; -import type { CleanTable, CleanOperation } from '../../types/schema'; -import type { QueryKeyConfig, EntityRelationship } from '../../types/config'; -import { getTableNames, getGeneratedFileHeader, ucFirst, lcFirst } from './utils'; +import type { EntityRelationship,QueryKeyConfig } from '../../types/config'; +import type { CleanOperation,CleanTable } from '../../types/schema'; import { - generateCode, addJSDocComment, asConst, constArray, - typedParam, + generateCode, keyofTypeof, + typedParam } from './babel-ast'; +import { getGeneratedFileHeader, getTableNames, lcFirst,ucFirst } from './utils'; export interface QueryKeyGeneratorOptions { tables: CleanTable[]; @@ -558,7 +558,7 @@ function generateUnifiedStoreDeclaration( '', '// Invalidate specific user', 'queryClient.invalidateQueries({ queryKey: queryKeys.user.detail(userId) });', - '```', + '```' ]); return decl; @@ -714,6 +714,6 @@ ${description} return { fileName: 'query-keys.ts', - content, + content }; } diff --git a/graphql/codegen/src/core/codegen/scalars.ts b/graphql/codegen/src/core/codegen/scalars.ts index f659cb095..f13047967 100644 --- a/graphql/codegen/src/core/codegen/scalars.ts +++ b/graphql/codegen/src/core/codegen/scalars.ts @@ -40,7 +40,7 @@ export const SCALAR_TS_MAP: Record = { TsQuery: 'string', // File upload - Upload: 'File', + Upload: 'File' }; export const SCALAR_FILTER_MAP: Record = { @@ -59,7 +59,7 @@ export const SCALAR_FILTER_MAP: Record = { BitString: 'BitStringFilter', InternetAddress: 'InternetAddressFilter', FullText: 'FullTextFilter', - Interval: 'StringFilter', + Interval: 'StringFilter' }; export const SCALAR_NAMES = new Set(Object.keys(SCALAR_TS_MAP)); @@ -70,7 +70,7 @@ const LIST_FILTER_SCALARS = new Set(['String', 'Int', 'UUID']); /** All base filter type names - skip these in schema-types.ts to avoid duplicates */ export const BASE_FILTER_TYPE_NAMES = new Set([ ...new Set(Object.values(SCALAR_FILTER_MAP)), - ...Array.from(LIST_FILTER_SCALARS).map((s) => `${s}ListFilter`), + ...Array.from(LIST_FILTER_SCALARS).map((s) => `${s}ListFilter`) ]); export function scalarToTsType( diff --git a/graphql/codegen/src/core/codegen/schema-gql-ast.ts b/graphql/codegen/src/core/codegen/schema-gql-ast.ts deleted file mode 100644 index 1d51f33de..000000000 --- a/graphql/codegen/src/core/codegen/schema-gql-ast.ts +++ /dev/null @@ -1,518 +0,0 @@ -/** - * Dynamic GraphQL AST builders for custom operations - * - * Generates GraphQL query/mutation documents from CleanOperation data - * using gql-ast library for proper AST construction. - */ -import * as t from 'gql-ast'; -import { print } from 'graphql'; -import type { - DocumentNode, - FieldNode, - ArgumentNode, - VariableDefinitionNode, - TypeNode, -} from 'graphql'; -import type { - CleanOperation, - CleanArgument, - CleanTypeRef, - CleanObjectField, - TypeRegistry, -} from '../../types/schema'; -import { getBaseTypeKind, shouldSkipField } from './type-resolver'; - -// ============================================================================ -// Configuration -// ============================================================================ - -export interface FieldSelectionConfig { - /** Max depth for nested object selections */ - maxDepth: number; - /** Skip the 'query' field in payloads */ - skipQueryField: boolean; - /** Type registry for resolving nested types */ - typeRegistry?: TypeRegistry; -} - -// ============================================================================ -// Type Node Builders (GraphQL Type AST) -// ============================================================================ - -/** - * Build a GraphQL type node from CleanTypeRef - * Handles NON_NULL, LIST, and named types - */ -function buildTypeNode(typeRef: CleanTypeRef): TypeNode { - switch (typeRef.kind) { - case 'NON_NULL': - if (typeRef.ofType) { - const innerType = buildTypeNode(typeRef.ofType); - // Can't wrap NON_NULL in NON_NULL - if (innerType.kind === 'NonNullType') { - return innerType; - } - return t.nonNullType({ type: innerType as any }); - } - return t.namedType({ type: 'String' }); - - case 'LIST': - if (typeRef.ofType) { - return t.listType({ type: buildTypeNode(typeRef.ofType) }); - } - return t.listType({ type: t.namedType({ type: 'String' }) }); - - case 'SCALAR': - case 'ENUM': - case 'OBJECT': - case 'INPUT_OBJECT': - return t.namedType({ type: typeRef.name ?? 'String' }); - - default: - return t.namedType({ type: typeRef.name ?? 'String' }); - } -} - -// ============================================================================ -// Variable Definition Builders -// ============================================================================ - -/** - * Build variable definitions from operation arguments - */ -export function buildVariableDefinitions( - args: CleanArgument[] -): VariableDefinitionNode[] { - return args.map((arg) => - t.variableDefinition({ - variable: t.variable({ name: arg.name }), - type: buildTypeNode(arg.type), - }) - ); -} - -/** - * Build argument nodes that reference variables - */ -function buildArgumentNodes(args: CleanArgument[]): ArgumentNode[] { - return args.map((arg) => - t.argument({ - name: arg.name, - value: t.variable({ name: arg.name }), - }) - ); -} - -// ============================================================================ -// Field Selection Builders -// ============================================================================ - -/** - * Check if a type should have selections (is an object type) - */ -function typeNeedsSelections(typeRef: CleanTypeRef): boolean { - const baseKind = getBaseTypeKind(typeRef); - return baseKind === 'OBJECT'; -} - -/** - * Get the resolved fields for a type reference - * Uses type registry for deep resolution - */ -function getResolvedFields( - typeRef: CleanTypeRef, - typeRegistry?: TypeRegistry -): CleanObjectField[] | undefined { - // First check if fields are directly on the typeRef - if (typeRef.fields) { - return typeRef.fields; - } - - // For wrapper types, unwrap and check - if (typeRef.ofType) { - return getResolvedFields(typeRef.ofType, typeRegistry); - } - - // Look up in type registry - if (typeRegistry && typeRef.name) { - const resolved = typeRegistry.get(typeRef.name); - if (resolved?.fields) { - return resolved.fields; - } - } - - return undefined; -} - -/** - * Build field selections for an object type - * Recursively handles nested objects up to maxDepth - */ -export function buildFieldSelections( - typeRef: CleanTypeRef, - config: FieldSelectionConfig, - currentDepth: number = 0 -): FieldNode[] { - const { maxDepth, skipQueryField, typeRegistry } = config; - - // Stop recursion at max depth - if (currentDepth >= maxDepth) { - return []; - } - - const fields = getResolvedFields(typeRef, typeRegistry); - if (!fields || fields.length === 0) { - return []; - } - - const selections: FieldNode[] = []; - - for (const field of fields) { - // Skip internal fields - if (shouldSkipField(field.name, skipQueryField)) { - continue; - } - - const fieldKind = getBaseTypeKind(field.type); - - // For scalar and enum types, just add the field - if (fieldKind === 'SCALAR' || fieldKind === 'ENUM') { - selections.push(t.field({ name: field.name })); - continue; - } - - // For object types, recurse if within depth limit - if (fieldKind === 'OBJECT' && currentDepth < maxDepth - 1) { - const nestedSelections = buildFieldSelections( - field.type, - config, - currentDepth + 1 - ); - - if (nestedSelections.length > 0) { - selections.push( - t.field({ - name: field.name, - selectionSet: t.selectionSet({ selections: nestedSelections }), - }) - ); - } - } - } - - return selections; -} - -/** - * Build selections for a return type, handling connections and payloads - */ -function buildReturnTypeSelections( - returnType: CleanTypeRef, - config: FieldSelectionConfig -): FieldNode[] { - const fields = getResolvedFields(returnType, config.typeRegistry); - - if (!fields || fields.length === 0) { - return []; - } - - // Check if this is a connection type - const hasNodes = fields.some((f) => f.name === 'nodes'); - const hasTotalCount = fields.some((f) => f.name === 'totalCount'); - - if (hasNodes && hasTotalCount) { - return buildConnectionSelections(fields, config); - } - - // Check if this is a mutation payload (has clientMutationId) - const hasClientMutationId = fields.some( - (f) => f.name === 'clientMutationId' - ); - - if (hasClientMutationId) { - return buildPayloadSelections(fields, config); - } - - // Regular object - build normal selections - return buildFieldSelections(returnType, config); -} - -/** - * Build selections for a connection type - */ -function buildConnectionSelections( - fields: CleanObjectField[], - config: FieldSelectionConfig -): FieldNode[] { - const selections: FieldNode[] = []; - - // Add totalCount - const totalCountField = fields.find((f) => f.name === 'totalCount'); - if (totalCountField) { - selections.push(t.field({ name: 'totalCount' })); - } - - // Add nodes with nested selections - const nodesField = fields.find((f) => f.name === 'nodes'); - if (nodesField) { - const nodeSelections = buildFieldSelections(nodesField.type, config); - if (nodeSelections.length > 0) { - selections.push( - t.field({ - name: 'nodes', - selectionSet: t.selectionSet({ selections: nodeSelections }), - }) - ); - } - } - - // Add pageInfo - const pageInfoField = fields.find((f) => f.name === 'pageInfo'); - if (pageInfoField) { - selections.push( - t.field({ - name: 'pageInfo', - selectionSet: t.selectionSet({ - selections: [ - t.field({ name: 'hasNextPage' }), - t.field({ name: 'hasPreviousPage' }), - t.field({ name: 'startCursor' }), - t.field({ name: 'endCursor' }), - ], - }), - }) - ); - } - - return selections; -} - -/** - * Build selections for a mutation payload type - */ -function buildPayloadSelections( - fields: CleanObjectField[], - config: FieldSelectionConfig -): FieldNode[] { - const selections: FieldNode[] = []; - - for (const field of fields) { - // Skip query field - if (shouldSkipField(field.name, config.skipQueryField)) { - continue; - } - - const fieldKind = getBaseTypeKind(field.type); - - // Add scalar fields directly - if (fieldKind === 'SCALAR' || fieldKind === 'ENUM') { - selections.push(t.field({ name: field.name })); - continue; - } - - // For object fields (like the returned entity), add with selections - if (fieldKind === 'OBJECT') { - const nestedSelections = buildFieldSelections(field.type, config); - if (nestedSelections.length > 0) { - selections.push( - t.field({ - name: field.name, - selectionSet: t.selectionSet({ selections: nestedSelections }), - }) - ); - } - } - } - - return selections; -} - -// ============================================================================ -// Custom Query Builder -// ============================================================================ - -export interface CustomQueryConfig { - operation: CleanOperation; - typeRegistry?: TypeRegistry; - maxDepth?: number; - skipQueryField?: boolean; -} - -/** - * Build a custom query AST from a CleanOperation - */ -export function buildCustomQueryAST(config: CustomQueryConfig): DocumentNode { - const { - operation, - typeRegistry, - maxDepth = 2, - skipQueryField = true, - } = config; - - const operationName = `${ucFirst(operation.name)}Query`; - - // Build variable definitions - const variableDefinitions = buildVariableDefinitions(operation.args); - - // Build arguments that reference the variables - const args = buildArgumentNodes(operation.args); - - // Build return type selections - const fieldSelectionConfig: FieldSelectionConfig = { - maxDepth, - skipQueryField, - typeRegistry, - }; - - const returnTypeNeedsSelections = typeNeedsSelections(operation.returnType); - let selections: FieldNode[] = []; - - if (returnTypeNeedsSelections) { - selections = buildReturnTypeSelections( - operation.returnType, - fieldSelectionConfig - ); - } - - // Build the query field - const queryField: FieldNode = - selections.length > 0 - ? t.field({ - name: operation.name, - args: args.length > 0 ? args : undefined, - selectionSet: t.selectionSet({ selections }), - }) - : t.field({ - name: operation.name, - args: args.length > 0 ? args : undefined, - }); - - return t.document({ - definitions: [ - t.operationDefinition({ - operation: 'query', - name: operationName, - variableDefinitions: - variableDefinitions.length > 0 ? variableDefinitions : undefined, - selectionSet: t.selectionSet({ - selections: [queryField], - }), - }), - ], - }); -} - -// ============================================================================ -// Custom Mutation Builder -// ============================================================================ - -export interface CustomMutationConfig { - operation: CleanOperation; - typeRegistry?: TypeRegistry; - maxDepth?: number; - skipQueryField?: boolean; -} - -/** - * Build a custom mutation AST from a CleanOperation - */ -export function buildCustomMutationAST( - config: CustomMutationConfig -): DocumentNode { - const { - operation, - typeRegistry, - maxDepth = 2, - skipQueryField = true, - } = config; - - const operationName = `${ucFirst(operation.name)}Mutation`; - - // Build variable definitions - const variableDefinitions = buildVariableDefinitions(operation.args); - - // Build arguments that reference the variables - const args = buildArgumentNodes(operation.args); - - // Build return type selections - const fieldSelectionConfig: FieldSelectionConfig = { - maxDepth, - skipQueryField, - typeRegistry, - }; - - const returnTypeNeedsSelections = typeNeedsSelections(operation.returnType); - let selections: FieldNode[] = []; - - if (returnTypeNeedsSelections) { - selections = buildReturnTypeSelections( - operation.returnType, - fieldSelectionConfig - ); - } - - // Build the mutation field - const mutationField: FieldNode = - selections.length > 0 - ? t.field({ - name: operation.name, - args: args.length > 0 ? args : undefined, - selectionSet: t.selectionSet({ selections }), - }) - : t.field({ - name: operation.name, - args: args.length > 0 ? args : undefined, - }); - - return t.document({ - definitions: [ - t.operationDefinition({ - operation: 'mutation', - name: operationName, - variableDefinitions: - variableDefinitions.length > 0 ? variableDefinitions : undefined, - selectionSet: t.selectionSet({ - selections: [mutationField], - }), - }), - ], - }); -} - -// ============================================================================ -// Print Utilities -// ============================================================================ - -/** - * Print a document AST to GraphQL string - */ -export function printGraphQL(ast: DocumentNode): string { - return print(ast); -} - -/** - * Build and print a custom query in one call - */ -export function buildCustomQueryString(config: CustomQueryConfig): string { - return printGraphQL(buildCustomQueryAST(config)); -} - -/** - * Build and print a custom mutation in one call - */ -export function buildCustomMutationString( - config: CustomMutationConfig -): string { - return printGraphQL(buildCustomMutationAST(config)); -} - -// ============================================================================ -// Helper Utilities -// ============================================================================ - -/** - * Uppercase first character - */ -function ucFirst(str: string): string { - return str.charAt(0).toUpperCase() + str.slice(1); -} diff --git a/graphql/codegen/src/core/codegen/schema-types-generator.ts b/graphql/codegen/src/core/codegen/schema-types-generator.ts index b4bc6a655..0e8e4b6a1 100644 --- a/graphql/codegen/src/core/codegen/schema-types-generator.ts +++ b/graphql/codegen/src/core/codegen/schema-types-generator.ts @@ -11,19 +11,20 @@ * * Uses Babel AST for robust code generation. */ +import * as t from '@babel/types'; + import type { - TypeRegistry, CleanArgument, ResolvedType, + TypeRegistry } from '../../types/schema'; -import * as t from '@babel/types'; import { generateCode } from './babel-ast'; -import { getTypeBaseName } from './type-resolver'; import { - scalarToTsType, - SCALAR_NAMES, BASE_FILTER_TYPE_NAMES, + SCALAR_NAMES, + scalarToTsType } from './scalars'; +import { getTypeBaseName } from './type-resolver'; import { getGeneratedFileHeader } from './utils'; export interface GeneratedSchemaTypesFile { @@ -49,7 +50,7 @@ const SKIP_TYPES = new Set([ '__InputValue', '__EnumValue', '__Directive', - ...BASE_FILTER_TYPE_NAMES, + ...BASE_FILTER_TYPE_NAMES ]); const SKIP_TYPE_PATTERNS: RegExp[] = []; @@ -390,6 +391,6 @@ export function generateSchemaTypesFile( fileName: 'schema-types.ts', content, generatedEnums: Array.from(enumResult.generatedTypes).sort(), - referencedTableTypes, + referencedTableTypes }; } diff --git a/graphql/codegen/src/core/codegen/select-helpers.ts b/graphql/codegen/src/core/codegen/select-helpers.ts new file mode 100644 index 000000000..4ae52a351 --- /dev/null +++ b/graphql/codegen/src/core/codegen/select-helpers.ts @@ -0,0 +1,91 @@ +/** + * Shared helpers for select type resolution in custom operations + * + * Used by custom-queries.ts, custom-mutations.ts, and orm/custom-ops-generator.ts + */ +import type { CleanArgument, TypeRegistry } from '../../types/schema'; +import { SCALAR_NAMES } from './scalars'; +import { getTypeBaseName } from './type-resolver'; + +/** + * Types that don't need Select types (scalars + root query/mutation types) + */ +export const NON_SELECT_TYPES = new Set([ + ...SCALAR_NAMES, + 'Query', + 'Mutation' +]); + +/** + * Get the Select type name for a return type. + * Returns null for scalar types, Connection types, and root types. + */ +export function getSelectTypeName(returnType: CleanArgument['type']): string | null { + const baseName = getTypeBaseName(returnType); + if ( + baseName && + !NON_SELECT_TYPES.has(baseName) && + !baseName.endsWith('Connection') + ) { + return `${baseName}Select`; + } + return null; +} + +/** + * Wrap a type reference in InferSelectResult, handling NON_NULL and LIST wrappers. + */ +export function wrapInferSelectResult( + typeRef: CleanArgument['type'], + payloadTypeName: string, + selectType: string = 'S' +): string { + if (typeRef.kind === 'NON_NULL' && typeRef.ofType) { + return wrapInferSelectResult(typeRef.ofType as CleanArgument['type'], payloadTypeName, selectType); + } + + if (typeRef.kind === 'LIST' && typeRef.ofType) { + return `${wrapInferSelectResult(typeRef.ofType as CleanArgument['type'], payloadTypeName, selectType)}[]`; + } + + return `InferSelectResult<${payloadTypeName}, ${selectType}>`; +} + +/** + * Build a default select literal string for a given type. + * Finds an 'id' or 'nodeId' field, or falls back to first scalar field. + */ +export function buildDefaultSelectLiteral( + typeName: string, + typeRegistry: TypeRegistry, + depth: number = 0 +): string { + const resolved = typeRegistry.get(typeName); + const fields = resolved?.fields ?? []; + + if (depth > 3 || fields.length === 0) { + // Use first field if available, otherwise fallback to 'id' + return fields.length > 0 ? `{ ${fields[0].name}: true }` : `{ id: true }`; + } + + const idLike = fields.find((f) => f.name === 'id' || f.name === 'nodeId'); + if (idLike) return `{ ${idLike.name}: true }`; + + const scalarField = fields.find((f) => { + const baseName = getTypeBaseName(f.type); + if (!baseName) return false; + if (NON_SELECT_TYPES.has(baseName)) return true; + return typeRegistry.get(baseName)?.kind === 'ENUM'; + }); + if (scalarField) return `{ ${scalarField.name}: true }`; + + const first = fields[0]; + + const firstBase = getTypeBaseName(first.type); + if (!firstBase || NON_SELECT_TYPES.has(firstBase) || typeRegistry.get(firstBase)?.kind === 'ENUM') { + return `{ ${first.name}: true }`; + } + + const nested = buildDefaultSelectLiteral(firstBase, typeRegistry, depth + 1); + return `{ ${first.name}: { select: ${nested} } }`; +} diff --git a/graphql/codegen/src/core/codegen/selection.ts b/graphql/codegen/src/core/codegen/selection.ts new file mode 100644 index 000000000..e9cd7fe3c --- /dev/null +++ b/graphql/codegen/src/core/codegen/selection.ts @@ -0,0 +1,39 @@ +/** + * Selection helper generator for React Query hooks + * + * Uses template-copy pattern: reads hooks-selection.ts from templates/ + * and writes it to the output directory with a generated file header. + */ +import * as fs from 'fs'; +import * as path from 'path'; + +import { getGeneratedFileHeader } from './utils'; + +function findTemplateFile(templateName: string): string { + const templatePath = path.join(__dirname, 'templates', templateName); + if (fs.existsSync(templatePath)) { + return templatePath; + } + throw new Error( + `Could not find template file: ${templateName}. Searched in: ${templatePath}` + ); +} + +function readTemplateFile(templateName: string, description: string): string { + const templatePath = findTemplateFile(templateName); + let content = fs.readFileSync(templatePath, 'utf-8'); + const headerPattern = + /\/\*\*[\s\S]*?\* NOTE: This file is read at codegen time and written to output\.[\s\S]*?\*\/\n*/; + content = content.replace( + headerPattern, + getGeneratedFileHeader(description) + '\n' + ); + return content; +} + +/** + * Generate selection.ts content - shared selection types + runtime mappers + */ +export function generateSelectionFile(): string { + return readTemplateFile('hooks-selection.ts', 'Selection helpers for React Query hooks'); +} diff --git a/graphql/codegen/src/core/codegen/shared/index.ts b/graphql/codegen/src/core/codegen/shared/index.ts index ccf6819fe..ccc31ead8 100644 --- a/graphql/codegen/src/core/codegen/shared/index.ts +++ b/graphql/codegen/src/core/codegen/shared/index.ts @@ -11,12 +11,13 @@ * 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 { GraphQLSDKConfigTarget } from '../../../types/config'; import * as t from '@babel/types'; -import { generateCode, addJSDocComment } from '../babel-ast'; -import { generateTypesFile } from '../types'; + +import type { GraphQLSDKConfigTarget } from '../../../types/config'; +import type { CleanOperation, CleanTable, TypeRegistry } from '../../../types/schema'; +import { addJSDocComment,generateCode } from '../babel-ast'; import { generateSchemaTypesFile } from '../schema-types-generator'; +import { generateTypesFile } from '../types'; import { getTableNames } from '../utils'; /** @@ -64,14 +65,14 @@ export function generateSharedTypes(options: GenerateSharedOptions): GenerateSha if (customOperations && customOperations.typeRegistry) { const schemaTypesResult = generateSchemaTypesFile({ typeRegistry: customOperations.typeRegistry, - tableTypeNames, + tableTypeNames }); // Only include if there's meaningful content if (schemaTypesResult.content.split('\n').length > 10) { files.push({ path: 'schema-types.ts', - content: schemaTypesResult.content, + content: schemaTypesResult.content }); hasSchemaTypes = true; generatedEnumNames = schemaTypesResult.generatedEnums || []; @@ -82,21 +83,21 @@ export function generateSharedTypes(options: GenerateSharedOptions): GenerateSha files.push({ path: 'types.ts', content: generateTypesFile(tables, { - enumsFromSchemaTypes: generatedEnumNames, - }), + enumsFromSchemaTypes: generatedEnumNames + }) }); // 3. Generate barrel export (index.ts) const barrelContent = generateSharedBarrel(hasSchemaTypes); files.push({ path: 'index.ts', - content: barrelContent, + content: barrelContent }); return { files, generatedEnumNames, - hasSchemaTypes, + hasSchemaTypes }; } @@ -118,12 +119,12 @@ function generateSharedBarrel(hasSchemaTypes: boolean): string { if (statements.length > 0) { addJSDocComment(statements[0], [ 'Shared types - auto-generated, do not edit', - '@generated by @constructive-io/graphql-codegen', + '@generated by @constructive-io/graphql-codegen' ]); } return generateCode(statements); } -export { generateTypesFile } from '../types'; export { generateSchemaTypesFile } from '../schema-types-generator'; +export { generateTypesFile } from '../types'; diff --git a/graphql/codegen/src/core/codegen/templates/client.browser.ts b/graphql/codegen/src/core/codegen/templates/client.browser.ts deleted file mode 100644 index 6db2d891c..000000000 --- a/graphql/codegen/src/core/codegen/templates/client.browser.ts +++ /dev/null @@ -1,271 +0,0 @@ -/** - * GraphQL client configuration and execution (Browser-compatible) - * - * This is the RUNTIME code that gets copied to generated output. - * Uses native W3C fetch API for browser compatibility. - * - * NOTE: This file is read at codegen time and written to output. - * Any changes here will affect all generated clients. - */ - -// ============================================================================ -// Configuration -// ============================================================================ - -export interface GraphQLClientConfig { - /** GraphQL endpoint URL */ - endpoint: string; - /** Default headers to include in all requests */ - headers?: Record; - /** Dynamic headers callback called on every request */ - getHeaders?: () => Record; -} - -let globalConfig: GraphQLClientConfig | null = null; - -/** - * Configure the GraphQL client - * - * @example - * ```ts - * import { configure } from './generated'; - * - * configure({ - * endpoint: 'https://api.example.com/graphql', - * headers: { - * Authorization: 'Bearer ', - * }, - * }); - * ``` - */ -export function configure(config: GraphQLClientConfig): void { - globalConfig = config; -} - -/** - * Get the current configuration - * @throws Error if not configured - */ -export function getConfig(): GraphQLClientConfig { - if (!globalConfig) { - throw new Error( - 'GraphQL client not configured. Call configure() before making requests.' - ); - } - return globalConfig; -} - -/** - * Set a single header value - * Useful for updating Authorization after login - * - * @example - * ```ts - * setHeader('Authorization', 'Bearer '); - * ``` - */ -export function setHeader(key: string, value: string): void { - const config = getConfig(); - globalConfig = { - ...config, - headers: { ...config.headers, [key]: value }, - }; -} - -/** - * Merge multiple headers into the current configuration - * - * @example - * ```ts - * setHeaders({ Authorization: 'Bearer ', 'X-Custom': 'value' }); - * ``` - */ -export function setHeaders(headers: Record): void { - const config = getConfig(); - globalConfig = { - ...config, - headers: { ...config.headers, ...headers }, - }; -} - -// ============================================================================ -// Error handling -// ============================================================================ - -export interface GraphQLError { - message: string; - locations?: Array<{ line: number; column: number }>; - path?: Array; - extensions?: Record; -} - -export class GraphQLClientError extends Error { - constructor( - message: string, - public errors: GraphQLError[], - public response?: Response - ) { - super(message); - this.name = 'GraphQLClientError'; - } -} - -// ============================================================================ -// Execution -// ============================================================================ - -export interface ExecuteOptions { - /** Override headers for this request */ - headers?: Record; - /** AbortSignal for request cancellation */ - signal?: AbortSignal; -} - -/** - * Execute a GraphQL operation - * - * @example - * ```ts - * const result = await execute( - * carsQueryDocument, - * { first: 10 } - * ); - * ``` - */ -export async function execute< - TData = unknown, - TVariables = Record, ->( - document: string, - variables?: TVariables, - options?: ExecuteOptions -): Promise { - const config = getConfig(); - const dynamicHeaders = config.getHeaders?.() ?? {}; - - const response = await fetch(config.endpoint, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...config.headers, - ...dynamicHeaders, - ...options?.headers, - }, - body: JSON.stringify({ - query: document, - variables, - }), - signal: options?.signal, - }); - - const json = await response.json(); - - if (json.errors && json.errors.length > 0) { - throw new GraphQLClientError( - json.errors[0].message || 'GraphQL request failed', - json.errors, - response - ); - } - - return json.data as TData; -} - -/** - * Execute a GraphQL operation with full response (data + errors) - * Useful when you want to handle partial data with errors - */ -export async function executeWithErrors< - TData = unknown, - TVariables = Record, ->( - document: string, - variables?: TVariables, - options?: ExecuteOptions -): Promise<{ data: TData | null; errors: GraphQLError[] | null }> { - const config = getConfig(); - const dynamicHeaders = config.getHeaders?.() ?? {}; - - const response = await fetch(config.endpoint, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...config.headers, - ...dynamicHeaders, - ...options?.headers, - }, - body: JSON.stringify({ - query: document, - variables, - }), - signal: options?.signal, - }); - - const json = await response.json(); - - return { - data: json.data ?? null, - errors: json.errors ?? null, - }; -} - -// ============================================================================ -// QueryClient Factory -// ============================================================================ - -/** - * Default QueryClient configuration optimized for GraphQL - * - * These defaults provide a good balance between freshness and performance: - * - staleTime: 1 minute - data considered fresh, won't refetch - * - gcTime: 5 minutes - unused data kept in cache - * - refetchOnWindowFocus: false - don't refetch when tab becomes active - * - retry: 1 - retry failed requests once - */ -export const defaultQueryClientOptions = { - defaultOptions: { - queries: { - staleTime: 1000 * 60, // 1 minute - gcTime: 1000 * 60 * 5, // 5 minutes - refetchOnWindowFocus: false, - retry: 1, - }, - }, -}; - -/** - * QueryClient options type for createQueryClient - */ -export interface CreateQueryClientOptions { - defaultOptions?: { - queries?: { - staleTime?: number; - gcTime?: number; - refetchOnWindowFocus?: boolean; - retry?: number | boolean; - retryDelay?: number | ((attemptIndex: number) => number); - }; - mutations?: { - retry?: number | boolean; - retryDelay?: number | ((attemptIndex: number) => number); - }; - }; -} - -// Note: createQueryClient is available when using with @tanstack/react-query -// Import QueryClient from '@tanstack/react-query' and use these options: -// -// import { QueryClient } from '@tanstack/react-query'; -// const queryClient = new QueryClient(defaultQueryClientOptions); -// -// Or merge with your own options: -// const queryClient = new QueryClient({ -// ...defaultQueryClientOptions, -// defaultOptions: { -// ...defaultQueryClientOptions.defaultOptions, -// queries: { -// ...defaultQueryClientOptions.defaultOptions.queries, -// staleTime: 30000, // Override specific options -// }, -// }, -// }); diff --git a/graphql/codegen/src/core/codegen/templates/client.node.ts b/graphql/codegen/src/core/codegen/templates/client.node.ts deleted file mode 100644 index 156f41ceb..000000000 --- a/graphql/codegen/src/core/codegen/templates/client.node.ts +++ /dev/null @@ -1,337 +0,0 @@ -/** - * GraphQL client configuration and execution (Node.js with native http/https) - * - * This is the RUNTIME code that gets copied to generated output. - * Uses native Node.js http/https modules. - * - * NOTE: This file is read at codegen time and written to output. - * Any changes here will affect all generated clients. - */ - -import http from 'node:http'; -import https from 'node:https'; - -// ============================================================================ -// HTTP Request Helper -// ============================================================================ - -interface HttpResponse { - statusCode: number; - statusMessage: string; - data: string; -} - -/** - * Make an HTTP/HTTPS request using native Node modules - */ -function makeRequest( - url: URL, - options: http.RequestOptions, - body: string -): Promise { - return new Promise((resolve, reject) => { - const protocol = url.protocol === 'https:' ? https : http; - - const req = protocol.request(url, options, (res) => { - let data = ''; - res.setEncoding('utf8'); - res.on('data', (chunk: string) => { - data += chunk; - }); - res.on('end', () => { - resolve({ - statusCode: res.statusCode || 0, - statusMessage: res.statusMessage || '', - data, - }); - }); - }); - - req.on('error', reject); - req.write(body); - req.end(); - }); -} - -// ============================================================================ -// Configuration -// ============================================================================ - -export interface GraphQLClientConfig { - /** GraphQL endpoint URL */ - endpoint: string; - /** Default headers to include in all requests */ - headers?: Record; - /** Dynamic headers callback called on every request */ - getHeaders?: () => Record; -} - -let globalConfig: GraphQLClientConfig | null = null; - -/** - * Configure the GraphQL client - * - * @example - * ```ts - * import { configure } from './generated'; - * - * configure({ - * endpoint: 'https://api.example.com/graphql', - * headers: { - * Authorization: 'Bearer ', - * }, - * }); - * ``` - */ -export function configure(config: GraphQLClientConfig): void { - globalConfig = config; -} - -/** - * Get the current configuration - * @throws Error if not configured - */ -export function getConfig(): GraphQLClientConfig { - if (!globalConfig) { - throw new Error( - 'GraphQL client not configured. Call configure() before making requests.' - ); - } - return globalConfig; -} - -/** - * Set a single header value - * Useful for updating Authorization after login - * - * @example - * ```ts - * setHeader('Authorization', 'Bearer '); - * ``` - */ -export function setHeader(key: string, value: string): void { - const config = getConfig(); - globalConfig = { - ...config, - headers: { ...config.headers, [key]: value }, - }; -} - -/** - * Merge multiple headers into the current configuration - * - * @example - * ```ts - * setHeaders({ Authorization: 'Bearer ', 'X-Custom': 'value' }); - * ``` - */ -export function setHeaders(headers: Record): void { - const config = getConfig(); - globalConfig = { - ...config, - headers: { ...config.headers, ...headers }, - }; -} - -// ============================================================================ -// Error handling -// ============================================================================ - -export interface GraphQLError { - message: string; - locations?: Array<{ line: number; column: number }>; - path?: Array; - extensions?: Record; -} - -export class GraphQLClientError extends Error { - constructor( - message: string, - public errors: GraphQLError[], - public statusCode?: number - ) { - super(message); - this.name = 'GraphQLClientError'; - } -} - -// ============================================================================ -// Execution -// ============================================================================ - -export interface ExecuteOptions { - /** Override headers for this request */ - headers?: Record; -} - -/** - * Execute a GraphQL operation - * - * @example - * ```ts - * const result = await execute( - * carsQueryDocument, - * { first: 10 } - * ); - * ``` - */ -export async function execute< - TData = unknown, - TVariables = Record, ->( - document: string, - variables?: TVariables, - options?: ExecuteOptions -): Promise { - const config = getConfig(); - const url = new URL(config.endpoint); - const dynamicHeaders = config.getHeaders?.() ?? {}; - - const body = JSON.stringify({ - query: document, - variables, - }); - - const requestOptions: http.RequestOptions = { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...config.headers, - ...dynamicHeaders, - ...options?.headers, - }, - }; - - const response = await makeRequest(url, requestOptions, body); - - if (response.statusCode < 200 || response.statusCode >= 300) { - throw new Error(`HTTP ${response.statusCode}: ${response.statusMessage}`); - } - - const json = JSON.parse(response.data) as { - data?: TData; - errors?: GraphQLError[]; - }; - - if (json.errors && json.errors.length > 0) { - throw new GraphQLClientError( - json.errors[0].message || 'GraphQL request failed', - json.errors, - response.statusCode - ); - } - - return json.data as TData; -} - -/** - * Execute a GraphQL operation with full response (data + errors) - * Useful when you want to handle partial data with errors - */ -export async function executeWithErrors< - TData = unknown, - TVariables = Record, ->( - document: string, - variables?: TVariables, - options?: ExecuteOptions -): Promise<{ data: TData | null; errors: GraphQLError[] | null }> { - const config = getConfig(); - const url = new URL(config.endpoint); - const dynamicHeaders = config.getHeaders?.() ?? {}; - - const body = JSON.stringify({ - query: document, - variables, - }); - - const requestOptions: http.RequestOptions = { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...config.headers, - ...dynamicHeaders, - ...options?.headers, - }, - }; - - const response = await makeRequest(url, requestOptions, body); - - if (response.statusCode < 200 || response.statusCode >= 300) { - return { - data: null, - errors: [{ message: `HTTP ${response.statusCode}: ${response.statusMessage}` }], - }; - } - - const json = JSON.parse(response.data) as { - data?: TData; - errors?: GraphQLError[]; - }; - - return { - data: json.data ?? null, - errors: json.errors ?? null, - }; -} - -// ============================================================================ -// QueryClient Factory -// ============================================================================ - -/** - * Default QueryClient configuration optimized for GraphQL - * - * These defaults provide a good balance between freshness and performance: - * - staleTime: 1 minute - data considered fresh, won't refetch - * - gcTime: 5 minutes - unused data kept in cache - * - refetchOnWindowFocus: false - don't refetch when tab becomes active - * - retry: 1 - retry failed requests once - */ -export const defaultQueryClientOptions = { - defaultOptions: { - queries: { - staleTime: 1000 * 60, // 1 minute - gcTime: 1000 * 60 * 5, // 5 minutes - refetchOnWindowFocus: false, - retry: 1, - }, - }, -}; - -/** - * QueryClient options type for createQueryClient - */ -export interface CreateQueryClientOptions { - defaultOptions?: { - queries?: { - staleTime?: number; - gcTime?: number; - refetchOnWindowFocus?: boolean; - retry?: number | boolean; - retryDelay?: number | ((attemptIndex: number) => number); - }; - mutations?: { - retry?: number | boolean; - retryDelay?: number | ((attemptIndex: number) => number); - }; - }; -} - -// Note: createQueryClient is available when using with @tanstack/react-query -// Import QueryClient from '@tanstack/react-query' and use these options: -// -// import { QueryClient } from '@tanstack/react-query'; -// const queryClient = new QueryClient(defaultQueryClientOptions); -// -// Or merge with your own options: -// const queryClient = new QueryClient({ -// ...defaultQueryClientOptions, -// defaultOptions: { -// ...defaultQueryClientOptions.defaultOptions, -// queries: { -// ...defaultQueryClientOptions.defaultOptions.queries, -// staleTime: 30000, // Override specific options -// }, -// }, -// }); diff --git a/graphql/codegen/src/core/codegen/templates/hooks-client.ts b/graphql/codegen/src/core/codegen/templates/hooks-client.ts new file mode 100644 index 000000000..197fad4c5 --- /dev/null +++ b/graphql/codegen/src/core/codegen/templates/hooks-client.ts @@ -0,0 +1,49 @@ +/** + * ORM client wrapper for React Query hooks + * + * This is the RUNTIME code that gets copied to generated output. + * Provides configure/getClient singleton for React Query hooks to access the ORM. + * + * NOTE: This file is read at codegen time and written to output. + * Any changes here will affect all generated hook clients. + */ + +import { createClient } from '../orm'; +import type { OrmClientConfig } from '../orm/client'; + +export type { OrmClientConfig } from '../orm/client'; +export type { GraphQLAdapter, GraphQLError, QueryResult } from '../orm/client'; +export { GraphQLRequestError } from '../orm/client'; + +type OrmClientInstance = ReturnType; +let client: OrmClientInstance | null = null; + +/** + * Configure the ORM client for React Query hooks + * + * @example + * ```ts + * import { configure } from './generated/hooks'; + * + * configure({ + * endpoint: 'https://api.example.com/graphql', + * headers: { Authorization: 'Bearer ' }, + * }); + * ``` + */ +export function configure(config: OrmClientConfig): void { + client = createClient(config); +} + +/** + * Get the configured ORM client instance + * @throws Error if configure() has not been called + */ +export function getClient(): OrmClientInstance { + if (!client) { + throw new Error( + 'ORM client not configured. Call configure() before using hooks.' + ); + } + return client; +} diff --git a/graphql/codegen/src/core/codegen/templates/hooks-selection.ts b/graphql/codegen/src/core/codegen/templates/hooks-selection.ts new file mode 100644 index 000000000..4e2741476 --- /dev/null +++ b/graphql/codegen/src/core/codegen/templates/hooks-selection.ts @@ -0,0 +1,79 @@ +/** + * Selection helpers for React Query hooks + * + * This is the RUNTIME code that gets copied to generated output. + * Provides selection types and runtime mappers between hook-facing + * `selection` params and ORM-facing args (`select`, `where`, `orderBy`, etc.). + * + * NOTE: This file is read at codegen time and written to output. + * Any changes here will affect all generated hook selection helpers. + */ + +export interface SelectionConfig { + fields?: TFields; +} + +export interface ListSelectionConfig + extends SelectionConfig { + where?: TWhere; + orderBy?: TOrderBy[]; + first?: number; + last?: number; + after?: string; + before?: string; + offset?: number; +} + +export function buildSelectionArgs( + selection?: SelectionConfig +): { select?: TFields } | undefined { + if (!selection || selection.fields === undefined) { + return undefined; + } + + return { select: selection.fields }; +} + +export function buildListSelectionArgs( + selection?: ListSelectionConfig +): + | { + select?: TFields; + where?: TWhere; + orderBy?: TOrderBy[]; + first?: number; + last?: number; + after?: string; + before?: string; + offset?: number; + } + | undefined { + if (!selection) { + return undefined; + } + + const hasAnyValues = + selection.fields !== undefined || + selection.where !== undefined || + selection.orderBy !== undefined || + selection.first !== undefined || + selection.last !== undefined || + selection.after !== undefined || + selection.before !== undefined || + selection.offset !== undefined; + + if (!hasAnyValues) { + return undefined; + } + + return { + select: selection.fields, + where: selection.where, + orderBy: selection.orderBy, + first: selection.first, + last: selection.last, + after: selection.after, + before: selection.before, + offset: selection.offset + }; +} diff --git a/graphql/codegen/src/core/codegen/templates/orm-client.ts b/graphql/codegen/src/core/codegen/templates/orm-client.ts index a71633d67..c6993a338 100644 --- a/graphql/codegen/src/core/codegen/templates/orm-client.ts +++ b/graphql/codegen/src/core/codegen/templates/orm-client.ts @@ -11,13 +11,13 @@ import type { GraphQLAdapter, GraphQLError, - QueryResult, + QueryResult } from '@constructive-io/graphql-types'; export type { GraphQLAdapter, GraphQLError, - QueryResult, + QueryResult } from '@constructive-io/graphql-types'; /** @@ -43,19 +43,19 @@ export class FetchAdapter implements GraphQLAdapter { headers: { 'Content-Type': 'application/json', Accept: 'application/json', - ...this.headers, + ...this.headers }, body: JSON.stringify({ query: document, - variables: variables ?? {}, - }), + variables: variables ?? {} + }) }); if (!response.ok) { return { ok: false, data: null, - errors: [{ message: `HTTP ${response.status}: ${response.statusText}` }], + errors: [{ message: `HTTP ${response.status}: ${response.statusText}` }] }; } @@ -68,14 +68,14 @@ export class FetchAdapter implements GraphQLAdapter { return { ok: false, data: null, - errors: json.errors, + errors: json.errors }; } return { ok: true, data: json.data as T, - errors: undefined, + errors: undefined }; } diff --git a/graphql/codegen/src/core/codegen/templates/query-builder.ts b/graphql/codegen/src/core/codegen/templates/query-builder.ts index 869e210e8..a62cdf075 100644 --- a/graphql/codegen/src/core/codegen/templates/query-builder.ts +++ b/graphql/codegen/src/core/codegen/templates/query-builder.ts @@ -8,15 +8,16 @@ * Any changes here will affect all generated ORM clients. */ -import * as t from 'gql-ast'; import { parseType, print } from '@0no-co/graphql.web'; +import * as t from 'gql-ast'; import type { ArgumentNode, - FieldNode, - VariableDefinitionNode, EnumValueNode, + FieldNode, + VariableDefinitionNode } from 'graphql'; -import { OrmClient, QueryResult, GraphQLRequestError } from './client'; + +import { GraphQLRequestError,OrmClient, QueryResult } from './client'; export interface QueryBuilderConfig { client: OrmClient; @@ -95,13 +96,16 @@ export class QueryBuilder { // ============================================================================ export function buildSelections( - select: Record | undefined + select: Record | undefined, + connectionFieldsMap?: Record>, + entityType?: string ): FieldNode[] { if (!select) { return []; } const fields: FieldNode[] = []; + const entityConnections = entityType ? connectionFieldsMap?.[entityType] : undefined; for (const [key, value] of Object.entries(select)) { if (value === false || value === undefined) { @@ -123,17 +127,19 @@ export function buildSelections( }; if (nested.select) { - const nestedSelections = buildSelections(nested.select); + const relatedEntityType = entityConnections?.[key]; + const nestedSelections = buildSelections(nested.select, connectionFieldsMap, relatedEntityType); const isConnection = nested.connection === true || nested.first !== undefined || - nested.filter !== undefined; + nested.filter !== undefined || + relatedEntityType !== undefined; const args = buildArgs([ buildOptionalArg('first', nested.first), nested.filter ? t.argument({ name: 'filter', value: buildValueAst(nested.filter) }) : null, - buildEnumListArg('orderBy', nested.orderBy), + buildEnumListArg('orderBy', nested.orderBy) ]); if (isConnection) { @@ -142,8 +148,8 @@ export function buildSelections( name: key, args, selectionSet: t.selectionSet({ - selections: buildConnectionSelections(nestedSelections), - }), + selections: buildConnectionSelections(nestedSelections) + }) }) ); } else { @@ -151,7 +157,7 @@ export function buildSelections( t.field({ name: key, args, - selectionSet: t.selectionSet({ selections: nestedSelections }), + selectionSet: t.selectionSet({ selections: nestedSelections }) }) ); } @@ -180,10 +186,11 @@ export function buildFindManyDocument( offset?: number; }, filterTypeName: string, - orderByTypeName: string + orderByTypeName: string, + connectionFieldsMap?: Record> ): { document: string; variables: Record } { const selections = select - ? buildSelections(select as Record) + ? buildSelections(select as Record, connectionFieldsMap, operationName) : [t.field({ name: 'id' })]; const variableDefinitions: VariableDefinitionNode[] = []; @@ -200,7 +207,7 @@ export function buildFindManyDocument( { varName: 'orderBy', typeName: '[' + orderByTypeName + '!]', - value: args.orderBy?.length ? args.orderBy : undefined, + value: args.orderBy?.length ? args.orderBy : undefined }, variableDefinitions, queryArgs, @@ -249,13 +256,13 @@ export function buildFindManyDocument( name: queryField, args: queryArgs.length ? queryArgs : undefined, selectionSet: t.selectionSet({ - selections: buildConnectionSelections(selections), - }), - }), - ], - }), - }), - ], + selections: buildConnectionSelections(selections) + }) + }) + ] + }) + }) + ] }); return { document: print(document), variables }; @@ -266,10 +273,11 @@ export function buildFindFirstDocument( queryField: string, select: TSelect, args: { where?: TWhere }, - filterTypeName: string + filterTypeName: string, + connectionFieldsMap?: Record> ): { document: string; variables: Record } { const selections = select - ? buildSelections(select as Record) + ? buildSelections(select as Record, connectionFieldsMap, operationName) : [t.field({ name: 'id' })]; const variableDefinitions: VariableDefinitionNode[] = []; @@ -305,15 +313,15 @@ export function buildFindFirstDocument( selections: [ t.field({ name: 'nodes', - selectionSet: t.selectionSet({ selections }), - }), - ], - }), - }), - ], - }), - }), - ], + selectionSet: t.selectionSet({ selections }) + }) + ] + }) + }) + ] + }) + }) + ] }); return { document: print(document), variables }; @@ -325,10 +333,11 @@ export function buildCreateDocument( entityField: string, select: TSelect, data: TData, - inputTypeName: string + inputTypeName: string, + connectionFieldsMap?: Record> ): { document: string; variables: Record } { const selections = select - ? buildSelections(select as Record) + ? buildSelections(select as Record, connectionFieldsMap, operationName) : [t.field({ name: 'id' })]; return { @@ -339,15 +348,15 @@ export function buildCreateDocument( resultSelections: [ t.field({ name: entityField, - selectionSet: t.selectionSet({ selections }), - }), - ], + selectionSet: t.selectionSet({ selections }) + }) + ] }), variables: { input: { - [entityField]: data, - }, - }, + [entityField]: data + } + } }; } @@ -358,10 +367,11 @@ export function buildUpdateDocument> ): { document: string; variables: Record } { const selections = select - ? buildSelections(select as Record) + ? buildSelections(select as Record, connectionFieldsMap, operationName) : [t.field({ name: 'id' })]; return { @@ -372,26 +382,120 @@ export function buildUpdateDocument( +export function buildUpdateByPkDocument( + operationName: string, + mutationField: string, + entityField: string, + select: TSelect, + id: string | number, + data: TData, + inputTypeName: string, + idFieldName: string, + connectionFieldsMap?: Record> +): { document: string; variables: Record } { + const selections = select + ? buildSelections(select as Record, connectionFieldsMap, operationName) + : [t.field({ name: 'id' })]; + + return { + document: buildInputMutationDocument({ + operationName, + mutationField, + inputTypeName, + resultSelections: [ + t.field({ + name: entityField, + selectionSet: t.selectionSet({ selections }) + }) + ] + }), + variables: { + input: { + [idFieldName]: id, + patch: data + } + } + }; +} + +export function buildFindOneDocument( + operationName: string, + queryField: string, + id: string | number, + select: TSelect, + idArgName: string, + idTypeName: string, + connectionFieldsMap?: Record> +): { document: string; variables: Record } { + const selections = select + ? buildSelections(select as Record, connectionFieldsMap, operationName) + : [t.field({ name: 'id' })]; + + const variableDefinitions: VariableDefinitionNode[] = [ + t.variableDefinition({ + variable: t.variable({ name: idArgName }), + type: parseType(idTypeName) + }) + ]; + + const queryArgs: ArgumentNode[] = [ + t.argument({ + name: idArgName, + value: t.variable({ name: idArgName }) + }) + ]; + + const document = t.document({ + definitions: [ + t.operationDefinition({ + operation: 'query', + name: operationName + 'Query', + variableDefinitions, + selectionSet: t.selectionSet({ + selections: [ + t.field({ + name: queryField, + args: queryArgs, + selectionSet: t.selectionSet({ selections }) + }) + ] + }) + }) + ] + }); + + return { + document: print(document), + variables: { [idArgName]: id } + }; +} + +export function buildDeleteDocument( operationName: string, mutationField: string, entityField: string, where: TWhere, - inputTypeName: string + inputTypeName: string, + select?: TSelect, + connectionFieldsMap?: Record> ): { document: string; variables: Record } { + const entitySelections = select + ? buildSelections(select as Record, connectionFieldsMap, operationName) + : [t.field({ name: 'id' })]; + return { document: buildInputMutationDocument({ operationName, @@ -401,16 +505,50 @@ export function buildDeleteDocument( t.field({ name: entityField, selectionSet: t.selectionSet({ - selections: [t.field({ name: 'id' })], - }), - }), - ], + selections: entitySelections + }) + }) + ] }), variables: { input: { - id: where.id, - }, - }, + id: where.id + } + } + }; +} + +export function buildDeleteByPkDocument( + operationName: string, + mutationField: string, + entityField: string, + id: string | number, + inputTypeName: string, + idFieldName: string, + select?: TSelect, + connectionFieldsMap?: Record> +): { document: string; variables: Record } { + const entitySelections = select + ? buildSelections(select as Record, connectionFieldsMap, operationName) + : [t.field({ name: 'id' })]; + + return { + document: buildInputMutationDocument({ + operationName, + mutationField, + inputTypeName, + resultSelections: [ + t.field({ + name: entityField, + selectionSet: t.selectionSet({ selections: entitySelections }) + }) + ] + }), + variables: { + input: { + [idFieldName]: id + } + } }; } @@ -420,7 +558,9 @@ export function buildCustomDocument( fieldName: string, select: TSelect, args: TArgs, - variableDefinitions: Array<{ name: string; type: string }> + variableDefinitions: Array<{ name: string; type: string }>, + connectionFieldsMap?: Record>, + entityType?: string ): { document: string; variables: Record } { let actualSelect = select; let isConnection = false; @@ -434,19 +574,19 @@ export function buildCustomDocument( } const selections = actualSelect - ? buildSelections(actualSelect as Record) + ? buildSelections(actualSelect as Record, connectionFieldsMap, entityType) : []; const variableDefs = variableDefinitions.map((definition) => t.variableDefinition({ variable: t.variable({ name: definition.name }), - type: parseType(definition.type), + type: parseType(definition.type) }) ); const fieldArgs = variableDefinitions.map((definition) => t.argument({ name: definition.name, - value: t.variable({ name: definition.name }), + value: t.variable({ name: definition.name }) }) ); @@ -467,17 +607,17 @@ export function buildCustomDocument( args: fieldArgs.length ? fieldArgs : undefined, selectionSet: fieldSelections.length ? t.selectionSet({ selections: fieldSelections }) - : undefined, - }), - ], - }), - }), - ], + : undefined + }) + ] + }) + }) + ] }); return { document: print(document), - variables: (args ?? {}) as Record, + variables: (args ?? {}) as Record }; } @@ -513,15 +653,15 @@ function buildEnumListArg( return t.argument({ name, value: t.listValue({ - values: values.map((value) => buildEnumValue(value)), - }), + values: values.map((value) => buildEnumValue(value)) + }) }); } function buildEnumValue(value: string): EnumValueNode { return { kind: 'EnumValue', - value, + value }; } @@ -530,7 +670,7 @@ function buildPageInfoSelections(): FieldNode[] { t.field({ name: 'hasNextPage' }), t.field({ name: 'hasPreviousPage' }), t.field({ name: 'startCursor' }), - t.field({ name: 'endCursor' }), + t.field({ name: 'endCursor' }) ]; } @@ -538,13 +678,13 @@ function buildConnectionSelections(nodeSelections: FieldNode[]): FieldNode[] { return [ t.field({ name: 'nodes', - selectionSet: t.selectionSet({ selections: nodeSelections }), + selectionSet: t.selectionSet({ selections: nodeSelections }) }), t.field({ name: 'totalCount' }), t.field({ name: 'pageInfo', - selectionSet: t.selectionSet({ selections: buildPageInfoSelections() }), - }), + selectionSet: t.selectionSet({ selections: buildPageInfoSelections() }) + }) ]; } @@ -571,8 +711,8 @@ function buildInputMutationDocument(config: InputMutationConfig): string { variableDefinitions: [ t.variableDefinition({ variable: t.variable({ name: 'input' }), - type: parseType(config.inputTypeName + '!'), - }), + type: parseType(config.inputTypeName + '!') + }) ], selectionSet: t.selectionSet({ selections: [ @@ -581,17 +721,17 @@ function buildInputMutationDocument(config: InputMutationConfig): string { args: [ t.argument({ name: 'input', - value: t.variable({ name: 'input' }), - }), + value: t.variable({ name: 'input' }) + }) ], selectionSet: t.selectionSet({ - selections: config.resultSelections, - }), - }), - ], - }), - }), - ], + selections: config.resultSelections + }) + }) + ] + }) + }) + ] }); return print(document); } @@ -607,13 +747,13 @@ function addVariable( definitions.push( t.variableDefinition({ variable: t.variable({ name: spec.varName }), - type: parseType(spec.typeName), + type: parseType(spec.typeName) }) ); args.push( t.argument({ name: spec.argName ?? spec.varName, - value: t.variable({ name: spec.varName }), + value: t.variable({ name: spec.varName }) }) ); variables[spec.varName] = spec.value; @@ -650,7 +790,7 @@ function buildValueAst( if (Array.isArray(value)) { return t.listValue({ - values: value.map((item) => buildValueAst(item)), + values: value.map((item) => buildValueAst(item)) }); } @@ -660,9 +800,9 @@ function buildValueAst( fields: Object.entries(obj).map(([key, val]) => t.objectField({ name: key, - value: buildValueAst(val), + value: buildValueAst(val) }) - ), + ) }); } diff --git a/graphql/codegen/src/core/codegen/templates/select-types.ts b/graphql/codegen/src/core/codegen/templates/select-types.ts index 4f0360a77..5656e4901 100644 --- a/graphql/codegen/src/core/codegen/templates/select-types.ts +++ b/graphql/codegen/src/core/codegen/templates/select-types.ts @@ -48,23 +48,26 @@ export interface UpdateArgs { select?: TSelect; } -export interface DeleteArgs { +export type FindOneArgs< + TSelect, + TIdName extends string = 'id', + TId = string +> = { + select?: TSelect; +} & Record; + +export interface DeleteArgs { where: TWhere; + select?: TSelect; } /** * Recursively validates select objects, rejecting unknown keys. * - * This type ensures that users can only select fields that actually exist - * in the GraphQL schema. It returns `never` if any excess keys are found - * at any nesting level, causing a TypeScript compile error. - * - * Why this is needed: - * TypeScript's excess property checking has a quirk where it only catches - * invalid fields when they are the ONLY fields. When mixed with valid fields - * (e.g., `{ id: true, invalidField: true }`), the structural typing allows - * the excess property through. This type explicitly checks for and rejects - * such cases. + * NOTE: This type is intentionally NOT used in generated parameter positions + * (conditional types block IDE autocompletion). Parameters use `S` directly + * with `S extends XxxSelect` constraints, which provides full + * autocompletion via TypeScript's contextual typing. * * @example * // This will cause a type error because 'invalid' doesn't exist: @@ -81,15 +84,25 @@ export type DeepExact = T extends Shape ? { [K in keyof T]: K extends keyof Shape ? T[K] extends { select: infer NS } - ? Shape[K] extends { select?: infer ShapeNS } - ? { select: DeepExact> } - : T[K] + ? Extract extends { select?: infer ShapeNS } + ? DeepExact< + Omit & { select: DeepExact> }, + Extract + > + : never : T[K] : never; } : never : never; +/** + * Enforces exact select shape while keeping contextual typing on `S extends XxxSelect`. + * Use this as an intersection in overloads: + * `{ select: S } & StrictSelect`. + */ +export type StrictSelect = S extends DeepExact ? {} : never; + /** * Infer result type from select configuration */ diff --git a/graphql/codegen/src/core/codegen/type-resolver.ts b/graphql/codegen/src/core/codegen/type-resolver.ts index f358cff12..9e8856aa3 100644 --- a/graphql/codegen/src/core/codegen/type-resolver.ts +++ b/graphql/codegen/src/core/codegen/type-resolver.ts @@ -5,11 +5,10 @@ * into TypeScript type strings and interface definitions. */ import type { - CleanTypeRef, - CleanArgument, CleanObjectField, + CleanTypeRef } from '../../types/schema'; -import { scalarToTsType as resolveScalarToTs, SCALAR_NAMES } from './scalars'; +import { SCALAR_NAMES,scalarToTsType as resolveScalarToTs } from './scalars'; // ============================================================================ // Type Tracker for Collecting Referenced Types @@ -31,7 +30,7 @@ const SKIP_TYPE_TRACKING = new Set([ '__EnumValue', '__Directive', // Connection types (handled separately) - 'PageInfo', + 'PageInfo' ]); /** @@ -88,7 +87,7 @@ export function createTypeTracker(options?: TypeTrackerOptions): TypeTracker { }, reset() { referencedTypes.clear(); - }, + } }; } @@ -116,42 +115,42 @@ export function scalarToTsType(scalarName: string): string { */ export function typeRefToTsType(typeRef: CleanTypeRef, tracker?: TypeTracker): string { switch (typeRef.kind) { - case 'NON_NULL': - // Non-null wrapper - unwrap and return the inner type - if (typeRef.ofType) { - return typeRefToTsType(typeRef.ofType, tracker); - } - return 'unknown'; + case 'NON_NULL': + // Non-null wrapper - unwrap and return the inner type + if (typeRef.ofType) { + return typeRefToTsType(typeRef.ofType, tracker); + } + return 'unknown'; - case 'LIST': - // List wrapper - wrap inner type in array - if (typeRef.ofType) { - const innerType = typeRefToTsType(typeRef.ofType, tracker); - return `${innerType}[]`; - } - return 'unknown[]'; + case 'LIST': + // List wrapper - wrap inner type in array + if (typeRef.ofType) { + const innerType = typeRefToTsType(typeRef.ofType, tracker); + return `${innerType}[]`; + } + return 'unknown[]'; - case 'SCALAR': - // Scalar type - map to TS type - return scalarToTsType(typeRef.name ?? 'unknown'); + case 'SCALAR': + // Scalar type - map to TS type + return scalarToTsType(typeRef.name ?? 'unknown'); - case 'ENUM': { - // Enum type - use the GraphQL enum name and track it - const typeName = typeRef.name ?? 'string'; - tracker?.track(typeName); - return typeName; - } + case 'ENUM': { + // Enum type - use the GraphQL enum name and track it + const typeName = typeRef.name ?? 'string'; + tracker?.track(typeName); + return typeName; + } - case 'OBJECT': - case 'INPUT_OBJECT': { - // Object types - use the GraphQL type name and track it - const typeName = typeRef.name ?? 'unknown'; - tracker?.track(typeName); - return typeName; - } + case 'OBJECT': + case 'INPUT_OBJECT': { + // Object types - use the GraphQL type name and track it + const typeName = typeRef.name ?? 'unknown'; + tracker?.track(typeName); + return typeName; + } - default: - return 'unknown'; + default: + return 'unknown'; } } diff --git a/graphql/codegen/src/core/codegen/types.ts b/graphql/codegen/src/core/codegen/types.ts index 4491ed972..1fb93e70c 100644 --- a/graphql/codegen/src/core/codegen/types.ts +++ b/graphql/codegen/src/core/codegen/types.ts @@ -1,10 +1,11 @@ /** * Types generator - generates types.ts with entity interfaces using Babel AST */ -import type { CleanTable } from '../../types/schema'; import * as t from '@babel/types'; + +import type { CleanTable } from '../../types/schema'; import { generateCode } from './babel-ast'; -import { getScalarFields, fieldTypeToTs, getGeneratedFileHeader } from './utils'; +import { fieldTypeToTs, getGeneratedFileHeader,getScalarFields } from './utils'; interface InterfaceProperty { name: string; @@ -37,7 +38,7 @@ const FILTER_CONFIGS: Array<{ name: string; tsType: string; operators: FilterOps // List filters { name: 'StringListFilter', tsType: 'string[]', operators: ['equality', 'distinct', 'comparison', 'listArray'] }, { name: 'IntListFilter', tsType: 'number[]', operators: ['equality', 'distinct', 'comparison', 'listArray'] }, - { name: 'UUIDListFilter', tsType: 'string[]', operators: ['equality', 'distinct', 'comparison', 'listArray'] }, + { name: 'UUIDListFilter', tsType: 'string[]', operators: ['equality', 'distinct', 'comparison', 'listArray'] } ]; /** Build filter properties based on operator sets */ @@ -49,7 +50,7 @@ function buildFilterProperties(tsType: string, operators: FilterOps[]): Interfac props.push( { name: 'isNull', type: 'boolean', optional: true }, { name: 'equalTo', type: tsType, optional: true }, - { name: 'notEqualTo', type: tsType, optional: true }, + { name: 'notEqualTo', type: tsType, optional: true } ); } @@ -57,7 +58,7 @@ function buildFilterProperties(tsType: string, operators: FilterOps[]): Interfac if (operators.includes('distinct')) { props.push( { name: 'distinctFrom', type: tsType, optional: true }, - { name: 'notDistinctFrom', type: tsType, optional: true }, + { name: 'notDistinctFrom', type: tsType, optional: true } ); } @@ -65,7 +66,7 @@ function buildFilterProperties(tsType: string, operators: FilterOps[]): Interfac if (operators.includes('inArray')) { props.push( { name: 'in', type: `${tsType}[]`, optional: true }, - { name: 'notIn', type: `${tsType}[]`, optional: true }, + { name: 'notIn', type: `${tsType}[]`, optional: true } ); } @@ -75,7 +76,7 @@ function buildFilterProperties(tsType: string, operators: FilterOps[]): Interfac { name: 'lessThan', type: tsType, optional: true }, { name: 'lessThanOrEqualTo', type: tsType, optional: true }, { name: 'greaterThan', type: tsType, optional: true }, - { name: 'greaterThanOrEqualTo', type: tsType, optional: true }, + { name: 'greaterThanOrEqualTo', type: tsType, optional: true } ); } @@ -97,7 +98,7 @@ function buildFilterProperties(tsType: string, operators: FilterOps[]): Interfac { name: 'like', type: 'string', optional: true }, { name: 'notLike', type: 'string', optional: true }, { name: 'likeInsensitive', type: 'string', optional: true }, - { name: 'notLikeInsensitive', type: 'string', optional: true }, + { name: 'notLikeInsensitive', type: 'string', optional: true } ); } @@ -108,7 +109,7 @@ function buildFilterProperties(tsType: string, operators: FilterOps[]): Interfac { name: 'containedBy', type: 'unknown', optional: true }, { name: 'containsKey', type: 'string', optional: true }, { name: 'containsAllKeys', type: 'string[]', optional: true }, - { name: 'containsAnyKeys', type: 'string[]', optional: true }, + { name: 'containsAnyKeys', type: 'string[]', optional: true } ); } @@ -117,7 +118,7 @@ function buildFilterProperties(tsType: string, operators: FilterOps[]): Interfac props.push( { name: 'contains', type: 'string', optional: true }, { name: 'containedBy', type: 'string', optional: true }, - { name: 'containsOrContainedBy', type: 'string', optional: true }, + { name: 'containsOrContainedBy', type: 'string', optional: true } ); } @@ -139,7 +140,7 @@ function buildFilterProperties(tsType: string, operators: FilterOps[]): Interfac { name: 'anyLessThan', type: baseType, optional: true }, { name: 'anyLessThanOrEqualTo', type: baseType, optional: true }, { name: 'anyGreaterThan', type: baseType, optional: true }, - { name: 'anyGreaterThanOrEqualTo', type: baseType, optional: true }, + { name: 'anyGreaterThanOrEqualTo', type: baseType, optional: true } ); } @@ -237,7 +238,7 @@ export function generateTypesFile( const properties: InterfaceProperty[] = scalarFields.map((field) => ({ name: field.name, - type: `${fieldTypeToTs(field.type)} | null`, + type: `${fieldTypeToTs(field.type)} | null` })); statements.push(createInterfaceDeclaration(table.name, properties)); diff --git a/graphql/codegen/src/core/codegen/utils.ts b/graphql/codegen/src/core/codegen/utils.ts index dc46b8703..859a67900 100644 --- a/graphql/codegen/src/core/codegen/utils.ts +++ b/graphql/codegen/src/core/codegen/utils.ts @@ -1,13 +1,14 @@ /** * Codegen utilities - naming conventions, type mapping, and helpers */ +import { pluralize } from 'inflekt'; + import type { - CleanTable, CleanField, CleanFieldType, + CleanTable } from '../../types/schema'; -import { scalarToTsType, scalarToFilterType } from './scalars'; -import { pluralize } from 'inflekt'; +import { scalarToFilterType,scalarToTsType } from './scalars'; // ============================================================================ // String manipulation @@ -77,7 +78,7 @@ export function getTableNames(table: CleanTable): TableNames { typeName, singularName, pluralName, - pluralTypeName, + pluralTypeName }; } @@ -360,8 +361,8 @@ export function getPrimaryKeyInfo(table: CleanTable): PrimaryKeyField[] { { name: idField.name, gqlType: idField.type.gqlType, - tsType: fieldTypeToTs(idField.type), - }, + tsType: fieldTypeToTs(idField.type) + } ]; } // Last resort: assume 'id' of type string (UUID) @@ -370,7 +371,7 @@ export function getPrimaryKeyInfo(table: CleanTable): PrimaryKeyField[] { return pk.fields.map((f) => ({ name: f.name, gqlType: f.type.gqlType, - tsType: fieldTypeToTs(f.type), + tsType: fieldTypeToTs(f.type) })); } @@ -400,6 +401,36 @@ export function hasValidPrimaryKey(table: CleanTable): boolean { return false; } +/** + * Get the best field name for a defaultSelect literal. + * Prefers PK field if valid, then 'id'/'nodeId', then first scalar field. + * Unlike getPrimaryKeyInfo(), never returns a fictional 'id' fallback. + */ +export function getDefaultSelectFieldName(table: CleanTable): string { + // 1. Try the actual primary key + const pk = table.constraints?.primaryKey?.[0]; + if (pk && pk.fields.length >= 1) { + return pk.fields[0].name; + } + // 2. Try id / nodeId fields + const idField = table.fields.find((f) => f.name === 'id' || f.name === 'nodeId'); + if (idField) { + return idField.name; + } + // 3. First non-array scalar field + const scalarField = table.fields.find( + (f) => !f.type.isArray && scalarToTsType(f.type.gqlType) !== f.type.gqlType + ); + if (scalarField) { + return scalarField.name; + } + // 4. First field of any kind + if (table.fields.length > 0) { + return table.fields[0].name; + } + return 'id'; +} + // ============================================================================ // Query key generation // ============================================================================ diff --git a/graphql/codegen/src/core/config/index.ts b/graphql/codegen/src/core/config/index.ts index 239e5581b..99dea07ad 100644 --- a/graphql/codegen/src/core/config/index.ts +++ b/graphql/codegen/src/core/config/index.ts @@ -6,12 +6,11 @@ export { CONFIG_FILENAME, findConfigFile, loadConfigFile, - type LoadConfigFileResult, + type LoadConfigFileResult } from './loader'; - export { - loadAndResolveConfig, - loadWatchConfig, type ConfigOverrideOptions, + loadAndResolveConfig, type LoadConfigResult, + loadWatchConfig } from './resolver'; diff --git a/graphql/codegen/src/core/config/loader.ts b/graphql/codegen/src/core/config/loader.ts index 2a80524c5..668b3adc9 100644 --- a/graphql/codegen/src/core/config/loader.ts +++ b/graphql/codegen/src/core/config/loader.ts @@ -6,6 +6,7 @@ */ import * as fs from 'node:fs'; import * as path from 'node:path'; + import { createJiti } from 'jiti'; export const CONFIG_FILENAME = 'graphql-codegen.config.ts'; @@ -55,7 +56,7 @@ export async function loadConfigFile( if (!fs.existsSync(resolvedPath)) { return { success: false, - error: `Config file not found: ${resolvedPath}`, + error: `Config file not found: ${resolvedPath}` }; } @@ -64,7 +65,7 @@ export async function loadConfigFile( // jiti handles .ts, .js, .mjs, .cjs and ESM/CJS interop const jiti = createJiti(__filename, { interopDefault: true, - debug: process.env.JITI_DEBUG === '1', + debug: process.env.JITI_DEBUG === '1' }); // jiti.import() with { default: true } returns mod?.default ?? mod @@ -73,19 +74,19 @@ export async function loadConfigFile( if (!config || typeof config !== 'object') { return { success: false, - error: 'Config file must export a configuration object', + error: 'Config file must export a configuration object' }; } return { success: true, - config, + config }; } catch (err) { const message = err instanceof Error ? err.message : 'Unknown error'; return { success: false, - error: `Failed to load config file: ${message}`, + 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 index 56c551e3b..aa71fe60b 100644 --- a/graphql/codegen/src/core/config/resolver.ts +++ b/graphql/codegen/src/core/config/resolver.ts @@ -6,9 +6,9 @@ */ import type { GraphQLSDKConfig, - GraphQLSDKConfigTarget, + GraphQLSDKConfigTarget } from '../../types/config'; -import { mergeConfig, getConfigOptions } from '../../types/config'; +import { getConfigOptions,mergeConfig } from '../../types/config'; import { findConfigFile, loadConfigFile } from './loader'; /** @@ -47,13 +47,13 @@ export async function loadAndResolveConfig( const sources = [ overrides.endpoint, overrides.schemaFile, - overrides.db, + overrides.db ].filter(Boolean); if (sources.length > 1) { return { success: false, error: - 'Multiple sources specified. Use only one of: endpoint, schemaFile, or db.', + 'Multiple sources specified. Use only one of: endpoint, schemaFile, or db.' }; } @@ -85,13 +85,13 @@ export async function loadAndResolveConfig( return { success: false, error: - 'No source specified. Use --endpoint, --schema-file, or --db, 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".' }; } return { success: true, - config: getConfigOptions(mergedConfig), + config: getConfigOptions(mergedConfig) }; } @@ -134,12 +134,12 @@ export async function loadWatchConfig(options: { const watchOverrides: GraphQLSDKConfigTarget = { watch: { ...(options.pollInterval !== undefined && { - pollInterval: options.pollInterval, + pollInterval: options.pollInterval }), ...(options.debounce !== undefined && { debounce: options.debounce }), ...(options.touch !== undefined && { touchFile: options.touch }), - ...(options.clear !== undefined && { clearScreen: options.clear }), - }, + ...(options.clear !== undefined && { clearScreen: options.clear }) + } }; let mergedConfig = mergeConfig(baseConfig, sourceOverrides); diff --git a/graphql/codegen/src/core/custom-ast.ts b/graphql/codegen/src/core/custom-ast.ts index 5d9a1428e..02ea4642b 100644 --- a/graphql/codegen/src/core/custom-ast.ts +++ b/graphql/codegen/src/core/custom-ast.ts @@ -22,7 +22,7 @@ export function getCustomAst(fieldDefn?: MetaField): FieldNode | null { } return t.field({ - name: fieldDefn.name, + name: fieldDefn.name }); } @@ -57,7 +57,7 @@ export function getCustomAstForCleanField(field: CleanField): FieldNode { // Return simple field for scalar types return t.field({ - name, + name }); } @@ -72,7 +72,7 @@ export function requiresSubfieldSelection(field: CleanField): boolean { 'GeometryPoint', 'Interval', 'GeometryGeometryCollection', - 'GeoJSON', + 'GeoJSON' ]; return complexTypes.includes(gqlType); @@ -85,8 +85,8 @@ export function geometryPointAst(name: string): FieldNode { return t.field({ name, selectionSet: t.selectionSet({ - selections: toFieldArray(['x', 'y']), - }), + selections: toFieldArray(['x', 'y']) + }) }); } @@ -101,8 +101,8 @@ export function geometryCollectionAst(name: string): FieldNode { kind: 'NamedType', name: { kind: 'Name', - value: 'GeometryPoint', - }, + value: 'GeometryPoint' + } }, selectionSet: { kind: 'SelectionSet', @@ -111,18 +111,18 @@ export function geometryCollectionAst(name: string): FieldNode { kind: 'Field', name: { kind: 'Name', - value: 'x', - }, + value: 'x' + } }, { kind: 'Field', name: { kind: 'Name', - value: 'y', - }, - }, - ], - }, + value: 'y' + } + } + ] + } }; return t.field({ @@ -133,11 +133,11 @@ export function geometryCollectionAst(name: string): FieldNode { name: 'geometries', selectionSet: t.selectionSet({ // eslint-disable-next-line @typescript-eslint/no-explicit-any - selections: [inlineFragment as any], // gql-ast limitation with inline fragments - }), - }), - ], - }), + selections: [inlineFragment as any] // gql-ast limitation with inline fragments + }) + }) + ] + }) }); } @@ -148,8 +148,8 @@ export function geometryAst(name: string): FieldNode { return t.field({ name, selectionSet: t.selectionSet({ - selections: toFieldArray(['geojson']), - }), + selections: toFieldArray(['geojson']) + }) }); } @@ -166,9 +166,9 @@ export function intervalAst(name: string): FieldNode { 'minutes', 'months', 'seconds', - 'years', - ]), - }), + 'years' + ]) + }) }); } diff --git a/graphql/codegen/src/core/database/index.ts b/graphql/codegen/src/core/database/index.ts index 74c41cb03..0ca12ff14 100644 --- a/graphql/codegen/src/core/database/index.ts +++ b/graphql/codegen/src/core/database/index.ts @@ -6,6 +6,7 @@ import * as fs from 'node:fs'; import * as path from 'node:path'; + import { buildSchemaSDL } from '@constructive-io/graphql-server'; export interface BuildSchemaFromDatabaseOptions { @@ -47,7 +48,7 @@ export async function buildSchemaFromDatabase( const sdl = await buildSchemaSDL({ database, schemas, - graphile: { pgSettings: async () => ({ role: 'administrator' }) }, + graphile: { pgSettings: async () => ({ role: 'administrator' }) } }); // Write schema to file @@ -74,6 +75,6 @@ export async function buildSchemaSDLFromDatabase(options: { return buildSchemaSDL({ database, schemas, - graphile: { pgSettings: async () => ({ role: 'administrator' }) }, + graphile: { pgSettings: async () => ({ role: 'administrator' }) } }); } diff --git a/graphql/codegen/src/core/generate.ts b/graphql/codegen/src/core/generate.ts index 51e679a2d..e73b34edc 100644 --- a/graphql/codegen/src/core/generate.ts +++ b/graphql/codegen/src/core/generate.ts @@ -6,15 +6,15 @@ */ import path from 'path'; -import { createSchemaSource, validateSourceOptions } from './introspect'; -import { runCodegenPipeline, validateTablesFound } from './pipeline'; +import type { GraphQLSDKConfigTarget } from '../types/config'; +import { getConfigOptions } from '../types/config'; import { generate as generateReactQueryFiles } from './codegen'; import { generateRootBarrel } from './codegen/barrel'; import { generateOrm as generateOrmFiles } from './codegen/orm'; import { generateSharedTypes } from './codegen/shared'; +import { createSchemaSource, validateSourceOptions } from './introspect'; import { writeGeneratedFiles } from './output'; -import type { GraphQLSDKConfigTarget } from '../types/config'; -import { getConfigOptions } from '../types/config'; +import { runCodegenPipeline, validateTablesFound } from './pipeline'; export interface GenerateOptions extends GraphQLSDKConfigTarget { authorization?: string; @@ -44,14 +44,16 @@ export async function generate(options: GenerateOptions = {}): Promise t.name), - filesWritten: allFilesWritten, + filesWritten: allFilesWritten }; } diff --git a/graphql/codegen/src/core/index.ts b/graphql/codegen/src/core/index.ts index 5dbf3eb23..86a01af13 100644 --- a/graphql/codegen/src/core/index.ts +++ b/graphql/codegen/src/core/index.ts @@ -6,8 +6,8 @@ */ // Main generate function (orchestrates the entire pipeline) -export { generate } from './generate'; export type { GenerateOptions, GenerateResult } from './generate'; +export { generate } from './generate'; // Types export * from './types'; @@ -17,10 +17,10 @@ export * from './ast'; export * from './custom-ast'; // Query builder -export { QueryBuilder, MetaObject } from './query-builder'; +export { MetaObject,QueryBuilder } from './query-builder'; // Meta object utilities -export { validateMetaObject, convertFromMetaSchema } from './meta-object'; +export { convertFromMetaSchema,validateMetaObject } from './meta-object'; // Configuration loading and resolution export * from './config'; diff --git a/graphql/codegen/src/core/introspect/fetch-schema.ts b/graphql/codegen/src/core/introspect/fetch-schema.ts index 81cd7b5bb..7cd561125 100644 --- a/graphql/codegen/src/core/introspect/fetch-schema.ts +++ b/graphql/codegen/src/core/introspect/fetch-schema.ts @@ -4,8 +4,9 @@ */ import http from 'node:http'; import https from 'node:https'; -import { SCHEMA_INTROSPECTION_QUERY } from './schema-query'; + import type { IntrospectionQueryResponse } from '../../types/introspection'; +import { SCHEMA_INTROSPECTION_QUERY } from './schema-query'; interface HttpResponse { statusCode: number; @@ -35,7 +36,7 @@ function makeRequest( resolve({ statusCode: res.statusCode || 0, statusMessage: res.statusMessage || '', - data, + data }); }); }); @@ -83,7 +84,7 @@ export async function fetchSchema( const requestHeaders: Record = { 'Content-Type': 'application/json', Accept: 'application/json', - ...headers, + ...headers }; if (authorization) { @@ -92,12 +93,12 @@ export async function fetchSchema( const body = JSON.stringify({ query: SCHEMA_INTROSPECTION_QUERY, - variables: {}, + variables: {} }); const requestOptions: http.RequestOptions = { method: 'POST', - headers: requestHeaders, + headers: requestHeaders }; try { @@ -107,7 +108,7 @@ export async function fetchSchema( return { success: false, error: `HTTP ${response.statusCode}: ${response.statusMessage}`, - statusCode: response.statusCode, + statusCode: response.statusCode }; } @@ -121,7 +122,7 @@ export async function fetchSchema( return { success: false, error: `GraphQL errors: ${errorMessages}`, - statusCode: response.statusCode, + statusCode: response.statusCode }; } @@ -130,21 +131,21 @@ export async function fetchSchema( success: false, error: 'No __schema field in response. Introspection may be disabled on this endpoint.', - statusCode: response.statusCode, + statusCode: response.statusCode }; } return { success: true, data: json.data, - statusCode: response.statusCode, + statusCode: response.statusCode }; } catch (err) { if (err instanceof Error) { if (err.message.includes('timeout')) { return { success: false, - error: `Request timeout after ${timeout}ms`, + error: `Request timeout after ${timeout}ms` }; } @@ -152,31 +153,31 @@ export async function fetchSchema( if (errorCode === 'ECONNREFUSED') { return { success: false, - error: `Connection refused - is the server running at ${endpoint}?`, + error: `Connection refused - is the server running at ${endpoint}?` }; } if (errorCode === 'ENOTFOUND') { return { success: false, - error: `DNS lookup failed for ${url.hostname} - check the endpoint URL`, + error: `DNS lookup failed for ${url.hostname} - check the endpoint URL` }; } if (errorCode === 'ECONNRESET') { return { success: false, - error: `Connection reset by server at ${endpoint}`, + error: `Connection reset by server at ${endpoint}` }; } return { success: false, - error: err.message, + error: err.message }; } return { success: false, - error: 'Unknown error occurred', + error: 'Unknown error occurred' }; } } diff --git a/graphql/codegen/src/core/introspect/index.ts b/graphql/codegen/src/core/introspect/index.ts index baaf7ebc2..5ddf28346 100644 --- a/graphql/codegen/src/core/introspect/index.ts +++ b/graphql/codegen/src/core/introspect/index.ts @@ -3,29 +3,29 @@ */ // Table inference from introspection -export { inferTablesFromIntrospection } from './infer-tables'; export type { InferTablesOptions } from './infer-tables'; +export { inferTablesFromIntrospection } from './infer-tables'; // Pluralization utilities (from inflekt) -export { singularize, pluralize } from 'inflekt'; +export { pluralize,singularize } from 'inflekt'; // Schema sources +export type { + CreateSchemaSourceOptions, + SchemaSource, + SchemaSourceResult +} from './source'; export { createSchemaSource, - validateSourceOptions, EndpointSchemaSource, FileSchemaSource, SchemaSourceError, -} from './source'; -export type { - SchemaSource, - SchemaSourceResult, - CreateSchemaSourceOptions, + validateSourceOptions } from './source'; // Schema fetching (still used by watch mode) -export { fetchSchema } from './fetch-schema'; export type { FetchSchemaOptions, FetchSchemaResult } from './fetch-schema'; +export { fetchSchema } from './fetch-schema'; // Transform utilities (only filterTables, getTableNames, findTable are still useful) -export { getTableNames, findTable, filterTables } from './transform'; +export { filterTables,findTable, getTableNames } from './transform'; diff --git a/graphql/codegen/src/core/introspect/infer-tables.ts b/graphql/codegen/src/core/introspect/infer-tables.ts index 9f5ab631a..ef53092be 100644 --- a/graphql/codegen/src/core/introspect/infer-tables.ts +++ b/graphql/codegen/src/core/introspect/infer-tables.ts @@ -12,27 +12,28 @@ * - Query operations: {pluralName} (list), {singularName} (single) * - Mutation operations: create{Name}, update{Name}, delete{Name} */ +import { lcFirst, pluralize, singularize, ucFirst } from 'inflekt'; + import type { + IntrospectionField, IntrospectionQueryResponse, IntrospectionType, - IntrospectionField, - IntrospectionTypeRef, + IntrospectionTypeRef } from '../../types/introspection'; -import { unwrapType, getBaseTypeName, isList } from '../../types/introspection'; +import { getBaseTypeName, isList,unwrapType } from '../../types/introspection'; import type { - CleanTable, + CleanBelongsToRelation, CleanField, CleanFieldType, - CleanRelations, - CleanBelongsToRelation, CleanHasManyRelation, CleanManyToManyRelation, - TableInflection, - TableQueryNames, - TableConstraints, + CleanRelations, + CleanTable, ConstraintInfo, + TableConstraints, + TableInflection, + TableQueryNames } from '../../types/schema'; -import { singularize, pluralize, lcFirst, ucFirst } from 'inflekt'; // ============================================================================ // Pattern Matching Constants @@ -63,7 +64,7 @@ const PATTERNS = { // Mutation name patterns (camelCase) createMutation: /^create([A-Z][a-zA-Z0-9]*)$/, updateMutation: /^update([A-Z][a-zA-Z0-9]*)$/, - deleteMutation: /^delete([A-Z][a-zA-Z0-9]*)$/, + deleteMutation: /^delete([A-Z][a-zA-Z0-9]*)$/ }; /** @@ -88,7 +89,7 @@ const BUILTIN_TYPES = new Set([ 'Time', 'JSON', 'BigInt', - 'BigFloat', + 'BigFloat' ]); /** @@ -244,7 +245,7 @@ function buildCleanTable( one: queryOps.one ?? lcFirst(entityName), create: mutationOps.create ?? `create${entityName}`, update: mutationOps.update, - delete: mutationOps.delete, + delete: mutationOps.delete }; return { @@ -254,9 +255,9 @@ function buildCleanTable( relations, inflection, query, - constraints, + constraints }, - hasRealOperation, + hasRealOperation }; } @@ -295,7 +296,7 @@ function extractEntityFields( // Include scalar, enum, and other non-relation fields fields.push({ name: field.name, - type: convertToCleanFieldType(field.type), + type: convertToCleanFieldType(field.type) }); } @@ -324,7 +325,7 @@ function convertToCleanFieldType( return { gqlType: baseType.name ?? 'Unknown', - isArray, + isArray // PostgreSQL-specific fields are not available from introspection // They were optional anyway and not used by generators }; @@ -371,7 +372,7 @@ function inferRelations( isUnique: false, // Can't determine from introspection alone referencesTable: baseTypeName, type: baseTypeName, - keys: [], // Would need FK info to populate + keys: [] // Would need FK info to populate }); } } @@ -425,8 +426,8 @@ function inferHasManyOrManyToMany( fieldName: field.name, rightTable: actualEntityName, junctionTable, - type: connectionTypeName, - }, + type: connectionTypeName + } }; } @@ -437,8 +438,8 @@ function inferHasManyOrManyToMany( isUnique: false, referencedByTable: relatedEntityName, type: connectionTypeName, - keys: [], - }, + keys: [] + } }; } @@ -596,9 +597,9 @@ function inferConstraints( fields: [ { name: idField.name, - type: convertToCleanFieldType(idField.type), - }, - ], + type: convertToCleanFieldType(idField.type) + } + ] }); } } @@ -617,9 +618,9 @@ function inferConstraints( fields: [ { name: idField.name, - type: convertToCleanFieldType(idField.type), - }, - ], + type: convertToCleanFieldType(idField.type) + } + ] }); } } @@ -628,7 +629,7 @@ function inferConstraints( return { primaryKey, foreignKey: [], // Would need FK info to populate - unique: [], // Would need constraint info to populate + unique: [] // Would need constraint info to populate }; } @@ -681,7 +682,7 @@ function buildInflection( tableType: entityName, typeName: entityName, updateByPrimaryKey: `update${entityName}`, - updatePayloadType: hasUpdatePayload ? `Update${entityName}Payload` : null, + updatePayloadType: hasUpdatePayload ? `Update${entityName}Payload` : null }; } @@ -710,7 +711,7 @@ function findOrderByType( const candidates = [ `${entityName}sOrderBy`, // Simple 's' plural: User -> UsersOrderBy `${entityName}esOrderBy`, // 'es' plural: Address -> AddressesOrderBy - `${entityName}OrderBy`, // No change (already plural or singular OK) + `${entityName}OrderBy` // No change (already plural or singular OK) ]; // Check each candidate diff --git a/graphql/codegen/src/core/introspect/source/api-schemas.ts b/graphql/codegen/src/core/introspect/source/api-schemas.ts index 4ff79229f..4b81f5280 100644 --- a/graphql/codegen/src/core/introspect/source/api-schemas.ts +++ b/graphql/codegen/src/core/introspect/source/api-schemas.ts @@ -39,7 +39,7 @@ export async function validateServicesSchemas( if (apisCheck.rows.length === 0) { return { valid: false, - error: 'services_public.apis table not found. The database must have the services schema deployed.', + error: 'services_public.apis table not found. The database must have the services schema deployed.' }; } @@ -52,7 +52,7 @@ export async function validateServicesSchemas( if (apiSchemasCheck.rows.length === 0) { return { valid: false, - error: 'services_public.api_schemas table not found. The database must have the services schema deployed.', + error: 'services_public.api_schemas table not found. The database must have the services schema deployed.' }; } @@ -65,7 +65,7 @@ export async function validateServicesSchemas( if (metaschemaCheck.rows.length === 0) { return { valid: false, - error: 'metaschema_public.schema table not found. The database must have the metaschema deployed.', + error: 'metaschema_public.schema table not found. The database must have the metaschema deployed.' }; } @@ -73,7 +73,7 @@ export async function validateServicesSchemas( } catch (err) { return { valid: false, - error: `Failed to validate services schemas: ${err instanceof Error ? err.message : 'Unknown error'}`, + error: `Failed to validate services schemas: ${err instanceof Error ? err.message : 'Unknown error'}` }; } } @@ -142,7 +142,7 @@ export function createDatabasePool(database: string): Pool { port: parseInt(url.port || '5432', 10), user: url.username, password: url.password, - database: dbName, + database: dbName }); } diff --git a/graphql/codegen/src/core/introspect/source/database.ts b/graphql/codegen/src/core/introspect/source/database.ts index 4b77ea12e..55dfb0355 100644 --- a/graphql/codegen/src/core/introspect/source/database.ts +++ b/graphql/codegen/src/core/introspect/source/database.ts @@ -5,11 +5,12 @@ * 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'; import { createDatabasePool, resolveApiSchemas, validateServicesSchemas } from './api-schemas'; +import type { SchemaSource, SchemaSourceResult } from './types'; +import { SchemaSourceError } from './types'; export interface DatabaseSchemaSourceOptions { /** @@ -77,7 +78,7 @@ export class DatabaseSchemaSource implements SchemaSource { try { sdl = await buildSchemaSDLFromDatabase({ database, - schemas, + schemas }); } catch (err) { throw new SchemaSourceError( diff --git a/graphql/codegen/src/core/introspect/source/endpoint.ts b/graphql/codegen/src/core/introspect/source/endpoint.ts index a5c50ff84..20ec8d931 100644 --- a/graphql/codegen/src/core/introspect/source/endpoint.ts +++ b/graphql/codegen/src/core/introspect/source/endpoint.ts @@ -4,9 +4,9 @@ * Fetches GraphQL schema via introspection from a live endpoint. * Wraps the existing fetchSchema() function with the SchemaSource interface. */ +import { fetchSchema } from '../fetch-schema'; import type { SchemaSource, SchemaSourceResult } from './types'; import { SchemaSourceError } from './types'; -import { fetchSchema } from '../fetch-schema'; export interface EndpointSchemaSourceOptions { /** @@ -45,7 +45,7 @@ export class EndpointSchemaSource implements SchemaSource { endpoint: this.options.endpoint, authorization: this.options.authorization, headers: this.options.headers, - timeout: this.options.timeout, + timeout: this.options.timeout }); if (!result.success) { @@ -63,7 +63,7 @@ export class EndpointSchemaSource implements SchemaSource { } return { - introspection: result.data, + introspection: result.data }; } diff --git a/graphql/codegen/src/core/introspect/source/file.ts b/graphql/codegen/src/core/introspect/source/file.ts index 6ab828aac..58ffe6b33 100644 --- a/graphql/codegen/src/core/introspect/source/file.ts +++ b/graphql/codegen/src/core/introspect/source/file.ts @@ -6,10 +6,12 @@ */ import * as fs from 'node:fs'; import * as path from 'node:path'; + import { buildSchema, introspectionFromSchema } from 'graphql'; + +import type { IntrospectionQueryResponse } from '../../../types/introspection'; import type { SchemaSource, SchemaSourceResult } from './types'; import { SchemaSourceError } from './types'; -import type { IntrospectionQueryResponse } from '../../../types/introspection'; export interface FileSchemaSourceOptions { /** diff --git a/graphql/codegen/src/core/introspect/source/index.ts b/graphql/codegen/src/core/introspect/source/index.ts index 9642201c0..c96b498be 100644 --- a/graphql/codegen/src/core/introspect/source/index.ts +++ b/graphql/codegen/src/core/introspect/source/index.ts @@ -7,23 +7,21 @@ * - PostgreSQL databases (via PostGraphile introspection) * - PGPM modules (via ephemeral database deployment) */ -export * from './types'; +export * from './api-schemas'; +export * from './database'; export * from './endpoint'; export * from './file'; -export * from './database'; export * from './pgpm-module'; -export * from './api-schemas'; +export * from './types'; -import type { SchemaSource } from './types'; -import type { DbConfig, PgpmConfig } from '../../../types/config'; +import type { DbConfig } from '../../../types/config'; +import { DatabaseSchemaSource } from './database'; import { EndpointSchemaSource } from './endpoint'; import { FileSchemaSource } from './file'; -import { DatabaseSchemaSource } from './database'; import { - PgpmModuleSchemaSource, - isPgpmModulePathOptions, - isPgpmWorkspaceOptions, + PgpmModuleSchemaSource } from './pgpm-module'; +import type { SchemaSource } from './types'; /** * Options for endpoint-based schema source @@ -142,49 +140,49 @@ export function createSchemaSource( const mode = detectSourceMode(options); switch (mode) { - case 'schemaFile': - return new FileSchemaSource({ - schemaPath: options.schemaFile!, - }); + case 'schemaFile': + return new FileSchemaSource({ + schemaPath: options.schemaFile! + }); - case 'endpoint': - return new EndpointSchemaSource({ - endpoint: options.endpoint!, - authorization: options.authorization, - headers: options.headers, - timeout: options.timeout, - }); + case 'endpoint': + return new EndpointSchemaSource({ + endpoint: options.endpoint!, + authorization: options.authorization, + headers: options.headers, + timeout: options.timeout + }); - 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.db?.config?.database ?? '', - schemas: options.db?.schemas, - apiNames: options.db?.apiNames, - }); + 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.db?.config?.database ?? '', + schemas: options.db?.schemas, + apiNames: options.db?.apiNames + }); - case 'pgpm-module': - return new PgpmModuleSchemaSource({ - pgpmModulePath: options.db!.pgpm!.modulePath!, - schemas: options.db?.schemas, - apiNames: options.db?.apiNames, - keepDb: options.db?.keepDb, - }); + case 'pgpm-module': + return new PgpmModuleSchemaSource({ + 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.db!.pgpm!.workspacePath!, - pgpmModuleName: options.db!.pgpm!.moduleName!, - schemas: options.db?.schemas, - apiNames: options.db?.apiNames, - keepDb: options.db?.keepDb, - }); + case 'pgpm-workspace': + return new PgpmModuleSchemaSource({ + 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, schemaFile, or db (with optional pgpm for module deployment).' - ); + default: + throw new Error( + 'No source specified. Use one of: endpoint, schemaFile, or db (with optional pgpm for module deployment).' + ); } } @@ -199,14 +197,14 @@ export function validateSourceOptions(options: CreateSchemaSourceOptions): { const sources = [ options.endpoint, options.schemaFile, - options.db, + options.db ].filter(Boolean); if (sources.length === 0) { return { valid: false, error: - 'No source specified. Use one of: endpoint, schemaFile, or db.', + 'No source specified. Use one of: endpoint, schemaFile, or db.' }; } @@ -214,7 +212,7 @@ export function validateSourceOptions(options: CreateSchemaSourceOptions): { return { valid: false, error: - 'Multiple sources specified. Use only one of: endpoint, schemaFile, or db.', + 'Multiple sources specified. Use only one of: endpoint, schemaFile, or db.' }; } @@ -224,14 +222,14 @@ export function validateSourceOptions(options: CreateSchemaSourceOptions): { if (pgpm.workspacePath && !pgpm.moduleName) { return { valid: false, - error: 'db.pgpm.workspacePath requires db.pgpm.moduleName to be specified.', + error: 'db.pgpm.workspacePath requires db.pgpm.moduleName to be specified.' }; } if (pgpm.moduleName && !pgpm.workspacePath) { return { valid: false, - error: 'db.pgpm.moduleName requires db.pgpm.workspacePath to be specified.', + error: 'db.pgpm.moduleName requires db.pgpm.workspacePath to be specified.' }; } @@ -239,7 +237,7 @@ export function validateSourceOptions(options: CreateSchemaSourceOptions): { if (!pgpm.modulePath && !(pgpm.workspacePath && pgpm.moduleName)) { return { valid: false, - error: 'db.pgpm requires either modulePath or both workspacePath and moduleName.', + error: 'db.pgpm requires either modulePath or both workspacePath and moduleName.' }; } } @@ -252,14 +250,14 @@ export function validateSourceOptions(options: CreateSchemaSourceOptions): { if (hasSchemas && hasApiNames) { return { valid: false, - error: 'Cannot specify both db.schemas and db.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 db.schemas or db.apiNames for database mode.', + error: 'Must specify either db.schemas or db.apiNames for database mode.' }; } } diff --git a/graphql/codegen/src/core/introspect/source/pgpm-module.ts b/graphql/codegen/src/core/introspect/source/pgpm-module.ts index a246d769f..4bbc7e14e 100644 --- a/graphql/codegen/src/core/introspect/source/pgpm-module.ts +++ b/graphql/codegen/src/core/introspect/source/pgpm-module.ts @@ -7,17 +7,17 @@ * 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 { buildSchema, introspectionFromSchema } from 'graphql'; +import { getPgPool } from 'pg-cache'; 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'; +import type { SchemaSource, SchemaSourceResult } from './types'; +import { SchemaSourceError } from './types'; /** * Options for PGPM module schema source using direct module path @@ -147,7 +147,7 @@ export class PgpmModuleSchemaSource implements SchemaSource { try { this.ephemeralDb = createEphemeralDb({ prefix: 'codegen_pgpm_', - verbose: false, + verbose: false }); } catch (err) { throw new SchemaSourceError( @@ -199,7 +199,7 @@ export class PgpmModuleSchemaSource implements SchemaSource { try { sdl = await buildSchemaSDLFromDatabase({ database: dbConfig.database, - schemas, + schemas }); } catch (err) { throw new SchemaSourceError( diff --git a/graphql/codegen/src/core/introspect/transform-schema.ts b/graphql/codegen/src/core/introspect/transform-schema.ts index 40cc4aa9f..a7edd5216 100644 --- a/graphql/codegen/src/core/introspect/transform-schema.ts +++ b/graphql/codegen/src/core/introspect/transform-schema.ts @@ -5,24 +5,24 @@ * format used by code generators. */ import type { - IntrospectionQueryResponse, - IntrospectionType, IntrospectionField, - IntrospectionTypeRef, IntrospectionInputValue, + IntrospectionQueryResponse, + IntrospectionType, + IntrospectionTypeRef } from '../../types/introspection'; import { - unwrapType, getBaseTypeName, isNonNull, + unwrapType } from '../../types/introspection'; import type { - CleanOperation, CleanArgument, - CleanTypeRef, CleanObjectField, - TypeRegistry, + CleanOperation, + CleanTypeRef, ResolvedType, + TypeRegistry } from '../../types/schema'; // ============================================================================ @@ -48,7 +48,7 @@ export function buildTypeRegistry(types: IntrospectionType[]): TypeRegistry { const resolvedType: ResolvedType = { kind: type.kind as ResolvedType['kind'], name: type.name, - description: type.description ?? undefined, + description: type.description ?? undefined }; // Resolve enum values for ENUM types (no circular refs possible) @@ -99,7 +99,7 @@ function transformFieldToCleanObjectFieldShallow( return { name: field.name, type: transformTypeRefShallow(field.type), - description: field.description ?? undefined, + description: field.description ?? undefined }; } @@ -113,7 +113,7 @@ function transformInputValueToCleanArgumentShallow( name: inputValue.name, type: transformTypeRefShallow(inputValue.type), defaultValue: inputValue.defaultValue ?? undefined, - description: inputValue.description ?? undefined, + description: inputValue.description ?? undefined }; } @@ -124,7 +124,7 @@ function transformInputValueToCleanArgumentShallow( function transformTypeRefShallow(typeRef: IntrospectionTypeRef): CleanTypeRef { const cleanRef: CleanTypeRef = { kind: typeRef.kind as CleanTypeRef['kind'], - name: typeRef.name, + name: typeRef.name }; if (typeRef.ofType) { @@ -165,15 +165,15 @@ export function transformSchemaToOperations( // Transform queries const queries: CleanOperation[] = queryTypeDef?.fields ? queryTypeDef.fields.map((field) => - transformFieldToCleanOperation(field, 'query', types) - ) + transformFieldToCleanOperation(field, 'query', types) + ) : []; // Transform mutations const mutations: CleanOperation[] = mutationTypeDef?.fields ? mutationTypeDef.fields.map((field) => - transformFieldToCleanOperation(field, 'mutation', types) - ) + transformFieldToCleanOperation(field, 'mutation', types) + ) : []; return { queries, mutations, typeRegistry }; @@ -200,7 +200,7 @@ function transformFieldToCleanOperation( returnType: transformTypeRefToCleanTypeRef(field.type, types), description: field.description ?? undefined, isDeprecated: field.isDeprecated, - deprecationReason: field.deprecationReason ?? undefined, + deprecationReason: field.deprecationReason ?? undefined }; } @@ -215,7 +215,7 @@ function transformInputValueToCleanArgument( name: inputValue.name, type: transformTypeRefToCleanTypeRef(inputValue.type, types), defaultValue: inputValue.defaultValue ?? undefined, - description: inputValue.description ?? undefined, + description: inputValue.description ?? undefined }; } @@ -237,7 +237,7 @@ function transformTypeRefToCleanTypeRef( ): CleanTypeRef { const cleanRef: CleanTypeRef = { kind: typeRef.kind as CleanTypeRef['kind'], - name: typeRef.name, + name: typeRef.name }; // Recursively transform ofType for wrappers (LIST, NON_NULL) @@ -400,4 +400,4 @@ export function getCustomOperations( } // Re-export utility functions from introspection types -export { unwrapType, getBaseTypeName, isNonNull }; +export { getBaseTypeName, isNonNull,unwrapType }; diff --git a/graphql/codegen/src/core/meta-object/convert.ts b/graphql/codegen/src/core/meta-object/convert.ts index 02bff2fe4..295ae7841 100644 --- a/graphql/codegen/src/core/meta-object/convert.ts +++ b/graphql/codegen/src/core/meta-object/convert.ts @@ -78,11 +78,11 @@ export function convertFromMetaSchema( metaSchema: MetaSchemaInput ): ConvertedMetaObject { const { - _meta: { tables }, + _meta: { tables } } = metaSchema; const result: ConvertedMetaObject = { - tables: [], + tables: [] }; for (const table of tables) { @@ -94,7 +94,7 @@ export function convertFromMetaSchema( foreignConstraints: pickForeignConstraint( table.foreignKeyConstraints, table.relations - ), + ) }); } @@ -136,7 +136,7 @@ function pickForeignConstraint( return { refTable: refTable.name, fromKey, - toKey, + toKey }; }); } @@ -144,13 +144,13 @@ function pickForeignConstraint( function pickField(field: MetaSchemaField): ConvertedField { return { name: field.name, - type: field.type, + type: field.type }; } function pickConstraintField(field: MetaSchemaField): ConvertedConstraint { return { name: field.name, - type: field.type, + type: field.type }; } diff --git a/graphql/codegen/src/core/meta-object/validate.ts b/graphql/codegen/src/core/meta-object/validate.ts index 1481e6b5d..eab7a346b 100644 --- a/graphql/codegen/src/core/meta-object/validate.ts +++ b/graphql/codegen/src/core/meta-object/validate.ts @@ -18,7 +18,7 @@ function getValidator() { return { ajv: cachedAjv, - validator: cachedValidator!, + validator: cachedValidator! }; } @@ -36,6 +36,6 @@ export function validateMetaObject( return { errors: validator.errors, - message: ajv.errorsText(validator.errors, { separator: '\n' }), + message: ajv.errorsText(validator.errors, { separator: '\n' }) }; } diff --git a/graphql/codegen/src/core/output/index.ts b/graphql/codegen/src/core/output/index.ts index 3d6344d9c..529f10e41 100644 --- a/graphql/codegen/src/core/output/index.ts +++ b/graphql/codegen/src/core/output/index.ts @@ -3,9 +3,9 @@ */ export { - writeGeneratedFiles, formatOutput, type GeneratedFile, - type WriteResult, + writeGeneratedFiles, type WriteOptions, + type WriteResult } from './writer'; diff --git a/graphql/codegen/src/core/output/writer.ts b/graphql/codegen/src/core/output/writer.ts index 6db930669..8b04f1613 100644 --- a/graphql/codegen/src/core/output/writer.ts +++ b/graphql/codegen/src/core/output/writer.ts @@ -62,7 +62,7 @@ async function formatFileContent( singleQuote: true, trailingComma: 'es5', tabWidth: 2, - semi: true, + semi: true }); return result.code; } catch { @@ -98,7 +98,7 @@ export async function writeGeneratedFiles( const message = err instanceof Error ? err.message : 'Unknown error'; return { success: false, - errors: [`Failed to create output directory: ${message}`], + errors: [`Failed to create output directory: ${message}`] }; } @@ -171,7 +171,7 @@ export async function writeGeneratedFiles( return { success: errors.length === 0, filesWritten: written, - errors: errors.length > 0 ? errors : undefined, + errors: errors.length > 0 ? errors : undefined }; } @@ -211,7 +211,7 @@ export async function formatOutput( if (!formatFn) { return { success: false, - error: 'oxfmt not available. Install it with: npm install oxfmt', + error: 'oxfmt not available. Install it with: npm install oxfmt' }; } diff --git a/graphql/codegen/src/core/pipeline/index.ts b/graphql/codegen/src/core/pipeline/index.ts index 65aba4e21..f2d33456d 100644 --- a/graphql/codegen/src/core/pipeline/index.ts +++ b/graphql/codegen/src/core/pipeline/index.ts @@ -10,18 +10,18 @@ */ import type { GraphQLSDKConfigTarget } from '../../types/config'; import type { - CleanTable, CleanOperation, - TypeRegistry, + CleanTable, + TypeRegistry } from '../../types/schema'; -import type { SchemaSource } from '../introspect/source'; import { inferTablesFromIntrospection } from '../introspect/infer-tables'; +import type { SchemaSource } from '../introspect/source'; import { filterTables } from '../introspect/transform'; import { - transformSchemaToOperations, filterOperations, - getTableOperationNames, getCustomOperations, + getTableOperationNames, + transformSchemaToOperations } from '../introspect/transform-schema'; // Re-export for convenience @@ -103,7 +103,7 @@ export async function runCodegenPipeline( source, config, verbose = false, - skipCustomOperations = false, + skipCustomOperations = false } = options; const log = verbose ? console.log : () => {}; @@ -120,7 +120,7 @@ export async function runCodegenPipeline( // 3. Filter tables by config (combine exclude and systemExclude) tables = filterTables(tables, config.tables.include, [ ...config.tables.exclude, - ...config.tables.systemExclude, + ...config.tables.systemExclude ]); const filteredTables = tables.length; log(` After filtering: ${filteredTables} tables`); @@ -130,7 +130,7 @@ export async function runCodegenPipeline( const { queries: allQueries, mutations: allMutations, - typeRegistry, + typeRegistry } = transformSchemaToOperations(introspection); const totalQueries = allQueries.length; @@ -178,7 +178,7 @@ export async function runCodegenPipeline( customOperations: { queries: customQueries, mutations: customMutations, - typeRegistry, + typeRegistry }, stats: { totalTables, @@ -186,8 +186,8 @@ export async function runCodegenPipeline( totalQueries, totalMutations, customQueries: customQueries.length, - customMutations: customMutations.length, - }, + customMutations: customMutations.length + } }; } @@ -206,7 +206,7 @@ export function validateTablesFound(tables: CleanTable[]): { return { valid: false, error: - 'No tables found after filtering. Check your include/exclude patterns.', + 'No tables found after filtering. Check your include/exclude patterns.' }; } return { valid: true }; diff --git a/graphql/codegen/src/core/query-builder.ts b/graphql/codegen/src/core/query-builder.ts index 8be4db4ca..403ed2e3b 100644 --- a/graphql/codegen/src/core/query-builder.ts +++ b/graphql/codegen/src/core/query-builder.ts @@ -1,5 +1,5 @@ import { DocumentNode, print as gqlPrint } from 'graphql'; -import { camelize, underscore, pluralize } from 'inflekt'; +import { camelize, pluralize,underscore } from 'inflekt'; import { createOne, @@ -8,11 +8,10 @@ import { getCount, getMany, getOne, - patchOne, + patchOne } from './ast'; import { validateMetaObject } from './meta-object'; import type { - QueryFieldSelection, IntrospectionSchema, MetaObject, MetaTable, @@ -20,7 +19,8 @@ import type { QueryBuilderOptions, QueryBuilderResult, QueryDefinition, - QuerySelectionOptions, + QueryFieldSelection, + QuerySelectionOptions } from './types'; export * as MetaObject from './meta-object'; @@ -46,7 +46,7 @@ export class QueryBuilder { constructor({ meta = {} as MetaObject, - introspection, + introspection }: QueryBuilderOptions) { this._introspection = introspection; this._meta = meta; @@ -144,17 +144,17 @@ export class QueryBuilder { // We only need deleteAction from all of [deleteAction, deleteActionBySlug, deleteActionByName] const getInputName = (mutationType: string): string => { switch (mutationType) { - case 'delete': { - return `Delete${camelize(this._model)}Input`; - } - case 'create': { - return `Create${camelize(this._model)}Input`; - } - case 'patch': { - return `Update${camelize(this._model)}Input`; - } - default: - throw new Error('Unhandled mutation type' + mutationType); + case 'delete': { + return `Delete${camelize(this._model)}Input`; + } + case 'create': { + return `Create${camelize(this._model)}Input`; + } + case 'patch': { + return `Update${camelize(this._model)}Input`; + } + default: + throw new Error('Unhandled mutation type' + mutationType); } }; @@ -208,7 +208,7 @@ export class QueryBuilder { queryName: this._queryName, operationName: this._key, query: defn, - selection: this._select, + selection: this._select }); return this; @@ -232,7 +232,7 @@ export class QueryBuilder { queryName: this._queryName, operationName: this._key, query: defn, - selection: this._select, + selection: this._select }); return this; @@ -254,7 +254,7 @@ export class QueryBuilder { this._ast = getCount({ queryName: this._queryName, operationName: this._key, - query: defn, + query: defn }); return this; @@ -278,7 +278,7 @@ export class QueryBuilder { queryName: this._queryName, operationName: this._key, query: defn, - selection: this._select, + selection: this._select }); return this; @@ -302,7 +302,7 @@ export class QueryBuilder { operationName: this._key, mutationName: this._queryName, mutation: defn, - selection: this._select, + selection: this._select }); return this; @@ -326,7 +326,7 @@ export class QueryBuilder { this._ast = deleteOne({ operationName: this._key, mutationName: this._queryName, - mutation: defn, + mutation: defn }); return this; @@ -351,7 +351,7 @@ export class QueryBuilder { operationName: this._key, mutationName: this._queryName, mutation: defn, - selection: this._select, + selection: this._select }); return this; @@ -370,7 +370,7 @@ export class QueryBuilder { return { _hash, _queryName: this._queryName, - _ast: this._ast, + _ast: this._ast }; } @@ -421,7 +421,7 @@ function pickScalarFields( .map((fieldName) => ({ name: fieldName, isObject: false, - fieldDefn: modelMeta.fields.find((f) => f.name === fieldName), + fieldDefn: modelMeta.fields.find((f) => f.name === fieldName) })); // This is for inferring the sub-selection of a mutation query @@ -498,7 +498,7 @@ function pickAllFields( isObject: true, isBelongTo, selection: subFields.map((name) => ({ name, isObject: false })), - variables: selectOptions.variables as QueryFieldSelection['variables'], + variables: selectOptions.variables as QueryFieldSelection['variables'] }; // Need to further expand selection of object fields, @@ -529,8 +529,8 @@ function pickAllFields( { name: fieldName, isObject: false, - fieldDefn: modelMeta.fields.find((f) => f.name === fieldName), - }, + fieldDefn: modelMeta.fields.find((f) => f.name === fieldName) + } ]; } } diff --git a/graphql/codegen/src/core/watch/cache.ts b/graphql/codegen/src/core/watch/cache.ts index f92764d02..2df07bc6d 100644 --- a/graphql/codegen/src/core/watch/cache.ts +++ b/graphql/codegen/src/core/watch/cache.ts @@ -7,6 +7,7 @@ import * as fs from 'node:fs'; import * as path from 'node:path'; + import type { IntrospectionQueryResponse } from '../../types/introspection'; import { hashObject } from './hash'; diff --git a/graphql/codegen/src/core/watch/index.ts b/graphql/codegen/src/core/watch/index.ts index 6e220682f..737f372d6 100644 --- a/graphql/codegen/src/core/watch/index.ts +++ b/graphql/codegen/src/core/watch/index.ts @@ -2,17 +2,17 @@ * Watch mode module exports */ -export { SchemaPoller, computeSchemaHash } from './poller'; export { SchemaCache, touchFile } from './cache'; -export { sha256, hashObject, combineHashes } from './hash'; export { debounce, debounceAsync } from './debounce'; -export { WatchOrchestrator, startWatch } from './orchestrator'; +export { combineHashes,hashObject, sha256 } from './hash'; +export type { WatchOrchestratorOptions, WatchStatus } from './orchestrator'; +export { startWatch,WatchOrchestrator } from './orchestrator'; +export { computeSchemaHash,SchemaPoller } from './poller'; export type { - PollResult, - WatchOptions, - PollEventType, - PollEventHandler, - PollEvent, GeneratorType, + PollEvent, + PollEventHandler, + PollEventType, + PollResult, + WatchOptions } from './types'; -export type { WatchOrchestratorOptions, WatchStatus } from './orchestrator'; diff --git a/graphql/codegen/src/core/watch/orchestrator.ts b/graphql/codegen/src/core/watch/orchestrator.ts index c530c113e..dc986a441 100644 --- a/graphql/codegen/src/core/watch/orchestrator.ts +++ b/graphql/codegen/src/core/watch/orchestrator.ts @@ -5,9 +5,9 @@ */ import type { GraphQLSDKConfigTarget } from '../../types/config'; -import type { GeneratorType, WatchOptions, PollEvent } from './types'; -import { SchemaPoller } from './poller'; import { debounce } from './debounce'; +import { SchemaPoller } from './poller'; +import type { GeneratorType, PollEvent,WatchOptions } from './types'; // 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 @@ -82,7 +82,7 @@ export class WatchOrchestrator { lastPollTime: null, lastRegenTime: null, lastError: null, - currentHash: null, + currentHash: null }; // Create debounced regenerate function @@ -105,7 +105,7 @@ export class WatchOrchestrator { debounce: config.watch.debounce, touchFile: config.watch.touchFile, clearScreen: config.watch.clearScreen, - verbose, + verbose }; } @@ -217,18 +217,18 @@ export class WatchOrchestrator { let outputDir: string | undefined; switch (this.options.generatorType) { - case 'react-query': - generateFn = this.options.generateReactQuery; - // React Query hooks go to {output}/hooks - outputDir = this.options.outputDir ?? `${this.options.config.output}/hooks`; - break; - case 'orm': - generateFn = this.options.generateOrm; - // 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}`); + case 'react-query': + generateFn = this.options.generateReactQuery; + // React Query hooks go to {output}/hooks + outputDir = this.options.outputDir ?? `${this.options.config.output}/hooks`; + break; + case 'orm': + generateFn = this.options.generateOrm; + // 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}`); } const result = await generateFn({ @@ -238,7 +238,7 @@ export class WatchOrchestrator { output: outputDir, authorization: this.options.authorization, verbose: this.watchOptions.verbose, - skipCustomOperations: this.options.skipCustomOperations, + skipCustomOperations: this.options.skipCustomOperations }); const duration = Date.now() - startTime; @@ -287,14 +287,14 @@ export class WatchOrchestrator { private logHeader(): void { 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}`); + 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})`); diff --git a/graphql/codegen/src/core/watch/poller.ts b/graphql/codegen/src/core/watch/poller.ts index c60583f85..78e2937ac 100644 --- a/graphql/codegen/src/core/watch/poller.ts +++ b/graphql/codegen/src/core/watch/poller.ts @@ -6,16 +6,17 @@ */ import { EventEmitter } from 'node:events'; + import type { IntrospectionQueryResponse } from '../../types/introspection'; import { fetchSchema } from '../introspect/fetch-schema'; import { SchemaCache, touchFile } from './cache'; +import { hashObject } from './hash'; import type { - PollResult, PollEvent, PollEventType, - WatchOptions, + PollResult, + WatchOptions } from './types'; -import { hashObject } from './hash'; /** * Schema poller that periodically introspects a GraphQL endpoint @@ -73,7 +74,7 @@ export class SchemaPoller extends EventEmitter { return { success: false, changed: false, - error: 'Poll already in progress', + error: 'Poll already in progress' }; } @@ -87,7 +88,7 @@ export class SchemaPoller extends EventEmitter { endpoint: this.options.endpoint, authorization: this.options.authorization, headers: this.options.headers, - timeout: 30000, + timeout: 30000 }); const duration = Date.now() - startTime; @@ -156,7 +157,7 @@ export class SchemaPoller extends EventEmitter { endpoint: this.options.endpoint, authorization: this.options.authorization, headers: this.options.headers, - timeout: 30000, + timeout: 30000 }); if (schemaResult.success) { @@ -218,7 +219,7 @@ export class SchemaPoller extends EventEmitter { return { type, timestamp: Date.now(), - ...extra, + ...extra }; } } diff --git a/graphql/codegen/src/generators/field-selector.ts b/graphql/codegen/src/generators/field-selector.ts index 8e42e5c9d..43ce4851c 100644 --- a/graphql/codegen/src/generators/field-selector.ts +++ b/graphql/codegen/src/generators/field-selector.ts @@ -7,7 +7,7 @@ import type { CleanTable } from '../types/schema'; import type { FieldSelection, FieldSelectionPreset, - SimpleFieldSelection, + SimpleFieldSelection } from '../types/selection'; /** @@ -39,47 +39,47 @@ function convertPresetToSelection( const options: QuerySelectionOptions = {}; switch (preset) { - case 'minimal': { - // Just id and first display field - const minimalFields = getMinimalFields(table); - minimalFields.forEach((field) => { - options[field] = true; - }); - break; - } + case 'minimal': { + // Just id and first display field + const minimalFields = getMinimalFields(table); + minimalFields.forEach((field) => { + options[field] = true; + }); + break; + } - case 'display': { - // Common display fields - const displayFields = getDisplayFields(table); - displayFields.forEach((field) => { - options[field] = true; - }); - break; - } + case 'display': { + // Common display fields + const displayFields = getDisplayFields(table); + displayFields.forEach((field) => { + options[field] = true; + }); + break; + } - case 'all': { - // All non-relational fields (includes complex fields like JSON, geometry, etc.) - const allFields = getNonRelationalFields(table); - allFields.forEach((field) => { - options[field] = true; - }); - break; - } + case 'all': { + // All non-relational fields (includes complex fields like JSON, geometry, etc.) + const allFields = getNonRelationalFields(table); + allFields.forEach((field) => { + options[field] = true; + }); + break; + } - case 'full': - // All fields including basic relations - table.fields.forEach((field) => { - options[field.name] = true; - }); - break; + case 'full': + // All fields including basic relations + table.fields.forEach((field) => { + options[field.name] = true; + }); + break; - default: { - // Default to display - const defaultFields = getDisplayFields(table); - defaultFields.forEach((field) => { - options[field] = true; - }); - } + default: { + // Default to display + const defaultFields = getDisplayFields(table); + defaultFields.forEach((field) => { + options[field] = true; + }); + } } return options; @@ -118,7 +118,7 @@ function convertCustomSelectionToOptions( // Include with dynamically determined scalar fields from the related table options[relationField] = { select: getRelatedTableScalarFields(relationField, table, allTables), - variables: {}, + variables: {} }; } }); @@ -137,7 +137,7 @@ function convertCustomSelectionToOptions( table, allTables ), - variables: {}, + variables: {} }; } else if (Array.isArray(relationSelection)) { // Include with specific fields @@ -147,7 +147,7 @@ function convertCustomSelectionToOptions( }); options[relationField] = { select: selectObj, - variables: {}, + variables: {} }; } } @@ -305,7 +305,7 @@ function getRelatedTableScalarFields( 'slug', 'code', 'createdAt', - 'updatedAt', + 'updatedAt' ]; const included: string[] = []; @@ -351,7 +351,7 @@ export function getAvailableRelations( relations.push({ fieldName: rel.fieldName, type: 'belongsTo', - referencedTable: rel.referencesTable || undefined, + referencedTable: rel.referencesTable || undefined }); } }); @@ -362,7 +362,7 @@ export function getAvailableRelations( relations.push({ fieldName: rel.fieldName, type: 'hasOne', - referencedTable: rel.referencedByTable || undefined, + referencedTable: rel.referencedByTable || undefined }); } }); @@ -373,7 +373,7 @@ export function getAvailableRelations( relations.push({ fieldName: rel.fieldName, type: 'hasMany', - referencedTable: rel.referencedByTable || undefined, + referencedTable: rel.referencedByTable || undefined }); } }); @@ -384,7 +384,7 @@ export function getAvailableRelations( relations.push({ fieldName: rel.fieldName, type: 'manyToMany', - referencedTable: rel.rightTable || undefined, + referencedTable: rel.rightTable || undefined }); } }); @@ -465,6 +465,6 @@ export function validateFieldSelection( return { isValid: errors.length === 0, - errors, + errors }; } diff --git a/graphql/codegen/src/generators/index.ts b/graphql/codegen/src/generators/index.ts index 1bc3c755e..4b38b3518 100644 --- a/graphql/codegen/src/generators/index.ts +++ b/graphql/codegen/src/generators/index.ts @@ -5,26 +5,26 @@ // Field selector utilities export { convertToSelectionOptions, - isRelationalField, getAvailableRelations, - validateFieldSelection, + isRelationalField, + validateFieldSelection } from './field-selector'; // Query generators export { - buildSelect, - buildFindOne, buildCount, - toCamelCasePlural, - toOrderByTypeName, + buildFindOne, + buildSelect, cleanTableToMetaObject, - generateIntrospectionSchema, createASTQueryBuilder, + generateIntrospectionSchema, + toCamelCasePlural, + toOrderByTypeName } from './select'; // Mutation generators export { buildPostGraphileCreate, - buildPostGraphileUpdate, buildPostGraphileDelete, + buildPostGraphileUpdate } from './mutations'; diff --git a/graphql/codegen/src/generators/mutations.ts b/graphql/codegen/src/generators/mutations.ts index a7d495e0b..3d86856e1 100644 --- a/graphql/codegen/src/generators/mutations.ts +++ b/graphql/codegen/src/generators/mutations.ts @@ -3,18 +3,17 @@ * Uses AST-based approach for PostGraphile-compatible mutations */ import * as t from 'gql-ast'; -import { print } from 'graphql'; import type { ArgumentNode, FieldNode, VariableDefinitionNode } from 'graphql'; +import { print } from 'graphql'; import { camelize } from 'inflekt'; import { TypedDocumentString } from '../client/typed-document'; import { getCustomAstForCleanField, - requiresSubfieldSelection, + requiresSubfieldSelection } from '../core/custom-ast'; -import type { CleanTable } from '../types/schema'; import type { MutationOptions } from '../types/mutation'; - +import type { CleanTable } from '../types/schema'; import { isRelationalField } from './field-selector'; /** @@ -55,17 +54,17 @@ export function buildPostGraphileCreate( t.variableDefinition({ variable: t.variable({ name: 'input' }), type: t.nonNullType({ - type: t.namedType({ type: `Create${table.name}Input` }), - }), - }), + type: t.namedType({ type: `Create${table.name}Input` }) + }) + }) ]; // Create the mutation arguments const mutationArgs: ArgumentNode[] = [ t.argument({ name: 'input', - value: t.variable({ name: 'input' }), - }), + value: t.variable({ name: 'input' }) + }) ]; // Get the field selections for the return value using custom AST logic @@ -88,23 +87,23 @@ export function buildPostGraphileCreate( t.field({ name: singularName, selectionSet: t.selectionSet({ - selections: fieldSelections, - }), - }), - ], - }), - }), - ], - }), - }), - ], + selections: fieldSelections + }) + }) + ] + }) + }) + ] + }) + }) + ] }); // Print the AST to get the query string const queryString = print(ast); return new TypedDocumentString(queryString, { - __ast: ast, + __ast: ast }) as TypedDocumentString< Record, { input: { [key: string]: Record } } @@ -131,17 +130,17 @@ export function buildPostGraphileUpdate( t.variableDefinition({ variable: t.variable({ name: 'input' }), type: t.nonNullType({ - type: t.namedType({ type: `Update${table.name}Input` }), - }), - }), + type: t.namedType({ type: `Update${table.name}Input` }) + }) + }) ]; // Create the mutation arguments const mutationArgs: ArgumentNode[] = [ t.argument({ name: 'input', - value: t.variable({ name: 'input' }), - }), + value: t.variable({ name: 'input' }) + }) ]; // Get the field selections for the return value using custom AST logic @@ -164,23 +163,23 @@ export function buildPostGraphileUpdate( t.field({ name: singularName, selectionSet: t.selectionSet({ - selections: fieldSelections, - }), - }), - ], - }), - }), - ], - }), - }), - ], + selections: fieldSelections + }) + }) + ] + }) + }) + ] + }) + }) + ] }); // Print the AST to get the query string const queryString = print(ast); return new TypedDocumentString(queryString, { - __ast: ast, + __ast: ast }) as TypedDocumentString< Record, { input: { id: string | number; patch: Record } } @@ -206,17 +205,17 @@ export function buildPostGraphileDelete( t.variableDefinition({ variable: t.variable({ name: 'input' }), type: t.nonNullType({ - type: t.namedType({ type: `Delete${table.name}Input` }), - }), - }), + type: t.namedType({ type: `Delete${table.name}Input` }) + }) + }) ]; // Create the mutation arguments const mutationArgs: ArgumentNode[] = [ t.argument({ name: 'input', - value: t.variable({ name: 'input' }), - }), + value: t.variable({ name: 'input' }) + }) ]; // PostGraphile delete mutations typically return clientMutationId @@ -235,20 +234,20 @@ export function buildPostGraphileDelete( name: mutationName, args: mutationArgs, selectionSet: t.selectionSet({ - selections: fieldSelections, - }), - }), - ], - }), - }), - ], + selections: fieldSelections + }) + }) + ] + }) + }) + ] }); // Print the AST to get the query string const queryString = print(ast); return new TypedDocumentString(queryString, { - __ast: ast, + __ast: ast }) as TypedDocumentString< Record, { input: { id: string | number } } diff --git a/graphql/codegen/src/generators/select.ts b/graphql/codegen/src/generators/select.ts index edf2cace7..8bd58ccf8 100644 --- a/graphql/codegen/src/generators/select.ts +++ b/graphql/codegen/src/generators/select.ts @@ -3,14 +3,14 @@ * Uses AST-based approach for all query generation */ import * as t from 'gql-ast'; -import { print } from 'graphql'; import type { ArgumentNode, FieldNode, VariableDefinitionNode } from 'graphql'; +import { print } from 'graphql'; import { camelize, pluralize } from 'inflekt'; import { TypedDocumentString } from '../client/typed-document'; import { getCustomAstForCleanField, - requiresSubfieldSelection, + requiresSubfieldSelection } from '../core/custom-ast'; import { QueryBuilder } from '../core/query-builder'; import type { @@ -20,12 +20,11 @@ import type { MetaObject, MutationDefinition, QueryDefinition, - QuerySelectionOptions, + QuerySelectionOptions } from '../core/types'; -import type { CleanTable } from '../types/schema'; import type { QueryOptions } from '../types/query'; +import type { CleanTable } from '../types/schema'; import type { FieldSelection } from '../types/selection'; - import { convertToSelectionOptions, isRelationalField } from './field-selector'; /** @@ -67,8 +66,8 @@ export function cleanTableToMetaObject(tables: CleanTable[]): MetaObject { pgAlias: field.type.pgAlias, pgType: field.type.pgType, subtype: field.type.subtype, - typmod: field.type.typmod, - }, + typmod: field.type.typmod + } })), primaryConstraints: [] as MetaConstraint[], // Would need to be derived from schema uniqueConstraints: [] as MetaConstraint[], // Would need to be derived from schema @@ -83,9 +82,9 @@ export function cleanTableToMetaObject(tables: CleanTable[]): MetaObject { pgAlias: null, pgType: null, subtype: null, - typmod: null, + typmod: null } as MetaFieldType, - alias: rel.fieldName || '', + alias: rel.fieldName || '' }, toKey: { name: 'id', @@ -96,11 +95,11 @@ export function cleanTableToMetaObject(tables: CleanTable[]): MetaObject { pgAlias: null, pgType: null, subtype: null, - typmod: null, - } as MetaFieldType, - }, - })), - })), + typmod: null + } as MetaFieldType + } + })) + })) }; } @@ -125,7 +124,7 @@ export function generateIntrospectionSchema( qtype: 'getMany', model: modelName, selection, - properties: convertFieldsToProperties(table.fields), + properties: convertFieldsToProperties(table.fields) } as QueryDefinition; // Add getOne query (by ID) @@ -134,7 +133,7 @@ export function generateIntrospectionSchema( qtype: 'getOne', model: modelName, selection, - properties: convertFieldsToProperties(table.fields), + properties: convertFieldsToProperties(table.fields) } as QueryDefinition; // Add create mutation @@ -157,11 +156,11 @@ export function generateIntrospectionSchema( isNotNull: true, isArray: false, isArrayNotNull: false, - properties: convertFieldsToNestedProperties(table.fields), - }, - }, - }, - }, + properties: convertFieldsToNestedProperties(table.fields) + } + } + } + } } as MutationDefinition; // Add update mutation @@ -184,11 +183,11 @@ export function generateIntrospectionSchema( isNotNull: true, isArray: false, isArrayNotNull: false, - properties: convertFieldsToNestedProperties(table.fields), - }, - }, - }, - }, + properties: convertFieldsToNestedProperties(table.fields) + } + } + } + } } as MutationDefinition; // Add delete mutation @@ -210,11 +209,11 @@ export function generateIntrospectionSchema( type: 'UUID', isNotNull: true, isArray: false, - isArrayNotNull: false, - }, - }, - }, - }, + isArrayNotNull: false + } + } + } + } } as MutationDefinition; } @@ -233,7 +232,7 @@ function convertFieldsToProperties(fields: CleanTable['fields']) { type: field.type.gqlType, isNotNull: !field.type.gqlType.endsWith('!'), isArray: field.type.isArray, - isArrayNotNull: false, + isArrayNotNull: false }; }); @@ -252,7 +251,7 @@ function convertFieldsToNestedProperties(fields: CleanTable['fields']) { type: field.type.gqlType, isNotNull: false, // Mutations typically allow optional fields isArray: field.type.isArray, - isArrayNotNull: false, + isArrayNotNull: false }; }); @@ -268,7 +267,7 @@ export function createASTQueryBuilder(tables: CleanTable[]): QueryBuilder { return new QueryBuilder({ meta: metaObject, - introspection: introspectionSchema, + introspection: introspectionSchema }); } @@ -370,13 +369,13 @@ function generateSelectQueryAST( variableDefinitions.push( t.variableDefinition({ variable: t.variable({ name: 'first' }), - type: t.namedType({ type: 'Int' }), + type: t.namedType({ type: 'Int' }) }) ); queryArgs.push( t.argument({ name: 'first', - value: t.variable({ name: 'first' }), + value: t.variable({ name: 'first' }) }) ); } @@ -385,13 +384,13 @@ function generateSelectQueryAST( variableDefinitions.push( t.variableDefinition({ variable: t.variable({ name: 'offset' }), - type: t.namedType({ type: 'Int' }), + type: t.namedType({ type: 'Int' }) }) ); queryArgs.push( t.argument({ name: 'offset', - value: t.variable({ name: 'offset' }), + value: t.variable({ name: 'offset' }) }) ); } @@ -401,13 +400,13 @@ function generateSelectQueryAST( variableDefinitions.push( t.variableDefinition({ variable: t.variable({ name: 'after' }), - type: t.namedType({ type: 'Cursor' }), + type: t.namedType({ type: 'Cursor' }) }) ); queryArgs.push( t.argument({ name: 'after', - value: t.variable({ name: 'after' }), + value: t.variable({ name: 'after' }) }) ); } @@ -416,13 +415,13 @@ function generateSelectQueryAST( variableDefinitions.push( t.variableDefinition({ variable: t.variable({ name: 'before' }), - type: t.namedType({ type: 'Cursor' }), + type: t.namedType({ type: 'Cursor' }) }) ); queryArgs.push( t.argument({ name: 'before', - value: t.variable({ name: 'before' }), + value: t.variable({ name: 'before' }) }) ); } @@ -432,13 +431,13 @@ function generateSelectQueryAST( variableDefinitions.push( t.variableDefinition({ variable: t.variable({ name: 'filter' }), - type: t.namedType({ type: `${table.name}Filter` }), + type: t.namedType({ type: `${table.name}Filter` }) }) ); queryArgs.push( t.argument({ name: 'filter', - value: t.variable({ name: 'filter' }), + value: t.variable({ name: 'filter' }) }) ); } @@ -451,15 +450,15 @@ function generateSelectQueryAST( // PostGraphile expects [ProductsOrderBy!] - list of non-null enum values type: t.listType({ type: t.nonNullType({ - type: t.namedType({ type: toOrderByTypeName(table.name) }), - }), - }), + type: t.namedType({ type: toOrderByTypeName(table.name) }) + }) + }) }) ); queryArgs.push( t.argument({ name: 'orderBy', - value: t.variable({ name: 'orderBy' }), + value: t.variable({ name: 'orderBy' }) }) ); } @@ -470,9 +469,9 @@ function generateSelectQueryAST( t.field({ name: 'nodes', selectionSet: t.selectionSet({ - selections: fieldSelections, - }), - }), + selections: fieldSelections + }) + }) ]; // Add pageInfo if requested (for cursor-based pagination / infinite scroll) @@ -489,9 +488,9 @@ function generateSelectQueryAST( t.field({ name: 'hasNextPage' }), t.field({ name: 'hasPreviousPage' }), t.field({ name: 'startCursor' }), - t.field({ name: 'endCursor' }), - ], - }), + t.field({ name: 'endCursor' }) + ] + }) }) ); } @@ -508,13 +507,13 @@ function generateSelectQueryAST( name: pluralName, args: queryArgs, selectionSet: t.selectionSet({ - selections: connectionSelections, - }), - }), - ], - }), - }), - ], + selections: connectionSelections + }) + }) + ] + }) + }) + ] }); return print(ast); @@ -595,20 +594,20 @@ function generateFieldSelectionsFromOptions( t.argument({ name: 'first', value: t.intValue({ - value: DEFAULT_NESTED_RELATION_FIRST.toString(), - }), - }), + value: DEFAULT_NESTED_RELATION_FIRST.toString() + }) + }) ], selectionSet: t.selectionSet({ selections: [ t.field({ name: 'nodes', selectionSet: t.selectionSet({ - selections: nestedSelections, - }), - }), - ], - }), + selections: nestedSelections + }) + }) + ] + }) }) ); } else { @@ -617,8 +616,8 @@ function generateFieldSelectionsFromOptions( t.field({ name: fieldName, selectionSet: t.selectionSet({ - selections: nestedSelections, - }), + selections: nestedSelections + }) }) ); } @@ -749,9 +748,9 @@ function generateFindOneQueryAST(table: CleanTable): string { t.variableDefinition({ variable: t.variable({ name: 'id' }), type: t.nonNullType({ - type: t.namedType({ type: 'UUID' }), - }), - }), + type: t.namedType({ type: 'UUID' }) + }) + }) ], selectionSet: t.selectionSet({ selections: [ @@ -760,17 +759,17 @@ function generateFindOneQueryAST(table: CleanTable): string { args: [ t.argument({ name: 'id', - value: t.variable({ name: 'id' }), - }), + value: t.variable({ name: 'id' }) + }) ], selectionSet: t.selectionSet({ - selections: fieldSelections, - }), - }), - ], - }), - }), - ], + selections: fieldSelections + }) + }) + ] + }) + }) + ] }); return print(ast); @@ -790,8 +789,8 @@ function generateCountQueryAST(table: CleanTable): string { variableDefinitions: [ t.variableDefinition({ variable: t.variable({ name: 'filter' }), - type: t.namedType({ type: `${table.name}Filter` }), - }), + type: t.namedType({ type: `${table.name}Filter` }) + }) ], selectionSet: t.selectionSet({ selections: [ @@ -800,17 +799,17 @@ function generateCountQueryAST(table: CleanTable): string { args: [ t.argument({ name: 'filter', - value: t.variable({ name: 'filter' }), - }), + value: t.variable({ name: 'filter' }) + }) ], selectionSet: t.selectionSet({ - selections: [t.field({ name: 'totalCount' })], - }), - }), - ], - }), - }), - ], + selections: [t.field({ name: 'totalCount' })] + }) + }) + ] + }) + }) + ] }); return print(ast); diff --git a/graphql/codegen/src/index.ts b/graphql/codegen/src/index.ts index 19ae82473..681af96af 100644 --- a/graphql/codegen/src/index.ts +++ b/graphql/codegen/src/index.ts @@ -22,22 +22,33 @@ export * from './client'; export { defineConfig } from './types/config'; // Main generate function (orchestrates the entire pipeline) -export { generate } from './core/generate'; export type { GenerateOptions, GenerateResult } from './core/generate'; +export { generate } from './core/generate'; // Config utilities export { findConfigFile, loadConfigFile } from './core/config'; // CLI shared utilities (for packages/cli to import) -export { codegenQuestions, splitCommas, printResult, camelizeArgv } from './cli/shared'; export type { CodegenAnswers } from './cli/shared'; +export { + buildDbConfig, + buildGenerateOptions, + camelizeArgv, + codegenQuestions, + filterDefined, + flattenDbFields, + hyphenateKeys, + printResult, + seedArgvFromConfig, + splitCommas +} from './cli/shared'; // Database schema utilities (re-exported from core for convenience) -export { - buildSchemaFromDatabase, - buildSchemaSDLFromDatabase, -} from './core/database'; export type { BuildSchemaFromDatabaseOptions, - BuildSchemaFromDatabaseResult, + BuildSchemaFromDatabaseResult +} from './core/database'; +export { + buildSchemaFromDatabase, + buildSchemaSDLFromDatabase } from './core/database'; diff --git a/graphql/codegen/src/types/config.ts b/graphql/codegen/src/types/config.ts index bae0a864f..b171e9d92 100644 --- a/graphql/codegen/src/types/config.ts +++ b/graphql/codegen/src/types/config.ts @@ -261,15 +261,6 @@ export interface GraphQLSDKConfigTarget { */ reactQuery?: boolean; - /** - * Generate browser-compatible code using native fetch - * When true (default), uses native W3C fetch API (works in browsers and Node.js) - * When false, uses undici fetch with dispatcher support for localhost DNS resolution - * (Node.js only - enables proper *.localhost subdomain resolution on macOS) - * @default true - */ - browserCompatible?: boolean; - /** * Query key generation configuration * Controls how query keys are structured for cache management @@ -356,7 +347,7 @@ export const DEFAULT_WATCH_CONFIG: WatchConfig = { pollInterval: 3000, debounce: 800, touchFile: undefined, - clearScreen: true, + clearScreen: true }; /** @@ -367,7 +358,7 @@ export const DEFAULT_QUERY_KEY_CONFIG: QueryKeyConfig = { relationships: {}, generateScopedKeys: true, generateCascadeHelpers: true, - generateMutationKeys: true, + generateMutationKeys: true }; /** @@ -380,36 +371,35 @@ export const DEFAULT_CONFIG: GraphQLSDKConfigTarget = { tables: { include: ['*'], exclude: [], - systemExclude: [], + systemExclude: [] }, queries: { include: ['*'], exclude: [], - systemExclude: ['_meta', 'query'], // Internal PostGraphile queries + systemExclude: ['_meta', 'query'] // Internal PostGraphile queries }, mutations: { include: ['*'], exclude: [], - systemExclude: [], + systemExclude: [] }, excludeFields: [], hooks: { queries: true, mutations: true, - queryKeyPrefix: 'graphql', + queryKeyPrefix: 'graphql' }, postgraphile: { - schema: 'public', + schema: 'public' }, codegen: { maxFieldDepth: 2, - skipQueryField: true, + skipQueryField: true }, orm: false, reactQuery: false, - browserCompatible: true, queryKeys: DEFAULT_QUERY_KEY_CONFIG, - watch: DEFAULT_WATCH_CONFIG, + watch: DEFAULT_WATCH_CONFIG }; diff --git a/graphql/codegen/src/types/index.ts b/graphql/codegen/src/types/index.ts index 8e23aad73..83a920137 100644 --- a/graphql/codegen/src/types/index.ts +++ b/graphql/codegen/src/types/index.ts @@ -4,59 +4,58 @@ // Schema types export type { - CleanTable, + CleanBelongsToRelation, CleanField, CleanFieldType, - CleanRelations, - CleanBelongsToRelation, - CleanHasOneRelation, CleanHasManyRelation, + CleanHasOneRelation, CleanManyToManyRelation, - TableInflection, - TableQueryNames, - TableConstraints, + CleanRelations, + CleanTable, ConstraintInfo, ForeignKeyConstraint, + TableConstraints, + TableInflection, + TableQueryNames } from './schema'; // Query types export type { - PageInfo, ConnectionResult, - QueryOptions, - OrderByItem, - FilterOperator, FieldFilter, - RelationalFilter, Filter, + FilterOperator, + OrderByItem, + PageInfo, + QueryOptions, + RelationalFilter } from './query'; // Mutation types export type { - MutationOptions, CreateInput, - UpdateInput, DeleteInput, + MutationOptions, MutationResult, + UpdateInput } from './mutation'; // Selection types export type { - SimpleFieldSelection, - FieldSelectionPreset, FieldSelection, + FieldSelectionPreset, SelectionOptions, + SimpleFieldSelection } from './selection'; // Config types export type { GraphQLSDKConfig, - GraphQLSDKConfigTarget, + GraphQLSDKConfigTarget } from './config'; - export { + DEFAULT_CONFIG, defineConfig, getConfigOptions, - mergeConfig, - DEFAULT_CONFIG, + mergeConfig } from './config'; diff --git a/graphql/test-app/.gitignore b/graphql/test-app/.gitignore new file mode 100644 index 000000000..a39b67259 --- /dev/null +++ b/graphql/test-app/.gitignore @@ -0,0 +1 @@ +src/generated/* \ No newline at end of file diff --git a/graphql/test-app/README.md b/graphql/test-app/README.md new file mode 100644 index 000000000..fbb152e9d --- /dev/null +++ b/graphql/test-app/README.md @@ -0,0 +1,62 @@ +# test-codegen-app + +Local integration app for validating `@constructive-io/graphql-codegen` output against a real GraphQL endpoint. + +This package is intended for: +- Generating React Query + ORM output from the current workspace codegen implementation. +- Type-checking real generated artifacts. +- Running live integration checks with real auth credentials. + +This package is not part of CI test gating and is meant for local/manual verification. + +## What It Tests + +- React Query output mode generation and usage. +- ORM output mode generation and usage. +- Generated type fidelity in real app code (`tsc --noEmit`). +- Live endpoint behavior in `tests/*.test.ts`. + +## Local Usage + +Run from repo root. + +1. Generate from `codegen.config.ts`: + +```bash +pnpm --filter @constructive-io/test-codegen-app codegen +``` + +2. Type-check generated output: + +```bash +pnpm --filter @constructive-io/test-codegen-app typecheck +``` + +3. Build the app: + +```bash +pnpm --filter @constructive-io/test-codegen-app build +``` + +4. Run integration tests (non-live mode, skips credentialed tests): + +```bash +pnpm --filter @constructive-io/test-codegen-app test:integration +``` + +5. Run live integration tests: + +```bash +GRAPHQL_TEST_EMAIL="you@example.com" \ +GRAPHQL_TEST_PASSWORD="your-password" \ +pnpm --filter @constructive-io/test-codegen-app test:integration:live +``` + +Optional: +- `GRAPHQL_TEST_ENDPOINT` to override the default endpoint used by live tests. + +## Notes + +- `codegen` uses `graphql/test-app/codegen.config.ts` (currently pointed at the production endpoint for validation). +- `codegen:orm` is available for direct endpoint-driven ORM generation checks. +- Keep this app focused on realistic generated-API usage and regression coverage for codegen refactors. diff --git a/graphql/test-app/codegen.config.ts b/graphql/test-app/codegen.config.ts new file mode 100644 index 000000000..9daf7e78f --- /dev/null +++ b/graphql/test-app/codegen.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from '@constructive-io/graphql-codegen'; + +const config = defineConfig({ + endpoint: 'https://api.launchql.dev/graphql', + output: 'src/generated', + reactQuery: true, +}); + +export default config; diff --git a/graphql/test-app/index.html b/graphql/test-app/index.html new file mode 100644 index 000000000..43074d8dc --- /dev/null +++ b/graphql/test-app/index.html @@ -0,0 +1,12 @@ + + + + + + GraphQL Codegen Test App + + +
+ + + diff --git a/graphql/test-app/package.json b/graphql/test-app/package.json new file mode 100644 index 000000000..139ad00f0 --- /dev/null +++ b/graphql/test-app/package.json @@ -0,0 +1,39 @@ +{ + "name": "@constructive-io/test-codegen-app", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "preview": "vite preview", + "codegen": "tsx ../codegen/src/cli/index.ts --config codegen.config.ts", + "codegen:orm": "tsx ../codegen/src/cli/index.ts --endpoint http://api.localhost:3000/graphql --output src/generated --orm", + "typecheck": "tsc --noEmit", + "test:types": "tsc --noEmit", + "test:integration": "node --import tsx --test \"tests/**/*.test.ts\"", + "test:integration:live": "GRAPHQL_TEST_LIVE_REQUIRED=1 node --import tsx --test \"tests/**/*.test.ts\"", + "analyze": "tsx scripts/analyze-bundle.ts", + "analyze:visual": "vite build && echo '\nBundle report: dist/bundle-stats.html'" + }, + "dependencies": { + "@0no-co/graphql.web": "^1.2.0", + "@constructive-io/graphql-types": "workspace:^", + "@tanstack/react-query": "^5.90.20", + "gql-ast": "workspace:^", + "graphql": "15.10.1", + "react": "^19.2.3", + "react-dom": "^19.2.3" + }, + "devDependencies": { + "@constructive-io/graphql-codegen": "workspace:^", + "@types/react": "^19.2.13", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^4.5.2", + "react-test-renderer": "^19.2.3", + "rollup-plugin-visualizer": "^6.0.5", + "tsx": "^4.20.3", + "typescript": "^5.8.3", + "vite": "^6.3.5" + } +} diff --git a/graphql/test-app/scripts/analyze-bundle.ts b/graphql/test-app/scripts/analyze-bundle.ts new file mode 100644 index 000000000..7db8f509e --- /dev/null +++ b/graphql/test-app/scripts/analyze-bundle.ts @@ -0,0 +1,155 @@ +/** + * Bundle size analysis script + * + * Builds the app with Rollup's generateBundle hook to capture per-module sizes, + * then groups them by category (generated hooks, ORM, vendor libs, app code). + * + * Usage: tsx scripts/analyze-bundle.ts + */ +import { build } from 'vite'; +import react from '@vitejs/plugin-react'; +import { gzipSync, brotliCompressSync } from 'node:zlib'; + +interface ModuleInfo { + originalLength: number; + renderedLength: number; + removedExports: string[]; + code: string | null; +} + +interface ChunkInfo { + name: string; + size: number; + gzip: number; + brotli: number; + modules: Record; +} + +const chunks: ChunkInfo[] = []; + +const result = await build({ + configFile: false, + plugins: [ + react(), + { + name: 'capture-bundle-stats', + generateBundle(_options, bundle) { + for (const [fileName, chunk] of Object.entries(bundle)) { + if (chunk.type !== 'chunk') continue; + const code = Buffer.from(chunk.code); + chunks.push({ + name: fileName, + size: code.length, + gzip: gzipSync(code).length, + brotli: brotliCompressSync(code).length, + modules: chunk.modules as Record, + }); + } + }, + }, + ], + build: { + write: false, + minify: 'esbuild', + }, + logLevel: 'silent', +}); + +// Categorize modules +interface Category { + label: string; + test: (id: string) => boolean; +} + +const categories: Category[] = [ + { label: 'Generated Hooks', test: (id) => id.includes('generated/hooks') }, + { label: 'Generated ORM', test: (id) => id.includes('generated/orm') }, + { label: 'Generated Types', test: (id) => id.includes('generated/') && (id.includes('types.ts') || id.includes('schema-types')) }, + { label: 'React', test: (id) => /node_modules\/(react|react-dom|scheduler)\//.test(id) }, + { label: 'React Query', test: (id) => id.includes('@tanstack/react-query') }, + { label: 'GraphQL (graphql.web + gql-ast)', test: (id) => id.includes('@0no-co/graphql.web') || id.includes('gql-ast') }, + { label: 'GraphQL (graphql 15)', test: (id) => id.includes('node_modules/graphql') }, + { label: 'App Code', test: (id) => !id.includes('node_modules') && !id.includes('generated/') }, +]; + +const catSizes: Record = {}; +let uncategorized = 0; + +for (const chunk of chunks) { + for (const [moduleId, info] of Object.entries(chunk.modules)) { + let matched = false; + for (const cat of categories) { + if (cat.test(moduleId)) { + if (!catSizes[cat.label]) catSizes[cat.label] = { original: 0, rendered: 0 }; + catSizes[cat.label].original += info.originalLength; + catSizes[cat.label].rendered += info.renderedLength; + matched = true; + break; + } + } + if (!matched) { + uncategorized += info.renderedLength; + } + } +} + +// Output +console.log('\n========================================'); +console.log(' BUNDLE SIZE ANALYSIS'); +console.log('========================================\n'); + +const totalChunk = chunks[0]; +if (totalChunk) { + const fmt = (n: number) => (n / 1024).toFixed(1) + ' KB'; + console.log(`Total bundle: ${fmt(totalChunk.size)} minified | ${fmt(totalChunk.gzip)} gzip | ${fmt(totalChunk.brotli)} brotli\n`); +} + +console.log('By category (rendered/minified size in bundle):'); +console.log('─'.repeat(60)); + +const sorted = Object.entries(catSizes).sort((a, b) => b[1].rendered - a[1].rendered); +const totalRendered = sorted.reduce((sum, [, v]) => sum + v.rendered, 0) + uncategorized; + +for (const [label, { original, rendered }] of sorted) { + const pct = ((rendered / totalRendered) * 100).toFixed(1); + const pad = label.padEnd(35); + const renderedKB = (rendered / 1024).toFixed(1).padStart(8); + const originalKB = (original / 1024).toFixed(1).padStart(8); + console.log(` ${pad} ${renderedKB} KB (${pct.padStart(5)}%) source: ${originalKB} KB`); +} + +if (uncategorized > 0) { + const pct = ((uncategorized / totalRendered) * 100).toFixed(1); + console.log(` ${'Other'.padEnd(35)} ${(uncategorized / 1024).toFixed(1).padStart(8)} KB (${pct.padStart(5)}%)`); +} + +console.log('─'.repeat(60)); +console.log(` ${'TOTAL'.padEnd(35)} ${(totalRendered / 1024).toFixed(1).padStart(8)} KB\n`); + +// Tree-shaking effectiveness +const hooksSource = catSizes['Generated Hooks']; +const ormSource = catSizes['Generated ORM']; +if (hooksSource || ormSource) { + console.log('Tree-shaking effectiveness:'); + console.log('─'.repeat(60)); + if (hooksSource) { + const ratio = ((1 - hooksSource.rendered / hooksSource.original) * 100).toFixed(1); + console.log(` Hooks: ${(hooksSource.original / 1024).toFixed(0)} KB source → ${(hooksSource.rendered / 1024).toFixed(1)} KB in bundle (${ratio}% eliminated)`); + } + if (ormSource) { + const ratio = ((1 - ormSource.rendered / ormSource.original) * 100).toFixed(1); + console.log(` ORM: ${(ormSource.original / 1024).toFixed(0)} KB source → ${(ormSource.rendered / 1024).toFixed(1)} KB in bundle (${ratio}% eliminated)`); + } + console.log(''); +} + +// Module count +let totalModules = 0; +let generatedModules = 0; +for (const chunk of chunks) { + for (const moduleId of Object.keys(chunk.modules)) { + totalModules++; + if (moduleId.includes('generated/')) generatedModules++; + } +} +console.log(`Modules: ${totalModules} total, ${generatedModules} generated (${(totalModules - generatedModules)} vendor/app)\n`); diff --git a/graphql/test-app/src/App.tsx b/graphql/test-app/src/App.tsx new file mode 100644 index 000000000..2c4498806 --- /dev/null +++ b/graphql/test-app/src/App.tsx @@ -0,0 +1,1034 @@ +/** + * Test App for graphql-codegen hooks + * + * Tests the full auth flow (signUp, signIn, signOut) and then + * exercises authenticated queries/mutations with type-safe select. + * + * Run `pnpm codegen` first to generate the hooks from the live API. + */ + +import { useState, FormEvent } from 'react'; +import { useQueryClient } from '@tanstack/react-query'; + +import { + // Client configuration + configure, + + // Auth mutation hooks + useSignUpMutation, + useSignInMutation, + useSignOutMutation, + + // Authenticated query hooks + useCurrentUserQuery, + useCurrentUserIdQuery, + useUsersQuery, + useDatabasesQuery, + useDatabaseQuery, + useSchemasQuery, + useApisQuery, + useDomainsQuery, + + // Authenticated mutation hooks — Users + useCreateUserMutation, + useUpdateUserMutation, + + // Authenticated mutation hooks — Databases + useCreateDatabaseMutation, + useUpdateDatabaseMutation, + useDeleteDatabaseMutation, + + // Authenticated mutation hooks — Schemas, APIs, Sites, Domains + useCreateSchemaMutation, + useCreateApiMutation, + useCreateSiteMutation, + useCreateDomainMutation, +} from './generated/hooks'; + +const ENDPOINT = 'http://api.localhost:3000/graphql'; + +// --------------------------------------------------------------------------- +// Auth helpers +// --------------------------------------------------------------------------- + +function reconfigureClient(token?: string) { + configure({ + endpoint: ENDPOINT, + headers: token ? { Authorization: `Bearer ${token}` } : {}, + }); +} + +// --------------------------------------------------------------------------- +// Sign Up Form +// --------------------------------------------------------------------------- +function SignUpForm({ onAuth }: { onAuth: (token: string, userId: string) => void }) { + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + + const { mutate, isPending, error } = useSignUpMutation({ + selection: { + fields: { + result: { + select: { + accessToken: true, + userId: true, + isVerified: true, + }, + }, + }, + }, + }); + + const handleSubmit = (e: FormEvent) => { + e.preventDefault(); + mutate( + { input: { email, password } }, + { + onSuccess: (data) => { + const result = data.signUp.result; + if (result?.accessToken) { + onAuth(result.accessToken, result.userId ?? ''); + } + }, + }, + ); + }; + + return ( +
+

Sign Up

+ setEmail(e.target.value)} required style={inputStyle} /> + setPassword(e.target.value)} required style={inputStyle} /> + + {error &&

{error.message}

} +
+ ); +} + +// --------------------------------------------------------------------------- +// Sign In Form +// --------------------------------------------------------------------------- +function SignInForm({ onAuth }: { onAuth: (token: string, userId: string) => void }) { + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + + const { mutate, isPending, error } = useSignInMutation({ + selection: { + fields: { + result: { + select: { + accessToken: true, + userId: true, + isVerified: true, + totpEnabled: true, + }, + }, + }, + }, + }); + + const handleSubmit = (e: FormEvent) => { + e.preventDefault(); + mutate( + { input: { email, password } }, + { + onSuccess: (data) => { + // AUTOCOMPLETION TEST: type `data.signIn.result.` — should suggest accessToken, userId, isVerified, totpEnabled + const result = data.signIn.result; + if (result?.accessToken) { + onAuth(result.accessToken, result.userId ?? ''); + } + }, + }, + ); + }; + + return ( +
+

Sign In

+ setEmail(e.target.value)} required style={inputStyle} /> + setPassword(e.target.value)} required style={inputStyle} /> + + {error &&

{error.message}

} +
+ ); +} + +// --------------------------------------------------------------------------- +// Auth Page (unauthenticated) +// --------------------------------------------------------------------------- +function AuthPage({ onAuth }: { onAuth: (token: string, userId: string) => void }) { + const [mode, setMode] = useState<'signin' | 'signup'>('signin'); + + return ( +
+
+ + +
+ {mode === 'signin' ? : } +
+ ); +} + +// =========================================================================== +// SECTION: Identity & Profile +// =========================================================================== + +function CurrentUser() { + const { data, isLoading, error } = useCurrentUserQuery({ + selection: { fields: { id: true, username: true, displayName: true, createdAt: true } }, + }); + + if (isLoading) return

Loading current user...

; + if (error) return

Error: {error.message}

; + + // AUTOCOMPLETION TEST: type `data?.currentUser.` — should suggest id, username, displayName, createdAt + const user = data?.currentUser; + + return ( +
+

Current User

+ {user ? ( +
+
ID
{user.id}
+
Username
{user.username ?? '—'}
+
Display Name
{user.displayName ?? '—'}
+
Created At
{user.createdAt}
+
+ ) : ( +

No user found

+ )} +
+ ); +} + +function CurrentUserId() { + const { data, isLoading } = useCurrentUserIdQuery(); + if (isLoading) return

Loading...

; + + return ( +
+

Current User ID (scalar)

+ {data?.currentUserId ?? 'null'} +
+ ); +} + +function UserList() { + const { data, isLoading, error } = useUsersQuery({ + selection: { + fields: { id: true, username: true, displayName: true, createdAt: true }, + first: 10, + orderBy: ['CREATED_AT_DESC'], + }, + }); + + if (isLoading) return

Loading users...

; + if (error) return

Error: {error.message}

; + + const users = data?.users?.nodes ?? []; + + return ( +
+

Users ({users.length})

+ [user.username, user.displayName, user.createdAt]} + /> +
+ ); +} + +function CreateUserForm() { + const [username, setUsername] = useState(''); + const [displayName, setDisplayName] = useState(''); + const { mutate, isPending, error, data: result } = useCreateUserMutation({ + selection: { fields: { id: true, username: true, displayName: true } }, + }); + + const handleSubmit = (e: FormEvent) => { + e.preventDefault(); + mutate({ username, displayName }); + }; + + return ( +
+

Create User

+
+ setUsername(e.target.value)} required style={inputStyle} /> + setDisplayName(e.target.value)} style={inputStyle} /> + +
+ {error &&

{error.message}

} + {result &&
{JSON.stringify(result.createUser.user, null, 2)}
} +
+ ); +} + +function UpdateUserForm({ userId }: { userId: string }) { + const [displayName, setDisplayName] = useState(''); + const { mutate, isPending, error, data: result } = useUpdateUserMutation({ + selection: { fields: { id: true, username: true, displayName: true } }, + }); + + const handleSubmit = (e: FormEvent) => { + e.preventDefault(); + mutate({ id: userId, patch: { displayName } }); + }; + + return ( +
+

Update Current User

+
+ setDisplayName(e.target.value)} required style={inputStyle} /> + +
+ {error &&

{error.message}

} + {result &&
{JSON.stringify(result.updateUser.user, null, 2)}
} +
+ ); +} + +// =========================================================================== +// SECTION: Database Management (full CRUD) +// =========================================================================== + +function DatabaseListWithSchemas() { + const { data, isLoading, error, refetch } = useDatabasesQuery({ + selection: { + fields: { + id: true, + name: true, + label: true, + schemaName: true, + createdAt: true, + schemas: { + first: 20, + filter: { + isPublic: { equalTo: true }, + schemaName: { startsWithInsensitive: 'app_' }, + }, + orderBy: ['SCHEMA_NAME_ASC'], + select: { + id: true, + name: true, + schemaName: true, + isPublic: true, + }, + }, + }, + first: 10, + where: { + and: [ + { name: { includesInsensitive: 'prod' } }, + { createdAt: { greaterThanOrEqualTo: '2026-01-01T00:00:00.000Z' } }, + ], + }, + orderBy: ['CREATED_AT_DESC'], + }, + }); + + if (isLoading) return

Loading databases...

; + if (error) return

Error: {error.message}

; + + // AUTOCOMPLETION TEST: type `db.` — should suggest id, name, label, createdAt, schemas + const databases = data?.databases?.nodes ?? []; + + return ( +
+
+

Databases ({databases.length})

+ +
+ {databases.length === 0 ? ( +

No databases — create one below

+ ) : ( + databases.map((db) => ( +
+
+
+ {db.name} + {db.label && ({db.label})} + {db.id.slice(0, 8)} +
+ {db.createdAt} +
+ {/* NESTED RELATION: schemas under this database */} + {db.schemas?.nodes && db.schemas.nodes.length > 0 && ( +
+ Schemas: {db.schemas.nodes.map((s) => ( + + {s.schemaName ?? s.name} + + ))} +
+ )} +
+ )) + )} +
+ ); +} + +function DatabaseDetail({ databaseId }: { databaseId: string }) { + const { data, isLoading, error } = useDatabaseQuery({ + id: databaseId, + selection: { + fields: { + id: true, + name: true, + label: true, + schemaName: true, + privateSchemaName: true, + createdAt: true, + updatedAt: true, + // NESTED: owner user + owner: { + select: { id: true, username: true, displayName: true }, + }, + }, + }, + }); + + if (isLoading) return

Loading database...

; + if (error) return

Error: {error.message}

; + + // AUTOCOMPLETION TEST: type `data?.database.` — should suggest id, name, label, owner, etc. + const db = data?.database; + if (!db) return

Database not found

; + + return ( +
+

Database Detail

+
+
ID
{db.id}
+
Name
{db.name}
+
Label
{db.label ?? '—'}
+
Public Schema
{db.schemaName ?? '—'}
+
Private Schema
{db.privateSchemaName ?? '—'}
+
Owner
{db.owner?.displayName ?? db.owner?.username ?? '—'}
+
Created
{db.createdAt}
+
Updated
{db.updatedAt}
+
+
+ ); +} + +function CreateDatabaseForm({ userId }: { userId: string }) { + const [name, setName] = useState(''); + const [label, setLabel] = useState(''); + const { mutate, isPending, error, data: result } = useCreateDatabaseMutation({ + selection: { fields: { id: true, name: true, label: true, createdAt: true } }, + }); + + const handleSubmit = (e: FormEvent) => { + e.preventDefault(); + // AUTOCOMPLETION TEST: mutate arg should suggest ownerId, name, label, schemaName, etc. + mutate({ + ownerId: userId, + name: name.toLowerCase().replace(/[^a-z0-9_]/g, '_'), + label: label || null, + }); + }; + + return ( +
+

Create Database

+
+ setName(e.target.value)} required style={inputStyle} /> + setLabel(e.target.value)} style={inputStyle} /> + +
+ {error &&

{error.message}

} + {result &&
{JSON.stringify(result.createDatabase.database, null, 2)}
} +
+ ); +} + +function UpdateDatabaseForm() { + const [id, setId] = useState(''); + const [label, setLabel] = useState(''); + const { mutate, isPending, error, data: result } = useUpdateDatabaseMutation({ + selection: { fields: { id: true, name: true, label: true } }, + }); + + const handleSubmit = (e: FormEvent) => { + e.preventDefault(); + // AUTOCOMPLETION TEST: patch should suggest DatabasePatch fields — ownerId, name, label, etc. + mutate({ id, patch: { label } }); + }; + + return ( +
+

Update Database

+
+ setId(e.target.value)} required style={{ ...inputStyle, fontFamily: 'monospace', fontSize: 12 }} /> + setLabel(e.target.value)} required style={inputStyle} /> + +
+ {error &&

{error.message}

} + {result &&
{JSON.stringify(result.updateDatabase.database, null, 2)}
} +
+ ); +} + +function DeleteDatabaseForm() { + const [id, setId] = useState(''); + const [confirm, setConfirm] = useState(false); + const { mutate, isPending, error, data: result } = useDeleteDatabaseMutation({ + selection: { fields: { id: true, name: true } }, + }); + + const handleSubmit = (e: FormEvent) => { + e.preventDefault(); + if (!confirm) return; + mutate({ id }); + }; + + return ( +
+

Delete Database

+
+ { setId(e.target.value); setConfirm(false); }} required style={{ ...inputStyle, fontFamily: 'monospace', fontSize: 12 }} /> + + +
+ {error &&

{error.message}

} + {result &&
Deleted: {JSON.stringify(result.deleteDatabase.database, null, 2)}
} +
+ ); +} + +// =========================================================================== +// SECTION: Schema & API Management +// =========================================================================== + +function SchemaList() { + const { data, isLoading, error } = useSchemasQuery({ + selection: { + fields: { + id: true, + name: true, + schemaName: true, + isPublic: true, + // NESTED RELATION: parent database + database: { + select: { id: true, name: true }, + }, + }, + first: 20, + }, + }); + + if (isLoading) return

Loading schemas...

; + if (error) return

Error: {error.message}

; + + const schemas = data?.schemas?.nodes ?? []; + + return ( +
+

Schemas ({schemas.length})

+ [ + s.schemaName, + s.name, + s.database?.name ?? '—', + s.isPublic ? 'Yes' : 'No', + ]} + /> +
+ ); +} + +function CreateSchemaForm() { + const [databaseId, setDatabaseId] = useState(''); + const [name, setName] = useState(''); + const [schemaName, setSchemaName] = useState(''); + const { mutate, isPending, error, data: result } = useCreateSchemaMutation({ + selection: { fields: { id: true, name: true, schemaName: true, isPublic: true } }, + }); + + const handleSubmit = (e: FormEvent) => { + e.preventDefault(); + // AUTOCOMPLETION TEST: mutate arg should suggest databaseId, name, schemaName, label, isPublic, etc. + mutate({ + databaseId, + name, + schemaName: schemaName.toLowerCase().replace(/[^a-z0-9_]/g, '_'), + }); + }; + + return ( +
+

Create Schema

+
+ setDatabaseId(e.target.value)} required style={{ ...inputStyle, fontFamily: 'monospace', fontSize: 12 }} /> + setName(e.target.value)} required style={inputStyle} /> + setSchemaName(e.target.value)} required style={inputStyle} /> + +
+ {error &&

{error.message}

} + {result &&
{JSON.stringify(result.createSchema.schema, null, 2)}
} +
+ ); +} + +function ApiList() { + const { data, isLoading, error } = useApisQuery({ + selection: { + fields: { + id: true, + name: true, + dbname: true, + roleName: true, + anonRole: true, + isPublic: true, + // NESTED RELATION: parent database + database: { + select: { id: true, name: true }, + }, + }, + first: 20, + }, + }); + + if (isLoading) return

Loading APIs...

; + if (error) return

Error: {error.message}

; + + const apis = data?.apis?.nodes ?? []; + + return ( +
+

APIs ({apis.length})

+ [ + api.name, + api.dbname, + api.roleName, + api.database?.name ?? '—', + api.isPublic ? 'Yes' : 'No', + ]} + /> +
+ ); +} + +function CreateApiForm() { + const [databaseId, setDatabaseId] = useState(''); + const [name, setName] = useState(''); + const { mutate, isPending, error, data: result } = useCreateApiMutation({ + selection: { fields: { id: true, name: true, dbname: true, roleName: true, anonRole: true, isPublic: true } }, + }); + + const handleSubmit = (e: FormEvent) => { + e.preventDefault(); + // AUTOCOMPLETION TEST: mutate arg should suggest databaseId, name, dbname, roleName, anonRole, isPublic + mutate({ databaseId, name }); + }; + + return ( +
+

Create API

+
+ setDatabaseId(e.target.value)} required style={{ ...inputStyle, fontFamily: 'monospace', fontSize: 12 }} /> + setName(e.target.value)} required style={inputStyle} /> + +
+ {error &&

{error.message}

} + {result &&
{JSON.stringify(result.createApi.api, null, 2)}
} +
+ ); +} + +// =========================================================================== +// SECTION: Site & Domain Management +// =========================================================================== + +function CreateSiteForm() { + const [databaseId, setDatabaseId] = useState(''); + const [title, setTitle] = useState(''); + const [description, setDescription] = useState(''); + const { mutate, isPending, error, data: result } = useCreateSiteMutation({ + selection: { fields: { id: true, title: true, description: true, dbname: true } }, + }); + + const handleSubmit = (e: FormEvent) => { + e.preventDefault(); + // AUTOCOMPLETION TEST: mutate arg should suggest databaseId, title, description, favicon, ogImage, etc. + mutate({ databaseId, title, description: description || null }); + }; + + return ( +
+

Create Site

+
+ setDatabaseId(e.target.value)} required style={{ ...inputStyle, fontFamily: 'monospace', fontSize: 12 }} /> + setTitle(e.target.value)} required style={inputStyle} /> + setDescription(e.target.value)} style={inputStyle} /> + +
+ {error &&

{error.message}

} + {result &&
{JSON.stringify(result.createSite.site, null, 2)}
} +
+ ); +} + +function DomainList() { + const { data, isLoading, error } = useDomainsQuery({ + selection: { + fields: { + id: true, + subdomain: true, + domain: true, + // NESTED RELATIONS: api and site via FK + api: { select: { id: true, name: true } }, + site: { select: { id: true, title: true } }, + }, + first: 20, + }, + }); + + if (isLoading) return

Loading domains...

; + if (error) return

Error: {error.message}

; + + // AUTOCOMPLETION TEST: type `d.` — should suggest id, subdomain, domain, api, site + const domains = data?.domains?.nodes ?? []; + + return ( +
+

Domains ({domains.length})

+ [ + d.subdomain ?? '—', + d.domain ?? '—', + d.api?.name ?? '—', + d.site?.title ?? '—', + ]} + /> +
+ ); +} + +function CreateDomainForm() { + const [databaseId, setDatabaseId] = useState(''); + const [apiId, setApiId] = useState(''); + const [siteId, setSiteId] = useState(''); + const [subdomain, setSubdomain] = useState(''); + const [domain, setDomain] = useState(''); + const { mutate, isPending, error, data: result } = useCreateDomainMutation({ + selection: { fields: { id: true, subdomain: true, domain: true } }, + }); + + const handleSubmit = (e: FormEvent) => { + e.preventDefault(); + // AUTOCOMPLETION TEST: mutate arg should suggest databaseId, apiId, siteId, subdomain, domain + mutate({ databaseId, apiId, siteId, subdomain, domain }); + }; + + return ( +
+

Create Domain

+
+
+ setDatabaseId(e.target.value)} required style={{ ...inputStyle, fontFamily: 'monospace', fontSize: 12 }} /> + setApiId(e.target.value)} required style={{ ...inputStyle, fontFamily: 'monospace', fontSize: 12 }} /> + setSiteId(e.target.value)} required style={{ ...inputStyle, fontFamily: 'monospace', fontSize: 12 }} /> +
+
+ setSubdomain(e.target.value)} style={inputStyle} /> + setDomain(e.target.value)} style={inputStyle} /> + +
+
+ {error &&

{error.message}

} + {result &&
{JSON.stringify(result.createDomain.domain, null, 2)}
} +
+ ); +} + +// =========================================================================== +// Shared: Generic data table component +// =========================================================================== + +function DataTable({ + columns, + rows, + renderRow, +}: { + columns: string[]; + rows: T[]; + renderRow: (row: T) => (string | boolean | null | undefined)[]; +}) { + if (rows.length === 0) return

None

; + + return ( + + + + {columns.map((col) => ( + + ))} + + + + {rows.map((row) => ( + + {renderRow(row).map((cell, i) => ( + + ))} + + ))} + +
{col}
{cell ?? '—'}
+ ); +} + +// =========================================================================== +// Authenticated Dashboard +// =========================================================================== + +function Dashboard({ token, userId, onSignOut }: { token: string; userId: string; onSignOut: () => void }) { + const queryClient = useQueryClient(); + const [activeDbId, setActiveDbId] = useState(null); + + const { mutate: signOut, isPending: signingOut } = useSignOutMutation({ + onSuccess: () => { + queryClient.clear(); + onSignOut(); + }, + }); + + return ( +
+ {/* Header */} +
+
+ Authenticated + {token.slice(0, 20)}... +
+ +
+ + {/* Identity & Profile */} + + + + + {/* Users */} + + + + + + {/* Database Management */} + + + + + + + {/* Database Detail (enter an ID to inspect) */} +
+

Inspect Database (findOne)

+
+ setActiveDbId(e.target.value || null)} + style={{ ...inputStyle, fontFamily: 'monospace', fontSize: 12, flex: 1 }} + /> +
+
+ {activeDbId && } + + {/* Schemas & APIs */} + + + + + + + {/* Sites & Domains */} + + + + +
+ ); +} + +function SectionHeader({ title }: { title: string }) { + return ( +

+ {title} +

+ ); +} + +// =========================================================================== +// Main App +// =========================================================================== + +export default function App() { + const [auth, setAuth] = useState<{ token: string; userId: string } | null>(null); + const queryClient = useQueryClient(); + + const handleAuth = (token: string, userId: string) => { + reconfigureClient(token); + queryClient.clear(); + setAuth({ token, userId }); + }; + + const handleSignOut = () => { + reconfigureClient(); + setAuth(null); + }; + + return ( +
+

GraphQL Codegen Test App

+

+ Auth flow + CRUD mutations + nested relation queries with type-safe select. + Open src/App.tsx in your editor to inspect types. +

+ + {auth ? ( + + ) : ( + + )} +
+ ); +} + +// =========================================================================== +// Styles +// =========================================================================== + +const formStyle: React.CSSProperties = { + display: 'flex', + flexDirection: 'column', + gap: 10, + maxWidth: 360, +}; + +const rowForm: React.CSSProperties = { + display: 'flex', + gap: 8, + alignItems: 'flex-end', + flexWrap: 'wrap', +}; + +const inputStyle: React.CSSProperties = { + padding: '8px 12px', + border: '1px solid #d1d5db', + borderRadius: 6, + fontSize: 14, +}; + +const btnStyle: React.CSSProperties = { + padding: '8px 16px', + background: '#2563eb', + color: '#fff', + border: 'none', + borderRadius: 6, + fontSize: 14, + cursor: 'pointer', + whiteSpace: 'nowrap', +}; + +const btnSmall: React.CSSProperties = { + padding: '4px 10px', + color: '#fff', + border: 'none', + borderRadius: 4, + fontSize: 12, + cursor: 'pointer', +}; + +const tabStyle: React.CSSProperties = { + padding: '6px 16px', + background: 'none', + border: '1px solid #d1d5db', + borderRadius: 6, + fontSize: 14, + cursor: 'pointer', +}; + +const errStyle: React.CSSProperties = { + color: '#dc2626', + fontSize: 13, + marginTop: 4, +}; + +const cardStyle: React.CSSProperties = { + border: '1px solid #e5e7eb', + borderRadius: 8, + padding: 16, + marginBottom: 16, +}; + +const dlStyle: React.CSSProperties = { + display: 'grid', + gridTemplateColumns: 'auto 1fr', + gap: '4px 16px', + margin: 0, + fontSize: 14, +}; + +const tableStyle: React.CSSProperties = { + width: '100%', + borderCollapse: 'collapse', + fontSize: 14, +}; + +const thStyle: React.CSSProperties = { + textAlign: 'left', + borderBottom: '2px solid #e5e7eb', + padding: '6px 8px', +}; + +const tdStyle: React.CSSProperties = { + borderBottom: '1px solid #f3f4f6', + padding: '6px 8px', +}; + +const preStyle: React.CSSProperties = { + background: '#f9fafb', + padding: 12, + borderRadius: 6, + fontSize: 12, + overflow: 'auto', + marginTop: 8, +}; + +const badge: React.CSSProperties = { + display: 'inline-block', + padding: '2px 8px', + borderRadius: 4, + fontSize: 12, + marginRight: 4, +}; diff --git a/graphql/test-app/src/main.tsx b/graphql/test-app/src/main.tsx new file mode 100644 index 000000000..040b1e09f --- /dev/null +++ b/graphql/test-app/src/main.tsx @@ -0,0 +1,28 @@ +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; + +import { configure } from './generated/hooks'; +import App from './App.tsx'; + +// Configure the generated SDK client (no auth initially — App manages JWT) +configure({ + endpoint: 'http://api.localhost:3000/graphql', +}); + +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: false, + refetchOnWindowFocus: false, + }, + }, +}); + +createRoot(document.getElementById('root')!).render( + + + + + , +); diff --git a/graphql/test-app/src/type-tests/react-query-helpers-options.type-test.ts b/graphql/test-app/src/type-tests/react-query-helpers-options.type-test.ts new file mode 100644 index 000000000..3728e01d0 --- /dev/null +++ b/graphql/test-app/src/type-tests/react-query-helpers-options.type-test.ts @@ -0,0 +1,266 @@ +/** + * Compile-time regression checks for helper overloads and React Query options. + * + * Focus: + * - fetch/prefetch overload behavior + * - optional variables + required selection.fields custom query overloads + * - default vs explicit selection result narrowing in helpers + * - allowed/disallowed React Query options on generated hooks + */ + +import { QueryClient } from '@tanstack/react-query'; + +import { + fetchDatabasesQuery, + fetchGetObjectAtPathQuery, + prefetchDatabasesQuery, + prefetchGetObjectAtPathQuery, + useCurrentUserQuery, + useDatabasesQuery, + useGetObjectAtPathQuery, + useSignInMutation, +} from '../generated/hooks'; + +type Assert = T; +type HasKey = K extends keyof T ? true : false; +type NotHasKey = K extends keyof T ? false : true; + +function helperOverloadChecks() { + const queryClient = new QueryClient(); + + const defaultDatabasesFetch = fetchDatabasesQuery({ selection: { first: 2 } }); + type DefaultDatabaseNode = Awaited['databases']['nodes'][number]; + type _defaultDatabaseFetchOmitsName = Assert>; + + const selectedDatabasesFetch = fetchDatabasesQuery({ + selection: { + first: 2, + fields: { + id: true, + name: true, + schemas: { + first: 1, + select: { + id: true, + schemaName: true, + }, + }, + }, + }, + }); + type SelectedDatabaseNode = Awaited['databases']['nodes'][number]; + type _selectedDatabaseFetchHasName = Assert>; + + prefetchDatabasesQuery(queryClient, { selection: { first: 2 } }); + prefetchDatabasesQuery(queryClient, { + selection: { + first: 2, + fields: { + id: true, + name: true, + }, + }, + }); + + // @ts-expect-error invalid helper nested select key should be rejected + fetchDatabasesQuery({ selection: { fields: { schemas: { select: { invalidField: true } } } } }); + + const defaultGetObjectFetch = fetchGetObjectAtPathQuery({ variables: undefined }); + type DefaultGetObject = Awaited['getObjectAtPath']; + type _defaultGetObjectOmitsData = Assert>; + + const selectedGetObjectFetch = fetchGetObjectAtPathQuery({ + variables: undefined, + selection: { + fields: { + id: true, + data: true, + }, + }, + }); + type SelectedGetObject = Awaited['getObjectAtPath']; + type _selectedGetObjectHasData = Assert>; + + prefetchGetObjectAtPathQuery(queryClient, { variables: undefined }); + prefetchGetObjectAtPathQuery(queryClient, { + variables: undefined, + selection: { + fields: { + id: true, + }, + }, + }); + + // @ts-expect-error invalid custom helper select key should be rejected + prefetchGetObjectAtPathQuery(queryClient, { + variables: undefined, + selection: { fields: { invalidField: true } }, + }); + + // @ts-expect-error custom helper select overload requires explicit variables + fetchGetObjectAtPathQuery({ selection: { fields: { id: true } } }); + + // @ts-expect-error custom helper prefetch overload requires explicit variables + prefetchGetObjectAtPathQuery(queryClient, { selection: { fields: { id: true } } }); +} + +function reactQueryOptionsChecks() { + useDatabasesQuery({ + selection: { + first: 10, + fields: { + id: true, + name: true, + }, + }, + enabled: true, + staleTime: 30_000, + gcTime: 300_000, + retry: 2, + refetchOnWindowFocus: false, + refetchInterval: false, + refetchOnReconnect: true, + refetchOnMount: 'always', + networkMode: 'always', + notifyOnChangeProps: ['data', 'error'], + meta: { source: 'type-test' }, + }); + + const transformedDatabases = useDatabasesQuery({ + selection: { + first: 10, + fields: { + id: true, + name: true, + }, + }, + select: (data) => data.databases.nodes.map((node) => node.name), + placeholderData: (previousData) => + previousData ?? { + databases: { + nodes: [], + totalCount: 0, + pageInfo: { + hasNextPage: false, + hasPreviousPage: false, + }, + }, + }, + staleTime: (query) => { + const status = query.state.status; + void status; + return 10_000; + }, + throwOnError: (error) => error.message.length > 0, + }); + const transformedDatabaseNames: string[] | undefined = transformedDatabases.data; + void transformedDatabaseNames; + // @ts-expect-error transformed query data should not expose connection shape + transformedDatabases.data.databases; + + const transformedCurrentUser = useCurrentUserQuery({ + select: (data) => data.currentUser.id, + placeholderData: (previousData) => + previousData ?? { + currentUser: { + id: 'fallback-user-id', + }, + }, + enabled: false, + staleTime: 5_000, + gcTime: 60_000, + retry: (failureCount, error) => { + const msg = error.message; + void msg; + return failureCount < 2; + }, + }); + const transformedCurrentUserId: string | undefined = transformedCurrentUser.data; + void transformedCurrentUserId; + // @ts-expect-error transformed query data should not expose object shape + transformedCurrentUser.data.currentUser; + + useGetObjectAtPathQuery({ + variables: undefined, + selection: { + fields: { + id: true, + }, + }, + enabled: false, + staleTime: 5_000, + gcTime: 60_000, + placeholderData: { + getObjectAtPath: { + id: 'placeholder', + }, + }, + select: (data) => data.getObjectAtPath.id, + }); + + // @ts-expect-error unknown React Query option should be rejected + useDatabasesQuery({ selection: { fields: { id: true } }, unknownOption: true }); + + // @ts-expect-error queryKey is owned by generated hooks + useDatabasesQuery({ selection: { fields: { id: true } }, queryKey: ['override'] as const }); + + // @ts-expect-error queryFn is owned by generated hooks + useDatabasesQuery({ + selection: { fields: { id: true } }, + queryFn: async () => + ({ + databases: { + nodes: [], + totalCount: 0, + pageInfo: { + hasNextPage: false, + hasPreviousPage: false, + }, + }, + }) as never, + }); + + useSignInMutation({ + selection: { + fields: { + clientMutationId: true, + }, + }, + retry: 1, + gcTime: 300_000, + meta: { source: 'type-test' }, + networkMode: 'always', + throwOnError: (error) => error.message.length > 0, + onMutate: (variables) => { + const email = variables.input.email; + return { email }; + }, + onError: (error, variables, context) => { + const message = error.message; + const rememberMe = variables.input.rememberMe; + void message; + void rememberMe; + void context; + }, + onSuccess: (data, variables) => { + const clientMutationId = data.signIn.clientMutationId; + const email = variables.input.email; + void clientMutationId; + void email; + }, + }); + + // @ts-expect-error mutationFn is owned by generated hooks + useSignInMutation({ + selection: { fields: { clientMutationId: true } }, + mutationFn: async () => + ({ + signIn: { + clientMutationId: 'x', + }, + }) as never, + }); +} + +void helperOverloadChecks; +void reactQueryOptionsChecks; diff --git a/graphql/test-app/src/type-tests/react-query-orm-overloads.type-test.ts b/graphql/test-app/src/type-tests/react-query-orm-overloads.type-test.ts new file mode 100644 index 000000000..c44f21281 --- /dev/null +++ b/graphql/test-app/src/type-tests/react-query-orm-overloads.type-test.ts @@ -0,0 +1,306 @@ +/** + * Compile-time regression checks for React Query + ORM output modes. + * + * These checks focus on overload behavior introduced to recover contextual + * typing/autocomplete for nested select objects. + */ + +import { + useCurrentUserQuery, + useGetObjectAtPathQuery, + useSignInMutation, + useUserQuery, + useUsersQuery, +} from '../generated/hooks'; +import { createClient } from '../generated/orm'; + +type Assert = T; +type HasKey = K extends keyof T ? true : false; +type NotHasKey = K extends keyof T ? false : true; + +const ormClient = createClient({ + endpoint: 'https://example.invalid/graphql', +}); + +function hookTypeChecks() { + const currentUser = useCurrentUserQuery({ + selection: { + fields: { + id: true, + username: true, + }, + } + }); + + const maybeUsername = currentUser.data?.currentUser.username; + void maybeUsername; + + const defaultUser = useUserQuery({ id: '00000000-0000-0000-0000-000000000000' }); + const defaultUserId = defaultUser.data?.user?.id; + void defaultUserId; + // @ts-expect-error default select for useUserQuery should not expose username + defaultUser.data?.user?.username; + + const selectedUser = useUserQuery({ + id: '00000000-0000-0000-0000-000000000000', + selection: { + fields: { + id: true, + username: true, + }, + }, + }); + const selectedUsername = selectedUser.data?.user?.username; + void selectedUsername; + + const users = useUsersQuery({ + selection: { + fields: { + id: true, + databasesByOwnerId: { + first: 2, + select: { + id: true, + schemaName: true, + name: true + }, + }, + }, + first: 5, + orderBy: ['CREATED_AT_DESC'], + }, + }); + + const nestedSchema = users.data?.users.nodes[0]?.databasesByOwnerId?.nodes[0]?.schemaName; + void nestedSchema; + + // Optional variables + required select args overload (custom query case) + useGetObjectAtPathQuery({ + variables: undefined, + selection: { + fields: { + id: true, + data: true, + }, + }, + }); + + const defaultSignIn = useSignInMutation(); + const defaultSignInClientMutationId = defaultSignIn.data?.signIn.clientMutationId; + void defaultSignInClientMutationId; + // @ts-expect-error default signIn select should not expose result + defaultSignIn.data?.signIn.result; + + useSignInMutation({ + selection: { + fields: { + clientMutationId: true, + result: { + select: { + accessToken: true, + accessTokenExpiresAt: true, + isVerified: true, + totpEnabled: true, + userId: true, + }, + }, + }, + }, + }); + + const validSignInSelect = { + clientMutationId: true, + result: { + select: { + accessToken: true, + isVerified: true, + totpEnabled: true, + userId: true, + }, + }, + }; + useSignInMutation({ selection: { fields: validSignInSelect } }); + + const invalidUsersSelect = { + id: true, + invalidField: true, + }; + // @ts-expect-error invalid variable select key should be rejected + useUsersQuery({ selection: { fields: invalidUsersSelect } }); + + const invalidNestedUsersSelect = { + databasesByOwnerId: { + select: { + id: true, + doesNotExist: true, + }, + }, + }; + // @ts-expect-error invalid nested variable select key should be rejected + useUsersQuery({ selection: { fields: invalidNestedUsersSelect } }); + + const invalidCurrentUserSelect = { + id: true, + nope: true, + }; + // @ts-expect-error invalid variable select key should be rejected + useCurrentUserQuery({ selection: { fields: invalidCurrentUserSelect } }); + + const invalidSignInSelect = { + result: { + select: { + accessToken: true, + nope: true, + }, + }, + }; + // @ts-expect-error invalid mutation variable select key should be rejected + useSignInMutation({ selection: { fields: invalidSignInSelect } }); + + // @ts-expect-error invalid nested select key should be rejected + useUsersQuery({ + selection: { + fields: { + databasesByOwnerId: { + select: { + doesNotExist: true, + }, + }, + }, + }, + }); + + // @ts-expect-error invalid custom query select key should be rejected + useGetObjectAtPathQuery({ + variables: undefined, + selection: { fields: { nope: true } }, + }); +} + +async function ormModelTypeChecks() { + const defaultBuilder = ormClient.user.findOne({ + id: '00000000-0000-0000-0000-000000000000', + }); + type DefaultUser = Awaited>['user']; + type _defaultOmitsUsername = Assert, 'username'>>; + + const defaultSelected = await defaultBuilder.unwrapOr({ user: null }); + + if (defaultSelected.user) { + const id: string = defaultSelected.user.id; + void id; + } + + const explicitlySelected = ormClient.user.findOne({ + id: '00000000-0000-0000-0000-000000000000', + select: { + id: true, + username: true, + databasesByOwnerId: { + first: 1, + select: { + id: true, + schemaName: true, + }, + }, + }, + }); + + type ExplicitUser = Awaited>['user']; + type _explicitHasUsername = Assert, 'username'>>; + + ormClient.user.findMany({ + first: 5, + select: { + id: true, + username: true, + databasesByOwnerId: { + first: 1, + select: { + id: true, + schemaName: true, + }, + }, + }, + }); + + ormClient.query.currentUser({ + select: { + id: true, + username: true, + databasesByOwnerId: { + first: 1, + select: { + id: true, + }, + }, + }, + }); + + ormClient.query.getObjectAtPath( + { + dbId: '00000000-0000-0000-0000-000000000000', + path: ['root'], + refname: 'main', + }, + { + select: { + id: true, + }, + } + ); + + // @ts-expect-error invalid model select key should be rejected + ormClient.user.findMany({ select: { invalidField: true } }); + + // @ts-expect-error invalid custom query select key should be rejected + ormClient.query.currentUser({ select: { invalidField: true } }); + + const invalidModelSelect = { + id: true, + invalidField: true, + }; + // @ts-expect-error invalid model variable select key should be rejected + ormClient.user.findMany({ select: invalidModelSelect }); + + const invalidNestedModelSelect = { + databasesByOwnerId: { + select: { + id: true, + invalidField: true, + }, + }, + }; + // @ts-expect-error invalid nested model variable select key should be rejected + ormClient.user.findMany({ select: invalidNestedModelSelect }); + + const invalidCustomQuerySelect = { + id: true, + invalidField: true, + }; + // @ts-expect-error invalid custom query variable select key should be rejected + ormClient.query.currentUser({ select: invalidCustomQuerySelect }); + + const invalidCustomMutationSelect = { + result: { + select: { + accessToken: true, + invalidField: true, + }, + }, + }; + ormClient.mutation.signIn( + { + input: { + email: 'dev@example.com', + password: 'password', + rememberMe: true, + }, + }, + // @ts-expect-error invalid custom mutation variable select key should be rejected + { select: invalidCustomMutationSelect } + ); +} + +void hookTypeChecks; +void ormModelTypeChecks; diff --git a/graphql/test-app/src/type-tests/select-strictness-regressions.type-test.ts b/graphql/test-app/src/type-tests/select-strictness-regressions.type-test.ts new file mode 100644 index 000000000..9c4e6a305 --- /dev/null +++ b/graphql/test-app/src/type-tests/select-strictness-regressions.type-test.ts @@ -0,0 +1,200 @@ +/** + * Additional compile-time regression checks focused on strict selection behavior. + * + * These tests target edge cases around: + * - nested relation select options (filter/orderBy) + * - invalid relation option keys + * - default vs explicit selection result narrowing + * - custom ORM operation option contracts + */ + +import { + useDatabasesQuery, + useSignInMutation, +} from '../generated/hooks'; +import { createClient } from '../generated/orm'; + +type Assert = T; +type HasKey = K extends keyof T ? true : false; +type NotHasKey = K extends keyof T ? false : true; + +const ormClient = createClient({ + endpoint: 'https://example.invalid/graphql', +}); + +function hookStrictnessChecks() { + const defaultDatabases = useDatabasesQuery({ selection: { first: 10 } }); + const defaultDatabaseId = defaultDatabases.data?.databases.nodes[0]?.id; + void defaultDatabaseId; + // @ts-expect-error default select for useDatabasesQuery should not expose name + defaultDatabases.data?.databases.nodes[0]?.name; + + const selectedDatabases = useDatabasesQuery({ + selection: { + first: 10, + where: { + and: [ + { name: { includesInsensitive: 'prod' } }, + { createdAt: { greaterThanOrEqualTo: '2026-01-01T00:00:00.000Z' } }, + ], + }, + orderBy: ['CREATED_AT_DESC'], + fields: { + id: true, + name: true, + schemas: { + first: 5, + filter: { + schemaName: { startsWithInsensitive: 'app_' }, + isPublic: { equalTo: true }, + }, + orderBy: ['SCHEMA_NAME_ASC'], + select: { + id: true, + schemaName: true, + isPublic: true, + }, + }, + }, + }, + }); + const selectedDatabaseName = selectedDatabases.data?.databases.nodes[0]?.name; + const selectedNestedSchema = selectedDatabases.data?.databases.nodes[0]?.schemas?.nodes[0]?.schemaName; + void selectedDatabaseName; + void selectedNestedSchema; + + // @ts-expect-error relation select options should use filter, not where + useDatabasesQuery({ + selection: { + fields: { + schemas: { + where: { + schemaName: { equalTo: 'public' }, + }, + select: { + id: true, + }, + }, + }, + }, + }); + + // @ts-expect-error invalid field inside nested relation filter should be rejected + useDatabasesQuery({ + selection: { + fields: { + schemas: { + filter: { + invalidField: { equalTo: 'x' }, + }, + select: { + id: true, + }, + }, + }, + }, + }); + + // @ts-expect-error invalid orderBy literal should be rejected + useDatabasesQuery({ + selection: { + fields: { + schemas: { + orderBy: ['INVALID_ASC'], + select: { + id: true, + }, + }, + }, + }, + }); + + const validSignInSelect = { + clientMutationId: true, + result: { + select: { + accessToken: true, + userId: true, + }, + }, + }; + useSignInMutation({ selection: { fields: validSignInSelect } }); + + const invalidSignInNested = { + clientMutationId: true, + result: { + select: { + accessToken: true, + invalidNestedField: true, + }, + }, + }; + // @ts-expect-error invalid nested variable select field should be rejected + useSignInMutation({ selection: { fields: invalidSignInNested } }); +} + +async function ormStrictnessChecks() { + const defaultCurrentUser = ormClient.query.currentUser(); + type DefaultCurrentUser = Awaited>['currentUser']; + type _defaultCurrentUserOmitsUsername = Assert>; + + const selectedCurrentUser = ormClient.query.currentUser({ + select: { + id: true, + username: true, + }, + }); + type SelectedCurrentUser = Awaited>['currentUser']; + type _selectedCurrentUserHasUsername = Assert>; + + // @ts-expect-error custom ORM query options object requires select when provided + ormClient.query.currentUser({}); + + const defaultSignIn = ormClient.mutation.signIn({ + input: { + email: 'dev@example.com', + password: 'password', + rememberMe: true, + }, + }); + type DefaultSignIn = Awaited>['signIn']; + type _defaultSignInOmitsResult = Assert>; + + const selectedSignIn = ormClient.mutation.signIn( + { + input: { + email: 'dev@example.com', + password: 'password', + rememberMe: true, + }, + }, + { + select: { + clientMutationId: true, + result: { + select: { + accessToken: true, + userId: true, + }, + }, + }, + } + ); + type SelectedSignIn = Awaited>['signIn']; + type _selectedSignInHasResult = Assert>; + + ormClient.mutation.signIn( + { + input: { + email: 'dev@example.com', + password: 'password', + rememberMe: true, + }, + }, + // @ts-expect-error custom ORM mutation options object requires select when provided + {} + ); +} + +void hookStrictnessChecks; +void ormStrictnessChecks; diff --git a/graphql/test-app/src/vite-env.d.ts b/graphql/test-app/src/vite-env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/graphql/test-app/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/graphql/test-app/tests/hook-test-utils.ts b/graphql/test-app/tests/hook-test-utils.ts new file mode 100644 index 000000000..a2957109f --- /dev/null +++ b/graphql/test-app/tests/hook-test-utils.ts @@ -0,0 +1,85 @@ +import assert from 'node:assert/strict'; + +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import React from 'react'; +import { act, create, type ReactTestRenderer } from 'react-test-renderer'; + +type WaitForOptions = { + timeoutMs?: number; + intervalMs?: number; +}; + +export interface HookHarness { + getResult: () => TResult; + waitFor: (predicate: (result: TResult) => boolean, options?: WaitForOptions) => Promise; + unmount: () => Promise; +} + +const DEFAULT_TIMEOUT_MS = 20_000; +const DEFAULT_INTERVAL_MS = 30; + +function sleep(ms: number): Promise { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); +} + +export async function renderHookWithClient( + useHook: () => TResult, + queryClient: QueryClient +): Promise> { + // Enables React's act() environment checks for non-Jest runtimes. + (globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true; + + let renderer: ReactTestRenderer | null = null; + let latestResult: TResult | undefined; + + function Probe() { + latestResult = useHook(); + return null; + } + + await act(async () => { + renderer = create( + React.createElement( + QueryClientProvider, + { client: queryClient }, + React.createElement(Probe, null) + ) + ); + }); + + return { + getResult() { + assert.notEqual(latestResult, undefined, 'Hook result is not ready yet'); + return latestResult; + }, + + async waitFor(predicate, options) { + const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS; + const intervalMs = options?.intervalMs ?? DEFAULT_INTERVAL_MS; + const start = Date.now(); + + while (Date.now() - start < timeoutMs) { + const result = this.getResult(); + if (predicate(result)) { + return result; + } + await act(async () => { + await sleep(intervalMs); + }); + } + + throw new Error(`Timed out waiting for hook condition after ${timeoutMs}ms`); + }, + + async unmount() { + if (!renderer) { + return; + } + await act(async () => { + renderer?.unmount(); + }); + }, + }; +} diff --git a/graphql/test-app/tests/hooks.live.test.ts b/graphql/test-app/tests/hooks.live.test.ts new file mode 100644 index 000000000..d780a88b4 --- /dev/null +++ b/graphql/test-app/tests/hooks.live.test.ts @@ -0,0 +1,341 @@ +import assert from 'node:assert/strict'; +import { after, before, describe, test } from 'node:test'; + +import { act } from 'react-test-renderer'; + +import { + currentUserIdQueryKey, + currentUserQueryKey, + fetchCurrentUserIdQuery, + fetchCurrentUserQuery, + fetchUserQuery, + fetchUsersQuery, + prefetchCurrentUserIdQuery, + prefetchCurrentUserQuery, + prefetchUserQuery, + prefetchUsersQuery, + useCheckPasswordMutation, + useCurrentUserIdQuery, + useCurrentUserQuery, + useSignInMutation, + useSignOutMutation, + useUserQuery, + useUsersQuery, + userQueryKey, + usersQueryKey, +} from '../src/generated/hooks'; + +import { renderHookWithClient } from './hook-test-utils'; +import { + assertLiveEnvConfigured, + configureHooks, + createTestQueryClient, + getLiveEnvHelpMessage, + getLiveTestEnv, + type AuthSession, + signIn, + signOut, +} from './live-test-utils'; + +const liveEnv = getLiveTestEnv(); +assertLiveEnvConfigured(liveEnv); + +if (!liveEnv) { + test.skip(getLiveEnvHelpMessage(), () => {}); +} else { + describe('React Query Hooks (live endpoint)', () => { + let sharedSession: AuthSession | null = null; + + const ensureAuth = async (): Promise => { + if (!sharedSession) { + sharedSession = await signIn(liveEnv); + } + configureHooks(liveEnv, sharedSession.token); + return sharedSession; + }; + + before(() => { + configureHooks(liveEnv); + }); + + after(async () => { + if (sharedSession) { + await signOut(liveEnv, sharedSession.token); + sharedSession = null; + } + configureHooks(liveEnv); + }); + + test('useSignInMutation returns token payload when explicit select is provided', async () => { + const queryClient = createTestQueryClient(); + const hook = await renderHookWithClient( + () => + useSignInMutation({ + select: { + result: { + select: { + accessToken: true, + userId: true, + isVerified: true, + totpEnabled: true, + }, + }, + }, + }), + queryClient + ); + + let result: + | { + signIn: { + result?: { + accessToken?: string | null; + userId?: string | null; + isVerified?: boolean | null; + totpEnabled?: boolean | null; + } | null; + }; + } + | null = null; + + await act(async () => { + result = await hook.getResult().mutateAsync({ + input: { + email: liveEnv.email, + password: liveEnv.password, + rememberMe: true, + }, + }); + }); + + const token = result?.signIn.result?.accessToken ?? null; + const userId = result?.signIn.result?.userId ?? null; + assert.ok(token, 'useSignInMutation did not return accessToken'); + assert.ok(userId, 'useSignInMutation did not return userId'); + + await signOut(liveEnv, token); + await hook.unmount(); + queryClient.clear(); + }); + + test('useCurrentUserQuery returns nested selected relation fields', async () => { + await ensureAuth(); + const queryClient = createTestQueryClient(); + const hook = await renderHookWithClient( + () => + useCurrentUserQuery({ + select: { + id: true, + username: true, + databasesByOwnerId: { + first: 1, + select: { + id: true, + schemaName: true, + }, + }, + }, + }), + queryClient + ); + + const result = await hook.waitFor((value) => value.isSuccess || value.isError); + assert.equal(result.isError, false, 'useCurrentUserQuery returned an error'); + assert.ok(result.data?.currentUser?.id, 'currentUser.id is missing'); + assert.ok( + Array.isArray(result.data?.currentUser?.databasesByOwnerId?.nodes), + 'currentUser.databasesByOwnerId.nodes should be an array' + ); + + await hook.unmount(); + queryClient.clear(); + }); + + test('useCurrentUserIdQuery matches useCurrentUserQuery id', async () => { + const session = await ensureAuth(); + const queryClient = createTestQueryClient(); + const hook = await renderHookWithClient(() => useCurrentUserIdQuery(), queryClient); + + const result = await hook.waitFor((value) => value.isSuccess || value.isError); + assert.equal(result.isError, false, 'useCurrentUserIdQuery returned an error'); + assert.equal(result.data?.currentUserId, session.userId, 'currentUserId does not match signed in user'); + + await hook.unmount(); + queryClient.clear(); + }); + + test('useUsersQuery and useUserQuery execute with select overloads', async () => { + const session = await ensureAuth(); + const queryClient = createTestQueryClient(); + + const usersHook = await renderHookWithClient( + () => + useUsersQuery({ + first: 5, + orderBy: ['CREATED_AT_DESC'], + select: { + id: true, + username: true, + databasesByOwnerId: { + first: 1, + select: { + id: true, + }, + }, + }, + }), + queryClient + ); + + const usersResult = await usersHook.waitFor((value) => value.isSuccess || value.isError); + assert.equal(usersResult.isError, false, 'useUsersQuery returned an error'); + assert.ok(Array.isArray(usersResult.data?.users.nodes), 'users.nodes should be an array'); + + const userHook = await renderHookWithClient( + () => + useUserQuery({ + id: session.userId, + select: { + id: true, + username: true, + }, + }), + queryClient + ); + + const userResult = await userHook.waitFor((value) => value.isSuccess || value.isError); + assert.equal(userResult.isError, false, 'useUserQuery returned an error'); + assert.equal(userResult.data?.user?.id, session.userId, 'useUserQuery did not return the requested user'); + + await usersHook.unmount(); + await userHook.unmount(); + queryClient.clear(); + }); + + test('fetch/prefetch helpers populate QueryClient cache with expected keys', async () => { + const session = await ensureAuth(); + const queryClient = createTestQueryClient(); + + const currentUser = await fetchCurrentUserQuery({ + select: { + id: true, + username: true, + }, + }); + assert.equal(currentUser.currentUser.id, session.userId, 'fetchCurrentUserQuery returned unexpected user'); + + const currentUserId = await fetchCurrentUserIdQuery(); + assert.equal(currentUserId.currentUserId, session.userId, 'fetchCurrentUserIdQuery returned unexpected user'); + + const usersArgs = { + first: 3, + select: { + id: true, + username: true, + }, + } as const; + const usersData = await fetchUsersQuery(usersArgs); + assert.ok(Array.isArray(usersData.users.nodes), 'fetchUsersQuery users.nodes should be an array'); + + const userData = await fetchUserQuery({ + id: session.userId, + select: { + id: true, + username: true, + }, + }); + assert.equal(userData.user?.id, session.userId, 'fetchUserQuery returned unexpected user'); + + await prefetchCurrentUserQuery(queryClient, { + select: { + id: true, + username: true, + }, + }); + await prefetchCurrentUserIdQuery(queryClient); + await prefetchUsersQuery(queryClient, usersArgs); + await prefetchUserQuery(queryClient, { id: session.userId }); + + assert.ok(queryClient.getQueryData(currentUserQueryKey()), 'currentUser cache entry missing'); + assert.ok(queryClient.getQueryData(currentUserIdQueryKey()), 'currentUserId cache entry missing'); + assert.ok(queryClient.getQueryData(usersQueryKey(usersArgs)), 'users cache entry missing'); + assert.ok( + queryClient.getQueryData(userQueryKey(session.userId)), + 'user detail cache entry missing' + ); + + queryClient.clear(); + }); + + test('useCheckPasswordMutation succeeds for the signed-in user', async () => { + await ensureAuth(); + const queryClient = createTestQueryClient(); + const hook = await renderHookWithClient( + () => + useCheckPasswordMutation({ + select: { + clientMutationId: true, + }, + }), + queryClient + ); + + let result: + | { + checkPassword: { + clientMutationId?: string | null; + }; + } + | null = null; + + await act(async () => { + result = await hook.getResult().mutateAsync({ + input: { + password: liveEnv.password, + }, + }); + }); + + assert.ok(result?.checkPassword, 'useCheckPasswordMutation returned empty payload'); + + await hook.unmount(); + queryClient.clear(); + }); + + test('useSignOutMutation signs out current session', async () => { + const session = await ensureAuth(); + const queryClient = createTestQueryClient(); + const hook = await renderHookWithClient( + () => + useSignOutMutation({ + select: { + clientMutationId: true, + }, + }), + queryClient + ); + + let result: + | { + signOut: { + clientMutationId?: string | null; + }; + } + | null = null; + + await act(async () => { + result = await hook.getResult().mutateAsync({ + input: {}, + }); + }); + + assert.ok(result?.signOut, 'useSignOutMutation returned empty payload'); + sharedSession = null; + configureHooks(liveEnv); + await signOut(liveEnv, session.token); + + await hook.unmount(); + queryClient.clear(); + }); + }); +} diff --git a/graphql/test-app/tests/live-test-utils.ts b/graphql/test-app/tests/live-test-utils.ts new file mode 100644 index 000000000..9befa2135 --- /dev/null +++ b/graphql/test-app/tests/live-test-utils.ts @@ -0,0 +1,130 @@ +import assert from 'node:assert/strict'; + +import { QueryClient } from '@tanstack/react-query'; + +import { configure } from '../src/generated/hooks/client'; +import { createClient } from '../src/generated/orm'; + +export interface LiveTestEnv { + endpoint: string; + email: string; + password: string; +} + +const DEFAULT_ENDPOINT = 'https://api.launchql.dev/graphql'; + +export function getLiveTestEnv(): LiveTestEnv | null { + const email = process.env.GRAPHQL_TEST_EMAIL; + const password = process.env.GRAPHQL_TEST_PASSWORD; + const endpoint = process.env.GRAPHQL_TEST_ENDPOINT ?? DEFAULT_ENDPOINT; + + if (!email || !password) { + return null; + } + + return { + endpoint, + email, + password, + }; +} + +export function getLiveEnvHelpMessage(): string { + return ( + 'Live tests require GRAPHQL_TEST_EMAIL and GRAPHQL_TEST_PASSWORD. ' + + `Optional GRAPHQL_TEST_ENDPOINT (default: ${DEFAULT_ENDPOINT}).` + ); +} + +export function assertLiveEnvConfigured( + env: LiveTestEnv | null +): asserts env is LiveTestEnv { + if (!env) { + if (process.env.GRAPHQL_TEST_LIVE_REQUIRED === '1') { + throw new Error(getLiveEnvHelpMessage()); + } + } +} + +export function createTestQueryClient(): QueryClient { + return new QueryClient({ + defaultOptions: { + queries: { + retry: false, + refetchOnWindowFocus: false, + }, + mutations: { + retry: false, + }, + }, + }); +} + +export function configureHooks(env: LiveTestEnv, token?: string): void { + configure({ + endpoint: env.endpoint, + headers: token ? { Authorization: `Bearer ${token}` } : {}, + }); +} + +export interface AuthSession { + token: string; + userId: string; +} + +export async function signIn(env: LiveTestEnv): Promise { + const client = createClient({ endpoint: env.endpoint }); + const result = await client.mutation + .signIn( + { + input: { + email: env.email, + password: env.password, + rememberMe: true, + }, + }, + { + select: { + result: { + select: { + accessToken: true, + userId: true, + isVerified: true, + totpEnabled: true, + }, + }, + }, + } + ) + .unwrap(); + + const token = result.signIn.result?.accessToken ?? null; + const userId = result.signIn.result?.userId ?? null; + + assert.ok(token, 'signIn did not return accessToken'); + assert.ok(userId, 'signIn did not return userId'); + + return { token, userId }; +} + +export async function signOut(env: LiveTestEnv, token: string): Promise { + const client = createClient({ + endpoint: env.endpoint, + headers: { Authorization: `Bearer ${token}` }, + }); + + try { + await client.mutation + .signOut( + { input: {} }, + { + select: { + clientMutationId: true, + }, + } + ) + .unwrap(); + } catch { + // Best-effort cleanup: token might already be invalidated. + } +} diff --git a/graphql/test-app/tests/orm.live.test.ts b/graphql/test-app/tests/orm.live.test.ts new file mode 100644 index 000000000..d40952864 --- /dev/null +++ b/graphql/test-app/tests/orm.live.test.ts @@ -0,0 +1,232 @@ +import assert from 'node:assert/strict'; +import { after, describe, test } from 'node:test'; + +import { createClient } from '../src/generated/orm'; + +import { + assertLiveEnvConfigured, + getLiveEnvHelpMessage, + getLiveTestEnv, + type AuthSession, + signIn, + signOut, +} from './live-test-utils'; + +const liveEnv = getLiveTestEnv(); +assertLiveEnvConfigured(liveEnv); + +if (!liveEnv) { + test.skip(getLiveEnvHelpMessage(), () => {}); +} else { + describe('ORM Client (live endpoint)', () => { + let sharedSession: AuthSession | null = null; + + const ensureAuth = async (): Promise => { + if (!sharedSession) { + sharedSession = await signIn(liveEnv); + } + return sharedSession; + }; + + const createAuthedClient = async () => { + const session = await ensureAuth(); + return createClient({ + endpoint: liveEnv.endpoint, + headers: { Authorization: `Bearer ${session.token}` }, + }); + }; + + after(async () => { + if (sharedSession) { + await signOut(liveEnv, sharedSession.token); + sharedSession = null; + } + }); + + test('custom signIn mutation returns token with explicit select', async () => { + const client = createClient({ endpoint: liveEnv.endpoint }); + const result = await client.mutation + .signIn( + { + input: { + email: liveEnv.email, + password: liveEnv.password, + rememberMe: true, + }, + }, + { + select: { + result: { + select: { + accessToken: true, + userId: true, + isVerified: true, + }, + }, + }, + } + ) + .unwrap(); + + const token = result.signIn.result?.accessToken ?? null; + assert.ok(token, 'ORM signIn did not return accessToken'); + await signOut(liveEnv, token); + }); + + test('custom signIn mutation default select path returns payload shape', async () => { + const client = createClient({ endpoint: liveEnv.endpoint }); + + const result = await client.mutation.signIn( + { + input: { + email: liveEnv.email, + password: liveEnv.password, + rememberMe: true + } + }, + { + select: { + clientMutationId: true, + result: { + select: { + accessToken: true, + userId: true, + isVerified: true, + totpEnabled: true, + }, + }, + }, + } + ).unwrap(); + + assert.ok(result.signIn, 'Default signIn payload is missing'); + assert.ok(result.signIn?.result?.accessToken, 'Default signIn result is missing accessToken'); + await ensureAuth(); + }); + + test('model findMany builds expected GraphQL and executes nested select', async () => { + const client = await createAuthedClient(); + + const builder = client.user.findMany({ + first: 5, + orderBy: ['CREATED_AT_DESC'], + select: { + id: true, + username: true, + databasesByOwnerId: { + first: 1, + select: { + id: true, + schemaName: true, + }, + }, + }, + }); + + const graphql = builder.toGraphQL(); + const variables = builder.getVariables() ?? {}; + assert.match(graphql, /query UserQuery/); + assert.match(graphql, /users\(/); + assert.match(graphql, /databasesByOwnerId\(first: 1\)/); + assert.equal(variables.first, 5, 'findMany first variable should be emitted'); + + const result = await builder.unwrap(); + assert.ok(Array.isArray(result.users.nodes), 'users.nodes should be an array'); + }); + + test('model findOne overloads work for default and explicit select', async () => { + const session = await ensureAuth(); + const client = await createAuthedClient(); + + const defaultResult = await client.user.findOne({ id: session.userId }).unwrap(); + assert.equal(defaultResult.user?.id, session.userId, 'findOne default select returned wrong user'); + + const explicitResult = await client.user + .findOne({ + id: session.userId, + select: { + id: true, + username: true, + displayName: true, + }, + }) + .unwrap(); + + assert.equal(explicitResult.user?.id, session.userId, 'findOne explicit select returned wrong user'); + }); + + test('model findFirst and custom currentUser/currentUserId queries execute', async () => { + const session = await ensureAuth(); + const client = await createAuthedClient(); + + const firstResult = await client.user + .findFirst({ + select: { + id: true, + username: true, + }, + }) + .unwrap(); + assert.ok(Array.isArray(firstResult.users.nodes), 'findFirst should return users.nodes array'); + + const currentUserResult = await client.query + .currentUser({ + select: { + id: true, + username: true, + }, + }) + .unwrap(); + assert.equal( + currentUserResult.currentUser.id, + session.userId, + 'currentUser query returned unexpected user' + ); + + const currentUserIdResult = await client.query.currentUserId().unwrap(); + assert.equal( + currentUserIdResult.currentUserId, + session.userId, + 'currentUserId query returned unexpected user' + ); + }); + + test('custom checkPassword and signOut mutations execute successfully', async () => { + const session = await ensureAuth(); + const client = await createAuthedClient(); + + const checkPasswordResult = await client.mutation + .checkPassword( + { + input: { + password: liveEnv.password, + }, + }, + { + select: { + clientMutationId: true, + }, + } + ) + .unwrap(); + assert.ok(checkPasswordResult.checkPassword, 'checkPassword payload missing'); + + const signOutResult = await client.mutation + .signOut( + { + input: {}, + }, + { + select: { + clientMutationId: true, + }, + } + ) + .unwrap(); + assert.ok(signOutResult.signOut, 'signOut payload missing'); + + sharedSession = null; + await signOut(liveEnv, session.token); + }); + }); +} diff --git a/graphql/test-app/tsconfig.json b/graphql/test-app/tsconfig.json new file mode 100644 index 000000000..4bad3d23e --- /dev/null +++ b/graphql/test-app/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2023", "DOM", "DOM.Iterable"], + "module": "ESNext", + "moduleResolution": "bundler", + "strict": true, + "strictNullChecks": false, + "noEmit": true, + "esModuleInterop": true, + "skipLibCheck": true, + "jsx": "react-jsx", + "resolveJsonModule": true, + "isolatedModules": true, + "allowImportingTsExtensions": true + }, + "include": ["src"] +} diff --git a/graphql/test-app/vite.config.ts b/graphql/test-app/vite.config.ts new file mode 100644 index 000000000..2e3f72d38 --- /dev/null +++ b/graphql/test-app/vite.config.ts @@ -0,0 +1,19 @@ +import react from '@vitejs/plugin-react'; +import { defineConfig } from 'vite'; +import { visualizer } from 'rollup-plugin-visualizer'; + +export default defineConfig({ + plugins: [ + react(), + visualizer({ + filename: 'dist/bundle-stats.html', + open: false, + gzipSize: true, + brotliSize: true, + template: 'treemap', + }), + ], + server: { + port: 5199, + }, +}); diff --git a/package.json b/package.json index 6ef5a5fb4..a784ca712 100644 --- a/package.json +++ b/package.json @@ -16,8 +16,8 @@ }, "scripts": { "clean": "pnpm -r run clean", - "build": "pnpm -r run build", - "build:dev": "pnpm -r run build:dev", + "build": "pnpm -r --filter '!@constructive-io/test-codegen-app' run build", + "build:dev": "pnpm -r --filter '!@constructive-io/test-codegen-app' run build:dev", "lint": "pnpm -r run lint", "internal:deps": "makage update-workspace", "deps": "pnpm up -r -i -L" diff --git a/packages/cli/__tests__/codegen.test.ts b/packages/cli/__tests__/codegen.test.ts index 5fa4bcc48..cf941bfaa 100644 --- a/packages/cli/__tests__/codegen.test.ts +++ b/packages/cli/__tests__/codegen.test.ts @@ -15,16 +15,18 @@ jest.mock('@constructive-io/graphql-codegen', () => { return { generate: jest.fn(async () => ({ success: true, message: 'Generated SDK', filesWritten: [] as string[] })), findConfigFile: jest.fn((): string | undefined => undefined), + loadConfigFile: jest.fn(async () => ({ success: false, error: 'not found' })), + splitCommas: splitCommasMock, codegenQuestions: [ { name: 'endpoint', message: 'GraphQL endpoint URL', type: 'text', required: false }, - { name: 'schemaFile', message: 'Path to GraphQL schema file', type: 'text', required: false }, + { name: 'schema-file', message: 'Path to GraphQL schema file', type: 'text', required: false }, { name: 'output', message: 'Output directory', type: 'text', required: false, default: 'codegen', useDefault: true }, { name: 'schemas', message: 'PostgreSQL schemas', type: 'text', required: false, sanitize: splitCommasMock }, - { name: 'apiNames', message: 'API names', type: 'text', required: false, sanitize: splitCommasMock }, - { name: 'reactQuery', message: 'Generate React Query hooks?', type: 'confirm', required: false, default: false, useDefault: true }, + { name: 'api-names', message: 'API names', type: 'text', required: false, sanitize: splitCommasMock }, + { name: 'react-query', message: 'Generate React Query hooks?', type: 'confirm', required: false, default: false, useDefault: true }, { name: 'orm', message: 'Generate ORM client?', type: 'confirm', required: false, default: false, useDefault: true }, { name: 'authorization', message: 'Authorization header value', type: 'text', required: false }, - { name: 'dryRun', message: 'Preview without writing files?', type: 'confirm', required: false, default: false, useDefault: true }, + { name: 'dry-run', message: 'Preview without writing files?', type: 'confirm', required: false, default: false, useDefault: true }, { name: 'verbose', message: 'Verbose output?', type: 'confirm', required: false, default: false, useDefault: true }, ], printResult: jest.fn((result: any) => { @@ -36,6 +38,14 @@ jest.mock('@constructive-io/graphql-codegen', () => { } }), camelizeArgv: jest.fn((argv: Record) => argv), + seedArgvFromConfig: jest.fn((argv: Record, _fileConfig: any) => argv), + buildGenerateOptions: jest.fn((answers: Record, _fileConfig: any) => { + const { schemas, apiNames, ...rest } = answers; + if (schemas || apiNames) { + return { ...rest, db: { schemas, apiNames } }; + } + return rest; + }), }; }) diff --git a/packages/cli/src/commands/codegen.ts b/packages/cli/src/commands/codegen.ts index 0d41bccae..391807fb0 100644 --- a/packages/cli/src/commands/codegen.ts +++ b/packages/cli/src/commands/codegen.ts @@ -2,10 +2,12 @@ import { CLIOptions, Inquirerer } from 'inquirerer'; import { generate, findConfigFile, + loadConfigFile, codegenQuestions, printResult, - camelizeArgv, - type CodegenAnswers, + buildGenerateOptions, + seedArgvFromConfig, + type GraphQLSDKConfigTarget, } from '@constructive-io/graphql-codegen'; const usage = ` @@ -27,8 +29,6 @@ Generator Options: --orm Generate ORM client --output Output directory (default: codegen) --authorization Authorization header value - --browser-compatible Generate browser-compatible code (default: true) - Set to false for Node.js with localhost DNS fix --dry-run Preview without writing files --verbose Verbose output @@ -45,38 +45,26 @@ export default async ( process.exit(0); } - // Auto-detect config file if not provided - const config = argv.config || findConfigFile(); - if (config) { - // If config file exists, just run generate with it (config file handles everything) - const result = await generate({}); - printResult(result); - return; - } - - // No config file - prompt for options using shared questions - const answers = await prompter.prompt(argv as CodegenAnswers, codegenQuestions); - // Convert kebab-case CLI args to camelCase for internal use - const camelized = camelizeArgv(answers); + const hasSourceFlags = Boolean( + argv.endpoint || argv['schema-file'] || argv.schemas || argv['api-names'] + ); + const configPath = (argv.config as string | undefined) || + (!hasSourceFlags ? findConfigFile() : undefined); - // Build db config if schemas or apiNames provided - const db = (camelized.schemas || camelized.apiNames) ? { - schemas: camelized.schemas, - apiNames: camelized.apiNames, - } : undefined; + let fileConfig: GraphQLSDKConfigTarget = {}; - const result = await generate({ - endpoint: camelized.endpoint, - schemaFile: camelized.schemaFile, - db, - output: camelized.output, - authorization: camelized.authorization, - reactQuery: camelized.reactQuery, - orm: camelized.orm, - browserCompatible: camelized.browserCompatible, - dryRun: camelized.dryRun, - verbose: camelized.verbose, - }); + if (configPath) { + const loaded = await loadConfigFile(configPath); + if (!loaded.success) { + console.error('x', loaded.error); + process.exit(1); + } + fileConfig = loaded.config as GraphQLSDKConfigTarget; + } + const seeded = seedArgvFromConfig(argv as Record, fileConfig); + const answers = await prompter.prompt(seeded, codegenQuestions); + const options = buildGenerateOptions(answers, fileConfig); + const result = await generate(options); printResult(result); }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e00bbd5de..b329b3a2c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,6 +7,7 @@ settings: packageExtensionsChecksum: sha256-x8B4zkJ4KLRX+yspUWxuggXWlz6zrBLSIh72pNhpPiE= importers: + .: devDependencies: '@jest/test-sequencer': @@ -77,10 +78,10 @@ importers: version: link:../../packages/postmaster/dist '@launchql/mjml': specifier: 0.1.1 - version: 0.1.1(@babel/core@7.28.6)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react-is@18.3.1)(react@19.2.3) + version: 0.1.1(@babel/core@7.28.6)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react-is@19.2.4)(react@19.2.3) '@launchql/styled-email': specifier: 0.1.0 - version: 0.1.0(@babel/core@7.28.6)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react-is@18.3.1)(react@19.2.3) + version: 0.1.0(@babel/core@7.28.6)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react-is@19.2.4)(react@19.2.3) '@pgpmjs/env': specifier: workspace:^ version: link:../../pgpm/env/dist @@ -1239,6 +1240,58 @@ importers: version: 0.1.10 publishDirectory: dist + graphql/test-app: + dependencies: + '@0no-co/graphql.web': + specifier: ^1.2.0 + version: 1.2.0(graphql@15.10.1) + '@constructive-io/graphql-types': + specifier: workspace:^ + version: link:../types/dist + '@tanstack/react-query': + specifier: ^5.90.20 + version: 5.90.20(react@19.2.3) + gql-ast: + specifier: workspace:^ + version: link:../gql-ast/dist + graphql: + specifier: 15.10.1 + version: 15.10.1 + react: + specifier: ^19.2.3 + version: 19.2.3 + react-dom: + specifier: ^19.2.3 + version: 19.2.3(react@19.2.3) + devDependencies: + '@constructive-io/graphql-codegen': + specifier: workspace:^ + version: link:../codegen/dist + '@types/react': + specifier: ^19.2.13 + version: 19.2.13 + '@types/react-dom': + specifier: ^19.2.3 + version: 19.2.3(@types/react@19.2.13) + '@vitejs/plugin-react': + specifier: ^4.5.2 + version: 4.7.0(vite@6.4.1(@types/node@20.19.27)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2)) + react-test-renderer: + specifier: ^19.2.3 + version: 19.2.3(react@19.2.3) + rollup-plugin-visualizer: + specifier: ^6.0.5 + version: 6.0.5(rollup@4.57.1) + tsx: + specifier: ^4.20.3 + version: 4.21.0 + typescript: + specifier: ^5.8.3 + version: 5.9.3 + vite: + specifier: ^6.3.5 + version: 6.4.1(@types/node@20.19.27)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2) + graphql/types: dependencies: '@pgpmjs/types': @@ -2432,11 +2485,9 @@ importers: publishDirectory: dist packages: + '@0no-co/graphql.web@1.2.0': - resolution: - { - integrity: sha512-/1iHy9TTr63gE1YcR5idjx8UREz1s0kFhydf3bBLCXyqjhkIc6igAzTOx3zPifCwFR87tsh/4Pa9cNts6d2otw==, - } + resolution: {integrity: sha512-/1iHy9TTr63gE1YcR5idjx8UREz1s0kFhydf3bBLCXyqjhkIc6igAzTOx3zPifCwFR87tsh/4Pa9cNts6d2otw==} peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 peerDependenciesMeta: @@ -2444,399 +2495,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: @@ -2844,11 +2724,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: @@ -2856,798 +2733,657 @@ packages: optional: true '@aws-sdk/xml-builder@3.969.0': - resolution: - { - integrity: sha512-BSe4Lx/qdRQQdX8cSSI7Et20vqBspzAjBy8ZmXVoyLkol3y4sXBXzn+BiLtR+oh60ExQn6o2DU4QjdOZbXaKIQ==, - } - engines: { node: '>=20.0.0' } + resolution: {integrity: sha512-BSe4Lx/qdRQQdX8cSSI7Et20vqBspzAjBy8ZmXVoyLkol3y4sXBXzn+BiLtR+oh60ExQn6o2DU4QjdOZbXaKIQ==} + engines: {node: '>=20.0.0'} '@aws/lambda-invoke-store@0.2.3': - resolution: - { - integrity: sha512-oLvsaPMTBejkkmHhjf09xTgk71mOqyr/409NKhRIL08If7AhVfUsJhVsx386uJaqNd42v9kWamQ9lFbkoC2dYw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-oLvsaPMTBejkkmHhjf09xTgk71mOqyr/409NKhRIL08If7AhVfUsJhVsx386uJaqNd42v9kWamQ9lFbkoC2dYw==} + engines: {node: '>=18.0.0'} '@babel/code-frame@7.27.1': - resolution: - { - integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + engines: {node: '>=6.9.0'} '@babel/code-frame@7.28.6': - resolution: - { - integrity: sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==} + engines: {node: '>=6.9.0'} '@babel/compat-data@7.28.6': - resolution: - { - integrity: sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==} + engines: {node: '>=6.9.0'} '@babel/core@7.28.6': - resolution: - { - integrity: sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==} + engines: {node: '>=6.9.0'} '@babel/generator@7.28.6': - resolution: - { - integrity: sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==} + engines: {node: '>=6.9.0'} '@babel/helper-annotate-as-pure@7.27.3': - resolution: - { - integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} + engines: {node: '>=6.9.0'} '@babel/helper-compilation-targets@7.28.6': - resolution: - { - integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} + engines: {node: '>=6.9.0'} '@babel/helper-globals@7.28.0': - resolution: - { - integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} '@babel/helper-module-imports@7.27.1': - resolution: - { - integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + engines: {node: '>=6.9.0'} '@babel/helper-module-imports@7.28.6': - resolution: - { - integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} + engines: {node: '>=6.9.0'} '@babel/helper-module-transforms@7.28.6': - resolution: - { - integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} + engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 '@babel/helper-plugin-utils@7.27.1': - resolution: - { - integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} + engines: {node: '>=6.9.0'} '@babel/helper-plugin-utils@7.28.6': - resolution: - { - integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} + engines: {node: '>=6.9.0'} '@babel/helper-string-parser@7.27.1': - resolution: - { - integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} '@babel/helper-validator-identifier@7.28.5': - resolution: - { - integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} '@babel/helper-validator-option@7.27.1': - resolution: - { - integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} '@babel/helpers@7.28.6': - resolution: - { - integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==} + engines: {node: '>=6.9.0'} '@babel/parser@7.28.6': - resolution: - { - integrity: sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==, - } - engines: { node: '>=6.0.0' } + resolution: {integrity: sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==} + engines: {node: '>=6.0.0'} hasBin: true '@babel/plugin-syntax-async-generators@7.8.4': - resolution: - { - integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==, - } + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-bigint@7.8.3': - resolution: - { - integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==, - } + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-class-properties@7.12.13': - resolution: - { - integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==, - } + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-class-static-block@7.14.5': - resolution: - { - integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-import-attributes@7.28.6': - resolution: - { - integrity: sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==} + engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-import-meta@7.10.4': - resolution: - { - integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==, - } + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-json-strings@7.8.3': - resolution: - { - integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==, - } + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-jsx@7.27.1': - resolution: - { - integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==} + engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-jsx@7.28.6': - resolution: - { - integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==} + engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-logical-assignment-operators@7.10.4': - resolution: - { - integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==, - } + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': - resolution: - { - integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==, - } + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-numeric-separator@7.10.4': - resolution: - { - integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==, - } + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-object-rest-spread@7.8.3': - resolution: - { - integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==, - } + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-optional-catch-binding@7.8.3': - resolution: - { - integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==, - } + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-optional-chaining@7.8.3': - resolution: - { - integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==, - } + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-private-property-in-object@7.14.5': - resolution: - { - integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-top-level-await@7.14.5': - resolution: - { - integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-syntax-typescript@7.28.6': - resolution: - { - integrity: sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==, - } - engines: { node: '>=6.9.0' } + resolution: {integrity: sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-self@7.27.1': + resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-source@7.27.1': + resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==} + engines: {node: '>=6.9.0'} 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.25.12': + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] '@esbuild/aix-ppc64@0.27.2': - resolution: - { - integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} + engines: {node: '>=18'} cpu: [ppc64] os: [aix] + '@esbuild/android-arm64@0.25.12': + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm64@0.27.2': - resolution: - { - integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==} + engines: {node: '>=18'} cpu: [arm64] os: [android] + '@esbuild/android-arm@0.25.12': + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-arm@0.27.2': - resolution: - { - integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==} + engines: {node: '>=18'} cpu: [arm] os: [android] + '@esbuild/android-x64@0.25.12': + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/android-x64@0.27.2': - resolution: - { - integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==} + engines: {node: '>=18'} cpu: [x64] os: [android] + '@esbuild/darwin-arm64@0.25.12': + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-arm64@0.27.2': - resolution: - { - integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==} + engines: {node: '>=18'} cpu: [arm64] os: [darwin] + '@esbuild/darwin-x64@0.25.12': + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/darwin-x64@0.27.2': - resolution: - { - integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==} + engines: {node: '>=18'} cpu: [x64] os: [darwin] + '@esbuild/freebsd-arm64@0.25.12': + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-arm64@0.27.2': - resolution: - { - integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==} + engines: {node: '>=18'} cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-x64@0.25.12': + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/freebsd-x64@0.27.2': - resolution: - { - integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==} + engines: {node: '>=18'} cpu: [x64] os: [freebsd] + '@esbuild/linux-arm64@0.25.12': + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm64@0.27.2': - resolution: - { - integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==} + engines: {node: '>=18'} cpu: [arm64] os: [linux] + '@esbuild/linux-arm@0.25.12': + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-arm@0.27.2': - resolution: - { - integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==} + engines: {node: '>=18'} cpu: [arm] os: [linux] + '@esbuild/linux-ia32@0.25.12': + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-ia32@0.27.2': - resolution: - { - integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==} + engines: {node: '>=18'} cpu: [ia32] os: [linux] + '@esbuild/linux-loong64@0.25.12': + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-loong64@0.27.2': - resolution: - { - integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==} + engines: {node: '>=18'} cpu: [loong64] os: [linux] + '@esbuild/linux-mips64el@0.25.12': + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-mips64el@0.27.2': - resolution: - { - integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==} + engines: {node: '>=18'} cpu: [mips64el] os: [linux] + '@esbuild/linux-ppc64@0.25.12': + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-ppc64@0.27.2': - resolution: - { - integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==} + engines: {node: '>=18'} cpu: [ppc64] os: [linux] + '@esbuild/linux-riscv64@0.25.12': + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-riscv64@0.27.2': - resolution: - { - integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==} + engines: {node: '>=18'} cpu: [riscv64] os: [linux] + '@esbuild/linux-s390x@0.25.12': + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-s390x@0.27.2': - resolution: - { - integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==} + engines: {node: '>=18'} cpu: [s390x] os: [linux] + '@esbuild/linux-x64@0.25.12': + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/linux-x64@0.27.2': - resolution: - { - integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==} + engines: {node: '>=18'} cpu: [x64] os: [linux] + '@esbuild/netbsd-arm64@0.25.12': + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-arm64@0.27.2': - resolution: - { - integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==} + engines: {node: '>=18'} cpu: [arm64] os: [netbsd] + '@esbuild/netbsd-x64@0.25.12': + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + '@esbuild/netbsd-x64@0.27.2': - resolution: - { - integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==} + engines: {node: '>=18'} cpu: [x64] os: [netbsd] + '@esbuild/openbsd-arm64@0.25.12': + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-arm64@0.27.2': - resolution: - { - integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==} + engines: {node: '>=18'} cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-x64@0.25.12': + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/openbsd-x64@0.27.2': - resolution: - { - integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==} + engines: {node: '>=18'} cpu: [x64] os: [openbsd] + '@esbuild/openharmony-arm64@0.25.12': + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + '@esbuild/openharmony-arm64@0.27.2': - resolution: - { - integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==} + engines: {node: '>=18'} cpu: [arm64] os: [openharmony] + '@esbuild/sunos-x64@0.25.12': + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/sunos-x64@0.27.2': - resolution: - { - integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==} + engines: {node: '>=18'} cpu: [x64] os: [sunos] + '@esbuild/win32-arm64@0.25.12': + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-arm64@0.27.2': - resolution: - { - integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==} + engines: {node: '>=18'} cpu: [arm64] os: [win32] + '@esbuild/win32-ia32@0.25.12': + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-ia32@0.27.2': - resolution: - { - integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==} + engines: {node: '>=18'} cpu: [ia32] os: [win32] + '@esbuild/win32-x64@0.25.12': + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@esbuild/win32-x64@0.27.2': - resolution: - { - integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==} + engines: {node: '>=18'} cpu: [x64] os: [win32] '@eslint-community/eslint-utils@4.9.0': - resolution: - { - integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 '@eslint-community/eslint-utils@4.9.1': - resolution: - { - integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 '@eslint-community/regexpp@4.12.2': - resolution: - { - integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==, - } - engines: { node: ^12.0.0 || ^14.0.0 || >=16.0.0 } + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} '@eslint/config-array@0.21.1': - resolution: - { - integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/config-helpers@0.4.2': - resolution: - { - integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/core@0.17.0': - resolution: - { - integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/eslintrc@3.3.3': - resolution: - { - integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/js@9.39.2': - resolution: - { - integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.7': - resolution: - { - integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/plugin-kit@0.4.1': - resolution: - { - integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@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: @@ -3655,10 +3391,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: @@ -3666,65 +3399,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: @@ -3732,67 +3438,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: @@ -3800,3161 +3479,1922 @@ packages: optional: true '@jest/schemas@29.6.3': - resolution: - { - integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==, - } - engines: { node: ^14.15.0 || ^16.10.0 || >=18.0.0 } + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} '@jest/schemas@30.0.5': - resolution: - { - integrity: sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} '@jest/snapshot-utils@30.2.0': - resolution: - { - integrity: sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} '@jest/source-map@30.0.1': - resolution: - { - integrity: sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} '@jest/test-result@30.2.0': - resolution: - { - integrity: sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} '@jest/test-sequencer@30.2.0': - resolution: - { - integrity: sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} '@jest/transform@30.2.0': - resolution: - { - integrity: sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} '@jest/types@26.6.2': - resolution: - { - integrity: sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==, - } - engines: { node: '>= 10.14.2' } + resolution: {integrity: sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==} + engines: {node: '>= 10.14.2'} '@jest/types@30.2.0': - resolution: - { - integrity: sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==, - } - engines: { node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} '@jridgewell/gen-mapping@0.3.13': - resolution: - { - integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==, - } + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} '@jridgewell/remapping@2.3.5': - resolution: - { - integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==, - } + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} '@jridgewell/resolve-uri@3.1.2': - resolution: - { - integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==, - } - engines: { node: '>=6.0.0' } + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} '@jridgewell/sourcemap-codec@1.5.5': - resolution: - { - integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==, - } + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} '@jridgewell/trace-mapping@0.3.31': - resolution: - { - integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==, - } + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} '@jridgewell/trace-mapping@0.3.9': - resolution: - { - integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==, - } + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} '@launchql/mjml@0.1.1': - resolution: - { - integrity: sha512-6+OEmECuu5atRZ43ovsMfFs+T4NWNaKbzNG0uA8HYaBSn3kWR7GH3QnmL3lCIeymLtvgua8aZChYvg6SxrQdnw==, - } + resolution: {integrity: sha512-6+OEmECuu5atRZ43ovsMfFs+T4NWNaKbzNG0uA8HYaBSn3kWR7GH3QnmL3lCIeymLtvgua8aZChYvg6SxrQdnw==} peerDependencies: react: '>=16' react-dom: '>=16' '@launchql/protobufjs@7.2.6': - resolution: - { - integrity: sha512-vwi1nG2/heVFsIMHQU1KxTjUp5c757CTtRAZn/jutApCkFlle1iv8tzM/DHlSZJKDldxaYqnNYTg0pTyp8Bbtg==, - } - engines: { node: '>=12.0.0' } + resolution: {integrity: sha512-vwi1nG2/heVFsIMHQU1KxTjUp5c757CTtRAZn/jutApCkFlle1iv8tzM/DHlSZJKDldxaYqnNYTg0pTyp8Bbtg==} + engines: {node: '>=12.0.0'} '@launchql/styled-email@0.1.0': - resolution: - { - integrity: sha512-ISjzsY+3EOH/qAKHPq3evw9QmmEyA8Vw+0pUf+Zf8l4/rAHJJKrSa/uPiaUf2Abi8yAZKyx2uyaZq4ExNNkD+w==, - } + resolution: {integrity: sha512-ISjzsY+3EOH/qAKHPq3evw9QmmEyA8Vw+0pUf+Zf8l4/rAHJJKrSa/uPiaUf2Abi8yAZKyx2uyaZq4ExNNkD+w==} peerDependencies: react: '>=16' react-dom: '>=16' '@lerna/create@8.2.4': - resolution: - { - integrity: sha512-A8AlzetnS2WIuhijdAzKUyFpR5YbLLfV3luQ4lzBgIBgRfuoBDZeF+RSZPhra+7A6/zTUlrbhKZIOi/MNhqgvQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-A8AlzetnS2WIuhijdAzKUyFpR5YbLLfV3luQ4lzBgIBgRfuoBDZeF+RSZPhra+7A6/zTUlrbhKZIOi/MNhqgvQ==} + engines: {node: '>=18.0.0'} '@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==} '@oxfmt/darwin-arm64@0.26.0': - resolution: - { - integrity: sha512-AAGc+8CffkiWeVgtWf4dPfQwHEE5c/j/8NWH7VGVxxJRCZFdmWcqCXprvL2H6qZFewvDLrFbuSPRCqYCpYGaTQ==, - } + resolution: {integrity: sha512-AAGc+8CffkiWeVgtWf4dPfQwHEE5c/j/8NWH7VGVxxJRCZFdmWcqCXprvL2H6qZFewvDLrFbuSPRCqYCpYGaTQ==} cpu: [arm64] os: [darwin] '@oxfmt/darwin-x64@0.26.0': - resolution: - { - integrity: sha512-xFx5ijCTjw577wJvFlZEMmKDnp3HSCcbYdCsLRmC5i3TZZiDe9DEYh3P46uqhzj8BkEw1Vm1ZCWdl48aEYAzvQ==, - } + resolution: {integrity: sha512-xFx5ijCTjw577wJvFlZEMmKDnp3HSCcbYdCsLRmC5i3TZZiDe9DEYh3P46uqhzj8BkEw1Vm1ZCWdl48aEYAzvQ==} cpu: [x64] os: [darwin] '@oxfmt/linux-arm64-gnu@0.26.0': - resolution: - { - integrity: sha512-GubkQeQT5d3B/Jx/IiR7NMkSmXrCZcVI0BPh1i7mpFi8HgD1hQ/LbhiBKAMsMqs5bbugdQOgBEl8bOhe8JhW1g==, - } + resolution: {integrity: sha512-GubkQeQT5d3B/Jx/IiR7NMkSmXrCZcVI0BPh1i7mpFi8HgD1hQ/LbhiBKAMsMqs5bbugdQOgBEl8bOhe8JhW1g==} cpu: [arm64] os: [linux] '@oxfmt/linux-arm64-musl@0.26.0': - resolution: - { - integrity: sha512-OEypUwK69bFPj+aa3/LYCnlIUPgoOLu//WNcriwpnWNmt47808Ht7RJSg+MNK8a7pSZHpXJ5/E6CRK/OTwFdaQ==, - } + resolution: {integrity: sha512-OEypUwK69bFPj+aa3/LYCnlIUPgoOLu//WNcriwpnWNmt47808Ht7RJSg+MNK8a7pSZHpXJ5/E6CRK/OTwFdaQ==} cpu: [arm64] os: [linux] '@oxfmt/linux-x64-gnu@0.26.0': - resolution: - { - integrity: sha512-xO6iEW2bC6ZHyOTPmPWrg/nM6xgzyRPaS84rATy6F8d79wz69LdRdJ3l/PXlkqhi7XoxhvX4ExysA0Nf10ZZEQ==, - } + resolution: {integrity: sha512-xO6iEW2bC6ZHyOTPmPWrg/nM6xgzyRPaS84rATy6F8d79wz69LdRdJ3l/PXlkqhi7XoxhvX4ExysA0Nf10ZZEQ==} cpu: [x64] os: [linux] '@oxfmt/linux-x64-musl@0.26.0': - resolution: - { - integrity: sha512-Z3KuZFC+MIuAyFCXBHY71kCsdRq1ulbsbzTe71v+hrEv7zVBn6yzql+/AZcgfIaKzWO9OXNuz5WWLWDmVALwow==, - } + resolution: {integrity: sha512-Z3KuZFC+MIuAyFCXBHY71kCsdRq1ulbsbzTe71v+hrEv7zVBn6yzql+/AZcgfIaKzWO9OXNuz5WWLWDmVALwow==} cpu: [x64] os: [linux] '@oxfmt/win32-arm64@0.26.0': - resolution: - { - integrity: sha512-3zRbqwVWK1mDhRhTknlQFpRFL9GhEB5GfU6U7wawnuEwpvi39q91kJ+SRJvJnhyPCARkjZBd1V8XnweN5IFd1g==, - } + resolution: {integrity: sha512-3zRbqwVWK1mDhRhTknlQFpRFL9GhEB5GfU6U7wawnuEwpvi39q91kJ+SRJvJnhyPCARkjZBd1V8XnweN5IFd1g==} cpu: [arm64] os: [win32] '@oxfmt/win32-x64@0.26.0': - resolution: - { - integrity: sha512-m8TfIljU22i9UEIkD+slGPifTFeaCwIUfxszN3E6ABWP1KQbtwSw9Ak0TdoikibvukF/dtbeyG3WW63jv9DnEg==, - } + resolution: {integrity: sha512-m8TfIljU22i9UEIkD+slGPifTFeaCwIUfxszN3E6ABWP1KQbtwSw9Ak0TdoikibvukF/dtbeyG3WW63jv9DnEg==} cpu: [x64] os: [win32] '@paralleldrive/cuid2@2.3.1': - resolution: - { - integrity: sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==, - } + resolution: {integrity: sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==} '@pgpm/database-jobs@0.16.0': - resolution: - { - integrity: sha512-s8I7958PlhfYXZKhYoU76R03yk6dlevjGk/Uy9uktveJkZ8C3JVsIhP6Lv4lo0SFEZCjFmXRCYpOY5xINIcX4w==, - } + resolution: {integrity: sha512-s8I7958PlhfYXZKhYoU76R03yk6dlevjGk/Uy9uktveJkZ8C3JVsIhP6Lv4lo0SFEZCjFmXRCYpOY5xINIcX4w==} '@pgpm/inflection@0.16.0': - resolution: - { - integrity: sha512-otjWGx+KkB113Wc5I9nsvoqPhBK6zD1ON2OcXw9PQRgqU43Y9f0yZjb559dDzZwDn5XUeiZMf6il5SIvJE5NPg==, - } + resolution: {integrity: sha512-otjWGx+KkB113Wc5I9nsvoqPhBK6zD1ON2OcXw9PQRgqU43Y9f0yZjb559dDzZwDn5XUeiZMf6il5SIvJE5NPg==} '@pgpm/metaschema-modules@0.16.4': - resolution: - { - integrity: sha512-sB3+5yljFEqUXTTHUOHBBxK52CwagHiUBumWjikHVN9C5w6NHUQ+xFde+3RJMCkoqnmcZn6HTGvWCF25QgciiA==, - } + resolution: {integrity: sha512-sB3+5yljFEqUXTTHUOHBBxK52CwagHiUBumWjikHVN9C5w6NHUQ+xFde+3RJMCkoqnmcZn6HTGvWCF25QgciiA==} '@pgpm/metaschema-schema@0.16.3': - resolution: - { - integrity: sha512-sDIWJY+uNaqMMGjL8NWo8ezzXH1OT0qdaqsX+YDrBL6v1u0PphWprdjd7HySzdqIGpPSax8sIy5u4P2M96wR9Q==, - } + resolution: {integrity: sha512-sDIWJY+uNaqMMGjL8NWo8ezzXH1OT0qdaqsX+YDrBL6v1u0PphWprdjd7HySzdqIGpPSax8sIy5u4P2M96wR9Q==} '@pgpm/services@0.16.3': - resolution: - { - integrity: sha512-TfYALB8RKPyR2WZIFH2Pirb5qfx1q2EKbr7gzG/CcZcQMgTGYyDHBtvSqIO4nDfJ6GgYcASoip9T0lzQmwGtlA==, - } + resolution: {integrity: sha512-TfYALB8RKPyR2WZIFH2Pirb5qfx1q2EKbr7gzG/CcZcQMgTGYyDHBtvSqIO4nDfJ6GgYcASoip9T0lzQmwGtlA==} '@pgpm/types@0.16.0': - resolution: - { - integrity: sha512-CioHCxZGQUnpLANw4aMOOq7Z6zi2SXCxJIRZ8CSBPJfJkWU1OgxX+EpSjnm4Td4bznJhOViXniLltibaaGkMPA==, - } + resolution: {integrity: sha512-CioHCxZGQUnpLANw4aMOOq7Z6zi2SXCxJIRZ8CSBPJfJkWU1OgxX+EpSjnm4Td4bznJhOViXniLltibaaGkMPA==} '@pgpm/verify@0.16.0': - resolution: - { - integrity: sha512-uG0zTXAWGLV8wTUiLdBn+2b4AO+gtiw7sZf+TFFU8h/mVGMBTHUb9Gbsl/GL/5/0zZKOxak7cRJ5deec79KB/A==, - } + resolution: {integrity: sha512-uG0zTXAWGLV8wTUiLdBn+2b4AO+gtiw7sZf+TFFU8h/mVGMBTHUb9Gbsl/GL/5/0zZKOxak7cRJ5deec79KB/A==} '@pgsql/types@17.6.2': - resolution: - { - integrity: sha512-1UtbELdbqNdyOShhrVfSz3a1gDi0s9XXiQemx+6QqtsrXe62a6zOGU+vjb2GRfG5jeEokI1zBBcfD42enRv0Rw==, - } + resolution: {integrity: sha512-1UtbELdbqNdyOShhrVfSz3a1gDi0s9XXiQemx+6QqtsrXe62a6zOGU+vjb2GRfG5jeEokI1zBBcfD42enRv0Rw==} '@pgsql/utils@17.8.11': - resolution: - { - integrity: sha512-gcaS9ATilQyGSIq8596tq+6rcb7TX54sdjOvOzGa9lu9NjqkptEKLbBae5UTjfkFGfH50duDFD1EpFogMnZToA==, - } + resolution: {integrity: sha512-gcaS9ATilQyGSIq8596tq+6rcb7TX54sdjOvOzGa9lu9NjqkptEKLbBae5UTjfkFGfH50duDFD1EpFogMnZToA==} '@pkgjs/parseargs@0.11.0': - resolution: - { - integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==, - } - engines: { node: '>=14' } + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} '@pkgr/core@0.2.9': - resolution: - { - integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==, - } - engines: { node: ^12.20.0 || ^14.18.0 || >=16.0.0 } + resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} '@playwright/test@1.57.0': - resolution: - { - integrity: sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==} + engines: {node: '>=18'} hasBin: true '@protobufjs/aspromise@1.1.2': - resolution: - { - integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==, - } + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} '@protobufjs/base64@1.1.2': - resolution: - { - integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==, - } + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} '@protobufjs/codegen@2.0.4': - resolution: - { - integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==, - } + resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} '@protobufjs/eventemitter@1.1.0': - resolution: - { - integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==, - } + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} '@protobufjs/fetch@1.1.0': - resolution: - { - integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==, - } + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} '@protobufjs/float@1.0.2': - resolution: - { - integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==, - } + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} '@protobufjs/inquire@1.1.0': - resolution: - { - integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==, - } + resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} '@protobufjs/path@1.1.2': - resolution: - { - integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==, - } + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} '@protobufjs/pool@1.1.0': - resolution: - { - integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==, - } + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} '@protobufjs/utf8@1.1.0': - resolution: - { - integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==, - } + resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + + '@rolldown/pluginutils@1.0.0-beta.27': + resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} + + '@rollup/rollup-android-arm-eabi@4.57.1': + resolution: {integrity: sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.57.1': + resolution: {integrity: sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.57.1': + resolution: {integrity: sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.57.1': + resolution: {integrity: sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.57.1': + resolution: {integrity: sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.57.1': + resolution: {integrity: sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.57.1': + resolution: {integrity: sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.57.1': + resolution: {integrity: sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.57.1': + resolution: {integrity: sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.57.1': + resolution: {integrity: sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loong64-gnu@4.57.1': + resolution: {integrity: sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-loong64-musl@4.57.1': + resolution: {integrity: sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.57.1': + resolution: {integrity: sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-ppc64-musl@4.57.1': + resolution: {integrity: sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.57.1': + resolution: {integrity: sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.57.1': + resolution: {integrity: sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.57.1': + resolution: {integrity: sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.57.1': + resolution: {integrity: sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.57.1': + resolution: {integrity: sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-openbsd-x64@4.57.1': + resolution: {integrity: sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.57.1': + resolution: {integrity: sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.57.1': + resolution: {integrity: sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.57.1': + resolution: {integrity: sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.57.1': + resolution: {integrity: sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.57.1': + resolution: {integrity: sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==} + cpu: [x64] + os: [win32] '@sigstore/bundle@2.3.2': - resolution: - { - integrity: sha512-wueKWDk70QixNLB363yHc2D2ItTgYiMTdPwK8D9dKQMR3ZQ0c35IxP5xnwQ8cNLoCgCRcHf14kE+CLIvNX1zmA==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-wueKWDk70QixNLB363yHc2D2ItTgYiMTdPwK8D9dKQMR3ZQ0c35IxP5xnwQ8cNLoCgCRcHf14kE+CLIvNX1zmA==} + engines: {node: ^16.14.0 || >=18.0.0} '@sigstore/core@1.1.0': - resolution: - { - integrity: sha512-JzBqdVIyqm2FRQCulY6nbQzMpJJpSiJ8XXWMhtOX9eKgaXXpfNOF53lzQEjIydlStnd/eFtuC1dW4VYdD93oRg==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-JzBqdVIyqm2FRQCulY6nbQzMpJJpSiJ8XXWMhtOX9eKgaXXpfNOF53lzQEjIydlStnd/eFtuC1dW4VYdD93oRg==} + engines: {node: ^16.14.0 || >=18.0.0} '@sigstore/protobuf-specs@0.3.3': - resolution: - { - integrity: sha512-RpacQhBlwpBWd7KEJsRKcBQalbV28fvkxwTOJIqhIuDysMMaJW47V4OqW30iJB9uRpqOSxxEAQFdr8tTattReQ==, - } - engines: { node: ^18.17.0 || >=20.5.0 } + resolution: {integrity: sha512-RpacQhBlwpBWd7KEJsRKcBQalbV28fvkxwTOJIqhIuDysMMaJW47V4OqW30iJB9uRpqOSxxEAQFdr8tTattReQ==} + engines: {node: ^18.17.0 || >=20.5.0} '@sigstore/sign@2.3.2': - resolution: - { - integrity: sha512-5Vz5dPVuunIIvC5vBb0APwo7qKA4G9yM48kPWJT+OEERs40md5GoUR1yedwpekWZ4m0Hhw44m6zU+ObsON+iDA==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-5Vz5dPVuunIIvC5vBb0APwo7qKA4G9yM48kPWJT+OEERs40md5GoUR1yedwpekWZ4m0Hhw44m6zU+ObsON+iDA==} + engines: {node: ^16.14.0 || >=18.0.0} '@sigstore/tuf@2.3.4': - resolution: - { - integrity: sha512-44vtsveTPUpqhm9NCrbU8CWLe3Vck2HO1PNLw7RIajbB7xhtn5RBPm1VNSCMwqGYHhDsBJG8gDF0q4lgydsJvw==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-44vtsveTPUpqhm9NCrbU8CWLe3Vck2HO1PNLw7RIajbB7xhtn5RBPm1VNSCMwqGYHhDsBJG8gDF0q4lgydsJvw==} + engines: {node: ^16.14.0 || >=18.0.0} '@sigstore/verify@1.2.1': - resolution: - { - integrity: sha512-8iKx79/F73DKbGfRf7+t4dqrc0bRr0thdPrxAtCKWRm/F0tG71i6O1rvlnScncJLLBZHn3h8M3c1BSUAb9yu8g==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-8iKx79/F73DKbGfRf7+t4dqrc0bRr0thdPrxAtCKWRm/F0tG71i6O1rvlnScncJLLBZHn3h8M3c1BSUAb9yu8g==} + engines: {node: ^16.14.0 || >=18.0.0} '@sinclair/typebox@0.27.8': - resolution: - { - integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==, - } + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} '@sinclair/typebox@0.34.47': - resolution: - { - integrity: sha512-ZGIBQ+XDvO5JQku9wmwtabcVTHJsgSWAHYtVuM9pBNNR5E88v6Jcj/llpmsjivig5X8A8HHOb4/mbEKPS5EvAw==, - } + resolution: {integrity: sha512-ZGIBQ+XDvO5JQku9wmwtabcVTHJsgSWAHYtVuM9pBNNR5E88v6Jcj/llpmsjivig5X8A8HHOb4/mbEKPS5EvAw==} '@sinonjs/commons@3.0.1': - resolution: - { - integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==, - } + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} '@sinonjs/fake-timers@13.0.5': - resolution: - { - integrity: sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==, - } + resolution: {integrity: sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==} '@smithy/abort-controller@4.2.7': - resolution: - { - integrity: sha512-rzMY6CaKx2qxrbYbqjXWS0plqEy7LOdKHS0bg4ixJ6aoGDPNUcLWk/FRNuCILh7GKLG9TFUXYYeQQldMBBwuyw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-rzMY6CaKx2qxrbYbqjXWS0plqEy7LOdKHS0bg4ixJ6aoGDPNUcLWk/FRNuCILh7GKLG9TFUXYYeQQldMBBwuyw==} + engines: {node: '>=18.0.0'} '@smithy/abort-controller@4.2.8': - resolution: - { - integrity: sha512-peuVfkYHAmS5ybKxWcfraK7WBBP0J+rkfUcbHJJKQ4ir3UAUNQI+Y4Vt/PqSzGqgloJ5O1dk7+WzNL8wcCSXbw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-peuVfkYHAmS5ybKxWcfraK7WBBP0J+rkfUcbHJJKQ4ir3UAUNQI+Y4Vt/PqSzGqgloJ5O1dk7+WzNL8wcCSXbw==} + engines: {node: '>=18.0.0'} '@smithy/chunked-blob-reader-native@4.2.1': - resolution: - { - integrity: sha512-lX9Ay+6LisTfpLid2zZtIhSEjHMZoAR5hHCR4H7tBz/Zkfr5ea8RcQ7Tk4mi0P76p4cN+Btz16Ffno7YHpKXnQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-lX9Ay+6LisTfpLid2zZtIhSEjHMZoAR5hHCR4H7tBz/Zkfr5ea8RcQ7Tk4mi0P76p4cN+Btz16Ffno7YHpKXnQ==} + engines: {node: '>=18.0.0'} '@smithy/chunked-blob-reader@5.2.0': - resolution: - { - integrity: sha512-WmU0TnhEAJLWvfSeMxBNe5xtbselEO8+4wG0NtZeL8oR21WgH1xiO37El+/Y+H/Ie4SCwBy3MxYWmOYaGgZueA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-WmU0TnhEAJLWvfSeMxBNe5xtbselEO8+4wG0NtZeL8oR21WgH1xiO37El+/Y+H/Ie4SCwBy3MxYWmOYaGgZueA==} + engines: {node: '>=18.0.0'} '@smithy/config-resolver@4.4.6': - resolution: - { - integrity: sha512-qJpzYC64kaj3S0fueiu3kXm8xPrR3PcXDPEgnaNMRn0EjNSZFoFjvbUp0YUDsRhN1CB90EnHJtbxWKevnH99UQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-qJpzYC64kaj3S0fueiu3kXm8xPrR3PcXDPEgnaNMRn0EjNSZFoFjvbUp0YUDsRhN1CB90EnHJtbxWKevnH99UQ==} + engines: {node: '>=18.0.0'} '@smithy/core@3.20.0': - resolution: - { - integrity: sha512-WsSHCPq/neD5G/MkK4csLI5Y5Pkd9c1NMfpYEKeghSGaD4Ja1qLIohRQf2D5c1Uy5aXp76DeKHkzWZ9KAlHroQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-WsSHCPq/neD5G/MkK4csLI5Y5Pkd9c1NMfpYEKeghSGaD4Ja1qLIohRQf2D5c1Uy5aXp76DeKHkzWZ9KAlHroQ==} + engines: {node: '>=18.0.0'} '@smithy/core@3.20.5': - resolution: - { - integrity: sha512-0Tz77Td8ynHaowXfOdrD0F1IH4tgWGUhwmLwmpFyTbr+U9WHXNNp9u/k2VjBXGnSe7BwjBERRpXsokGTXzNjhA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-0Tz77Td8ynHaowXfOdrD0F1IH4tgWGUhwmLwmpFyTbr+U9WHXNNp9u/k2VjBXGnSe7BwjBERRpXsokGTXzNjhA==} + engines: {node: '>=18.0.0'} '@smithy/core@3.20.7': - resolution: - { - integrity: sha512-aO7jmh3CtrmPsIJxUwYIzI5WVlMK8BMCPQ4D4nTzqTqBhbzvxHNzBMGcEg13yg/z9R2Qsz49NUFl0F0lVbTVFw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-aO7jmh3CtrmPsIJxUwYIzI5WVlMK8BMCPQ4D4nTzqTqBhbzvxHNzBMGcEg13yg/z9R2Qsz49NUFl0F0lVbTVFw==} + engines: {node: '>=18.0.0'} '@smithy/credential-provider-imds@4.2.8': - resolution: - { - integrity: sha512-FNT0xHS1c/CPN8upqbMFP83+ul5YgdisfCfkZ86Jh2NSmnqw/AJ6x5pEogVCTVvSm7j9MopRU89bmDelxuDMYw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-FNT0xHS1c/CPN8upqbMFP83+ul5YgdisfCfkZ86Jh2NSmnqw/AJ6x5pEogVCTVvSm7j9MopRU89bmDelxuDMYw==} + engines: {node: '>=18.0.0'} '@smithy/eventstream-codec@4.2.8': - resolution: - { - integrity: sha512-jS/O5Q14UsufqoGhov7dHLOPCzkYJl9QDzusI2Psh4wyYx/izhzvX9P4D69aTxcdfVhEPhjK+wYyn/PzLjKbbw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-jS/O5Q14UsufqoGhov7dHLOPCzkYJl9QDzusI2Psh4wyYx/izhzvX9P4D69aTxcdfVhEPhjK+wYyn/PzLjKbbw==} + engines: {node: '>=18.0.0'} '@smithy/eventstream-serde-browser@4.2.8': - resolution: - { - integrity: sha512-MTfQT/CRQz5g24ayXdjg53V0mhucZth4PESoA5IhvaWVDTOQLfo8qI9vzqHcPsdd2v6sqfTYqF5L/l+pea5Uyw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-MTfQT/CRQz5g24ayXdjg53V0mhucZth4PESoA5IhvaWVDTOQLfo8qI9vzqHcPsdd2v6sqfTYqF5L/l+pea5Uyw==} + engines: {node: '>=18.0.0'} '@smithy/eventstream-serde-config-resolver@4.3.8': - resolution: - { - integrity: sha512-ah12+luBiDGzBruhu3efNy1IlbwSEdNiw8fOZksoKoWW1ZHvO/04MQsdnws/9Aj+5b0YXSSN2JXKy/ClIsW8MQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-ah12+luBiDGzBruhu3efNy1IlbwSEdNiw8fOZksoKoWW1ZHvO/04MQsdnws/9Aj+5b0YXSSN2JXKy/ClIsW8MQ==} + engines: {node: '>=18.0.0'} '@smithy/eventstream-serde-node@4.2.8': - resolution: - { - integrity: sha512-cYpCpp29z6EJHa5T9WL0KAlq3SOKUQkcgSoeRfRVwjGgSFl7Uh32eYGt7IDYCX20skiEdRffyDpvF2efEZPC0A==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-cYpCpp29z6EJHa5T9WL0KAlq3SOKUQkcgSoeRfRVwjGgSFl7Uh32eYGt7IDYCX20skiEdRffyDpvF2efEZPC0A==} + engines: {node: '>=18.0.0'} '@smithy/eventstream-serde-universal@4.2.8': - resolution: - { - integrity: sha512-iJ6YNJd0bntJYnX6s52NC4WFYcZeKrPUr1Kmmr5AwZcwCSzVpS7oavAmxMR7pMq7V+D1G4s9F5NJK0xwOsKAlQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-iJ6YNJd0bntJYnX6s52NC4WFYcZeKrPUr1Kmmr5AwZcwCSzVpS7oavAmxMR7pMq7V+D1G4s9F5NJK0xwOsKAlQ==} + engines: {node: '>=18.0.0'} '@smithy/fetch-http-handler@5.3.8': - resolution: - { - integrity: sha512-h/Fi+o7mti4n8wx1SR6UHWLaakwHRx29sizvp8OOm7iqwKGFneT06GCSFhml6Bha5BT6ot5pj3CYZnCHhGC2Rg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-h/Fi+o7mti4n8wx1SR6UHWLaakwHRx29sizvp8OOm7iqwKGFneT06GCSFhml6Bha5BT6ot5pj3CYZnCHhGC2Rg==} + engines: {node: '>=18.0.0'} '@smithy/fetch-http-handler@5.3.9': - resolution: - { - integrity: sha512-I4UhmcTYXBrct03rwzQX1Y/iqQlzVQaPxWjCjula++5EmWq9YGBrx6bbGqluGc1f0XEfhSkiY4jhLgbsJUMKRA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-I4UhmcTYXBrct03rwzQX1Y/iqQlzVQaPxWjCjula++5EmWq9YGBrx6bbGqluGc1f0XEfhSkiY4jhLgbsJUMKRA==} + engines: {node: '>=18.0.0'} '@smithy/hash-blob-browser@4.2.9': - resolution: - { - integrity: sha512-m80d/iicI7DlBDxyQP6Th7BW/ejDGiF0bgI754+tiwK0lgMkcaIBgvwwVc7OFbY4eUzpGtnig52MhPAEJ7iNYg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-m80d/iicI7DlBDxyQP6Th7BW/ejDGiF0bgI754+tiwK0lgMkcaIBgvwwVc7OFbY4eUzpGtnig52MhPAEJ7iNYg==} + engines: {node: '>=18.0.0'} '@smithy/hash-node@4.2.8': - resolution: - { - integrity: sha512-7ZIlPbmaDGxVoxErDZnuFG18WekhbA/g2/i97wGj+wUBeS6pcUeAym8u4BXh/75RXWhgIJhyC11hBzig6MljwA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-7ZIlPbmaDGxVoxErDZnuFG18WekhbA/g2/i97wGj+wUBeS6pcUeAym8u4BXh/75RXWhgIJhyC11hBzig6MljwA==} + engines: {node: '>=18.0.0'} '@smithy/hash-stream-node@4.2.8': - resolution: - { - integrity: sha512-v0FLTXgHrTeheYZFGhR+ehX5qUm4IQsjAiL9qehad2cyjMWcN2QG6/4mSwbSgEQzI7jwfoXj7z4fxZUx/Mhj2w==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-v0FLTXgHrTeheYZFGhR+ehX5qUm4IQsjAiL9qehad2cyjMWcN2QG6/4mSwbSgEQzI7jwfoXj7z4fxZUx/Mhj2w==} + engines: {node: '>=18.0.0'} '@smithy/invalid-dependency@4.2.8': - resolution: - { - integrity: sha512-N9iozRybwAQ2dn9Fot9kI6/w9vos2oTXLhtK7ovGqwZjlOcxu6XhPlpLpC+INsxktqHinn5gS2DXDjDF2kG5sQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-N9iozRybwAQ2dn9Fot9kI6/w9vos2oTXLhtK7ovGqwZjlOcxu6XhPlpLpC+INsxktqHinn5gS2DXDjDF2kG5sQ==} + engines: {node: '>=18.0.0'} '@smithy/is-array-buffer@2.2.0': - resolution: - { - integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==, - } - engines: { node: '>=14.0.0' } + resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} + engines: {node: '>=14.0.0'} '@smithy/is-array-buffer@4.2.0': - resolution: - { - integrity: sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==} + engines: {node: '>=18.0.0'} '@smithy/md5-js@4.2.8': - resolution: - { - integrity: sha512-oGMaLj4tVZzLi3itBa9TCswgMBr7k9b+qKYowQ6x1rTyTuO1IU2YHdHUa+891OsOH+wCsH7aTPRsTJO3RMQmjQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-oGMaLj4tVZzLi3itBa9TCswgMBr7k9b+qKYowQ6x1rTyTuO1IU2YHdHUa+891OsOH+wCsH7aTPRsTJO3RMQmjQ==} + engines: {node: '>=18.0.0'} '@smithy/middleware-content-length@4.2.8': - resolution: - { - integrity: sha512-RO0jeoaYAB1qBRhfVyq0pMgBoUK34YEJxVxyjOWYZiOKOq2yMZ4MnVXMZCUDenpozHue207+9P5ilTV1zeda0A==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-RO0jeoaYAB1qBRhfVyq0pMgBoUK34YEJxVxyjOWYZiOKOq2yMZ4MnVXMZCUDenpozHue207+9P5ilTV1zeda0A==} + engines: {node: '>=18.0.0'} '@smithy/middleware-endpoint@4.4.1': - resolution: - { - integrity: sha512-gpLspUAoe6f1M6H0u4cVuFzxZBrsGZmjx2O9SigurTx4PbntYa4AJ+o0G0oGm1L2oSX6oBhcGHwrfJHup2JnJg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-gpLspUAoe6f1M6H0u4cVuFzxZBrsGZmjx2O9SigurTx4PbntYa4AJ+o0G0oGm1L2oSX6oBhcGHwrfJHup2JnJg==} + engines: {node: '>=18.0.0'} '@smithy/middleware-endpoint@4.4.6': - resolution: - { - integrity: sha512-dpq3bHqbEOBqGBjRVHVFP3eUSPpX0BYtg1D5d5Irgk6orGGAuZfY22rC4sErhg+ZfY/Y0kPqm1XpAmDZg7DeuA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-dpq3bHqbEOBqGBjRVHVFP3eUSPpX0BYtg1D5d5Irgk6orGGAuZfY22rC4sErhg+ZfY/Y0kPqm1XpAmDZg7DeuA==} + engines: {node: '>=18.0.0'} '@smithy/middleware-endpoint@4.4.8': - resolution: - { - integrity: sha512-TV44qwB/T0OMMzjIuI+JeS0ort3bvlPJ8XIH0MSlGADraXpZqmyND27ueuAL3E14optleADWqtd7dUgc2w+qhQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-TV44qwB/T0OMMzjIuI+JeS0ort3bvlPJ8XIH0MSlGADraXpZqmyND27ueuAL3E14optleADWqtd7dUgc2w+qhQ==} + engines: {node: '>=18.0.0'} '@smithy/middleware-retry@4.4.22': - resolution: - { - integrity: sha512-vwWDMaObSMjw6WCC/3Ae9G7uul5Sk95jr07CDk1gkIMpaDic0phPS1MpVAZ6+YkF7PAzRlpsDjxPwRlh/S11FQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-vwWDMaObSMjw6WCC/3Ae9G7uul5Sk95jr07CDk1gkIMpaDic0phPS1MpVAZ6+YkF7PAzRlpsDjxPwRlh/S11FQ==} + engines: {node: '>=18.0.0'} '@smithy/middleware-retry@4.4.24': - resolution: - { - integrity: sha512-yiUY1UvnbUFfP5izoKLtfxDSTRv724YRRwyiC/5HYY6vdsVDcDOXKSXmkJl/Hovcxt5r+8tZEUAdrOaCJwrl9Q==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-yiUY1UvnbUFfP5izoKLtfxDSTRv724YRRwyiC/5HYY6vdsVDcDOXKSXmkJl/Hovcxt5r+8tZEUAdrOaCJwrl9Q==} + engines: {node: '>=18.0.0'} '@smithy/middleware-serde@4.2.8': - resolution: - { - integrity: sha512-8rDGYen5m5+NV9eHv9ry0sqm2gI6W7mc1VSFMtn6Igo25S507/HaOX9LTHAS2/J32VXD0xSzrY0H5FJtOMS4/w==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-8rDGYen5m5+NV9eHv9ry0sqm2gI6W7mc1VSFMtn6Igo25S507/HaOX9LTHAS2/J32VXD0xSzrY0H5FJtOMS4/w==} + engines: {node: '>=18.0.0'} '@smithy/middleware-serde@4.2.9': - resolution: - { - integrity: sha512-eMNiej0u/snzDvlqRGSN3Vl0ESn3838+nKyVfF2FKNXFbi4SERYT6PR392D39iczngbqqGG0Jl1DlCnp7tBbXQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-eMNiej0u/snzDvlqRGSN3Vl0ESn3838+nKyVfF2FKNXFbi4SERYT6PR392D39iczngbqqGG0Jl1DlCnp7tBbXQ==} + engines: {node: '>=18.0.0'} '@smithy/middleware-stack@4.2.7': - resolution: - { - integrity: sha512-bsOT0rJ+HHlZd9crHoS37mt8qRRN/h9jRve1SXUhVbkRzu0QaNYZp1i1jha4n098tsvROjcwfLlfvcFuJSXEsw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-bsOT0rJ+HHlZd9crHoS37mt8qRRN/h9jRve1SXUhVbkRzu0QaNYZp1i1jha4n098tsvROjcwfLlfvcFuJSXEsw==} + engines: {node: '>=18.0.0'} '@smithy/middleware-stack@4.2.8': - resolution: - { - integrity: sha512-w6LCfOviTYQjBctOKSwy6A8FIkQy7ICvglrZFl6Bw4FmcQ1Z420fUtIhxaUZZshRe0VCq4kvDiPiXrPZAe8oRA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-w6LCfOviTYQjBctOKSwy6A8FIkQy7ICvglrZFl6Bw4FmcQ1Z420fUtIhxaUZZshRe0VCq4kvDiPiXrPZAe8oRA==} + engines: {node: '>=18.0.0'} '@smithy/node-config-provider@4.3.7': - resolution: - { - integrity: sha512-7r58wq8sdOcrwWe+klL9y3bc4GW1gnlfnFOuL7CXa7UzfhzhxKuzNdtqgzmTV+53lEp9NXh5hY/S4UgjLOzPfw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-7r58wq8sdOcrwWe+klL9y3bc4GW1gnlfnFOuL7CXa7UzfhzhxKuzNdtqgzmTV+53lEp9NXh5hY/S4UgjLOzPfw==} + engines: {node: '>=18.0.0'} '@smithy/node-config-provider@4.3.8': - resolution: - { - integrity: sha512-aFP1ai4lrbVlWjfpAfRSL8KFcnJQYfTl5QxLJXY32vghJrDuFyPZ6LtUL+JEGYiFRG1PfPLHLoxj107ulncLIg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-aFP1ai4lrbVlWjfpAfRSL8KFcnJQYfTl5QxLJXY32vghJrDuFyPZ6LtUL+JEGYiFRG1PfPLHLoxj107ulncLIg==} + engines: {node: '>=18.0.0'} '@smithy/node-http-handler@4.4.7': - resolution: - { - integrity: sha512-NELpdmBOO6EpZtWgQiHjoShs1kmweaiNuETUpuup+cmm/xJYjT4eUjfhrXRP4jCOaAsS3c3yPsP3B+K+/fyPCQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-NELpdmBOO6EpZtWgQiHjoShs1kmweaiNuETUpuup+cmm/xJYjT4eUjfhrXRP4jCOaAsS3c3yPsP3B+K+/fyPCQ==} + engines: {node: '>=18.0.0'} '@smithy/node-http-handler@4.4.8': - resolution: - { - integrity: sha512-q9u+MSbJVIJ1QmJ4+1u+cERXkrhuILCBDsJUBAW1MPE6sFonbCNaegFuwW9ll8kh5UdyY3jOkoOGlc7BesoLpg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-q9u+MSbJVIJ1QmJ4+1u+cERXkrhuILCBDsJUBAW1MPE6sFonbCNaegFuwW9ll8kh5UdyY3jOkoOGlc7BesoLpg==} + engines: {node: '>=18.0.0'} '@smithy/property-provider@4.2.7': - resolution: - { - integrity: sha512-jmNYKe9MGGPoSl/D7JDDs1C8b3dC8f/w78LbaVfoTtWy4xAd5dfjaFG9c9PWPihY4ggMQNQSMtzU77CNgAJwmA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-jmNYKe9MGGPoSl/D7JDDs1C8b3dC8f/w78LbaVfoTtWy4xAd5dfjaFG9c9PWPihY4ggMQNQSMtzU77CNgAJwmA==} + engines: {node: '>=18.0.0'} '@smithy/property-provider@4.2.8': - resolution: - { - integrity: sha512-EtCTbyIveCKeOXDSWSdze3k612yCPq1YbXsbqX3UHhkOSW8zKsM9NOJG5gTIya0vbY2DIaieG8pKo1rITHYL0w==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-EtCTbyIveCKeOXDSWSdze3k612yCPq1YbXsbqX3UHhkOSW8zKsM9NOJG5gTIya0vbY2DIaieG8pKo1rITHYL0w==} + engines: {node: '>=18.0.0'} '@smithy/protocol-http@5.3.7': - resolution: - { - integrity: sha512-1r07pb994I20dD/c2seaZhoCuNYm0rWrvBxhCQ70brNh11M5Ml2ew6qJVo0lclB3jMIXirD4s2XRXRe7QEi0xA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-1r07pb994I20dD/c2seaZhoCuNYm0rWrvBxhCQ70brNh11M5Ml2ew6qJVo0lclB3jMIXirD4s2XRXRe7QEi0xA==} + engines: {node: '>=18.0.0'} '@smithy/protocol-http@5.3.8': - resolution: - { - integrity: sha512-QNINVDhxpZ5QnP3aviNHQFlRogQZDfYlCkQT+7tJnErPQbDhysondEjhikuANxgMsZrkGeiAxXy4jguEGsDrWQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-QNINVDhxpZ5QnP3aviNHQFlRogQZDfYlCkQT+7tJnErPQbDhysondEjhikuANxgMsZrkGeiAxXy4jguEGsDrWQ==} + engines: {node: '>=18.0.0'} '@smithy/querystring-builder@4.2.7': - resolution: - { - integrity: sha512-eKONSywHZxK4tBxe2lXEysh8wbBdvDWiA+RIuaxZSgCMmA0zMgoDpGLJhnyj+c0leOQprVnXOmcB4m+W9Rw7sg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-eKONSywHZxK4tBxe2lXEysh8wbBdvDWiA+RIuaxZSgCMmA0zMgoDpGLJhnyj+c0leOQprVnXOmcB4m+W9Rw7sg==} + engines: {node: '>=18.0.0'} '@smithy/querystring-builder@4.2.8': - resolution: - { - integrity: sha512-Xr83r31+DrE8CP3MqPgMJl+pQlLLmOfiEUnoyAlGzzJIrEsbKsPy1hqH0qySaQm4oWrCBlUqRt+idEgunKB+iw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-Xr83r31+DrE8CP3MqPgMJl+pQlLLmOfiEUnoyAlGzzJIrEsbKsPy1hqH0qySaQm4oWrCBlUqRt+idEgunKB+iw==} + engines: {node: '>=18.0.0'} '@smithy/querystring-parser@4.2.7': - resolution: - { - integrity: sha512-3X5ZvzUHmlSTHAXFlswrS6EGt8fMSIxX/c3Rm1Pni3+wYWB6cjGocmRIoqcQF9nU5OgGmL0u7l9m44tSUpfj9w==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-3X5ZvzUHmlSTHAXFlswrS6EGt8fMSIxX/c3Rm1Pni3+wYWB6cjGocmRIoqcQF9nU5OgGmL0u7l9m44tSUpfj9w==} + engines: {node: '>=18.0.0'} '@smithy/querystring-parser@4.2.8': - resolution: - { - integrity: sha512-vUurovluVy50CUlazOiXkPq40KGvGWSdmusa3130MwrR1UNnNgKAlj58wlOe61XSHRpUfIIh6cE0zZ8mzKaDPA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-vUurovluVy50CUlazOiXkPq40KGvGWSdmusa3130MwrR1UNnNgKAlj58wlOe61XSHRpUfIIh6cE0zZ8mzKaDPA==} + engines: {node: '>=18.0.0'} '@smithy/service-error-classification@4.2.8': - resolution: - { - integrity: sha512-mZ5xddodpJhEt3RkCjbmUQuXUOaPNTkbMGR0bcS8FE0bJDLMZlhmpgrvPNCYglVw5rsYTpSnv19womw9WWXKQQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-mZ5xddodpJhEt3RkCjbmUQuXUOaPNTkbMGR0bcS8FE0bJDLMZlhmpgrvPNCYglVw5rsYTpSnv19womw9WWXKQQ==} + engines: {node: '>=18.0.0'} '@smithy/shared-ini-file-loader@4.4.2': - resolution: - { - integrity: sha512-M7iUUff/KwfNunmrgtqBfvZSzh3bmFgv/j/t1Y1dQ+8dNo34br1cqVEqy6v0mYEgi0DkGO7Xig0AnuOaEGVlcg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-M7iUUff/KwfNunmrgtqBfvZSzh3bmFgv/j/t1Y1dQ+8dNo34br1cqVEqy6v0mYEgi0DkGO7Xig0AnuOaEGVlcg==} + engines: {node: '>=18.0.0'} '@smithy/shared-ini-file-loader@4.4.3': - resolution: - { - integrity: sha512-DfQjxXQnzC5UbCUPeC3Ie8u+rIWZTvuDPAGU/BxzrOGhRvgUanaP68kDZA+jaT3ZI+djOf+4dERGlm9mWfFDrg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-DfQjxXQnzC5UbCUPeC3Ie8u+rIWZTvuDPAGU/BxzrOGhRvgUanaP68kDZA+jaT3ZI+djOf+4dERGlm9mWfFDrg==} + engines: {node: '>=18.0.0'} '@smithy/signature-v4@5.3.8': - resolution: - { - integrity: sha512-6A4vdGj7qKNRF16UIcO8HhHjKW27thsxYci+5r/uVRkdcBEkOEiY8OMPuydLX4QHSrJqGHPJzPRwwVTqbLZJhg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-6A4vdGj7qKNRF16UIcO8HhHjKW27thsxYci+5r/uVRkdcBEkOEiY8OMPuydLX4QHSrJqGHPJzPRwwVTqbLZJhg==} + engines: {node: '>=18.0.0'} '@smithy/smithy-client@4.10.2': - resolution: - { - integrity: sha512-D5z79xQWpgrGpAHb054Fn2CCTQZpog7JELbVQ6XAvXs5MNKWf28U9gzSBlJkOyMl9LA1TZEjRtwvGXfP0Sl90g==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-D5z79xQWpgrGpAHb054Fn2CCTQZpog7JELbVQ6XAvXs5MNKWf28U9gzSBlJkOyMl9LA1TZEjRtwvGXfP0Sl90g==} + engines: {node: '>=18.0.0'} '@smithy/smithy-client@4.10.7': - resolution: - { - integrity: sha512-Uznt0I9z3os3Z+8pbXrOSCTXCA6vrjyN7Ub+8l2pRDum44vLv8qw0qGVkJN0/tZBZotaEFHrDPKUoPNueTr5Vg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-Uznt0I9z3os3Z+8pbXrOSCTXCA6vrjyN7Ub+8l2pRDum44vLv8qw0qGVkJN0/tZBZotaEFHrDPKUoPNueTr5Vg==} + engines: {node: '>=18.0.0'} '@smithy/smithy-client@4.10.9': - resolution: - { - integrity: sha512-Je0EvGXVJ0Vrrr2lsubq43JGRIluJ/hX17aN/W/A0WfE+JpoMdI8kwk2t9F0zTX9232sJDGcoH4zZre6m6f/sg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-Je0EvGXVJ0Vrrr2lsubq43JGRIluJ/hX17aN/W/A0WfE+JpoMdI8kwk2t9F0zTX9232sJDGcoH4zZre6m6f/sg==} + engines: {node: '>=18.0.0'} '@smithy/types@4.11.0': - resolution: - { - integrity: sha512-mlrmL0DRDVe3mNrjTcVcZEgkFmufITfUAPBEA+AHYiIeYyJebso/He1qLbP3PssRe22KUzLRpQSdBPbXdgZ2VA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-mlrmL0DRDVe3mNrjTcVcZEgkFmufITfUAPBEA+AHYiIeYyJebso/He1qLbP3PssRe22KUzLRpQSdBPbXdgZ2VA==} + engines: {node: '>=18.0.0'} '@smithy/types@4.12.0': - resolution: - { - integrity: sha512-9YcuJVTOBDjg9LWo23Qp0lTQ3D7fQsQtwle0jVfpbUHy9qBwCEgKuVH4FqFB3VYu0nwdHKiEMA+oXz7oV8X1kw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-9YcuJVTOBDjg9LWo23Qp0lTQ3D7fQsQtwle0jVfpbUHy9qBwCEgKuVH4FqFB3VYu0nwdHKiEMA+oXz7oV8X1kw==} + engines: {node: '>=18.0.0'} '@smithy/url-parser@4.2.7': - resolution: - { - integrity: sha512-/RLtVsRV4uY3qPWhBDsjwahAtt3x2IsMGnP5W1b2VZIe+qgCqkLxI1UOHDZp1Q1QSOrdOR32MF3Ph2JfWT1VHg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-/RLtVsRV4uY3qPWhBDsjwahAtt3x2IsMGnP5W1b2VZIe+qgCqkLxI1UOHDZp1Q1QSOrdOR32MF3Ph2JfWT1VHg==} + engines: {node: '>=18.0.0'} '@smithy/url-parser@4.2.8': - resolution: - { - integrity: sha512-NQho9U68TGMEU639YkXnVMV3GEFFULmmaWdlu1E9qzyIePOHsoSnagTGSDv1Zi8DCNN6btxOSdgmy5E/hsZwhA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-NQho9U68TGMEU639YkXnVMV3GEFFULmmaWdlu1E9qzyIePOHsoSnagTGSDv1Zi8DCNN6btxOSdgmy5E/hsZwhA==} + engines: {node: '>=18.0.0'} '@smithy/util-base64@4.3.0': - resolution: - { - integrity: sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==} + engines: {node: '>=18.0.0'} '@smithy/util-body-length-browser@4.2.0': - resolution: - { - integrity: sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==} + engines: {node: '>=18.0.0'} '@smithy/util-body-length-node@4.2.1': - resolution: - { - integrity: sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==} + engines: {node: '>=18.0.0'} '@smithy/util-buffer-from@2.2.0': - resolution: - { - integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==, - } - engines: { node: '>=14.0.0' } + resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} + engines: {node: '>=14.0.0'} '@smithy/util-buffer-from@4.2.0': - resolution: - { - integrity: sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew==} + engines: {node: '>=18.0.0'} '@smithy/util-config-provider@4.2.0': - resolution: - { - integrity: sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==} + engines: {node: '>=18.0.0'} '@smithy/util-defaults-mode-browser@4.3.21': - resolution: - { - integrity: sha512-DtmVJarzqtjghtGjCw/PFJolcJkP7GkZgy+hWTAN3YLXNH+IC82uMoMhFoC3ZtIz5mOgCm5+hOGi1wfhVYgrxw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-DtmVJarzqtjghtGjCw/PFJolcJkP7GkZgy+hWTAN3YLXNH+IC82uMoMhFoC3ZtIz5mOgCm5+hOGi1wfhVYgrxw==} + engines: {node: '>=18.0.0'} '@smithy/util-defaults-mode-browser@4.3.23': - resolution: - { - integrity: sha512-mMg+r/qDfjfF/0psMbV4zd7F/i+rpyp7Hjh0Wry7eY15UnzTEId+xmQTGDU8IdZtDfbGQxuWNfgBZKBj+WuYbA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-mMg+r/qDfjfF/0psMbV4zd7F/i+rpyp7Hjh0Wry7eY15UnzTEId+xmQTGDU8IdZtDfbGQxuWNfgBZKBj+WuYbA==} + engines: {node: '>=18.0.0'} '@smithy/util-defaults-mode-node@4.2.24': - resolution: - { - integrity: sha512-JelBDKPAVswVY666rezBvY6b0nF/v9TXjUbNwDNAyme7qqKYEX687wJv0uze8lBIZVbg30wlWnlYfVSjjpKYFA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-JelBDKPAVswVY666rezBvY6b0nF/v9TXjUbNwDNAyme7qqKYEX687wJv0uze8lBIZVbg30wlWnlYfVSjjpKYFA==} + engines: {node: '>=18.0.0'} '@smithy/util-defaults-mode-node@4.2.26': - resolution: - { - integrity: sha512-EQqe/WkbCinah0h1lMWh9ICl0Ob4lyl20/10WTB35SC9vDQfD8zWsOT+x2FIOXKAoZQ8z/y0EFMoodbcqWJY/w==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-EQqe/WkbCinah0h1lMWh9ICl0Ob4lyl20/10WTB35SC9vDQfD8zWsOT+x2FIOXKAoZQ8z/y0EFMoodbcqWJY/w==} + engines: {node: '>=18.0.0'} '@smithy/util-endpoints@3.2.8': - resolution: - { - integrity: sha512-8JaVTn3pBDkhZgHQ8R0epwWt+BqPSLCjdjXXusK1onwJlRuN69fbvSK66aIKKO7SwVFM6x2J2ox5X8pOaWcUEw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-8JaVTn3pBDkhZgHQ8R0epwWt+BqPSLCjdjXXusK1onwJlRuN69fbvSK66aIKKO7SwVFM6x2J2ox5X8pOaWcUEw==} + engines: {node: '>=18.0.0'} '@smithy/util-hex-encoding@4.2.0': - resolution: - { - integrity: sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==} + engines: {node: '>=18.0.0'} '@smithy/util-middleware@4.2.7': - resolution: - { - integrity: sha512-i1IkpbOae6NvIKsEeLLM9/2q4X+M90KV3oCFgWQI4q0Qz+yUZvsr+gZPdAEAtFhWQhAHpTsJO8DRJPuwVyln+w==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-i1IkpbOae6NvIKsEeLLM9/2q4X+M90KV3oCFgWQI4q0Qz+yUZvsr+gZPdAEAtFhWQhAHpTsJO8DRJPuwVyln+w==} + engines: {node: '>=18.0.0'} '@smithy/util-middleware@4.2.8': - resolution: - { - integrity: sha512-PMqfeJxLcNPMDgvPbbLl/2Vpin+luxqTGPpW3NAQVLbRrFRzTa4rNAASYeIGjRV9Ytuhzny39SpyU04EQreF+A==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-PMqfeJxLcNPMDgvPbbLl/2Vpin+luxqTGPpW3NAQVLbRrFRzTa4rNAASYeIGjRV9Ytuhzny39SpyU04EQreF+A==} + engines: {node: '>=18.0.0'} '@smithy/util-retry@4.2.8': - resolution: - { - integrity: sha512-CfJqwvoRY0kTGe5AkQokpURNCT1u/MkRzMTASWMPPo2hNSnKtF1D45dQl3DE2LKLr4m+PW9mCeBMJr5mCAVThg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-CfJqwvoRY0kTGe5AkQokpURNCT1u/MkRzMTASWMPPo2hNSnKtF1D45dQl3DE2LKLr4m+PW9mCeBMJr5mCAVThg==} + engines: {node: '>=18.0.0'} '@smithy/util-stream@4.5.10': - resolution: - { - integrity: sha512-jbqemy51UFSZSp2y0ZmRfckmrzuKww95zT9BYMmuJ8v3altGcqjwoV1tzpOwuHaKrwQrCjIzOib499ymr2f98g==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-jbqemy51UFSZSp2y0ZmRfckmrzuKww95zT9BYMmuJ8v3altGcqjwoV1tzpOwuHaKrwQrCjIzOib499ymr2f98g==} + engines: {node: '>=18.0.0'} '@smithy/util-stream@4.5.8': - resolution: - { - integrity: sha512-ZnnBhTapjM0YPGUSmOs0Mcg/Gg87k503qG4zU2v/+Js2Gu+daKOJMeqcQns8ajepY8tgzzfYxl6kQyZKml6O2w==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-ZnnBhTapjM0YPGUSmOs0Mcg/Gg87k503qG4zU2v/+Js2Gu+daKOJMeqcQns8ajepY8tgzzfYxl6kQyZKml6O2w==} + engines: {node: '>=18.0.0'} '@smithy/util-uri-escape@4.2.0': - resolution: - { - integrity: sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==} + engines: {node: '>=18.0.0'} '@smithy/util-utf8@2.3.0': - resolution: - { - integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==, - } - engines: { node: '>=14.0.0' } + resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} + engines: {node: '>=14.0.0'} '@smithy/util-utf8@4.2.0': - resolution: - { - integrity: sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==} + engines: {node: '>=18.0.0'} '@smithy/util-waiter@4.2.8': - resolution: - { - integrity: sha512-n+lahlMWk+aejGuax7DPWtqav8HYnWxQwR+LCG2BgCUmaGcTe9qZCFsmw8TMg9iG75HOwhrJCX9TCJRLH+Yzqg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-n+lahlMWk+aejGuax7DPWtqav8HYnWxQwR+LCG2BgCUmaGcTe9qZCFsmw8TMg9iG75HOwhrJCX9TCJRLH+Yzqg==} + engines: {node: '>=18.0.0'} '@smithy/uuid@1.1.0': - resolution: - { - integrity: sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==} + engines: {node: '>=18.0.0'} '@styled-system/background@5.1.2': - resolution: - { - integrity: sha512-jtwH2C/U6ssuGSvwTN3ri/IyjdHb8W9X/g8Y0JLcrH02G+BW3OS8kZdHphF1/YyRklnrKrBT2ngwGUK6aqqV3A==, - } + resolution: {integrity: sha512-jtwH2C/U6ssuGSvwTN3ri/IyjdHb8W9X/g8Y0JLcrH02G+BW3OS8kZdHphF1/YyRklnrKrBT2ngwGUK6aqqV3A==} '@styled-system/border@5.1.5': - resolution: - { - integrity: sha512-JvddhNrnhGigtzWRCVuAHepniyVi6hBlimxWDVAdcTuk7aRn9BYJUwfHslURtwYFsF5FoEs8Zmr1oZq2M1AP0A==, - } + resolution: {integrity: sha512-JvddhNrnhGigtzWRCVuAHepniyVi6hBlimxWDVAdcTuk7aRn9BYJUwfHslURtwYFsF5FoEs8Zmr1oZq2M1AP0A==} '@styled-system/color@5.1.2': - resolution: - { - integrity: sha512-1kCkeKDZkt4GYkuFNKc7vJQMcOmTl3bJY3YBUs7fCNM6mMYJeT1pViQ2LwBSBJytj3AB0o4IdLBoepgSgGl5MA==, - } + resolution: {integrity: sha512-1kCkeKDZkt4GYkuFNKc7vJQMcOmTl3bJY3YBUs7fCNM6mMYJeT1pViQ2LwBSBJytj3AB0o4IdLBoepgSgGl5MA==} '@styled-system/core@5.1.2': - resolution: - { - integrity: sha512-XclBDdNIy7OPOsN4HBsawG2eiWfCcuFt6gxKn1x4QfMIgeO6TOlA2pZZ5GWZtIhCUqEPTgIBta6JXsGyCkLBYw==, - } + resolution: {integrity: sha512-XclBDdNIy7OPOsN4HBsawG2eiWfCcuFt6gxKn1x4QfMIgeO6TOlA2pZZ5GWZtIhCUqEPTgIBta6JXsGyCkLBYw==} '@styled-system/css@5.1.5': - resolution: - { - integrity: sha512-XkORZdS5kypzcBotAMPBoeckDs9aSZVkvrAlq5K3xP8IMAUek+x2O4NtwoSgkYkWWzVBu6DGdFZLR790QWGG+A==, - } + resolution: {integrity: sha512-XkORZdS5kypzcBotAMPBoeckDs9aSZVkvrAlq5K3xP8IMAUek+x2O4NtwoSgkYkWWzVBu6DGdFZLR790QWGG+A==} '@styled-system/flexbox@5.1.2': - resolution: - { - integrity: sha512-6hHV52+eUk654Y1J2v77B8iLeBNtc+SA3R4necsu2VVinSD7+XY5PCCEzBFaWs42dtOEDIa2lMrgL0YBC01mDQ==, - } + resolution: {integrity: sha512-6hHV52+eUk654Y1J2v77B8iLeBNtc+SA3R4necsu2VVinSD7+XY5PCCEzBFaWs42dtOEDIa2lMrgL0YBC01mDQ==} '@styled-system/grid@5.1.2': - resolution: - { - integrity: sha512-K3YiV1KyHHzgdNuNlaw8oW2ktMuGga99o1e/NAfTEi5Zsa7JXxzwEnVSDSBdJC+z6R8WYTCYRQC6bkVFcvdTeg==, - } + resolution: {integrity: sha512-K3YiV1KyHHzgdNuNlaw8oW2ktMuGga99o1e/NAfTEi5Zsa7JXxzwEnVSDSBdJC+z6R8WYTCYRQC6bkVFcvdTeg==} '@styled-system/layout@5.1.2': - resolution: - { - integrity: sha512-wUhkMBqSeacPFhoE9S6UF3fsMEKFv91gF4AdDWp0Aym1yeMPpqz9l9qS/6vjSsDPF7zOb5cOKC3tcKKOMuDCPw==, - } + resolution: {integrity: sha512-wUhkMBqSeacPFhoE9S6UF3fsMEKFv91gF4AdDWp0Aym1yeMPpqz9l9qS/6vjSsDPF7zOb5cOKC3tcKKOMuDCPw==} '@styled-system/position@5.1.2': - resolution: - { - integrity: sha512-60IZfMXEOOZe3l1mCu6sj/2NAyUmES2kR9Kzp7s2D3P4qKsZWxD1Se1+wJvevb+1TP+ZMkGPEYYXRyU8M1aF5A==, - } + resolution: {integrity: sha512-60IZfMXEOOZe3l1mCu6sj/2NAyUmES2kR9Kzp7s2D3P4qKsZWxD1Se1+wJvevb+1TP+ZMkGPEYYXRyU8M1aF5A==} '@styled-system/shadow@5.1.2': - resolution: - { - integrity: sha512-wqniqYb7XuZM7K7C0d1Euxc4eGtqEe/lvM0WjuAFsQVImiq6KGT7s7is+0bNI8O4Dwg27jyu4Lfqo/oIQXNzAg==, - } + resolution: {integrity: sha512-wqniqYb7XuZM7K7C0d1Euxc4eGtqEe/lvM0WjuAFsQVImiq6KGT7s7is+0bNI8O4Dwg27jyu4Lfqo/oIQXNzAg==} '@styled-system/space@5.1.2': - resolution: - { - integrity: sha512-+zzYpR8uvfhcAbaPXhH8QgDAV//flxqxSjHiS9cDFQQUSznXMQmxJegbhcdEF7/eNnJgHeIXv1jmny78kipgBA==, - } + resolution: {integrity: sha512-+zzYpR8uvfhcAbaPXhH8QgDAV//flxqxSjHiS9cDFQQUSznXMQmxJegbhcdEF7/eNnJgHeIXv1jmny78kipgBA==} '@styled-system/typography@5.1.2': - resolution: - { - integrity: sha512-BxbVUnN8N7hJ4aaPOd7wEsudeT7CxarR+2hns8XCX1zp0DFfbWw4xYa/olA0oQaqx7F1hzDg+eRaGzAJbF+jOg==, - } + resolution: {integrity: sha512-BxbVUnN8N7hJ4aaPOd7wEsudeT7CxarR+2hns8XCX1zp0DFfbWw4xYa/olA0oQaqx7F1hzDg+eRaGzAJbF+jOg==} '@styled-system/variant@5.1.5': - resolution: - { - integrity: sha512-Yn8hXAFoWIro8+Q5J8YJd/mP85Teiut3fsGVR9CAxwgNfIAiqlYxsk5iHU7VHJks/0KjL4ATSjmbtCDC/4l1qw==, - } + resolution: {integrity: sha512-Yn8hXAFoWIro8+Q5J8YJd/mP85Teiut3fsGVR9CAxwgNfIAiqlYxsk5iHU7VHJks/0KjL4ATSjmbtCDC/4l1qw==} '@tanstack/query-core@5.90.19': - resolution: - { - integrity: sha512-GLW5sjPVIvH491VV1ufddnfldyVB+teCnpPIvweEfkpRx7CfUmUGhoh9cdcUKBh/KwVxk22aNEDxeTsvmyB/WA==, - } + resolution: {integrity: sha512-GLW5sjPVIvH491VV1ufddnfldyVB+teCnpPIvweEfkpRx7CfUmUGhoh9cdcUKBh/KwVxk22aNEDxeTsvmyB/WA==} + + '@tanstack/query-core@5.90.20': + resolution: {integrity: sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg==} '@tanstack/react-query@5.90.19': - resolution: - { - integrity: sha512-qTZRZ4QyTzQc+M0IzrbKHxSeISUmRB3RPGmao5bT+sI6ayxSRhn0FXEnT5Hg3as8SBFcRosrXXRFB+yAcxVxJQ==, - } + resolution: {integrity: sha512-qTZRZ4QyTzQc+M0IzrbKHxSeISUmRB3RPGmao5bT+sI6ayxSRhn0FXEnT5Hg3as8SBFcRosrXXRFB+yAcxVxJQ==} + peerDependencies: + react: ^18 || ^19 + + '@tanstack/react-query@5.90.20': + resolution: {integrity: sha512-vXBxa+qeyveVO7OA0jX1z+DeyCA4JKnThKv411jd5SORpBKgkcVnYKCiBgECvADvniBX7tobwBmg01qq9JmMJw==} 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-dom@19.2.3': + resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} + peerDependencies: + '@types/react': ^19.2.0 + + '@types/react@19.2.13': + resolution: {integrity: sha512-KkiJeU6VbYbUOp5ITMIc7kBfqlYkKA5KhEHVrGMmUUMt7NeaZg65ojdPk+FtNrBAOXNVM5QM72jnADjM+XVRAQ==} '@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] + '@vitejs/plugin-react@4.7.0': + resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + '@yarnpkg/lockfile@1.1.0': - resolution: - { - integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==, - } + resolution: {integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==} '@yarnpkg/parsers@3.0.2': - resolution: - { - integrity: sha512-/HcYgtUSiJiot/XWGLOlGxPYUG65+/31V8oqk17vZLW1xlCoR4PampyePljOxY2n8/3jz9+tIFzICsyGujJZoA==, - } - engines: { node: '>=18.12.0' } + resolution: {integrity: sha512-/HcYgtUSiJiot/XWGLOlGxPYUG65+/31V8oqk17vZLW1xlCoR4PampyePljOxY2n8/3jz9+tIFzICsyGujJZoA==} + engines: {node: '>=18.12.0'} '@zkochan/js-yaml@0.0.7': - resolution: - { - integrity: sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==, - } + resolution: {integrity: sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==} hasBin: true JSONStream@1.3.5: - resolution: - { - integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==, - } + resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} hasBin: true abbrev@2.0.0: - resolution: - { - integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} 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@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'} async-retry@1.3.1: - resolution: - { - integrity: sha512-aiieFW/7h3hY0Bq5d+ktDBejxuwR78vRu9hDUdR8rNhSaQ29VzPL4AoIRG7D/c7tdenwOcKvgPM6tIxB3cB6HA==, - } + resolution: {integrity: sha512-aiieFW/7h3hY0Bq5d+ktDBejxuwR78vRu9hDUdR8rNhSaQ29VzPL4AoIRG7D/c7tdenwOcKvgPM6tIxB3cB6HA==} async@3.2.6: - resolution: - { - integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==, - } + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} asynckit@0.4.0: - resolution: - { - integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==, - } + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} atob@2.1.2: - resolution: - { - integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==, - } - engines: { node: '>= 4.5.0' } + resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} + engines: {node: '>= 4.5.0'} hasBin: true 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==} base-64@1.0.0: - resolution: - { - integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==, - } + resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==} base32.js@0.1.0: - resolution: - { - integrity: sha512-n3TkB02ixgBOhTvANakDb4xaMXnYUVkNoRFJjQflcqMQhyEKxEHdj3E6N8t8sUQ0mjH/3/JxzlXuz3ul/J90pQ==, - } - engines: { node: '>=0.12.0' } + resolution: {integrity: sha512-n3TkB02ixgBOhTvANakDb4xaMXnYUVkNoRFJjQflcqMQhyEKxEHdj3E6N8t8sUQ0mjH/3/JxzlXuz3ul/J90pQ==} + engines: {node: '>=0.12.0'} base64-js@1.5.1: - resolution: - { - integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==, - } + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} baseline-browser-mapping@2.9.15: - resolution: - { - integrity: sha512-kX8h7K2srmDyYnXRIppo4AH/wYgzWVCs+eKr3RusRSQ5PvRYoEFmR/I0PbdTjKFAoKqp5+kbxnNTFO9jOfSVJg==, - } + resolution: {integrity: sha512-kX8h7K2srmDyYnXRIppo4AH/wYgzWVCs+eKr3RusRSQ5PvRYoEFmR/I0PbdTjKFAoKqp5+kbxnNTFO9jOfSVJg==} hasBin: true 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: @@ -6962,134 +5402,74 @@ 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'} 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: @@ -7097,11 +5477,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: @@ -7109,31 +5486,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: @@ -7141,10 +5506,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: @@ -7152,238 +5514,130 @@ 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'} 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'} 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' @@ -7475,268 +5729,156 @@ 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@8.1.1: - resolution: - { - integrity: sha512-vOUfHxAFFvkBjbVQbBfgnCO9d3GcNfMMTtVfgqSU2rQGMFEVqWy9GBuoSfHnwGu7EqR0/GeukQcL3KjFBaga9w==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-vOUfHxAFFvkBjbVQbBfgnCO9d3GcNfMMTtVfgqSU2rQGMFEVqWy9GBuoSfHnwGu7EqR0/GeukQcL3KjFBaga9w==} + engines: {node: '>=18'} envinfo@7.13.0: - resolution: - { - integrity: sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==} + engines: {node: '>=4'} hasBin: true err-code@2.0.3: - resolution: - { - integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==, - } + resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} error-ex@1.3.4: - resolution: - { - integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==, - } + resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} es-define-property@1.0.1: - resolution: - { - integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} es-errors@1.3.0: - resolution: - { - integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} es-object-atoms@1.1.1: - resolution: - { - integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} es-set-tostringtag@2.1.0: - resolution: - { - integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + esbuild@0.25.12: + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} + engines: {node: '>=18'} + hasBin: true esbuild@0.27.2: - resolution: - { - integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} + engines: {node: '>=18'} hasBin: true escalade@3.2.0: - resolution: - { - integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} escape-goat@3.0.0: - resolution: - { - integrity: sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw==} + engines: {node: '>=10'} escape-html@1.0.3: - resolution: - { - integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==, - } + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} escape-string-regexp@1.0.5: - resolution: - { - integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==, - } - engines: { node: '>=0.8.0' } + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} escape-string-regexp@2.0.0: - resolution: - { - integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} escape-string-regexp@4.0.0: - resolution: - { - integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} eslint-config-prettier@10.1.8: - resolution: - { - integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==, - } + resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==} hasBin: true peerDependencies: eslint: '>=7.0.0' eslint-plugin-simple-import-sort@12.1.1: - resolution: - { - integrity: sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA==, - } + resolution: {integrity: sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA==} peerDependencies: eslint: '>=5.0.0' eslint-plugin-unused-imports@4.3.0: - resolution: - { - integrity: sha512-ZFBmXMGBYfHttdRtOG9nFFpmUvMtbHSjsKrS20vdWdbfiVYsO3yA2SGYy9i9XmZJDfMGBflZGBCm70SEnFQtOA==, - } + resolution: {integrity: sha512-ZFBmXMGBYfHttdRtOG9nFFpmUvMtbHSjsKrS20vdWdbfiVYsO3yA2SGYy9i9XmZJDfMGBflZGBCm70SEnFQtOA==} peerDependencies: '@typescript-eslint/eslint-plugin': ^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0 eslint: ^9.0.0 || ^8.0.0 @@ -7745,32 +5887,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: '*' @@ -7779,190 +5909,106 @@ packages: optional: true espree@10.4.0: - resolution: - { - integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} esprima@4.0.1: - resolution: - { - integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} hasBin: true esquery@1.6.0: - resolution: - { - integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==, - } - engines: { node: '>=0.10' } + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} esrecurse@4.3.0: - resolution: - { - integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==, - } - engines: { node: '>=4.0' } + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} estraverse@5.3.0: - resolution: - { - integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==, - } - engines: { node: '>=4.0' } + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} esutils@2.0.3: - resolution: - { - integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} etag@1.8.1: - resolution: - { - integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==, - } - engines: { node: '>= 0.6' } + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} eventemitter3@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: @@ -7970,99 +6016,57 @@ packages: optional: true figures@3.2.0: - resolution: - { - integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} + engines: {node: '>=8'} file-entry-cache@8.0.0: - resolution: - { - integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==, - } - engines: { node: '>=16.0.0' } + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} filelist@1.0.4: - resolution: - { - integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==, - } + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} fill-range@7.1.1: - resolution: - { - integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} finalhandler@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: @@ -8070,1069 +6074,607 @@ 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@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] 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==} 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@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@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@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==} inflekt@0.3.1: - resolution: - { - integrity: sha512-z5jvjelE61KiWinkjlainPDROpO3u0NqlUsCoSTxrSV7yNhcnaIb71ckx3utm8GZ2wifjqGFyaqyYomSXEgMfQ==, - } + resolution: {integrity: sha512-z5jvjelE61KiWinkjlainPDROpO3u0NqlUsCoSTxrSV7yNhcnaIb71ckx3utm8GZ2wifjqGFyaqyYomSXEgMfQ==} inflight@1.0.6: - resolution: - { - integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==, - } + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. inherits@2.0.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==} inquirerer@4.5.0: - resolution: - { - integrity: sha512-ULWscyMV6Y/OH1XRODvunrQH1EO4r7q+UV/boWFiVIt9h2UZ7wa/Qc+ZpAqUaWynKUhDtY3UqZV4MVrRcEkmNg==, - } + resolution: {integrity: sha512-ULWscyMV6Y/OH1XRODvunrQH1EO4r7q+UV/boWFiVIt9h2UZ7wa/Qc+ZpAqUaWynKUhDtY3UqZV4MVrRcEkmNg==} ip-address@10.1.0: - resolution: - { - integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==, - } - engines: { node: '>= 12' } + resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} + engines: {node: '>= 12'} ipaddr.js@1.9.1: - resolution: - { - integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==, - } - engines: { node: '>= 0.10' } + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} ipv6-normalize@1.0.1: - resolution: - { - integrity: sha512-Bm6H79i01DjgGTCWjUuCjJ6QDo1HB96PT/xCYuyJUP9WFbVDrLSbG4EZCvOCun2rNswZb0c3e4Jt/ws795esHA==, - } + resolution: {integrity: sha512-Bm6H79i01DjgGTCWjUuCjJ6QDo1HB96PT/xCYuyJUP9WFbVDrLSbG4EZCvOCun2rNswZb0c3e4Jt/ws795esHA==} is-arrayish@0.2.1: - resolution: - { - integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==, - } + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} is-binary-path@2.1.0: - resolution: - { - integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} is-ci@3.0.1: - resolution: - { - integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==, - } + resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} hasBin: true is-core-module@2.16.1: - resolution: - { - integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==, - } - engines: { node: '>= 0.4' } + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} is-docker@2.2.1: - resolution: - { - integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} hasBin: true is-extglob@2.1.1: - resolution: - { - integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} is-fullwidth-code-point@3.0.0: - resolution: - { - integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} is-generator-fn@2.1.0: - resolution: - { - integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} is-glob@4.0.3: - resolution: - { - integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} is-interactive@1.0.0: - resolution: - { - integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} is-lambda@1.0.1: - resolution: - { - integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==, - } + resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} is-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@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 @@ -9141,11 +6683,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' @@ -9159,95 +6698,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: @@ -9255,81 +6755,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 @@ -9338,1116 +6805,611 @@ 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.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@10.4.0: - resolution: - { - integrity: sha512-YrdaZEAJwwjXGBTfZTNQ1LM7tmkdUaz2NpZEu7+zULcG4Wrlhd7cWSNZW0bxT3bP48k5N0mZWz8C2f9gc2+Geg==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-YrdaZEAJwwjXGBTfZTNQ1LM7tmkdUaz2NpZEu7+zULcG4Wrlhd7cWSNZW0bxT3bP48k5N0mZWz8C2f9gc2+Geg==} + engines: {node: '>=18.0.0'} makage@0.1.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'} 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==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true napi-postinstall@0.3.4: - resolution: - { - integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==, - } - engines: { node: ^12.20.0 || ^14.18.0 || >=16.0.0 } + resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} hasBin: true natural-compare@1.4.0: - resolution: - { - integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==, - } + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} negotiator@0.6.4: - resolution: - { - integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==, - } - engines: { node: '>= 0.6' } + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} negotiator@1.0.0: - resolution: - { - integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==, - } - engines: { node: '>= 0.6' } + resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} + engines: {node: '>= 0.6'} neo-async@2.6.2: - resolution: - { - integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==, - } + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} nested-obj@0.1.10: - resolution: - { - integrity: sha512-5V2kUPrBee/tmoS2p0IJ35BcaJuW1p1yXF5GP8JpXIkDoPbaYeYypAHizUeZkAUxcC7Rago7izWmEq7qa8+Mhw==, - } + resolution: {integrity: sha512-5V2kUPrBee/tmoS2p0IJ35BcaJuW1p1yXF5GP8JpXIkDoPbaYeYypAHizUeZkAUxcC7Rago7izWmEq7qa8+Mhw==} nested-obj@0.1.5: - resolution: - { - integrity: sha512-04Y7qDMlI8RbYTn0cJAKaw/mLrO9UmLj3xbrjTZKDfOn9f3b/RXEQFIIpveJlwn8KfPwdVFWLZUaL5gNuQ7G0w==, - } + resolution: {integrity: sha512-04Y7qDMlI8RbYTn0cJAKaw/mLrO9UmLj3xbrjTZKDfOn9f3b/RXEQFIIpveJlwn8KfPwdVFWLZUaL5gNuQ7G0w==} nested-obj@0.2.0: - resolution: - { - integrity: sha512-uPzih1V6f7yb563xUkFA/oainPdrlc0ojpV8OuRAg4qWK70TPt14D5hWuU3ta1eVacJQv+VVuMJRqFRyTgYZ0Q==, - } + resolution: {integrity: sha512-uPzih1V6f7yb563xUkFA/oainPdrlc0ojpV8OuRAg4qWK70TPt14D5hWuU3ta1eVacJQv+VVuMJRqFRyTgYZ0Q==} no-case@2.3.2: - resolution: - { - integrity: sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==, - } + resolution: {integrity: sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==} node-fetch@2.6.7: - resolution: - { - integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==, - } - engines: { node: 4.x || >=6.0.0 } + resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} + engines: {node: 4.x || >=6.0.0} peerDependencies: encoding: ^0.1.0 peerDependenciesMeta: @@ -10455,11 +7417,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: @@ -10467,173 +7426,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 @@ -10645,470 +7529,263 @@ 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.9.4: - resolution: - { - integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==, - } - engines: { node: '>= 0.8.0' } + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} ora@5.3.0: - resolution: - { - integrity: sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==} + engines: {node: '>=10'} ora@5.4.1: - resolution: - { - integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} oxfmt@0.26.0: - resolution: - { - integrity: sha512-UDD1wFNwfeorMm2ZY0xy1KRAAvJ5NjKBfbDmiMwGP7baEHTq65cYpC0aPP+BGHc8weXUbSZaK8MdGyvuRUvS4Q==, - } - engines: { node: ^20.19.0 || >=22.12.0 } + resolution: {integrity: sha512-UDD1wFNwfeorMm2ZY0xy1KRAAvJ5NjKBfbDmiMwGP7baEHTq65cYpC0aPP+BGHc8weXUbSZaK8MdGyvuRUvS4Q==} + engines: {node: ^20.19.0 || >=22.12.0} hasBin: true p-finally@1.0.0: - resolution: - { - integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} + engines: {node: '>=4'} p-limit@1.3.0: - resolution: - { - integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==} + engines: {node: '>=4'} p-limit@2.3.0: - resolution: - { - integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} p-limit@3.1.0: - resolution: - { - integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} p-locate@2.0.0: - resolution: - { - integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==} + engines: {node: '>=4'} p-locate@4.1.0: - resolution: - { - integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} p-locate@5.0.0: - resolution: - { - integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} p-map-series@2.1.0: - resolution: - { - integrity: sha512-RpYIIK1zXSNEOdwxcfe7FdvGcs7+y5n8rifMhMNWvaxRNMPINJHF5GDeuVxWqnfrcHPSCnp7Oo5yNXHId9Av2Q==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-RpYIIK1zXSNEOdwxcfe7FdvGcs7+y5n8rifMhMNWvaxRNMPINJHF5GDeuVxWqnfrcHPSCnp7Oo5yNXHId9Av2Q==} + engines: {node: '>=8'} p-map@4.0.0: - resolution: - { - integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} p-pipe@3.1.0: - resolution: - { - integrity: sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw==} + engines: {node: '>=8'} p-queue@6.6.2: - resolution: - { - integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==} + engines: {node: '>=8'} p-reduce@2.1.0: - resolution: - { - integrity: sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==} + engines: {node: '>=8'} p-timeout@3.2.0: - resolution: - { - integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} + engines: {node: '>=8'} p-try@1.0.0: - resolution: - { - integrity: sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==} + engines: {node: '>=4'} p-try@2.2.0: - resolution: - { - integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} p-waterfall@2.1.1: - resolution: - { - integrity: sha512-RRTnDb2TBG/epPRI2yYXsimO0v3BXC8Yd3ogr1545IaqKK17VGhbWVeGGN+XfCm/08OK8635nH31c8bATkHuSw==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-RRTnDb2TBG/epPRI2yYXsimO0v3BXC8Yd3ogr1545IaqKK17VGhbWVeGGN+XfCm/08OK8635nH31c8bATkHuSw==} + engines: {node: '>=8'} package-json-from-dist@1.0.1: - resolution: - { - integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==, - } + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} 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-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: @@ -11116,240 +7793,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==} + + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} 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.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: @@ -11357,175 +7936,100 @@ packages: optional: true promise-retry@2.0.1: - resolution: - { - integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} + engines: {node: '>=10'} promzard@1.0.2: - resolution: - { - integrity: sha512-2FPputGL+mP3jJ3UZg/Dl9YOkovB7DX0oOr+ck5QbZ5MtORtds8k/BZdn+02peDLI8/YWbmzx34k5fA+fHvCVQ==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-2FPputGL+mP3jJ3UZg/Dl9YOkovB7DX0oOr+ck5QbZ5MtORtds8k/BZdn+02peDLI8/YWbmzx34k5fA+fHvCVQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} proto-list@1.2.4: - resolution: - { - integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==, - } + resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} protocols@2.0.2: - resolution: - { - integrity: sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==, - } + resolution: {integrity: sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==} proxy-addr@2.0.7: - resolution: - { - integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==, - } - engines: { node: '>= 0.10' } + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} proxy-from-env@1.1.0: - resolution: - { - integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==, - } + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} 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@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-is@19.2.4: + resolution: {integrity: sha512-W+EWGn2v0ApPKgKKCy/7s7WHXkboGcsrXE+2joLyVxkbyVQfO3MUEaUQDHoSmb8TFFrSKYa9mw64WZHNHSDzYA==} react-query@3.39.3: - resolution: - { - integrity: sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g==, - } + resolution: {integrity: sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: '*' @@ -11536,947 +8040,568 @@ packages: react-native: optional: true + react-refresh@0.17.0: + resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} + engines: {node: '>=0.10.0'} + + react-test-renderer@19.2.3: + resolution: {integrity: sha512-TMR1LnSFiWZMJkCgNf5ATSvAheTT2NvKIwiVwdBPHxjBI7n/JbWd4gaZ16DVd9foAXdvDz+sB5yxZTwMjPRxpw==} + peerDependencies: + react: ^19.2.3 + react@19.2.3: - resolution: - { - integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==} + engines: {node: '>=0.10.0'} read-cmd-shim@4.0.0: - resolution: - { - integrity: sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} read-package-json-fast@3.0.2: - resolution: - { - integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} read-pkg-up@3.0.0: - resolution: - { - integrity: sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==} + engines: {node: '>=4'} read-pkg-up@7.0.1: - resolution: - { - integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} read-pkg@3.0.0: - resolution: - { - integrity: sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==} + engines: {node: '>=4'} read-pkg@5.2.0: - resolution: - { - integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} read@3.0.1: - resolution: - { - integrity: sha512-SLBrDU/Srs/9EoWhU5GdbAoxG1GzpQHo/6qiGItaoLJ1thmYpcNIM1qISEUvyHBzfGlWIyd6p2DNi1oV1VmAuw==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-SLBrDU/Srs/9EoWhU5GdbAoxG1GzpQHo/6qiGItaoLJ1thmYpcNIM1qISEUvyHBzfGlWIyd6p2DNi1oV1VmAuw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} readable-stream@1.0.34: - resolution: - { - integrity: sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==, - } + resolution: {integrity: sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==} readable-stream@2.3.8: - resolution: - { - integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==, - } + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} readable-stream@3.6.2: - resolution: - { - integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==, - } - engines: { node: '>= 6' } + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} readdirp@3.6.0: - resolution: - { - integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==, - } - engines: { node: '>=8.10.0' } + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} redent@3.0.0: - resolution: - { - integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} regenerator-runtime@0.10.5: - resolution: - { - integrity: sha512-02YopEIhAgiBHWeoTiA8aitHDt8z6w+rQqNuIftlM+ZtvSl/brTouaU7DW6GO/cHtvxJvS4Hwv2ibKdxIRi24w==, - } + resolution: {integrity: sha512-02YopEIhAgiBHWeoTiA8aitHDt8z6w+rQqNuIftlM+ZtvSl/brTouaU7DW6GO/cHtvxJvS4Hwv2ibKdxIRi24w==} relateurl@0.2.7: - resolution: - { - integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==, - } - engines: { node: '>= 0.10' } + resolution: {integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==} + engines: {node: '>= 0.10'} remove-accents@0.5.0: - resolution: - { - integrity: sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==, - } + resolution: {integrity: sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==} request-ip@3.3.0: - resolution: - { - integrity: sha512-cA6Xh6e0fDBBBwH77SLJaJPBmD3nWVAcF9/XAcsrIHdjhFzFiB5aNQFytdjCGPezU3ROwrR11IddKAM08vohxA==, - } + resolution: {integrity: sha512-cA6Xh6e0fDBBBwH77SLJaJPBmD3nWVAcF9/XAcsrIHdjhFzFiB5aNQFytdjCGPezU3ROwrR11IddKAM08vohxA==} 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 + + rollup-plugin-visualizer@6.0.5: + resolution: {integrity: sha512-9+HlNgKCVbJDs8tVtjQ43US12eqaiHyyiLMdBwQ7vSZPiHMysGNo2E88TAp1si5wx8NAoYriI2A5kuKfIakmJg==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + rolldown: 1.x || ^1.0.0-beta + rollup: 2.x || 3.x || 4.x + peerDependenciesMeta: + rolldown: + optional: true + rollup: + optional: true + + rollup@4.57.1: + resolution: {integrity: sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} 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@8.0.5: - resolution: - { - integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==, - } - engines: { node: '>= 14' } + resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} + engines: {node: '>= 14'} socks@2.8.7: - resolution: - { - integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==, - } - engines: { node: '>= 10.0.0', npm: '>= 3.0.0' } + resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} sort-keys@2.0.0: - resolution: - { - integrity: sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==} + engines: {node: '>=4'} sorted-array-functions@1.3.0: - resolution: - { - integrity: sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==, - } + resolution: {integrity: sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} source-map-resolve@0.6.0: - resolution: - { - integrity: sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==, - } + resolution: {integrity: sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==} deprecated: See https://github.com/lydell/source-map-resolve#deprecated source-map-support@0.5.13: - resolution: - { - integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==, - } + resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} source-map@0.6.1: - resolution: - { - integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + source-map@0.7.6: + resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} + engines: {node: '>= 12'} 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==} tinyglobby@0.2.12: - resolution: - { - integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==, - } - engines: { node: '>=12.0.0' } + resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} + engines: {node: '>=12.0.0'} tinyglobby@0.2.15: - resolution: - { - integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==, - } - engines: { node: '>=12.0.0' } + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} tinypool@2.0.0: - resolution: - { - integrity: sha512-/RX9RzeH2xU5ADE7n2Ykvmi9ED3FBGPAjw9u3zucrNNaEBIO0HPSYgL0NT7+3p147ojeSdaVu08F6hjpv31HJg==, - } - engines: { node: ^20.0.0 || >=22.0.0 } + resolution: {integrity: sha512-/RX9RzeH2xU5ADE7n2Ykvmi9ED3FBGPAjw9u3zucrNNaEBIO0HPSYgL0NT7+3p147ojeSdaVu08F6hjpv31HJg==} + engines: {node: ^20.0.0 || >=22.0.0} tmp@0.2.5: - resolution: - { - integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==, - } - engines: { node: '>=14.14' } + resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==} + engines: {node: '>=14.14'} tmpl@1.0.5: - resolution: - { - integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==, - } + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} to-regex-range@5.0.1: - resolution: - { - integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==, - } - engines: { node: '>=8.0' } + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} toidentifier@1.0.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' @@ -12502,10 +8627,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' @@ -12519,491 +8641,315 @@ packages: optional: true tsconfig-paths@4.2.0: - resolution: - { - integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} + engines: {node: '>=6'} tslib@2.8.1: - resolution: - { - integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==, - } + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} tsx@4.21.0: - resolution: - { - integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==, - } - engines: { node: '>=18.0.0' } + resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} + engines: {node: '>=18.0.0'} hasBin: true tuf-js@2.2.1: - resolution: - { - integrity: sha512-GwIJau9XaA8nLVbUXsN3IlFi7WmQ48gBUrl3FTkkL/XLu/POhBzfmX9hd33FNMX1qAsfl6ozO1iMmW9NC8YniA==, - } - engines: { node: ^16.14.0 || >=18.0.0 } + resolution: {integrity: sha512-GwIJau9XaA8nLVbUXsN3IlFi7WmQ48gBUrl3FTkkL/XLu/POhBzfmX9hd33FNMX1qAsfl6ozO1iMmW9NC8YniA==} + engines: {node: ^16.14.0 || >=18.0.0} 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.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'} undici@7.19.0: - resolution: - { - integrity: sha512-Heho1hJD81YChi+uS2RkSjcVO+EQLmLSyUlHyp7Y/wFbxQaGb4WXVKD073JytrjXJVkSZVzoE2MCSOKugFGtOQ==, - } - engines: { node: '>=20.18.1' } + resolution: {integrity: sha512-Heho1hJD81YChi+uS2RkSjcVO+EQLmLSyUlHyp7Y/wFbxQaGb4WXVKD073JytrjXJVkSZVzoE2MCSOKugFGtOQ==} + engines: {node: '>=20.18.1'} unique-filename@3.0.0: - resolution: - { - integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} unique-slug@4.0.0: - resolution: - { - integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} universal-user-agent@6.0.1: - resolution: - { - integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==, - } + resolution: {integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==} universalify@2.0.1: - resolution: - { - integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==, - } - engines: { node: '>= 10.0.0' } + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} unload@2.2.0: - resolution: - { - integrity: sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==, - } + resolution: {integrity: sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==} unpipe@1.0.0: - resolution: - { - integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==, - } - engines: { node: '>= 0.8' } + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} unrs-resolver@1.11.1: - resolution: - { - integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==, - } + resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} untildify@4.0.0: - resolution: - { - integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} + engines: {node: '>=8'} upath@2.0.1: - resolution: - { - integrity: sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==, - } - engines: { node: '>=4' } + resolution: {integrity: sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==} + engines: {node: '>=4'} update-browserslist-db@1.2.3: - resolution: - { - integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==, - } + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' upper-case@1.1.3: - resolution: - { - integrity: sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==, - } + resolution: {integrity: sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==} uri-js@4.4.1: - resolution: - { - integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==, - } + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} url-join@4.0.1: - resolution: - { - integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==, - } + resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==} 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} 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} + + vite@6.4.1: + resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true walk-up-path@3.0.1: - resolution: - { - integrity: sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==, - } + resolution: {integrity: sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==} walker@1.0.8: - resolution: - { - integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==, - } + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} warning@3.0.0: - resolution: - { - integrity: sha512-jMBt6pUrKn5I+OGgtQ4YZLdhIeJmObddh6CsibPxyQ5yPZm1XExSyzC1LCNX7BzhxWgiHmizBWJTHJIjMjTQYQ==, - } + resolution: {integrity: sha512-jMBt6pUrKn5I+OGgtQ4YZLdhIeJmObddh6CsibPxyQ5yPZm1XExSyzC1LCNX7BzhxWgiHmizBWJTHJIjMjTQYQ==} wcwidth@1.0.1: - resolution: - { - integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==, - } + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} web-resource-inliner@5.0.0: - resolution: - { - integrity: sha512-AIihwH+ZmdHfkJm7BjSXiEClVt4zUFqX4YlFAzjL13wLtDuUneSaFvDBTbdYRecs35SiU7iNKbMnN+++wVfb6A==, - } - engines: { node: '>=10.0.0' } + resolution: {integrity: sha512-AIihwH+ZmdHfkJm7BjSXiEClVt4zUFqX4YlFAzjL13wLtDuUneSaFvDBTbdYRecs35SiU7iNKbMnN+++wVfb6A==} + engines: {node: '>=10.0.0'} webidl-conversions@3.0.1: - resolution: - { - integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==, - } + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} whatwg-encoding@3.1.1: - resolution: - { - integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation whatwg-mimetype@4.0.0: - resolution: - { - integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==, - } - engines: { node: '>=18' } + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} whatwg-url@5.0.0: - resolution: - { - integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==, - } + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} which-module@2.0.1: - resolution: - { - integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==, - } + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} which@2.0.2: - resolution: - { - integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==, - } - engines: { node: '>= 8' } + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} hasBin: true which@4.0.0: - resolution: - { - integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==, - } - engines: { node: ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==} + engines: {node: ^16.13.0 || >=18.0.0} hasBin: true wide-align@1.1.5: - resolution: - { - integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==, - } + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} word-wrap@1.2.5: - resolution: - { - integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==, - } - engines: { node: '>=0.10.0' } + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} wordwrap@1.0.0: - resolution: - { - integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==, - } + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} wrap-ansi@6.2.0: - resolution: - { - integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} wrap-ansi@7.0.0: - resolution: - { - integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} wrap-ansi@8.1.0: - resolution: - { - integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==, - } - engines: { node: '>=12' } + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} wrappy@1.0.2: - resolution: - { - integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==, - } + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} write-file-atomic@2.4.3: - resolution: - { - integrity: sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==, - } + resolution: {integrity: sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==} write-file-atomic@5.0.1: - resolution: - { - integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} write-json-file@3.2.0: - resolution: - { - integrity: sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==, - } - engines: { node: '>=6' } + resolution: {integrity: sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==} + engines: {node: '>=6'} write-pkg@4.0.0: - resolution: - { - integrity: sha512-v2UQ+50TNf2rNHJ8NyWttfm/EJUBWMJcx6ZTYZr6Qp52uuegWw/lBkCtCbnYZEmPRNL61m+u67dAmGxo+HTULA==, - } - engines: { node: '>=8' } + resolution: {integrity: sha512-v2UQ+50TNf2rNHJ8NyWttfm/EJUBWMJcx6ZTYZr6Qp52uuegWw/lBkCtCbnYZEmPRNL61m+u67dAmGxo+HTULA==} + engines: {node: '>=8'} ws@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 @@ -13014,114 +8960,67 @@ packages: optional: true xtend@4.0.2: - resolution: - { - integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==, - } - engines: { node: '>=0.4' } + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} y18n@4.0.3: - resolution: - { - integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==, - } + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} y18n@5.0.8: - resolution: - { - integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==, - } - engines: { node: '>=10' } + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} yallist@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: + '@0no-co/graphql.web@1.2.0(graphql@15.10.1)': optionalDependencies: graphql: 15.10.1 @@ -14125,6 +10024,16 @@ snapshots: '@babel/core': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.6)': + dependencies: + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.6)': + dependencies: + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/runtime-corejs3@7.28.4': dependencies: core-js-pure: 3.47.0 @@ -14217,81 +10126,159 @@ snapshots: '@emotion/unitless@0.7.5': {} + '@esbuild/aix-ppc64@0.25.12': + optional: true + '@esbuild/aix-ppc64@0.27.2': optional: true + '@esbuild/android-arm64@0.25.12': + optional: true + '@esbuild/android-arm64@0.27.2': optional: true + '@esbuild/android-arm@0.25.12': + optional: true + '@esbuild/android-arm@0.27.2': optional: true + '@esbuild/android-x64@0.25.12': + optional: true + '@esbuild/android-x64@0.27.2': optional: true + '@esbuild/darwin-arm64@0.25.12': + optional: true + '@esbuild/darwin-arm64@0.27.2': optional: true + '@esbuild/darwin-x64@0.25.12': + optional: true + '@esbuild/darwin-x64@0.27.2': optional: true + '@esbuild/freebsd-arm64@0.25.12': + optional: true + '@esbuild/freebsd-arm64@0.27.2': optional: true + '@esbuild/freebsd-x64@0.25.12': + optional: true + '@esbuild/freebsd-x64@0.27.2': optional: true + '@esbuild/linux-arm64@0.25.12': + optional: true + '@esbuild/linux-arm64@0.27.2': optional: true + '@esbuild/linux-arm@0.25.12': + optional: true + '@esbuild/linux-arm@0.27.2': optional: true + '@esbuild/linux-ia32@0.25.12': + optional: true + '@esbuild/linux-ia32@0.27.2': optional: true + '@esbuild/linux-loong64@0.25.12': + optional: true + '@esbuild/linux-loong64@0.27.2': optional: true + '@esbuild/linux-mips64el@0.25.12': + optional: true + '@esbuild/linux-mips64el@0.27.2': optional: true + '@esbuild/linux-ppc64@0.25.12': + optional: true + '@esbuild/linux-ppc64@0.27.2': optional: true + '@esbuild/linux-riscv64@0.25.12': + optional: true + '@esbuild/linux-riscv64@0.27.2': optional: true + '@esbuild/linux-s390x@0.25.12': + optional: true + '@esbuild/linux-s390x@0.27.2': optional: true + '@esbuild/linux-x64@0.25.12': + optional: true + '@esbuild/linux-x64@0.27.2': optional: true + '@esbuild/netbsd-arm64@0.25.12': + optional: true + '@esbuild/netbsd-arm64@0.27.2': optional: true + '@esbuild/netbsd-x64@0.25.12': + optional: true + '@esbuild/netbsd-x64@0.27.2': optional: true + '@esbuild/openbsd-arm64@0.25.12': + optional: true + '@esbuild/openbsd-arm64@0.27.2': optional: true + '@esbuild/openbsd-x64@0.25.12': + optional: true + '@esbuild/openbsd-x64@0.27.2': optional: true + '@esbuild/openharmony-arm64@0.25.12': + optional: true + '@esbuild/openharmony-arm64@0.27.2': optional: true + '@esbuild/sunos-x64@0.25.12': + optional: true + '@esbuild/sunos-x64@0.27.2': optional: true + '@esbuild/win32-arm64@0.25.12': + optional: true + '@esbuild/win32-arm64@0.27.2': optional: true + '@esbuild/win32-ia32@0.25.12': + optional: true + '@esbuild/win32-ia32@0.27.2': optional: true + '@esbuild/win32-x64@0.25.12': + optional: true + '@esbuild/win32-x64@0.27.2': optional: true @@ -14632,14 +10619,14 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@launchql/mjml@0.1.1(@babel/core@7.28.6)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react-is@18.3.1)(react@19.2.3)': + '@launchql/mjml@0.1.1(@babel/core@7.28.6)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react-is@19.2.4)(react@19.2.3)': dependencies: '@babel/runtime': 7.28.4 mjml: 4.7.1(encoding@0.1.13) mjml-react: 1.0.59(mjml@4.7.1(encoding@0.1.13))(react-dom@19.2.3(react@19.2.3))(react@19.2.3) react: 19.2.3 react-dom: 19.2.3(react@19.2.3) - styled-components: 5.3.11(@babel/core@7.28.6)(react-dom@19.2.3(react@19.2.3))(react-is@18.3.1)(react@19.2.3) + styled-components: 5.3.11(@babel/core@7.28.6)(react-dom@19.2.3(react@19.2.3))(react-is@19.2.4)(react@19.2.3) styled-system: 5.1.5 transitivePeerDependencies: - '@babel/core' @@ -14661,13 +10648,13 @@ snapshots: '@types/node': 20.19.27 long: 5.3.2 - '@launchql/styled-email@0.1.0(@babel/core@7.28.6)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react-is@18.3.1)(react@19.2.3)': + '@launchql/styled-email@0.1.0(@babel/core@7.28.6)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react-is@19.2.4)(react@19.2.3)': dependencies: '@babel/runtime': 7.28.4 juice: 7.0.0(encoding@0.1.13) react: 19.2.3 react-dom: 19.2.3(react@19.2.3) - styled-components: 5.3.11(@babel/core@7.28.6)(react-dom@19.2.3(react@19.2.3))(react-is@18.3.1)(react@19.2.3) + styled-components: 5.3.11(@babel/core@7.28.6)(react-dom@19.2.3(react@19.2.3))(react-is@19.2.4)(react@19.2.3) styled-system: 5.1.5 transitivePeerDependencies: - '@babel/core' @@ -15121,6 +11108,83 @@ snapshots: '@protobufjs/utf8@1.1.0': {} + '@rolldown/pluginutils@1.0.0-beta.27': {} + + '@rollup/rollup-android-arm-eabi@4.57.1': + optional: true + + '@rollup/rollup-android-arm64@4.57.1': + optional: true + + '@rollup/rollup-darwin-arm64@4.57.1': + optional: true + + '@rollup/rollup-darwin-x64@4.57.1': + optional: true + + '@rollup/rollup-freebsd-arm64@4.57.1': + optional: true + + '@rollup/rollup-freebsd-x64@4.57.1': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.57.1': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.57.1': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.57.1': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.57.1': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.57.1': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.57.1': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.57.1': + optional: true + + '@rollup/rollup-linux-x64-musl@4.57.1': + optional: true + + '@rollup/rollup-openbsd-x64@4.57.1': + optional: true + + '@rollup/rollup-openharmony-arm64@4.57.1': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.57.1': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.57.1': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.57.1': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.57.1': + optional: true + '@sigstore/bundle@2.3.2': dependencies: '@sigstore/protobuf-specs': 0.3.3 @@ -15744,11 +11808,18 @@ snapshots: '@tanstack/query-core@5.90.19': {} + '@tanstack/query-core@5.90.20': {} + '@tanstack/react-query@5.90.19(react@19.2.3)': dependencies: '@tanstack/query-core': 5.90.19 react: 19.2.3 + '@tanstack/react-query@5.90.20(react@19.2.3)': + dependencies: + '@tanstack/query-core': 5.90.20 + react: 19.2.3 + '@testing-library/dom@7.31.2': dependencies: '@babel/code-frame': 7.27.1 @@ -15971,6 +12042,14 @@ snapshots: '@types/range-parser@1.2.7': {} + '@types/react-dom@19.2.3(@types/react@19.2.13)': + dependencies: + '@types/react': 19.2.13 + + '@types/react@19.2.13': + dependencies: + csstype: 3.2.3 + '@types/react@19.2.8': dependencies: csstype: 3.2.3 @@ -16186,6 +12265,18 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.11.1': optional: true + '@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@20.19.27)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2))': + dependencies: + '@babel/core': 7.28.6 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.6) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.6) + '@rolldown/pluginutils': 1.0.0-beta.27 + '@types/babel__core': 7.20.5 + react-refresh: 0.17.0 + vite: 6.4.1(@types/node@20.19.27)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2) + transitivePeerDependencies: + - supports-color + '@yarnpkg/lockfile@1.1.0': {} '@yarnpkg/parsers@3.0.2': @@ -16362,14 +12453,14 @@ snapshots: dependencies: '@types/babel__core': 7.20.5 - babel-plugin-styled-components@2.1.4(@babel/core@7.28.6)(styled-components@5.3.11(@babel/core@7.28.6)(react-dom@19.2.3(react@19.2.3))(react-is@18.3.1)(react@19.2.3))(supports-color@5.5.0): + babel-plugin-styled-components@2.1.4(@babel/core@7.28.6)(styled-components@5.3.11(@babel/core@7.28.6)(react-dom@19.2.3(react@19.2.3))(react-is@19.2.4)(react@19.2.3))(supports-color@5.5.0): dependencies: '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-module-imports': 7.27.1(supports-color@5.5.0) '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.6) lodash: 4.17.21 picomatch: 2.3.1 - styled-components: 5.3.11(@babel/core@7.28.6)(react-dom@19.2.3(react@19.2.3))(react-is@18.3.1)(react@19.2.3) + styled-components: 5.3.11(@babel/core@7.28.6)(react-dom@19.2.3(react@19.2.3))(react-is@19.2.4)(react@19.2.3) transitivePeerDependencies: - '@babel/core' - supports-color @@ -17191,6 +13282,35 @@ snapshots: has-tostringtag: 1.0.2 hasown: 2.0.2 + esbuild@0.25.12: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.12 + '@esbuild/android-arm': 0.25.12 + '@esbuild/android-arm64': 0.25.12 + '@esbuild/android-x64': 0.25.12 + '@esbuild/darwin-arm64': 0.25.12 + '@esbuild/darwin-x64': 0.25.12 + '@esbuild/freebsd-arm64': 0.25.12 + '@esbuild/freebsd-x64': 0.25.12 + '@esbuild/linux-arm': 0.25.12 + '@esbuild/linux-arm64': 0.25.12 + '@esbuild/linux-ia32': 0.25.12 + '@esbuild/linux-loong64': 0.25.12 + '@esbuild/linux-mips64el': 0.25.12 + '@esbuild/linux-ppc64': 0.25.12 + '@esbuild/linux-riscv64': 0.25.12 + '@esbuild/linux-s390x': 0.25.12 + '@esbuild/linux-x64': 0.25.12 + '@esbuild/netbsd-arm64': 0.25.12 + '@esbuild/netbsd-x64': 0.25.12 + '@esbuild/openbsd-arm64': 0.25.12 + '@esbuild/openbsd-x64': 0.25.12 + '@esbuild/openharmony-arm64': 0.25.12 + '@esbuild/sunos-x64': 0.25.12 + '@esbuild/win32-arm64': 0.25.12 + '@esbuild/win32-ia32': 0.25.12 + '@esbuild/win32-x64': 0.25.12 + esbuild@0.27.2: optionalDependencies: '@esbuild/aix-ppc64': 0.27.2 @@ -19314,6 +15434,8 @@ snapshots: dependencies: big-integer: 1.6.52 + nanoid@3.3.11: {} + napi-postinstall@0.3.4: {} natural-compare@1.4.0: {} @@ -19702,7 +15824,7 @@ snapshots: parse-json@5.2.0: dependencies: - '@babel/code-frame': 7.27.1 + '@babel/code-frame': 7.28.6 error-ex: 1.3.4 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -19878,6 +16000,12 @@ snapshots: postcss-value-parser@4.2.0: {} + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + postgraphile-core@4.14.1(graphql@15.10.1)(pg@8.17.1): dependencies: graphile-build: 4.14.1(graphql@15.10.1) @@ -20045,6 +16173,8 @@ snapshots: react-is@18.3.1: {} + react-is@19.2.4: {} + react-query@3.39.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3): dependencies: '@babel/runtime': 7.28.4 @@ -20054,6 +16184,14 @@ snapshots: optionalDependencies: react-dom: 19.2.3(react@19.2.3) + react-refresh@0.17.0: {} + + react-test-renderer@19.2.3(react@19.2.3): + dependencies: + react: 19.2.3 + react-is: 19.2.4 + scheduler: 0.27.0 + react@19.2.3: {} read-cmd-shim@4.0.0: {} @@ -20200,6 +16338,46 @@ snapshots: glob: 13.0.0 package-json-from-dist: 1.0.1 + rollup-plugin-visualizer@6.0.5(rollup@4.57.1): + dependencies: + open: 8.4.2 + picomatch: 4.0.3 + source-map: 0.7.6 + yargs: 17.7.2 + optionalDependencies: + rollup: 4.57.1 + + rollup@4.57.1: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.57.1 + '@rollup/rollup-android-arm64': 4.57.1 + '@rollup/rollup-darwin-arm64': 4.57.1 + '@rollup/rollup-darwin-x64': 4.57.1 + '@rollup/rollup-freebsd-arm64': 4.57.1 + '@rollup/rollup-freebsd-x64': 4.57.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.57.1 + '@rollup/rollup-linux-arm-musleabihf': 4.57.1 + '@rollup/rollup-linux-arm64-gnu': 4.57.1 + '@rollup/rollup-linux-arm64-musl': 4.57.1 + '@rollup/rollup-linux-loong64-gnu': 4.57.1 + '@rollup/rollup-linux-loong64-musl': 4.57.1 + '@rollup/rollup-linux-ppc64-gnu': 4.57.1 + '@rollup/rollup-linux-ppc64-musl': 4.57.1 + '@rollup/rollup-linux-riscv64-gnu': 4.57.1 + '@rollup/rollup-linux-riscv64-musl': 4.57.1 + '@rollup/rollup-linux-s390x-gnu': 4.57.1 + '@rollup/rollup-linux-x64-gnu': 4.57.1 + '@rollup/rollup-linux-x64-musl': 4.57.1 + '@rollup/rollup-openbsd-x64': 4.57.1 + '@rollup/rollup-openharmony-arm64': 4.57.1 + '@rollup/rollup-win32-arm64-msvc': 4.57.1 + '@rollup/rollup-win32-ia32-msvc': 4.57.1 + '@rollup/rollup-win32-x64-gnu': 4.57.1 + '@rollup/rollup-win32-x64-msvc': 4.57.1 + fsevents: 2.3.3 + router@2.2.0: dependencies: debug: 4.4.3(supports-color@5.5.0) @@ -20370,6 +16548,8 @@ snapshots: sorted-array-functions@1.3.0: {} + source-map-js@1.2.1: {} + source-map-resolve@0.6.0: dependencies: atob: 2.1.2 @@ -20382,6 +16562,8 @@ snapshots: source-map@0.6.1: {} + source-map@0.7.6: {} + spdx-correct@3.2.0: dependencies: spdx-expression-parse: 3.0.1 @@ -20492,19 +16674,19 @@ snapshots: strnum@2.1.2: {} - styled-components@5.3.11(@babel/core@7.28.6)(react-dom@19.2.3(react@19.2.3))(react-is@18.3.1)(react@19.2.3): + styled-components@5.3.11(@babel/core@7.28.6)(react-dom@19.2.3(react@19.2.3))(react-is@19.2.4)(react@19.2.3): dependencies: '@babel/helper-module-imports': 7.27.1(supports-color@5.5.0) '@babel/traverse': 7.28.6(supports-color@5.5.0) '@emotion/is-prop-valid': 1.4.0 '@emotion/stylis': 0.8.5 '@emotion/unitless': 0.7.5 - babel-plugin-styled-components: 2.1.4(@babel/core@7.28.6)(styled-components@5.3.11(@babel/core@7.28.6)(react-dom@19.2.3(react@19.2.3))(react-is@18.3.1)(react@19.2.3))(supports-color@5.5.0) + babel-plugin-styled-components: 2.1.4(@babel/core@7.28.6)(styled-components@5.3.11(@babel/core@7.28.6)(react-dom@19.2.3(react@19.2.3))(react-is@19.2.4)(react@19.2.3))(supports-color@5.5.0) css-to-react-native: 3.2.0 hoist-non-react-statics: 3.3.2 react: 19.2.3 react-dom: 19.2.3(react@19.2.3) - react-is: 18.3.1 + react-is: 19.2.4 shallowequal: 1.1.0 supports-color: 5.5.0 transitivePeerDependencies: @@ -20870,6 +17052,21 @@ snapshots: core-util-is: 1.0.2 extsprintf: 1.3.0 + vite@6.4.1(@types/node@20.19.27)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2): + dependencies: + esbuild: 0.25.12 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.57.1 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 20.19.27 + fsevents: 2.3.3 + jiti: 2.6.1 + tsx: 4.21.0 + yaml: 2.8.2 + walk-up-path@3.0.1: {} walker@1.0.8: