@ronin/compiler 0.17.0 → 0.17.1-leo-ron-1099-experimental-378
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/index.d.ts +19 -18
- package/dist/index.js +154 -147
- package/package.json +1 -1
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']>, Omit<T, 'slug'>>;
|
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
|
};
|
package/dist/index.js
CHANGED
@@ -587,22 +587,25 @@ var handleTo = (models, model, statementParams, queryType, dependencyStatements,
|
|
587
587
|
var handleUsing = (model, instructions) => {
|
588
588
|
const normalizedUsing = Array.isArray(instructions.using) ? Object.fromEntries(instructions.using.map((presetSlug) => [presetSlug, null])) : instructions.using;
|
589
589
|
if ("links" in normalizedUsing) {
|
590
|
-
for (const
|
590
|
+
for (const [fieldSlug, rest] of Object.entries(model.fields)) {
|
591
|
+
const field = { slug: fieldSlug, ...rest };
|
591
592
|
if (field.type !== "link" || field.kind === "many") continue;
|
592
|
-
normalizedUsing[
|
593
|
+
normalizedUsing[fieldSlug] = null;
|
593
594
|
}
|
594
595
|
}
|
595
596
|
for (const presetSlug in normalizedUsing) {
|
596
597
|
if (!Object.hasOwn(normalizedUsing, presetSlug) || presetSlug === "links") continue;
|
597
598
|
const arg = normalizedUsing[presetSlug];
|
598
|
-
const preset = model.presets?.
|
599
|
+
const preset = model.presets?.[presetSlug];
|
599
600
|
if (!preset) {
|
600
601
|
throw new RoninError({
|
601
602
|
message: `Preset "${presetSlug}" does not exist in model "${model.name}".`,
|
602
603
|
code: "PRESET_NOT_FOUND"
|
603
604
|
});
|
604
605
|
}
|
605
|
-
const replacedUsingFilter = structuredClone(
|
606
|
+
const replacedUsingFilter = structuredClone(
|
607
|
+
preset.instructions
|
608
|
+
);
|
606
609
|
if (arg !== null) {
|
607
610
|
findInObject(
|
608
611
|
replacedUsingFilter,
|
@@ -827,13 +830,16 @@ var matchSelectedFields = (fields, pattern) => {
|
|
827
830
|
return fields.filter((field) => regex2.test(field.slug));
|
828
831
|
};
|
829
832
|
var filterSelectedFields = (model, instruction) => {
|
830
|
-
|
833
|
+
const mappedFields = Object.entries(model.fields).map(
|
834
|
+
([fieldSlug, field]) => ({ slug: fieldSlug, ...field })
|
835
|
+
);
|
836
|
+
if (!instruction) return mappedFields;
|
831
837
|
let selectedFields = [];
|
832
838
|
for (const pattern of instruction) {
|
833
839
|
const isNegative = pattern.startsWith("!");
|
834
840
|
const cleanPattern = isNegative ? pattern.slice(1) : pattern;
|
835
841
|
const matchedFields = matchSelectedFields(
|
836
|
-
isNegative ? selectedFields :
|
842
|
+
isNegative ? selectedFields : mappedFields,
|
837
843
|
cleanPattern
|
838
844
|
);
|
839
845
|
if (isNegative) {
|
@@ -922,7 +928,7 @@ var composeConditions = (models, model, statementParams, instructionName, value,
|
|
922
928
|
return conditions.join(" AND ");
|
923
929
|
}
|
924
930
|
if (options.fieldSlug) {
|
925
|
-
const childField = model.fields.some((
|
931
|
+
const childField = Object.keys(model.fields).some((slug) => {
|
926
932
|
return slug.includes(".") && slug.split(".")[0] === options.fieldSlug;
|
927
933
|
});
|
928
934
|
if (!childField) {
|
@@ -1282,19 +1288,19 @@ var addDefaultModelAttributes = (model, isNew) => {
|
|
1282
1288
|
copiedModel[setting] = generator(copiedModel[base]);
|
1283
1289
|
}
|
1284
1290
|
const newFields = copiedModel.fields || [];
|
1285
|
-
if (isNew || newFields.length > 0) {
|
1291
|
+
if (isNew || Object.keys(newFields).length > 0) {
|
1286
1292
|
if (!copiedModel.identifiers) copiedModel.identifiers = {};
|
1287
1293
|
if (!copiedModel.identifiers.name) {
|
1288
|
-
const suitableField = newFields.find(
|
1289
|
-
(field) => field.type === "string" && field.required === true && ["name"].includes(
|
1294
|
+
const suitableField = Object.entries(newFields).find(
|
1295
|
+
([fieldSlug, field]) => field.type === "string" && field.required === true && ["name"].includes(fieldSlug)
|
1290
1296
|
);
|
1291
|
-
copiedModel.identifiers.name = suitableField?.
|
1297
|
+
copiedModel.identifiers.name = suitableField?.[0] || "id";
|
1292
1298
|
}
|
1293
1299
|
if (!copiedModel.identifiers.slug) {
|
1294
|
-
const suitableField = newFields.find(
|
1295
|
-
(field) => field.type === "string" && field.unique === true && field.required === true && ["slug", "handle"].includes(
|
1300
|
+
const suitableField = Object.entries(newFields).find(
|
1301
|
+
([fieldSlug, field]) => field.type === "string" && field.unique === true && field.required === true && ["slug", "handle"].includes(fieldSlug)
|
1296
1302
|
);
|
1297
|
-
copiedModel.identifiers.slug = suitableField?.
|
1303
|
+
copiedModel.identifiers.slug = suitableField?.[0] || "id";
|
1298
1304
|
}
|
1299
1305
|
}
|
1300
1306
|
return copiedModel;
|
@@ -1302,29 +1308,32 @@ var addDefaultModelAttributes = (model, isNew) => {
|
|
1302
1308
|
var addDefaultModelFields = (model, isNew) => {
|
1303
1309
|
const copiedModel = { ...model };
|
1304
1310
|
const existingFields = copiedModel.fields || [];
|
1305
|
-
if (isNew || existingFields.length > 0) {
|
1306
|
-
const additionalFields =
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1311
|
+
if (isNew || Object.keys(existingFields).length > 0) {
|
1312
|
+
const additionalFields = Object.fromEntries(
|
1313
|
+
Object.entries(getSystemFields(copiedModel.idPrefix)).filter(([newFieldSlug]) => {
|
1314
|
+
return !Object.hasOwn(existingFields, newFieldSlug);
|
1315
|
+
})
|
1316
|
+
);
|
1317
|
+
copiedModel.fields = { ...additionalFields, ...existingFields };
|
1310
1318
|
}
|
1311
1319
|
return copiedModel;
|
1312
1320
|
};
|
1313
1321
|
var addDefaultModelPresets = (list, model) => {
|
1314
|
-
const defaultPresets =
|
1315
|
-
for (const
|
1316
|
-
|
1322
|
+
const defaultPresets = {};
|
1323
|
+
for (const [fieldSlug, rest] of Object.entries(model.fields || {})) {
|
1324
|
+
const field = { slug: fieldSlug, ...rest };
|
1325
|
+
if (field.type === "link" && !fieldSlug.startsWith("ronin.")) {
|
1317
1326
|
const targetModel = getModelBySlug(list, field.target);
|
1318
1327
|
if (field.kind === "many") {
|
1319
1328
|
const systemModel = list.find(({ system }) => {
|
1320
1329
|
return system?.model === model.id && system?.associationSlug === field.slug;
|
1321
1330
|
});
|
1322
1331
|
if (!systemModel) continue;
|
1323
|
-
const
|
1332
|
+
const preset2 = {
|
1324
1333
|
instructions: {
|
1325
1334
|
// Perform a LEFT JOIN that adds the associative table.
|
1326
1335
|
including: {
|
1327
|
-
[
|
1336
|
+
[fieldSlug]: {
|
1328
1337
|
[QUERY_SYMBOLS.QUERY]: {
|
1329
1338
|
get: {
|
1330
1339
|
[systemModel.pluralSlug]: {
|
@@ -1355,16 +1364,15 @@ var addDefaultModelPresets = (list, model) => {
|
|
1355
1364
|
}
|
1356
1365
|
}
|
1357
1366
|
}
|
1358
|
-
}
|
1359
|
-
slug: field.slug
|
1367
|
+
}
|
1360
1368
|
};
|
1361
|
-
defaultPresets
|
1369
|
+
defaultPresets[fieldSlug] = preset2;
|
1362
1370
|
continue;
|
1363
1371
|
}
|
1364
|
-
|
1372
|
+
const preset = {
|
1365
1373
|
instructions: {
|
1366
1374
|
including: {
|
1367
|
-
[
|
1375
|
+
[fieldSlug]: {
|
1368
1376
|
[QUERY_SYMBOLS.QUERY]: {
|
1369
1377
|
get: {
|
1370
1378
|
[targetModel.slug]: {
|
@@ -1380,24 +1388,25 @@ var addDefaultModelPresets = (list, model) => {
|
|
1380
1388
|
}
|
1381
1389
|
}
|
1382
1390
|
}
|
1383
|
-
}
|
1384
|
-
|
1385
|
-
|
1391
|
+
}
|
1392
|
+
};
|
1393
|
+
defaultPresets[fieldSlug] = preset;
|
1386
1394
|
}
|
1387
1395
|
}
|
1388
1396
|
const childModels = list.map((subModel) => {
|
1389
1397
|
if (subModel.system?.associationSlug) return null;
|
1390
|
-
const field = subModel.fields
|
1398
|
+
const field = Object.entries(subModel.fields).find(([fieldSlug, rest]) => {
|
1399
|
+
const field2 = { slug: fieldSlug, ...rest };
|
1391
1400
|
return field2.type === "link" && field2.target === model.slug;
|
1392
1401
|
});
|
1393
1402
|
if (!field) return null;
|
1394
|
-
return { model: subModel, field };
|
1403
|
+
return { model: subModel, field: { slug: field[0], ...field[1] } };
|
1395
1404
|
}).filter((match) => match !== null);
|
1396
1405
|
for (const childMatch of childModels) {
|
1397
1406
|
const { model: childModel, field: childField } = childMatch;
|
1398
1407
|
const pluralSlug = childModel.pluralSlug;
|
1399
1408
|
const presetSlug = childModel.system?.associationSlug || pluralSlug;
|
1400
|
-
|
1409
|
+
const preset = {
|
1401
1410
|
instructions: {
|
1402
1411
|
including: {
|
1403
1412
|
[presetSlug]: {
|
@@ -1414,16 +1423,18 @@ var addDefaultModelPresets = (list, model) => {
|
|
1414
1423
|
}
|
1415
1424
|
}
|
1416
1425
|
}
|
1417
|
-
}
|
1418
|
-
|
1419
|
-
|
1426
|
+
}
|
1427
|
+
};
|
1428
|
+
defaultPresets[presetSlug] = preset;
|
1420
1429
|
}
|
1421
|
-
if (defaultPresets.length > 0) {
|
1422
|
-
const existingPresets = model.presets
|
1423
|
-
const additionalPresets =
|
1424
|
-
|
1425
|
-
|
1426
|
-
|
1430
|
+
if (Object.keys(defaultPresets).length > 0) {
|
1431
|
+
const existingPresets = model.presets;
|
1432
|
+
const additionalPresets = Object.fromEntries(
|
1433
|
+
Object.entries(defaultPresets).filter(([newPresetSlug]) => {
|
1434
|
+
return !existingPresets?.[newPresetSlug];
|
1435
|
+
})
|
1436
|
+
);
|
1437
|
+
model.presets = { ...additionalPresets, ...existingPresets };
|
1427
1438
|
}
|
1428
1439
|
return model;
|
1429
1440
|
};
|
@@ -1455,7 +1466,12 @@ function getFieldFromModel(model, fieldPath, source, shouldThrow = true) {
|
|
1455
1466
|
const writingField = "instructionName" in source ? source.instructionName === "to" : true;
|
1456
1467
|
const errorTarget = "instructionName" in source ? `\`${source.instructionName}\`` : `${source.modelEntityType} "${source.modelEntityName}"`;
|
1457
1468
|
const errorPrefix = `Field "${fieldPath}" defined for ${errorTarget}`;
|
1458
|
-
const modelFields = model.fields
|
1469
|
+
const modelFields = Object.entries(model.fields).map(
|
1470
|
+
([fieldSlug, field]) => ({
|
1471
|
+
slug: fieldSlug,
|
1472
|
+
...field
|
1473
|
+
})
|
1474
|
+
);
|
1459
1475
|
let modelField;
|
1460
1476
|
if (fieldPath.includes(".")) {
|
1461
1477
|
modelField = modelFields.find((field) => field.slug === fieldPath.split(".")[0]);
|
@@ -1479,36 +1495,31 @@ function getFieldFromModel(model, fieldPath, source, shouldThrow = true) {
|
|
1479
1495
|
const fieldSelector = getFieldSelector(model, modelField, fieldPath, writingField);
|
1480
1496
|
return { field: modelField, fieldSelector };
|
1481
1497
|
}
|
1482
|
-
var getSystemFields = (idPrefix) =>
|
1483
|
-
{
|
1498
|
+
var getSystemFields = (idPrefix) => ({
|
1499
|
+
id: {
|
1484
1500
|
name: "ID",
|
1485
1501
|
type: "string",
|
1486
|
-
slug: "id",
|
1487
1502
|
defaultValue: ID_EXPRESSION(idPrefix)
|
1488
1503
|
},
|
1489
|
-
{
|
1504
|
+
"ronin.createdAt": {
|
1490
1505
|
name: "RONIN - Created At",
|
1491
1506
|
type: "date",
|
1492
|
-
slug: "ronin.createdAt",
|
1493
1507
|
defaultValue: CURRENT_TIME_EXPRESSION
|
1494
1508
|
},
|
1495
|
-
{
|
1509
|
+
"ronin.createdBy": {
|
1496
1510
|
name: "RONIN - Created By",
|
1497
|
-
type: "string"
|
1498
|
-
slug: "ronin.createdBy"
|
1511
|
+
type: "string"
|
1499
1512
|
},
|
1500
|
-
{
|
1513
|
+
"ronin.updatedAt": {
|
1501
1514
|
name: "RONIN - Updated At",
|
1502
1515
|
type: "date",
|
1503
|
-
slug: "ronin.updatedAt",
|
1504
1516
|
defaultValue: CURRENT_TIME_EXPRESSION
|
1505
1517
|
},
|
1506
|
-
{
|
1518
|
+
"ronin.updatedBy": {
|
1507
1519
|
name: "RONIN - Updated By",
|
1508
|
-
type: "string"
|
1509
|
-
slug: "ronin.updatedBy"
|
1520
|
+
type: "string"
|
1510
1521
|
}
|
1511
|
-
|
1522
|
+
});
|
1512
1523
|
var ROOT_MODEL = {
|
1513
1524
|
slug: "model",
|
1514
1525
|
identifiers: {
|
@@ -1519,43 +1530,43 @@ var ROOT_MODEL = {
|
|
1519
1530
|
table: "ronin_schema",
|
1520
1531
|
// Indicates that the model was automatically generated by RONIN.
|
1521
1532
|
system: { model: "root" },
|
1522
|
-
fields:
|
1523
|
-
|
1524
|
-
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
1530
|
-
|
1533
|
+
fields: {
|
1534
|
+
name: { type: "string" },
|
1535
|
+
pluralName: { type: "string" },
|
1536
|
+
slug: { type: "string" },
|
1537
|
+
pluralSlug: { type: "string" },
|
1538
|
+
idPrefix: { type: "string" },
|
1539
|
+
table: { type: "string" },
|
1540
|
+
"identifiers.name": { type: "string" },
|
1541
|
+
"identifiers.slug": { type: "string" },
|
1531
1542
|
// Providing an empty object as a default value allows us to use `json_insert`
|
1532
1543
|
// without needing to fall back to an empty object in the insertion statement,
|
1533
1544
|
// which makes the statement shorter.
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1545
|
+
fields: { type: "json", defaultValue: "{}" },
|
1546
|
+
indexes: { type: "json", defaultValue: "{}" },
|
1547
|
+
triggers: { type: "json", defaultValue: "{}" },
|
1548
|
+
presets: { type: "json", defaultValue: "{}" }
|
1549
|
+
}
|
1539
1550
|
};
|
1540
1551
|
var ROOT_MODEL_WITH_ATTRIBUTES = addDefaultModelAttributes(ROOT_MODEL, true);
|
1541
1552
|
var getSystemModels = (models, model) => {
|
1542
1553
|
const addedModels = [];
|
1543
|
-
for (const
|
1544
|
-
|
1554
|
+
for (const [fieldSlug, rest] of Object.entries(model.fields || {})) {
|
1555
|
+
const field = { slug: fieldSlug, ...rest };
|
1556
|
+
if (field.type === "link" && !fieldSlug.startsWith("ronin.")) {
|
1545
1557
|
const relatedModel = getModelBySlug(models, field.target);
|
1546
|
-
let
|
1558
|
+
let fieldSlug2 = relatedModel.slug;
|
1547
1559
|
if (field.kind === "many") {
|
1548
|
-
|
1560
|
+
fieldSlug2 = composeAssociationModelSlug(model, field);
|
1549
1561
|
addedModels.push({
|
1550
|
-
pluralSlug:
|
1551
|
-
slug:
|
1562
|
+
pluralSlug: fieldSlug2,
|
1563
|
+
slug: fieldSlug2,
|
1552
1564
|
system: {
|
1553
1565
|
model: model.id,
|
1554
1566
|
associationSlug: field.slug
|
1555
1567
|
},
|
1556
|
-
fields:
|
1557
|
-
{
|
1558
|
-
slug: "source",
|
1568
|
+
fields: {
|
1569
|
+
source: {
|
1559
1570
|
type: "link",
|
1560
1571
|
target: model.slug,
|
1561
1572
|
actions: {
|
@@ -1563,8 +1574,7 @@ var getSystemModels = (models, model) => {
|
|
1563
1574
|
onUpdate: "CASCADE"
|
1564
1575
|
}
|
1565
1576
|
},
|
1566
|
-
{
|
1567
|
-
slug: "target",
|
1577
|
+
target: {
|
1568
1578
|
type: "link",
|
1569
1579
|
target: relatedModel.slug,
|
1570
1580
|
actions: {
|
@@ -1572,7 +1582,7 @@ var getSystemModels = (models, model) => {
|
|
1572
1582
|
onUpdate: "CASCADE"
|
1573
1583
|
}
|
1574
1584
|
}
|
1575
|
-
|
1585
|
+
}
|
1576
1586
|
});
|
1577
1587
|
}
|
1578
1588
|
}
|
@@ -1636,13 +1646,6 @@ var PLURAL_MODEL_ENTITIES = {
|
|
1636
1646
|
preset: "presets"
|
1637
1647
|
};
|
1638
1648
|
var PLURAL_MODEL_ENTITIES_VALUES = Object.values(PLURAL_MODEL_ENTITIES);
|
1639
|
-
var formatModelEntity = (type, entities) => {
|
1640
|
-
const entries = entities?.map((entity) => {
|
1641
|
-
const { slug, ...rest } = "slug" in entity ? entity : { slug: `${type}Slug`, ...entity };
|
1642
|
-
return [slug, rest];
|
1643
|
-
});
|
1644
|
-
return entries ? Object.fromEntries(entries) : void 0;
|
1645
|
-
};
|
1646
1649
|
var handleSystemModel = (models, dependencyStatements, action, inlineDefaults, systemModel, newModel) => {
|
1647
1650
|
const { system: _, ...systemModelClean } = systemModel;
|
1648
1651
|
const query = {
|
@@ -1665,11 +1668,11 @@ var handleSystemModels = (models, dependencyStatements, previousModel, newModel,
|
|
1665
1668
|
oldSystemModel.system?.model === newSystemModel.system?.model
|
1666
1669
|
];
|
1667
1670
|
if (oldSystemModel.system?.associationSlug) {
|
1668
|
-
const oldFieldIndex = previousModel.fields.findIndex((
|
1669
|
-
return
|
1671
|
+
const oldFieldIndex = Object.keys(previousModel.fields).findIndex((slug) => {
|
1672
|
+
return slug === newSystemModel.system?.associationSlug;
|
1670
1673
|
});
|
1671
|
-
const newFieldIndex = newModel.fields.findIndex((
|
1672
|
-
return
|
1674
|
+
const newFieldIndex = Object.keys(newModel.fields).findIndex((slug) => {
|
1675
|
+
return slug === oldSystemModel.system?.associationSlug;
|
1673
1676
|
});
|
1674
1677
|
conditions.push(oldFieldIndex === newFieldIndex);
|
1675
1678
|
}
|
@@ -1725,7 +1728,7 @@ var transformMetaQuery = (models, dependencyStatements, statementParams, query,
|
|
1725
1728
|
slug = query.alter[action][entity];
|
1726
1729
|
if ("create" in query.alter) {
|
1727
1730
|
const item = query.alter.create[entity];
|
1728
|
-
slug = item.slug
|
1731
|
+
slug = item.slug;
|
1729
1732
|
jsonValue = { slug, ...item };
|
1730
1733
|
}
|
1731
1734
|
if ("alter" in query.alter && query.alter.alter) jsonValue = query.alter.alter.to;
|
@@ -1743,20 +1746,24 @@ var transformMetaQuery = (models, dependencyStatements, statementParams, query,
|
|
1743
1746
|
[...models, modelWithFields],
|
1744
1747
|
modelWithFields
|
1745
1748
|
);
|
1746
|
-
modelWithPresets.fields =
|
1747
|
-
|
1748
|
-
|
1749
|
-
|
1750
|
-
|
1751
|
-
|
1752
|
-
|
1753
|
-
|
1754
|
-
|
1755
|
-
|
1756
|
-
|
1757
|
-
return [pluralType2, formatModelEntity(type, list)];
|
1758
|
-
})
|
1749
|
+
modelWithPresets.fields = Object.fromEntries(
|
1750
|
+
Object.entries(modelWithPresets.fields).map(([fieldSlug, rest]) => [
|
1751
|
+
fieldSlug,
|
1752
|
+
{
|
1753
|
+
...rest,
|
1754
|
+
// Default field type.
|
1755
|
+
type: rest.type || "string",
|
1756
|
+
// Default field name.
|
1757
|
+
name: rest.name || slugToName(fieldSlug)
|
1758
|
+
}
|
1759
|
+
])
|
1759
1760
|
);
|
1761
|
+
const columns = Object.entries(modelWithPresets.fields).map(
|
1762
|
+
([fieldSlug, rest]) => getFieldStatement(models, modelWithPresets, {
|
1763
|
+
slug: fieldSlug,
|
1764
|
+
...rest
|
1765
|
+
})
|
1766
|
+
).filter(Boolean);
|
1760
1767
|
models.push(modelWithPresets);
|
1761
1768
|
dependencyStatements.push({
|
1762
1769
|
statement: `CREATE TABLE "${modelWithPresets.table}" (${columns.join(", ")})`,
|
@@ -1766,28 +1773,27 @@ var transformMetaQuery = (models, dependencyStatements, statementParams, query,
|
|
1766
1773
|
["index", "indexes"],
|
1767
1774
|
["trigger", "triggers"]
|
1768
1775
|
]) {
|
1769
|
-
const
|
1770
|
-
if (!
|
1771
|
-
for (const item of
|
1776
|
+
const entityList = modelWithPresets[pluralModelEntity];
|
1777
|
+
if (!entityList) continue;
|
1778
|
+
for (const [itemSlug, item] of Object.entries(entityList)) {
|
1772
1779
|
const query2 = {
|
1773
1780
|
alter: {
|
1774
1781
|
model: modelWithPresets.slug,
|
1775
1782
|
create: {
|
1776
|
-
[modelEntity]: item
|
1783
|
+
[modelEntity]: { slug: itemSlug, ...item }
|
1777
1784
|
}
|
1778
1785
|
}
|
1779
1786
|
};
|
1780
|
-
|
1787
|
+
const tempModels = [
|
1788
|
+
...models.filter((model2) => model2.slug !== modelWithPresets.slug),
|
1789
|
+
{ ...modelWithPresets, indexes: {}, triggers: {} }
|
1790
|
+
];
|
1791
|
+
transformMetaQuery(tempModels, dependencyStatements, null, query2, {
|
1781
1792
|
inlineDefaults: options.inlineDefaults
|
1782
1793
|
});
|
1783
1794
|
}
|
1784
1795
|
}
|
1785
|
-
|
1786
|
-
for (const entity2 in entities) {
|
1787
|
-
if (!Object.hasOwn(entities, entity2)) continue;
|
1788
|
-
Object.defineProperty(modelWithObjects, entity2, { value: entities[entity2] });
|
1789
|
-
}
|
1790
|
-
queryTypeDetails = { with: modelWithObjects };
|
1796
|
+
queryTypeDetails = { with: modelWithPresets };
|
1791
1797
|
getSystemModels(models, modelWithPresets).map((systemModel) => {
|
1792
1798
|
return handleSystemModel(
|
1793
1799
|
models,
|
@@ -1852,16 +1858,13 @@ var transformMetaQuery = (models, dependencyStatements, statementParams, query,
|
|
1852
1858
|
const modelBeforeUpdate = structuredClone(model);
|
1853
1859
|
const existingModel = model;
|
1854
1860
|
const pluralType = PLURAL_MODEL_ENTITIES[entity];
|
1855
|
-
const
|
1856
|
-
|
1857
|
-
);
|
1858
|
-
if ((action === "alter" || action === "drop") && (typeof targetEntityIndex === "undefined" || targetEntityIndex === -1)) {
|
1861
|
+
const existingEntity = existingModel[pluralType]?.[slug];
|
1862
|
+
if ((action === "alter" || action === "drop") && !existingEntity) {
|
1859
1863
|
throw new RoninError({
|
1860
1864
|
message: `No ${entity} with slug "${slug}" defined in model "${existingModel.name}".`,
|
1861
1865
|
code: MODEL_ENTITY_ERROR_CODES[entity]
|
1862
1866
|
});
|
1863
1867
|
}
|
1864
|
-
const existingEntity = existingModel[pluralType]?.[targetEntityIndex];
|
1865
1868
|
if (action === "create" && existingEntity) {
|
1866
1869
|
throw new RoninError({
|
1867
1870
|
message: `A ${entity} with the slug "${slug}" already exists.`,
|
@@ -1898,7 +1901,7 @@ var transformMetaQuery = (models, dependencyStatements, statementParams, query,
|
|
1898
1901
|
}
|
1899
1902
|
} else if (action === "drop" && !existingLinkField) {
|
1900
1903
|
const systemFields = getSystemFields(existingModel.idPrefix);
|
1901
|
-
const isSystemField =
|
1904
|
+
const isSystemField = slug in systemFields;
|
1902
1905
|
if (isSystemField) {
|
1903
1906
|
throw new RoninError({
|
1904
1907
|
message: `The ${entity} "${slug}" is a system ${entity} and cannot be removed.`,
|
@@ -2002,23 +2005,33 @@ var transformMetaQuery = (models, dependencyStatements, statementParams, query,
|
|
2002
2005
|
case "create": {
|
2003
2006
|
const value = prepareStatementValue(statementParams, jsonValue);
|
2004
2007
|
json = `json_insert(${field}, '$.${slug}', ${value})`;
|
2005
|
-
existingModel[pluralType] =
|
2006
|
-
|
2007
|
-
jsonValue
|
2008
|
-
];
|
2008
|
+
if (!existingModel[pluralType]) existingModel[pluralType] = {};
|
2009
|
+
existingModel[pluralType][slug] = jsonValue;
|
2009
2010
|
break;
|
2010
2011
|
}
|
2011
2012
|
case "alter": {
|
2012
|
-
const
|
2013
|
-
|
2014
|
-
|
2015
|
-
|
2013
|
+
const targetEntities = existingModel[pluralType];
|
2014
|
+
if (jsonValue?.slug && jsonValue.slug !== slug) {
|
2015
|
+
const { slug: newSlug, ...entityValue } = jsonValue;
|
2016
|
+
Object.defineProperty(
|
2017
|
+
targetEntities,
|
2018
|
+
newSlug,
|
2019
|
+
Object.getOwnPropertyDescriptor(targetEntities, slug)
|
2020
|
+
);
|
2021
|
+
delete targetEntities[slug];
|
2022
|
+
const value = prepareStatementValue(statementParams, entityValue);
|
2023
|
+
json = `json_insert(json_remove(${field}, '$.${slug}'), '$.${newSlug}', ${value})`;
|
2024
|
+
} else {
|
2025
|
+
Object.assign(targetEntities[slug], jsonValue);
|
2026
|
+
const value = prepareStatementValue(statementParams, jsonValue);
|
2027
|
+
json = `json_set(${field}, '$.${slug}', json_patch(json_extract(${field}, '$.${slug}'), ${value}))`;
|
2028
|
+
}
|
2016
2029
|
break;
|
2017
2030
|
}
|
2018
2031
|
case "drop": {
|
2019
2032
|
json = `json_remove(${field}, '$.${slug}')`;
|
2020
|
-
const
|
2021
|
-
|
2033
|
+
const targetEntities = existingModel[pluralType];
|
2034
|
+
delete targetEntities[slug];
|
2022
2035
|
}
|
2023
2036
|
}
|
2024
2037
|
handleSystemModels(
|
@@ -2110,7 +2123,7 @@ var Transaction = class {
|
|
2110
2123
|
this.models = modelsWithPresets;
|
2111
2124
|
return statements;
|
2112
2125
|
};
|
2113
|
-
#formatRows(fields, rows, single
|
2126
|
+
#formatRows(fields, rows, single) {
|
2114
2127
|
const records = [];
|
2115
2128
|
for (const row of rows) {
|
2116
2129
|
const record = fields.reduce((acc, field, fieldIndex) => {
|
@@ -2123,11 +2136,6 @@ var Transaction = class {
|
|
2123
2136
|
newValue = Boolean(newValue);
|
2124
2137
|
}
|
2125
2138
|
}
|
2126
|
-
if (isMeta && PLURAL_MODEL_ENTITIES_VALUES.includes(newSlug)) {
|
2127
|
-
newValue = newValue ? Object.entries(newValue).map(([slug, attributes]) => {
|
2128
|
-
return { slug, ...attributes };
|
2129
|
-
}) : [];
|
2130
|
-
}
|
2131
2139
|
const { parentField, parentIsArray } = (() => {
|
2132
2140
|
const lastDotIndex = newSlug.lastIndexOf(".");
|
2133
2141
|
if (lastDotIndex === -1) return { parentField: null };
|
@@ -2221,9 +2229,8 @@ var Transaction = class {
|
|
2221
2229
|
};
|
2222
2230
|
const { queryType, queryModel, queryInstructions } = splitQuery(query);
|
2223
2231
|
const model = getModelBySlug(this.models, queryModel);
|
2224
|
-
const isMeta = queryModel === "model" || queryModel === "models";
|
2225
2232
|
const modelFields = Object.fromEntries(
|
2226
|
-
model.fields.map((
|
2233
|
+
Object.entries(model.fields).map(([slug, rest]) => [slug, rest.type])
|
2227
2234
|
);
|
2228
2235
|
if (queryType === "count") {
|
2229
2236
|
return addResult({ amount: rows[0][0] });
|
@@ -2231,13 +2238,13 @@ var Transaction = class {
|
|
2231
2238
|
const single = queryModel !== model.pluralSlug;
|
2232
2239
|
if (single) {
|
2233
2240
|
return addResult({
|
2234
|
-
record: rows[0] ? this.#formatRows(selectedFields, rows, true
|
2241
|
+
record: rows[0] ? this.#formatRows(selectedFields, rows, true) : null,
|
2235
2242
|
modelFields
|
2236
2243
|
});
|
2237
2244
|
}
|
2238
2245
|
const pageSize = queryInstructions?.limitedTo;
|
2239
2246
|
const result = {
|
2240
|
-
records: this.#formatRows(selectedFields, rows, false
|
2247
|
+
records: this.#formatRows(selectedFields, rows, false),
|
2241
2248
|
modelFields
|
2242
2249
|
};
|
2243
2250
|
if (pageSize && result.records.length > 0) {
|