arkormx 0.2.10 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -0
- package/dist/cli.mjs +39 -9
- package/dist/index.cjs +553 -43
- package/dist/index.d.cts +246 -9
- package/dist/index.d.mts +246 -9
- package/dist/index.mjs +544 -44
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import { str } from "@h3ravel/support";
|
|
|
5
5
|
import path, { dirname as dirname$1, extname as extname$1, join as join$1, relative } from "path";
|
|
6
6
|
import { copyFileSync, existsSync as existsSync$1, mkdirSync as mkdirSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, rmSync as rmSync$1, writeFileSync as writeFileSync$1 } from "fs";
|
|
7
7
|
import { fileURLToPath, pathToFileURL } from "url";
|
|
8
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
8
9
|
import { createRequire } from "module";
|
|
9
10
|
import { Logger } from "@h3ravel/shared";
|
|
10
11
|
import { Command } from "@h3ravel/musket";
|
|
@@ -93,17 +94,43 @@ function resolveCast(definition) {
|
|
|
93
94
|
|
|
94
95
|
//#endregion
|
|
95
96
|
//#region src/Exceptions/ArkormException.ts
|
|
96
|
-
/**
|
|
97
|
-
* The ArkormException class is a custom error type for handling
|
|
98
|
-
* exceptions specific to the Arkormˣ.
|
|
99
|
-
*
|
|
100
|
-
* @author Legacy (3m1n3nc3)
|
|
101
|
-
* @since 0.1.0
|
|
102
|
-
*/
|
|
103
97
|
var ArkormException = class extends Error {
|
|
104
|
-
|
|
105
|
-
|
|
98
|
+
code;
|
|
99
|
+
operation;
|
|
100
|
+
model;
|
|
101
|
+
delegate;
|
|
102
|
+
relation;
|
|
103
|
+
scope;
|
|
104
|
+
meta;
|
|
105
|
+
constructor(message, context = {}) {
|
|
106
|
+
super(message, context.cause === void 0 ? void 0 : { cause: context.cause });
|
|
106
107
|
this.name = "ArkormException";
|
|
108
|
+
this.code = context.code;
|
|
109
|
+
this.operation = context.operation;
|
|
110
|
+
this.model = context.model;
|
|
111
|
+
this.delegate = context.delegate;
|
|
112
|
+
this.relation = context.relation;
|
|
113
|
+
this.scope = context.scope;
|
|
114
|
+
this.meta = context.meta;
|
|
115
|
+
}
|
|
116
|
+
getContext() {
|
|
117
|
+
return {
|
|
118
|
+
code: this.code,
|
|
119
|
+
operation: this.operation,
|
|
120
|
+
model: this.model,
|
|
121
|
+
delegate: this.delegate,
|
|
122
|
+
relation: this.relation,
|
|
123
|
+
scope: this.scope,
|
|
124
|
+
meta: this.meta,
|
|
125
|
+
cause: this.cause
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
toJSON() {
|
|
129
|
+
return {
|
|
130
|
+
name: this.name,
|
|
131
|
+
message: this.message,
|
|
132
|
+
...this.getContext()
|
|
133
|
+
};
|
|
107
134
|
}
|
|
108
135
|
};
|
|
109
136
|
|
|
@@ -1213,6 +1240,18 @@ const runMigrationWithPrisma = async (migration, options = {}) => {
|
|
|
1213
1240
|
};
|
|
1214
1241
|
};
|
|
1215
1242
|
|
|
1243
|
+
//#endregion
|
|
1244
|
+
//#region src/Exceptions/UnsupportedAdapterFeatureException.ts
|
|
1245
|
+
var UnsupportedAdapterFeatureException = class extends ArkormException {
|
|
1246
|
+
constructor(message, context = {}) {
|
|
1247
|
+
super(message, {
|
|
1248
|
+
code: "UNSUPPORTED_ADAPTER_FEATURE",
|
|
1249
|
+
...context
|
|
1250
|
+
});
|
|
1251
|
+
this.name = "UnsupportedAdapterFeatureException";
|
|
1252
|
+
}
|
|
1253
|
+
};
|
|
1254
|
+
|
|
1216
1255
|
//#endregion
|
|
1217
1256
|
//#region src/helpers/runtime-config.ts
|
|
1218
1257
|
const resolveDefaultStubsPath = () => {
|
|
@@ -1246,6 +1285,8 @@ let runtimeConfigLoaded = false;
|
|
|
1246
1285
|
let runtimeConfigLoadingPromise;
|
|
1247
1286
|
let runtimeClientResolver;
|
|
1248
1287
|
let runtimePaginationURLDriverFactory;
|
|
1288
|
+
let runtimePaginationCurrentPageResolver;
|
|
1289
|
+
const transactionClientStorage = new AsyncLocalStorage();
|
|
1249
1290
|
const mergePathConfig = (paths) => {
|
|
1250
1291
|
const defaults = baseConfig.paths ?? {};
|
|
1251
1292
|
const current = userConfig.paths ?? {};
|
|
@@ -1295,6 +1336,7 @@ const configureArkormRuntime = (prisma, options = {}) => {
|
|
|
1295
1336
|
Object.assign(userConfig, { ...nextConfig });
|
|
1296
1337
|
runtimeClientResolver = prisma;
|
|
1297
1338
|
runtimePaginationURLDriverFactory = nextConfig.pagination?.urlDriver;
|
|
1339
|
+
runtimePaginationCurrentPageResolver = nextConfig.pagination?.resolveCurrentPage;
|
|
1298
1340
|
};
|
|
1299
1341
|
/**
|
|
1300
1342
|
* Reset the ArkORM runtime configuration.
|
|
@@ -1309,6 +1351,7 @@ const resetArkormRuntimeForTests = () => {
|
|
|
1309
1351
|
runtimeConfigLoadingPromise = void 0;
|
|
1310
1352
|
runtimeClientResolver = void 0;
|
|
1311
1353
|
runtimePaginationURLDriverFactory = void 0;
|
|
1354
|
+
runtimePaginationCurrentPageResolver = void 0;
|
|
1312
1355
|
};
|
|
1313
1356
|
/**
|
|
1314
1357
|
* Resolve a Prisma client instance from the provided resolver, which can be either
|
|
@@ -1411,9 +1454,36 @@ const getDefaultStubsPath = () => {
|
|
|
1411
1454
|
* @returns
|
|
1412
1455
|
*/
|
|
1413
1456
|
const getRuntimePrismaClient = () => {
|
|
1457
|
+
const activeTransactionClient = transactionClientStorage.getStore();
|
|
1458
|
+
if (activeTransactionClient) return activeTransactionClient;
|
|
1414
1459
|
if (!runtimeConfigLoaded) loadRuntimeConfigSync();
|
|
1415
1460
|
return resolveClient(runtimeClientResolver);
|
|
1416
1461
|
};
|
|
1462
|
+
const getActiveTransactionClient = () => {
|
|
1463
|
+
return transactionClientStorage.getStore();
|
|
1464
|
+
};
|
|
1465
|
+
const isTransactionCapableClient = (value) => {
|
|
1466
|
+
if (!value || typeof value !== "object") return false;
|
|
1467
|
+
return typeof value.$transaction === "function";
|
|
1468
|
+
};
|
|
1469
|
+
const runArkormTransaction = async (callback, options = {}) => {
|
|
1470
|
+
const activeTransactionClient = transactionClientStorage.getStore();
|
|
1471
|
+
if (activeTransactionClient) return await callback(activeTransactionClient);
|
|
1472
|
+
const client = getRuntimePrismaClient();
|
|
1473
|
+
if (!client) throw new ArkormException("Cannot start a transaction without a configured Prisma client.", {
|
|
1474
|
+
code: "CLIENT_NOT_CONFIGURED",
|
|
1475
|
+
operation: "transaction"
|
|
1476
|
+
});
|
|
1477
|
+
if (!isTransactionCapableClient(client)) throw new UnsupportedAdapterFeatureException("Transactions are not supported by the current adapter.", {
|
|
1478
|
+
code: "TRANSACTION_NOT_SUPPORTED",
|
|
1479
|
+
operation: "transaction"
|
|
1480
|
+
});
|
|
1481
|
+
return await client.$transaction(async (transactionClient) => {
|
|
1482
|
+
return await transactionClientStorage.run(transactionClient, async () => {
|
|
1483
|
+
return await callback(transactionClient);
|
|
1484
|
+
});
|
|
1485
|
+
}, options);
|
|
1486
|
+
};
|
|
1417
1487
|
/**
|
|
1418
1488
|
* Get the configured pagination URL driver factory from runtime config.
|
|
1419
1489
|
*
|
|
@@ -1424,6 +1494,15 @@ const getRuntimePaginationURLDriverFactory = () => {
|
|
|
1424
1494
|
return runtimePaginationURLDriverFactory;
|
|
1425
1495
|
};
|
|
1426
1496
|
/**
|
|
1497
|
+
* Get the configured current-page resolver from runtime config.
|
|
1498
|
+
*
|
|
1499
|
+
* @returns
|
|
1500
|
+
*/
|
|
1501
|
+
const getRuntimePaginationCurrentPageResolver = () => {
|
|
1502
|
+
if (!runtimeConfigLoaded) loadRuntimeConfigSync();
|
|
1503
|
+
return runtimePaginationCurrentPageResolver;
|
|
1504
|
+
};
|
|
1505
|
+
/**
|
|
1427
1506
|
* Check if a given value is a Prisma delegate-like object
|
|
1428
1507
|
* by verifying the presence of common delegate methods.
|
|
1429
1508
|
*
|
|
@@ -2760,6 +2839,18 @@ const defineFactory = (model, definition) => {
|
|
|
2760
2839
|
return new InlineFactory(model, definition);
|
|
2761
2840
|
};
|
|
2762
2841
|
|
|
2842
|
+
//#endregion
|
|
2843
|
+
//#region src/Exceptions/MissingDelegateException.ts
|
|
2844
|
+
var MissingDelegateException = class extends ArkormException {
|
|
2845
|
+
constructor(message, context = {}) {
|
|
2846
|
+
super(message, {
|
|
2847
|
+
code: "MISSING_DELEGATE",
|
|
2848
|
+
...context
|
|
2849
|
+
});
|
|
2850
|
+
this.name = "MissingDelegateException";
|
|
2851
|
+
}
|
|
2852
|
+
};
|
|
2853
|
+
|
|
2763
2854
|
//#endregion
|
|
2764
2855
|
//#region src/Exceptions/ModelNotFoundException.ts
|
|
2765
2856
|
/**
|
|
@@ -2771,8 +2862,12 @@ const defineFactory = (model, definition) => {
|
|
|
2771
2862
|
*/
|
|
2772
2863
|
var ModelNotFoundException = class extends ArkormException {
|
|
2773
2864
|
modelName;
|
|
2774
|
-
constructor(modelName, message = "No query results for the given model.") {
|
|
2775
|
-
super(message
|
|
2865
|
+
constructor(modelName, message = "No query results for the given model.", context = {}) {
|
|
2866
|
+
super(message, {
|
|
2867
|
+
code: "MODEL_NOT_FOUND",
|
|
2868
|
+
model: modelName,
|
|
2869
|
+
...context
|
|
2870
|
+
});
|
|
2776
2871
|
this.name = "ModelNotFoundException";
|
|
2777
2872
|
this.modelName = modelName;
|
|
2778
2873
|
}
|
|
@@ -2781,6 +2876,54 @@ var ModelNotFoundException = class extends ArkormException {
|
|
|
2781
2876
|
}
|
|
2782
2877
|
};
|
|
2783
2878
|
|
|
2879
|
+
//#endregion
|
|
2880
|
+
//#region src/Exceptions/QueryConstraintException.ts
|
|
2881
|
+
var QueryConstraintException = class extends ArkormException {
|
|
2882
|
+
constructor(message, context = {}) {
|
|
2883
|
+
super(message, {
|
|
2884
|
+
code: "QUERY_CONSTRAINT",
|
|
2885
|
+
...context
|
|
2886
|
+
});
|
|
2887
|
+
this.name = "QueryConstraintException";
|
|
2888
|
+
}
|
|
2889
|
+
};
|
|
2890
|
+
|
|
2891
|
+
//#endregion
|
|
2892
|
+
//#region src/Exceptions/RelationResolutionException.ts
|
|
2893
|
+
var RelationResolutionException = class extends ArkormException {
|
|
2894
|
+
constructor(message, context = {}) {
|
|
2895
|
+
super(message, {
|
|
2896
|
+
code: "RELATION_RESOLUTION_FAILED",
|
|
2897
|
+
...context
|
|
2898
|
+
});
|
|
2899
|
+
this.name = "RelationResolutionException";
|
|
2900
|
+
}
|
|
2901
|
+
};
|
|
2902
|
+
|
|
2903
|
+
//#endregion
|
|
2904
|
+
//#region src/Exceptions/ScopeNotDefinedException.ts
|
|
2905
|
+
var ScopeNotDefinedException = class extends ArkormException {
|
|
2906
|
+
constructor(message, context = {}) {
|
|
2907
|
+
super(message, {
|
|
2908
|
+
code: "SCOPE_NOT_DEFINED",
|
|
2909
|
+
...context
|
|
2910
|
+
});
|
|
2911
|
+
this.name = "ScopeNotDefinedException";
|
|
2912
|
+
}
|
|
2913
|
+
};
|
|
2914
|
+
|
|
2915
|
+
//#endregion
|
|
2916
|
+
//#region src/Exceptions/UniqueConstraintResolutionException.ts
|
|
2917
|
+
var UniqueConstraintResolutionException = class extends ArkormException {
|
|
2918
|
+
constructor(message, context = {}) {
|
|
2919
|
+
super(message, {
|
|
2920
|
+
code: "UNIQUE_CONSTRAINT_RESOLUTION_FAILED",
|
|
2921
|
+
...context
|
|
2922
|
+
});
|
|
2923
|
+
this.name = "UniqueConstraintResolutionException";
|
|
2924
|
+
}
|
|
2925
|
+
};
|
|
2926
|
+
|
|
2784
2927
|
//#endregion
|
|
2785
2928
|
//#region src/helpers/prisma.ts
|
|
2786
2929
|
/**
|
|
@@ -3021,6 +3164,7 @@ var BelongsToManyRelation = class extends Relation {
|
|
|
3021
3164
|
async getResults() {
|
|
3022
3165
|
const parentValue = this.parent.getAttribute(this.parentKey);
|
|
3023
3166
|
const ids = (await this.related.getDelegate(this.throughDelegate).findMany({ where: { [this.foreignPivotKey]: parentValue } })).map((row) => row[this.relatedPivotKey]);
|
|
3167
|
+
if (ids.length === 0) return new ArkormCollection([]);
|
|
3024
3168
|
return this.applyConstraint(this.related.query().where({ [this.relatedKey]: { in: ids } })).get();
|
|
3025
3169
|
}
|
|
3026
3170
|
};
|
|
@@ -3107,6 +3251,7 @@ var HasManyThroughRelation = class extends Relation {
|
|
|
3107
3251
|
async getResults() {
|
|
3108
3252
|
const localValue = this.parent.getAttribute(this.localKey);
|
|
3109
3253
|
const keys = (await this.related.getDelegate(this.throughDelegate).findMany({ where: { [this.firstKey]: localValue } })).map((row) => row[this.secondLocalKey]);
|
|
3254
|
+
if (keys.length === 0) return new ArkormCollection([]);
|
|
3110
3255
|
return this.applyConstraint(this.related.query().where({ [this.secondKey]: { in: keys } })).get();
|
|
3111
3256
|
}
|
|
3112
3257
|
};
|
|
@@ -3264,6 +3409,7 @@ var MorphToManyRelation = class extends Relation {
|
|
|
3264
3409
|
[`${this.morphName}Id`]: parentValue,
|
|
3265
3410
|
[`${this.morphName}Type`]: morphType
|
|
3266
3411
|
} })).map((row) => row[this.relatedPivotKey]);
|
|
3412
|
+
if (ids.length === 0) return new ArkormCollection([]);
|
|
3267
3413
|
return this.applyConstraint(this.related.query().where({ [this.relatedKey]: { in: ids } })).get();
|
|
3268
3414
|
}
|
|
3269
3415
|
};
|
|
@@ -3476,6 +3622,13 @@ var QueryBuilder = class QueryBuilder {
|
|
|
3476
3622
|
this.delegate = delegate;
|
|
3477
3623
|
this.model = model;
|
|
3478
3624
|
}
|
|
3625
|
+
resolvePaginationPage(page, options) {
|
|
3626
|
+
if (typeof page !== "undefined") return Number.isFinite(page) ? Math.max(1, page) : 1;
|
|
3627
|
+
const pageName = options.pageName ?? "page";
|
|
3628
|
+
const resolvedPage = getRuntimePaginationCurrentPageResolver()?.(pageName, options);
|
|
3629
|
+
if (typeof resolvedPage !== "number" || !Number.isFinite(resolvedPage)) return 1;
|
|
3630
|
+
return Math.max(1, resolvedPage);
|
|
3631
|
+
}
|
|
3479
3632
|
/**
|
|
3480
3633
|
* Adds a where clause to the query. Multiple calls to where will combine
|
|
3481
3634
|
* the clauses with AND logic.
|
|
@@ -4008,7 +4161,11 @@ var QueryBuilder = class QueryBuilder {
|
|
|
4008
4161
|
scope(name, ...args) {
|
|
4009
4162
|
const methodName = `scope${name.charAt(0).toUpperCase()}${name.slice(1)}`;
|
|
4010
4163
|
const scope = this.model.prototype?.[methodName];
|
|
4011
|
-
if (typeof scope !== "function") throw new
|
|
4164
|
+
if (typeof scope !== "function") throw new ScopeNotDefinedException(`Scope [${name}] is not defined.`, {
|
|
4165
|
+
operation: "scope",
|
|
4166
|
+
model: this.model.name,
|
|
4167
|
+
scope: name
|
|
4168
|
+
});
|
|
4012
4169
|
const scoped = scope.call(void 0, this, ...args);
|
|
4013
4170
|
if (scoped && scoped !== this) return scoped;
|
|
4014
4171
|
return this;
|
|
@@ -4130,7 +4287,7 @@ var QueryBuilder = class QueryBuilder {
|
|
|
4130
4287
|
const relationCache = /* @__PURE__ */ new WeakMap();
|
|
4131
4288
|
const rows = await this.delegate.findMany(this.buildFindArgs());
|
|
4132
4289
|
const normalizedRows = this.randomOrderEnabled ? this.shuffleRows(rows) : rows;
|
|
4133
|
-
const models = this.model.
|
|
4290
|
+
const models = await this.model.hydrateManyRetrieved(normalizedRows);
|
|
4134
4291
|
let filteredModels = models;
|
|
4135
4292
|
if (this.hasRelationFilters()) if (this.hasOrRelationFilters() && this.args.where) {
|
|
4136
4293
|
const baseIds = new Set(models.map((model) => this.getModelId(model)).filter((id) => id != null));
|
|
@@ -4160,13 +4317,13 @@ var QueryBuilder = class QueryBuilder {
|
|
|
4160
4317
|
if (rows.length === 0) return null;
|
|
4161
4318
|
const row = this.shuffleRows(rows)[0];
|
|
4162
4319
|
if (!row) return null;
|
|
4163
|
-
const model = this.model.
|
|
4320
|
+
const model = await this.model.hydrateRetrieved(row);
|
|
4164
4321
|
await model.load(this.eagerLoads);
|
|
4165
4322
|
return model;
|
|
4166
4323
|
}
|
|
4167
4324
|
const row = await this.delegate.findFirst(this.buildFindArgs());
|
|
4168
4325
|
if (!row) return null;
|
|
4169
|
-
const model = this.model.
|
|
4326
|
+
const model = await this.model.hydrateRetrieved(row);
|
|
4170
4327
|
await model.load(this.eagerLoads);
|
|
4171
4328
|
return model;
|
|
4172
4329
|
}
|
|
@@ -4186,7 +4343,10 @@ var QueryBuilder = class QueryBuilder {
|
|
|
4186
4343
|
async findOr(value, keyOrCallback, maybeCallback) {
|
|
4187
4344
|
const key = typeof keyOrCallback === "string" ? keyOrCallback : "id";
|
|
4188
4345
|
const callback = typeof keyOrCallback === "function" ? keyOrCallback : maybeCallback;
|
|
4189
|
-
if (!callback) throw new
|
|
4346
|
+
if (!callback) throw new QueryConstraintException("findOr requires a fallback callback.", {
|
|
4347
|
+
operation: "findOr",
|
|
4348
|
+
model: this.model.name
|
|
4349
|
+
});
|
|
4190
4350
|
const found = await this.find(value, key);
|
|
4191
4351
|
if (found) return found;
|
|
4192
4352
|
return callback();
|
|
@@ -4300,7 +4460,11 @@ var QueryBuilder = class QueryBuilder {
|
|
|
4300
4460
|
async insertGetId(values, sequence) {
|
|
4301
4461
|
const created = await this.delegate.create({ data: values });
|
|
4302
4462
|
const key = sequence ?? "id";
|
|
4303
|
-
if (!(key in created)) throw new
|
|
4463
|
+
if (!(key in created)) throw new UniqueConstraintResolutionException(`Inserted record does not contain key [${key}].`, {
|
|
4464
|
+
operation: "insertGetId",
|
|
4465
|
+
model: this.model.name,
|
|
4466
|
+
meta: { key }
|
|
4467
|
+
});
|
|
4304
4468
|
return created[key];
|
|
4305
4469
|
}
|
|
4306
4470
|
/**
|
|
@@ -4337,7 +4501,10 @@ var QueryBuilder = class QueryBuilder {
|
|
|
4337
4501
|
*/
|
|
4338
4502
|
async update(data) {
|
|
4339
4503
|
const where = this.buildWhere();
|
|
4340
|
-
if (!where) throw new
|
|
4504
|
+
if (!where) throw new QueryConstraintException("Update requires a where clause.", {
|
|
4505
|
+
operation: "update",
|
|
4506
|
+
model: this.model.name
|
|
4507
|
+
});
|
|
4341
4508
|
const uniqueWhere = await this.resolveUniqueWhere(where);
|
|
4342
4509
|
const updated = await this.delegate.update({
|
|
4343
4510
|
where: uniqueWhere,
|
|
@@ -4353,7 +4520,10 @@ var QueryBuilder = class QueryBuilder {
|
|
|
4353
4520
|
*/
|
|
4354
4521
|
async updateFrom(data) {
|
|
4355
4522
|
const where = this.buildWhere();
|
|
4356
|
-
if (!where) throw new
|
|
4523
|
+
if (!where) throw new QueryConstraintException("Update requires a where clause.", {
|
|
4524
|
+
operation: "updateFrom",
|
|
4525
|
+
model: this.model.name
|
|
4526
|
+
});
|
|
4357
4527
|
const delegate = this.delegate;
|
|
4358
4528
|
if (typeof delegate.updateMany === "function") {
|
|
4359
4529
|
const result = await delegate.updateMany({
|
|
@@ -4418,7 +4588,10 @@ var QueryBuilder = class QueryBuilder {
|
|
|
4418
4588
|
*/
|
|
4419
4589
|
async delete() {
|
|
4420
4590
|
const where = this.buildWhere();
|
|
4421
|
-
if (!where) throw new
|
|
4591
|
+
if (!where) throw new QueryConstraintException("Delete requires a where clause.", {
|
|
4592
|
+
operation: "delete",
|
|
4593
|
+
model: this.model.name
|
|
4594
|
+
});
|
|
4422
4595
|
const uniqueWhere = await this.resolveUniqueWhere(where);
|
|
4423
4596
|
const deleted = await this.delegate.delete({ where: uniqueWhere });
|
|
4424
4597
|
return this.model.hydrate(deleted);
|
|
@@ -4484,7 +4657,10 @@ var QueryBuilder = class QueryBuilder {
|
|
|
4484
4657
|
if (Array.isArray(source)) return source;
|
|
4485
4658
|
}
|
|
4486
4659
|
if (Array.isArray(source)) return source;
|
|
4487
|
-
throw new
|
|
4660
|
+
throw new QueryConstraintException("insertUsing expects a query builder, array of records, or async resolver.", {
|
|
4661
|
+
operation: "insertUsing",
|
|
4662
|
+
model: this.model.name
|
|
4663
|
+
});
|
|
4488
4664
|
}
|
|
4489
4665
|
/**
|
|
4490
4666
|
* Execute callback when no records exist.
|
|
@@ -4568,7 +4744,11 @@ var QueryBuilder = class QueryBuilder {
|
|
|
4568
4744
|
*/
|
|
4569
4745
|
whereRaw(sql, bindings = []) {
|
|
4570
4746
|
const delegate = this.delegate;
|
|
4571
|
-
if (typeof delegate.applyRawWhere !== "function") throw new
|
|
4747
|
+
if (typeof delegate.applyRawWhere !== "function") throw new UnsupportedAdapterFeatureException("Raw where clauses are not supported by the current adapter.", {
|
|
4748
|
+
operation: "whereRaw",
|
|
4749
|
+
model: this.model.name,
|
|
4750
|
+
meta: { feature: "rawWhere" }
|
|
4751
|
+
});
|
|
4572
4752
|
this.args.where = delegate.applyRawWhere(this.buildWhere(), sql, bindings);
|
|
4573
4753
|
return this;
|
|
4574
4754
|
}
|
|
@@ -4581,7 +4761,11 @@ var QueryBuilder = class QueryBuilder {
|
|
|
4581
4761
|
*/
|
|
4582
4762
|
orWhereRaw(sql, bindings = []) {
|
|
4583
4763
|
const delegate = this.delegate;
|
|
4584
|
-
if (typeof delegate.applyRawWhere !== "function") throw new
|
|
4764
|
+
if (typeof delegate.applyRawWhere !== "function") throw new UnsupportedAdapterFeatureException("Raw where clauses are not supported by the current adapter.", {
|
|
4765
|
+
operation: "orWhereRaw",
|
|
4766
|
+
model: this.model.name,
|
|
4767
|
+
meta: { feature: "rawWhere" }
|
|
4768
|
+
});
|
|
4585
4769
|
const rawWhere = delegate.applyRawWhere(void 0, sql, bindings);
|
|
4586
4770
|
return this.orWhere(rawWhere);
|
|
4587
4771
|
}
|
|
@@ -4594,15 +4778,14 @@ var QueryBuilder = class QueryBuilder {
|
|
|
4594
4778
|
* @param options
|
|
4595
4779
|
* @returns
|
|
4596
4780
|
*/
|
|
4597
|
-
async paginate(
|
|
4781
|
+
async paginate(perPage = 15, page = void 0, options = {}) {
|
|
4782
|
+
const currentPage = this.resolvePaginationPage(page, options);
|
|
4598
4783
|
if (this.hasRelationFilters() || this.hasRelationAggregates()) {
|
|
4599
|
-
const currentPage = Math.max(1, page);
|
|
4600
4784
|
const pageSize = Math.max(1, perPage);
|
|
4601
4785
|
const rows = (await this.get()).all();
|
|
4602
4786
|
const start = (currentPage - 1) * pageSize;
|
|
4603
4787
|
return new LengthAwarePaginator(new ArkormCollection(rows.slice(start, start + pageSize)), rows.length, pageSize, currentPage, options);
|
|
4604
4788
|
}
|
|
4605
|
-
const currentPage = Math.max(1, page);
|
|
4606
4789
|
const pageSize = Math.max(1, perPage);
|
|
4607
4790
|
const total = await this.count();
|
|
4608
4791
|
return new LengthAwarePaginator(await this.clone().skip((currentPage - 1) * pageSize).take(pageSize).get(), total, pageSize, currentPage, options);
|
|
@@ -4614,9 +4797,9 @@ var QueryBuilder = class QueryBuilder {
|
|
|
4614
4797
|
* @param page
|
|
4615
4798
|
* @returns
|
|
4616
4799
|
*/
|
|
4617
|
-
async simplePaginate(perPage = 15, page =
|
|
4800
|
+
async simplePaginate(perPage = 15, page = void 0, options = {}) {
|
|
4801
|
+
const currentPage = this.resolvePaginationPage(page, options);
|
|
4618
4802
|
if (this.hasRelationFilters() || this.hasRelationAggregates()) {
|
|
4619
|
-
const currentPage = Math.max(1, page);
|
|
4620
4803
|
const pageSize = Math.max(1, perPage);
|
|
4621
4804
|
const rows = (await this.get()).all();
|
|
4622
4805
|
const start = (currentPage - 1) * pageSize;
|
|
@@ -4624,7 +4807,6 @@ var QueryBuilder = class QueryBuilder {
|
|
|
4624
4807
|
const hasMorePages = start + pageSize < rows.length;
|
|
4625
4808
|
return new Paginator(new ArkormCollection(pageRows), pageSize, currentPage, hasMorePages, options);
|
|
4626
4809
|
}
|
|
4627
|
-
const currentPage = Math.max(1, page);
|
|
4628
4810
|
const pageSize = Math.max(1, perPage);
|
|
4629
4811
|
const items = await this.clone().skip((currentPage - 1) * pageSize).take(pageSize + 1).get();
|
|
4630
4812
|
const hasMorePages = items.all().length > pageSize;
|
|
@@ -4705,9 +4887,16 @@ var QueryBuilder = class QueryBuilder {
|
|
|
4705
4887
|
async resolveUniqueWhere(where) {
|
|
4706
4888
|
if (this.isUniqueWhere(where)) return where;
|
|
4707
4889
|
const row = await this.delegate.findFirst({ where });
|
|
4708
|
-
if (!row) throw new
|
|
4890
|
+
if (!row) throw new ModelNotFoundException(this.model.name, "Record not found for update/delete operation.", {
|
|
4891
|
+
operation: "resolveUniqueWhere",
|
|
4892
|
+
meta: { where }
|
|
4893
|
+
});
|
|
4709
4894
|
const record = row;
|
|
4710
|
-
if (!Object.prototype.hasOwnProperty.call(record, "id")) throw new
|
|
4895
|
+
if (!Object.prototype.hasOwnProperty.call(record, "id")) throw new UniqueConstraintResolutionException("Unable to resolve a unique identifier for update/delete operation. Include an id in the query constraints.", {
|
|
4896
|
+
operation: "resolveUniqueWhere",
|
|
4897
|
+
model: this.model.name,
|
|
4898
|
+
meta: { where }
|
|
4899
|
+
});
|
|
4711
4900
|
return { id: record.id };
|
|
4712
4901
|
}
|
|
4713
4902
|
/**
|
|
@@ -4830,7 +5019,11 @@ var QueryBuilder = class QueryBuilder {
|
|
|
4830
5019
|
if (cached) return await cached;
|
|
4831
5020
|
const resolver = (async () => {
|
|
4832
5021
|
const relationMethod = model[relation];
|
|
4833
|
-
if (typeof relationMethod !== "function") throw new
|
|
5022
|
+
if (typeof relationMethod !== "function") throw new RelationResolutionException(`Relation [${relation}] is not defined on the model.`, {
|
|
5023
|
+
operation: "resolveRelatedResults",
|
|
5024
|
+
model: this.model.name,
|
|
5025
|
+
relation
|
|
5026
|
+
});
|
|
4834
5027
|
const relationInstance = relationMethod.call(model);
|
|
4835
5028
|
if (callback && typeof relationInstance.constrain === "function") relationInstance.constrain((query) => {
|
|
4836
5029
|
return callback(query) ?? query;
|
|
@@ -4845,7 +5038,11 @@ var QueryBuilder = class QueryBuilder {
|
|
|
4845
5038
|
if (results instanceof ArkormCollection) return results.all();
|
|
4846
5039
|
return results;
|
|
4847
5040
|
}
|
|
4848
|
-
throw new
|
|
5041
|
+
throw new RelationResolutionException(`Relation [${relation}] does not support result resolution.`, {
|
|
5042
|
+
operation: "resolveRelatedResults",
|
|
5043
|
+
model: this.model.name,
|
|
5044
|
+
relation
|
|
5045
|
+
});
|
|
4849
5046
|
})();
|
|
4850
5047
|
callbackMap.set(callbackCacheKey, resolver);
|
|
4851
5048
|
return await resolver;
|
|
@@ -4886,6 +5083,8 @@ var QueryBuilder = class QueryBuilder {
|
|
|
4886
5083
|
* @since 0.1.0
|
|
4887
5084
|
*/
|
|
4888
5085
|
var Model = class Model {
|
|
5086
|
+
static lifecycleStates = /* @__PURE__ */ new WeakMap();
|
|
5087
|
+
static eventsSuppressed = 0;
|
|
4889
5088
|
static factoryClass;
|
|
4890
5089
|
static client;
|
|
4891
5090
|
static delegate;
|
|
@@ -4893,6 +5092,7 @@ var Model = class Model {
|
|
|
4893
5092
|
static deletedAtColumn = "deletedAt";
|
|
4894
5093
|
static globalScopes = {};
|
|
4895
5094
|
static eventListeners = {};
|
|
5095
|
+
static dispatchesEvents = {};
|
|
4896
5096
|
casts = {};
|
|
4897
5097
|
hidden = [];
|
|
4898
5098
|
visible = [];
|
|
@@ -4930,7 +5130,11 @@ var Model = class Model {
|
|
|
4930
5130
|
}
|
|
4931
5131
|
static factory(count) {
|
|
4932
5132
|
const factoryClass = this.factoryClass;
|
|
4933
|
-
if (!factoryClass) throw new ArkormException(`Factory is not configured for model [${this.name}]
|
|
5133
|
+
if (!factoryClass) throw new ArkormException(`Factory is not configured for model [${this.name}].`, {
|
|
5134
|
+
code: "FACTORY_NOT_CONFIGURED",
|
|
5135
|
+
operation: "factory",
|
|
5136
|
+
model: this.name
|
|
5137
|
+
});
|
|
4934
5138
|
const factory = new factoryClass();
|
|
4935
5139
|
if (typeof count === "number") factory.count(count);
|
|
4936
5140
|
return factory;
|
|
@@ -4946,6 +5150,21 @@ var Model = class Model {
|
|
|
4946
5150
|
this.globalScopes[name] = scope;
|
|
4947
5151
|
}
|
|
4948
5152
|
/**
|
|
5153
|
+
* Execute a callback without applying global scopes for the current model class.
|
|
5154
|
+
*
|
|
5155
|
+
* @param callback
|
|
5156
|
+
* @returns
|
|
5157
|
+
*/
|
|
5158
|
+
static async withoutGlobalScopes(callback) {
|
|
5159
|
+
const state = Model.getLifecycleState(this);
|
|
5160
|
+
state.globalScopesSuppressed += 1;
|
|
5161
|
+
try {
|
|
5162
|
+
return await callback();
|
|
5163
|
+
} finally {
|
|
5164
|
+
state.globalScopesSuppressed = Math.max(0, state.globalScopesSuppressed - 1);
|
|
5165
|
+
}
|
|
5166
|
+
}
|
|
5167
|
+
/**
|
|
4949
5168
|
* Remove a global scope by name.
|
|
4950
5169
|
*
|
|
4951
5170
|
* @param name
|
|
@@ -4967,11 +5186,60 @@ var Model = class Model {
|
|
|
4967
5186
|
* @param listener
|
|
4968
5187
|
*/
|
|
4969
5188
|
static on(event, listener) {
|
|
5189
|
+
Model.ensureModelBooted(this);
|
|
4970
5190
|
this.ensureOwnEventListeners();
|
|
4971
5191
|
if (!this.eventListeners[event]) this.eventListeners[event] = [];
|
|
4972
5192
|
this.eventListeners[event]?.push(listener);
|
|
4973
5193
|
}
|
|
4974
5194
|
/**
|
|
5195
|
+
* Register a model lifecycle callback listener.
|
|
5196
|
+
*
|
|
5197
|
+
* @param event
|
|
5198
|
+
* @param listener
|
|
5199
|
+
*/
|
|
5200
|
+
static event(event, listener) {
|
|
5201
|
+
this.on(event, listener);
|
|
5202
|
+
}
|
|
5203
|
+
static retrieved(listener) {
|
|
5204
|
+
this.event("retrieved", listener);
|
|
5205
|
+
}
|
|
5206
|
+
static saving(listener) {
|
|
5207
|
+
this.event("saving", listener);
|
|
5208
|
+
}
|
|
5209
|
+
static saved(listener) {
|
|
5210
|
+
this.event("saved", listener);
|
|
5211
|
+
}
|
|
5212
|
+
static creating(listener) {
|
|
5213
|
+
this.event("creating", listener);
|
|
5214
|
+
}
|
|
5215
|
+
static created(listener) {
|
|
5216
|
+
this.event("created", listener);
|
|
5217
|
+
}
|
|
5218
|
+
static updating(listener) {
|
|
5219
|
+
this.event("updating", listener);
|
|
5220
|
+
}
|
|
5221
|
+
static updated(listener) {
|
|
5222
|
+
this.event("updated", listener);
|
|
5223
|
+
}
|
|
5224
|
+
static deleting(listener) {
|
|
5225
|
+
this.event("deleting", listener);
|
|
5226
|
+
}
|
|
5227
|
+
static deleted(listener) {
|
|
5228
|
+
this.event("deleted", listener);
|
|
5229
|
+
}
|
|
5230
|
+
static restoring(listener) {
|
|
5231
|
+
this.event("restoring", listener);
|
|
5232
|
+
}
|
|
5233
|
+
static restored(listener) {
|
|
5234
|
+
this.event("restored", listener);
|
|
5235
|
+
}
|
|
5236
|
+
static forceDeleting(listener) {
|
|
5237
|
+
this.event("forceDeleting", listener);
|
|
5238
|
+
}
|
|
5239
|
+
static forceDeleted(listener) {
|
|
5240
|
+
this.event("forceDeleted", listener);
|
|
5241
|
+
}
|
|
5242
|
+
/**
|
|
4975
5243
|
* Remove listeners for an event. If listener is omitted, all listeners for that event are removed.
|
|
4976
5244
|
*
|
|
4977
5245
|
* @param event
|
|
@@ -4992,6 +5260,34 @@ var Model = class Model {
|
|
|
4992
5260
|
this.eventListeners = {};
|
|
4993
5261
|
}
|
|
4994
5262
|
/**
|
|
5263
|
+
* Execute a callback while suppressing lifecycle events for all models.
|
|
5264
|
+
*
|
|
5265
|
+
* @param callback
|
|
5266
|
+
* @returns
|
|
5267
|
+
*/
|
|
5268
|
+
static async withoutEvents(callback) {
|
|
5269
|
+
Model.eventsSuppressed += 1;
|
|
5270
|
+
try {
|
|
5271
|
+
return await callback();
|
|
5272
|
+
} finally {
|
|
5273
|
+
Model.eventsSuppressed = Math.max(0, Model.eventsSuppressed - 1);
|
|
5274
|
+
}
|
|
5275
|
+
}
|
|
5276
|
+
/**
|
|
5277
|
+
* Execute a callback within a transaction scope.
|
|
5278
|
+
* Nested calls reuse the active transaction client.
|
|
5279
|
+
*
|
|
5280
|
+
* @param callback
|
|
5281
|
+
* @param options
|
|
5282
|
+
* @returns
|
|
5283
|
+
*/
|
|
5284
|
+
static async transaction(callback, options = {}) {
|
|
5285
|
+
ensureArkormConfigLoading();
|
|
5286
|
+
return await runArkormTransaction(async (client) => {
|
|
5287
|
+
return await callback(client);
|
|
5288
|
+
}, options);
|
|
5289
|
+
}
|
|
5290
|
+
/**
|
|
4995
5291
|
* Get the Prisma delegate for the model.
|
|
4996
5292
|
* If a delegate name is provided, it will attempt to resolve that delegate.
|
|
4997
5293
|
* Otherwise, it will attempt to resolve a delegate based on the model's name or
|
|
@@ -5009,9 +5305,20 @@ var Model = class Model {
|
|
|
5009
5305
|
`${str(key).singular()}`,
|
|
5010
5306
|
`${str(key).camel().singular()}`
|
|
5011
5307
|
];
|
|
5308
|
+
const activeTransactionClient = getActiveTransactionClient();
|
|
5012
5309
|
const runtimeClient = getRuntimePrismaClient();
|
|
5013
|
-
const
|
|
5014
|
-
|
|
5310
|
+
const sources = activeTransactionClient ? [
|
|
5311
|
+
activeTransactionClient,
|
|
5312
|
+
this.client,
|
|
5313
|
+
runtimeClient
|
|
5314
|
+
] : [this.client, runtimeClient];
|
|
5315
|
+
const resolved = candidates.flatMap((name) => sources.map((source) => source?.[name])).find((candidate) => isDelegateLike(candidate));
|
|
5316
|
+
if (!resolved) throw new MissingDelegateException(`Database delegate [${key}] is not configured.`, {
|
|
5317
|
+
operation: "getDelegate",
|
|
5318
|
+
model: this.name,
|
|
5319
|
+
delegate: key,
|
|
5320
|
+
meta: { candidates }
|
|
5321
|
+
});
|
|
5015
5322
|
return resolved;
|
|
5016
5323
|
}
|
|
5017
5324
|
/**
|
|
@@ -5021,16 +5328,27 @@ var Model = class Model {
|
|
|
5021
5328
|
* @returns
|
|
5022
5329
|
*/
|
|
5023
5330
|
static query() {
|
|
5331
|
+
Model.ensureModelBooted(this);
|
|
5024
5332
|
let builder = new QueryBuilder(this.getDelegate(), this);
|
|
5025
5333
|
const modelClass = this;
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
5334
|
+
if (!Model.areGlobalScopesSuppressed(modelClass)) {
|
|
5335
|
+
modelClass.ensureOwnGlobalScopes();
|
|
5336
|
+
Object.values(modelClass.globalScopes).forEach((scope) => {
|
|
5337
|
+
const scoped = scope(builder);
|
|
5338
|
+
if (scoped && scoped !== builder) builder = scoped;
|
|
5339
|
+
});
|
|
5340
|
+
}
|
|
5031
5341
|
return builder;
|
|
5032
5342
|
}
|
|
5033
5343
|
/**
|
|
5344
|
+
* Boot hook for subclasses to register scopes or perform one-time setup.
|
|
5345
|
+
*/
|
|
5346
|
+
static boot() {}
|
|
5347
|
+
/**
|
|
5348
|
+
* Booted hook for subclasses to register callbacks after boot logic runs.
|
|
5349
|
+
*/
|
|
5350
|
+
static booted() {}
|
|
5351
|
+
/**
|
|
5034
5352
|
* Get a query builder instance that includes soft-deleted records.
|
|
5035
5353
|
*
|
|
5036
5354
|
* @param this
|
|
@@ -5093,6 +5411,36 @@ var Model = class Model {
|
|
|
5093
5411
|
static hydrateMany(attributes) {
|
|
5094
5412
|
return attributes.map((attribute) => new this(attribute));
|
|
5095
5413
|
}
|
|
5414
|
+
/**
|
|
5415
|
+
* Hydrate a model instance and dispatch the retrieved lifecycle event.
|
|
5416
|
+
*
|
|
5417
|
+
* @param this
|
|
5418
|
+
* @param attributes
|
|
5419
|
+
* @returns
|
|
5420
|
+
*/
|
|
5421
|
+
static async hydrateRetrieved(attributes) {
|
|
5422
|
+
Model.ensureModelBooted(this);
|
|
5423
|
+
if (!Model.hasEventListeners(this, "retrieved")) return this.hydrate(attributes);
|
|
5424
|
+
const model = this.hydrate(attributes);
|
|
5425
|
+
await Model.dispatchEvent(this, "retrieved", model);
|
|
5426
|
+
return model;
|
|
5427
|
+
}
|
|
5428
|
+
/**
|
|
5429
|
+
* Hydrate multiple model instances and dispatch the retrieved lifecycle event for each.
|
|
5430
|
+
*
|
|
5431
|
+
* @param this
|
|
5432
|
+
* @param attributes
|
|
5433
|
+
* @returns
|
|
5434
|
+
*/
|
|
5435
|
+
static async hydrateManyRetrieved(attributes) {
|
|
5436
|
+
Model.ensureModelBooted(this);
|
|
5437
|
+
if (!Model.hasEventListeners(this, "retrieved")) return this.hydrateMany(attributes);
|
|
5438
|
+
const models = this.hydrateMany(attributes);
|
|
5439
|
+
await Promise.all(models.map(async (model) => {
|
|
5440
|
+
await Model.dispatchEvent(this, "retrieved", model);
|
|
5441
|
+
}));
|
|
5442
|
+
return models;
|
|
5443
|
+
}
|
|
5096
5444
|
fill(attributes) {
|
|
5097
5445
|
Object.entries(attributes).forEach(([key, value]) => {
|
|
5098
5446
|
this.setAttribute(key, value);
|
|
@@ -5149,6 +5497,14 @@ var Model = class Model {
|
|
|
5149
5497
|
return this;
|
|
5150
5498
|
}
|
|
5151
5499
|
/**
|
|
5500
|
+
* Save the model without dispatching lifecycle events.
|
|
5501
|
+
*
|
|
5502
|
+
* @returns
|
|
5503
|
+
*/
|
|
5504
|
+
async saveQuietly() {
|
|
5505
|
+
return await Model.withoutEvents(() => this.save());
|
|
5506
|
+
}
|
|
5507
|
+
/**
|
|
5152
5508
|
* Delete the model from the database.
|
|
5153
5509
|
* If soft deletes are enabled, it will perform a soft delete by
|
|
5154
5510
|
* setting the deleted at column to the current date.
|
|
@@ -5174,6 +5530,14 @@ var Model = class Model {
|
|
|
5174
5530
|
return this;
|
|
5175
5531
|
}
|
|
5176
5532
|
/**
|
|
5533
|
+
* Delete the model without dispatching lifecycle events.
|
|
5534
|
+
*
|
|
5535
|
+
* @returns
|
|
5536
|
+
*/
|
|
5537
|
+
async deleteQuietly() {
|
|
5538
|
+
return await Model.withoutEvents(() => this.delete());
|
|
5539
|
+
}
|
|
5540
|
+
/**
|
|
5177
5541
|
* Permanently delete the model from the database, regardless of whether soft
|
|
5178
5542
|
* deletes are enabled.
|
|
5179
5543
|
*
|
|
@@ -5192,6 +5556,14 @@ var Model = class Model {
|
|
|
5192
5556
|
return this;
|
|
5193
5557
|
}
|
|
5194
5558
|
/**
|
|
5559
|
+
* Force delete the model without dispatching lifecycle events.
|
|
5560
|
+
*
|
|
5561
|
+
* @returns
|
|
5562
|
+
*/
|
|
5563
|
+
async forceDeleteQuietly() {
|
|
5564
|
+
return await Model.withoutEvents(() => this.forceDelete());
|
|
5565
|
+
}
|
|
5566
|
+
/**
|
|
5195
5567
|
* Restore a soft-deleted model by setting the deleted at column to null.
|
|
5196
5568
|
*
|
|
5197
5569
|
* @returns
|
|
@@ -5209,6 +5581,14 @@ var Model = class Model {
|
|
|
5209
5581
|
return this;
|
|
5210
5582
|
}
|
|
5211
5583
|
/**
|
|
5584
|
+
* Restore the model without dispatching lifecycle events.
|
|
5585
|
+
*
|
|
5586
|
+
* @returns
|
|
5587
|
+
*/
|
|
5588
|
+
async restoreQuietly() {
|
|
5589
|
+
return await Model.withoutEvents(() => this.restore());
|
|
5590
|
+
}
|
|
5591
|
+
/**
|
|
5212
5592
|
* Load related models onto the current model instance.
|
|
5213
5593
|
*
|
|
5214
5594
|
* @param relations
|
|
@@ -5261,6 +5641,47 @@ var Model = class Model {
|
|
|
5261
5641
|
return this.toObject();
|
|
5262
5642
|
}
|
|
5263
5643
|
/**
|
|
5644
|
+
* Determine if another model represents the same persisted record.
|
|
5645
|
+
*
|
|
5646
|
+
* @param model
|
|
5647
|
+
* @returns
|
|
5648
|
+
*/
|
|
5649
|
+
is(model) {
|
|
5650
|
+
if (!(model instanceof Model)) return false;
|
|
5651
|
+
if (this.constructor !== model.constructor) return false;
|
|
5652
|
+
const identifier = this.getAttribute("id");
|
|
5653
|
+
const otherIdentifier = model.getAttribute("id");
|
|
5654
|
+
if (identifier == null || otherIdentifier == null) return false;
|
|
5655
|
+
return identifier === otherIdentifier;
|
|
5656
|
+
}
|
|
5657
|
+
/**
|
|
5658
|
+
* Determine if another model does not represent the same persisted record.
|
|
5659
|
+
*
|
|
5660
|
+
* @param model
|
|
5661
|
+
* @returns
|
|
5662
|
+
*/
|
|
5663
|
+
isNot(model) {
|
|
5664
|
+
return !this.is(model);
|
|
5665
|
+
}
|
|
5666
|
+
/**
|
|
5667
|
+
* Determine if another model is the same in-memory instance.
|
|
5668
|
+
*
|
|
5669
|
+
* @param model
|
|
5670
|
+
* @returns
|
|
5671
|
+
*/
|
|
5672
|
+
isSame(model) {
|
|
5673
|
+
return this === model;
|
|
5674
|
+
}
|
|
5675
|
+
/**
|
|
5676
|
+
* Determine if another model is not the same in-memory instance.
|
|
5677
|
+
*
|
|
5678
|
+
* @param model
|
|
5679
|
+
* @returns
|
|
5680
|
+
*/
|
|
5681
|
+
isNotSame(model) {
|
|
5682
|
+
return !this.isSame(model);
|
|
5683
|
+
}
|
|
5684
|
+
/**
|
|
5264
5685
|
* Define a has one relationship.
|
|
5265
5686
|
*
|
|
5266
5687
|
* @param related
|
|
@@ -5424,6 +5845,84 @@ var Model = class Model {
|
|
|
5424
5845
|
if (!Object.prototype.hasOwnProperty.call(this, "eventListeners")) this.eventListeners = { ...this.eventListeners || {} };
|
|
5425
5846
|
}
|
|
5426
5847
|
/**
|
|
5848
|
+
* Resolve lifecycle state for the provided model class.
|
|
5849
|
+
*
|
|
5850
|
+
* @param modelClass
|
|
5851
|
+
* @returns
|
|
5852
|
+
*/
|
|
5853
|
+
static getLifecycleState(modelClass) {
|
|
5854
|
+
const existing = Model.lifecycleStates.get(modelClass);
|
|
5855
|
+
if (existing) return existing;
|
|
5856
|
+
const state = {
|
|
5857
|
+
booted: false,
|
|
5858
|
+
booting: false,
|
|
5859
|
+
globalScopesSuppressed: 0
|
|
5860
|
+
};
|
|
5861
|
+
Model.lifecycleStates.set(modelClass, state);
|
|
5862
|
+
return state;
|
|
5863
|
+
}
|
|
5864
|
+
/**
|
|
5865
|
+
* Ensure the target model class has executed its boot lifecycle.
|
|
5866
|
+
*
|
|
5867
|
+
* @param modelClass
|
|
5868
|
+
*/
|
|
5869
|
+
static ensureModelBooted(modelClass) {
|
|
5870
|
+
const state = Model.getLifecycleState(modelClass);
|
|
5871
|
+
if (state.booted || state.booting) return;
|
|
5872
|
+
state.booting = true;
|
|
5873
|
+
try {
|
|
5874
|
+
const boot = modelClass.boot;
|
|
5875
|
+
if (boot !== Model.boot) boot.call(modelClass);
|
|
5876
|
+
const booted = modelClass.booted;
|
|
5877
|
+
if (booted !== Model.booted) booted.call(modelClass);
|
|
5878
|
+
state.booted = true;
|
|
5879
|
+
} finally {
|
|
5880
|
+
state.booting = false;
|
|
5881
|
+
}
|
|
5882
|
+
}
|
|
5883
|
+
/**
|
|
5884
|
+
* Determine if global scopes are currently suppressed for the model class.
|
|
5885
|
+
*
|
|
5886
|
+
* @param modelClass
|
|
5887
|
+
* @returns
|
|
5888
|
+
*/
|
|
5889
|
+
static areGlobalScopesSuppressed(modelClass) {
|
|
5890
|
+
return Model.getLifecycleState(modelClass).globalScopesSuppressed > 0;
|
|
5891
|
+
}
|
|
5892
|
+
/**
|
|
5893
|
+
* Resolve configured class-based event handlers for a lifecycle event.
|
|
5894
|
+
*
|
|
5895
|
+
* @param modelClass
|
|
5896
|
+
* @param event
|
|
5897
|
+
* @returns
|
|
5898
|
+
*/
|
|
5899
|
+
static resolveDispatchedEventListeners(modelClass, event) {
|
|
5900
|
+
const configured = modelClass.dispatchesEvents[event];
|
|
5901
|
+
if (!configured) return [];
|
|
5902
|
+
return (Array.isArray(configured) ? configured : [configured]).map((entry) => {
|
|
5903
|
+
const handler = typeof entry === "function" ? new entry() : entry;
|
|
5904
|
+
if (!handler || typeof handler.handle !== "function") throw new ArkormException(`Invalid event handler configured for [${modelClass.name}.${event}].`);
|
|
5905
|
+
return async (model) => {
|
|
5906
|
+
await handler.handle(model);
|
|
5907
|
+
};
|
|
5908
|
+
});
|
|
5909
|
+
}
|
|
5910
|
+
/**
|
|
5911
|
+
* Determine whether a lifecycle event has any registered listeners.
|
|
5912
|
+
*
|
|
5913
|
+
* @param modelClass
|
|
5914
|
+
* @param event
|
|
5915
|
+
* @returns
|
|
5916
|
+
*/
|
|
5917
|
+
static hasEventListeners(modelClass, event) {
|
|
5918
|
+
if (Model.eventsSuppressed > 0) return false;
|
|
5919
|
+
modelClass.ensureOwnEventListeners();
|
|
5920
|
+
if ((modelClass.eventListeners[event] || []).length > 0) return true;
|
|
5921
|
+
const configuredDispatchers = modelClass.dispatchesEvents[event];
|
|
5922
|
+
if (!configuredDispatchers) return false;
|
|
5923
|
+
return Array.isArray(configuredDispatchers) ? configuredDispatchers.length > 0 : true;
|
|
5924
|
+
}
|
|
5925
|
+
/**
|
|
5427
5926
|
* Dispatches lifecycle events to registered listeners.
|
|
5428
5927
|
*
|
|
5429
5928
|
* @param modelClass
|
|
@@ -5431,8 +5930,9 @@ var Model = class Model {
|
|
|
5431
5930
|
* @param model
|
|
5432
5931
|
*/
|
|
5433
5932
|
static async dispatchEvent(modelClass, event, model) {
|
|
5434
|
-
|
|
5435
|
-
|
|
5933
|
+
Model.ensureModelBooted(modelClass);
|
|
5934
|
+
if (!Model.hasEventListeners(modelClass, event)) return;
|
|
5935
|
+
const listeners = [...Model.resolveDispatchedEventListeners(modelClass, event), ...modelClass.eventListeners[event] || []];
|
|
5436
5936
|
for (const listener of listeners) await listener(model);
|
|
5437
5937
|
}
|
|
5438
5938
|
/**
|
|
@@ -5452,4 +5952,4 @@ var Model = class Model {
|
|
|
5452
5952
|
};
|
|
5453
5953
|
|
|
5454
5954
|
//#endregion
|
|
5455
|
-
export { ArkormCollection, ArkormException, Attribute, CliApp, ForeignKeyBuilder, InitCommand, InlineFactory, LengthAwarePaginator, MIGRATION_BRAND, MakeFactoryCommand, MakeMigrationCommand, MakeModelCommand, MakeSeederCommand, MigrateCommand, MigrateRollbackCommand, Migration, MigrationHistoryCommand, Model, ModelFactory, ModelNotFoundException, ModelsSyncCommand, PRISMA_MODEL_REGEX, Paginator, QueryBuilder, SEEDER_BRAND, SchemaBuilder, SeedCommand, Seeder, TableBuilder, URLDriver, applyAlterTableOperation, applyCreateTableOperation, applyDropTableOperation, applyMigrationRollbackToPrismaSchema, applyMigrationToPrismaSchema, applyOperationsToPrismaSchema, buildFieldLine, buildIndexLine, buildInverseRelationLine, buildMigrationIdentity, buildMigrationRunId, buildMigrationSource, buildModelBlock, buildRelationLine, computeMigrationChecksum, configureArkormRuntime, createMigrationTimestamp, createPrismaAdapter, createPrismaDelegateMap, defineConfig, defineFactory, deriveCollectionFieldName, deriveInverseRelationAlias, deriveRelationFieldName, ensureArkormConfigLoading, escapeRegex, findAppliedMigration, findModelBlock, formatDefaultValue, formatRelationAction, generateMigrationFile, getDefaultStubsPath, getLastMigrationRun, getLatestAppliedMigrations, getMigrationPlan, getRuntimePaginationURLDriverFactory, getRuntimePrismaClient, getUserConfig, inferDelegateName, isDelegateLike, isMigrationApplied, loadArkormConfig, markMigrationApplied, markMigrationRun, pad, readAppliedMigrationsState, removeAppliedMigration, resetArkormRuntimeForTests, resolveCast, resolveMigrationClassName, resolveMigrationStateFilePath, resolvePrismaType, runMigrationWithPrisma, runPrismaCommand, toMigrationFileSlug, toModelName, writeAppliedMigrationsState };
|
|
5955
|
+
export { ArkormCollection, ArkormException, Attribute, CliApp, ForeignKeyBuilder, InitCommand, InlineFactory, LengthAwarePaginator, MIGRATION_BRAND, MakeFactoryCommand, MakeMigrationCommand, MakeModelCommand, MakeSeederCommand, MigrateCommand, MigrateRollbackCommand, Migration, MigrationHistoryCommand, MissingDelegateException, Model, ModelFactory, ModelNotFoundException, ModelsSyncCommand, PRISMA_MODEL_REGEX, Paginator, QueryBuilder, QueryConstraintException, RelationResolutionException, SEEDER_BRAND, SchemaBuilder, ScopeNotDefinedException, SeedCommand, Seeder, TableBuilder, URLDriver, UniqueConstraintResolutionException, UnsupportedAdapterFeatureException, applyAlterTableOperation, applyCreateTableOperation, applyDropTableOperation, applyMigrationRollbackToPrismaSchema, applyMigrationToPrismaSchema, applyOperationsToPrismaSchema, buildFieldLine, buildIndexLine, buildInverseRelationLine, buildMigrationIdentity, buildMigrationRunId, buildMigrationSource, buildModelBlock, buildRelationLine, computeMigrationChecksum, configureArkormRuntime, createMigrationTimestamp, createPrismaAdapter, createPrismaDelegateMap, defineConfig, defineFactory, deriveCollectionFieldName, deriveInverseRelationAlias, deriveRelationFieldName, ensureArkormConfigLoading, escapeRegex, findAppliedMigration, findModelBlock, formatDefaultValue, formatRelationAction, generateMigrationFile, getActiveTransactionClient, getDefaultStubsPath, getLastMigrationRun, getLatestAppliedMigrations, getMigrationPlan, getRuntimePaginationCurrentPageResolver, getRuntimePaginationURLDriverFactory, getRuntimePrismaClient, getUserConfig, inferDelegateName, isDelegateLike, isMigrationApplied, isTransactionCapableClient, loadArkormConfig, markMigrationApplied, markMigrationRun, pad, readAppliedMigrationsState, removeAppliedMigration, resetArkormRuntimeForTests, resolveCast, resolveMigrationClassName, resolveMigrationStateFilePath, resolvePrismaType, runArkormTransaction, runMigrationWithPrisma, runPrismaCommand, toMigrationFileSlug, toModelName, writeAppliedMigrationsState };
|