@ronin/compiler 0.16.3 → 0.16.4-leo-ron-1099-1-experimental-372

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 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
@@ -371,7 +371,6 @@ type ObjectRow = Record<string, unknown>;
371
371
  type ResultRecord = Record<string, unknown> & {
372
372
  id: string;
373
373
  ronin: {
374
- locked: boolean;
375
374
  createdAt: string;
376
375
  createdBy: string | null;
377
376
  updatedAt: string;
@@ -405,6 +404,10 @@ interface TransactionOptions {
405
404
  * separating them out into a dedicated `params` array.
406
405
  */
407
406
  inlineParams?: boolean;
407
+ /**
408
+ * Whether to compute default field values as part of the generated statement.
409
+ */
410
+ inlineDefaults?: boolean;
408
411
  }
409
412
  declare class Transaction {
410
413
  #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, parentModel) => {
469
+ var handleTo = (models, model, statementParams, queryType, dependencyStatements, instructions, options) => {
461
470
  const { with: withInstruction, to: toInstruction } = instructions;
462
471
  const defaultFields = {};
463
- if (queryType === "set" || toInstruction.ronin) {
464
- defaultFields.ronin = {
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).main.statement;
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
- { returning: false }
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
  );
@@ -625,7 +645,11 @@ var compileQueryInput = (defaultQuery, models, statementParams, options) => {
625
645
  models,
626
646
  dependencyStatements,
627
647
  statementParams,
628
- defaultQuery
648
+ defaultQuery,
649
+ {
650
+ // biome-ignore lint/complexity/useSimplifiedLogicExpression: This is needed.
651
+ inlineDefaults: options?.inlineDefaults || false
652
+ }
629
653
  );
630
654
  if (query === null)
631
655
  return { dependencies: [], main: dependencyStatements[0], selectedFields: [] };
@@ -655,7 +679,9 @@ var compileQueryInput = (defaultQuery, models, statementParams, options) => {
655
679
  {
656
680
  selecting: instructions?.selecting,
657
681
  including: instructions?.including
658
- }
682
+ },
683
+ // biome-ignore lint/complexity/useSimplifiedLogicExpression: This is needed.
684
+ { inlineDefaults: options?.inlineDefaults || false }
659
685
  );
660
686
  let statement = "";
661
687
  switch (queryType) {
@@ -709,7 +735,7 @@ var compileQueryInput = (defaultQuery, models, statementParams, options) => {
709
735
  queryType,
710
736
  dependencyStatements,
711
737
  { with: instructions.with, to: instructionValue },
712
- options?.parentModel
738
+ options
713
739
  );
714
740
  statement += `${toStatement} `;
715
741
  }
@@ -1458,17 +1484,7 @@ var getSystemFields = (idPrefix) => [
1458
1484
  name: "ID",
1459
1485
  type: "string",
1460
1486
  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
- }
1467
- },
1468
- {
1469
- name: "RONIN - Locked",
1470
- type: "boolean",
1471
- slug: "ronin.locked"
1487
+ defaultValue: ID_EXPRESSION(idPrefix)
1472
1488
  },
1473
1489
  {
1474
1490
  name: "RONIN - Created At",
@@ -1627,7 +1643,7 @@ var formatModelEntity = (type, entities) => {
1627
1643
  });
1628
1644
  return entries ? Object.fromEntries(entries) : void 0;
1629
1645
  };
1630
- var handleSystemModel = (models, dependencyStatements, action, systemModel, newModel) => {
1646
+ var handleSystemModel = (models, dependencyStatements, action, inlineDefaults, systemModel, newModel) => {
1631
1647
  const { system: _, ...systemModelClean } = systemModel;
1632
1648
  const query = {
1633
1649
  [action]: { model: action === "create" ? systemModelClean : systemModelClean.slug }
@@ -1636,10 +1652,10 @@ var handleSystemModel = (models, dependencyStatements, action, systemModel, newM
1636
1652
  const { system: _2, ...newModelClean } = newModel;
1637
1653
  query.alter.to = newModelClean;
1638
1654
  }
1639
- const statement = compileQueryInput(query, models, []);
1655
+ const statement = compileQueryInput(query, models, [], { inlineDefaults });
1640
1656
  dependencyStatements.push(...statement.dependencies);
1641
1657
  };
1642
- var handleSystemModels = (models, dependencyStatements, previousModel, newModel) => {
1658
+ var handleSystemModels = (models, dependencyStatements, previousModel, newModel, inlineDefaults) => {
1643
1659
  const currentSystemModels = models.filter(({ system }) => {
1644
1660
  return system?.model === newModel.id;
1645
1661
  });
@@ -1663,19 +1679,32 @@ var handleSystemModels = (models, dependencyStatements, previousModel, newModel)
1663
1679
  const exists = newSystemModels.find(matchSystemModels.bind(null, systemModel));
1664
1680
  if (exists) {
1665
1681
  if (exists.slug !== systemModel.slug) {
1666
- handleSystemModel(models, dependencyStatements, "alter", systemModel, exists);
1682
+ handleSystemModel(
1683
+ models,
1684
+ dependencyStatements,
1685
+ "alter",
1686
+ inlineDefaults,
1687
+ systemModel,
1688
+ exists
1689
+ );
1667
1690
  }
1668
1691
  continue;
1669
1692
  }
1670
- handleSystemModel(models, dependencyStatements, "drop", systemModel);
1693
+ handleSystemModel(models, dependencyStatements, "drop", inlineDefaults, systemModel);
1671
1694
  }
1672
1695
  for (const systemModel of newSystemModels) {
1673
1696
  const exists = currentSystemModels.find(matchSystemModels.bind(null, systemModel));
1674
1697
  if (exists) continue;
1675
- handleSystemModel(models, dependencyStatements, "create", systemModel);
1698
+ handleSystemModel(
1699
+ models,
1700
+ dependencyStatements,
1701
+ "create",
1702
+ inlineDefaults,
1703
+ systemModel
1704
+ );
1676
1705
  }
1677
1706
  };
1678
- var transformMetaQuery = (models, dependencyStatements, statementParams, query) => {
1707
+ var transformMetaQuery = (models, dependencyStatements, statementParams, query, options) => {
1679
1708
  const { queryType } = splitQuery(query);
1680
1709
  const subAltering = "alter" in query && query.alter && !("to" in query.alter);
1681
1710
  const action = subAltering && query.alter ? Object.keys(query.alter).filter((key) => key !== "model")[0] : queryType;
@@ -1748,7 +1777,9 @@ var transformMetaQuery = (models, dependencyStatements, statementParams, query)
1748
1777
  }
1749
1778
  }
1750
1779
  };
1751
- transformMetaQuery(models, dependencyStatements, null, query2);
1780
+ transformMetaQuery(models, dependencyStatements, null, query2, {
1781
+ inlineDefaults: options.inlineDefaults
1782
+ });
1752
1783
  }
1753
1784
  }
