diff --git a/package.json b/package.json index 73f953f73..edcfe5c82 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "zenstack-monorepo", - "version": "1.0.0-alpha.79", + "version": "1.0.0-alpha.81", "description": "", "scripts": { "build": "pnpm -r build", diff --git a/packages/language/package.json b/packages/language/package.json index a8d7d3a16..75de13f1f 100644 --- a/packages/language/package.json +++ b/packages/language/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/language", - "version": "1.0.0-alpha.79", + "version": "1.0.0-alpha.81", "displayName": "ZenStack modeling language compiler", "description": "ZenStack modeling language compiler", "homepage": "https://zenstack.dev", diff --git a/packages/next/package.json b/packages/next/package.json index 698de99d0..6a189d0fb 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/next", - "version": "1.0.0-alpha.79", + "version": "1.0.0-alpha.81", "displayName": "ZenStack Next.js integration", "description": "ZenStack Next.js integration", "homepage": "https://zenstack.dev", diff --git a/packages/plugins/openapi/package.json b/packages/plugins/openapi/package.json index 6f1936ad2..62fc4a242 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": "1.0.0-alpha.79", + "version": "1.0.0-alpha.81", "description": "ZenStack plugin and runtime supporting OpenAPI", "main": "index.js", "repository": { diff --git a/packages/plugins/openapi/src/generator.ts b/packages/plugins/openapi/src/generator.ts index 7420f21e5..fbab3e160 100644 --- a/packages/plugins/openapi/src/generator.ts +++ b/packages/plugins/openapi/src/generator.ts @@ -1,7 +1,7 @@ // Inspired by: https://github.com/omar-dulaimi/prisma-trpc-generator import { DMMF } from '@prisma/generator-helper'; -import { AUXILIARY_FIELDS, hasAttribute, PluginError, PluginOptions } from '@zenstackhq/sdk'; +import { AUXILIARY_FIELDS, getDataModels, hasAttribute, PluginError, PluginOptions } from '@zenstackhq/sdk'; import { DataModel, isDataModel, type Model } from '@zenstackhq/sdk/ast'; import { addMissingInputObjectTypesForAggregate, @@ -28,6 +28,7 @@ export class OpenAPIGenerator { private usedComponents: Set = new Set(); private aggregateOperationSupport: AggregateOperationSupport; private includedModels: DataModel[]; + private warnings: string[] = []; constructor(private model: Model, private options: PluginOptions, private dmmf: DMMF.Document) {} @@ -40,9 +41,7 @@ export class OpenAPIGenerator { // input types this.inputObjectTypes.push(...this.dmmf.schema.inputObjectTypes.prisma); this.outputObjectTypes.push(...this.dmmf.schema.outputObjectTypes.prisma); - this.includedModels = this.model.declarations.filter( - (d): d is DataModel => isDataModel(d) && !hasAttribute(d, '@@openapi.ignore') - ); + this.includedModels = getDataModels(this.model).filter((d) => !hasAttribute(d, '@@openapi.ignore')); // add input object types that are missing from Prisma dmmf addMissingInputObjectTypesForModelArgs(this.inputObjectTypes, this.dmmf.datamodel.models); @@ -80,6 +79,8 @@ export class OpenAPIGenerator { } else { fs.writeFileSync(output, JSON.stringify(openapi, undefined, 2)); } + + return this.warnings; } private pruneComponents(components: OAPI.ComponentsObject) { @@ -148,7 +149,7 @@ export class OpenAPIGenerator { ...this.generatePathsForModel(model, zmodel, components), } as OAPI.PathsObject; } else { - console.warn(`Unable to load ZModel definition for: ${model.name}}`); + this.warnings.push(`Unable to load ZModel definition for: ${model.name}}`); } } } @@ -159,13 +160,14 @@ export class OpenAPIGenerator { model: DMMF.Model, zmodel: DataModel, components: OAPI.ComponentsObject - ): OAPI.PathItemObject { + ): OAPI.PathItemObject | undefined { const result: OAPI.PathItemObject & Record = {}; // eslint-disable-next-line @typescript-eslint/no-explicit-any const ops: (DMMF.ModelMapping & { createOne?: string | null } & Record) | undefined = this.dmmf.mappings.modelOperations.find((ops) => ops.model === model.name); if (!ops) { - throw new PluginError(`No operations found for model ${model.name}`); + this.warnings.push(`Unable to find mapping for model ${model.name}`); + return undefined; } type OperationDefinition = { diff --git a/packages/plugins/openapi/tests/openapi.test.ts b/packages/plugins/openapi/tests/openapi.test.ts index 243fd0109..70aae2e83 100644 --- a/packages/plugins/openapi/tests/openapi.test.ts +++ b/packages/plugins/openapi/tests/openapi.test.ts @@ -1,91 +1,70 @@ /// -import { getDMMF } from '@prisma/internals'; import OpenAPIParser from '@readme/openapi-parser'; -import * as fs from 'fs'; +import { loadZModelAndDmmf } from '@zenstackhq/testtools'; import * as tmp from 'tmp'; -import { loadDocument } from 'zenstack/cli/cli-util'; -import prismaPlugin from 'zenstack/plugins/prisma'; import generate from '../src'; -async function loadZModelAndDmmf(content: string) { - const prelude = ` - datasource db { - provider = 'postgresql' - url = env('DATABASE_URL') - } -`; - - const { name: modelFile } = tmp.fileSync({ postfix: '.zmodel' }); - fs.writeFileSync(modelFile, `${prelude}\n${content}`); - - const model = await loadDocument(modelFile); - - const { name: prismaFile } = tmp.fileSync({ postfix: '.prisma' }); - await prismaPlugin(model, { schemaPath: modelFile, output: prismaFile, generateClient: false }); - - const prismaContent = fs.readFileSync(prismaFile, { encoding: 'utf-8' }); - - const dmmf = await getDMMF({ datamodel: prismaContent }); - return { model, dmmf, modelFile }; -} - describe('Open API Plugin Tests', () => { it('run plugin', async () => { const { model, dmmf, modelFile } = await loadZModelAndDmmf(` - plugin openapi { - provider = '${process.cwd()}/dist' - } +plugin openapi { + provider = '${process.cwd()}/dist' +} - enum Role { - USER - ADMIN - } +enum Role { + USER + ADMIN +} - model User { - id String @id - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - email String @unique - role Role @default(USER) - posts Post[] - - @@openapi.meta({ - findMany: { - description: 'Find users matching the given conditions' - }, - delete: { - method: 'put', - path: 'dodelete', - description: 'Delete a unique user', - summary: 'Delete a user yeah yeah', - tags: ['delete', 'user'] - }, - }) - } - - model Post { - id String @id - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - title String - author User? @relation(fields: [authorId], references: [id]) - authorId String? - published Boolean @default(false) - viewCount Int @default(0) - - @@openapi.meta({ - findMany: { - ignore: true - } - }) - } +model User { + id String @id + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + email String @unique + role Role @default(USER) + posts Post[] + + @@openapi.meta({ + findMany: { + description: 'Find users matching the given conditions' + }, + delete: { + method: 'put', + path: 'dodelete', + description: 'Delete a unique user', + summary: 'Delete a user yeah yeah', + tags: ['delete', 'user'] + }, + }) +} - model Foo { - id String @id +model Post { + id String @id + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + title String + author User? @relation(fields: [authorId], references: [id]) + authorId String? + published Boolean @default(false) + viewCount Int @default(0) + + @@openapi.meta({ + findMany: { + ignore: true + } + }) +} - @@openapi.ignore - } +model Foo { + id String @id + @@openapi.ignore +} + +model Bar { + id String @id + @@ignore +} `); const { name: output } = tmp.fileSync({ postfix: '.yaml' }); @@ -102,5 +81,6 @@ describe('Open API Plugin Tests', () => { expect(api.paths?.['/post/findMany']).toBeUndefined(); expect(api.paths?.['/foo/findMany']).toBeUndefined(); + expect(api.paths?.['/bar/findMany']).toBeUndefined(); }); }); diff --git a/packages/plugins/react/jest.config.ts b/packages/plugins/react/jest.config.ts new file mode 100644 index 000000000..917cf52f6 --- /dev/null +++ b/packages/plugins/react/jest.config.ts @@ -0,0 +1,29 @@ +/* + * For a detailed explanation regarding each configuration property and type check, visit: + * https://jestjs.io/docs/configuration + */ + +export default { + // Automatically clear mock calls, instances, contexts and results before every test + clearMocks: true, + + // Indicates whether the coverage information should be collected while executing the test + collectCoverage: true, + + // The directory where Jest should output its coverage files + coverageDirectory: 'tests/coverage', + + // An array of regexp pattern strings used to skip coverage collection + coveragePathIgnorePatterns: ['/node_modules/', '/tests/'], + + // Indicates which provider should be used to instrument code for coverage + coverageProvider: 'v8', + + // A list of reporter names that Jest uses when writing coverage reports + coverageReporters: ['json', 'text', 'lcov', 'clover'], + + // A map from regular expressions to paths to transformers + transform: { '^.+\\.tsx?$': 'ts-jest' }, + + testTimeout: 300000, +}; diff --git a/packages/plugins/react/package.json b/packages/plugins/react/package.json index 8e328bb63..1ab246060 100644 --- a/packages/plugins/react/package.json +++ b/packages/plugins/react/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/react", "displayName": "ZenStack plugin and runtime for ReactJS", - "version": "1.0.0-alpha.79", + "version": "1.0.0-alpha.81", "description": "ZenStack plugin and runtime for ReactJS", "main": "index.js", "repository": { @@ -37,9 +37,14 @@ "react-dom": "^17.0.2 || ^18" }, "devDependencies": { + "@types/jest": "^29.5.0", "@types/react": "^18.0.26", + "@types/tmp": "^0.2.3", "copyfiles": "^2.4.1", + "jest": "^29.5.0", "rimraf": "^3.0.2", - "typescript": "^4.9.4" + "ts-jest": "^29.0.5", + "typescript": "^4.9.4", + "@zenstackhq/testtools": "workspace:*" } } diff --git a/packages/plugins/react/src/react-hooks-generator.ts b/packages/plugins/react/src/react-hooks-generator.ts index 5b2a8c708..1efda5bdf 100644 --- a/packages/plugins/react/src/react-hooks-generator.ts +++ b/packages/plugins/react/src/react-hooks-generator.ts @@ -1,6 +1,6 @@ import { DMMF } from '@prisma/generator-helper'; -import { CrudFailureReason, PluginError, PluginOptions } from '@zenstackhq/sdk'; -import { DataModel, isDataModel, Model } from '@zenstackhq/sdk/ast'; +import { CrudFailureReason, getDataModels, PluginError, PluginOptions } from '@zenstackhq/sdk'; +import { DataModel, Model } from '@zenstackhq/sdk/ast'; import { camelCase, paramCase } from 'change-case'; import * as path from 'path'; import { Project } from 'ts-morph'; @@ -18,13 +18,17 @@ export async function generate(model: Model, options: PluginOptions, dmmf: DMMF. const project = new Project(); const warnings: string[] = []; - const models = model.declarations.filter((d): d is DataModel => isDataModel(d)); + const models = getDataModels(model); generateIndex(project, outDir, models); - models.forEach((model) => { - const mapping = dmmf.mappings.modelOperations.find((op) => op.model === model.name); - generateModelHooks(project, outDir, model, mapping); + models.forEach((dataModel) => { + const mapping = dmmf.mappings.modelOperations.find((op) => op.model === dataModel.name); + if (!mapping) { + warnings.push(`Unable to find mapping for model ${dataModel.name}`); + return; + } + generateModelHooks(project, outDir, dataModel, mapping); }); await project.save(); @@ -44,12 +48,7 @@ function wrapReadbackErrorCheck(code: string) { }`; } -function generateModelHooks( - project: Project, - outDir: string, - model: DataModel, - mapping: DMMF.ModelMapping | undefined -) { +function generateModelHooks(project: Project, outDir: string, model: DataModel, mapping: DMMF.ModelMapping) { const fileName = paramCase(model.name); const sf = project.createSourceFile(path.join(outDir, `${fileName}.ts`), undefined, { overwrite: true }); @@ -86,7 +85,7 @@ function generateModelHooks( // create is somehow named "createOne" in the DMMF // eslint-disable-next-line @typescript-eslint/no-explicit-any - if (mapping?.create || (mapping as any)?.createOne) { + if (mapping.create || (mapping as any).createOne) { methods.push('create'); const argsType = `Prisma.${model.name}CreateArgs`; const inputType = `Prisma.SelectSubset`; @@ -112,7 +111,7 @@ function generateModelHooks( } // createMany - if (mapping?.createMany) { + if (mapping.createMany) { methods.push('createMany'); const argsType = `Prisma.${model.name}CreateManyArgs`; const inputType = `Prisma.SelectSubset`; @@ -136,7 +135,7 @@ function generateModelHooks( } // findMany - if (mapping?.findMany) { + if (mapping.findMany) { methods.push('findMany'); const argsType = `Prisma.${model.name}FindManyArgs`; const inputType = `Prisma.SelectSubset`; @@ -163,7 +162,7 @@ function generateModelHooks( } // findUnique - if (mapping?.findUnique) { + if (mapping.findUnique) { methods.push('findUnique'); const argsType = `Prisma.${model.name}FindUniqueArgs`; const inputType = `Prisma.SelectSubset`; @@ -190,7 +189,7 @@ function generateModelHooks( } // findFirst - if (mapping?.findFirst) { + if (mapping.findFirst) { methods.push('findFirst'); const argsType = `Prisma.${model.name}FindFirstArgs`; const inputType = `Prisma.SelectSubset`; @@ -219,7 +218,7 @@ function generateModelHooks( // update // update is somehow named "updateOne" in the DMMF // eslint-disable-next-line @typescript-eslint/no-explicit-any - if (mapping?.update || (mapping as any).updateOne) { + if (mapping.update || (mapping as any).updateOne) { methods.push('update'); const argsType = `Prisma.${model.name}UpdateArgs`; const inputType = `Prisma.SelectSubset`; @@ -245,7 +244,7 @@ function generateModelHooks( } // updateMany - if (mapping?.updateMany) { + if (mapping.updateMany) { methods.push('updateMany'); const argsType = `Prisma.${model.name}UpdateManyArgs`; const inputType = `Prisma.SelectSubset`; @@ -271,7 +270,7 @@ function generateModelHooks( // upsert // upsert is somehow named "upsertOne" in the DMMF // eslint-disable-next-line @typescript-eslint/no-explicit-any - if (mapping?.upsert || (mapping as any).upsertOne) { + if (mapping.upsert || (mapping as any).upsertOne) { methods.push('upsert'); const argsType = `Prisma.${model.name}UpsertArgs`; const inputType = `Prisma.SelectSubset`; @@ -299,7 +298,7 @@ function generateModelHooks( // del // delete is somehow named "deleteOne" in the DMMF // eslint-disable-next-line @typescript-eslint/no-explicit-any - if (mapping?.delete || (mapping as any).deleteOne) { + if (mapping.delete || (mapping as any).deleteOne) { methods.push('del'); const argsType = `Prisma.${model.name}DeleteArgs`; const inputType = `Prisma.SelectSubset`; @@ -325,7 +324,7 @@ function generateModelHooks( } // deleteMany - if (mapping?.deleteMany) { + if (mapping.deleteMany) { methods.push('deleteMany'); const argsType = `Prisma.${model.name}DeleteManyArgs`; const inputType = `Prisma.SelectSubset`; @@ -349,7 +348,7 @@ function generateModelHooks( } // aggregate - if (mapping?.aggregate) { + if (mapping.aggregate) { methods.push('aggregate'); const argsType = `Prisma.${model.name}AggregateArgs`; const inputType = `Prisma.Subset`; @@ -376,7 +375,7 @@ function generateModelHooks( } // groupBy - if (mapping?.groupBy) { + if (mapping.groupBy) { methods.push('groupBy'); const returnType = `{} extends InputErrors ? Prisma.Get${model.name}GroupByPayload : InputErrors`; useFunc @@ -453,7 +452,7 @@ function generateModelHooks( } // count - if (mapping?.count) { + if (mapping.count) { methods.push('count'); const argsType = `Prisma.${model.name}CountArgs`; const inputType = `Prisma.Subset`; diff --git a/packages/plugins/react/tests/react-hooks.test.ts b/packages/plugins/react/tests/react-hooks.test.ts new file mode 100644 index 000000000..01b8e0209 --- /dev/null +++ b/packages/plugins/react/tests/react-hooks.test.ts @@ -0,0 +1,55 @@ +/// + +import { loadSchema } from '@zenstackhq/testtools'; + +describe('React Hooks Plugin Tests', () => { + let origDir: string; + + beforeAll(() => { + origDir = process.cwd(); + }); + + afterEach(() => { + process.chdir(origDir); + }); + + it('run plugin', async () => { + await loadSchema( + ` +plugin react { + provider = '${process.cwd()}/dist' + output = '$projectRoot/hooks' +} + +model User { + id String @id + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + email String @unique + role String @default('USER') + posts Post[] +} + +model Post { + id String @id + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + title String + author User? @relation(fields: [authorId], references: [id]) + authorId String? + published Boolean @default(false) + viewCount Int @default(0) +} + +model Foo { + id String @id + @@ignore +} + `, + true, + false, + [`${origDir}/dist`, 'react', '@types/react'], + true + ); + }); +}); diff --git a/packages/plugins/trpc/jest.config.ts b/packages/plugins/trpc/jest.config.ts new file mode 100644 index 000000000..917cf52f6 --- /dev/null +++ b/packages/plugins/trpc/jest.config.ts @@ -0,0 +1,29 @@ +/* + * For a detailed explanation regarding each configuration property and type check, visit: + * https://jestjs.io/docs/configuration + */ + +export default { + // Automatically clear mock calls, instances, contexts and results before every test + clearMocks: true, + + // Indicates whether the coverage information should be collected while executing the test + collectCoverage: true, + + // The directory where Jest should output its coverage files + coverageDirectory: 'tests/coverage', + + // An array of regexp pattern strings used to skip coverage collection + coveragePathIgnorePatterns: ['/node_modules/', '/tests/'], + + // Indicates which provider should be used to instrument code for coverage + coverageProvider: 'v8', + + // A list of reporter names that Jest uses when writing coverage reports + coverageReporters: ['json', 'text', 'lcov', 'clover'], + + // A map from regular expressions to paths to transformers + transform: { '^.+\\.tsx?$': 'ts-jest' }, + + testTimeout: 300000, +}; diff --git a/packages/plugins/trpc/package.json b/packages/plugins/trpc/package.json index d8a7e5afa..edee7573c 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": "1.0.0-alpha.79", + "version": "1.0.0-alpha.81", "description": "ZenStack plugin for tRPC", "main": "index.js", "repository": { @@ -34,9 +34,13 @@ "zod": "^3.19.1" }, "devDependencies": { + "@types/jest": "^29.5.0", "@types/prettier": "^2.7.2", + "@zenstackhq/testtools": "workspace:*", "copyfiles": "^2.4.1", + "jest": "^29.5.0", "rimraf": "^3.0.2", + "ts-jest": "^29.0.5", "typescript": "^4.9.4" } } diff --git a/packages/plugins/trpc/tests/trpc.test.ts b/packages/plugins/trpc/tests/trpc.test.ts new file mode 100644 index 000000000..2ca105c7e --- /dev/null +++ b/packages/plugins/trpc/tests/trpc.test.ts @@ -0,0 +1,55 @@ +/// + +import { loadSchema } from '@zenstackhq/testtools'; + +describe('tRPC Plugin Tests', () => { + let origDir: string; + + beforeAll(() => { + origDir = process.cwd(); + }); + + afterEach(() => { + process.chdir(origDir); + }); + + it('run plugin', async () => { + await loadSchema( + ` +plugin trpc { + provider = '${process.cwd()}/dist' + output = '$projectRoot/trpc' +} + +model User { + id String @id + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + email String @unique + role String @default('USER') + posts Post[] +} + +model Post { + id String @id + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + title String + author User? @relation(fields: [authorId], references: [id]) + authorId String? + published Boolean @default(false) + viewCount Int @default(0) +} + +model Foo { + id String @id + @@ignore +} + `, + true, + false, + [`${origDir}/dist`, '@trpc/client', '@trpc/server'], + true + ); + }); +}); diff --git a/packages/runtime/package.json b/packages/runtime/package.json index 86c2c8533..e45798a46 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/runtime", "displayName": "ZenStack Runtime Library", - "version": "1.0.0-alpha.79", + "version": "1.0.0-alpha.81", "description": "Runtime of ZenStack for both client-side and server-side environments.", "repository": { "type": "git", diff --git a/packages/schema/package.json b/packages/schema/package.json index 3b09fddd3..4e8378105 100644 --- a/packages/schema/package.json +++ b/packages/schema/package.json @@ -3,7 +3,7 @@ "publisher": "zenstack", "displayName": "ZenStack Language Tools", "description": "A toolkit for building secure CRUD apps with Next.js + Typescript", - "version": "1.0.0-alpha.79", + "version": "1.0.0-alpha.81", "author": { "name": "ZenStack Team" }, diff --git a/packages/schema/src/plugins/access-policy/policy-guard-generator.ts b/packages/schema/src/plugins/access-policy/policy-guard-generator.ts index c0b9c3b86..9f0fcd5af 100644 --- a/packages/schema/src/plugins/access-policy/policy-guard-generator.ts +++ b/packages/schema/src/plugins/access-policy/policy-guard-generator.ts @@ -14,7 +14,7 @@ import { Model, } from '@zenstackhq/language/ast'; import { PolicyKind, PolicyOperationKind } from '@zenstackhq/runtime'; -import { getLiteral, GUARD_FIELD_NAME, PluginError, PluginOptions, resolved } from '@zenstackhq/sdk'; +import { getDataModels, getLiteral, GUARD_FIELD_NAME, PluginError, PluginOptions, resolved } from '@zenstackhq/sdk'; import { camelCase } from 'change-case'; import { streamAllContents } from 'langium'; import path from 'path'; @@ -60,7 +60,7 @@ export default class PolicyGenerator { }); } - const models = model.declarations.filter((d) => isDataModel(d)) as DataModel[]; + const models = getDataModels(model); const policyMap: Record> = {}; for (const model of models) { diff --git a/packages/schema/src/plugins/model-meta/index.ts b/packages/schema/src/plugins/model-meta/index.ts index 1608baf2e..7ff2f918a 100644 --- a/packages/schema/src/plugins/model-meta/index.ts +++ b/packages/schema/src/plugins/model-meta/index.ts @@ -8,7 +8,7 @@ import { ReferenceExpr, } from '@zenstackhq/language/ast'; import { RuntimeAttribute } from '@zenstackhq/runtime'; -import { getAttributeArgs, getLiteral, hasAttribute, PluginOptions, resolved } from '@zenstackhq/sdk'; +import { getAttributeArgs, getDataModels, getLiteral, hasAttribute, PluginOptions, resolved } from '@zenstackhq/sdk'; import { camelCase } from 'change-case'; import path from 'path'; import { CodeBlockWriter, Project, VariableDeclarationKind } from 'ts-morph'; @@ -24,7 +24,7 @@ export default async function run(model: Model, options: PluginOptions) { return; } - const dataModels = model.declarations.filter((d): d is DataModel => isDataModel(d)); + const dataModels = getDataModels(model); const project = new Project(); diff --git a/packages/schema/tests/schema/cal-com.zmodel b/packages/schema/tests/schema/cal-com.zmodel index 9d3f40196..c6e874304 100644 --- a/packages/schema/tests/schema/cal-com.zmodel +++ b/packages/schema/tests/schema/cal-com.zmodel @@ -8,7 +8,6 @@ datasource db { generator client { provider = "prisma-client-js" - output = '../.prisma' previewFeatures = [] } diff --git a/packages/sdk/package.json b/packages/sdk/package.json index affe2b201..3d718bd59 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/sdk", - "version": "1.0.0-alpha.79", + "version": "1.0.0-alpha.81", "description": "ZenStack plugin development SDK", "main": "index.js", "scripts": { diff --git a/packages/sdk/src/utils.ts b/packages/sdk/src/utils.ts index 5a29d6425..d27a35da2 100644 --- a/packages/sdk/src/utils.ts +++ b/packages/sdk/src/utils.ts @@ -8,11 +8,20 @@ import { EnumField, Expression, isArrayExpr, + isDataModel, isLiteralExpr, isObjectExpr, + Model, Reference, } from '@zenstackhq/language/ast'; +/** + * Gets data models that are not ignored + */ +export function getDataModels(model: Model) { + return model.declarations.filter((d): d is DataModel => isDataModel(d) && !hasAttribute(d, '@@ignore')); +} + export function resolved(ref: Reference): T { if (!ref.ref) { throw new Error(`Reference not resolved: ${ref.$refText}`); diff --git a/packages/server/package.json b/packages/server/package.json index d0f4ef782..5053e2c9c 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/server", - "version": "1.0.0-alpha.79", + "version": "1.0.0-alpha.81", "displayName": "ZenStack Server-side Adapters", "description": "ZenStack server-side adapters", "homepage": "https://zenstack.dev", diff --git a/packages/testtools/package.json b/packages/testtools/package.json index 89d37be2e..7e2b6e85a 100644 --- a/packages/testtools/package.json +++ b/packages/testtools/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/testtools", - "version": "1.0.0-alpha.79", + "version": "1.0.0-alpha.81", "description": "ZenStack Test Tools", "main": "index.js", "publishConfig": { @@ -19,14 +19,18 @@ "license": "MIT", "dependencies": { "@prisma/client": "^4.7.0", + "@prisma/generator-helper": "^4.7.1", + "@prisma/internals": "^4.7.1", "@zenstackhq/runtime": "workspace:*", - "tmp": "^0.2.1" + "@zenstackhq/language": "workspace:*", + "prisma": "~4.7.0", + "tmp": "^0.2.1", + "zenstack": "workspace:*" }, "devDependencies": { "@types/node": "^18.14.2", "@types/tmp": "^0.2.3", "copyfiles": "^2.4.1", - "prisma": "~4.7.0", "rimraf": "^3.0.2", "typescript": "^4.9.5" } diff --git a/packages/testtools/src/schema.ts b/packages/testtools/src/schema.ts index 985d32937..9aa684d95 100644 --- a/packages/testtools/src/schema.ts +++ b/packages/testtools/src/schema.ts @@ -1,10 +1,15 @@ /* eslint-disable @typescript-eslint/no-var-requires */ /* eslint-disable @typescript-eslint/no-explicit-any */ +import type { DMMF } from '@prisma/generator-helper'; +import { getDMMF } from '@prisma/internals'; +import type { Model } from '@zenstackhq/language/ast'; import { withOmit, withPassword, withPolicy, withPresets, type AuthUser, type DbOperations } from '@zenstackhq/runtime'; import { execSync } from 'child_process'; import * as fs from 'fs'; import * as path from 'path'; import tmp from 'tmp'; +import { loadDocument } from 'zenstack/cli/cli-util'; +import prismaPlugin from 'zenstack/plugins/prisma'; export type WeakDbOperations = { [key in keyof DbOperations]: (...args: any[]) => Promise; @@ -54,7 +59,6 @@ datasource db { generator js { provider = 'prisma-client-js' - output = '../.prisma' previewFeatures = ['clientExtensions'] } @@ -79,8 +83,14 @@ export async function loadSchemaFromFile(schemaFile: string, addPrelude = true, return loadSchema(content, addPrelude, pushDb); } -export async function loadSchema(schema: string, addPrelude = true, pushDb = true) { - const { name: workDir } = tmp.dirSync(); +export async function loadSchema( + schema: string, + addPrelude = true, + pushDb = true, + extraDependencies: string[] = [], + compile = false +) { + const { name: projectRoot } = tmp.dirSync(); const root = getWorkspaceRoot(__dirname); if (!root) { @@ -89,13 +99,15 @@ export async function loadSchema(schema: string, addPrelude = true, pushDb = tru console.log('Workspace root:', root); const pkgContent = fs.readFileSync(path.join(__dirname, 'package.template.json'), { encoding: 'utf-8' }); - fs.writeFileSync(path.join(workDir, 'package.json'), pkgContent.replaceAll('', root)); + fs.writeFileSync(path.join(projectRoot, 'package.json'), pkgContent.replaceAll('', root)); const npmrcContent = fs.readFileSync(path.join(__dirname, '.npmrc.template'), { encoding: 'utf-8' }); - fs.writeFileSync(path.join(workDir, '.npmrc'), npmrcContent.replaceAll('', root)); + fs.writeFileSync(path.join(projectRoot, '.npmrc'), npmrcContent.replaceAll('', root)); - console.log('Workdir:', workDir); - process.chdir(workDir); + console.log('Workdir:', projectRoot); + process.chdir(projectRoot); + + schema = schema.replaceAll('$projectRoot', projectRoot); const content = addPrelude ? `${MODEL_PRELUDE}\n${schema}` : schema; fs.writeFileSync('schema.zmodel', content); @@ -106,14 +118,26 @@ export async function loadSchema(schema: string, addPrelude = true, pushDb = tru run('npx prisma db push'); } - const PrismaClient = require(path.join(workDir, '.prisma')).PrismaClient; + const PrismaClient = require(path.join(projectRoot, 'node_modules/.prisma/client')).PrismaClient; const prisma = new PrismaClient({ log: ['info', 'warn', 'error'] }); - const policy = require(path.join(workDir, '.zenstack/policy')).default; - const modelMeta = require(path.join(workDir, '.zenstack/model-meta')).default; - const zodSchemas = require(path.join(workDir, '.zenstack/zod')).default; + extraDependencies.forEach((dep) => { + console.log(`Installing dependency ${dep}`); + run(`npm install ${dep}`); + }); + + if (compile) { + console.log('Compiling...'); + run('npx tsc --init'); + run('npx tsc --project tsconfig.json'); + } + + const policy = require(path.join(projectRoot, '.zenstack/policy')).default; + const modelMeta = require(path.join(projectRoot, '.zenstack/model-meta')).default; + const zodSchemas = require(path.join(projectRoot, '.zenstack/zod')).default; return { + projectDir: projectRoot, prisma, withPolicy: (user?: AuthUser) => withPolicy(prisma, { user }, policy, modelMeta), withOmit: () => withOmit(prisma, modelMeta), @@ -122,3 +146,32 @@ export async function loadSchema(schema: string, addPrelude = true, pushDb = tru zodSchemas, }; } + +/** + * Load ZModel and Prisma DMM from a string without creating a NPM project. + * @param content + * @returns + */ +export async function loadZModelAndDmmf( + content: string +): Promise<{ model: Model; dmmf: DMMF.Document; modelFile: string }> { + const prelude = ` + datasource db { + provider = 'postgresql' + url = env('DATABASE_URL') + } +`; + + const { name: modelFile } = tmp.fileSync({ postfix: '.zmodel' }); + fs.writeFileSync(modelFile, `${prelude}\n${content}`); + + const model = await loadDocument(modelFile); + + const { name: prismaFile } = tmp.fileSync({ postfix: '.prisma' }); + await prismaPlugin(model, { schemaPath: modelFile, output: prismaFile, generateClient: false }); + + const prismaContent = fs.readFileSync(prismaFile, { encoding: 'utf-8' }); + + const dmmf = await getDMMF({ datamodel: prismaContent }); + return { model, dmmf, modelFile }; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c4c96389c..3e2c38efc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -115,16 +115,21 @@ importers: packages/plugins/react: specifiers: '@prisma/generator-helper': ^4.7.1 + '@types/jest': ^29.5.0 '@types/react': ^18.0.26 + '@types/tmp': ^0.2.3 '@zenstackhq/sdk': workspace:* + '@zenstackhq/testtools': workspace:* change-case: ^4.1.2 copyfiles: ^2.4.1 decimal.js: ^10.4.2 + jest: ^29.5.0 react: ^17.0.2 || ^18 react-dom: ^17.0.2 || ^18 rimraf: ^3.0.2 superjson: ^1.11.0 swr: ^2.0.3 + ts-jest: ^29.0.5 ts-morph: ^16.0.0 typescript: ^4.9.4 dependencies: @@ -138,9 +143,14 @@ importers: swr: 2.0.3_react@18.2.0 ts-morph: 16.0.0 devDependencies: + '@types/jest': 29.5.0 '@types/react': 18.0.26 + '@types/tmp': 0.2.3 + '@zenstackhq/testtools': link:../../testtools/dist copyfiles: 2.4.1 + jest: 29.5.0 rimraf: 3.0.2 + ts-jest: 29.0.5_xv37nfqpz6757dg24cw6wqnoey typescript: 4.9.4 publishDirectory: dist @@ -148,12 +158,16 @@ importers: specifiers: '@prisma/generator-helper': ^4.7.1 '@prisma/internals': ^4.7.1 + '@types/jest': ^29.5.0 '@types/prettier': ^2.7.2 '@zenstackhq/sdk': workspace:* + '@zenstackhq/testtools': workspace:* change-case: ^4.1.2 copyfiles: ^2.4.1 + jest: ^29.5.0 prettier: ^2.8.3 rimraf: ^3.0.2 + ts-jest: ^29.0.5 ts-morph: ^16.0.0 tslib: ^2.4.1 typescript: ^4.9.4 @@ -168,9 +182,13 @@ importers: tslib: 2.4.1 zod: 3.19.1 devDependencies: + '@types/jest': 29.5.0 '@types/prettier': 2.7.2 + '@zenstackhq/testtools': link:../../testtools/dist copyfiles: 2.4.1 + jest: 29.5.0 rimraf: 3.0.2 + ts-jest: 29.0.5_xv37nfqpz6757dg24cw6wqnoey typescript: 4.9.4 publishDirectory: dist @@ -407,23 +425,31 @@ importers: packages/testtools: specifiers: '@prisma/client': ^4.7.0 + '@prisma/generator-helper': ^4.7.1 + '@prisma/internals': ^4.7.1 '@types/node': ^18.14.2 '@types/tmp': ^0.2.3 + '@zenstackhq/language': workspace:* '@zenstackhq/runtime': workspace:* copyfiles: ^2.4.1 prisma: ~4.7.0 rimraf: ^3.0.2 tmp: ^0.2.1 typescript: ^4.9.5 + zenstack: workspace:* dependencies: '@prisma/client': 4.7.1_prisma@4.7.0 + '@prisma/generator-helper': 4.7.1 + '@prisma/internals': 4.7.1 + '@zenstackhq/language': link:../language/dist '@zenstackhq/runtime': link:../runtime/dist + prisma: 4.7.0 tmp: 0.2.1 + zenstack: link:../schema/dist devDependencies: '@types/node': 18.14.2 '@types/tmp': 0.2.3 copyfiles: 2.4.1 - prisma: 4.7.0 rimraf: 3.0.2 typescript: 4.9.5 publishDirectory: dist @@ -1528,6 +1554,18 @@ packages: slash: 3.0.0 dev: true + /@jest/console/29.5.0: + resolution: {integrity: sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.5.0 + '@types/node': 18.14.2 + chalk: 4.1.2 + jest-message-util: 29.5.0 + jest-util: 29.5.0 + slash: 3.0.0 + dev: true + /@jest/core/29.0.3_ts-node@10.9.1: resolution: {integrity: sha512-1d0hLbOrM1qQE3eP3DtakeMbKTcXiXP3afWxqz103xPyddS2NhnNghS7MaXx1dcDt4/6p4nlhmeILo2ofgi8cQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -1654,6 +1692,48 @@ packages: - ts-node dev: true + /@jest/core/29.5.0: + resolution: {integrity: sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/console': 29.5.0 + '@jest/reporters': 29.5.0 + '@jest/test-result': 29.5.0 + '@jest/transform': 29.5.0 + '@jest/types': 29.5.0 + '@types/node': 18.14.2 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.7.1 + exit: 0.1.2 + graceful-fs: 4.2.10 + jest-changed-files: 29.5.0 + jest-config: 29.5.0_@types+node@18.14.2 + jest-haste-map: 29.5.0 + jest-message-util: 29.5.0 + jest-regex-util: 29.4.3 + jest-resolve: 29.5.0 + jest-resolve-dependencies: 29.5.0 + jest-runner: 29.5.0 + jest-runtime: 29.5.0 + jest-snapshot: 29.5.0 + jest-util: 29.5.0 + jest-validate: 29.5.0 + jest-watcher: 29.5.0 + micromatch: 4.0.5 + pretty-format: 29.5.0 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - supports-color + - ts-node + dev: true + /@jest/environment/29.0.3: resolution: {integrity: sha512-iKl272NKxYNQNqXMQandAIwjhQaGw5uJfGXduu8dS9llHi8jV2ChWrtOAVPnMbaaoDhnI3wgUGNDvZgHeEJQCA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -1694,6 +1774,16 @@ packages: jest-mock: 29.4.3 dev: true + /@jest/environment/29.5.0: + resolution: {integrity: sha512-5FXw2+wD29YU1d4I2htpRX7jYnAyTRjP2CsXQdo9SAM8g3ifxWPSV0HnClSn71xwctr0U3oZIIH+dtbfmnbXVQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/fake-timers': 29.5.0 + '@jest/types': 29.5.0 + '@types/node': 18.14.2 + jest-mock: 29.5.0 + dev: true + /@jest/expect-utils/29.0.3: resolution: {integrity: sha512-i1xUkau7K/63MpdwiRqaxgZOjxYs4f0WMTGJnYwUKubsNRZSeQbLorS7+I4uXVF9KQ5r61BUPAUMZ7Lf66l64Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -1722,6 +1812,13 @@ packages: jest-get-type: 29.4.3 dev: true + /@jest/expect-utils/29.5.0: + resolution: {integrity: sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + jest-get-type: 29.4.3 + dev: true + /@jest/expect/29.0.3: resolution: {integrity: sha512-6W7K+fsI23FQ01H/BWccPyDZFrnU9QlzDcKOjrNVU5L8yUORFAJJIpmyxWPW70+X624KUNqzZwPThPMX28aXEQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -1762,6 +1859,16 @@ packages: - supports-color dev: true + /@jest/expect/29.5.0: + resolution: {integrity: sha512-PueDR2HGihN3ciUNGr4uelropW7rqUfTiOn+8u0leg/42UhblPxHkfoh0Ruu3I9Y1962P3u2DY4+h7GVTSVU6g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + expect: 29.5.0 + jest-snapshot: 29.5.0 + transitivePeerDependencies: + - supports-color + dev: true + /@jest/fake-timers/29.0.3: resolution: {integrity: sha512-tmbUIo03x0TdtcZCESQ0oQSakPCpo7+s6+9mU19dd71MptkP4zCwoeZqna23//pgbhtT1Wq02VmA9Z9cNtvtCQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -1810,6 +1917,18 @@ packages: jest-util: 29.4.3 dev: true + /@jest/fake-timers/29.5.0: + resolution: {integrity: sha512-9ARvuAAQcBwDAqOnglWq2zwNIRUDtk/SCkp/ToGEhFv5r86K21l+VEs0qNTaXtyiY0lEePl3kylijSYJQqdbDg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.5.0 + '@sinonjs/fake-timers': 10.0.2 + '@types/node': 18.14.2 + jest-message-util: 29.5.0 + jest-mock: 29.5.0 + jest-util: 29.5.0 + dev: true + /@jest/globals/29.2.1: resolution: {integrity: sha512-Z4EejYPP1OPVq2abk1+9urAwJqkgw5jB2UJGlPjb5ZwzPQF8WLMcigKEfFzZb2OHhEVPP0RZD0/DbVTY1R6iQA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -1846,6 +1965,18 @@ packages: - supports-color dev: true + /@jest/globals/29.5.0: + resolution: {integrity: sha512-S02y0qMWGihdzNbUiqSAiKSpSozSuHX5UYc7QbnHP+D9Lyw8DgGGCinrN9uSuHPeKgSSzvPom2q1nAtBvUsvPQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.5.0 + '@jest/expect': 29.5.0 + '@jest/types': 29.5.0 + jest-mock: 29.5.0 + transitivePeerDependencies: + - supports-color + dev: true + /@jest/reporters/29.0.3: resolution: {integrity: sha512-3+QU3d4aiyOWfmk1obDerie4XNCaD5Xo1IlKNde2yGEi02WQD+ZQD0i5Hgqm1e73sMV7kw6pMlCnprtEwEVwxw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -1958,6 +2089,43 @@ packages: - supports-color dev: true + /@jest/reporters/29.5.0: + resolution: {integrity: sha512-D05STXqj/M8bP9hQNSICtPqz97u7ffGzZu+9XLucXhkOFBqKcXe04JLZOgIekOxdb73MAoBUFnqvf7MCpKk5OA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 29.5.0 + '@jest/test-result': 29.5.0 + '@jest/transform': 29.5.0 + '@jest/types': 29.5.0 + '@jridgewell/trace-mapping': 0.3.17 + '@types/node': 18.14.2 + chalk: 4.1.2 + collect-v8-coverage: 1.0.1 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.10 + istanbul-lib-coverage: 3.2.0 + istanbul-lib-instrument: 5.2.1 + istanbul-lib-report: 3.0.0 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.5 + jest-message-util: 29.5.0 + jest-util: 29.5.0 + jest-worker: 29.5.0 + slash: 3.0.0 + string-length: 4.0.2 + strip-ansi: 6.0.1 + v8-to-istanbul: 9.0.1 + transitivePeerDependencies: + - supports-color + dev: true + /@jest/schemas/29.0.0: resolution: {integrity: sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -2029,6 +2197,16 @@ packages: collect-v8-coverage: 1.0.1 dev: true + /@jest/test-result/29.5.0: + resolution: {integrity: sha512-fGl4rfitnbfLsrfx1uUpDEESS7zM8JdgZgOCQuxQvL1Sn/I6ijeAVQWGfXI9zb1i9Mzo495cIpVZhA0yr60PkQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/console': 29.5.0 + '@jest/types': 29.5.0 + '@types/istanbul-lib-coverage': 2.0.4 + collect-v8-coverage: 1.0.1 + dev: true + /@jest/test-sequencer/29.0.3: resolution: {integrity: sha512-Hf4+xYSWZdxTNnhDykr8JBs0yBN/nxOXyUQWfotBUqqy0LF9vzcFB0jm/EDNZCx587znLWTIgxcokW7WeZMobQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -2059,6 +2237,16 @@ packages: slash: 3.0.0 dev: true + /@jest/test-sequencer/29.5.0: + resolution: {integrity: sha512-yPafQEcKjkSfDXyvtgiV4pevSeyuA6MQr6ZIdVkWJly9vkqjnFfcfhRQqpD5whjoU8EORki752xQmjaqoFjzMQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/test-result': 29.5.0 + graceful-fs: 4.2.10 + jest-haste-map: 29.5.0 + slash: 3.0.0 + dev: true + /@jest/transform/29.0.3: resolution: {integrity: sha512-C5ihFTRYaGDbi/xbRQRdbo5ddGtI4VSpmL6AIcZxdhwLbXMa7PcXxxqyI91vGOFHnn5aVM3WYnYKCHEqmLVGzg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -2151,6 +2339,29 @@ packages: - supports-color dev: true + /@jest/transform/29.5.0: + resolution: {integrity: sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/core': 7.20.5 + '@jest/types': 29.5.0 + '@jridgewell/trace-mapping': 0.3.17 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.10 + jest-haste-map: 29.5.0 + jest-regex-util: 29.4.3 + jest-util: 29.5.0 + micromatch: 4.0.5 + pirates: 4.0.5 + slash: 3.0.0 + write-file-atomic: 4.0.2 + transitivePeerDependencies: + - supports-color + dev: true + /@jest/types/29.0.3: resolution: {integrity: sha512-coBJmOQvurXjN1Hh5PzF7cmsod0zLIOXpP8KD161mqNlroMhLcwpODiEzi7ZsRl5Z/AIuxpeNm8DCl43F4kz8A==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -2199,6 +2410,18 @@ packages: chalk: 4.1.2 dev: true + /@jest/types/29.5.0: + resolution: {integrity: sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/schemas': 29.4.3 + '@types/istanbul-lib-coverage': 2.0.4 + '@types/istanbul-reports': 3.0.1 + '@types/node': 18.14.2 + '@types/yargs': 17.0.13 + chalk: 4.1.2 + dev: true + /@jridgewell/gen-mapping/0.1.1: resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==} engines: {node: '>=6.0.0'} @@ -2845,6 +3068,13 @@ packages: pretty-format: 29.4.3 dev: true + /@types/jest/29.5.0: + resolution: {integrity: sha512-3Emr5VOl/aoBwnWcH/EFQvlSAmjV+XtV9GGu5mwdYew5vhQh0IUZx/60x0TzHDu09Bi7HMx10t/namdJw5QIcg==} + dependencies: + expect: 29.5.0 + pretty-format: 29.5.0 + dev: true + /@types/json-schema/7.0.11: resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} dev: true @@ -3611,6 +3841,24 @@ packages: - supports-color dev: true + /babel-jest/29.5.0_@babel+core@7.20.5: + resolution: {integrity: sha512-mA4eCDh5mSo2EcA9xQjVTpmbbNk32Zb3Q3QFQsNhaK56Q+yoXowzFodLux30HRgyOho5rsQ6B0P9QpMkvvnJ0Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.8.0 + dependencies: + '@babel/core': 7.20.5 + '@jest/transform': 29.5.0 + '@types/babel__core': 7.1.19 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 29.5.0_@babel+core@7.20.5 + chalk: 4.1.2 + graceful-fs: 4.2.10 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: true + /babel-plugin-istanbul/6.1.1: resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} engines: {node: '>=8'} @@ -3654,6 +3902,16 @@ packages: '@types/babel__traverse': 7.18.2 dev: true + /babel-plugin-jest-hoist/29.5.0: + resolution: {integrity: sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/template': 7.18.10 + '@babel/types': 7.20.5 + '@types/babel__core': 7.1.19 + '@types/babel__traverse': 7.18.2 + dev: true + /babel-preset-current-node-syntax/1.0.1_@babel+core@7.19.3: resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} peerDependencies: @@ -3727,6 +3985,17 @@ packages: babel-preset-current-node-syntax: 1.0.1_@babel+core@7.20.5 dev: true + /babel-preset-jest/29.5.0_@babel+core@7.20.5: + resolution: {integrity: sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.20.5 + babel-plugin-jest-hoist: 29.5.0 + babel-preset-current-node-syntax: 1.0.1_@babel+core@7.20.5 + dev: true + /balanced-match/1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -5334,6 +5603,17 @@ packages: jest-util: 29.4.3 dev: true + /expect/29.5.0: + resolution: {integrity: sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/expect-utils': 29.5.0 + jest-get-type: 29.4.3 + jest-matcher-utils: 29.5.0 + jest-message-util: 29.5.0 + jest-util: 29.5.0 + dev: true + /express/4.18.2: resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} engines: {node: '>= 0.10.0'} @@ -6319,6 +6599,14 @@ packages: p-limit: 3.1.0 dev: true + /jest-changed-files/29.5.0: + resolution: {integrity: sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + execa: 5.1.1 + p-limit: 3.1.0 + dev: true + /jest-circus/29.0.3: resolution: {integrity: sha512-QeGzagC6Hw5pP+df1+aoF8+FBSgkPmraC1UdkeunWh0jmrp7wC0Hr6umdUAOELBQmxtKAOMNC3KAdjmCds92Zg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -6400,6 +6688,34 @@ packages: - supports-color dev: true + /jest-circus/29.5.0: + resolution: {integrity: sha512-gq/ongqeQKAplVxqJmbeUOJJKkW3dDNPY8PjhJ5G0lBRvu0e3EWGxGy5cI4LAGA7gV2UHCtWBI4EMXK8c9nQKA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.5.0 + '@jest/expect': 29.5.0 + '@jest/test-result': 29.5.0 + '@jest/types': 29.5.0 + '@types/node': 18.14.2 + chalk: 4.1.2 + co: 4.6.0 + dedent: 0.7.0 + is-generator-fn: 2.1.0 + jest-each: 29.5.0 + jest-matcher-utils: 29.5.0 + jest-message-util: 29.5.0 + jest-runtime: 29.5.0 + jest-snapshot: 29.5.0 + jest-util: 29.5.0 + p-limit: 3.1.0 + pretty-format: 29.5.0 + pure-rand: 6.0.1 + slash: 3.0.0 + stack-utils: 2.0.5 + transitivePeerDependencies: + - supports-color + dev: true + /jest-cli/29.0.3_johvxhudwcpndp4mle25vwrlq4: resolution: {integrity: sha512-aUy9Gd/Kut1z80eBzG10jAn6BgS3BoBbXyv+uXEqBJ8wnnuZ5RpNfARoskSrTIy1GY4a8f32YGuCMwibtkl9CQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -6484,6 +6800,34 @@ packages: - ts-node dev: true + /jest-cli/29.5.0: + resolution: {integrity: sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/core': 29.5.0 + '@jest/test-result': 29.5.0 + '@jest/types': 29.5.0 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.10 + import-local: 3.1.0 + jest-config: 29.5.0 + jest-util: 29.5.0 + jest-validate: 29.5.0 + prompts: 2.4.2 + yargs: 17.6.2 + transitivePeerDependencies: + - '@types/node' + - supports-color + - ts-node + dev: true + /jest-config/29.0.3_jboh4c3iv3wxuja4m36ecyac7e: resolution: {integrity: sha512-U5qkc82HHVYe3fNu2CRXLN4g761Na26rWKf7CjM8LlZB3In1jadEkZdMwsE37rd9RSPV0NfYaCjHdk/gu3v+Ew==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -6721,6 +7065,83 @@ packages: - supports-color dev: true + /jest-config/29.5.0: + resolution: {integrity: sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + dependencies: + '@babel/core': 7.20.5 + '@jest/test-sequencer': 29.5.0 + '@jest/types': 29.5.0 + babel-jest: 29.5.0_@babel+core@7.20.5 + chalk: 4.1.2 + ci-info: 3.7.1 + deepmerge: 4.2.2 + glob: 7.2.3 + graceful-fs: 4.2.10 + jest-circus: 29.5.0 + jest-environment-node: 29.5.0 + jest-get-type: 29.4.3 + jest-regex-util: 29.4.3 + jest-resolve: 29.5.0 + jest-runner: 29.5.0 + jest-util: 29.5.0 + jest-validate: 29.5.0 + micromatch: 4.0.5 + parse-json: 5.2.0 + pretty-format: 29.5.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-config/29.5.0_@types+node@18.14.2: + resolution: {integrity: sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + dependencies: + '@babel/core': 7.20.5 + '@jest/test-sequencer': 29.5.0 + '@jest/types': 29.5.0 + '@types/node': 18.14.2 + babel-jest: 29.5.0_@babel+core@7.20.5 + chalk: 4.1.2 + ci-info: 3.7.1 + deepmerge: 4.2.2 + glob: 7.2.3 + graceful-fs: 4.2.10 + jest-circus: 29.5.0 + jest-environment-node: 29.5.0 + jest-get-type: 29.4.3 + jest-regex-util: 29.4.3 + jest-resolve: 29.5.0 + jest-runner: 29.5.0 + jest-util: 29.5.0 + jest-validate: 29.5.0 + micromatch: 4.0.5 + parse-json: 5.2.0 + pretty-format: 29.5.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + /jest-diff/29.0.3: resolution: {integrity: sha512-+X/AIF5G/vX9fWK+Db9bi9BQas7M9oBME7egU7psbn4jlszLFCu0dW63UgeE6cs/GANq4fLaT+8sGHQQ0eCUfg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -6761,6 +7182,16 @@ packages: pretty-format: 29.4.3 dev: true + /jest-diff/29.5.0: + resolution: {integrity: sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + chalk: 4.1.2 + diff-sequences: 29.4.3 + jest-get-type: 29.4.3 + pretty-format: 29.5.0 + dev: true + /jest-docblock/29.0.0: resolution: {integrity: sha512-s5Kpra/kLzbqu9dEjov30kj1n4tfu3e7Pl8v+f8jOkeWNqM6Ds8jRaJfZow3ducoQUrf2Z4rs2N5S3zXnb83gw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -6815,6 +7246,17 @@ packages: pretty-format: 29.4.3 dev: true + /jest-each/29.5.0: + resolution: {integrity: sha512-HM5kIJ1BTnVt+DQZ2ALp3rzXEl+g726csObrW/jpEGl+CDSSQpOJJX2KE/vEg8cxcMXdyEPu6U4QX5eruQv5hA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.5.0 + chalk: 4.1.2 + jest-get-type: 29.4.3 + jest-util: 29.5.0 + pretty-format: 29.5.0 + dev: true + /jest-environment-node/29.0.3: resolution: {integrity: sha512-cdZqRCnmIlTXC+9vtvmfiY/40Cj6s2T0czXuq1whvQdmpzAnj4sbqVYuZ4zFHk766xTTJ+Ij3uUqkk8KCfXoyg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -6851,6 +7293,18 @@ packages: jest-util: 29.4.3 dev: true + /jest-environment-node/29.5.0: + resolution: {integrity: sha512-ExxuIK/+yQ+6PRGaHkKewYtg6hto2uGCgvKdb2nfJfKXgZ17DfXjvbZ+jA1Qt9A8EQSfPnt5FKIfnOO3u1h9qw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.5.0 + '@jest/fake-timers': 29.5.0 + '@jest/types': 29.5.0 + '@types/node': 18.14.2 + jest-mock: 29.5.0 + jest-util: 29.5.0 + dev: true + /jest-fetch-mock/3.0.3: resolution: {integrity: sha512-Ux1nWprtLrdrH4XwE7O7InRY6psIi3GOsqNESJgMJ+M5cv4A8Lh7SN9d2V2kKRZ8ebAfcd1LNyZguAOb6JiDqw==} dependencies: @@ -6951,6 +7405,25 @@ packages: fsevents: 2.3.2 dev: true + /jest-haste-map/29.5.0: + resolution: {integrity: sha512-IspOPnnBro8YfVYSw6yDRKh/TiCdRngjxeacCps1cQ9cgVN6+10JUcuJ1EabrgYLOATsIAigxA0rLR9x/YlrSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.5.0 + '@types/graceful-fs': 4.1.5 + '@types/node': 18.14.2 + anymatch: 3.1.2 + fb-watchman: 2.0.2 + graceful-fs: 4.2.10 + jest-regex-util: 29.4.3 + jest-util: 29.5.0 + jest-worker: 29.5.0 + micromatch: 4.0.5 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.2 + dev: true + /jest-leak-detector/29.0.3: resolution: {integrity: sha512-YfW/G63dAuiuQ3QmQlh8hnqLDe25WFY3eQhuc/Ev1AGmkw5zREblTh7TCSKLoheyggu6G9gxO2hY8p9o6xbaRQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -6975,6 +7448,14 @@ packages: pretty-format: 29.4.3 dev: true + /jest-leak-detector/29.5.0: + resolution: {integrity: sha512-u9YdeeVnghBUtpN5mVxjID7KbkKE1QU4f6uUwuxiY0vYRi9BUCLKlPEZfDGR67ofdFmDz9oPAy2G92Ujrntmow==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + jest-get-type: 29.4.3 + pretty-format: 29.5.0 + dev: true + /jest-matcher-utils/29.0.3: resolution: {integrity: sha512-RsR1+cZ6p1hDV4GSCQTg+9qjeotQCgkaleIKLK7dm+U4V/H2bWedU3RAtLm8+mANzZ7eDV33dMar4pejd7047w==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -7015,6 +7496,16 @@ packages: pretty-format: 29.4.3 dev: true + /jest-matcher-utils/29.5.0: + resolution: {integrity: sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + chalk: 4.1.2 + jest-diff: 29.5.0 + jest-get-type: 29.4.3 + pretty-format: 29.5.0 + dev: true + /jest-message-util/29.0.3: resolution: {integrity: sha512-7T8JiUTtDfppojosORAflABfLsLKMLkBHSWkjNQrjIltGoDzNGn7wEPOSfjqYAGTYME65esQzMJxGDjuLBKdOg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -7065,7 +7556,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@babel/code-frame': 7.18.6 - '@jest/types': 29.4.3 + '@jest/types': 29.5.0 '@types/stack-utils': 2.0.1 chalk: 4.1.2 graceful-fs: 4.2.10 @@ -7075,6 +7566,21 @@ packages: stack-utils: 2.0.5 dev: true + /jest-message-util/29.5.0: + resolution: {integrity: sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/code-frame': 7.18.6 + '@jest/types': 29.5.0 + '@types/stack-utils': 2.0.1 + chalk: 4.1.2 + graceful-fs: 4.2.10 + micromatch: 4.0.5 + pretty-format: 29.5.0 + slash: 3.0.0 + stack-utils: 2.0.5 + dev: true + /jest-mock/29.0.3: resolution: {integrity: sha512-ort9pYowltbcrCVR43wdlqfAiFJXBx8l4uJDsD8U72LgBcetvEp+Qxj1W9ZYgMRoeAo+ov5cnAGF2B6+Oth+ww==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -7110,6 +7616,15 @@ packages: jest-util: 29.4.3 dev: true + /jest-mock/29.5.0: + resolution: {integrity: sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.5.0 + '@types/node': 18.14.2 + jest-util: 29.5.0 + dev: true + /jest-pnp-resolver/1.2.2_jest-resolve@29.0.3: resolution: {integrity: sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==} engines: {node: '>=6'} @@ -7146,6 +7661,18 @@ packages: jest-resolve: 29.4.3 dev: true + /jest-pnp-resolver/1.2.2_jest-resolve@29.5.0: + resolution: {integrity: sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + dependencies: + jest-resolve: 29.5.0 + dev: true + /jest-regex-util/29.0.0: resolution: {integrity: sha512-BV7VW7Sy0fInHWN93MMPtlClweYv2qrSCwfeFWmpribGZtQPWNvRSq9XOVgOEjU1iBGRKXUZil0o2AH7Iy9Lug==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -7191,6 +7718,16 @@ packages: - supports-color dev: true + /jest-resolve-dependencies/29.5.0: + resolution: {integrity: sha512-sjV3GFr0hDJMBpYeUuGduP+YeCRbd7S/ck6IvL3kQ9cpySYKqcqhdLLC2rFwrcL7tz5vYibomBrsFYWkIGGjOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + jest-regex-util: 29.4.3 + jest-snapshot: 29.5.0 + transitivePeerDependencies: + - supports-color + dev: true + /jest-resolve/29.0.3: resolution: {integrity: sha512-toVkia85Y/BPAjJasTC9zIPY6MmVXQPtrCk8SmiheC4MwVFE/CMFlOtMN6jrwPMC6TtNh8+sTMllasFeu1wMPg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -7236,6 +7773,21 @@ packages: slash: 3.0.0 dev: true + /jest-resolve/29.5.0: + resolution: {integrity: sha512-1TzxJ37FQq7J10jPtQjcc+MkCkE3GBpBecsSUWJ0qZNJpmg6m0D9/7II03yJulm3H/fvVjgqLh/k2eYg+ui52w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + chalk: 4.1.2 + graceful-fs: 4.2.10 + jest-haste-map: 29.5.0 + jest-pnp-resolver: 1.2.2_jest-resolve@29.5.0 + jest-util: 29.5.0 + jest-validate: 29.5.0 + resolve: 1.22.1 + resolve.exports: 2.0.0 + slash: 3.0.0 + dev: true + /jest-runner/29.0.3: resolution: {integrity: sha512-Usu6VlTOZlCZoNuh3b2Tv/yzDpKqtiNAetG9t3kJuHfUyVMNW7ipCCJOUojzKkjPoaN7Bl1f7Buu6PE0sGpQxw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -7323,6 +7875,35 @@ packages: - supports-color dev: true + /jest-runner/29.5.0: + resolution: {integrity: sha512-m7b6ypERhFghJsslMLhydaXBiLf7+jXy8FwGRHO3BGV1mcQpPbwiqiKUR2zU2NJuNeMenJmlFZCsIqzJCTeGLQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/console': 29.5.0 + '@jest/environment': 29.5.0 + '@jest/test-result': 29.5.0 + '@jest/transform': 29.5.0 + '@jest/types': 29.5.0 + '@types/node': 18.14.2 + chalk: 4.1.2 + emittery: 0.13.1 + graceful-fs: 4.2.10 + jest-docblock: 29.4.3 + jest-environment-node: 29.5.0 + jest-haste-map: 29.5.0 + jest-leak-detector: 29.5.0 + jest-message-util: 29.5.0 + jest-resolve: 29.5.0 + jest-runtime: 29.5.0 + jest-util: 29.5.0 + jest-watcher: 29.5.0 + jest-worker: 29.5.0 + p-limit: 3.1.0 + source-map-support: 0.5.13 + transitivePeerDependencies: + - supports-color + dev: true + /jest-runtime/29.0.3: resolution: {integrity: sha512-12gZXRQ7ozEeEHKTY45a+YLqzNDR/x4c//X6AqwKwKJPpWM8FY4vwn4VQJOcLRS3Nd1fWwgP7LU4SoynhuUMHQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -7413,6 +7994,36 @@ packages: - supports-color dev: true + /jest-runtime/29.5.0: + resolution: {integrity: sha512-1Hr6Hh7bAgXQP+pln3homOiEZtCDZFqwmle7Ew2j8OlbkIu6uE3Y/etJQG8MLQs3Zy90xrp2C0BRrtPHG4zryw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.5.0 + '@jest/fake-timers': 29.5.0 + '@jest/globals': 29.5.0 + '@jest/source-map': 29.4.3 + '@jest/test-result': 29.5.0 + '@jest/transform': 29.5.0 + '@jest/types': 29.5.0 + '@types/node': 18.14.2 + chalk: 4.1.2 + cjs-module-lexer: 1.2.2 + collect-v8-coverage: 1.0.1 + glob: 7.2.3 + graceful-fs: 4.2.10 + jest-haste-map: 29.5.0 + jest-message-util: 29.5.0 + jest-mock: 29.5.0 + jest-regex-util: 29.4.3 + jest-resolve: 29.5.0 + jest-snapshot: 29.5.0 + jest-util: 29.5.0 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color + dev: true + /jest-snapshot/29.0.3: resolution: {integrity: sha512-52q6JChm04U3deq+mkQ7R/7uy7YyfVIrebMi6ZkBoDJ85yEjm/sJwdr1P0LOIEHmpyLlXrxy3QP0Zf5J2kj0ew==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -7541,6 +8152,37 @@ packages: - supports-color dev: true + /jest-snapshot/29.5.0: + resolution: {integrity: sha512-x7Wolra5V0tt3wRs3/ts3S6ciSQVypgGQlJpz2rsdQYoUKxMxPNaoHMGJN6qAuPJqS+2iQ1ZUn5kl7HCyls84g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/core': 7.20.5 + '@babel/generator': 7.20.5 + '@babel/plugin-syntax-jsx': 7.18.6_@babel+core@7.20.5 + '@babel/plugin-syntax-typescript': 7.20.0_@babel+core@7.20.5 + '@babel/traverse': 7.20.5 + '@babel/types': 7.20.5 + '@jest/expect-utils': 29.5.0 + '@jest/transform': 29.5.0 + '@jest/types': 29.5.0 + '@types/babel__traverse': 7.18.2 + '@types/prettier': 2.7.2 + babel-preset-current-node-syntax: 1.0.1_@babel+core@7.20.5 + chalk: 4.1.2 + expect: 29.5.0 + graceful-fs: 4.2.10 + jest-diff: 29.5.0 + jest-get-type: 29.4.3 + jest-matcher-utils: 29.5.0 + jest-message-util: 29.5.0 + jest-util: 29.5.0 + natural-compare: 1.4.0 + pretty-format: 29.5.0 + semver: 7.3.8 + transitivePeerDependencies: + - supports-color + dev: true + /jest-util/29.0.3: resolution: {integrity: sha512-Q0xaG3YRG8QiTC4R6fHjHQPaPpz9pJBEi0AeOE4mQh/FuWOijFjGXMMOfQEaU9i3z76cNR7FobZZUQnL6IyfdQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -7581,7 +8223,19 @@ packages: resolution: {integrity: sha512-ToSGORAz4SSSoqxDSylWX8JzkOQR7zoBtNRsA7e+1WUX5F8jrOwaNpuh1YfJHJKDHXLHmObv5eOjejUd+/Ws+Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/types': 29.4.3 + '@jest/types': 29.5.0 + '@types/node': 18.14.2 + chalk: 4.1.2 + ci-info: 3.7.1 + graceful-fs: 4.2.10 + picomatch: 2.3.1 + dev: true + + /jest-util/29.5.0: + resolution: {integrity: sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.5.0 '@types/node': 18.14.2 chalk: 4.1.2 ci-info: 3.7.1 @@ -7625,6 +8279,18 @@ packages: pretty-format: 29.4.3 dev: true + /jest-validate/29.5.0: + resolution: {integrity: sha512-pC26etNIi+y3HV8A+tUGr/lph9B18GnzSRAkPaaZJIE1eFdiYm6/CewuiJQ8/RlfHd1u/8Ioi8/sJ+CmbA+zAQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.5.0 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 29.4.3 + leven: 3.1.0 + pretty-format: 29.5.0 + dev: true + /jest-watcher/29.0.3: resolution: {integrity: sha512-tQX9lU91A+9tyUQKUMp0Ns8xAcdhC9fo73eqA3LFxP2bSgiF49TNcc+vf3qgGYYK9qRjFpXW9+4RgF/mbxyOOw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -7667,6 +8333,20 @@ packages: string-length: 4.0.2 dev: true + /jest-watcher/29.5.0: + resolution: {integrity: sha512-KmTojKcapuqYrKDpRwfqcQ3zjMlwu27SYext9pt4GlF5FUgB+7XE1mcCnSm6a4uUpFyQIkb6ZhzZvHl+jiBCiA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/test-result': 29.5.0 + '@jest/types': 29.5.0 + '@types/node': 18.14.2 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.13.1 + jest-util: 29.5.0 + string-length: 4.0.2 + dev: true + /jest-worker/29.0.3: resolution: {integrity: sha512-Tl/YWUugQOjoTYwjKdfJWkSOfhufJHO5LhXTSZC3TRoQKO+fuXnZAdoXXBlpLXKGODBL3OvdUasfDD4PcMe6ng==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -7706,6 +8386,16 @@ packages: supports-color: 8.1.1 dev: true + /jest-worker/29.5.0: + resolution: {integrity: sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@types/node': 18.14.2 + jest-util: 29.5.0 + merge-stream: 2.0.0 + supports-color: 8.1.1 + dev: true + /jest/29.0.3_johvxhudwcpndp4mle25vwrlq4: resolution: {integrity: sha512-ElgUtJBLgXM1E8L6K1RW1T96R897YY/3lRYqq9uVcPWtP2AAl/nQ16IYDh/FzQOOQ12VEuLdcPU83mbhG2C3PQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -7766,6 +8456,26 @@ packages: - ts-node dev: true + /jest/29.5.0: + resolution: {integrity: sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/core': 29.5.0 + '@jest/types': 29.5.0 + import-local: 3.1.0 + jest-cli: 29.5.0 + transitivePeerDependencies: + - '@types/node' + - supports-color + - ts-node + dev: true + /js-sdsl/4.1.5: resolution: {integrity: sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==} dev: true @@ -8729,6 +9439,15 @@ packages: react-is: 18.2.0 dev: true + /pretty-format/29.5.0: + resolution: {integrity: sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/schemas': 29.4.3 + ansi-styles: 5.2.0 + react-is: 18.2.0 + dev: true + /printj/1.3.1: resolution: {integrity: sha512-GA3TdL8szPK4AQ2YnOe/b+Y1jUFwmmGMMK/qbY7VcE3Z7FU8JstbKiKRzO6CIiAKPhTO8m01NoQ0V5f3jc4OGg==} engines: {node: '>=0.8'} @@ -8800,6 +9519,10 @@ packages: engines: {node: '>=6'} dev: true + /pure-rand/6.0.1: + resolution: {integrity: sha512-t+x1zEHDjBwkDGY5v5ApnZ/utcd4XYDiJsaQQoptTXgUXX95sDg1elCdJghzicm7n2mbCBJ3uYWr6M22SO19rg==} + dev: true + /qs/6.11.0: resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} engines: {node: '>=0.6'} @@ -9863,6 +10586,40 @@ packages: yargs-parser: 21.1.1 dev: true + /ts-jest/29.0.5_xv37nfqpz6757dg24cw6wqnoey: + resolution: {integrity: sha512-PL3UciSgIpQ7f6XjVOmbi96vmDHUqAyqDr8YxzopDqX3kfgYtX1cuNeBjP+L9sFXi6nzsGGA6R3fP3DDDJyrxA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + '@babel/core': '>=7.0.0-beta.0 <8' + '@jest/types': ^29.0.0 + babel-jest: ^29.0.0 + esbuild: '*' + jest: ^29.0.0 + typescript: '>=4.3' + peerDependenciesMeta: + '@babel/core': + optional: true + '@jest/types': + optional: true + babel-jest: + optional: true + esbuild: + optional: true + dependencies: + '@babel/core': 7.20.5 + bs-logger: 0.2.6 + fast-json-stable-stringify: 2.1.0 + jest: 29.5.0 + jest-util: 29.4.3 + json5: 2.2.3 + lodash.memoize: 4.1.2 + make-error: 1.3.6 + semver: 7.3.8 + typescript: 4.9.4 + yargs-parser: 21.1.1 + dev: true + /ts-morph/16.0.0: resolution: {integrity: sha512-jGNF0GVpFj0orFw55LTsQxVYEUOCWBAbR5Ls7fTYE5pQsbW18ssTb/6UXx/GYAEjS+DQTp8VoTw0vqYMiaaQuw==} dependencies: diff --git a/tests/integration/test-run/package-lock.json b/tests/integration/test-run/package-lock.json index dcc7660ec..65febe9d1 100644 --- a/tests/integration/test-run/package-lock.json +++ b/tests/integration/test-run/package-lock.json @@ -126,7 +126,7 @@ }, "../../../packages/runtime/dist": { "name": "@zenstackhq/runtime", - "version": "1.0.0-alpha.77", + "version": "1.0.0-alpha.81", "license": "MIT", "dependencies": { "@types/bcryptjs": "^2.4.2", @@ -158,7 +158,7 @@ }, "../../../packages/schema/dist": { "name": "zenstack", - "version": "1.0.0-alpha.77", + "version": "1.0.0-alpha.81", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/tests/integration/tests/schema/cal-com.zmodel b/tests/integration/tests/schema/cal-com.zmodel index 8984bc758..583fd14ab 100644 --- a/tests/integration/tests/schema/cal-com.zmodel +++ b/tests/integration/tests/schema/cal-com.zmodel @@ -8,7 +8,6 @@ datasource db { generator client { provider = "prisma-client-js" - output = '../.prisma' previewFeatures = [] } diff --git a/tests/integration/tests/schema/todo.zmodel b/tests/integration/tests/schema/todo.zmodel index 19697086c..eac571be3 100644 --- a/tests/integration/tests/schema/todo.zmodel +++ b/tests/integration/tests/schema/todo.zmodel @@ -9,7 +9,6 @@ datasource db { generator js { provider = 'prisma-client-js' - output = '../.prisma' previewFeatures = ['clientExtensions'] }