@zenstackhq/testtools 3.0.0-beta.9 → 3.1.0
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 +121 -58
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +56 -8
- package/dist/index.d.ts +56 -8
- package/dist/index.js +124 -57
- package/dist/index.js.map +1 -1
- package/package.json +15 -14
package/dist/index.cjs
CHANGED
|
@@ -31,6 +31,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
// src/index.ts
|
|
32
32
|
var src_exports = {};
|
|
33
33
|
__export(src_exports, {
|
|
34
|
+
TEST_PG_CONFIG: () => TEST_PG_CONFIG,
|
|
35
|
+
TEST_PG_URL: () => TEST_PG_URL,
|
|
34
36
|
createPolicyTestClient: () => createPolicyTestClient,
|
|
35
37
|
createTestClient: () => createTestClient,
|
|
36
38
|
createTestProject: () => createTestProject,
|
|
@@ -46,11 +48,11 @@ module.exports = __toCommonJS(src_exports);
|
|
|
46
48
|
|
|
47
49
|
// src/client.ts
|
|
48
50
|
var import_common_helpers2 = require("@zenstackhq/common-helpers");
|
|
49
|
-
var
|
|
51
|
+
var import_orm = require("@zenstackhq/orm");
|
|
50
52
|
var import_plugin_policy = require("@zenstackhq/plugin-policy");
|
|
51
|
-
var import_runtime3 = require("@zenstackhq/runtime");
|
|
52
53
|
var import_sdk2 = require("@zenstackhq/sdk");
|
|
53
54
|
var import_better_sqlite3 = __toESM(require("better-sqlite3"), 1);
|
|
55
|
+
var import_glob = require("glob");
|
|
54
56
|
var import_kysely = require("kysely");
|
|
55
57
|
var import_node_child_process2 = require("child_process");
|
|
56
58
|
var import_node_crypto2 = require("crypto");
|
|
@@ -78,7 +80,7 @@ function createTestProject(zmodelContent) {
|
|
|
78
80
|
const zenstackPackages = [
|
|
79
81
|
"language",
|
|
80
82
|
"sdk",
|
|
81
|
-
"
|
|
83
|
+
"orm",
|
|
82
84
|
"cli"
|
|
83
85
|
];
|
|
84
86
|
import_node_fs.default.mkdirSync(import_node_path.default.join(workDir, "node_modules/@zenstackhq"));
|
|
@@ -112,7 +114,6 @@ __name(createTestProject, "createTestProject");
|
|
|
112
114
|
|
|
113
115
|
// src/schema.ts
|
|
114
116
|
var import_common_helpers = require("@zenstackhq/common-helpers");
|
|
115
|
-
var import_language = require("@zenstackhq/language");
|
|
116
117
|
var import_sdk = require("@zenstackhq/sdk");
|
|
117
118
|
var import_node_child_process = require("child_process");
|
|
118
119
|
var import_node_crypto = __toESM(require("crypto"), 1);
|
|
@@ -121,6 +122,18 @@ var import_node_os = __toESM(require("os"), 1);
|
|
|
121
122
|
var import_node_path2 = __toESM(require("path"), 1);
|
|
122
123
|
var import_ts_pattern = require("ts-pattern");
|
|
123
124
|
var import_vitest = require("vitest");
|
|
125
|
+
|
|
126
|
+
// src/utils.ts
|
|
127
|
+
var import_language = require("@zenstackhq/language");
|
|
128
|
+
function loadDocumentWithPlugins(filePath) {
|
|
129
|
+
const pluginModelFiles = [
|
|
130
|
+
require.resolve("@zenstackhq/plugin-policy/plugin.zmodel")
|
|
131
|
+
];
|
|
132
|
+
return (0, import_language.loadDocument)(filePath, pluginModelFiles);
|
|
133
|
+
}
|
|
134
|
+
__name(loadDocumentWithPlugins, "loadDocumentWithPlugins");
|
|
135
|
+
|
|
136
|
+
// src/schema.ts
|
|
124
137
|
function makePrelude(provider, dbUrl) {
|
|
125
138
|
return (0, import_ts_pattern.match)(provider).with("sqlite", () => {
|
|
126
139
|
return `
|
|
@@ -139,19 +152,27 @@ datasource db {
|
|
|
139
152
|
}).exhaustive();
|
|
140
153
|
}
|
|
141
154
|
__name(makePrelude, "makePrelude");
|
|
142
|
-
|
|
155
|
+
function replacePlaceholders(schemaText, provider, dbUrl) {
|
|
156
|
+
const url = dbUrl ?? (provider === "sqlite" ? "file:./test.db" : "postgres://postgres:postgres@localhost:5432/db");
|
|
157
|
+
return schemaText.replace(/\$DB_URL/g, url).replace(/\$PROVIDER/g, provider);
|
|
158
|
+
}
|
|
159
|
+
__name(replacePlaceholders, "replacePlaceholders");
|
|
160
|
+
async function generateTsSchema(schemaText, provider = "sqlite", dbUrl, extraSourceFiles, withLiteSchema) {
|
|
143
161
|
const workDir = createTestProject();
|
|
144
162
|
const zmodelPath = import_node_path2.default.join(workDir, "schema.zmodel");
|
|
145
163
|
const noPrelude = schemaText.includes("datasource ");
|
|
146
164
|
import_node_fs2.default.writeFileSync(zmodelPath, `${noPrelude ? "" : makePrelude(provider, dbUrl)}
|
|
147
165
|
|
|
148
|
-
${schemaText}`);
|
|
149
|
-
const result = await (
|
|
166
|
+
${replacePlaceholders(schemaText, provider, dbUrl)}`);
|
|
167
|
+
const result = await loadDocumentWithPlugins(zmodelPath);
|
|
150
168
|
if (!result.success) {
|
|
151
169
|
throw new Error(`Failed to load schema from ${zmodelPath}: ${result.errors}`);
|
|
152
170
|
}
|
|
153
171
|
const generator = new import_sdk.TsSchemaGenerator();
|
|
154
|
-
await generator.generate(result.model,
|
|
172
|
+
await generator.generate(result.model, {
|
|
173
|
+
outDir: workDir,
|
|
174
|
+
lite: withLiteSchema
|
|
175
|
+
});
|
|
155
176
|
if (extraSourceFiles) {
|
|
156
177
|
for (const [fileName, content] of Object.entries(extraSourceFiles)) {
|
|
157
178
|
const filePath = import_node_path2.default.resolve(workDir, !fileName.endsWith(".ts") ? `${fileName}.ts` : fileName);
|
|
@@ -173,9 +194,15 @@ async function compileAndLoad(workDir) {
|
|
|
173
194
|
stdio: "inherit"
|
|
174
195
|
});
|
|
175
196
|
const module2 = await import(import_node_path2.default.join(workDir, "schema.js"));
|
|
197
|
+
let moduleLite;
|
|
198
|
+
try {
|
|
199
|
+
moduleLite = await import(import_node_path2.default.join(workDir, "schema-lite.js"));
|
|
200
|
+
} catch {
|
|
201
|
+
}
|
|
176
202
|
return {
|
|
177
203
|
workDir,
|
|
178
|
-
schema: module2.schema
|
|
204
|
+
schema: module2.schema,
|
|
205
|
+
schemaLite: moduleLite?.schema
|
|
179
206
|
};
|
|
180
207
|
}
|
|
181
208
|
__name(compileAndLoad, "compileAndLoad");
|
|
@@ -186,12 +213,14 @@ function generateTsSchemaFromFile(filePath) {
|
|
|
186
213
|
__name(generateTsSchemaFromFile, "generateTsSchemaFromFile");
|
|
187
214
|
async function generateTsSchemaInPlace(schemaPath) {
|
|
188
215
|
const workDir = import_node_path2.default.dirname(schemaPath);
|
|
189
|
-
const result = await (
|
|
216
|
+
const result = await loadDocumentWithPlugins(schemaPath);
|
|
190
217
|
if (!result.success) {
|
|
191
218
|
throw new Error(`Failed to load schema from ${schemaPath}: ${result.errors}`);
|
|
192
219
|
}
|
|
193
220
|
const generator = new import_sdk.TsSchemaGenerator();
|
|
194
|
-
await generator.generate(result.model,
|
|
221
|
+
await generator.generate(result.model, {
|
|
222
|
+
outDir: workDir
|
|
223
|
+
});
|
|
195
224
|
return compileAndLoad(workDir);
|
|
196
225
|
}
|
|
197
226
|
__name(generateTsSchemaInPlace, "generateTsSchemaInPlace");
|
|
@@ -214,7 +243,7 @@ ${schema}`;
|
|
|
214
243
|
import_node_fs2.default.writeFileSync(filePath, content);
|
|
215
244
|
}
|
|
216
245
|
}
|
|
217
|
-
const r = await (
|
|
246
|
+
const r = await loadDocumentWithPlugins(tempFile);
|
|
218
247
|
(0, import_vitest.expect)(r).toSatisfy((r2) => r2.success, `Failed to load schema: ${r.errors?.map((e) => e.toString()).join(", ")}`);
|
|
219
248
|
(0, import_common_helpers.invariant)(r.success);
|
|
220
249
|
return r.model;
|
|
@@ -228,7 +257,7 @@ ${schema}`;
|
|
|
228
257
|
}
|
|
229
258
|
const tempFile = import_node_path2.default.join(import_node_os.default.tmpdir(), `zenstack-schema-${import_node_crypto.default.randomUUID()}.zmodel`);
|
|
230
259
|
import_node_fs2.default.writeFileSync(tempFile, schema);
|
|
231
|
-
const r = await (
|
|
260
|
+
const r = await loadDocumentWithPlugins(tempFile);
|
|
232
261
|
(0, import_vitest.expect)(r.success).toBe(false);
|
|
233
262
|
(0, import_common_helpers.invariant)(!r.success);
|
|
234
263
|
if (typeof error === "string") {
|
|
@@ -257,20 +286,22 @@ var TEST_PG_CONFIG = {
|
|
|
257
286
|
user: process.env["TEST_PG_USER"] ?? "postgres",
|
|
258
287
|
password: process.env["TEST_PG_PASSWORD"] ?? "postgres"
|
|
259
288
|
};
|
|
260
|
-
|
|
289
|
+
var TEST_PG_URL = `postgres://${TEST_PG_CONFIG.user}:${TEST_PG_CONFIG.password}@${TEST_PG_CONFIG.host}:${TEST_PG_CONFIG.port}`;
|
|
290
|
+
async function createTestClient(schema, options) {
|
|
261
291
|
let workDir = options?.workDir;
|
|
262
292
|
let _schema;
|
|
263
293
|
const provider = options?.provider ?? getTestDbProvider() ?? "sqlite";
|
|
264
294
|
const dbName = options?.dbName ?? getTestDbName(provider);
|
|
265
|
-
const dbUrl = provider === "sqlite" ? `file:${dbName}` :
|
|
295
|
+
const dbUrl = provider === "sqlite" ? `file:${dbName}` : `${TEST_PG_URL}/${dbName}`;
|
|
266
296
|
let model;
|
|
267
297
|
if (typeof schema === "string") {
|
|
268
|
-
const generated = await generateTsSchema(schema, provider, dbUrl, options?.extraSourceFiles);
|
|
298
|
+
const generated = await generateTsSchema(schema, provider, dbUrl, options?.extraSourceFiles, void 0);
|
|
269
299
|
workDir = generated.workDir;
|
|
270
300
|
model = generated.model;
|
|
271
301
|
_schema = {
|
|
272
302
|
...generated.schema,
|
|
273
303
|
provider: {
|
|
304
|
+
...generated.schema.provider,
|
|
274
305
|
type: provider
|
|
275
306
|
}
|
|
276
307
|
};
|
|
@@ -282,49 +313,80 @@ async function createTestClient(schema, options, schemaFile) {
|
|
|
282
313
|
}
|
|
283
314
|
};
|
|
284
315
|
workDir ??= createTestProject();
|
|
285
|
-
if (schemaFile) {
|
|
286
|
-
let schemaContent = import_node_fs3.default.readFileSync(schemaFile, "utf-8");
|
|
316
|
+
if (options?.schemaFile) {
|
|
317
|
+
let schemaContent = import_node_fs3.default.readFileSync(options.schemaFile, "utf-8");
|
|
287
318
|
if (dbUrl) {
|
|
288
319
|
schemaContent = schemaContent.replace(/datasource\s+db\s*{[^}]*}/m, `datasource db {
|
|
289
320
|
provider = '${provider}'
|
|
290
321
|
url = '${dbUrl}'
|
|
322
|
+
${options.dataSourceExtensions ? `extensions = [${options.dataSourceExtensions.join(", ")}]` : ""}
|
|
291
323
|
}`);
|
|
292
324
|
}
|
|
293
325
|
import_node_fs3.default.writeFileSync(import_node_path3.default.join(workDir, "schema.zmodel"), schemaContent);
|
|
294
326
|
}
|
|
295
327
|
}
|
|
296
328
|
(0, import_common_helpers2.invariant)(workDir);
|
|
297
|
-
if (options?.debug) {
|
|
298
|
-
console.log(`Work directory: ${workDir}`);
|
|
299
|
-
}
|
|
300
329
|
const { plugins, ...rest } = options ?? {};
|
|
301
330
|
const _options = {
|
|
302
331
|
...rest
|
|
303
332
|
};
|
|
304
|
-
if (options?.
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
333
|
+
if (options?.debug) {
|
|
334
|
+
console.log(`Work directory: ${workDir}`);
|
|
335
|
+
console.log(`Database name: ${dbName}`);
|
|
336
|
+
_options.log = testLogger;
|
|
337
|
+
}
|
|
338
|
+
if (options?.dbFile) {
|
|
339
|
+
if (provider !== "sqlite") {
|
|
340
|
+
throw new Error("dbFile option is only supported for sqlite provider");
|
|
341
|
+
}
|
|
342
|
+
import_node_fs3.default.copyFileSync(options.dbFile, import_node_path3.default.join(workDir, dbName));
|
|
343
|
+
}
|
|
344
|
+
if (options?.copyFiles) {
|
|
345
|
+
const state = import_vitest2.expect.getState();
|
|
346
|
+
const currentTestPath = state.testPath;
|
|
347
|
+
if (!currentTestPath) {
|
|
348
|
+
throw new Error("Unable to determine current test file path");
|
|
349
|
+
}
|
|
350
|
+
for (const { globPattern, destination } of options.copyFiles) {
|
|
351
|
+
const files = import_glob.glob.sync(globPattern, {
|
|
352
|
+
cwd: import_node_path3.default.dirname(currentTestPath)
|
|
353
|
+
});
|
|
354
|
+
for (const file of files) {
|
|
355
|
+
const src = import_node_path3.default.resolve(import_node_path3.default.dirname(currentTestPath), file);
|
|
356
|
+
const dest = import_node_path3.default.resolve(workDir, destination, import_node_path3.default.basename(file));
|
|
357
|
+
import_node_fs3.default.mkdirSync(import_node_path3.default.dirname(dest), {
|
|
358
|
+
recursive: true
|
|
359
|
+
});
|
|
360
|
+
import_node_fs3.default.copyFileSync(src, dest);
|
|
310
361
|
}
|
|
311
|
-
model = r.model;
|
|
312
362
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
await
|
|
326
|
-
|
|
327
|
-
|
|
363
|
+
}
|
|
364
|
+
if (!options?.dbFile) {
|
|
365
|
+
if (options?.usePrismaPush) {
|
|
366
|
+
(0, import_common_helpers2.invariant)(typeof schema === "string" || options?.schemaFile, "a schema file must be provided when using prisma db push");
|
|
367
|
+
if (!model) {
|
|
368
|
+
const r = await loadDocumentWithPlugins(import_node_path3.default.join(workDir, "schema.zmodel"));
|
|
369
|
+
if (!r.success) {
|
|
370
|
+
throw new Error(r.errors.join("\n"));
|
|
371
|
+
}
|
|
372
|
+
model = r.model;
|
|
373
|
+
}
|
|
374
|
+
const prismaSchema = new import_sdk2.PrismaSchemaGenerator(model);
|
|
375
|
+
const prismaSchemaText = await prismaSchema.generate();
|
|
376
|
+
import_node_fs3.default.writeFileSync(import_node_path3.default.resolve(workDir, "schema.prisma"), prismaSchemaText);
|
|
377
|
+
(0, import_node_child_process2.execSync)("npx prisma db push --schema ./schema.prisma --skip-generate --force-reset", {
|
|
378
|
+
cwd: workDir,
|
|
379
|
+
stdio: "ignore"
|
|
380
|
+
});
|
|
381
|
+
} else {
|
|
382
|
+
if (provider === "postgresql") {
|
|
383
|
+
(0, import_common_helpers2.invariant)(dbName, "dbName is required");
|
|
384
|
+
const pgClient = new import_pg.Client(TEST_PG_CONFIG);
|
|
385
|
+
await pgClient.connect();
|
|
386
|
+
await pgClient.query(`DROP DATABASE IF EXISTS "${dbName}"`);
|
|
387
|
+
await pgClient.query(`CREATE DATABASE "${dbName}"`);
|
|
388
|
+
await pgClient.end();
|
|
389
|
+
}
|
|
328
390
|
}
|
|
329
391
|
}
|
|
330
392
|
if (provider === "postgresql") {
|
|
@@ -339,8 +401,8 @@ async function createTestClient(schema, options, schemaFile) {
|
|
|
339
401
|
database: new import_better_sqlite3.default(import_node_path3.default.join(workDir, dbName))
|
|
340
402
|
});
|
|
341
403
|
}
|
|
342
|
-
let client = new
|
|
343
|
-
if (!options?.usePrismaPush) {
|
|
404
|
+
let client = new import_orm.ZenStackClient(_schema, _options);
|
|
405
|
+
if (!options?.usePrismaPush && !options?.dbFile) {
|
|
344
406
|
await client.$pushSchema();
|
|
345
407
|
}
|
|
346
408
|
if (plugins) {
|
|
@@ -369,38 +431,37 @@ function getTestDbName(provider) {
|
|
|
369
431
|
if (provider === "sqlite") {
|
|
370
432
|
return "./test.db";
|
|
371
433
|
}
|
|
372
|
-
const testName = import_vitest2.expect.getState().currentTestName;
|
|
434
|
+
const testName = import_vitest2.expect.getState().currentTestName ?? "unnamed";
|
|
373
435
|
const testPath = import_vitest2.expect.getState().testPath ?? "";
|
|
374
|
-
(0, import_common_helpers2.invariant)(testName);
|
|
375
436
|
const digest = (0, import_node_crypto2.createHash)("md5").update(testName + testPath).digest("hex");
|
|
376
437
|
return "test_" + testName.toLowerCase().replace(/[^a-z0-9_]/g, "_").replace(/_+/g, "_").substring(0, 30) + digest.slice(0, 6);
|
|
377
438
|
}
|
|
378
439
|
__name(getTestDbName, "getTestDbName");
|
|
379
440
|
|
|
380
441
|
// src/vitest-ext.ts
|
|
381
|
-
var
|
|
442
|
+
var import_orm2 = require("@zenstackhq/orm");
|
|
382
443
|
var import_vitest3 = require("vitest");
|
|
383
444
|
function isPromise(value) {
|
|
384
445
|
return typeof value.then === "function" && typeof value.catch === "function";
|
|
385
446
|
}
|
|
386
447
|
__name(isPromise, "isPromise");
|
|
387
|
-
function
|
|
388
|
-
if (err instanceof
|
|
448
|
+
function expectErrorReason(err, errorReason) {
|
|
449
|
+
if (err instanceof import_orm2.ORMError && err.reason === errorReason) {
|
|
389
450
|
return {
|
|
390
451
|
message: /* @__PURE__ */ __name(() => "", "message"),
|
|
391
452
|
pass: true
|
|
392
453
|
};
|
|
393
454
|
} else {
|
|
394
455
|
return {
|
|
395
|
-
message: /* @__PURE__ */ __name(() => `expected ${
|
|
456
|
+
message: /* @__PURE__ */ __name(() => `expected ORMError of reason ${errorReason}, got ${err}`, "message"),
|
|
396
457
|
pass: false
|
|
397
458
|
};
|
|
398
459
|
}
|
|
399
460
|
}
|
|
400
|
-
__name(
|
|
461
|
+
__name(expectErrorReason, "expectErrorReason");
|
|
401
462
|
function expectErrorMessages(expectedMessages, message) {
|
|
402
463
|
for (const m of expectedMessages) {
|
|
403
|
-
if (!message.includes(m)) {
|
|
464
|
+
if (!message.toLowerCase().includes(m.toLowerCase())) {
|
|
404
465
|
return {
|
|
405
466
|
message: /* @__PURE__ */ __name(() => `expected message not found in error: ${m}, got message: ${message}`, "message"),
|
|
406
467
|
pass: false
|
|
@@ -467,7 +528,7 @@ import_vitest3.expect.extend({
|
|
|
467
528
|
try {
|
|
468
529
|
await received;
|
|
469
530
|
} catch (err) {
|
|
470
|
-
return
|
|
531
|
+
return expectErrorReason(err, import_orm2.ORMErrorReason.NOT_FOUND);
|
|
471
532
|
}
|
|
472
533
|
return {
|
|
473
534
|
message: /* @__PURE__ */ __name(() => `expected NotFoundError, got no error`, "message"),
|
|
@@ -484,13 +545,13 @@ import_vitest3.expect.extend({
|
|
|
484
545
|
try {
|
|
485
546
|
await received;
|
|
486
547
|
} catch (err) {
|
|
487
|
-
if (expectedMessages && err instanceof
|
|
548
|
+
if (expectedMessages && err instanceof import_orm2.ORMError && err.reason === import_orm2.ORMErrorReason.REJECTED_BY_POLICY) {
|
|
488
549
|
const r = expectErrorMessages(expectedMessages, err.message || "");
|
|
489
550
|
if (r) {
|
|
490
551
|
return r;
|
|
491
552
|
}
|
|
492
553
|
}
|
|
493
|
-
return
|
|
554
|
+
return expectErrorReason(err, import_orm2.ORMErrorReason.REJECTED_BY_POLICY);
|
|
494
555
|
}
|
|
495
556
|
return {
|
|
496
557
|
message: /* @__PURE__ */ __name(() => `expected PolicyError, got no error`, "message"),
|
|
@@ -507,13 +568,13 @@ import_vitest3.expect.extend({
|
|
|
507
568
|
try {
|
|
508
569
|
await received;
|
|
509
570
|
} catch (err) {
|
|
510
|
-
if (expectedMessages && err instanceof
|
|
571
|
+
if (expectedMessages && err instanceof import_orm2.ORMError && err.reason === import_orm2.ORMErrorReason.INVALID_INPUT) {
|
|
511
572
|
const r = expectErrorMessages(expectedMessages, err.message || "");
|
|
512
573
|
if (r) {
|
|
513
574
|
return r;
|
|
514
575
|
}
|
|
515
576
|
}
|
|
516
|
-
return
|
|
577
|
+
return expectErrorReason(err, import_orm2.ORMErrorReason.INVALID_INPUT);
|
|
517
578
|
}
|
|
518
579
|
return {
|
|
519
580
|
message: /* @__PURE__ */ __name(() => `expected InputValidationError, got no error`, "message"),
|
|
@@ -523,6 +584,8 @@ import_vitest3.expect.extend({
|
|
|
523
584
|
});
|
|
524
585
|
// Annotate the CommonJS export names for ESM import in node:
|
|
525
586
|
0 && (module.exports = {
|
|
587
|
+
TEST_PG_CONFIG,
|
|
588
|
+
TEST_PG_URL,
|
|
526
589
|
createPolicyTestClient,
|
|
527
590
|
createTestClient,
|
|
528
591
|
createTestProject,
|
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/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 { loadDocument } from '@zenstackhq/language';\nimport type { Model } from '@zenstackhq/language/ast';\nimport { PolicyPlugin } from '@zenstackhq/plugin-policy';\nimport { ZenStackClient, type ClientContract, type ClientOptions } from '@zenstackhq/runtime';\nimport type { SchemaDef } from '@zenstackhq/runtime/schema';\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';\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 dbName?: string;\n usePrismaPush?: boolean;\n extraSourceFiles?: Record<string, string>;\n workDir?: string;\n debug?: boolean;\n};\n\nexport async function createTestClient<Schema extends SchemaDef>(\n schema: Schema,\n options?: CreateTestClientOptions<Schema>,\n schemaFile?: string,\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 schemaFile?: string,\n): Promise<any> {\n let workDir = options?.workDir;\n let _schema: Schema;\n const provider = options?.provider ?? getTestDbProvider() ?? 'sqlite';\n\n const dbName = options?.dbName ?? getTestDbName(provider);\n\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);\n workDir = generated.workDir;\n model = generated.model;\n // replace schema's provider\n _schema = {\n ...generated.schema,\n 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 (schemaFile) {\n let schemaContent = fs.readFileSync(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 const { plugins, ...rest } = options ?? {};\n const _options: ClientOptions<Schema> = {\n ...rest,\n } as ClientOptions<Schema>;\n\n if (options?.usePrismaPush) {\n invariant(typeof schema === 'string' || schemaFile, 'a schema file must be provided when using prisma db push');\n if (!model) {\n const r = await loadDocument(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 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) {\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;\n const testPath = expect.getState().testPath ?? '';\n invariant(testName);\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', 'runtime', '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 { loadDocument } from '@zenstackhq/language';\nimport { TsSchemaGenerator } from '@zenstackhq/sdk';\nimport type { SchemaDef } from '@zenstackhq/sdk/schema';\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';\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\nexport async function generateTsSchema(\n schemaText: string,\n provider: 'sqlite' | 'postgresql' = 'sqlite',\n dbUrl?: string,\n extraSourceFiles?: Record<string, string>,\n) {\n const workDir = createTestProject();\n\n const zmodelPath = path.join(workDir, 'schema.zmodel');\n const noPrelude = schemaText.includes('datasource ');\n fs.writeFileSync(zmodelPath, `${noPrelude ? '' : makePrelude(provider, dbUrl)}\\n\\n${schemaText}`);\n\n const result = await loadDocument(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, workDir);\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 return { workDir, schema: module.schema as SchemaDef };\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 loadDocument(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, 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 loadDocument(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 loadDocument(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 { InputValidationError, NotFoundError, RejectedByPolicyError } from '@zenstackhq/runtime';\nimport { expect } from 'vitest';\n\nfunction isPromise(value: any) {\n return typeof value.then === 'function' && typeof value.catch === 'function';\n}\n\nfunction expectError(err: any, errorType: any) {\n if (err instanceof errorType) {\n return {\n message: () => '',\n pass: true,\n };\n } else {\n return {\n message: () => `expected ${errorType}, got ${err}`,\n pass: false,\n };\n }\n}\n\nfunction expectErrorMessages(expectedMessages: string[], message: string) {\n for (const m of expectedMessages) {\n if (!message.includes(m)) {\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 expectError(err, NotFoundError);\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 RejectedByPolicyError) {\n const r = expectErrorMessages(expectedMessages, err.message || '');\n if (r) {\n return r;\n }\n }\n return expectError(err, RejectedByPolicyError);\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 InputValidationError) {\n const r = expectErrorMessages(expectedMessages, err.message || '');\n if (r) {\n return r;\n }\n }\n return expectError(err, InputValidationError);\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_language","import_runtime","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","makePrelude","provider","dbUrl","match","with","exhaustive","generateTsSchema","schemaText","extraSourceFiles","workDir","createTestProject","zmodelPath","path","join","noPrelude","includes","fs","writeFileSync","result","loadDocument","success","Error","errors","generator","TsSchemaGenerator","generate","model","fileName","content","Object","entries","filePath","resolve","endsWith","mkdirSync","dirname","recursive","compileAndLoad","execSync","cwd","stdio","module","schema","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","schemaFile","workDir","_schema","provider","dbName","getTestDbName","dbUrl","model","generated","generateTsSchema","extraSourceFiles","type","createTestProject","schemaContent","fs","readFileSync","replace","writeFileSync","path","join","invariant","debug","console","log","plugins","rest","_options","usePrismaPush","r","loadDocument","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_runtime","import_vitest","isPromise","value","then","catch","expectError","err","errorType","message","pass","expectErrorMessages","expectedMessages","m","includes","undefined","expect","extend","toResolveTruthy","received","r","toResolveFalsy","toResolveNull","toResolveWithLength","length","Array","isArray","toBeRejectedNotFound","NotFoundError","toBeRejectedByPolicy","RejectedByPolicyError","toBeRejectedByValidation","InputValidationError"]}
|
|
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\nexport const 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 const TEST_PG_URL = `postgres://${TEST_PG_CONFIG.user}:${TEST_PG_CONFIG.password}@${TEST_PG_CONFIG.host}:${TEST_PG_CONFIG.port}`;\n\ntype ExtraTestClientOptions = {\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?: {\n globPattern: string;\n destination: string;\n }[];\n};\n\nexport type CreateTestClientOptions<Schema extends SchemaDef> = Omit<ClientOptions<Schema>, 'dialect'> &\n ExtraTestClientOptions;\n\nexport async function createTestClient<\n Schema extends SchemaDef,\n Options extends ClientOptions<Schema>,\n CreateOptions = Omit<Options, 'dialect'>,\n>(schema: Schema, options?: CreateOptions): Promise<ClientContract<Schema, Options>>;\nexport async function createTestClient(schema: string, options?: CreateTestClientOptions<SchemaDef>): Promise<any>;\nexport async function createTestClient(\n schema: SchemaDef | string,\n options?: CreateTestClientOptions<SchemaDef>,\n): Promise<any> {\n let workDir = options?.workDir;\n let _schema: SchemaDef;\n const provider = options?.provider ?? getTestDbProvider() ?? 'sqlite';\n const dbName = options?.dbName ?? getTestDbName(provider);\n const dbUrl = provider === 'sqlite' ? `file:${dbName}` : `${TEST_PG_URL}/${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 SchemaDef;\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 = {\n ...rest,\n } as ClientOptions<SchemaDef>;\n\n if (options?.debug) {\n console.log(`Work directory: ${workDir}`);\n console.log(`Database name: ${dbName}`);\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","TEST_PG_URL","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"]}
|