diff --git a/examples/complex-app/package.json b/examples/complex-app/package.json index 5d1a5e10c..941001a18 100644 --- a/examples/complex-app/package.json +++ b/examples/complex-app/package.json @@ -33,7 +33,7 @@ "prisma": "^6.0.0", "react": "^18.3.1", "urql": "^4.2.1", - "zod": "^3.23.8" + "zod": "^3.24.1" }, "publishConfig": { "access": "public" diff --git a/packages/core/package.json b/packages/core/package.json index 618c1267f..2f7998026 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -47,7 +47,7 @@ "provenance": true }, "peerDependencies": { - "graphql": ">=16.6.0" + "graphql": "^16.8.1" }, "devDependencies": { "@pothos/test-utils": "workspace:*", diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index c669beede..f7a9f54a8 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -17,11 +17,18 @@ import { ListRef as InternalListRef } from './refs/list'; import { ObjectRef as InternalObjectRef } from './refs/object'; import { ScalarRef as InternalScalarRef } from './refs/scalar'; import { UnionRef as InternalUnionRef } from './refs/union'; +import { FieldRef as InternalFieldRef } from './refs/field'; +import { InputFieldRef as InternalInputFieldRef } from './refs/input-field'; +import { ArgumentRef as InternalArgumentRef } from './refs/arg'; + import type { AddVersionedDefaultsToBuilderOptions, FieldKind, InputTypeParam, NormalizeSchemeBuilderOptions, + PothosInputFieldConfig, + PothosOutputFieldConfig, + PothosTypeConfig, RootName, SchemaTypes, TypeParam, @@ -203,12 +210,37 @@ export const ListRef = InternalListRef as new PothosSchemaTypes.ListRef; +export type FieldRef< + Types extends SchemaTypes, + T = unknown, + Kind extends FieldKind = FieldKind, +> = PothosSchemaTypes.FieldRef; +export const FieldRef = InternalFieldRef as new < + Types extends SchemaTypes, + T = unknown, + Kind extends FieldKind = FieldKind, +>( + kind: Kind, + initConfig: (name: string, typeConfig: PothosTypeConfig) => PothosOutputFieldConfig, +) => PothosSchemaTypes.FieldRef; + +export type InputFieldRef = PothosSchemaTypes.InputFieldRef; +export const InputFieldRef = InternalInputFieldRef as new ( + initConfig: (name: string, typeConfig: PothosTypeConfig) => PothosInputFieldConfig, +) => PothosSchemaTypes.InputFieldRef; + +export type ArgumentRef = PothosSchemaTypes.ArgumentRef; +export const ArgumentRef = InternalArgumentRef as new ( + initConfig: ( + name: string, + field: string, + typeConfig: PothosTypeConfig, + ) => PothosInputFieldConfig, +) => PothosSchemaTypes.ArgumentRef; + export { BuildCache } from './build-cache'; -export { ArgumentRef } from './refs/arg'; export { BuiltinScalarRef } from './refs/builtin-scalar'; -export { FieldRef } from './refs/field'; export { InputTypeRef } from './refs/input'; -export { InputFieldRef } from './refs/input-field'; export { ImplementableInputObjectRef } from './refs/input-object'; export { ImplementableInterfaceRef } from './refs/interface'; export { MutationRef } from './refs/mutation'; diff --git a/packages/core/src/plugins/merge-plugins.ts b/packages/core/src/plugins/merge-plugins.ts index 348b14979..a8d60410c 100644 --- a/packages/core/src/plugins/merge-plugins.ts +++ b/packages/core/src/plugins/merge-plugins.ts @@ -16,6 +16,7 @@ import type { SchemaTypes, } from '../types'; import { BasePlugin } from './plugin'; +import { completeValue, reduceMaybeAsync } from '../utils'; export class MergedPlugins extends BasePlugin { plugins; @@ -77,14 +78,13 @@ export class MergedPlugins extends BasePlugin const argMappers = fieldConfig.argMappers; return (parent, args, context, info) => { - const mappedArgs = argMappers.reduce( - (acc, argMapper) => { - return argMapper(acc, context, info); - }, - args as Record, - ); + const mappedArgs = reduceMaybeAsync(argMappers, args, (acc, argMapper) => { + return argMapper(acc as Record, context, info); + }); - return wrapped(parent, mappedArgs, context, info); + return completeValue(mappedArgs, (mappedArgs) => + wrapped(parent, mappedArgs, context, info), + ); }; } @@ -106,14 +106,11 @@ export class MergedPlugins extends BasePlugin const argMappers = fieldConfig.argMappers; return (parent, args, context, info) => { - const mappedArgs = argMappers.reduce( - (acc, argMapper) => { - return argMapper(acc, context, info); - }, - args as Record, - ); - - return wrapped(parent, mappedArgs, context, info); + const mappedArgs = reduceMaybeAsync(argMappers, args, (acc, argMapper) => { + return argMapper(acc as Record, context, info); + }); + + return completeValue(mappedArgs, (mappedArgs) => wrapped(parent, mappedArgs, context, info)); }; } diff --git a/packages/core/src/refs/field.ts b/packages/core/src/refs/field.ts index 6923d843e..a0701af8f 100644 --- a/packages/core/src/refs/field.ts +++ b/packages/core/src/refs/field.ts @@ -6,7 +6,9 @@ import { outputFieldShapeKey, } from '../types'; -export class FieldRef { +export class FieldRef + implements PothosSchemaTypes.FieldRef +{ kind: FieldKind; fieldName?: string; diff --git a/packages/core/src/refs/input-field.ts b/packages/core/src/refs/input-field.ts index 6e3998e7b..1ac8e12a8 100644 --- a/packages/core/src/refs/input-field.ts +++ b/packages/core/src/refs/input-field.ts @@ -5,7 +5,9 @@ import { inputFieldShapeKey, } from '../types'; -export class InputFieldRef { +export class InputFieldRef + implements PothosSchemaTypes.InputFieldRef +{ kind = 'InputObject' as const; fieldName?: string; diff --git a/packages/core/src/types/configs.ts b/packages/core/src/types/configs.ts index 62928bdb8..ae0d29734 100644 --- a/packages/core/src/types/configs.ts +++ b/packages/core/src/types/configs.ts @@ -28,7 +28,7 @@ import type { OutputType, TypeParam, } from './type-params'; -import type { Merge, MergeUnion, PartialResolveInfo } from './utils'; +import type { MaybePromise, Merge, MergeUnion, PartialResolveInfo } from './utils'; export interface PothosQueryTypeConfig extends Omit, 'fields' | 'interfaces'> { @@ -127,7 +127,7 @@ export type PothosFieldKindToConfig, context: Types['Context'], info: PartialResolveInfo, - ) => Record)[]; + ) => MaybePromise>)[]; pothosOptions: FieldOptionsFromKind< Types, unknown, diff --git a/packages/core/src/types/global/classes.ts b/packages/core/src/types/global/classes.ts index 37507e3c8..850cebc07 100644 --- a/packages/core/src/types/global/classes.ts +++ b/packages/core/src/types/global/classes.ts @@ -11,6 +11,9 @@ import type { ListRef as InternalListRef } from '../../refs/list'; import type { ObjectRef as InternalObjectRef } from '../../refs/object'; import type { ScalarRef as InternalScalarRef } from '../../refs/scalar'; import type { UnionRef as InternalUnionRef } from '../../refs/union'; +import type { FieldRef as InternalFieldRef } from '../../refs/field'; +import type { InputFieldRef as InternalInputFieldRef } from '../../refs/input-field'; +import type { ArgumentRef as InternalArgumentRef } from '../../refs/arg'; import type { FieldKind } from '../builder-options'; import type { SchemaTypes } from '../schema-types'; @@ -68,5 +71,17 @@ declare global { extends InternalUnionRef {} export interface ListRef extends InternalListRef {} + + export interface FieldRef< + Types extends SchemaTypes, + T = unknown, + Kind extends FieldKind = FieldKind, + > extends InternalFieldRef {} + + export interface InputFieldRef + extends InternalInputFieldRef {} + + export interface ArgumentRef + extends InternalArgumentRef {} } } diff --git a/packages/core/src/types/type-params.ts b/packages/core/src/types/type-params.ts index 43781fee7..94daa49a5 100644 --- a/packages/core/src/types/type-params.ts +++ b/packages/core/src/types/type-params.ts @@ -259,9 +259,9 @@ export type InputOrArgRef< T, Kind extends 'Arg' | 'InputObject', > = Kind extends 'Arg' - ? ArgumentRef + ? PothosSchemaTypes.ArgumentRef : Kind extends 'InputObject' - ? InputFieldRef + ? PothosSchemaTypes.InputFieldRef : never; export interface GenericFieldRef { diff --git a/packages/core/src/utils/index.ts b/packages/core/src/utils/index.ts index af54b56e6..7cc59252e 100644 --- a/packages/core/src/utils/index.ts +++ b/packages/core/src/utils/index.ts @@ -11,6 +11,7 @@ import { ListRef } from '../refs/list'; import { type InputType, type InputTypeParam, + type MaybePromise, type OutputType, type PartialResolveInfo, type PothosOutputFieldConfig, @@ -154,8 +155,8 @@ export function unwrapInputListParam( */ export function completeValue( valOrPromise: PromiseLike | T, - onSuccess: (completedVal: T) => R, - onError?: (errVal: unknown) => R, + onSuccess: (completedVal: T) => PromiseLike | R, + onError?: (errVal: unknown) => PromiseLike | R, ): Promise | R { if (isThenable(valOrPromise)) { return Promise.resolve(valOrPromise).then(onSuccess, onError); @@ -183,11 +184,26 @@ export function getMappedArgumentValues( | undefined; if (mappers && mappers.length > 0) { - return mappers.reduce>( - (acc, argMapper) => argMapper(acc, context, info), - args, - ); + return reduceMaybeAsync(mappers, args, (acc, argMapper) => argMapper(acc, context, info)); } return args; } + +export function reduceMaybeAsync( + items: T[], + initialValue: R, + fn: (value: R, item: T, i: number) => MaybePromise, +): MaybePromise { + function next(value: R, i: number): MaybePromise { + if (i === items.length) { + return value; + } + + return completeValue(fn(value, items[i], i), (result) => { + return result === null ? (null as R) : next(result, i + 1); + }); + } + + return next(initialValue, 0); +} diff --git a/packages/plugin-add-graphql/package.json b/packages/plugin-add-graphql/package.json index 6df339550..1d0f374d1 100644 --- a/packages/plugin-add-graphql/package.json +++ b/packages/plugin-add-graphql/package.json @@ -31,14 +31,22 @@ }, "author": "Michael Hayes", "license": "ISC", - "keywords": ["pothos", "graphql", "schema", "typescript", "add", "existing", "plugin"], + "keywords": [ + "pothos", + "graphql", + "schema", + "typescript", + "add", + "existing", + "plugin" + ], "publishConfig": { "access": "public", "provenance": true }, "peerDependencies": { "@pothos/core": "*", - "graphql": ">=16.6.0" + "graphql": "^16.8.1" }, "devDependencies": { "@pothos/core": "workspace:*", diff --git a/packages/plugin-add-graphql/src/schema-builder.ts b/packages/plugin-add-graphql/src/schema-builder.ts index c29b45b8d..2a4d8fb14 100644 --- a/packages/plugin-add-graphql/src/schema-builder.ts +++ b/packages/plugin-add-graphql/src/schema-builder.ts @@ -131,7 +131,7 @@ proto.addGraphQLObject = function addGraphQLObject( continue; } - const args: Record> = {}; + const args: Record> = {}; for (const { name, ...arg } of field.args) { const input = resolveInputType(this, arg.type); @@ -203,7 +203,7 @@ proto.addGraphQLInterface = function addGraphQLInterface( continue; } - const args: Record> = {}; + const args: Record> = {}; for (const { name, ...arg } of field.args) { args[name] = t.arg({ diff --git a/packages/plugin-complexity/package.json b/packages/plugin-complexity/package.json index a81b93191..1872ef87d 100644 --- a/packages/plugin-complexity/package.json +++ b/packages/plugin-complexity/package.json @@ -31,14 +31,23 @@ }, "author": "Michael Hayes", "license": "ISC", - "keywords": ["pothos", "graphql", "schema", "plugin", "complexity", "depth", "query", "limit"], + "keywords": [ + "pothos", + "graphql", + "schema", + "plugin", + "complexity", + "depth", + "query", + "limit" + ], "publishConfig": { "access": "public", "provenance": true }, "peerDependencies": { "@pothos/core": "*", - "graphql": ">=16.6.0" + "graphql": "^16.8.1" }, "devDependencies": { "@pothos/core": "workspace:*", diff --git a/packages/plugin-dataloader/package.json b/packages/plugin-dataloader/package.json index f37c8d2cf..540d832e0 100644 --- a/packages/plugin-dataloader/package.json +++ b/packages/plugin-dataloader/package.json @@ -31,7 +31,13 @@ "url": "git+https://github.com/hayes/pothos.git", "directory": "packages/plugin-dataloader" }, - "keywords": ["pothos", "graphql", "schema", "typescript", "dataloader"], + "keywords": [ + "pothos", + "graphql", + "schema", + "typescript", + "dataloader" + ], "publishConfig": { "access": "public", "provenance": true @@ -39,7 +45,7 @@ "peerDependencies": { "@pothos/core": "*", "dataloader": "2", - "graphql": ">=16.6.0" + "graphql": "^16.8.1" }, "devDependencies": { "@pothos/core": "workspace:*", diff --git a/packages/plugin-directives/package.json b/packages/plugin-directives/package.json index 0328dd804..594216a95 100644 --- a/packages/plugin-directives/package.json +++ b/packages/plugin-directives/package.json @@ -46,7 +46,7 @@ "provenance": true }, "peerDependencies": { - "graphql": ">=16.6.0" + "graphql": "^16.8.1" }, "devDependencies": { "@graphql-tools/utils": "^10.6.1", diff --git a/packages/plugin-drizzle/package.json b/packages/plugin-drizzle/package.json index b0f01502e..4d386a293 100644 --- a/packages/plugin-drizzle/package.json +++ b/packages/plugin-drizzle/package.json @@ -31,14 +31,21 @@ }, "author": "Michael Hayes", "license": "ISC", - "keywords": ["pothos", "graphql", "schema", "typescript", "drizzle", "plugin"], + "keywords": [ + "pothos", + "graphql", + "schema", + "typescript", + "drizzle", + "plugin" + ], "publishConfig": { "access": "public", "provenance": true }, "peerDependencies": { "@pothos/core": "*", - "graphql": ">=16.6.0" + "graphql": "^16.8.1" }, "devDependencies": { "@libsql/client": "^0.14.0", diff --git a/packages/plugin-drizzle/src/drizzle-field-builder.ts b/packages/plugin-drizzle/src/drizzle-field-builder.ts index 5cd51c07e..6b5f18be7 100644 --- a/packages/plugin-drizzle/src/drizzle-field-builder.ts +++ b/packages/plugin-drizzle/src/drizzle-field-builder.ts @@ -452,13 +452,13 @@ export class DrizzleObjectFieldBuilder< >, ] > - ) { + ): FieldRef, 'DrizzleObject'> { const [name, options = {} as never] = args; const typeConfig = this.builder.configStore.getTypeConfig(this.typename, 'Object'); const usingSelect = !!typeConfig.extensions?.pothosDrizzleSelect; - return this.exposeField(name as never, { + return this.exposeField(name as never, { ...options, extensions: { ...options.extensions, diff --git a/packages/plugin-errors/package.json b/packages/plugin-errors/package.json index fd3986ac3..00716aef5 100644 --- a/packages/plugin-errors/package.json +++ b/packages/plugin-errors/package.json @@ -31,14 +31,22 @@ }, "author": "Michael Hayes", "license": "ISC", - "keywords": ["pothos", "graphql", "schema", "typescript", "error", "errors", "plugin"], + "keywords": [ + "pothos", + "graphql", + "schema", + "typescript", + "error", + "errors", + "plugin" + ], "publishConfig": { "access": "public", "provenance": true }, "peerDependencies": { "@pothos/core": "*", - "graphql": ">=16.6.0" + "graphql": "^16.8.1" }, "devDependencies": { "@pothos/core": "workspace:*", @@ -46,7 +54,7 @@ "@pothos/test-utils": "workspace:*", "graphql": "^16.8.1", "graphql-tag": "^2.12.6", - "zod": "^3.23.8" + "zod": "^3.24.1" }, "gitHead": "9dfe52f1975f41a111e01bf96a20033a914e2acc" } diff --git a/packages/plugin-federation/package.json b/packages/plugin-federation/package.json index f0b29cace..9986a8140 100644 --- a/packages/plugin-federation/package.json +++ b/packages/plugin-federation/package.json @@ -47,7 +47,7 @@ }, "peerDependencies": { "@apollo/subgraph": "^2.0.0", - "graphql": ">=16.6.0" + "graphql": "^16.8.1" }, "devDependencies": { "@apollo/gateway": "^2.9.3", diff --git a/packages/plugin-mocks/package.json b/packages/plugin-mocks/package.json index 938cd12e8..a62573e70 100644 --- a/packages/plugin-mocks/package.json +++ b/packages/plugin-mocks/package.json @@ -31,14 +31,23 @@ }, "author": "Michael Hayes", "license": "ISC", - "keywords": ["pothos", "graphql", "schema", "typescript", "mock", "mocks", "test", "stub"], + "keywords": [ + "pothos", + "graphql", + "schema", + "typescript", + "mock", + "mocks", + "test", + "stub" + ], "publishConfig": { "access": "public", "provenance": true }, "peerDependencies": { "@pothos/core": "*", - "graphql": ">=16.6.0" + "graphql": "^16.8.1" }, "devDependencies": { "@pothos/core": "workspace:*", diff --git a/packages/plugin-prisma-utils/package.json b/packages/plugin-prisma-utils/package.json index 1bfb743a8..6b3bae9b9 100644 --- a/packages/plugin-prisma-utils/package.json +++ b/packages/plugin-prisma-utils/package.json @@ -33,7 +33,13 @@ }, "author": "Michael Hayes", "license": "ISC", - "keywords": ["pothos", "graphql", "schema", "typescript", "prisma"], + "keywords": [ + "pothos", + "graphql", + "schema", + "typescript", + "prisma" + ], "publishConfig": { "access": "public", "provenance": true @@ -48,7 +54,7 @@ "@pothos/core": "*", "@pothos/plugin-prisma": "*", "@prisma/client": "*", - "graphql": ">=16.6.0" + "graphql": "^16.8.1" }, "devDependencies": { "@pothos/core": "workspace:*", @@ -63,6 +69,6 @@ "prisma": "^6.0.0", "ts-node": "^10.9.2", "typescript": "5.5.4", - "zod": "^3.23.8" + "zod": "^3.24.1" } } diff --git a/packages/plugin-prisma-utils/src/schema-builder.ts b/packages/plugin-prisma-utils/src/schema-builder.ts index b1c2ca494..fed278187 100644 --- a/packages/plugin-prisma-utils/src/schema-builder.ts +++ b/packages/plugin-prisma-utils/src/schema-builder.ts @@ -665,8 +665,8 @@ schemaBuilder.prismaUpdateRelation = function prismaUpdateRelation< data: dataType, } = fieldOption as { name?: string; - where: InputFieldRef | InputRef; - data: InputFieldRef | InputRef; + where: InputFieldRef | InputRef; + data: InputFieldRef | InputRef; }; const nestedRef = this.inputType(nestedName, { @@ -687,8 +687,8 @@ schemaBuilder.prismaUpdateRelation = function prismaUpdateRelation< skipDuplicates, } = fieldOption as { name?: string; - data: InputFieldRef | InputRef; - skipDuplicates?: InputFieldRef | InputRef; + data: InputFieldRef | InputRef; + skipDuplicates?: InputFieldRef | InputRef; }; const nestedRef = this.inputType(nestedName, { diff --git a/packages/plugin-prisma/package.json b/packages/plugin-prisma/package.json index 29aaf8bdc..36cde38cf 100644 --- a/packages/plugin-prisma/package.json +++ b/packages/plugin-prisma/package.json @@ -73,7 +73,7 @@ "peerDependencies": { "@pothos/core": "*", "@prisma/client": "*", - "graphql": ">=16.6.0", + "graphql": "^16.8.1", "typescript": ">=4.7.2" }, "devDependencies": { diff --git a/packages/plugin-prisma/src/prisma-field-builder.ts b/packages/plugin-prisma/src/prisma-field-builder.ts index 9bffe5267..4577649c4 100644 --- a/packages/plugin-prisma/src/prisma-field-builder.ts +++ b/packages/plugin-prisma/src/prisma-field-builder.ts @@ -614,7 +614,7 @@ export class PrismaObjectFieldBuilder< }, ] > - ) { + ): FieldRef, 'PrismaObject'> { const [options = {} as never] = args; const typeConfig = this.builder.configStore.getTypeConfig(this.typename); diff --git a/packages/plugin-relay/package.json b/packages/plugin-relay/package.json index ee846b8c4..7c6bb4574 100644 --- a/packages/plugin-relay/package.json +++ b/packages/plugin-relay/package.json @@ -49,7 +49,7 @@ }, "peerDependencies": { "@pothos/core": "*", - "graphql": ">=16.6.0" + "graphql": "^16.8.1" }, "devDependencies": { "@pothos/core": "workspace:*", diff --git a/packages/plugin-scope-auth/package.json b/packages/plugin-scope-auth/package.json index 3cbd88a0e..b3f678f6e 100644 --- a/packages/plugin-scope-auth/package.json +++ b/packages/plugin-scope-auth/package.json @@ -53,7 +53,7 @@ }, "peerDependencies": { "@pothos/core": "*", - "graphql": ">=16.6.0" + "graphql": "^16.8.1" }, "devDependencies": { "@pothos/core": "workspace:*", diff --git a/packages/plugin-simple-objects/package.json b/packages/plugin-simple-objects/package.json index dd548186c..19c0e79fe 100644 --- a/packages/plugin-simple-objects/package.json +++ b/packages/plugin-simple-objects/package.json @@ -47,7 +47,7 @@ }, "peerDependencies": { "@pothos/core": "*", - "graphql": ">=16.6.0" + "graphql": "^16.8.1" }, "devDependencies": { "@pothos/core": "workspace:*", diff --git a/packages/plugin-smart-subscriptions/package.json b/packages/plugin-smart-subscriptions/package.json index 149568dac..6347d238d 100644 --- a/packages/plugin-smart-subscriptions/package.json +++ b/packages/plugin-smart-subscriptions/package.json @@ -47,7 +47,7 @@ }, "peerDependencies": { "@pothos/core": "*", - "graphql": ">=16.6.0" + "graphql": "^16.8.1" }, "devDependencies": { "@pothos/core": "workspace:*", diff --git a/packages/plugin-sub-graph/package.json b/packages/plugin-sub-graph/package.json index 88d29d21a..63f94b35e 100644 --- a/packages/plugin-sub-graph/package.json +++ b/packages/plugin-sub-graph/package.json @@ -50,7 +50,7 @@ }, "peerDependencies": { "@pothos/core": "*", - "graphql": ">=16.6.0" + "graphql": "^16.8.1" }, "devDependencies": { "@pothos/core": "workspace:*", diff --git a/packages/plugin-tracing/package.json b/packages/plugin-tracing/package.json index ca814141f..50c5afb43 100644 --- a/packages/plugin-tracing/package.json +++ b/packages/plugin-tracing/package.json @@ -49,7 +49,7 @@ }, "peerDependencies": { "@pothos/core": "*", - "graphql": ">=16.6.0" + "graphql": "^16.8.1" }, "devDependencies": { "@pothos/core": "workspace:*", diff --git a/packages/plugin-validation/.npmignore b/packages/plugin-validation/.npmignore new file mode 100644 index 000000000..846254022 --- /dev/null +++ b/packages/plugin-validation/.npmignore @@ -0,0 +1,6 @@ +test +tests +.turbo +babel.config.js +*.tsbuildinfo +tsconfig.* diff --git a/packages/plugin-validation/LICENSE b/packages/plugin-validation/LICENSE new file mode 100644 index 000000000..4a3e5989f --- /dev/null +++ b/packages/plugin-validation/LICENSE @@ -0,0 +1,6 @@ +ISC License (ISC) +Copyright 2025 Michael Hayes + +Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/packages/plugin-validation/README.md b/packages/plugin-validation/README.md new file mode 100644 index 000000000..861842bbc --- /dev/null +++ b/packages/plugin-validation/README.md @@ -0,0 +1 @@ +# Validation Plugin diff --git a/packages/plugin-validation/esm/.gitignore b/packages/plugin-validation/esm/.gitignore new file mode 100755 index 000000000..e4704508f --- /dev/null +++ b/packages/plugin-validation/esm/.gitignore @@ -0,0 +1,4 @@ +* +!.gitignore +!.npmignore +!package.json diff --git a/packages/plugin-validation/esm/.npmignore b/packages/plugin-validation/esm/.npmignore new file mode 100755 index 000000000..e69de29bb diff --git a/packages/plugin-validation/esm/package.json b/packages/plugin-validation/esm/package.json new file mode 100755 index 000000000..3dbc1ca59 --- /dev/null +++ b/packages/plugin-validation/esm/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/packages/plugin-validation/package.json b/packages/plugin-validation/package.json new file mode 100644 index 000000000..f62023a40 --- /dev/null +++ b/packages/plugin-validation/package.json @@ -0,0 +1,61 @@ +{ + "name": "@pothos/plugin-validation", + "version": "4.0.0", + "description": "A Pothos plugin for adding schema based validation", + "main": "./lib/index.js", + "types": "./dts/index.d.ts", + "module": "./esm/index.js", + "exports": { + "import": { + "default": "./esm/index.js" + }, + "require": { + "types": "./dts/index.d.ts", + "default": "./lib/index.js" + } + }, + "scripts": { + "type": "tsc --project tsconfig.type.json", + "build": "pnpm build:clean && pnpm build:cjs && pnpm build:dts && pnpm build:esm", + "build:clean": "git clean -dfX esm lib", + "build:cjs": "swc src -d lib --config-file ../../.swcrc -C module.type=commonjs --strip-leading-paths", + "build:esm": "cp -r dts/* esm/ && swc src -d esm --config-file ../../.swcrc -C module.type=es6 --strip-leading-paths && pnpm esm:extensions", + "build:dts": "tsc", + "esm:extensions": "TS_NODE_PROJECT=../../tsconfig.json node -r @swc-node/register ../../scripts/esm-transformer.ts", + "test": "pnpm vitest --run" + }, + "author": "Michael Hayes", + "license": "ISC", + "repository": { + "type": "git", + "url": "git+https://github.com/hayes/pothos.git", + "directory": "packages/plugin-zod" + }, + "keywords": [ + "pothos", + "graphql", + "schema", + "typescript", + "validation", + "validate" + ], + "publishConfig": { + "access": "public", + "provenance": true + }, + "peerDependencies": { + "@pothos/core": "*", + "graphql": "^16.8.1" + }, + "devDependencies": { + "@pothos/core": "workspace:*", + "@pothos/test-utils": "workspace:*", + "@standard-schema/spec": "1.0.0-beta.4", + "graphql": "^16.8.1", + "graphql-tag": "^2.12.6" + }, + "gitHead": "9dfe52f1975f41a111e01bf96a20033a914e2acc", + "dependencies": { + "zod": "^3.24.1" + } +} diff --git a/packages/plugin-validation/src/errors.ts b/packages/plugin-validation/src/errors.ts new file mode 100644 index 000000000..3397958d5 --- /dev/null +++ b/packages/plugin-validation/src/errors.ts @@ -0,0 +1,30 @@ +import { PothosValidationError } from '@pothos/core'; +import type { StandardSchemaV1 } from './standard-schema'; +export class InputValidationError extends PothosValidationError { + issues: readonly StandardSchemaV1.Issue[]; + + constructor(issues: readonly StandardSchemaV1.Issue[]) { + super( + issues + .map((issue) => { + return `${ + issue.path + ?.map((path) => { + if ( + typeof path === 'string' || + typeof path === 'number' || + typeof path === 'symbol' + ) { + return path.toString(); + } + return path.key.toString(); + }) + .join('.') ?? 'unknown' + }: ${issue.message}`; + }) + .join(', '), + ); + + this.issues = issues; + } +} diff --git a/packages/plugin-validation/src/global-types.ts b/packages/plugin-validation/src/global-types.ts new file mode 100644 index 000000000..e9f4bc75a --- /dev/null +++ b/packages/plugin-validation/src/global-types.ts @@ -0,0 +1,84 @@ +import type { + FieldKind, + FieldNullability, + FieldRequiredness, + InputFieldMap, + InputFieldsFromShape, + InputType, + SchemaTypes, + TypeParam, +} from '@pothos/core'; +import type { ValidationPluginOptions } from './types'; + +import type { PothosZodPlugin } from '.'; +import type { StandardSchemaV1 } from './standard-schema'; + +declare global { + export namespace PothosSchemaTypes { + export interface Plugins { + validation: PothosZodPlugin; + } + + export interface SchemaBuilderOptions { + validation?: ValidationPluginOptions; + } + + export interface FieldOptions< + Types extends SchemaTypes, + ParentShape, + Type extends TypeParam, + Nullable extends FieldNullability, + Args extends InputFieldMap, + ResolveShape, + ResolveReturnShape, + > { + validate?: StandardSchemaV1; + } + + export interface InputObjectTypeOptions< + Types extends SchemaTypes = SchemaTypes, + Fields extends InputFieldMap = InputFieldMap, + > { + validate?: StandardSchemaV1; + } + + export interface InputFieldOptions< + Types extends SchemaTypes = SchemaTypes, + Type extends InputType | [InputType] = InputType | [InputType], + Req extends FieldRequiredness = FieldRequiredness, + > { + validate?: StandardSchemaV1; + } + + export interface InputObjectRef { + validate(schema: StandardSchemaV1): InputObjectRef; + } + + export interface FieldRef< + Types extends SchemaTypes, + T = unknown, + Kind extends FieldKind = FieldKind, + > { + validate(schema: StandardSchemaV1): FieldRef; + } + + export interface InputFieldRef { + validate(schema: StandardSchemaV1): InputFieldRef; + } + + export interface ArgumentRef { + validate(schema: StandardSchemaV1): ArgumentRef; + } + + export interface RootFieldBuilder< + Types extends SchemaTypes, + ParentShape, + Kind extends FieldKind = FieldKind, + > { + validate( + args: Args, + schema: StandardSchemaV1, + ): InputFieldsFromShape; + } + } +} diff --git a/packages/plugin-validation/src/index.ts b/packages/plugin-validation/src/index.ts new file mode 100644 index 000000000..906e11961 --- /dev/null +++ b/packages/plugin-validation/src/index.ts @@ -0,0 +1,76 @@ +import './global-types'; +import './methods'; +import SchemaBuilder, { + BasePlugin, + type PothosInputFieldConfig, + type SchemaTypes, + mapInputFields, + type PothosOutputFieldConfig, + unwrapInputFieldType, +} from '@pothos/core'; +import type { StandardSchemaV1 } from './standard-schema'; +import { createArgsValidator } from './utils'; + +export * from './types'; + +const pluginName = 'validation'; + +export class PothosZodPlugin extends BasePlugin { + override onInputFieldConfig( + fieldConfig: PothosInputFieldConfig, + ): PothosInputFieldConfig { + if (fieldConfig.pothosOptions.validate) { + const extensions = (fieldConfig.extensions ?? {}) as { + validationSchemas?: StandardSchemaV1[]; + }; + + return { + ...fieldConfig, + extensions: { + ...extensions, + validationSchemas: [ + ...(extensions.validationSchemas ?? []), + fieldConfig.pothosOptions.validate, + ], + }, + }; + } + + return fieldConfig; + } + + override onOutputFieldConfig( + fieldConfig: PothosOutputFieldConfig, + ): PothosOutputFieldConfig | null { + const argsSchema = fieldConfig.pothosOptions.validate ?? null; + const argMappings = mapInputFields(fieldConfig.args, this.buildCache, (field) => { + const fieldSchemas = (field.extensions?.validationSchemas as StandardSchemaV1[]) ?? null; + const fieldTypeName = unwrapInputFieldType(field.type); + const typeSchemas = + (this.buildCache.getTypeConfig(fieldTypeName).extensions + ?.validationSchemas as StandardSchemaV1[]) ?? null; + + return fieldSchemas || typeSchemas + ? { + fieldSchemas, + typeSchemas, + } + : null; + }); + + if (!argMappings && !argsSchema) { + return fieldConfig; + } + + const argValidator = createArgsValidator(argMappings, argsSchema); + + return { + ...fieldConfig, + argMappers: [...(fieldConfig.argMappers ?? []), (args) => argValidator(args)], + }; + } +} + +SchemaBuilder.registerPlugin(pluginName, PothosZodPlugin); + +export default pluginName; diff --git a/packages/plugin-validation/src/methods.ts b/packages/plugin-validation/src/methods.ts new file mode 100644 index 000000000..aedaf2bea --- /dev/null +++ b/packages/plugin-validation/src/methods.ts @@ -0,0 +1,97 @@ +import { + ArgumentRef, + FieldRef, + type InputFieldMap, + InputFieldRef, + InputObjectRef, + RootFieldBuilder, + type SchemaTypes, +} from '@pothos/core'; +import type * as standardSchema from './standard-schema'; + +(RootFieldBuilder.prototype as RootFieldBuilder).validate = function validate< + Args extends InputFieldMap, + R, +>(args: Args, _schema: standardSchema.StandardSchemaV1) { + return args as never; +}; + +(FieldRef.prototype as FieldRef).validate = function validate(schema) { + this.updateConfig((config) => { + const extensions = (config.extensions ?? {}) as { + validationSchemas?: standardSchema.StandardSchemaV1[]; + }; + + return { + ...config, + extensions: { + ...extensions, + validationSchemas: extensions.validationSchemas + ? [schema, ...extensions.validationSchemas] + : [schema], + }, + }; + }); + return this as never; +}; + +(InputFieldRef.prototype as InputFieldRef).validate = function validate( + schema, +) { + this.updateConfig((config) => { + const extensions = (config.extensions ?? {}) as { + validationSchemas?: standardSchema.StandardSchemaV1[]; + }; + + return { + ...config, + extensions: { + ...extensions, + validationSchemas: extensions.validationSchemas + ? [schema, ...extensions.validationSchemas] + : [schema], + }, + }; + }); + return this as never; +}; + +(ArgumentRef.prototype as ArgumentRef).validate = function validate(schema) { + this.updateConfig((config) => { + const extensions = (config.extensions ?? {}) as { + validationSchemas?: standardSchema.StandardSchemaV1[]; + }; + + return { + ...config, + extensions: { + ...extensions, + validationSchemas: extensions.validationSchemas + ? [schema, ...extensions.validationSchemas] + : [schema], + }, + }; + }); + return this as never; +}; + +(InputObjectRef.prototype as InputObjectRef).validate = function validate( + schema, +) { + this.updateConfig((config) => { + const extensions = (config.extensions ?? {}) as { + validationSchemas?: standardSchema.StandardSchemaV1[]; + }; + + return { + ...config, + extensions: { + ...extensions, + validationSchemas: extensions.validationSchemas + ? [schema, ...extensions.validationSchemas] + : [schema], + }, + }; + }); + return this as never; +}; diff --git a/packages/plugin-validation/src/standard-schema.ts b/packages/plugin-validation/src/standard-schema.ts new file mode 100644 index 000000000..131937ca9 --- /dev/null +++ b/packages/plugin-validation/src/standard-schema.ts @@ -0,0 +1,145 @@ +/** +Copied without modification from https://github.com/standard-schema/standard-schema + +MIT License + +Copyright (c) 2024 Colin McDonnell + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +/** + * The Standard Schema interface. + */ +export type StandardSchemaV1 = { + /** + * The Standard Schema properties. + */ + readonly '~standard': StandardSchemaV1.Props; +}; + +export declare namespace StandardSchemaV1 { + /** + * The Standard Schema properties interface. + */ + export interface Props { + /** + * The version number of the standard. + */ + readonly version: 1; + /** + * The vendor name of the schema library. + */ + readonly vendor: string; + /** + * Validates unknown input values. + */ + readonly validate: (value: unknown) => Result | Promise>; + /** + * Inferred types associated with the schema. + */ + readonly types?: Types | undefined; + } + + /** + * The result interface of the validate function. + */ + export type Result = SuccessResult | FailureResult; + + /** + * The result interface if validation succeeds. + */ + export interface SuccessResult { + /** + * The typed output value. + */ + readonly value: Output; + /** + * The non-existent issues. + */ + readonly issues?: undefined; + } + + /** + * The result interface if validation fails. + */ + export interface FailureResult { + /** + * The issues of failed validation. + */ + + // biome-ignore lint/style/useConsistentArrayType: + readonly issues: ReadonlyArray; + } + + /** + * The issue interface of the failure output. + */ + export interface Issue { + /** + * The error message of the issue. + */ + readonly message: string; + /** + * The path of the issue, if any. + */ + readonly path?: ReadonlyArray | undefined; + } + + /** + * The path segment interface of the issue. + */ + export interface PathSegment { + /** + * The key representing a path segment. + */ + readonly key: PropertyKey; + } + + /** + * The Standard Schema types interface. + */ + export interface Types { + /** + * The input type of the schema. + */ + readonly input: Input; + /** + * The output type of the schema. + */ + readonly output: Output; + } + + /** + * Infers the input type of a Standard Schema. + */ + export type InferInput = NonNullable< + Schema['~standard']['types'] + >['input']; + + /** + * Infers the output type of a Standard Schema. + */ + export type InferOutput = NonNullable< + Schema['~standard']['types'] + >['output']; + + // biome-ignore lint/complexity/noUselessEmptyExport: needed for granular visibility control of TS namespace + export {}; +} diff --git a/packages/plugin-validation/src/types.ts b/packages/plugin-validation/src/types.ts new file mode 100644 index 000000000..07f94e342 --- /dev/null +++ b/packages/plugin-validation/src/types.ts @@ -0,0 +1,14 @@ +import type { SchemaTypes } from '@pothos/core'; +import type { GraphQLResolveInfo } from 'graphql'; +import type { ZodError } from 'zod'; + +export interface ValidationPluginOptions { + validationError?: ValidationErrorFn; +} + +export type ValidationErrorFn = ( + error: ZodError, + args: Record, + context: Types['Context'], + info: GraphQLResolveInfo, +) => Error | string; diff --git a/packages/plugin-validation/src/utils.ts b/packages/plugin-validation/src/utils.ts new file mode 100644 index 000000000..150f5c585 --- /dev/null +++ b/packages/plugin-validation/src/utils.ts @@ -0,0 +1,229 @@ +import { + completeValue, + type InputFieldMapping, + type InputFieldsMapping, + isThenable, + type MaybePromise, + type SchemaTypes, +} from '@pothos/core'; +import type { StandardSchemaV1 } from './standard-schema'; +import { InputValidationError } from './errors'; + +export function createArgsValidator( + argMappings: InputFieldsMapping< + Types, + { + typeSchemas: StandardSchemaV1[]; + fieldSchemas: StandardSchemaV1[]; + } + > | null, + argsSchema: StandardSchemaV1 | null, +) { + const argMapper = argMappings + ? createInputValueMapper(argMappings, (value, mappings, addIssues) => { + const { typeSchemas, fieldSchemas } = mappings.value!; + const mapped = typeSchemas + ? reduceMaybeAsync(typeSchemas, value, (val, schema) => + completeValue(schema['~standard'].validate(val), (result) => { + if (result.issues) { + addIssues(result.issues); + return null; + } + + return result.value; + }), + ) + : value; + + if (mapped === null) { + return value; + } + + if (fieldSchemas) { + return reduceMaybeAsync(fieldSchemas, mapped, (val, schema) => + completeValue(schema['~standard'].validate(val), (result) => { + if (result.issues) { + addIssues(result.issues); + return null; + } + + return result.value; + }), + ); + } + + return mapped; + }) + : null; + + return function validateArgs( + args: Record, + ): MaybePromise> { + return completeValue( + argMapper ? argMapper(args) : { value: args, issues: undefined }, + (mapped) => { + if (mapped.issues) { + throw new InputValidationError(mapped.issues); + } + + if (!argsSchema) { + return mapped.value; + } + + const issues: StandardSchemaV1.Issue[] = []; + + const validated = completeValue( + argsSchema['~standard'].validate(mapped.value), + (result) => { + if (result.issues) { + issues.push(...result.issues); + return null; + } + + return result.value; + }, + ); + + return completeValue(validated, (result) => { + if (issues.length) { + throw new InputValidationError(issues); + } + + return result as Record; + }); + }, + ); + }; +} + +function createInputValueMapper( + argMap: InputFieldsMapping, + mapValue: ( + val: unknown, + mapping: InputFieldMapping, + addIssues: (issues: readonly StandardSchemaV1.Issue[]) => void, + ...args: Args + ) => unknown, +) { + return function mapObject( + obj: object, + map: InputFieldsMapping = argMap, + path: (string | number)[] = [], + ...args: Args + ): MaybePromise>> { + const mapped: Record = { ...obj }; + const issues: StandardSchemaV1.Issue[] = []; + + function addIssues(path: (string | number)[]) { + return (newIssues: readonly StandardSchemaV1.Issue[]) => { + issues.push( + ...newIssues.map((issue) => ({ ...issue, path: [...path, ...(issue.path ?? [])] })), + ); + }; + } + + const promises: Promise[] = []; + + map.forEach((field, fieldName) => { + const fieldVal = (obj as Record)[fieldName]; + const fieldPromises: Promise[] = []; + + if (fieldVal === null || fieldVal === undefined) { + mapped[fieldName] = fieldVal; + return; + } + + if (field.kind === 'InputObject' && field.fields.map) { + if (field.isList) { + const newList = [...(fieldVal as unknown[])]; + mapped[fieldName] = newList; + + (fieldVal as (Record | null)[]).map((val, i) => { + if (val) { + const promise = completeValue( + mapObject(val, field.fields.map!, [...path, fieldName, i], ...args), + (newVal) => { + if (newVal.issues) { + issues.push(...newVal.issues); + } else { + newList[i] = newVal.value; + } + }, + ); + + if (isThenable(promise)) { + fieldPromises.push(promise); + } + } + }); + } else { + const promise = completeValue( + mapObject( + fieldVal as Record, + field.fields.map, + [...path, fieldName], + ...args, + ), + (newVal) => { + if (newVal.issues) { + issues.push(...newVal.issues); + } else { + mapped[fieldName] = newVal.value; + } + }, + ); + + if (isThenable(promise)) { + fieldPromises.push(promise); + } + } + } + + const promise = completeValue( + fieldPromises.length ? Promise.all(fieldPromises) : null, + () => { + if (field.value !== null && !issues.length) { + return completeValue( + mapValue(mapped[fieldName], field, addIssues([...path, fieldName]), ...args), + (newVal) => { + mapped[fieldName] = newVal; + }, + ); + } + }, + ); + + if (isThenable(promise)) { + promises.push(promise); + } + }); + + return completeValue(promises.length ? Promise.all(promises) : null, () => { + return issues.length + ? { + issues, + } + : { + value: mapped, + issues: undefined, + }; + }); + }; +} +function reduceMaybeAsync( + items: T[], + initialValue: R, + fn: (value: R, item: T, i: number) => MaybePromise, +) { + function next(value: R, i: number): MaybePromise { + if (i === items.length) { + return value; + } + + return completeValue(fn(value, items[i], i), (result) => { + return result === null ? null : next(result, i + 1); + }); + } + + return next(initialValue, 0); +} diff --git a/packages/plugin-validation/tests/example/builder.ts b/packages/plugin-validation/tests/example/builder.ts new file mode 100644 index 000000000..cffb05bf6 --- /dev/null +++ b/packages/plugin-validation/tests/example/builder.ts @@ -0,0 +1,14 @@ +import '../../src'; +import SchemaBuilder from '@pothos/core'; + +export default new SchemaBuilder<{ + Scalars: { + ID: { Input: bigint | number | string; Output: bigint | number | string }; + }; +}>({ + plugins: ['validation'], + validation: { + validationError: (error) => + error.issues.map((issue) => `${issue.path.join('.')}: ${issue.message}`).join(', '), + }, +}); diff --git a/packages/plugin-validation/tests/example/schema/index.ts b/packages/plugin-validation/tests/example/schema/index.ts new file mode 100644 index 000000000..88424068a --- /dev/null +++ b/packages/plugin-validation/tests/example/schema/index.ts @@ -0,0 +1,356 @@ +import * as zod from 'zod'; +import builder from '../builder'; + +interface RecursiveShape { + number: number; + recurse?: RecursiveShape; +} +const Recursive = builder.inputRef('Recursive'); + +Recursive.implement({ + validate: zod.object({ + number: zod.number().refine((n) => n !== 3, { message: 'number must not be 3' }), + }), + fields: (t) => ({ + number: t.int({ + required: true, + validate: zod.number().max(5), + }), + float: t.float({ + required: true, + validate: zod.number().refine((val) => val % 1 !== 0), + }), + recurse: t.field({ + required: false, + type: Recursive, + }), + }), +}); + +enum Enum1 { + One = 0, + Two = 1, + Three = 2, +} + +const Enum1Type = builder.enumType(Enum1, { + name: 'Enum1', +}); + +const ContactInfo = builder.inputType('ContactInfo', { + fields: (t) => ({ + name: t.string({ + required: true, + validate: zod + .string() + .max(30) + .refine(async (name) => Promise.resolve(name[0].toUpperCase() === name[0]), { + message: 'Name should be capitalized', + }), + }), + aliases: t.stringList({ + validate: zod.array( + zod + .string() + .max(30) + .refine((alias) => alias[0].toUpperCase() === alias[0], { + message: 'Aliases should be capitalized', + }), + ), + }), + email: t.string({ + required: true, + validate: zod + .string() + .email() + .refine((arg) => arg.split('@')[1] !== 'example.com', { + message: 'no example.com email addresses', + }), + }), + phone: t.string({ + validate: zod + .string() + .trim() + .regex(/^\d{3}-\d{3}-\d{4}$/u), + }), + }), +}); + +builder.queryType({ + fields: (t) => ({ + simple: t.boolean({ + nullable: true, + args: { + email: t.arg.string({ + validate: zod.string().email(), + }), + phone: t.arg.string({ + validate: zod.string().trim(), + }), + }, + validate: zod + .object({ + email: zod.string(), + phone: zod.string(), + }) + .refine((args) => Promise.resolve(!!args.phone || !!args.email)), + resolve: () => true, + }), + withMessage: t.boolean({ + nullable: true, + args: { + email: t.arg.string({ + validate: zod.string().email({ + message: 'invalid email address', + }), + }), + phone: t.arg.string({ + validate: zod.string().trim(), + }), + }, + validate: zod + .object({ + email: zod.string(), + phone: zod.string(), + }) + .refine((args) => !!args.phone || !!args.email, { + message: 'Must provide either phone number or email address', + }), + resolve: () => true, + }), + list: t.boolean({ + nullable: true, + args: { + list: t.arg.stringList({ + validate: zod.array(zod.string().max(3)).max(3), + }), + }, + resolve: () => true, + }), + exampleField: t.int({ + args: { + enum1: t.arg({ + type: [Enum1Type], + validate: zod.array(zod.unknown()).refine((val) => val[0] === Enum1.One), + }), + recursive: t.arg({ + type: Recursive, + required: true, + }), + odd: t.arg.int({ + validate: zod + .number() + .max(5) + .refine((n) => n % 2 === 1, { + message: 'number must be odd', + }), + required: true, + }), + contactInfo: t.arg({ + type: ContactInfo, + validate: zod + .object({ + email: zod.string().email(), + }) + .refine((info) => info.email.toLocaleLowerCase() === info.email, { + message: 'email should be lowercase', + path: ['email'], + }), + }), + }, + validate: zod + .object({ + enum1: zod.unknown(), + recursive: zod.unknown(), + odd: zod.unknown(), + contactInfo: zod.object({ + aliases: zod.array(zod.string()), + }), + }) + .refine((args) => (args.contactInfo?.aliases?.length ?? 0) > 1, { + path: ['contactInfo', 'aliases'], + message: 'contactInfo should include at least 2 aliases', + }), + resolve(_parent, args) { + return args.odd; + }, + }), + all: t.boolean({ + description: 'all possible validations, (these constraints cant be satisfied', + args: { + number: t.arg.float({ + validate: zod + .number() + .positive() + .negative() + .nonnegative() + .nonpositive() + .int() + .min(5) + .max(5) + .refine(() => true), + }), + bigint: t.arg.id({ + validate: zod.bigint().refine(() => true), + }), + string: t.arg.string({ + validate: zod + .string() + .email() + .url() + .uuid() + .regex(/abc/u) + .length(5) + .max(5) + .min(5) + .refine(() => true), + }), + object: t.arg({ + required: false, + type: Recursive, + validate: zod + .object({ + recurse: zod.object({}), + }) + .refine((obj) => !obj.recurse), + }), + array: t.arg.stringList({ + validate: zod + .array(zod.string().max(5)) + .length(5) + .refine(() => true), + }), + }, + resolve: () => true, + }), + argsSchema: t.boolean({ + nullable: true, + args: { + num: t.arg.int(), + string: t.arg.string(), + }, + validate: zod.object({ num: zod.number().min(2), string: zod.string().min(2) }), + resolve: () => true, + }), + }), +}); + +const WithValidationInput = builder.inputType('WithValidationInput', { + fields: (t) => ({ + name: t.string(), + age: t.int(), + }), + validate: zod + .object({ + name: zod.string(), + age: zod.number(), + }) + .refine((args) => args.name === 'secret', { message: 'Incorrect name given' }) + .refine((args) => args.age === 100, { message: 'Incorrect age given' }), +}); +const WithValidationAndFieldValidator = builder.inputType('WithValidationAndFieldValidator', { + fields: (t) => ({ + name: t.string(), + age: t.int(), + }), + validate: zod + .object({ + name: zod.string(), + age: zod.number(), + }) + .refine((args) => args.name === 'secret', { message: 'Incorrect name given' }) + .refine((args) => args.age === 100, { message: 'Incorrect age given' }), +}); + +const NestedInput = builder.inputType('NestedInput', { + fields: (t) => ({ id: t.id() }), +}); + +const SoloNestedInput = builder.inputType('SoloNestedInput', { + fields: (t) => ({ + nested: t.field({ + required: true, + type: NestedInput, + validate: zod.object({ id: zod.string().min(2) }), + }), + }), +}); + +const NestedObjectListInput = builder.inputType('NestedObjectListInput', { + fields: (t) => ({ + nested: t.field({ + required: true, + type: [NestedInput], + validate: zod.array(zod.object({ id: zod.string().min(2) })), + }), + }), +}); + +const WithSchemaInput = builder.inputType('WithSchemaInput', { + fields: (t) => ({ + name: t.string(), + }), + validate: zod.object({ name: zod.string().min(2) }), +}); + +builder.queryField('soloNested', (t) => + t.boolean({ + nullable: true, + args: { + input: t.arg({ type: SoloNestedInput }), + }, + resolve: () => true, + }), +); + +builder.queryField('nestedObjectList', (t) => + t.boolean({ + nullable: true, + args: { + input: t.arg({ type: NestedObjectListInput }), + }, + resolve: () => true, + }), +); + +builder.queryField('withValidationInput', (t) => + t.boolean({ + nullable: true, + args: { + input: t.arg({ type: WithValidationInput }), + }, + resolve: () => true, + }), +); + +builder.queryField('withValidationAndFieldValidator', (t) => + t.boolean({ + nullable: true, + args: { + input: t.arg({ type: WithValidationAndFieldValidator }), + }, + resolve: () => true, + }), +); + +builder.queryField('withSchemaInput', (t) => + t.boolean({ + nullable: true, + args: { + input: t.arg({ type: WithSchemaInput }), + }, + resolve: () => true, + }), +); + +builder.queryField('withSchemaInputList', (t) => + t.boolean({ + nullable: true, + args: { + input: t.arg({ type: [WithSchemaInput] }), + }, + resolve: () => true, + }), +); + +export default builder.toSchema(); diff --git a/packages/plugin-validation/tests/example/server.ts b/packages/plugin-validation/tests/example/server.ts new file mode 100644 index 000000000..9165c37a0 --- /dev/null +++ b/packages/plugin-validation/tests/example/server.ts @@ -0,0 +1,8 @@ +import { createTestServer } from '@pothos/test-utils'; +import schema from './schema'; + +const server = createTestServer({ schema }); + +server.listen(3000, () => { + console.log('🚀 Server started at http://127.0.0.1:3000'); +}); diff --git a/packages/plugin-validation/tests/index.test.ts b/packages/plugin-validation/tests/index.test.ts new file mode 100644 index 000000000..c9d9b2f16 --- /dev/null +++ b/packages/plugin-validation/tests/index.test.ts @@ -0,0 +1,230 @@ +import { execute } from 'graphql'; +import { gql } from 'graphql-tag'; +import schema from './example/schema'; + +describe('validation', () => { + it('valid query', async () => { + const query = gql` + query { + exampleField( + odd: 1 + recursive: { float: 1.1, number: 2, recurse: { float: 1.1, number: 1 } } + contactInfo: { + name: "Michael" + email: "michael@test.com" + phone: " 555-123-4567 " + aliases: ["Hayes", "MHayes"] + } + enum1: [One, Two] + ) + } + `; + + const result = await execute({ + schema, + document: query, + contextValue: {}, + }); + + expect(result).toMatchInlineSnapshot(` + { + "data": { + "exampleField": 1, + }, + } + `); + }); + + it.only('invalid query', async () => { + const query = gql` + query { + exampleField( + odd: 2 + recursive: { + float: 1 + number: 2 + recurse: { float: 1, number: 6, recurse: { float: 1.1, number: 3 } } + } + contactInfo: { + name: "michael" + email: "michael@example.com" + phone: " 555-123-456 " + aliases: ["hayes"] + } + enum1: [Two, One] + ) + } + `; + + const result = await execute({ + schema, + document: query, + contextValue: {}, + }); + + expect(result).toMatchInlineSnapshot(` + { + "data": { + "exampleField": null, + }, + "errors": [ + [GraphQLError: recursive.recurse.number: Number must be less than or equal to 5, recursive.float: Invalid input, recursive.recurse.float: Invalid input, odd: number must be odd, contactInfo.email: no example.com email addresses, enum1: Invalid input, contactInfo.phone: Invalid, contactInfo.aliases: Aliases should be capitalized, contactInfo.name: Name should be capitalized, recursive.recurse.recurse: number must not be 3, contactInfo.aliases: contactInfo should include at least 2 aliases], + ], + } + `); + }); + + it('example queries', async () => { + const query = gql` + query { + simpleValid: simple(email: "abc@def.com") + simpleInvalid: simple(email: "abc") + simpleInvalid2: simple + messageValid: withMessage(email: "abc@def.com") + messageInvalid: withMessage(email: "abc") + messageInvalid2: withMessage + listValid: list(list: ["abc", "def", "ghi"]) + listInvalid: list(list: ["abcdef", "ghi"]) + listInvalid2: list(list: ["a", "b", "c", "d"]) + } + `; + + const result = await execute({ + schema, + document: query, + contextValue: {}, + }); + + expect(result).toMatchInlineSnapshot(` + { + "data": { + "listInvalid": null, + "listInvalid2": null, + "listValid": true, + "messageInvalid": null, + "messageInvalid2": null, + "messageValid": true, + "simpleInvalid": null, + "simpleInvalid2": null, + "simpleValid": true, + }, + "errors": [ + [GraphQLError: email: invalid email address], + [GraphQLError: : Must provide either phone number or email address], + [GraphQLError: list.0: String must contain at most 3 character(s)], + [GraphQLError: list: Array must contain at most 3 element(s)], + [GraphQLError: email: Invalid email], + [GraphQLError: : Invalid input], + ], + } + `); + }); + + it('input object with schema', async () => { + const query = gql` + query { + invalid: soloNested(input: { nested: { id: "1" } }) + valid: soloNested(input: { nested: { id: "12" } }) + invalidList: nestedObjectList(input: { nested: [{ id: "1" }] }) + validList: nestedObjectList(input: { nested: [{ id: "12" }] }) + } + `; + + const result = await execute({ + schema, + document: query, + contextValue: {}, + }); + + expect(result).toMatchInlineSnapshot(` + { + "data": { + "invalid": null, + "invalidList": null, + "valid": true, + "validList": true, + }, + "errors": [ + [GraphQLError: input.nested.id: String must contain at least 2 character(s)], + [GraphQLError: input.nested.0.id: String must contain at least 2 character(s)], + ], + } + `); + }); + it('input object with input', async () => { + const query = gql` + query { + withValidationInput(input: { name: "secret", age: 100 }) + withValidationInputInvalid: withValidationInput(input: { name: "not secret", age: 101 }) + withValidationInputInvalid2: withValidationInput(input: { name: "not secret", age: 100 }) + withValidationInputInvalid3: withValidationInput(input: { name: "secret", age: 101 }) + withValidationAndFieldValidator(input: { name: "secret", age: 100 }) + withValidationAndFieldValidatorInvalid: withValidationAndFieldValidator( + input: { name: "not secret", age: 101 } + ) + } + `; + + const result = await execute({ + schema, + document: query, + contextValue: {}, + }); + + expect(result).toMatchInlineSnapshot(` + { + "data": { + "withValidationAndFieldValidator": true, + "withValidationAndFieldValidatorInvalid": null, + "withValidationInput": true, + "withValidationInputInvalid": null, + "withValidationInputInvalid2": null, + "withValidationInputInvalid3": null, + }, + "errors": [ + [GraphQLError: input: Incorrect name given, input: Incorrect age given], + [GraphQLError: input: Incorrect name given], + [GraphQLError: input: Incorrect age given], + [GraphQLError: input: Incorrect name given, input: Incorrect age given], + ], + } + `); + }); + + it('schema on field', async () => { + const query = gql` + query { + valid: argsSchema(num: 3, string: "abc") + invalid: argsSchema(num: 1, string: "a") + validInput: withSchemaInput(input: { name: "abc" }) + validInputList: withSchemaInputList(input: [{ name: "abc" }]) + invalidInput: withSchemaInput(input: { name: "a" }) + invalidInputList: withSchemaInputList(input: [{ name: "a" }]) + } + `; + + const result = await execute({ + schema, + document: query, + contextValue: {}, + }); + + expect(result).toMatchInlineSnapshot(` + { + "data": { + "invalid": null, + "invalidInput": null, + "invalidInputList": null, + "valid": true, + "validInput": true, + "validInputList": true, + }, + "errors": [ + [GraphQLError: num: Number must be greater than or equal to 2, string: String must contain at least 2 character(s)], + [GraphQLError: input.name: String must contain at least 2 character(s)], + [GraphQLError: input.0.name: String must contain at least 2 character(s)], + ], + } + `); + }); +}); diff --git a/packages/plugin-validation/tests/tsconfig.json b/packages/plugin-validation/tests/tsconfig.json new file mode 100644 index 000000000..7cc249b18 --- /dev/null +++ b/packages/plugin-validation/tests/tsconfig.json @@ -0,0 +1,9 @@ +{ + "include": ["**/*"], + "extends": "../../../tsconfig.options.json", + "references": [ + { + "path": "../" + } + ] +} diff --git a/packages/plugin-validation/tsconfig.json b/packages/plugin-validation/tsconfig.json new file mode 100644 index 000000000..62e9bc339 --- /dev/null +++ b/packages/plugin-validation/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "noEmit": false, + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "dts", + "rootDir": "src" + }, + "include": ["src/**/*"], + "extends": "../../tsconfig.options.json" +} diff --git a/packages/plugin-validation/tsconfig.type.json b/packages/plugin-validation/tsconfig.type.json new file mode 100644 index 000000000..ba0eac9d4 --- /dev/null +++ b/packages/plugin-validation/tsconfig.type.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "skipLibCheck": true + }, + "extends": "../../tsconfig.options.json", + "include": ["src/**/*", "tests/**/*"] +} diff --git a/packages/plugin-with-input/package.json b/packages/plugin-with-input/package.json index 812c52fad..7a3038efe 100644 --- a/packages/plugin-with-input/package.json +++ b/packages/plugin-with-input/package.json @@ -32,14 +32,21 @@ }, "author": "Michael Hayes", "license": "ISC", - "keywords": ["pothos", "graphql", "schema", "typescript", "plugin", "input"], + "keywords": [ + "pothos", + "graphql", + "schema", + "typescript", + "plugin", + "input" + ], "publishConfig": { "access": "public", "provenance": true }, "peerDependencies": { "@pothos/core": "*", - "graphql": ">=16.6.0" + "graphql": "^16.8.1" }, "devDependencies": { "@pothos/core": "workspace:*", diff --git a/packages/plugin-zod/package.json b/packages/plugin-zod/package.json index ddcea6b2e..70e0e0908 100644 --- a/packages/plugin-zod/package.json +++ b/packages/plugin-zod/package.json @@ -31,14 +31,22 @@ "url": "git+https://github.com/hayes/pothos.git", "directory": "packages/plugin-zod" }, - "keywords": ["pothos", "graphql", "schema", "typescript", "zod", "validation", "validate"], + "keywords": [ + "pothos", + "graphql", + "schema", + "typescript", + "zod", + "validation", + "validate" + ], "publishConfig": { "access": "public", "provenance": true }, "peerDependencies": { "@pothos/core": "*", - "graphql": ">=16.6.0", + "graphql": "^16.8.1", "zod": "*" }, "devDependencies": { @@ -46,7 +54,7 @@ "@pothos/test-utils": "workspace:*", "graphql": "^16.8.1", "graphql-tag": "^2.12.6", - "zod": "^3.23.8" + "zod": "^3.24.1" }, "gitHead": "9dfe52f1975f41a111e01bf96a20033a914e2acc" } diff --git a/packages/tracing-newrelic/package.json b/packages/tracing-newrelic/package.json index 0404c2303..2a4dcbb8c 100644 --- a/packages/tracing-newrelic/package.json +++ b/packages/tracing-newrelic/package.json @@ -48,7 +48,7 @@ "peerDependencies": { "@pothos/core": "*", "@pothos/plugin-tracing": "*", - "graphql": ">=16.6.0", + "graphql": "^16.8.1", "newrelic": "*" }, "devDependencies": { diff --git a/packages/tracing-opentelemetry/package.json b/packages/tracing-opentelemetry/package.json index aa2677d0f..552b3aba7 100644 --- a/packages/tracing-opentelemetry/package.json +++ b/packages/tracing-opentelemetry/package.json @@ -51,7 +51,7 @@ "@opentelemetry/semantic-conventions": "*", "@pothos/core": "*", "@pothos/plugin-tracing": "*", - "graphql": ">=16.6.0" + "graphql": "^16.8.1" }, "devDependencies": { "@envelop/core": "^5.0.2", diff --git a/packages/tracing-sentry/package.json b/packages/tracing-sentry/package.json index 9fbf026bc..e3f614f4b 100644 --- a/packages/tracing-sentry/package.json +++ b/packages/tracing-sentry/package.json @@ -50,7 +50,7 @@ "@pothos/core": "*", "@pothos/plugin-tracing": "*", "@sentry/node": "*", - "graphql": ">=16.6.0" + "graphql": "^16.8.1" }, "devDependencies": { "@pothos/core": "workspace:*", diff --git a/packages/tracing-xray/package.json b/packages/tracing-xray/package.json index 807dc5454..c44215cb3 100644 --- a/packages/tracing-xray/package.json +++ b/packages/tracing-xray/package.json @@ -51,7 +51,7 @@ "@pothos/core": "*", "@pothos/plugin-tracing": "*", "aws-xray-sdk-core": "*", - "graphql": ">=16.6.0" + "graphql": "^16.8.1" }, "devDependencies": { "@pothos/core": "workspace:*", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6b8a3e69e..4a23d3682 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -31,7 +31,7 @@ importers: version: 1.10.9(@swc/core@1.9.3(@swc/helpers@0.5.15))(@swc/types@0.1.17)(typescript@5.7.2) '@swc/cli': specifier: ^0.5.1 - version: 0.5.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(chokidar@3.6.0) + version: 0.5.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(chokidar@4.0.3) '@swc/core': specifier: ^1.9.3 version: 1.9.3(@swc/helpers@0.5.15) @@ -46,7 +46,7 @@ importers: version: 22.10.1 '@vitest/coverage-c8': specifier: ^0.33.0 - version: 0.33.0(vitest@2.1.6(@types/node@22.10.1)(jiti@2.4.1)(tsx@4.19.2)(yaml@2.6.1)) + version: 0.33.0(vitest@2.1.6(@types/node@22.10.1)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0)) globals: specifier: ^15.12.0 version: 15.12.0 @@ -76,7 +76,7 @@ importers: version: 0.65.1(@swc/core@1.9.3(@swc/helpers@0.5.15)) vitest: specifier: ^2.1.6 - version: 2.1.6(@types/node@22.10.1)(jiti@2.4.1)(tsx@4.19.2)(yaml@2.6.1) + version: 2.1.6(@types/node@22.10.1)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0) examples/complex-app: dependencies: @@ -130,10 +130,10 @@ importers: version: 18.3.1 urql: specifier: ^4.2.1 - version: 4.2.1(@urql/core@5.0.8(graphql@16.9.0))(react@18.3.1) + version: 4.2.1(@urql/core@5.1.0(graphql@16.9.0))(react@18.3.1) zod: - specifier: ^3.23.8 - version: 3.23.8 + specifier: ^3.24.1 + version: 3.24.1 devDependencies: '@graphql-codegen/cli': specifier: 5.0.3 @@ -342,7 +342,7 @@ importers: version: link:../../packages/tracing-opentelemetry bema: specifier: ^0.1.2 - version: 0.1.2(@babel/core@7.26.0)(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.1)(encoding@0.1.13) + version: 0.1.2(@babel/core@7.26.0)(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.5)(encoding@0.1.13) graphql: specifier: ^16.8.1 version: 16.9.0 @@ -734,13 +734,13 @@ importers: version: link:../test-utils drizzle-graphql: specifier: ^0.8.5 - version: 0.8.5(drizzle-orm@0.36.4(@libsql/client@0.14.0)(@opentelemetry/api@1.9.0)(@prisma/client@6.0.0(prisma@6.0.0))(@types/pg@8.11.10)(@types/react@18.3.12)(postgres@3.4.5)(prisma@6.0.0)(react@18.3.1))(graphql@16.9.0) + version: 0.8.5(drizzle-orm@0.36.4(@libsql/client@0.14.0)(@opentelemetry/api@1.9.0)(@prisma/client@6.1.0(prisma@6.1.0))(@types/pg@8.11.10)(@types/react@19.0.3)(postgres@3.4.5)(prisma@6.1.0)(react@19.0.0))(graphql@16.9.0) drizzle-kit: specifier: ^0.28.1 version: 0.28.1 drizzle-orm: specifier: ^0.36.4 - version: 0.36.4(@libsql/client@0.14.0)(@opentelemetry/api@1.9.0)(@prisma/client@6.0.0(prisma@6.0.0))(@types/pg@8.11.10)(@types/react@18.3.12)(postgres@3.4.5)(prisma@6.0.0)(react@18.3.1) + version: 0.36.4(@libsql/client@0.14.0)(@opentelemetry/api@1.9.0)(@prisma/client@6.1.0(prisma@6.1.0))(@types/pg@8.11.10)(@types/react@19.0.3)(postgres@3.4.5)(prisma@6.1.0)(react@19.0.0) graphql: specifier: ^16.8.1 version: 16.9.0 @@ -772,8 +772,8 @@ importers: specifier: ^2.12.6 version: 2.12.6(graphql@16.9.0) zod: - specifier: ^3.23.8 - version: 3.23.8 + specifier: ^3.24.1 + version: 3.24.1 packages/plugin-example: devDependencies: @@ -882,7 +882,7 @@ importers: version: 6.0.0 vitest: specifier: ^2.1.6 - version: 2.1.6(@types/node@22.10.1)(jiti@2.4.1)(tsx@4.19.2)(yaml@2.6.1) + version: 2.1.6(@types/node@22.10.5)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0) packages/plugin-prisma-utils: dependencies: @@ -922,13 +922,13 @@ importers: version: 6.0.0 ts-node: specifier: ^10.9.2 - version: 10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.1)(typescript@5.5.4) + version: 10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.5)(typescript@5.5.4) typescript: specifier: 5.5.4 version: 5.5.4 zod: - specifier: ^3.23.8 - version: 3.23.8 + specifier: ^3.24.1 + version: 3.24.1 packages/plugin-relay: devDependencies: @@ -1050,6 +1050,28 @@ importers: specifier: ^2.12.6 version: 2.12.6(graphql@16.9.0) + packages/plugin-validation: + dependencies: + zod: + specifier: ^3.24.1 + version: 3.24.1 + devDependencies: + '@pothos/core': + specifier: workspace:* + version: link:../core + '@pothos/test-utils': + specifier: workspace:* + version: link:../test-utils + '@standard-schema/spec': + specifier: 1.0.0-beta.4 + version: 1.0.0-beta.4 + graphql: + specifier: ^16.8.1 + version: 16.9.0 + graphql-tag: + specifier: ^2.12.6 + version: 2.12.6(graphql@16.9.0) + packages/plugin-with-input: devDependencies: '@pothos/core': @@ -1092,8 +1114,8 @@ importers: specifier: ^2.12.6 version: 2.12.6(graphql@16.9.0) zod: - specifier: ^3.23.8 - version: 3.23.8 + specifier: ^3.24.1 + version: 3.24.1 packages/test-utils: dependencies: @@ -1256,7 +1278,7 @@ importers: version: 11.1.2(acorn@8.14.0)(fumadocs-core@14.5.4(@types/react@18.3.12)(next@15.0.3(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(next@15.0.3(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) fumadocs-ui: specifier: 13.4.9 - version: 13.4.9(@types/react-dom@18.3.1)(@types/react@18.3.12)(next@15.0.3(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.15(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.1)(typescript@5.7.2))) + version: 13.4.9(@types/react-dom@18.3.1)(@types/react@18.3.12)(next@15.0.3(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.15(ts-node@10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.5)(typescript@5.7.2))) next: specifier: ^15.0.3 version: 15.0.3(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -1284,15 +1306,15 @@ importers: version: 8.4.49 tailwindcss: specifier: ^3.4.15 - version: 3.4.15(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.1)(typescript@5.7.2)) + version: 3.4.15(ts-node@10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.5)(typescript@5.7.2)) typescript: specifier: ^5.7.2 version: 5.7.2 packages: - '@0no-co/graphql.web@1.0.11': - resolution: {integrity: sha512-xuSJ9WXwTmtngWkbdEoopMo6F8NLtjy84UNAMsAr5C3/2SgAL/dEU10TMqTIsipqPQ8HA/7WzeqQ9DEQxSvPPA==} + '@0no-co/graphql.web@1.0.13': + resolution: {integrity: sha512-jqYxOevheVTU1S36ZdzAkJIdvRp2m3OYIG5SEoKDw5NI8eVwkoI0D/Q3DYNGmXCxkA6CQuoa7zvMiDPTLqUNuw==} peerDependencies: graphql: ^16.8.1 peerDependenciesMeta: @@ -3932,24 +3954,48 @@ packages: prisma: optional: true + '@prisma/client@6.1.0': + resolution: {integrity: sha512-AbQYc5+EJKm1Ydfq3KxwcGiy7wIbm4/QbjCKWWoNROtvy7d6a3gmAGkKjK0iUCzh+rHV8xDhD5Cge8ke/kiy5Q==} + engines: {node: '>=18.18'} + peerDependencies: + prisma: '*' + peerDependenciesMeta: + prisma: + optional: true + '@prisma/debug@6.0.0': resolution: {integrity: sha512-eUjoNThlDXdyJ1iQ2d7U6aTVwm59EwvODb5zFVNJEokNoSiQmiYWNzZIwZyDmZ+j51j42/0iTaHIJ4/aZPKFRg==} + '@prisma/debug@6.1.0': + resolution: {integrity: sha512-0himsvcM4DGBTtvXkd2Tggv6sl2JyUYLzEGXXleFY+7Kp6rZeSS3hiTW9mwtUlXrwYbJP6pwlVNB7jYElrjWUg==} + '@prisma/engines-version@5.23.0-27.5dbef10bdbfb579e07d35cc85fb1518d357cb99e': resolution: {integrity: sha512-JmIds0Q2/vsOmnuTJYxY4LE+sajqjYKhLtdOT6y4imojqv5d/aeVEfbBGC74t8Be1uSp0OP8lxIj2OqoKbLsfQ==} + '@prisma/engines-version@6.1.0-21.11f085a2012c0f4778414c8db2651556ee0ef959': + resolution: {integrity: sha512-PdJqmYM2Fd8K0weOOtQThWylwjsDlTig+8Pcg47/jszMuLL9iLIaygC3cjWJLda69siRW4STlCTMSgOjZzvKPQ==} + '@prisma/engines@6.0.0': resolution: {integrity: sha512-ZZCVP3q22ifN6Ex6C8RIcTDBlRtMJS2H1ljV0knCiWNGArvvkEbE88W3uDdq/l4+UvyvHpGzdf9ZsCWSQR7ZQQ==} + '@prisma/engines@6.1.0': + resolution: {integrity: sha512-GnYJbCiep3Vyr1P/415ReYrgJUjP79fBNc1wCo7NP6Eia0CzL2Ot9vK7Infczv3oK7JLrCcawOSAxFxNFsAERQ==} + '@prisma/fetch-engine@6.0.0': resolution: {integrity: sha512-j2m+iO5RDPRI7SUc7sHo8wX7SA4iTkJ+18Sxch8KinQM46YiCQD1iXKN6qU79C1Fliw5Bw/qDyTHaTsa3JMerA==} + '@prisma/fetch-engine@6.1.0': + resolution: {integrity: sha512-asdFi7TvPlEZ8CzSZ/+Du5wZ27q6OJbRSXh+S8ISZguu+S9KtS/gP7NeXceZyb1Jv1SM1S5YfiCv+STDsG6rrg==} + '@prisma/generator-helper@6.0.0': resolution: {integrity: sha512-5DkG7hspZo6U4OtqI2W0JcgtY37sr7HgT8Q0W/sjL4VoV4px6ivzK6Eif5bKM7q+S4yFUHtjUt/3s69ErfLn7A==} '@prisma/get-platform@6.0.0': resolution: {integrity: sha512-PS6nYyIm9g8C03E4y7LknOfdCw/t2KyEJxntMPQHQZCOUgOpF82Ma60mdlOD08w90I3fjLiZZ0+MadenR3naDQ==} + '@prisma/get-platform@6.1.0': + resolution: {integrity: sha512-ia8bNjboBoHkmKGGaWtqtlgQOhCi7+f85aOkPJKgNwWvYrT6l78KgojLekE8zMhVk0R9lWcifV0Pf8l3/15V0Q==} + '@prisma/instrumentation@5.19.1': resolution: {integrity: sha512-VLnzMQq7CWroL5AeaW0Py2huiNKeoMfCH3SUxstdzPrlWQi6UQ9UrfcbUkNHlVFqOMacqy8X/8YtE0kuKDpD9w==} @@ -4479,6 +4525,9 @@ packages: resolution: {integrity: sha512-XKLcLXZY7sUQgvvWyeaL/qwNPp6V3dWcUjqrQKjSb+tzYiCy340R/c64LV5j+Tnb2GhmunEX0eou+L+m2hJNYA==} engines: {node: '>=16.0.0'} + '@standard-schema/spec@1.0.0-beta.4': + resolution: {integrity: sha512-d3IxtzLo7P1oZ8s8YNvxzBUXRXojSut8pbPrTYtzsc5sn4+53jVqbk66pQerSZbZSJZQux6LkclB/+8IDordHg==} + '@swc-node/core@1.13.3': resolution: {integrity: sha512-OGsvXIid2Go21kiNqeTIn79jcaX4l0G93X2rAnas4LFoDyA9wAwVK7xZdm+QsKoMn5Mus2yFLCc4OtX2dD/PWA==} engines: {node: '>= 10'} @@ -4506,66 +4555,135 @@ packages: chokidar: optional: true + '@swc/core-darwin-arm64@1.10.4': + resolution: {integrity: sha512-sV/eurLhkjn/197y48bxKP19oqcLydSel42Qsy2zepBltqUx+/zZ8+/IS0Bi7kaWVFxerbW1IPB09uq8Zuvm3g==} + engines: {node: '>=10'} + cpu: [arm64] + os: [darwin] + '@swc/core-darwin-arm64@1.9.3': resolution: {integrity: sha512-hGfl/KTic/QY4tB9DkTbNuxy5cV4IeejpPD4zo+Lzt4iLlDWIeANL4Fkg67FiVceNJboqg48CUX+APhDHO5G1w==} engines: {node: '>=10'} cpu: [arm64] os: [darwin] + '@swc/core-darwin-x64@1.10.4': + resolution: {integrity: sha512-gjYNU6vrAUO4+FuovEo9ofnVosTFXkF0VDuo1MKPItz6e2pxc2ale4FGzLw0Nf7JB1sX4a8h06CN16/pLJ8Q2w==} + engines: {node: '>=10'} + cpu: [x64] + os: [darwin] + '@swc/core-darwin-x64@1.9.3': resolution: {integrity: sha512-IaRq05ZLdtgF5h9CzlcgaNHyg4VXuiStnOFpfNEMuI5fm5afP2S0FHq8WdakUz5WppsbddTdplL+vpeApt/WCQ==} engines: {node: '>=10'} cpu: [x64] os: [darwin] + '@swc/core-linux-arm-gnueabihf@1.10.4': + resolution: {integrity: sha512-zd7fXH5w8s+Sfvn2oO464KDWl+ZX1MJiVmE4Pdk46N3PEaNwE0koTfgx2vQRqRG4vBBobzVvzICC3618WcefOA==} + engines: {node: '>=10'} + cpu: [arm] + os: [linux] + '@swc/core-linux-arm-gnueabihf@1.9.3': resolution: {integrity: sha512-Pbwe7xYprj/nEnZrNBvZfjnTxlBIcfApAGdz2EROhjpPj+FBqBa3wOogqbsuGGBdCphf8S+KPprL1z+oDWkmSQ==} engines: {node: '>=10'} cpu: [arm] os: [linux] + '@swc/core-linux-arm64-gnu@1.10.4': + resolution: {integrity: sha512-+UGfoHDxsMZgFD3tABKLeEZHqLNOkxStu+qCG7atGBhS4Slri6h6zijVvf4yI5X3kbXdvc44XV/hrP/Klnui2A==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + '@swc/core-linux-arm64-gnu@1.9.3': resolution: {integrity: sha512-AQ5JZiwNGVV/2K2TVulg0mw/3LYfqpjZO6jDPtR2evNbk9Yt57YsVzS+3vHSlUBQDRV9/jqMuZYVU3P13xrk+g==} engines: {node: '>=10'} cpu: [arm64] os: [linux] + '@swc/core-linux-arm64-musl@1.10.4': + resolution: {integrity: sha512-cDDj2/uYsOH0pgAnDkovLZvKJpFmBMyXkxEG6Q4yw99HbzO6QzZ5HDGWGWVq/6dLgYKlnnmpjZCPPQIu01mXEg==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + '@swc/core-linux-arm64-musl@1.9.3': resolution: {integrity: sha512-tzVH480RY6RbMl/QRgh5HK3zn1ZTFsThuxDGo6Iuk1MdwIbdFYUY034heWUTI4u3Db97ArKh0hNL0xhO3+PZdg==} engines: {node: '>=10'} cpu: [arm64] os: [linux] + '@swc/core-linux-x64-gnu@1.10.4': + resolution: {integrity: sha512-qJXh9D6Kf5xSdGWPINpLGixAbB5JX8JcbEJpRamhlDBoOcQC79dYfOMEIxWPhTS1DGLyFakAx2FX/b2VmQmj0g==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + '@swc/core-linux-x64-gnu@1.9.3': resolution: {integrity: sha512-ivXXBRDXDc9k4cdv10R21ccBmGebVOwKXT/UdH1PhxUn9m/h8erAWjz5pcELwjiMf27WokqPgaWVfaclDbgE+w==} engines: {node: '>=10'} cpu: [x64] os: [linux] + '@swc/core-linux-x64-musl@1.10.4': + resolution: {integrity: sha512-A76lIAeyQnHCVt0RL/pG+0er8Qk9+acGJqSZOZm67Ve3B0oqMd871kPtaHBM0BW3OZAhoILgfHW3Op9Q3mx3Cw==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + '@swc/core-linux-x64-musl@1.9.3': resolution: {integrity: sha512-ILsGMgfnOz1HwdDz+ZgEuomIwkP1PHT6maigZxaCIuC6OPEhKE8uYna22uU63XvYcLQvZYDzpR3ms47WQPuNEg==} engines: {node: '>=10'} cpu: [x64] os: [linux] + '@swc/core-win32-arm64-msvc@1.10.4': + resolution: {integrity: sha512-e6j5kBu4fIY7fFxFxnZI0MlEovRvp50Lg59Fw+DVbtqHk3C85dckcy5xKP+UoXeuEmFceauQDczUcGs19SRGSQ==} + engines: {node: '>=10'} + cpu: [arm64] + os: [win32] + '@swc/core-win32-arm64-msvc@1.9.3': resolution: {integrity: sha512-e+XmltDVIHieUnNJHtspn6B+PCcFOMYXNJB1GqoCcyinkEIQNwC8KtWgMqUucUbEWJkPc35NHy9k8aCXRmw9Kg==} engines: {node: '>=10'} cpu: [arm64] os: [win32] + '@swc/core-win32-ia32-msvc@1.10.4': + resolution: {integrity: sha512-RSYHfdKgNXV/amY5Tqk1EWVsyQnhlsM//jeqMLw5Fy9rfxP592W9UTumNikNRPdjI8wKKzNMXDb1U29tQjN0dg==} + engines: {node: '>=10'} + cpu: [ia32] + os: [win32] + '@swc/core-win32-ia32-msvc@1.9.3': resolution: {integrity: sha512-rqpzNfpAooSL4UfQnHhkW8aL+oyjqJniDP0qwZfGnjDoJSbtPysHg2LpcOBEdSnEH+uIZq6J96qf0ZFD8AGfXA==} engines: {node: '>=10'} cpu: [ia32] os: [win32] + '@swc/core-win32-x64-msvc@1.10.4': + resolution: {integrity: sha512-1ujYpaqfqNPYdwKBlvJnOqcl+Syn3UrQ4XE0Txz6zMYgyh6cdU6a3pxqLqIUSJ12MtXRA9ZUhEz1ekU3LfLWXw==} + engines: {node: '>=10'} + cpu: [x64] + os: [win32] + '@swc/core-win32-x64-msvc@1.9.3': resolution: {integrity: sha512-3YJJLQ5suIEHEKc1GHtqVq475guiyqisKSoUnoaRtxkDaW5g1yvPt9IoSLOe2mRs7+FFhGGU693RsBUSwOXSdQ==} engines: {node: '>=10'} cpu: [x64] os: [win32] + '@swc/core@1.10.4': + resolution: {integrity: sha512-ut3zfiTLORMxhr6y/GBxkHmzcGuVpwJYX4qyXWuBKkpw/0g0S5iO1/wW7RnLnZbAi8wS/n0atRZoaZlXWBkeJg==} + engines: {node: '>=10'} + peerDependencies: + '@swc/helpers': '*' + peerDependenciesMeta: + '@swc/helpers': + optional: true + '@swc/core@1.9.3': resolution: {integrity: sha512-oRj0AFePUhtatX+BscVhnzaAmWjpfAeySpM1TCbxA1rtBDeH/JDhi5yYzAKneDYtVtBvA7ApfeuzhMC9ye4xSg==} engines: {node: '>=10'} @@ -4786,6 +4904,9 @@ packages: '@types/node@22.10.1': resolution: {integrity: sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==} + '@types/node@22.10.5': + resolution: {integrity: sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==} + '@types/node@22.8.1': resolution: {integrity: sha512-k6Gi8Yyo8EtrNtkHXutUu2corfDf9su95VYVP10aGYMMROM6SAItZi0w1XszA6RtWTHSVp5OeFof37w0IEqCQg==} @@ -4816,6 +4937,9 @@ packages: '@types/react@18.3.12': resolution: {integrity: sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==} + '@types/react@19.0.3': + resolution: {integrity: sha512-UavfHguIjnnuq9O67uXfgy/h3SRJbidAYvNjLceB+2RIKVRBzVsh0QO+Pw6BCSQqFS9xwzKfwstXx0m6AbAREA==} + '@types/responselike@1.0.3': resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} @@ -4864,8 +4988,8 @@ packages: '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - '@urql/core@5.0.8': - resolution: {integrity: sha512-1GOnUw7/a9bzkcM0+U8U5MmxW2A7FE5YquuEmcJzTtW5tIs2EoS4F2ITpuKBjRBbyRjZgO860nWFPo1m4JImGA==} + '@urql/core@5.1.0': + resolution: {integrity: sha512-yC3sw8yqjbX45GbXxfiBY8GLYCiyW/hLBbQF9l3TJrv4ro00Y0ChkKaD9I2KntRxAVm9IYBqh0awX8fwWAe/Yw==} '@vitest/coverage-c8@0.33.0': resolution: {integrity: sha512-DaF1zJz4dcOZS4k/neiQJokmOWqsGXwhthfmUdPGorXIQHjdPvV6JQSYhQDI41MyI8c+IieQUdIDs5XAMHtDDw==} @@ -5516,6 +5640,10 @@ packages: resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==} engines: {node: '>= 14.16.0'} + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + chownr@1.1.4: resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} @@ -7639,6 +7767,10 @@ packages: resolution: {integrity: sha512-yPBThwecp1wS9DmoA4x4KR2h3QoslacnDR8ypuFM962kI4/456Iy1oHx2RAgh4jfZNdn0bctsdadceiBUgpU1g==} hasBin: true + jiti@2.4.2: + resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} + hasBin: true + jose@5.9.6: resolution: {integrity: sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ==} @@ -8892,6 +9024,11 @@ packages: engines: {node: '>=18.18'} hasBin: true + prisma@6.1.0: + resolution: {integrity: sha512-aFI3Yi+ApUxkwCJJwyQSwpyzUX7YX3ihzuHNHOyv4GJg3X5tQsmRaJEnZ+ZyfHpMtnyahhmXVfbTZ+lS8ZtfKw==} + engines: {node: '>=18.18'} + hasBin: true + process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} @@ -9093,6 +9230,10 @@ packages: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} + react@19.0.0: + resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==} + engines: {node: '>=0.10.0'} + read-cache@1.0.0: resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} @@ -10606,6 +10747,11 @@ packages: engines: {node: '>= 14'} hasBin: true + yaml@2.7.0: + resolution: {integrity: sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==} + engines: {node: '>= 14'} + hasBin: true + yargs-parser@18.1.3: resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} engines: {node: '>=6'} @@ -10655,15 +10801,15 @@ packages: zen-observable@0.8.15: resolution: {integrity: sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==} - zod@3.23.8: - resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} + zod@3.24.1: + resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==} zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} snapshots: - '@0no-co/graphql.web@1.0.11(graphql@16.9.0)': + '@0no-co/graphql.web@1.0.13(graphql@16.9.0)': optionalDependencies: graphql: 16.9.0 @@ -13779,10 +13925,21 @@ snapshots: optionalDependencies: prisma: 6.0.0 + '@prisma/client@6.1.0(prisma@6.1.0)': + optionalDependencies: + prisma: 6.1.0 + optional: true + '@prisma/debug@6.0.0': {} + '@prisma/debug@6.1.0': + optional: true + '@prisma/engines-version@5.23.0-27.5dbef10bdbfb579e07d35cc85fb1518d357cb99e': {} + '@prisma/engines-version@6.1.0-21.11f085a2012c0f4778414c8db2651556ee0ef959': + optional: true + '@prisma/engines@6.0.0': dependencies: '@prisma/debug': 6.0.0 @@ -13790,12 +13947,27 @@ snapshots: '@prisma/fetch-engine': 6.0.0 '@prisma/get-platform': 6.0.0 + '@prisma/engines@6.1.0': + dependencies: + '@prisma/debug': 6.1.0 + '@prisma/engines-version': 6.1.0-21.11f085a2012c0f4778414c8db2651556ee0ef959 + '@prisma/fetch-engine': 6.1.0 + '@prisma/get-platform': 6.1.0 + optional: true + '@prisma/fetch-engine@6.0.0': dependencies: '@prisma/debug': 6.0.0 '@prisma/engines-version': 5.23.0-27.5dbef10bdbfb579e07d35cc85fb1518d357cb99e '@prisma/get-platform': 6.0.0 + '@prisma/fetch-engine@6.1.0': + dependencies: + '@prisma/debug': 6.1.0 + '@prisma/engines-version': 6.1.0-21.11f085a2012c0f4778414c8db2651556ee0ef959 + '@prisma/get-platform': 6.1.0 + optional: true + '@prisma/generator-helper@6.0.0': dependencies: '@prisma/debug': 6.0.0 @@ -13804,6 +13976,11 @@ snapshots: dependencies: '@prisma/debug': 6.0.0 + '@prisma/get-platform@6.1.0': + dependencies: + '@prisma/debug': 6.1.0 + optional: true + '@prisma/instrumentation@5.19.1': dependencies: '@opentelemetry/api': 1.9.0 @@ -14331,6 +14508,8 @@ snapshots: dependencies: tslib: 2.8.1 + '@standard-schema/spec@1.0.0-beta.4': {} + '@swc-node/core@1.13.3(@swc/core@1.9.3(@swc/helpers@0.5.15))(@swc/types@0.1.17)': dependencies: '@swc/core': 1.9.3(@swc/helpers@0.5.15) @@ -14356,7 +14535,7 @@ snapshots: source-map-support: 0.5.21 tslib: 2.7.0 - '@swc/cli@0.5.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(chokidar@3.6.0)': + '@swc/cli@0.5.1(@swc/core@1.9.3(@swc/helpers@0.5.15))(chokidar@4.0.3)': dependencies: '@swc/core': 1.9.3(@swc/helpers@0.5.15) '@swc/counter': 0.1.3 @@ -14369,38 +14548,86 @@ snapshots: slash: 3.0.0 source-map: 0.7.4 optionalDependencies: - chokidar: 3.6.0 + chokidar: 4.0.3 + + '@swc/core-darwin-arm64@1.10.4': + optional: true '@swc/core-darwin-arm64@1.9.3': optional: true + '@swc/core-darwin-x64@1.10.4': + optional: true + '@swc/core-darwin-x64@1.9.3': optional: true + '@swc/core-linux-arm-gnueabihf@1.10.4': + optional: true + '@swc/core-linux-arm-gnueabihf@1.9.3': optional: true + '@swc/core-linux-arm64-gnu@1.10.4': + optional: true + '@swc/core-linux-arm64-gnu@1.9.3': optional: true + '@swc/core-linux-arm64-musl@1.10.4': + optional: true + '@swc/core-linux-arm64-musl@1.9.3': optional: true + '@swc/core-linux-x64-gnu@1.10.4': + optional: true + '@swc/core-linux-x64-gnu@1.9.3': optional: true + '@swc/core-linux-x64-musl@1.10.4': + optional: true + '@swc/core-linux-x64-musl@1.9.3': optional: true + '@swc/core-win32-arm64-msvc@1.10.4': + optional: true + '@swc/core-win32-arm64-msvc@1.9.3': optional: true + '@swc/core-win32-ia32-msvc@1.10.4': + optional: true + '@swc/core-win32-ia32-msvc@1.9.3': optional: true + '@swc/core-win32-x64-msvc@1.10.4': + optional: true + '@swc/core-win32-x64-msvc@1.9.3': optional: true + '@swc/core@1.10.4(@swc/helpers@0.5.15)': + dependencies: + '@swc/counter': 0.1.3 + '@swc/types': 0.1.17 + optionalDependencies: + '@swc/core-darwin-arm64': 1.10.4 + '@swc/core-darwin-x64': 1.10.4 + '@swc/core-linux-arm-gnueabihf': 1.10.4 + '@swc/core-linux-arm64-gnu': 1.10.4 + '@swc/core-linux-arm64-musl': 1.10.4 + '@swc/core-linux-x64-gnu': 1.10.4 + '@swc/core-linux-x64-musl': 1.10.4 + '@swc/core-win32-arm64-msvc': 1.10.4 + '@swc/core-win32-ia32-msvc': 1.10.4 + '@swc/core-win32-x64-msvc': 1.10.4 + '@swc/helpers': 0.5.15 + optional: true + '@swc/core@1.9.3(@swc/helpers@0.5.15)': dependencies: '@swc/counter': 0.1.3 @@ -14448,13 +14675,13 @@ snapshots: dependencies: defer-to-connect: 2.0.1 - '@tailwindcss/typography@0.5.15(tailwindcss@3.4.15(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.1)(typescript@5.7.2)))': + '@tailwindcss/typography@0.5.15(tailwindcss@3.4.15(ts-node@10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.5)(typescript@5.7.2)))': dependencies: lodash.castarray: 4.4.0 lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 postcss-selector-parser: 6.0.10 - tailwindcss: 3.4.15(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.1)(typescript@5.7.2)) + tailwindcss: 3.4.15(ts-node@10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.5)(typescript@5.7.2)) '@tanstack/query-core@5.62.0': {} @@ -14667,6 +14894,10 @@ snapshots: dependencies: undici-types: 6.20.0 + '@types/node@22.10.5': + dependencies: + undici-types: 6.20.0 + '@types/node@22.8.1': dependencies: undici-types: 6.19.8 @@ -14679,7 +14910,7 @@ snapshots: '@types/pg@8.11.10': dependencies: - '@types/node': 22.10.1 + '@types/node': 22.10.5 pg-protocol: 1.7.0 pg-types: 4.0.2 optional: true @@ -14705,6 +14936,11 @@ snapshots: '@types/prop-types': 15.7.13 csstype: 3.1.3 + '@types/react@19.0.3': + dependencies: + csstype: 3.1.3 + optional: true + '@types/responselike@1.0.3': dependencies: '@types/node': 22.10.1 @@ -14752,21 +14988,21 @@ snapshots: '@ungap/structured-clone@1.2.0': {} - '@urql/core@5.0.8(graphql@16.9.0)': + '@urql/core@5.1.0(graphql@16.9.0)': dependencies: - '@0no-co/graphql.web': 1.0.11(graphql@16.9.0) + '@0no-co/graphql.web': 1.0.13(graphql@16.9.0) wonka: 6.3.4 transitivePeerDependencies: - graphql - '@vitest/coverage-c8@0.33.0(vitest@2.1.6(@types/node@22.10.1)(jiti@2.4.1)(tsx@4.19.2)(yaml@2.6.1))': + '@vitest/coverage-c8@0.33.0(vitest@2.1.6(@types/node@22.10.1)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0))': dependencies: '@ampproject/remapping': 2.3.0 c8: 7.14.0 magic-string: 0.30.14 picocolors: 1.1.1 std-env: 3.8.0 - vitest: 2.1.6(@types/node@22.10.1)(jiti@2.4.1)(tsx@4.19.2)(yaml@2.6.1) + vitest: 2.1.6(@types/node@22.10.1)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0) '@vitest/expect@2.1.6': dependencies: @@ -14775,13 +15011,21 @@ snapshots: chai: 5.1.2 tinyrainbow: 1.2.0 - '@vitest/mocker@2.1.6(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.1)(tsx@4.19.2)(yaml@2.6.1))': + '@vitest/mocker@2.1.6(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0))': dependencies: '@vitest/spy': 2.1.6 estree-walker: 3.0.3 magic-string: 0.30.14 optionalDependencies: - vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.1)(tsx@4.19.2)(yaml@2.6.1) + vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0) + + '@vitest/mocker@2.1.6(vite@6.0.1(@types/node@22.10.5)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0))': + dependencies: + '@vitest/spy': 2.1.6 + estree-walker: 3.0.3 + magic-string: 0.30.14 + optionalDependencies: + vite: 6.0.1(@types/node@22.10.5)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0) '@vitest/pretty-format@2.1.6': dependencies: @@ -15230,7 +15474,7 @@ snapshots: before-after-hook@2.2.3: {} - bema@0.1.2(@babel/core@7.26.0)(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.1)(encoding@0.1.13): + bema@0.1.2(@babel/core@7.26.0)(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.5)(encoding@0.1.13): dependencies: '@fast-csv/format': 4.3.5 '@fast-csv/parse': 4.3.6 @@ -15265,7 +15509,7 @@ snapshots: slugify: 1.6.6 strip-ansi: 6.0.1 ts-custom-error: 3.3.1 - ts-node: 10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.1)(typescript@4.9.5) + ts-node: 10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.5)(typescript@4.9.5) tslib: 2.7.0 type-fest: 1.4.0 typescript: 4.9.5 @@ -15682,6 +15926,11 @@ snapshots: dependencies: readdirp: 4.0.2 + chokidar@4.0.3: + dependencies: + readdirp: 4.0.2 + optional: true + chownr@1.1.4: optional: true @@ -16251,9 +16500,9 @@ snapshots: p-event: 2.3.1 pify: 4.0.1 - drizzle-graphql@0.8.5(drizzle-orm@0.36.4(@libsql/client@0.14.0)(@opentelemetry/api@1.9.0)(@prisma/client@6.0.0(prisma@6.0.0))(@types/pg@8.11.10)(@types/react@18.3.12)(postgres@3.4.5)(prisma@6.0.0)(react@18.3.1))(graphql@16.9.0): + drizzle-graphql@0.8.5(drizzle-orm@0.36.4(@libsql/client@0.14.0)(@opentelemetry/api@1.9.0)(@prisma/client@6.1.0(prisma@6.1.0))(@types/pg@8.11.10)(@types/react@19.0.3)(postgres@3.4.5)(prisma@6.1.0)(react@19.0.0))(graphql@16.9.0): dependencies: - drizzle-orm: 0.36.4(@libsql/client@0.14.0)(@opentelemetry/api@1.9.0)(@prisma/client@6.0.0(prisma@6.0.0))(@types/pg@8.11.10)(@types/react@18.3.12)(postgres@3.4.5)(prisma@6.0.0)(react@18.3.1) + drizzle-orm: 0.36.4(@libsql/client@0.14.0)(@opentelemetry/api@1.9.0)(@prisma/client@6.1.0(prisma@6.1.0))(@types/pg@8.11.10)(@types/react@19.0.3)(postgres@3.4.5)(prisma@6.1.0)(react@19.0.0) graphql: 16.9.0 graphql-parse-resolve-info: 4.13.0(graphql@16.9.0) transitivePeerDependencies: @@ -16268,16 +16517,16 @@ snapshots: transitivePeerDependencies: - supports-color - drizzle-orm@0.36.4(@libsql/client@0.14.0)(@opentelemetry/api@1.9.0)(@prisma/client@6.0.0(prisma@6.0.0))(@types/pg@8.11.10)(@types/react@18.3.12)(postgres@3.4.5)(prisma@6.0.0)(react@18.3.1): + drizzle-orm@0.36.4(@libsql/client@0.14.0)(@opentelemetry/api@1.9.0)(@prisma/client@6.1.0(prisma@6.1.0))(@types/pg@8.11.10)(@types/react@19.0.3)(postgres@3.4.5)(prisma@6.1.0)(react@19.0.0): optionalDependencies: '@libsql/client': 0.14.0 '@opentelemetry/api': 1.9.0 - '@prisma/client': 6.0.0(prisma@6.0.0) + '@prisma/client': 6.1.0(prisma@6.1.0) '@types/pg': 8.11.10 - '@types/react': 18.3.12 + '@types/react': 19.0.3 postgres: 3.4.5 - prisma: 6.0.0 - react: 18.3.1 + prisma: 6.1.0 + react: 19.0.0 dset@3.1.3: {} @@ -17053,7 +17302,7 @@ snapshots: npm-to-yarn: 3.0.0 ts-morph: 24.0.0 unist-util-visit: 5.0.0 - zod: 3.23.8 + zod: 3.24.1 transitivePeerDependencies: - supports-color - typescript @@ -17070,7 +17319,7 @@ snapshots: gray-matter: 4.0.3 micromatch: 4.0.8 next: 15.0.3(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - zod: 3.23.8 + zod: 3.24.1 transitivePeerDependencies: - acorn - supports-color @@ -17089,7 +17338,7 @@ snapshots: transitivePeerDependencies: - supports-color - fumadocs-ui@13.4.9(@types/react-dom@18.3.1)(@types/react@18.3.12)(next@15.0.3(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.15(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.1)(typescript@5.7.2))): + fumadocs-ui@13.4.9(@types/react-dom@18.3.1)(@types/react@18.3.12)(next@15.0.3(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.15(ts-node@10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.5)(typescript@5.7.2))): dependencies: '@radix-ui/react-accordion': 1.2.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-collapsible': 1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -17098,7 +17347,7 @@ snapshots: '@radix-ui/react-popover': 1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-scroll-area': 1.2.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-tabs': 1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@tailwindcss/typography': 0.5.15(tailwindcss@3.4.15(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.1)(typescript@5.7.2))) + '@tailwindcss/typography': 0.5.15(tailwindcss@3.4.15(ts-node@10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.5)(typescript@5.7.2))) class-variance-authority: 0.7.1 cmdk: 1.0.4(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) fumadocs-core: 13.4.9(@types/react@18.3.12)(next@15.0.3(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -18236,6 +18485,9 @@ snapshots: jiti@2.4.1: {} + jiti@2.4.2: + optional: true + jose@5.9.6: {} js-base64@3.7.7: {} @@ -19684,13 +19936,13 @@ snapshots: camelcase-css: 2.0.1 postcss: 8.4.49 - postcss-load-config@4.0.2(postcss@8.4.49)(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.1)(typescript@5.7.2)): + postcss-load-config@4.0.2(postcss@8.4.49)(ts-node@10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.5)(typescript@5.7.2)): dependencies: lilconfig: 3.1.2 yaml: 2.6.1 optionalDependencies: postcss: 8.4.49 - ts-node: 10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.1)(typescript@5.7.2) + ts-node: 10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.5)(typescript@5.7.2) postcss-nested@6.2.0(postcss@8.4.49): dependencies: @@ -19786,6 +20038,13 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + prisma@6.1.0: + dependencies: + '@prisma/engines': 6.1.0 + optionalDependencies: + fsevents: 2.3.3 + optional: true + process-nextick-args@2.0.1: {} process-warning@4.0.0: {} @@ -19998,6 +20257,9 @@ snapshots: dependencies: loose-envify: 1.4.0 + react@19.0.0: + optional: true + read-cache@1.0.0: dependencies: pify: 2.3.0 @@ -20796,7 +21058,7 @@ snapshots: tailwind-merge@2.5.5: {} - tailwindcss@3.4.15(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.1)(typescript@5.7.2)): + tailwindcss@3.4.15(ts-node@10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.5)(typescript@5.7.2)): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -20815,7 +21077,7 @@ snapshots: postcss: 8.4.49 postcss-import: 15.1.0(postcss@8.4.49) postcss-js: 4.0.1(postcss@8.4.49) - postcss-load-config: 4.0.2(postcss@8.4.49)(ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.1)(typescript@5.7.2)) + postcss-load-config: 4.0.2(postcss@8.4.49)(ts-node@10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.5)(typescript@5.7.2)) postcss-nested: 6.2.0(postcss@8.4.49) postcss-selector-parser: 6.1.2 resolve: 1.22.8 @@ -20996,14 +21258,34 @@ snapshots: '@ts-morph/common': 0.25.0 code-block-writer: 13.0.3 - ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@18.19.67)(typescript@5.5.4): + ts-node@10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.5)(typescript@4.9.5): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 18.19.67 + '@types/node': 22.10.5 + acorn: 8.12.1 + acorn-walk: 8.3.3 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 4.9.5 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + optionalDependencies: + '@swc/core': 1.10.4(@swc/helpers@0.5.15) + + ts-node@10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.5)(typescript@5.5.4): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.11 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 22.10.5 acorn: 8.12.1 acorn-walk: 8.3.3 arg: 4.1.3 @@ -21014,36 +21296,37 @@ snapshots: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 optionalDependencies: - '@swc/core': 1.9.3(@swc/helpers@0.5.15) + '@swc/core': 1.10.4(@swc/helpers@0.5.15) - ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.1)(typescript@4.9.5): + ts-node@10.9.2(@swc/core@1.10.4(@swc/helpers@0.5.15))(@types/node@22.10.5)(typescript@5.7.2): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 22.10.1 + '@types/node': 22.10.5 acorn: 8.12.1 acorn-walk: 8.3.3 arg: 4.1.3 create-require: 1.1.1 diff: 4.0.2 make-error: 1.3.6 - typescript: 4.9.5 + typescript: 5.7.2 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 optionalDependencies: - '@swc/core': 1.9.3(@swc/helpers@0.5.15) + '@swc/core': 1.10.4(@swc/helpers@0.5.15) + optional: true - ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@22.10.1)(typescript@5.5.4): + ts-node@10.9.2(@swc/core@1.9.3(@swc/helpers@0.5.15))(@types/node@18.19.67)(typescript@5.5.4): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 22.10.1 + '@types/node': 18.19.67 acorn: 8.12.1 acorn-walk: 8.3.3 arg: 4.1.3 @@ -21281,9 +21564,9 @@ snapshots: urlpattern-polyfill@8.0.2: {} - urql@4.2.1(@urql/core@5.0.8(graphql@16.9.0))(react@18.3.1): + urql@4.2.1(@urql/core@5.1.0(graphql@16.9.0))(react@18.3.1): dependencies: - '@urql/core': 5.0.8(graphql@16.9.0) + '@urql/core': 5.1.0(graphql@16.9.0) react: 18.3.1 wonka: 6.3.4 @@ -21610,13 +21893,13 @@ snapshots: victory-voronoi-container: 35.11.4(react@17.0.2) victory-zoom-container: 35.11.4(react@17.0.2) - vite-node@2.1.6(@types/node@22.10.1)(jiti@2.4.1)(tsx@4.19.2)(yaml@2.6.1): + vite-node@2.1.6(@types/node@22.10.1)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0): dependencies: cac: 6.7.14 debug: 4.3.7 es-module-lexer: 1.5.4 pathe: 1.1.2 - vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.1)(tsx@4.19.2)(yaml@2.6.1) + vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0) transitivePeerDependencies: - '@types/node' - jiti @@ -21631,7 +21914,28 @@ snapshots: - tsx - yaml - vite@6.0.1(@types/node@22.10.1)(jiti@2.4.1)(tsx@4.19.2)(yaml@2.6.1): + vite-node@2.1.6(@types/node@22.10.5)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0): + dependencies: + cac: 6.7.14 + debug: 4.3.7 + es-module-lexer: 1.5.4 + pathe: 1.1.2 + vite: 6.0.1(@types/node@22.10.5)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0) + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + vite@6.0.1(@types/node@22.10.1)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0): dependencies: esbuild: 0.24.0 postcss: 8.4.49 @@ -21639,14 +21943,26 @@ snapshots: optionalDependencies: '@types/node': 22.10.1 fsevents: 2.3.3 - jiti: 2.4.1 + jiti: 2.4.2 tsx: 4.19.2 - yaml: 2.6.1 + yaml: 2.7.0 + + vite@6.0.1(@types/node@22.10.5)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0): + dependencies: + esbuild: 0.24.0 + postcss: 8.4.49 + rollup: 4.27.4 + optionalDependencies: + '@types/node': 22.10.5 + fsevents: 2.3.3 + jiti: 2.4.2 + tsx: 4.19.2 + yaml: 2.7.0 - vitest@2.1.6(@types/node@22.10.1)(jiti@2.4.1)(tsx@4.19.2)(yaml@2.6.1): + vitest@2.1.6(@types/node@22.10.1)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0): dependencies: '@vitest/expect': 2.1.6 - '@vitest/mocker': 2.1.6(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.1)(tsx@4.19.2)(yaml@2.6.1)) + '@vitest/mocker': 2.1.6(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0)) '@vitest/pretty-format': 2.1.6 '@vitest/runner': 2.1.6 '@vitest/snapshot': 2.1.6 @@ -21662,8 +21978,8 @@ snapshots: tinyexec: 0.3.1 tinypool: 1.0.2 tinyrainbow: 1.2.0 - vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.1)(tsx@4.19.2)(yaml@2.6.1) - vite-node: 2.1.6(@types/node@22.10.1)(jiti@2.4.1)(tsx@4.19.2)(yaml@2.6.1) + vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0) + vite-node: 2.1.6(@types/node@22.10.1)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.10.1 @@ -21681,6 +21997,44 @@ snapshots: - tsx - yaml + vitest@2.1.6(@types/node@22.10.5)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0): + dependencies: + '@vitest/expect': 2.1.6 + '@vitest/mocker': 2.1.6(vite@6.0.1(@types/node@22.10.5)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0)) + '@vitest/pretty-format': 2.1.6 + '@vitest/runner': 2.1.6 + '@vitest/snapshot': 2.1.6 + '@vitest/spy': 2.1.6 + '@vitest/utils': 2.1.6 + chai: 5.1.2 + debug: 4.3.7 + expect-type: 1.1.0 + magic-string: 0.30.14 + pathe: 1.1.2 + std-env: 3.8.0 + tinybench: 2.9.0 + tinyexec: 0.3.1 + tinypool: 1.0.2 + tinyrainbow: 1.2.0 + vite: 6.0.1(@types/node@22.10.5)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0) + vite-node: 2.1.6(@types/node@22.10.5)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 22.10.5 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + vm-browserify@1.1.2: {} walker@1.0.8: @@ -21814,6 +22168,9 @@ snapshots: yaml@2.6.1: {} + yaml@2.7.0: + optional: true + yargs-parser@18.1.3: dependencies: camelcase: 5.3.1 @@ -21887,6 +22244,6 @@ snapshots: zen-observable@0.8.15: {} - zod@3.23.8: {} + zod@3.24.1: {} zwitch@2.0.4: {}