@skmdev/prisma-fixtures 0.1.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/LICENSE +21 -0
- package/NOTICE +29 -0
- package/README.md +631 -0
- package/dist/cleanup-options.d.ts +5 -0
- package/dist/cleanup-options.js +19 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +342 -0
- package/dist/fixture-config.d.ts +14 -0
- package/dist/fixture-config.js +95 -0
- package/dist/fixture-document.d.ts +23 -0
- package/dist/fixture-document.js +349 -0
- package/dist/fixture-error.d.ts +22 -0
- package/dist/fixture-error.js +54 -0
- package/dist/fixture-reference.d.ts +17 -0
- package/dist/fixture-reference.js +234 -0
- package/dist/fixture-schema.d.ts +10 -0
- package/dist/fixture-schema.js +243 -0
- package/dist/fixture-template.d.ts +14 -0
- package/dist/fixture-template.js +239 -0
- package/dist/generator.d.ts +2 -0
- package/dist/generator.js +25 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +257 -0
- package/dist/load-options.d.ts +11 -0
- package/dist/load-options.js +47 -0
- package/dist/prisma-config.d.ts +8 -0
- package/dist/prisma-config.js +111 -0
- package/package.json +83 -0
- package/schema/fixture.schema.json +119 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeCleanupOptions = normalizeCleanupOptions;
|
|
4
|
+
const fixture_document_1 = require("./fixture-document");
|
|
5
|
+
function normalizeCleanupOptions(value = {}) {
|
|
6
|
+
if (!(0, fixture_document_1.isFixtureRecord)(value) ||
|
|
7
|
+
Object.keys(value).some((key) => key !== 'preserveTables')) {
|
|
8
|
+
throw new Error('Invalid fixture cleanup options');
|
|
9
|
+
}
|
|
10
|
+
const preserveTables = value.preserveTables;
|
|
11
|
+
if (preserveTables === undefined)
|
|
12
|
+
return {};
|
|
13
|
+
if (!Array.isArray(preserveTables) ||
|
|
14
|
+
preserveTables.some((entry) => typeof entry !== 'string' || !/^[^.]+\.[^.]+$/.test(entry)) ||
|
|
15
|
+
new Set(preserveTables).size !== preserveTables.length) {
|
|
16
|
+
throw new Error('Invalid fixture cleanup options');
|
|
17
|
+
}
|
|
18
|
+
return { preserveTables };
|
|
19
|
+
}
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
+
const node_module_1 = require("node:module");
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
+
const node_url_1 = require("node:url");
|
|
11
|
+
const node_util_1 = require("node:util");
|
|
12
|
+
const ajv_1 = __importDefault(require("ajv"));
|
|
13
|
+
const fixture_document_1 = require("./fixture-document");
|
|
14
|
+
const fixture_error_1 = require("./fixture-error");
|
|
15
|
+
const fixture_reference_1 = require("./fixture-reference");
|
|
16
|
+
const load_options_1 = require("./load-options");
|
|
17
|
+
const prisma_config_1 = require("./prisma-config");
|
|
18
|
+
const fixture_config_1 = require("./fixture-config");
|
|
19
|
+
const index_1 = require("./index");
|
|
20
|
+
const help = `Usage: prisma-fixtures [path...] [--client <module>] [options]
|
|
21
|
+
prisma-fixtures init [fixtures-directory]
|
|
22
|
+
|
|
23
|
+
Load YAML/JSON fixtures using your Prisma client, in one transaction.
|
|
24
|
+
Defaults are read from .prisma-fixtures (JSON) and adjacent Prisma config.
|
|
25
|
+
A string client exports a client/factory; a config client object names generated Prisma output.
|
|
26
|
+
init creates a minimal config without overwriting existing config.
|
|
27
|
+
|
|
28
|
+
--config <file> Read a JSON config instead of .prisma-fixtures
|
|
29
|
+
--client <module> Path to your client module (.js, .cjs, .mjs, .ts)
|
|
30
|
+
--databaseUrl <url> Override Prisma config URL or pass to a client factory
|
|
31
|
+
--require <module> Preload a module; repeat for additional modules
|
|
32
|
+
--timeout <ms> Transaction timeout (default: 60000)
|
|
33
|
+
--seed <integer> Reproduce generated values and random references
|
|
34
|
+
--refDate <timestamp> Fix Faker relative dates (canonical UTC timestamp)
|
|
35
|
+
--clean Clear database data, preserving schema and migrations
|
|
36
|
+
--reset Clear database data, then load fixtures
|
|
37
|
+
--list List fixture names/entities without executing code
|
|
38
|
+
--lint Check fixture syntax/structure without executing code
|
|
39
|
+
--schema <file> Also validate --lint against a generated JSON Schema
|
|
40
|
+
--debug, -d Include error type/code, never record data or URLs
|
|
41
|
+
--no-color Accepted for compatibility; output is always plain
|
|
42
|
+
--version, -v Print the package version
|
|
43
|
+
--help, -h Show this help
|
|
44
|
+
`;
|
|
45
|
+
let stage = 'arguments';
|
|
46
|
+
let debug = false;
|
|
47
|
+
async function main() {
|
|
48
|
+
const { values, positionals } = parseCliArguments();
|
|
49
|
+
debug = values.debug ?? false;
|
|
50
|
+
const lint = values.lint ?? false;
|
|
51
|
+
if (values.help)
|
|
52
|
+
return void process.stdout.write(help);
|
|
53
|
+
if (values.version) {
|
|
54
|
+
const { version } = require('../package.json');
|
|
55
|
+
return void console.log(version);
|
|
56
|
+
}
|
|
57
|
+
if (positionals[0] === 'init') {
|
|
58
|
+
if (positionals.length > 2 || Object.keys(values).length !== 0) {
|
|
59
|
+
throw new Error('init accepts only an optional fixtures directory');
|
|
60
|
+
}
|
|
61
|
+
stage = 'initializing config';
|
|
62
|
+
return initializeConfig(positionals[1]);
|
|
63
|
+
}
|
|
64
|
+
stage = 'reading config';
|
|
65
|
+
const config = (0, fixture_config_1.readFixtureConfig)(values.config);
|
|
66
|
+
const targets = positionals.length ? positionals : (config.fixtures ?? []);
|
|
67
|
+
stage = 'arguments';
|
|
68
|
+
if ((!values.clean && targets.length === 0) ||
|
|
69
|
+
[values.list, lint, values.clean, values.reset].filter(Boolean).length > 1) {
|
|
70
|
+
process.stderr.write(help);
|
|
71
|
+
process.exitCode = 1;
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const timeout = Number(values.timeout ?? config.timeout ?? 60000);
|
|
75
|
+
if (!Number.isSafeInteger(timeout) || timeout <= 0) {
|
|
76
|
+
throw new Error('Invalid transaction timeout');
|
|
77
|
+
}
|
|
78
|
+
const cliSeed = values.seed;
|
|
79
|
+
if (cliSeed !== undefined && !/^\d+$/.test(cliSeed)) {
|
|
80
|
+
throw new Error('Invalid fixture load options');
|
|
81
|
+
}
|
|
82
|
+
const loadOptions = (0, load_options_1.normalizeLoadOptions)({
|
|
83
|
+
seed: cliSeed === undefined ? config.seed : Number(cliSeed),
|
|
84
|
+
refDate: values.refDate ?? config.refDate,
|
|
85
|
+
});
|
|
86
|
+
const schemaFile = values.schema ?? config.schema;
|
|
87
|
+
const validate = lint && schemaFile !== undefined
|
|
88
|
+
? readSchemaValidator(schemaFile)
|
|
89
|
+
: undefined;
|
|
90
|
+
stage = 'reading fixtures';
|
|
91
|
+
const definitions = values.clean ? [] : (0, fixture_document_1.readFixturePaths)(targets, validate);
|
|
92
|
+
if (lint) {
|
|
93
|
+
if (definitions.length > fixture_document_1.MAX_FIXTURE_DEFINITIONS) {
|
|
94
|
+
throw new fixture_document_1.FixtureDocumentError('Too many fixture definitions');
|
|
95
|
+
}
|
|
96
|
+
const { unresolved } = (0, fixture_reference_1.lintFixtureReferences)(definitions);
|
|
97
|
+
console.log(`Linted ${definitions.length} fixtures (syntax and structure${schemaFile === undefined ? '' : ', model schema'}, static references; ${unresolved} dynamic values or multi-candidate references unresolved).`);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (values.list) {
|
|
101
|
+
console.log(JSON.stringify(definitions.map(({ name, entity }) => ({ name, entity })), null, 2));
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const { client, guard, preserveTables } = await loadClient(config, values);
|
|
105
|
+
let count;
|
|
106
|
+
let operationError;
|
|
107
|
+
try {
|
|
108
|
+
if (typeof client.$transaction !== 'function') {
|
|
109
|
+
throw new Error('The client must implement $transaction');
|
|
110
|
+
}
|
|
111
|
+
stage = values.clean
|
|
112
|
+
? 'cleaning fixtures'
|
|
113
|
+
: values.reset
|
|
114
|
+
? 'resetting fixtures'
|
|
115
|
+
: 'loading fixtures';
|
|
116
|
+
const action = async (transaction) => {
|
|
117
|
+
if (values.clean) {
|
|
118
|
+
await (0, index_1.cleanFixtures)(transaction, {
|
|
119
|
+
preserveTables,
|
|
120
|
+
});
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
return values.reset
|
|
124
|
+
? (0, index_1.resetFixtures)(transaction, definitions, {
|
|
125
|
+
preserveTables,
|
|
126
|
+
...loadOptions,
|
|
127
|
+
})
|
|
128
|
+
: (0, index_1.loadFixtures)(transaction, definitions, loadOptions);
|
|
129
|
+
};
|
|
130
|
+
const records = guard
|
|
131
|
+
? await guard.fixtureTransaction(client, action, timeout)
|
|
132
|
+
: await client.$transaction(action, { timeout });
|
|
133
|
+
count = records === undefined ? 0 : Object.keys(records).length;
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
operationError = error;
|
|
137
|
+
throw error;
|
|
138
|
+
}
|
|
139
|
+
finally {
|
|
140
|
+
try {
|
|
141
|
+
if (operationError === undefined)
|
|
142
|
+
stage = 'disconnecting the client';
|
|
143
|
+
await client.$disconnect();
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
if (operationError === undefined)
|
|
147
|
+
throw error;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
console.log(values.clean
|
|
151
|
+
? 'Cleaned database data.'
|
|
152
|
+
: `${values.reset ? 'Reset and loaded' : 'Loaded'} ${count} fixtures.`);
|
|
153
|
+
}
|
|
154
|
+
function parseCliArguments() {
|
|
155
|
+
return (0, node_util_1.parseArgs)({
|
|
156
|
+
allowPositionals: true,
|
|
157
|
+
options: {
|
|
158
|
+
config: { type: 'string' },
|
|
159
|
+
client: { type: 'string' },
|
|
160
|
+
databaseUrl: { type: 'string' },
|
|
161
|
+
require: { type: 'string', multiple: true },
|
|
162
|
+
timeout: { type: 'string' },
|
|
163
|
+
seed: { type: 'string' },
|
|
164
|
+
refDate: { type: 'string' },
|
|
165
|
+
clean: { type: 'boolean' },
|
|
166
|
+
reset: { type: 'boolean' },
|
|
167
|
+
list: { type: 'boolean' },
|
|
168
|
+
lint: { type: 'boolean' },
|
|
169
|
+
schema: { type: 'string' },
|
|
170
|
+
debug: { type: 'boolean', short: 'd' },
|
|
171
|
+
'no-color': { type: 'boolean' },
|
|
172
|
+
version: { type: 'boolean', short: 'v' },
|
|
173
|
+
help: { type: 'boolean', short: 'h' },
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
function initializeConfig(directory) {
|
|
178
|
+
if (node_fs_1.default.existsSync('.prisma-fixtures')) {
|
|
179
|
+
console.error('.prisma-fixtures already exists; no changes made.');
|
|
180
|
+
process.exitCode = 1;
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
const fixtures = directory ??
|
|
184
|
+
(node_fs_1.default.existsSync('prisma/fixtures') ? './prisma/fixtures' : './fixtures');
|
|
185
|
+
if (directory) {
|
|
186
|
+
if (!node_fs_1.default.existsSync(fixtures) || !node_fs_1.default.statSync(fixtures).isDirectory()) {
|
|
187
|
+
console.error('Fixture directory does not exist; no changes made.');
|
|
188
|
+
process.exitCode = 1;
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
node_fs_1.default.mkdirSync(fixtures, { recursive: true });
|
|
194
|
+
}
|
|
195
|
+
node_fs_1.default.writeFileSync('.prisma-fixtures', `${JSON.stringify({ fixtures: [fixtures] }, null, 2)}\n`, { flag: 'wx' });
|
|
196
|
+
console.log(`Created .prisma-fixtures using ${fixtures}.`);
|
|
197
|
+
}
|
|
198
|
+
function readSchemaValidator(schemaFile) {
|
|
199
|
+
stage = 'reading schema';
|
|
200
|
+
const raw = node_fs_1.default.readFileSync(node_path_1.default.resolve(schemaFile), 'utf8');
|
|
201
|
+
let validate;
|
|
202
|
+
try {
|
|
203
|
+
validate = new ajv_1.default({ strict: false, validateFormats: false }).compile(JSON.parse(raw));
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
throw new fixture_document_1.FixtureDocumentError('Invalid fixture JSON Schema');
|
|
207
|
+
}
|
|
208
|
+
return (document, file) => {
|
|
209
|
+
if (validate(document))
|
|
210
|
+
return;
|
|
211
|
+
const error = validate.errors?.[0];
|
|
212
|
+
throw new fixture_document_1.FixtureDocumentError(`Fixture document ${JSON.stringify(node_path_1.default.basename(file))}: ${JSON.stringify(error?.instancePath || '/')} ${error?.message ?? 'does not match the schema'}`);
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
async function loadClient(config, values) {
|
|
216
|
+
stage = 'loading the client';
|
|
217
|
+
let clientConfig = values.client ? node_path_1.default.resolve(values.client) : config.client;
|
|
218
|
+
const requireFromCwd = (0, node_module_1.createRequire)(node_path_1.default.resolve('package.json'));
|
|
219
|
+
for (const preload of values.require ?? [])
|
|
220
|
+
requireFromCwd(preload);
|
|
221
|
+
let prismaDefaults;
|
|
222
|
+
if (!clientConfig) {
|
|
223
|
+
stage = 'loading Prisma config';
|
|
224
|
+
prismaDefaults = await (0, prisma_config_1.loadPrismaDefaults)(node_path_1.default.dirname(node_path_1.default.resolve(values.config ?? '.prisma-fixtures')), requireFromCwd, values.databaseUrl);
|
|
225
|
+
const clientExtension = node_path_1.default.extname(prismaDefaults.module);
|
|
226
|
+
if ((clientExtension === '.ts' || clientExtension === '.cts') &&
|
|
227
|
+
!require.extensions[clientExtension]) {
|
|
228
|
+
requireFromCwd('ts-node/register');
|
|
229
|
+
}
|
|
230
|
+
clientConfig = { module: prismaDefaults.module, adapter: 'pg' };
|
|
231
|
+
stage = 'loading the client';
|
|
232
|
+
}
|
|
233
|
+
const preserveTables = [
|
|
234
|
+
...new Set([
|
|
235
|
+
...(config.preserveTables ?? []),
|
|
236
|
+
...(prismaDefaults?.preserveTables ?? []),
|
|
237
|
+
]),
|
|
238
|
+
];
|
|
239
|
+
let candidate;
|
|
240
|
+
let guard;
|
|
241
|
+
if (typeof clientConfig === 'string') {
|
|
242
|
+
const imported = await import((0, node_url_1.pathToFileURL)(clientConfig).href);
|
|
243
|
+
let exported = imported.default;
|
|
244
|
+
if (exported && typeof exported === 'object' && 'default' in exported) {
|
|
245
|
+
exported = exported.default;
|
|
246
|
+
}
|
|
247
|
+
if (values.databaseUrl !== undefined && typeof exported !== 'function') {
|
|
248
|
+
throw new Error('--databaseUrl requires a client factory');
|
|
249
|
+
}
|
|
250
|
+
candidate =
|
|
251
|
+
typeof exported === 'function'
|
|
252
|
+
? await exported({ databaseUrl: values.databaseUrl })
|
|
253
|
+
: exported;
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
if (clientConfig.guard) {
|
|
257
|
+
const imported = requireFromCwd(clientConfig.guard);
|
|
258
|
+
if (!(0, fixture_document_1.isFixtureRecord)(imported) ||
|
|
259
|
+
typeof imported.fixtureDatabaseUrl !== 'function' ||
|
|
260
|
+
typeof imported.fixtureTransaction !== 'function') {
|
|
261
|
+
throw new Error('Invalid fixture guard module');
|
|
262
|
+
}
|
|
263
|
+
guard = imported;
|
|
264
|
+
}
|
|
265
|
+
const environment = {
|
|
266
|
+
...process.env,
|
|
267
|
+
...(values.databaseUrl === undefined
|
|
268
|
+
? {}
|
|
269
|
+
: { DATABASE_URL: values.databaseUrl }),
|
|
270
|
+
};
|
|
271
|
+
const databaseUrl = guard
|
|
272
|
+
? guard.fixtureDatabaseUrl(environment)
|
|
273
|
+
: (values.databaseUrl ??
|
|
274
|
+
prismaDefaults?.databaseUrl ??
|
|
275
|
+
environment.DATABASE_URL);
|
|
276
|
+
if (typeof databaseUrl !== 'string' || !databaseUrl.trim()) {
|
|
277
|
+
throw new Error('DATABASE_URL is required');
|
|
278
|
+
}
|
|
279
|
+
const generated = await importGeneratedClient(clientConfig.module, requireFromCwd);
|
|
280
|
+
candidate = createGeneratedClient(generated, requireFromCwd, databaseUrl);
|
|
281
|
+
}
|
|
282
|
+
if (!candidate ||
|
|
283
|
+
typeof candidate !== 'object' ||
|
|
284
|
+
!('$disconnect' in candidate) ||
|
|
285
|
+
typeof candidate.$disconnect !== 'function') {
|
|
286
|
+
throw new Error('The client must implement $disconnect');
|
|
287
|
+
}
|
|
288
|
+
return { client: candidate, guard, preserveTables };
|
|
289
|
+
}
|
|
290
|
+
function createGeneratedClient(generated, requireFromCwd, databaseUrl) {
|
|
291
|
+
const clientExports = (0, fixture_document_1.isFixtureRecord)(generated) ? generated : undefined;
|
|
292
|
+
const defaultExport = (0, fixture_document_1.isFixtureRecord)(clientExports?.default)
|
|
293
|
+
? clientExports.default
|
|
294
|
+
: undefined;
|
|
295
|
+
const PrismaClient = clientExports?.PrismaClient ?? defaultExport?.PrismaClient;
|
|
296
|
+
const adapter = requireFromCwd('@prisma/adapter-pg');
|
|
297
|
+
if (typeof PrismaClient !== 'function' ||
|
|
298
|
+
typeof adapter.PrismaPg !== 'function') {
|
|
299
|
+
throw new Error('Invalid generated Prisma client or pg adapter');
|
|
300
|
+
}
|
|
301
|
+
return new PrismaClient({
|
|
302
|
+
adapter: new adapter.PrismaPg({ connectionString: databaseUrl }),
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
async function importGeneratedClient(modulePath, requireFromCwd) {
|
|
306
|
+
try {
|
|
307
|
+
return requireFromCwd(modulePath);
|
|
308
|
+
}
|
|
309
|
+
catch (error) {
|
|
310
|
+
if (error === null ||
|
|
311
|
+
typeof error !== 'object' ||
|
|
312
|
+
!('code' in error) ||
|
|
313
|
+
!['ERR_REQUIRE_ESM', 'ERR_REQUIRE_ASYNC_MODULE'].includes(String(error.code))) {
|
|
314
|
+
throw error;
|
|
315
|
+
}
|
|
316
|
+
return import((0, node_url_1.pathToFileURL)(modulePath).href);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
main().catch((error) => {
|
|
320
|
+
if ((0, fixture_error_1.isTrustedFixtureError)(error)) {
|
|
321
|
+
console.error(formatFixtureError(error));
|
|
322
|
+
process.exitCode = 1;
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
// Prisma and user hooks can put database URLs or record data in messages/stacks.
|
|
326
|
+
const details = debug && error instanceof Error
|
|
327
|
+
? ` (${error.name.replace(/[^A-Za-z0-9_]/g, '').slice(0, 60)})`
|
|
328
|
+
: '';
|
|
329
|
+
console.error(`Fixture command failed during ${stage}${details}.`);
|
|
330
|
+
process.exitCode = 1;
|
|
331
|
+
});
|
|
332
|
+
function formatFixtureError(error) {
|
|
333
|
+
const location = [error.file, error.fixtureName, error.path]
|
|
334
|
+
.filter((value) => value !== undefined)
|
|
335
|
+
.map((value) => JSON.stringify(value))
|
|
336
|
+
.join(' ');
|
|
337
|
+
const output = `Fixture command failed during ${error.stage} [${error.code}]: ${location}${location ? ' ' : ''}${error.message}.`;
|
|
338
|
+
const suffix = '… [truncated]';
|
|
339
|
+
return output.length <= 4096
|
|
340
|
+
? output
|
|
341
|
+
: `${output.slice(0, 4096 - suffix.length)}${suffix}`;
|
|
342
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type FixtureCleanupOptions } from './cleanup-options';
|
|
2
|
+
import { type FixtureLoadOptions } from './load-options';
|
|
3
|
+
export type ConfiguredPrismaClient = {
|
|
4
|
+
module: string;
|
|
5
|
+
adapter: 'pg';
|
|
6
|
+
guard?: string;
|
|
7
|
+
};
|
|
8
|
+
export type FixtureConfig = FixtureCleanupOptions & FixtureLoadOptions & {
|
|
9
|
+
fixtures?: string[];
|
|
10
|
+
client?: string | ConfiguredPrismaClient;
|
|
11
|
+
timeout?: number;
|
|
12
|
+
schema?: string;
|
|
13
|
+
};
|
|
14
|
+
export declare function readFixtureConfig(file?: string): FixtureConfig;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.readFixtureConfig = readFixtureConfig;
|
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const cleanup_options_1 = require("./cleanup-options");
|
|
10
|
+
const fixture_document_1 = require("./fixture-document");
|
|
11
|
+
const load_options_1 = require("./load-options");
|
|
12
|
+
function readFixtureConfig(file) {
|
|
13
|
+
const configFile = node_path_1.default.resolve(file ?? '.prisma-fixtures');
|
|
14
|
+
let raw;
|
|
15
|
+
try {
|
|
16
|
+
raw = node_fs_1.default.readFileSync(configFile, 'utf8');
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
if (file === undefined &&
|
|
20
|
+
error instanceof Error &&
|
|
21
|
+
'code' in error &&
|
|
22
|
+
error.code === 'ENOENT') {
|
|
23
|
+
return {};
|
|
24
|
+
}
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
const config = JSON.parse(raw);
|
|
28
|
+
if (!(0, fixture_document_1.isFixtureRecord)(config) ||
|
|
29
|
+
Object.keys(config).some((key) => ![
|
|
30
|
+
'fixtures',
|
|
31
|
+
'client',
|
|
32
|
+
'timeout',
|
|
33
|
+
'schema',
|
|
34
|
+
'preserveTables',
|
|
35
|
+
'seed',
|
|
36
|
+
'refDate',
|
|
37
|
+
].includes(key))) {
|
|
38
|
+
throw new Error('Invalid fixture CLI config');
|
|
39
|
+
}
|
|
40
|
+
const { fixtures, client, timeout, schema, preserveTables, seed, refDate } = config;
|
|
41
|
+
if ((fixtures !== undefined &&
|
|
42
|
+
(!Array.isArray(fixtures) ||
|
|
43
|
+
!fixtures.length ||
|
|
44
|
+
!fixtures.every(isPath))) ||
|
|
45
|
+
(client !== undefined && !isClientConfig(client)) ||
|
|
46
|
+
(schema !== undefined && !isPath(schema)) ||
|
|
47
|
+
(timeout !== undefined &&
|
|
48
|
+
(typeof timeout !== 'number' ||
|
|
49
|
+
!Number.isSafeInteger(timeout) ||
|
|
50
|
+
timeout <= 0))) {
|
|
51
|
+
throw new Error('Invalid fixture CLI config');
|
|
52
|
+
}
|
|
53
|
+
let cleanup;
|
|
54
|
+
let load;
|
|
55
|
+
try {
|
|
56
|
+
cleanup = (0, cleanup_options_1.normalizeCleanupOptions)({ preserveTables });
|
|
57
|
+
load = (0, load_options_1.normalizeLoadOptions)({ seed, refDate });
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
throw new Error('Invalid fixture CLI config');
|
|
61
|
+
}
|
|
62
|
+
const directory = node_path_1.default.dirname(configFile);
|
|
63
|
+
return {
|
|
64
|
+
fixtures: fixtures?.map((target) => node_path_1.default.resolve(directory, target)),
|
|
65
|
+
client: resolveClientPaths(client, directory),
|
|
66
|
+
timeout,
|
|
67
|
+
schema: schema === undefined ? undefined : node_path_1.default.resolve(directory, schema),
|
|
68
|
+
...cleanup,
|
|
69
|
+
...load,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function isPath(value) {
|
|
73
|
+
return typeof value === 'string' && value.trim().length > 0;
|
|
74
|
+
}
|
|
75
|
+
function isClientConfig(value) {
|
|
76
|
+
return (isPath(value) ||
|
|
77
|
+
((0, fixture_document_1.isFixtureRecord)(value) &&
|
|
78
|
+
Object.keys(value).every((key) => ['module', 'adapter', 'guard'].includes(key)) &&
|
|
79
|
+
isPath(value.module) &&
|
|
80
|
+
value.adapter === 'pg' &&
|
|
81
|
+
(value.guard === undefined || isPath(value.guard))));
|
|
82
|
+
}
|
|
83
|
+
function resolveClientPaths(client, directory) {
|
|
84
|
+
if (client === undefined)
|
|
85
|
+
return undefined;
|
|
86
|
+
if (typeof client === 'string')
|
|
87
|
+
return node_path_1.default.resolve(directory, client);
|
|
88
|
+
return {
|
|
89
|
+
module: node_path_1.default.resolve(directory, client.module),
|
|
90
|
+
adapter: 'pg',
|
|
91
|
+
...(client.guard === undefined
|
|
92
|
+
? {}
|
|
93
|
+
: { guard: node_path_1.default.resolve(directory, client.guard) }),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { FixtureError, type FixtureErrorContext } from './fixture-error';
|
|
2
|
+
export declare class FixtureDocumentError extends FixtureError {
|
|
3
|
+
constructor(message: string, context?: Partial<FixtureErrorContext>, cause?: unknown);
|
|
4
|
+
}
|
|
5
|
+
export type FixtureDefinition = {
|
|
6
|
+
name: string;
|
|
7
|
+
entity: string;
|
|
8
|
+
data: Record<string, unknown>;
|
|
9
|
+
parameters: Record<string, unknown>;
|
|
10
|
+
processor?: string;
|
|
11
|
+
locale?: string;
|
|
12
|
+
connectedFields?: string[];
|
|
13
|
+
deferredFields?: string[];
|
|
14
|
+
};
|
|
15
|
+
export declare function fixtureErrorContext(fixture: FixtureDefinition | undefined, stage: string, path?: string): FixtureErrorContext;
|
|
16
|
+
export declare function inheritFixtureSource(source: FixtureDefinition, target: FixtureDefinition): void;
|
|
17
|
+
export declare const MAX_FIXTURE_DEFINITIONS = 2000;
|
|
18
|
+
export declare const DANGEROUS_KEYS: Set<string>;
|
|
19
|
+
export declare function readFixturePaths(targets: string[], validateDocument?: (value: unknown, file: string) => void): FixtureDefinition[];
|
|
20
|
+
export declare function readFixtureDocuments(targetPath: string, validateDocument?: (value: unknown, file: string) => void): FixtureDefinition[];
|
|
21
|
+
export declare function assertFixtureDefinition(value: unknown): asserts value is FixtureDefinition;
|
|
22
|
+
export declare function isFixtureRecord(value: unknown): value is Record<string, unknown>;
|
|
23
|
+
export declare function assertSafeFixtureValue(value: unknown): void;
|