prisma-flare 1.1.0 → 1.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/dist/cli/db-migrate.cjs +3 -3
- package/dist/cli/db-migrate.js +3 -3
- package/dist/cli/index.cjs +48 -10
- package/dist/cli/index.js +48 -10
- package/dist/core/flareBuilder.d.cts +4 -4
- package/dist/core/flareBuilder.d.ts +4 -4
- package/dist/index.cjs +110 -144
- package/dist/index.d.cts +24 -15
- package/dist/index.d.ts +24 -15
- package/dist/index.js +114 -148
- package/package.json +1 -1
- package/readme.md +42 -23
package/dist/cli/db-migrate.cjs
CHANGED
|
@@ -86,7 +86,7 @@ function parseRelations(schemaContent, models) {
|
|
|
86
86
|
if (fieldMatch) {
|
|
87
87
|
const fieldName = fieldMatch[1];
|
|
88
88
|
const fieldType = fieldMatch[2];
|
|
89
|
-
const
|
|
89
|
+
const _isArray = !!fieldMatch[3];
|
|
90
90
|
if (models.includes(fieldType)) {
|
|
91
91
|
const modelRelations = relations.get(modelName) || [];
|
|
92
92
|
modelRelations.push({ fieldName, targetModel: fieldType });
|
|
@@ -188,7 +188,7 @@ export default class ${model} extends FlareBuilder<'${modelCamel}'> {
|
|
|
188
188
|
registrationLines.push(`modelRegistry.register('${modelCamel}', ${model});`);
|
|
189
189
|
registrationLines.push(`modelRegistry.register('${modelPlural}', ${model});`);
|
|
190
190
|
});
|
|
191
|
-
relations.forEach((rels,
|
|
191
|
+
relations.forEach((rels, _modelName) => {
|
|
192
192
|
rels.forEach((rel) => {
|
|
193
193
|
registrationLines.push(`modelRegistry.register('${rel.fieldName}', ${rel.targetModel});`);
|
|
194
194
|
});
|
|
@@ -255,7 +255,7 @@ exports.DB = DB;
|
|
|
255
255
|
relationMapEntries.push(` ${modelCamel}: ${model};`);
|
|
256
256
|
relationMapEntries.push(` ${modelPlural}: ${model};`);
|
|
257
257
|
});
|
|
258
|
-
relations.forEach((rels,
|
|
258
|
+
relations.forEach((rels, _modelName) => {
|
|
259
259
|
rels.forEach((rel) => {
|
|
260
260
|
const entry = ` ${rel.fieldName}: ${rel.targetModel};`;
|
|
261
261
|
if (!relationMapEntries.includes(entry)) {
|
package/dist/cli/db-migrate.js
CHANGED
|
@@ -63,7 +63,7 @@ function parseRelations(schemaContent, models) {
|
|
|
63
63
|
if (fieldMatch) {
|
|
64
64
|
const fieldName = fieldMatch[1];
|
|
65
65
|
const fieldType = fieldMatch[2];
|
|
66
|
-
const
|
|
66
|
+
const _isArray = !!fieldMatch[3];
|
|
67
67
|
if (models.includes(fieldType)) {
|
|
68
68
|
const modelRelations = relations.get(modelName) || [];
|
|
69
69
|
modelRelations.push({ fieldName, targetModel: fieldType });
|
|
@@ -165,7 +165,7 @@ export default class ${model} extends FlareBuilder<'${modelCamel}'> {
|
|
|
165
165
|
registrationLines.push(`modelRegistry.register('${modelCamel}', ${model});`);
|
|
166
166
|
registrationLines.push(`modelRegistry.register('${modelPlural}', ${model});`);
|
|
167
167
|
});
|
|
168
|
-
relations.forEach((rels,
|
|
168
|
+
relations.forEach((rels, _modelName) => {
|
|
169
169
|
rels.forEach((rel) => {
|
|
170
170
|
registrationLines.push(`modelRegistry.register('${rel.fieldName}', ${rel.targetModel});`);
|
|
171
171
|
});
|
|
@@ -232,7 +232,7 @@ exports.DB = DB;
|
|
|
232
232
|
relationMapEntries.push(` ${modelCamel}: ${model};`);
|
|
233
233
|
relationMapEntries.push(` ${modelPlural}: ${model};`);
|
|
234
234
|
});
|
|
235
|
-
relations.forEach((rels,
|
|
235
|
+
relations.forEach((rels, _modelName) => {
|
|
236
236
|
rels.forEach((rel) => {
|
|
237
237
|
const entry = ` ${rel.fieldName}: ${rel.targetModel};`;
|
|
238
238
|
if (!relationMapEntries.includes(entry)) {
|
package/dist/cli/index.cjs
CHANGED
|
@@ -83,7 +83,7 @@ function parseRelations(schemaContent, models) {
|
|
|
83
83
|
if (fieldMatch) {
|
|
84
84
|
const fieldName = fieldMatch[1];
|
|
85
85
|
const fieldType = fieldMatch[2];
|
|
86
|
-
const
|
|
86
|
+
const _isArray = !!fieldMatch[3];
|
|
87
87
|
if (models.includes(fieldType)) {
|
|
88
88
|
const modelRelations = relations.get(modelName) || [];
|
|
89
89
|
modelRelations.push({ fieldName, targetModel: fieldType });
|
|
@@ -185,7 +185,7 @@ export default class ${model} extends FlareBuilder<'${modelCamel}'> {
|
|
|
185
185
|
registrationLines.push(`modelRegistry.register('${modelCamel}', ${model});`);
|
|
186
186
|
registrationLines.push(`modelRegistry.register('${modelPlural}', ${model});`);
|
|
187
187
|
});
|
|
188
|
-
relations.forEach((rels,
|
|
188
|
+
relations.forEach((rels, _modelName) => {
|
|
189
189
|
rels.forEach((rel) => {
|
|
190
190
|
registrationLines.push(`modelRegistry.register('${rel.fieldName}', ${rel.targetModel});`);
|
|
191
191
|
});
|
|
@@ -252,7 +252,7 @@ exports.DB = DB;
|
|
|
252
252
|
relationMapEntries.push(` ${modelCamel}: ${model};`);
|
|
253
253
|
relationMapEntries.push(` ${modelPlural}: ${model};`);
|
|
254
254
|
});
|
|
255
|
-
relations.forEach((rels,
|
|
255
|
+
relations.forEach((rels, _modelName) => {
|
|
256
256
|
rels.forEach((rel) => {
|
|
257
257
|
const entry = ` ${rel.fieldName}: ${rel.targetModel};`;
|
|
258
258
|
if (!relationMapEntries.includes(entry)) {
|
|
@@ -283,15 +283,52 @@ ${gettersTypes}
|
|
|
283
283
|
fs2.writeFileSync(generatedDtsPath, generatedDtsContent);
|
|
284
284
|
}
|
|
285
285
|
|
|
286
|
+
// src/cli/generate-callbacks.ts
|
|
287
|
+
var fs3 = __toESM(require("fs"), 1);
|
|
288
|
+
var path3 = __toESM(require("path"), 1);
|
|
289
|
+
function generateCallbacksIndex() {
|
|
290
|
+
const rootDir = findProjectRoot(process.cwd());
|
|
291
|
+
const config = loadConfig(rootDir);
|
|
292
|
+
const callbacksDir = path3.join(rootDir, config.callbacksPath);
|
|
293
|
+
if (!fs3.existsSync(callbacksDir)) {
|
|
294
|
+
console.log(`\u2139\uFE0F Callbacks directory not found: ${callbacksDir}`);
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
const files = fs3.readdirSync(callbacksDir);
|
|
298
|
+
const callbackFiles = files.filter((file) => {
|
|
299
|
+
if (file === "index.ts" || file === "index.js" || file.startsWith(".")) {
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
return file.endsWith(".ts") || file.endsWith(".js");
|
|
303
|
+
});
|
|
304
|
+
if (callbackFiles.length === 0) {
|
|
305
|
+
console.log(`\u2139\uFE0F No callback files found in: ${callbacksDir}`);
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
const imports = callbackFiles.map((file) => {
|
|
309
|
+
const basename = file.replace(/\.(ts|js)$/, "");
|
|
310
|
+
return `import './${basename}';`;
|
|
311
|
+
}).join("\n");
|
|
312
|
+
const content = `// AUTO-GENERATED by prisma-flare - DO NOT EDIT
|
|
313
|
+
// This file imports all callbacks to ensure they are registered.
|
|
314
|
+
// Re-run 'npx prisma-flare generate' after adding new callback files.
|
|
315
|
+
|
|
316
|
+
${imports}
|
|
317
|
+
`;
|
|
318
|
+
const indexPath = path3.join(callbacksDir, "index.ts");
|
|
319
|
+
fs3.writeFileSync(indexPath, content);
|
|
320
|
+
console.log(`\u2705 Generated callbacks index: ${callbacksDir}/index.ts (${callbackFiles.length} callbacks)`);
|
|
321
|
+
}
|
|
322
|
+
|
|
286
323
|
// src/cli/index.ts
|
|
287
324
|
var import_child_process = require("child_process");
|
|
288
|
-
var
|
|
289
|
-
var
|
|
325
|
+
var path4 = __toESM(require("path"), 1);
|
|
326
|
+
var fs4 = __toESM(require("fs"), 1);
|
|
290
327
|
var import_url = require("url");
|
|
291
328
|
var import_meta = {};
|
|
292
329
|
var getDirname = () => {
|
|
293
330
|
try {
|
|
294
|
-
return
|
|
331
|
+
return path4.dirname((0, import_url.fileURLToPath)(import_meta.url));
|
|
295
332
|
} catch {
|
|
296
333
|
return __dirname;
|
|
297
334
|
}
|
|
@@ -313,6 +350,7 @@ if (!command) {
|
|
|
313
350
|
switch (command) {
|
|
314
351
|
case "generate":
|
|
315
352
|
generateQueries();
|
|
353
|
+
generateCallbacksIndex();
|
|
316
354
|
break;
|
|
317
355
|
case "create":
|
|
318
356
|
case "drop":
|
|
@@ -338,10 +376,10 @@ function runScript(scriptName) {
|
|
|
338
376
|
console.error(`No script found for ${scriptName}`);
|
|
339
377
|
return;
|
|
340
378
|
}
|
|
341
|
-
let scriptPath =
|
|
342
|
-
if (!
|
|
343
|
-
const cliScriptPath =
|
|
344
|
-
if (
|
|
379
|
+
let scriptPath = path4.join(__dirname_, file.replace(".ts", ".js"));
|
|
380
|
+
if (!fs4.existsSync(scriptPath)) {
|
|
381
|
+
const cliScriptPath = path4.join(__dirname_, "cli", file.replace(".ts", ".js"));
|
|
382
|
+
if (fs4.existsSync(cliScriptPath)) {
|
|
345
383
|
scriptPath = cliScriptPath;
|
|
346
384
|
}
|
|
347
385
|
}
|
package/dist/cli/index.js
CHANGED
|
@@ -60,7 +60,7 @@ function parseRelations(schemaContent, models) {
|
|
|
60
60
|
if (fieldMatch) {
|
|
61
61
|
const fieldName = fieldMatch[1];
|
|
62
62
|
const fieldType = fieldMatch[2];
|
|
63
|
-
const
|
|
63
|
+
const _isArray = !!fieldMatch[3];
|
|
64
64
|
if (models.includes(fieldType)) {
|
|
65
65
|
const modelRelations = relations.get(modelName) || [];
|
|
66
66
|
modelRelations.push({ fieldName, targetModel: fieldType });
|
|
@@ -162,7 +162,7 @@ export default class ${model} extends FlareBuilder<'${modelCamel}'> {
|
|
|
162
162
|
registrationLines.push(`modelRegistry.register('${modelCamel}', ${model});`);
|
|
163
163
|
registrationLines.push(`modelRegistry.register('${modelPlural}', ${model});`);
|
|
164
164
|
});
|
|
165
|
-
relations.forEach((rels,
|
|
165
|
+
relations.forEach((rels, _modelName) => {
|
|
166
166
|
rels.forEach((rel) => {
|
|
167
167
|
registrationLines.push(`modelRegistry.register('${rel.fieldName}', ${rel.targetModel});`);
|
|
168
168
|
});
|
|
@@ -229,7 +229,7 @@ exports.DB = DB;
|
|
|
229
229
|
relationMapEntries.push(` ${modelCamel}: ${model};`);
|
|
230
230
|
relationMapEntries.push(` ${modelPlural}: ${model};`);
|
|
231
231
|
});
|
|
232
|
-
relations.forEach((rels,
|
|
232
|
+
relations.forEach((rels, _modelName) => {
|
|
233
233
|
rels.forEach((rel) => {
|
|
234
234
|
const entry = ` ${rel.fieldName}: ${rel.targetModel};`;
|
|
235
235
|
if (!relationMapEntries.includes(entry)) {
|
|
@@ -260,14 +260,51 @@ ${gettersTypes}
|
|
|
260
260
|
fs2.writeFileSync(generatedDtsPath, generatedDtsContent);
|
|
261
261
|
}
|
|
262
262
|
|
|
263
|
+
// src/cli/generate-callbacks.ts
|
|
264
|
+
import * as fs3 from "fs";
|
|
265
|
+
import * as path3 from "path";
|
|
266
|
+
function generateCallbacksIndex() {
|
|
267
|
+
const rootDir = findProjectRoot(process.cwd());
|
|
268
|
+
const config = loadConfig(rootDir);
|
|
269
|
+
const callbacksDir = path3.join(rootDir, config.callbacksPath);
|
|
270
|
+
if (!fs3.existsSync(callbacksDir)) {
|
|
271
|
+
console.log(`\u2139\uFE0F Callbacks directory not found: ${callbacksDir}`);
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
const files = fs3.readdirSync(callbacksDir);
|
|
275
|
+
const callbackFiles = files.filter((file) => {
|
|
276
|
+
if (file === "index.ts" || file === "index.js" || file.startsWith(".")) {
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
return file.endsWith(".ts") || file.endsWith(".js");
|
|
280
|
+
});
|
|
281
|
+
if (callbackFiles.length === 0) {
|
|
282
|
+
console.log(`\u2139\uFE0F No callback files found in: ${callbacksDir}`);
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
const imports = callbackFiles.map((file) => {
|
|
286
|
+
const basename = file.replace(/\.(ts|js)$/, "");
|
|
287
|
+
return `import './${basename}';`;
|
|
288
|
+
}).join("\n");
|
|
289
|
+
const content = `// AUTO-GENERATED by prisma-flare - DO NOT EDIT
|
|
290
|
+
// This file imports all callbacks to ensure they are registered.
|
|
291
|
+
// Re-run 'npx prisma-flare generate' after adding new callback files.
|
|
292
|
+
|
|
293
|
+
${imports}
|
|
294
|
+
`;
|
|
295
|
+
const indexPath = path3.join(callbacksDir, "index.ts");
|
|
296
|
+
fs3.writeFileSync(indexPath, content);
|
|
297
|
+
console.log(`\u2705 Generated callbacks index: ${callbacksDir}/index.ts (${callbackFiles.length} callbacks)`);
|
|
298
|
+
}
|
|
299
|
+
|
|
263
300
|
// src/cli/index.ts
|
|
264
301
|
import { spawn } from "child_process";
|
|
265
|
-
import * as
|
|
266
|
-
import * as
|
|
302
|
+
import * as path4 from "path";
|
|
303
|
+
import * as fs4 from "fs";
|
|
267
304
|
import { fileURLToPath } from "url";
|
|
268
305
|
var getDirname = () => {
|
|
269
306
|
try {
|
|
270
|
-
return
|
|
307
|
+
return path4.dirname(fileURLToPath(import.meta.url));
|
|
271
308
|
} catch {
|
|
272
309
|
return __dirname;
|
|
273
310
|
}
|
|
@@ -289,6 +326,7 @@ if (!command) {
|
|
|
289
326
|
switch (command) {
|
|
290
327
|
case "generate":
|
|
291
328
|
generateQueries();
|
|
329
|
+
generateCallbacksIndex();
|
|
292
330
|
break;
|
|
293
331
|
case "create":
|
|
294
332
|
case "drop":
|
|
@@ -314,10 +352,10 @@ function runScript(scriptName) {
|
|
|
314
352
|
console.error(`No script found for ${scriptName}`);
|
|
315
353
|
return;
|
|
316
354
|
}
|
|
317
|
-
let scriptPath =
|
|
318
|
-
if (!
|
|
319
|
-
const cliScriptPath =
|
|
320
|
-
if (
|
|
355
|
+
let scriptPath = path4.join(__dirname_, file.replace(".ts", ".js"));
|
|
356
|
+
if (!fs4.existsSync(scriptPath)) {
|
|
357
|
+
const cliScriptPath = path4.join(__dirname_, "cli", file.replace(".ts", ".js"));
|
|
358
|
+
if (fs4.existsSync(cliScriptPath)) {
|
|
321
359
|
scriptPath = cliScriptPath;
|
|
322
360
|
}
|
|
323
361
|
}
|
|
@@ -20,12 +20,12 @@ interface RelationModelMap {
|
|
|
20
20
|
/**
|
|
21
21
|
* Helper type to get the model class for a relation name
|
|
22
22
|
*/
|
|
23
|
-
type GetRelationModel<K extends string> = K extends keyof RelationModelMap ? RelationModelMap[K] : FlareBuilder<any,
|
|
23
|
+
type GetRelationModel<K extends string> = K extends keyof RelationModelMap ? RelationModelMap[K] : FlareBuilder<any, Record<string, never>>;
|
|
24
24
|
/**
|
|
25
25
|
* FlareBuilder for chainable Prisma queries with full type safety
|
|
26
26
|
* The type safety is enforced through the ModelDelegate parameter
|
|
27
27
|
*/
|
|
28
|
-
declare class FlareBuilder<T extends ModelName, Args extends Record<string, any> =
|
|
28
|
+
declare class FlareBuilder<T extends ModelName, Args extends Record<string, any> = Record<string, never>> {
|
|
29
29
|
protected model: ModelDelegate<T>;
|
|
30
30
|
protected query: QueryArgs;
|
|
31
31
|
constructor(model: ModelDelegate<T>, query?: QueryArgs);
|
|
@@ -122,7 +122,7 @@ declare class FlareBuilder<T extends ModelName, Args extends Record<string, any>
|
|
|
122
122
|
* , 'OR')
|
|
123
123
|
* .findMany()
|
|
124
124
|
*/
|
|
125
|
-
whereGroup(callback: (builder: FlareBuilder<T,
|
|
125
|
+
whereGroup(callback: (builder: FlareBuilder<T, Record<string, never>>) => FlareBuilder<T, any>, mode?: 'AND' | 'OR'): FlareBuilder<T, Args & {
|
|
126
126
|
where: WhereInput<T>;
|
|
127
127
|
}>;
|
|
128
128
|
/**
|
|
@@ -141,7 +141,7 @@ declare class FlareBuilder<T extends ModelName, Args extends Record<string, any>
|
|
|
141
141
|
* )
|
|
142
142
|
* .findMany()
|
|
143
143
|
*/
|
|
144
|
-
orWhereGroup(callback: (builder: FlareBuilder<T,
|
|
144
|
+
orWhereGroup(callback: (builder: FlareBuilder<T, Record<string, never>>) => FlareBuilder<T, any>): FlareBuilder<T, Args & {
|
|
145
145
|
where: WhereInput<T>;
|
|
146
146
|
}>;
|
|
147
147
|
/**
|
|
@@ -20,12 +20,12 @@ interface RelationModelMap {
|
|
|
20
20
|
/**
|
|
21
21
|
* Helper type to get the model class for a relation name
|
|
22
22
|
*/
|
|
23
|
-
type GetRelationModel<K extends string> = K extends keyof RelationModelMap ? RelationModelMap[K] : FlareBuilder<any,
|
|
23
|
+
type GetRelationModel<K extends string> = K extends keyof RelationModelMap ? RelationModelMap[K] : FlareBuilder<any, Record<string, never>>;
|
|
24
24
|
/**
|
|
25
25
|
* FlareBuilder for chainable Prisma queries with full type safety
|
|
26
26
|
* The type safety is enforced through the ModelDelegate parameter
|
|
27
27
|
*/
|
|
28
|
-
declare class FlareBuilder<T extends ModelName, Args extends Record<string, any> =
|
|
28
|
+
declare class FlareBuilder<T extends ModelName, Args extends Record<string, any> = Record<string, never>> {
|
|
29
29
|
protected model: ModelDelegate<T>;
|
|
30
30
|
protected query: QueryArgs;
|
|
31
31
|
constructor(model: ModelDelegate<T>, query?: QueryArgs);
|
|
@@ -122,7 +122,7 @@ declare class FlareBuilder<T extends ModelName, Args extends Record<string, any>
|
|
|
122
122
|
* , 'OR')
|
|
123
123
|
* .findMany()
|
|
124
124
|
*/
|
|
125
|
-
whereGroup(callback: (builder: FlareBuilder<T,
|
|
125
|
+
whereGroup(callback: (builder: FlareBuilder<T, Record<string, never>>) => FlareBuilder<T, any>, mode?: 'AND' | 'OR'): FlareBuilder<T, Args & {
|
|
126
126
|
where: WhereInput<T>;
|
|
127
127
|
}>;
|
|
128
128
|
/**
|
|
@@ -141,7 +141,7 @@ declare class FlareBuilder<T extends ModelName, Args extends Record<string, any>
|
|
|
141
141
|
* )
|
|
142
142
|
* .findMany()
|
|
143
143
|
*/
|
|
144
|
-
orWhereGroup(callback: (builder: FlareBuilder<T,
|
|
144
|
+
orWhereGroup(callback: (builder: FlareBuilder<T, Record<string, never>>) => FlareBuilder<T, any>): FlareBuilder<T, Args & {
|
|
145
145
|
where: WhereInput<T>;
|
|
146
146
|
}>;
|
|
147
147
|
/**
|
package/dist/index.cjs
CHANGED
|
@@ -52,7 +52,7 @@ __export(index_exports, {
|
|
|
52
52
|
module.exports = __toCommonJS(index_exports);
|
|
53
53
|
|
|
54
54
|
// src/core/extendedPrismaClient.ts
|
|
55
|
-
var
|
|
55
|
+
var import_client2 = require("@prisma/client");
|
|
56
56
|
|
|
57
57
|
// src/core/modelRegistry.ts
|
|
58
58
|
var ModelRegistry = class {
|
|
@@ -710,53 +710,6 @@ var FlareBuilder = class _FlareBuilder {
|
|
|
710
710
|
}
|
|
711
711
|
};
|
|
712
712
|
|
|
713
|
-
// src/core/extendedPrismaClient.ts
|
|
714
|
-
var FlareClient = class extends import_client.PrismaClient {
|
|
715
|
-
constructor(options = {}) {
|
|
716
|
-
super(options);
|
|
717
|
-
}
|
|
718
|
-
/**
|
|
719
|
-
* Creates a new FlareBuilder instance for the specified model.
|
|
720
|
-
* @param modelName - The name of the model.
|
|
721
|
-
* @returns FlareBuilder instance
|
|
722
|
-
*/
|
|
723
|
-
from(modelName) {
|
|
724
|
-
const key = modelName.charAt(0).toLowerCase() + modelName.slice(1);
|
|
725
|
-
const model = this[key];
|
|
726
|
-
if (!model) {
|
|
727
|
-
throw new Error(`Model ${modelName} does not exist on PrismaClient.`);
|
|
728
|
-
}
|
|
729
|
-
return new FlareBuilder(model);
|
|
730
|
-
}
|
|
731
|
-
/**
|
|
732
|
-
* Executes a transaction with the FlareClient capabilities.
|
|
733
|
-
* @param fn - The transaction function.
|
|
734
|
-
* @param options - Transaction options.
|
|
735
|
-
* @returns The result of the transaction.
|
|
736
|
-
*/
|
|
737
|
-
async transaction(fn, options) {
|
|
738
|
-
return super.$transaction(async (tx) => {
|
|
739
|
-
const extendedTx = new Proxy(tx, {
|
|
740
|
-
get: (target, prop, receiver) => {
|
|
741
|
-
if (prop === "from") {
|
|
742
|
-
return (modelName) => {
|
|
743
|
-
const key = modelName.charAt(0).toLowerCase() + modelName.slice(1);
|
|
744
|
-
const model = target[key];
|
|
745
|
-
if (!model) {
|
|
746
|
-
throw new Error(`Model ${modelName} does not exist on TransactionClient.`);
|
|
747
|
-
}
|
|
748
|
-
return new FlareBuilder(model);
|
|
749
|
-
};
|
|
750
|
-
}
|
|
751
|
-
return Reflect.get(target, prop, receiver);
|
|
752
|
-
}
|
|
753
|
-
});
|
|
754
|
-
return fn(extendedTx);
|
|
755
|
-
}, options);
|
|
756
|
-
}
|
|
757
|
-
};
|
|
758
|
-
var ExtendedPrismaClient = FlareClient;
|
|
759
|
-
|
|
760
713
|
// src/core/hookRegistry.ts
|
|
761
714
|
function valuesEqual(a, b) {
|
|
762
715
|
if (a == null && b == null) return true;
|
|
@@ -928,74 +881,8 @@ var HookRegistry = class {
|
|
|
928
881
|
var hookRegistry = new HookRegistry();
|
|
929
882
|
var hookRegistry_default = hookRegistry;
|
|
930
883
|
|
|
931
|
-
// src/core/hooks.ts
|
|
932
|
-
function normalizeModelName(model) {
|
|
933
|
-
return model.toLowerCase();
|
|
934
|
-
}
|
|
935
|
-
function beforeCreate(model, callback) {
|
|
936
|
-
hookRegistry_default.addHook(normalizeModelName(model), "create", "before", callback);
|
|
937
|
-
}
|
|
938
|
-
function beforeDelete(model, callback) {
|
|
939
|
-
hookRegistry_default.addHook(normalizeModelName(model), "delete", "before", callback);
|
|
940
|
-
}
|
|
941
|
-
function afterCreate(model, callback) {
|
|
942
|
-
hookRegistry_default.addHook(normalizeModelName(model), "create", "after", callback);
|
|
943
|
-
}
|
|
944
|
-
function afterDelete(model, callback) {
|
|
945
|
-
hookRegistry_default.addHook(normalizeModelName(model), "delete", "after", callback);
|
|
946
|
-
}
|
|
947
|
-
function beforeUpdate(model, callback) {
|
|
948
|
-
hookRegistry_default.addHook(normalizeModelName(model), "update", "before", callback);
|
|
949
|
-
}
|
|
950
|
-
function afterUpdate(model, callback) {
|
|
951
|
-
hookRegistry_default.addHook(normalizeModelName(model), "update", "after", callback);
|
|
952
|
-
}
|
|
953
|
-
function afterChange(model, column, callback) {
|
|
954
|
-
hookRegistry_default.addColumnHook(normalizeModelName(model), column, callback);
|
|
955
|
-
}
|
|
956
|
-
function afterUpsert(model, callback) {
|
|
957
|
-
hookRegistry_default.addHook(normalizeModelName(model), "upsert", "after", callback);
|
|
958
|
-
}
|
|
959
|
-
|
|
960
|
-
// src/core/hookMiddleware.ts
|
|
961
|
-
var import_client2 = require("@prisma/client");
|
|
962
|
-
|
|
963
|
-
// src/cli/config.ts
|
|
964
|
-
var fs = __toESM(require("fs"), 1);
|
|
965
|
-
var path = __toESM(require("path"), 1);
|
|
966
|
-
function findProjectRoot(currentDir) {
|
|
967
|
-
if (fs.existsSync(path.join(currentDir, "package.json"))) {
|
|
968
|
-
return currentDir;
|
|
969
|
-
}
|
|
970
|
-
const parentDir = path.dirname(currentDir);
|
|
971
|
-
if (parentDir === currentDir) {
|
|
972
|
-
throw new Error("Could not find package.json");
|
|
973
|
-
}
|
|
974
|
-
return findProjectRoot(parentDir);
|
|
975
|
-
}
|
|
976
|
-
function loadConfig(rootDir) {
|
|
977
|
-
const projectRoot = rootDir || findProjectRoot(process.cwd());
|
|
978
|
-
const configPath = path.join(projectRoot, "prisma-flare.config.json");
|
|
979
|
-
let config = {
|
|
980
|
-
modelsPath: "prisma/models",
|
|
981
|
-
dbPath: "prisma/db",
|
|
982
|
-
callbacksPath: "prisma/callbacks"
|
|
983
|
-
};
|
|
984
|
-
if (fs.existsSync(configPath)) {
|
|
985
|
-
try {
|
|
986
|
-
const configFile = fs.readFileSync(configPath, "utf-8");
|
|
987
|
-
const userConfig = JSON.parse(configFile);
|
|
988
|
-
config = { ...config, ...userConfig };
|
|
989
|
-
} catch {
|
|
990
|
-
console.warn("\u26A0\uFE0F Could not read prisma-flare.config.json, using defaults.");
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
|
-
return {
|
|
994
|
-
...config
|
|
995
|
-
};
|
|
996
|
-
}
|
|
997
|
-
|
|
998
884
|
// src/core/hookMiddleware.ts
|
|
885
|
+
var import_client = require("@prisma/client");
|
|
999
886
|
var import_fs = __toESM(require("fs"), 1);
|
|
1000
887
|
var import_path = __toESM(require("path"), 1);
|
|
1001
888
|
function supportsTypeScriptImports() {
|
|
@@ -1094,7 +981,7 @@ function supportsPrisma6Middleware(prisma) {
|
|
|
1094
981
|
return typeof prisma.$use === "function";
|
|
1095
982
|
}
|
|
1096
983
|
function createHooksExtension(basePrisma) {
|
|
1097
|
-
return
|
|
984
|
+
return import_client.Prisma.defineExtension({
|
|
1098
985
|
name: "prisma-flare-hooks",
|
|
1099
986
|
query: {
|
|
1100
987
|
$allModels: {
|
|
@@ -1117,23 +1004,102 @@ function registerHooksLegacy(prisma) {
|
|
|
1117
1004
|
return executeHookLogic(prisma, model, action, args, () => next(params));
|
|
1118
1005
|
});
|
|
1119
1006
|
}
|
|
1120
|
-
|
|
1121
|
-
let client;
|
|
1007
|
+
function registerHooks(prisma) {
|
|
1122
1008
|
if (supportsPrisma6Middleware(prisma)) {
|
|
1123
1009
|
registerHooksLegacy(prisma);
|
|
1124
|
-
|
|
1010
|
+
return prisma;
|
|
1125
1011
|
} else {
|
|
1126
1012
|
const extension = createHooksExtension(prisma);
|
|
1127
|
-
|
|
1013
|
+
return prisma.$extends(extension);
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
// src/core/extendedPrismaClient.ts
|
|
1018
|
+
function supportsPrisma6Middleware2(prisma) {
|
|
1019
|
+
return typeof prisma.$use === "function";
|
|
1020
|
+
}
|
|
1021
|
+
var FlareClient = class extends import_client2.PrismaClient {
|
|
1022
|
+
constructor(options = {}) {
|
|
1023
|
+
const { callbacks = true, ...prismaOptions } = options;
|
|
1024
|
+
super(prismaOptions);
|
|
1025
|
+
if (callbacks) {
|
|
1026
|
+
if (supportsPrisma6Middleware2(this)) {
|
|
1027
|
+
registerHooksLegacy(this);
|
|
1028
|
+
} else {
|
|
1029
|
+
const extension = createHooksExtension(this);
|
|
1030
|
+
return this.$extends(extension);
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
/**
|
|
1035
|
+
* Creates a new FlareBuilder instance for the specified model.
|
|
1036
|
+
* @param modelName - The name of the model.
|
|
1037
|
+
* @returns FlareBuilder instance
|
|
1038
|
+
*/
|
|
1039
|
+
from(modelName) {
|
|
1040
|
+
const key = modelName.charAt(0).toLowerCase() + modelName.slice(1);
|
|
1041
|
+
const model = this[key];
|
|
1042
|
+
if (!model) {
|
|
1043
|
+
throw new Error(`Model ${modelName} does not exist on PrismaClient.`);
|
|
1044
|
+
}
|
|
1045
|
+
return new FlareBuilder(model);
|
|
1128
1046
|
}
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1047
|
+
/**
|
|
1048
|
+
* Executes a transaction with the FlareClient capabilities.
|
|
1049
|
+
* @param fn - The transaction function.
|
|
1050
|
+
* @param options - Transaction options.
|
|
1051
|
+
* @returns The result of the transaction.
|
|
1052
|
+
*/
|
|
1053
|
+
async transaction(fn, options) {
|
|
1054
|
+
return super.$transaction(async (tx) => {
|
|
1055
|
+
const extendedTx = new Proxy(tx, {
|
|
1056
|
+
get: (target, prop, receiver) => {
|
|
1057
|
+
if (prop === "from") {
|
|
1058
|
+
return (modelName) => {
|
|
1059
|
+
const key = modelName.charAt(0).toLowerCase() + modelName.slice(1);
|
|
1060
|
+
const model = target[key];
|
|
1061
|
+
if (!model) {
|
|
1062
|
+
throw new Error(`Model ${modelName} does not exist on TransactionClient.`);
|
|
1063
|
+
}
|
|
1064
|
+
return new FlareBuilder(model);
|
|
1065
|
+
};
|
|
1066
|
+
}
|
|
1067
|
+
return Reflect.get(target, prop, receiver);
|
|
1068
|
+
}
|
|
1069
|
+
});
|
|
1070
|
+
return fn(extendedTx);
|
|
1071
|
+
}, options);
|
|
1135
1072
|
}
|
|
1136
|
-
|
|
1073
|
+
};
|
|
1074
|
+
var ExtendedPrismaClient = FlareClient;
|
|
1075
|
+
|
|
1076
|
+
// src/core/hooks.ts
|
|
1077
|
+
function normalizeModelName(model) {
|
|
1078
|
+
return model.toLowerCase();
|
|
1079
|
+
}
|
|
1080
|
+
function beforeCreate(model, callback) {
|
|
1081
|
+
hookRegistry_default.addHook(normalizeModelName(model), "create", "before", callback);
|
|
1082
|
+
}
|
|
1083
|
+
function beforeDelete(model, callback) {
|
|
1084
|
+
hookRegistry_default.addHook(normalizeModelName(model), "delete", "before", callback);
|
|
1085
|
+
}
|
|
1086
|
+
function afterCreate(model, callback) {
|
|
1087
|
+
hookRegistry_default.addHook(normalizeModelName(model), "create", "after", callback);
|
|
1088
|
+
}
|
|
1089
|
+
function afterDelete(model, callback) {
|
|
1090
|
+
hookRegistry_default.addHook(normalizeModelName(model), "delete", "after", callback);
|
|
1091
|
+
}
|
|
1092
|
+
function beforeUpdate(model, callback) {
|
|
1093
|
+
hookRegistry_default.addHook(normalizeModelName(model), "update", "before", callback);
|
|
1094
|
+
}
|
|
1095
|
+
function afterUpdate(model, callback) {
|
|
1096
|
+
hookRegistry_default.addHook(normalizeModelName(model), "update", "after", callback);
|
|
1097
|
+
}
|
|
1098
|
+
function afterChange(model, column, callback) {
|
|
1099
|
+
hookRegistry_default.addColumnHook(normalizeModelName(model), column, callback);
|
|
1100
|
+
}
|
|
1101
|
+
function afterUpsert(model, callback) {
|
|
1102
|
+
hookRegistry_default.addHook(normalizeModelName(model), "upsert", "after", callback);
|
|
1137
1103
|
}
|
|
1138
1104
|
|
|
1139
1105
|
// src/core/adapters/postgres.ts
|
|
@@ -1216,8 +1182,8 @@ function parseDatabaseUrl(url) {
|
|
|
1216
1182
|
}
|
|
1217
1183
|
|
|
1218
1184
|
// src/core/adapters/sqlite.ts
|
|
1219
|
-
var
|
|
1220
|
-
var
|
|
1185
|
+
var fs2 = __toESM(require("fs"), 1);
|
|
1186
|
+
var path2 = __toESM(require("path"), 1);
|
|
1221
1187
|
var SqliteAdapter = {
|
|
1222
1188
|
name: "sqlite",
|
|
1223
1189
|
matches(url) {
|
|
@@ -1225,13 +1191,13 @@ var SqliteAdapter = {
|
|
|
1225
1191
|
},
|
|
1226
1192
|
async create(url) {
|
|
1227
1193
|
const filePath = parseSqliteUrl(url);
|
|
1228
|
-
const dir =
|
|
1194
|
+
const dir = path2.dirname(filePath);
|
|
1229
1195
|
try {
|
|
1230
|
-
if (!
|
|
1231
|
-
|
|
1196
|
+
if (!fs2.existsSync(dir)) {
|
|
1197
|
+
fs2.mkdirSync(dir, { recursive: true });
|
|
1232
1198
|
}
|
|
1233
|
-
if (!
|
|
1234
|
-
|
|
1199
|
+
if (!fs2.existsSync(filePath)) {
|
|
1200
|
+
fs2.writeFileSync(filePath, "");
|
|
1235
1201
|
console.log(`\u2705 SQLite database created at "${filePath}"`);
|
|
1236
1202
|
} else {
|
|
1237
1203
|
console.log(`\u26A0\uFE0F SQLite database already exists at "${filePath}"`);
|
|
@@ -1244,20 +1210,20 @@ var SqliteAdapter = {
|
|
|
1244
1210
|
async drop(url) {
|
|
1245
1211
|
const filePath = parseSqliteUrl(url);
|
|
1246
1212
|
try {
|
|
1247
|
-
if (
|
|
1248
|
-
|
|
1213
|
+
if (fs2.existsSync(filePath)) {
|
|
1214
|
+
fs2.unlinkSync(filePath);
|
|
1249
1215
|
console.log(`\u2705 SQLite database at "${filePath}" dropped successfully.`);
|
|
1250
1216
|
} else {
|
|
1251
1217
|
console.log(`\u26A0\uFE0F SQLite database does not exist at "${filePath}"`);
|
|
1252
1218
|
}
|
|
1253
|
-
if (
|
|
1254
|
-
|
|
1219
|
+
if (fs2.existsSync(`${filePath}-journal`)) {
|
|
1220
|
+
fs2.unlinkSync(`${filePath}-journal`);
|
|
1255
1221
|
}
|
|
1256
|
-
if (
|
|
1257
|
-
|
|
1222
|
+
if (fs2.existsSync(`${filePath}-wal`)) {
|
|
1223
|
+
fs2.unlinkSync(`${filePath}-wal`);
|
|
1258
1224
|
}
|
|
1259
|
-
if (
|
|
1260
|
-
|
|
1225
|
+
if (fs2.existsSync(`${filePath}-shm`)) {
|
|
1226
|
+
fs2.unlinkSync(`${filePath}-shm`);
|
|
1261
1227
|
}
|
|
1262
1228
|
} catch (error) {
|
|
1263
1229
|
console.error("\u274C Error dropping SQLite database:", error);
|
|
@@ -1267,8 +1233,8 @@ var SqliteAdapter = {
|
|
|
1267
1233
|
};
|
|
1268
1234
|
function parseSqliteUrl(url) {
|
|
1269
1235
|
let cleanPath = url.replace(/^file:/, "");
|
|
1270
|
-
if (!
|
|
1271
|
-
cleanPath =
|
|
1236
|
+
if (!path2.isAbsolute(cleanPath)) {
|
|
1237
|
+
cleanPath = path2.resolve(process.cwd(), cleanPath);
|
|
1272
1238
|
}
|
|
1273
1239
|
return cleanPath;
|
|
1274
1240
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -8,8 +8,18 @@ import { M as ModelName, l as PrismaOperation, m as HookTiming, B as BeforeHookC
|
|
|
8
8
|
export { r as AggregateResult, o as CreateArgs, C as CreateData, p as CreateManyArgs, b as CreateManyData, c as DeleteArgs, n as FindFirstArgs, F as FindManyArgs, a as ModelDelegate, R as RecordType, q as UpdateArgs, f as UpsertArgs } from './prisma.types-nGNe1CG8.cjs';
|
|
9
9
|
export { afterChange, afterCreate, afterDelete, afterUpdate, afterUpsert, beforeCreate, beforeDelete, beforeUpdate } from './core/hooks.cjs';
|
|
10
10
|
|
|
11
|
+
interface FlareClientOptions extends PrismaClientOptions {
|
|
12
|
+
/**
|
|
13
|
+
* Enable callbacks/hooks middleware. When true (default), the middleware
|
|
14
|
+
* that executes your registered callbacks (beforeCreate, afterUpdate, etc.)
|
|
15
|
+
* is automatically attached.
|
|
16
|
+
*
|
|
17
|
+
* @default true
|
|
18
|
+
*/
|
|
19
|
+
callbacks?: boolean;
|
|
20
|
+
}
|
|
11
21
|
declare class FlareClient extends PrismaClient {
|
|
12
|
-
constructor(options?:
|
|
22
|
+
constructor(options?: FlareClientOptions);
|
|
13
23
|
/**
|
|
14
24
|
* Creates a new FlareBuilder instance for the specified model.
|
|
15
25
|
* @param modelName - The name of the model.
|
|
@@ -186,22 +196,21 @@ declare function createHooksExtension(basePrisma: PrismaClient): (client: any) =
|
|
|
186
196
|
*/
|
|
187
197
|
declare function registerHooksLegacy(prisma: PrismaClient): void;
|
|
188
198
|
/**
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
* - Prisma ≤6: Uses $use middleware
|
|
192
|
-
* - Prisma 7+: Returns extended client with hooks extension
|
|
193
|
-
*
|
|
194
|
-
* Callbacks are loaded from the path specified in prisma-flare.config.json
|
|
195
|
-
* (defaults to 'prisma/callbacks'). Set `callbacksPath` in config to customize.
|
|
196
|
-
*
|
|
197
|
-
* @param prisma - The Prisma client instance
|
|
198
|
-
* @returns Promise resolving to the Prisma client (possibly extended for Prisma 7+)
|
|
199
|
+
* @deprecated Use `new FlareClient()` instead. FlareClient now automatically
|
|
200
|
+
* attaches the callbacks middleware. This function will be removed in a future version.
|
|
199
201
|
*
|
|
200
202
|
* @example
|
|
201
|
-
* //
|
|
202
|
-
*
|
|
203
|
+
* // Old way (deprecated):
|
|
204
|
+
* import './callbacks';
|
|
205
|
+
* import { FlareClient, registerHooks } from 'prisma-flare';
|
|
206
|
+
* export const db = registerHooks(new FlareClient());
|
|
207
|
+
*
|
|
208
|
+
* // New way:
|
|
209
|
+
* import './callbacks';
|
|
210
|
+
* import { FlareClient } from 'prisma-flare';
|
|
211
|
+
* export const db = new FlareClient();
|
|
203
212
|
*/
|
|
204
|
-
declare function registerHooks<T extends PrismaClient>(prisma: T):
|
|
213
|
+
declare function registerHooks<T extends PrismaClient>(prisma: T): T;
|
|
205
214
|
|
|
206
215
|
/**
|
|
207
216
|
* Database Adapter Interface
|
|
@@ -234,4 +243,4 @@ declare class AdapterRegistry {
|
|
|
234
243
|
}
|
|
235
244
|
declare const registry: AdapterRegistry;
|
|
236
245
|
|
|
237
|
-
export { AfterHookCallback, BeforeHookCallback, ColumnChangeCallback, type DatabaseAdapter, ExtendedPrismaClient, FlareBuilder, FlareClient, type HookConfig, HookTiming, ModelName, PrismaOperation, createHooksExtension, registry as dbAdapterRegistry, hookRegistry, loadCallbacks, modelRegistry, registerHooks, registerHooksLegacy };
|
|
246
|
+
export { AfterHookCallback, BeforeHookCallback, ColumnChangeCallback, type DatabaseAdapter, ExtendedPrismaClient, FlareBuilder, FlareClient, type FlareClientOptions, type HookConfig, HookTiming, ModelName, PrismaOperation, createHooksExtension, registry as dbAdapterRegistry, hookRegistry, loadCallbacks, modelRegistry, registerHooks, registerHooksLegacy };
|
package/dist/index.d.ts
CHANGED
|
@@ -8,8 +8,18 @@ import { M as ModelName, l as PrismaOperation, m as HookTiming, B as BeforeHookC
|
|
|
8
8
|
export { r as AggregateResult, o as CreateArgs, C as CreateData, p as CreateManyArgs, b as CreateManyData, c as DeleteArgs, n as FindFirstArgs, F as FindManyArgs, a as ModelDelegate, R as RecordType, q as UpdateArgs, f as UpsertArgs } from './prisma.types-nGNe1CG8.js';
|
|
9
9
|
export { afterChange, afterCreate, afterDelete, afterUpdate, afterUpsert, beforeCreate, beforeDelete, beforeUpdate } from './core/hooks.js';
|
|
10
10
|
|
|
11
|
+
interface FlareClientOptions extends PrismaClientOptions {
|
|
12
|
+
/**
|
|
13
|
+
* Enable callbacks/hooks middleware. When true (default), the middleware
|
|
14
|
+
* that executes your registered callbacks (beforeCreate, afterUpdate, etc.)
|
|
15
|
+
* is automatically attached.
|
|
16
|
+
*
|
|
17
|
+
* @default true
|
|
18
|
+
*/
|
|
19
|
+
callbacks?: boolean;
|
|
20
|
+
}
|
|
11
21
|
declare class FlareClient extends PrismaClient {
|
|
12
|
-
constructor(options?:
|
|
22
|
+
constructor(options?: FlareClientOptions);
|
|
13
23
|
/**
|
|
14
24
|
* Creates a new FlareBuilder instance for the specified model.
|
|
15
25
|
* @param modelName - The name of the model.
|
|
@@ -186,22 +196,21 @@ declare function createHooksExtension(basePrisma: PrismaClient): (client: any) =
|
|
|
186
196
|
*/
|
|
187
197
|
declare function registerHooksLegacy(prisma: PrismaClient): void;
|
|
188
198
|
/**
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
* - Prisma ≤6: Uses $use middleware
|
|
192
|
-
* - Prisma 7+: Returns extended client with hooks extension
|
|
193
|
-
*
|
|
194
|
-
* Callbacks are loaded from the path specified in prisma-flare.config.json
|
|
195
|
-
* (defaults to 'prisma/callbacks'). Set `callbacksPath` in config to customize.
|
|
196
|
-
*
|
|
197
|
-
* @param prisma - The Prisma client instance
|
|
198
|
-
* @returns Promise resolving to the Prisma client (possibly extended for Prisma 7+)
|
|
199
|
+
* @deprecated Use `new FlareClient()` instead. FlareClient now automatically
|
|
200
|
+
* attaches the callbacks middleware. This function will be removed in a future version.
|
|
199
201
|
*
|
|
200
202
|
* @example
|
|
201
|
-
* //
|
|
202
|
-
*
|
|
203
|
+
* // Old way (deprecated):
|
|
204
|
+
* import './callbacks';
|
|
205
|
+
* import { FlareClient, registerHooks } from 'prisma-flare';
|
|
206
|
+
* export const db = registerHooks(new FlareClient());
|
|
207
|
+
*
|
|
208
|
+
* // New way:
|
|
209
|
+
* import './callbacks';
|
|
210
|
+
* import { FlareClient } from 'prisma-flare';
|
|
211
|
+
* export const db = new FlareClient();
|
|
203
212
|
*/
|
|
204
|
-
declare function registerHooks<T extends PrismaClient>(prisma: T):
|
|
213
|
+
declare function registerHooks<T extends PrismaClient>(prisma: T): T;
|
|
205
214
|
|
|
206
215
|
/**
|
|
207
216
|
* Database Adapter Interface
|
|
@@ -234,4 +243,4 @@ declare class AdapterRegistry {
|
|
|
234
243
|
}
|
|
235
244
|
declare const registry: AdapterRegistry;
|
|
236
245
|
|
|
237
|
-
export { AfterHookCallback, BeforeHookCallback, ColumnChangeCallback, type DatabaseAdapter, ExtendedPrismaClient, FlareBuilder, FlareClient, type HookConfig, HookTiming, ModelName, PrismaOperation, createHooksExtension, registry as dbAdapterRegistry, hookRegistry, loadCallbacks, modelRegistry, registerHooks, registerHooksLegacy };
|
|
246
|
+
export { AfterHookCallback, BeforeHookCallback, ColumnChangeCallback, type DatabaseAdapter, ExtendedPrismaClient, FlareBuilder, FlareClient, type FlareClientOptions, type HookConfig, HookTiming, ModelName, PrismaOperation, createHooksExtension, registry as dbAdapterRegistry, hookRegistry, loadCallbacks, modelRegistry, registerHooks, registerHooksLegacy };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/core/extendedPrismaClient.ts
|
|
2
|
-
import { PrismaClient } from "@prisma/client";
|
|
2
|
+
import { PrismaClient as PrismaClient2 } from "@prisma/client";
|
|
3
3
|
|
|
4
4
|
// src/core/modelRegistry.ts
|
|
5
5
|
var ModelRegistry = class {
|
|
@@ -657,53 +657,6 @@ var FlareBuilder = class _FlareBuilder {
|
|
|
657
657
|
}
|
|
658
658
|
};
|
|
659
659
|
|
|
660
|
-
// src/core/extendedPrismaClient.ts
|
|
661
|
-
var FlareClient = class extends PrismaClient {
|
|
662
|
-
constructor(options = {}) {
|
|
663
|
-
super(options);
|
|
664
|
-
}
|
|
665
|
-
/**
|
|
666
|
-
* Creates a new FlareBuilder instance for the specified model.
|
|
667
|
-
* @param modelName - The name of the model.
|
|
668
|
-
* @returns FlareBuilder instance
|
|
669
|
-
*/
|
|
670
|
-
from(modelName) {
|
|
671
|
-
const key = modelName.charAt(0).toLowerCase() + modelName.slice(1);
|
|
672
|
-
const model = this[key];
|
|
673
|
-
if (!model) {
|
|
674
|
-
throw new Error(`Model ${modelName} does not exist on PrismaClient.`);
|
|
675
|
-
}
|
|
676
|
-
return new FlareBuilder(model);
|
|
677
|
-
}
|
|
678
|
-
/**
|
|
679
|
-
* Executes a transaction with the FlareClient capabilities.
|
|
680
|
-
* @param fn - The transaction function.
|
|
681
|
-
* @param options - Transaction options.
|
|
682
|
-
* @returns The result of the transaction.
|
|
683
|
-
*/
|
|
684
|
-
async transaction(fn, options) {
|
|
685
|
-
return super.$transaction(async (tx) => {
|
|
686
|
-
const extendedTx = new Proxy(tx, {
|
|
687
|
-
get: (target, prop, receiver) => {
|
|
688
|
-
if (prop === "from") {
|
|
689
|
-
return (modelName) => {
|
|
690
|
-
const key = modelName.charAt(0).toLowerCase() + modelName.slice(1);
|
|
691
|
-
const model = target[key];
|
|
692
|
-
if (!model) {
|
|
693
|
-
throw new Error(`Model ${modelName} does not exist on TransactionClient.`);
|
|
694
|
-
}
|
|
695
|
-
return new FlareBuilder(model);
|
|
696
|
-
};
|
|
697
|
-
}
|
|
698
|
-
return Reflect.get(target, prop, receiver);
|
|
699
|
-
}
|
|
700
|
-
});
|
|
701
|
-
return fn(extendedTx);
|
|
702
|
-
}, options);
|
|
703
|
-
}
|
|
704
|
-
};
|
|
705
|
-
var ExtendedPrismaClient = FlareClient;
|
|
706
|
-
|
|
707
660
|
// src/core/hookRegistry.ts
|
|
708
661
|
function valuesEqual(a, b) {
|
|
709
662
|
if (a == null && b == null) return true;
|
|
@@ -875,76 +828,10 @@ var HookRegistry = class {
|
|
|
875
828
|
var hookRegistry = new HookRegistry();
|
|
876
829
|
var hookRegistry_default = hookRegistry;
|
|
877
830
|
|
|
878
|
-
// src/core/hooks.ts
|
|
879
|
-
function normalizeModelName(model) {
|
|
880
|
-
return model.toLowerCase();
|
|
881
|
-
}
|
|
882
|
-
function beforeCreate(model, callback) {
|
|
883
|
-
hookRegistry_default.addHook(normalizeModelName(model), "create", "before", callback);
|
|
884
|
-
}
|
|
885
|
-
function beforeDelete(model, callback) {
|
|
886
|
-
hookRegistry_default.addHook(normalizeModelName(model), "delete", "before", callback);
|
|
887
|
-
}
|
|
888
|
-
function afterCreate(model, callback) {
|
|
889
|
-
hookRegistry_default.addHook(normalizeModelName(model), "create", "after", callback);
|
|
890
|
-
}
|
|
891
|
-
function afterDelete(model, callback) {
|
|
892
|
-
hookRegistry_default.addHook(normalizeModelName(model), "delete", "after", callback);
|
|
893
|
-
}
|
|
894
|
-
function beforeUpdate(model, callback) {
|
|
895
|
-
hookRegistry_default.addHook(normalizeModelName(model), "update", "before", callback);
|
|
896
|
-
}
|
|
897
|
-
function afterUpdate(model, callback) {
|
|
898
|
-
hookRegistry_default.addHook(normalizeModelName(model), "update", "after", callback);
|
|
899
|
-
}
|
|
900
|
-
function afterChange(model, column, callback) {
|
|
901
|
-
hookRegistry_default.addColumnHook(normalizeModelName(model), column, callback);
|
|
902
|
-
}
|
|
903
|
-
function afterUpsert(model, callback) {
|
|
904
|
-
hookRegistry_default.addHook(normalizeModelName(model), "upsert", "after", callback);
|
|
905
|
-
}
|
|
906
|
-
|
|
907
831
|
// src/core/hookMiddleware.ts
|
|
908
832
|
import { Prisma } from "@prisma/client";
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
import * as fs from "fs";
|
|
912
|
-
import * as path from "path";
|
|
913
|
-
function findProjectRoot(currentDir) {
|
|
914
|
-
if (fs.existsSync(path.join(currentDir, "package.json"))) {
|
|
915
|
-
return currentDir;
|
|
916
|
-
}
|
|
917
|
-
const parentDir = path.dirname(currentDir);
|
|
918
|
-
if (parentDir === currentDir) {
|
|
919
|
-
throw new Error("Could not find package.json");
|
|
920
|
-
}
|
|
921
|
-
return findProjectRoot(parentDir);
|
|
922
|
-
}
|
|
923
|
-
function loadConfig(rootDir) {
|
|
924
|
-
const projectRoot = rootDir || findProjectRoot(process.cwd());
|
|
925
|
-
const configPath = path.join(projectRoot, "prisma-flare.config.json");
|
|
926
|
-
let config = {
|
|
927
|
-
modelsPath: "prisma/models",
|
|
928
|
-
dbPath: "prisma/db",
|
|
929
|
-
callbacksPath: "prisma/callbacks"
|
|
930
|
-
};
|
|
931
|
-
if (fs.existsSync(configPath)) {
|
|
932
|
-
try {
|
|
933
|
-
const configFile = fs.readFileSync(configPath, "utf-8");
|
|
934
|
-
const userConfig = JSON.parse(configFile);
|
|
935
|
-
config = { ...config, ...userConfig };
|
|
936
|
-
} catch {
|
|
937
|
-
console.warn("\u26A0\uFE0F Could not read prisma-flare.config.json, using defaults.");
|
|
938
|
-
}
|
|
939
|
-
}
|
|
940
|
-
return {
|
|
941
|
-
...config
|
|
942
|
-
};
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
// src/core/hookMiddleware.ts
|
|
946
|
-
import fs2 from "fs";
|
|
947
|
-
import path2 from "path";
|
|
833
|
+
import fs from "fs";
|
|
834
|
+
import path from "path";
|
|
948
835
|
function supportsTypeScriptImports() {
|
|
949
836
|
if (process.env.TS_NODE || /* @__PURE__ */ Symbol.for("ts-node.register.instance") in process) {
|
|
950
837
|
return true;
|
|
@@ -962,16 +849,16 @@ function supportsTypeScriptImports() {
|
|
|
962
849
|
}
|
|
963
850
|
async function loadCallbacks(callbacksDir) {
|
|
964
851
|
if (!callbacksDir) {
|
|
965
|
-
callbacksDir =
|
|
852
|
+
callbacksDir = path.join(process.cwd(), "prisma", "callbacks");
|
|
966
853
|
}
|
|
967
|
-
if (!
|
|
854
|
+
if (!fs.existsSync(callbacksDir)) {
|
|
968
855
|
console.warn(`Callbacks directory not found: ${callbacksDir}`);
|
|
969
856
|
return;
|
|
970
857
|
}
|
|
971
858
|
const canImportTs = supportsTypeScriptImports();
|
|
972
|
-
const files =
|
|
859
|
+
const files = fs.readdirSync(callbacksDir);
|
|
973
860
|
for (const file of files) {
|
|
974
|
-
const filePath =
|
|
861
|
+
const filePath = path.join(callbacksDir, file);
|
|
975
862
|
if (file.endsWith(".js")) {
|
|
976
863
|
await import(filePath);
|
|
977
864
|
} else if (file.endsWith(".ts") && canImportTs) {
|
|
@@ -1064,23 +951,102 @@ function registerHooksLegacy(prisma) {
|
|
|
1064
951
|
return executeHookLogic(prisma, model, action, args, () => next(params));
|
|
1065
952
|
});
|
|
1066
953
|
}
|
|
1067
|
-
|
|
1068
|
-
let client;
|
|
954
|
+
function registerHooks(prisma) {
|
|
1069
955
|
if (supportsPrisma6Middleware(prisma)) {
|
|
1070
956
|
registerHooksLegacy(prisma);
|
|
1071
|
-
|
|
957
|
+
return prisma;
|
|
1072
958
|
} else {
|
|
1073
959
|
const extension = createHooksExtension(prisma);
|
|
1074
|
-
|
|
960
|
+
return prisma.$extends(extension);
|
|
1075
961
|
}
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
// src/core/extendedPrismaClient.ts
|
|
965
|
+
function supportsPrisma6Middleware2(prisma) {
|
|
966
|
+
return typeof prisma.$use === "function";
|
|
967
|
+
}
|
|
968
|
+
var FlareClient = class extends PrismaClient2 {
|
|
969
|
+
constructor(options = {}) {
|
|
970
|
+
const { callbacks = true, ...prismaOptions } = options;
|
|
971
|
+
super(prismaOptions);
|
|
972
|
+
if (callbacks) {
|
|
973
|
+
if (supportsPrisma6Middleware2(this)) {
|
|
974
|
+
registerHooksLegacy(this);
|
|
975
|
+
} else {
|
|
976
|
+
const extension = createHooksExtension(this);
|
|
977
|
+
return this.$extends(extension);
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
/**
|
|
982
|
+
* Creates a new FlareBuilder instance for the specified model.
|
|
983
|
+
* @param modelName - The name of the model.
|
|
984
|
+
* @returns FlareBuilder instance
|
|
985
|
+
*/
|
|
986
|
+
from(modelName) {
|
|
987
|
+
const key = modelName.charAt(0).toLowerCase() + modelName.slice(1);
|
|
988
|
+
const model = this[key];
|
|
989
|
+
if (!model) {
|
|
990
|
+
throw new Error(`Model ${modelName} does not exist on PrismaClient.`);
|
|
991
|
+
}
|
|
992
|
+
return new FlareBuilder(model);
|
|
993
|
+
}
|
|
994
|
+
/**
|
|
995
|
+
* Executes a transaction with the FlareClient capabilities.
|
|
996
|
+
* @param fn - The transaction function.
|
|
997
|
+
* @param options - Transaction options.
|
|
998
|
+
* @returns The result of the transaction.
|
|
999
|
+
*/
|
|
1000
|
+
async transaction(fn, options) {
|
|
1001
|
+
return super.$transaction(async (tx) => {
|
|
1002
|
+
const extendedTx = new Proxy(tx, {
|
|
1003
|
+
get: (target, prop, receiver) => {
|
|
1004
|
+
if (prop === "from") {
|
|
1005
|
+
return (modelName) => {
|
|
1006
|
+
const key = modelName.charAt(0).toLowerCase() + modelName.slice(1);
|
|
1007
|
+
const model = target[key];
|
|
1008
|
+
if (!model) {
|
|
1009
|
+
throw new Error(`Model ${modelName} does not exist on TransactionClient.`);
|
|
1010
|
+
}
|
|
1011
|
+
return new FlareBuilder(model);
|
|
1012
|
+
};
|
|
1013
|
+
}
|
|
1014
|
+
return Reflect.get(target, prop, receiver);
|
|
1015
|
+
}
|
|
1016
|
+
});
|
|
1017
|
+
return fn(extendedTx);
|
|
1018
|
+
}, options);
|
|
1082
1019
|
}
|
|
1083
|
-
|
|
1020
|
+
};
|
|
1021
|
+
var ExtendedPrismaClient = FlareClient;
|
|
1022
|
+
|
|
1023
|
+
// src/core/hooks.ts
|
|
1024
|
+
function normalizeModelName(model) {
|
|
1025
|
+
return model.toLowerCase();
|
|
1026
|
+
}
|
|
1027
|
+
function beforeCreate(model, callback) {
|
|
1028
|
+
hookRegistry_default.addHook(normalizeModelName(model), "create", "before", callback);
|
|
1029
|
+
}
|
|
1030
|
+
function beforeDelete(model, callback) {
|
|
1031
|
+
hookRegistry_default.addHook(normalizeModelName(model), "delete", "before", callback);
|
|
1032
|
+
}
|
|
1033
|
+
function afterCreate(model, callback) {
|
|
1034
|
+
hookRegistry_default.addHook(normalizeModelName(model), "create", "after", callback);
|
|
1035
|
+
}
|
|
1036
|
+
function afterDelete(model, callback) {
|
|
1037
|
+
hookRegistry_default.addHook(normalizeModelName(model), "delete", "after", callback);
|
|
1038
|
+
}
|
|
1039
|
+
function beforeUpdate(model, callback) {
|
|
1040
|
+
hookRegistry_default.addHook(normalizeModelName(model), "update", "before", callback);
|
|
1041
|
+
}
|
|
1042
|
+
function afterUpdate(model, callback) {
|
|
1043
|
+
hookRegistry_default.addHook(normalizeModelName(model), "update", "after", callback);
|
|
1044
|
+
}
|
|
1045
|
+
function afterChange(model, column, callback) {
|
|
1046
|
+
hookRegistry_default.addColumnHook(normalizeModelName(model), column, callback);
|
|
1047
|
+
}
|
|
1048
|
+
function afterUpsert(model, callback) {
|
|
1049
|
+
hookRegistry_default.addHook(normalizeModelName(model), "upsert", "after", callback);
|
|
1084
1050
|
}
|
|
1085
1051
|
|
|
1086
1052
|
// src/core/adapters/postgres.ts
|
|
@@ -1163,8 +1129,8 @@ function parseDatabaseUrl(url) {
|
|
|
1163
1129
|
}
|
|
1164
1130
|
|
|
1165
1131
|
// src/core/adapters/sqlite.ts
|
|
1166
|
-
import * as
|
|
1167
|
-
import * as
|
|
1132
|
+
import * as fs2 from "fs";
|
|
1133
|
+
import * as path2 from "path";
|
|
1168
1134
|
var SqliteAdapter = {
|
|
1169
1135
|
name: "sqlite",
|
|
1170
1136
|
matches(url) {
|
|
@@ -1172,13 +1138,13 @@ var SqliteAdapter = {
|
|
|
1172
1138
|
},
|
|
1173
1139
|
async create(url) {
|
|
1174
1140
|
const filePath = parseSqliteUrl(url);
|
|
1175
|
-
const dir =
|
|
1141
|
+
const dir = path2.dirname(filePath);
|
|
1176
1142
|
try {
|
|
1177
|
-
if (!
|
|
1178
|
-
|
|
1143
|
+
if (!fs2.existsSync(dir)) {
|
|
1144
|
+
fs2.mkdirSync(dir, { recursive: true });
|
|
1179
1145
|
}
|
|
1180
|
-
if (!
|
|
1181
|
-
|
|
1146
|
+
if (!fs2.existsSync(filePath)) {
|
|
1147
|
+
fs2.writeFileSync(filePath, "");
|
|
1182
1148
|
console.log(`\u2705 SQLite database created at "${filePath}"`);
|
|
1183
1149
|
} else {
|
|
1184
1150
|
console.log(`\u26A0\uFE0F SQLite database already exists at "${filePath}"`);
|
|
@@ -1191,20 +1157,20 @@ var SqliteAdapter = {
|
|
|
1191
1157
|
async drop(url) {
|
|
1192
1158
|
const filePath = parseSqliteUrl(url);
|
|
1193
1159
|
try {
|
|
1194
|
-
if (
|
|
1195
|
-
|
|
1160
|
+
if (fs2.existsSync(filePath)) {
|
|
1161
|
+
fs2.unlinkSync(filePath);
|
|
1196
1162
|
console.log(`\u2705 SQLite database at "${filePath}" dropped successfully.`);
|
|
1197
1163
|
} else {
|
|
1198
1164
|
console.log(`\u26A0\uFE0F SQLite database does not exist at "${filePath}"`);
|
|
1199
1165
|
}
|
|
1200
|
-
if (
|
|
1201
|
-
|
|
1166
|
+
if (fs2.existsSync(`${filePath}-journal`)) {
|
|
1167
|
+
fs2.unlinkSync(`${filePath}-journal`);
|
|
1202
1168
|
}
|
|
1203
|
-
if (
|
|
1204
|
-
|
|
1169
|
+
if (fs2.existsSync(`${filePath}-wal`)) {
|
|
1170
|
+
fs2.unlinkSync(`${filePath}-wal`);
|
|
1205
1171
|
}
|
|
1206
|
-
if (
|
|
1207
|
-
|
|
1172
|
+
if (fs2.existsSync(`${filePath}-shm`)) {
|
|
1173
|
+
fs2.unlinkSync(`${filePath}-shm`);
|
|
1208
1174
|
}
|
|
1209
1175
|
} catch (error) {
|
|
1210
1176
|
console.error("\u274C Error dropping SQLite database:", error);
|
|
@@ -1214,8 +1180,8 @@ var SqliteAdapter = {
|
|
|
1214
1180
|
};
|
|
1215
1181
|
function parseSqliteUrl(url) {
|
|
1216
1182
|
let cleanPath = url.replace(/^file:/, "");
|
|
1217
|
-
if (!
|
|
1218
|
-
cleanPath =
|
|
1183
|
+
if (!path2.isAbsolute(cleanPath)) {
|
|
1184
|
+
cleanPath = path2.resolve(process.cwd(), cleanPath);
|
|
1219
1185
|
}
|
|
1220
1186
|
return cleanPath;
|
|
1221
1187
|
}
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -73,27 +73,49 @@ prisma-flare automatically detects your Prisma version at runtime and uses the a
|
|
|
73
73
|
Replace your standard `PrismaClient` with `FlareClient` in your database setup file (e.g., `src/db.ts` or `src/lib/prisma.ts`).
|
|
74
74
|
|
|
75
75
|
```typescript
|
|
76
|
-
//
|
|
77
|
-
import
|
|
76
|
+
// prisma/db.ts
|
|
77
|
+
import './callbacks'; // Import generated index to register all hooks
|
|
78
|
+
import { FlareClient } from 'prisma-flare';
|
|
78
79
|
|
|
79
|
-
|
|
80
|
-
export const db = await registerHooks(new FlareClient());
|
|
80
|
+
export const db = new FlareClient();
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
-
`
|
|
84
|
-
- Registers the hooks middleware (using the appropriate API for your Prisma version)
|
|
85
|
-
- Automatically loads all callback files from `prisma/callbacks` (or your configured path)
|
|
86
|
-
- Returns the extended client instance
|
|
83
|
+
`FlareClient` automatically attaches the callbacks middleware (using the appropriate API for your Prisma version). The callbacks import loads a generated barrel file that registers all your hooks - this pattern works in all environments (bundlers, Node.js, serverless, etc.).
|
|
87
84
|
|
|
88
|
-
|
|
85
|
+
**With Prisma adapters:**
|
|
89
86
|
|
|
90
|
-
|
|
87
|
+
```typescript
|
|
88
|
+
import './callbacks';
|
|
89
|
+
import { PrismaPg } from '@prisma/adapter-pg';
|
|
90
|
+
import { FlareClient } from 'prisma-flare';
|
|
91
|
+
|
|
92
|
+
const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL });
|
|
93
|
+
|
|
94
|
+
export const db = new FlareClient({ adapter });
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Disable callbacks middleware:**
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
import { FlareClient } from 'prisma-flare';
|
|
101
|
+
|
|
102
|
+
// If you don't use callbacks, disable the middleware for slightly less overhead
|
|
103
|
+
export const db = new FlareClient({ callbacks: false });
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 2. Generate Query Classes & Callbacks Index
|
|
107
|
+
|
|
108
|
+
Run the generator to create type-safe query classes and the callbacks barrel file.
|
|
91
109
|
|
|
92
110
|
```bash
|
|
93
111
|
npx prisma-flare generate
|
|
94
112
|
```
|
|
95
113
|
|
|
96
|
-
|
|
114
|
+
This command:
|
|
115
|
+
- Generates query classes based on your `schema.prisma`
|
|
116
|
+
- Generates `prisma/callbacks/index.ts` that imports all your callback files
|
|
117
|
+
|
|
118
|
+
**Important:** Re-run this command after adding new callback files to update the index.
|
|
97
119
|
|
|
98
120
|
### 3. Configuration (Optional)
|
|
99
121
|
|
|
@@ -110,7 +132,7 @@ If your project structure is different, create a `prisma-flare.config.json` in y
|
|
|
110
132
|
|
|
111
133
|
- `modelsPath`: Where to generate the query classes (defaults to `prisma/models`).
|
|
112
134
|
- `dbPath`: Path to the file exporting your `db` instance (relative to project root, defaults to `prisma/db`).
|
|
113
|
-
- `callbacksPath`: Directory containing your callback/hook files (defaults to `prisma/callbacks`).
|
|
135
|
+
- `callbacksPath`: Directory containing your callback/hook files (defaults to `prisma/callbacks`). The generator creates an `index.ts` barrel file in this directory.
|
|
114
136
|
- `envPath`: Path to your environment file (optional, defaults to `.env`).
|
|
115
137
|
- `plurals`: Custom pluralization for model names (optional).
|
|
116
138
|
|
|
@@ -203,7 +225,7 @@ await DB.instance.transaction(async (tx) => {
|
|
|
203
225
|
|
|
204
226
|
### Callhooks & Middleware
|
|
205
227
|
|
|
206
|
-
Define hooks to run logic before or after database operations. Create callback files in your callbacks directory (default: `prisma/callbacks`)
|
|
228
|
+
Define hooks to run logic before or after database operations. Create callback files in your callbacks directory (default: `prisma/callbacks`), then run `npx prisma-flare generate` to update the index.
|
|
207
229
|
|
|
208
230
|
```typescript
|
|
209
231
|
// prisma/callbacks/user.ts
|
|
@@ -235,7 +257,7 @@ afterChange('post', 'published', async (oldValue, newValue, record) => {
|
|
|
235
257
|
});
|
|
236
258
|
```
|
|
237
259
|
|
|
238
|
-
|
|
260
|
+
After creating callback files, run `npx prisma-flare generate` to update the index. The generated `index.ts` imports all callbacks, which you then import in your db setup file.
|
|
239
261
|
|
|
240
262
|
#### Hook Configuration
|
|
241
263
|
|
|
@@ -306,25 +328,22 @@ This prevents false positives when:
|
|
|
306
328
|
|
|
307
329
|
#### Advanced Hook Registration
|
|
308
330
|
|
|
309
|
-
For
|
|
331
|
+
For advanced use cases, prisma-flare exports lower-level utilities:
|
|
310
332
|
|
|
311
333
|
```typescript
|
|
312
334
|
import {
|
|
313
|
-
|
|
314
|
-
registerHooksLegacy, // Force legacy $use API (Prisma ≤6 only, no auto-load)
|
|
335
|
+
registerHooksLegacy, // Force legacy $use API (Prisma ≤6 only)
|
|
315
336
|
createHooksExtension, // Get raw extension for manual use
|
|
316
|
-
loadCallbacks // Manually load callbacks
|
|
337
|
+
loadCallbacks // Manually load callbacks at runtime (dev only)
|
|
317
338
|
} from 'prisma-flare';
|
|
318
339
|
|
|
319
|
-
//
|
|
320
|
-
const db = await registerHooks(new FlareClient());
|
|
321
|
-
|
|
322
|
-
// Option 2: Manual callback loading from custom path
|
|
340
|
+
// Manual extension on raw PrismaClient (advanced)
|
|
323
341
|
import { PrismaClient } from '@prisma/client';
|
|
324
342
|
const prisma = new PrismaClient().$extends(createHooksExtension(new PrismaClient()));
|
|
325
|
-
await loadCallbacks('/custom/path/to/callbacks');
|
|
326
343
|
```
|
|
327
344
|
|
|
345
|
+
For most use cases, just use `new FlareClient()` which handles everything automatically.
|
|
346
|
+
|
|
328
347
|
## CLI Utilities
|
|
329
348
|
|
|
330
349
|
Prisma Flare comes with a suite of CLI tools to manage your database workflow. It supports **PostgreSQL** and **SQLite** out of the box, and is extensible for other databases.
|