1754
1785
  const modelWithObjects = Object.assign({}, modelWithPresets);
@@ -1758,7 +1789,13 @@ var transformMetaQuery = (models, dependencyStatements, statementParams, query)
1758
1789
  }
1759
1790
  queryTypeDetails = { with: modelWithObjects };
1760
1791
  getSystemModels(models, modelWithPresets).map((systemModel) => {
1761
- return handleSystemModel(models, dependencyStatements, "create", systemModel);
1792
+ return handleSystemModel(
1793
+ models,
1794
+ dependencyStatements,
1795
+ "create",
1796
+ options.inlineDefaults,
1797
+ systemModel
1798
+ );
1762
1799
  });
1763
1800
  }
1764
1801
  if (action === "alter" && model) {
@@ -1781,14 +1818,26 @@ var transformMetaQuery = (models, dependencyStatements, statementParams, query)
1781
1818
  },
1782
1819
  to: modelWithPresets
1783
1820
  };
1784
- handleSystemModels(models, dependencyStatements, modelBeforeUpdate2, model);
1821
+ handleSystemModels(
1822
+ models,
1823
+ dependencyStatements,
1824
+ modelBeforeUpdate2,
1825
+ model,
1826
+ options.inlineDefaults
1827
+ );
1785
1828
  }
