@zenstackhq/testtools 3.0.0-beta.21 → 3.0.0-beta.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +27 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +35 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.js +27 -4
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
package/dist/index.cjs
CHANGED
|
@@ -50,6 +50,7 @@ var import_orm = require("@zenstackhq/orm");
|
|
|
50
50
|
var import_plugin_policy = require("@zenstackhq/plugin-policy");
|
|
51
51
|
var import_sdk2 = require("@zenstackhq/sdk");
|
|
52
52
|
var import_better_sqlite3 = __toESM(require("better-sqlite3"), 1);
|
|
53
|
+
var import_glob = require("glob");
|
|
53
54
|
var import_kysely = require("kysely");
|
|
54
55
|
var import_node_child_process2 = require("child_process");
|
|
55
56
|
var import_node_crypto2 = require("crypto");
|
|
@@ -315,14 +316,20 @@ async function createTestClient(schema, options) {
|
|
|
315
316
|
schemaContent = schemaContent.replace(/datasource\s+db\s*{[^}]*}/m, `datasource db {
|
|
316
317
|
provider = '${provider}'
|
|
317
318
|
url = '${dbUrl}'
|
|
319
|
+
${options.dataSourceExtensions ? `extensions = [${options.dataSourceExtensions.join(", ")}]` : ""}
|
|
318
320
|
}`);
|
|
319
321
|
}
|
|
320
322
|
import_node_fs3.default.writeFileSync(import_node_path3.default.join(workDir, "schema.zmodel"), schemaContent);
|
|
321
323
|
}
|
|
322
324
|
}
|
|
323
325
|
(0, import_common_helpers2.invariant)(workDir);
|
|
326
|
+
const { plugins, ...rest } = options ?? {};
|
|
327
|
+
const _options = {
|
|
328
|
+
...rest
|
|
329
|
+
};
|
|
324
330
|
if (options?.debug) {
|
|
325
331
|
console.log(`Work directory: ${workDir}`);
|
|
332
|
+
_options.log = testLogger;
|
|
326
333
|
}
|
|
327
334
|
if (options?.dbFile) {
|
|
328
335
|
if (provider !== "sqlite") {
|
|
@@ -330,10 +337,26 @@ async function createTestClient(schema, options) {
|
|
|
330
337
|
}
|
|
331
338
|
import_node_fs3.default.copyFileSync(options.dbFile, import_node_path3.default.join(workDir, dbName));
|
|
332
339
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
340
|
+
if (options?.copyFiles) {
|
|
341
|
+
const state = import_vitest2.expect.getState();
|
|
342
|
+
const currentTestPath = state.testPath;
|
|
343
|
+
if (!currentTestPath) {
|
|
344
|
+
throw new Error("Unable to determine current test file path");
|
|
345
|
+
}
|
|
346
|
+
for (const { globPattern, destination } of options.copyFiles) {
|
|
347
|
+
const files = import_glob.glob.sync(globPattern, {
|
|
348
|
+
cwd: import_node_path3.default.dirname(currentTestPath)
|
|
349
|
+
});
|
|
350
|
+
for (const file of files) {
|
|
351
|
+
const src = import_node_path3.default.resolve(import_node_path3.default.dirname(currentTestPath), file);
|
|
352
|
+
const dest = import_node_path3.default.resolve(workDir, destination, import_node_path3.default.basename(file));
|
|
353
|
+
import_node_fs3.default.mkdirSync(import_node_path3.default.dirname(dest), {
|
|
354
|
+
recursive: true
|
|
355
|
+
});
|
|
356
|
+
import_node_fs3.default.copyFileSync(src, dest);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
337
360
|
if (!options?.dbFile) {
|
|
338
361
|
if (options?.usePrismaPush) {
|
|
339
362
|
(0, import_common_helpers2.invariant)(typeof schema === "string" || options?.schemaFile, "a schema file must be provided when using prisma db push");
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/client.ts","../src/project.ts","../src/schema.ts","../src/utils.ts","../src/vitest-ext.ts"],"sourcesContent":["export * from './client';\nexport * from './project';\nexport * from './schema';\nexport * from './vitest-ext';\n","import { invariant } from '@zenstackhq/common-helpers';\nimport type { Model } from '@zenstackhq/language/ast';\nimport { ZenStackClient, type ClientContract, type ClientOptions } from '@zenstackhq/orm';\nimport type { SchemaDef } from '@zenstackhq/orm/schema';\nimport { PolicyPlugin } from '@zenstackhq/plugin-policy';\nimport { PrismaSchemaGenerator } from '@zenstackhq/sdk';\nimport SQLite from 'better-sqlite3';\nimport { PostgresDialect, SqliteDialect, type LogEvent } from 'kysely';\nimport { execSync } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { Client as PGClient, Pool } from 'pg';\nimport { expect } from 'vitest';\nimport { createTestProject } from './project';\nimport { generateTsSchema } from './schema';\nimport { loadDocumentWithPlugins } from './utils';\n\nexport function getTestDbProvider() {\n const val = process.env['TEST_DB_PROVIDER'] ?? 'sqlite';\n if (!['sqlite', 'postgresql'].includes(val!)) {\n throw new Error(`Invalid TEST_DB_PROVIDER value: ${val}`);\n }\n return val as 'sqlite' | 'postgresql';\n}\n\nconst TEST_PG_CONFIG = {\n host: process.env['TEST_PG_HOST'] ?? 'localhost',\n port: process.env['TEST_PG_PORT'] ? parseInt(process.env['TEST_PG_PORT']) : 5432,\n user: process.env['TEST_PG_USER'] ?? 'postgres',\n password: process.env['TEST_PG_PASSWORD'] ?? 'postgres',\n};\n\nexport type CreateTestClientOptions<Schema extends SchemaDef> = Omit<ClientOptions<Schema>, 'dialect'> & {\n provider?: 'sqlite' | 'postgresql';\n schemaFile?: string;\n dbName?: string;\n usePrismaPush?: boolean;\n extraSourceFiles?: Record<string, string>;\n workDir?: string;\n debug?: boolean;\n dbFile?: string;\n};\n\nexport async function createTestClient<Schema extends SchemaDef>(\n schema: Schema,\n options?: CreateTestClientOptions<Schema>,\n): Promise<ClientContract<Schema>>;\nexport async function createTestClient<Schema extends SchemaDef>(\n schema: string,\n options?: CreateTestClientOptions<Schema>,\n): Promise<any>;\nexport async function createTestClient<Schema extends SchemaDef>(\n schema: Schema | string,\n options?: CreateTestClientOptions<Schema>,\n): Promise<any> {\n let workDir = options?.workDir;\n let _schema: Schema;\n const provider = options?.provider ?? getTestDbProvider() ?? 'sqlite';\n const dbName = options?.dbName ?? getTestDbName(provider);\n const dbUrl =\n provider === 'sqlite'\n ? `file:${dbName}`\n : `postgres://${TEST_PG_CONFIG.user}:${TEST_PG_CONFIG.password}@${TEST_PG_CONFIG.host}:${TEST_PG_CONFIG.port}/${dbName}`;\n\n let model: Model | undefined;\n\n if (typeof schema === 'string') {\n const generated = await generateTsSchema(schema, provider, dbUrl, options?.extraSourceFiles, undefined);\n workDir = generated.workDir;\n model = generated.model;\n // replace schema's provider\n _schema = {\n ...generated.schema,\n provider: {\n ...generated.schema.provider,\n type: provider,\n },\n } as Schema;\n } else {\n // replace schema's provider\n _schema = {\n ...schema,\n provider: {\n type: provider,\n },\n };\n workDir ??= createTestProject();\n if (options?.schemaFile) {\n let schemaContent = fs.readFileSync(options.schemaFile, 'utf-8');\n if (dbUrl) {\n // replace `datasource db { }` section\n schemaContent = schemaContent.replace(\n /datasource\\s+db\\s*{[^}]*}/m,\n `datasource db {\n provider = '${provider}'\n url = '${dbUrl}'\n}`,\n );\n }\n fs.writeFileSync(path.join(workDir, 'schema.zmodel'), schemaContent);\n }\n }\n\n invariant(workDir);\n if (options?.debug) {\n console.log(`Work directory: ${workDir}`);\n }\n\n // copy db file to workDir if specified\n if (options?.dbFile) {\n if (provider !== 'sqlite') {\n throw new Error('dbFile option is only supported for sqlite provider');\n }\n fs.copyFileSync(options.dbFile, path.join(workDir, dbName));\n }\n\n const { plugins, ...rest } = options ?? {};\n const _options: ClientOptions<Schema> = {\n ...rest,\n } as ClientOptions<Schema>;\n\n if (!options?.dbFile) {\n if (options?.usePrismaPush) {\n invariant(\n typeof schema === 'string' || options?.schemaFile,\n 'a schema file must be provided when using prisma db push',\n );\n if (!model) {\n const r = await loadDocumentWithPlugins(path.join(workDir, 'schema.zmodel'));\n if (!r.success) {\n throw new Error(r.errors.join('\\n'));\n }\n model = r.model;\n }\n const prismaSchema = new PrismaSchemaGenerator(model);\n const prismaSchemaText = await prismaSchema.generate();\n fs.writeFileSync(path.resolve(workDir!, 'schema.prisma'), prismaSchemaText);\n execSync('npx prisma db push --schema ./schema.prisma --skip-generate --force-reset', {\n cwd: workDir,\n stdio: 'ignore',\n });\n } else {\n if (provider === 'postgresql') {\n invariant(dbName, 'dbName is required');\n const pgClient = new PGClient(TEST_PG_CONFIG);\n await pgClient.connect();\n await pgClient.query(`DROP DATABASE IF EXISTS \"${dbName}\"`);\n await pgClient.query(`CREATE DATABASE \"${dbName}\"`);\n await pgClient.end();\n }\n }\n }\n\n if (provider === 'postgresql') {\n _options.dialect = new PostgresDialect({\n pool: new Pool({\n ...TEST_PG_CONFIG,\n database: dbName,\n }),\n });\n } else {\n _options.dialect = new SqliteDialect({\n database: new SQLite(path.join(workDir!, dbName)),\n });\n }\n\n let client = new ZenStackClient(_schema, _options);\n\n if (!options?.usePrismaPush && !options?.dbFile) {\n await client.$pushSchema();\n }\n\n if (plugins) {\n for (const plugin of plugins) {\n client = client.$use(plugin);\n }\n }\n\n return client;\n}\n\nexport async function createPolicyTestClient<Schema extends SchemaDef>(\n schema: Schema,\n options?: CreateTestClientOptions<Schema>,\n): Promise<ClientContract<Schema>>;\nexport async function createPolicyTestClient<Schema extends SchemaDef>(\n schema: string,\n options?: CreateTestClientOptions<Schema>,\n): Promise<any>;\nexport async function createPolicyTestClient<Schema extends SchemaDef>(\n schema: Schema | string,\n options?: CreateTestClientOptions<Schema>,\n): Promise<any> {\n return createTestClient(\n schema as any,\n {\n ...options,\n plugins: [...(options?.plugins ?? []), new PolicyPlugin()],\n } as any,\n );\n}\n\nexport function testLogger(e: LogEvent) {\n console.log(e.query.sql, e.query.parameters);\n}\n\nfunction getTestDbName(provider: string) {\n if (provider === 'sqlite') {\n return './test.db';\n }\n const testName = expect.getState().currentTestName ?? 'unnamed';\n const testPath = expect.getState().testPath ?? '';\n // digest test name\n const digest = createHash('md5')\n .update(testName + testPath)\n .digest('hex');\n // compute a database name based on test name\n return (\n 'test_' +\n testName\n .toLowerCase()\n .replace(/[^a-z0-9_]/g, '_')\n .replace(/_+/g, '_')\n .substring(0, 30) +\n digest.slice(0, 6)\n );\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport tmp from 'tmp';\n\nexport function createTestProject(zmodelContent?: string) {\n const { name: workDir } = tmp.dirSync({ unsafeCleanup: true });\n\n fs.mkdirSync(path.join(workDir, 'node_modules'));\n\n // symlink all entries from \"node_modules\"\n const nodeModules = fs.readdirSync(path.join(__dirname, '../node_modules'));\n for (const entry of nodeModules) {\n if (entry.startsWith('@zenstackhq')) {\n continue;\n }\n fs.symlinkSync(\n path.join(__dirname, '../node_modules', entry),\n path.join(workDir, 'node_modules', entry),\n 'dir',\n );\n }\n\n // in addition, symlink zenstack packages\n const zenstackPackages = ['language', 'sdk', 'orm', 'cli'];\n fs.mkdirSync(path.join(workDir, 'node_modules/@zenstackhq'));\n for (const pkg of zenstackPackages) {\n fs.symlinkSync(\n path.join(__dirname, `../../${pkg}`),\n path.join(workDir, `node_modules/@zenstackhq/${pkg}`),\n 'dir',\n );\n }\n\n fs.writeFileSync(\n path.join(workDir, 'package.json'),\n JSON.stringify(\n {\n name: 'test',\n version: '1.0.0',\n type: 'module',\n },\n null,\n 4,\n ),\n );\n\n fs.writeFileSync(\n path.join(workDir, 'tsconfig.json'),\n JSON.stringify(\n {\n compilerOptions: {\n module: 'ESNext',\n target: 'ESNext',\n moduleResolution: 'Bundler',\n esModuleInterop: true,\n skipLibCheck: true,\n strict: true,\n },\n include: ['**/*.ts'],\n },\n null,\n 4,\n ),\n );\n\n if (zmodelContent) {\n fs.writeFileSync(path.join(workDir, 'schema.zmodel'), zmodelContent);\n }\n\n return workDir;\n}\n","import { invariant } from '@zenstackhq/common-helpers';\nimport type { SchemaDef } from '@zenstackhq/schema';\nimport { TsSchemaGenerator } from '@zenstackhq/sdk';\nimport { execSync } from 'node:child_process';\nimport crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { match } from 'ts-pattern';\nimport { expect } from 'vitest';\nimport { createTestProject } from './project';\nimport { loadDocumentWithPlugins } from './utils';\n\nfunction makePrelude(provider: 'sqlite' | 'postgresql', dbUrl?: string) {\n return match(provider)\n .with('sqlite', () => {\n return `\ndatasource db {\n provider = 'sqlite'\n url = '${dbUrl ?? 'file:./test.db'}'\n}\n`;\n })\n .with('postgresql', () => {\n return `\ndatasource db {\n provider = 'postgresql'\n url = '${dbUrl ?? 'postgres://postgres:postgres@localhost:5432/db'}'\n}\n`;\n })\n .exhaustive();\n}\n\nfunction replacePlaceholders(schemaText: string, provider: 'sqlite' | 'postgresql', dbUrl: string | undefined) {\n const url = dbUrl ?? (provider === 'sqlite' ? 'file:./test.db' : 'postgres://postgres:postgres@localhost:5432/db');\n return schemaText.replace(/\\$DB_URL/g, url).replace(/\\$PROVIDER/g, provider);\n}\n\nexport async function generateTsSchema(\n schemaText: string,\n provider: 'sqlite' | 'postgresql' = 'sqlite',\n dbUrl?: string,\n extraSourceFiles?: Record<string, string>,\n withLiteSchema?: boolean,\n) {\n const workDir = createTestProject();\n\n const zmodelPath = path.join(workDir, 'schema.zmodel');\n const noPrelude = schemaText.includes('datasource ');\n fs.writeFileSync(\n zmodelPath,\n `${noPrelude ? '' : makePrelude(provider, dbUrl)}\\n\\n${replacePlaceholders(schemaText, provider, dbUrl)}`,\n );\n\n const result = await loadDocumentWithPlugins(zmodelPath);\n if (!result.success) {\n throw new Error(`Failed to load schema from ${zmodelPath}: ${result.errors}`);\n }\n\n const generator = new TsSchemaGenerator();\n await generator.generate(result.model, { outDir: workDir, lite: withLiteSchema });\n\n if (extraSourceFiles) {\n for (const [fileName, content] of Object.entries(extraSourceFiles)) {\n const filePath = path.resolve(workDir, !fileName.endsWith('.ts') ? `${fileName}.ts` : fileName);\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n fs.writeFileSync(filePath, content);\n }\n }\n\n // compile the generated TS schema\n return { ...(await compileAndLoad(workDir)), model: result.model };\n}\n\nasync function compileAndLoad(workDir: string) {\n execSync('npx tsc', {\n cwd: workDir,\n stdio: 'inherit',\n });\n\n // load the schema module\n const module = await import(path.join(workDir, 'schema.js'));\n\n let moduleLite: any;\n try {\n moduleLite = await import(path.join(workDir, 'schema-lite.js'));\n } catch {\n // ignore\n }\n return { workDir, schema: module.schema as SchemaDef, schemaLite: moduleLite?.schema as SchemaDef | undefined };\n}\n\nexport function generateTsSchemaFromFile(filePath: string) {\n const schemaText = fs.readFileSync(filePath, 'utf8');\n return generateTsSchema(schemaText);\n}\n\nexport async function generateTsSchemaInPlace(schemaPath: string) {\n const workDir = path.dirname(schemaPath);\n const result = await loadDocumentWithPlugins(schemaPath);\n if (!result.success) {\n throw new Error(`Failed to load schema from ${schemaPath}: ${result.errors}`);\n }\n const generator = new TsSchemaGenerator();\n await generator.generate(result.model, { outDir: workDir });\n return compileAndLoad(workDir);\n}\n\nexport async function loadSchema(schema: string, additionalSchemas?: Record<string, string>) {\n if (!schema.includes('datasource ')) {\n schema = `${makePrelude('sqlite')}\\n\\n${schema}`;\n }\n\n // create a temp folder\n const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zenstack-schema'));\n\n // create a temp file\n const tempFile = path.join(tempDir, `schema.zmodel`);\n fs.writeFileSync(tempFile, schema);\n\n if (additionalSchemas) {\n for (const [fileName, content] of Object.entries(additionalSchemas)) {\n let name = fileName;\n if (!name.endsWith('.zmodel')) {\n name += '.zmodel';\n }\n const filePath = path.join(tempDir, name);\n fs.writeFileSync(filePath, content);\n }\n }\n\n const r = await loadDocumentWithPlugins(tempFile);\n expect(r).toSatisfy(\n (r) => r.success,\n `Failed to load schema: ${(r as any).errors?.map((e: any) => e.toString()).join(', ')}`,\n );\n invariant(r.success);\n return r.model;\n}\n\nexport async function loadSchemaWithError(schema: string, error: string | RegExp) {\n if (!schema.includes('datasource ')) {\n schema = `${makePrelude('sqlite')}\\n\\n${schema}`;\n }\n\n // create a temp file\n const tempFile = path.join(os.tmpdir(), `zenstack-schema-${crypto.randomUUID()}.zmodel`);\n fs.writeFileSync(tempFile, schema);\n const r = await loadDocumentWithPlugins(tempFile);\n expect(r.success).toBe(false);\n invariant(!r.success);\n if (typeof error === 'string') {\n expect(r).toSatisfy(\n (r) => r.errors.some((e: any) => e.toString().toLowerCase().includes(error.toLowerCase())),\n `Expected error message to include \"${error}\" but got: ${r.errors.map((e: any) => e.toString()).join(', ')}`,\n );\n } else {\n expect(r).toSatisfy(\n (r) => r.errors.some((e: any) => error.test(e)),\n `Expected error message to match \"${error}\" but got: ${r.errors.map((e: any) => e.toString()).join(', ')}`,\n );\n }\n}\n","import { loadDocument } from '@zenstackhq/language';\n\nexport function loadDocumentWithPlugins(filePath: string) {\n const pluginModelFiles = [require.resolve('@zenstackhq/plugin-policy/plugin.zmodel')];\n return loadDocument(filePath, pluginModelFiles);\n}\n","import { ORMError, ORMErrorReason } from '@zenstackhq/orm';\nimport { expect } from 'vitest';\n\nfunction isPromise(value: any) {\n return typeof value.then === 'function' && typeof value.catch === 'function';\n}\n\nfunction expectErrorReason(err: any, errorReason: ORMErrorReason) {\n if (err instanceof ORMError && err.reason === errorReason) {\n return {\n message: () => '',\n pass: true,\n };\n } else {\n return {\n message: () => `expected ORMError of reason ${errorReason}, got ${err}`,\n pass: false,\n };\n }\n}\n\nfunction expectErrorMessages(expectedMessages: string[], message: string) {\n for (const m of expectedMessages) {\n if (!message.toLowerCase().includes(m.toLowerCase())) {\n return {\n message: () => `expected message not found in error: ${m}, got message: ${message}`,\n pass: false,\n };\n }\n }\n return undefined;\n}\n\nexpect.extend({\n async toResolveTruthy(received: Promise<unknown>) {\n if (!isPromise(received)) {\n return { message: () => 'a promise is expected', pass: false };\n }\n const r = await received;\n return {\n pass: !!r,\n message: () => `Expected promise to resolve to a truthy value, but got ${r}`,\n };\n },\n\n async toResolveFalsy(received: Promise<unknown>) {\n if (!isPromise(received)) {\n return { message: () => 'a promise is expected', pass: false };\n }\n const r = await received;\n return {\n pass: !r,\n message: () => `Expected promise to resolve to a falsy value, but got ${r}`,\n };\n },\n\n async toResolveNull(received: Promise<unknown>) {\n if (!isPromise(received)) {\n return { message: () => 'a promise is expected', pass: false };\n }\n const r = await received;\n return {\n pass: r === null,\n message: () => `Expected promise to resolve to a null value, but got ${r}`,\n };\n },\n\n async toResolveWithLength(received: Promise<unknown>, length: number) {\n const r = await received;\n return {\n pass: Array.isArray(r) && r.length === length,\n message: () => `Expected promise to resolve with an array with length ${length}, but got ${r}`,\n };\n },\n\n async toBeRejectedNotFound(received: Promise<unknown>) {\n if (!isPromise(received)) {\n return { message: () => 'a promise is expected', pass: false };\n }\n try {\n await received;\n } catch (err) {\n return expectErrorReason(err, ORMErrorReason.NOT_FOUND);\n }\n return {\n message: () => `expected NotFoundError, got no error`,\n pass: false,\n };\n },\n\n async toBeRejectedByPolicy(received: Promise<unknown>, expectedMessages?: string[]) {\n if (!isPromise(received)) {\n return { message: () => 'a promise is expected', pass: false };\n }\n try {\n await received;\n } catch (err) {\n if (expectedMessages && err instanceof ORMError && err.reason === ORMErrorReason.REJECTED_BY_POLICY) {\n const r = expectErrorMessages(expectedMessages, err.message || '');\n if (r) {\n return r;\n }\n }\n return expectErrorReason(err, ORMErrorReason.REJECTED_BY_POLICY);\n }\n return {\n message: () => `expected PolicyError, got no error`,\n pass: false,\n };\n },\n\n async toBeRejectedByValidation(received: Promise<unknown>, expectedMessages?: string[]) {\n if (!isPromise(received)) {\n return { message: () => 'a promise is expected', pass: false };\n }\n try {\n await received;\n } catch (err) {\n if (expectedMessages && err instanceof ORMError && err.reason === ORMErrorReason.INVALID_INPUT) {\n const r = expectErrorMessages(expectedMessages, err.message || '');\n if (r) {\n return r;\n }\n }\n return expectErrorReason(err, ORMErrorReason.INVALID_INPUT);\n }\n return {\n message: () => `expected InputValidationError, got no error`,\n pass: false,\n };\n },\n});\n"],"mappings":"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","names":["import_common_helpers","import_sdk","import_node_child_process","import_node_crypto","import_node_fs","import_node_path","import_vitest","createTestProject","zmodelContent","name","workDir","tmp","dirSync","unsafeCleanup","fs","mkdirSync","path","join","nodeModules","readdirSync","__dirname","entry","startsWith","symlinkSync","zenstackPackages","pkg","writeFileSync","JSON","stringify","version","type","compilerOptions","module","target","moduleResolution","esModuleInterop","skipLibCheck","strict","include","import_node_fs","import_node_path","loadDocumentWithPlugins","filePath","pluginModelFiles","require","loadDocument","makePrelude","provider","dbUrl","match","with","exhaustive","replacePlaceholders","schemaText","url","replace","generateTsSchema","extraSourceFiles","withLiteSchema","workDir","createTestProject","zmodelPath","path","join","noPrelude","includes","fs","writeFileSync","result","loadDocumentWithPlugins","success","Error","errors","generator","TsSchemaGenerator","generate","model","outDir","lite","fileName","content","Object","entries","filePath","resolve","endsWith","mkdirSync","dirname","recursive","compileAndLoad","execSync","cwd","stdio","module","moduleLite","schema","schemaLite","generateTsSchemaFromFile","readFileSync","generateTsSchemaInPlace","schemaPath","loadSchema","additionalSchemas","tempDir","mkdtempSync","os","tmpdir","tempFile","name","r","expect","toSatisfy","map","e","toString","invariant","loadSchemaWithError","error","crypto","randomUUID","toBe","some","toLowerCase","test","getTestDbProvider","val","process","env","includes","Error","TEST_PG_CONFIG","host","port","parseInt","user","password","createTestClient","schema","options","workDir","_schema","provider","dbName","getTestDbName","dbUrl","model","generated","generateTsSchema","extraSourceFiles","undefined","type","createTestProject","schemaFile","schemaContent","fs","readFileSync","replace","writeFileSync","path","join","invariant","debug","console","log","dbFile","copyFileSync","plugins","rest","_options","usePrismaPush","r","loadDocumentWithPlugins","success","errors","prismaSchema","PrismaSchemaGenerator","prismaSchemaText","generate","resolve","execSync","cwd","stdio","pgClient","PGClient","connect","query","end","dialect","PostgresDialect","pool","Pool","database","SqliteDialect","SQLite","client","ZenStackClient","$pushSchema","plugin","$use","createPolicyTestClient","PolicyPlugin","testLogger","e","sql","parameters","testName","expect","getState","currentTestName","testPath","digest","createHash","update","toLowerCase","substring","slice","import_orm","import_vitest","isPromise","value","then","catch","expectErrorReason","err","errorReason","ORMError","reason","message","pass","expectErrorMessages","expectedMessages","m","toLowerCase","includes","undefined","expect","extend","toResolveTruthy","received","r","toResolveFalsy","toResolveNull","toResolveWithLength","length","Array","isArray","toBeRejectedNotFound","ORMErrorReason","NOT_FOUND","toBeRejectedByPolicy","REJECTED_BY_POLICY","toBeRejectedByValidation","INVALID_INPUT"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/client.ts","../src/project.ts","../src/schema.ts","../src/utils.ts","../src/vitest-ext.ts"],"sourcesContent":["export * from './client';\nexport * from './project';\nexport * from './schema';\nexport * from './vitest-ext';\n","import { invariant } from '@zenstackhq/common-helpers';\nimport type { Model } from '@zenstackhq/language/ast';\nimport { ZenStackClient, type ClientContract, type ClientOptions } from '@zenstackhq/orm';\nimport type { SchemaDef } from '@zenstackhq/orm/schema';\nimport { PolicyPlugin } from '@zenstackhq/plugin-policy';\nimport { PrismaSchemaGenerator } from '@zenstackhq/sdk';\nimport SQLite from 'better-sqlite3';\nimport { glob } from 'glob';\nimport { PostgresDialect, SqliteDialect, type LogEvent } from 'kysely';\nimport { execSync } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { Client as PGClient, Pool } from 'pg';\nimport { expect } from 'vitest';\nimport { createTestProject } from './project';\nimport { generateTsSchema } from './schema';\nimport { loadDocumentWithPlugins } from './utils';\n\nexport function getTestDbProvider() {\n const val = process.env['TEST_DB_PROVIDER'] ?? 'sqlite';\n if (!['sqlite', 'postgresql'].includes(val!)) {\n throw new Error(`Invalid TEST_DB_PROVIDER value: ${val}`);\n }\n return val as 'sqlite' | 'postgresql';\n}\n\nconst TEST_PG_CONFIG = {\n host: process.env['TEST_PG_HOST'] ?? 'localhost',\n port: process.env['TEST_PG_PORT'] ? parseInt(process.env['TEST_PG_PORT']) : 5432,\n user: process.env['TEST_PG_USER'] ?? 'postgres',\n password: process.env['TEST_PG_PASSWORD'] ?? 'postgres',\n};\n\nexport type CreateTestClientOptions<Schema extends SchemaDef> = Omit<ClientOptions<Schema>, 'dialect'> & {\n /**\n * Database provider\n */\n provider?: 'sqlite' | 'postgresql';\n\n /**\n * The main ZModel file. Only used when `usePrismaPush` is true and `schema` is an object.\n */\n schemaFile?: string;\n\n /**\n * Database name. If not provided, a name will be generated based on the test name.\n */\n dbName?: string;\n\n /**\n * Use `prisma db push` instead of ZenStack's `$pushSchema` for database initialization.\n */\n usePrismaPush?: boolean;\n\n /**\n * Extra source files to create and compile.\n */\n extraSourceFiles?: Record<string, string>;\n\n /**\n * Working directory for the test client. If not provided, a temporary directory will be created.\n */\n workDir?: string;\n\n /**\n * Debug mode.\n */\n debug?: boolean;\n\n /**\n * A sqlite database file to be used for the test. Only supported for sqlite provider.\n */\n dbFile?: string;\n\n /**\n * PostgreSQL extensions to be added to the datasource. Only supported for postgresql provider.\n */\n dataSourceExtensions?: string[];\n\n /**\n * Additional files to be copied to the working directory. The glob pattern is relative to the test file.\n */\n copyFiles?: { globPattern: string; destination: string }[];\n};\n\nexport async function createTestClient<Schema extends SchemaDef>(\n schema: Schema,\n options?: CreateTestClientOptions<Schema>,\n): Promise<ClientContract<Schema>>;\nexport async function createTestClient<Schema extends SchemaDef>(\n schema: string,\n options?: CreateTestClientOptions<Schema>,\n): Promise<any>;\nexport async function createTestClient<Schema extends SchemaDef>(\n schema: Schema | string,\n options?: CreateTestClientOptions<Schema>,\n): Promise<any> {\n let workDir = options?.workDir;\n let _schema: Schema;\n const provider = options?.provider ?? getTestDbProvider() ?? 'sqlite';\n const dbName = options?.dbName ?? getTestDbName(provider);\n const dbUrl =\n provider === 'sqlite'\n ? `file:${dbName}`\n : `postgres://${TEST_PG_CONFIG.user}:${TEST_PG_CONFIG.password}@${TEST_PG_CONFIG.host}:${TEST_PG_CONFIG.port}/${dbName}`;\n\n let model: Model | undefined;\n\n if (typeof schema === 'string') {\n const generated = await generateTsSchema(schema, provider, dbUrl, options?.extraSourceFiles, undefined);\n workDir = generated.workDir;\n model = generated.model;\n // replace schema's provider\n _schema = {\n ...generated.schema,\n provider: {\n ...generated.schema.provider,\n type: provider,\n },\n } as Schema;\n } else {\n // replace schema's provider\n _schema = {\n ...schema,\n provider: {\n type: provider,\n },\n };\n workDir ??= createTestProject();\n if (options?.schemaFile) {\n let schemaContent = fs.readFileSync(options.schemaFile, 'utf-8');\n if (dbUrl) {\n // replace `datasource db { }` section\n schemaContent = schemaContent.replace(\n /datasource\\s+db\\s*{[^}]*}/m,\n `datasource db {\n provider = '${provider}'\n url = '${dbUrl}'\n ${options.dataSourceExtensions ? `extensions = [${options.dataSourceExtensions.join(', ')}]` : ''}\n}`,\n );\n }\n fs.writeFileSync(path.join(workDir!, 'schema.zmodel'), schemaContent);\n }\n }\n\n invariant(workDir);\n\n const { plugins, ...rest } = options ?? {};\n const _options: ClientOptions<Schema> = {\n ...rest,\n } as ClientOptions<Schema>;\n\n if (options?.debug) {\n console.log(`Work directory: ${workDir}`);\n _options.log = testLogger;\n }\n\n // copy db file to workDir if specified\n if (options?.dbFile) {\n if (provider !== 'sqlite') {\n throw new Error('dbFile option is only supported for sqlite provider');\n }\n fs.copyFileSync(options.dbFile, path.join(workDir, dbName));\n }\n\n // copy additional files if specified\n if (options?.copyFiles) {\n const state = expect.getState();\n const currentTestPath = state.testPath;\n if (!currentTestPath) {\n throw new Error('Unable to determine current test file path');\n }\n for (const { globPattern, destination } of options.copyFiles) {\n const files = glob.sync(globPattern, { cwd: path.dirname(currentTestPath) });\n for (const file of files) {\n const src = path.resolve(path.dirname(currentTestPath), file);\n const dest = path.resolve(workDir, destination, path.basename(file));\n fs.mkdirSync(path.dirname(dest), { recursive: true });\n fs.copyFileSync(src, dest);\n }\n }\n }\n\n if (!options?.dbFile) {\n if (options?.usePrismaPush) {\n invariant(\n typeof schema === 'string' || options?.schemaFile,\n 'a schema file must be provided when using prisma db push',\n );\n if (!model) {\n const r = await loadDocumentWithPlugins(path.join(workDir, 'schema.zmodel'));\n if (!r.success) {\n throw new Error(r.errors.join('\\n'));\n }\n model = r.model;\n }\n const prismaSchema = new PrismaSchemaGenerator(model);\n const prismaSchemaText = await prismaSchema.generate();\n fs.writeFileSync(path.resolve(workDir!, 'schema.prisma'), prismaSchemaText);\n execSync('npx prisma db push --schema ./schema.prisma --skip-generate --force-reset', {\n cwd: workDir,\n stdio: 'ignore',\n });\n } else {\n if (provider === 'postgresql') {\n invariant(dbName, 'dbName is required');\n const pgClient = new PGClient(TEST_PG_CONFIG);\n await pgClient.connect();\n await pgClient.query(`DROP DATABASE IF EXISTS \"${dbName}\"`);\n await pgClient.query(`CREATE DATABASE \"${dbName}\"`);\n await pgClient.end();\n }\n }\n }\n\n if (provider === 'postgresql') {\n _options.dialect = new PostgresDialect({\n pool: new Pool({\n ...TEST_PG_CONFIG,\n database: dbName,\n }),\n });\n } else {\n _options.dialect = new SqliteDialect({\n database: new SQLite(path.join(workDir!, dbName)),\n });\n }\n\n let client = new ZenStackClient(_schema, _options);\n\n if (!options?.usePrismaPush && !options?.dbFile) {\n await client.$pushSchema();\n }\n\n if (plugins) {\n for (const plugin of plugins) {\n client = client.$use(plugin);\n }\n }\n\n return client;\n}\n\nexport async function createPolicyTestClient<Schema extends SchemaDef>(\n schema: Schema,\n options?: CreateTestClientOptions<Schema>,\n): Promise<ClientContract<Schema>>;\nexport async function createPolicyTestClient<Schema extends SchemaDef>(\n schema: string,\n options?: CreateTestClientOptions<Schema>,\n): Promise<any>;\nexport async function createPolicyTestClient<Schema extends SchemaDef>(\n schema: Schema | string,\n options?: CreateTestClientOptions<Schema>,\n): Promise<any> {\n return createTestClient(\n schema as any,\n {\n ...options,\n plugins: [...(options?.plugins ?? []), new PolicyPlugin()],\n } as any,\n );\n}\n\nexport function testLogger(e: LogEvent) {\n console.log(e.query.sql, e.query.parameters);\n}\n\nfunction getTestDbName(provider: string) {\n if (provider === 'sqlite') {\n return './test.db';\n }\n const testName = expect.getState().currentTestName ?? 'unnamed';\n const testPath = expect.getState().testPath ?? '';\n // digest test name\n const digest = createHash('md5')\n .update(testName + testPath)\n .digest('hex');\n // compute a database name based on test name\n return (\n 'test_' +\n testName\n .toLowerCase()\n .replace(/[^a-z0-9_]/g, '_')\n .replace(/_+/g, '_')\n .substring(0, 30) +\n digest.slice(0, 6)\n );\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport tmp from 'tmp';\n\nexport function createTestProject(zmodelContent?: string) {\n const { name: workDir } = tmp.dirSync({ unsafeCleanup: true });\n\n fs.mkdirSync(path.join(workDir, 'node_modules'));\n\n // symlink all entries from \"node_modules\"\n const nodeModules = fs.readdirSync(path.join(__dirname, '../node_modules'));\n for (const entry of nodeModules) {\n if (entry.startsWith('@zenstackhq')) {\n continue;\n }\n fs.symlinkSync(\n path.join(__dirname, '../node_modules', entry),\n path.join(workDir, 'node_modules', entry),\n 'dir',\n );\n }\n\n // in addition, symlink zenstack packages\n const zenstackPackages = ['language', 'sdk', 'orm', 'cli'];\n fs.mkdirSync(path.join(workDir, 'node_modules/@zenstackhq'));\n for (const pkg of zenstackPackages) {\n fs.symlinkSync(\n path.join(__dirname, `../../${pkg}`),\n path.join(workDir, `node_modules/@zenstackhq/${pkg}`),\n 'dir',\n );\n }\n\n fs.writeFileSync(\n path.join(workDir, 'package.json'),\n JSON.stringify(\n {\n name: 'test',\n version: '1.0.0',\n type: 'module',\n },\n null,\n 4,\n ),\n );\n\n fs.writeFileSync(\n path.join(workDir, 'tsconfig.json'),\n JSON.stringify(\n {\n compilerOptions: {\n module: 'ESNext',\n target: 'ESNext',\n moduleResolution: 'Bundler',\n esModuleInterop: true,\n skipLibCheck: true,\n strict: true,\n },\n include: ['**/*.ts'],\n },\n null,\n 4,\n ),\n );\n\n if (zmodelContent) {\n fs.writeFileSync(path.join(workDir, 'schema.zmodel'), zmodelContent);\n }\n\n return workDir;\n}\n","import { invariant } from '@zenstackhq/common-helpers';\nimport type { SchemaDef } from '@zenstackhq/schema';\nimport { TsSchemaGenerator } from '@zenstackhq/sdk';\nimport { execSync } from 'node:child_process';\nimport crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { match } from 'ts-pattern';\nimport { expect } from 'vitest';\nimport { createTestProject } from './project';\nimport { loadDocumentWithPlugins } from './utils';\n\nfunction makePrelude(provider: 'sqlite' | 'postgresql', dbUrl?: string) {\n return match(provider)\n .with('sqlite', () => {\n return `\ndatasource db {\n provider = 'sqlite'\n url = '${dbUrl ?? 'file:./test.db'}'\n}\n`;\n })\n .with('postgresql', () => {\n return `\ndatasource db {\n provider = 'postgresql'\n url = '${dbUrl ?? 'postgres://postgres:postgres@localhost:5432/db'}'\n}\n`;\n })\n .exhaustive();\n}\n\nfunction replacePlaceholders(schemaText: string, provider: 'sqlite' | 'postgresql', dbUrl: string | undefined) {\n const url = dbUrl ?? (provider === 'sqlite' ? 'file:./test.db' : 'postgres://postgres:postgres@localhost:5432/db');\n return schemaText.replace(/\\$DB_URL/g, url).replace(/\\$PROVIDER/g, provider);\n}\n\nexport async function generateTsSchema(\n schemaText: string,\n provider: 'sqlite' | 'postgresql' = 'sqlite',\n dbUrl?: string,\n extraSourceFiles?: Record<string, string>,\n withLiteSchema?: boolean,\n) {\n const workDir = createTestProject();\n\n const zmodelPath = path.join(workDir, 'schema.zmodel');\n const noPrelude = schemaText.includes('datasource ');\n fs.writeFileSync(\n zmodelPath,\n `${noPrelude ? '' : makePrelude(provider, dbUrl)}\\n\\n${replacePlaceholders(schemaText, provider, dbUrl)}`,\n );\n\n const result = await loadDocumentWithPlugins(zmodelPath);\n if (!result.success) {\n throw new Error(`Failed to load schema from ${zmodelPath}: ${result.errors}`);\n }\n\n const generator = new TsSchemaGenerator();\n await generator.generate(result.model, { outDir: workDir, lite: withLiteSchema });\n\n if (extraSourceFiles) {\n for (const [fileName, content] of Object.entries(extraSourceFiles)) {\n const filePath = path.resolve(workDir, !fileName.endsWith('.ts') ? `${fileName}.ts` : fileName);\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n fs.writeFileSync(filePath, content);\n }\n }\n\n // compile the generated TS schema\n return { ...(await compileAndLoad(workDir)), model: result.model };\n}\n\nasync function compileAndLoad(workDir: string) {\n execSync('npx tsc', {\n cwd: workDir,\n stdio: 'inherit',\n });\n\n // load the schema module\n const module = await import(path.join(workDir, 'schema.js'));\n\n let moduleLite: any;\n try {\n moduleLite = await import(path.join(workDir, 'schema-lite.js'));\n } catch {\n // ignore\n }\n return { workDir, schema: module.schema as SchemaDef, schemaLite: moduleLite?.schema as SchemaDef | undefined };\n}\n\nexport function generateTsSchemaFromFile(filePath: string) {\n const schemaText = fs.readFileSync(filePath, 'utf8');\n return generateTsSchema(schemaText);\n}\n\nexport async function generateTsSchemaInPlace(schemaPath: string) {\n const workDir = path.dirname(schemaPath);\n const result = await loadDocumentWithPlugins(schemaPath);\n if (!result.success) {\n throw new Error(`Failed to load schema from ${schemaPath}: ${result.errors}`);\n }\n const generator = new TsSchemaGenerator();\n await generator.generate(result.model, { outDir: workDir });\n return compileAndLoad(workDir);\n}\n\nexport async function loadSchema(schema: string, additionalSchemas?: Record<string, string>) {\n if (!schema.includes('datasource ')) {\n schema = `${makePrelude('sqlite')}\\n\\n${schema}`;\n }\n\n // create a temp folder\n const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zenstack-schema'));\n\n // create a temp file\n const tempFile = path.join(tempDir, `schema.zmodel`);\n fs.writeFileSync(tempFile, schema);\n\n if (additionalSchemas) {\n for (const [fileName, content] of Object.entries(additionalSchemas)) {\n let name = fileName;\n if (!name.endsWith('.zmodel')) {\n name += '.zmodel';\n }\n const filePath = path.join(tempDir, name);\n fs.writeFileSync(filePath, content);\n }\n }\n\n const r = await loadDocumentWithPlugins(tempFile);\n expect(r).toSatisfy(\n (r) => r.success,\n `Failed to load schema: ${(r as any).errors?.map((e: any) => e.toString()).join(', ')}`,\n );\n invariant(r.success);\n return r.model;\n}\n\nexport async function loadSchemaWithError(schema: string, error: string | RegExp) {\n if (!schema.includes('datasource ')) {\n schema = `${makePrelude('sqlite')}\\n\\n${schema}`;\n }\n\n // create a temp file\n const tempFile = path.join(os.tmpdir(), `zenstack-schema-${crypto.randomUUID()}.zmodel`);\n fs.writeFileSync(tempFile, schema);\n const r = await loadDocumentWithPlugins(tempFile);\n expect(r.success).toBe(false);\n invariant(!r.success);\n if (typeof error === 'string') {\n expect(r).toSatisfy(\n (r) => r.errors.some((e: any) => e.toString().toLowerCase().includes(error.toLowerCase())),\n `Expected error message to include \"${error}\" but got: ${r.errors.map((e: any) => e.toString()).join(', ')}`,\n );\n } else {\n expect(r).toSatisfy(\n (r) => r.errors.some((e: any) => error.test(e)),\n `Expected error message to match \"${error}\" but got: ${r.errors.map((e: any) => e.toString()).join(', ')}`,\n );\n }\n}\n","import { loadDocument } from '@zenstackhq/language';\n\nexport function loadDocumentWithPlugins(filePath: string) {\n const pluginModelFiles = [require.resolve('@zenstackhq/plugin-policy/plugin.zmodel')];\n return loadDocument(filePath, pluginModelFiles);\n}\n","import { ORMError, ORMErrorReason } from '@zenstackhq/orm';\nimport { expect } from 'vitest';\n\nfunction isPromise(value: any) {\n return typeof value.then === 'function' && typeof value.catch === 'function';\n}\n\nfunction expectErrorReason(err: any, errorReason: ORMErrorReason) {\n if (err instanceof ORMError && err.reason === errorReason) {\n return {\n message: () => '',\n pass: true,\n };\n } else {\n return {\n message: () => `expected ORMError of reason ${errorReason}, got ${err}`,\n pass: false,\n };\n }\n}\n\nfunction expectErrorMessages(expectedMessages: string[], message: string) {\n for (const m of expectedMessages) {\n if (!message.toLowerCase().includes(m.toLowerCase())) {\n return {\n message: () => `expected message not found in error: ${m}, got message: ${message}`,\n pass: false,\n };\n }\n }\n return undefined;\n}\n\nexpect.extend({\n async toResolveTruthy(received: Promise<unknown>) {\n if (!isPromise(received)) {\n return { message: () => 'a promise is expected', pass: false };\n }\n const r = await received;\n return {\n pass: !!r,\n message: () => `Expected promise to resolve to a truthy value, but got ${r}`,\n };\n },\n\n async toResolveFalsy(received: Promise<unknown>) {\n if (!isPromise(received)) {\n return { message: () => 'a promise is expected', pass: false };\n }\n const r = await received;\n return {\n pass: !r,\n message: () => `Expected promise to resolve to a falsy value, but got ${r}`,\n };\n },\n\n async toResolveNull(received: Promise<unknown>) {\n if (!isPromise(received)) {\n return { message: () => 'a promise is expected', pass: false };\n }\n const r = await received;\n return {\n pass: r === null,\n message: () => `Expected promise to resolve to a null value, but got ${r}`,\n };\n },\n\n async toResolveWithLength(received: Promise<unknown>, length: number) {\n const r = await received;\n return {\n pass: Array.isArray(r) && r.length === length,\n message: () => `Expected promise to resolve with an array with length ${length}, but got ${r}`,\n };\n },\n\n async toBeRejectedNotFound(received: Promise<unknown>) {\n if (!isPromise(received)) {\n return { message: () => 'a promise is expected', pass: false };\n }\n try {\n await received;\n } catch (err) {\n return expectErrorReason(err, ORMErrorReason.NOT_FOUND);\n }\n return {\n message: () => `expected NotFoundError, got no error`,\n pass: false,\n };\n },\n\n async toBeRejectedByPolicy(received: Promise<unknown>, expectedMessages?: string[]) {\n if (!isPromise(received)) {\n return { message: () => 'a promise is expected', pass: false };\n }\n try {\n await received;\n } catch (err) {\n if (expectedMessages && err instanceof ORMError && err.reason === ORMErrorReason.REJECTED_BY_POLICY) {\n const r = expectErrorMessages(expectedMessages, err.message || '');\n if (r) {\n return r;\n }\n }\n return expectErrorReason(err, ORMErrorReason.REJECTED_BY_POLICY);\n }\n return {\n message: () => `expected PolicyError, got no error`,\n pass: false,\n };\n },\n\n async toBeRejectedByValidation(received: Promise<unknown>, expectedMessages?: string[]) {\n if (!isPromise(received)) {\n return { message: () => 'a promise is expected', pass: false };\n }\n try {\n await received;\n } catch (err) {\n if (expectedMessages && err instanceof ORMError && err.reason === ORMErrorReason.INVALID_INPUT) {\n const r = expectErrorMessages(expectedMessages, err.message || '');\n if (r) {\n return r;\n }\n }\n return expectErrorReason(err, ORMErrorReason.INVALID_INPUT);\n }\n return {\n message: () => `expected InputValidationError, got no error`,\n pass: false,\n };\n },\n});\n"],"mappings":"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","names":["import_common_helpers","import_sdk","import_node_child_process","import_node_crypto","import_node_fs","import_node_path","import_vitest","createTestProject","zmodelContent","name","workDir","tmp","dirSync","unsafeCleanup","fs","mkdirSync","path","join","nodeModules","readdirSync","__dirname","entry","startsWith","symlinkSync","zenstackPackages","pkg","writeFileSync","JSON","stringify","version","type","compilerOptions","module","target","moduleResolution","esModuleInterop","skipLibCheck","strict","include","import_node_fs","import_node_path","loadDocumentWithPlugins","filePath","pluginModelFiles","require","loadDocument","makePrelude","provider","dbUrl","match","with","exhaustive","replacePlaceholders","schemaText","url","replace","generateTsSchema","extraSourceFiles","withLiteSchema","workDir","createTestProject","zmodelPath","path","join","noPrelude","includes","fs","writeFileSync","result","loadDocumentWithPlugins","success","Error","errors","generator","TsSchemaGenerator","generate","model","outDir","lite","fileName","content","Object","entries","filePath","resolve","endsWith","mkdirSync","dirname","recursive","compileAndLoad","execSync","cwd","stdio","module","moduleLite","schema","schemaLite","generateTsSchemaFromFile","readFileSync","generateTsSchemaInPlace","schemaPath","loadSchema","additionalSchemas","tempDir","mkdtempSync","os","tmpdir","tempFile","name","r","expect","toSatisfy","map","e","toString","invariant","loadSchemaWithError","error","crypto","randomUUID","toBe","some","toLowerCase","test","getTestDbProvider","val","process","env","includes","Error","TEST_PG_CONFIG","host","port","parseInt","user","password","createTestClient","schema","options","workDir","_schema","provider","dbName","getTestDbName","dbUrl","model","generated","generateTsSchema","extraSourceFiles","undefined","type","createTestProject","schemaFile","schemaContent","fs","readFileSync","replace","dataSourceExtensions","join","writeFileSync","path","invariant","plugins","rest","_options","debug","console","log","testLogger","dbFile","copyFileSync","copyFiles","state","expect","getState","currentTestPath","testPath","globPattern","destination","files","glob","sync","cwd","dirname","file","src","resolve","dest","basename","mkdirSync","recursive","usePrismaPush","r","loadDocumentWithPlugins","success","errors","prismaSchema","PrismaSchemaGenerator","prismaSchemaText","generate","execSync","stdio","pgClient","PGClient","connect","query","end","dialect","PostgresDialect","pool","Pool","database","SqliteDialect","SQLite","client","ZenStackClient","$pushSchema","plugin","$use","createPolicyTestClient","PolicyPlugin","e","sql","parameters","testName","currentTestName","digest","createHash","update","toLowerCase","substring","slice","import_orm","import_vitest","isPromise","value","then","catch","expectErrorReason","err","errorReason","ORMError","reason","message","pass","expectErrorMessages","expectedMessages","m","toLowerCase","includes","undefined","expect","extend","toResolveTruthy","received","r","toResolveFalsy","toResolveNull","toResolveWithLength","length","Array","isArray","toBeRejectedNotFound","ORMErrorReason","NOT_FOUND","toBeRejectedByPolicy","REJECTED_BY_POLICY","toBeRejectedByValidation","INVALID_INPUT"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -6,14 +6,49 @@ import { SchemaDef as SchemaDef$1 } from '@zenstackhq/schema';
|
|
|
6
6
|
|
|
7
7
|
declare function getTestDbProvider(): "sqlite" | "postgresql";
|
|
8
8
|
type CreateTestClientOptions<Schema extends SchemaDef> = Omit<ClientOptions<Schema>, 'dialect'> & {
|
|
9
|
+
/**
|
|
10
|
+
* Database provider
|
|
11
|
+
*/
|
|
9
12
|
provider?: 'sqlite' | 'postgresql';
|
|
13
|
+
/**
|
|
14
|
+
* The main ZModel file. Only used when `usePrismaPush` is true and `schema` is an object.
|
|
15
|
+
*/
|
|
10
16
|
schemaFile?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Database name. If not provided, a name will be generated based on the test name.
|
|
19
|
+
*/
|
|
11
20
|
dbName?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Use `prisma db push` instead of ZenStack's `$pushSchema` for database initialization.
|
|
23
|
+
*/
|
|
12
24
|
usePrismaPush?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Extra source files to create and compile.
|
|
27
|
+
*/
|
|
13
28
|
extraSourceFiles?: Record<string, string>;
|
|
29
|
+
/**
|
|
30
|
+
* Working directory for the test client. If not provided, a temporary directory will be created.
|
|
31
|
+
*/
|
|
14
32
|
workDir?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Debug mode.
|
|
35
|
+
*/
|
|
15
36
|
debug?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* A sqlite database file to be used for the test. Only supported for sqlite provider.
|
|
39
|
+
*/
|
|
16
40
|
dbFile?: string;
|
|
41
|
+
/**
|
|
42
|
+
* PostgreSQL extensions to be added to the datasource. Only supported for postgresql provider.
|
|
43
|
+
*/
|
|
44
|
+
dataSourceExtensions?: string[];
|
|
45
|
+
/**
|
|
46
|
+
* Additional files to be copied to the working directory. The glob pattern is relative to the test file.
|
|
47
|
+
*/
|
|
48
|
+
copyFiles?: {
|
|
49
|
+
globPattern: string;
|
|
50
|
+
destination: string;
|
|
51
|
+
}[];
|
|
17
52
|
};
|
|
18
53
|
declare function createTestClient<Schema extends SchemaDef>(schema: Schema, options?: CreateTestClientOptions<Schema>): Promise<ClientContract<Schema>>;
|
|
19
54
|
declare function createTestClient<Schema extends SchemaDef>(schema: string, options?: CreateTestClientOptions<Schema>): Promise<any>;
|
package/dist/index.d.ts
CHANGED
|
@@ -6,14 +6,49 @@ import { SchemaDef as SchemaDef$1 } from '@zenstackhq/schema';
|
|
|
6
6
|
|
|
7
7
|
declare function getTestDbProvider(): "sqlite" | "postgresql";
|
|
8
8
|
type CreateTestClientOptions<Schema extends SchemaDef> = Omit<ClientOptions<Schema>, 'dialect'> & {
|
|
9
|
+
/**
|
|
10
|
+
* Database provider
|
|
11
|
+
*/
|
|
9
12
|
provider?: 'sqlite' | 'postgresql';
|
|
13
|
+
/**
|
|
14
|
+
* The main ZModel file. Only used when `usePrismaPush` is true and `schema` is an object.
|
|
15
|
+
*/
|
|
10
16
|
schemaFile?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Database name. If not provided, a name will be generated based on the test name.
|
|
19
|
+
*/
|
|
11
20
|
dbName?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Use `prisma db push` instead of ZenStack's `$pushSchema` for database initialization.
|
|
23
|
+
*/
|
|
12
24
|
usePrismaPush?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Extra source files to create and compile.
|
|
27
|
+
*/
|
|
13
28
|
extraSourceFiles?: Record<string, string>;
|
|
29
|
+
/**
|
|
30
|
+
* Working directory for the test client. If not provided, a temporary directory will be created.
|
|
31
|
+
*/
|
|
14
32
|
workDir?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Debug mode.
|
|
35
|
+
*/
|
|
15
36
|
debug?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* A sqlite database file to be used for the test. Only supported for sqlite provider.
|
|
39
|
+
*/
|
|
16
40
|
dbFile?: string;
|
|
41
|
+
/**
|
|
42
|
+
* PostgreSQL extensions to be added to the datasource. Only supported for postgresql provider.
|
|
43
|
+
*/
|
|
44
|
+
dataSourceExtensions?: string[];
|
|
45
|
+
/**
|
|
46
|
+
* Additional files to be copied to the working directory. The glob pattern is relative to the test file.
|
|
47
|
+
*/
|
|
48
|
+
copyFiles?: {
|
|
49
|
+
globPattern: string;
|
|
50
|
+
destination: string;
|
|
51
|
+
}[];
|
|
17
52
|
};
|
|
18
53
|
declare function createTestClient<Schema extends SchemaDef>(schema: Schema, options?: CreateTestClientOptions<Schema>): Promise<ClientContract<Schema>>;
|
|
19
54
|
declare function createTestClient<Schema extends SchemaDef>(schema: string, options?: CreateTestClientOptions<Schema>): Promise<any>;
|
package/dist/index.js
CHANGED
|
@@ -13,6 +13,7 @@ import { ZenStackClient } from "@zenstackhq/orm";
|
|
|
13
13
|
import { PolicyPlugin } from "@zenstackhq/plugin-policy";
|
|
14
14
|
import { PrismaSchemaGenerator } from "@zenstackhq/sdk";
|
|
15
15
|
import SQLite from "better-sqlite3";
|
|
16
|
+
import { glob } from "glob";
|
|
16
17
|
import { PostgresDialect, SqliteDialect } from "kysely";
|
|
17
18
|
import { execSync as execSync2 } from "child_process";
|
|
18
19
|
import { createHash } from "crypto";
|
|
@@ -278,14 +279,20 @@ async function createTestClient(schema, options) {
|
|
|
278
279
|
schemaContent = schemaContent.replace(/datasource\s+db\s*{[^}]*}/m, `datasource db {
|
|
279
280
|
provider = '${provider}'
|
|
280
281
|
url = '${dbUrl}'
|
|
282
|
+
${options.dataSourceExtensions ? `extensions = [${options.dataSourceExtensions.join(", ")}]` : ""}
|
|
281
283
|
}`);
|
|
282
284
|
}
|
|
283
285
|
fs3.writeFileSync(path3.join(workDir, "schema.zmodel"), schemaContent);
|
|
284
286
|
}
|
|
285
287
|
}
|
|
286
288
|
invariant2(workDir);
|
|
289
|
+
const { plugins, ...rest } = options ?? {};
|
|
290
|
+
const _options = {
|
|
291
|
+
...rest
|
|
292
|
+
};
|
|
287
293
|
if (options?.debug) {
|
|
288
294
|
console.log(`Work directory: ${workDir}`);
|
|
295
|
+
_options.log = testLogger;
|
|
289
296
|
}
|
|
290
297
|
if (options?.dbFile) {
|
|
291
298
|
if (provider !== "sqlite") {
|
|
@@ -293,10 +300,26 @@ async function createTestClient(schema, options) {
|
|
|
293
300
|
}
|
|
294
301
|
fs3.copyFileSync(options.dbFile, path3.join(workDir, dbName));
|
|
295
302
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
303
|
+
if (options?.copyFiles) {
|
|
304
|
+
const state = expect2.getState();
|
|
305
|
+
const currentTestPath = state.testPath;
|
|
306
|
+
if (!currentTestPath) {
|
|
307
|
+
throw new Error("Unable to determine current test file path");
|
|
308
|
+
}
|
|
309
|
+
for (const { globPattern, destination } of options.copyFiles) {
|
|
310
|
+
const files = glob.sync(globPattern, {
|
|
311
|
+
cwd: path3.dirname(currentTestPath)
|
|
312
|
+
});
|
|
313
|
+
for (const file of files) {
|
|
314
|
+
const src = path3.resolve(path3.dirname(currentTestPath), file);
|
|
315
|
+
const dest = path3.resolve(workDir, destination, path3.basename(file));
|
|
316
|
+
fs3.mkdirSync(path3.dirname(dest), {
|
|
317
|
+
recursive: true
|
|
318
|
+
});
|
|
319
|
+
fs3.copyFileSync(src, dest);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
300
323
|
if (!options?.dbFile) {
|
|
301
324
|
if (options?.usePrismaPush) {
|
|
302
325
|
invariant2(typeof schema === "string" || options?.schemaFile, "a schema file must be provided when using prisma db push");
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client.ts","../src/project.ts","../src/schema.ts","../src/utils.ts","../src/vitest-ext.ts"],"sourcesContent":["import { invariant } from '@zenstackhq/common-helpers';\nimport type { Model } from '@zenstackhq/language/ast';\nimport { ZenStackClient, type ClientContract, type ClientOptions } from '@zenstackhq/orm';\nimport type { SchemaDef } from '@zenstackhq/orm/schema';\nimport { PolicyPlugin } from '@zenstackhq/plugin-policy';\nimport { PrismaSchemaGenerator } from '@zenstackhq/sdk';\nimport SQLite from 'better-sqlite3';\nimport { PostgresDialect, SqliteDialect, type LogEvent } from 'kysely';\nimport { execSync } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { Client as PGClient, Pool } from 'pg';\nimport { expect } from 'vitest';\nimport { createTestProject } from './project';\nimport { generateTsSchema } from './schema';\nimport { loadDocumentWithPlugins } from './utils';\n\nexport function getTestDbProvider() {\n const val = process.env['TEST_DB_PROVIDER'] ?? 'sqlite';\n if (!['sqlite', 'postgresql'].includes(val!)) {\n throw new Error(`Invalid TEST_DB_PROVIDER value: ${val}`);\n }\n return val as 'sqlite' | 'postgresql';\n}\n\nconst TEST_PG_CONFIG = {\n host: process.env['TEST_PG_HOST'] ?? 'localhost',\n port: process.env['TEST_PG_PORT'] ? parseInt(process.env['TEST_PG_PORT']) : 5432,\n user: process.env['TEST_PG_USER'] ?? 'postgres',\n password: process.env['TEST_PG_PASSWORD'] ?? 'postgres',\n};\n\nexport type CreateTestClientOptions<Schema extends SchemaDef> = Omit<ClientOptions<Schema>, 'dialect'> & {\n provider?: 'sqlite' | 'postgresql';\n schemaFile?: string;\n dbName?: string;\n usePrismaPush?: boolean;\n extraSourceFiles?: Record<string, string>;\n workDir?: string;\n debug?: boolean;\n dbFile?: string;\n};\n\nexport async function createTestClient<Schema extends SchemaDef>(\n schema: Schema,\n options?: CreateTestClientOptions<Schema>,\n): Promise<ClientContract<Schema>>;\nexport async function createTestClient<Schema extends SchemaDef>(\n schema: string,\n options?: CreateTestClientOptions<Schema>,\n): Promise<any>;\nexport async function createTestClient<Schema extends SchemaDef>(\n schema: Schema | string,\n options?: CreateTestClientOptions<Schema>,\n): Promise<any> {\n let workDir = options?.workDir;\n let _schema: Schema;\n const provider = options?.provider ?? getTestDbProvider() ?? 'sqlite';\n const dbName = options?.dbName ?? getTestDbName(provider);\n const dbUrl =\n provider === 'sqlite'\n ? `file:${dbName}`\n : `postgres://${TEST_PG_CONFIG.user}:${TEST_PG_CONFIG.password}@${TEST_PG_CONFIG.host}:${TEST_PG_CONFIG.port}/${dbName}`;\n\n let model: Model | undefined;\n\n if (typeof schema === 'string') {\n const generated = await generateTsSchema(schema, provider, dbUrl, options?.extraSourceFiles, undefined);\n workDir = generated.workDir;\n model = generated.model;\n // replace schema's provider\n _schema = {\n ...generated.schema,\n provider: {\n ...generated.schema.provider,\n type: provider,\n },\n } as Schema;\n } else {\n // replace schema's provider\n _schema = {\n ...schema,\n provider: {\n type: provider,\n },\n };\n workDir ??= createTestProject();\n if (options?.schemaFile) {\n let schemaContent = fs.readFileSync(options.schemaFile, 'utf-8');\n if (dbUrl) {\n // replace `datasource db { }` section\n schemaContent = schemaContent.replace(\n /datasource\\s+db\\s*{[^}]*}/m,\n `datasource db {\n provider = '${provider}'\n url = '${dbUrl}'\n}`,\n );\n }\n fs.writeFileSync(path.join(workDir, 'schema.zmodel'), schemaContent);\n }\n }\n\n invariant(workDir);\n if (options?.debug) {\n console.log(`Work directory: ${workDir}`);\n }\n\n // copy db file to workDir if specified\n if (options?.dbFile) {\n if (provider !== 'sqlite') {\n throw new Error('dbFile option is only supported for sqlite provider');\n }\n fs.copyFileSync(options.dbFile, path.join(workDir, dbName));\n }\n\n const { plugins, ...rest } = options ?? {};\n const _options: ClientOptions<Schema> = {\n ...rest,\n } as ClientOptions<Schema>;\n\n if (!options?.dbFile) {\n if (options?.usePrismaPush) {\n invariant(\n typeof schema === 'string' || options?.schemaFile,\n 'a schema file must be provided when using prisma db push',\n );\n if (!model) {\n const r = await loadDocumentWithPlugins(path.join(workDir, 'schema.zmodel'));\n if (!r.success) {\n throw new Error(r.errors.join('\\n'));\n }\n model = r.model;\n }\n const prismaSchema = new PrismaSchemaGenerator(model);\n const prismaSchemaText = await prismaSchema.generate();\n fs.writeFileSync(path.resolve(workDir!, 'schema.prisma'), prismaSchemaText);\n execSync('npx prisma db push --schema ./schema.prisma --skip-generate --force-reset', {\n cwd: workDir,\n stdio: 'ignore',\n });\n } else {\n if (provider === 'postgresql') {\n invariant(dbName, 'dbName is required');\n const pgClient = new PGClient(TEST_PG_CONFIG);\n await pgClient.connect();\n await pgClient.query(`DROP DATABASE IF EXISTS \"${dbName}\"`);\n await pgClient.query(`CREATE DATABASE \"${dbName}\"`);\n await pgClient.end();\n }\n }\n }\n\n if (provider === 'postgresql') {\n _options.dialect = new PostgresDialect({\n pool: new Pool({\n ...TEST_PG_CONFIG,\n database: dbName,\n }),\n });\n } else {\n _options.dialect = new SqliteDialect({\n database: new SQLite(path.join(workDir!, dbName)),\n });\n }\n\n let client = new ZenStackClient(_schema, _options);\n\n if (!options?.usePrismaPush && !options?.dbFile) {\n await client.$pushSchema();\n }\n\n if (plugins) {\n for (const plugin of plugins) {\n client = client.$use(plugin);\n }\n }\n\n return client;\n}\n\nexport async function createPolicyTestClient<Schema extends SchemaDef>(\n schema: Schema,\n options?: CreateTestClientOptions<Schema>,\n): Promise<ClientContract<Schema>>;\nexport async function createPolicyTestClient<Schema extends SchemaDef>(\n schema: string,\n options?: CreateTestClientOptions<Schema>,\n): Promise<any>;\nexport async function createPolicyTestClient<Schema extends SchemaDef>(\n schema: Schema | string,\n options?: CreateTestClientOptions<Schema>,\n): Promise<any> {\n return createTestClient(\n schema as any,\n {\n ...options,\n plugins: [...(options?.plugins ?? []), new PolicyPlugin()],\n } as any,\n );\n}\n\nexport function testLogger(e: LogEvent) {\n console.log(e.query.sql, e.query.parameters);\n}\n\nfunction getTestDbName(provider: string) {\n if (provider === 'sqlite') {\n return './test.db';\n }\n const testName = expect.getState().currentTestName ?? 'unnamed';\n const testPath = expect.getState().testPath ?? '';\n // digest test name\n const digest = createHash('md5')\n .update(testName + testPath)\n .digest('hex');\n // compute a database name based on test name\n return (\n 'test_' +\n testName\n .toLowerCase()\n .replace(/[^a-z0-9_]/g, '_')\n .replace(/_+/g, '_')\n .substring(0, 30) +\n digest.slice(0, 6)\n );\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport tmp from 'tmp';\n\nexport function createTestProject(zmodelContent?: string) {\n const { name: workDir } = tmp.dirSync({ unsafeCleanup: true });\n\n fs.mkdirSync(path.join(workDir, 'node_modules'));\n\n // symlink all entries from \"node_modules\"\n const nodeModules = fs.readdirSync(path.join(__dirname, '../node_modules'));\n for (const entry of nodeModules) {\n if (entry.startsWith('@zenstackhq')) {\n continue;\n }\n fs.symlinkSync(\n path.join(__dirname, '../node_modules', entry),\n path.join(workDir, 'node_modules', entry),\n 'dir',\n );\n }\n\n // in addition, symlink zenstack packages\n const zenstackPackages = ['language', 'sdk', 'orm', 'cli'];\n fs.mkdirSync(path.join(workDir, 'node_modules/@zenstackhq'));\n for (const pkg of zenstackPackages) {\n fs.symlinkSync(\n path.join(__dirname, `../../${pkg}`),\n path.join(workDir, `node_modules/@zenstackhq/${pkg}`),\n 'dir',\n );\n }\n\n fs.writeFileSync(\n path.join(workDir, 'package.json'),\n JSON.stringify(\n {\n name: 'test',\n version: '1.0.0',\n type: 'module',\n },\n null,\n 4,\n ),\n );\n\n fs.writeFileSync(\n path.join(workDir, 'tsconfig.json'),\n JSON.stringify(\n {\n compilerOptions: {\n module: 'ESNext',\n target: 'ESNext',\n moduleResolution: 'Bundler',\n esModuleInterop: true,\n skipLibCheck: true,\n strict: true,\n },\n include: ['**/*.ts'],\n },\n null,\n 4,\n ),\n );\n\n if (zmodelContent) {\n fs.writeFileSync(path.join(workDir, 'schema.zmodel'), zmodelContent);\n }\n\n return workDir;\n}\n","import { invariant } from '@zenstackhq/common-helpers';\nimport type { SchemaDef } from '@zenstackhq/schema';\nimport { TsSchemaGenerator } from '@zenstackhq/sdk';\nimport { execSync } from 'node:child_process';\nimport crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { match } from 'ts-pattern';\nimport { expect } from 'vitest';\nimport { createTestProject } from './project';\nimport { loadDocumentWithPlugins } from './utils';\n\nfunction makePrelude(provider: 'sqlite' | 'postgresql', dbUrl?: string) {\n return match(provider)\n .with('sqlite', () => {\n return `\ndatasource db {\n provider = 'sqlite'\n url = '${dbUrl ?? 'file:./test.db'}'\n}\n`;\n })\n .with('postgresql', () => {\n return `\ndatasource db {\n provider = 'postgresql'\n url = '${dbUrl ?? 'postgres://postgres:postgres@localhost:5432/db'}'\n}\n`;\n })\n .exhaustive();\n}\n\nfunction replacePlaceholders(schemaText: string, provider: 'sqlite' | 'postgresql', dbUrl: string | undefined) {\n const url = dbUrl ?? (provider === 'sqlite' ? 'file:./test.db' : 'postgres://postgres:postgres@localhost:5432/db');\n return schemaText.replace(/\\$DB_URL/g, url).replace(/\\$PROVIDER/g, provider);\n}\n\nexport async function generateTsSchema(\n schemaText: string,\n provider: 'sqlite' | 'postgresql' = 'sqlite',\n dbUrl?: string,\n extraSourceFiles?: Record<string, string>,\n withLiteSchema?: boolean,\n) {\n const workDir = createTestProject();\n\n const zmodelPath = path.join(workDir, 'schema.zmodel');\n const noPrelude = schemaText.includes('datasource ');\n fs.writeFileSync(\n zmodelPath,\n `${noPrelude ? '' : makePrelude(provider, dbUrl)}\\n\\n${replacePlaceholders(schemaText, provider, dbUrl)}`,\n );\n\n const result = await loadDocumentWithPlugins(zmodelPath);\n if (!result.success) {\n throw new Error(`Failed to load schema from ${zmodelPath}: ${result.errors}`);\n }\n\n const generator = new TsSchemaGenerator();\n await generator.generate(result.model, { outDir: workDir, lite: withLiteSchema });\n\n if (extraSourceFiles) {\n for (const [fileName, content] of Object.entries(extraSourceFiles)) {\n const filePath = path.resolve(workDir, !fileName.endsWith('.ts') ? `${fileName}.ts` : fileName);\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n fs.writeFileSync(filePath, content);\n }\n }\n\n // compile the generated TS schema\n return { ...(await compileAndLoad(workDir)), model: result.model };\n}\n\nasync function compileAndLoad(workDir: string) {\n execSync('npx tsc', {\n cwd: workDir,\n stdio: 'inherit',\n });\n\n // load the schema module\n const module = await import(path.join(workDir, 'schema.js'));\n\n let moduleLite: any;\n try {\n moduleLite = await import(path.join(workDir, 'schema-lite.js'));\n } catch {\n // ignore\n }\n return { workDir, schema: module.schema as SchemaDef, schemaLite: moduleLite?.schema as SchemaDef | undefined };\n}\n\nexport function generateTsSchemaFromFile(filePath: string) {\n const schemaText = fs.readFileSync(filePath, 'utf8');\n return generateTsSchema(schemaText);\n}\n\nexport async function generateTsSchemaInPlace(schemaPath: string) {\n const workDir = path.dirname(schemaPath);\n const result = await loadDocumentWithPlugins(schemaPath);\n if (!result.success) {\n throw new Error(`Failed to load schema from ${schemaPath}: ${result.errors}`);\n }\n const generator = new TsSchemaGenerator();\n await generator.generate(result.model, { outDir: workDir });\n return compileAndLoad(workDir);\n}\n\nexport async function loadSchema(schema: string, additionalSchemas?: Record<string, string>) {\n if (!schema.includes('datasource ')) {\n schema = `${makePrelude('sqlite')}\\n\\n${schema}`;\n }\n\n // create a temp folder\n const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zenstack-schema'));\n\n // create a temp file\n const tempFile = path.join(tempDir, `schema.zmodel`);\n fs.writeFileSync(tempFile, schema);\n\n if (additionalSchemas) {\n for (const [fileName, content] of Object.entries(additionalSchemas)) {\n let name = fileName;\n if (!name.endsWith('.zmodel')) {\n name += '.zmodel';\n }\n const filePath = path.join(tempDir, name);\n fs.writeFileSync(filePath, content);\n }\n }\n\n const r = await loadDocumentWithPlugins(tempFile);\n expect(r).toSatisfy(\n (r) => r.success,\n `Failed to load schema: ${(r as any).errors?.map((e: any) => e.toString()).join(', ')}`,\n );\n invariant(r.success);\n return r.model;\n}\n\nexport async function loadSchemaWithError(schema: string, error: string | RegExp) {\n if (!schema.includes('datasource ')) {\n schema = `${makePrelude('sqlite')}\\n\\n${schema}`;\n }\n\n // create a temp file\n const tempFile = path.join(os.tmpdir(), `zenstack-schema-${crypto.randomUUID()}.zmodel`);\n fs.writeFileSync(tempFile, schema);\n const r = await loadDocumentWithPlugins(tempFile);\n expect(r.success).toBe(false);\n invariant(!r.success);\n if (typeof error === 'string') {\n expect(r).toSatisfy(\n (r) => r.errors.some((e: any) => e.toString().toLowerCase().includes(error.toLowerCase())),\n `Expected error message to include \"${error}\" but got: ${r.errors.map((e: any) => e.toString()).join(', ')}`,\n );\n } else {\n expect(r).toSatisfy(\n (r) => r.errors.some((e: any) => error.test(e)),\n `Expected error message to match \"${error}\" but got: ${r.errors.map((e: any) => e.toString()).join(', ')}`,\n );\n }\n}\n","import { loadDocument } from '@zenstackhq/language';\n\nexport function loadDocumentWithPlugins(filePath: string) {\n const pluginModelFiles = [require.resolve('@zenstackhq/plugin-policy/plugin.zmodel')];\n return loadDocument(filePath, pluginModelFiles);\n}\n","import { ORMError, ORMErrorReason } from '@zenstackhq/orm';\nimport { expect } from 'vitest';\n\nfunction isPromise(value: any) {\n return typeof value.then === 'function' && typeof value.catch === 'function';\n}\n\nfunction expectErrorReason(err: any, errorReason: ORMErrorReason) {\n if (err instanceof ORMError && err.reason === errorReason) {\n return {\n message: () => '',\n pass: true,\n };\n } else {\n return {\n message: () => `expected ORMError of reason ${errorReason}, got ${err}`,\n pass: false,\n };\n }\n}\n\nfunction expectErrorMessages(expectedMessages: string[], message: string) {\n for (const m of expectedMessages) {\n if (!message.toLowerCase().includes(m.toLowerCase())) {\n return {\n message: () => `expected message not found in error: ${m}, got message: ${message}`,\n pass: false,\n };\n }\n }\n return undefined;\n}\n\nexpect.extend({\n async toResolveTruthy(received: Promise<unknown>) {\n if (!isPromise(received)) {\n return { message: () => 'a promise is expected', pass: false };\n }\n const r = await received;\n return {\n pass: !!r,\n message: () => `Expected promise to resolve to a truthy value, but got ${r}`,\n };\n },\n\n async toResolveFalsy(received: Promise<unknown>) {\n if (!isPromise(received)) {\n return { message: () => 'a promise is expected', pass: false };\n }\n const r = await received;\n return {\n pass: !r,\n message: () => `Expected promise to resolve to a falsy value, but got ${r}`,\n };\n },\n\n async toResolveNull(received: Promise<unknown>) {\n if (!isPromise(received)) {\n return { message: () => 'a promise is expected', pass: false };\n }\n const r = await received;\n return {\n pass: r === null,\n message: () => `Expected promise to resolve to a null value, but got ${r}`,\n };\n },\n\n async toResolveWithLength(received: Promise<unknown>, length: number) {\n const r = await received;\n return {\n pass: Array.isArray(r) && r.length === length,\n message: () => `Expected promise to resolve with an array with length ${length}, but got ${r}`,\n };\n },\n\n async toBeRejectedNotFound(received: Promise<unknown>) {\n if (!isPromise(received)) {\n return { message: () => 'a promise is expected', pass: false };\n }\n try {\n await received;\n } catch (err) {\n return expectErrorReason(err, ORMErrorReason.NOT_FOUND);\n }\n return {\n message: () => `expected NotFoundError, got no error`,\n pass: false,\n };\n },\n\n async toBeRejectedByPolicy(received: Promise<unknown>, expectedMessages?: string[]) {\n if (!isPromise(received)) {\n return { message: () => 'a promise is expected', pass: false };\n }\n try {\n await received;\n } catch (err) {\n if (expectedMessages && err instanceof ORMError && err.reason === ORMErrorReason.REJECTED_BY_POLICY) {\n const r = expectErrorMessages(expectedMessages, err.message || '');\n if (r) {\n return r;\n }\n }\n return expectErrorReason(err, ORMErrorReason.REJECTED_BY_POLICY);\n }\n return {\n message: () => `expected PolicyError, got no error`,\n pass: false,\n };\n },\n\n async toBeRejectedByValidation(received: Promise<unknown>, expectedMessages?: string[]) {\n if (!isPromise(received)) {\n return { message: () => 'a promise is expected', pass: false };\n }\n try {\n await received;\n } catch (err) {\n if (expectedMessages && err instanceof ORMError && err.reason === ORMErrorReason.INVALID_INPUT) {\n const r = expectErrorMessages(expectedMessages, err.message || '');\n if (r) {\n return r;\n }\n }\n return expectErrorReason(err, ORMErrorReason.INVALID_INPUT);\n }\n return {\n message: () => `expected InputValidationError, got no error`,\n pass: false,\n };\n },\n});\n"],"mappings":";;;;;;;;;;AAAA,SAASA,aAAAA,kBAAiB;AAE1B,SAASC,sBAA+D;AAExE,SAASC,oBAAoB;AAC7B,SAASC,6BAA6B;AACtC,OAAOC,YAAY;AACnB,SAASC,iBAAiBC,qBAAoC;AAC9D,SAASC,YAAAA,iBAAgB;AACzB,SAASC,kBAAkB;AAC3B,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,SAASC,UAAUC,UAAUC,YAAY;AACzC,SAASC,UAAAA,eAAc;;;ACbvB,OAAOC,QAAQ;AACf,OAAOC,UAAU;AACjB,OAAOC,SAAS;AAET,SAASC,kBAAkBC,eAAsB;AACpD,QAAM,EAAEC,MAAMC,QAAO,IAAKC,IAAIC,QAAQ;IAAEC,eAAe;EAAK,CAAA;AAE5DC,KAAGC,UAAUC,KAAKC,KAAKP,SAAS,cAAA,CAAA;AAGhC,QAAMQ,cAAcJ,GAAGK,YAAYH,KAAKC,KAAKG,WAAW,iBAAA,CAAA;AACxD,aAAWC,SAASH,aAAa;AAC7B,QAAIG,MAAMC,WAAW,aAAA,GAAgB;AACjC;IACJ;AACAR,OAAGS,YACCP,KAAKC,KAAKG,WAAW,mBAAmBC,KAAAA,GACxCL,KAAKC,KAAKP,SAAS,gBAAgBW,KAAAA,GACnC,KAAA;EAER;AAGA,QAAMG,mBAAmB;IAAC;IAAY;IAAO;IAAO;;AACpDV,KAAGC,UAAUC,KAAKC,KAAKP,SAAS,0BAAA,CAAA;AAChC,aAAWe,OAAOD,kBAAkB;AAChCV,OAAGS,YACCP,KAAKC,KAAKG,WAAW,SAASK,GAAAA,EAAK,GACnCT,KAAKC,KAAKP,SAAS,4BAA4Be,GAAAA,EAAK,GACpD,KAAA;EAER;AAEAX,KAAGY,cACCV,KAAKC,KAAKP,SAAS,cAAA,GACnBiB,KAAKC,UACD;IACInB,MAAM;IACNoB,SAAS;IACTC,MAAM;EACV,GACA,MACA,CAAA,CAAA;AAIRhB,KAAGY,cACCV,KAAKC,KAAKP,SAAS,eAAA,GACnBiB,KAAKC,UACD;IACIG,iBAAiB;MACbC,QAAQ;MACRC,QAAQ;MACRC,kBAAkB;MAClBC,iBAAiB;MACjBC,cAAc;MACdC,QAAQ;IACZ;IACAC,SAAS;MAAC;;EACd,GACA,MACA,CAAA,CAAA;AAIR,MAAI9B,eAAe;AACfM,OAAGY,cAAcV,KAAKC,KAAKP,SAAS,eAAA,GAAkBF,aAAAA;EAC1D;AAEA,SAAOE;AACX;AAlEgBH;;;ACJhB,SAASgC,iBAAiB;AAE1B,SAASC,yBAAyB;AAClC,SAASC,gBAAgB;AACzB,OAAOC,YAAY;AACnB,OAAOC,SAAQ;AACf,OAAOC,QAAQ;AACf,OAAOC,WAAU;AACjB,SAASC,aAAa;AACtB,SAASC,cAAc;;;ACTvB,SAASC,oBAAoB;AAEtB,SAASC,wBAAwBC,UAAgB;AACpD,QAAMC,mBAAmB;IAACC,UAAQC,QAAQ,yCAAA;;AAC1C,SAAOC,aAAaJ,UAAUC,gBAAAA;AAClC;AAHgBF;;;ADWhB,SAASM,YAAYC,UAAmCC,OAAc;AAClE,SAAOC,MAAMF,QAAAA,EACRG,KAAK,UAAU,MAAA;AACZ,WAAO;;;aAGNF,SAAS,gBAAA;;;EAGd,CAAA,EACCE,KAAK,cAAc,MAAA;AAChB,WAAO;;;aAGNF,SAAS,gDAAA;;;EAGd,CAAA,EACCG,WAAU;AACnB;AAnBSL;AAqBT,SAASM,oBAAoBC,YAAoBN,UAAmCC,OAAyB;AACzG,QAAMM,MAAMN,UAAUD,aAAa,WAAW,mBAAmB;AACjE,SAAOM,WAAWE,QAAQ,aAAaD,GAAAA,EAAKC,QAAQ,eAAeR,QAAAA;AACvE;AAHSK;AAKT,eAAsBI,iBAClBH,YACAN,WAAoC,UACpCC,OACAS,kBACAC,gBAAwB;AAExB,QAAMC,UAAUC,kBAAAA;AAEhB,QAAMC,aAAaC,MAAKC,KAAKJ,SAAS,eAAA;AACtC,QAAMK,YAAYX,WAAWY,SAAS,aAAA;AACtCC,EAAAA,IAAGC,cACCN,YACA,GAAGG,YAAY,KAAKlB,YAAYC,UAAUC,KAAAA,CAAAA;;EAAaI,oBAAoBC,YAAYN,UAAUC,KAAAA,CAAAA,EAAQ;AAG7G,QAAMoB,SAAS,MAAMC,wBAAwBR,UAAAA;AAC7C,MAAI,CAACO,OAAOE,SAAS;AACjB,UAAM,IAAIC,MAAM,8BAA8BV,UAAAA,KAAeO,OAAOI,MAAM,EAAE;EAChF;AAEA,QAAMC,YAAY,IAAIC,kBAAAA;AACtB,QAAMD,UAAUE,SAASP,OAAOQ,OAAO;IAAEC,QAAQlB;IAASmB,MAAMpB;EAAe,CAAA;AAE/E,MAAID,kBAAkB;AAClB,eAAW,CAACsB,UAAUC,OAAAA,KAAYC,OAAOC,QAAQzB,gBAAAA,GAAmB;AAChE,YAAM0B,WAAWrB,MAAKsB,QAAQzB,SAAS,CAACoB,SAASM,SAAS,KAAA,IAAS,GAAGN,QAAAA,QAAgBA,QAAAA;AACtFb,MAAAA,IAAGoB,UAAUxB,MAAKyB,QAAQJ,QAAAA,GAAW;QAAEK,WAAW;MAAK,CAAA;AACvDtB,MAAAA,IAAGC,cAAcgB,UAAUH,OAAAA;IAC/B;EACJ;AAGA,SAAO;IAAE,GAAI,MAAMS,eAAe9B,OAAAA;IAAWiB,OAAOR,OAAOQ;EAAM;AACrE;AAlCsBpB;AAoCtB,eAAeiC,eAAe9B,SAAe;AACzC+B,WAAS,WAAW;IAChBC,KAAKhC;IACLiC,OAAO;EACX,CAAA;AAGA,QAAMC,SAAS,MAAM,OAAO/B,MAAKC,KAAKJ,SAAS,WAAA;AAE/C,MAAImC;AACJ,MAAI;AACAA,iBAAa,MAAM,OAAOhC,MAAKC,KAAKJ,SAAS,gBAAA;EACjD,QAAQ;EAER;AACA,SAAO;IAAEA;IAASoC,QAAQF,OAAOE;IAAqBC,YAAYF,YAAYC;EAAgC;AAClH;AAhBeN;AAkBR,SAASQ,yBAAyBd,UAAgB;AACrD,QAAM9B,aAAaa,IAAGgC,aAAaf,UAAU,MAAA;AAC7C,SAAO3B,iBAAiBH,UAAAA;AAC5B;AAHgB4C;AAKhB,eAAsBE,wBAAwBC,YAAkB;AAC5D,QAAMzC,UAAUG,MAAKyB,QAAQa,UAAAA;AAC7B,QAAMhC,SAAS,MAAMC,wBAAwB+B,UAAAA;AAC7C,MAAI,CAAChC,OAAOE,SAAS;AACjB,UAAM,IAAIC,MAAM,8BAA8B6B,UAAAA,KAAehC,OAAOI,MAAM,EAAE;EAChF;AACA,QAAMC,YAAY,IAAIC,kBAAAA;AACtB,QAAMD,UAAUE,SAASP,OAAOQ,OAAO;IAAEC,QAAQlB;EAAQ,CAAA;AACzD,SAAO8B,eAAe9B,OAAAA;AAC1B;AATsBwC;AAWtB,eAAsBE,WAAWN,QAAgBO,mBAA0C;AACvF,MAAI,CAACP,OAAO9B,SAAS,aAAA,GAAgB;AACjC8B,aAAS,GAAGjD,YAAY,QAAA,CAAA;;EAAgBiD,MAAAA;EAC5C;AAGA,QAAMQ,UAAUrC,IAAGsC,YAAY1C,MAAKC,KAAK0C,GAAGC,OAAM,GAAI,iBAAA,CAAA;AAGtD,QAAMC,WAAW7C,MAAKC,KAAKwC,SAAS,eAAe;AACnDrC,EAAAA,IAAGC,cAAcwC,UAAUZ,MAAAA;AAE3B,MAAIO,mBAAmB;AACnB,eAAW,CAACvB,UAAUC,OAAAA,KAAYC,OAAOC,QAAQoB,iBAAAA,GAAoB;AACjE,UAAIM,OAAO7B;AACX,UAAI,CAAC6B,KAAKvB,SAAS,SAAA,GAAY;AAC3BuB,gBAAQ;MACZ;AACA,YAAMzB,WAAWrB,MAAKC,KAAKwC,SAASK,IAAAA;AACpC1C,MAAAA,IAAGC,cAAcgB,UAAUH,OAAAA;IAC/B;EACJ;AAEA,QAAM6B,IAAI,MAAMxC,wBAAwBsC,QAAAA;AACxCG,SAAOD,CAAAA,EAAGE,UACN,CAACF,OAAMA,GAAEvC,SACT,0BAA2BuC,EAAUrC,QAAQwC,IAAI,CAACC,MAAWA,EAAEC,SAAQ,CAAA,EAAInD,KAAK,IAAA,CAAA,EAAO;AAE3FoD,YAAUN,EAAEvC,OAAO;AACnB,SAAOuC,EAAEjC;AACb;AA9BsByB;AAgCtB,eAAsBe,oBAAoBrB,QAAgBsB,OAAsB;AAC5E,MAAI,CAACtB,OAAO9B,SAAS,aAAA,GAAgB;AACjC8B,aAAS,GAAGjD,YAAY,QAAA,CAAA;;EAAgBiD,MAAAA;EAC5C;AAGA,QAAMY,WAAW7C,MAAKC,KAAK0C,GAAGC,OAAM,GAAI,mBAAmBY,OAAOC,WAAU,CAAA,SAAW;AACvFrD,EAAAA,IAAGC,cAAcwC,UAAUZ,MAAAA;AAC3B,QAAMc,IAAI,MAAMxC,wBAAwBsC,QAAAA;AACxCG,SAAOD,EAAEvC,OAAO,EAAEkD,KAAK,KAAA;AACvBL,YAAU,CAACN,EAAEvC,OAAO;AACpB,MAAI,OAAO+C,UAAU,UAAU;AAC3BP,WAAOD,CAAAA,EAAGE,UACN,CAACF,OAAMA,GAAErC,OAAOiD,KAAK,CAACR,MAAWA,EAAEC,SAAQ,EAAGQ,YAAW,EAAGzD,SAASoD,MAAMK,YAAW,CAAA,CAAA,GACtF,sCAAsCL,KAAAA,cAAmBR,EAAErC,OAAOwC,IAAI,CAACC,MAAWA,EAAEC,SAAQ,CAAA,EAAInD,KAAK,IAAA,CAAA,EAAO;EAEpH,OAAO;AACH+C,WAAOD,CAAAA,EAAGE,UACN,CAACF,OAAMA,GAAErC,OAAOiD,KAAK,CAACR,MAAWI,MAAMM,KAAKV,CAAAA,CAAAA,GAC5C,oCAAoCI,KAAAA,cAAmBR,EAAErC,OAAOwC,IAAI,CAACC,MAAWA,EAAEC,SAAQ,CAAA,EAAInD,KAAK,IAAA,CAAA,EAAO;EAElH;AACJ;AAtBsBqD;;;AF3Hf,SAASQ,oBAAAA;AACZ,QAAMC,MAAMC,QAAQC,IAAI,kBAAA,KAAuB;AAC/C,MAAI,CAAC;IAAC;IAAU;IAAcC,SAASH,GAAAA,GAAO;AAC1C,UAAM,IAAII,MAAM,mCAAmCJ,GAAAA,EAAK;EAC5D;AACA,SAAOA;AACX;AANgBD;AAQhB,IAAMM,iBAAiB;EACnBC,MAAML,QAAQC,IAAI,cAAA,KAAmB;EACrCK,MAAMN,QAAQC,IAAI,cAAA,IAAkBM,SAASP,QAAQC,IAAI,cAAA,CAAe,IAAI;EAC5EO,MAAMR,QAAQC,IAAI,cAAA,KAAmB;EACrCQ,UAAUT,QAAQC,IAAI,kBAAA,KAAuB;AACjD;AAqBA,eAAsBS,iBAClBC,QACAC,SAAyC;AAEzC,MAAIC,UAAUD,SAASC;AACvB,MAAIC;AACJ,QAAMC,WAAWH,SAASG,YAAYjB,kBAAAA,KAAuB;AAC7D,QAAMkB,SAASJ,SAASI,UAAUC,cAAcF,QAAAA;AAChD,QAAMG,QACFH,aAAa,WACP,QAAQC,MAAAA,KACR,cAAcZ,eAAeI,IAAI,IAAIJ,eAAeK,QAAQ,IAAIL,eAAeC,IAAI,IAAID,eAAeE,IAAI,IAAIU,MAAAA;AAExH,MAAIG;AAEJ,MAAI,OAAOR,WAAW,UAAU;AAC5B,UAAMS,YAAY,MAAMC,iBAAiBV,QAAQI,UAAUG,OAAON,SAASU,kBAAkBC,MAAAA;AAC7FV,cAAUO,UAAUP;AACpBM,YAAQC,UAAUD;AAElBL,cAAU;MACN,GAAGM,UAAUT;MACbI,UAAU;QACN,GAAGK,UAAUT,OAAOI;QACpBS,MAAMT;MACV;IACJ;EACJ,OAAO;AAEHD,cAAU;MACN,GAAGH;MACHI,UAAU;QACNS,MAAMT;MACV;IACJ;AACAF,gBAAYY,kBAAAA;AACZ,QAAIb,SAASc,YAAY;AACrB,UAAIC,gBAAgBC,IAAGC,aAAajB,QAAQc,YAAY,OAAA;AACxD,UAAIR,OAAO;AAEPS,wBAAgBA,cAAcG,QAC1B,8BACA;kBACFf,QAAAA;aACLG,KAAAA;EACX;MAEU;AACAU,MAAAA,IAAGG,cAAcC,MAAKC,KAAKpB,SAAS,eAAA,GAAkBc,aAAAA;IAC1D;EACJ;AAEAO,EAAAA,WAAUrB,OAAAA;AACV,MAAID,SAASuB,OAAO;AAChBC,YAAQC,IAAI,mBAAmBxB,OAAAA,EAAS;EAC5C;AAGA,MAAID,SAAS0B,QAAQ;AACjB,QAAIvB,aAAa,UAAU;AACvB,YAAM,IAAIZ,MAAM,qDAAA;IACpB;AACAyB,IAAAA,IAAGW,aAAa3B,QAAQ0B,QAAQN,MAAKC,KAAKpB,SAASG,MAAAA,CAAAA;EACvD;AAEA,QAAM,EAAEwB,SAAS,GAAGC,KAAAA,IAAS7B,WAAW,CAAC;AACzC,QAAM8B,WAAkC;IACpC,GAAGD;EACP;AAEA,MAAI,CAAC7B,SAAS0B,QAAQ;AAClB,QAAI1B,SAAS+B,eAAe;AACxBT,MAAAA,WACI,OAAOvB,WAAW,YAAYC,SAASc,YACvC,0DAAA;AAEJ,UAAI,CAACP,OAAO;AACR,cAAMyB,IAAI,MAAMC,wBAAwBb,MAAKC,KAAKpB,SAAS,eAAA,CAAA;AAC3D,YAAI,CAAC+B,EAAEE,SAAS;AACZ,gBAAM,IAAI3C,MAAMyC,EAAEG,OAAOd,KAAK,IAAA,CAAA;QAClC;AACAd,gBAAQyB,EAAEzB;MACd;AACA,YAAM6B,eAAe,IAAIC,sBAAsB9B,KAAAA;AAC/C,YAAM+B,mBAAmB,MAAMF,aAAaG,SAAQ;AACpDvB,MAAAA,IAAGG,cAAcC,MAAKoB,QAAQvC,SAAU,eAAA,GAAkBqC,gBAAAA;AAC1DG,MAAAA,UAAS,6EAA6E;QAClFC,KAAKzC;QACL0C,OAAO;MACX,CAAA;IACJ,OAAO;AACH,UAAIxC,aAAa,cAAc;AAC3BmB,QAAAA,WAAUlB,QAAQ,oBAAA;AAClB,cAAMwC,WAAW,IAAIC,SAASrD,cAAAA;AAC9B,cAAMoD,SAASE,QAAO;AACtB,cAAMF,SAASG,MAAM,4BAA4B3C,MAAAA,GAAS;AAC1D,cAAMwC,SAASG,MAAM,oBAAoB3C,MAAAA,GAAS;AAClD,cAAMwC,SAASI,IAAG;MACtB;IACJ;EACJ;AAEA,MAAI7C,aAAa,cAAc;AAC3B2B,aAASmB,UAAU,IAAIC,gBAAgB;MACnCC,MAAM,IAAIC,KAAK;QACX,GAAG5D;QACH6D,UAAUjD;MACd,CAAA;IACJ,CAAA;EACJ,OAAO;AACH0B,aAASmB,UAAU,IAAIK,cAAc;MACjCD,UAAU,IAAIE,OAAOnC,MAAKC,KAAKpB,SAAUG,MAAAA,CAAAA;IAC7C,CAAA;EACJ;AAEA,MAAIoD,SAAS,IAAIC,eAAevD,SAAS4B,QAAAA;AAEzC,MAAI,CAAC9B,SAAS+B,iBAAiB,CAAC/B,SAAS0B,QAAQ;AAC7C,UAAM8B,OAAOE,YAAW;EAC5B;AAEA,MAAI9B,SAAS;AACT,eAAW+B,UAAU/B,SAAS;AAC1B4B,eAASA,OAAOI,KAAKD,MAAAA;IACzB;EACJ;AAEA,SAAOH;AACX;AAhIsB1D;AA0ItB,eAAsB+D,uBAClB9D,QACAC,SAAyC;AAEzC,SAAOF,iBACHC,QACA;IACI,GAAGC;IACH4B,SAAS;SAAK5B,SAAS4B,WAAW,CAAA;MAAK,IAAIkC,aAAAA;;EAC/C,CAAA;AAER;AAXsBD;AAaf,SAASE,WAAWC,GAAW;AAClCxC,UAAQC,IAAIuC,EAAEjB,MAAMkB,KAAKD,EAAEjB,MAAMmB,UAAU;AAC/C;AAFgBH;AAIhB,SAAS1D,cAAcF,UAAgB;AACnC,MAAIA,aAAa,UAAU;AACvB,WAAO;EACX;AACA,QAAMgE,WAAWC,QAAOC,SAAQ,EAAGC,mBAAmB;AACtD,QAAMC,WAAWH,QAAOC,SAAQ,EAAGE,YAAY;AAE/C,QAAMC,SAASC,WAAW,KAAA,EACrBC,OAAOP,WAAWI,QAAAA,EAClBC,OAAO,KAAA;AAEZ,SACI,UACAL,SACKQ,YAAW,EACXzD,QAAQ,eAAe,GAAA,EACvBA,QAAQ,OAAO,GAAA,EACf0D,UAAU,GAAG,EAAA,IAClBJ,OAAOK,MAAM,GAAG,CAAA;AAExB;AApBSxE;;;AI/MT,SAASyE,UAAUC,sBAAsB;AACzC,SAASC,UAAAA,eAAc;AAEvB,SAASC,UAAUC,OAAU;AACzB,SAAO,OAAOA,MAAMC,SAAS,cAAc,OAAOD,MAAME,UAAU;AACtE;AAFSH;AAIT,SAASI,kBAAkBC,KAAUC,aAA2B;AAC5D,MAAID,eAAeE,YAAYF,IAAIG,WAAWF,aAAa;AACvD,WAAO;MACHG,SAAS,6BAAM,IAAN;MACTC,MAAM;IACV;EACJ,OAAO;AACH,WAAO;MACHD,SAAS,6BAAM,+BAA+BH,WAAAA,SAAoBD,GAAAA,IAAzD;MACTK,MAAM;IACV;EACJ;AACJ;AAZSN;AAcT,SAASO,oBAAoBC,kBAA4BH,SAAe;AACpE,aAAWI,KAAKD,kBAAkB;AAC9B,QAAI,CAACH,QAAQK,YAAW,EAAGC,SAASF,EAAEC,YAAW,CAAA,GAAK;AAClD,aAAO;QACHL,SAAS,6BAAM,wCAAwCI,CAAAA,kBAAmBJ,OAAAA,IAAjE;QACTC,MAAM;MACV;IACJ;EACJ;AACA,SAAOM;AACX;AAVSL;AAYTM,QAAOC,OAAO;EACV,MAAMC,gBAAgBC,UAA0B;AAC5C,QAAI,CAACpB,UAAUoB,QAAAA,GAAW;AACtB,aAAO;QAAEX,SAAS,6BAAM,yBAAN;QAA+BC,MAAM;MAAM;IACjE;AACA,UAAMW,IAAI,MAAMD;AAChB,WAAO;MACHV,MAAM,CAAC,CAACW;MACRZ,SAAS,6BAAM,0DAA0DY,CAAAA,IAAhE;IACb;EACJ;EAEA,MAAMC,eAAeF,UAA0B;AAC3C,QAAI,CAACpB,UAAUoB,QAAAA,GAAW;AACtB,aAAO;QAAEX,SAAS,6BAAM,yBAAN;QAA+BC,MAAM;MAAM;IACjE;AACA,UAAMW,IAAI,MAAMD;AAChB,WAAO;MACHV,MAAM,CAACW;MACPZ,SAAS,6BAAM,yDAAyDY,CAAAA,IAA/D;IACb;EACJ;EAEA,MAAME,cAAcH,UAA0B;AAC1C,QAAI,CAACpB,UAAUoB,QAAAA,GAAW;AACtB,aAAO;QAAEX,SAAS,6BAAM,yBAAN;QAA+BC,MAAM;MAAM;IACjE;AACA,UAAMW,IAAI,MAAMD;AAChB,WAAO;MACHV,MAAMW,MAAM;MACZZ,SAAS,6BAAM,wDAAwDY,CAAAA,IAA9D;IACb;EACJ;EAEA,MAAMG,oBAAoBJ,UAA4BK,QAAc;AAChE,UAAMJ,IAAI,MAAMD;AAChB,WAAO;MACHV,MAAMgB,MAAMC,QAAQN,CAAAA,KAAMA,EAAEI,WAAWA;MACvChB,SAAS,6BAAM,yDAAyDgB,MAAAA,aAAmBJ,CAAAA,IAAlF;IACb;EACJ;EAEA,MAAMO,qBAAqBR,UAA0B;AACjD,QAAI,CAACpB,UAAUoB,QAAAA,GAAW;AACtB,aAAO;QAAEX,SAAS,6BAAM,yBAAN;QAA+BC,MAAM;MAAM;IACjE;AACA,QAAI;AACA,YAAMU;IACV,SAASf,KAAK;AACV,aAAOD,kBAAkBC,KAAKwB,eAAeC,SAAS;IAC1D;AACA,WAAO;MACHrB,SAAS,6BAAM,wCAAN;MACTC,MAAM;IACV;EACJ;EAEA,MAAMqB,qBAAqBX,UAA4BR,kBAA2B;AAC9E,QAAI,CAACZ,UAAUoB,QAAAA,GAAW;AACtB,aAAO;QAAEX,SAAS,6BAAM,yBAAN;QAA+BC,MAAM;MAAM;IACjE;AACA,QAAI;AACA,YAAMU;IACV,SAASf,KAAK;AACV,UAAIO,oBAAoBP,eAAeE,YAAYF,IAAIG,WAAWqB,eAAeG,oBAAoB;AACjG,cAAMX,IAAIV,oBAAoBC,kBAAkBP,IAAII,WAAW,EAAA;AAC/D,YAAIY,GAAG;AACH,iBAAOA;QACX;MACJ;AACA,aAAOjB,kBAAkBC,KAAKwB,eAAeG,kBAAkB;IACnE;AACA,WAAO;MACHvB,SAAS,6BAAM,sCAAN;MACTC,MAAM;IACV;EACJ;EAEA,MAAMuB,yBAAyBb,UAA4BR,kBAA2B;AAClF,QAAI,CAACZ,UAAUoB,QAAAA,GAAW;AACtB,aAAO;QAAEX,SAAS,6BAAM,yBAAN;QAA+BC,MAAM;MAAM;IACjE;AACA,QAAI;AACA,YAAMU;IACV,SAASf,KAAK;AACV,UAAIO,oBAAoBP,eAAeE,YAAYF,IAAIG,WAAWqB,eAAeK,eAAe;AAC5F,cAAMb,IAAIV,oBAAoBC,kBAAkBP,IAAII,WAAW,EAAA;AAC/D,YAAIY,GAAG;AACH,iBAAOA;QACX;MACJ;AACA,aAAOjB,kBAAkBC,KAAKwB,eAAeK,aAAa;IAC9D;AACA,WAAO;MACHzB,SAAS,6BAAM,+CAAN;MACTC,MAAM;IACV;EACJ;AACJ,CAAA;","names":["invariant","ZenStackClient","PolicyPlugin","PrismaSchemaGenerator","SQLite","PostgresDialect","SqliteDialect","execSync","createHash","fs","path","Client","PGClient","Pool","expect","fs","path","tmp","createTestProject","zmodelContent","name","workDir","tmp","dirSync","unsafeCleanup","fs","mkdirSync","path","join","nodeModules","readdirSync","__dirname","entry","startsWith","symlinkSync","zenstackPackages","pkg","writeFileSync","JSON","stringify","version","type","compilerOptions","module","target","moduleResolution","esModuleInterop","skipLibCheck","strict","include","invariant","TsSchemaGenerator","execSync","crypto","fs","os","path","match","expect","loadDocument","loadDocumentWithPlugins","filePath","pluginModelFiles","require","resolve","loadDocument","makePrelude","provider","dbUrl","match","with","exhaustive","replacePlaceholders","schemaText","url","replace","generateTsSchema","extraSourceFiles","withLiteSchema","workDir","createTestProject","zmodelPath","path","join","noPrelude","includes","fs","writeFileSync","result","loadDocumentWithPlugins","success","Error","errors","generator","TsSchemaGenerator","generate","model","outDir","lite","fileName","content","Object","entries","filePath","resolve","endsWith","mkdirSync","dirname","recursive","compileAndLoad","execSync","cwd","stdio","module","moduleLite","schema","schemaLite","generateTsSchemaFromFile","readFileSync","generateTsSchemaInPlace","schemaPath","loadSchema","additionalSchemas","tempDir","mkdtempSync","os","tmpdir","tempFile","name","r","expect","toSatisfy","map","e","toString","invariant","loadSchemaWithError","error","crypto","randomUUID","toBe","some","toLowerCase","test","getTestDbProvider","val","process","env","includes","Error","TEST_PG_CONFIG","host","port","parseInt","user","password","createTestClient","schema","options","workDir","_schema","provider","dbName","getTestDbName","dbUrl","model","generated","generateTsSchema","extraSourceFiles","undefined","type","createTestProject","schemaFile","schemaContent","fs","readFileSync","replace","writeFileSync","path","join","invariant","debug","console","log","dbFile","copyFileSync","plugins","rest","_options","usePrismaPush","r","loadDocumentWithPlugins","success","errors","prismaSchema","PrismaSchemaGenerator","prismaSchemaText","generate","resolve","execSync","cwd","stdio","pgClient","PGClient","connect","query","end","dialect","PostgresDialect","pool","Pool","database","SqliteDialect","SQLite","client","ZenStackClient","$pushSchema","plugin","$use","createPolicyTestClient","PolicyPlugin","testLogger","e","sql","parameters","testName","expect","getState","currentTestName","testPath","digest","createHash","update","toLowerCase","substring","slice","ORMError","ORMErrorReason","expect","isPromise","value","then","catch","expectErrorReason","err","errorReason","ORMError","reason","message","pass","expectErrorMessages","expectedMessages","m","toLowerCase","includes","undefined","expect","extend","toResolveTruthy","received","r","toResolveFalsy","toResolveNull","toResolveWithLength","length","Array","isArray","toBeRejectedNotFound","ORMErrorReason","NOT_FOUND","toBeRejectedByPolicy","REJECTED_BY_POLICY","toBeRejectedByValidation","INVALID_INPUT"]}
|
|
1
|
+
{"version":3,"sources":["../src/client.ts","../src/project.ts","../src/schema.ts","../src/utils.ts","../src/vitest-ext.ts"],"sourcesContent":["import { invariant } from '@zenstackhq/common-helpers';\nimport type { Model } from '@zenstackhq/language/ast';\nimport { ZenStackClient, type ClientContract, type ClientOptions } from '@zenstackhq/orm';\nimport type { SchemaDef } from '@zenstackhq/orm/schema';\nimport { PolicyPlugin } from '@zenstackhq/plugin-policy';\nimport { PrismaSchemaGenerator } from '@zenstackhq/sdk';\nimport SQLite from 'better-sqlite3';\nimport { glob } from 'glob';\nimport { PostgresDialect, SqliteDialect, type LogEvent } from 'kysely';\nimport { execSync } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { Client as PGClient, Pool } from 'pg';\nimport { expect } from 'vitest';\nimport { createTestProject } from './project';\nimport { generateTsSchema } from './schema';\nimport { loadDocumentWithPlugins } from './utils';\n\nexport function getTestDbProvider() {\n const val = process.env['TEST_DB_PROVIDER'] ?? 'sqlite';\n if (!['sqlite', 'postgresql'].includes(val!)) {\n throw new Error(`Invalid TEST_DB_PROVIDER value: ${val}`);\n }\n return val as 'sqlite' | 'postgresql';\n}\n\nconst TEST_PG_CONFIG = {\n host: process.env['TEST_PG_HOST'] ?? 'localhost',\n port: process.env['TEST_PG_PORT'] ? parseInt(process.env['TEST_PG_PORT']) : 5432,\n user: process.env['TEST_PG_USER'] ?? 'postgres',\n password: process.env['TEST_PG_PASSWORD'] ?? 'postgres',\n};\n\nexport type CreateTestClientOptions<Schema extends SchemaDef> = Omit<ClientOptions<Schema>, 'dialect'> & {\n /**\n * Database provider\n */\n provider?: 'sqlite' | 'postgresql';\n\n /**\n * The main ZModel file. Only used when `usePrismaPush` is true and `schema` is an object.\n */\n schemaFile?: string;\n\n /**\n * Database name. If not provided, a name will be generated based on the test name.\n */\n dbName?: string;\n\n /**\n * Use `prisma db push` instead of ZenStack's `$pushSchema` for database initialization.\n */\n usePrismaPush?: boolean;\n\n /**\n * Extra source files to create and compile.\n */\n extraSourceFiles?: Record<string, string>;\n\n /**\n * Working directory for the test client. If not provided, a temporary directory will be created.\n */\n workDir?: string;\n\n /**\n * Debug mode.\n */\n debug?: boolean;\n\n /**\n * A sqlite database file to be used for the test. Only supported for sqlite provider.\n */\n dbFile?: string;\n\n /**\n * PostgreSQL extensions to be added to the datasource. Only supported for postgresql provider.\n */\n dataSourceExtensions?: string[];\n\n /**\n * Additional files to be copied to the working directory. The glob pattern is relative to the test file.\n */\n copyFiles?: { globPattern: string; destination: string }[];\n};\n\nexport async function createTestClient<Schema extends SchemaDef>(\n schema: Schema,\n options?: CreateTestClientOptions<Schema>,\n): Promise<ClientContract<Schema>>;\nexport async function createTestClient<Schema extends SchemaDef>(\n schema: string,\n options?: CreateTestClientOptions<Schema>,\n): Promise<any>;\nexport async function createTestClient<Schema extends SchemaDef>(\n schema: Schema | string,\n options?: CreateTestClientOptions<Schema>,\n): Promise<any> {\n let workDir = options?.workDir;\n let _schema: Schema;\n const provider = options?.provider ?? getTestDbProvider() ?? 'sqlite';\n const dbName = options?.dbName ?? getTestDbName(provider);\n const dbUrl =\n provider === 'sqlite'\n ? `file:${dbName}`\n : `postgres://${TEST_PG_CONFIG.user}:${TEST_PG_CONFIG.password}@${TEST_PG_CONFIG.host}:${TEST_PG_CONFIG.port}/${dbName}`;\n\n let model: Model | undefined;\n\n if (typeof schema === 'string') {\n const generated = await generateTsSchema(schema, provider, dbUrl, options?.extraSourceFiles, undefined);\n workDir = generated.workDir;\n model = generated.model;\n // replace schema's provider\n _schema = {\n ...generated.schema,\n provider: {\n ...generated.schema.provider,\n type: provider,\n },\n } as Schema;\n } else {\n // replace schema's provider\n _schema = {\n ...schema,\n provider: {\n type: provider,\n },\n };\n workDir ??= createTestProject();\n if (options?.schemaFile) {\n let schemaContent = fs.readFileSync(options.schemaFile, 'utf-8');\n if (dbUrl) {\n // replace `datasource db { }` section\n schemaContent = schemaContent.replace(\n /datasource\\s+db\\s*{[^}]*}/m,\n `datasource db {\n provider = '${provider}'\n url = '${dbUrl}'\n ${options.dataSourceExtensions ? `extensions = [${options.dataSourceExtensions.join(', ')}]` : ''}\n}`,\n );\n }\n fs.writeFileSync(path.join(workDir!, 'schema.zmodel'), schemaContent);\n }\n }\n\n invariant(workDir);\n\n const { plugins, ...rest } = options ?? {};\n const _options: ClientOptions<Schema> = {\n ...rest,\n } as ClientOptions<Schema>;\n\n if (options?.debug) {\n console.log(`Work directory: ${workDir}`);\n _options.log = testLogger;\n }\n\n // copy db file to workDir if specified\n if (options?.dbFile) {\n if (provider !== 'sqlite') {\n throw new Error('dbFile option is only supported for sqlite provider');\n }\n fs.copyFileSync(options.dbFile, path.join(workDir, dbName));\n }\n\n // copy additional files if specified\n if (options?.copyFiles) {\n const state = expect.getState();\n const currentTestPath = state.testPath;\n if (!currentTestPath) {\n throw new Error('Unable to determine current test file path');\n }\n for (const { globPattern, destination } of options.copyFiles) {\n const files = glob.sync(globPattern, { cwd: path.dirname(currentTestPath) });\n for (const file of files) {\n const src = path.resolve(path.dirname(currentTestPath), file);\n const dest = path.resolve(workDir, destination, path.basename(file));\n fs.mkdirSync(path.dirname(dest), { recursive: true });\n fs.copyFileSync(src, dest);\n }\n }\n }\n\n if (!options?.dbFile) {\n if (options?.usePrismaPush) {\n invariant(\n typeof schema === 'string' || options?.schemaFile,\n 'a schema file must be provided when using prisma db push',\n );\n if (!model) {\n const r = await loadDocumentWithPlugins(path.join(workDir, 'schema.zmodel'));\n if (!r.success) {\n throw new Error(r.errors.join('\\n'));\n }\n model = r.model;\n }\n const prismaSchema = new PrismaSchemaGenerator(model);\n const prismaSchemaText = await prismaSchema.generate();\n fs.writeFileSync(path.resolve(workDir!, 'schema.prisma'), prismaSchemaText);\n execSync('npx prisma db push --schema ./schema.prisma --skip-generate --force-reset', {\n cwd: workDir,\n stdio: 'ignore',\n });\n } else {\n if (provider === 'postgresql') {\n invariant(dbName, 'dbName is required');\n const pgClient = new PGClient(TEST_PG_CONFIG);\n await pgClient.connect();\n await pgClient.query(`DROP DATABASE IF EXISTS \"${dbName}\"`);\n await pgClient.query(`CREATE DATABASE \"${dbName}\"`);\n await pgClient.end();\n }\n }\n }\n\n if (provider === 'postgresql') {\n _options.dialect = new PostgresDialect({\n pool: new Pool({\n ...TEST_PG_CONFIG,\n database: dbName,\n }),\n });\n } else {\n _options.dialect = new SqliteDialect({\n database: new SQLite(path.join(workDir!, dbName)),\n });\n }\n\n let client = new ZenStackClient(_schema, _options);\n\n if (!options?.usePrismaPush && !options?.dbFile) {\n await client.$pushSchema();\n }\n\n if (plugins) {\n for (const plugin of plugins) {\n client = client.$use(plugin);\n }\n }\n\n return client;\n}\n\nexport async function createPolicyTestClient<Schema extends SchemaDef>(\n schema: Schema,\n options?: CreateTestClientOptions<Schema>,\n): Promise<ClientContract<Schema>>;\nexport async function createPolicyTestClient<Schema extends SchemaDef>(\n schema: string,\n options?: CreateTestClientOptions<Schema>,\n): Promise<any>;\nexport async function createPolicyTestClient<Schema extends SchemaDef>(\n schema: Schema | string,\n options?: CreateTestClientOptions<Schema>,\n): Promise<any> {\n return createTestClient(\n schema as any,\n {\n ...options,\n plugins: [...(options?.plugins ?? []), new PolicyPlugin()],\n } as any,\n );\n}\n\nexport function testLogger(e: LogEvent) {\n console.log(e.query.sql, e.query.parameters);\n}\n\nfunction getTestDbName(provider: string) {\n if (provider === 'sqlite') {\n return './test.db';\n }\n const testName = expect.getState().currentTestName ?? 'unnamed';\n const testPath = expect.getState().testPath ?? '';\n // digest test name\n const digest = createHash('md5')\n .update(testName + testPath)\n .digest('hex');\n // compute a database name based on test name\n return (\n 'test_' +\n testName\n .toLowerCase()\n .replace(/[^a-z0-9_]/g, '_')\n .replace(/_+/g, '_')\n .substring(0, 30) +\n digest.slice(0, 6)\n );\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport tmp from 'tmp';\n\nexport function createTestProject(zmodelContent?: string) {\n const { name: workDir } = tmp.dirSync({ unsafeCleanup: true });\n\n fs.mkdirSync(path.join(workDir, 'node_modules'));\n\n // symlink all entries from \"node_modules\"\n const nodeModules = fs.readdirSync(path.join(__dirname, '../node_modules'));\n for (const entry of nodeModules) {\n if (entry.startsWith('@zenstackhq')) {\n continue;\n }\n fs.symlinkSync(\n path.join(__dirname, '../node_modules', entry),\n path.join(workDir, 'node_modules', entry),\n 'dir',\n );\n }\n\n // in addition, symlink zenstack packages\n const zenstackPackages = ['language', 'sdk', 'orm', 'cli'];\n fs.mkdirSync(path.join(workDir, 'node_modules/@zenstackhq'));\n for (const pkg of zenstackPackages) {\n fs.symlinkSync(\n path.join(__dirname, `../../${pkg}`),\n path.join(workDir, `node_modules/@zenstackhq/${pkg}`),\n 'dir',\n );\n }\n\n fs.writeFileSync(\n path.join(workDir, 'package.json'),\n JSON.stringify(\n {\n name: 'test',\n version: '1.0.0',\n type: 'module',\n },\n null,\n 4,\n ),\n );\n\n fs.writeFileSync(\n path.join(workDir, 'tsconfig.json'),\n JSON.stringify(\n {\n compilerOptions: {\n module: 'ESNext',\n target: 'ESNext',\n moduleResolution: 'Bundler',\n esModuleInterop: true,\n skipLibCheck: true,\n strict: true,\n },\n include: ['**/*.ts'],\n },\n null,\n 4,\n ),\n );\n\n if (zmodelContent) {\n fs.writeFileSync(path.join(workDir, 'schema.zmodel'), zmodelContent);\n }\n\n return workDir;\n}\n","import { invariant } from '@zenstackhq/common-helpers';\nimport type { SchemaDef } from '@zenstackhq/schema';\nimport { TsSchemaGenerator } from '@zenstackhq/sdk';\nimport { execSync } from 'node:child_process';\nimport crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { match } from 'ts-pattern';\nimport { expect } from 'vitest';\nimport { createTestProject } from './project';\nimport { loadDocumentWithPlugins } from './utils';\n\nfunction makePrelude(provider: 'sqlite' | 'postgresql', dbUrl?: string) {\n return match(provider)\n .with('sqlite', () => {\n return `\ndatasource db {\n provider = 'sqlite'\n url = '${dbUrl ?? 'file:./test.db'}'\n}\n`;\n })\n .with('postgresql', () => {\n return `\ndatasource db {\n provider = 'postgresql'\n url = '${dbUrl ?? 'postgres://postgres:postgres@localhost:5432/db'}'\n}\n`;\n })\n .exhaustive();\n}\n\nfunction replacePlaceholders(schemaText: string, provider: 'sqlite' | 'postgresql', dbUrl: string | undefined) {\n const url = dbUrl ?? (provider === 'sqlite' ? 'file:./test.db' : 'postgres://postgres:postgres@localhost:5432/db');\n return schemaText.replace(/\\$DB_URL/g, url).replace(/\\$PROVIDER/g, provider);\n}\n\nexport async function generateTsSchema(\n schemaText: string,\n provider: 'sqlite' | 'postgresql' = 'sqlite',\n dbUrl?: string,\n extraSourceFiles?: Record<string, string>,\n withLiteSchema?: boolean,\n) {\n const workDir = createTestProject();\n\n const zmodelPath = path.join(workDir, 'schema.zmodel');\n const noPrelude = schemaText.includes('datasource ');\n fs.writeFileSync(\n zmodelPath,\n `${noPrelude ? '' : makePrelude(provider, dbUrl)}\\n\\n${replacePlaceholders(schemaText, provider, dbUrl)}`,\n );\n\n const result = await loadDocumentWithPlugins(zmodelPath);\n if (!result.success) {\n throw new Error(`Failed to load schema from ${zmodelPath}: ${result.errors}`);\n }\n\n const generator = new TsSchemaGenerator();\n await generator.generate(result.model, { outDir: workDir, lite: withLiteSchema });\n\n if (extraSourceFiles) {\n for (const [fileName, content] of Object.entries(extraSourceFiles)) {\n const filePath = path.resolve(workDir, !fileName.endsWith('.ts') ? `${fileName}.ts` : fileName);\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n fs.writeFileSync(filePath, content);\n }\n }\n\n // compile the generated TS schema\n return { ...(await compileAndLoad(workDir)), model: result.model };\n}\n\nasync function compileAndLoad(workDir: string) {\n execSync('npx tsc', {\n cwd: workDir,\n stdio: 'inherit',\n });\n\n // load the schema module\n const module = await import(path.join(workDir, 'schema.js'));\n\n let moduleLite: any;\n try {\n moduleLite = await import(path.join(workDir, 'schema-lite.js'));\n } catch {\n // ignore\n }\n return { workDir, schema: module.schema as SchemaDef, schemaLite: moduleLite?.schema as SchemaDef | undefined };\n}\n\nexport function generateTsSchemaFromFile(filePath: string) {\n const schemaText = fs.readFileSync(filePath, 'utf8');\n return generateTsSchema(schemaText);\n}\n\nexport async function generateTsSchemaInPlace(schemaPath: string) {\n const workDir = path.dirname(schemaPath);\n const result = await loadDocumentWithPlugins(schemaPath);\n if (!result.success) {\n throw new Error(`Failed to load schema from ${schemaPath}: ${result.errors}`);\n }\n const generator = new TsSchemaGenerator();\n await generator.generate(result.model, { outDir: workDir });\n return compileAndLoad(workDir);\n}\n\nexport async function loadSchema(schema: string, additionalSchemas?: Record<string, string>) {\n if (!schema.includes('datasource ')) {\n schema = `${makePrelude('sqlite')}\\n\\n${schema}`;\n }\n\n // create a temp folder\n const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'zenstack-schema'));\n\n // create a temp file\n const tempFile = path.join(tempDir, `schema.zmodel`);\n fs.writeFileSync(tempFile, schema);\n\n if (additionalSchemas) {\n for (const [fileName, content] of Object.entries(additionalSchemas)) {\n let name = fileName;\n if (!name.endsWith('.zmodel')) {\n name += '.zmodel';\n }\n const filePath = path.join(tempDir, name);\n fs.writeFileSync(filePath, content);\n }\n }\n\n const r = await loadDocumentWithPlugins(tempFile);\n expect(r).toSatisfy(\n (r) => r.success,\n `Failed to load schema: ${(r as any).errors?.map((e: any) => e.toString()).join(', ')}`,\n );\n invariant(r.success);\n return r.model;\n}\n\nexport async function loadSchemaWithError(schema: string, error: string | RegExp) {\n if (!schema.includes('datasource ')) {\n schema = `${makePrelude('sqlite')}\\n\\n${schema}`;\n }\n\n // create a temp file\n const tempFile = path.join(os.tmpdir(), `zenstack-schema-${crypto.randomUUID()}.zmodel`);\n fs.writeFileSync(tempFile, schema);\n const r = await loadDocumentWithPlugins(tempFile);\n expect(r.success).toBe(false);\n invariant(!r.success);\n if (typeof error === 'string') {\n expect(r).toSatisfy(\n (r) => r.errors.some((e: any) => e.toString().toLowerCase().includes(error.toLowerCase())),\n `Expected error message to include \"${error}\" but got: ${r.errors.map((e: any) => e.toString()).join(', ')}`,\n );\n } else {\n expect(r).toSatisfy(\n (r) => r.errors.some((e: any) => error.test(e)),\n `Expected error message to match \"${error}\" but got: ${r.errors.map((e: any) => e.toString()).join(', ')}`,\n );\n }\n}\n","import { loadDocument } from '@zenstackhq/language';\n\nexport function loadDocumentWithPlugins(filePath: string) {\n const pluginModelFiles = [require.resolve('@zenstackhq/plugin-policy/plugin.zmodel')];\n return loadDocument(filePath, pluginModelFiles);\n}\n","import { ORMError, ORMErrorReason } from '@zenstackhq/orm';\nimport { expect } from 'vitest';\n\nfunction isPromise(value: any) {\n return typeof value.then === 'function' && typeof value.catch === 'function';\n}\n\nfunction expectErrorReason(err: any, errorReason: ORMErrorReason) {\n if (err instanceof ORMError && err.reason === errorReason) {\n return {\n message: () => '',\n pass: true,\n };\n } else {\n return {\n message: () => `expected ORMError of reason ${errorReason}, got ${err}`,\n pass: false,\n };\n }\n}\n\nfunction expectErrorMessages(expectedMessages: string[], message: string) {\n for (const m of expectedMessages) {\n if (!message.toLowerCase().includes(m.toLowerCase())) {\n return {\n message: () => `expected message not found in error: ${m}, got message: ${message}`,\n pass: false,\n };\n }\n }\n return undefined;\n}\n\nexpect.extend({\n async toResolveTruthy(received: Promise<unknown>) {\n if (!isPromise(received)) {\n return { message: () => 'a promise is expected', pass: false };\n }\n const r = await received;\n return {\n pass: !!r,\n message: () => `Expected promise to resolve to a truthy value, but got ${r}`,\n };\n },\n\n async toResolveFalsy(received: Promise<unknown>) {\n if (!isPromise(received)) {\n return { message: () => 'a promise is expected', pass: false };\n }\n const r = await received;\n return {\n pass: !r,\n message: () => `Expected promise to resolve to a falsy value, but got ${r}`,\n };\n },\n\n async toResolveNull(received: Promise<unknown>) {\n if (!isPromise(received)) {\n return { message: () => 'a promise is expected', pass: false };\n }\n const r = await received;\n return {\n pass: r === null,\n message: () => `Expected promise to resolve to a null value, but got ${r}`,\n };\n },\n\n async toResolveWithLength(received: Promise<unknown>, length: number) {\n const r = await received;\n return {\n pass: Array.isArray(r) && r.length === length,\n message: () => `Expected promise to resolve with an array with length ${length}, but got ${r}`,\n };\n },\n\n async toBeRejectedNotFound(received: Promise<unknown>) {\n if (!isPromise(received)) {\n return { message: () => 'a promise is expected', pass: false };\n }\n try {\n await received;\n } catch (err) {\n return expectErrorReason(err, ORMErrorReason.NOT_FOUND);\n }\n return {\n message: () => `expected NotFoundError, got no error`,\n pass: false,\n };\n },\n\n async toBeRejectedByPolicy(received: Promise<unknown>, expectedMessages?: string[]) {\n if (!isPromise(received)) {\n return { message: () => 'a promise is expected', pass: false };\n }\n try {\n await received;\n } catch (err) {\n if (expectedMessages && err instanceof ORMError && err.reason === ORMErrorReason.REJECTED_BY_POLICY) {\n const r = expectErrorMessages(expectedMessages, err.message || '');\n if (r) {\n return r;\n }\n }\n return expectErrorReason(err, ORMErrorReason.REJECTED_BY_POLICY);\n }\n return {\n message: () => `expected PolicyError, got no error`,\n pass: false,\n };\n },\n\n async toBeRejectedByValidation(received: Promise<unknown>, expectedMessages?: string[]) {\n if (!isPromise(received)) {\n return { message: () => 'a promise is expected', pass: false };\n }\n try {\n await received;\n } catch (err) {\n if (expectedMessages && err instanceof ORMError && err.reason === ORMErrorReason.INVALID_INPUT) {\n const r = expectErrorMessages(expectedMessages, err.message || '');\n if (r) {\n return r;\n }\n }\n return expectErrorReason(err, ORMErrorReason.INVALID_INPUT);\n }\n return {\n message: () => `expected InputValidationError, got no error`,\n pass: false,\n };\n },\n});\n"],"mappings":"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","names":["invariant","ZenStackClient","PolicyPlugin","PrismaSchemaGenerator","SQLite","glob","PostgresDialect","SqliteDialect","execSync","createHash","fs","path","Client","PGClient","Pool","expect","fs","path","tmp","createTestProject","zmodelContent","name","workDir","tmp","dirSync","unsafeCleanup","fs","mkdirSync","path","join","nodeModules","readdirSync","__dirname","entry","startsWith","symlinkSync","zenstackPackages","pkg","writeFileSync","JSON","stringify","version","type","compilerOptions","module","target","moduleResolution","esModuleInterop","skipLibCheck","strict","include","invariant","TsSchemaGenerator","execSync","crypto","fs","os","path","match","expect","loadDocument","loadDocumentWithPlugins","filePath","pluginModelFiles","require","resolve","loadDocument","makePrelude","provider","dbUrl","match","with","exhaustive","replacePlaceholders","schemaText","url","replace","generateTsSchema","extraSourceFiles","withLiteSchema","workDir","createTestProject","zmodelPath","path","join","noPrelude","includes","fs","writeFileSync","result","loadDocumentWithPlugins","success","Error","errors","generator","TsSchemaGenerator","generate","model","outDir","lite","fileName","content","Object","entries","filePath","resolve","endsWith","mkdirSync","dirname","recursive","compileAndLoad","execSync","cwd","stdio","module","moduleLite","schema","schemaLite","generateTsSchemaFromFile","readFileSync","generateTsSchemaInPlace","schemaPath","loadSchema","additionalSchemas","tempDir","mkdtempSync","os","tmpdir","tempFile","name","r","expect","toSatisfy","map","e","toString","invariant","loadSchemaWithError","error","crypto","randomUUID","toBe","some","toLowerCase","test","getTestDbProvider","val","process","env","includes","Error","TEST_PG_CONFIG","host","port","parseInt","user","password","createTestClient","schema","options","workDir","_schema","provider","dbName","getTestDbName","dbUrl","model","generated","generateTsSchema","extraSourceFiles","undefined","type","createTestProject","schemaFile","schemaContent","fs","readFileSync","replace","dataSourceExtensions","join","writeFileSync","path","invariant","plugins","rest","_options","debug","console","log","testLogger","dbFile","copyFileSync","copyFiles","state","expect","getState","currentTestPath","testPath","globPattern","destination","files","glob","sync","cwd","dirname","file","src","resolve","dest","basename","mkdirSync","recursive","usePrismaPush","r","loadDocumentWithPlugins","success","errors","prismaSchema","PrismaSchemaGenerator","prismaSchemaText","generate","execSync","stdio","pgClient","PGClient","connect","query","end","dialect","PostgresDialect","pool","Pool","database","SqliteDialect","SQLite","client","ZenStackClient","$pushSchema","plugin","$use","createPolicyTestClient","PolicyPlugin","e","sql","parameters","testName","currentTestName","digest","createHash","update","toLowerCase","substring","slice","ORMError","ORMErrorReason","expect","isPromise","value","then","catch","expectErrorReason","err","errorReason","ORMError","reason","message","pass","expectErrorMessages","expectedMessages","m","toLowerCase","includes","undefined","expect","extend","toResolveTruthy","received","r","toResolveFalsy","toResolveNull","toResolveWithLength","length","Array","isArray","toBeRejectedNotFound","ORMErrorReason","NOT_FOUND","toBeRejectedByPolicy","REJECTED_BY_POLICY","toBeRejectedByValidation","INVALID_INPUT"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zenstackhq/testtools",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.23",
|
|
4
4
|
"description": "ZenStack Test Tools",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [],
|
|
@@ -30,12 +30,12 @@
|
|
|
30
30
|
"prisma": "^6.10.0",
|
|
31
31
|
"tmp": "^0.2.3",
|
|
32
32
|
"ts-pattern": "^5.7.1",
|
|
33
|
-
"@zenstackhq/common-helpers": "3.0.0-beta.
|
|
34
|
-
"@zenstackhq/language": "3.0.0-beta.
|
|
35
|
-
"@zenstackhq/orm": "3.0.0-beta.
|
|
36
|
-
"@zenstackhq/schema": "3.0.0-beta.
|
|
37
|
-
"@zenstackhq/
|
|
38
|
-
"@zenstackhq/
|
|
33
|
+
"@zenstackhq/common-helpers": "3.0.0-beta.23",
|
|
34
|
+
"@zenstackhq/language": "3.0.0-beta.23",
|
|
35
|
+
"@zenstackhq/orm": "3.0.0-beta.23",
|
|
36
|
+
"@zenstackhq/schema": "3.0.0-beta.23",
|
|
37
|
+
"@zenstackhq/sdk": "3.0.0-beta.23",
|
|
38
|
+
"@zenstackhq/plugin-policy": "3.0.0-beta.23"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"better-sqlite3": "^12.2.0",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"@types/tmp": "^0.2.6",
|
|
48
48
|
"@types/pg": "^8.11.11",
|
|
49
49
|
"typescript": "^5.8.0",
|
|
50
|
-
"@zenstackhq/eslint-config": "3.0.0-beta.
|
|
51
|
-
"@zenstackhq/typescript-config": "3.0.0-beta.
|
|
50
|
+
"@zenstackhq/eslint-config": "3.0.0-beta.23",
|
|
51
|
+
"@zenstackhq/typescript-config": "3.0.0-beta.23"
|
|
52
52
|
},
|
|
53
53
|
"scripts": {
|
|
54
54
|
"build": "tsc --noEmit && tsup-node",
|