@ronin/compiler 0.16.5 → 0.17.0-leo-ron-1099-experimental-373
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 +6 -1
- package/dist/index.d.ts +23 -18
- package/dist/index.js +248 -175
- package/package.json +1 -1
package/README.md
CHANGED
@@ -127,7 +127,12 @@ new Transaction(queries, {
|
|
127
127
|
// Instead of returning an array of parameters for every statement (which allows for
|
128
128
|
// preventing SQL injections), all parameters are inlined directly into the SQL strings.
|
129
129
|
// This option should only be used if the generated SQL will be manually verified.
|
130
|
-
inlineParams: true
|
130
|
+
inlineParams: true,
|
131
|
+
|
132
|
+
// By default, the compiler relies on dynamic column default values for computing the
|
133
|
+
// values of all meta fields (such as `id`, `ronin.createdAt`, etc). In order to compute
|
134
|
+
// those values at the time of insertion instead, use this option.
|
135
|
+
inlineDefaults: true
|
131
136
|
});
|
132
137
|
```
|
133
138
|
|
package/dist/index.d.ts
CHANGED
@@ -261,19 +261,19 @@ type ModelField = ModelFieldBasics & ({
|
|
261
261
|
/** Whether the field should be related to one record, or many records. */
|
262
262
|
kind: 'many';
|
263
263
|
});
|
264
|
-
type ModelIndexField<T extends
|
264
|
+
type ModelIndexField<T extends ModelEntityList<ModelField> = ModelEntityList<ModelField>> = {
|
265
265
|
/** The collating sequence used for text placed inside the field. */
|
266
266
|
collation?: ModelFieldCollation;
|
267
267
|
/** How the records in the index should be ordered. */
|
268
268
|
order?: 'ASC' | 'DESC';
|
269
269
|
} & ({
|
270
270
|
/** The field slug for which the index should be created. */
|
271
|
-
slug: T
|
271
|
+
slug: keyof T;
|
272
272
|
} | {
|
273
273
|
/** The field expression for which the index should be created. */
|
274
274
|
expression: string;
|
275
275
|
});
|
276
|
-
type ModelIndex<T extends
|
276
|
+
type ModelIndex<T extends ModelEntityList<ModelField> = ModelEntityList<ModelField>> = {
|
277
277
|
/**
|
278
278
|
* The list of fields in the model for which the index should be created.
|
279
279
|
*/
|
@@ -281,7 +281,7 @@ type ModelIndex<T extends Array<ModelField> = Array<ModelField>> = {
|
|
281
281
|
/**
|
282
282
|
* The identifier of the index.
|
283
283
|
*/
|
284
|
-
slug
|
284
|
+
slug: string;
|
285
285
|
/**
|
286
286
|
* Whether only one record with a unique value for the provided fields will be allowed.
|
287
287
|
*/
|
@@ -292,18 +292,16 @@ type ModelIndex<T extends Array<ModelField> = Array<ModelField>> = {
|
|
292
292
|
*/
|
293
293
|
filter?: WithInstruction;
|
294
294
|
};
|
295
|
-
type ModelTriggerField<T extends
|
295
|
+
type ModelTriggerField<T extends ModelEntityList<ModelField> = ModelEntityList<ModelField>> = {
|
296
296
|
/**
|
297
297
|
* The slug of the field that should cause the trigger to fire if the value of the
|
298
298
|
* field has changed.
|
299
299
|
*/
|
300
|
-
slug: T
|
300
|
+
slug: keyof T;
|
301
301
|
};
|
302
|
-
type ModelTrigger<T extends
|
303
|
-
/**
|
304
|
-
|
305
|
-
*/
|
306
|
-
slug?: string;
|
302
|
+
type ModelTrigger<T extends ModelEntityList<ModelField> = ModelEntityList<ModelField>> = {
|
303
|
+
/** The identifier of the trigger. */
|
304
|
+
slug: string;
|
307
305
|
/** The type of query for which the trigger should fire. */
|
308
306
|
action: 'INSERT' | 'UPDATE' | 'DELETE';
|
309
307
|
/** When the trigger should fire in the case that a matching query is executed. */
|
@@ -324,15 +322,18 @@ type ModelPreset = {
|
|
324
322
|
/** The query instructions that should be applied when the preset is used. */
|
325
323
|
instructions: GetInstructions;
|
326
324
|
};
|
327
|
-
|
325
|
+
type ModelEntityList<T extends {
|
326
|
+
slug: string;
|
327
|
+
}> = Record<NonNullable<T['slug']>, Partial<T>>;
|
328
|
+
interface Model<T extends ModelEntityList<ModelField> = ModelEntityList<ModelField>> {
|
328
329
|
id: string;
|
329
330
|
name: string;
|
330
331
|
pluralName: string;
|
331
332
|
slug: string;
|
332
333
|
pluralSlug: string;
|
333
334
|
identifiers: {
|
334
|
-
name: T
|
335
|
-
slug: T
|
335
|
+
name: keyof T;
|
336
|
+
slug: keyof T;
|
336
337
|
};
|
337
338
|
idPrefix: string;
|
338
339
|
/** The name of the table in SQLite. */
|
@@ -357,11 +358,11 @@ interface Model<T extends Array<ModelField> = Array<ModelField>> {
|
|
357
358
|
associationSlug?: string;
|
358
359
|
};
|
359
360
|
fields: T;
|
360
|
-
indexes?:
|
361
|
-
triggers?:
|
362
|
-
presets?:
|
361
|
+
indexes?: ModelEntityList<ModelIndex<T>>;
|
362
|
+
triggers?: ModelEntityList<ModelTrigger<T>>;
|
363
|
+
presets?: ModelEntityList<ModelPreset>;
|
363
364
|
}
|
364
|
-
type PublicModel<T extends
|
365
|
+
type PublicModel<T extends ModelEntityList<ModelField> = ModelEntityList<ModelField>> = Omit<Partial<Model<T>>, 'slug' | 'identifiers' | 'system' | 'tableAlias'> & {
|
365
366
|
slug: Required<Model['slug']>;
|
366
367
|
identifiers?: Partial<Model['identifiers']>;
|
367
368
|
};
|
@@ -404,6 +405,10 @@ interface TransactionOptions {
|
|
404
405
|
* separating them out into a dedicated `params` array.
|
405
406
|
*/
|
406
407
|
inlineParams?: boolean;
|
408
|
+
/**
|
409
|
+
* Whether to compute default field values as part of the generated statement.
|
410
|
+
*/
|
411
|
+
inlineDefaults?: boolean;
|
407
412
|
}
|
408
413
|
declare class Transaction {
|
409
414
|
#private;
|
package/dist/index.js
CHANGED
@@ -23,6 +23,12 @@ var RAW_FIELD_TYPES = ["string", "number", "boolean"];
|
|
23
23
|
var CURRENT_TIME_EXPRESSION = {
|
24
24
|
[QUERY_SYMBOLS.EXPRESSION]: `strftime('%Y-%m-%dT%H:%M:%f', 'now') || 'Z'`
|
25
25
|
};
|
26
|
+
var ID_EXPRESSION = (idPrefix) => ({
|
27
|
+
// Since default values in SQLite cannot rely on other columns, we unfortunately
|
28
|
+
// cannot rely on the `idPrefix` column here. Instead, we need to inject it directly
|
29
|
+
// into the expression as a static string.
|
30
|
+
[QUERY_SYMBOLS.EXPRESSION]: `'${idPrefix}_' || lower(substr(hex(randomblob(12)), 1, 16))`
|
31
|
+
});
|
26
32
|
var MOUNTING_PATH_SUFFIX = /(.*?)(\{(\d+)\})?$/;
|
27
33
|
var composeMountingPath = (single, key, mountingPath) => {
|
28
34
|
if (key === "ronin_root") {
|
@@ -257,7 +263,9 @@ var handleBeforeOrAfter = (model, statementParams, queryType, instructions) => {
|
|
257
263
|
};
|
258
264
|
|
259
265
|
// src/instructions/including.ts
|
260
|
-
var handleIncluding = (models, model, statementParams, single, instruction, options = {
|
266
|
+
var handleIncluding = (models, model, statementParams, single, instruction, options = {
|
267
|
+
inlineDefaults: false
|
268
|
+
}) => {
|
261
269
|
let statement = "";
|
262
270
|
let tableSubQuery;
|
263
271
|
for (const ephemeralFieldSlug in instruction) {
|
@@ -293,7 +301,7 @@ var handleIncluding = (models, model, statementParams, single, instruction, opti
|
|
293
301
|
},
|
294
302
|
models,
|
295
303
|
statementParams,
|
296
|
-
{ parentModel: model }
|
304
|
+
{ parentModel: model, inlineDefaults: options.inlineDefaults }
|
297
305
|
);
|
298
306
|
relatedTableSelector = `(${subSelect.main.statement})`;
|
299
307
|
}
|
@@ -322,7 +330,7 @@ var handleIncluding = (models, model, statementParams, single, instruction, opti
|
|
322
330
|
statementParams,
|
323
331
|
subSingle,
|
324
332
|
modifiableQueryInstructions.including,
|
325
|
-
{ mountingPath: subMountingPath }
|
333
|
+
{ mountingPath: subMountingPath, inlineDefaults: options.inlineDefaults }
|
326
334
|
);
|
327
335
|
statement += ` ${subIncluding.statement}`;
|
328
336
|
}
|
@@ -367,7 +375,7 @@ var handleOrderedBy = (model, instruction) => {
|
|
367
375
|
};
|
368
376
|
|
369
377
|
// src/instructions/selecting.ts
|
370
|
-
var handleSelecting = (models, model, statementParams, single, instructions, options = {}) => {
|
378
|
+
var handleSelecting = (models, model, statementParams, single, instructions, options = { inlineDefaults: false }) => {
|
371
379
|
let isJoining = false;
|
372
380
|
const selectedFields = filterSelectedFields(
|
373
381
|
model,
|
@@ -395,7 +403,8 @@ var handleSelecting = (models, model, statementParams, single, instructions, opt
|
|
395
403
|
const subQueryModel = getModelBySlug(models, queryModel);
|
396
404
|
if (queryType === "count") {
|
397
405
|
const subSelect = compileQueryInput(symbol2.value, models, statementParams, {
|
398
|
-
parentModel: { ...model, tableAlias: model.table }
|
406
|
+
parentModel: { ...model, tableAlias: model.table },
|
407
|
+
inlineDefaults: options.inlineDefaults
|
399
408
|
});
|
400
409
|
selectedFields.push({
|
401
410
|
slug: key,
|
@@ -457,16 +466,23 @@ var handleSelecting = (models, model, statementParams, single, instructions, opt
|
|
457
466
|
};
|
458
467
|
|
459
468
|
// src/instructions/to.ts
|
460
|
-
var handleTo = (models, model, statementParams, queryType, dependencyStatements, instructions,
|
469
|
+
var handleTo = (models, model, statementParams, queryType, dependencyStatements, instructions, options) => {
|
461
470
|
const { with: withInstruction, to: toInstruction } = instructions;
|
462
471
|
const defaultFields = {};
|
463
|
-
|
464
|
-
|
472
|
+
const inlineDefaultInsertionFields = queryType === "add" && options?.inlineDefaults;
|
473
|
+
if (inlineDefaultInsertionFields) {
|
474
|
+
defaultFields.id = toInstruction.id || ID_EXPRESSION(model.idPrefix);
|
475
|
+
}
|
476
|
+
if (queryType === "add" || queryType === "set" || toInstruction.ronin) {
|
477
|
+
const defaults = {
|
478
|
+
// If records are being created, set their creation time.
|
479
|
+
...inlineDefaultInsertionFields ? { createdAt: CURRENT_TIME_EXPRESSION } : {},
|
465
480
|
// If records are being updated, bump their update time.
|
466
|
-
...queryType === "set" ? { updatedAt: CURRENT_TIME_EXPRESSION } : {},
|
481
|
+
...queryType === "set" || inlineDefaultInsertionFields ? { updatedAt: CURRENT_TIME_EXPRESSION } : {},
|
467
482
|
// Allow for overwriting the default values provided above.
|
468
483
|
...toInstruction.ronin
|
469
484
|
};
|
485
|
+
if (Object.keys(defaults).length > 0) defaultFields.ronin = defaults;
|
470
486
|
}
|
471
487
|
const symbol = getQuerySymbol(toInstruction);
|
472
488
|
if (symbol?.type === "query") {
|
@@ -492,7 +508,10 @@ var handleTo = (models, model, statementParams, queryType, dependencyStatements,
|
|
492
508
|
});
|
493
509
|
statement2 = `(${columns.join(", ")}) `;
|
494
510
|
}
|
495
|
-
statement2 += compileQueryInput(symbol.value, models, statementParams
|
511
|
+
statement2 += compileQueryInput(symbol.value, models, statementParams, {
|
512
|
+
// biome-ignore lint/complexity/useSimplifiedLogicExpression: This is needed.
|
513
|
+
inlineDefaults: options?.inlineDefaults || false
|
514
|
+
}).main.statement;
|
496
515
|
return statement2;
|
497
516
|
}
|
498
517
|
Object.assign(toInstruction, defaultFields);
|
@@ -520,7 +539,8 @@ var handleTo = (models, model, statementParams, queryType, dependencyStatements,
|
|
520
539
|
},
|
521
540
|
models,
|
522
541
|
[],
|
523
|
-
|
542
|
+
// biome-ignore lint/complexity/useSimplifiedLogicExpression: This is needed.
|
543
|
+
{ returning: false, inlineDefaults: options?.inlineDefaults || false }
|
524
544
|
).main;
|
525
545
|
dependencyStatements.push({ ...query, after: true });
|
526
546
|
};
|
@@ -541,7 +561,7 @@ var handleTo = (models, model, statementParams, queryType, dependencyStatements,
|
|
541
561
|
}
|
542
562
|
}
|
543
563
|
let statement = composeConditions(models, model, statementParams, "to", toInstruction, {
|
544
|
-
parentModel,
|
564
|
+
parentModel: options?.parentModel,
|
545
565
|
type: queryType === "add" ? "fields" : void 0
|
546
566
|
});
|
547
567
|
if (queryType === "add") {
|
@@ -552,7 +572,7 @@ var handleTo = (models, model, statementParams, queryType, dependencyStatements,
|
|
552
572
|
"to",
|
553
573
|
toInstruction,
|
554
574
|
{
|
555
|
-
parentModel,
|
575
|
+
parentModel: options?.parentModel,
|
556
576
|
type: "values"
|
557
577
|
}
|
558
578
|
);
|
@@ -567,22 +587,24 @@ var handleTo = (models, model, statementParams, queryType, dependencyStatements,
|
|
567
587
|
var handleUsing = (model, instructions) => {
|
568
588
|
const normalizedUsing = Array.isArray(instructions.using) ? Object.fromEntries(instructions.using.map((presetSlug) => [presetSlug, null])) : instructions.using;
|
569
589
|
if ("links" in normalizedUsing) {
|
570
|
-
for (const field of model.fields) {
|
590
|
+
for (const [fieldSlug, field] of Object.entries(model.fields)) {
|
571
591
|
if (field.type !== "link" || field.kind === "many") continue;
|
572
|
-
normalizedUsing[
|
592
|
+
normalizedUsing[fieldSlug] = null;
|
573
593
|
}
|
574
594
|
}
|
575
595
|
for (const presetSlug in normalizedUsing) {
|
576
596
|
if (!Object.hasOwn(normalizedUsing, presetSlug) || presetSlug === "links") continue;
|
577
597
|
const arg = normalizedUsing[presetSlug];
|
578
|
-
const preset = model.presets?.
|
598
|
+
const preset = model.presets?.[presetSlug];
|
579
599
|
if (!preset) {
|
580
600
|
throw new RoninError({
|
581
601
|
message: `Preset "${presetSlug}" does not exist in model "${model.name}".`,
|
582
602
|
code: "PRESET_NOT_FOUND"
|
583
603
|
});
|
584
604
|
}
|
585
|
-
const replacedUsingFilter = structuredClone(
|
605
|
+
const replacedUsingFilter = structuredClone(
|
606
|
+
preset.instructions
|
607
|
+
);
|
586
608
|
if (arg !== null) {
|
587
609
|
findInObject(
|
588
610
|
replacedUsingFilter,
|
@@ -625,7 +647,11 @@ var compileQueryInput = (defaultQuery, models, statementParams, options) => {
|
|
625
647
|
models,
|
626
648
|
dependencyStatements,
|
627
649
|
statementParams,
|
628
|
-
defaultQuery
|
650
|
+
defaultQuery,
|
651
|
+
{
|
652
|
+
// biome-ignore lint/complexity/useSimplifiedLogicExpression: This is needed.
|
653
|
+
inlineDefaults: options?.inlineDefaults || false
|
654
|
+
}
|
629
655
|
);
|
630
656
|
if (query === null)
|
631
657
|
return { dependencies: [], main: dependencyStatements[0], selectedFields: [] };
|
@@ -655,7 +681,9 @@ var compileQueryInput = (defaultQuery, models, statementParams, options) => {
|
|
655
681
|
{
|
656
682
|
selecting: instructions?.selecting,
|
657
683
|
including: instructions?.including
|
658
|
-
}
|
684
|
+
},
|
685
|
+
// biome-ignore lint/complexity/useSimplifiedLogicExpression: This is needed.
|
686
|
+
{ inlineDefaults: options?.inlineDefaults || false }
|
659
687
|
);
|
660
688
|
let statement = "";
|
661
689
|
switch (queryType) {
|
@@ -709,7 +737,7 @@ var compileQueryInput = (defaultQuery, models, statementParams, options) => {
|
|
709
737
|
queryType,
|
710
738
|
dependencyStatements,
|
711
739
|
{ with: instructions.with, to: instructionValue },
|
712
|
-
options
|
740
|
+
options
|
713
741
|
);
|
714
742
|
statement += `${toStatement} `;
|
715
743
|
}
|
@@ -801,13 +829,16 @@ var matchSelectedFields = (fields, pattern) => {
|
|
801
829
|
return fields.filter((field) => regex2.test(field.slug));
|
802
830
|
};
|
803
831
|
var filterSelectedFields = (model, instruction) => {
|
804
|
-
|
832
|
+
const mappedFields = Object.entries(model.fields).map(
|
833
|
+
([fieldSlug, field]) => ({ slug: fieldSlug, ...field })
|
834
|
+
);
|
835
|
+
if (!instruction) return mappedFields;
|
805
836
|
let selectedFields = [];
|
806
837
|
for (const pattern of instruction) {
|
807
838
|
const isNegative = pattern.startsWith("!");
|
808
839
|
const cleanPattern = isNegative ? pattern.slice(1) : pattern;
|
809
840
|
const matchedFields = matchSelectedFields(
|
810
|
-
isNegative ? selectedFields :
|
841
|
+
isNegative ? selectedFields : mappedFields,
|
811
842
|
cleanPattern
|
812
843
|
);
|
813
844
|
if (isNegative) {
|
@@ -896,7 +927,7 @@ var composeConditions = (models, model, statementParams, instructionName, value,
|
|
896
927
|
return conditions.join(" AND ");
|
897
928
|
}
|
898
929
|
if (options.fieldSlug) {
|
899
|
-
const childField = model.fields.some((
|
930
|
+
const childField = Object.keys(model.fields).some((slug) => {
|
900
931
|
return slug.includes(".") && slug.split(".")[0] === options.fieldSlug;
|
901
932
|
});
|
902
933
|
if (!childField) {
|
@@ -1256,19 +1287,19 @@ var addDefaultModelAttributes = (model, isNew) => {
|
|
1256
1287
|
copiedModel[setting] = generator(copiedModel[base]);
|
1257
1288
|
}
|
1258
1289
|
const newFields = copiedModel.fields || [];
|
1259
|
-
if (isNew || newFields.length > 0) {
|
1290
|
+
if (isNew || Object.keys(newFields).length > 0) {
|
1260
1291
|
if (!copiedModel.identifiers) copiedModel.identifiers = {};
|
1261
1292
|
if (!copiedModel.identifiers.name) {
|
1262
|
-
const suitableField = newFields.find(
|
1263
|
-
(field) => field.type === "string" && field.required === true && ["name"].includes(
|
1293
|
+
const suitableField = Object.entries(newFields).find(
|
1294
|
+
([fieldSlug, field]) => field.type === "string" && field.required === true && ["name"].includes(fieldSlug)
|
1264
1295
|
);
|
1265
|
-
copiedModel.identifiers.name = suitableField?.
|
1296
|
+
copiedModel.identifiers.name = suitableField?.[0] || "id";
|
1266
1297
|
}
|
1267
1298
|
if (!copiedModel.identifiers.slug) {
|
1268
|
-
const suitableField = newFields.find(
|
1269
|
-
(field) => field.type === "string" && field.unique === true && field.required === true && ["slug", "handle"].includes(
|
1299
|
+
const suitableField = Object.entries(newFields).find(
|
1300
|
+
([fieldSlug, field]) => field.type === "string" && field.unique === true && field.required === true && ["slug", "handle"].includes(fieldSlug)
|
1270
1301
|
);
|
1271
|
-
copiedModel.identifiers.slug = suitableField?.
|
1302
|
+
copiedModel.identifiers.slug = suitableField?.[0] || "id";
|
1272
1303
|
}
|
1273
1304
|
}
|
1274
1305
|
return copiedModel;
|
@@ -1276,29 +1307,32 @@ var addDefaultModelAttributes = (model, isNew) => {
|
|
1276
1307
|
var addDefaultModelFields = (model, isNew) => {
|
1277
1308
|
const copiedModel = { ...model };
|
1278
1309
|
const existingFields = copiedModel.fields || [];
|
1279
|
-
if (isNew || existingFields.length > 0) {
|
1280
|
-
const additionalFields =
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1310
|
+
if (isNew || Object.keys(existingFields).length > 0) {
|
1311
|
+
const additionalFields = Object.fromEntries(
|
1312
|
+
Object.entries(getSystemFields(copiedModel.idPrefix)).filter(([newFieldSlug]) => {
|
1313
|
+
return !Object.hasOwn(existingFields, newFieldSlug);
|
1314
|
+
})
|
1315
|
+
);
|
1316
|
+
copiedModel.fields = { ...additionalFields, ...existingFields };
|
1284
1317
|
}
|
1285
1318
|
return copiedModel;
|
1286
1319
|
};
|
1287
1320
|
var addDefaultModelPresets = (list, model) => {
|
1288
|
-
const defaultPresets =
|
1289
|
-
for (const
|
1290
|
-
|
1321
|
+
const defaultPresets = {};
|
1322
|
+
for (const [fieldSlug, rest] of Object.entries(model.fields || {})) {
|
1323
|
+
const field = { slug: fieldSlug, ...rest };
|
1324
|
+
if (field.type === "link" && !fieldSlug.startsWith("ronin.")) {
|
1291
1325
|
const targetModel = getModelBySlug(list, field.target);
|
1292
1326
|
if (field.kind === "many") {
|
1293
1327
|
const systemModel = list.find(({ system }) => {
|
1294
1328
|
return system?.model === model.id && system?.associationSlug === field.slug;
|
1295
1329
|
});
|
1296
1330
|
if (!systemModel) continue;
|
1297
|
-
const
|
1331
|
+
const preset2 = {
|
1298
1332
|
instructions: {
|
1299
1333
|
// Perform a LEFT JOIN that adds the associative table.
|
1300
1334
|
including: {
|
1301
|
-
[
|
1335
|
+
[fieldSlug]: {
|
1302
1336
|
[QUERY_SYMBOLS.QUERY]: {
|
1303
1337
|
get: {
|
1304
1338
|
[systemModel.pluralSlug]: {
|
@@ -1329,16 +1363,15 @@ var addDefaultModelPresets = (list, model) => {
|
|
1329
1363
|
}
|
1330
1364
|
}
|
1331
1365
|
}
|
1332
|
-
}
|
1333
|
-
slug: field.slug
|
1366
|
+
}
|
1334
1367
|
};
|
1335
|
-
defaultPresets
|
1368
|
+
defaultPresets[fieldSlug] = preset2;
|
1336
1369
|
continue;
|
1337
1370
|
}
|
1338
|
-
|
1371
|
+
const preset = {
|
1339
1372
|
instructions: {
|
1340
1373
|
including: {
|
1341
|
-
[
|
1374
|
+
[fieldSlug]: {
|
1342
1375
|
[QUERY_SYMBOLS.QUERY]: {
|
1343
1376
|
get: {
|
1344
1377
|
[targetModel.slug]: {
|
@@ -1354,24 +1387,24 @@ var addDefaultModelPresets = (list, model) => {
|
|
1354
1387
|
}
|
1355
1388
|
}
|
1356
1389
|
}
|
1357
|
-
}
|
1358
|
-
|
1359
|
-
|
1390
|
+
}
|
1391
|
+
};
|
1392
|
+
defaultPresets[fieldSlug] = preset;
|
1360
1393
|
}
|
1361
1394
|
}
|
1362
1395
|
const childModels = list.map((subModel) => {
|
1363
1396
|
if (subModel.system?.associationSlug) return null;
|
1364
|
-
const field = subModel.fields
|
1397
|
+
const field = Object.entries(subModel.fields).find(([_, field2]) => {
|
1365
1398
|
return field2.type === "link" && field2.target === model.slug;
|
1366
1399
|
});
|
1367
1400
|
if (!field) return null;
|
1368
|
-
return { model: subModel, field };
|
1401
|
+
return { model: subModel, field: { slug: field[0], ...field[1] } };
|
1369
1402
|
}).filter((match) => match !== null);
|
1370
1403
|
for (const childMatch of childModels) {
|
1371
1404
|
const { model: childModel, field: childField } = childMatch;
|
1372
1405
|
const pluralSlug = childModel.pluralSlug;
|
1373
1406
|
const presetSlug = childModel.system?.associationSlug || pluralSlug;
|
1374
|
-
|
1407
|
+
const preset = {
|
1375
1408
|
instructions: {
|
1376
1409
|
including: {
|
1377
1410
|
[presetSlug]: {
|
@@ -1388,16 +1421,18 @@ var addDefaultModelPresets = (list, model) => {
|
|
1388
1421
|
}
|
1389
1422
|
}
|
1390
1423
|
}
|
1391
|
-
}
|
1392
|
-
|
1393
|
-
|
1424
|
+
}
|
1425
|
+
};
|
1426
|
+
defaultPresets[presetSlug] = preset;
|
1394
1427
|
}
|
1395
|
-
if (defaultPresets.length > 0) {
|
1396
|
-
const existingPresets = model.presets
|
1397
|
-
const additionalPresets =
|
1398
|
-
|
1399
|
-
|
1400
|
-
|
1428
|
+
if (Object.keys(defaultPresets).length > 0) {
|
1429
|
+
const existingPresets = model.presets;
|
1430
|
+
const additionalPresets = Object.fromEntries(
|
1431
|
+
Object.entries(defaultPresets).filter(([newPresetSlug]) => {
|
1432
|
+
return !existingPresets?.[newPresetSlug];
|
1433
|
+
})
|
1434
|
+
);
|
1435
|
+
model.presets = { ...additionalPresets, ...existingPresets };
|
1401
1436
|
}
|
1402
1437
|
return model;
|
1403
1438
|
};
|
@@ -1429,7 +1464,12 @@ function getFieldFromModel(model, fieldPath, source, shouldThrow = true) {
|
|
1429
1464
|
const writingField = "instructionName" in source ? source.instructionName === "to" : true;
|
1430
1465
|
const errorTarget = "instructionName" in source ? `\`${source.instructionName}\`` : `${source.modelEntityType} "${source.modelEntityName}"`;
|
1431
1466
|
const errorPrefix = `Field "${fieldPath}" defined for ${errorTarget}`;
|
1432
|
-
const modelFields = model.fields
|
1467
|
+
const modelFields = Object.entries(model.fields).map(
|
1468
|
+
([fieldSlug, field]) => ({
|
1469
|
+
slug: fieldSlug,
|
1470
|
+
...field
|
1471
|
+
})
|
1472
|
+
);
|
1433
1473
|
let modelField;
|
1434
1474
|
if (fieldPath.includes(".")) {
|
1435
1475
|
modelField = modelFields.find((field) => field.slug === fieldPath.split(".")[0]);
|
@@ -1453,41 +1493,36 @@ function getFieldFromModel(model, fieldPath, source, shouldThrow = true) {
|
|
1453
1493
|
const fieldSelector = getFieldSelector(model, modelField, fieldPath, writingField);
|
1454
1494
|
return { field: modelField, fieldSelector };
|
1455
1495
|
}
|
1456
|
-
var getSystemFields = (idPrefix) =>
|
1457
|
-
{
|
1496
|
+
var getSystemFields = (idPrefix) => ({
|
1497
|
+
id: {
|
1458
1498
|
name: "ID",
|
1459
1499
|
type: "string",
|
1460
1500
|
slug: "id",
|
1461
|
-
defaultValue:
|
1462
|
-
// Since default values in SQLite cannot rely on other columns, we unfortunately
|
1463
|
-
// cannot rely on the `idPrefix` column here. Instead, we need to inject it directly
|
1464
|
-
// into the expression as a static string.
|
1465
|
-
[QUERY_SYMBOLS.EXPRESSION]: `'${idPrefix}_' || lower(substr(hex(randomblob(12)), 1, 16))`
|
1466
|
-
}
|
1501
|
+
defaultValue: ID_EXPRESSION(idPrefix)
|
1467
1502
|
},
|
1468
|
-
{
|
1503
|
+
"ronin.createdAt": {
|
1469
1504
|
name: "RONIN - Created At",
|
1470
1505
|
type: "date",
|
1471
1506
|
slug: "ronin.createdAt",
|
1472
1507
|
defaultValue: CURRENT_TIME_EXPRESSION
|
1473
1508
|
},
|
1474
|
-
{
|
1509
|
+
"ronin.createdBy": {
|
1475
1510
|
name: "RONIN - Created By",
|
1476
1511
|
type: "string",
|
1477
1512
|
slug: "ronin.createdBy"
|
1478
1513
|
},
|
1479
|
-
{
|
1514
|
+
"ronin.updatedAt": {
|
1480
1515
|
name: "RONIN - Updated At",
|
1481
1516
|
type: "date",
|
1482
1517
|
slug: "ronin.updatedAt",
|
1483
1518
|
defaultValue: CURRENT_TIME_EXPRESSION
|
1484
1519
|
},
|
1485
|
-
{
|
1520
|
+
"ronin.updatedBy": {
|
1486
1521
|
name: "RONIN - Updated By",
|
1487
1522
|
type: "string",
|
1488
1523
|
slug: "ronin.updatedBy"
|
1489
1524
|
}
|
1490
|
-
|
1525
|
+
});
|
1491
1526
|
var ROOT_MODEL = {
|
1492
1527
|
slug: "model",
|
1493
1528
|
identifiers: {
|
@@ -1498,43 +1533,43 @@ var ROOT_MODEL = {
|
|
1498
1533
|
table: "ronin_schema",
|
1499
1534
|
// Indicates that the model was automatically generated by RONIN.
|
1500
1535
|
system: { model: "root" },
|
1501
|
-
fields:
|
1502
|
-
|
1503
|
-
|
1504
|
-
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1509
|
-
|
1536
|
+
fields: {
|
1537
|
+
name: { type: "string" },
|
1538
|
+
pluralName: { type: "string" },
|
1539
|
+
slug: { type: "string" },
|
1540
|
+
pluralSlug: { type: "string" },
|
1541
|
+
idPrefix: { type: "string" },
|
1542
|
+
table: { type: "string" },
|
1543
|
+
"identifiers.name": { type: "string" },
|
1544
|
+
"identifiers.slug": { type: "string" },
|
1510
1545
|
// Providing an empty object as a default value allows us to use `json_insert`
|
1511
1546
|
// without needing to fall back to an empty object in the insertion statement,
|
1512
1547
|
// which makes the statement shorter.
|
1513
|
-
|
1514
|
-
|
1515
|
-
|
1516
|
-
|
1517
|
-
|
1548
|
+
fields: { type: "json", defaultValue: "{}" },
|
1549
|
+
indexes: { type: "json", defaultValue: "{}" },
|
1550
|
+
triggers: { type: "json", defaultValue: "{}" },
|
1551
|
+
presets: { type: "json", defaultValue: "{}" }
|
1552
|
+
}
|
1518
1553
|
};
|
1519
1554
|
var ROOT_MODEL_WITH_ATTRIBUTES = addDefaultModelAttributes(ROOT_MODEL, true);
|
1520
1555
|
var getSystemModels = (models, model) => {
|
1521
1556
|
const addedModels = [];
|
1522
|
-
for (const
|
1523
|
-
|
1557
|
+
for (const [fieldSlug, rest] of Object.entries(model.fields || {})) {
|
1558
|
+
const field = { slug: fieldSlug, ...rest };
|
1559
|
+
if (field.type === "link" && !fieldSlug.startsWith("ronin.")) {
|
1524
1560
|
const relatedModel = getModelBySlug(models, field.target);
|
1525
|
-
let
|
1561
|
+
let fieldSlug2 = relatedModel.slug;
|
1526
1562
|
if (field.kind === "many") {
|
1527
|
-
|
1563
|
+
fieldSlug2 = composeAssociationModelSlug(model, field);
|
1528
1564
|
addedModels.push({
|
1529
|
-
pluralSlug:
|
1530
|
-
slug:
|
1565
|
+
pluralSlug: fieldSlug2,
|
1566
|
+
slug: fieldSlug2,
|
1531
1567
|
system: {
|
1532
1568
|
model: model.id,
|
1533
1569
|
associationSlug: field.slug
|
1534
1570
|
},
|
1535
|
-
fields:
|
1536
|
-
{
|
1537
|
-
slug: "source",
|
1571
|
+
fields: {
|
1572
|
+
source: {
|
1538
1573
|
type: "link",
|
1539
1574
|
target: model.slug,
|
1540
1575
|
actions: {
|
@@ -1542,8 +1577,7 @@ var getSystemModels = (models, model) => {
|
|
1542
1577
|
onUpdate: "CASCADE"
|
1543
1578
|
}
|
1544
1579
|
},
|
1545
|
-
{
|
1546
|
-
slug: "target",
|
1580
|
+
target: {
|
1547
1581
|
type: "link",
|
1548
1582
|
target: relatedModel.slug,
|
1549
1583
|
actions: {
|
@@ -1551,7 +1585,7 @@ var getSystemModels = (models, model) => {
|
|
1551
1585
|
onUpdate: "CASCADE"
|
1552
1586
|
}
|
1553
1587
|
}
|
1554
|
-
|
1588
|
+
}
|
1555
1589
|
});
|
1556
1590
|
}
|
1557
1591
|
}
|
@@ -1615,14 +1649,7 @@ var PLURAL_MODEL_ENTITIES = {
|
|
1615
1649
|
preset: "presets"
|
1616
1650
|
};
|
1617
1651
|
var PLURAL_MODEL_ENTITIES_VALUES = Object.values(PLURAL_MODEL_ENTITIES);
|
1618
|
-
var
|
1619
|
-
const entries = entities?.map((entity) => {
|
1620
|
-
const { slug, ...rest } = "slug" in entity ? entity : { slug: `${type}Slug`, ...entity };
|
1621
|
-
return [slug, rest];
|
1622
|
-
});
|
1623
|
-
return entries ? Object.fromEntries(entries) : void 0;
|
1624
|
-
};
|
1625
|
-
var handleSystemModel = (models, dependencyStatements, action, systemModel, newModel) => {
|
1652
|
+
var handleSystemModel = (models, dependencyStatements, action, inlineDefaults, systemModel, newModel) => {
|
1626
1653
|
const { system: _, ...systemModelClean } = systemModel;
|
1627
1654
|
const query = {
|
1628
1655
|
[action]: { model: action === "create" ? systemModelClean : systemModelClean.slug }
|
@@ -1631,10 +1658,10 @@ var handleSystemModel = (models, dependencyStatements, action, systemModel, newM
|
|
1631
1658
|
const { system: _2, ...newModelClean } = newModel;
|
1632
1659
|
query.alter.to = newModelClean;
|
1633
1660
|
}
|
1634
|
-
const statement = compileQueryInput(query, models, []);
|
1661
|
+
const statement = compileQueryInput(query, models, [], { inlineDefaults });
|
1635
1662
|
dependencyStatements.push(...statement.dependencies);
|
1636
1663
|
};
|
1637
|
-
var handleSystemModels = (models, dependencyStatements, previousModel, newModel) => {
|
1664
|
+
var handleSystemModels = (models, dependencyStatements, previousModel, newModel, inlineDefaults) => {
|
1638
1665
|
const currentSystemModels = models.filter(({ system }) => {
|
1639
1666
|
return system?.model === newModel.id;
|
1640
1667
|
});
|
@@ -1644,11 +1671,11 @@ var handleSystemModels = (models, dependencyStatements, previousModel, newModel)
|
|
1644
1671
|
oldSystemModel.system?.model === newSystemModel.system?.model
|
1645
1672
|
];
|
1646
1673
|
if (oldSystemModel.system?.associationSlug) {
|
1647
|
-
const oldFieldIndex = previousModel.fields.findIndex((
|
1648
|
-
return
|
1674
|
+
const oldFieldIndex = Object.keys(previousModel.fields).findIndex((slug) => {
|
1675
|
+
return slug === newSystemModel.system?.associationSlug;
|
1649
1676
|
});
|
1650
|
-
const newFieldIndex = newModel.fields.findIndex((
|
1651
|
-
return
|
1677
|
+
const newFieldIndex = Object.keys(newModel.fields).findIndex((slug) => {
|
1678
|
+
return slug === oldSystemModel.system?.associationSlug;
|
1652
1679
|
});
|
1653
1680
|
conditions.push(oldFieldIndex === newFieldIndex);
|
1654
1681
|
}
|
@@ -1658,19 +1685,32 @@ var handleSystemModels = (models, dependencyStatements, previousModel, newModel)
|
|
1658
1685
|
const exists = newSystemModels.find(matchSystemModels.bind(null, systemModel));
|
1659
1686
|
if (exists) {
|
1660
1687
|
if (exists.slug !== systemModel.slug) {
|
1661
|
-
handleSystemModel(
|
1688
|
+
handleSystemModel(
|
1689
|
+
models,
|
1690
|
+
dependencyStatements,
|
1691
|
+
"alter",
|
1692
|
+
inlineDefaults,
|
1693
|
+
systemModel,
|
1694
|
+
exists
|
1695
|
+
);
|
1662
1696
|
}
|
1663
1697
|
continue;
|
1664
1698
|
}
|
1665
|
-
handleSystemModel(models, dependencyStatements, "drop", systemModel);
|
1699
|
+
handleSystemModel(models, dependencyStatements, "drop", inlineDefaults, systemModel);
|
1666
1700
|
}
|
1667
1701
|
for (const systemModel of newSystemModels) {
|
1668
1702
|
const exists = currentSystemModels.find(matchSystemModels.bind(null, systemModel));
|
1669
1703
|
if (exists) continue;
|
1670
|
-
handleSystemModel(
|
1704
|
+
handleSystemModel(
|
1705
|
+
models,
|
1706
|
+
dependencyStatements,
|
1707
|
+
"create",
|
1708
|
+
inlineDefaults,
|
1709
|
+
systemModel
|
1710
|
+
);
|
1671
1711
|
}
|
1672
1712
|
};
|
1673
|
-
var transformMetaQuery = (models, dependencyStatements, statementParams, query) => {
|
1713
|
+
var transformMetaQuery = (models, dependencyStatements, statementParams, query, options) => {
|
1674
1714
|
const { queryType } = splitQuery(query);
|
1675
1715
|
const subAltering = "alter" in query && query.alter && !("to" in query.alter);
|
1676
1716
|
const action = subAltering && query.alter ? Object.keys(query.alter).filter((key) => key !== "model")[0] : queryType;
|
@@ -1691,7 +1731,7 @@ var transformMetaQuery = (models, dependencyStatements, statementParams, query)
|
|
1691
1731
|
slug = query.alter[action][entity];
|
1692
1732
|
if ("create" in query.alter) {
|
1693
1733
|
const item = query.alter.create[entity];
|
1694
|
-
slug = item.slug
|
1734
|
+
slug = item.slug;
|
1695
1735
|
jsonValue = { slug, ...item };
|
1696
1736
|
}
|
1697
1737
|
if ("alter" in query.alter && query.alter.alter) jsonValue = query.alter.alter.to;
|
@@ -1709,20 +1749,24 @@ var transformMetaQuery = (models, dependencyStatements, statementParams, query)
|
|
1709
1749
|
[...models, modelWithFields],
|
1710
1750
|
modelWithFields
|
1711
1751
|
);
|
1712
|
-
modelWithPresets.fields =
|
1713
|
-
|
1714
|
-
|
1715
|
-
|
1716
|
-
|
1717
|
-
|
1718
|
-
|
1719
|
-
|
1720
|
-
|
1721
|
-
|
1722
|
-
|
1723
|
-
return [pluralType2, formatModelEntity(type, list)];
|
1724
|
-
})
|
1752
|
+
modelWithPresets.fields = Object.fromEntries(
|
1753
|
+
Object.entries(modelWithPresets.fields).map(([fieldSlug, rest]) => [
|
1754
|
+
fieldSlug,
|
1755
|
+
{
|
1756
|
+
...rest,
|
1757
|
+
// Default field type.
|
1758
|
+
type: rest.type || "string",
|
1759
|
+
// Default field name.
|
1760
|
+
name: rest.name || slugToName(fieldSlug)
|
1761
|
+
}
|
1762
|
+
])
|
1725
1763
|
);
|
1764
|
+
const columns = Object.entries(modelWithPresets.fields).map(
|
1765
|
+
([fieldSlug, rest]) => getFieldStatement(models, modelWithPresets, {
|
1766
|
+
slug: fieldSlug,
|
1767
|
+
...rest
|
1768
|
+
})
|
1769
|
+
).filter(Boolean);
|
1726
1770
|
models.push(modelWithPresets);
|
1727
1771
|
dependencyStatements.push({
|
1728
1772
|
statement: `CREATE TABLE "${modelWithPresets.table}" (${columns.join(", ")})`,
|
@@ -1732,28 +1776,35 @@ var transformMetaQuery = (models, dependencyStatements, statementParams, query)
|
|
1732
1776
|
["index", "indexes"],
|
1733
1777
|
["trigger", "triggers"]
|
1734
1778
|
]) {
|
1735
|
-
const
|
1736
|
-
if (!
|
1737
|
-
for (const item of
|
1779
|
+
const entityList = modelWithPresets[pluralModelEntity];
|
1780
|
+
if (!entityList) continue;
|
1781
|
+
for (const [itemSlug, item] of Object.entries(entityList)) {
|
1738
1782
|
const query2 = {
|
1739
1783
|
alter: {
|
1740
1784
|
model: modelWithPresets.slug,
|
1741
1785
|
create: {
|
1742
|
-
[modelEntity]: item
|
1786
|
+
[modelEntity]: { slug: itemSlug, ...item }
|
1743
1787
|
}
|
1744
1788
|
}
|
1745
1789
|
};
|
1746
|
-
|
1790
|
+
const tempModels = [
|
1791
|
+
...models.filter((model2) => model2.slug !== modelWithPresets.slug),
|
1792
|
+
{ slug: modelWithPresets.slug, fields: modelWithPresets.fields }
|
1793
|
+
];
|
1794
|
+
transformMetaQuery(tempModels, dependencyStatements, null, query2, {
|
1795
|
+
inlineDefaults: options.inlineDefaults
|
1796
|
+
});
|
1747
1797
|
}
|
1748
1798
|
}
|
1749
|
-
|
1750
|
-
for (const entity2 in entities) {
|
1751
|
-
if (!Object.hasOwn(entities, entity2)) continue;
|
1752
|
-
Object.defineProperty(modelWithObjects, entity2, { value: entities[entity2] });
|
1753
|
-
}
|
1754
|
-
queryTypeDetails = { with: modelWithObjects };
|
1799
|
+
queryTypeDetails = { with: modelWithPresets };
|
1755
1800
|
getSystemModels(models, modelWithPresets).map((systemModel) => {
|
1756
|
-
return handleSystemModel(
|
1801
|
+
return handleSystemModel(
|
1802
|
+
models,
|
1803
|
+
dependencyStatements,
|
1804
|
+
"create",
|
1805
|
+
options.inlineDefaults,
|
1806
|
+
systemModel
|
1807
|
+
);
|
1757
1808
|
});
|
1758
1809
|
}
|
1759
1810
|
if (action === "alter" && model) {
|
@@ -1776,14 +1827,26 @@ var transformMetaQuery = (models, dependencyStatements, statementParams, query)
|
|
1776
1827
|
},
|
1777
1828
|
to: modelWithPresets
|
1778
1829
|
};
|
1779
|
-
handleSystemModels(
|
1830
|
+
handleSystemModels(
|
1831
|
+
models,
|
1832
|
+
dependencyStatements,
|
1833
|
+
modelBeforeUpdate2,
|
1834
|
+
model,
|
1835
|
+
options.inlineDefaults
|
1836
|
+
);
|
1780
1837
|
}
|
1781
1838
|
if (action === "drop" && model) {
|
1782
1839
|
models.splice(models.indexOf(model), 1);
|
1783
1840
|
dependencyStatements.push({ statement: `DROP TABLE "${model.table}"`, params: [] });
|
1784
1841
|
queryTypeDetails = { with: { slug } };
|
1785
1842
|
models.filter(({ system }) => system?.model === model.id).map((systemModel) => {
|
1786
|
-
return handleSystemModel(
|
1843
|
+
return handleSystemModel(
|
1844
|
+
models,
|
1845
|
+
dependencyStatements,
|
1846
|
+
"drop",
|
1847
|
+
options.inlineDefaults,
|
1848
|
+
systemModel
|
1849
|
+
);
|
1787
1850
|
});
|
1788
1851
|
}
|
1789
1852
|
const modelSlug2 = "to" in queryTypeDetails ? queryTypeDetails?.to?.slug : "with" in queryTypeDetails ? queryTypeDetails?.with?.slug : void 0;
|
@@ -1798,16 +1861,13 @@ var transformMetaQuery = (models, dependencyStatements, statementParams, query)
|
|
1798
1861
|
const modelBeforeUpdate = structuredClone(model);
|
1799
1862
|
const existingModel = model;
|
1800
1863
|
const pluralType = PLURAL_MODEL_ENTITIES[entity];
|
1801
|
-
const
|
1802
|
-
|
1803
|
-
);
|
1804
|
-
if ((action === "alter" || action === "drop") && (typeof targetEntityIndex === "undefined" || targetEntityIndex === -1)) {
|
1864
|
+
const existingEntity = existingModel[pluralType]?.[slug];
|
1865
|
+
if ((action === "alter" || action === "drop") && !existingEntity) {
|
1805
1866
|
throw new RoninError({
|
1806
1867
|
message: `No ${entity} with slug "${slug}" defined in model "${existingModel.name}".`,
|
1807
1868
|
code: MODEL_ENTITY_ERROR_CODES[entity]
|
1808
1869
|
});
|
1809
1870
|
}
|
1810
|
-
const existingEntity = existingModel[pluralType]?.[targetEntityIndex];
|
1811
1871
|
if (action === "create" && existingEntity) {
|
1812
1872
|
throw new RoninError({
|
1813
1873
|
message: `A ${entity} with the slug "${slug}" already exists.`,
|
@@ -1844,7 +1904,7 @@ var transformMetaQuery = (models, dependencyStatements, statementParams, query)
|
|
1844
1904
|
}
|
1845
1905
|
} else if (action === "drop" && !existingLinkField) {
|
1846
1906
|
const systemFields = getSystemFields(existingModel.idPrefix);
|
1847
|
-
const isSystemField =
|
1907
|
+
const isSystemField = slug in systemFields;
|
1848
1908
|
if (isSystemField) {
|
1849
1909
|
throw new RoninError({
|
1850
1910
|
message: `The ${entity} "${slug}" is a system ${entity} and cannot be removed.`,
|
@@ -1931,7 +1991,8 @@ var transformMetaQuery = (models, dependencyStatements, statementParams, query)
|
|
1931
1991
|
const effectStatements = trigger.effects.map((effectQuery) => {
|
1932
1992
|
return compileQueryInput(effectQuery, models, null, {
|
1933
1993
|
returning: false,
|
1934
|
-
parentModel: existingModel
|
1994
|
+
parentModel: existingModel,
|
1995
|
+
inlineDefaults: options.inlineDefaults
|
1935
1996
|
}).main.statement;
|
1936
1997
|
});
|
1937
1998
|
statementParts.push("BEGIN");
|
@@ -1947,26 +2008,42 @@ var transformMetaQuery = (models, dependencyStatements, statementParams, query)
|
|
1947
2008
|
case "create": {
|
1948
2009
|
const value = prepareStatementValue(statementParams, jsonValue);
|
1949
2010
|
json = `json_insert(${field}, '$.${slug}', ${value})`;
|
1950
|
-
existingModel[pluralType] =
|
1951
|
-
|
1952
|
-
jsonValue
|
1953
|
-
];
|
2011
|
+
if (!existingModel[pluralType]) existingModel[pluralType] = {};
|
2012
|
+
existingModel[pluralType][slug] = jsonValue;
|
1954
2013
|
break;
|
1955
2014
|
}
|
1956
2015
|
case "alter": {
|
1957
|
-
const
|
1958
|
-
|
1959
|
-
|
1960
|
-
|
2016
|
+
const targetEntities = existingModel[pluralType];
|
2017
|
+
if (jsonValue?.slug && jsonValue.slug !== slug) {
|
2018
|
+
const { slug: newSlug, ...entityValue } = jsonValue;
|
2019
|
+
Object.defineProperty(
|
2020
|
+
targetEntities,
|
2021
|
+
newSlug,
|
2022
|
+
Object.getOwnPropertyDescriptor(targetEntities, slug)
|
2023
|
+
);
|
2024
|
+
delete targetEntities[slug];
|
2025
|
+
const value = prepareStatementValue(statementParams, entityValue);
|
2026
|
+
json = `json_insert(json_remove(${field}, '$.${slug}'), '$.${newSlug}', ${value})`;
|
2027
|
+
} else {
|
2028
|
+
Object.assign(targetEntities[slug], jsonValue);
|
2029
|
+
const value = prepareStatementValue(statementParams, jsonValue);
|
2030
|
+
json = `json_set(${field}, '$.${slug}', json_patch(json_extract(${field}, '$.${slug}'), ${value}))`;
|
2031
|
+
}
|
1961
2032
|
break;
|
1962
2033
|
}
|
1963
2034
|
case "drop": {
|
1964
2035
|
json = `json_remove(${field}, '$.${slug}')`;
|
1965
|
-
const
|
1966
|
-
|
2036
|
+
const targetEntities = existingModel[pluralType];
|
2037
|
+
delete targetEntities[slug];
|
1967
2038
|
}
|
1968
2039
|
}
|
1969
|
-
handleSystemModels(
|
2040
|
+
handleSystemModels(
|
2041
|
+
models,
|
2042
|
+
dependencyStatements,
|
2043
|
+
modelBeforeUpdate,
|
2044
|
+
existingModel,
|
2045
|
+
options.inlineDefaults
|
2046
|
+
);
|
1970
2047
|
return {
|
1971
2048
|
set: {
|
1972
2049
|
model: {
|
@@ -2029,7 +2106,9 @@ var Transaction = class {
|
|
2029
2106
|
const { dependencies, main, selectedFields } = compileQueryInput(
|
2030
2107
|
query,
|
2031
2108
|
modelsWithPresets,
|
2032
|
-
options?.inlineParams ? null : []
|
2109
|
+
options?.inlineParams ? null : [],
|
2110
|
+
// biome-ignore lint/complexity/useSimplifiedLogicExpression: This is needed.
|
2111
|
+
{ inlineDefaults: options?.inlineDefaults || false }
|
2033
2112
|
);
|
2034
2113
|
const preDependencies = dependencies.filter(({ after }) => !after);
|
2035
2114
|
const postDependencies = dependencies.map(({ after, ...rest }) => after ? rest : null).filter((item) => item != null);
|
@@ -2047,7 +2126,7 @@ var Transaction = class {
|
|
2047
2126
|
this.models = modelsWithPresets;
|
2048
2127
|
return statements;
|
2049
2128
|
};
|
2050
|
-
#formatRows(fields, rows, single
|
2129
|
+
#formatRows(fields, rows, single) {
|
2051
2130
|
const records = [];
|
2052
2131
|
for (const row of rows) {
|
2053
2132
|
const record = fields.reduce((acc, field, fieldIndex) => {
|
@@ -2060,11 +2139,6 @@ var Transaction = class {
|
|
2060
2139
|
newValue = Boolean(newValue);
|
2061
2140
|
}
|
2062
2141
|
}
|
2063
|
-
if (isMeta && PLURAL_MODEL_ENTITIES_VALUES.includes(newSlug)) {
|
2064
|
-
newValue = newValue ? Object.entries(newValue).map(([slug, attributes]) => {
|
2065
|
-
return { slug, ...attributes };
|
2066
|
-
}) : [];
|
2067
|
-
}
|
2068
2142
|
const { parentField, parentIsArray } = (() => {
|
2069
2143
|
const lastDotIndex = newSlug.lastIndexOf(".");
|
2070
2144
|
if (lastDotIndex === -1) return { parentField: null };
|
@@ -2158,9 +2232,8 @@ var Transaction = class {
|
|
2158
2232
|
};
|
2159
2233
|
const { queryType, queryModel, queryInstructions } = splitQuery(query);
|
2160
2234
|
const model = getModelBySlug(this.models, queryModel);
|
2161
|
-
const isMeta = queryModel === "model" || queryModel === "models";
|
2162
2235
|
const modelFields = Object.fromEntries(
|
2163
|
-
model.fields.map((
|
2236
|
+
Object.entries(model.fields).map(([slug, rest]) => [slug, rest.type])
|
2164
2237
|
);
|
2165
2238
|
if (queryType === "count") {
|
2166
2239
|
return addResult({ amount: rows[0][0] });
|
@@ -2168,13 +2241,13 @@ var Transaction = class {
|
|
2168
2241
|
const single = queryModel !== model.pluralSlug;
|
2169
2242
|
if (single) {
|
2170
2243
|
return addResult({
|
2171
|
-
record: rows[0] ? this.#formatRows(selectedFields, rows, true
|
2244
|
+
record: rows[0] ? this.#formatRows(selectedFields, rows, true) : null,
|
2172
2245
|
modelFields
|
2173
2246
|
});
|
2174
2247
|
}
|
2175
2248
|
const pageSize = queryInstructions?.limitedTo;
|
2176
2249
|
const result = {
|
2177
|
-
records: this.#formatRows(selectedFields, rows, false
|
2250
|
+
records: this.#formatRows(selectedFields, rows, false),
|
2178
2251
|
modelFields
|
2179
2252
|
};
|
2180
2253
|
if (pageSize && result.records.length > 0) {
|