1786
1829
  if (action === "drop" && model) {
1787
1830
  models.splice(models.indexOf(model), 1);
1788
1831
  dependencyStatements.push({ statement: `DROP TABLE "${model.table}"`, params: [] });
1789
1832
  queryTypeDetails = { with: { slug } };
1790
1833
  models.filter(({ system }) => system?.model === model.id).map((systemModel) => {
1791
- return handleSystemModel(models, dependencyStatements, "drop", systemModel);
1834
+ return handleSystemModel(
1835
+ models,
1836
+ dependencyStatements,
1837
+ "drop",
1838
+ options.inlineDefaults,
1839
+ systemModel
1840
+ );
1792
1841
  });
1793
1842
  }
1794
1843
  const modelSlug2 = "to" in queryTypeDetails ? queryTypeDetails?.to?.slug : "with" in queryTypeDetails ? queryTypeDetails?.with?.slug : void 0;
@@ -1936,7 +1985,8 @@ var transformMetaQuery = (models, dependencyStatements, statementParams, query)
1936
1985
  const effectStatements = trigger.effects.map((effectQuery) => {
1937
1986
  return compileQueryInput(effectQuery, models, null, {
1938
1987
  returning: false,
1939
- parentModel: existingModel
1988
+ parentModel: existingModel,
1989
+ inlineDefaults: options.inlineDefaults
1940
1990
  }).main.statement;
1941
1991
  });
1942
1992
  statementParts.push("BEGIN");
@@ -1971,7 +2021,13 @@ var transformMetaQuery = (models, dependencyStatements, statementParams, query)
1971
2021
  targetEntity.splice(targetEntityIndex, 1);
1972
2022
  }
1973
2023
  }
1974
- handleSystemModels(models, dependencyStatements, modelBeforeUpdate, existingModel);
2024
+ handleSystemModels(
2025
+ models,
2026
+ dependencyStatements,
2027
+ modelBeforeUpdate,
2028
+ existingModel,
2029
+ options.inlineDefaults
2030
+ );
1975
2031
  return {
1976
2032
  set: {
1977
2033
  model: {
@@ -2034,7 +2090,9 @@ var Transaction = class {
2034
2090
  const { dependencies, main, selectedFields } = compileQueryInput(
2035
2091
  query,
2036
2092
  modelsWithPresets,
2037
- options?.inlineParams ? null : []
2093
+ options?.inlineParams ? null : [],
2094
+ // biome-ignore lint/complexity/useSimplifiedLogicExpression: This is needed.
2095
+ { inlineDefaults: options?.inlineDefaults || false }
2038
2096
  );
2039
2097
  const preDependencies = dependencies.filter(({ after }) => !after);
2040
2098
  const postDependencies = dependencies.map(({ after, ...rest }) => after ? rest : null).filter((item) => item != null);
@@ -2058,10 +2116,12 @@ var Transaction = class {
2058
2116
  const record = fields.reduce((acc, field, fieldIndex) => {
2059
2117
  let newSlug = field.mountingPath;
2060
2118
  let newValue = row[fieldIndex];
2061
- if (field.type === "json" || field.type === "blob") {
2062
- newValue = JSON.parse(newValue);
2063
- } else if (field.type === "boolean") {
2064
- newValue = Boolean(newValue);
2119
+ if (newValue !== null) {
2120
+ if (field.type === "json" || field.type === "blob") {
2121
+ newValue = JSON.parse(newValue);
2122
+ } else if (field.type === "boolean") {
2123
+ newValue = Boolean(newValue);
2124
+ }
2065
2125
  }
2066
2126
  if (isMeta && PLURAL_MODEL_ENTITIES_VALUES.includes(newSlug)) {
2067
2127
  newValue = newValue ? Object.entries(newValue).map(([slug, attributes]) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ronin/compiler",
3
- "version": "0.16.3",
3
+ "version": "0.16.4-leo-ron-1099-1-experimental-372",
4
4
  "type": "module",
5
5
  "description": "Compiles RONIN queries to SQL statements.",
6
6
  "publishConfig": {