@ronin/compiler 0.8.2 → 0.8.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. package/dist/index.d.ts +15 -15
  2. package/dist/index.js +169 -219
  3. package/package.json +1 -1
package/dist/index.d.ts CHANGED
@@ -5880,23 +5880,23 @@ type ModelFieldReference = ModelFieldBasics & {
5880
5880
  };
5881
5881
  };
5882
5882
  type ModelField = ModelFieldNormal | ModelFieldReference;
5883
- type ModelIndexField = {
5883
+ type ModelIndexField<T extends Array<ModelField> = Array<ModelField>> = {
5884
5884
  /** The collating sequence used for text placed inside the field. */
5885
5885
  collation?: ModelFieldCollation;
5886
5886
  /** How the records in the index should be ordered. */
5887
5887
  order?: 'ASC' | 'DESC';
5888
5888
  } & ({
5889
5889
  /** The field slug for which the index should be created. */
5890
- slug: string;
5890
+ slug: T[number]['slug'];
5891
5891
  } | {
5892
5892
  /** The field expression for which the index should be created. */
5893
5893
  expression: string;
5894
5894
  });
5895
- type ModelIndex = {
5895
+ type ModelIndex<T extends Array<ModelField> = Array<ModelField>> = {
5896
5896
  /**
5897
5897
  * The list of fields in the model for which the index should be created.
5898
5898
  */
5899
- fields: Array<ModelIndexField>;
5899
+ fields: Array<ModelIndexField<T>>;
5900
5900
  /**
5901
5901
  * The identifier of the index.
5902
5902
  */
@@ -5911,14 +5911,14 @@ type ModelIndex = {
5911
5911
  */
5912
5912
  filter?: WithInstruction;
5913
5913
  };
5914
- type ModelTriggerField = {
5914
+ type ModelTriggerField<T extends Array<ModelField> = Array<ModelField>> = {
5915
5915
  /**
5916
5916
  * The slug of the field that should cause the trigger to fire if the value of the
5917
5917
  * field has changed.
5918
5918
  */
5919
- slug: string;
5919
+ slug: T[number]['slug'];
5920
5920
  };
5921
- type ModelTrigger = {
5921
+ type ModelTrigger<T extends Array<ModelField> = Array<ModelField>> = {
5922
5922
  /** The type of query for which the trigger should fire. */
5923
5923
  action: 'INSERT' | 'UPDATE' | 'DELETE';
5924
5924
  /** When the trigger should fire in the case that a matching query is executed. */
@@ -5926,7 +5926,7 @@ type ModelTrigger = {
5926
5926
  /** A list of queries that should be executed when the trigger fires. */
5927
5927
  effects: Array<Query>;
5928
5928
  /** A list of field slugs for which the trigger should fire. */
5929
- fields?: Array<ModelTriggerField>;
5929
+ fields?: Array<ModelTriggerField<T>>;
5930
5930
  /**
5931
5931
  * An object containing query instructions used to determine whether the trigger should
5932
5932
  * fire, or not.
@@ -5939,14 +5939,14 @@ type ModelPreset = {
5939
5939
  /** The query instructions that should be applied when the preset is used. */
5940
5940
  instructions: GetInstructions;
5941
5941
  };
5942
- interface Model {
5942
+ interface Model<T extends Array<ModelField> = Array<ModelField>> {
5943
5943
  name: string;
5944
5944
  pluralName: string;
5945
5945
  slug: string;
5946
5946
  pluralSlug: string;
5947
5947
  identifiers: {
5948
- name: string;
5949
- slug: string;
5948
+ name: T[number]['slug'];
5949
+ slug: T[number]['slug'];
5950
5950
  };
5951
5951
  idPrefix: string;
5952
5952
  /** The name of the table in SQLite. */
@@ -5962,12 +5962,12 @@ interface Model {
5962
5962
  * the associative model should be mounted on the source model.
5963
5963
  */
5964
5964
  associationSlug?: string;
5965
- fields: Array<ModelField>;
5966
- indexes?: Array<ModelIndex>;
5967
- triggers?: Array<ModelTrigger>;
5965
+ fields: T;
5966
+ indexes?: Array<ModelIndex<T>>;
5967
+ triggers?: Array<ModelTrigger<T>>;
5968
5968
  presets?: Array<ModelPreset>;
5969
5969
  }
5970
- type PublicModel = Omit<Partial<Model>, 'slug' | 'identifiers' | 'associationSlug' | 'table' | 'tableAlias'> & {
5970
+ type PublicModel<T extends Array<ModelField> = Array<ModelField>> = Omit<Partial<Model<T>>, 'slug' | 'identifiers' | 'associationSlug' | 'table' | 'tableAlias'> & {
5971
5971
  slug: Required<Model['slug']>;
5972
5972
  identifiers?: Partial<Model['identifiers']>;
5973
5973
  };
package/dist/index.js CHANGED
@@ -318,6 +318,151 @@ var handleWith = (models, model, statementParams, instruction, parentModel) => {
318
318
  return `(${subStatement})`;
319
319
  };
320
320
 
321
+ // src/utils/meta.ts
322
+ var PLURAL_MODEL_ENTITIES = {
323
+ field: "fields",
324
+ index: "indexes",
325
+ trigger: "triggers",
326
+ preset: "presets"
327
+ };
328
+ var transformMetaQuery = (models, dependencyStatements, statementParams, query) => {
329
+ if (query.create) {
330
+ const init = query.create.model;
331
+ const details = "to" in query.create ? { slug: init, ...query.create.to } : init;
332
+ const modelWithFields = addDefaultModelFields(details, true);
333
+ const modelWithPresets = addDefaultModelPresets(models, modelWithFields);
334
+ const instructions = {
335
+ to: modelWithPresets
336
+ };
337
+ addModelQueries(models, dependencyStatements, {
338
+ queryType: "add",
339
+ queryModel: "model",
340
+ queryInstructions: instructions
341
+ });
342
+ return {
343
+ add: {
344
+ model: instructions
345
+ }
346
+ };
347
+ }
348
+ if (query.drop) {
349
+ const slug = query.drop.model;
350
+ const instructions = {
351
+ with: { slug }
352
+ };
353
+ addModelQueries(models, dependencyStatements, {
354
+ queryType: "remove",
355
+ queryModel: "model",
356
+ queryInstructions: instructions
357
+ });
358
+ return {
359
+ remove: {
360
+ model: instructions
361
+ }
362
+ };
363
+ }
364
+ if (query.alter) {
365
+ const slug = query.alter.model;
366
+ if ("to" in query.alter) {
367
+ const modelWithFields = addDefaultModelFields(query.alter.to, false);
368
+ const modelWithPresets = addDefaultModelPresets(models, modelWithFields);
369
+ const instructions = {
370
+ with: { slug },
371
+ to: modelWithPresets
372
+ };
373
+ addModelQueries(models, dependencyStatements, {
374
+ queryType: "set",
375
+ queryModel: "model",
376
+ queryInstructions: instructions
377
+ });
378
+ return {
379
+ set: {
380
+ model: instructions
381
+ }
382
+ };
383
+ }
384
+ if ("create" in query.alter) {
385
+ const type2 = Object.keys(query.alter.create)[0];
386
+ const pluralType2 = PLURAL_MODEL_ENTITIES[type2];
387
+ const item = query.alter.create[type2];
388
+ const completeItem = { slug: item.slug || `${type2}Slug`, ...item };
389
+ addModelQueries(models, dependencyStatements, {
390
+ queryType: "add",
391
+ queryModel: type2,
392
+ queryInstructions: {
393
+ to: {
394
+ model: { slug },
395
+ ...completeItem
396
+ }
397
+ }
398
+ });
399
+ const value = prepareStatementValue(statementParams, completeItem);
400
+ const json2 = `json_insert(${RONIN_MODEL_SYMBOLS.FIELD}${pluralType2}, '$.${completeItem.slug}', ${value})`;
401
+ const expression2 = { [RONIN_MODEL_SYMBOLS.EXPRESSION]: json2 };
402
+ return {
403
+ set: {
404
+ model: {
405
+ with: { slug },
406
+ to: {
407
+ [pluralType2]: expression2
408
+ }
409
+ }
410
+ }
411
+ };
412
+ }
413
+ if ("alter" in query.alter) {
414
+ const type2 = Object.keys(query.alter.alter)[0];
415
+ const pluralType2 = PLURAL_MODEL_ENTITIES[type2];
416
+ const itemSlug2 = query.alter.alter[type2];
417
+ const newItem = query.alter.alter.to;
418
+ addModelQueries(models, dependencyStatements, {
419
+ queryType: "set",
420
+ queryModel: type2,
421
+ queryInstructions: {
422
+ with: { model: { slug }, slug: itemSlug2 },
423
+ to: newItem
424
+ }
425
+ });
426
+ const value = prepareStatementValue(statementParams, newItem);
427
+ const json2 = `json_patch(${RONIN_MODEL_SYMBOLS.FIELD}${pluralType2}, '$.${itemSlug2}', ${value})`;
428
+ const expression2 = { [RONIN_MODEL_SYMBOLS.EXPRESSION]: json2 };
429
+ return {
430
+ set: {
431
+ model: {
432
+ with: { slug },
433
+ to: {
434
+ [pluralType2]: expression2
435
+ }
436
+ }
437
+ }
438
+ };
439
+ }
440
+ const type = Object.keys(query.alter.drop)[0];
441
+ const pluralType = PLURAL_MODEL_ENTITIES[type];
442
+ const itemSlug = query.alter.drop[type];
443
+ addModelQueries(models, dependencyStatements, {
444
+ queryType: "remove",
445
+ queryModel: type,
446
+ queryInstructions: {
447
+ with: { model: { slug }, slug: itemSlug }
448
+ }
449
+ });
450
+ const json = `json_insert(${RONIN_MODEL_SYMBOLS.FIELD}${pluralType}, '$.${itemSlug}')`;
451
+ const expression = { [RONIN_MODEL_SYMBOLS.EXPRESSION]: json };
452
+ return {
453
+ set: {
454
+ model: {
455
+ with: { slug },
456
+ to: {
457
+ [pluralType]: expression
458
+ }
459
+ }
460
+ }
461
+ };
462
+ }
463
+ return query;
464
+ };
465
+
321
466
  // src/utils/model.ts
322
467
  import title from "title";
323
468
  var getModelBySlug = (models, slug) => {
@@ -465,6 +610,8 @@ var SYSTEM_MODELS = [
465
610
  name: "name",
466
611
  slug: "slug"
467
612
  },
613
+ // This name mimics the `sqlite_schema` table in SQLite.
614
+ table: "ronin_schema",
468
615
  fields: [
469
616
  { slug: "name", type: "string" },
470
617
  { slug: "pluralName", type: "string" },
@@ -475,98 +622,16 @@ var SYSTEM_MODELS = [
475
622
  { slug: "identifiers", type: "group" },
476
623
  { slug: "identifiers.name", type: "string" },
477
624
  { slug: "identifiers.slug", type: "string" },
478
- { slug: "fields", type: "json" },
479
- { slug: "indexes", type: "json" },
480
- { slug: "triggers", type: "json" },
481
- { slug: "presets", type: "json" }
482
- ]
483
- },
484
- {
485
- slug: "field",
486
- identifiers: {
487
- name: "name",
488
- slug: "slug"
489
- },
490
- fields: [
491
- { slug: "name", type: "string" },
492
- { slug: "slug", type: "string", required: true },
493
- { slug: "type", type: "string", required: true },
494
- {
495
- slug: "model",
496
- type: "link",
497
- target: "model",
498
- required: true
499
- },
500
- { slug: "required", type: "boolean" },
501
- { slug: "defaultValue", type: "string" },
502
- { slug: "unique", type: "boolean" },
503
- { slug: "autoIncrement", type: "boolean" },
504
- // Only allowed for fields of type "link".
505
- { slug: "target", type: "string" },
506
- { slug: "kind", type: "string" },
507
- { slug: "actions", type: "group" },
508
- { slug: "actions.onDelete", type: "string" },
509
- { slug: "actions.onUpdate", type: "string" }
510
- ]
511
- },
512
- {
513
- slug: "index",
514
- identifiers: {
515
- name: "slug",
516
- slug: "slug"
517
- },
518
- fields: [
519
- { slug: "slug", type: "string", required: true },
520
- {
521
- slug: "model",
522
- type: "link",
523
- target: "model",
524
- required: true
525
- },
526
- { slug: "unique", type: "boolean" },
527
- { slug: "filter", type: "json" },
528
- { slug: "fields", type: "json", required: true }
529
- ]
530
- },
531
- {
532
- slug: "trigger",
533
- identifiers: {
534
- name: "slug",
535
- slug: "slug"
536
- },
537
- fields: [
538
- { slug: "slug", type: "string", required: true },
539
- {
540
- slug: "model",
541
- type: "link",
542
- target: "model",
543
- required: true
544
- },
545
- { slug: "when", type: "string", required: true },
546
- { slug: "action", type: "string", required: true },
547
- { slug: "filter", type: "json" },
548
- { slug: "effects", type: "json", required: true },
549
- { slug: "fields", type: "json" }
550
- ]
551
- },
552
- {
553
- slug: "preset",
554
- fields: [
555
- { slug: "slug", type: "string", required: true },
556
- {
557
- slug: "model",
558
- type: "link",
559
- target: "model",
560
- required: true
561
- },
562
- { slug: "instructions", type: "json", required: true }
625
+ // Providing an empty object as a default value allows us to use `json_insert`
626
+ // without needing to fall back to an empty object in the insertion statement,
627
+ // which makes the statement shorter.
628
+ { slug: "fields", type: "json", defaultValue: "{}" },
629
+ { slug: "indexes", type: "json", defaultValue: "{}" },
630
+ { slug: "triggers", type: "json", defaultValue: "{}" },
631
+ { slug: "presets", type: "json", defaultValue: "{}" }
563
632
  ]
564
633
  }
565
- ].map((model) => addDefaultModelFields(model, true));
566
- var SYSTEM_MODEL_SLUGS = SYSTEM_MODELS.flatMap(({ slug, pluralSlug }) => [
567
- slug,
568
- pluralSlug
569
- ]);
634
+ ];
570
635
  var addSystemModels = (models) => {
571
636
  const associativeModels = models.flatMap((model) => {
572
637
  const addedModels = [];
@@ -715,27 +780,26 @@ var getFieldStatement = (models, model, field) => {
715
780
  var addModelQueries = (models, dependencyStatements, queryDetails) => {
716
781
  const { queryType, queryModel, queryInstructions } = queryDetails;
717
782
  if (!["add", "set", "remove"].includes(queryType)) return;
718
- if (!SYSTEM_MODEL_SLUGS.includes(queryModel)) return;
783
+ if (!["model", "field", "index", "trigger", "preset"].includes(queryModel)) return;
719
784
  const instructionName = mappedInstructions[queryType];
720
785
  const instructionList = queryInstructions[instructionName];
721
- const kind = getModelBySlug(SYSTEM_MODELS, queryModel).pluralSlug;
722
786
  let tableAction = "ALTER";
723
787
  let queryTypeReadable = null;
724
788
  switch (queryType) {
725
789
  case "add": {
726
- if (kind === "models" || kind === "indexes" || kind === "triggers") {
790
+ if (queryModel === "model" || queryModel === "index" || queryModel === "trigger") {
727
791
  tableAction = "CREATE";
728
792
  }
729
793
  queryTypeReadable = "creating";
730
794
  break;
731
795
  }
732
796
  case "set": {
733
- if (kind === "models") tableAction = "ALTER";
797
+ if (queryModel === "model") tableAction = "ALTER";
734
798
  queryTypeReadable = "updating";
735
799
  break;
736
800
  }
737
801
  case "remove": {
738
- if (kind === "models" || kind === "indexes" || kind === "triggers") {
802
+ if (queryModel === "model" || queryModel === "index" || queryModel === "trigger") {
739
803
  tableAction = "DROP";
740
804
  }
741
805
  queryTypeReadable = "deleting";
@@ -745,10 +809,10 @@ var addModelQueries = (models, dependencyStatements, queryDetails) => {
745
809
  const slug = instructionList?.slug?.being || instructionList?.slug;
746
810
  const modelInstruction = instructionList?.model;
747
811
  const modelSlug = modelInstruction?.slug?.being || modelInstruction?.slug;
748
- const usableSlug = kind === "models" ? slug : modelSlug;
812
+ const usableSlug = queryModel === "model" ? slug : modelSlug;
749
813
  const tableName = convertToSnakeCase(pluralize(usableSlug));
750
- const targetModel = kind === "models" && queryType === "add" ? null : getModelBySlug(models, usableSlug);
751
- if (kind === "indexes") {
814
+ const targetModel = queryModel === "model" && queryType === "add" ? null : getModelBySlug(models, usableSlug);
815
+ if (queryModel === "index") {
752
816
  const indexName = convertToSnakeCase(slug);
753
817
  const unique = instructionList?.unique;
754
818
  const filterQuery = instructionList?.filter;
@@ -782,7 +846,7 @@ var addModelQueries = (models, dependencyStatements, queryDetails) => {
782
846
  dependencyStatements.push({ statement: statement2, params });
783
847
  return;
784
848
  }
785
- if (kind === "triggers") {
849
+ if (queryModel === "trigger") {
786
850
  const triggerName = convertToSnakeCase(slug);
787
851
  const params = [];
788
852
  let statement2 = `${tableAction} TRIGGER "${triggerName}"`;
@@ -796,7 +860,7 @@ var addModelQueries = (models, dependencyStatements, queryDetails) => {
796
860
  if (fields) {
797
861
  if (action !== "UPDATE") {
798
862
  throw new RoninError({
799
- message: `When ${queryTypeReadable} ${kind}, targeting specific fields requires the \`UPDATE\` action.`,
863
+ message: `When ${queryTypeReadable} ${PLURAL_MODEL_ENTITIES[queryModel]}, targeting specific fields requires the \`UPDATE\` action.`,
800
864
  code: "INVALID_MODEL_VALUE",
801
865
  fields: ["action"]
802
866
  });
@@ -835,7 +899,7 @@ var addModelQueries = (models, dependencyStatements, queryDetails) => {
835
899
  return;
836
900
  }
837
901
  const statement = `${tableAction} TABLE "${tableName}"`;
838
- if (kind === "models") {
902
+ if (queryModel === "model") {
839
903
  if (queryType === "add") {
840
904
  const newModel = queryInstructions.to;
841
905
  const { fields } = newModel;
@@ -861,7 +925,7 @@ var addModelQueries = (models, dependencyStatements, queryDetails) => {
861
925
  }
862
926
  return;
863
927
  }
864
- if (kind === "fields") {
928
+ if (queryModel === "field") {
865
929
  if (queryType === "add") {
866
930
  if (!instructionList.type) instructionList.type = "string";
867
931
  dependencyStatements.push({
@@ -1381,122 +1445,6 @@ var compileQueryInput = (query, models, statementParams, options) => {
1381
1445
  };
1382
1446
  };
1383
1447
 
1384
- // src/utils/meta.ts
1385
- var transformMetaQuery = (models, dependencyStatements, query) => {
1386
- if (query.create) {
1387
- const init = query.create.model;
1388
- const details = "to" in query.create ? { slug: init, ...query.create.to } : init;
1389
- const modelWithFields = addDefaultModelFields(details, true);
1390
- const modelWithPresets = addDefaultModelPresets(models, modelWithFields);
1391
- const instructions = {
1392
- to: modelWithPresets
1393
- };
1394
- addModelQueries(models, dependencyStatements, {
1395
- queryType: "add",
1396
- queryModel: "model",
1397
- queryInstructions: instructions
1398
- });
1399
- return {
1400
- add: {
1401
- model: instructions
1402
- }
1403
- };
1404
- }
1405
- if (query.drop) {
1406
- const slug = query.drop.model;
1407
- const instructions = {
1408
- with: { slug }
1409
- };
1410
- addModelQueries(models, dependencyStatements, {
1411
- queryType: "remove",
1412
- queryModel: "model",
1413
- queryInstructions: instructions
1414
- });
1415
- return {
1416
- remove: {
1417
- model: instructions
1418
- }
1419
- };
1420
- }
1421
- if (query.alter) {
1422
- const slug = query.alter.model;
1423
- if ("to" in query.alter) {
1424
- const modelWithFields = addDefaultModelFields(query.alter.to, false);
1425
- const modelWithPresets = addDefaultModelPresets(models, modelWithFields);
1426
- const instructions2 = {
1427
- with: { slug },
1428
- to: modelWithPresets
1429
- };
1430
- addModelQueries(models, dependencyStatements, {
1431
- queryType: "set",
1432
- queryModel: "model",
1433
- queryInstructions: instructions2
1434
- });
1435
- return {
1436
- set: {
1437
- model: instructions2
1438
- }
1439
- };
1440
- }
1441
- if ("create" in query.alter) {
1442
- const type2 = Object.keys(query.alter.create)[0];
1443
- const item = query.alter.create[type2];
1444
- const completeItem = { slug: item.slug || `${type2}_slug`, ...item };
1445
- const instructions2 = {
1446
- to: {
1447
- model: { slug },
1448
- ...completeItem
1449
- }
1450
- };
1451
- addModelQueries(models, dependencyStatements, {
1452
- queryType: "add",
1453
- queryModel: type2,
1454
- queryInstructions: instructions2
1455
- });
1456
- return {
1457
- add: {
1458
- [type2]: instructions2
1459
- }
1460
- };
1461
- }
1462
- if ("alter" in query.alter) {
1463
- const type2 = Object.keys(query.alter.alter)[0];
1464
- const itemSlug2 = query.alter.alter[type2];
1465
- const newItem = query.alter.alter.to;
1466
- const instructions2 = {
1467
- with: { model: { slug }, slug: itemSlug2 },
1468
- to: newItem
1469
- };
1470
- addModelQueries(models, dependencyStatements, {
1471
- queryType: "set",
1472
- queryModel: type2,
1473
- queryInstructions: instructions2
1474
- });
1475
- return {
1476
- set: {
1477
- [type2]: instructions2
1478
- }
1479
- };
1480
- }
1481
- const type = Object.keys(query.alter.drop)[0];
1482
- const itemSlug = query.alter.drop[type];
1483
- const instructions = {
1484
- with: { model: { slug }, slug: itemSlug }
1485
- };
1486
- addModelQueries(models, dependencyStatements, {
1487
- queryType: "remove",
1488
- queryModel: type,
1489
- queryInstructions: instructions
1490
- });
1491
- return {
1492
- remove: {
1493
- [type]: instructions
1494
- }
1495
- };
1496
- }
1497
- return query;
1498
- };
1499
-
1500
1448
  // src/index.ts
1501
1449
  var compileQueries = (queries, models, options) => {
1502
1450
  const modelList = addSystemModels(models).map((model) => {
@@ -1508,15 +1456,17 @@ var compileQueries = (queries, models, options) => {
1508
1456
  const dependencyStatements = [];
1509
1457
  const mainStatements = [];
1510
1458
  for (const query of queries) {
1459
+ const statementValues = options?.inlineParams ? null : [];
1511
1460
  const transformedQuery = transformMetaQuery(
1512
1461
  modelListWithPresets,
1513
1462
  dependencyStatements,
1463
+ statementValues,
1514
1464
  query
1515
1465
  );
1516
1466
  const result = compileQueryInput(
1517
1467
  transformedQuery,
1518
1468
  modelListWithPresets,
1519
- options?.inlineParams ? null : []
1469
+ statementValues
1520
1470
  );
1521
1471
  dependencyStatements.push(...result.dependencies);
1522
1472
  mainStatements.push(result.main);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ronin/compiler",
3
- "version": "0.8.2",
3
+ "version": "0.8.4",
4
4
  "type": "module",
5
5
  "description": "Compiles RONIN queries to SQL statements.",
6
6
  "publishConfig": {