prisma-flare 1.0.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-create.cjs +17 -57
- package/dist/cli/db-create.js +17 -57
- package/dist/cli/db-drop.cjs +17 -55
- package/dist/cli/db-drop.js +17 -55
- package/dist/cli/db-migrate.cjs +13 -16
- package/dist/cli/db-migrate.js +13 -16
- package/dist/cli/db-reset.cjs +0 -40
- package/dist/cli/db-reset.js +0 -40
- package/dist/cli/db-seed.cjs +0 -62
- package/dist/cli/db-seed.js +0 -40
- 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 +112 -146
- package/dist/index.d.cts +24 -15
- package/dist/index.d.ts +24 -15
- package/dist/index.js +116 -150
- package/package.json +2 -3
- package/readme.md +42 -23
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) {
|
|
@@ -1013,7 +900,7 @@ async function executeHookLogic(prisma, model, action, args, next) {
|
|
|
1013
900
|
const isUpdateAction = action === "update" || action === "updateMany";
|
|
1014
901
|
if (hasColumnHooks && isUpdateAction) {
|
|
1015
902
|
fields = hookRegistry_default.getRelevantFields(modelName);
|
|
1016
|
-
prevData = await fetchAffectedRecords(prisma,
|
|
903
|
+
prevData = await fetchAffectedRecords(prisma, model, args.where, fields);
|
|
1017
904
|
shouldRunColumnHooks = hookRegistry_default.shouldRunColumnHooks(modelName, prevData.length, { __flare: flareOptions });
|
|
1018
905
|
}
|
|
1019
906
|
await hookRegistry_default.runHooks("before", modelName, action, [args], prisma);
|
|
@@ -1021,7 +908,7 @@ async function executeHookLogic(prisma, model, action, args, next) {
|
|
|
1021
908
|
if (shouldRunColumnHooks && prevData.length > 0) {
|
|
1022
909
|
let newData = [];
|
|
1023
910
|
const ids = prevData.map((r) => r.id);
|
|
1024
|
-
newData = await fetchAffectedRecords(prisma,
|
|
911
|
+
newData = await fetchAffectedRecords(prisma, model, { id: { in: ids } }, fields);
|
|
1025
912
|
for (let i = 0; i < prevData.length; i++) {
|
|
1026
913
|
const prevRecord = prevData[i];
|
|
1027
914
|
const newRecord = newData.find((record) => record.id === prevRecord.id);
|
|
@@ -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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prisma-flare",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Prisma utilities package with callback system and query builder for chained operations",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -52,8 +52,7 @@
|
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"pg": "^8.16.3",
|
|
55
|
-
"pluralize": "^8.0.0"
|
|
56
|
-
"dotenv": "^17.2.3"
|
|
55
|
+
"pluralize": "^8.0.0"
|
|
57
56
|
},
|
|
58
57
|
"devDependencies": {
|
|
59
58
|
"@prisma/client": "^5.18.0",
|
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.
|