@zenstackhq/testtools 3.5.6 → 3.6.1
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 +411 -584
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +86 -82
- package/dist/index.d.mts +110 -0
- package/dist/index.mjs +444 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +16 -15
- package/dist/index.d.ts +0 -106
- package/dist/index.js +0 -613
- package/dist/index.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,655 +1,482 @@
|
|
|
1
|
-
"
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
2
3
|
var __create = Object.create;
|
|
3
4
|
var __defProp = Object.defineProperty;
|
|
4
5
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
9
|
-
var __export = (target, all) => {
|
|
10
|
-
for (var name in all)
|
|
11
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
-
};
|
|
13
9
|
var __copyProps = (to, from, except, desc) => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
+
key = keys[i];
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
13
|
+
get: ((k) => from[k]).bind(null, key),
|
|
14
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
20
18
|
};
|
|
21
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
// src/client.ts
|
|
52
|
-
var import_common_helpers2 = require("@zenstackhq/common-helpers");
|
|
53
|
-
var import_orm = require("@zenstackhq/orm");
|
|
54
|
-
var import_plugin_policy = require("@zenstackhq/plugin-policy");
|
|
55
|
-
var import_sdk2 = require("@zenstackhq/sdk");
|
|
56
|
-
var import_better_sqlite3 = __toESM(require("better-sqlite3"), 1);
|
|
57
|
-
var import_glob = require("glob");
|
|
58
|
-
var import_kysely = require("kysely");
|
|
59
|
-
var import_mysql2 = require("mysql2");
|
|
60
|
-
var import_node_child_process2 = require("child_process");
|
|
61
|
-
var import_node_crypto2 = require("crypto");
|
|
62
|
-
var import_node_fs3 = __toESM(require("fs"), 1);
|
|
63
|
-
var import_node_path3 = __toESM(require("path"), 1);
|
|
64
|
-
var import_pg = require("pg");
|
|
65
|
-
var import_ts_pattern2 = require("ts-pattern");
|
|
66
|
-
var import_vitest2 = require("vitest");
|
|
67
|
-
|
|
68
|
-
// src/project.ts
|
|
69
|
-
var import_node_fs = __toESM(require("fs"), 1);
|
|
70
|
-
var import_node_path = __toESM(require("path"), 1);
|
|
71
|
-
var import_tmp = __toESM(require("tmp"), 1);
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
20
|
+
value: mod,
|
|
21
|
+
enumerable: true
|
|
22
|
+
}) : target, mod));
|
|
23
|
+
//#endregion
|
|
24
|
+
let _zenstackhq_common_helpers = require("@zenstackhq/common-helpers");
|
|
25
|
+
let _zenstackhq_orm = require("@zenstackhq/orm");
|
|
26
|
+
let _zenstackhq_plugin_policy = require("@zenstackhq/plugin-policy");
|
|
27
|
+
let _zenstackhq_sdk = require("@zenstackhq/sdk");
|
|
28
|
+
let better_sqlite3 = require("better-sqlite3");
|
|
29
|
+
better_sqlite3 = __toESM(better_sqlite3, 1);
|
|
30
|
+
let glob = require("glob");
|
|
31
|
+
let kysely = require("kysely");
|
|
32
|
+
let mysql2 = require("mysql2");
|
|
33
|
+
let node_child_process = require("node:child_process");
|
|
34
|
+
let node_crypto = require("node:crypto");
|
|
35
|
+
node_crypto = __toESM(node_crypto, 1);
|
|
36
|
+
let node_fs = require("node:fs");
|
|
37
|
+
node_fs = __toESM(node_fs, 1);
|
|
38
|
+
let node_path = require("node:path");
|
|
39
|
+
node_path = __toESM(node_path, 1);
|
|
40
|
+
let pg = require("pg");
|
|
41
|
+
let ts_pattern = require("ts-pattern");
|
|
42
|
+
let vitest = require("vitest");
|
|
43
|
+
let tmp = require("tmp");
|
|
44
|
+
tmp = __toESM(tmp, 1);
|
|
45
|
+
let node_os = require("node:os");
|
|
46
|
+
node_os = __toESM(node_os, 1);
|
|
47
|
+
let _zenstackhq_language = require("@zenstackhq/language");
|
|
48
|
+
//#region src/project.ts
|
|
72
49
|
function createTestProject(zmodelContent) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
strict: true
|
|
108
|
-
},
|
|
109
|
-
include: [
|
|
110
|
-
"**/*.ts"
|
|
111
|
-
]
|
|
112
|
-
}, null, 4));
|
|
113
|
-
if (zmodelContent) {
|
|
114
|
-
import_node_fs.default.writeFileSync(import_node_path.default.join(workDir, "schema.zmodel"), zmodelContent);
|
|
115
|
-
}
|
|
116
|
-
return workDir;
|
|
50
|
+
const { name: workDir } = tmp.default.dirSync({ unsafeCleanup: true });
|
|
51
|
+
node_fs.default.mkdirSync(node_path.default.join(workDir, "node_modules"));
|
|
52
|
+
const nodeModules = node_fs.default.readdirSync(node_path.default.join(__dirname, "../node_modules"));
|
|
53
|
+
for (const entry of nodeModules) {
|
|
54
|
+
if (entry.startsWith("@zenstackhq")) continue;
|
|
55
|
+
node_fs.default.symlinkSync(node_path.default.join(__dirname, "../node_modules", entry), node_path.default.join(workDir, "node_modules", entry), "dir");
|
|
56
|
+
}
|
|
57
|
+
const zenstackPackages = [
|
|
58
|
+
"language",
|
|
59
|
+
"sdk",
|
|
60
|
+
"schema",
|
|
61
|
+
"orm",
|
|
62
|
+
"cli"
|
|
63
|
+
];
|
|
64
|
+
node_fs.default.mkdirSync(node_path.default.join(workDir, "node_modules/@zenstackhq"));
|
|
65
|
+
for (const pkg of zenstackPackages) node_fs.default.symlinkSync(node_path.default.join(__dirname, `../../${pkg}`), node_path.default.join(workDir, `node_modules/@zenstackhq/${pkg}`), "dir");
|
|
66
|
+
node_fs.default.writeFileSync(node_path.default.join(workDir, "package.json"), JSON.stringify({
|
|
67
|
+
name: "test",
|
|
68
|
+
version: "1.0.0",
|
|
69
|
+
type: "module"
|
|
70
|
+
}, null, 4));
|
|
71
|
+
node_fs.default.writeFileSync(node_path.default.join(workDir, "tsconfig.json"), JSON.stringify({
|
|
72
|
+
compilerOptions: {
|
|
73
|
+
module: "ESNext",
|
|
74
|
+
target: "ESNext",
|
|
75
|
+
moduleResolution: "Bundler",
|
|
76
|
+
esModuleInterop: true,
|
|
77
|
+
skipLibCheck: true,
|
|
78
|
+
strict: true
|
|
79
|
+
},
|
|
80
|
+
include: ["**/*.ts"]
|
|
81
|
+
}, null, 4));
|
|
82
|
+
if (zmodelContent) node_fs.default.writeFileSync(node_path.default.join(workDir, "schema.zmodel"), zmodelContent);
|
|
83
|
+
return workDir;
|
|
117
84
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
// src/schema.ts
|
|
121
|
-
var import_common_helpers = require("@zenstackhq/common-helpers");
|
|
122
|
-
var import_sdk = require("@zenstackhq/sdk");
|
|
123
|
-
var import_node_child_process = require("child_process");
|
|
124
|
-
var import_node_crypto = __toESM(require("crypto"), 1);
|
|
125
|
-
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
126
|
-
var import_node_os = __toESM(require("os"), 1);
|
|
127
|
-
var import_node_path2 = __toESM(require("path"), 1);
|
|
128
|
-
var import_ts_pattern = require("ts-pattern");
|
|
129
|
-
var import_vitest = require("vitest");
|
|
130
|
-
|
|
131
|
-
// src/utils.ts
|
|
132
|
-
var import_language = require("@zenstackhq/language");
|
|
85
|
+
//#endregion
|
|
86
|
+
//#region src/utils.ts
|
|
133
87
|
function loadDocumentWithPlugins(filePath) {
|
|
134
|
-
|
|
135
|
-
require.resolve("@zenstackhq/plugin-policy/plugin.zmodel")
|
|
136
|
-
];
|
|
137
|
-
return (0, import_language.loadDocument)(filePath, pluginModelFiles);
|
|
88
|
+
return (0, _zenstackhq_language.loadDocument)(filePath, [require.resolve("@zenstackhq/plugin-policy/plugin.zmodel")]);
|
|
138
89
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
// src/schema.ts
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/schema.ts
|
|
142
92
|
function makePrelude(provider, dbUrl) {
|
|
143
|
-
|
|
144
|
-
|
|
93
|
+
return (0, ts_pattern.match)(provider).with("sqlite", () => {
|
|
94
|
+
return `
|
|
145
95
|
datasource db {
|
|
146
96
|
provider = 'sqlite'
|
|
147
97
|
url = '${dbUrl ?? "file:./test.db"}'
|
|
148
98
|
}
|
|
149
99
|
`;
|
|
150
|
-
|
|
151
|
-
|
|
100
|
+
}).with("postgresql", () => {
|
|
101
|
+
return `
|
|
152
102
|
datasource db {
|
|
153
103
|
provider = 'postgresql'
|
|
154
104
|
url = '${dbUrl ?? "postgres://postgres:postgres@localhost:5432/db"}'
|
|
155
105
|
}
|
|
156
106
|
`;
|
|
157
|
-
|
|
158
|
-
|
|
107
|
+
}).with("mysql", () => {
|
|
108
|
+
return `
|
|
159
109
|
datasource db {
|
|
160
110
|
provider = 'mysql'
|
|
161
111
|
url = '${dbUrl ?? "mysql://root:mysql@localhost:3306/db"}'
|
|
162
112
|
}
|
|
163
113
|
`;
|
|
164
|
-
|
|
114
|
+
}).exhaustive();
|
|
165
115
|
}
|
|
166
|
-
__name(makePrelude, "makePrelude");
|
|
167
116
|
function replacePlaceholders(schemaText, provider, dbUrl) {
|
|
168
|
-
|
|
169
|
-
|
|
117
|
+
const url = dbUrl ?? (provider === "sqlite" ? "file:./test.db" : provider === "mysql" ? "mysql://root:mysql@localhost:3306/db" : "postgres://postgres:postgres@localhost:5432/db");
|
|
118
|
+
return schemaText.replace(/\$DB_URL/g, url).replace(/\$PROVIDER/g, provider);
|
|
170
119
|
}
|
|
171
|
-
__name(replacePlaceholders, "replacePlaceholders");
|
|
172
120
|
async function generateTsSchema(schemaText, provider = "sqlite", dbUrl, extraSourceFiles, withLiteSchema, extraZModelFiles) {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
lite: withLiteSchema
|
|
200
|
-
});
|
|
201
|
-
if (extraSourceFiles) {
|
|
202
|
-
for (const [fileName, content] of Object.entries(extraSourceFiles)) {
|
|
203
|
-
const filePath = import_node_path2.default.resolve(workDir, !fileName.endsWith(".ts") ? `${fileName}.ts` : fileName);
|
|
204
|
-
import_node_fs2.default.mkdirSync(import_node_path2.default.dirname(filePath), {
|
|
205
|
-
recursive: true
|
|
206
|
-
});
|
|
207
|
-
import_node_fs2.default.writeFileSync(filePath, content);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
return {
|
|
211
|
-
...await compileAndLoad(workDir),
|
|
212
|
-
model: result.model
|
|
213
|
-
};
|
|
121
|
+
const workDir = createTestProject();
|
|
122
|
+
const zmodelPath = node_path.default.join(workDir, "schema.zmodel");
|
|
123
|
+
const noPrelude = schemaText.includes("datasource ");
|
|
124
|
+
node_fs.default.writeFileSync(zmodelPath, `${noPrelude ? "" : makePrelude(provider, dbUrl)}\n\n${replacePlaceholders(schemaText, provider, dbUrl)}`);
|
|
125
|
+
if (extraZModelFiles) for (const [fileName, content] of Object.entries(extraZModelFiles)) {
|
|
126
|
+
let name = fileName;
|
|
127
|
+
if (!name.endsWith(".zmodel")) name += ".zmodel";
|
|
128
|
+
const filePath = node_path.default.join(workDir, name);
|
|
129
|
+
node_fs.default.mkdirSync(node_path.default.dirname(filePath), { recursive: true });
|
|
130
|
+
node_fs.default.writeFileSync(filePath, content);
|
|
131
|
+
}
|
|
132
|
+
const result = await loadDocumentWithPlugins(zmodelPath);
|
|
133
|
+
if (!result.success) throw new Error(`Failed to load schema from ${zmodelPath}: ${result.errors}`);
|
|
134
|
+
await new _zenstackhq_sdk.TsSchemaGenerator().generate(result.model, {
|
|
135
|
+
outDir: workDir,
|
|
136
|
+
lite: withLiteSchema
|
|
137
|
+
});
|
|
138
|
+
if (extraSourceFiles) for (const [fileName, content] of Object.entries(extraSourceFiles)) {
|
|
139
|
+
const filePath = node_path.default.resolve(workDir, !fileName.endsWith(".ts") ? `${fileName}.ts` : fileName);
|
|
140
|
+
node_fs.default.mkdirSync(node_path.default.dirname(filePath), { recursive: true });
|
|
141
|
+
node_fs.default.writeFileSync(filePath, content);
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
...await compileAndLoad(workDir),
|
|
145
|
+
model: result.model
|
|
146
|
+
};
|
|
214
147
|
}
|
|
215
|
-
__name(generateTsSchema, "generateTsSchema");
|
|
216
148
|
async function compileAndLoad(workDir) {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
};
|
|
149
|
+
(0, node_child_process.execSync)("npx tsc", {
|
|
150
|
+
cwd: workDir,
|
|
151
|
+
stdio: "inherit"
|
|
152
|
+
});
|
|
153
|
+
const module = await import(node_path.default.join(workDir, "schema.js"));
|
|
154
|
+
let moduleLite;
|
|
155
|
+
try {
|
|
156
|
+
moduleLite = await import(node_path.default.join(workDir, "schema-lite.js"));
|
|
157
|
+
} catch {}
|
|
158
|
+
return {
|
|
159
|
+
workDir,
|
|
160
|
+
schema: module.schema,
|
|
161
|
+
schemaLite: moduleLite?.schema
|
|
162
|
+
};
|
|
232
163
|
}
|
|
233
|
-
__name(compileAndLoad, "compileAndLoad");
|
|
234
164
|
function generateTsSchemaFromFile(filePath) {
|
|
235
|
-
|
|
236
|
-
return generateTsSchema(schemaText);
|
|
165
|
+
return generateTsSchema(node_fs.default.readFileSync(filePath, "utf8"));
|
|
237
166
|
}
|
|
238
|
-
__name(generateTsSchemaFromFile, "generateTsSchemaFromFile");
|
|
239
167
|
async function generateTsSchemaInPlace(schemaPath) {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
const generator = new import_sdk.TsSchemaGenerator();
|
|
246
|
-
await generator.generate(result.model, {
|
|
247
|
-
outDir: workDir
|
|
248
|
-
});
|
|
249
|
-
return compileAndLoad(workDir);
|
|
168
|
+
const workDir = node_path.default.dirname(schemaPath);
|
|
169
|
+
const result = await loadDocumentWithPlugins(schemaPath);
|
|
170
|
+
if (!result.success) throw new Error(`Failed to load schema from ${schemaPath}: ${result.errors}`);
|
|
171
|
+
await new _zenstackhq_sdk.TsSchemaGenerator().generate(result.model, { outDir: workDir });
|
|
172
|
+
return compileAndLoad(workDir);
|
|
250
173
|
}
|
|
251
|
-
__name(generateTsSchemaInPlace, "generateTsSchemaInPlace");
|
|
252
174
|
async function loadSchema(schema, additionalSchemas) {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
const filePath = import_node_path2.default.join(tempDir, name);
|
|
268
|
-
import_node_fs2.default.writeFileSync(filePath, content);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
const r = await loadDocumentWithPlugins(tempFile);
|
|
272
|
-
(0, import_vitest.expect)(r).toSatisfy((r2) => r2.success, `Failed to load schema: ${r.errors?.map((e) => e.toString()).join(", ")}`);
|
|
273
|
-
(0, import_common_helpers.invariant)(r.success);
|
|
274
|
-
return r.model;
|
|
175
|
+
if (!schema.includes("datasource ")) schema = `${makePrelude("sqlite")}\n\n${schema}`;
|
|
176
|
+
const tempDir = node_fs.default.mkdtempSync(node_path.default.join(node_os.default.tmpdir(), "zenstack-schema"));
|
|
177
|
+
const tempFile = node_path.default.join(tempDir, `schema.zmodel`);
|
|
178
|
+
node_fs.default.writeFileSync(tempFile, schema);
|
|
179
|
+
if (additionalSchemas) for (const [fileName, content] of Object.entries(additionalSchemas)) {
|
|
180
|
+
let name = fileName;
|
|
181
|
+
if (!name.endsWith(".zmodel")) name += ".zmodel";
|
|
182
|
+
const filePath = node_path.default.join(tempDir, name);
|
|
183
|
+
node_fs.default.writeFileSync(filePath, content);
|
|
184
|
+
}
|
|
185
|
+
const r = await loadDocumentWithPlugins(tempFile);
|
|
186
|
+
(0, vitest.expect)(r).toSatisfy((r) => r.success, `Failed to load schema: ${r.errors?.map((e) => e.toString()).join(", ")}`);
|
|
187
|
+
(0, _zenstackhq_common_helpers.invariant)(r.success);
|
|
188
|
+
return r.model;
|
|
275
189
|
}
|
|
276
|
-
__name(loadSchema, "loadSchema");
|
|
277
190
|
async function loadSchemaWithError(schema, error) {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
(0, import_vitest.expect)(r.success).toBe(false);
|
|
287
|
-
(0, import_common_helpers.invariant)(!r.success);
|
|
288
|
-
if (typeof error === "string") {
|
|
289
|
-
(0, import_vitest.expect)(r).toSatisfy((r2) => r2.errors.some((e) => e.toString().toLowerCase().includes(error.toLowerCase())), `Expected error message to include "${error}" but got: ${r.errors.map((e) => e.toString()).join(", ")}`);
|
|
290
|
-
} else {
|
|
291
|
-
(0, import_vitest.expect)(r).toSatisfy((r2) => r2.errors.some((e) => error.test(e)), `Expected error message to match "${error}" but got: ${r.errors.map((e) => e.toString()).join(", ")}`);
|
|
292
|
-
}
|
|
191
|
+
if (!schema.includes("datasource ")) schema = `${makePrelude("sqlite")}\n\n${schema}`;
|
|
192
|
+
const tempFile = node_path.default.join(node_os.default.tmpdir(), `zenstack-schema-${node_crypto.default.randomUUID()}.zmodel`);
|
|
193
|
+
node_fs.default.writeFileSync(tempFile, schema);
|
|
194
|
+
const r = await loadDocumentWithPlugins(tempFile);
|
|
195
|
+
(0, vitest.expect)(r.success).toBe(false);
|
|
196
|
+
(0, _zenstackhq_common_helpers.invariant)(!r.success);
|
|
197
|
+
if (typeof error === "string") (0, vitest.expect)(r).toSatisfy((r) => r.errors.some((e) => e.toString().toLowerCase().includes(error.toLowerCase())), `Expected error message to include "${error}" but got: ${r.errors.map((e) => e.toString()).join(", ")}`);
|
|
198
|
+
else (0, vitest.expect)(r).toSatisfy((r) => r.errors.some((e) => error.test(e)), `Expected error message to match "${error}" but got: ${r.errors.map((e) => e.toString()).join(", ")}`);
|
|
293
199
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
// src/client.ts
|
|
200
|
+
//#endregion
|
|
201
|
+
//#region src/client.ts
|
|
297
202
|
function getTestDbProvider() {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
}
|
|
306
|
-
return val;
|
|
203
|
+
const val = process.env["TEST_DB_PROVIDER"] ?? "sqlite";
|
|
204
|
+
if (![
|
|
205
|
+
"sqlite",
|
|
206
|
+
"postgresql",
|
|
207
|
+
"mysql"
|
|
208
|
+
].includes(val)) throw new Error(`Invalid TEST_DB_PROVIDER value: ${val}`);
|
|
209
|
+
return val;
|
|
307
210
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
password: process.env["TEST_PG_PASSWORD"] ?? "postgres"
|
|
211
|
+
const TEST_PG_CONFIG = {
|
|
212
|
+
host: process.env["TEST_PG_HOST"] ?? "localhost",
|
|
213
|
+
port: process.env["TEST_PG_PORT"] ? parseInt(process.env["TEST_PG_PORT"]) : 5432,
|
|
214
|
+
user: process.env["TEST_PG_USER"] ?? "postgres",
|
|
215
|
+
password: process.env["TEST_PG_PASSWORD"] ?? "postgres"
|
|
314
216
|
};
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
217
|
+
const TEST_PG_URL = `postgres://${TEST_PG_CONFIG.user}:${TEST_PG_CONFIG.password}@${TEST_PG_CONFIG.host}:${TEST_PG_CONFIG.port}`;
|
|
218
|
+
const TEST_MYSQL_CONFIG = {
|
|
219
|
+
host: process.env["TEST_MYSQL_HOST"] ?? "localhost",
|
|
220
|
+
port: process.env["TEST_MYSQL_PORT"] ? parseInt(process.env["TEST_MYSQL_PORT"]) : 3306,
|
|
221
|
+
user: process.env["TEST_MYSQL_USER"] ?? "root",
|
|
222
|
+
password: process.env["TEST_MYSQL_PASSWORD"] ?? "mysql",
|
|
223
|
+
timezone: "Z"
|
|
322
224
|
};
|
|
323
|
-
|
|
225
|
+
const TEST_MYSQL_URL = `mysql://${TEST_MYSQL_CONFIG.user}:${TEST_MYSQL_CONFIG.password}@${TEST_MYSQL_CONFIG.host}:${TEST_MYSQL_CONFIG.port}`;
|
|
324
226
|
async function createTestClient(schema, options) {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
let schemaContent = import_node_fs3.default.readFileSync(options.schemaFile, "utf-8");
|
|
352
|
-
if (dbUrl) {
|
|
353
|
-
schemaContent = schemaContent.replace(/datasource\s+db\s*{[^}]*}/m, `datasource db {
|
|
227
|
+
let workDir = options?.workDir;
|
|
228
|
+
let _schema;
|
|
229
|
+
const provider = options?.provider ?? getTestDbProvider() ?? "sqlite";
|
|
230
|
+
const dbName = options?.dbName ?? getTestDbName(provider);
|
|
231
|
+
const dbUrl = (0, ts_pattern.match)(provider).with("sqlite", () => `file:${dbName}`).with("mysql", () => `${TEST_MYSQL_URL}/${dbName}`).with("postgresql", () => `${TEST_PG_URL}/${dbName}`).exhaustive();
|
|
232
|
+
let model;
|
|
233
|
+
if (typeof schema === "string") {
|
|
234
|
+
const generated = await generateTsSchema(schema, provider, dbUrl, options?.extraSourceFiles, void 0, options?.extraZModelFiles);
|
|
235
|
+
workDir = generated.workDir;
|
|
236
|
+
model = generated.model;
|
|
237
|
+
_schema = {
|
|
238
|
+
...generated.schema,
|
|
239
|
+
provider: {
|
|
240
|
+
...generated.schema.provider,
|
|
241
|
+
type: provider
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
} else {
|
|
245
|
+
_schema = {
|
|
246
|
+
...schema,
|
|
247
|
+
provider: { type: provider }
|
|
248
|
+
};
|
|
249
|
+
workDir ??= createTestProject();
|
|
250
|
+
if (options?.schemaFile) {
|
|
251
|
+
let schemaContent = node_fs.default.readFileSync(options.schemaFile, "utf-8");
|
|
252
|
+
if (dbUrl) schemaContent = schemaContent.replace(/datasource\s+db\s*{[^}]*}/m, `datasource db {
|
|
354
253
|
provider = '${provider}'
|
|
355
254
|
url = '${dbUrl}'
|
|
356
255
|
${options.dataSourceExtensions ? `extensions = [${options.dataSourceExtensions.join(", ")}]` : ""}
|
|
357
256
|
}`);
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
const prismaSchemaText = await prismaSchema.generate();
|
|
410
|
-
import_node_fs3.default.writeFileSync(import_node_path3.default.resolve(workDir, "schema.prisma"), prismaSchemaText);
|
|
411
|
-
(0, import_node_child_process2.execSync)("npx prisma db push --schema ./schema.prisma --skip-generate --force-reset", {
|
|
412
|
-
cwd: workDir,
|
|
413
|
-
stdio: options.debug ? "inherit" : "ignore",
|
|
414
|
-
env: {
|
|
415
|
-
...process.env,
|
|
416
|
-
PRISMA_USER_CONSENT_FOR_DANGEROUS_AI_ACTION: "true"
|
|
417
|
-
}
|
|
418
|
-
});
|
|
419
|
-
} else {
|
|
420
|
-
await prepareDatabase(provider, dbName);
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
_options.dialect = createDialect(provider, dbName, workDir);
|
|
424
|
-
let client = new import_orm.ZenStackClient(_schema, _options);
|
|
425
|
-
if (!options?.usePrismaPush && !options?.dbFile) {
|
|
426
|
-
await client.$pushSchema();
|
|
427
|
-
}
|
|
428
|
-
if (plugins) {
|
|
429
|
-
for (const plugin of plugins) {
|
|
430
|
-
client = client.$use(plugin);
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
return client;
|
|
257
|
+
node_fs.default.writeFileSync(node_path.default.join(workDir, "schema.zmodel"), schemaContent);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
(0, _zenstackhq_common_helpers.invariant)(workDir);
|
|
261
|
+
const { plugins, ...rest } = options ?? {};
|
|
262
|
+
const _options = { ...rest };
|
|
263
|
+
if (options?.debug) {
|
|
264
|
+
console.log(`Work directory: ${workDir}`);
|
|
265
|
+
console.log(`Database name: ${dbName}`);
|
|
266
|
+
_options.log ??= testLogger;
|
|
267
|
+
}
|
|
268
|
+
if (options?.dbFile) {
|
|
269
|
+
if (provider !== "sqlite") throw new Error("dbFile option is only supported for sqlite provider");
|
|
270
|
+
node_fs.default.copyFileSync(options.dbFile, node_path.default.join(workDir, dbName));
|
|
271
|
+
}
|
|
272
|
+
if (options?.copyFiles) {
|
|
273
|
+
const currentTestPath = vitest.expect.getState().testPath;
|
|
274
|
+
if (!currentTestPath) throw new Error("Unable to determine current test file path");
|
|
275
|
+
for (const { globPattern, destination } of options.copyFiles) {
|
|
276
|
+
const files = glob.glob.sync(globPattern, { cwd: node_path.default.dirname(currentTestPath) });
|
|
277
|
+
for (const file of files) {
|
|
278
|
+
const src = node_path.default.resolve(node_path.default.dirname(currentTestPath), file);
|
|
279
|
+
const dest = node_path.default.resolve(workDir, destination, node_path.default.basename(file));
|
|
280
|
+
node_fs.default.mkdirSync(node_path.default.dirname(dest), { recursive: true });
|
|
281
|
+
node_fs.default.copyFileSync(src, dest);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
if (!options?.dbFile) if (options?.usePrismaPush) {
|
|
286
|
+
(0, _zenstackhq_common_helpers.invariant)(typeof schema === "string" || options?.schemaFile, "a schema file must be provided when using prisma db push");
|
|
287
|
+
if (!model) {
|
|
288
|
+
const r = await loadDocumentWithPlugins(node_path.default.join(workDir, "schema.zmodel"));
|
|
289
|
+
if (!r.success) throw new Error(r.errors.join("\n"));
|
|
290
|
+
model = r.model;
|
|
291
|
+
}
|
|
292
|
+
const prismaSchemaText = await new _zenstackhq_sdk.PrismaSchemaGenerator(model).generate();
|
|
293
|
+
node_fs.default.writeFileSync(node_path.default.resolve(workDir, "schema.prisma"), prismaSchemaText);
|
|
294
|
+
(0, node_child_process.execSync)("npx prisma db push --schema ./schema.prisma --skip-generate --force-reset", {
|
|
295
|
+
cwd: workDir,
|
|
296
|
+
stdio: options.debug ? "inherit" : "ignore",
|
|
297
|
+
env: {
|
|
298
|
+
...process.env,
|
|
299
|
+
PRISMA_USER_CONSENT_FOR_DANGEROUS_AI_ACTION: "true"
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
} else await prepareDatabase(provider, dbName);
|
|
303
|
+
_options.dialect = createDialect(provider, dbName, workDir);
|
|
304
|
+
let client = new _zenstackhq_orm.ZenStackClient(_schema, _options);
|
|
305
|
+
if (!options?.usePrismaPush && !options?.dbFile) await client.$pushSchema();
|
|
306
|
+
if (plugins) for (const plugin of plugins) client = client.$use(plugin);
|
|
307
|
+
return client;
|
|
434
308
|
}
|
|
435
|
-
__name(createTestClient, "createTestClient");
|
|
436
309
|
function createDialect(provider, dbName, workDir) {
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
...TEST_MYSQL_CONFIG,
|
|
445
|
-
database: dbName
|
|
446
|
-
})
|
|
447
|
-
})).with("sqlite", () => new import_kysely.SqliteDialect({
|
|
448
|
-
database: new import_better_sqlite3.default(import_node_path3.default.join(workDir, dbName))
|
|
449
|
-
})).exhaustive();
|
|
310
|
+
return (0, ts_pattern.match)(provider).with("postgresql", () => new kysely.PostgresDialect({ pool: new pg.Pool({
|
|
311
|
+
...TEST_PG_CONFIG,
|
|
312
|
+
database: dbName
|
|
313
|
+
}) })).with("mysql", () => new kysely.MysqlDialect({ pool: (0, mysql2.createPool)({
|
|
314
|
+
...TEST_MYSQL_CONFIG,
|
|
315
|
+
database: dbName
|
|
316
|
+
}) })).with("sqlite", () => new kysely.SqliteDialect({ database: new better_sqlite3.default(node_path.default.join(workDir, dbName)) })).exhaustive();
|
|
450
317
|
}
|
|
451
|
-
__name(createDialect, "createDialect");
|
|
452
318
|
async function prepareDatabase(provider, dbName) {
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
319
|
+
if (provider === "postgresql") {
|
|
320
|
+
(0, _zenstackhq_common_helpers.invariant)(dbName, "dbName is required");
|
|
321
|
+
const pgClient = new pg.Client(TEST_PG_CONFIG);
|
|
322
|
+
await pgClient.connect();
|
|
323
|
+
await pgClient.query(`DROP DATABASE IF EXISTS "${dbName}"`);
|
|
324
|
+
await pgClient.query(`CREATE DATABASE "${dbName}"`);
|
|
325
|
+
await pgClient.end();
|
|
326
|
+
} else if (provider === "mysql") {
|
|
327
|
+
(0, _zenstackhq_common_helpers.invariant)(dbName, "dbName is required");
|
|
328
|
+
const mysqlPool = (0, mysql2.createPool)(TEST_MYSQL_CONFIG);
|
|
329
|
+
await mysqlPool.promise().query(`DROP DATABASE IF EXISTS \`${dbName}\``);
|
|
330
|
+
await mysqlPool.promise().query(`CREATE DATABASE \`${dbName}\``);
|
|
331
|
+
await mysqlPool.promise().end();
|
|
332
|
+
}
|
|
467
333
|
}
|
|
468
|
-
__name(prepareDatabase, "prepareDatabase");
|
|
469
334
|
async function createPolicyTestClient(schema, options) {
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
new import_plugin_policy.PolicyPlugin()
|
|
475
|
-
]
|
|
476
|
-
});
|
|
335
|
+
return createTestClient(schema, {
|
|
336
|
+
...options,
|
|
337
|
+
plugins: [...options?.plugins ?? [], new _zenstackhq_plugin_policy.PolicyPlugin()]
|
|
338
|
+
});
|
|
477
339
|
}
|
|
478
|
-
__name(createPolicyTestClient, "createPolicyTestClient");
|
|
479
340
|
function testLogger(e) {
|
|
480
|
-
|
|
341
|
+
console.log(e.query.sql, e.query.parameters);
|
|
481
342
|
}
|
|
482
|
-
__name(testLogger, "testLogger");
|
|
483
343
|
function getTestDbName(provider) {
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
const digest = (0, import_node_crypto2.createHash)("md5").update(testName + testPath).digest("hex");
|
|
490
|
-
return "test_" + testName.toLowerCase().replace(/[^a-z0-9_]/g, "_").replace(/_+/g, "_").substring(0, 30) + digest.slice(0, 6);
|
|
344
|
+
if (provider === "sqlite") return "./test.db";
|
|
345
|
+
const testName = vitest.expect.getState().currentTestName ?? "unnamed";
|
|
346
|
+
const testPath = vitest.expect.getState().testPath ?? "";
|
|
347
|
+
const digest = (0, node_crypto.createHash)("md5").update(testName + testPath).digest("hex");
|
|
348
|
+
return "test_" + testName.toLowerCase().replace(/[^a-z0-9_]/g, "_").replace(/_+/g, "_").substring(0, 30) + digest.slice(0, 6);
|
|
491
349
|
}
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
// src/vitest-ext.ts
|
|
495
|
-
var import_orm2 = require("@zenstackhq/orm");
|
|
496
|
-
var import_vitest3 = require("vitest");
|
|
350
|
+
//#endregion
|
|
351
|
+
//#region src/vitest-ext.ts
|
|
497
352
|
function isPromise(value) {
|
|
498
|
-
|
|
353
|
+
return typeof value.then === "function" && typeof value.catch === "function";
|
|
499
354
|
}
|
|
500
|
-
__name(isPromise, "isPromise");
|
|
501
355
|
function expectErrorReason(err, errorReason) {
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
pass: false
|
|
511
|
-
};
|
|
512
|
-
}
|
|
356
|
+
if (err instanceof _zenstackhq_orm.ORMError && err.reason === errorReason) return {
|
|
357
|
+
message: () => "",
|
|
358
|
+
pass: true
|
|
359
|
+
};
|
|
360
|
+
else return {
|
|
361
|
+
message: () => `expected ORMError of reason ${errorReason}, got ${err}`,
|
|
362
|
+
pass: false
|
|
363
|
+
};
|
|
513
364
|
}
|
|
514
|
-
__name(expectErrorReason, "expectErrorReason");
|
|
515
365
|
function expectErrorMessages(expectedMessages, message) {
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
pass: false
|
|
521
|
-
};
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
return void 0;
|
|
366
|
+
for (const m of expectedMessages) if (!message.toLowerCase().includes(m.toLowerCase())) return {
|
|
367
|
+
message: () => `expected message not found in error: ${m}, got message: ${message}`,
|
|
368
|
+
pass: false
|
|
369
|
+
};
|
|
525
370
|
}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
}
|
|
621
|
-
try {
|
|
622
|
-
await received;
|
|
623
|
-
} catch (err) {
|
|
624
|
-
if (expectedMessages && err instanceof import_orm2.ORMError && err.reason === import_orm2.ORMErrorReason.INVALID_INPUT) {
|
|
625
|
-
const r = expectErrorMessages(expectedMessages, err.message || "");
|
|
626
|
-
if (r) {
|
|
627
|
-
return r;
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
return expectErrorReason(err, import_orm2.ORMErrorReason.INVALID_INPUT);
|
|
631
|
-
}
|
|
632
|
-
return {
|
|
633
|
-
message: /* @__PURE__ */ __name(() => `expected InputValidationError, got no error`, "message"),
|
|
634
|
-
pass: false
|
|
635
|
-
};
|
|
636
|
-
}
|
|
637
|
-
});
|
|
638
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
639
|
-
0 && (module.exports = {
|
|
640
|
-
TEST_MYSQL_CONFIG,
|
|
641
|
-
TEST_MYSQL_URL,
|
|
642
|
-
TEST_PG_CONFIG,
|
|
643
|
-
TEST_PG_URL,
|
|
644
|
-
createPolicyTestClient,
|
|
645
|
-
createTestClient,
|
|
646
|
-
createTestProject,
|
|
647
|
-
generateTsSchema,
|
|
648
|
-
generateTsSchemaFromFile,
|
|
649
|
-
generateTsSchemaInPlace,
|
|
650
|
-
getTestDbProvider,
|
|
651
|
-
loadSchema,
|
|
652
|
-
loadSchemaWithError,
|
|
653
|
-
testLogger
|
|
371
|
+
vitest.expect.extend({
|
|
372
|
+
async toResolveTruthy(received) {
|
|
373
|
+
if (!isPromise(received)) return {
|
|
374
|
+
message: () => "a promise is expected",
|
|
375
|
+
pass: false
|
|
376
|
+
};
|
|
377
|
+
const r = await received;
|
|
378
|
+
return {
|
|
379
|
+
pass: !!r,
|
|
380
|
+
message: () => `Expected promise to resolve to a truthy value, but got ${r}`
|
|
381
|
+
};
|
|
382
|
+
},
|
|
383
|
+
async toResolveFalsy(received) {
|
|
384
|
+
if (!isPromise(received)) return {
|
|
385
|
+
message: () => "a promise is expected",
|
|
386
|
+
pass: false
|
|
387
|
+
};
|
|
388
|
+
const r = await received;
|
|
389
|
+
return {
|
|
390
|
+
pass: !r,
|
|
391
|
+
message: () => `Expected promise to resolve to a falsy value, but got ${r}`
|
|
392
|
+
};
|
|
393
|
+
},
|
|
394
|
+
async toResolveNull(received) {
|
|
395
|
+
if (!isPromise(received)) return {
|
|
396
|
+
message: () => "a promise is expected",
|
|
397
|
+
pass: false
|
|
398
|
+
};
|
|
399
|
+
const r = await received;
|
|
400
|
+
return {
|
|
401
|
+
pass: r === null,
|
|
402
|
+
message: () => `Expected promise to resolve to a null value, but got ${r}`
|
|
403
|
+
};
|
|
404
|
+
},
|
|
405
|
+
async toResolveWithLength(received, length) {
|
|
406
|
+
const r = await received;
|
|
407
|
+
return {
|
|
408
|
+
pass: Array.isArray(r) && r.length === length,
|
|
409
|
+
message: () => `Expected promise to resolve with an array with length ${length}, but got ${r}`
|
|
410
|
+
};
|
|
411
|
+
},
|
|
412
|
+
async toBeRejectedNotFound(received) {
|
|
413
|
+
if (!isPromise(received)) return {
|
|
414
|
+
message: () => "a promise is expected",
|
|
415
|
+
pass: false
|
|
416
|
+
};
|
|
417
|
+
try {
|
|
418
|
+
await received;
|
|
419
|
+
} catch (err) {
|
|
420
|
+
return expectErrorReason(err, _zenstackhq_orm.ORMErrorReason.NOT_FOUND);
|
|
421
|
+
}
|
|
422
|
+
return {
|
|
423
|
+
message: () => `expected NotFoundError, got no error`,
|
|
424
|
+
pass: false
|
|
425
|
+
};
|
|
426
|
+
},
|
|
427
|
+
async toBeRejectedByPolicy(received, expectedMessages) {
|
|
428
|
+
if (!isPromise(received)) return {
|
|
429
|
+
message: () => "a promise is expected",
|
|
430
|
+
pass: false
|
|
431
|
+
};
|
|
432
|
+
try {
|
|
433
|
+
await received;
|
|
434
|
+
} catch (err) {
|
|
435
|
+
if (expectedMessages && err instanceof _zenstackhq_orm.ORMError && err.reason === _zenstackhq_orm.ORMErrorReason.REJECTED_BY_POLICY) {
|
|
436
|
+
const r = expectErrorMessages(expectedMessages, err.message || "");
|
|
437
|
+
if (r) return r;
|
|
438
|
+
}
|
|
439
|
+
return expectErrorReason(err, _zenstackhq_orm.ORMErrorReason.REJECTED_BY_POLICY);
|
|
440
|
+
}
|
|
441
|
+
return {
|
|
442
|
+
message: () => `expected PolicyError, got no error`,
|
|
443
|
+
pass: false
|
|
444
|
+
};
|
|
445
|
+
},
|
|
446
|
+
async toBeRejectedByValidation(received, expectedMessages) {
|
|
447
|
+
if (!isPromise(received)) return {
|
|
448
|
+
message: () => "a promise is expected",
|
|
449
|
+
pass: false
|
|
450
|
+
};
|
|
451
|
+
try {
|
|
452
|
+
await received;
|
|
453
|
+
} catch (err) {
|
|
454
|
+
if (expectedMessages && err instanceof _zenstackhq_orm.ORMError && err.reason === _zenstackhq_orm.ORMErrorReason.INVALID_INPUT) {
|
|
455
|
+
const r = expectErrorMessages(expectedMessages, err.message || "");
|
|
456
|
+
if (r) return r;
|
|
457
|
+
}
|
|
458
|
+
return expectErrorReason(err, _zenstackhq_orm.ORMErrorReason.INVALID_INPUT);
|
|
459
|
+
}
|
|
460
|
+
return {
|
|
461
|
+
message: () => `expected InputValidationError, got no error`,
|
|
462
|
+
pass: false
|
|
463
|
+
};
|
|
464
|
+
}
|
|
654
465
|
});
|
|
466
|
+
//#endregion
|
|
467
|
+
exports.TEST_MYSQL_CONFIG = TEST_MYSQL_CONFIG;
|
|
468
|
+
exports.TEST_MYSQL_URL = TEST_MYSQL_URL;
|
|
469
|
+
exports.TEST_PG_CONFIG = TEST_PG_CONFIG;
|
|
470
|
+
exports.TEST_PG_URL = TEST_PG_URL;
|
|
471
|
+
exports.createPolicyTestClient = createPolicyTestClient;
|
|
472
|
+
exports.createTestClient = createTestClient;
|
|
473
|
+
exports.createTestProject = createTestProject;
|
|
474
|
+
exports.generateTsSchema = generateTsSchema;
|
|
475
|
+
exports.generateTsSchemaFromFile = generateTsSchemaFromFile;
|
|
476
|
+
exports.generateTsSchemaInPlace = generateTsSchemaInPlace;
|
|
477
|
+
exports.getTestDbProvider = getTestDbProvider;
|
|
478
|
+
exports.loadSchema = loadSchema;
|
|
479
|
+
exports.loadSchemaWithError = loadSchemaWithError;
|
|
480
|
+
exports.testLogger = testLogger;
|
|
481
|
+
|
|
655
482
|
//# sourceMappingURL=index.cjs.map
|