arkormx 2.6.1 → 2.8.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/dist/cli.mjs +53 -7
- package/dist/{index-BTBfGF_o.d.mts → index-4mi5sLRA.d.cts} +556 -7
- package/dist/{index-CBh5Z2sS.d.cts → index-De8zXqTD.d.mts} +556 -7
- package/dist/index.cjs +948 -15
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +948 -16
- package/dist/relationship/index.cjs +1 -1
- package/dist/relationship/index.d.cts +1 -1
- package/dist/relationship/index.d.mts +1 -1
- package/dist/relationship/index.mjs +1 -1
- package/dist/{relationship-DT4myOWX.mjs → relationship--l8RA_yy.mjs} +52 -8
- package/dist/{relationship-CxCQj_Pg.cjs → relationship-WiXlopzY.cjs} +52 -8
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as applyOperationsToPersistedColumnMappingsState, $t as resolvePrismaType, A as getRuntimePrismaClient, An as writeAppliedMigrationsStateToStore, At as buildInverseRelationLine, B as getRegisteredModels, Bt as deriveRelationFieldName, C as getActiveTransactionClient, Cn as markMigrationRun, Ct as applyMigrationRollbackToPrismaSchema, D as getRuntimeDebugHandler, Dn as resolveMigrationStateFilePath, Dt as buildEnumBlock, E as getRuntimeClient, En as removeAppliedMigration, Et as applyOperationsToPrismaSchema, F as loadArkormConfig, Fn as RelationResolutionException, Ft as buildUniqueConstraintLine, G as loadModelsFrom, Gt as formatDefaultValue, H as getRegisteredSeeders, Ht as escapeRegex, I as resetArkormRuntimeForTests, In as ArkormCollection, It as createMigrationTimestamp, J as registerMigrations, Jt as generateMigrationFile, K as loadSeedersFrom, Kt as formatEnumDefaultValue, L as runArkormTransaction, Ln as ArkormException, Lt as deriveCollectionFieldName, M as isDelegateLike, Mn as UnsupportedAdapterFeatureException, Mt as buildModelBlock, N as isQuerySchemaLike, Nn as SetBasedEagerLoader, Nt as buildPrimaryKeyLine, O as getRuntimePaginationCurrentPageResolver, On as supportsDatabaseMigrationState, Ot as buildFieldLine, P as isTransactionCapableClient, Pt as buildRelationLine, Q as resetRuntimeRegistryForTests, Qt as resolveMigrationClassName, R as getRegisteredFactories, Rt as deriveInverseRelationAlias, S as getActiveTransactionAdapter, Sn as markMigrationApplied, St as applyMigrationRollbackToDatabase, T as getRuntimeAdapter, Tn as readAppliedMigrationsStateFromStore, Tt as applyMigrationToPrismaSchema, U as loadFactoriesFrom, Ut as findEnumBlock, V as getRegisteredPaths, Vt as deriveSingularFieldName, W as loadMigrationsFrom, Wt as findModelBlock, X as registerPaths, Xt as pad, Y as registerModels, Yt as getMigrationPlan, Z as registerSeeders, Zt as resolveEnumName, _ as bindAdapterToModels, _n as deleteAppliedMigrationsStateFromStore, _t as PRISMA_ENUM_REGEX, a as HasOneThroughRelation, an as supportsDatabaseReset, at as getPersistedPrimaryKeyGeneration, b as emitRuntimeDebugEvent, bn as getLatestAppliedMigrations, bt as applyCreateTableOperation, c as HasManyRelation, cn as SchemaBuilder, ct as readPersistedColumnMappingsState, d as BelongsToManyRelation, dn as PrimaryKeyGenerationPlanner, dt as resolveColumnMappingsFilePath, en as runMigrationWithPrisma, et as createEmptyPersistedColumnMappingsState, f as Relation, fn as ForeignKeyBuilder, ft as resolvePersistedMetadataFeatures, g as awaitConfiguredModelsRegistration, gn as createEmptyAppliedMigrationsState, gt as PRISMA_ENUM_MEMBER_REGEX, h as URLDriver, hn as computeMigrationChecksum, ht as writePersistedColumnMappingsState, i as MorphManyRelation, in as supportsDatabaseMigrationExecution, it as getPersistedEnumTsType, j as getUserConfig, jn as RuntimeModuleLoader, jt as buildMigrationSource, k as getRuntimePaginationURLDriverFactory, kn as writeAppliedMigrationsState, kt as buildIndexLine, l as BelongsToRelation, ln as EnumBuilder, lt as rebuildPersistedColumnMappingsState, m as Paginator, mn as buildMigrationRunId, mt as validatePersistedMetadataFeaturesForMigrations, n as MorphToManyRelation, nn as stripPrismaSchemaModelsAndEnums, nt as getPersistedColumnMap, o as HasOneRelation, on as toMigrationFileSlug, ot as getPersistedTableMetadata, p as LengthAwarePaginator, pn as buildMigrationIdentity, pt as syncPersistedColumnMappingsFromState, q as registerFactories, qt as formatRelationAction, r as MorphOneRelation, rn as supportsDatabaseCreation, rt as getPersistedEnumMap, s as HasManyThroughRelation, sn as toModelName, st as getPersistedTimestampColumns, t as MorphToRelation, tn as runPrismaCommand, tt as deletePersistedColumnMappingsState, un as TableBuilder, ut as resetPersistedColumnMappingsCache, v as configureArkormRuntime, vn as findAppliedMigration, vt as PRISMA_MODEL_REGEX, w as getDefaultStubsPath, wn as readAppliedMigrationsState, wt as applyMigrationToDatabase, x as ensureArkormConfigLoading, xn as isMigrationApplied, xt as applyDropTableOperation, y as defineConfig, yn as getLastMigrationRun, yt as applyAlterTableOperation, z as getRegisteredMigrations, zt as deriveRelationAlias } from "./relationship
|
|
1
|
+
import { $ as applyOperationsToPersistedColumnMappingsState, $t as resolvePrismaType, A as getRuntimePrismaClient, An as writeAppliedMigrationsStateToStore, At as buildInverseRelationLine, B as getRegisteredModels, Bt as deriveRelationFieldName, C as getActiveTransactionClient, Cn as markMigrationRun, Ct as applyMigrationRollbackToPrismaSchema, D as getRuntimeDebugHandler, Dn as resolveMigrationStateFilePath, Dt as buildEnumBlock, E as getRuntimeClient, En as removeAppliedMigration, Et as applyOperationsToPrismaSchema, F as loadArkormConfig, Fn as RelationResolutionException, Ft as buildUniqueConstraintLine, G as loadModelsFrom, Gt as formatDefaultValue, H as getRegisteredSeeders, Ht as escapeRegex, I as resetArkormRuntimeForTests, In as ArkormCollection, It as createMigrationTimestamp, J as registerMigrations, Jt as generateMigrationFile, K as loadSeedersFrom, Kt as formatEnumDefaultValue, L as runArkormTransaction, Ln as ArkormException, Lt as deriveCollectionFieldName, M as isDelegateLike, Mn as UnsupportedAdapterFeatureException, Mt as buildModelBlock, N as isQuerySchemaLike, Nn as SetBasedEagerLoader, Nt as buildPrimaryKeyLine, O as getRuntimePaginationCurrentPageResolver, On as supportsDatabaseMigrationState, Ot as buildFieldLine, P as isTransactionCapableClient, Pt as buildRelationLine, Q as resetRuntimeRegistryForTests, Qt as resolveMigrationClassName, R as getRegisteredFactories, Rt as deriveInverseRelationAlias, S as getActiveTransactionAdapter, Sn as markMigrationApplied, St as applyMigrationRollbackToDatabase, T as getRuntimeAdapter, Tn as readAppliedMigrationsStateFromStore, Tt as applyMigrationToPrismaSchema, U as loadFactoriesFrom, Ut as findEnumBlock, V as getRegisteredPaths, Vt as deriveSingularFieldName, W as loadMigrationsFrom, Wt as findModelBlock, X as registerPaths, Xt as pad, Y as registerModels, Yt as getMigrationPlan, Z as registerSeeders, Zt as resolveEnumName, _ as bindAdapterToModels, _n as deleteAppliedMigrationsStateFromStore, _t as PRISMA_ENUM_REGEX, a as HasOneThroughRelation, an as supportsDatabaseReset, at as getPersistedPrimaryKeyGeneration, b as emitRuntimeDebugEvent, bn as getLatestAppliedMigrations, bt as applyCreateTableOperation, c as HasManyRelation, cn as SchemaBuilder, ct as readPersistedColumnMappingsState, d as BelongsToManyRelation, dn as PrimaryKeyGenerationPlanner, dt as resolveColumnMappingsFilePath, en as runMigrationWithPrisma, et as createEmptyPersistedColumnMappingsState, f as Relation, fn as ForeignKeyBuilder, ft as resolvePersistedMetadataFeatures, g as awaitConfiguredModelsRegistration, gn as createEmptyAppliedMigrationsState, gt as PRISMA_ENUM_MEMBER_REGEX, h as URLDriver, hn as computeMigrationChecksum, ht as writePersistedColumnMappingsState, i as MorphManyRelation, in as supportsDatabaseMigrationExecution, it as getPersistedEnumTsType, j as getUserConfig, jn as RuntimeModuleLoader, jt as buildMigrationSource, k as getRuntimePaginationURLDriverFactory, kn as writeAppliedMigrationsState, kt as buildIndexLine, l as BelongsToRelation, ln as EnumBuilder, lt as rebuildPersistedColumnMappingsState, m as Paginator, mn as buildMigrationRunId, mt as validatePersistedMetadataFeaturesForMigrations, n as MorphToManyRelation, nn as stripPrismaSchemaModelsAndEnums, nt as getPersistedColumnMap, o as HasOneRelation, on as toMigrationFileSlug, ot as getPersistedTableMetadata, p as LengthAwarePaginator, pn as buildMigrationIdentity, pt as syncPersistedColumnMappingsFromState, q as registerFactories, qt as formatRelationAction, r as MorphOneRelation, rn as supportsDatabaseCreation, rt as getPersistedEnumMap, s as HasManyThroughRelation, sn as toModelName, st as getPersistedTimestampColumns, t as MorphToRelation, tn as runPrismaCommand, tt as deletePersistedColumnMappingsState, un as TableBuilder, ut as resetPersistedColumnMappingsCache, v as configureArkormRuntime, vn as findAppliedMigration, vt as PRISMA_MODEL_REGEX, w as getDefaultStubsPath, wn as readAppliedMigrationsState, wt as applyMigrationToDatabase, x as ensureArkormConfigLoading, xn as isMigrationApplied, xt as applyDropTableOperation, y as defineConfig, yn as getLastMigrationRun, yt as applyAlterTableOperation, z as getRegisteredMigrations, zt as deriveRelationAlias } from "./relationship--l8RA_yy.mjs";
|
|
2
2
|
import { Pool } from "pg";
|
|
3
3
|
import { join, resolve } from "node:path";
|
|
4
4
|
import { createRequire } from "module";
|
|
@@ -63,7 +63,8 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
|
|
|
63
63
|
rawSelect: true,
|
|
64
64
|
rawWhere: true,
|
|
65
65
|
distinct: true,
|
|
66
|
-
groupBy: true
|
|
66
|
+
groupBy: true,
|
|
67
|
+
joins: true
|
|
67
68
|
};
|
|
68
69
|
}
|
|
69
70
|
resolveConfiguredDatabaseName(connectionString) {
|
|
@@ -88,6 +89,85 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
|
|
|
88
89
|
quoteIdentifier(value) {
|
|
89
90
|
return `"${value.replace(/"/g, "\"\"")}"`;
|
|
90
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Wraps bare camelCase identifiers in a fragment of raw SQL with double quotes
|
|
94
|
+
* so PostgreSQL preserves their casing instead of folding them to lower case.
|
|
95
|
+
*
|
|
96
|
+
* Identifiers that are already quoted, string literals, dollar-quoted bodies,
|
|
97
|
+
* comments and function names (a camelCase token immediately followed by `(`)
|
|
98
|
+
* are left untouched. Lower-case identifiers are also left alone since
|
|
99
|
+
* PostgreSQL folds them to the same value with or without quotes.
|
|
100
|
+
*
|
|
101
|
+
* @param sql The raw SQL fragment to normalize.
|
|
102
|
+
* @returns
|
|
103
|
+
*/
|
|
104
|
+
quoteCamelCaseIdentifiers(sql) {
|
|
105
|
+
let result = "";
|
|
106
|
+
let index = 0;
|
|
107
|
+
const isIdentifierStart = (char) => /[A-Za-z_]/.test(char);
|
|
108
|
+
const isIdentifierPart = (char) => /[A-Za-z0-9_$]/.test(char);
|
|
109
|
+
const isMixedCase = (token) => /[A-Z]/.test(token) && /[a-z]/.test(token);
|
|
110
|
+
while (index < sql.length) {
|
|
111
|
+
const char = sql[index];
|
|
112
|
+
if (char === "'") {
|
|
113
|
+
const start = index;
|
|
114
|
+
index += 1;
|
|
115
|
+
while (index < sql.length) {
|
|
116
|
+
if (sql[index] === "'" && sql[index + 1] === "'") {
|
|
117
|
+
index += 2;
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (sql[index] === "'") {
|
|
121
|
+
index += 1;
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
index += 1;
|
|
125
|
+
}
|
|
126
|
+
result += sql.slice(start, index);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (char === "\"") {
|
|
130
|
+
const start = index;
|
|
131
|
+
index += 1;
|
|
132
|
+
while (index < sql.length) {
|
|
133
|
+
if (sql[index] === "\"" && sql[index + 1] === "\"") {
|
|
134
|
+
index += 2;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
if (sql[index] === "\"") {
|
|
138
|
+
index += 1;
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
index += 1;
|
|
142
|
+
}
|
|
143
|
+
result += sql.slice(start, index);
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
if (char === "$") {
|
|
147
|
+
const tagMatch = /^\$[A-Za-z0-9_]*\$/.exec(sql.slice(index));
|
|
148
|
+
if (tagMatch) {
|
|
149
|
+
const tag = tagMatch[0];
|
|
150
|
+
const closeIndex = sql.indexOf(tag, index + tag.length);
|
|
151
|
+
const end = closeIndex === -1 ? sql.length : closeIndex + tag.length;
|
|
152
|
+
result += sql.slice(index, end);
|
|
153
|
+
index = end;
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (isIdentifierStart(char)) {
|
|
158
|
+
const start = index;
|
|
159
|
+
while (index < sql.length && isIdentifierPart(sql[index])) index += 1;
|
|
160
|
+
const token = sql.slice(start, index);
|
|
161
|
+
const isFunctionCall = sql[index] === "(";
|
|
162
|
+
if (isMixedCase(token) && !isFunctionCall) result += this.quoteIdentifier(token);
|
|
163
|
+
else result += token;
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
result += char;
|
|
167
|
+
index += 1;
|
|
168
|
+
}
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
91
171
|
quoteLiteral(value) {
|
|
92
172
|
if (value == null) return "null";
|
|
93
173
|
if (typeof value === "number" || typeof value === "bigint") return String(value);
|
|
@@ -107,10 +187,102 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
|
|
|
107
187
|
async executeRawStatement(statement, executor = this.db) {
|
|
108
188
|
await sql.raw(statement).execute(executor);
|
|
109
189
|
}
|
|
190
|
+
/**
|
|
191
|
+
* Splits a SQL script into individual top-level statements.
|
|
192
|
+
*
|
|
193
|
+
* The PostgreSQL wire protocol used by Kysely rejects scripts that contain
|
|
194
|
+
* more than one command, so multi-statement raw SQL (for example a migration
|
|
195
|
+
* that mixes `do $$ ... $$` blocks with `alter table` statements) must be
|
|
196
|
+
* executed one statement at a time. Semicolons inside single-quoted strings,
|
|
197
|
+
* double-quoted identifiers, dollar-quoted bodies and comments are ignored.
|
|
198
|
+
*
|
|
199
|
+
* @param sql The raw SQL script to split.
|
|
200
|
+
* @returns
|
|
201
|
+
*/
|
|
202
|
+
splitSqlStatements(sql) {
|
|
203
|
+
const statements = [];
|
|
204
|
+
let current = "";
|
|
205
|
+
let index = 0;
|
|
206
|
+
while (index < sql.length) {
|
|
207
|
+
const char = sql[index];
|
|
208
|
+
const next = sql[index + 1];
|
|
209
|
+
if (char === "-" && next === "-") {
|
|
210
|
+
const end = sql.indexOf("\n", index);
|
|
211
|
+
const stop = end === -1 ? sql.length : end;
|
|
212
|
+
current += sql.slice(index, stop);
|
|
213
|
+
index = stop;
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
if (char === "/" && next === "*") {
|
|
217
|
+
const end = sql.indexOf("*/", index + 2);
|
|
218
|
+
const stop = end === -1 ? sql.length : end + 2;
|
|
219
|
+
current += sql.slice(index, stop);
|
|
220
|
+
index = stop;
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
if (char === "'") {
|
|
224
|
+
const start = index;
|
|
225
|
+
index += 1;
|
|
226
|
+
while (index < sql.length) {
|
|
227
|
+
if (sql[index] === "'" && sql[index + 1] === "'") {
|
|
228
|
+
index += 2;
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
if (sql[index] === "'") {
|
|
232
|
+
index += 1;
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
index += 1;
|
|
236
|
+
}
|
|
237
|
+
current += sql.slice(start, index);
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
if (char === "\"") {
|
|
241
|
+
const start = index;
|
|
242
|
+
index += 1;
|
|
243
|
+
while (index < sql.length) {
|
|
244
|
+
if (sql[index] === "\"" && sql[index + 1] === "\"") {
|
|
245
|
+
index += 2;
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
if (sql[index] === "\"") {
|
|
249
|
+
index += 1;
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
252
|
+
index += 1;
|
|
253
|
+
}
|
|
254
|
+
current += sql.slice(start, index);
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
if (char === "$") {
|
|
258
|
+
const tagMatch = /^\$[A-Za-z0-9_]*\$/.exec(sql.slice(index));
|
|
259
|
+
if (tagMatch) {
|
|
260
|
+
const tag = tagMatch[0];
|
|
261
|
+
const closeIndex = sql.indexOf(tag, index + tag.length);
|
|
262
|
+
const end = closeIndex === -1 ? sql.length : closeIndex + tag.length;
|
|
263
|
+
current += sql.slice(index, end);
|
|
264
|
+
index = end;
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
if (char === ";") {
|
|
269
|
+
if (current.trim().length > 0) statements.push(current.trim());
|
|
270
|
+
current = "";
|
|
271
|
+
index += 1;
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
current += char;
|
|
275
|
+
index += 1;
|
|
276
|
+
}
|
|
277
|
+
if (current.trim().length > 0) statements.push(current.trim());
|
|
278
|
+
return statements;
|
|
279
|
+
}
|
|
110
280
|
async rawQuery(spec) {
|
|
111
281
|
const statement = this.interpolateRawSql(spec.sql, spec.bindings);
|
|
282
|
+
const statements = this.splitSqlStatements(statement);
|
|
283
|
+
if (statements.length > 1) return await this.runMultiStatementRawQuery(statements, statement);
|
|
112
284
|
try {
|
|
113
|
-
return (await sql.raw(statement).execute(this.db)).rows ?? [];
|
|
285
|
+
return (await sql.raw(statements[0] ?? statement).execute(this.db)).rows ?? [];
|
|
114
286
|
} catch (error) {
|
|
115
287
|
throw new QueryExecutionException("Raw query execution failed for the Kysely adapter.", {
|
|
116
288
|
code: "QUERY_EXECUTION_FAILED",
|
|
@@ -122,6 +294,45 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
|
|
|
122
294
|
});
|
|
123
295
|
}
|
|
124
296
|
}
|
|
297
|
+
/**
|
|
298
|
+
* Executes a multi-statement raw SQL script one statement at a time.
|
|
299
|
+
*
|
|
300
|
+
* Each statement is sent individually so the PostgreSQL extended protocol
|
|
301
|
+
* accepts it, and the rows of the last statement that returns any are used as
|
|
302
|
+
* the result. The script is wrapped in a transaction when the adapter is not
|
|
303
|
+
* already operating inside one so partial failures do not leave the database
|
|
304
|
+
* in a half-applied state.
|
|
305
|
+
*
|
|
306
|
+
* @param statements The individual statements to execute in order.
|
|
307
|
+
* @param fullScript The original (joined) script, used for error context.
|
|
308
|
+
* @returns
|
|
309
|
+
*/
|
|
310
|
+
async runMultiStatementRawQuery(statements, fullScript) {
|
|
311
|
+
const execute = async (executor) => {
|
|
312
|
+
let rows = [];
|
|
313
|
+
for (const statement of statements) {
|
|
314
|
+
const result = await sql.raw(statement).execute(executor);
|
|
315
|
+
if (result.rows && result.rows.length > 0) rows = result.rows;
|
|
316
|
+
}
|
|
317
|
+
return rows;
|
|
318
|
+
};
|
|
319
|
+
try {
|
|
320
|
+
if (!this.db.isTransaction) return await this.db.transaction().execute((transaction) => execute(transaction));
|
|
321
|
+
return await execute(this.db);
|
|
322
|
+
} catch (error) {
|
|
323
|
+
throw new QueryExecutionException("Raw query execution failed for the Kysely adapter.", {
|
|
324
|
+
code: "QUERY_EXECUTION_FAILED",
|
|
325
|
+
operation: "adapter.rawQuery",
|
|
326
|
+
delegate: "raw",
|
|
327
|
+
inspection: this.tryInspectRawQuery(fullScript),
|
|
328
|
+
meta: {
|
|
329
|
+
sql: fullScript,
|
|
330
|
+
statements
|
|
331
|
+
},
|
|
332
|
+
cause: error
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
}
|
|
125
336
|
tryInspectRawQuery(statement) {
|
|
126
337
|
return {
|
|
127
338
|
adapter: "kysely",
|
|
@@ -403,6 +614,70 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
|
|
|
403
614
|
if (!groupBy || groupBy.length === 0) return sql``;
|
|
404
615
|
return sql` group by ${sql.join(groupBy.map((column) => sql.ref(this.mapColumn(target, column))), sql`, `)}`;
|
|
405
616
|
}
|
|
617
|
+
buildJoinClause(target, joins) {
|
|
618
|
+
if (!joins || joins.length === 0) return sql``;
|
|
619
|
+
return sql` ${sql.join(joins.map((join) => this.buildSingleJoin(target, join)), sql` `)}`;
|
|
620
|
+
}
|
|
621
|
+
joinKeyword(join) {
|
|
622
|
+
const base = {
|
|
623
|
+
inner: "inner join",
|
|
624
|
+
left: "left join",
|
|
625
|
+
right: "right join",
|
|
626
|
+
full: "full join",
|
|
627
|
+
cross: "cross join"
|
|
628
|
+
}[join.type];
|
|
629
|
+
return join.lateral ? `${base} lateral` : base;
|
|
630
|
+
}
|
|
631
|
+
buildJoinSource(join) {
|
|
632
|
+
if (join.subquery) {
|
|
633
|
+
const subquery = this.buildSelectStatement(join.subquery);
|
|
634
|
+
return join.alias ? sql`(${subquery}) as ${sql.id(join.alias)}` : sql`(${subquery})`;
|
|
635
|
+
}
|
|
636
|
+
if (join.subquerySql) return join.alias ? sql`(${sql.raw(join.subquerySql)}) as ${sql.id(join.alias)}` : sql.raw(`(${join.subquerySql})`);
|
|
637
|
+
const table = this.resolveMappedTable(join.table ?? "");
|
|
638
|
+
return join.alias ? sql`${sql.table(table)} as ${sql.id(join.alias)}` : sql.table(table);
|
|
639
|
+
}
|
|
640
|
+
buildSingleJoin(target, join) {
|
|
641
|
+
const keyword = sql.raw(this.joinKeyword(join));
|
|
642
|
+
const source = this.buildJoinSource(join);
|
|
643
|
+
if (join.type === "cross") return sql`${keyword} ${source}`;
|
|
644
|
+
if (join.constraints.length === 0) return join.lateral ? sql`${keyword} ${source} on true` : sql`${keyword} ${source}`;
|
|
645
|
+
return sql`${keyword} ${source} on ${this.buildJoinConstraints(target, join.constraints)}`;
|
|
646
|
+
}
|
|
647
|
+
buildJoinConstraints(target, constraints) {
|
|
648
|
+
const parts = [];
|
|
649
|
+
constraints.forEach((constraint, index) => {
|
|
650
|
+
if (index > 0) parts.push(sql.raw(` ${constraint.boolean} `));
|
|
651
|
+
parts.push(this.buildJoinConstraint(target, constraint));
|
|
652
|
+
});
|
|
653
|
+
return sql`${sql.join(parts, sql``)}`;
|
|
654
|
+
}
|
|
655
|
+
buildJoinConstraint(target, constraint) {
|
|
656
|
+
if (constraint.type === "column") return sql`${sql.ref(constraint.first)} ${sql.raw(constraint.operator)} ${sql.ref(constraint.second)}`;
|
|
657
|
+
if (constraint.type === "null") return constraint.not ? sql`${sql.ref(constraint.column)} is not null` : sql`${sql.ref(constraint.column)} is null`;
|
|
658
|
+
if (constraint.type === "raw") return this.buildRawWhereCondition({
|
|
659
|
+
type: "raw",
|
|
660
|
+
sql: constraint.sql,
|
|
661
|
+
bindings: constraint.bindings
|
|
662
|
+
});
|
|
663
|
+
if (constraint.type === "nested") return sql`(${this.buildJoinConstraints(target, constraint.constraints)})`;
|
|
664
|
+
const column = sql.ref(constraint.column);
|
|
665
|
+
const operator = constraint.operator;
|
|
666
|
+
if (operator === "is-null") return sql`${column} is null`;
|
|
667
|
+
if (operator === "is-not-null") return sql`${column} is not null`;
|
|
668
|
+
if (operator === "in") {
|
|
669
|
+
const values = this.buildConditionValueList(constraint.value);
|
|
670
|
+
return values.length === 0 ? sql`1 = 0` : sql`${column} in (${sql.join(values)})`;
|
|
671
|
+
}
|
|
672
|
+
if (operator === "not-in") {
|
|
673
|
+
const values = this.buildConditionValueList(constraint.value);
|
|
674
|
+
return values.length === 0 ? sql`1 = 1` : sql`${column} not in (${sql.join(values)})`;
|
|
675
|
+
}
|
|
676
|
+
if (operator === "contains") return sql`${column} like ${`%${String(constraint.value ?? "")}%`}`;
|
|
677
|
+
if (operator === "starts-with") return sql`${column} like ${`${String(constraint.value ?? "")}%`}`;
|
|
678
|
+
if (operator === "ends-with") return sql`${column} like ${`%${String(constraint.value ?? "")}`}`;
|
|
679
|
+
return sql`${column} ${sql.raw(operator)} ${constraint.value}`;
|
|
680
|
+
}
|
|
406
681
|
buildConditionValueList(value) {
|
|
407
682
|
if (Array.isArray(value)) return value;
|
|
408
683
|
return typeof value === "undefined" ? [] : [value];
|
|
@@ -432,7 +707,7 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
|
|
|
432
707
|
if (segments.length !== bindings.length + 1) throw new ArkormException("Raw where bindings do not match the number of placeholders.");
|
|
433
708
|
const parts = [];
|
|
434
709
|
segments.forEach((segment, index) => {
|
|
435
|
-
if (segment.length > 0) parts.push(sql.raw(segment));
|
|
710
|
+
if (segment.length > 0) parts.push(sql.raw(this.quoteCamelCaseIdentifiers(segment)));
|
|
436
711
|
if (index < bindings.length) parts.push(sql`${bindings[index]}`);
|
|
437
712
|
});
|
|
438
713
|
if (parts.length === 0) return sql`1 = 1`;
|
|
@@ -696,6 +971,7 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
|
|
|
696
971
|
select ${spec.distinct ? sql`distinct ` : sql``}${this.buildSelectList(spec.target, spec.columns)}
|
|
697
972
|
${this.buildRelationAggregateSelectList(spec.target, spec.relationAggregates)}
|
|
698
973
|
from ${sql.table(this.resolveTable(spec.target))}
|
|
974
|
+
${this.buildJoinClause(spec.target, spec.joins)}
|
|
699
975
|
${this.buildCombinedWhereClause(spec.target, spec.where, spec.relationFilters)}
|
|
700
976
|
${this.buildGroupBy(spec.target, spec.groupBy)}
|
|
701
977
|
${this.buildOrderBy(spec.target, spec.orderBy)}
|
|
@@ -706,6 +982,7 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
|
|
|
706
982
|
return sql`
|
|
707
983
|
select count(*)::int as count
|
|
708
984
|
from ${sql.table(this.resolveTable(spec.target))}
|
|
985
|
+
${this.buildJoinClause(spec.target, spec.joins)}
|
|
709
986
|
${this.buildCombinedWhereClause(spec.target, spec.where, spec.relationFilters)}
|
|
710
987
|
`;
|
|
711
988
|
}
|
|
@@ -714,6 +991,7 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
|
|
|
714
991
|
select exists(
|
|
715
992
|
select 1
|
|
716
993
|
from ${sql.table(this.resolveTable(spec.target))}
|
|
994
|
+
${this.buildJoinClause(spec.target, spec.joins)}
|
|
717
995
|
${this.buildCombinedWhereClause(spec.target, spec.where, spec.relationFilters)}
|
|
718
996
|
${this.buildGroupBy(spec.target, spec.groupBy)}
|
|
719
997
|
limit 1
|
|
@@ -1445,6 +1723,10 @@ var PrismaDatabaseAdapter = class PrismaDatabaseAdapter {
|
|
|
1445
1723
|
operation: "adapter.select",
|
|
1446
1724
|
meta: { feature: "groupBy" }
|
|
1447
1725
|
});
|
|
1726
|
+
if (spec.joins?.length) throw new UnsupportedAdapterFeatureException("Join clauses are not supported by the Prisma compatibility adapter; use a SQL-backed adapter or DB.raw().", {
|
|
1727
|
+
operation: "adapter.select",
|
|
1728
|
+
meta: { feature: "joins" }
|
|
1729
|
+
});
|
|
1448
1730
|
return {
|
|
1449
1731
|
include: this.toQueryInclude(spec.relationLoads),
|
|
1450
1732
|
where: this.toQueryWhere(spec.where),
|
|
@@ -3799,6 +4081,204 @@ const resolveRuntimeCompatibilityQuerySchemaOrThrow = (key, candidates, modelNam
|
|
|
3799
4081
|
return resolved;
|
|
3800
4082
|
};
|
|
3801
4083
|
|
|
4084
|
+
//#endregion
|
|
4085
|
+
//#region src/JoinClause.ts
|
|
4086
|
+
/**
|
|
4087
|
+
* A fluent builder for the `on`/`where` constraints of a join clause.
|
|
4088
|
+
*
|
|
4089
|
+
* Instances are handed to the closure form of the query builder join helpers
|
|
4090
|
+
* (for example `query.join('posts', join => join.on(...).where(...))`) and
|
|
4091
|
+
* mirror Laravel's `JoinClause` surface. Column identifiers are treated as raw
|
|
4092
|
+
* database identifiers (qualify them as `table.column` when needed).
|
|
4093
|
+
*
|
|
4094
|
+
* @author Legacy (3m1n3nc3)
|
|
4095
|
+
*/
|
|
4096
|
+
var JoinClause = class JoinClause {
|
|
4097
|
+
constructor() {
|
|
4098
|
+
this.constraints = [];
|
|
4099
|
+
}
|
|
4100
|
+
/**
|
|
4101
|
+
* Adds a column-to-column `on` constraint, joined with `and`.
|
|
4102
|
+
*
|
|
4103
|
+
* Accepts either a closure (for a nested group) or a column comparison in
|
|
4104
|
+
* the `(first, second)` or `(first, operator, second)` form.
|
|
4105
|
+
*
|
|
4106
|
+
* @param first The left-hand column or a nested closure.
|
|
4107
|
+
* @param operator The comparison operator (defaults to `=`).
|
|
4108
|
+
* @param second The right-hand column.
|
|
4109
|
+
* @returns
|
|
4110
|
+
*/
|
|
4111
|
+
on(first, operator, second) {
|
|
4112
|
+
return this.addOn("and", first, operator, second);
|
|
4113
|
+
}
|
|
4114
|
+
/**
|
|
4115
|
+
* Adds a column-to-column `on` constraint, joined with `or`.
|
|
4116
|
+
*
|
|
4117
|
+
* @param first The left-hand column or a nested closure.
|
|
4118
|
+
* @param operator The comparison operator (defaults to `=`).
|
|
4119
|
+
* @param second The right-hand column.
|
|
4120
|
+
* @returns
|
|
4121
|
+
*/
|
|
4122
|
+
orOn(first, operator, second) {
|
|
4123
|
+
return this.addOn("or", first, operator, second);
|
|
4124
|
+
}
|
|
4125
|
+
/**
|
|
4126
|
+
* Adds a column-to-value constraint, joined with `and`.
|
|
4127
|
+
*
|
|
4128
|
+
* @param column The column being compared.
|
|
4129
|
+
* @param operator The comparison operator or the value when omitted.
|
|
4130
|
+
* @param value The value to compare against.
|
|
4131
|
+
* @returns
|
|
4132
|
+
*/
|
|
4133
|
+
where(column, operator, value) {
|
|
4134
|
+
return this.addWhere("and", column, operator, value);
|
|
4135
|
+
}
|
|
4136
|
+
/**
|
|
4137
|
+
* Adds a column-to-value constraint, joined with `or`.
|
|
4138
|
+
*
|
|
4139
|
+
* @param column The column being compared.
|
|
4140
|
+
* @param operator The comparison operator or the value when omitted.
|
|
4141
|
+
* @param value The value to compare against.
|
|
4142
|
+
* @returns
|
|
4143
|
+
*/
|
|
4144
|
+
orWhere(column, operator, value) {
|
|
4145
|
+
return this.addWhere("or", column, operator, value);
|
|
4146
|
+
}
|
|
4147
|
+
/**
|
|
4148
|
+
* Adds an `is null` constraint joined with `and`.
|
|
4149
|
+
*
|
|
4150
|
+
* @param column The column to test for null.
|
|
4151
|
+
* @returns
|
|
4152
|
+
*/
|
|
4153
|
+
whereNull(column) {
|
|
4154
|
+
this.constraints.push({
|
|
4155
|
+
type: "null",
|
|
4156
|
+
boolean: "and",
|
|
4157
|
+
column,
|
|
4158
|
+
not: false
|
|
4159
|
+
});
|
|
4160
|
+
return this;
|
|
4161
|
+
}
|
|
4162
|
+
/**
|
|
4163
|
+
* Adds an `is null` constraint joined with `or`.
|
|
4164
|
+
*
|
|
4165
|
+
* @param column The column to test for null.
|
|
4166
|
+
* @returns
|
|
4167
|
+
*/
|
|
4168
|
+
orWhereNull(column) {
|
|
4169
|
+
this.constraints.push({
|
|
4170
|
+
type: "null",
|
|
4171
|
+
boolean: "or",
|
|
4172
|
+
column,
|
|
4173
|
+
not: false
|
|
4174
|
+
});
|
|
4175
|
+
return this;
|
|
4176
|
+
}
|
|
4177
|
+
/**
|
|
4178
|
+
* Adds an `is not null` constraint joined with `and`.
|
|
4179
|
+
*
|
|
4180
|
+
* @param column The column to test for non-null.
|
|
4181
|
+
* @returns
|
|
4182
|
+
*/
|
|
4183
|
+
whereNotNull(column) {
|
|
4184
|
+
this.constraints.push({
|
|
4185
|
+
type: "null",
|
|
4186
|
+
boolean: "and",
|
|
4187
|
+
column,
|
|
4188
|
+
not: true
|
|
4189
|
+
});
|
|
4190
|
+
return this;
|
|
4191
|
+
}
|
|
4192
|
+
/**
|
|
4193
|
+
* Adds an `is not null` constraint joined with `or`.
|
|
4194
|
+
*
|
|
4195
|
+
* @param column The column to test for non-null.
|
|
4196
|
+
* @returns
|
|
4197
|
+
*/
|
|
4198
|
+
orWhereNotNull(column) {
|
|
4199
|
+
this.constraints.push({
|
|
4200
|
+
type: "null",
|
|
4201
|
+
boolean: "or",
|
|
4202
|
+
column,
|
|
4203
|
+
not: true
|
|
4204
|
+
});
|
|
4205
|
+
return this;
|
|
4206
|
+
}
|
|
4207
|
+
/**
|
|
4208
|
+
* Adds a raw constraint joined with `and`.
|
|
4209
|
+
*
|
|
4210
|
+
* @param sql The raw SQL fragment (with `?` placeholders for bindings).
|
|
4211
|
+
* @param bindings The values bound to the placeholders.
|
|
4212
|
+
* @returns
|
|
4213
|
+
*/
|
|
4214
|
+
onRaw(sql, bindings = []) {
|
|
4215
|
+
this.constraints.push({
|
|
4216
|
+
type: "raw",
|
|
4217
|
+
boolean: "and",
|
|
4218
|
+
sql,
|
|
4219
|
+
bindings
|
|
4220
|
+
});
|
|
4221
|
+
return this;
|
|
4222
|
+
}
|
|
4223
|
+
/**
|
|
4224
|
+
* Adds a raw constraint joined with `or`.
|
|
4225
|
+
*
|
|
4226
|
+
* @param sql The raw SQL fragment (with `?` placeholders for bindings).
|
|
4227
|
+
* @param bindings The values bound to the placeholders.
|
|
4228
|
+
* @returns
|
|
4229
|
+
*/
|
|
4230
|
+
orOnRaw(sql, bindings = []) {
|
|
4231
|
+
this.constraints.push({
|
|
4232
|
+
type: "raw",
|
|
4233
|
+
boolean: "or",
|
|
4234
|
+
sql,
|
|
4235
|
+
bindings
|
|
4236
|
+
});
|
|
4237
|
+
return this;
|
|
4238
|
+
}
|
|
4239
|
+
/**
|
|
4240
|
+
* Returns the accumulated constraints for this join clause.
|
|
4241
|
+
*
|
|
4242
|
+
* @returns
|
|
4243
|
+
*/
|
|
4244
|
+
getConstraints() {
|
|
4245
|
+
return this.constraints;
|
|
4246
|
+
}
|
|
4247
|
+
addOn(boolean, first, operator, second) {
|
|
4248
|
+
if (typeof first === "function") {
|
|
4249
|
+
const nested = new JoinClause();
|
|
4250
|
+
first(nested);
|
|
4251
|
+
this.constraints.push({
|
|
4252
|
+
type: "nested",
|
|
4253
|
+
boolean,
|
|
4254
|
+
constraints: nested.getConstraints()
|
|
4255
|
+
});
|
|
4256
|
+
return this;
|
|
4257
|
+
}
|
|
4258
|
+
const [resolvedOperator, resolvedSecond] = second === void 0 ? ["=", operator] : [operator, second];
|
|
4259
|
+
if (typeof resolvedSecond !== "string") throw new Error("A join \"on\" constraint requires a second column.");
|
|
4260
|
+
this.constraints.push({
|
|
4261
|
+
type: "column",
|
|
4262
|
+
boolean,
|
|
4263
|
+
first,
|
|
4264
|
+
operator: resolvedOperator ?? "=",
|
|
4265
|
+
second: resolvedSecond
|
|
4266
|
+
});
|
|
4267
|
+
return this;
|
|
4268
|
+
}
|
|
4269
|
+
addWhere(boolean, column, operator, value) {
|
|
4270
|
+
const [resolvedOperator, resolvedValue] = value === void 0 ? ["=", operator] : [operator, value];
|
|
4271
|
+
this.constraints.push({
|
|
4272
|
+
type: "value",
|
|
4273
|
+
boolean,
|
|
4274
|
+
column,
|
|
4275
|
+
operator: resolvedOperator ?? "=",
|
|
4276
|
+
value: resolvedValue
|
|
4277
|
+
});
|
|
4278
|
+
return this;
|
|
4279
|
+
}
|
|
4280
|
+
};
|
|
4281
|
+
|
|
3802
4282
|
//#endregion
|
|
3803
4283
|
//#region src/Exceptions/ModelNotFoundException.ts
|
|
3804
4284
|
/**
|
|
@@ -4770,7 +5250,248 @@ var QueryBuilder = class QueryBuilder {
|
|
|
4770
5250
|
return this;
|
|
4771
5251
|
}
|
|
4772
5252
|
/**
|
|
4773
|
-
* Adds a
|
|
5253
|
+
* Adds a join clause to the query.
|
|
5254
|
+
*
|
|
5255
|
+
* The `first`/`second` arguments are treated as raw database identifiers, so
|
|
5256
|
+
* qualify them as `table.column` when needed. Pass a closure as `first` to
|
|
5257
|
+
* build a compound `on` condition through a {@link JoinClause}.
|
|
5258
|
+
*
|
|
5259
|
+
* @param table The table (or aliased table) to join.
|
|
5260
|
+
* @param first The left-hand column or a closure receiving a JoinClause.
|
|
5261
|
+
* @param operator The comparison operator (defaults to `=`).
|
|
5262
|
+
* @param second The right-hand column.
|
|
5263
|
+
* @param type The join type (defaults to `inner`).
|
|
5264
|
+
* @returns
|
|
5265
|
+
*/
|
|
5266
|
+
join(table, first, operator, second, type = "inner") {
|
|
5267
|
+
return this.addJoin(type, table, first, operator, second);
|
|
5268
|
+
}
|
|
5269
|
+
/**
|
|
5270
|
+
* Adds an inner join clause to the query.
|
|
5271
|
+
*
|
|
5272
|
+
* @param table The table (or aliased table) to join.
|
|
5273
|
+
* @param first The left-hand column or a closure receiving a JoinClause.
|
|
5274
|
+
* @param operator The comparison operator (defaults to `=`).
|
|
5275
|
+
* @param second The right-hand column.
|
|
5276
|
+
* @returns
|
|
5277
|
+
*/
|
|
5278
|
+
innerJoin(table, first, operator, second) {
|
|
5279
|
+
return this.addJoin("inner", table, first, operator, second);
|
|
5280
|
+
}
|
|
5281
|
+
/**
|
|
5282
|
+
* Adds a left join clause to the query.
|
|
5283
|
+
*
|
|
5284
|
+
* @param table The table (or aliased table) to join.
|
|
5285
|
+
* @param first The left-hand column or a closure receiving a JoinClause.
|
|
5286
|
+
* @param operator The comparison operator (defaults to `=`).
|
|
5287
|
+
* @param second The right-hand column.
|
|
5288
|
+
* @returns
|
|
5289
|
+
*/
|
|
5290
|
+
leftJoin(table, first, operator, second) {
|
|
5291
|
+
return this.addJoin("left", table, first, operator, second);
|
|
5292
|
+
}
|
|
5293
|
+
/**
|
|
5294
|
+
* Adds a right join clause to the query.
|
|
5295
|
+
*
|
|
5296
|
+
* @param table The table (or aliased table) to join.
|
|
5297
|
+
* @param first The left-hand column or a closure receiving a JoinClause.
|
|
5298
|
+
* @param operator The comparison operator (defaults to `=`).
|
|
5299
|
+
* @param second The right-hand column.
|
|
5300
|
+
* @returns
|
|
5301
|
+
*/
|
|
5302
|
+
rightJoin(table, first, operator, second) {
|
|
5303
|
+
return this.addJoin("right", table, first, operator, second);
|
|
5304
|
+
}
|
|
5305
|
+
/**
|
|
5306
|
+
* Adds a cross join clause to the query.
|
|
5307
|
+
*
|
|
5308
|
+
* When a `first` column (or closure) is supplied the cross join is promoted
|
|
5309
|
+
* to an inner join with the given constraints, mirroring Laravel's behaviour.
|
|
5310
|
+
*
|
|
5311
|
+
* @param table The table (or aliased table) to join.
|
|
5312
|
+
* @param first Optional column or closure to constrain the join.
|
|
5313
|
+
* @returns
|
|
5314
|
+
*/
|
|
5315
|
+
crossJoin(table, first) {
|
|
5316
|
+
if (first === void 0) return this.addJoin("cross", table);
|
|
5317
|
+
return this.addJoin("inner", table, first);
|
|
5318
|
+
}
|
|
5319
|
+
/**
|
|
5320
|
+
* Adds a join clause that compares a column to a value.
|
|
5321
|
+
*
|
|
5322
|
+
* @param table The table (or aliased table) to join.
|
|
5323
|
+
* @param first The column being compared.
|
|
5324
|
+
* @param operator The comparison operator.
|
|
5325
|
+
* @param value The value to compare against.
|
|
5326
|
+
* @param type The join type (defaults to `inner`).
|
|
5327
|
+
* @returns
|
|
5328
|
+
*/
|
|
5329
|
+
joinWhere(table, first, operator, value, type = "inner") {
|
|
5330
|
+
return this.addJoinWhere(type, table, first, operator, value);
|
|
5331
|
+
}
|
|
5332
|
+
/**
|
|
5333
|
+
* Adds a left join clause that compares a column to a value.
|
|
5334
|
+
*
|
|
5335
|
+
* @param table The table (or aliased table) to join.
|
|
5336
|
+
* @param first The column being compared.
|
|
5337
|
+
* @param operator The comparison operator.
|
|
5338
|
+
* @param value The value to compare against.
|
|
5339
|
+
* @returns
|
|
5340
|
+
*/
|
|
5341
|
+
leftJoinWhere(table, first, operator, value) {
|
|
5342
|
+
return this.addJoinWhere("left", table, first, operator, value);
|
|
5343
|
+
}
|
|
5344
|
+
/**
|
|
5345
|
+
* Adds a right join clause that compares a column to a value.
|
|
5346
|
+
*
|
|
5347
|
+
* @param table The table (or aliased table) to join.
|
|
5348
|
+
* @param first The column being compared.
|
|
5349
|
+
* @param operator The comparison operator.
|
|
5350
|
+
* @param value The value to compare against.
|
|
5351
|
+
* @returns
|
|
5352
|
+
*/
|
|
5353
|
+
rightJoinWhere(table, first, operator, value) {
|
|
5354
|
+
return this.addJoinWhere("right", table, first, operator, value);
|
|
5355
|
+
}
|
|
5356
|
+
/**
|
|
5357
|
+
* Adds a subquery join clause to the query.
|
|
5358
|
+
*
|
|
5359
|
+
* @param query The subquery (a QueryBuilder instance or raw SQL string).
|
|
5360
|
+
* @param alias The alias assigned to the subquery.
|
|
5361
|
+
* @param first The left-hand column or a closure receiving a JoinClause.
|
|
5362
|
+
* @param operator The comparison operator (defaults to `=`).
|
|
5363
|
+
* @param second The right-hand column.
|
|
5364
|
+
* @param type The join type (defaults to `inner`).
|
|
5365
|
+
* @returns
|
|
5366
|
+
*/
|
|
5367
|
+
joinSub(query, alias, first, operator, second, type = "inner") {
|
|
5368
|
+
return this.addJoinSub(type, query, alias, first, operator, second);
|
|
5369
|
+
}
|
|
5370
|
+
/**
|
|
5371
|
+
* Adds a subquery left join clause to the query.
|
|
5372
|
+
*
|
|
5373
|
+
* @param query The subquery (a QueryBuilder instance or raw SQL string).
|
|
5374
|
+
* @param alias The alias assigned to the subquery.
|
|
5375
|
+
* @param first The left-hand column or a closure receiving a JoinClause.
|
|
5376
|
+
* @param operator The comparison operator (defaults to `=`).
|
|
5377
|
+
* @param second The right-hand column.
|
|
5378
|
+
* @returns
|
|
5379
|
+
*/
|
|
5380
|
+
leftJoinSub(query, alias, first, operator, second) {
|
|
5381
|
+
return this.addJoinSub("left", query, alias, first, operator, second);
|
|
5382
|
+
}
|
|
5383
|
+
/**
|
|
5384
|
+
* Adds a subquery right join clause to the query.
|
|
5385
|
+
*
|
|
5386
|
+
* @param query The subquery (a QueryBuilder instance or raw SQL string).
|
|
5387
|
+
* @param alias The alias assigned to the subquery.
|
|
5388
|
+
* @param first The left-hand column or a closure receiving a JoinClause.
|
|
5389
|
+
* @param operator The comparison operator (defaults to `=`).
|
|
5390
|
+
* @param second The right-hand column.
|
|
5391
|
+
* @returns
|
|
5392
|
+
*/
|
|
5393
|
+
rightJoinSub(query, alias, first, operator, second) {
|
|
5394
|
+
return this.addJoinSub("right", query, alias, first, operator, second);
|
|
5395
|
+
}
|
|
5396
|
+
/**
|
|
5397
|
+
* Adds a cross subquery join clause to the query.
|
|
5398
|
+
*
|
|
5399
|
+
* @param query The subquery (a QueryBuilder instance or raw SQL string).
|
|
5400
|
+
* @param alias The alias assigned to the subquery.
|
|
5401
|
+
* @returns
|
|
5402
|
+
*/
|
|
5403
|
+
crossJoinSub(query, alias) {
|
|
5404
|
+
return this.addJoinSub("cross", query, alias);
|
|
5405
|
+
}
|
|
5406
|
+
/**
|
|
5407
|
+
* Adds a lateral join clause to the query.
|
|
5408
|
+
*
|
|
5409
|
+
* @param query The subquery (a QueryBuilder instance or raw SQL string).
|
|
5410
|
+
* @param alias The alias assigned to the subquery.
|
|
5411
|
+
* @param type The join type (defaults to `inner`).
|
|
5412
|
+
* @returns
|
|
5413
|
+
*/
|
|
5414
|
+
joinLateral(query, alias, type = "inner") {
|
|
5415
|
+
return this.addJoinSub(type, query, alias, void 0, void 0, void 0, true);
|
|
5416
|
+
}
|
|
5417
|
+
/**
|
|
5418
|
+
* Adds a lateral left join clause to the query.
|
|
5419
|
+
*
|
|
5420
|
+
* @param query The subquery (a QueryBuilder instance or raw SQL string).
|
|
5421
|
+
* @param alias The alias assigned to the subquery.
|
|
5422
|
+
* @returns
|
|
5423
|
+
*/
|
|
5424
|
+
leftJoinLateral(query, alias) {
|
|
5425
|
+
return this.addJoinSub("left", query, alias, void 0, void 0, void 0, true);
|
|
5426
|
+
}
|
|
5427
|
+
/**
|
|
5428
|
+
* Builds a self-contained select specification used when this query is joined
|
|
5429
|
+
* as a subquery by another query builder.
|
|
5430
|
+
*
|
|
5431
|
+
* @returns
|
|
5432
|
+
*/
|
|
5433
|
+
buildJoinSubquerySpec() {
|
|
5434
|
+
const spec = this.tryBuildSelectSpec(this.buildWhere());
|
|
5435
|
+
if (!spec) throw new UnsupportedAdapterFeatureException("Subquery join could not be compiled into an Arkorm select specification.", {
|
|
5436
|
+
operation: "query.joinSub",
|
|
5437
|
+
model: this.model.name
|
|
5438
|
+
});
|
|
5439
|
+
return spec;
|
|
5440
|
+
}
|
|
5441
|
+
guardJoinSupport() {
|
|
5442
|
+
if (!this.adapter?.capabilities?.joins) throw new UnsupportedAdapterFeatureException("Join clauses are not supported by the current adapter.", {
|
|
5443
|
+
operation: "join",
|
|
5444
|
+
model: this.model.name,
|
|
5445
|
+
meta: { feature: "joins" }
|
|
5446
|
+
});
|
|
5447
|
+
}
|
|
5448
|
+
pushJoin(join) {
|
|
5449
|
+
(this.queryJoins ??= []).push(join);
|
|
5450
|
+
}
|
|
5451
|
+
resolveJoinConstraints(first, operator, second) {
|
|
5452
|
+
if (first === void 0) return [];
|
|
5453
|
+
const clause = new JoinClause();
|
|
5454
|
+
if (typeof first === "function") first(clause);
|
|
5455
|
+
else clause.on(first, operator, second);
|
|
5456
|
+
return clause.getConstraints();
|
|
5457
|
+
}
|
|
5458
|
+
resolveJoinSource(query) {
|
|
5459
|
+
if (typeof query === "string") return { subquerySql: query };
|
|
5460
|
+
return { subquery: query.buildJoinSubquerySpec() };
|
|
5461
|
+
}
|
|
5462
|
+
addJoin(type, table, first, operator, second) {
|
|
5463
|
+
this.guardJoinSupport();
|
|
5464
|
+
this.pushJoin({
|
|
5465
|
+
type,
|
|
5466
|
+
table,
|
|
5467
|
+
constraints: this.resolveJoinConstraints(first, operator, second)
|
|
5468
|
+
});
|
|
5469
|
+
return this;
|
|
5470
|
+
}
|
|
5471
|
+
addJoinWhere(type, table, column, operator, value) {
|
|
5472
|
+
this.guardJoinSupport();
|
|
5473
|
+
const clause = new JoinClause();
|
|
5474
|
+
clause.where(column, operator, value);
|
|
5475
|
+
this.pushJoin({
|
|
5476
|
+
type,
|
|
5477
|
+
table,
|
|
5478
|
+
constraints: clause.getConstraints()
|
|
5479
|
+
});
|
|
5480
|
+
return this;
|
|
5481
|
+
}
|
|
5482
|
+
addJoinSub(type, query, alias, first, operator, second, lateral = false) {
|
|
5483
|
+
this.guardJoinSupport();
|
|
5484
|
+
this.pushJoin({
|
|
5485
|
+
type,
|
|
5486
|
+
alias,
|
|
5487
|
+
...this.resolveJoinSource(query),
|
|
5488
|
+
...lateral ? { lateral: true } : {},
|
|
5489
|
+
constraints: this.resolveJoinConstraints(first, operator, second)
|
|
5490
|
+
});
|
|
5491
|
+
return this;
|
|
5492
|
+
}
|
|
5493
|
+
/**
|
|
5494
|
+
* Adds a skip clause to the query for pagination.
|
|
4774
5495
|
* This will overwrite any existing skip clause.
|
|
4775
5496
|
*
|
|
4776
5497
|
* @param skip
|
|
@@ -4913,6 +5634,56 @@ var QueryBuilder = class QueryBuilder {
|
|
|
4913
5634
|
if (!model) throw new ModelNotFoundException(this.model.name, "Record not found.");
|
|
4914
5635
|
return model;
|
|
4915
5636
|
}
|
|
5637
|
+
/**
|
|
5638
|
+
* Returns the first record matching the given attributes or instantiates a
|
|
5639
|
+
* new, unpersisted model populated with the merged attributes and values.
|
|
5640
|
+
*
|
|
5641
|
+
* @param attributes
|
|
5642
|
+
* @param values
|
|
5643
|
+
* @returns
|
|
5644
|
+
*/
|
|
5645
|
+
async firstOrNew(attributes, values = {}) {
|
|
5646
|
+
const existing = await this.clone().where(attributes).first();
|
|
5647
|
+
if (existing) return existing;
|
|
5648
|
+
const ModelConstructor = this.model;
|
|
5649
|
+
return new ModelConstructor({
|
|
5650
|
+
...attributes,
|
|
5651
|
+
...values
|
|
5652
|
+
});
|
|
5653
|
+
}
|
|
5654
|
+
/**
|
|
5655
|
+
* Returns the first record matching the given attributes or creates and
|
|
5656
|
+
* persists a new record populated with the merged attributes and values.
|
|
5657
|
+
*
|
|
5658
|
+
* @param attributes
|
|
5659
|
+
* @param values
|
|
5660
|
+
* @returns
|
|
5661
|
+
*/
|
|
5662
|
+
async firstOrCreate(attributes, values = {}) {
|
|
5663
|
+
const existing = await this.clone().where(attributes).first();
|
|
5664
|
+
if (existing) return existing;
|
|
5665
|
+
return await this.create({
|
|
5666
|
+
...attributes,
|
|
5667
|
+
...values
|
|
5668
|
+
});
|
|
5669
|
+
}
|
|
5670
|
+
async firstOr(columnsOrCallback, maybeCallback) {
|
|
5671
|
+
const callback = typeof columnsOrCallback === "function" ? columnsOrCallback : maybeCallback;
|
|
5672
|
+
if (!callback) throw new QueryConstraintException("firstOr requires a fallback callback.", {
|
|
5673
|
+
operation: "firstOr",
|
|
5674
|
+
model: this.model.name
|
|
5675
|
+
});
|
|
5676
|
+
if (Array.isArray(columnsOrCallback) && columnsOrCallback.length > 0) {
|
|
5677
|
+
const select = columnsOrCallback.reduce((all, column) => {
|
|
5678
|
+
all[column] = true;
|
|
5679
|
+
return all;
|
|
5680
|
+
}, {});
|
|
5681
|
+
this.select(select);
|
|
5682
|
+
}
|
|
5683
|
+
const found = await this.first();
|
|
5684
|
+
if (found) return found;
|
|
5685
|
+
return callback();
|
|
5686
|
+
}
|
|
4916
5687
|
async find(value, key) {
|
|
4917
5688
|
const resolvedKey = key ?? this.model.getPrimaryKey();
|
|
4918
5689
|
return this.where({ [resolvedKey]: value }).first();
|
|
@@ -5122,6 +5893,23 @@ var QueryBuilder = class QueryBuilder {
|
|
|
5122
5893
|
}
|
|
5123
5894
|
return await this.clone().where(attributes).update(resolvedValues) != null;
|
|
5124
5895
|
}
|
|
5896
|
+
/**
|
|
5897
|
+
* Update the first record matching the given attributes, or create a new
|
|
5898
|
+
* record populated with the merged attributes and values when none exists.
|
|
5899
|
+
*
|
|
5900
|
+
* @param attributes
|
|
5901
|
+
* @param values
|
|
5902
|
+
* @returns
|
|
5903
|
+
*/
|
|
5904
|
+
async updateOrCreate(attributes, values = {}) {
|
|
5905
|
+
const existing = await this.clone().where(attributes).first();
|
|
5906
|
+
if (!existing) return await this.create({
|
|
5907
|
+
...attributes,
|
|
5908
|
+
...values
|
|
5909
|
+
});
|
|
5910
|
+
if (Object.keys(values).length === 0) return existing;
|
|
5911
|
+
return await this.clone().where(attributes).update(values);
|
|
5912
|
+
}
|
|
5125
5913
|
shouldFallbackUpdateOrInsertUpsert(error) {
|
|
5126
5914
|
if (!(error instanceof QueryExecutionException)) return false;
|
|
5127
5915
|
const cause = error.cause;
|
|
@@ -5173,13 +5961,25 @@ var QueryBuilder = class QueryBuilder {
|
|
|
5173
5961
|
if (!this.isUniqueWhere(where) && directSpec && typeof adapter.deleteFirst === "function") {
|
|
5174
5962
|
const deleted = await adapter.deleteFirst(directSpec);
|
|
5175
5963
|
if (!deleted) return null;
|
|
5176
|
-
return this.
|
|
5964
|
+
return this.hydrateDeleted(deleted);
|
|
5177
5965
|
}
|
|
5178
5966
|
const uniqueWhere = await this.resolveUniqueWhere(where, false);
|
|
5179
5967
|
if (!uniqueWhere) return null;
|
|
5180
5968
|
const deleted = await this.executeDeleteRow(uniqueWhere, false);
|
|
5181
5969
|
if (!deleted) return null;
|
|
5182
|
-
return this.
|
|
5970
|
+
return this.hydrateDeleted(deleted);
|
|
5971
|
+
}
|
|
5972
|
+
/**
|
|
5973
|
+
* Hydrate a row that was just deleted, marking the resulting model as no
|
|
5974
|
+
* longer existing in the database.
|
|
5975
|
+
*
|
|
5976
|
+
* @param attributes
|
|
5977
|
+
* @returns
|
|
5978
|
+
*/
|
|
5979
|
+
hydrateDeleted(attributes) {
|
|
5980
|
+
const model = this.model.hydrate(attributes);
|
|
5981
|
+
model.exists = false;
|
|
5982
|
+
return model;
|
|
5183
5983
|
}
|
|
5184
5984
|
/**
|
|
5185
5985
|
* Deletes the first record matching the current query constraints and throws
|
|
@@ -6025,6 +6825,7 @@ var QueryBuilder = class QueryBuilder {
|
|
|
6025
6825
|
columns,
|
|
6026
6826
|
distinct: this.queryDistinct || void 0,
|
|
6027
6827
|
groupBy: this.queryGroupBy ? [...this.queryGroupBy] : void 0,
|
|
6828
|
+
joins: this.queryJoins ? [...this.queryJoins] : void 0,
|
|
6028
6829
|
where: condition,
|
|
6029
6830
|
orderBy,
|
|
6030
6831
|
limit: this.limitValue,
|
|
@@ -6041,6 +6842,7 @@ var QueryBuilder = class QueryBuilder {
|
|
|
6041
6842
|
if (this.hasRelationFilters() && this.canExecuteRelationFiltersInAdapter() && relationFilters === null) return null;
|
|
6042
6843
|
return {
|
|
6043
6844
|
target: this.buildQueryTarget(),
|
|
6845
|
+
joins: this.queryJoins ? [...this.queryJoins] : void 0,
|
|
6044
6846
|
where: condition,
|
|
6045
6847
|
relationFilters: this.canExecuteRelationFiltersInAdapter() ? relationFilters ?? void 0 : void 0,
|
|
6046
6848
|
aggregate: { type: "count" }
|
|
@@ -6546,9 +7348,12 @@ var Model = class Model {
|
|
|
6546
7348
|
this.hidden = [];
|
|
6547
7349
|
this.visible = [];
|
|
6548
7350
|
this.appends = [];
|
|
7351
|
+
this.exists = false;
|
|
7352
|
+
this.wasRecentlyCreated = false;
|
|
6549
7353
|
this.attributes = {};
|
|
6550
7354
|
this.original = {};
|
|
6551
7355
|
this.changes = {};
|
|
7356
|
+
this.previous = {};
|
|
6552
7357
|
this.touchedAttributes = /* @__PURE__ */ new Set();
|
|
6553
7358
|
this.fill(attributes);
|
|
6554
7359
|
return new Proxy(this, {
|
|
@@ -6908,6 +7713,68 @@ var Model = class Model {
|
|
|
6908
7713
|
return this.query().scope(name, ...args);
|
|
6909
7714
|
}
|
|
6910
7715
|
/**
|
|
7716
|
+
* Start a query constrained by the given where clause.
|
|
7717
|
+
*
|
|
7718
|
+
* @param this
|
|
7719
|
+
* @param where
|
|
7720
|
+
* @returns
|
|
7721
|
+
*/
|
|
7722
|
+
static where(where) {
|
|
7723
|
+
return this.query().where(where);
|
|
7724
|
+
}
|
|
7725
|
+
/**
|
|
7726
|
+
* Retrieve all records for the model.
|
|
7727
|
+
*
|
|
7728
|
+
* @param this
|
|
7729
|
+
* @returns
|
|
7730
|
+
*/
|
|
7731
|
+
static async all() {
|
|
7732
|
+
return await this.query().get();
|
|
7733
|
+
}
|
|
7734
|
+
/**
|
|
7735
|
+
* Create and persist a new record, returning the hydrated model instance.
|
|
7736
|
+
*
|
|
7737
|
+
* @param this
|
|
7738
|
+
* @param data
|
|
7739
|
+
* @returns
|
|
7740
|
+
*/
|
|
7741
|
+
static async create(data) {
|
|
7742
|
+
return await this.query().create(data);
|
|
7743
|
+
}
|
|
7744
|
+
/**
|
|
7745
|
+
* Insert new records or update existing records by one or more unique keys.
|
|
7746
|
+
*
|
|
7747
|
+
* @param this
|
|
7748
|
+
* @param values
|
|
7749
|
+
* @param uniqueBy
|
|
7750
|
+
* @param update
|
|
7751
|
+
* @returns
|
|
7752
|
+
*/
|
|
7753
|
+
static async upsert(values, uniqueBy, update = null) {
|
|
7754
|
+
return await this.query().upsert(values, uniqueBy, update);
|
|
7755
|
+
}
|
|
7756
|
+
/**
|
|
7757
|
+
* Delete records by their primary key(s), dispatching model events for each
|
|
7758
|
+
* matched record. Returns the number of records deleted.
|
|
7759
|
+
*
|
|
7760
|
+
* @param this
|
|
7761
|
+
* @param ids
|
|
7762
|
+
* @returns
|
|
7763
|
+
*/
|
|
7764
|
+
static async destroy(ids) {
|
|
7765
|
+
const constructor = this;
|
|
7766
|
+
const identifiers = (Array.isArray(ids) ? ids : [ids]).filter((identifier, index, all) => all.indexOf(identifier) === index);
|
|
7767
|
+
const primaryKey = constructor.getPrimaryKey();
|
|
7768
|
+
let deleted = 0;
|
|
7769
|
+
for (const identifier of identifiers) {
|
|
7770
|
+
const model = await constructor.query().where({ [primaryKey]: identifier }).first();
|
|
7771
|
+
if (!model) continue;
|
|
7772
|
+
await model.delete();
|
|
7773
|
+
deleted += 1;
|
|
7774
|
+
}
|
|
7775
|
+
return deleted;
|
|
7776
|
+
}
|
|
7777
|
+
/**
|
|
6911
7778
|
* Get the soft delete configuration for the model, including whether
|
|
6912
7779
|
* soft deletes are enabled and the name of the deleted at column.
|
|
6913
7780
|
*
|
|
@@ -6930,6 +7797,7 @@ var Model = class Model {
|
|
|
6930
7797
|
const model = new this(attributes);
|
|
6931
7798
|
model.syncOriginal();
|
|
6932
7799
|
model.syncChanges({});
|
|
7800
|
+
model.exists = true;
|
|
6933
7801
|
return model;
|
|
6934
7802
|
}
|
|
6935
7803
|
/**
|
|
@@ -6940,7 +7808,8 @@ var Model = class Model {
|
|
|
6940
7808
|
* @returns
|
|
6941
7809
|
*/
|
|
6942
7810
|
static hydrateMany(attributes) {
|
|
6943
|
-
|
|
7811
|
+
const constructor = this;
|
|
7812
|
+
return attributes.map((attribute) => constructor.hydrate(attribute));
|
|
6944
7813
|
}
|
|
6945
7814
|
/**
|
|
6946
7815
|
* Hydrate a model instance and dispatch the retrieved lifecycle event.
|
|
@@ -6988,6 +7857,11 @@ var Model = class Model {
|
|
|
6988
7857
|
return false;
|
|
6989
7858
|
}
|
|
6990
7859
|
}
|
|
7860
|
+
async updateOrFail(attributes) {
|
|
7861
|
+
const primaryKey = this.constructor.getPrimaryKey();
|
|
7862
|
+
if (this.getAttribute(primaryKey) == null) throw new ArkormException(primaryKey === "id" ? "Cannot update a model without an id." : `Cannot update a model without a [${primaryKey}] value.`);
|
|
7863
|
+
return await this.fill(attributes).saveOrFail();
|
|
7864
|
+
}
|
|
6991
7865
|
getAttribute(key) {
|
|
6992
7866
|
const attributeMutator = this.resolveAttributeMutator(key);
|
|
6993
7867
|
const mutator = this.resolveGetMutator(key);
|
|
@@ -7011,29 +7885,35 @@ var Model = class Model {
|
|
|
7011
7885
|
return this;
|
|
7012
7886
|
}
|
|
7013
7887
|
/**
|
|
7014
|
-
* Save the model to the database.
|
|
7015
|
-
* If the model
|
|
7016
|
-
*
|
|
7017
|
-
*
|
|
7018
|
-
*
|
|
7888
|
+
* Save the model to the database.
|
|
7889
|
+
* If the model already exists in the database it performs an update;
|
|
7890
|
+
* otherwise it performs an insert. Existence is tracked through the
|
|
7891
|
+
* `exists` flag rather than the presence of a primary-key value, so a model
|
|
7892
|
+
* built with an explicit primary key still inserts on its first save.
|
|
7893
|
+
*
|
|
7894
|
+
* @returns
|
|
7019
7895
|
*/
|
|
7020
7896
|
async save() {
|
|
7021
7897
|
const constructor = this.constructor;
|
|
7022
7898
|
const primaryKey = constructor.getPrimaryKey();
|
|
7023
|
-
const identifier = this.getAttribute(primaryKey);
|
|
7024
7899
|
const previousOriginal = this.getOriginal();
|
|
7025
|
-
if (
|
|
7900
|
+
if (!this.exists) {
|
|
7026
7901
|
await Model.dispatchEvent(constructor, "saving", this);
|
|
7027
7902
|
await Model.dispatchEvent(constructor, "creating", this);
|
|
7028
7903
|
const payload = this.normalizePersistenceAttributes(this.getRawAttributes());
|
|
7029
7904
|
const model = await constructor.query().create(payload);
|
|
7030
7905
|
this.fill(model.getRawAttributes());
|
|
7031
7906
|
this.syncChanges(previousOriginal);
|
|
7907
|
+
this.syncPrevious(previousOriginal);
|
|
7032
7908
|
this.syncOriginal();
|
|
7909
|
+
this.exists = true;
|
|
7910
|
+
this.wasRecentlyCreated = true;
|
|
7033
7911
|
await Model.dispatchEvent(constructor, "created", this);
|
|
7034
7912
|
await Model.dispatchEvent(constructor, "saved", this);
|
|
7035
7913
|
return this;
|
|
7036
7914
|
}
|
|
7915
|
+
const identifier = this.getAttribute(primaryKey);
|
|
7916
|
+
if (identifier == null) throw new ArkormException(primaryKey === "id" ? "Cannot update an existing model without an id." : `Cannot update an existing model without a [${primaryKey}] value.`);
|
|
7037
7917
|
await Model.dispatchEvent(constructor, "saving", this);
|
|
7038
7918
|
await Model.dispatchEvent(constructor, "updating", this);
|
|
7039
7919
|
const payload = this.normalizePersistenceAttributes(this.getDirtyAttributes());
|
|
@@ -7041,6 +7921,7 @@ var Model = class Model {
|
|
|
7041
7921
|
const model = await constructor.query().where({ [primaryKey]: identifier }).update(payload);
|
|
7042
7922
|
this.fill(model.getRawAttributes());
|
|
7043
7923
|
this.syncChanges(previousOriginal);
|
|
7924
|
+
this.syncPrevious(previousOriginal);
|
|
7044
7925
|
this.syncOriginal();
|
|
7045
7926
|
await Model.dispatchEvent(constructor, "updated", this);
|
|
7046
7927
|
await Model.dispatchEvent(constructor, "saved", this);
|
|
@@ -7055,6 +7936,15 @@ var Model = class Model {
|
|
|
7055
7936
|
return await Model.withoutEvents(() => this.save());
|
|
7056
7937
|
}
|
|
7057
7938
|
/**
|
|
7939
|
+
* Save the model within a transaction, rolling back and rethrowing if the
|
|
7940
|
+
* operation fails. Unlike update(), this never swallows errors.
|
|
7941
|
+
*
|
|
7942
|
+
* @returns
|
|
7943
|
+
*/
|
|
7944
|
+
async saveOrFail() {
|
|
7945
|
+
return await this.constructor.transaction(async () => await this.save());
|
|
7946
|
+
}
|
|
7947
|
+
/**
|
|
7058
7948
|
* Delete the model from the database.
|
|
7059
7949
|
* If soft deletes are enabled, it will perform a soft delete by
|
|
7060
7950
|
* setting the deleted at column to the current date.
|
|
@@ -7082,6 +7972,7 @@ var Model = class Model {
|
|
|
7082
7972
|
this.fill(deleted.getRawAttributes());
|
|
7083
7973
|
this.syncChanges(previousOriginal);
|
|
7084
7974
|
this.syncOriginal();
|
|
7975
|
+
this.exists = false;
|
|
7085
7976
|
await Model.dispatchEvent(constructor, "deleted", this);
|
|
7086
7977
|
return this;
|
|
7087
7978
|
}
|
|
@@ -7094,6 +7985,15 @@ var Model = class Model {
|
|
|
7094
7985
|
return await Model.withoutEvents(() => this.delete());
|
|
7095
7986
|
}
|
|
7096
7987
|
/**
|
|
7988
|
+
* Delete the model within a transaction, rolling back and rethrowing if the
|
|
7989
|
+
* operation fails.
|
|
7990
|
+
*
|
|
7991
|
+
* @returns
|
|
7992
|
+
*/
|
|
7993
|
+
async deleteOrFail() {
|
|
7994
|
+
return await this.constructor.transaction(async () => await this.delete());
|
|
7995
|
+
}
|
|
7996
|
+
/**
|
|
7097
7997
|
* Permanently delete the model from the database, regardless of whether soft
|
|
7098
7998
|
* deletes are enabled.
|
|
7099
7999
|
*
|
|
@@ -7111,6 +8011,7 @@ var Model = class Model {
|
|
|
7111
8011
|
this.fill(deleted.getRawAttributes());
|
|
7112
8012
|
this.syncChanges(previousOriginal);
|
|
7113
8013
|
this.syncOriginal();
|
|
8014
|
+
this.exists = false;
|
|
7114
8015
|
await Model.dispatchEvent(constructor, "deleted", this);
|
|
7115
8016
|
await Model.dispatchEvent(constructor, "forceDeleted", this);
|
|
7116
8017
|
return this;
|
|
@@ -7265,6 +8166,25 @@ var Model = class Model {
|
|
|
7265
8166
|
return keyList.some((key) => Object.prototype.hasOwnProperty.call(this.changes, key));
|
|
7266
8167
|
}
|
|
7267
8168
|
/**
|
|
8169
|
+
* Get the attributes that were changed during the last successful
|
|
8170
|
+
* persistence operation.
|
|
8171
|
+
*
|
|
8172
|
+
* @returns
|
|
8173
|
+
*/
|
|
8174
|
+
getChanges() {
|
|
8175
|
+
return Object.entries(this.changes).reduce((all, [key, value]) => {
|
|
8176
|
+
all[key] = Model.cloneAttributeValue(value);
|
|
8177
|
+
return all;
|
|
8178
|
+
}, {});
|
|
8179
|
+
}
|
|
8180
|
+
getPrevious(key) {
|
|
8181
|
+
if (typeof key === "string") return Model.cloneAttributeValue(this.previous[key]);
|
|
8182
|
+
return Object.entries(this.previous).reduce((all, [previousKey, value]) => {
|
|
8183
|
+
all[previousKey] = Model.cloneAttributeValue(value);
|
|
8184
|
+
return all;
|
|
8185
|
+
}, {});
|
|
8186
|
+
}
|
|
8187
|
+
/**
|
|
7268
8188
|
* Convert the model instance to a plain object, applying visibility
|
|
7269
8189
|
* rules, appends, and mutators.
|
|
7270
8190
|
*
|
|
@@ -7681,6 +8601,18 @@ var Model = class Model {
|
|
|
7681
8601
|
}, {});
|
|
7682
8602
|
}
|
|
7683
8603
|
/**
|
|
8604
|
+
* Capture the attribute snapshot that was persisted before the most recent
|
|
8605
|
+
* save so it can be read back via getPrevious().
|
|
8606
|
+
*
|
|
8607
|
+
* @param previousOriginal
|
|
8608
|
+
*/
|
|
8609
|
+
syncPrevious(previousOriginal) {
|
|
8610
|
+
this.previous = Object.entries(previousOriginal).reduce((all, [key, value]) => {
|
|
8611
|
+
all[key] = Model.cloneAttributeValue(value);
|
|
8612
|
+
return all;
|
|
8613
|
+
}, {});
|
|
8614
|
+
}
|
|
8615
|
+
/**
|
|
7684
8616
|
* Resolve lifecycle state for the provided model class.
|
|
7685
8617
|
*
|
|
7686
8618
|
* @param modelClass
|
|
@@ -8354,4 +9286,4 @@ var PivotModel = class extends Model {
|
|
|
8354
9286
|
};
|
|
8355
9287
|
|
|
8356
9288
|
//#endregion
|
|
8357
|
-
export { Arkorm, ArkormCollection, ArkormException, Arkormx, Attribute, CliApp, DB, EnumBuilder, ForeignKeyBuilder, InitCommand, InlineFactory, KyselyDatabaseAdapter, LengthAwarePaginator, MIGRATION_BRAND, MakeFactoryCommand, MakeMigrationCommand, MakeModelCommand, MakeSeederCommand, MigrateCommand, MigrateFreshCommand, MigrateRollbackCommand, Migration, MigrationHistoryCommand, MissingDelegateException, Model, ModelFactory, ModelNotFoundException, ModelsSyncCommand, PRISMA_ENUM_MEMBER_REGEX, PRISMA_ENUM_REGEX, PRISMA_MODEL_REGEX, Paginator, PivotModel, PrimaryKeyGenerationPlanner, PrismaDatabaseAdapter, QueryBuilder, QueryConstraintException, QueryExecutionException, RelationResolutionException, RuntimeModuleLoader, SEEDER_BRAND, SchemaBuilder, ScopeNotDefinedException, SeedCommand, Seeder, TableBuilder, URLDriver, UniqueConstraintResolutionException, UnsupportedAdapterFeatureException, applyAlterTableOperation, applyCreateTableOperation, applyDropTableOperation, applyMigrationRollbackToDatabase, applyMigrationRollbackToPrismaSchema, applyMigrationToDatabase, applyMigrationToPrismaSchema, applyOperationsToPersistedColumnMappingsState, applyOperationsToPrismaSchema, awaitConfiguredModelsRegistration, bindAdapterToModels, buildEnumBlock, buildFieldLine, buildIndexLine, buildInverseRelationLine, buildMigrationIdentity, buildMigrationRunId, buildMigrationSource, buildModelBlock, buildPrimaryKeyLine, buildRelationLine, buildUniqueConstraintLine, computeMigrationChecksum, configureArkormRuntime, createEmptyAppliedMigrationsState, createEmptyPersistedColumnMappingsState, createKyselyAdapter, createMigrationTimestamp, createPrismaAdapter, createPrismaCompatibilityAdapter, createPrismaDatabaseAdapter, createPrismaDelegateMap, defineConfig, defineFactory, deleteAppliedMigrationsStateFromStore, deletePersistedColumnMappingsState, deriveCollectionFieldName, deriveInverseRelationAlias, deriveRelationAlias, deriveRelationFieldName, deriveSingularFieldName, emitRuntimeDebugEvent, ensureArkormConfigLoading, escapeRegex, findAppliedMigration, findEnumBlock, findModelBlock, formatDefaultValue, formatEnumDefaultValue, formatRelationAction, generateMigrationFile, getActiveTransactionAdapter, getActiveTransactionClient, getDefaultStubsPath, getLastMigrationRun, getLatestAppliedMigrations, getMigrationPlan, getPersistedColumnMap, getPersistedEnumMap, getPersistedEnumTsType, getPersistedPrimaryKeyGeneration, getPersistedTableMetadata, getPersistedTimestampColumns, getRegisteredFactories, getRegisteredMigrations, getRegisteredModels, getRegisteredPaths, getRegisteredSeeders, getRuntimeAdapter, getRuntimeClient, getRuntimeCompatibilityAdapter, getRuntimeDebugHandler, getRuntimePaginationCurrentPageResolver, getRuntimePaginationURLDriverFactory, getRuntimePrismaClient, getUserConfig, inferDelegateName, isDelegateLike, isMigrationApplied, isQuerySchemaLike, isTransactionCapableClient, loadArkormConfig, loadFactoriesFrom, loadMigrationsFrom, loadModelsFrom, loadSeedersFrom, markMigrationApplied, markMigrationRun, pad, readAppliedMigrationsState, readAppliedMigrationsStateFromStore, readPersistedColumnMappingsState, rebuildPersistedColumnMappingsState, registerFactories, registerMigrations, registerModels, registerPaths, registerSeeders, removeAppliedMigration, resetArkormRuntimeForTests, resetPersistedColumnMappingsCache, resetRuntimeRegistryForTests, resolveCast, resolveColumnMappingsFilePath, resolveEnumName, resolveMigrationClassName, resolveMigrationStateFilePath, resolvePersistedMetadataFeatures, resolvePrismaType, resolveRuntimeCompatibilityQuerySchema, resolveRuntimeCompatibilityQuerySchemaOrThrow, runArkormTransaction, runMigrationWithPrisma, runPrismaCommand, stripPrismaSchemaModelsAndEnums, supportsDatabaseCreation, supportsDatabaseMigrationExecution, supportsDatabaseMigrationState, supportsDatabaseReset, syncPersistedColumnMappingsFromState, toMigrationFileSlug, toModelName, validatePersistedMetadataFeaturesForMigrations, writeAppliedMigrationsState, writeAppliedMigrationsStateToStore, writePersistedColumnMappingsState };
|
|
9289
|
+
export { Arkorm, ArkormCollection, ArkormException, Arkormx, Attribute, CliApp, DB, EnumBuilder, ForeignKeyBuilder, InitCommand, InlineFactory, JoinClause, KyselyDatabaseAdapter, LengthAwarePaginator, MIGRATION_BRAND, MakeFactoryCommand, MakeMigrationCommand, MakeModelCommand, MakeSeederCommand, MigrateCommand, MigrateFreshCommand, MigrateRollbackCommand, Migration, MigrationHistoryCommand, MissingDelegateException, Model, ModelFactory, ModelNotFoundException, ModelsSyncCommand, PRISMA_ENUM_MEMBER_REGEX, PRISMA_ENUM_REGEX, PRISMA_MODEL_REGEX, Paginator, PivotModel, PrimaryKeyGenerationPlanner, PrismaDatabaseAdapter, QueryBuilder, QueryConstraintException, QueryExecutionException, RelationResolutionException, RuntimeModuleLoader, SEEDER_BRAND, SchemaBuilder, ScopeNotDefinedException, SeedCommand, Seeder, TableBuilder, URLDriver, UniqueConstraintResolutionException, UnsupportedAdapterFeatureException, applyAlterTableOperation, applyCreateTableOperation, applyDropTableOperation, applyMigrationRollbackToDatabase, applyMigrationRollbackToPrismaSchema, applyMigrationToDatabase, applyMigrationToPrismaSchema, applyOperationsToPersistedColumnMappingsState, applyOperationsToPrismaSchema, awaitConfiguredModelsRegistration, bindAdapterToModels, buildEnumBlock, buildFieldLine, buildIndexLine, buildInverseRelationLine, buildMigrationIdentity, buildMigrationRunId, buildMigrationSource, buildModelBlock, buildPrimaryKeyLine, buildRelationLine, buildUniqueConstraintLine, computeMigrationChecksum, configureArkormRuntime, createEmptyAppliedMigrationsState, createEmptyPersistedColumnMappingsState, createKyselyAdapter, createMigrationTimestamp, createPrismaAdapter, createPrismaCompatibilityAdapter, createPrismaDatabaseAdapter, createPrismaDelegateMap, defineConfig, defineFactory, deleteAppliedMigrationsStateFromStore, deletePersistedColumnMappingsState, deriveCollectionFieldName, deriveInverseRelationAlias, deriveRelationAlias, deriveRelationFieldName, deriveSingularFieldName, emitRuntimeDebugEvent, ensureArkormConfigLoading, escapeRegex, findAppliedMigration, findEnumBlock, findModelBlock, formatDefaultValue, formatEnumDefaultValue, formatRelationAction, generateMigrationFile, getActiveTransactionAdapter, getActiveTransactionClient, getDefaultStubsPath, getLastMigrationRun, getLatestAppliedMigrations, getMigrationPlan, getPersistedColumnMap, getPersistedEnumMap, getPersistedEnumTsType, getPersistedPrimaryKeyGeneration, getPersistedTableMetadata, getPersistedTimestampColumns, getRegisteredFactories, getRegisteredMigrations, getRegisteredModels, getRegisteredPaths, getRegisteredSeeders, getRuntimeAdapter, getRuntimeClient, getRuntimeCompatibilityAdapter, getRuntimeDebugHandler, getRuntimePaginationCurrentPageResolver, getRuntimePaginationURLDriverFactory, getRuntimePrismaClient, getUserConfig, inferDelegateName, isDelegateLike, isMigrationApplied, isQuerySchemaLike, isTransactionCapableClient, loadArkormConfig, loadFactoriesFrom, loadMigrationsFrom, loadModelsFrom, loadSeedersFrom, markMigrationApplied, markMigrationRun, pad, readAppliedMigrationsState, readAppliedMigrationsStateFromStore, readPersistedColumnMappingsState, rebuildPersistedColumnMappingsState, registerFactories, registerMigrations, registerModels, registerPaths, registerSeeders, removeAppliedMigration, resetArkormRuntimeForTests, resetPersistedColumnMappingsCache, resetRuntimeRegistryForTests, resolveCast, resolveColumnMappingsFilePath, resolveEnumName, resolveMigrationClassName, resolveMigrationStateFilePath, resolvePersistedMetadataFeatures, resolvePrismaType, resolveRuntimeCompatibilityQuerySchema, resolveRuntimeCompatibilityQuerySchemaOrThrow, runArkormTransaction, runMigrationWithPrisma, runPrismaCommand, stripPrismaSchemaModelsAndEnums, supportsDatabaseCreation, supportsDatabaseMigrationExecution, supportsDatabaseMigrationState, supportsDatabaseReset, syncPersistedColumnMappingsFromState, toMigrationFileSlug, toModelName, validatePersistedMetadataFeaturesForMigrations, writeAppliedMigrationsState, writeAppliedMigrationsStateToStore, writePersistedColumnMappingsState };
|