diff --git a/package.json b/package.json index 0c86fb9bb..e896bb5f3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "zenstack-monorepo", - "version": "2.4.1", + "version": "2.5.0", "description": "", "scripts": { "build": "pnpm -r build", diff --git a/packages/ide/jetbrains/.idea/misc.xml b/packages/ide/jetbrains/.idea/misc.xml index faebea582..510c2cda9 100644 --- a/packages/ide/jetbrains/.idea/misc.xml +++ b/packages/ide/jetbrains/.idea/misc.xml @@ -4,7 +4,7 @@ - + diff --git a/packages/ide/jetbrains/CHANGELOG.md b/packages/ide/jetbrains/CHANGELOG.md index 85a3c2e65..1d9a8b78d 100644 --- a/packages/ide/jetbrains/CHANGELOG.md +++ b/packages/ide/jetbrains/CHANGELOG.md @@ -2,6 +2,14 @@ ## [Unreleased] ### Added +- A new `path` parameter to the `@@validate` attribute for providing an optional path to the field that caused the error. + +## 2.4.0 +### Added +- The `uuid()` function is updated to support the new UUID version feature from Prisma. + +## 2.3.0 +### Added - New `check()` policy rule function. ### Fixed diff --git a/packages/ide/jetbrains/build.gradle.kts b/packages/ide/jetbrains/build.gradle.kts index 230f7a6e0..d3a2d9fb2 100644 --- a/packages/ide/jetbrains/build.gradle.kts +++ b/packages/ide/jetbrains/build.gradle.kts @@ -9,7 +9,7 @@ plugins { } group = "dev.zenstack" -version = "2.4.1" +version = "2.5.0" repositories { mavenCentral() diff --git a/packages/ide/jetbrains/package.json b/packages/ide/jetbrains/package.json index 5e97ad848..b48439ad0 100644 --- a/packages/ide/jetbrains/package.json +++ b/packages/ide/jetbrains/package.json @@ -1,6 +1,6 @@ { "name": "jetbrains", - "version": "2.4.1", + "version": "2.5.0", "displayName": "ZenStack JetBrains IDE Plugin", "description": "ZenStack JetBrains IDE plugin", "homepage": "https://zenstack.dev", diff --git a/packages/language/package.json b/packages/language/package.json index fd84f0710..2369cbab9 100644 --- a/packages/language/package.json +++ b/packages/language/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/language", - "version": "2.4.1", + "version": "2.5.0", "displayName": "ZenStack modeling language compiler", "description": "ZenStack modeling language compiler", "homepage": "https://zenstack.dev", diff --git a/packages/misc/redwood/package.json b/packages/misc/redwood/package.json index fdd3a6835..784826caf 100644 --- a/packages/misc/redwood/package.json +++ b/packages/misc/redwood/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/redwood", "displayName": "ZenStack RedwoodJS Integration", - "version": "2.4.1", + "version": "2.5.0", "description": "CLI and runtime for integrating ZenStack with RedwoodJS projects.", "repository": { "type": "git", diff --git a/packages/misc/redwood/src/graphql.ts b/packages/misc/redwood/src/graphql.ts index 69267b5e2..943329744 100644 --- a/packages/misc/redwood/src/graphql.ts +++ b/packages/misc/redwood/src/graphql.ts @@ -1,9 +1,8 @@ -import { ForbiddenError } from '@redwoodjs/graphql-server'; +import { ForbiddenError, ValidationError } from '@redwoodjs/graphql-server'; import { CrudFailureReason, EnhancementOptions, PrismaErrorCode, - ValidationError, enhance, isPrismaClientKnownRequestError, type AuthUser, @@ -47,7 +46,7 @@ export function useZenStack( // Transforms ZenStack errors into appropriate RedwoodJS errors function transformError(error: unknown) { - if (isPrismaClientKnownRequestError(error) && error.code === PrismaErrorCode.CONSTRAINED_FAILED) { + if (isPrismaClientKnownRequestError(error) && error.code === PrismaErrorCode.CONSTRAINT_FAILED) { if ( error.meta?.reason === CrudFailureReason.ACCESS_POLICY_VIOLATION || error.meta?.reason === CrudFailureReason.RESULT_NOT_READABLE diff --git a/packages/plugins/openapi/package.json b/packages/plugins/openapi/package.json index 74b00750d..38f55551b 100644 --- a/packages/plugins/openapi/package.json +++ b/packages/plugins/openapi/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/openapi", "displayName": "ZenStack Plugin and Runtime for OpenAPI", - "version": "2.4.1", + "version": "2.5.0", "description": "ZenStack plugin and runtime supporting OpenAPI", "main": "index.js", "repository": { diff --git a/packages/plugins/openapi/src/rpc-generator.ts b/packages/plugins/openapi/src/rpc-generator.ts index 7339ef788..c524d9cd1 100644 --- a/packages/plugins/openapi/src/rpc-generator.ts +++ b/packages/plugins/openapi/src/rpc-generator.ts @@ -637,18 +637,13 @@ export class RPCOpenAPIGenerator extends OpenAPIGeneratorBase { schemas['_Meta'] = { type: 'object', + description: 'Meta information about the request or response', properties: { - meta: { - type: 'object', - description: 'Meta information about the request or response', - properties: { - serialization: { - description: 'Serialization metadata', - }, - }, - additionalProperties: true, + serialization: { + description: 'Serialization metadata', }, }, + additionalProperties: true, }; schemas['_Error'] = { diff --git a/packages/plugins/openapi/tests/baseline/rpc-3.0.0.baseline.yaml b/packages/plugins/openapi/tests/baseline/rpc-3.0.0.baseline.yaml index 68885daed..81ff8d587 100644 --- a/packages/plugins/openapi/tests/baseline/rpc-3.0.0.baseline.yaml +++ b/packages/plugins/openapi/tests/baseline/rpc-3.0.0.baseline.yaml @@ -3212,14 +3212,11 @@ components: nullable: true _Meta: type: object + description: Meta information about the request or response properties: - meta: - type: object - description: Meta information about the request or response - properties: - serialization: - description: Serialization metadata - additionalProperties: true + serialization: + description: Serialization metadata + additionalProperties: true _Error: type: object required: diff --git a/packages/plugins/openapi/tests/baseline/rpc-3.1.0.baseline.yaml b/packages/plugins/openapi/tests/baseline/rpc-3.1.0.baseline.yaml index 0f36abca2..7665b3070 100644 --- a/packages/plugins/openapi/tests/baseline/rpc-3.1.0.baseline.yaml +++ b/packages/plugins/openapi/tests/baseline/rpc-3.1.0.baseline.yaml @@ -3276,14 +3276,11 @@ components: - type: string _Meta: type: object + description: Meta information about the request or response properties: - meta: - type: object - description: Meta information about the request or response - properties: - serialization: - description: Serialization metadata - additionalProperties: true + serialization: + description: Serialization metadata + additionalProperties: true _Error: type: object required: diff --git a/packages/plugins/openapi/tests/baseline/rpc-type-coverage-3.0.0.baseline.yaml b/packages/plugins/openapi/tests/baseline/rpc-type-coverage-3.0.0.baseline.yaml index 495ebd42b..01c9a2d0f 100644 --- a/packages/plugins/openapi/tests/baseline/rpc-type-coverage-3.0.0.baseline.yaml +++ b/packages/plugins/openapi/tests/baseline/rpc-type-coverage-3.0.0.baseline.yaml @@ -1861,14 +1861,11 @@ components: nullable: true _Meta: type: object + description: Meta information about the request or response properties: - meta: - type: object - description: Meta information about the request or response - properties: - serialization: - description: Serialization metadata - additionalProperties: true + serialization: + description: Serialization metadata + additionalProperties: true _Error: type: object required: diff --git a/packages/plugins/openapi/tests/baseline/rpc-type-coverage-3.1.0.baseline.yaml b/packages/plugins/openapi/tests/baseline/rpc-type-coverage-3.1.0.baseline.yaml index c9327b7f2..3ada4651d 100644 --- a/packages/plugins/openapi/tests/baseline/rpc-type-coverage-3.1.0.baseline.yaml +++ b/packages/plugins/openapi/tests/baseline/rpc-type-coverage-3.1.0.baseline.yaml @@ -1903,14 +1903,11 @@ components: format: byte _Meta: type: object + description: Meta information about the request or response properties: - meta: - type: object - description: Meta information about the request or response - properties: - serialization: - description: Serialization metadata - additionalProperties: true + serialization: + description: Serialization metadata + additionalProperties: true _Error: type: object required: diff --git a/packages/plugins/swr/package.json b/packages/plugins/swr/package.json index d3137a579..7b36c0533 100644 --- a/packages/plugins/swr/package.json +++ b/packages/plugins/swr/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/swr", "displayName": "ZenStack plugin for generating SWR hooks", - "version": "2.4.1", + "version": "2.5.0", "description": "ZenStack plugin for generating SWR hooks", "main": "index.js", "repository": { @@ -42,7 +42,6 @@ "@zenstackhq/sdk": "workspace:*", "change-case": "^4.1.2", "cross-fetch": "^4.0.0", - "decimal.js": "^10.4.2", "lower-case-first": "^2.0.2", "semver": "^7.5.2", "ts-morph": "^16.0.0", diff --git a/packages/plugins/tanstack-query/package.json b/packages/plugins/tanstack-query/package.json index 5dc120283..c35644f88 100644 --- a/packages/plugins/tanstack-query/package.json +++ b/packages/plugins/tanstack-query/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/tanstack-query", "displayName": "ZenStack plugin for generating tanstack-query hooks", - "version": "2.4.1", + "version": "2.5.0", "description": "ZenStack plugin for generating tanstack-query hooks", "main": "index.js", "exports": { @@ -84,7 +84,6 @@ "@zenstackhq/sdk": "workspace:*", "change-case": "^4.1.2", "cross-fetch": "^4.0.0", - "decimal.js": "^10.4.2", "lower-case-first": "^2.0.2", "semver": "^7.5.2", "ts-morph": "^16.0.0", diff --git a/packages/plugins/trpc/package.json b/packages/plugins/trpc/package.json index f49a872f0..4f457071f 100644 --- a/packages/plugins/trpc/package.json +++ b/packages/plugins/trpc/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/trpc", "displayName": "ZenStack plugin for tRPC", - "version": "2.4.1", + "version": "2.5.0", "description": "ZenStack plugin for tRPC", "main": "index.js", "repository": { diff --git a/packages/plugins/trpc/res/client/next.ts b/packages/plugins/trpc/res/client/v10/next.ts similarity index 100% rename from packages/plugins/trpc/res/client/next.ts rename to packages/plugins/trpc/res/client/v10/next.ts diff --git a/packages/plugins/trpc/res/client/react.ts b/packages/plugins/trpc/res/client/v10/react.ts similarity index 100% rename from packages/plugins/trpc/res/client/react.ts rename to packages/plugins/trpc/res/client/v10/react.ts diff --git a/packages/plugins/trpc/res/client/utils.ts b/packages/plugins/trpc/res/client/v10/utils.ts similarity index 100% rename from packages/plugins/trpc/res/client/utils.ts rename to packages/plugins/trpc/res/client/v10/utils.ts diff --git a/packages/plugins/trpc/res/client/v11/next.ts b/packages/plugins/trpc/res/client/v11/next.ts new file mode 100644 index 000000000..659d657a7 --- /dev/null +++ b/packages/plugins/trpc/res/client/v11/next.ts @@ -0,0 +1,16 @@ +/* eslint-disable */ + +import type { AnyTRPCRouter as AnyRouter } from '@trpc/server'; +import type { NextPageContext } from 'next'; +import { type CreateTRPCNext, createTRPCNext as _createTRPCNext } from '@trpc/next'; +import type { DeepOverrideAtPath } from './utils'; +import type { ClientType } from '../routers'; + +export function createTRPCNext< + TRouter extends AnyRouter, + TPath extends string | undefined = undefined, + TSSRContext extends NextPageContext = NextPageContext +>(opts: Parameters[0]) { + const r: CreateTRPCNext = _createTRPCNext(opts); + return r as DeepOverrideAtPath, ClientType, TPath>; +} diff --git a/packages/plugins/trpc/res/client/v11/react.ts b/packages/plugins/trpc/res/client/v11/react.ts new file mode 100644 index 000000000..be69328fe --- /dev/null +++ b/packages/plugins/trpc/res/client/v11/react.ts @@ -0,0 +1,16 @@ +/* eslint-disable */ + +import type { AnyTRPCRouter as AnyRouter } from '@trpc/server'; +import type { CreateTRPCReactOptions } from '@trpc/react-query/shared'; +import { type CreateTRPCReact, createTRPCReact as _createTRPCReact } from '@trpc/react-query'; +import type { DeepOverrideAtPath } from './utils'; +import type { ClientType } from '../routers'; + +export function createTRPCReact< + TRouter extends AnyRouter, + TPath extends string | undefined = undefined, + TSSRContext = unknown +>(opts?: CreateTRPCReactOptions) { + const r: CreateTRPCReact = _createTRPCReact(opts); + return r as DeepOverrideAtPath, ClientType, TPath>; +} diff --git a/packages/plugins/trpc/res/client/v11/utils.ts b/packages/plugins/trpc/res/client/v11/utils.ts new file mode 100644 index 000000000..223fde54d --- /dev/null +++ b/packages/plugins/trpc/res/client/v11/utils.ts @@ -0,0 +1,32 @@ +/* eslint-disable */ + +// inspired by: https://stackoverflow.com/questions/70632026/generic-to-recursively-modify-a-given-type-interface-in-typescript + +type Primitive = string | Function | number | boolean | Symbol | undefined | null; + +/** + * Recursively merges `T` and `R`. If there's a shared key, use `R`'s field type to overwrite `T`. + */ +export type DeepOverride = T extends Primitive + ? R + : R extends Primitive + ? R + : { + [K in keyof T]: K extends keyof R ? DeepOverride : T[K]; + } & { + [K in Exclude]: R[K]; + }; + +/** + * Traverse to `Path` (denoted by dot separated string literal type) in `T`, and starting from there, + * recursively merge with `R`. + */ +export type DeepOverrideAtPath = Path extends undefined + ? DeepOverride + : Path extends `${infer P1}.${infer P2}` + ? P1 extends keyof T + ? Omit & Record>> + : never + : Path extends keyof T + ? Omit & Record> + : never; diff --git a/packages/plugins/trpc/src/generator.ts b/packages/plugins/trpc/src/generator.ts index bf1e8b53e..b8ae9ec37 100644 --- a/packages/plugins/trpc/src/generator.ts +++ b/packages/plugins/trpc/src/generator.ts @@ -50,6 +50,24 @@ export async function generate(model: Model, options: PluginOptions, dmmf: DMMF. outDir = resolvePath(outDir, options); ensureEmptyDir(outDir); + const version = typeof options.version === 'string' ? options.version : 'v10'; + if (!['v10', 'v11'].includes(version)) { + throw new PluginError(name, `Unsupported tRPC version "${version}". Use "v10" (default) or "v11".`); + } + + if (version === 'v11') { + // v11 require options for importing `createTRPCRouter` and `procedure` + const importCreateRouter = options.importCreateRouter as string; + if (!importCreateRouter) { + throw new PluginError(name, `Option "importCreateRouter" is required for tRPC v11`); + } + + const importProcedure = options.importProcedure as string; + if (!importProcedure) { + throw new PluginError(name, `Option "importProcedure" is required for tRPC v11`); + } + } + const prismaClientDmmf = dmmf; let modelOperations = prismaClientDmmf.mappings.modelOperations; @@ -71,8 +89,10 @@ export async function generate(model: Model, options: PluginOptions, dmmf: DMMF. generateClientHelpers, model, zodSchemasImport, - options + options, + version ); + createHelper(outDir); await saveProject(project); @@ -86,7 +106,8 @@ function createAppRouter( generateClientHelpers: string[] | undefined, zmodel: Model, zodSchemasImport: string, - options: PluginOptions + options: PluginOptions, + version: string ) { const indexFile = path.resolve(outDir, 'routers', `index.ts`); const appRouter = project.createSourceFile(indexFile, undefined, { @@ -96,22 +117,36 @@ function createAppRouter( appRouter.addStatements('/* eslint-disable */'); const prismaImport = getPrismaClientImportSpec(path.dirname(indexFile), options); + + if (version === 'v10') { + appRouter.addImportDeclarations([ + { + namedImports: [ + 'unsetMarker', + 'AnyRouter', + 'AnyRootConfig', + 'CreateRouterInner', + 'Procedure', + 'ProcedureBuilder', + 'ProcedureParams', + 'ProcedureRouterRecord', + 'ProcedureType', + ], + isTypeOnly: true, + moduleSpecifier: '@trpc/server', + }, + ]); + } else { + appRouter.addImportDeclarations([ + { + namedImports: ['AnyTRPCRouter as AnyRouter'], + isTypeOnly: true, + moduleSpecifier: '@trpc/server', + }, + ]); + } + appRouter.addImportDeclarations([ - { - namedImports: [ - 'unsetMarker', - 'AnyRouter', - 'AnyRootConfig', - 'CreateRouterInner', - 'Procedure', - 'ProcedureBuilder', - 'ProcedureParams', - 'ProcedureRouterRecord', - 'ProcedureType', - ], - isTypeOnly: true, - moduleSpecifier: '@trpc/server', - }, { namedImports: ['PrismaClient'], isTypeOnly: true, @@ -119,8 +154,8 @@ function createAppRouter( }, ]); - appRouter.addStatements(` - + if (version === 'v10') { + appRouter.addStatements(` export type BaseConfig = AnyRootConfig; export type RouterFactory = < @@ -133,30 +168,40 @@ function createAppRouter( export type ProcBuilder = ProcedureBuilder< ProcedureParams - >; + >; + `); + } else { + appRouter.addImportDeclaration({ + namedImports: ['createTRPCRouter'], + moduleSpecifier: options.importCreateRouter as string, + }); + } + appRouter.addStatements(` export function db(ctx: any) { if (!ctx.prisma) { throw new Error('Missing "prisma" field in trpc context'); } return ctx.prisma as PrismaClient; } - `); const filteredModelOperations = modelOperations.filter((mo) => !hiddenModels.includes(mo.model)); appRouter .addFunction({ - name: 'createRouter', - parameters: [ - { name: 'router', type: 'RouterFactory' }, - { name: 'procedure', type: 'ProcBuilder' }, - ], + name: version === 'v10' ? 'createRouter' : 'createRouter', + parameters: + version === 'v10' + ? [ + { name: 'router', type: 'RouterFactory' }, + { name: 'procedure', type: 'ProcBuilder' }, + ] + : [], isExported: true, }) .setBodyText((writer) => { - writer.write('return router('); + writer.write(`return ${version === 'v10' ? 'router' : 'createTRPCRouter'}(`); writer.block(() => { for (const modelOperation of filteredModelOperations) { const { model, ...operations } = modelOperation; @@ -173,7 +218,8 @@ function createAppRouter( generateClientHelpers, zodSchemasImport, options, - zmodel + zmodel, + version ); appRouter.addImportDeclaration({ @@ -181,7 +227,11 @@ function createAppRouter( moduleSpecifier: `./${model}.router`, }); - writer.writeLine(`${lowerCaseFirst(model)}: create${model}Router(router, procedure),`); + if (version === 'v10') { + writer.writeLine(`${lowerCaseFirst(model)}: create${model}Router(router, procedure),`); + } else { + writer.writeLine(`${lowerCaseFirst(model)}: create${model}Router(),`); + } } }); writer.write(');'); @@ -204,22 +254,22 @@ function createAppRouter( }), }); - createClientHelpers(outDir, generateClientHelpers); + createClientHelpers(outDir, generateClientHelpers, version); } appRouter.formatText(); } -function createClientHelpers(outputDir: string, generateClientHelpers: string[]) { +function createClientHelpers(outputDir: string, generateClientHelpers: string[], version: string) { const utils = project.createSourceFile(path.resolve(outputDir, 'client', `utils.ts`), undefined, { overwrite: true, }); - utils.replaceWithText(fs.readFileSync(path.join(__dirname, './res/client/utils.ts'), 'utf-8')); + utils.replaceWithText(fs.readFileSync(path.join(__dirname, `./res/client/${version}/utils.ts`), 'utf-8')); for (const client of generateClientHelpers) { switch (client) { case 'react': { - const content = fs.readFileSync(path.join(__dirname, './res/client/react.ts'), 'utf-8'); + const content = fs.readFileSync(path.join(__dirname, `./res/client/${version}/react.ts`), 'utf-8'); project.createSourceFile(path.resolve(outputDir, 'client', 'react.ts'), content, { overwrite: true, }); @@ -227,7 +277,7 @@ function createClientHelpers(outputDir: string, generateClientHelpers: string[]) } case 'next': { - const content = fs.readFileSync(path.join(__dirname, './res/client/next.ts'), 'utf-8'); + const content = fs.readFileSync(path.join(__dirname, `./res/client/${version}/next.ts`), 'utf-8'); project.createSourceFile(path.resolve(outputDir, 'client', 'next.ts'), content, { overwrite: true }); break; } @@ -244,7 +294,8 @@ function generateModelCreateRouter( generateClientHelpers: string[] | undefined, zodSchemasImport: string, options: PluginOptions, - zmodel: Model + zmodel: Model, + version: string ) { const modelRouter = project.createSourceFile(path.resolve(outputDir, 'routers', `${model}.router.ts`), undefined, { overwrite: true, @@ -252,28 +303,63 @@ function generateModelCreateRouter( modelRouter.addStatements('/* eslint-disable */'); - modelRouter.addImportDeclarations([ - { - namedImports: ['type RouterFactory', 'type ProcBuilder', 'type BaseConfig', 'db'], - moduleSpecifier: '.', - }, - ]); + if (version === 'v10') { + modelRouter.addImportDeclarations([ + { + namedImports: ['type RouterFactory', 'type ProcBuilder', 'type BaseConfig', 'db'], + moduleSpecifier: '.', + }, + ]); + } else { + modelRouter.addImportDeclarations([ + { + namedImports: ['db'], + moduleSpecifier: '.', + }, + ]); + modelRouter.addImportDeclarations([ + { + namedImports: ['createTRPCRouter'], + moduleSpecifier: options.importCreateRouter as string, + }, + ]); + + modelRouter.addImportDeclarations([ + { + namedImports: ['procedure'], + moduleSpecifier: options.importProcedure as string, + }, + ]); + } + + // zod schema import generateRouterSchemaImport(modelRouter, zodSchemasImport); + + // runtime helpers generateHelperImport(modelRouter); + + // client helper imports if (generateClientHelpers) { - generateRouterTypingImports(modelRouter, options); + generateRouterTypingImports(modelRouter, options, version); } - const createRouterFunc = modelRouter.addFunction({ - name: 'createRouter', - parameters: [ - { name: 'router', type: 'RouterFactory' }, - { name: 'procedure', type: 'ProcBuilder' }, - ], - isExported: true, - isDefaultExport: true, - }); + const createRouterFunc = + version === 'v10' + ? modelRouter.addFunction({ + name: 'createRouter', + parameters: [ + { name: 'router', type: 'RouterFactory' }, + { name: 'procedure', type: 'ProcBuilder' }, + ], + isExported: true, + isDefaultExport: true, + }) + : modelRouter.addFunction({ + name: 'createRouter', + isExported: true, + isDefaultExport: true, + }); let routerTypingStructure: InterfaceDeclarationStructure | undefined = undefined; if (generateClientHelpers) { @@ -294,7 +380,7 @@ function generateModelCreateRouter( } createRouterFunc.setBodyText((funcWriter) => { - funcWriter.write('return router('); + funcWriter.write(`return ${version === 'v10' ? 'router' : 'createTRPCRouter'}(`); funcWriter.block(() => { for (const [opType, opNameWithModel] of Object.entries(operations)) { if (isDelegateModel(dataModel) && (opType.startsWith('create') || opType.startsWith('upsert'))) { @@ -322,7 +408,7 @@ function generateModelCreateRouter( kind: StructureKind.PropertySignature, name: generateOpName, type: (writer) => { - generateRouterTyping(writer, generateOpName, model, baseOpType); + generateRouterTyping(writer, generateOpName, model, baseOpType, version); }, }); } diff --git a/packages/plugins/trpc/src/helpers.ts b/packages/plugins/trpc/src/helpers.ts index c165288f7..ca0ee55fc 100644 --- a/packages/plugins/trpc/src/helpers.ts +++ b/packages/plugins/trpc/src/helpers.ts @@ -184,14 +184,21 @@ function getPrismaOperationTypes(model: string, operation: string) { /** * Generate precise Prisma-like typing for router procedures. */ -export function generateRouterTyping(writer: CodeBlockWriter, opType: string, modelName: string, baseOpType: string) { +export function generateRouterTyping( + writer: CodeBlockWriter, + opType: string, + modelName: string, + baseOpType: string, + version: string +) { const procType = getProcedureTypeByOpName(baseOpType); const { genericBase, argsType, resultType } = getPrismaOperationTypes(modelName, opType); const errorType = `TRPCClientErrorLike`; writer.block(() => { if (procType === 'query') { - writer.writeLine(` + if (version === 'v10') { + writer.writeLine(` useQuery: ( input: ${argsType}, opts?: UseTRPCQueryOptions @@ -206,7 +213,34 @@ export function generateRouterTyping(writer: CodeBlockWriter, opType: string, mo ${resultType}, ${errorType} >; - `); + `); + } else { + writer.writeLine(` + useQuery: ( + input: ${argsType}, + opts?: UseTRPCQueryOptions<${resultType}, TData, Error> + ) => UseTRPCQueryResult< + TData, + ${errorType} + >; + useInfiniteQuery: ( + input: Omit<${argsType}, 'cursor'>, + opts?: UseTRPCInfiniteQueryOptions + ) => UseTRPCInfiniteQueryResult< + ${resultType}, + ${errorType}, + T + >; + useSuspenseQuery: ( + input: ${argsType}, + opts?: UseTRPCSuspenseQueryOptions<${resultType}, TData, Error> + ) => UseTRPCSuspenseQueryResult; + useSuspenseInfiniteQuery: ( + input: Omit<${argsType}, 'cursor'>, + opts?: UseTRPCSuspenseInfiniteQueryOptions + ) => UseTRPCSuspenseInfiniteQueryResult<${resultType}, ${errorType}, T>; + `); + } } else if (procType === 'mutation') { writer.writeLine(` useMutation: (opts?: UseTRPCMutationOptions< @@ -224,15 +258,22 @@ export function generateRouterTyping(writer: CodeBlockWriter, opType: string, mo }); } -export function generateRouterTypingImports(sourceFile: SourceFile, options: PluginOptions) { +export function generateRouterTypingImports(sourceFile: SourceFile, options: PluginOptions, version: string) { const importingDir = sourceFile.getDirectoryPath(); const prismaImport = getPrismaClientImportSpec(importingDir, options); sourceFile.addStatements([ `import type { Prisma } from '${prismaImport}';`, `import type { UseTRPCMutationOptions, UseTRPCMutationResult, UseTRPCQueryOptions, UseTRPCQueryResult, UseTRPCInfiniteQueryOptions, UseTRPCInfiniteQueryResult } from '@trpc/react-query/shared';`, `import type { TRPCClientErrorLike } from '@trpc/client';`, - `import type { AnyRouter } from '@trpc/server';`, ]); + if (version === 'v10') { + sourceFile.addStatements([`import type { AnyRouter } from '@trpc/server';`]); + } else { + sourceFile.addStatements([ + `import type { AnyTRPCRouter as AnyRouter } from '@trpc/server';`, + `import type { UseTRPCSuspenseQueryOptions, UseTRPCSuspenseQueryResult, UseTRPCSuspenseInfiniteQueryOptions, UseTRPCSuspenseInfiniteQueryResult } from '@trpc/react-query/shared';`, + ]); + } } // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/package.json b/packages/plugins/trpc/tests/projects/t3-trpc-v10/package.json index 355df648c..179831693 100644 --- a/packages/plugins/trpc/tests/projects/t3-trpc-v10/package.json +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/package.json @@ -36,7 +36,7 @@ "eslint": "^8.54.0", "eslint-config-next": "^14.0.4", "prisma": "^5.13.0", - "typescript": "^5.1.6" + "typescript": "^5.5.4" }, "ct3aMetadata": { "initVersion": "7.26.0" diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/pages/index.tsx b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/pages/index.tsx index 50a3d3e7d..5d563b369 100644 --- a/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/pages/index.tsx +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/pages/index.tsx @@ -4,19 +4,23 @@ import styles from './index.module.css'; export default function Home() { const hello = api.greet.hello.useQuery({ text: 'from tRPC' }); const posts = api.post.findMany.useQuery({ where: { published: true }, include: { author: true } }); - const postsTransformed = api.post.findMany.useQuery({}, { select: (data) => data.map((p) => ({ title: p.name })) }); + const postsTransformed = api.post.findMany.useQuery( + {}, + { select: (data) => data.map((p) => ({ id: p.id, title: p.name })) } + ); return ( <>
{hello.data &&

{hello.data.greeting}

} - {posts.data && - posts.data.map((post) => ( -

- {post.name} by {post.author.email} -

- ))} - {postsTransformed.data && postsTransformed.data.map((post) =>

{post.title}

)} + {posts.data?.map((post) => ( +

+ {post.name} by {post.author.email} +

+ ))} + {postsTransformed.data?.map((post) => ( +

{post.title}

+ ))}
); diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/.eslintrc.cjs b/packages/plugins/trpc/tests/projects/t3-trpc-v11/.eslintrc.cjs new file mode 100644 index 000000000..a92fb0bc2 --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/.eslintrc.cjs @@ -0,0 +1,42 @@ +/** @type {import("eslint").Linter.Config} */ +const config = { + "parser": "@typescript-eslint/parser", + "parserOptions": { + "project": true + }, + "plugins": [ + "@typescript-eslint" + ], + "extends": [ + "next/core-web-vitals", + "plugin:@typescript-eslint/recommended-type-checked", + "plugin:@typescript-eslint/stylistic-type-checked" + ], + "rules": { + "@typescript-eslint/array-type": "off", + "@typescript-eslint/consistent-type-definitions": "off", + "@typescript-eslint/consistent-type-imports": [ + "warn", + { + "prefer": "type-imports", + "fixStyle": "inline-type-imports" + } + ], + "@typescript-eslint/no-unused-vars": [ + "warn", + { + "argsIgnorePattern": "^_" + } + ], + "@typescript-eslint/require-await": "off", + "@typescript-eslint/no-misused-promises": [ + "error", + { + "checksVoidReturn": { + "attributes": false + } + } + ] + } +} +module.exports = config; \ No newline at end of file diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/.gitignore b/packages/plugins/trpc/tests/projects/t3-trpc-v11/.gitignore new file mode 100644 index 000000000..c24a8359c --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/.gitignore @@ -0,0 +1,46 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# database +/prisma/db.sqlite +/prisma/db.sqlite-journal +db.sqlite + +# next.js +/.next/ +/out/ +next-env.d.ts + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# local env files +# do not commit any .env files to git, except for the .env.example file. https://create.t3.gg/en/usage/env-variables#using-environment-variables +.env +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo + +# idea files +.idea \ No newline at end of file diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/README.md b/packages/plugins/trpc/tests/projects/t3-trpc-v11/README.md new file mode 100644 index 000000000..67943c7fb --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/README.md @@ -0,0 +1,29 @@ +# Create T3 App + +This is a [T3 Stack](https://create.t3.gg/) project bootstrapped with `create-t3-app`. + +## What's next? How do I make an app with this? + +We try to keep this project as simple as possible, so you can start with just the scaffolding we set up for you, and add additional things later when they become necessary. + +If you are not familiar with the different technologies used in this project, please refer to the respective docs. If you still are in the wind, please join our [Discord](https://t3.gg/discord) and ask for help. + +- [Next.js](https://nextjs.org) +- [NextAuth.js](https://next-auth.js.org) +- [Prisma](https://prisma.io) +- [Drizzle](https://orm.drizzle.team) +- [Tailwind CSS](https://tailwindcss.com) +- [tRPC](https://trpc.io) + +## Learn More + +To learn more about the [T3 Stack](https://create.t3.gg/), take a look at the following resources: + +- [Documentation](https://create.t3.gg/) +- [Learn the T3 Stack](https://create.t3.gg/en/faq#what-learning-resources-are-currently-available) — Check out these awesome tutorials + +You can check out the [create-t3-app GitHub repository](https://github.com/t3-oss/create-t3-app) — your feedback and contributions are welcome! + +## How do I deploy this? + +Follow our deployment guides for [Vercel](https://create.t3.gg/en/deployment/vercel), [Netlify](https://create.t3.gg/en/deployment/netlify) and [Docker](https://create.t3.gg/en/deployment/docker) for more information. diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/next.config.js b/packages/plugins/trpc/tests/projects/t3-trpc-v11/next.config.js new file mode 100644 index 000000000..9bfe4a0e2 --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/next.config.js @@ -0,0 +1,10 @@ +/** + * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially useful + * for Docker builds. + */ +await import("./src/env.js"); + +/** @type {import("next").NextConfig} */ +const config = {}; + +export default config; diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/package-lock.json b/packages/plugins/trpc/tests/projects/t3-trpc-v11/package-lock.json new file mode 100644 index 000000000..205d2fb29 --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/package-lock.json @@ -0,0 +1,6001 @@ +{ + "name": "trpc11", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "trpc11", + "version": "0.1.0", + "hasInstallScript": true, + "dependencies": { + "@prisma/client": "^5.14.0", + "@t3-oss/env-nextjs": "^0.10.1", + "@tanstack/react-query": "^5.50.0", + "@trpc/client": "^11.0.0-rc.446", + "@trpc/next": "^11.0.0-rc.446", + "@trpc/react-query": "^11.0.0-rc.446", + "@trpc/server": "^11.0.0-rc.446", + "@zenstackhq/language": "file:../../../../../../.build/zenstackhq-language-2.5.0.tgz", + "@zenstackhq/runtime": "file:../../../../../../.build/zenstackhq-runtime-2.5.0.tgz", + "@zenstackhq/sdk": "file:../../../../../../.build/zenstackhq-sdk-2.5.0.tgz", + "geist": "^1.3.0", + "next": "^14.2.4", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "server-only": "^0.0.1", + "superjson": "^2.2.1", + "zenstack": "file:../../../../../../.build/zenstack-2.5.0.tgz", + "zod": "^3.23.3" + }, + "devDependencies": { + "@types/eslint": "^8.56.10", + "@types/node": "^20.14.10", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@typescript-eslint/eslint-plugin": "^8.1.0", + "@typescript-eslint/parser": "^8.1.0", + "eslint": "^8.57.0", + "eslint-config-next": "^14.2.4", + "prisma": "^5.14.0", + "typescript": "^5.5.3" + } + }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-10.4.2.tgz", + "integrity": "sha512-0+4bNjlndNWMoVLH/+y4uHnf6GrTipsC+YTppJxelVJo+xeRVQ0s2PpkdDCVTsu7efyj+8r1gFiwVXsp6JZ0iQ==", + "dependencies": { + "@chevrotain/gast": "10.4.2", + "@chevrotain/types": "10.4.2", + "lodash": "4.17.21" + } + }, + "node_modules/@chevrotain/gast": { + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-10.4.2.tgz", + "integrity": "sha512-4ZAn8/mjkmYonilSJ60gGj1tAF0cVWYUMlIGA0e4ATAc3a648aCnvpBw7zlPHDQjFp50XC13iyWEgWAKiRKTOA==", + "dependencies": { + "@chevrotain/types": "10.4.2", + "lodash": "4.17.21" + } + }, + "node_modules/@chevrotain/types": { + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-10.4.2.tgz", + "integrity": "sha512-QzSCjg6G4MvIoLeIgOiMR0IgzkGEQqrNJJIr3T5ETRa7l4Av4AMIiEctV99mvDr57iXwwk0/kr3RJxiU36Nevw==" + }, + "node_modules/@chevrotain/utils": { + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-10.4.2.tgz", + "integrity": "sha512-V34dacxWLwKcvcy32dx96ADJVdB7kOJLm7LyBkBQw5u5HC9WdEFw2G17zml+U3ivavGTrGPJHl8o9/UJm0PlUw==" + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@next/env": { + "version": "14.2.5", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.5.tgz", + "integrity": "sha512-/zZGkrTOsraVfYjGP8uM0p6r0BDT6xWpkjdVbcz66PJVSpwXX3yNiRycxAuDfBKGWBrZBXRuK/YVlkNgxHGwmA==" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "14.2.5", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.5.tgz", + "integrity": "sha512-LY3btOpPh+OTIpviNojDpUdIbHW9j0JBYBjsIp8IxtDFfYFyORvw3yNq6N231FVqQA7n7lwaf7xHbVJlA1ED7g==", + "dev": true, + "dependencies": { + "glob": "10.3.10" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "14.2.5", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.5.tgz", + "integrity": "sha512-/9zVxJ+K9lrzSGli1///ujyRfon/ZneeZ+v4ptpiPoOU+GKZnm8Wj8ELWU1Pm7GHltYRBklmXMTUqM/DqQ99FQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.2.5", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.5.tgz", + "integrity": "sha512-vXHOPCwfDe9qLDuq7U1OYM2wUY+KQ4Ex6ozwsKxp26BlJ6XXbHleOUldenM67JRyBfVjv371oneEvYd3H2gNSA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.2.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.5.tgz", + "integrity": "sha512-vlhB8wI+lj8q1ExFW8lbWutA4M2ZazQNvMWuEDqZcuJJc78iUnLdPPunBPX8rC4IgT6lIx/adB+Cwrl99MzNaA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.2.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.5.tgz", + "integrity": "sha512-NpDB9NUR2t0hXzJJwQSGu1IAOYybsfeB+LxpGsXrRIb7QOrYmidJz3shzY8cM6+rO4Aojuef0N/PEaX18pi9OA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "14.2.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.5.tgz", + "integrity": "sha512-8XFikMSxWleYNryWIjiCX+gU201YS+erTUidKdyOVYi5qUQo/gRxv/3N1oZFCgqpesN6FPeqGM72Zve+nReVXQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.2.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.5.tgz", + "integrity": "sha512-6QLwi7RaYiQDcRDSU/os40r5o06b5ue7Jsk5JgdRBGGp8l37RZEh9JsLSM8QF0YDsgcosSeHjglgqi25+m04IQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.2.5", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.5.tgz", + "integrity": "sha512-1GpG2VhbspO+aYoMOQPQiqc/tG3LzmsdBH0LhnDS3JrtDx2QmzXe0B6mSZZiN3Bq7IOMXxv1nlsjzoS1+9mzZw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.2.5", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.5.tgz", + "integrity": "sha512-Igh9ZlxwvCDsu6438FXlQTHlRno4gFpJzqPjSIBZooD22tKeI4fE/YMRoHVJHmrQ2P5YL1DoZ0qaOKkbeFWeMg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "14.2.5", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.5.tgz", + "integrity": "sha512-tEQ7oinq1/CjSG9uSTerca3v4AZ+dFa+4Yu6ihaG8Ud8ddqLQgFGcnwYls13H5X5CPDPZJdYxyeMui6muOLd4g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@paralleldrive/cuid2": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.2.2.tgz", + "integrity": "sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==", + "dependencies": { + "@noble/hashes": "^1.1.5" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@prisma/client": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.18.0.tgz", + "integrity": "sha512-BWivkLh+af1kqC89zCJYkHsRcyWsM8/JHpsDMM76DjP3ZdEquJhXa4IeX+HkWPnwJ5FanxEJFZZDTWiDs/Kvyw==", + "hasInstallScript": true, + "engines": { + "node": ">=16.13" + }, + "peerDependencies": { + "prisma": "*" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + } + } + }, + "node_modules/@prisma/debug": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.18.0.tgz", + "integrity": "sha512-f+ZvpTLidSo3LMJxQPVgAxdAjzv5OpzAo/eF8qZqbwvgi2F5cTOI9XCpdRzJYA0iGfajjwjOKKrVq64vkxEfUw==" + }, + "node_modules/@prisma/engines": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.18.0.tgz", + "integrity": "sha512-ofmpGLeJ2q2P0wa/XaEgTnX/IsLnvSp/gZts0zjgLNdBhfuj2lowOOPmDcfKljLQUXMvAek3lw5T01kHmCG8rg==", + "hasInstallScript": true, + "dependencies": { + "@prisma/debug": "5.18.0", + "@prisma/engines-version": "5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169", + "@prisma/fetch-engine": "5.18.0", + "@prisma/get-platform": "5.18.0" + } + }, + "node_modules/@prisma/engines-version": { + "version": "5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169.tgz", + "integrity": "sha512-a/+LpJj8vYU3nmtkg+N3X51ddbt35yYrRe8wqHTJtYQt7l1f8kjIBcCs6sHJvodW/EK5XGvboOiwm47fmNrbgg==" + }, + "node_modules/@prisma/fetch-engine": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.18.0.tgz", + "integrity": "sha512-I/3u0x2n31rGaAuBRx2YK4eB7R/1zCuayo2DGwSpGyrJWsZesrV7QVw7ND0/Suxeo/vLkJ5OwuBqHoCxvTHpOg==", + "dependencies": { + "@prisma/debug": "5.18.0", + "@prisma/engines-version": "5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169", + "@prisma/get-platform": "5.18.0" + } + }, + "node_modules/@prisma/generator-helper": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@prisma/generator-helper/-/generator-helper-5.18.0.tgz", + "integrity": "sha512-3ffmrd9KE8ssg/fwyvfwMxrDAunLF8DLFjfwYnDRE7VaNIhkUVZwB77jAwpMCtukvCsAp14WGWu4itvLMzH3GQ==", + "dependencies": { + "@prisma/debug": "5.18.0" + } + }, + "node_modules/@prisma/get-platform": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.18.0.tgz", + "integrity": "sha512-Tk+m7+uhqcKDgnMnFN0lRiH7Ewea0OEsZZs9pqXa7i3+7svS3FSCqDBCaM9x5fmhhkufiG0BtunJVDka+46DlA==", + "dependencies": { + "@prisma/debug": "5.18.0" + } + }, + "node_modules/@prisma/internals": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@prisma/internals/-/internals-5.18.0.tgz", + "integrity": "sha512-NYG69q0FxpPHXDtEM2GS5kU22IwgtriCceNH00dWP9dV7oHz23+8QWJMlDsICTR7gnULLCeS2gWBuXWTS1PRmA==", + "dependencies": { + "@prisma/debug": "5.18.0", + "@prisma/engines": "5.18.0", + "@prisma/fetch-engine": "5.18.0", + "@prisma/generator-helper": "5.18.0", + "@prisma/get-platform": "5.18.0", + "@prisma/prisma-schema-wasm": "5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169", + "@prisma/schema-files-loader": "5.18.0", + "arg": "5.0.2", + "prompts": "2.4.2" + } + }, + "node_modules/@prisma/prisma-schema-wasm": { + "version": "5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169", + "resolved": "https://registry.npmjs.org/@prisma/prisma-schema-wasm/-/prisma-schema-wasm-5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169.tgz", + "integrity": "sha512-2h7MDiYVXHVSdz0CylOUktVouPHRKUw5ciXz2r/oZsO2T6Zycez/eSvh4SKiKbHuxDq6SSb3R97mO7bjzh+NVQ==" + }, + "node_modules/@prisma/schema-files-loader": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@prisma/schema-files-loader/-/schema-files-loader-5.18.0.tgz", + "integrity": "sha512-JtjPOZ8odMMr3etCcQ5kDsuljmckuNNCRMJglouPWSyzRbv4nOQJZCD4qPmoMUSoX0gwV7wGgwUw50XsoFYVzA==", + "dependencies": { + "@prisma/prisma-schema-wasm": "5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169", + "fs-extra": "11.1.1" + } + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz", + "integrity": "sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==", + "dev": true + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" + }, + "node_modules/@swc/helpers": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", + "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "dependencies": { + "@swc/counter": "^0.1.3", + "tslib": "^2.4.0" + } + }, + "node_modules/@t3-oss/env-core": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@t3-oss/env-core/-/env-core-0.10.1.tgz", + "integrity": "sha512-GcKZiCfWks5CTxhezn9k5zWX3sMDIYf6Kaxy2Gx9YEQftFcz8hDRN56hcbylyAO3t4jQnQ5ifLawINsNgCDpOg==", + "peerDependencies": { + "typescript": ">=5.0.0", + "zod": "^3.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@t3-oss/env-nextjs": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@t3-oss/env-nextjs/-/env-nextjs-0.10.1.tgz", + "integrity": "sha512-iy2qqJLnFh1RjEWno2ZeyTu0ufomkXruUsOZludzDIroUabVvHsrSjtkHqwHp1/pgPUzN3yBRHMILW162X7x2Q==", + "dependencies": { + "@t3-oss/env-core": "0.10.1" + }, + "peerDependencies": { + "typescript": ">=5.0.0", + "zod": "^3.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@tanstack/query-core": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.52.0.tgz", + "integrity": "sha512-U1DOEgltjUwalN6uWYTewSnA14b+tE7lSylOiASKCAO61ENJeCq9VVD/TXHA6O5u9+6v5+UgGYBSccTKDoyMqw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.52.0.tgz", + "integrity": "sha512-T8tLZdPEopSD3A1EBZ/sq7WkI76pKLKKiT82F486K8wf26EPgYCdeiSnJfuayssdQjWwLQMQVl/ROUBNmlWgCQ==", + "dependencies": { + "@tanstack/query-core": "5.52.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, + "node_modules/@trpc/client": { + "version": "11.0.0-rc.485", + "resolved": "https://registry.npmjs.org/@trpc/client/-/client-11.0.0-rc.485.tgz", + "integrity": "sha512-Ld1gQjdYyrku0rjP/4QMg/SdsKgujr0P5XNoWkCyPRjdw3PuJbZFebauQPRC17cbbqGcpJrR+T3vnkhjMb1sgw==", + "funding": [ + "https://trpc.io/sponsor" + ], + "peerDependencies": { + "@trpc/server": "11.0.0-rc.485+1c1d824cd" + } + }, + "node_modules/@trpc/next": { + "version": "11.0.0-rc.485", + "resolved": "https://registry.npmjs.org/@trpc/next/-/next-11.0.0-rc.485.tgz", + "integrity": "sha512-LBj9KjHwiqjGEPEeDyYE5clgtDC3Qyoyq1Q0aaW9lpBtx6lG9tdCcvFowQ5Ai+zTpRpdIXjeWDT7q1ZXzTHYgQ==", + "funding": [ + "https://trpc.io/sponsor" + ], + "peerDependencies": { + "@tanstack/react-query": "^5.49.2", + "@trpc/client": "11.0.0-rc.485+1c1d824cd", + "@trpc/react-query": "11.0.0-rc.485+1c1d824cd", + "@trpc/server": "11.0.0-rc.485+1c1d824cd", + "next": "*", + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@tanstack/react-query": { + "optional": true + }, + "@trpc/react-query": { + "optional": true + } + } + }, + "node_modules/@trpc/react-query": { + "version": "11.0.0-rc.485", + "resolved": "https://registry.npmjs.org/@trpc/react-query/-/react-query-11.0.0-rc.485.tgz", + "integrity": "sha512-gFlJu9CXysfgsrVdKHFeROB8jsI50NjCQRrRimx5Tv4z3qSyT9IOVx+tyMhISDaj2haUPL1pFWhGMUiJGwo+Gg==", + "funding": [ + "https://trpc.io/sponsor" + ], + "peerDependencies": { + "@tanstack/react-query": "^5.49.2", + "@trpc/client": "11.0.0-rc.485+1c1d824cd", + "@trpc/server": "11.0.0-rc.485+1c1d824cd", + "react": ">=18.2.0", + "react-dom": ">=18.2.0" + } + }, + "node_modules/@trpc/server": { + "version": "11.0.0-rc.485", + "resolved": "https://registry.npmjs.org/@trpc/server/-/server-11.0.0-rc.485.tgz", + "integrity": "sha512-U9SK9jbqCjR8S9wGSe4UBu2e0fqxhQWriZiDb5BLzdxXzls4Jv+XhAkI65yBzlcTbt6VqXegZDAXB3IARPhUCg==", + "funding": [ + "https://trpc.io/sponsor" + ] + }, + "node_modules/@ts-morph/common": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.17.0.tgz", + "integrity": "sha512-RMSSvSfs9kb0VzkvQ2NWobwnj7TxCA9vI/IjR9bDHqgAyVbu2T0DN4wiKVqomyDWqO7dPr/tErSfq7urQ1Q37g==", + "dependencies": { + "fast-glob": "^3.2.11", + "minimatch": "^5.1.0", + "mkdirp": "^1.0.4", + "path-browserify": "^1.0.1" + } + }, + "node_modules/@ts-morph/common/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@types/eslint": { + "version": "8.56.11", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.11.tgz", + "integrity": "sha512-sVBpJMf7UPo/wGecYOpk2aQya2VUGeHhe38WG7/mN5FufNSubf5VT9Uh9Uyp8/eLJpu1/tuhJ/qTo4mhSB4V4Q==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.16.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.1.tgz", + "integrity": "sha512-zJDo7wEadFtSyNz5QITDfRcrhqDvQI1xQNQ0VoizPjM/dVAODqqIUWbJPkvsxmTI0MYRGRikcdjMPhOssnPejQ==", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "dev": true + }, + "node_modules/@types/react": { + "version": "18.3.4", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.4.tgz", + "integrity": "sha512-J7W30FTdfCxDDjmfRM+/JqLHBIyl7xUIp9kwK637FGmY7+mkSFSe6L4jpZzhj5QMfLssSDP4/i75AKkrdC7/Jw==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.2.0.tgz", + "integrity": "sha512-02tJIs655em7fvt9gps/+4k4OsKULYGtLBPJfOsmOq1+3cdClYiF0+d6mHu6qDnTcg88wJBkcPLpQhq7FyDz0A==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.2.0", + "@typescript-eslint/type-utils": "8.2.0", + "@typescript-eslint/utils": "8.2.0", + "@typescript-eslint/visitor-keys": "8.2.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.2.0.tgz", + "integrity": "sha512-j3Di+o0lHgPrb7FxL3fdEy6LJ/j2NE8u+AP/5cQ9SKb+JLH6V6UHDqJ+e0hXBkHP1wn1YDFjYCS9LBQsZDlDEg==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "8.2.0", + "@typescript-eslint/types": "8.2.0", + "@typescript-eslint/typescript-estree": "8.2.0", + "@typescript-eslint/visitor-keys": "8.2.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.2.0.tgz", + "integrity": "sha512-OFn80B38yD6WwpoHU2Tz/fTz7CgFqInllBoC3WP+/jLbTb4gGPTy9HBSTsbDWkMdN55XlVU0mMDYAtgvlUspGw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.2.0", + "@typescript-eslint/visitor-keys": "8.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.2.0.tgz", + "integrity": "sha512-g1CfXGFMQdT5S+0PSO0fvGXUaiSkl73U1n9LTK5aRAFnPlJ8dLKkXr4AaLFvPedW8lVDoMgLLE3JN98ZZfsj0w==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "8.2.0", + "@typescript-eslint/utils": "8.2.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.2.0.tgz", + "integrity": "sha512-6a9QSK396YqmiBKPkJtxsgZZZVjYQ6wQ/TlI0C65z7vInaETuC6HAHD98AGLC8DyIPqHytvNuS8bBVvNLKyqvQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.2.0.tgz", + "integrity": "sha512-kiG4EDUT4dImplOsbh47B1QnNmXSoUqOjWDvCJw/o8LgfD0yr7k2uy54D5Wm0j4t71Ge1NkynGhpWdS0dEIAUA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.2.0", + "@typescript-eslint/visitor-keys": "8.2.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.2.0.tgz", + "integrity": "sha512-O46eaYKDlV3TvAVDNcoDzd5N550ckSe8G4phko++OCSC1dYIb9LTc3HDGYdWqWIAT5qDUKphO6sd9RrpIJJPfg==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.2.0", + "@typescript-eslint/types": "8.2.0", + "@typescript-eslint/typescript-estree": "8.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.2.0.tgz", + "integrity": "sha512-sbgsPMW9yLvS7IhCi8IpuK1oBmtbWUNP+hBdwl/I9nzqVsszGnNGti5r9dUtF5RLivHUFFIdRvLiTsPhzSyJ3Q==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.2.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/@zenstackhq/language": { + "version": "2.5.0", + "resolved": "file:../../../../../../.build/zenstackhq-language-2.5.0.tgz", + "integrity": "sha512-Et9VBPz2U7Cx0SBmypK7Wks8BvxasYw0bNdKv6aNEm1QtNecYPM7PeinDEeFzfaD2gC1G4nzzEX5REhkF1n/KQ==", + "license": "MIT", + "dependencies": { + "langium": "1.3.1" + } + }, + "node_modules/@zenstackhq/runtime": { + "version": "2.5.0", + "resolved": "file:../../../../../../.build/zenstackhq-runtime-2.5.0.tgz", + "integrity": "sha512-bgR9sQQ/DysANEp/HyU6QJMs53IV2HAwfYesmzesC/PkP9+H3g4Kue5I7N6xdRzlG2ua4zwL8RR1ctk8J4/5pA==", + "license": "MIT", + "dependencies": { + "bcryptjs": "^2.4.3", + "buffer": "^6.0.3", + "change-case": "^4.1.2", + "decimal.js": "^10.4.2", + "deepmerge": "^4.3.1", + "is-plain-object": "^5.0.0", + "logic-solver": "^2.0.1", + "lower-case-first": "^2.0.2", + "pluralize": "^8.0.0", + "safe-json-stringify": "^1.2.0", + "semver": "^7.5.2", + "superjson": "^1.13.0", + "tiny-invariant": "^1.3.1", + "ts-pattern": "^4.3.0", + "tslib": "^2.4.1", + "upper-case-first": "^2.0.2", + "uuid": "^9.0.0", + "zod": "^3.22.4", + "zod-validation-error": "^1.5.0" + }, + "peerDependencies": { + "@prisma/client": "5.0.0 - 5.18.x" + } + }, + "node_modules/@zenstackhq/runtime/node_modules/superjson": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/superjson/-/superjson-1.13.3.tgz", + "integrity": "sha512-mJiVjfd2vokfDxsQPOwJ/PtanO87LhpYY88ubI5dUB1Ab58Txbyje3+jpm+/83R/fevaq/107NNhtYBLuoTrFg==", + "dependencies": { + "copy-anything": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@zenstackhq/sdk": { + "version": "2.5.0", + "resolved": "file:../../../../../../.build/zenstackhq-sdk-2.5.0.tgz", + "integrity": "sha512-8Jkt+MmWaLkt1FpZXw+SryYKjbquRhQNU5HiwvFBZuaoVM+7EJqFmONRW+Zek+ivNIF3MqNBE7Dt1Ha34wrj5Q==", + "license": "MIT", + "dependencies": { + "@prisma/generator-helper": "5.18.x", + "@prisma/internals": "5.18.x", + "@zenstackhq/language": "2.5.0", + "@zenstackhq/runtime": "2.5.0", + "langium": "1.3.1", + "lower-case-first": "^2.0.2", + "semver": "^7.5.2", + "ts-morph": "^16.0.0", + "ts-pattern": "^4.3.0", + "upper-case-first": "^2.0.2" + } + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true + }, + "node_modules/async-exit-hook": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", + "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.0.tgz", + "integrity": "sha512-Mr2ZakwQ7XUAjp7pAwQWRhhK8mQQ6JAaNWSjmjxil0R8BPioMtQsTLOolGYkji1rcL++3dCqZA3zWqpT+9Ew6g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001651", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001651.tgz", + "integrity": "sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/capital-case": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", + "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case-first": "^2.0.2" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/change-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", + "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==", + "dependencies": { + "camel-case": "^4.1.2", + "capital-case": "^1.0.4", + "constant-case": "^3.0.4", + "dot-case": "^3.0.4", + "header-case": "^2.0.4", + "no-case": "^3.0.4", + "param-case": "^3.0.4", + "pascal-case": "^3.1.2", + "path-case": "^3.0.4", + "sentence-case": "^3.0.4", + "snake-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/chevrotain": { + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-10.4.2.tgz", + "integrity": "sha512-gzF5GxE0Ckti5kZVuKEZycLntB5X2aj9RVY0r4/220GwQjdnljU+/t3kP74/FMWC7IzCDDEjQ9wsFUf0WCdSHg==", + "dependencies": { + "@chevrotain/cst-dts-gen": "10.4.2", + "@chevrotain/gast": "10.4.2", + "@chevrotain/types": "10.4.2", + "@chevrotain/utils": "10.4.2", + "lodash": "4.17.21", + "regexp-to-ast": "0.5.0" + } + }, + "node_modules/chevrotain-allstar": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/chevrotain-allstar/-/chevrotain-allstar-0.1.7.tgz", + "integrity": "sha512-oMSHkXVCDQxnj3tDCqcEoMnNIEiYlAYT0FVja1PaLrT3njXGvg5JXTXs/tk2NI42SR3LMJyqTNgjR4VyDIf19w==", + "dependencies": { + "lodash": "^4.17.21" + }, + "peerDependencies": { + "chevrotain": "~10.4.1" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/code-block-writer": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-11.0.3.tgz", + "integrity": "sha512-NiujjUFB4SwScJq2bwbYUtXbZhBSlY6vYzm++3Q6oC+U+injTqfPYFK8wS9COOmb2lueqp0ZRB4nK1VYeHgNyw==" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/constant-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", + "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case": "^2.0.2" + } + }, + "node_modules/copy-anything": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", + "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==", + "dependencies": { + "is-what": "^4.1.8" + }, + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" + }, + "node_modules/deep-equal": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/emphasize": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/emphasize/-/emphasize-4.2.0.tgz", + "integrity": "sha512-yGKvcFUHlBsUPwlxTlzKLR8+zhpbitkFOMCUxN8fTJng9bdH3WNzUGkhdaGdjndSUgqmMPBN7umfwnUdLz5Axg==", + "dependencies": { + "chalk": "^4.0.0", + "highlight.js": "~10.4.0", + "lowlight": "~1.17.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", + "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-next": { + "version": "14.2.5", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.2.5.tgz", + "integrity": "sha512-zogs9zlOiZ7ka+wgUnmcM0KBEDjo4Jis7kxN1jvC0N4wynQ2MIx/KBkg4mVF63J5EK4W0QMCn7xO3vNisjaAoA==", + "dev": true, + "dependencies": { + "@next/eslint-plugin-next": "14.2.5", + "@rushstack/eslint-patch": "^1.3.3", + "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || 7.0.0 - 7.2.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" + }, + "peerDependencies": { + "eslint": "^7.23.0 || ^8.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-config-next/node_modules/@typescript-eslint/parser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.2.0.tgz", + "integrity": "sha512-5FKsVcHTk6TafQKQbuIVkXq58Fnbkd2wDL4LB7AURN7RUOu1utVP+G8+6u3ZhEroW3DF6hyo3ZEXxgKgp4KeCg==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "7.2.0", + "@typescript-eslint/types": "7.2.0", + "@typescript-eslint/typescript-estree": "7.2.0", + "@typescript-eslint/visitor-keys": "7.2.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-config-next/node_modules/@typescript-eslint/scope-manager": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.2.0.tgz", + "integrity": "sha512-Qh976RbQM/fYtjx9hs4XkayYujB/aPwglw2choHmf3zBjB4qOywWSdt9+KLRdHubGcoSwBnXUH2sR3hkyaERRg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.2.0", + "@typescript-eslint/visitor-keys": "7.2.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-config-next/node_modules/@typescript-eslint/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.2.0.tgz", + "integrity": "sha512-XFtUHPI/abFhm4cbCDc5Ykc8npOKBSJePY3a3s+lwumt7XWJuzP5cZcfZ610MIPHjQjNsOLlYK8ASPaNG8UiyA==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-config-next/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.2.0.tgz", + "integrity": "sha512-cyxS5WQQCoBwSakpMrvMXuMDEbhOo9bNHHrNcEWis6XHx6KF518tkF1wBvKIn/tpq5ZpUYK7Bdklu8qY0MsFIA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.2.0", + "@typescript-eslint/visitor-keys": "7.2.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-config-next/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.2.0.tgz", + "integrity": "sha512-c6EIQRHhcpl6+tO8EMR+kjkkV+ugUNXOmeASA1rlzkd8EPIriavpWoiEz1HR/VLhbVIdhqnV6E7JZm00cBDx2A==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.2.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-config-next/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", + "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "fast-glob": "^3.3.1", + "get-tsconfig": "^4.5.0", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz", + "integrity": "sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g==", + "dev": true, + "dependencies": { + "aria-query": "~5.1.3", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.9.1", + "axobject-query": "~3.1.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "es-iterator-helpers": "^1.0.19", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.0" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.35.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz", + "integrity": "sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.19", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fault": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz", + "integrity": "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==", + "dependencies": { + "format": "^0.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/format": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", + "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/fs-extra": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/geist": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/geist/-/geist-1.3.1.tgz", + "integrity": "sha512-Q4gC1pBVPN+D579pBaz0TRRnGA4p9UK6elDY/xizXdFk/g4EKR5g0I+4p/Kj6gM0SajDBZ/0FvDV9ey9ud7BWw==", + "peerDependencies": { + "next": ">=13.2.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.6.tgz", + "integrity": "sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/header-case": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz", + "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==", + "dependencies": { + "capital-case": "^1.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/highlight.js": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.4.1.tgz", + "integrity": "sha512-yR5lWvNz7c85OhVAEAeFhVCc/GV4C30Fjzc/rCP0aCWzc1UUOPUk55dK/qdwTZHBvMZo+eZ2jpk62ndX/xMFlg==", + "engines": { + "node": "*" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-what": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz", + "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==", + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/iterator.prototype": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", + "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + } + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "engines": { + "node": ">=6" + } + }, + "node_modules/langium": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/langium/-/langium-1.3.1.tgz", + "integrity": "sha512-xC+DnAunl6cZIgYjRpgm3s1kYAB5/Wycsj24iYaXG9uai7SgvMaFZSrRvdA5rUK/lSta/CRvgF+ZFoEKEOFJ5w==", + "dependencies": { + "chevrotain": "~10.4.2", + "chevrotain-allstar": "~0.1.4", + "vscode-languageserver": "~8.0.2", + "vscode-languageserver-textdocument": "~1.0.8", + "vscode-uri": "~3.0.7" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/logic-solver": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/logic-solver/-/logic-solver-2.0.1.tgz", + "integrity": "sha512-F1oCywXUzvAF4Z98mMyXySUCpUU3hNyc+JfYV3g2x/4BupC/xv94iPJuHh9us2XX5UrvY5lnKUXNvjcJNQBJ/g==", + "dependencies": { + "underscore": "^1.7.0" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lower-case-first": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case-first/-/lower-case-first-2.0.2.tgz", + "integrity": "sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lowlight": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.17.0.tgz", + "integrity": "sha512-vmtBgYKD+QVNy7tIa7ulz5d//Il9R4MooOVh4nkOf9R9Cb/Dk5TXMSTieg/vDulkBkIWj59/BIlyFQxT9X1oAQ==", + "dependencies": { + "fault": "^1.0.0", + "highlight.js": "~10.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mixpanel": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/mixpanel/-/mixpanel-0.17.0.tgz", + "integrity": "sha512-DY5WeOy/hmkPrNiiZugJpWR0iMuOwuj1a3u0bgwB2eUFRV6oIew/pIahhpawdbNjb+Bye4a8ID3gefeNPvL81g==", + "dependencies": { + "https-proxy-agent": "5.0.0" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/next": { + "version": "14.2.5", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.5.tgz", + "integrity": "sha512-0f8aRfBVL+mpzfBjYfQuLWh2WyAwtJXCRfkPF4UJ5qd2YwrHczsrSzXU4tRMV0OAxR8ZJZWPFn6uhSC56UTsLA==", + "dependencies": { + "@next/env": "14.2.5", + "@swc/helpers": "0.5.5", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001579", + "graceful-fs": "^4.2.11", + "postcss": "8.4.31", + "styled-jsx": "5.1.1" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=18.17.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "14.2.5", + "@next/swc-darwin-x64": "14.2.5", + "@next/swc-linux-arm64-gnu": "14.2.5", + "@next/swc-linux-arm64-musl": "14.2.5", + "@next/swc-linux-x64-gnu": "14.2.5", + "@next/swc-linux-x64-musl": "14.2.5", + "@next/swc-win32-arm64-msvc": "14.2.5", + "@next/swc-win32-ia32-msvc": "14.2.5", + "@next/swc-win32-x64-msvc": "14.2.5" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.41.2", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" + }, + "node_modules/path-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", + "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/pretty-repl": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pretty-repl/-/pretty-repl-4.0.1.tgz", + "integrity": "sha512-Ve+ZNS5fwxylks3TTR4su7SaNAHVOh++7J5R8VKFAHIjmAMS8X79rnETc/JJoqay52cfgeHum7vm2+9hFSys9Q==", + "dependencies": { + "ansi-regex": "^5.0.1", + "chalk": "^4.1.1", + "emphasize": "^4.2.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/prisma": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.18.0.tgz", + "integrity": "sha512-+TrSIxZsh64OPOmaSgVPH7ALL9dfU0jceYaMJXsNrTkFHO7/3RANi5K2ZiPB1De9+KDxCWn7jvRq8y8pvk+o9g==", + "hasInstallScript": true, + "dependencies": { + "@prisma/engines": "5.18.0" + }, + "bin": { + "prisma": "build/index.js" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp-to-ast": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz", + "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-json-stringify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz", + "integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==" + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sentence-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", + "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case-first": "^2.0.2" + } + }, + "node_modules/server-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz", + "integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/sleep-promise": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/sleep-promise/-/sleep-promise-9.1.0.tgz", + "integrity": "sha512-UHYzVpz9Xn8b+jikYSD6bqvf754xL2uBUzDFwiU6NcdZeifPr6UfgU43xpkPu67VMS88+TI2PSI7Eohgqf2fKA==" + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dev": true, + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/string.prototype.includes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.0.tgz", + "integrity": "sha512-E34CkBgyeqNDcrbU76cDjL5JLcVrtSdYq0MEh/B10r17pRP4ciHLwTgnuLV8Ay6cgEMLkcBkFCKyFZ43YldYzg==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-color": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/strip-color/-/strip-color-0.1.0.tgz", + "integrity": "sha512-p9LsUieSjWNNAxVCXLeilaDlmuUOrDS5/dF9znM1nZc7EGX5+zEFC0bEevsNIaldjlks+2jns5Siz6F9iK6jwA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/superjson": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.1.tgz", + "integrity": "sha512-8iGv75BYOa0xRJHK5vRLEjE2H/i4lulTjzpUXic3Eg8akftYjkmQDa8JARQ42rlczXyFR3IeRoeFCc7RxHsYZA==", + "dependencies": { + "copy-anything": "^3.0.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-morph": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-16.0.0.tgz", + "integrity": "sha512-jGNF0GVpFj0orFw55LTsQxVYEUOCWBAbR5Ls7fTYE5pQsbW18ssTb/6UXx/GYAEjS+DQTp8VoTw0vqYMiaaQuw==", + "dependencies": { + "@ts-morph/common": "~0.17.0", + "code-block-writer": "^11.0.3" + } + }, + "node_modules/ts-pattern": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ts-pattern/-/ts-pattern-4.3.0.tgz", + "integrity": "sha512-pefrkcd4lmIVR0LA49Imjf9DYLK8vtWhqBPA3Ya1ir8xCW0O2yjL9dsCVvI7pCodLC5q7smNpEtDR2yVulQxOg==" + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "devOptional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/underscore": { + "version": "1.13.7", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", + "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==" + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/upper-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", + "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/upper-case-first": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", + "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/vscode-jsonrpc": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.2.tgz", + "integrity": "sha512-RY7HwI/ydoC1Wwg4gJ3y6LpU9FJRZAUnTYMXthqhFXXu77ErDd/xkREpGuk4MyYkk4a+XDWAMqe0S3KkelYQEQ==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageclient": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-8.1.0.tgz", + "integrity": "sha512-GL4QdbYUF/XxQlAsvYWZRV3V34kOkpRlvV60/72ghHfsYFnS/v2MANZ9P6sHmxFcZKOse8O+L9G7Czg0NUWing==", + "dependencies": { + "minimatch": "^5.1.0", + "semver": "^7.3.7", + "vscode-languageserver-protocol": "3.17.3" + }, + "engines": { + "vscode": "^1.67.0" + } + }, + "node_modules/vscode-languageclient/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/vscode-languageclient/node_modules/vscode-jsonrpc": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.1.0.tgz", + "integrity": "sha512-6TDy/abTQk+zDGYazgbIPc+4JoXdwC8NHU9Pbn4UJP1fehUyZmM4RHp5IthX7A6L5KS30PRui+j+tbbMMMafdw==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageclient/node_modules/vscode-languageserver-protocol": { + "version": "3.17.3", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.3.tgz", + "integrity": "sha512-924/h0AqsMtA5yK22GgMtCYiMdCOtWTSGgUOkgEDX+wk2b0x4sAfLiO4NxBxqbiVtz7K7/1/RgVrVI0NClZwqA==", + "dependencies": { + "vscode-jsonrpc": "8.1.0", + "vscode-languageserver-types": "3.17.3" + } + }, + "node_modules/vscode-languageclient/node_modules/vscode-languageserver-types": { + "version": "3.17.3", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.3.tgz", + "integrity": "sha512-SYU4z1dL0PyIMd4Vj8YOqFvHu7Hz/enbWtpfnVbJHU4Nd1YNYx8u0ennumc6h48GQNeOLxmwySmnADouT/AuZA==" + }, + "node_modules/vscode-languageserver": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-8.0.2.tgz", + "integrity": "sha512-bpEt2ggPxKzsAOZlXmCJ50bV7VrxwCS5BI4+egUmure/oI/t4OlFzi/YNtVvY24A2UDOZAgwFGgnZPwqSJubkA==", + "dependencies": { + "vscode-languageserver-protocol": "3.17.2" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.2.tgz", + "integrity": "sha512-8kYisQ3z/SQ2kyjlNeQxbkkTNmVFoQCqkmGrzLH6A9ecPlgTbp3wDTnUNqaUxYr4vlAcloxx8zwy7G5WdguYNg==", + "dependencies": { + "vscode-jsonrpc": "8.0.2", + "vscode-languageserver-types": "3.17.2" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.2.tgz", + "integrity": "sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA==" + }, + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==" + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", + "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", + "dev": true, + "dependencies": { + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zenstack": { + "version": "2.5.0", + "resolved": "file:../../../../../../.build/zenstack-2.5.0.tgz", + "integrity": "sha512-Zs+0T2j4ZLiqxD6PgYqhigvN62S0Ag6exMmw2x+NGhZJvjxmy/JuMgMvKAQXz8GFYU6MUCjXi4KaBXzuAg2SXQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@paralleldrive/cuid2": "^2.2.0", + "@types/node": "^20.12.7", + "@zenstackhq/language": "2.5.0", + "@zenstackhq/sdk": "2.5.0", + "async-exit-hook": "^2.0.1", + "change-case": "^4.1.2", + "colors": "1.4.0", + "commander": "^8.3.0", + "deepmerge": "^4.3.1", + "langium": "1.3.1", + "lower-case-first": "^2.0.2", + "mixpanel": "^0.17.0", + "ora": "^5.4.1", + "pluralize": "^8.0.0", + "pretty-repl": "^4.0.0", + "semver": "^7.5.2", + "sleep-promise": "^9.1.0", + "strip-color": "^0.1.0", + "tiny-invariant": "^1.3.1", + "ts-morph": "^16.0.0", + "ts-pattern": "^4.3.0", + "upper-case-first": "^2.0.2", + "uuid": "^9.0.0", + "vscode-jsonrpc": "^8.0.2", + "vscode-languageclient": "^8.0.2", + "vscode-languageserver": "^8.0.2", + "vscode-languageserver-textdocument": "^1.0.7", + "vscode-uri": "^3.0.6", + "zod": "^3.22.4", + "zod-validation-error": "^1.5.0" + }, + "bin": { + "zenstack": "bin/cli" + }, + "engines": { + "vscode": "^1.63.0" + }, + "peerDependencies": { + "prisma": "5.0.0 - 5.18.x" + } + }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-validation-error": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-1.5.0.tgz", + "integrity": "sha512-/7eFkAI4qV0tcxMBB/3+d2c1P6jzzZYdYSlBuAklzMuCrJu5bzJfHS0yVAS87dRHVlhftd6RFJDIvv03JgkSbw==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "zod": "^3.18.0" + } + } + } +} diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/package.json b/packages/plugins/trpc/tests/projects/t3-trpc-v11/package.json new file mode 100644 index 000000000..4f346d96b --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/package.json @@ -0,0 +1,49 @@ +{ + "name": "trpc11", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "build": "next build", + "db:generate": "prisma migrate dev", + "db:migrate": "prisma migrate deploy", + "db:push": "prisma db push", + "db:studio": "prisma studio", + "dev": "next dev", + "postinstall": "prisma generate", + "lint": "next lint", + "start": "next start" + }, + "dependencies": { + "@prisma/client": "^5.14.0", + "@t3-oss/env-nextjs": "^0.10.1", + "@tanstack/react-query": "^5.50.0", + "@trpc/client": "^11.0.0-rc.446", + "@trpc/next": "^11.0.0-rc.446", + "@trpc/react-query": "^11.0.0-rc.446", + "@trpc/server": "^11.0.0-rc.446", + "geist": "^1.3.0", + "next": "^14.2.4", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "server-only": "^0.0.1", + "superjson": "^2.2.1", + "zod": "^3.23.3" + }, + "devDependencies": { + "@types/eslint": "^8.56.10", + "@types/node": "^20.14.10", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@typescript-eslint/eslint-plugin": "^8.1.0", + "@typescript-eslint/parser": "^8.1.0", + "eslint": "^8.57.0", + "eslint-config-next": "^14.2.4", + "prisma": "^5.14.0", + "typescript": "^5.5.3" + }, + "ct3aMetadata": { + "initVersion": "7.37.0" + }, + "packageManager": "npm@10.2.3" +} diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/prisma/schema.prisma b/packages/plugins/trpc/tests/projects/t3-trpc-v11/prisma/schema.prisma new file mode 100644 index 000000000..5199cfaa7 --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/prisma/schema.prisma @@ -0,0 +1,33 @@ +////////////////////////////////////////////////////////////////////////////////////////////// +// DO NOT MODIFY THIS FILE // +// This file is automatically generated by ZenStack CLI and should not be manually updated. // +////////////////////////////////////////////////////////////////////////////////////////////// + +datasource db { + provider = "sqlite" + url = "file:./dev.db" +} + +generator client { + provider = "prisma-client-js" +} + +/// @@allow('all', true) +model User { + id Int @id() @default(autoincrement()) + email String @unique() + posts Post[] +} + +/// @@allow('all', true) +model Post { + id Int @id() @default(autoincrement()) + name String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt() + published Boolean @default(false) + author User @relation(fields: [authorId], references: [id]) + authorId Int + + @@index([name]) +} diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/public/favicon.ico b/packages/plugins/trpc/tests/projects/t3-trpc-v11/public/favicon.ico new file mode 100644 index 000000000..60c702aac Binary files /dev/null and b/packages/plugins/trpc/tests/projects/t3-trpc-v11/public/favicon.ico differ diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/schema.zmodel b/packages/plugins/trpc/tests/projects/t3-trpc-v11/schema.zmodel new file mode 100644 index 000000000..fd6a8118a --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/schema.zmodel @@ -0,0 +1,41 @@ +// This is your Prisma schema file, +// learn more about it in the docs: https://pris.ly/d/prisma-schema + +generator client { + provider = "prisma-client-js" +} + +datasource db { + provider = "sqlite" + url = "file:./dev.db" +} + +plugin trpc { + provider = "../../../dist" + output = "src/server/api/routers/generated" + version = "v11" + importCreateRouter = "../../generated-router-helper" + importProcedure = "../../generated-router-helper" + generateClientHelpers = "react" +} + +model User { + id Int @id @default(autoincrement()) + email String @unique + posts Post[] + + @@allow('all', true) +} + +model Post { + id Int @id @default(autoincrement()) + name String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + published Boolean @default(false) + author User @relation(fields: [authorId], references: [id]) + authorId Int + + @@index([name]) + @@allow('all', true) +} diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/app/_components/post.tsx b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/app/_components/post.tsx new file mode 100644 index 000000000..6acb6600c --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/app/_components/post.tsx @@ -0,0 +1,78 @@ +'use client'; + +import { useState } from 'react'; + +import { api } from '~/trpc/react'; +import styles from '../index.module.css'; + +export function LatestPost() { + const { data: latestPost } = api.post.findFirst.useQuery( + { + orderBy: { createdAt: 'desc' }, + include: { author: true }, + }, + { staleTime: 1000 * 60 } + ); + + const [latestPost1] = api.post.findFirst.useSuspenseQuery( + { + orderBy: { createdAt: 'desc' }, + include: { author: true }, + }, + { staleTime: 1000 * 60 } + ); + console.log(latestPost1.author.email); + + api.post.findMany.useInfiniteQuery( + { + take: 10, + orderBy: { createdAt: 'desc' }, + include: { author: true }, + }, + { + getNextPageParam: (lastPage) => ({ + id: lastPage?.[lastPage.length - 1]?.id, + }), + } + ); + + const utils = api.useUtils(); + const [name, setName] = useState(''); + const createPost = api.post.create.useMutation({ + onSuccess: async () => { + await utils.post.invalidate(); + setName(''); + }, + }); + + return ( +
+ {latestPost ? ( +

+ Your most recent post: {latestPost.name} by {latestPost.author.email} +

+ ) : ( +

You have no posts yet.

+ )} + +
{ + e.preventDefault(); + createPost.mutate({ data: { name, author: { connect: { id: 1 } } } }); + }} + className={styles.form} + > + setName(e.target.value)} + className={styles.input} + /> + +
+
+ ); +} diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/app/api/trpc/[trpc]/route.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/app/api/trpc/[trpc]/route.ts new file mode 100644 index 000000000..5fbd827d9 --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/app/api/trpc/[trpc]/route.ts @@ -0,0 +1,34 @@ +import { fetchRequestHandler } from "@trpc/server/adapters/fetch"; +import { type NextRequest } from "next/server"; + +import { env } from "~/env"; +import { appRouter } from "~/server/api/root"; +import { createTRPCContext } from "~/server/api/trpc"; + +/** + * This wraps the `createTRPCContext` helper and provides the required context for the tRPC API when + * handling a HTTP request (e.g. when you make requests from Client Components). + */ +const createContext = async (req: NextRequest) => { + return createTRPCContext({ + headers: req.headers, + }); +}; + +const handler = (req: NextRequest) => + fetchRequestHandler({ + endpoint: "/api/trpc", + req, + router: appRouter, + createContext: () => createContext(req), + onError: + env.NODE_ENV === "development" + ? ({ path, error }) => { + console.error( + `❌ tRPC failed on ${path ?? ""}: ${error.message}` + ); + } + : undefined, + }); + +export { handler as GET, handler as POST }; diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/app/index.module.css b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/app/index.module.css new file mode 100644 index 000000000..fac9982a3 --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/app/index.module.css @@ -0,0 +1,177 @@ +.main { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + min-height: 100vh; + background-image: linear-gradient(to bottom, #2e026d, #15162c); +} + +.container { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 3rem; + padding: 4rem 1rem; +} + +@media (min-width: 640px) { + .container { + max-width: 640px; + } +} + +@media (min-width: 768px) { + .container { + max-width: 768px; + } +} + +@media (min-width: 1024px) { + .container { + max-width: 1024px; + } +} + +@media (min-width: 1280px) { + .container { + max-width: 1280px; + } +} + +@media (min-width: 1536px) { + .container { + max-width: 1536px; + } +} + +.title { + font-size: 3rem; + line-height: 1; + font-weight: 800; + letter-spacing: -0.025em; + margin: 0; + color: white; +} + +@media (min-width: 640px) { + .title { + font-size: 5rem; + } +} + +.pinkSpan { + color: hsl(280 100% 70%); +} + +.cardRow { + display: grid; + grid-template-columns: repeat(1, minmax(0, 1fr)); + gap: 1rem; +} + +@media (min-width: 640px) { + .cardRow { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} + +@media (min-width: 768px) { + .cardRow { + gap: 2rem; + } +} + +.card { + max-width: 20rem; + display: flex; + flex-direction: column; + gap: 1rem; + padding: 1rem; + border-radius: 0.75rem; + color: white; + background-color: rgb(255 255 255 / 0.1); +} + +.card:hover { + background-color: rgb(255 255 255 / 0.2); + transition: background-color 150ms cubic-bezier(0.5, 0, 0.2, 1); +} + +.cardTitle { + font-size: 1.5rem; + line-height: 2rem; + font-weight: 700; + margin: 0; +} + +.cardText { + font-size: 1.125rem; + line-height: 1.75rem; +} + +.showcaseContainer { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.5rem; +} + +.showcaseText { + color: white; + text-align: center; + font-size: 1.5rem; + line-height: 2rem; +} + +.authContainer { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 1rem; +} + +.loginButton { + border-radius: 9999px; + background-color: rgb(255 255 255 / 0.1); + padding: 0.75rem 2.5rem; + font-weight: 600; + color: white; + text-decoration-line: none; + transition: background-color 150ms cubic-bezier(0.5, 0, 0.2, 1); +} + +.loginButton:hover { + background-color: rgb(255 255 255 / 0.2); +} + +.form { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.input { + width: 100%; + border-radius: 9999px; + padding: 0.5rem 1rem; + color: black; +} + +.submitButton { + all: unset; + border-radius: 9999px; + background-color: rgb(255 255 255 / 0.1); + padding: 0.75rem 2.5rem; + font-weight: 600; + color: white; + text-align: center; + transition: background-color 150ms cubic-bezier(0.5, 0, 0.2, 1); +} + +.submitButton:hover { + background-color: rgb(255 255 255 / 0.2); +} diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/app/layout.tsx b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/app/layout.tsx new file mode 100644 index 000000000..56d99f3f6 --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/app/layout.tsx @@ -0,0 +1,24 @@ +import "~/styles/globals.css"; + +import { GeistSans } from "geist/font/sans"; +import { type Metadata } from "next"; + +import { TRPCReactProvider } from "~/trpc/react"; + +export const metadata: Metadata = { + title: "Create T3 App", + description: "Generated by create-t3-app", + icons: [{ rel: "icon", url: "/favicon.ico" }], +}; + +export default function RootLayout({ + children, +}: Readonly<{ children: React.ReactNode }>) { + return ( + + + {children} + + + ); +} diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/app/page.tsx b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/app/page.tsx new file mode 100644 index 000000000..79efd1d9c --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/app/page.tsx @@ -0,0 +1,37 @@ +import Link from 'next/link'; + +import { LatestPost } from '~/app/_components/post'; +import { HydrateClient } from '~/trpc/server'; +import styles from './index.module.css'; + +export default async function Home() { + return ( + +
+
+

+ Create T3 App +

+
+ +

First Steps →

+
+ Just the basics - Everything you need to know to set up your database and + authentication. +
+ + +

Documentation →

+
+ Learn more about Create T3 App, the libraries it uses, and how to deploy it. +
+ +
+ +
+
+
+ ); +} + +export const dynamic = 'force-dynamic'; diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/env.js b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/env.js new file mode 100644 index 000000000..829273519 --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/env.js @@ -0,0 +1,42 @@ +import { createEnv } from '@t3-oss/env-nextjs'; +import { z } from 'zod'; + +export const env = createEnv({ + /** + * Specify your server-side environment variables schema here. This way you can ensure the app + * isn't built with invalid env vars. + */ + server: { + NODE_ENV: z + .enum(['development', 'test', 'production']) + .default('development'), + }, + + /** + * Specify your client-side environment variables schema here. This way you can ensure the app + * isn't built with invalid env vars. To expose them to the client, prefix them with + * `NEXT_PUBLIC_`. + */ + client: { + // NEXT_PUBLIC_CLIENTVAR: z.string(), + }, + + /** + * You can't destruct `process.env` as a regular object in the Next.js edge runtimes (e.g. + * middlewares) or client-side so we need to destruct manually. + */ + runtimeEnv: { + NODE_ENV: process.env.NODE_ENV, + // NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR, + }, + /** + * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially + * useful for Docker builds. + */ + skipValidation: !!process.env.SKIP_ENV_VALIDATION, + /** + * Makes it so that empty strings are treated as undefined. `SOME_VAR: z.string()` and + * `SOME_VAR=''` will throw an error. + */ + emptyStringAsUndefined: true, +}); diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/root.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/root.ts new file mode 100644 index 000000000..63d72797d --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/root.ts @@ -0,0 +1,21 @@ +import { createCallerFactory } from '~/server/api/trpc'; +import { createRouter } from './routers/generated/routers'; + +/** + * This is the primary router for your server. + * + * All routers added in /api/routers should be manually added here. + */ +export const appRouter = createRouter(); + +// export type definition of API +export type AppRouter = typeof appRouter; + +/** + * Create a server-side caller for the tRPC API. + * @example + * const trpc = createCaller(createContext); + * const res = await trpc.post.all(); + * ^? Post[] + */ +export const createCaller = createCallerFactory(appRouter); diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/routers/generated-router-helper.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/routers/generated-router-helper.ts new file mode 100644 index 000000000..90eccfe13 --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/routers/generated-router-helper.ts @@ -0,0 +1,2 @@ +export { createTRPCRouter } from '../trpc'; +export { publicProcedure as procedure } from '../trpc'; diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/routers/generated/client/react.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/routers/generated/client/react.ts new file mode 100644 index 000000000..be69328fe --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/routers/generated/client/react.ts @@ -0,0 +1,16 @@ +/* eslint-disable */ + +import type { AnyTRPCRouter as AnyRouter } from '@trpc/server'; +import type { CreateTRPCReactOptions } from '@trpc/react-query/shared'; +import { type CreateTRPCReact, createTRPCReact as _createTRPCReact } from '@trpc/react-query'; +import type { DeepOverrideAtPath } from './utils'; +import type { ClientType } from '../routers'; + +export function createTRPCReact< + TRouter extends AnyRouter, + TPath extends string | undefined = undefined, + TSSRContext = unknown +>(opts?: CreateTRPCReactOptions) { + const r: CreateTRPCReact = _createTRPCReact(opts); + return r as DeepOverrideAtPath, ClientType, TPath>; +} diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/routers/generated/client/utils.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/routers/generated/client/utils.ts new file mode 100644 index 000000000..45a0df890 --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/routers/generated/client/utils.ts @@ -0,0 +1,32 @@ +/* eslint-disable */ + +// inspired by: https://stackoverflow.com/questions/70632026/generic-to-recursively-modify-a-given-type-interface-in-typescript + +type Primitive = string | Function | number | boolean | Symbol | undefined | null; + +/** + * Recursively merges `T` and `R`. If there's a shared key, use `R`'s field type to overwrite `T`. + */ +export type DeepOverride = T extends Primitive + ? R + : R extends Primitive + ? R + : { + [K in keyof T]: K extends keyof R ? DeepOverride : T[K]; + } & { + [K in Exclude]: R[K]; + }; + +/** + * Traverse to `Path` (denoted by dot separated string literal type) in `T`, and starting from there, + * recursively merge with `R`. + */ +export type DeepOverrideAtPath = Path extends undefined + ? DeepOverride + : Path extends `${infer P1}.${infer P2}` + ? P1 extends keyof T + ? Omit & Record>> + : never + : Path extends keyof T + ? Omit & Record> + : never; diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/routers/generated/helper.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/routers/generated/helper.ts new file mode 100644 index 000000000..7f292fff2 --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/routers/generated/helper.ts @@ -0,0 +1,69 @@ +/* eslint-disable */ +import { TRPCError } from '@trpc/server'; +import { isPrismaClientKnownRequestError } from '@zenstackhq/runtime'; + +export async function checkMutate(promise: Promise): Promise { + try { + return await promise; + } catch (err: any) { + if (isPrismaClientKnownRequestError(err)) { + if (err.code === 'P2004') { + if (err.meta?.reason === 'RESULT_NOT_READABLE') { + // unable to readback data + return undefined; + } else { + // rejected by policy + throw new TRPCError({ + code: 'FORBIDDEN', + message: err.message, + cause: err, + }); + } + } else { + // request error + throw new TRPCError({ + code: 'BAD_REQUEST', + message: err.message, + cause: err, + }); + } + } else { + throw err; + } + } + +} + +export async function checkRead(promise: Promise): Promise { + try { + return await promise; + } catch (err: any) { + if (isPrismaClientKnownRequestError(err)) { + if (err.code === 'P2004') { + // rejected by policy + throw new TRPCError({ + code: 'FORBIDDEN', + message: err.message, + cause: err, + }); + } else if (err.code === 'P2025') { + // not found + throw new TRPCError({ + code: 'NOT_FOUND', + message: err.message, + cause: err, + }); + } else { + // request error + throw new TRPCError({ + code: 'BAD_REQUEST', + message: err.message, + cause: err, + }) + } + } else { + throw err; + } + } + +} diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/routers/generated/routers/Post.router.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/routers/generated/routers/Post.router.ts new file mode 100644 index 000000000..f4b661167 --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/routers/generated/routers/Post.router.ts @@ -0,0 +1,622 @@ +/* eslint-disable */ +import { db } from "."; +import { createTRPCRouter } from "../../generated-router-helper"; +import { procedure } from "../../generated-router-helper"; +import * as _Schema from '@zenstackhq/runtime/zod/input'; +const $Schema: typeof _Schema = (_Schema as any).default ?? _Schema; +import { checkRead, checkMutate } from '../helper'; +import type { Prisma } from '@prisma/client'; +import type { UseTRPCMutationOptions, UseTRPCMutationResult, UseTRPCQueryOptions, UseTRPCQueryResult, UseTRPCInfiniteQueryOptions, UseTRPCInfiniteQueryResult } from '@trpc/react-query/shared'; +import type { TRPCClientErrorLike } from '@trpc/client'; +import type { AnyTRPCRouter as AnyRouter } from '@trpc/server'; +import type { UseTRPCSuspenseQueryOptions, UseTRPCSuspenseQueryResult, UseTRPCSuspenseInfiniteQueryOptions, UseTRPCSuspenseInfiniteQueryResult } from '@trpc/react-query/shared'; + +export default function createRouter() { + return createTRPCRouter({ + + aggregate: procedure.input($Schema.PostInputSchema.aggregate).query(({ ctx, input }) => checkRead(db(ctx).post.aggregate(input as any))), + + createMany: procedure.input($Schema.PostInputSchema.createMany).mutation(async ({ ctx, input }) => checkMutate(db(ctx).post.createMany(input as any))), + + create: procedure.input($Schema.PostInputSchema.create).mutation(async ({ ctx, input }) => checkMutate(db(ctx).post.create(input as any))), + + deleteMany: procedure.input($Schema.PostInputSchema.deleteMany).mutation(async ({ ctx, input }) => checkMutate(db(ctx).post.deleteMany(input as any))), + + delete: procedure.input($Schema.PostInputSchema.delete).mutation(async ({ ctx, input }) => checkMutate(db(ctx).post.delete(input as any))), + + findFirst: procedure.input($Schema.PostInputSchema.findFirst).query(({ ctx, input }) => checkRead(db(ctx).post.findFirst(input as any))), + + findFirstOrThrow: procedure.input($Schema.PostInputSchema.findFirst).query(({ ctx, input }) => checkRead(db(ctx).post.findFirstOrThrow(input as any))), + + findMany: procedure.input($Schema.PostInputSchema.findMany).query(({ ctx, input }) => checkRead(db(ctx).post.findMany(input as any))), + + findUnique: procedure.input($Schema.PostInputSchema.findUnique).query(({ ctx, input }) => checkRead(db(ctx).post.findUnique(input as any))), + + findUniqueOrThrow: procedure.input($Schema.PostInputSchema.findUnique).query(({ ctx, input }) => checkRead(db(ctx).post.findUniqueOrThrow(input as any))), + + groupBy: procedure.input($Schema.PostInputSchema.groupBy).query(({ ctx, input }) => checkRead(db(ctx).post.groupBy(input as any))), + + updateMany: procedure.input($Schema.PostInputSchema.updateMany).mutation(async ({ ctx, input }) => checkMutate(db(ctx).post.updateMany(input as any))), + + update: procedure.input($Schema.PostInputSchema.update).mutation(async ({ ctx, input }) => checkMutate(db(ctx).post.update(input as any))), + + upsert: procedure.input($Schema.PostInputSchema.upsert).mutation(async ({ ctx, input }) => checkMutate(db(ctx).post.upsert(input as any))), + + count: procedure.input($Schema.PostInputSchema.count).query(({ ctx, input }) => checkRead(db(ctx).post.count(input as any))), + + } + ); +} + +export interface ClientType { + aggregate: { + + useQuery: >( + input: Prisma.Subset, + opts?: UseTRPCQueryOptions, TData, Error> + ) => UseTRPCQueryResult< + TData, + TRPCClientErrorLike + >; + useInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCInfiniteQueryOptions, Error> + ) => UseTRPCInfiniteQueryResult< + Prisma.GetPostAggregateType, + TRPCClientErrorLike, + T + >; + useSuspenseQuery: >( + input: Prisma.Subset, + opts?: UseTRPCSuspenseQueryOptions, TData, Error> + ) => UseTRPCSuspenseQueryResult>; + useSuspenseInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCSuspenseInfiniteQueryOptions, Error> + ) => UseTRPCSuspenseInfiniteQueryResult, TRPCClientErrorLike, T>; + + }; + createMany: { + + useMutation: (opts?: UseTRPCMutationOptions< + Prisma.PostCreateManyArgs, + TRPCClientErrorLike, + Prisma.BatchPayload, + Context + >,) => + Omit, Prisma.SelectSubset, Context>, 'mutateAsync'> & { + mutateAsync: + (variables: T, opts?: UseTRPCMutationOptions, Prisma.BatchPayload, Context>) => Promise + }; + + }; + create: { + + useMutation: (opts?: UseTRPCMutationOptions< + Prisma.PostCreateArgs, + TRPCClientErrorLike, + Prisma.PostGetPayload, + Context + >,) => + Omit, TRPCClientErrorLike, Prisma.SelectSubset, Context>, 'mutateAsync'> & { + mutateAsync: + (variables: T, opts?: UseTRPCMutationOptions, Prisma.PostGetPayload, Context>) => Promise> + }; + + }; + deleteMany: { + + useMutation: (opts?: UseTRPCMutationOptions< + Prisma.PostDeleteManyArgs, + TRPCClientErrorLike, + Prisma.BatchPayload, + Context + >,) => + Omit, Prisma.SelectSubset, Context>, 'mutateAsync'> & { + mutateAsync: + (variables: T, opts?: UseTRPCMutationOptions, Prisma.BatchPayload, Context>) => Promise + }; + + }; + delete: { + + useMutation: (opts?: UseTRPCMutationOptions< + Prisma.PostDeleteArgs, + TRPCClientErrorLike, + Prisma.PostGetPayload, + Context + >,) => + Omit, TRPCClientErrorLike, Prisma.SelectSubset, Context>, 'mutateAsync'> & { + mutateAsync: + (variables: T, opts?: UseTRPCMutationOptions, Prisma.PostGetPayload, Context>) => Promise> + }; + + }; + findFirst: { + + useQuery: >( + input: Prisma.SelectSubset, + opts?: UseTRPCQueryOptions, TData, Error> + ) => UseTRPCQueryResult< + TData, + TRPCClientErrorLike + >; + useInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCInfiniteQueryOptions, Error> + ) => UseTRPCInfiniteQueryResult< + Prisma.PostGetPayload, + TRPCClientErrorLike, + T + >; + useSuspenseQuery: >( + input: Prisma.SelectSubset, + opts?: UseTRPCSuspenseQueryOptions, TData, Error> + ) => UseTRPCSuspenseQueryResult>; + useSuspenseInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCSuspenseInfiniteQueryOptions, Error> + ) => UseTRPCSuspenseInfiniteQueryResult, TRPCClientErrorLike, T>; + + }; + findFirstOrThrow: { + + useQuery: >( + input: Prisma.SelectSubset, + opts?: UseTRPCQueryOptions, TData, Error> + ) => UseTRPCQueryResult< + TData, + TRPCClientErrorLike + >; + useInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCInfiniteQueryOptions, Error> + ) => UseTRPCInfiniteQueryResult< + Prisma.PostGetPayload, + TRPCClientErrorLike, + T + >; + useSuspenseQuery: >( + input: Prisma.SelectSubset, + opts?: UseTRPCSuspenseQueryOptions, TData, Error> + ) => UseTRPCSuspenseQueryResult>; + useSuspenseInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCSuspenseInfiniteQueryOptions, Error> + ) => UseTRPCSuspenseInfiniteQueryResult, TRPCClientErrorLike, T>; + + }; + findMany: { + + useQuery: >>( + input: Prisma.SelectSubset, + opts?: UseTRPCQueryOptions>, TData, Error> + ) => UseTRPCQueryResult< + TData, + TRPCClientErrorLike + >; + useInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCInfiniteQueryOptions>, Error> + ) => UseTRPCInfiniteQueryResult< + Array>, + TRPCClientErrorLike, + T + >; + useSuspenseQuery: >>( + input: Prisma.SelectSubset, + opts?: UseTRPCSuspenseQueryOptions>, TData, Error> + ) => UseTRPCSuspenseQueryResult>; + useSuspenseInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCSuspenseInfiniteQueryOptions>, Error> + ) => UseTRPCSuspenseInfiniteQueryResult>, TRPCClientErrorLike, T>; + + }; + findUnique: { + + useQuery: >( + input: Prisma.SelectSubset, + opts?: UseTRPCQueryOptions, TData, Error> + ) => UseTRPCQueryResult< + TData, + TRPCClientErrorLike + >; + useInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCInfiniteQueryOptions, Error> + ) => UseTRPCInfiniteQueryResult< + Prisma.PostGetPayload, + TRPCClientErrorLike, + T + >; + useSuspenseQuery: >( + input: Prisma.SelectSubset, + opts?: UseTRPCSuspenseQueryOptions, TData, Error> + ) => UseTRPCSuspenseQueryResult>; + useSuspenseInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCSuspenseInfiniteQueryOptions, Error> + ) => UseTRPCSuspenseInfiniteQueryResult, TRPCClientErrorLike, T>; + + }; + findUniqueOrThrow: { + + useQuery: >( + input: Prisma.SelectSubset, + opts?: UseTRPCQueryOptions, TData, Error> + ) => UseTRPCQueryResult< + TData, + TRPCClientErrorLike + >; + useInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCInfiniteQueryOptions, Error> + ) => UseTRPCInfiniteQueryResult< + Prisma.PostGetPayload, + TRPCClientErrorLike, + T + >; + useSuspenseQuery: >( + input: Prisma.SelectSubset, + opts?: UseTRPCSuspenseQueryOptions, TData, Error> + ) => UseTRPCSuspenseQueryResult>; + useSuspenseInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCSuspenseInfiniteQueryOptions, Error> + ) => UseTRPCSuspenseInfiniteQueryResult, TRPCClientErrorLike, T>; + + }; + groupBy: { + + useQuery: >, + Prisma.Extends<'take', Prisma.Keys> + >, + OrderByArg extends Prisma.True extends HasSelectOrTake + ? { orderBy: Prisma.PostGroupByArgs['orderBy'] } + : { orderBy?: Prisma.PostGroupByArgs['orderBy'] }, + OrderFields extends Prisma.ExcludeUnderscoreKeys>>, + ByFields extends Prisma.MaybeTupleToUnion, + ByValid extends Prisma.Has, + HavingFields extends Prisma.GetHavingFields, + HavingValid extends Prisma.Has, + ByEmpty extends T['by'] extends never[] ? Prisma.True : Prisma.False, + InputErrors extends ByEmpty extends Prisma.True + ? `Error: "by" must not be empty.` + : HavingValid extends Prisma.False + ? { + [P in HavingFields]: P extends ByFields + ? never + : P extends string + ? `Error: Field "${P}" used in "having" needs to be provided in "by".` + : [ + Error, + 'Field ', + P, + ` in "having" needs to be provided in "by"`, + ] + }[HavingFields] + : 'take' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "take", you also need to provide "orderBy"' + : 'skip' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "skip", you also need to provide "orderBy"' + : ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + , TData = {} extends InputErrors ? Prisma.GetPostGroupByPayload : InputErrors>( + input: Prisma.SubsetIntersection & InputErrors, + opts?: UseTRPCQueryOptions<{} extends InputErrors ? Prisma.GetPostGroupByPayload : InputErrors, TData, Error> + ) => UseTRPCQueryResult< + TData, + TRPCClientErrorLike + >; + useInfiniteQuery: >, + Prisma.Extends<'take', Prisma.Keys> + >, + OrderByArg extends Prisma.True extends HasSelectOrTake + ? { orderBy: Prisma.PostGroupByArgs['orderBy'] } + : { orderBy?: Prisma.PostGroupByArgs['orderBy'] }, + OrderFields extends Prisma.ExcludeUnderscoreKeys>>, + ByFields extends Prisma.MaybeTupleToUnion, + ByValid extends Prisma.Has, + HavingFields extends Prisma.GetHavingFields, + HavingValid extends Prisma.Has, + ByEmpty extends T['by'] extends never[] ? Prisma.True : Prisma.False, + InputErrors extends ByEmpty extends Prisma.True + ? `Error: "by" must not be empty.` + : HavingValid extends Prisma.False + ? { + [P in HavingFields]: P extends ByFields + ? never + : P extends string + ? `Error: Field "${P}" used in "having" needs to be provided in "by".` + : [ + Error, + 'Field ', + P, + ` in "having" needs to be provided in "by"`, + ] + }[HavingFields] + : 'take' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "take", you also need to provide "orderBy"' + : 'skip' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "skip", you also need to provide "orderBy"' + : ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + >( + input: Omit & InputErrors, 'cursor'>, + opts?: UseTRPCInfiniteQueryOptions : InputErrors, Error> + ) => UseTRPCInfiniteQueryResult< + {} extends InputErrors ? Prisma.GetPostGroupByPayload : InputErrors, + TRPCClientErrorLike, + T + >; + useSuspenseQuery: >, + Prisma.Extends<'take', Prisma.Keys> + >, + OrderByArg extends Prisma.True extends HasSelectOrTake + ? { orderBy: Prisma.PostGroupByArgs['orderBy'] } + : { orderBy?: Prisma.PostGroupByArgs['orderBy'] }, + OrderFields extends Prisma.ExcludeUnderscoreKeys>>, + ByFields extends Prisma.MaybeTupleToUnion, + ByValid extends Prisma.Has, + HavingFields extends Prisma.GetHavingFields, + HavingValid extends Prisma.Has, + ByEmpty extends T['by'] extends never[] ? Prisma.True : Prisma.False, + InputErrors extends ByEmpty extends Prisma.True + ? `Error: "by" must not be empty.` + : HavingValid extends Prisma.False + ? { + [P in HavingFields]: P extends ByFields + ? never + : P extends string + ? `Error: Field "${P}" used in "having" needs to be provided in "by".` + : [ + Error, + 'Field ', + P, + ` in "having" needs to be provided in "by"`, + ] + }[HavingFields] + : 'take' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "take", you also need to provide "orderBy"' + : 'skip' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "skip", you also need to provide "orderBy"' + : ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + , TData = {} extends InputErrors ? Prisma.GetPostGroupByPayload : InputErrors>( + input: Prisma.SubsetIntersection & InputErrors, + opts?: UseTRPCSuspenseQueryOptions<{} extends InputErrors ? Prisma.GetPostGroupByPayload : InputErrors, TData, Error> + ) => UseTRPCSuspenseQueryResult>; + useSuspenseInfiniteQuery: >, + Prisma.Extends<'take', Prisma.Keys> + >, + OrderByArg extends Prisma.True extends HasSelectOrTake + ? { orderBy: Prisma.PostGroupByArgs['orderBy'] } + : { orderBy?: Prisma.PostGroupByArgs['orderBy'] }, + OrderFields extends Prisma.ExcludeUnderscoreKeys>>, + ByFields extends Prisma.MaybeTupleToUnion, + ByValid extends Prisma.Has, + HavingFields extends Prisma.GetHavingFields, + HavingValid extends Prisma.Has, + ByEmpty extends T['by'] extends never[] ? Prisma.True : Prisma.False, + InputErrors extends ByEmpty extends Prisma.True + ? `Error: "by" must not be empty.` + : HavingValid extends Prisma.False + ? { + [P in HavingFields]: P extends ByFields + ? never + : P extends string + ? `Error: Field "${P}" used in "having" needs to be provided in "by".` + : [ + Error, + 'Field ', + P, + ` in "having" needs to be provided in "by"`, + ] + }[HavingFields] + : 'take' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "take", you also need to provide "orderBy"' + : 'skip' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "skip", you also need to provide "orderBy"' + : ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + >( + input: Omit & InputErrors, 'cursor'>, + opts?: UseTRPCSuspenseInfiniteQueryOptions : InputErrors, Error> + ) => UseTRPCSuspenseInfiniteQueryResult<{} extends InputErrors ? Prisma.GetPostGroupByPayload : InputErrors, TRPCClientErrorLike, T>; + + }; + updateMany: { + + useMutation: (opts?: UseTRPCMutationOptions< + Prisma.PostUpdateManyArgs, + TRPCClientErrorLike, + Prisma.BatchPayload, + Context + >,) => + Omit, Prisma.SelectSubset, Context>, 'mutateAsync'> & { + mutateAsync: + (variables: T, opts?: UseTRPCMutationOptions, Prisma.BatchPayload, Context>) => Promise + }; + + }; + update: { + + useMutation: (opts?: UseTRPCMutationOptions< + Prisma.PostUpdateArgs, + TRPCClientErrorLike, + Prisma.PostGetPayload, + Context + >,) => + Omit, TRPCClientErrorLike, Prisma.SelectSubset, Context>, 'mutateAsync'> & { + mutateAsync: + (variables: T, opts?: UseTRPCMutationOptions, Prisma.PostGetPayload, Context>) => Promise> + }; + + }; + upsert: { + + useMutation: (opts?: UseTRPCMutationOptions< + Prisma.PostUpsertArgs, + TRPCClientErrorLike, + Prisma.PostGetPayload, + Context + >,) => + Omit, TRPCClientErrorLike, Prisma.SelectSubset, Context>, 'mutateAsync'> & { + mutateAsync: + (variables: T, opts?: UseTRPCMutationOptions, Prisma.PostGetPayload, Context>) => Promise> + }; + + }; + count: { + + useQuery: + : number>( + input: Prisma.Subset, + opts?: UseTRPCQueryOptions<'select' extends keyof T + ? T['select'] extends true + ? number + : Prisma.GetScalarType + : number, TData, Error> + ) => UseTRPCQueryResult< + TData, + TRPCClientErrorLike + >; + useInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCInfiniteQueryOptions + : number, Error> + ) => UseTRPCInfiniteQueryResult< + 'select' extends keyof T + ? T['select'] extends true + ? number + : Prisma.GetScalarType + : number, + TRPCClientErrorLike, + T + >; + useSuspenseQuery: + : number>( + input: Prisma.Subset, + opts?: UseTRPCSuspenseQueryOptions<'select' extends keyof T + ? T['select'] extends true + ? number + : Prisma.GetScalarType + : number, TData, Error> + ) => UseTRPCSuspenseQueryResult>; + useSuspenseInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCSuspenseInfiniteQueryOptions + : number, Error> + ) => UseTRPCSuspenseInfiniteQueryResult<'select' extends keyof T + ? T['select'] extends true + ? number + : Prisma.GetScalarType + : number, TRPCClientErrorLike, T>; + + }; +} diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/routers/generated/routers/User.router.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/routers/generated/routers/User.router.ts new file mode 100644 index 000000000..1d4b4488b --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/routers/generated/routers/User.router.ts @@ -0,0 +1,622 @@ +/* eslint-disable */ +import { db } from "."; +import { createTRPCRouter } from "../../generated-router-helper"; +import { procedure } from "../../generated-router-helper"; +import * as _Schema from '@zenstackhq/runtime/zod/input'; +const $Schema: typeof _Schema = (_Schema as any).default ?? _Schema; +import { checkRead, checkMutate } from '../helper'; +import type { Prisma } from '@prisma/client'; +import type { UseTRPCMutationOptions, UseTRPCMutationResult, UseTRPCQueryOptions, UseTRPCQueryResult, UseTRPCInfiniteQueryOptions, UseTRPCInfiniteQueryResult } from '@trpc/react-query/shared'; +import type { TRPCClientErrorLike } from '@trpc/client'; +import type { AnyTRPCRouter as AnyRouter } from '@trpc/server'; +import type { UseTRPCSuspenseQueryOptions, UseTRPCSuspenseQueryResult, UseTRPCSuspenseInfiniteQueryOptions, UseTRPCSuspenseInfiniteQueryResult } from '@trpc/react-query/shared'; + +export default function createRouter() { + return createTRPCRouter({ + + aggregate: procedure.input($Schema.UserInputSchema.aggregate).query(({ ctx, input }) => checkRead(db(ctx).user.aggregate(input as any))), + + createMany: procedure.input($Schema.UserInputSchema.createMany).mutation(async ({ ctx, input }) => checkMutate(db(ctx).user.createMany(input as any))), + + create: procedure.input($Schema.UserInputSchema.create).mutation(async ({ ctx, input }) => checkMutate(db(ctx).user.create(input as any))), + + deleteMany: procedure.input($Schema.UserInputSchema.deleteMany).mutation(async ({ ctx, input }) => checkMutate(db(ctx).user.deleteMany(input as any))), + + delete: procedure.input($Schema.UserInputSchema.delete).mutation(async ({ ctx, input }) => checkMutate(db(ctx).user.delete(input as any))), + + findFirst: procedure.input($Schema.UserInputSchema.findFirst).query(({ ctx, input }) => checkRead(db(ctx).user.findFirst(input as any))), + + findFirstOrThrow: procedure.input($Schema.UserInputSchema.findFirst).query(({ ctx, input }) => checkRead(db(ctx).user.findFirstOrThrow(input as any))), + + findMany: procedure.input($Schema.UserInputSchema.findMany).query(({ ctx, input }) => checkRead(db(ctx).user.findMany(input as any))), + + findUnique: procedure.input($Schema.UserInputSchema.findUnique).query(({ ctx, input }) => checkRead(db(ctx).user.findUnique(input as any))), + + findUniqueOrThrow: procedure.input($Schema.UserInputSchema.findUnique).query(({ ctx, input }) => checkRead(db(ctx).user.findUniqueOrThrow(input as any))), + + groupBy: procedure.input($Schema.UserInputSchema.groupBy).query(({ ctx, input }) => checkRead(db(ctx).user.groupBy(input as any))), + + updateMany: procedure.input($Schema.UserInputSchema.updateMany).mutation(async ({ ctx, input }) => checkMutate(db(ctx).user.updateMany(input as any))), + + update: procedure.input($Schema.UserInputSchema.update).mutation(async ({ ctx, input }) => checkMutate(db(ctx).user.update(input as any))), + + upsert: procedure.input($Schema.UserInputSchema.upsert).mutation(async ({ ctx, input }) => checkMutate(db(ctx).user.upsert(input as any))), + + count: procedure.input($Schema.UserInputSchema.count).query(({ ctx, input }) => checkRead(db(ctx).user.count(input as any))), + + } + ); +} + +export interface ClientType { + aggregate: { + + useQuery: >( + input: Prisma.Subset, + opts?: UseTRPCQueryOptions, TData, Error> + ) => UseTRPCQueryResult< + TData, + TRPCClientErrorLike + >; + useInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCInfiniteQueryOptions, Error> + ) => UseTRPCInfiniteQueryResult< + Prisma.GetUserAggregateType, + TRPCClientErrorLike, + T + >; + useSuspenseQuery: >( + input: Prisma.Subset, + opts?: UseTRPCSuspenseQueryOptions, TData, Error> + ) => UseTRPCSuspenseQueryResult>; + useSuspenseInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCSuspenseInfiniteQueryOptions, Error> + ) => UseTRPCSuspenseInfiniteQueryResult, TRPCClientErrorLike, T>; + + }; + createMany: { + + useMutation: (opts?: UseTRPCMutationOptions< + Prisma.UserCreateManyArgs, + TRPCClientErrorLike, + Prisma.BatchPayload, + Context + >,) => + Omit, Prisma.SelectSubset, Context>, 'mutateAsync'> & { + mutateAsync: + (variables: T, opts?: UseTRPCMutationOptions, Prisma.BatchPayload, Context>) => Promise + }; + + }; + create: { + + useMutation: (opts?: UseTRPCMutationOptions< + Prisma.UserCreateArgs, + TRPCClientErrorLike, + Prisma.UserGetPayload, + Context + >,) => + Omit, TRPCClientErrorLike, Prisma.SelectSubset, Context>, 'mutateAsync'> & { + mutateAsync: + (variables: T, opts?: UseTRPCMutationOptions, Prisma.UserGetPayload, Context>) => Promise> + }; + + }; + deleteMany: { + + useMutation: (opts?: UseTRPCMutationOptions< + Prisma.UserDeleteManyArgs, + TRPCClientErrorLike, + Prisma.BatchPayload, + Context + >,) => + Omit, Prisma.SelectSubset, Context>, 'mutateAsync'> & { + mutateAsync: + (variables: T, opts?: UseTRPCMutationOptions, Prisma.BatchPayload, Context>) => Promise + }; + + }; + delete: { + + useMutation: (opts?: UseTRPCMutationOptions< + Prisma.UserDeleteArgs, + TRPCClientErrorLike, + Prisma.UserGetPayload, + Context + >,) => + Omit, TRPCClientErrorLike, Prisma.SelectSubset, Context>, 'mutateAsync'> & { + mutateAsync: + (variables: T, opts?: UseTRPCMutationOptions, Prisma.UserGetPayload, Context>) => Promise> + }; + + }; + findFirst: { + + useQuery: >( + input: Prisma.SelectSubset, + opts?: UseTRPCQueryOptions, TData, Error> + ) => UseTRPCQueryResult< + TData, + TRPCClientErrorLike + >; + useInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCInfiniteQueryOptions, Error> + ) => UseTRPCInfiniteQueryResult< + Prisma.UserGetPayload, + TRPCClientErrorLike, + T + >; + useSuspenseQuery: >( + input: Prisma.SelectSubset, + opts?: UseTRPCSuspenseQueryOptions, TData, Error> + ) => UseTRPCSuspenseQueryResult>; + useSuspenseInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCSuspenseInfiniteQueryOptions, Error> + ) => UseTRPCSuspenseInfiniteQueryResult, TRPCClientErrorLike, T>; + + }; + findFirstOrThrow: { + + useQuery: >( + input: Prisma.SelectSubset, + opts?: UseTRPCQueryOptions, TData, Error> + ) => UseTRPCQueryResult< + TData, + TRPCClientErrorLike + >; + useInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCInfiniteQueryOptions, Error> + ) => UseTRPCInfiniteQueryResult< + Prisma.UserGetPayload, + TRPCClientErrorLike, + T + >; + useSuspenseQuery: >( + input: Prisma.SelectSubset, + opts?: UseTRPCSuspenseQueryOptions, TData, Error> + ) => UseTRPCSuspenseQueryResult>; + useSuspenseInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCSuspenseInfiniteQueryOptions, Error> + ) => UseTRPCSuspenseInfiniteQueryResult, TRPCClientErrorLike, T>; + + }; + findMany: { + + useQuery: >>( + input: Prisma.SelectSubset, + opts?: UseTRPCQueryOptions>, TData, Error> + ) => UseTRPCQueryResult< + TData, + TRPCClientErrorLike + >; + useInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCInfiniteQueryOptions>, Error> + ) => UseTRPCInfiniteQueryResult< + Array>, + TRPCClientErrorLike, + T + >; + useSuspenseQuery: >>( + input: Prisma.SelectSubset, + opts?: UseTRPCSuspenseQueryOptions>, TData, Error> + ) => UseTRPCSuspenseQueryResult>; + useSuspenseInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCSuspenseInfiniteQueryOptions>, Error> + ) => UseTRPCSuspenseInfiniteQueryResult>, TRPCClientErrorLike, T>; + + }; + findUnique: { + + useQuery: >( + input: Prisma.SelectSubset, + opts?: UseTRPCQueryOptions, TData, Error> + ) => UseTRPCQueryResult< + TData, + TRPCClientErrorLike + >; + useInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCInfiniteQueryOptions, Error> + ) => UseTRPCInfiniteQueryResult< + Prisma.UserGetPayload, + TRPCClientErrorLike, + T + >; + useSuspenseQuery: >( + input: Prisma.SelectSubset, + opts?: UseTRPCSuspenseQueryOptions, TData, Error> + ) => UseTRPCSuspenseQueryResult>; + useSuspenseInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCSuspenseInfiniteQueryOptions, Error> + ) => UseTRPCSuspenseInfiniteQueryResult, TRPCClientErrorLike, T>; + + }; + findUniqueOrThrow: { + + useQuery: >( + input: Prisma.SelectSubset, + opts?: UseTRPCQueryOptions, TData, Error> + ) => UseTRPCQueryResult< + TData, + TRPCClientErrorLike + >; + useInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCInfiniteQueryOptions, Error> + ) => UseTRPCInfiniteQueryResult< + Prisma.UserGetPayload, + TRPCClientErrorLike, + T + >; + useSuspenseQuery: >( + input: Prisma.SelectSubset, + opts?: UseTRPCSuspenseQueryOptions, TData, Error> + ) => UseTRPCSuspenseQueryResult>; + useSuspenseInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCSuspenseInfiniteQueryOptions, Error> + ) => UseTRPCSuspenseInfiniteQueryResult, TRPCClientErrorLike, T>; + + }; + groupBy: { + + useQuery: >, + Prisma.Extends<'take', Prisma.Keys> + >, + OrderByArg extends Prisma.True extends HasSelectOrTake + ? { orderBy: Prisma.UserGroupByArgs['orderBy'] } + : { orderBy?: Prisma.UserGroupByArgs['orderBy'] }, + OrderFields extends Prisma.ExcludeUnderscoreKeys>>, + ByFields extends Prisma.MaybeTupleToUnion, + ByValid extends Prisma.Has, + HavingFields extends Prisma.GetHavingFields, + HavingValid extends Prisma.Has, + ByEmpty extends T['by'] extends never[] ? Prisma.True : Prisma.False, + InputErrors extends ByEmpty extends Prisma.True + ? `Error: "by" must not be empty.` + : HavingValid extends Prisma.False + ? { + [P in HavingFields]: P extends ByFields + ? never + : P extends string + ? `Error: Field "${P}" used in "having" needs to be provided in "by".` + : [ + Error, + 'Field ', + P, + ` in "having" needs to be provided in "by"`, + ] + }[HavingFields] + : 'take' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "take", you also need to provide "orderBy"' + : 'skip' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "skip", you also need to provide "orderBy"' + : ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + , TData = {} extends InputErrors ? Prisma.GetUserGroupByPayload : InputErrors>( + input: Prisma.SubsetIntersection & InputErrors, + opts?: UseTRPCQueryOptions<{} extends InputErrors ? Prisma.GetUserGroupByPayload : InputErrors, TData, Error> + ) => UseTRPCQueryResult< + TData, + TRPCClientErrorLike + >; + useInfiniteQuery: >, + Prisma.Extends<'take', Prisma.Keys> + >, + OrderByArg extends Prisma.True extends HasSelectOrTake + ? { orderBy: Prisma.UserGroupByArgs['orderBy'] } + : { orderBy?: Prisma.UserGroupByArgs['orderBy'] }, + OrderFields extends Prisma.ExcludeUnderscoreKeys>>, + ByFields extends Prisma.MaybeTupleToUnion, + ByValid extends Prisma.Has, + HavingFields extends Prisma.GetHavingFields, + HavingValid extends Prisma.Has, + ByEmpty extends T['by'] extends never[] ? Prisma.True : Prisma.False, + InputErrors extends ByEmpty extends Prisma.True + ? `Error: "by" must not be empty.` + : HavingValid extends Prisma.False + ? { + [P in HavingFields]: P extends ByFields + ? never + : P extends string + ? `Error: Field "${P}" used in "having" needs to be provided in "by".` + : [ + Error, + 'Field ', + P, + ` in "having" needs to be provided in "by"`, + ] + }[HavingFields] + : 'take' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "take", you also need to provide "orderBy"' + : 'skip' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "skip", you also need to provide "orderBy"' + : ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + >( + input: Omit & InputErrors, 'cursor'>, + opts?: UseTRPCInfiniteQueryOptions : InputErrors, Error> + ) => UseTRPCInfiniteQueryResult< + {} extends InputErrors ? Prisma.GetUserGroupByPayload : InputErrors, + TRPCClientErrorLike, + T + >; + useSuspenseQuery: >, + Prisma.Extends<'take', Prisma.Keys> + >, + OrderByArg extends Prisma.True extends HasSelectOrTake + ? { orderBy: Prisma.UserGroupByArgs['orderBy'] } + : { orderBy?: Prisma.UserGroupByArgs['orderBy'] }, + OrderFields extends Prisma.ExcludeUnderscoreKeys>>, + ByFields extends Prisma.MaybeTupleToUnion, + ByValid extends Prisma.Has, + HavingFields extends Prisma.GetHavingFields, + HavingValid extends Prisma.Has, + ByEmpty extends T['by'] extends never[] ? Prisma.True : Prisma.False, + InputErrors extends ByEmpty extends Prisma.True + ? `Error: "by" must not be empty.` + : HavingValid extends Prisma.False + ? { + [P in HavingFields]: P extends ByFields + ? never + : P extends string + ? `Error: Field "${P}" used in "having" needs to be provided in "by".` + : [ + Error, + 'Field ', + P, + ` in "having" needs to be provided in "by"`, + ] + }[HavingFields] + : 'take' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "take", you also need to provide "orderBy"' + : 'skip' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "skip", you also need to provide "orderBy"' + : ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + , TData = {} extends InputErrors ? Prisma.GetUserGroupByPayload : InputErrors>( + input: Prisma.SubsetIntersection & InputErrors, + opts?: UseTRPCSuspenseQueryOptions<{} extends InputErrors ? Prisma.GetUserGroupByPayload : InputErrors, TData, Error> + ) => UseTRPCSuspenseQueryResult>; + useSuspenseInfiniteQuery: >, + Prisma.Extends<'take', Prisma.Keys> + >, + OrderByArg extends Prisma.True extends HasSelectOrTake + ? { orderBy: Prisma.UserGroupByArgs['orderBy'] } + : { orderBy?: Prisma.UserGroupByArgs['orderBy'] }, + OrderFields extends Prisma.ExcludeUnderscoreKeys>>, + ByFields extends Prisma.MaybeTupleToUnion, + ByValid extends Prisma.Has, + HavingFields extends Prisma.GetHavingFields, + HavingValid extends Prisma.Has, + ByEmpty extends T['by'] extends never[] ? Prisma.True : Prisma.False, + InputErrors extends ByEmpty extends Prisma.True + ? `Error: "by" must not be empty.` + : HavingValid extends Prisma.False + ? { + [P in HavingFields]: P extends ByFields + ? never + : P extends string + ? `Error: Field "${P}" used in "having" needs to be provided in "by".` + : [ + Error, + 'Field ', + P, + ` in "having" needs to be provided in "by"`, + ] + }[HavingFields] + : 'take' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "take", you also need to provide "orderBy"' + : 'skip' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "skip", you also need to provide "orderBy"' + : ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + >( + input: Omit & InputErrors, 'cursor'>, + opts?: UseTRPCSuspenseInfiniteQueryOptions : InputErrors, Error> + ) => UseTRPCSuspenseInfiniteQueryResult<{} extends InputErrors ? Prisma.GetUserGroupByPayload : InputErrors, TRPCClientErrorLike, T>; + + }; + updateMany: { + + useMutation: (opts?: UseTRPCMutationOptions< + Prisma.UserUpdateManyArgs, + TRPCClientErrorLike, + Prisma.BatchPayload, + Context + >,) => + Omit, Prisma.SelectSubset, Context>, 'mutateAsync'> & { + mutateAsync: + (variables: T, opts?: UseTRPCMutationOptions, Prisma.BatchPayload, Context>) => Promise + }; + + }; + update: { + + useMutation: (opts?: UseTRPCMutationOptions< + Prisma.UserUpdateArgs, + TRPCClientErrorLike, + Prisma.UserGetPayload, + Context + >,) => + Omit, TRPCClientErrorLike, Prisma.SelectSubset, Context>, 'mutateAsync'> & { + mutateAsync: + (variables: T, opts?: UseTRPCMutationOptions, Prisma.UserGetPayload, Context>) => Promise> + }; + + }; + upsert: { + + useMutation: (opts?: UseTRPCMutationOptions< + Prisma.UserUpsertArgs, + TRPCClientErrorLike, + Prisma.UserGetPayload, + Context + >,) => + Omit, TRPCClientErrorLike, Prisma.SelectSubset, Context>, 'mutateAsync'> & { + mutateAsync: + (variables: T, opts?: UseTRPCMutationOptions, Prisma.UserGetPayload, Context>) => Promise> + }; + + }; + count: { + + useQuery: + : number>( + input: Prisma.Subset, + opts?: UseTRPCQueryOptions<'select' extends keyof T + ? T['select'] extends true + ? number + : Prisma.GetScalarType + : number, TData, Error> + ) => UseTRPCQueryResult< + TData, + TRPCClientErrorLike + >; + useInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCInfiniteQueryOptions + : number, Error> + ) => UseTRPCInfiniteQueryResult< + 'select' extends keyof T + ? T['select'] extends true + ? number + : Prisma.GetScalarType + : number, + TRPCClientErrorLike, + T + >; + useSuspenseQuery: + : number>( + input: Prisma.Subset, + opts?: UseTRPCSuspenseQueryOptions<'select' extends keyof T + ? T['select'] extends true + ? number + : Prisma.GetScalarType + : number, TData, Error> + ) => UseTRPCSuspenseQueryResult>; + useSuspenseInfiniteQuery: ( + input: Omit, 'cursor'>, + opts?: UseTRPCSuspenseInfiniteQueryOptions + : number, Error> + ) => UseTRPCSuspenseInfiniteQueryResult<'select' extends keyof T + ? T['select'] extends true + ? number + : Prisma.GetScalarType + : number, TRPCClientErrorLike, T>; + + }; +} diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/routers/generated/routers/index.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/routers/generated/routers/index.ts new file mode 100644 index 000000000..f44daeffc --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/routers/generated/routers/index.ts @@ -0,0 +1,28 @@ +/* eslint-disable */ +import type { AnyTRPCRouter as AnyRouter } from "@trpc/server"; +import type { PrismaClient } from "@prisma/client"; +import { createTRPCRouter } from "../../generated-router-helper"; +import createUserRouter from "./User.router"; +import createPostRouter from "./Post.router"; +import { ClientType as UserClientType } from "./User.router"; +import { ClientType as PostClientType } from "./Post.router"; + +export function db(ctx: any) { + if (!ctx.prisma) { + throw new Error('Missing "prisma" field in trpc context'); + } + return ctx.prisma as PrismaClient; +} + +export function createRouter() { + return createTRPCRouter({ + user: createUserRouter(), + post: createPostRouter(), + } + ); +} + +export interface ClientType { + user: UserClientType; + post: PostClientType; +} diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/trpc.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/trpc.ts new file mode 100644 index 000000000..a685a033b --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/api/trpc.ts @@ -0,0 +1,105 @@ +/** + * YOU PROBABLY DON'T NEED TO EDIT THIS FILE, UNLESS: + * 1. You want to modify request context (see Part 1). + * 2. You want to create a new middleware or type of procedure (see Part 3). + * + * TL;DR - This is where all the tRPC server stuff is created and plugged in. The pieces you will + * need to use are documented accordingly near the end. + */ +import { initTRPC } from '@trpc/server'; +import superjson from 'superjson'; +import { ZodError } from 'zod'; + +import { db } from '~/server/db'; + +/** + * 1. CONTEXT + * + * This section defines the "contexts" that are available in the backend API. + * + * These allow you to access things when processing a request, like the database, the session, etc. + * + * This helper generates the "internals" for a tRPC context. The API handler and RSC clients each + * wrap this and provides the required context. + * + * @see https://trpc.io/docs/server/context + */ +export const createTRPCContext = async (opts: { headers: Headers }) => { + return { + db, + ...opts, + }; +}; + +/** + * 2. INITIALIZATION + * + * This is where the tRPC API is initialized, connecting the context and transformer. We also parse + * ZodErrors so that you get typesafety on the frontend if your procedure fails due to validation + * errors on the backend. + */ +const t = initTRPC.context().create({ + transformer: superjson, + errorFormatter({ shape, error }) { + return { + ...shape, + data: { + ...shape.data, + zodError: error.cause instanceof ZodError ? error.cause.flatten() : null, + }, + }; + }, +}); + +/** + * Create a server-side caller. + * + * @see https://trpc.io/docs/server/server-side-calls + */ +export const createCallerFactory = t.createCallerFactory; + +/** + * 3. ROUTER & PROCEDURE (THE IMPORTANT BIT) + * + * These are the pieces you use to build your tRPC API. You should import these a lot in the + * "/src/server/api/routers" directory. + */ + +/** + * This is how you create new routers and sub-routers in your tRPC API. + * + * @see https://trpc.io/docs/router + */ +export const createTRPCRouter = t.router; + +/** + * Middleware for timing procedure execution and adding an artificial delay in development. + * + * You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating + * network latency that would occur in production but not in local development. + */ +const timingMiddleware = t.middleware(async ({ next, path }) => { + const start = Date.now(); + + if (t._config.isDev) { + // artificial delay in dev + const waitMs = Math.floor(Math.random() * 400) + 100; + await new Promise((resolve) => setTimeout(resolve, waitMs)); + } + + const result = await next(); + + const end = Date.now(); + console.log(`[TRPC] ${path} took ${end - start}ms to execute`); + + return result; +}); + +/** + * Public (unauthenticated) procedure + * + * This is the base piece you use to build new queries and mutations on your tRPC API. It does not + * guarantee that a user querying is authorized, but you can still access user session data if they + * are logged in. + */ +export const publicProcedure = t.procedure.use(timingMiddleware); diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/db.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/db.ts new file mode 100644 index 000000000..07dc0271a --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/server/db.ts @@ -0,0 +1,17 @@ +import { PrismaClient } from "@prisma/client"; + +import { env } from "~/env"; + +const createPrismaClient = () => + new PrismaClient({ + log: + env.NODE_ENV === "development" ? ["query", "error", "warn"] : ["error"], + }); + +const globalForPrisma = globalThis as unknown as { + prisma: ReturnType | undefined; +}; + +export const db = globalForPrisma.prisma ?? createPrismaClient(); + +if (env.NODE_ENV !== "production") globalForPrisma.prisma = db; diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/styles/globals.css b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/styles/globals.css new file mode 100644 index 000000000..e5e2dcc23 --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/styles/globals.css @@ -0,0 +1,16 @@ +html, +body { + padding: 0; + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, + Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; +} + +a { + color: inherit; + text-decoration: none; +} + +* { + box-sizing: border-box; +} diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/trpc/query-client.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/trpc/query-client.ts new file mode 100644 index 000000000..bda64397c --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/trpc/query-client.ts @@ -0,0 +1,25 @@ +import { + defaultShouldDehydrateQuery, + QueryClient, +} from "@tanstack/react-query"; +import SuperJSON from "superjson"; + +export const createQueryClient = () => + new QueryClient({ + defaultOptions: { + queries: { + // With SSR, we usually want to set some default staleTime + // above 0 to avoid refetching immediately on the client + staleTime: 30 * 1000, + }, + dehydrate: { + serializeData: SuperJSON.serialize, + shouldDehydrateQuery: (query) => + defaultShouldDehydrateQuery(query) || + query.state.status === "pending", + }, + hydrate: { + deserializeData: SuperJSON.deserialize, + }, + }, + }); diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/trpc/react.tsx b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/trpc/react.tsx new file mode 100644 index 000000000..be9631708 --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/trpc/react.tsx @@ -0,0 +1,76 @@ +'use client'; + +import { QueryClientProvider, type QueryClient } from '@tanstack/react-query'; +import { loggerLink, unstable_httpBatchStreamLink } from '@trpc/client'; +import { type inferRouterInputs, type inferRouterOutputs } from '@trpc/server'; +import { useState } from 'react'; +import SuperJSON from 'superjson'; + +import { type AppRouter } from '~/server/api/root'; +import { createQueryClient } from './query-client'; +import { createTRPCReact } from '../server/api/routers/generated/client/react'; + +let clientQueryClientSingleton: QueryClient | undefined = undefined; +const getQueryClient = () => { + if (typeof window === 'undefined') { + // Server: always make a new query client + return createQueryClient(); + } + // Browser: use singleton pattern to keep the same query client + return (clientQueryClientSingleton ??= createQueryClient()); +}; + +export const api = createTRPCReact(); + +/** + * Inference helper for inputs. + * + * @example type HelloInput = RouterInputs['example']['hello'] + */ +export type RouterInputs = inferRouterInputs; + +/** + * Inference helper for outputs. + * + * @example type HelloOutput = RouterOutputs['example']['hello'] + */ +export type RouterOutputs = inferRouterOutputs; + +export function TRPCReactProvider(props: { children: React.ReactNode }) { + const queryClient = getQueryClient(); + + const [trpcClient] = useState(() => + api.createClient({ + links: [ + loggerLink({ + enabled: (op) => + process.env.NODE_ENV === 'development' || + (op.direction === 'down' && op.result instanceof Error), + }), + unstable_httpBatchStreamLink({ + transformer: SuperJSON, + url: getBaseUrl() + '/api/trpc', + headers: () => { + const headers = new Headers(); + headers.set('x-trpc-source', 'nextjs-react'); + return headers; + }, + }), + ], + }) + ); + + return ( + + + {props.children} + + + ); +} + +function getBaseUrl() { + if (typeof window !== 'undefined') return window.location.origin; + if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`; + return `http://localhost:${process.env.PORT ?? 3000}`; +} diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/trpc/server.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/trpc/server.ts new file mode 100644 index 000000000..59300a638 --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/src/trpc/server.ts @@ -0,0 +1,30 @@ +import "server-only"; + +import { createHydrationHelpers } from "@trpc/react-query/rsc"; +import { headers } from "next/headers"; +import { cache } from "react"; + +import { createCaller, type AppRouter } from "~/server/api/root"; +import { createTRPCContext } from "~/server/api/trpc"; +import { createQueryClient } from "./query-client"; + +/** + * This wraps the `createTRPCContext` helper and provides the required context for the tRPC API when + * handling a tRPC call from a React Server Component. + */ +const createContext = cache(() => { + const heads = new Headers(headers()); + heads.set("x-trpc-source", "rsc"); + + return createTRPCContext({ + headers: heads, + }); +}); + +const getQueryClient = cache(createQueryClient); +const caller = createCaller(createContext); + +export const { trpc: api, HydrateClient } = createHydrationHelpers( + caller, + getQueryClient +); diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v11/tsconfig.json b/packages/plugins/trpc/tests/projects/t3-trpc-v11/tsconfig.json new file mode 100644 index 000000000..905062ded --- /dev/null +++ b/packages/plugins/trpc/tests/projects/t3-trpc-v11/tsconfig.json @@ -0,0 +1,42 @@ +{ + "compilerOptions": { + /* Base Options: */ + "esModuleInterop": true, + "skipLibCheck": true, + "target": "es2022", + "allowJs": true, + "resolveJsonModule": true, + "moduleDetection": "force", + "isolatedModules": true, + + /* Strictness */ + "strict": true, + "noUncheckedIndexedAccess": true, + "checkJs": true, + + /* Bundled projects */ + "lib": ["dom", "dom.iterable", "ES2022"], + "noEmit": true, + "module": "ESNext", + "moduleResolution": "Bundler", + "jsx": "preserve", + "plugins": [{ "name": "next" }], + "incremental": true, + + /* Path Aliases */ + "baseUrl": ".", + "paths": { + "~/*": ["./src/*"] + } + }, + "include": [ + ".eslintrc.cjs", + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + "**/*.cjs", + "**/*.js", + ".next/types/**/*.ts" + ], + "exclude": ["node_modules"] +} diff --git a/packages/plugins/trpc/tests/t3.test.ts b/packages/plugins/trpc/tests/t3.test.ts index 1c808de23..6a7843f11 100644 --- a/packages/plugins/trpc/tests/t3.test.ts +++ b/packages/plugins/trpc/tests/t3.test.ts @@ -27,4 +27,17 @@ describe('tRPC plugin tests with create-t3-app', () => { run('npx zenstack generate'); run('npm run build'); }); + + it('project test trpc v11', () => { + const ver = require(path.join(__dirname, '../package.json')).version; + process.chdir(path.join(__dirname, './projects/t3-trpc-v11')); + + const deps = ['zenstackhq-language', 'zenstackhq-runtime', 'zenstackhq-sdk', 'zenstack']; + for (const dep of deps) { + run(`npm install ${path.join(__dirname, '../../../../.build/') + dep + '-' + ver + '.tgz'}`); + } + + run('npx zenstack generate'); + run('npm run build'); + }); }); diff --git a/packages/runtime/package.json b/packages/runtime/package.json index 25766bec9..ec9e03ffb 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/runtime", "displayName": "ZenStack Runtime Library", - "version": "2.4.1", + "version": "2.5.0", "description": "Runtime of ZenStack for both client-side and server-side environments.", "repository": { "type": "git", @@ -25,9 +25,17 @@ "types": "./edge.d.ts", "default": "./edge.js" }, - "./enhancements": { - "types": "./enhancements/index.d.ts", - "default": "./enhancements/index.js" + "./enhancements/node": { + "types": "./enhancements/node/index.d.ts", + "default": "./enhancements/node/index.js" + }, + "./enhancements/edge": { + "types": "./enhancements/edge/index.d.ts", + "default": "./enhancements/edge/index.js" + }, + "./validation": { + "types": "./validation.d.ts", + "default": "./validation.js" }, "./constraint-solver": { "types": "./constraint-solver.d.ts", @@ -80,7 +88,7 @@ "bcryptjs": "^2.4.3", "buffer": "^6.0.3", "change-case": "^4.1.2", - "decimal.js": "^10.4.2", + "decimal.js-light": "^2.5.1", "deepmerge": "^4.3.1", "is-plain-object": "^5.0.0", "logic-solver": "^2.0.1", @@ -98,7 +106,7 @@ "zod-validation-error": "^1.5.0" }, "peerDependencies": { - "@prisma/client": "5.0.0 - 5.18.x" + "@prisma/client": "5.0.0 - 5.19.x" }, "author": { "name": "ZenStack Team" diff --git a/packages/runtime/res/enhance-edge.d.ts b/packages/runtime/res/enhance-edge.d.ts new file mode 100644 index 000000000..7f165c4d4 --- /dev/null +++ b/packages/runtime/res/enhance-edge.d.ts @@ -0,0 +1 @@ +export { auth, enhance, type PrismaClient } from '.zenstack/enhance-edge'; diff --git a/packages/runtime/res/enhance-edge.js b/packages/runtime/res/enhance-edge.js new file mode 100644 index 000000000..7c716a79a --- /dev/null +++ b/packages/runtime/res/enhance-edge.js @@ -0,0 +1,10 @@ +'use strict'; +Object.defineProperty(exports, '__esModule', { value: true }); + +try { + exports.enhance = require('.zenstack/enhance-edge').enhance; +} catch { + exports.enhance = function () { + throw new Error('Generated "enhance" function not found. Please run `zenstack generate` first.'); + }; +} diff --git a/packages/runtime/src/browser/serialization.ts b/packages/runtime/src/browser/serialization.ts index 4b55311f3..478bd66a9 100644 --- a/packages/runtime/src/browser/serialization.ts +++ b/packages/runtime/src/browser/serialization.ts @@ -1,11 +1,14 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { Buffer } from 'buffer'; -import Decimal from 'decimal.js'; +import Decimal from 'decimal.js-light'; import SuperJSON from 'superjson'; SuperJSON.registerCustom( { - isApplicable: (v): v is Decimal => Decimal.isDecimal(v), + isApplicable: (v): v is Decimal => + v instanceof Decimal || + // interop with decimal.js + v?.toStringTag === '[object Decimal]', serialize: (v) => v.toJSON(), deserialize: (v) => new Decimal(v), }, diff --git a/packages/runtime/src/constants.ts b/packages/runtime/src/constants.ts index 5fd8c2901..36acf8c83 100644 --- a/packages/runtime/src/constants.ts +++ b/packages/runtime/src/constants.ts @@ -40,7 +40,7 @@ export enum PrismaErrorCode { /** * A constraint failed on the database */ - CONSTRAINED_FAILED = 'P2004', + CONSTRAINT_FAILED = 'P2004', /** * The required connected records were not found diff --git a/packages/runtime/src/edge.ts b/packages/runtime/src/edge.ts deleted file mode 120000 index a2e78d748..000000000 --- a/packages/runtime/src/edge.ts +++ /dev/null @@ -1 +0,0 @@ -index.ts \ No newline at end of file diff --git a/packages/runtime/src/edge.ts b/packages/runtime/src/edge.ts new file mode 100644 index 000000000..cce09ec57 --- /dev/null +++ b/packages/runtime/src/edge.ts @@ -0,0 +1 @@ +export * from './enhance-edge'; diff --git a/packages/runtime/src/enhance-edge.d.ts b/packages/runtime/src/enhance-edge.d.ts new file mode 100644 index 000000000..2f6d6218e --- /dev/null +++ b/packages/runtime/src/enhance-edge.d.ts @@ -0,0 +1,2 @@ +// @ts-expect-error stub for re-exporting generated code +export { auth, enhance } from '.zenstack/enhance-edge'; diff --git a/packages/runtime/src/enhancements/edge/create-enhancement.ts b/packages/runtime/src/enhancements/edge/create-enhancement.ts new file mode 120000 index 000000000..e06076ec0 --- /dev/null +++ b/packages/runtime/src/enhancements/edge/create-enhancement.ts @@ -0,0 +1 @@ +../node/create-enhancement.ts \ No newline at end of file diff --git a/packages/runtime/src/enhancements/edge/default-auth.ts b/packages/runtime/src/enhancements/edge/default-auth.ts new file mode 120000 index 000000000..63249aec9 --- /dev/null +++ b/packages/runtime/src/enhancements/edge/default-auth.ts @@ -0,0 +1 @@ +../node/default-auth.ts \ No newline at end of file diff --git a/packages/runtime/src/enhancements/edge/delegate.ts b/packages/runtime/src/enhancements/edge/delegate.ts new file mode 120000 index 000000000..fc4213954 --- /dev/null +++ b/packages/runtime/src/enhancements/edge/delegate.ts @@ -0,0 +1 @@ +../node/delegate.ts \ No newline at end of file diff --git a/packages/runtime/src/enhancements/edge/index.ts b/packages/runtime/src/enhancements/edge/index.ts new file mode 120000 index 000000000..1baad1b89 --- /dev/null +++ b/packages/runtime/src/enhancements/edge/index.ts @@ -0,0 +1 @@ +../node/index.ts \ No newline at end of file diff --git a/packages/runtime/src/enhancements/edge/logger.ts b/packages/runtime/src/enhancements/edge/logger.ts new file mode 120000 index 000000000..b223d7301 --- /dev/null +++ b/packages/runtime/src/enhancements/edge/logger.ts @@ -0,0 +1 @@ +../node/logger.ts \ No newline at end of file diff --git a/packages/runtime/src/enhancements/edge/omit.ts b/packages/runtime/src/enhancements/edge/omit.ts new file mode 120000 index 000000000..eb506bb87 --- /dev/null +++ b/packages/runtime/src/enhancements/edge/omit.ts @@ -0,0 +1 @@ +../node/omit.ts \ No newline at end of file diff --git a/packages/runtime/src/enhancements/edge/password.ts b/packages/runtime/src/enhancements/edge/password.ts new file mode 120000 index 000000000..8d06b6e3c --- /dev/null +++ b/packages/runtime/src/enhancements/edge/password.ts @@ -0,0 +1 @@ +../node/password.ts \ No newline at end of file diff --git a/packages/runtime/src/enhancements/edge/policy/check-utils.ts b/packages/runtime/src/enhancements/edge/policy/check-utils.ts new file mode 100644 index 000000000..b3f27c4fb --- /dev/null +++ b/packages/runtime/src/enhancements/edge/policy/check-utils.ts @@ -0,0 +1,16 @@ +import { ModelMeta } from '..'; +import type { DbClientContract } from '../../../types'; +import { PermissionCheckArgs } from '../types'; +import { PolicyUtil } from './policy-utils'; + +export async function checkPermission( + _model: string, + _args: PermissionCheckArgs, + _modelMeta: ModelMeta, + _policyUtils: PolicyUtil, + _prisma: DbClientContract, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + _prismaModule: any +): Promise { + throw new Error('`check()` API is not supported on edge runtime'); +} diff --git a/packages/runtime/src/enhancements/edge/policy/handler.ts b/packages/runtime/src/enhancements/edge/policy/handler.ts new file mode 120000 index 000000000..1439205ac --- /dev/null +++ b/packages/runtime/src/enhancements/edge/policy/handler.ts @@ -0,0 +1 @@ +../../node/policy/handler.ts \ No newline at end of file diff --git a/packages/runtime/src/enhancements/edge/policy/index.ts b/packages/runtime/src/enhancements/edge/policy/index.ts new file mode 120000 index 000000000..3d4a1fa9c --- /dev/null +++ b/packages/runtime/src/enhancements/edge/policy/index.ts @@ -0,0 +1 @@ +../../node/policy/index.ts \ No newline at end of file diff --git a/packages/runtime/src/enhancements/edge/policy/policy-utils.ts b/packages/runtime/src/enhancements/edge/policy/policy-utils.ts new file mode 120000 index 000000000..7dadd4769 --- /dev/null +++ b/packages/runtime/src/enhancements/edge/policy/policy-utils.ts @@ -0,0 +1 @@ +../../node/policy/policy-utils.ts \ No newline at end of file diff --git a/packages/runtime/src/enhancements/edge/promise.ts b/packages/runtime/src/enhancements/edge/promise.ts new file mode 120000 index 000000000..a00819e60 --- /dev/null +++ b/packages/runtime/src/enhancements/edge/promise.ts @@ -0,0 +1 @@ +../node/promise.ts \ No newline at end of file diff --git a/packages/runtime/src/enhancements/edge/proxy.ts b/packages/runtime/src/enhancements/edge/proxy.ts new file mode 120000 index 000000000..de440c0e0 --- /dev/null +++ b/packages/runtime/src/enhancements/edge/proxy.ts @@ -0,0 +1 @@ +../node/proxy.ts \ No newline at end of file diff --git a/packages/runtime/src/enhancements/edge/query-utils.ts b/packages/runtime/src/enhancements/edge/query-utils.ts new file mode 120000 index 000000000..4a42067b1 --- /dev/null +++ b/packages/runtime/src/enhancements/edge/query-utils.ts @@ -0,0 +1 @@ +../node/query-utils.ts \ No newline at end of file diff --git a/packages/runtime/src/enhancements/edge/types.ts b/packages/runtime/src/enhancements/edge/types.ts new file mode 120000 index 000000000..3faa30754 --- /dev/null +++ b/packages/runtime/src/enhancements/edge/types.ts @@ -0,0 +1 @@ +../node/types.ts \ No newline at end of file diff --git a/packages/runtime/src/enhancements/edge/utils.ts b/packages/runtime/src/enhancements/edge/utils.ts new file mode 120000 index 000000000..c6f4d9b46 --- /dev/null +++ b/packages/runtime/src/enhancements/edge/utils.ts @@ -0,0 +1 @@ +../node/utils.ts \ No newline at end of file diff --git a/packages/runtime/src/enhancements/edge/where-visitor.ts b/packages/runtime/src/enhancements/edge/where-visitor.ts new file mode 120000 index 000000000..7b6cb94d8 --- /dev/null +++ b/packages/runtime/src/enhancements/edge/where-visitor.ts @@ -0,0 +1 @@ +../node/where-visitor.ts \ No newline at end of file diff --git a/packages/runtime/src/enhancements/create-enhancement.ts b/packages/runtime/src/enhancements/node/create-enhancement.ts similarity index 68% rename from packages/runtime/src/enhancements/create-enhancement.ts rename to packages/runtime/src/enhancements/node/create-enhancement.ts index 053580b8d..127574e26 100644 --- a/packages/runtime/src/enhancements/create-enhancement.ts +++ b/packages/runtime/src/enhancements/node/create-enhancement.ts @@ -1,68 +1,20 @@ import semver from 'semver'; -import { PRISMA_MINIMUM_VERSION } from '../constants'; -import { isDelegateModel, type ModelMeta } from '../cross'; -import type { AuthUser } from '../types'; +import { PRISMA_MINIMUM_VERSION } from '../../constants'; +import { isDelegateModel, type ModelMeta } from '../../cross'; +import type { EnhancementContext, EnhancementKind, EnhancementOptions, ZodSchemas } from '../../types'; import { withDefaultAuth } from './default-auth'; import { withDelegate } from './delegate'; import { Logger } from './logger'; import { withOmit } from './omit'; import { withPassword } from './password'; import { withPolicy } from './policy'; -import type { ErrorTransformer } from './proxy'; -import type { PolicyDef, ZodSchemas } from './types'; - -/** - * Kinds of enhancements to `PrismaClient` - */ -export type EnhancementKind = 'password' | 'omit' | 'policy' | 'validation' | 'delegate'; +import type { PolicyDef } from './types'; /** * All enhancement kinds */ const ALL_ENHANCEMENTS: EnhancementKind[] = ['password', 'omit', 'policy', 'validation', 'delegate']; -/** - * Transaction isolation levels: https://www.prisma.io/docs/orm/prisma-client/queries/transactions#transaction-isolation-level - */ -export type TransactionIsolationLevel = - | 'ReadUncommitted' - | 'ReadCommitted' - | 'RepeatableRead' - | 'Snapshot' - | 'Serializable'; - -export type EnhancementOptions = { - /** - * The kinds of enhancements to apply. By default all enhancements are applied. - */ - kinds?: EnhancementKind[]; - - /** - * Whether to log Prisma query - */ - logPrismaQuery?: boolean; - - /** - * Hook for transforming errors before they are thrown to the caller. - */ - errorTransformer?: ErrorTransformer; - - /** - * The `maxWait` option passed to `prisma.$transaction()` call for transactions initiated by ZenStack. - */ - transactionMaxWait?: number; - - /** - * The `timeout` option passed to `prisma.$transaction()` call for transactions initiated by ZenStack. - */ - transactionTimeout?: number; - - /** - * The `isolationLevel` option passed to `prisma.$transaction()` call for transactions initiated by ZenStack. - */ - transactionIsolationLevel?: TransactionIsolationLevel; -}; - /** * Options for {@link createEnhancement} * @@ -91,13 +43,6 @@ export type InternalEnhancementOptions = EnhancementOptions & { prismaModule: any; }; -/** - * Context for creating enhanced `PrismaClient` - */ -export type EnhancementContext = { - user?: User; -}; - /** * Gets a Prisma client enhanced with all enhancement behaviors, including access * policy, field validation, field omission and password hashing. diff --git a/packages/runtime/src/enhancements/default-auth.ts b/packages/runtime/src/enhancements/node/default-auth.ts similarity index 97% rename from packages/runtime/src/enhancements/default-auth.ts rename to packages/runtime/src/enhancements/node/default-auth.ts index 1408a93b7..10f4f3504 100644 --- a/packages/runtime/src/enhancements/default-auth.ts +++ b/packages/runtime/src/enhancements/node/default-auth.ts @@ -9,9 +9,9 @@ import { enumerate, getFields, requireField, -} from '../cross'; -import { DbClientContract } from '../types'; -import { EnhancementContext, InternalEnhancementOptions } from './create-enhancement'; +} from '../../cross'; +import { DbClientContract, EnhancementContext } from '../../types'; +import { InternalEnhancementOptions } from './create-enhancement'; import { DefaultPrismaProxyHandler, PrismaProxyActions, makeProxy } from './proxy'; import { isUnsafeMutate, prismaClientValidationError } from './utils'; diff --git a/packages/runtime/src/enhancements/delegate.ts b/packages/runtime/src/enhancements/node/delegate.ts similarity index 97% rename from packages/runtime/src/enhancements/delegate.ts rename to packages/runtime/src/enhancements/node/delegate.ts index e82d24d72..8efad7568 100644 --- a/packages/runtime/src/enhancements/delegate.ts +++ b/packages/runtime/src/enhancements/node/delegate.ts @@ -2,7 +2,7 @@ import deepmerge, { type ArrayMergeOptions } from 'deepmerge'; import { isPlainObject } from 'is-plain-object'; import { lowerCaseFirst } from 'lower-case-first'; -import { DELEGATE_AUX_RELATION_PREFIX } from '../constants'; +import { DELEGATE_AUX_RELATION_PREFIX } from '../../constants'; import { FieldInfo, ModelInfo, @@ -13,8 +13,8 @@ import { getModelInfo, isDelegateModel, resolveField, -} from '../cross'; -import type { CrudContract, DbClientContract } from '../types'; +} from '../../cross'; +import type { CrudContract, DbClientContract } from '../../types'; import type { InternalEnhancementOptions } from './create-enhancement'; import { Logger } from './logger'; import { DefaultPrismaProxyHandler, makeProxy } from './proxy'; @@ -153,7 +153,22 @@ export class DelegateProxyHandler extends DefaultPrismaProxyHandler { if (args[kind] && typeof args[kind] === 'object') { for (const [field, value] of Object.entries(args[kind])) { const fieldInfo = resolveField(this.options.modelMeta, model, field); - if (fieldInfo && value !== undefined) { + if (!fieldInfo) { + continue; + } + + if (this.isDelegateOrDescendantOfDelegate(fieldInfo?.type) && value) { + // delegate model, recursively inject hierarchy + if (args[kind][field]) { + if (args[kind][field] === true) { + // make sure the payload is an object + args[kind][field] = {}; + } + this.injectSelectIncludeHierarchy(fieldInfo.type, args[kind][field]); + } + } + + if (value !== undefined) { if (value?.orderBy) { // `orderBy` may contain fields from base types this.injectWhereHierarchy(fieldInfo.type, value.orderBy); @@ -1127,7 +1142,7 @@ export class DelegateProxyHandler extends DefaultPrismaProxyHandler { return destination; }; - const result = deepmerge(upMerged, downMerged, { + const result: any = deepmerge(upMerged, downMerged, { arrayMerge: combineMerge, isMergeableObject: (v) => isPlainObject(v) || Array.isArray(v), // avoid messing with Decimal, Date, etc. }); diff --git a/packages/runtime/src/enhancements/index.ts b/packages/runtime/src/enhancements/node/index.ts similarity index 75% rename from packages/runtime/src/enhancements/index.ts rename to packages/runtime/src/enhancements/node/index.ts index 3ddeddac0..a6f0e9446 100644 --- a/packages/runtime/src/enhancements/index.ts +++ b/packages/runtime/src/enhancements/node/index.ts @@ -1,4 +1,4 @@ -export * from '../cross'; +export * from '../../cross'; export * from './create-enhancement'; export * from './types'; export * from './utils'; diff --git a/packages/runtime/src/enhancements/logger.ts b/packages/runtime/src/enhancements/node/logger.ts similarity index 100% rename from packages/runtime/src/enhancements/logger.ts rename to packages/runtime/src/enhancements/node/logger.ts diff --git a/packages/runtime/src/enhancements/omit.ts b/packages/runtime/src/enhancements/node/omit.ts similarity index 58% rename from packages/runtime/src/enhancements/omit.ts rename to packages/runtime/src/enhancements/node/omit.ts index fa834166d..18c81cc18 100644 --- a/packages/runtime/src/enhancements/omit.ts +++ b/packages/runtime/src/enhancements/node/omit.ts @@ -1,8 +1,8 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { enumerate, getModelFields, resolveField } from '../cross'; -import { DbClientContract } from '../types'; +import { enumerate, getModelFields, resolveField } from '../../cross'; +import { DbClientContract } from '../../types'; import { InternalEnhancementOptions } from './create-enhancement'; import { DefaultPrismaProxyHandler, makeProxy } from './proxy'; @@ -26,8 +26,39 @@ class OmitHandler extends DefaultPrismaProxyHandler { } // base override - protected async processResultEntity(data: T): Promise { - if (data) { + protected async processResultEntity(method: string, data: T): Promise { + if (!data || typeof data !== 'object') { + return data; + } + + if (method === 'subscribe' || method === 'stream') { + if (!('action' in data)) { + return data; + } + + // Prisma Pulse result + switch (data.action) { + case 'create': + if ('created' in data) { + await this.doPostProcess(data.created, this.model); + } + break; + case 'update': + if ('before' in data) { + await this.doPostProcess(data.before, this.model); + } + if ('after' in data) { + await this.doPostProcess(data.after, this.model); + } + break; + case 'delete': + if ('deleted' in data) { + await this.doPostProcess(data.deleted, this.model); + } + break; + } + } else { + // regular prisma client result for (const value of enumerate(data)) { await this.doPostProcess(value, this.model); } diff --git a/packages/runtime/src/enhancements/password.ts b/packages/runtime/src/enhancements/node/password.ts similarity index 95% rename from packages/runtime/src/enhancements/password.ts rename to packages/runtime/src/enhancements/node/password.ts index 297613e1b..8c1aeb959 100644 --- a/packages/runtime/src/enhancements/password.ts +++ b/packages/runtime/src/enhancements/node/password.ts @@ -1,9 +1,9 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-unused-vars */ -import { DEFAULT_PASSWORD_SALT_LENGTH } from '../constants'; -import { NestedWriteVisitor, type PrismaWriteActionType } from '../cross'; -import { DbClientContract } from '../types'; +import { DEFAULT_PASSWORD_SALT_LENGTH } from '../../constants'; +import { NestedWriteVisitor, type PrismaWriteActionType } from '../../cross'; +import { DbClientContract } from '../../types'; import { InternalEnhancementOptions } from './create-enhancement'; import { DefaultPrismaProxyHandler, PrismaProxyActions, makeProxy } from './proxy'; diff --git a/packages/runtime/src/enhancements/node/policy/check-utils.ts b/packages/runtime/src/enhancements/node/policy/check-utils.ts new file mode 100644 index 000000000..bb8a2c88e --- /dev/null +++ b/packages/runtime/src/enhancements/node/policy/check-utils.ts @@ -0,0 +1,124 @@ +import { match, P } from 'ts-pattern'; +import { ModelMeta, requireField } from '..'; +import type { DbClientContract } from '../../../types'; +import { createDeferredPromise } from '../promise'; +import { PermissionCheckArgs, PermissionCheckerConstraint } from '../types'; +import { prismaClientValidationError } from '../utils'; +import { ConstraintSolver } from './constraint-solver'; +import { PolicyUtil } from './policy-utils'; + +export async function checkPermission( + model: string, + args: PermissionCheckArgs, + modelMeta: ModelMeta, + policyUtils: PolicyUtil, + prisma: DbClientContract, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + prismaModule: any +) { + return createDeferredPromise(() => doCheckPermission(model, args, modelMeta, policyUtils, prisma, prismaModule)); +} + +async function doCheckPermission( + model: string, + args: PermissionCheckArgs, + modelMeta: ModelMeta, + policyUtils: PolicyUtil, + prisma: DbClientContract, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + prismaModule: any +) { + if (!['create', 'read', 'update', 'delete'].includes(args.operation)) { + throw prismaClientValidationError(prisma, prismaModule, `Invalid "operation" ${args.operation}`); + } + + let constraint = policyUtils.getCheckerConstraint(model, args.operation); + if (typeof constraint === 'boolean') { + return constraint; + } + + if (args.where) { + // combine runtime filters with generated constraints + + const extraConstraints: PermissionCheckerConstraint[] = []; + for (const [field, value] of Object.entries(args.where)) { + if (value === undefined) { + continue; + } + + if (value === null) { + throw prismaClientValidationError( + prisma, + prismaModule, + `Using "null" as filter value is not supported yet` + ); + } + + const fieldInfo = requireField(modelMeta, model, field); + + // relation and array fields are not supported + if (fieldInfo.isDataModel || fieldInfo.isArray) { + throw prismaClientValidationError( + prisma, + prismaModule, + `Providing filter for field "${field}" is not supported. Only scalar fields are allowed.` + ); + } + + // map field type to constraint type + const fieldType = match(fieldInfo.type) + .with(P.union('Int', 'BigInt', 'Float', 'Decimal'), () => 'number') + .with('String', () => 'string') + .with('Boolean', () => 'boolean') + .otherwise(() => { + throw prismaClientValidationError( + prisma, + prismaModule, + `Providing filter for field "${field}" is not supported. Only number, string, and boolean fields are allowed.` + ); + }); + + // check value type + const valueType = typeof value; + if (valueType !== 'number' && valueType !== 'string' && valueType !== 'boolean') { + throw prismaClientValidationError( + prisma, + prismaModule, + `Invalid value type for field "${field}". Only number, string or boolean is allowed.` + ); + } + + if (fieldType !== valueType) { + throw prismaClientValidationError( + prisma, + prismaModule, + `Invalid value type for field "${field}". Expected "${fieldType}".` + ); + } + + // check number validity + if (typeof value === 'number' && (!Number.isInteger(value) || value < 0)) { + throw prismaClientValidationError( + prisma, + prismaModule, + `Invalid value for field "${field}". Only non-negative integers are allowed.` + ); + } + + // build a constraint + extraConstraints.push({ + kind: 'eq', + left: { kind: 'variable', name: field, type: fieldType }, + right: { kind: 'value', value, type: fieldType }, + }); + } + + if (extraConstraints.length > 0) { + // combine the constraints + constraint = { kind: 'and', children: [constraint, ...extraConstraints] }; + } + } + + // check satisfiability + return new ConstraintSolver().checkSat(constraint); +} diff --git a/packages/runtime/src/enhancements/policy/constraint-solver.ts b/packages/runtime/src/enhancements/node/policy/constraint-solver.ts similarity index 100% rename from packages/runtime/src/enhancements/policy/constraint-solver.ts rename to packages/runtime/src/enhancements/node/policy/constraint-solver.ts diff --git a/packages/runtime/src/enhancements/policy/handler.ts b/packages/runtime/src/enhancements/node/policy/handler.ts similarity index 91% rename from packages/runtime/src/enhancements/policy/handler.ts rename to packages/runtime/src/enhancements/node/policy/handler.ts index 4c5e5667f..999a7c9d9 100644 --- a/packages/runtime/src/enhancements/policy/handler.ts +++ b/packages/runtime/src/enhancements/node/policy/handler.ts @@ -3,10 +3,9 @@ import deepmerge from 'deepmerge'; import { lowerCaseFirst } from 'lower-case-first'; import invariant from 'tiny-invariant'; -import { P, match } from 'ts-pattern'; import { upperCaseFirst } from 'upper-case-first'; import { fromZodError } from 'zod-validation-error'; -import { CrudFailureReason } from '../../constants'; +import { CrudFailureReason } from '../../../constants'; import { ModelDataVisitor, NestedWriteVisitor, @@ -17,16 +16,16 @@ import { resolveField, type FieldInfo, type ModelMeta, -} from '../../cross'; -import { PolicyCrudKind, PolicyOperationKind, type CrudContract, type DbClientContract } from '../../types'; -import type { EnhancementContext, InternalEnhancementOptions } from '../create-enhancement'; +} from '../../../cross'; +import { EnhancementContext, PolicyOperationKind, type CrudContract, type DbClientContract } from '../../../types'; +import type { InternalEnhancementOptions } from '../create-enhancement'; import { Logger } from '../logger'; import { createDeferredPromise, createFluentPromise } from '../promise'; import { PrismaProxyHandler } from '../proxy'; import { QueryUtils } from '../query-utils'; -import type { EntityCheckerFunc, PermissionCheckerConstraint } from '../types'; +import type { EntityCheckerFunc, PermissionCheckArgs } from '../types'; import { formatObject, isUnsafeMutate, prismaClientValidationError } from '../utils'; -import { ConstraintSolver } from './constraint-solver'; +import { checkPermission } from './check-utils'; import { PolicyUtil } from './policy-utils'; // a record for post-write policy check @@ -39,12 +38,6 @@ type PostWriteCheckRecord = { type FindOperations = 'findUnique' | 'findUniqueOrThrow' | 'findFirst' | 'findFirstOrThrow' | 'findMany'; -// input arg type for `check` API -type PermissionCheckArgs = { - operation: PolicyCrudKind; - where?: Record; -}; - /** * Prisma proxy handler for injecting access policy check. */ @@ -1537,53 +1530,102 @@ export class PolicyProxyHandler implements Pr //#endregion - //#region Subscribe (Prisma Pulse) + //#region Prisma Pulse subscribe(args: any) { - return createDeferredPromise(() => { - const readGuard = this.policyUtils.getAuthGuard(this.prisma, this.model, 'read'); - if (this.policyUtils.isTrue(readGuard)) { - // no need to inject - if (this.shouldLogQuery) { - this.logger.info(`[policy] \`subscribe\` ${this.model}:\n${formatObject(args)}`); - } - return this.modelClient.subscribe(args); - } - - if (!args) { - // include all - args = { create: {}, update: {}, delete: {} }; - } else { - if (typeof args !== 'object') { - throw prismaClientValidationError(this.prisma, this.prismaModule, 'argument must be an object'); - } - if (Object.keys(args).length === 0) { - // include all - args = { create: {}, update: {}, delete: {} }; - } else { - args = this.policyUtils.safeClone(args); - } - } + return this.handleSubscribeStream('subscribe', args); + } - // inject into subscribe conditions + stream(args: any) { + return this.handleSubscribeStream('stream', args); + } - if (args.create) { - args.create.after = this.policyUtils.and(args.create.after, readGuard); + private async handleSubscribeStream(action: 'subscribe' | 'stream', args: any) { + if (!args) { + // include all + args = { create: {}, update: {}, delete: {} }; + } else { + if (typeof args !== 'object') { + throw prismaClientValidationError(this.prisma, this.prismaModule, 'argument must be an object'); } + args = this.policyUtils.safeClone(args); + } - if (args.update) { - args.update.after = this.policyUtils.and(args.update.after, readGuard); + // inject read guard as subscription filter + for (const key of ['create', 'update', 'delete']) { + if (args[key] === undefined) { + continue; } - - if (args.delete) { - args.delete.before = this.policyUtils.and(args.delete.before, readGuard); + // "update" has an extra layer of "after" + const payload = key === 'update' ? args[key].after : args[key]; + const toInject = { where: payload }; + this.policyUtils.injectForRead(this.prisma, this.model, toInject); + if (key === 'update') { + // "update" has an extra layer of "after" + args[key].after = toInject.where; + } else { + args[key] = toInject.where; } + } - if (this.shouldLogQuery) { - this.logger.info(`[policy] \`subscribe\` ${this.model}:\n${formatObject(args)}`); - } - return this.modelClient.subscribe(args); - }); + if (this.shouldLogQuery) { + this.logger.info(`[policy] \`${action}\` ${this.model}:\n${formatObject(args)}`); + } + + // Prisma Pulse returns an async iterable, which we need to wrap + // and post-process the iteration results + const iterable = await this.modelClient[action](args); + return { + [Symbol.asyncIterator]: () => { + const iter = iterable[Symbol.asyncIterator].bind(iterable)(); + return { + next: async () => { + const { done, value } = await iter.next(); + let processedValue = value; + if (value && 'action' in value) { + switch (value.action) { + case 'create': + if ('created' in value) { + processedValue = { + ...value, + created: this.policyUtils.postProcessForRead(value.created, this.model, {}), + }; + } + break; + + case 'update': + if ('before' in value) { + processedValue = { + ...value, + before: this.policyUtils.postProcessForRead(value.before, this.model, {}), + }; + } + if ('after' in value) { + processedValue = { + ...value, + after: this.policyUtils.postProcessForRead(value.after, this.model, {}), + }; + } + break; + + case 'delete': + if ('deleted' in value) { + processedValue = { + ...value, + deleted: this.policyUtils.postProcessForRead(value.deleted, this.model, {}), + }; + } + break; + } + } + + return { done, value: processedValue }; + }, + return: () => iter.return?.(), + throw: () => iter.throw?.(), + }; + }, + }; } //#endregion @@ -1596,103 +1638,7 @@ export class PolicyProxyHandler implements Pr * @param fieldValues Extra field value filters to be combined with the policy constraints. */ async check(args: PermissionCheckArgs): Promise { - return createDeferredPromise(() => this.doCheck(args)); - } - - private async doCheck(args: PermissionCheckArgs) { - if (!['create', 'read', 'update', 'delete'].includes(args.operation)) { - throw prismaClientValidationError(this.prisma, this.prismaModule, `Invalid "operation" ${args.operation}`); - } - - let constraint = this.policyUtils.getCheckerConstraint(this.model, args.operation); - if (typeof constraint === 'boolean') { - return constraint; - } - - if (args.where) { - // combine runtime filters with generated constraints - - const extraConstraints: PermissionCheckerConstraint[] = []; - for (const [field, value] of Object.entries(args.where)) { - if (value === undefined) { - continue; - } - - if (value === null) { - throw prismaClientValidationError( - this.prisma, - this.prismaModule, - `Using "null" as filter value is not supported yet` - ); - } - - const fieldInfo = requireField(this.modelMeta, this.model, field); - - // relation and array fields are not supported - if (fieldInfo.isDataModel || fieldInfo.isArray) { - throw prismaClientValidationError( - this.prisma, - this.prismaModule, - `Providing filter for field "${field}" is not supported. Only scalar fields are allowed.` - ); - } - - // map field type to constraint type - const fieldType = match(fieldInfo.type) - .with(P.union('Int', 'BigInt', 'Float', 'Decimal'), () => 'number') - .with('String', () => 'string') - .with('Boolean', () => 'boolean') - .otherwise(() => { - throw prismaClientValidationError( - this.prisma, - this.prismaModule, - `Providing filter for field "${field}" is not supported. Only number, string, and boolean fields are allowed.` - ); - }); - - // check value type - const valueType = typeof value; - if (valueType !== 'number' && valueType !== 'string' && valueType !== 'boolean') { - throw prismaClientValidationError( - this.prisma, - this.prismaModule, - `Invalid value type for field "${field}". Only number, string or boolean is allowed.` - ); - } - - if (fieldType !== valueType) { - throw prismaClientValidationError( - this.prisma, - this.prismaModule, - `Invalid value type for field "${field}". Expected "${fieldType}".` - ); - } - - // check number validity - if (typeof value === 'number' && (!Number.isInteger(value) || value < 0)) { - throw prismaClientValidationError( - this.prisma, - this.prismaModule, - `Invalid value for field "${field}". Only non-negative integers are allowed.` - ); - } - - // build a constraint - extraConstraints.push({ - kind: 'eq', - left: { kind: 'variable', name: field, type: fieldType }, - right: { kind: 'value', value, type: fieldType }, - }); - } - - if (extraConstraints.length > 0) { - // combine the constraints - constraint = { kind: 'and', children: [constraint, ...extraConstraints] }; - } - } - - // check satisfiability - return new ConstraintSolver().checkSat(constraint); + return checkPermission(this.model, args, this.modelMeta, this.policyUtils, this.prisma, this.prismaModule); } //#endregion diff --git a/packages/runtime/src/enhancements/policy/index.ts b/packages/runtime/src/enhancements/node/policy/index.ts similarity index 88% rename from packages/runtime/src/enhancements/policy/index.ts rename to packages/runtime/src/enhancements/node/policy/index.ts index c76812a51..66834a802 100644 --- a/packages/runtime/src/enhancements/policy/index.ts +++ b/packages/runtime/src/enhancements/node/policy/index.ts @@ -1,9 +1,9 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { getIdFields } from '../../cross'; -import { DbClientContract } from '../../types'; -import { hasAllFields } from '../../validation'; -import type { EnhancementContext, InternalEnhancementOptions } from '../create-enhancement'; +import { getIdFields } from '../../../cross'; +import { DbClientContract, EnhancementContext } from '../../../types'; +import { hasAllFields } from '../../../validation'; +import type { InternalEnhancementOptions } from '../create-enhancement'; import { Logger } from '../logger'; import { makeProxy } from '../proxy'; import { PolicyProxyHandler } from './handler'; diff --git a/packages/runtime/src/enhancements/policy/logic-solver.d.ts b/packages/runtime/src/enhancements/node/policy/logic-solver.d.ts similarity index 100% rename from packages/runtime/src/enhancements/policy/logic-solver.d.ts rename to packages/runtime/src/enhancements/node/policy/logic-solver.d.ts diff --git a/packages/runtime/src/enhancements/policy/policy-utils.ts b/packages/runtime/src/enhancements/node/policy/policy-utils.ts similarity index 96% rename from packages/runtime/src/enhancements/policy/policy-utils.ts rename to packages/runtime/src/enhancements/node/policy/policy-utils.ts index 79c50b6c9..ab4ed8fc2 100644 --- a/packages/runtime/src/enhancements/policy/policy-utils.ts +++ b/packages/runtime/src/enhancements/node/policy/policy-utils.ts @@ -1,11 +1,12 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import deepmerge from 'deepmerge'; +import { isPlainObject } from 'is-plain-object'; import { lowerCaseFirst } from 'lower-case-first'; import { upperCaseFirst } from 'upper-case-first'; import { z, type ZodError, type ZodObject, type ZodSchema } from 'zod'; import { fromZodError } from 'zod-validation-error'; -import { CrudFailureReason, PrismaErrorCode } from '../../constants'; +import { CrudFailureReason, PrismaErrorCode } from '../../../constants'; import { clone, enumerate, @@ -15,22 +16,23 @@ import { zip, type FieldInfo, type ModelMeta, -} from '../../cross'; +} from '../../../cross'; import { AuthUser, CrudContract, DbClientContract, + EnhancementContext, PolicyCrudKind, PolicyOperationKind, QueryContext, -} from '../../types'; -import { getVersion } from '../../version'; -import type { EnhancementContext, InternalEnhancementOptions } from '../create-enhancement'; + ZodSchemas, +} from '../../../types'; +import { getVersion } from '../../../version'; +import type { InternalEnhancementOptions } from '../create-enhancement'; import { Logger } from '../logger'; import { QueryUtils } from '../query-utils'; -import type { EntityChecker, ModelPolicyDef, PermissionCheckerFunc, PolicyDef, PolicyFunc, ZodSchemas } from '../types'; +import type { EntityChecker, ModelPolicyDef, PermissionCheckerFunc, PolicyDef, PolicyFunc } from '../types'; import { formatObject, prismaClientKnownRequestError } from '../utils'; -import { isPlainObject } from 'is-plain-object'; /** * Access policy enforcement utilities @@ -473,10 +475,11 @@ export class PolicyUtil extends QueryUtils { let mergedGuard = guard; if (args.where) { - // inject into relation fields: + // inject into fields: // to-many: some/none/every // to-one: direct-conditions/is/isNot - mergedGuard = this.injectReadGuardForRelationFields(db, model, args.where, guard); + // regular fields + mergedGuard = this.buildReadGuardForFields(db, model, args.where, guard); } args.where = this.and(args.where, mergedGuard); @@ -485,7 +488,7 @@ export class PolicyUtil extends QueryUtils { // Injects guard for relation fields nested in `payload`. The `modelGuard` parameter represents the model-level guard for `model`. // The function returns a modified copy of `modelGuard` with field-level policies combined. - private injectReadGuardForRelationFields(db: CrudContract, model: string, payload: any, modelGuard: any) { + private buildReadGuardForFields(db: CrudContract, model: string, payload: any, modelGuard: any) { if (!payload || typeof payload !== 'object' || Object.keys(payload).length === 0) { return modelGuard; } @@ -530,12 +533,12 @@ export class PolicyUtil extends QueryUtils { ) { const guard = this.getAuthGuard(db, fieldInfo.type, 'read'); if (payload.some) { - const mergedGuard = this.injectReadGuardForRelationFields(db, fieldInfo.type, payload.some, guard); + const mergedGuard = this.buildReadGuardForFields(db, fieldInfo.type, payload.some, guard); // turn "some" into: { some: { AND: [guard, payload.some] } } payload.some = this.and(payload.some, mergedGuard); } if (payload.none) { - const mergedGuard = this.injectReadGuardForRelationFields(db, fieldInfo.type, payload.none, guard); + const mergedGuard = this.buildReadGuardForFields(db, fieldInfo.type, payload.none, guard); // turn none into: { none: { AND: [guard, payload.none] } } payload.none = this.and(payload.none, mergedGuard); } @@ -545,7 +548,7 @@ export class PolicyUtil extends QueryUtils { // ignore empty every clause Object.keys(payload.every).length > 0 ) { - const mergedGuard = this.injectReadGuardForRelationFields(db, fieldInfo.type, payload.every, guard); + const mergedGuard = this.buildReadGuardForFields(db, fieldInfo.type, payload.every, guard); // turn "every" into: { none: { AND: [guard, { NOT: payload.every }] } } if (!payload.none) { @@ -569,18 +572,18 @@ export class PolicyUtil extends QueryUtils { if (payload.is !== undefined || payload.isNot !== undefined) { if (payload.is) { - const mergedGuard = this.injectReadGuardForRelationFields(db, fieldInfo.type, payload.is, guard); + const mergedGuard = this.buildReadGuardForFields(db, fieldInfo.type, payload.is, guard); // merge guard with existing "is": { is: { AND: [originalIs, guard] } } payload.is = this.and(payload.is, mergedGuard); } if (payload.isNot) { - const mergedGuard = this.injectReadGuardForRelationFields(db, fieldInfo.type, payload.isNot, guard); + const mergedGuard = this.buildReadGuardForFields(db, fieldInfo.type, payload.isNot, guard); // merge guard with existing "isNot": { isNot: { AND: [originalIsNot, guard] } } payload.isNot = this.and(payload.isNot, mergedGuard); } } else { - const mergedGuard = this.injectReadGuardForRelationFields(db, fieldInfo.type, payload, guard); + const mergedGuard = this.buildReadGuardForFields(db, fieldInfo.type, payload, guard); // turn direct conditions into: { is: { AND: [ originalConditions, guard ] } } const combined = this.and(clone(payload), mergedGuard); Object.keys(payload).forEach((key) => delete payload[key]); @@ -595,22 +598,27 @@ export class PolicyUtil extends QueryUtils { // make select and include visible to the injection const injected: any = { select: args.select, include: args.include }; if (!this.injectAuthGuardAsWhere(db, injected, model, 'read')) { + args.where = this.makeFalse(); return false; } if (args.where) { - // inject into relation fields: + // inject into fields: // to-many: some/none/every // to-one: direct-conditions/is/isNot - this.injectReadGuardForRelationFields(db, model, args.where, {}); + // regular fields + const mergedGuard = this.buildReadGuardForFields(db, model, args.where, {}); + this.mergeWhereClause(args.where, mergedGuard); } - if (injected.where && Object.keys(injected.where).length > 0 && !this.isTrue(injected.where)) { - if (!args.where) { - args.where = injected.where; - } else { + if (args.where) { + if (injected.where && Object.keys(injected.where).length > 0) { + // merge injected guard with the user-provided where clause this.mergeWhereClause(args.where, injected.where); } + } else if (injected.where) { + // no user-provided where clause, use the injected one + args.where = injected.where; } // recursively inject read guard conditions into nested select, include, and _count @@ -1214,7 +1222,7 @@ export class PolicyUtil extends QueryUtils { reason?: CrudFailureReason, zodErrors?: ZodError ) { - const args: any = { clientVersion: getVersion(), code: PrismaErrorCode.CONSTRAINED_FAILED, meta: {} }; + const args: any = { clientVersion: getVersion(), code: PrismaErrorCode.CONSTRAINT_FAILED, meta: {} }; if (reason) { args.meta.reason = reason; } diff --git a/packages/runtime/src/enhancements/promise.ts b/packages/runtime/src/enhancements/node/promise.ts similarity index 98% rename from packages/runtime/src/enhancements/promise.ts rename to packages/runtime/src/enhancements/node/promise.ts index 28a211146..471fcb642 100644 --- a/packages/runtime/src/enhancements/promise.ts +++ b/packages/runtime/src/enhancements/node/promise.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { getModelInfo, type ModelMeta } from '../cross'; +import { getModelInfo, type ModelMeta } from '../../cross'; /** * Creates a promise that only executes when it's awaited or .then() is called. diff --git a/packages/runtime/src/enhancements/proxy.ts b/packages/runtime/src/enhancements/node/proxy.ts similarity index 87% rename from packages/runtime/src/enhancements/proxy.ts rename to packages/runtime/src/enhancements/node/proxy.ts index f99cdfab4..3802e2390 100644 --- a/packages/runtime/src/enhancements/proxy.ts +++ b/packages/runtime/src/enhancements/node/proxy.ts @@ -1,9 +1,8 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { PRISMA_PROXY_ENHANCER } from '../constants'; -import type { ModelMeta } from '../cross'; -import { clone } from '../cross'; -import type { DbClientContract } from '../types'; +import { PRISMA_PROXY_ENHANCER } from '../../constants'; +import { type ModelMeta, clone } from '../../cross'; +import type { DbClientContract, ErrorTransformer } from '../../types'; import type { InternalEnhancementOptions } from './create-enhancement'; import { createDeferredPromise, createFluentPromise } from './promise'; @@ -12,11 +11,6 @@ import { createDeferredPromise, createFluentPromise } from './promise'; */ export type BatchResult = { count: number }; -/** - * Function for transforming errors. - */ -export type ErrorTransformer = (error: unknown) => unknown; - /** * Interface for proxy that intercepts Prisma operations. */ @@ -54,6 +48,8 @@ export interface PrismaProxyHandler { count(args: any): Promise; subscribe(args: any): Promise; + + stream(args: any): Promise; } /** @@ -79,7 +75,7 @@ export class DefaultPrismaProxyHandler implements PrismaProxyHandler { async () => { args = await this.preprocessArgs(method, args); const r = await this.prisma[this.model][method](args); - return postProcess ? this.processResultEntity(r) : r; + return postProcess ? this.processResultEntity(method, r) : r; }, args, this.options.modelMeta, @@ -92,7 +88,7 @@ export class DefaultPrismaProxyHandler implements PrismaProxyHandler { return createDeferredPromise(async () => { args = await this.preprocessArgs(method, args); const r = await this.prisma[this.model][method](args); - return postProcess ? this.processResultEntity(r) : r; + return postProcess ? this.processResultEntity(method, r) : r; }); } @@ -161,20 +157,44 @@ export class DefaultPrismaProxyHandler implements PrismaProxyHandler { } subscribe(args: any) { - return this.deferred('subscribe', args, false); + return this.doSubscribeStream('subscribe', args); + } + + stream(args: any) { + return this.doSubscribeStream('stream', args); + } + + private async doSubscribeStream(method: 'subscribe' | 'stream', args: any) { + // Prisma's `subscribe` and `stream` methods return an async iterable + // which we need to wrap to process the iteration results + const iterable = await this.prisma[this.model][method](args); + return { + [Symbol.asyncIterator]: () => { + const iter = iterable[Symbol.asyncIterator].bind(iterable)(); + return { + next: async () => { + const { done, value } = await iter.next(); + const processedValue = value ? await this.processResultEntity(method, value) : value; + return { done, value: processedValue }; + }, + return: () => iter.return?.(), + throw: () => iter.throw?.(), + }; + }, + }; } /** * Processes result entities before they're returned */ - protected async processResultEntity(data: T): Promise { + protected async processResultEntity(_method: PrismaProxyActions, data: T): Promise { return data; } /** * Processes query args before they're passed to Prisma. */ - protected async preprocessArgs(method: PrismaProxyActions, args: any) { + protected async preprocessArgs(_method: PrismaProxyActions, args: any) { return args; } } diff --git a/packages/runtime/src/enhancements/query-utils.ts b/packages/runtime/src/enhancements/node/query-utils.ts similarity index 98% rename from packages/runtime/src/enhancements/query-utils.ts rename to packages/runtime/src/enhancements/node/query-utils.ts index e7864ceac..5d23c6d99 100644 --- a/packages/runtime/src/enhancements/query-utils.ts +++ b/packages/runtime/src/enhancements/node/query-utils.ts @@ -1,15 +1,15 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { + clone, getIdFields, getModelInfo, getUniqueConstraints, resolveField, type FieldInfo, type NestedWriteVisitorContext, -} from '../cross'; -import { clone } from '../cross'; -import type { CrudContract, DbClientContract } from '../types'; -import { getVersion } from '../version'; +} from '../../cross'; +import type { CrudContract, DbClientContract } from '../../types'; +import { getVersion } from '../../version'; import { InternalEnhancementOptions } from './create-enhancement'; import { prismaClientUnknownRequestError, prismaClientValidationError } from './utils'; diff --git a/packages/runtime/src/enhancements/types.ts b/packages/runtime/src/enhancements/node/types.ts similarity index 93% rename from packages/runtime/src/enhancements/types.ts rename to packages/runtime/src/enhancements/node/types.ts index a5cd85314..37a304b99 100644 --- a/packages/runtime/src/enhancements/types.ts +++ b/packages/runtime/src/enhancements/node/types.ts @@ -1,6 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { z } from 'zod'; -import type { CrudContract, PermissionCheckerContext, QueryContext } from '../types'; +import type { CrudContract, PermissionCheckerContext, PolicyCrudKind, QueryContext } from '../../types'; /** * Common options for PrismaClient enhancements @@ -258,16 +257,9 @@ type FieldUpdateDef = { }; /** - * Zod schemas for validation + * Permission check API (`check()`) arguments */ -export type ZodSchemas = { - /** - * Zod schema for each model - */ - models: Record; - - /** - * Zod schema for Prisma input types for each model - */ - input?: Record>; +export type PermissionCheckArgs = { + operation: PolicyCrudKind; + where?: Record; }; diff --git a/packages/runtime/src/enhancements/utils.ts b/packages/runtime/src/enhancements/node/utils.ts similarity index 96% rename from packages/runtime/src/enhancements/utils.ts rename to packages/runtime/src/enhancements/node/utils.ts index 50b53b996..347447618 100644 --- a/packages/runtime/src/enhancements/utils.ts +++ b/packages/runtime/src/enhancements/node/utils.ts @@ -1,6 +1,6 @@ import safeJsonStringify from 'safe-json-stringify'; -import { resolveField, type FieldInfo, type ModelMeta } from '..'; -import type { DbClientContract } from '../types'; +import { resolveField, type FieldInfo, type ModelMeta } from '../../cross'; +import type { DbClientContract } from '../../types'; /** * Formats an object for pretty printing. diff --git a/packages/runtime/src/enhancements/where-visitor.ts b/packages/runtime/src/enhancements/node/where-visitor.ts similarity index 99% rename from packages/runtime/src/enhancements/where-visitor.ts rename to packages/runtime/src/enhancements/node/where-visitor.ts index 17a7ec3bc..71b303985 100644 --- a/packages/runtime/src/enhancements/where-visitor.ts +++ b/packages/runtime/src/enhancements/node/where-visitor.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { enumerate, resolveField, type FieldInfo, type ModelMeta } from '../cross'; +import { enumerate, resolveField, type FieldInfo, type ModelMeta } from '../../cross'; /** * Context for visiting diff --git a/packages/runtime/src/index.ts b/packages/runtime/src/index.ts index 6a2609156..a735da875 100644 --- a/packages/runtime/src/index.ts +++ b/packages/runtime/src/index.ts @@ -1,7 +1,7 @@ export * from './constants'; -export * from './enhancements'; +export * from './cross'; +export * from './enhance'; export * from './error'; export * from './types'; export * from './validation'; export * from './version'; -export * from './enhance'; diff --git a/packages/runtime/src/types.ts b/packages/runtime/src/types.ts index bf1660090..7c4df97c1 100644 --- a/packages/runtime/src/types.ts +++ b/packages/runtime/src/types.ts @@ -1,5 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ +import type { z } from 'zod'; + export type PrismaPromise = Promise & Record PrismaPromise>; /** @@ -23,6 +25,7 @@ export interface DbOperations { groupBy(args: unknown): Promise; count(args?: unknown): Promise; subscribe(args?: unknown): Promise; + stream(args?: unknown): Promise; check(args: unknown): Promise; fields: Record; } @@ -86,3 +89,80 @@ export type CrudContract = Record; export type DbClientContract = CrudContract & { $transaction: (action: (tx: CrudContract) => Promise, options?: unknown) => Promise; }; + +/** + * Transaction isolation levels: https://www.prisma.io/docs/orm/prisma-client/queries/transactions#transaction-isolation-level + */ +export type TransactionIsolationLevel = + | 'ReadUncommitted' + | 'ReadCommitted' + | 'RepeatableRead' + | 'Snapshot' + | 'Serializable'; + +/** + * Options for enhancing a PrismaClient. + */ +export type EnhancementOptions = { + /** + * The kinds of enhancements to apply. By default all enhancements are applied. + */ + kinds?: EnhancementKind[]; + + /** + * Whether to log Prisma query + */ + logPrismaQuery?: boolean; + + /** + * Hook for transforming errors before they are thrown to the caller. + */ + errorTransformer?: ErrorTransformer; + + /** + * The `maxWait` option passed to `prisma.$transaction()` call for transactions initiated by ZenStack. + */ + transactionMaxWait?: number; + + /** + * The `timeout` option passed to `prisma.$transaction()` call for transactions initiated by ZenStack. + */ + transactionTimeout?: number; + + /** + * The `isolationLevel` option passed to `prisma.$transaction()` call for transactions initiated by ZenStack. + */ + transactionIsolationLevel?: TransactionIsolationLevel; +}; + +/** + * Context for creating enhanced `PrismaClient` + */ +export type EnhancementContext = { + user?: User; +}; + +/** + * Kinds of enhancements to `PrismaClient` + */ +export type EnhancementKind = 'password' | 'omit' | 'policy' | 'validation' | 'delegate'; + +/** + * Function for transforming errors. + */ +export type ErrorTransformer = (error: unknown) => unknown; + +/** + * Zod schemas for validation + */ +export type ZodSchemas = { + /** + * Zod schema for each model + */ + models: Record; + + /** + * Zod schema for Prisma input types for each model + */ + input?: Record>; +}; diff --git a/packages/schema/package.json b/packages/schema/package.json index d669567f3..75b71d619 100644 --- a/packages/schema/package.json +++ b/packages/schema/package.json @@ -2,8 +2,8 @@ "name": "zenstack", "publisher": "zenstack", "displayName": "ZenStack Language Tools", - "description": "Build scalable web apps with minimum code by defining authorization and validation rules inside the data schema that closer to the database", - "version": "2.4.1", + "description": "FullStack enhancement for Prisma ORM: seamless integration from database to UI", + "version": "2.5.0", "author": { "name": "ZenStack Team" }, @@ -13,7 +13,8 @@ "fullstack", "react", "typescript", - "data modeling" + "data modeling", + "prisma" ], "preview": false, "icon": "asset/logo-256-bg.png", @@ -107,6 +108,7 @@ "semver": "^7.5.2", "sleep-promise": "^9.1.0", "strip-color": "^0.1.0", + "terminal-link": "^2.0.0", "tiny-invariant": "^1.3.1", "ts-morph": "^16.0.0", "ts-pattern": "^4.3.0", @@ -121,10 +123,10 @@ "zod-validation-error": "^1.5.0" }, "peerDependencies": { - "prisma": "5.0.0 - 5.18.x" + "prisma": "5.0.0 - 5.19.x" }, "devDependencies": { - "@prisma/client": "5.18.x", + "@prisma/client": "5.19.x", "@types/async-exit-hook": "^2.0.0", "@types/pluralize": "^0.0.29", "@types/semver": "^7.3.13", diff --git a/packages/schema/src/cli/actions/check.ts b/packages/schema/src/cli/actions/check.ts new file mode 100644 index 000000000..df161b5c0 --- /dev/null +++ b/packages/schema/src/cli/actions/check.ts @@ -0,0 +1,14 @@ +import { getDefaultSchemaLocation, loadDocument } from '../cli-util'; + +type Options = { + schema: string; +}; + +/** + * CLI action for checking schema + */ +export async function check(_projectPath: string, options: Options) { + const schema = options.schema ?? getDefaultSchemaLocation(); + await loadDocument(schema); + console.log('The schema is valid.'); +} diff --git a/packages/schema/src/cli/actions/generate.ts b/packages/schema/src/cli/actions/generate.ts index 4da84c05d..d697504ee 100644 --- a/packages/schema/src/cli/actions/generate.ts +++ b/packages/schema/src/cli/actions/generate.ts @@ -1,4 +1,5 @@ import { PluginError } from '@zenstackhq/sdk'; +import { isPlugin } from '@zenstackhq/sdk/ast'; import colors from 'colors'; import path from 'path'; import { CliError } from '../cli-error'; @@ -9,6 +10,7 @@ import { getZenStackPackages, loadDocument, requiredPrismaVersion, + showNotification, } from '../cli-util'; import { PluginRunner, PluginRunnerOptions } from '../plugin-runner'; @@ -18,7 +20,10 @@ type Options = { dependencyCheck: boolean; versionCheck: boolean; compile: boolean; + withPlugins?: string[]; + withoutPlugins?: string[]; defaultPlugins: boolean; + offline?: boolean; }; /** @@ -45,11 +50,19 @@ export async function generate(projectPath: string, options: Options) { await runPlugins(options); - if (options.versionCheck) { - // note that we can't run plugins and do version check concurrently because - // plugins are CPU-bound and can cause version check to false timeout - await checkNewVersion(); + // note that we can't run online jobs concurrently with plugins because + // plugins are CPU-bound and can cause false timeout + const postJobs: Promise[] = []; + + if (options.versionCheck && !options.offline) { + postJobs.push(checkNewVersion()); + } + + if (!options.offline) { + postJobs.push(showNotification()); } + + await Promise.all(postJobs); } async function runPlugins(options: Options) { @@ -57,9 +70,19 @@ async function runPlugins(options: Options) { const model = await loadDocument(schema); + for (const name of [...(options.withPlugins ?? []), ...(options.withoutPlugins ?? [])]) { + const pluginDecl = model.declarations.find((d) => isPlugin(d) && d.name === name); + if (!pluginDecl) { + console.error(colors.red(`Plugin "${name}" not found in schema.`)); + throw new CliError(`Plugin "${name}" not found in schema.`); + } + } + const runnerOpts: PluginRunnerOptions = { schema: model, schemaPath: path.resolve(schema), + withPlugins: options.withPlugins, + withoutPlugins: options.withoutPlugins, defaultPlugins: options.defaultPlugins, output: options.output, compile: options.compile, diff --git a/packages/schema/src/cli/actions/index.ts b/packages/schema/src/cli/actions/index.ts index e56e4797c..7e172d4bc 100644 --- a/packages/schema/src/cli/actions/index.ts +++ b/packages/schema/src/cli/actions/index.ts @@ -1,5 +1,6 @@ +export * from './check'; +export * from './format'; export * from './generate'; export * from './info'; export * from './init'; export * from './repl'; -export * from './format'; diff --git a/packages/schema/src/cli/cli-util.ts b/packages/schema/src/cli/cli-util.ts index 7309aa49a..43216656e 100644 --- a/packages/schema/src/cli/cli-util.ts +++ b/packages/schema/src/cli/cli-util.ts @@ -6,8 +6,10 @@ import { getDocument, LangiumDocument, LangiumDocuments, linkContentToContainer import { NodeFileSystem } from 'langium/node'; import path from 'path'; import semver from 'semver'; +import terminalLink from 'terminal-link'; import { TextDocument } from 'vscode-languageserver-textdocument'; import { URI } from 'vscode-uri'; +import { z } from 'zod'; import { PLUGIN_MODULE_NAME, STD_LIB_MODULE_NAME } from '../language-server/constants'; import { ZModelFormatter } from '../language-server/zmodel-formatter'; import { createZModelServices, ZModelServices } from '../language-server/zmodel-module'; @@ -20,6 +22,8 @@ import { CliError } from './cli-error'; export const requiredPrismaVersion = '4.8.0'; const CHECK_VERSION_TIMEOUT = 1000; +const FETCH_CLI_CONFIG_TIMEOUT = 500; +const CLI_CONFIG_ENDPOINT = 'https://zenstack.dev/config/cli.json'; /** * Loads a zmodel document from a file. @@ -27,7 +31,7 @@ const CHECK_VERSION_TIMEOUT = 1000; * @param services Language services * @returns Parsed and validated AST */ -export async function loadDocument(fileName: string): Promise { +export async function loadDocument(fileName: string, validateOnly = false): Promise { const services = createZModelServices(NodeFileSystem).ZModel; const extensions = services.LanguageMetaData.fileExtensions; if (!extensions.includes(path.extname(fileName))) { @@ -93,6 +97,10 @@ export async function loadDocument(fileName: string): Promise { const model = document.parseResult.value as Model; + if (validateOnly) { + return model; + } + // merge all declarations into the main document const imported = mergeImportsDeclarations(langiumDocuments, model); @@ -360,3 +368,33 @@ async function relinkAll(model: Model, services: ZModelServices) { return newDoc.parseResult.value as Model; } + +export async function showNotification() { + try { + const fetchResult = await fetch(CLI_CONFIG_ENDPOINT, { + headers: { accept: 'application/json' }, + signal: AbortSignal.timeout(FETCH_CLI_CONFIG_TIMEOUT), + }); + + if (!fetchResult.ok) { + return; + } + + const data = await fetchResult.json(); + const schema = z.object({ + notifications: z.array(z.object({ title: z.string(), url: z.string().url(), active: z.boolean() })), + }); + const parseResult = schema.safeParse(data); + + if (parseResult.success) { + const activeItems = parseResult.data.notifications.filter((item) => item.active); + // return a random active item + if (activeItems.length > 0) { + const item = activeItems[Math.floor(Math.random() * activeItems.length)]; + console.log(terminalLink(item.title, item.url)); + } + } + } catch { + // noop + } +} diff --git a/packages/schema/src/cli/index.ts b/packages/schema/src/cli/index.ts index f430f7662..e8773fddd 100644 --- a/packages/schema/src/cli/index.ts +++ b/packages/schema/src/cli/index.ts @@ -60,6 +60,16 @@ export const formatAction = async (options: Parameters[1] ); }; +export const checkAction = async (options: Parameters[1]): Promise => { + await telemetry.trackSpan( + 'cli:command:start', + 'cli:command:complete', + 'cli:command:error', + { command: 'check' }, + () => actions.check(process.cwd(), options) + ); +}; + export function createProgram() { const program = new Command('zenstack'); @@ -87,7 +97,8 @@ export function createProgram() { 'pnpm', ]); const noVersionCheckOption = new Option('--no-version-check', 'do not check for new version'); - const noDependencyCheck = new Option('--no-dependency-check', 'do not check if dependencies are installed'); + const noDependencyCheckOption = new Option('--no-dependency-check', 'do not check if dependencies are installed'); + const offlineOption = new Option('--offline', 'run in offline mode'); program .command('info') @@ -110,10 +121,13 @@ export function createProgram() { .description('Run code generation.') .addOption(schemaOption) .addOption(new Option('-o, --output ', 'default output directory for core plugins')) + .addOption(new Option('--with-plugins ', 'only run specific plugins')) + .addOption(new Option('--without-plugins ', 'exclude specific plugins')) .addOption(new Option('--no-default-plugins', 'do not run default plugins')) .addOption(new Option('--no-compile', 'do not compile the output of core plugins')) .addOption(noVersionCheckOption) - .addOption(noDependencyCheck) + .addOption(noDependencyCheckOption) + .addOption(offlineOption) .action(generateAction); program @@ -131,6 +145,12 @@ export function createProgram() { .option('--no-prisma-style', 'do not use prisma style') .action(formatAction); + program + .command('check') + .description('Check a ZenStack schema file for syntax or semantic errors.') + .addOption(schemaOption) + .action(checkAction); + // make sure config is loaded before actions run program.hook('preAction', async (_, actionCommand) => { let configFile: string | undefined = actionCommand.opts().config; diff --git a/packages/schema/src/cli/plugin-runner.ts b/packages/schema/src/cli/plugin-runner.ts index ea00809fe..2912bfb60 100644 --- a/packages/schema/src/cli/plugin-runner.ts +++ b/packages/schema/src/cli/plugin-runner.ts @@ -40,6 +40,8 @@ export type PluginRunnerOptions = { schema: Model; schemaPath: string; output?: string; + withPlugins?: string[]; + withoutPlugins?: string[]; defaultPlugins: boolean; compile: boolean; }; @@ -137,7 +139,17 @@ export class PluginRunner { const project = createProject(); for (const { name, description, run, options: pluginOptions } of corePlugins) { const options = { ...pluginOptions, prismaClientPath }; - const r = await this.runPlugin(name, description, run, runnerOptions, options, dmmf, shortNameMap, project); + const r = await this.runPlugin( + name, + description, + run, + runnerOptions, + options, + dmmf, + shortNameMap, + project, + true + ); warnings.push(...(r?.warnings ?? [])); // the null-check is for backward compatibility if (r.dmmf) { @@ -162,7 +174,17 @@ export class PluginRunner { // run user plugins for (const { name, description, run, options: pluginOptions } of userPlugins) { const options = { ...pluginOptions, prismaClientPath }; - const r = await this.runPlugin(name, description, run, runnerOptions, options, dmmf, shortNameMap, project); + const r = await this.runPlugin( + name, + description, + run, + runnerOptions, + options, + dmmf, + shortNameMap, + project, + false + ); warnings.push(...(r?.warnings ?? [])); // the null-check is for backward compatibility } @@ -180,8 +202,7 @@ export class PluginRunner { if (existingPrisma) { corePlugins.push(existingPrisma); plugins.splice(plugins.indexOf(existingPrisma), 1); - } else if (options.defaultPlugins || plugins.some((p) => p.provider !== CorePlugins.Prisma)) { - // "@core/prisma" is enabled as default or if any other plugin is configured + } else if (options.defaultPlugins) { corePlugins.push(this.makeCorePlugin(CorePlugins.Prisma, options.schemaPath, {})); } @@ -215,7 +236,8 @@ export class PluginRunner { if ( !corePlugins.some((p) => p.provider === CorePlugins.Zod) && - (options.defaultPlugins || corePlugins.some((p) => p.provider === CorePlugins.Enhancer)) && + options.defaultPlugins && + corePlugins.some((p) => p.provider === CorePlugins.Enhancer) && hasValidation ) { // ensure "@core/zod" is enabled if "@core/enhancer" is enabled and there're validation rules @@ -319,10 +341,17 @@ export class PluginRunner { options: PluginDeclaredOptions, dmmf: DMMF.Document | undefined, shortNameMap: Map | undefined, - project: Project + project: Project, + isCorePlugin: boolean ) { + if (!isCorePlugin && !this.isPluginEnabled(name, runnerOptions)) { + ora(`Plugin "${name}" is skipped`).start().warn(); + return { warnings: [] }; + } + const title = description ?? `Running plugin ${colors.cyan(name)}`; const spinner = ora(title).start(); + try { const r = await telemetry.trackSpan( 'cli:plugin:start', @@ -358,6 +387,18 @@ export class PluginRunner { } } + private isPluginEnabled(name: string, runnerOptions: PluginRunnerOptions) { + if (runnerOptions.withPlugins && !runnerOptions.withPlugins.includes(name)) { + return false; + } + + if (runnerOptions.withoutPlugins && runnerOptions.withoutPlugins.includes(name)) { + return false; + } + + return true; + } + private getPluginModulePath(provider: string, schemaPath: string) { if (process.env.ZENSTACK_TEST === '1' && provider.startsWith('@zenstackhq/')) { // test code runs with its own sandbox of node_modules, make sure we don't diff --git a/packages/schema/src/plugins/enhancer/enhance/index.ts b/packages/schema/src/plugins/enhancer/enhance/index.ts index ad64f513a..8d411eb19 100644 --- a/packages/schema/src/plugins/enhancer/enhance/index.ts +++ b/packages/schema/src/plugins/enhancer/enhance/index.ts @@ -38,6 +38,7 @@ import { import { upperCaseFirst } from 'upper-case-first'; import { name } from '..'; import { execPackage } from '../../../utils/exec-utils'; +import { CorePlugins, getPluginCustomOutputFolder } from '../../plugin-utils'; import { trackPrismaSchemaError } from '../../prisma'; import { PrismaSchemaGenerator } from '../../prisma/schema-generator'; import { isDefaultWithAuth } from '../enhancer-utils'; @@ -93,14 +94,21 @@ export class EnhancerGenerator { const checkerTypes = this.generatePermissionChecker ? generateCheckerType(this.model) : ''; - const enhanceTs = this.project.createSourceFile( - path.join(this.outDir, 'enhance.ts'), - `/* eslint-disable */ + for (const target of ['node', 'edge']) { + // generate separate `enhance()` for node and edge runtime + const outFile = target === 'node' ? 'enhance.ts' : 'enhance-edge.ts'; + const enhanceTs = this.project.createSourceFile( + path.join(this.outDir, outFile), + `/* eslint-disable */ import { type EnhancementContext, type EnhancementOptions, type ZodSchemas, type AuthUser } from '@zenstackhq/runtime'; -import { createEnhancement } from '@zenstackhq/runtime/enhancements'; +import { createEnhancement } from '@zenstackhq/runtime/enhancements/${target}'; import modelMeta from './model-meta'; import policy from './policy'; -${this.options.withZodSchemas ? "import * as zodSchemas from './zod';" : 'const zodSchemas = undefined;'} +${ + this.options.withZodSchemas + ? `import * as zodSchemas from '${this.getZodImport()}';` + : 'const zodSchemas = undefined;' +} ${ logicalPrismaClientDir @@ -118,14 +126,42 @@ ${ : this.createSimplePrismaEnhanceFunction(authTypeParam) } `, - { overwrite: true } - ); + { overwrite: true } + ); - await this.saveSourceFile(enhanceTs); + await this.saveSourceFile(enhanceTs); + } return { dmmf }; } + private getZodImport() { + const zodCustomOutput = getPluginCustomOutputFolder(this.model, CorePlugins.Zod); + + if (!this.options.output && !zodCustomOutput) { + // neither zod or me (enhancer) have custom output, use the default + return './zod'; + } + + if (!zodCustomOutput) { + // I have a custom output, but zod doesn't, import from runtime + return '@zenstackhq/runtime/zod'; + } + + if (!this.options.output) { + // I don't have a custom output, but zod has, CLI will still generate + // a copy into the default output, so we can still import from there + return './zod'; + } + + // both zod and me have custom output, resolve to relative path and import + const schemaDir = path.dirname(this.options.schemaPath); + const zodAbsPath = path.isAbsolute(zodCustomOutput) + ? zodCustomOutput + : path.resolve(schemaDir, zodCustomOutput); + return path.relative(this.outDir, zodAbsPath) || '.'; + } + private createSimplePrismaImports(prismaImport: string) { return `import { Prisma, type PrismaClient } from '${prismaImport}'; import type * as _P from '${prismaImport}'; diff --git a/packages/schema/src/plugins/enhancer/policy/expression-writer.ts b/packages/schema/src/plugins/enhancer/policy/expression-writer.ts index 66e5df73d..645e02cd1 100644 --- a/packages/schema/src/plugins/enhancer/policy/expression-writer.ts +++ b/packages/schema/src/plugins/enhancer/policy/expression-writer.ts @@ -378,17 +378,9 @@ export class ExpressionWriter { operator = this.negateOperator(operator); } - if (this.isFutureMemberAccess(fieldAccess)) { - // future().field should be treated as the "field" directly, so we - // strip 'future().' and synthesize a reference expr - fieldAccess = { - $type: ReferenceExpr, - $container: fieldAccess.$container, - target: fieldAccess.member, - $resolvedType: fieldAccess.$resolvedType, - $future: true, - } as unknown as ReferenceExpr; - } + // future()...field should be treated as the "field" directly, so we + // strip 'future().' and synthesize a reference/member-access expr + fieldAccess = this.stripFutureCall(fieldAccess); // guard member access of `auth()` with null check if (this.isAuthOrAuthMemberAccess(operand) && !fieldAccess.$resolvedType?.nullable) { @@ -472,6 +464,39 @@ export class ExpressionWriter { ); } + private stripFutureCall(fieldAccess: Expression) { + if (!this.isFutureMemberAccess(fieldAccess)) { + return fieldAccess; + } + + const memberAccessStack: MemberAccessExpr[] = []; + let current: Expression = fieldAccess; + while (isMemberAccessExpr(current)) { + memberAccessStack.push(current); + current = current.operand; + } + + const top = memberAccessStack.pop()!; + + // turn the inner-most member access into a reference expr (strip 'future()') + let result: Expression = { + $type: ReferenceExpr, + $container: top.$container, + target: top.member, + $resolvedType: top.$resolvedType, + args: [], + } satisfies ReferenceExpr; + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (result as any).$future = true; + + // re-apply member accesses + for (const memberAccess of memberAccessStack.reverse()) { + result = { ...memberAccess, operand: result }; + } + return result; + } + private isFutureMemberAccess(expr: Expression): expr is MemberAccessExpr { if (!isMemberAccessExpr(expr)) { return false; @@ -815,8 +840,15 @@ export class ExpressionWriter { } this.block(() => { - const targetGuardFunc = getQueryGuardFunctionName(targetModel, undefined, false, operation); - this.writer.write(`${fieldRef.target.$refText}: ${targetGuardFunc}(context, db)`); + if (operation === 'postUpdate') { + // 'postUpdate' policies are not delegated to relations, just use constant `false` here + // e.g.: + // @@allow('all', check(author)) should not delegate "postUpdate" to author + this.writer.write(`${fieldRef.target.$refText}: ${FALSE}`); + } else { + const targetGuardFunc = getQueryGuardFunctionName(targetModel, undefined, false, operation); + this.writer.write(`${fieldRef.target.$refText}: ${targetGuardFunc}(context, db)`); + } }); } } diff --git a/packages/schema/src/plugins/enhancer/policy/policy-guard-generator.ts b/packages/schema/src/plugins/enhancer/policy/policy-guard-generator.ts index 2c54949f4..aa54c80d8 100644 --- a/packages/schema/src/plugins/enhancer/policy/policy-guard-generator.ts +++ b/packages/schema/src/plugins/enhancer/policy/policy-guard-generator.ts @@ -95,14 +95,21 @@ export class PolicyGenerator { namedImports: [ { name: 'type QueryContext' }, { name: 'type CrudContract' }, - { name: 'allFieldsEqual' }, - { name: 'type PolicyDef' }, { name: 'type PermissionCheckerContext' }, - { name: 'type PermissionCheckerConstraint' }, ], moduleSpecifier: `${RUNTIME_PACKAGE}`, }); + sf.addImportDeclaration({ + namedImports: [{ name: 'allFieldsEqual' }], + moduleSpecifier: `${RUNTIME_PACKAGE}/validation`, + }); + + sf.addImportDeclaration({ + namedImports: [{ name: 'type PolicyDef' }, { name: 'type PermissionCheckerConstraint' }], + moduleSpecifier: `${RUNTIME_PACKAGE}/enhancements/node`, + }); + // import enums const prismaImport = getPrismaClientImportSpec(output, this.options); for (const e of model.declarations.filter((d) => isEnum(d) && isEnumReferenced(model, d))) { diff --git a/packages/schema/src/plugins/plugin-utils.ts b/packages/schema/src/plugins/plugin-utils.ts index 9a3da35e6..b443e6ca7 100644 --- a/packages/schema/src/plugins/plugin-utils.ts +++ b/packages/schema/src/plugins/plugin-utils.ts @@ -1,8 +1,9 @@ import { DEFAULT_RUNTIME_LOAD_PATH, type PolicyOperationKind } from '@zenstackhq/runtime'; -import { PluginGlobalOptions, ensureEmptyDir } from '@zenstackhq/sdk'; +import { PluginGlobalOptions, ensureEmptyDir, getLiteral } from '@zenstackhq/sdk'; import fs from 'fs'; import path from 'path'; import { PluginRunnerOptions } from '../cli/plugin-runner'; +import { isPlugin, Model, Plugin } from '@zenstackhq/sdk/ast'; export const ALL_OPERATION_KINDS: PolicyOperationKind[] = ['create', 'update', 'postUpdate', 'read', 'delete']; @@ -39,6 +40,10 @@ export function ensureDefaultOutputFolder(options: PluginRunnerOptions) { types: './enhance.d.ts', default: './enhance.js', }, + './enhance-edge': { + types: './enhance-edge.d.ts', + default: './enhance-edge.js', + }, './zod': { types: './zod/index.d.ts', default: './zod/index.js', @@ -114,3 +119,18 @@ export enum CorePlugins { Zod = '@core/zod', Enhancer = '@core/enhancer', } + +/** + * Gets the custom output folder for a plugin. + */ +export function getPluginCustomOutputFolder(zmodel: Model, provider: string) { + const plugin = zmodel.declarations.find( + (d): d is Plugin => + isPlugin(d) && d.fields.some((f) => f.name === 'provider' && getLiteral(f.value) === provider) + ); + if (!plugin) { + return undefined; + } + const output = plugin.fields.find((f) => f.name === 'output'); + return output && getLiteral(output.value); +} diff --git a/packages/schema/src/plugins/zod/utils/schema-gen.ts b/packages/schema/src/plugins/zod/utils/schema-gen.ts index 3df90bd95..6d96087d0 100644 --- a/packages/schema/src/plugins/zod/utils/schema-gen.ts +++ b/packages/schema/src/plugins/zod/utils/schema-gen.ts @@ -6,6 +6,7 @@ import { getAttributeArg, getAttributeArgLiteral, getLiteral, + getLiteralArray, isDataModelFieldReference, isFromStdlib, } from '@zenstackhq/sdk'; @@ -14,6 +15,7 @@ import { DataModelField, DataModelFieldAttribute, isDataModel, + isArrayExpr, isEnum, isInvocationExpr, isNumberLiteral, @@ -221,7 +223,12 @@ export function makeValidationRefinements(model: DataModel) { } const messageArg = getAttributeArgLiteral(attr, 'message'); - const message = messageArg ? `, { message: ${JSON.stringify(messageArg)} }` : ''; + const message = messageArg ? `message: ${JSON.stringify(messageArg)},` : ''; + + const pathArg = getAttributeArg(attr, 'path'); + const path = pathArg && isArrayExpr(pathArg) ? `path: ['${getLiteralArray(pathArg)?.join(`', '`)}'],` : ''; + + const options = `, { ${message} ${path} }`; try { let expr = new TypeScriptExpressionTransformer({ @@ -235,7 +242,7 @@ export function makeValidationRefinements(model: DataModel) { expr = `${expr} ?? true`; } - return `.refine((value: any) => ${expr}${message})`; + return `.refine((value: any) => ${expr}${options})`; } catch (err) { if (err instanceof TypeScriptExpressionTransformerError) { throw new PluginError(name, err.message); diff --git a/packages/schema/src/res/stdlib.zmodel b/packages/schema/src/res/stdlib.zmodel index 3a57ef6b0..c711e7404 100644 --- a/packages/schema/src/res/stdlib.zmodel +++ b/packages/schema/src/res/stdlib.zmodel @@ -633,7 +633,7 @@ attribute @lte(_ value: Int, _ message: String?) @@@targetField([IntField, Float /** * Validates the entity with a complex condition. */ -attribute @@validate(_ value: Boolean, _ message: String?) @@@validation +attribute @@validate(_ value: Boolean, _ message: String?, _ path: String[]?) @@@validation /** * Validates length of a string field. diff --git a/packages/sdk/package.json b/packages/sdk/package.json index c5338bbfe..6cd796584 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/sdk", - "version": "2.4.1", + "version": "2.5.0", "description": "ZenStack plugin development SDK", "main": "index.js", "scripts": { @@ -18,8 +18,8 @@ "author": "", "license": "MIT", "dependencies": { - "@prisma/generator-helper": "5.18.x", - "@prisma/internals": "5.18.x", + "@prisma/generator-helper": "5.19.x", + "@prisma/internals": "5.19.x", "@zenstackhq/language": "workspace:*", "@zenstackhq/runtime": "workspace:*", "langium": "1.3.1", diff --git a/packages/sdk/src/model-meta-generator.ts b/packages/sdk/src/model-meta-generator.ts index 68f6fde3c..d4cf52ab9 100644 --- a/packages/sdk/src/model-meta-generator.ts +++ b/packages/sdk/src/model-meta-generator.ts @@ -298,7 +298,8 @@ function getBackLink(field: DataModelField) { const relName = getRelationName(field); - const sourceModel = field.$container as DataModel; + // in case of polymorphism, the source model is the base delegate model + const sourceModel = field.$inheritedFrom ?? (field.$container as DataModel); const targetModel = field.type.reference.ref as DataModel; for (const otherField of targetModel.fields) { diff --git a/packages/server/package.json b/packages/server/package.json index fb956f241..f3e913956 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/server", - "version": "2.4.1", + "version": "2.5.0", "displayName": "ZenStack Server-side Adapters", "description": "ZenStack server-side adapters", "homepage": "https://zenstack.dev", @@ -35,7 +35,8 @@ "upper-case-first": "^2.0.2", "url-pattern": "^1.0.3", "zod": "^3.22.4", - "zod-validation-error": "^1.5.0" + "zod-validation-error": "^1.5.0", + "decimal.js": "^10.4.2" }, "devDependencies": { "@nestjs/common": "^10.3.7", @@ -47,7 +48,6 @@ "@types/supertest": "^2.0.12", "@zenstackhq/testtools": "workspace:*", "body-parser": "^1.20.2", - "decimal.js": "^10.4.2", "express": "^4.19.2", "fastify": "^4.14.1", "fastify-plugin": "^4.5.0", diff --git a/packages/server/src/api/rest/index.ts b/packages/server/src/api/rest/index.ts index 022ac72a7..75b2f738b 100644 --- a/packages/server/src/api/rest/index.ts +++ b/packages/server/src/api/rest/index.ts @@ -1589,7 +1589,7 @@ class RequestHandler extends APIHandlerBase { private handlePrismaError(err: unknown) { if (isPrismaClientKnownRequestError(err)) { - if (err.code === PrismaErrorCode.CONSTRAINED_FAILED) { + if (err.code === PrismaErrorCode.CONSTRAINT_FAILED) { if (err.meta?.reason === CrudFailureReason.DATA_VALIDATION_VIOLATION) { return this.makeError( 'validationError', diff --git a/packages/server/src/api/rpc/index.ts b/packages/server/src/api/rpc/index.ts index a8882b8be..a1a71c1c6 100644 --- a/packages/server/src/api/rpc/index.ts +++ b/packages/server/src/api/rpc/index.ts @@ -18,7 +18,7 @@ import { logError, registerCustomSerializers } from '../utils'; registerCustomSerializers(); const ERROR_STATUS_MAPPING: Record = { - [PrismaErrorCode.CONSTRAINED_FAILED]: 403, + [PrismaErrorCode.CONSTRAINT_FAILED]: 403, [PrismaErrorCode.REQUIRED_CONNECTED_RECORD_NOT_FOUND]: 404, [PrismaErrorCode.DEPEND_ON_RECORD_NOT_FOUND]: 404, }; diff --git a/packages/testtools/package.json b/packages/testtools/package.json index 34a4ba6ea..aa8562163 100644 --- a/packages/testtools/package.json +++ b/packages/testtools/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/testtools", - "version": "2.4.1", + "version": "2.5.0", "description": "ZenStack Test Tools", "main": "index.js", "private": true, diff --git a/packages/testtools/src/schema.ts b/packages/testtools/src/schema.ts index 919a9d411..7cce9bd36 100644 --- a/packages/testtools/src/schema.ts +++ b/packages/testtools/src/schema.ts @@ -3,12 +3,12 @@ import type { Model } from '@zenstackhq/language/ast'; import { DEFAULT_RUNTIME_LOAD_PATH, - PolicyDef, type AuthUser, type CrudContract, type EnhancementKind, type EnhancementOptions, } from '@zenstackhq/runtime'; +import type { PolicyDef } from '@zenstackhq/runtime/enhancements/node'; import { getDMMF, type DMMF } from '@zenstackhq/sdk/prisma'; import { execSync } from 'child_process'; import * as fs from 'fs'; @@ -135,6 +135,7 @@ export type SchemaLoadOptions = { generatePermissionChecker?: boolean; previewFeatures?: string[]; prismaClientOptions?: object; + generateNoCompile?: boolean; }; const defaultOptions: SchemaLoadOptions = { @@ -146,6 +147,7 @@ const defaultOptions: SchemaLoadOptions = { logPrismaQuery: false, provider: 'sqlite', preserveTsFiles: false, + generateNoCompile: false, }; export async function loadSchemaFromFile(schemaFile: string, options?: SchemaLoadOptions) { @@ -225,19 +227,26 @@ export async function loadSchema(schema: string, options?: SchemaLoadOptions) { } const outputArg = opt.output ? ` --output ${opt.output}` : ''; + let otherArgs = ''; + if (opt.generateNoCompile) { + otherArgs = ' --no-compile'; + } if (opt.customSchemaFilePath) { - run(`npx zenstack generate --no-version-check --schema ${zmodelPath} --no-dependency-check${outputArg}`, { - NODE_PATH: './node_modules', - }); + run( + `npx zenstack generate --no-version-check --schema ${zmodelPath} --no-dependency-check${outputArg}${otherArgs}`, + { + NODE_PATH: './node_modules', + } + ); } else { - run(`npx zenstack generate --no-version-check --no-dependency-check${outputArg}`, { + run(`npx zenstack generate --no-version-check --no-dependency-check${outputArg}${otherArgs}`, { NODE_PATH: './node_modules', }); } if (opt.pushDb) { - run('npx prisma db push --skip-generate'); + run('npx prisma db push --skip-generate --accept-data-loss'); } if (opt.pulseApiKey) { @@ -264,10 +273,10 @@ export async function loadSchema(schema: string, options?: SchemaLoadOptions) { // https://github.com/prisma/prisma/issues/18292 prisma[Symbol.for('nodejs.util.inspect.custom')] = 'PrismaClient'; - const prismaModule = require(path.join(projectDir, 'node_modules/@prisma/client')).Prisma; + const prismaModule = loadModule('@prisma/client', projectDir).Prisma; if (opt.pulseApiKey) { - const withPulse = require(path.join(projectDir, 'node_modules/@prisma/extension-pulse/dist/cjs')).withPulse; + const withPulse = loadModule('@prisma/extension-pulse/node', projectDir).withPulse; prisma = prisma.$extends(withPulse({ apiKey: opt.pulseApiKey })); } @@ -388,3 +397,8 @@ export async function loadZModelAndDmmf( const dmmf = await getDMMF({ datamodel: prismaContent }); return { model, dmmf, modelFile }; } + +function loadModule(module: string, basePath: string): any { + const modulePath = require.resolve(module, { paths: [basePath] }); + return require(modulePath); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c186ab20d..552ed617a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -205,9 +205,6 @@ importers: cross-fetch: specifier: ^4.0.0 version: 4.0.0(encoding@0.1.13) - decimal.js: - specifier: ^10.4.2 - version: 10.4.3 lower-case-first: specifier: ^2.0.2 version: 2.0.2 @@ -267,9 +264,6 @@ importers: cross-fetch: specifier: ^4.0.0 version: 4.0.0(encoding@0.1.13) - decimal.js: - specifier: ^10.4.2 - version: 10.4.3 lower-case-first: specifier: ^2.0.2 version: 2.0.2 @@ -398,8 +392,8 @@ importers: packages/runtime: dependencies: '@prisma/client': - specifier: 5.0.0 - 5.18.x - version: 5.18.0(prisma@5.16.1) + specifier: 5.0.0 - 5.19.x + version: 5.19.0(prisma@5.16.1) bcryptjs: specifier: ^2.4.3 version: 2.4.3 @@ -409,9 +403,9 @@ importers: change-case: specifier: ^4.1.2 version: 4.1.2 - decimal.js: - specifier: ^10.4.2 - version: 10.4.3 + decimal.js-light: + specifier: ^2.5.1 + version: 2.5.1 deepmerge: specifier: ^4.3.1 version: 4.3.1 @@ -523,7 +517,7 @@ importers: specifier: ^4.0.0 version: 4.0.1 prisma: - specifier: 5.0.0 - 5.18.x + specifier: 5.0.0 - 5.19.x version: 5.16.1 semver: specifier: ^7.5.2 @@ -534,6 +528,9 @@ importers: strip-color: specifier: ^0.1.0 version: 0.1.0 + terminal-link: + specifier: ^2.0.0 + version: 2.1.1 tiny-invariant: specifier: ^1.3.1 version: 1.3.3 @@ -572,8 +569,8 @@ importers: version: 1.5.0(zod@3.23.8) devDependencies: '@prisma/client': - specifier: 5.18.x - version: 5.18.0(prisma@5.16.1) + specifier: 5.19.x + version: 5.19.0(prisma@5.16.1) '@types/async-exit-hook': specifier: ^2.0.0 version: 2.0.2 @@ -624,11 +621,11 @@ importers: packages/sdk: dependencies: '@prisma/generator-helper': - specifier: 5.18.x - version: 5.18.0 + specifier: 5.19.x + version: 5.19.0 '@prisma/internals': - specifier: 5.18.x - version: 5.18.0 + specifier: 5.19.x + version: 5.19.0 '@zenstackhq/language': specifier: workspace:* version: link:../language/dist @@ -667,6 +664,9 @@ importers: change-case: specifier: ^4.1.2 version: 4.1.2 + decimal.js: + specifier: ^10.4.2 + version: 10.4.3 lower-case-first: specifier: ^2.0.2 version: 2.0.2 @@ -719,9 +719,6 @@ importers: body-parser: specifier: ^1.20.2 version: 1.20.2 - decimal.js: - specifier: ^10.4.2 - version: 10.4.3 express: specifier: ^4.19.2 version: 4.19.2 @@ -2436,8 +2433,8 @@ packages: prisma: optional: true - '@prisma/client@5.18.0': - resolution: {integrity: sha512-BWivkLh+af1kqC89zCJYkHsRcyWsM8/JHpsDMM76DjP3ZdEquJhXa4IeX+HkWPnwJ5FanxEJFZZDTWiDs/Kvyw==} + '@prisma/client@5.19.0': + resolution: {integrity: sha512-CzOpau+q1kEWQyoQMvlnXIHqPvwmWbh48xZ4n8KWbAql0p8PC0BIgSTYW5ncxXa4JSEff0tcoxSZB874wDstdg==} engines: {node: '>=16.13'} peerDependencies: prisma: '*' @@ -2451,8 +2448,8 @@ packages: '@prisma/debug@5.16.1': resolution: {integrity: sha512-JsNgZAg6BD9RInLSrg7ZYzo11N7cVvYArq3fHGSD89HSgtN0VDdjV6bib7YddbcO6snzjchTiLfjeTqBjtArVQ==} - '@prisma/debug@5.18.0': - resolution: {integrity: sha512-f+ZvpTLidSo3LMJxQPVgAxdAjzv5OpzAo/eF8qZqbwvgi2F5cTOI9XCpdRzJYA0iGfajjwjOKKrVq64vkxEfUw==} + '@prisma/debug@5.19.0': + resolution: {integrity: sha512-+b/G0ubAZlrS+JSiDhXnYV5DF/aTJ3pinktkiV/L4TtLRLZO6SVGyFELgxBsicCTWJ2ZMu5vEV/jTtYCdjFTRA==} '@prisma/engines-version@5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48': resolution: {integrity: sha512-ip6pNkRo1UxWv+6toxNcYvItNYaqQjXdFNGJ+Nuk2eYtRoEdoF13wxo7/jsClJFFenMPVNVqXQDV0oveXnR1cA==} @@ -2460,8 +2457,8 @@ packages: '@prisma/engines-version@5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303': resolution: {integrity: sha512-HkT2WbfmFZ9WUPyuJHhkiADxazHg8Y4gByrTSVeb3OikP6tjQ7txtSUGu9OBOBH0C13dPKN2qqH12xKtHu/Hiw==} - '@prisma/engines-version@5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169': - resolution: {integrity: sha512-a/+LpJj8vYU3nmtkg+N3X51ddbt35yYrRe8wqHTJtYQt7l1f8kjIBcCs6sHJvodW/EK5XGvboOiwm47fmNrbgg==} + '@prisma/engines-version@5.19.0-31.5fe21811a6ba0b952a3bc71400666511fe3b902f': + resolution: {integrity: sha512-GimI9aZIFy/yvvR11KfXRn3pliFn1QAkdebVlsXlnoh5uk0YhLblVmeYiHfsu+wDA7BeKqYT4sFfzg8mutzuWw==} '@prisma/engines@5.14.0': resolution: {integrity: sha512-lgxkKZ6IEygVcw6IZZUlPIfLQ9hjSYAtHjZ5r64sCLDgVzsPFCi2XBBJgzPMkOQ5RHzUD4E/dVdpn9+ez8tk1A==} @@ -2469,8 +2466,8 @@ packages: '@prisma/engines@5.16.1': resolution: {integrity: sha512-KkyF3eIUtBIyp5A/rJHCtwQO18OjpGgx18PzjyGcJDY/+vNgaVyuVd+TgwBgeq6NLdd1XMwRCI+58vinHsAdfA==} - '@prisma/engines@5.18.0': - resolution: {integrity: sha512-ofmpGLeJ2q2P0wa/XaEgTnX/IsLnvSp/gZts0zjgLNdBhfuj2lowOOPmDcfKljLQUXMvAek3lw5T01kHmCG8rg==} + '@prisma/engines@5.19.0': + resolution: {integrity: sha512-UtW+0m4HYoRSSR3LoDGKF3Ud4BSMWYlLEt4slTnuP1mI+vrV3zaDoiAPmejdAT76vCN5UqnWURbkXxf66nSylQ==} '@prisma/fetch-engine@5.14.0': resolution: {integrity: sha512-VrheA9y9DMURK5vu8OJoOgQpxOhas3qF0IBHJ8G/0X44k82kc8E0w98HCn2nhnbOOMwbWsJWXfLC2/F8n5u0gQ==} @@ -2478,14 +2475,14 @@ packages: '@prisma/fetch-engine@5.16.1': resolution: {integrity: sha512-oOkjaPU1lhcA/Rvr4GVfd1NLJBwExgNBE36Ueq7dr71kTMwy++a3U3oLd2ZwrV9dj9xoP6LjCcky799D9nEt4w==} - '@prisma/fetch-engine@5.18.0': - resolution: {integrity: sha512-I/3u0x2n31rGaAuBRx2YK4eB7R/1zCuayo2DGwSpGyrJWsZesrV7QVw7ND0/Suxeo/vLkJ5OwuBqHoCxvTHpOg==} + '@prisma/fetch-engine@5.19.0': + resolution: {integrity: sha512-oOiPNtmJX0cP/ebu7BBEouJvCw8T84/MFD/Hf2zlqjxkK4ojl38bB9i9J5LAxotL6WlYVThKdxc7HqoWnPOhqQ==} '@prisma/generator-helper@5.14.0': resolution: {integrity: sha512-xVc71cmTnPZ0lnSs4FAY6Ta72vFJ3webrQwKMQ2ujr6hDG1VPIEf820T1TOS3ZZQd/OKigNKXnq3co8biz9/qw==} - '@prisma/generator-helper@5.18.0': - resolution: {integrity: sha512-3ffmrd9KE8ssg/fwyvfwMxrDAunLF8DLFjfwYnDRE7VaNIhkUVZwB77jAwpMCtukvCsAp14WGWu4itvLMzH3GQ==} + '@prisma/generator-helper@5.19.0': + resolution: {integrity: sha512-qZDgnq/dHVHYUNRG8ETuIvoiZzWxwKHhG9Jb4WWoQFXXuTY+1km0L5QAPOJ0U7Qo8ookUf25B88n1Z9Az7l/UQ==} '@prisma/get-platform@5.14.0': resolution: {integrity: sha512-/yAyBvcEjRv41ynZrhdrPtHgk47xLRRq/o5eWGcUpBJ1YrUZTYB8EoPiopnP7iQrMATK8stXQdPOoVlrzuTQZw==} @@ -2493,14 +2490,14 @@ packages: '@prisma/get-platform@5.16.1': resolution: {integrity: sha512-R4IKnWnMkR2nUAbU5gjrPehdQYUUd7RENFD2/D+xXTNhcqczp0N+WEGQ3ViyI3+6mtVcjjNIMdnUTNyu3GxIgA==} - '@prisma/get-platform@5.18.0': - resolution: {integrity: sha512-Tk+m7+uhqcKDgnMnFN0lRiH7Ewea0OEsZZs9pqXa7i3+7svS3FSCqDBCaM9x5fmhhkufiG0BtunJVDka+46DlA==} + '@prisma/get-platform@5.19.0': + resolution: {integrity: sha512-s9DWkZKnuP4Y8uy6yZfvqQ/9X3/+2KYf3IZUVZz5OstJdGBJrBlbmIuMl81917wp5TuK/1k2TpHNCEdpYLPKmg==} '@prisma/internals@5.14.0': resolution: {integrity: sha512-s0JRNDmR2bvcyy0toz89jy7SbbjANAs4e9KCReNvSm5czctIaZzDf68tcOXdtH0G7m9mKhVhNPdS9lMky0DhWA==} - '@prisma/internals@5.18.0': - resolution: {integrity: sha512-NYG69q0FxpPHXDtEM2GS5kU22IwgtriCceNH00dWP9dV7oHz23+8QWJMlDsICTR7gnULLCeS2gWBuXWTS1PRmA==} + '@prisma/internals@5.19.0': + resolution: {integrity: sha512-T64de7FG2UUkXbbjT+Zu31dODddR7s2vFBvxZ5Ac2DKYnFUhb9UT8Er3qYsFfAQz9CqUvBRjFb8B+yBylu+LFA==} '@prisma/prisma-schema-wasm@5.14.0-17.56ca112d5a19c9925b53af75c3c6b7ada97f9f85': resolution: {integrity: sha512-SX9vE9dGYBap6xsfJuDE5b2eoA6w1vKsx8QpLUHZR+kIV6GQVUYUboEfkvYYoBVen3s9LqxJ1+LjHL/1MqBZag==} @@ -2508,14 +2505,14 @@ packages: '@prisma/prisma-schema-wasm@5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48': resolution: {integrity: sha512-WeTmJ0mK8ALoKJUQFO+465k9lm1JWS4ODUg7akJq1wjgyDU1RTAzDFli8ESmNJlMVgJgoAd6jXmzcnoA0HT9Lg==} - '@prisma/prisma-schema-wasm@5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169': - resolution: {integrity: sha512-2h7MDiYVXHVSdz0CylOUktVouPHRKUw5ciXz2r/oZsO2T6Zycez/eSvh4SKiKbHuxDq6SSb3R97mO7bjzh+NVQ==} + '@prisma/prisma-schema-wasm@5.19.0-31.5fe21811a6ba0b952a3bc71400666511fe3b902f': + resolution: {integrity: sha512-GFCdGqah8pPCrfAejzPuc/XiqlAeD3D1W8ysr9sQx0tLyzixgVKqjrDnI+I2OkRAQFmVlkh2xqWjfbWfhVALBQ==} '@prisma/schema-files-loader@5.14.0': resolution: {integrity: sha512-n1QHR2C63dARKPZe0WPn7biybcBHzXe+BEmiHC5Drq9KPWnpmQtIfGpqm1ZKdvCZfcA5FF3wgpSMPK4LnB0obQ==} - '@prisma/schema-files-loader@5.18.0': - resolution: {integrity: sha512-JtjPOZ8odMMr3etCcQ5kDsuljmckuNNCRMJglouPWSyzRbv4nOQJZCD4qPmoMUSoX0gwV7wGgwUw50XsoFYVzA==} + '@prisma/schema-files-loader@5.19.0': + resolution: {integrity: sha512-o8uTfuJLFm64e9Qng+jIKHrTiMFaEkPzsl4hqzjseJOoZvlKrMpAyKdKlfrBAodpXbBTg9ajcAyAcyY4m21iMw==} '@protobufjs/aspromise@1.1.2': resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} @@ -4204,6 +4201,9 @@ packages: resolution: {integrity: sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==} engines: {node: '>=4'} + decimal.js-light@2.5.1: + resolution: {integrity: sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==} + decimal.js@10.4.3: resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} @@ -10484,7 +10484,7 @@ snapshots: optionalDependencies: prisma: 5.16.1 - '@prisma/client@5.18.0(prisma@5.16.1)': + '@prisma/client@5.19.0(prisma@5.16.1)': optionalDependencies: prisma: 5.16.1 @@ -10492,13 +10492,13 @@ snapshots: '@prisma/debug@5.16.1': {} - '@prisma/debug@5.18.0': {} + '@prisma/debug@5.19.0': {} '@prisma/engines-version@5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48': {} '@prisma/engines-version@5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303': {} - '@prisma/engines-version@5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169': {} + '@prisma/engines-version@5.19.0-31.5fe21811a6ba0b952a3bc71400666511fe3b902f': {} '@prisma/engines@5.14.0': dependencies: @@ -10514,12 +10514,12 @@ snapshots: '@prisma/fetch-engine': 5.16.1 '@prisma/get-platform': 5.16.1 - '@prisma/engines@5.18.0': + '@prisma/engines@5.19.0': dependencies: - '@prisma/debug': 5.18.0 - '@prisma/engines-version': 5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169 - '@prisma/fetch-engine': 5.18.0 - '@prisma/get-platform': 5.18.0 + '@prisma/debug': 5.19.0 + '@prisma/engines-version': 5.19.0-31.5fe21811a6ba0b952a3bc71400666511fe3b902f + '@prisma/fetch-engine': 5.19.0 + '@prisma/get-platform': 5.19.0 '@prisma/fetch-engine@5.14.0': dependencies: @@ -10533,19 +10533,19 @@ snapshots: '@prisma/engines-version': 5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303 '@prisma/get-platform': 5.16.1 - '@prisma/fetch-engine@5.18.0': + '@prisma/fetch-engine@5.19.0': dependencies: - '@prisma/debug': 5.18.0 - '@prisma/engines-version': 5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169 - '@prisma/get-platform': 5.18.0 + '@prisma/debug': 5.19.0 + '@prisma/engines-version': 5.19.0-31.5fe21811a6ba0b952a3bc71400666511fe3b902f + '@prisma/get-platform': 5.19.0 '@prisma/generator-helper@5.14.0': dependencies: '@prisma/debug': 5.14.0 - '@prisma/generator-helper@5.18.0': + '@prisma/generator-helper@5.19.0': dependencies: - '@prisma/debug': 5.18.0 + '@prisma/debug': 5.19.0 '@prisma/get-platform@5.14.0': dependencies: @@ -10555,9 +10555,9 @@ snapshots: dependencies: '@prisma/debug': 5.16.1 - '@prisma/get-platform@5.18.0': + '@prisma/get-platform@5.19.0': dependencies: - '@prisma/debug': 5.18.0 + '@prisma/debug': 5.19.0 '@prisma/internals@5.14.0': dependencies: @@ -10571,15 +10571,15 @@ snapshots: arg: 5.0.2 prompts: 2.4.2 - '@prisma/internals@5.18.0': + '@prisma/internals@5.19.0': dependencies: - '@prisma/debug': 5.18.0 - '@prisma/engines': 5.18.0 - '@prisma/fetch-engine': 5.18.0 - '@prisma/generator-helper': 5.18.0 - '@prisma/get-platform': 5.18.0 - '@prisma/prisma-schema-wasm': 5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169 - '@prisma/schema-files-loader': 5.18.0 + '@prisma/debug': 5.19.0 + '@prisma/engines': 5.19.0 + '@prisma/fetch-engine': 5.19.0 + '@prisma/generator-helper': 5.19.0 + '@prisma/get-platform': 5.19.0 + '@prisma/prisma-schema-wasm': 5.19.0-31.5fe21811a6ba0b952a3bc71400666511fe3b902f + '@prisma/schema-files-loader': 5.19.0 arg: 5.0.2 prompts: 2.4.2 @@ -10587,16 +10587,16 @@ snapshots: '@prisma/prisma-schema-wasm@5.14.0-25.e9771e62de70f79a5e1c604a2d7c8e2a0a874b48': {} - '@prisma/prisma-schema-wasm@5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169': {} + '@prisma/prisma-schema-wasm@5.19.0-31.5fe21811a6ba0b952a3bc71400666511fe3b902f': {} '@prisma/schema-files-loader@5.14.0': dependencies: '@prisma/prisma-schema-wasm': 5.14.0-17.56ca112d5a19c9925b53af75c3c6b7ada97f9f85 fs-extra: 11.1.1 - '@prisma/schema-files-loader@5.18.0': + '@prisma/schema-files-loader@5.19.0': dependencies: - '@prisma/prisma-schema-wasm': 5.18.0-25.4c784e32044a8a016d99474bd02a3b6123742169 + '@prisma/prisma-schema-wasm': 5.19.0-31.5fe21811a6ba0b952a3bc71400666511fe3b902f fs-extra: 11.1.1 '@protobufjs/aspromise@1.1.2': {} @@ -12589,6 +12589,8 @@ snapshots: dependencies: xregexp: 4.0.0 + decimal.js-light@2.5.1: {} + decimal.js@10.4.3: {} decompress-response@6.0.0: diff --git a/script/test-scaffold.ts b/script/test-scaffold.ts index 1c131d7f6..ac6d00526 100644 --- a/script/test-scaffold.ts +++ b/script/test-scaffold.ts @@ -19,6 +19,6 @@ function run(cmd: string) { } run('npm init -y'); -run('npm i --no-audit --no-fund typescript prisma@5.18.x @prisma/client@5.18.x zod decimal.js @types/node'); +run('npm i --no-audit --no-fund typescript prisma@5.19.x @prisma/client@5.19.x zod decimal.js @types/node'); console.log('Test scaffold setup complete.'); diff --git a/tests/integration/test-run/package.json b/tests/integration/test-run/package.json index 5e7c4a468..a9883a957 100644 --- a/tests/integration/test-run/package.json +++ b/tests/integration/test-run/package.json @@ -10,9 +10,9 @@ "author": "", "license": "ISC", "dependencies": { - "@prisma/client": "5.18.x", + "@prisma/client": "5.19.x", "@zenstackhq/runtime": "file:../../../packages/runtime/dist", - "prisma": "5.18.x", + "prisma": "5.19.x", "react": "^18.2.0", "swr": "^1.3.0", "typescript": "^4.9.3", diff --git a/tests/integration/tests/cli/generate.test.ts b/tests/integration/tests/cli/generate.test.ts index d90ce14cc..c4aed8e51 100644 --- a/tests/integration/tests/cli/generate.test.ts +++ b/tests/integration/tests/cli/generate.test.ts @@ -112,42 +112,28 @@ model Post { expect(fs.existsSync('./prisma/schema.prisma')).toBeTruthy(); }); - it('generate no default plugins with access-policy with zod', async () => { + it('generate no default plugins with enhancer and zod', async () => { fs.appendFileSync( 'schema.zmodel', ` - plugin enhancer { - provider = '@core/enhancer' + plugin prisma { + provider = '@core/prisma' + } + + plugin zod { + provider = '@core/zod' } - ` - ); - const program = createProgram(); - await program.parseAsync(['generate', '--no-dependency-check', '--no-default-plugins'], { from: 'user' }); - expect(fs.existsSync('./node_modules/.zenstack/policy.js')).toBeTruthy(); - expect(fs.existsSync('./node_modules/.zenstack/model-meta.js')).toBeTruthy(); - expect(fs.existsSync('./prisma/schema.prisma')).toBeTruthy(); - }); - it('generate no default plugins with access-policy without zod', async () => { - fs.appendFileSync( - 'schema.zmodel', - ` plugin enhancer { provider = '@core/enhancer' } ` ); - let content = fs.readFileSync('schema.zmodel', 'utf-8'); - content = content.replace('@email', ''); - fs.writeFileSync('schema.zmodel', content, 'utf-8'); - const program = createProgram(); await program.parseAsync(['generate', '--no-dependency-check', '--no-default-plugins'], { from: 'user' }); expect(fs.existsSync('./node_modules/.zenstack/policy.js')).toBeTruthy(); expect(fs.existsSync('./node_modules/.zenstack/model-meta.js')).toBeTruthy(); expect(fs.existsSync('./prisma/schema.prisma')).toBeTruthy(); - const z = require(path.join(process.cwd(), './node_modules/.zenstack/zod/models')); - expect(z).toEqual({}); }); it('generate no compile', async () => { diff --git a/tests/integration/tests/cli/plugins.test.ts b/tests/integration/tests/cli/plugins.test.ts index cf45fab5b..757b03bb1 100644 --- a/tests/integration/tests/cli/plugins.test.ts +++ b/tests/integration/tests/cli/plugins.test.ts @@ -75,7 +75,7 @@ describe('CLI Plugins Tests', () => { 'swr', '@tanstack/react-query@^5.0.0', '@trpc/server', - '@prisma/client@5.18.x', + '@prisma/client@5.19.x', `${path.join(__dirname, '../../../../.build/zenstackhq-language-' + ver + '.tgz')}`, `${path.join(__dirname, '../../../../.build/zenstackhq-sdk-' + ver + '.tgz')}`, `${path.join(__dirname, '../../../../.build/zenstackhq-runtime-' + ver + '.tgz')}`, @@ -85,7 +85,7 @@ describe('CLI Plugins Tests', () => { const devDepPkgs = [ 'typescript', '@types/react', - 'prisma@5.18.x', + 'prisma@5.19.x', `${path.join(__dirname, '../../../../.build/zenstack-' + ver + '.tgz')}`, `${path.join(__dirname, '../../../../.build/zenstackhq-tanstack-query-' + ver + '.tgz')}`, `${path.join(__dirname, '../../../../.build/zenstackhq-swr-' + ver + '.tgz')}`, diff --git a/tests/integration/tests/enhancements/with-delegate/policy-interaction.test.ts b/tests/integration/tests/enhancements/with-delegate/policy-interaction.test.ts index c8e5bd432..f84e3c603 100644 --- a/tests/integration/tests/enhancements/with-delegate/policy-interaction.test.ts +++ b/tests/integration/tests/enhancements/with-delegate/policy-interaction.test.ts @@ -208,4 +208,64 @@ describe('Polymorphic Policy Test', () => { await expect(db.asset.findUnique({ where: { id: vid1.id } })).toResolveNull(); await expect(db.asset.findUnique({ where: { id: vid2.id } })).toResolveTruthy(); }); + + it('interaction with connect', async () => { + const schema = ` + model User { + id Int @id @default(autoincrement()) + } + + model Asset { + id Int @id @default(autoincrement()) + assetType String + comments Comment[] + + @@delegate(assetType) + @@allow('all', true) + } + + model Post extends Asset { + title String + postType String + @@delegate(postType) + } + + model RatedPost extends Post { + rating Int + } + + model Comment { + id Int @id @default(autoincrement()) + content String + asset Asset? @relation(fields: [assetId], references: [id]) + assetId Int? + @@allow('read,create', true) + @@allow('update', auth().id == 1) + } + `; + + const { enhance } = await loadSchema(schema); + const db = enhance(); + + const comment1 = await db.comment.create({ + data: { content: 'Comment1' }, + }); + + await expect( + db.ratedPost.create({ data: { title: 'Post1', rating: 5, comments: { connect: { id: comment1.id } } } }) + ).toBeRejectedByPolicy(); + + const post1 = await db.ratedPost.create({ data: { title: 'Post1', rating: 5 } }); + await expect( + db.post.update({ where: { id: post1.id }, data: { comments: { connect: { id: comment1.id } } } }) + ).toBeRejectedByPolicy(); + await expect( + db.ratedPost.update({ where: { id: post1.id }, data: { comments: { connect: { id: comment1.id } } } }) + ).toBeRejectedByPolicy(); + + const user1Db = enhance({ id: 1 }); + await expect( + user1Db.ratedPost.update({ where: { id: post1.id }, data: { comments: { connect: { id: comment1.id } } } }) + ).toResolveTruthy(); + }); }); diff --git a/tests/integration/tests/enhancements/with-policy/create-many-and-return.test.ts b/tests/integration/tests/enhancements/with-policy/create-many-and-return.test.ts index c96f16256..e03cd096b 100644 --- a/tests/integration/tests/enhancements/with-policy/create-many-and-return.test.ts +++ b/tests/integration/tests/enhancements/with-policy/create-many-and-return.test.ts @@ -92,14 +92,17 @@ describe('Test API createManyAndReturn', () => { const db = enhance(); - const r = await db.post.createManyAndReturn({ - data: [ - { title: 'post1', published: true }, - { title: 'post2', published: false }, - ], - }); - expect(r).toHaveLength(2); - expect(r[0].title).toBe('post1'); - expect(r[1].title).toBeUndefined(); + // create should succeed but one result can't be read back + await expect( + db.post.createManyAndReturn({ + data: [ + { title: 'post1', published: true }, + { title: 'post2', published: false }, + ], + }) + ).toBeRejectedByPolicy(); + + // check posts are created + await expect(prisma.post.findMany()).resolves.toHaveLength(2); }); }); diff --git a/tests/integration/tests/enhancements/with-policy/post-update.test.ts b/tests/integration/tests/enhancements/with-policy/post-update.test.ts index d43804787..21681bee5 100644 --- a/tests/integration/tests/enhancements/with-policy/post-update.test.ts +++ b/tests/integration/tests/enhancements/with-policy/post-update.test.ts @@ -552,4 +552,47 @@ describe('With Policy: post update', () => { expect.arrayContaining([expect.objectContaining({ value: 3 }), expect.objectContaining({ value: 4 })]) ); }); + + it('deep member access', async () => { + const { enhance } = await loadSchema( + ` + model M1 { + id Int @id @default(autoincrement()) + m2 M2? + v1 Int + @@allow('all', true) + @@deny('update', future().m2.m3.v3 > 1) + } + + model M2 { + id Int @id @default(autoincrement()) + m1 M1 @relation(fields: [m1Id], references:[id]) + m1Id Int @unique + m3 M3? + @@allow('all', true) + } + + model M3 { + id Int @id @default(autoincrement()) + v3 Int + m2 M2 @relation(fields: [m2Id], references:[id]) + m2Id Int @unique + @@allow('all', true) + } + ` + ); + + const db = enhance(); + + await db.m1.create({ + data: { id: 1, v1: 1, m2: { create: { id: 1, m3: { create: { id: 1, v3: 1 } } } } }, + }); + + await db.m1.create({ + data: { id: 2, v1: 2, m2: { create: { id: 2, m3: { create: { id: 2, v3: 2 } } } } }, + }); + + await expect(db.m1.update({ where: { id: 1 }, data: { v1: 2 } })).toResolveTruthy(); + await expect(db.m1.update({ where: { id: 2 }, data: { v1: 3 } })).toBeRejectedByPolicy(); + }); }); diff --git a/tests/integration/tests/enhancements/with-policy/prisma-pulse.test.ts b/tests/integration/tests/enhancements/with-policy/prisma-pulse.test.ts new file mode 100644 index 000000000..62a1bbbe5 --- /dev/null +++ b/tests/integration/tests/enhancements/with-policy/prisma-pulse.test.ts @@ -0,0 +1,373 @@ +/* eslint-disable jest/no-conditional-expect */ +import { loadSchema } from '@zenstackhq/testtools'; +import path from 'path'; + +const PULSE_DB_URL = process.env.PULSE_DB_URL; +const PULSE_API_KEY = process.env.PULSE_API_KEY; + +// eslint-disable-next-line jest/no-disabled-tests +describe.skip('With Policy: prisma pulse test', () => { + let origDir: string; + + beforeAll(async () => { + origDir = path.resolve('.'); + }); + + afterEach(() => { + process.chdir(origDir); + }); + + it('should conform to auth check', async () => { + const { prisma, enhance } = await loadSchema( + ` + model User { + id Int @id @default(autoincrement()) + } + + model Post { + id Int @id @default(autoincrement()) + name String + + @@allow('read', auth() != null) + } + `, + { + provider: 'postgresql', + dbUrl: PULSE_DB_URL, + pulseApiKey: PULSE_API_KEY, + logPrismaQuery: true, + } + ); + + await prisma.$queryRaw`ALTER TABLE public."Post" REPLICA IDENTITY FULL;`; + await prisma.post.deleteMany(); + + const rawSub = await prisma.post.stream(); + + const anonDb = enhance(); + console.log('Anonymous db subscribing'); + const anonSub = await anonDb.post.stream(); + + const authDb = enhance({ id: 1 }); + console.log('Auth db subscribing'); + const authSub = await authDb.post.stream(); + + async function produce() { + await prisma.post.create({ data: { id: 1, name: 'abc' } }); + console.log('created'); + await prisma.post.update({ where: { id: 1 }, data: { name: 'bcd' } }); + console.log('updated'); + await prisma.post.delete({ where: { id: 1 } }); + console.log('deleted'); + await new Promise((resolve) => setTimeout(resolve, 3000)); + } + + const rawEvents: any[] = []; + const authEvents: any[] = []; + const anonEvents: any[] = []; + await Promise.race([ + produce(), + consume(rawSub, 'Raw', rawEvents), + consume(authSub, 'Auth', authEvents), + consume(anonSub, 'Anonymous', anonEvents), + ]); + expect(rawEvents.length).toBe(3); + expect(authEvents.length).toBe(3); + expect(anonEvents.length).toBe(0); + }); + + it('should conform to model-level policy', async () => { + const { prisma, enhance } = await loadSchema( + ` + model Post { + id Int @id @default(autoincrement()) + name String + + @@allow('read', contains(name, 'hello')) + } + `, + { + provider: 'postgresql', + dbUrl: PULSE_DB_URL, + pulseApiKey: PULSE_API_KEY, + logPrismaQuery: true, + } + ); + + await prisma.$queryRaw`ALTER TABLE public."Post" REPLICA IDENTITY FULL;`; + await prisma.post.deleteMany(); + + const rawSub = await prisma.post.stream(); + + const enhanced = enhance(); + const enhancedSub = await enhanced.post.stream(); + + async function produce() { + await prisma.post.create({ data: { id: 1, name: 'abc' } }); + console.log('created'); + await prisma.post.update({ where: { id: 1 }, data: { name: 'bcd' } }); + console.log('updated'); + await prisma.post.delete({ where: { id: 1 } }); + console.log('deleted'); + + await prisma.post.create({ data: { id: 2, name: 'hello world' } }); + console.log('created'); + await prisma.post.update({ where: { id: 2 }, data: { name: 'hello moon' } }); + console.log('updated'); + await prisma.post.delete({ where: { id: 2 } }); + console.log('deleted'); + + await new Promise((resolve) => setTimeout(resolve, 3000)); + } + + const rawEvents: any[] = []; + const enhancedEvents: any[] = []; + await Promise.race([ + produce(), + consume(rawSub, 'Raw', rawEvents), + consume(enhancedSub, 'Enhanced', enhancedEvents), + ]); + expect(rawEvents.length).toBe(6); + expect(enhancedEvents.length).toBe(3); + }); + + it('should work with partial subscription', async () => { + const { prisma, enhance } = await loadSchema( + ` + model Post { + id Int @id @default(autoincrement()) + name String + + @@allow('read', contains(name, 'hello')) + } + `, + { + provider: 'postgresql', + dbUrl: PULSE_DB_URL, + pulseApiKey: PULSE_API_KEY, + logPrismaQuery: true, + } + ); + + await prisma.$queryRaw`ALTER TABLE public."Post" REPLICA IDENTITY FULL;`; + await prisma.post.deleteMany(); + + const rawSub = await prisma.post.stream({ create: {} }); + + const enhanced = enhance(); + const enhancedSub = await enhanced.post.stream({ create: {} }); + + async function produce() { + await prisma.post.create({ data: { id: 1, name: 'abc' } }); + console.log('created'); + await prisma.post.update({ where: { id: 1 }, data: { name: 'bcd' } }); + console.log('updated'); + await prisma.post.delete({ where: { id: 1 } }); + console.log('deleted'); + + await prisma.post.create({ data: { id: 2, name: 'hello world' } }); + console.log('created'); + await prisma.post.update({ where: { id: 2 }, data: { name: 'hello moon' } }); + console.log('updated'); + await prisma.post.delete({ where: { id: 2 } }); + console.log('deleted'); + + await new Promise((resolve) => setTimeout(resolve, 3000)); + } + + const rawEvents: any[] = []; + const enhancedEvents: any[] = []; + await Promise.race([ + produce(), + consume(rawSub, 'Raw', rawEvents), + consume(enhancedSub, 'Enhanced', enhancedEvents), + ]); + expect(rawEvents.length).toBe(2); + expect(enhancedEvents.length).toBe(1); + }); + + it('should work with combination of policies and user-provided filters', async () => { + const { prisma, enhance } = await loadSchema( + ` + model Post { + id Int @id @default(autoincrement()) + name String + + @@allow('read', contains(name, 'hello')) + } + `, + { + provider: 'postgresql', + dbUrl: PULSE_DB_URL, + pulseApiKey: PULSE_API_KEY, + logPrismaQuery: true, + } + ); + + await prisma.$queryRaw`ALTER TABLE public."Post" REPLICA IDENTITY FULL;`; + await prisma.post.deleteMany(); + + const rawSub = await prisma.post.stream({ + create: { name: { contains: 'world' } }, + update: { after: { name: { contains: 'world' } } }, + delete: { name: { contains: 'world' } }, + }); + + const enhanced = enhance(); + const enhancedSub = await enhanced.post.stream({ + create: { name: { contains: 'world' } }, + update: { after: { name: { contains: 'world' } } }, + delete: { name: { contains: 'world' } }, + }); + + async function produce() { + await prisma.post.create({ data: { id: 1, name: 'abc' } }); + console.log('created'); + await prisma.post.update({ where: { id: 1 }, data: { name: 'bcd' } }); + console.log('updated'); + await prisma.post.delete({ where: { id: 1 } }); + console.log('deleted'); + + await prisma.post.create({ data: { id: 2, name: 'good world' } }); + console.log('created'); + await prisma.post.update({ where: { id: 2 }, data: { name: 'nice world' } }); + console.log('updated'); + await prisma.post.delete({ where: { id: 2 } }); + console.log('deleted'); + + await prisma.post.create({ data: { id: 3, name: 'hello world' } }); + console.log('created'); + await prisma.post.update({ where: { id: 3 }, data: { name: 'hello nice world' } }); + console.log('updated'); + await prisma.post.delete({ where: { id: 3 } }); + console.log('deleted'); + + await new Promise((resolve) => setTimeout(resolve, 10000)); + } + + const rawEvents: any[] = []; + const enhancedEvents: any[] = []; + await Promise.race([ + produce(), + consume(rawSub, 'Raw', rawEvents), + consume(enhancedSub, 'Enhanced', enhancedEvents), + ]); + expect(rawEvents.length).toBe(6); + expect(enhancedEvents.length).toBe(3); + }); + + it('should work with field-level policies', async () => { + const { prisma, enhance } = await loadSchema( + ` + model Post { + id Int @id @default(autoincrement()) + name String @allow('read', contains(name, 'hello')) + + @@allow('all', true) + } + `, + { + provider: 'postgresql', + dbUrl: PULSE_DB_URL, + pulseApiKey: PULSE_API_KEY, + logPrismaQuery: true, + } + ); + + await prisma.$queryRaw`ALTER TABLE public."Post" REPLICA IDENTITY FULL;`; + await prisma.post.deleteMany(); + + const enhanced = enhance(); + const enhancedSub = await enhanced.post.stream(); + + async function produce() { + await prisma.post.create({ data: { id: 1, name: 'abc' } }); + console.log('created'); + await prisma.post.update({ where: { id: 1 }, data: { name: 'abc1' } }); + console.log('updated'); + await prisma.post.delete({ where: { id: 1 } }); + console.log('deleted'); + + await prisma.post.create({ data: { id: 2, name: 'hello1' } }); + console.log('created'); + await prisma.post.update({ where: { id: 2 }, data: { name: 'hello2' } }); + console.log('updated'); + await prisma.post.delete({ where: { id: 2 } }); + console.log('deleted'); + + await new Promise((resolve) => setTimeout(resolve, 10000)); + } + + const enhancedEvents: any[] = []; + await Promise.race([produce(), consume(enhancedSub, 'Enhanced', enhancedEvents)]); + expect(enhancedEvents.length).toBe(6); + expect(enhancedEvents.filter((e) => e.created?.name?.includes('abc'))).toHaveLength(0); + expect(enhancedEvents.filter((e) => e.updated?.before?.name?.includes('abc'))).toHaveLength(0); + expect(enhancedEvents.filter((e) => e.updated?.after?.name?.includes('abc'))).toHaveLength(0); + expect(enhancedEvents.filter((e) => e.updated?.name?.includes('abc'))).toHaveLength(0); + expect(enhancedEvents.filter((e) => e.deleted?.name?.includes('abc'))).toHaveLength(0); + }); + + it('should work with `@omit`', async () => { + const { prisma, enhance } = await loadSchema( + ` + model Post { + id Int @id @default(autoincrement()) + name String @omit + + @@allow('all', true) + } + `, + { + provider: 'postgresql', + dbUrl: PULSE_DB_URL, + pulseApiKey: PULSE_API_KEY, + logPrismaQuery: true, + } + ); + + await prisma.$queryRaw`ALTER TABLE public."Post" REPLICA IDENTITY FULL;`; + await prisma.post.deleteMany(); + + const enhanced = enhance(); + const enhancedSub = await enhanced.post.stream(); + + async function produce() { + await prisma.post.create({ data: { id: 1, name: 'abc' } }); + console.log('created'); + await prisma.post.update({ where: { id: 1 }, data: { name: 'bcd' } }); + console.log('updated'); + await prisma.post.delete({ where: { id: 1 } }); + console.log('deleted'); + + await new Promise((resolve) => setTimeout(resolve, 5000)); + } + + const enhancedEvents: any[] = []; + await Promise.race([produce(), consume(enhancedSub, 'Enhanced', enhancedEvents)]); + expect(enhancedEvents.length).toBe(3); + + for (const event of enhancedEvents) { + switch (event.action) { + case 'create': + expect(event.created.name).toBeUndefined(); + break; + case 'update': + expect(event.before?.name).toBeUndefined(); + expect(event.after?.name).toBeUndefined(); + break; + case 'delete': + expect(event.deleted.name).toBeUndefined(); + break; + } + } + }); +}); + +async function consume(subscription: any, name: string, events: any[]) { + console.log('Consuming', name); + for await (const event of subscription) { + console.log(name, 'got event:', event); + events.push(event); + } +} diff --git a/tests/integration/tests/enhancements/with-policy/subscription.test.ts b/tests/integration/tests/enhancements/with-policy/subscription.test.ts deleted file mode 100644 index aa93706d8..000000000 --- a/tests/integration/tests/enhancements/with-policy/subscription.test.ts +++ /dev/null @@ -1,260 +0,0 @@ -import { loadSchema } from '@zenstackhq/testtools'; -import path from 'path'; - -const DB_URL = ''; -const PULSE_API_KEY = ''; - -// eslint-disable-next-line jest/no-disabled-tests -describe.skip('With Policy: subscription test', () => { - let origDir: string; - - beforeAll(async () => { - origDir = path.resolve('.'); - }); - - afterEach(() => { - process.chdir(origDir); - }); - - it('subscribe auth check', async () => { - const { prisma, enhance } = await loadSchema( - ` - model User { - id Int @id @default(autoincrement()) - } - - model Model { - id Int @id @default(autoincrement()) - name String - - @@allow('read', auth() != null) - } - `, - { - provider: 'postgresql', - dbUrl: DB_URL, - pulseApiKey: PULSE_API_KEY, - } - ); - - await prisma.model.deleteMany(); - - const rawSub = await prisma.model.subscribe(); - - const anonDb = enhance(); - console.log('Anonymous db subscribing'); - const anonSub = await anonDb.model.subscribe(); - - const authDb = enhance({ id: 1 }); - console.log('Auth db subscribing'); - const authSub = await authDb.model.subscribe(); - - async function produce() { - await prisma.model.create({ data: { id: 1, name: 'abc' } }); - console.log('created'); - await prisma.model.update({ where: { id: 1 }, data: { name: 'bcd' } }); - console.log('updated'); - await prisma.model.delete({ where: { id: 1 } }); - console.log('deleted'); - await new Promise((resolve) => setTimeout(resolve, 2000)); - } - - const rawEvents: any[] = []; - const authEvents: any[] = []; - const anonEvents: any[] = []; - await Promise.race([ - produce(), - consume(rawSub, 'Raw', rawEvents), - consume(authSub, 'Auth', authEvents), - consume(anonSub, 'Anonymous', anonEvents), - ]); - expect(rawEvents.length).toBe(3); - expect(authEvents.length).toBe(3); - expect(anonEvents.length).toBe(0); - }); - - it('subscribe model check', async () => { - const { prisma, enhance } = await loadSchema( - ` - model Model { - id Int @id @default(autoincrement()) - name String - - @@allow('read', contains(name, 'hello')) - } - `, - { - provider: 'postgresql', - dbUrl: DB_URL, - pulseApiKey: PULSE_API_KEY, - } - ); - - await prisma.model.deleteMany(); - - const rawSub = await prisma.model.subscribe(); - - const enhanced = enhance(); - console.log('Auth db subscribing'); - const enhancedSub = await enhanced.model.subscribe(); - - async function produce() { - await prisma.model.create({ data: { id: 1, name: 'abc' } }); - console.log('created'); - await prisma.model.update({ where: { id: 1 }, data: { name: 'bcd' } }); - console.log('updated'); - await prisma.model.delete({ where: { id: 1 } }); - console.log('deleted'); - - await prisma.model.create({ data: { id: 2, name: 'hello world' } }); - console.log('created'); - await prisma.model.update({ where: { id: 2 }, data: { name: 'hello moon' } }); - console.log('updated'); - await prisma.model.delete({ where: { id: 2 } }); - console.log('deleted'); - - await new Promise((resolve) => setTimeout(resolve, 2000)); - } - - const rawEvents: any[] = []; - const enhancedEvents: any[] = []; - await Promise.race([ - produce(), - consume(rawSub, 'Raw', rawEvents), - consume(enhancedSub, 'Enhanced', enhancedEvents), - ]); - expect(rawEvents.length).toBe(6); - expect(enhancedEvents.length).toBe(3); - }); - - it('subscribe partial', async () => { - const { prisma, enhance } = await loadSchema( - ` - model Model { - id Int @id @default(autoincrement()) - name String - - @@allow('read', contains(name, 'hello')) - } - `, - { - provider: 'postgresql', - dbUrl: DB_URL, - pulseApiKey: PULSE_API_KEY, - } - ); - - await prisma.model.deleteMany(); - - const rawSub = await prisma.model.subscribe({ create: {} }); - - const enhanced = enhance(); - console.log('Auth db subscribing'); - const enhancedSub = await enhanced.model.subscribe({ create: {} }); - - async function produce() { - await prisma.model.create({ data: { id: 1, name: 'abc' } }); - console.log('created'); - await prisma.model.update({ where: { id: 1 }, data: { name: 'bcd' } }); - console.log('updated'); - await prisma.model.delete({ where: { id: 1 } }); - console.log('deleted'); - - await prisma.model.create({ data: { id: 2, name: 'hello world' } }); - console.log('created'); - await prisma.model.update({ where: { id: 2 }, data: { name: 'hello moon' } }); - console.log('updated'); - await prisma.model.delete({ where: { id: 2 } }); - console.log('deleted'); - - await new Promise((resolve) => setTimeout(resolve, 2000)); - } - - const rawEvents: any[] = []; - const enhancedEvents: any[] = []; - await Promise.race([ - produce(), - consume(rawSub, 'Raw', rawEvents), - consume(enhancedSub, 'Enhanced', enhancedEvents), - ]); - expect(rawEvents.length).toBe(2); - expect(enhancedEvents.length).toBe(1); - }); - - it('subscribe mixed model check', async () => { - const { prisma, enhance } = await loadSchema( - ` - model Model { - id Int @id @default(autoincrement()) - name String - - @@allow('read', contains(name, 'hello')) - } - `, - { - provider: 'postgresql', - dbUrl: DB_URL, - pulseApiKey: PULSE_API_KEY, - } - ); - - await prisma.model.deleteMany(); - - const rawSub = await prisma.model.subscribe({ - create: { after: { name: { contains: 'world' } } }, - update: { after: { name: { contains: 'world' } } }, - delete: { before: { name: { contains: 'world' } } }, - }); - - const enhanced = enhance(); - console.log('Auth db subscribing'); - const enhancedSub = await enhanced.model.subscribe({ - create: { after: { name: { contains: 'world' } } }, - update: { after: { name: { contains: 'world' } } }, - delete: { before: { name: { contains: 'world' } } }, - }); - - async function produce() { - await prisma.model.create({ data: { id: 1, name: 'abc' } }); - console.log('created'); - await prisma.model.update({ where: { id: 1 }, data: { name: 'bcd' } }); - console.log('updated'); - await prisma.model.delete({ where: { id: 1 } }); - console.log('deleted'); - - await prisma.model.create({ data: { id: 2, name: 'good world' } }); - console.log('created'); - await prisma.model.update({ where: { id: 2 }, data: { name: 'nice world' } }); - console.log('updated'); - await prisma.model.delete({ where: { id: 2 } }); - console.log('deleted'); - - await prisma.model.create({ data: { id: 3, name: 'hello world' } }); - console.log('created'); - await prisma.model.update({ where: { id: 3 }, data: { name: 'hello nice world' } }); - console.log('updated'); - await prisma.model.delete({ where: { id: 3 } }); - console.log('deleted'); - - await new Promise((resolve) => setTimeout(resolve, 2000)); - } - - const rawEvents: any[] = []; - const enhancedEvents: any[] = []; - await Promise.race([ - produce(), - consume(rawSub, 'Raw', rawEvents), - consume(enhancedSub, 'Enhanced', enhancedEvents), - ]); - expect(rawEvents.length).toBe(6); - expect(enhancedEvents.length).toBe(3); - }); -}); - -async function consume(subscription: any, name: string, events: any[]) { - console.log('Consuming', name); - for await (const event of subscription) { - console.log(name, 'got event:', event); - events.push(event); - } -} diff --git a/tests/integration/tests/frameworks/nextjs/test-project/package.json b/tests/integration/tests/frameworks/nextjs/test-project/package.json index 4e484cd8a..270f126d8 100644 --- a/tests/integration/tests/frameworks/nextjs/test-project/package.json +++ b/tests/integration/tests/frameworks/nextjs/test-project/package.json @@ -9,7 +9,7 @@ "lint": "next lint" }, "dependencies": { - "@prisma/client": "5.18.x", + "@prisma/client": "5.19.x", "@types/node": "18.11.18", "@types/react": "18.0.27", "@types/react-dom": "18.0.10", @@ -26,6 +26,6 @@ "@zenstackhq/swr": "../../../../../../../packages/plugins/swr/dist" }, "devDependencies": { - "prisma": "5.18.x" + "prisma": "5.19.x" } } diff --git a/tests/integration/tests/frameworks/trpc/test-project/package.json b/tests/integration/tests/frameworks/trpc/test-project/package.json index d75fb4f34..cb5d62b4c 100644 --- a/tests/integration/tests/frameworks/trpc/test-project/package.json +++ b/tests/integration/tests/frameworks/trpc/test-project/package.json @@ -9,7 +9,7 @@ "lint": "next lint" }, "dependencies": { - "@prisma/client": "5.18.x", + "@prisma/client": "5.19.x", "@tanstack/react-query": "^4.22.4", "@trpc/client": "^10.34.0", "@trpc/next": "^10.34.0", @@ -31,6 +31,6 @@ "@zenstackhq/trpc": "../../../../../../../packages/plugins/trpc/dist" }, "devDependencies": { - "prisma": "5.18.x" + "prisma": "5.19.x" } } diff --git a/tests/integration/tests/plugins/zod.test.ts b/tests/integration/tests/plugins/zod.test.ts index 5b896416d..2b9d73c59 100644 --- a/tests/integration/tests/plugins/zod.test.ts +++ b/tests/integration/tests/plugins/zod.test.ts @@ -458,6 +458,47 @@ describe('Zod plugin tests', () => { expect(schema.safeParse({ arr: [1, 2, 3] }).success).toBeTruthy(); }); + it('refinement with path', async () => { + const model = ` + datasource db { + provider = 'postgresql' + url = env('DATABASE_URL') + } + + generator js { + provider = 'prisma-client-js' + } + + plugin zod { + provider = "@core/zod" + } + + model M { + id Int @id @default(autoincrement()) + arr Int[] + + @@validate(!isEmpty(arr), 'condition1', ['array']) + @@validate(has(arr, 1), 'condition2', ['arr']) + @@validate(hasEvery(arr, [1, 2]), 'condition3', ['arr', 'every']) + @@validate(hasSome(arr, [1, 2]), 'condition4', ['arr', 'some']) + } + `; + + const { zodSchemas } = await loadSchema(model, { addPrelude: false, pushDb: false }); + + const schema = zodSchemas.models.MCreateSchema; + expect(schema.safeParse({}).error.issues[0].path).toEqual(['array']); + expect(schema.safeParse({ arr: [] }).error.issues[0].path).toEqual(['array']); + expect(schema.safeParse({ arr: [3] }).error.issues[0].path).toEqual(['arr']); + expect(schema.safeParse({ arr: [3] }).error.issues[1].path).toEqual(['arr', 'every']); + expect(schema.safeParse({ arr: [3] }).error.issues[2].path).toEqual(['arr', 'some']); + expect(schema.safeParse({ arr: [1] }).error.issues[0].path).toEqual(['arr', 'every']); + expect(schema.safeParse({ arr: [4] }).error.issues[0].path).toEqual(['arr']); + expect(schema.safeParse({ arr: [4] }).error.issues[1].path).toEqual(['arr', 'every']); + expect(schema.safeParse({ arr: [4] }).error.issues[2].path).toEqual(['arr', 'some']); + expect(schema.safeParse({ arr: [1, 2, 3] }).success).toBeTruthy(); + }); + it('full-text search', async () => { const model = ` datasource db { @@ -747,6 +788,11 @@ describe('Zod plugin tests', () => { provider = 'prisma-client-js' } + plugin enhancer { + provider = '@core/enhancer' + output = "$projectRoot/enhance" + } + plugin zod { provider = "@core/zod" output = "$projectRoot/zod" @@ -760,7 +806,7 @@ describe('Zod plugin tests', () => { password String @omit } `, - { addPrelude: false, pushDb: false, projectDir } + { addPrelude: false, pushDb: false, projectDir, getPrismaOnly: true, generateNoCompile: true } ); expect(fs.existsSync(path.join(projectDir, 'zod', 'test.txt'))).toBeFalsy(); @@ -781,6 +827,11 @@ describe('Zod plugin tests', () => { generator js { provider = 'prisma-client-js' } + + plugin enhancer { + provider = '@core/enhancer' + output = "$projectRoot/enhance" + } plugin zod { provider = "@core/zod" @@ -795,7 +846,7 @@ describe('Zod plugin tests', () => { password String @omit } `, - { addPrelude: false, pushDb: false, projectDir } + { addPrelude: false, pushDb: false, projectDir, generateNoCompile: true } ) ).rejects.toThrow('already exists and is not a directory'); }); diff --git a/tests/regression/tests/issue-1642.test.ts b/tests/regression/tests/issue-1642.test.ts new file mode 100644 index 000000000..70c0580e6 --- /dev/null +++ b/tests/regression/tests/issue-1642.test.ts @@ -0,0 +1,40 @@ +import { loadSchema } from '@zenstackhq/testtools'; +describe('issue 1642', () => { + it('regression', async () => { + const { prisma, enhance } = await loadSchema( + ` + model User { + id Int @id + name String + posts Post[] + + @@allow('read', true) + @@allow('all', auth().id == 1) + } + + model Post { + id Int @id + title String + description String + author User @relation(fields: [authorId], references: [id]) + authorId Int + + // delegate all access policies to the author: + @@allow('all', check(author)) + + @@allow('update', future().title == 'hello') + } + ` + ); + + await prisma.user.create({ data: { id: 1, name: 'User1' } }); + await prisma.post.create({ data: { id: 1, title: 'hello', description: 'desc1', authorId: 1 } }); + + const db = enhance({ id: 2 }); + await expect( + db.post.update({ where: { id: 1 }, data: { title: 'world', description: 'desc2' } }) + ).toBeRejectedByPolicy(); + + await expect(db.post.update({ where: { id: 1 }, data: { description: 'desc2' } })).toResolveTruthy(); + }); +}); diff --git a/tests/regression/tests/issue-1644.test.ts b/tests/regression/tests/issue-1644.test.ts new file mode 100644 index 000000000..212cf5c99 --- /dev/null +++ b/tests/regression/tests/issue-1644.test.ts @@ -0,0 +1,23 @@ +import { loadSchema } from '@zenstackhq/testtools'; +describe('issue 1644', () => { + it('regression', async () => { + const { prisma, enhance } = await loadSchema( + ` + model User { + id Int @id @default(autoincrement()) + email String @unique @email @length(6, 32) @allow('read', auth() == this) + + // full access to all + @@allow('all', true) + } + ` + ); + + await prisma.user.create({ data: { id: 1, email: 'a@example.com' } }); + await prisma.user.create({ data: { id: 2, email: 'b@example.com' } }); + + const db = enhance({ id: 1 }); + await expect(db.user.count({ where: { email: { contains: 'example.com' } } })).resolves.toBe(1); + await expect(db.user.findMany({ where: { email: { contains: 'example.com' } } })).resolves.toHaveLength(1); + }); +}); diff --git a/tests/regression/tests/issue-1645.test.ts b/tests/regression/tests/issue-1645.test.ts new file mode 100644 index 000000000..3bf717f96 --- /dev/null +++ b/tests/regression/tests/issue-1645.test.ts @@ -0,0 +1,203 @@ +import { loadSchema } from '@zenstackhq/testtools'; +describe('issue 1645', () => { + it('regression', async () => { + const { enhance } = await loadSchema( + ` + model Product { + id String @id @default(cuid()) + name String + slug String + description String? + sku String + price Int + onSale Boolean @default(false) + salePrice Int @default(0) + saleStartDateTime DateTime? + saleEndDateTime DateTime? + scheduledAvailability Boolean @default(false) + availabilityStartDateTime DateTime? + availabilityEndDateTime DateTime? + type String @default('VARIABLE') + image String + orderItems OrderItem[] + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@unique([slug]) + + @@allow('all', true) + } + + model BaseOrder { + id String @id @default(cuid()) + orderNumber String @unique @default(nanoid(16)) + lineItems OrderItem[] + status String @default('PENDING') + type String @default('PARENT') + userType String? + billingAddress BillingAddress @relation(fields: [billingAddressId], references: [id]) + billingAddressId String @map("billing_address_id") + shippingAddress ShippingAddress @relation(fields: [shippingAddressId], references: [id]) + shippingAddressId String @map("shipping_address_id") + notes String? @default('') + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@allow('all', true) + @@delegate(userType) + } + + model Order extends BaseOrder { + parentId String? @map("parent_id") + parent Order? @relation("OrderToParent", fields: [parentId], references: [id]) + groupedOrders Order[] @relation("OrderToParent") + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + userId String @map("user_id") + } + + model User { + id String @id @default(cuid()) + name String? + email String? @unique + emailVerified DateTime? + image String? + orders Order[] + billingAddresses BillingAddress[] + shippingAddresses ShippingAddress[] + + @@allow('create,read', true) + @@allow('update,delete', auth().id == this.id) + } + + model GuestUser { + id String @id @default(cuid()) + name String? + email String @unique + orders GuestOrder[] + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@auth + @@allow('all', true) + } + + model GuestOrder extends BaseOrder { + guestUser GuestUser @relation(fields: [guestUserId], references: [id], onDelete: Cascade) + guestUserId String @map("guest_user_id") + parentId String? @map("parent_id") + parent GuestOrder? @relation("OrderToParent", fields: [parentId], references: [id]) + groupedOrders GuestOrder[] @relation("OrderToParent") + } + + model OrderItem { + id String @id @default(cuid()) + order BaseOrder @relation(fields: [orderId], references: [id], onDelete: Cascade) + orderId String @map("order_id") + product Product @relation(fields: [productId], references: [id]) + productId String @map("product_id") + quantity Int + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@allow('all', true) + } + + model OrderAddress { + id String @id @default(cuid()) + firstName String + lastName String + address1 String + address2 String? + city String + state String + postalCode String + country String + email String + phone String + type String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@allow('all', true) + @@delegate(type) + } + + model BillingAddress extends OrderAddress { + user User? @relation(fields: [userId], references: [id], onDelete: Cascade) + userId String? @map("user_id") + order BaseOrder[] + } + + model ShippingAddress extends OrderAddress { + user User? @relation(fields: [userId], references: [id], onDelete: Cascade) + userId String? @map("user_id") + order BaseOrder[] + } + ` + ); + + const db = enhance(); + + await db.user.create({ data: { id: '1', name: 'John', email: 'john@example.com' } }); + + const shipping = await db.shippingAddress.create({ + data: { + id: '1', + firstName: 'John', + lastName: 'Doe', + address1: '123 Main St', + city: 'Anytown', + state: 'CA', + postalCode: '12345', + country: 'US', + email: 'john@example.com', + phone: '123-456-7890', + user: { connect: { id: '1' } }, + }, + }); + + const billing = await db.billingAddress.create({ + data: { + id: '2', + firstName: 'John', + lastName: 'Doe', + address1: '123 Main St', + city: 'Anytown', + state: 'CA', + postalCode: '12345', + country: 'US', + email: 'john@example.com', + phone: '123-456-7890', + user: { connect: { id: '1' } }, + }, + }); + + await db.order.create({ + data: { + id: '1', + orderNumber: '1', + status: 'PENDING', + type: 'PARENT', + shippingAddress: { connect: { id: '1' } }, + billingAddress: { connect: { id: '2' } }, + user: { connect: { id: '1' } }, + }, + }); + + const updated = await db.order.update({ + where: { id: '1' }, + include: { + lineItems: true, + billingAddress: true, + shippingAddress: true, + }, + data: { + type: 'CAMPAIGN', + }, + }); + + console.log(updated); + expect(updated.shippingAddress).toEqual(shipping); + expect(updated.billingAddress).toEqual(billing); + }); +}); diff --git a/tests/regression/tests/issue-1648.test.ts b/tests/regression/tests/issue-1648.test.ts new file mode 100644 index 000000000..67a19e0ed --- /dev/null +++ b/tests/regression/tests/issue-1648.test.ts @@ -0,0 +1,43 @@ +import { loadSchema } from '@zenstackhq/testtools'; +describe('issue 1648', () => { + it('regression', async () => { + const { prisma, enhance } = await loadSchema( + ` + model User { + id Int @id @default(autoincrement()) + profile Profile? + posts Post[] + } + + model Profile { + id Int @id @default(autoincrement()) + someText String + user User @relation(fields: [userId], references: [id]) + userId Int @unique + } + + model Post { + id Int @id @default(autoincrement()) + title String + + userId Int + user User @relation(fields: [userId], references: [id]) + + // this will always be true, even if the someText field is "canUpdate" + @@deny("update", future().user.profile.someText != "canUpdate") + + @@allow("all", true) + } + ` + ); + + await prisma.user.create({ data: { id: 1, profile: { create: { someText: 'canUpdate' } } } }); + await prisma.user.create({ data: { id: 2, profile: { create: { someText: 'nothing' } } } }); + await prisma.post.create({ data: { id: 1, title: 'Post1', userId: 1 } }); + await prisma.post.create({ data: { id: 2, title: 'Post2', userId: 2 } }); + + const db = enhance(); + await expect(db.post.update({ where: { id: 1 }, data: { title: 'Post1-1' } })).toResolveTruthy(); + await expect(db.post.update({ where: { id: 2 }, data: { title: 'Post2-2' } })).toBeRejectedByPolicy(); + }); +}); diff --git a/tests/regression/tests/issue-1667.test.ts b/tests/regression/tests/issue-1667.test.ts new file mode 100644 index 000000000..0e84d5f14 --- /dev/null +++ b/tests/regression/tests/issue-1667.test.ts @@ -0,0 +1,86 @@ +import { loadSchema } from '@zenstackhq/testtools'; + +describe('issue 1667', () => { + it('custom enhance standard zod output', async () => { + await loadSchema( + ` + generator client { + provider = "prisma-client-js" + } + + datasource db { + provider = "sqlite" + url = "file:./dev.db" + } + + plugin enhancer { + provider = '@core/enhancer' + output = './zen' + } + + model User { + id Int @id + email String @unique @email + } + `, + { addPrelude: false, getPrismaOnly: true, preserveTsFiles: true } + ); + }); + + it('custom enhance custom zod output', async () => { + await loadSchema( + ` + generator client { + provider = "prisma-client-js" + } + + datasource db { + provider = "sqlite" + url = "file:./dev.db" + } + + plugin enhancer { + provider = '@core/enhancer' + output = './zen' + } + + plugin zod { + provider = '@core/zod' + output = './myzod' + } + + model User { + id Int @id + email String @unique @email + } + `, + { addPrelude: false, getPrismaOnly: true, generateNoCompile: true, compile: true } + ); + }); + + it('standard enhance custom zod output', async () => { + await loadSchema( + ` + generator client { + provider = "prisma-client-js" + } + + datasource db { + provider = "sqlite" + url = "file:./dev.db" + } + + plugin zod { + provider = '@core/zod' + output = './myzod' + } + + model User { + id Int @id + email String @unique @email + } + `, + { addPrelude: false, getPrismaOnly: true, compile: true } + ); + }); +}); diff --git a/tests/regression/tests/issue-1674.test.ts b/tests/regression/tests/issue-1674.test.ts new file mode 100644 index 000000000..0928e5464 --- /dev/null +++ b/tests/regression/tests/issue-1674.test.ts @@ -0,0 +1,87 @@ +import { loadSchema } from '@zenstackhq/testtools'; +describe('issue 1674', () => { + it('regression', async () => { + const { prisma, enhance } = await loadSchema( + ` + model User { + id String @id @default(cuid()) + email String @unique @email @length(6, 32) + password String @password @omit + posts Post[] + + // everybody can signup + @@allow('create', true) + + // full access by self + @@allow('all', auth() == this) + } + + model Blog { + id String @id @default(cuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + post Post? @relation(fields: [postId], references: [id], onDelete: Cascade) + postId String? + } + + model Post { + id String @id @default(cuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + title String @length(1, 256) + content String + published Boolean @default(false) + author User @relation(fields: [authorId], references: [id]) + authorId String + + blogs Blog[] + + type String + + // allow read for all signin users + @@allow('read', auth() != null && published) + + // full access by author + @@allow('all', author == auth()) + + @@delegate(type) + } + + model PostA extends Post { + } + + model PostB extends Post { + } + ` + ); + + const user = await prisma.user.create({ + data: { email: 'abc@def.com', password: 'password' }, + }); + + const blog = await prisma.blog.create({ + data: {}, + }); + + const db = enhance(user); + await expect( + db.postA.create({ + data: { + content: 'content', + title: 'title', + blogs: { + connect: { + id: blog.id, + }, + }, + author: { + connect: { + id: user.id, + }, + }, + }, + }) + ).toBeRejectedByPolicy(); + }); +});