@ronin/compiler 0.8.3 → 0.8.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. package/dist/index.js +188 -288
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -465,6 +465,8 @@ var SYSTEM_MODELS = [
465
465
  name: "name",
466
466
  slug: "slug"
467
467
  },
468
+ // This name mimics the `sqlite_schema` table in SQLite.
469
+ table: "ronin_schema",
468
470
  fields: [
469
471
  { slug: "name", type: "string" },
470
472
  { slug: "pluralName", type: "string" },
@@ -475,98 +477,16 @@ var SYSTEM_MODELS = [
475
477
  { slug: "identifiers", type: "group" },
476
478
  { slug: "identifiers.name", type: "string" },
477
479
  { 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 }
480
+ // Providing an empty object as a default value allows us to use `json_insert`
481
+ // without needing to fall back to an empty object in the insertion statement,
482
+ // which makes the statement shorter.
483
+ { slug: "fields", type: "json", defaultValue: "{}" },
484
+ { slug: "indexes", type: "json", defaultValue: "{}" },
485
+ { slug: "triggers", type: "json", defaultValue: "{}" },
486
+ { slug: "presets", type: "json", defaultValue: "{}" }
563
487
  ]
564
488
  }
565
- ].map((model) => addDefaultModelFields(model, true));
566
- var SYSTEM_MODEL_SLUGS = SYSTEM_MODELS.flatMap(({ slug, pluralSlug }) => [
567
- slug,
568
- pluralSlug
569
- ]);
489
+ ];
570
490
  var addSystemModels = (models) => {
571
491
  const associativeModels = models.flatMap((model) => {
572
492
  const addedModels = [];
@@ -668,9 +588,9 @@ var addDefaultModelPresets = (list, model) => {
668
588
  return model;
669
589
  };
670
590
  var mappedInstructions = {
671
- add: "to",
672
- set: "with",
673
- remove: "with"
591
+ create: "to",
592
+ alter: "with",
593
+ drop: "with"
674
594
  };
675
595
  var typesInSQLite = {
676
596
  link: "TEXT",
@@ -712,50 +632,179 @@ var getFieldStatement = (models, model, field) => {
712
632
  }
713
633
  return statement;
714
634
  };
715
- var addModelQueries = (models, dependencyStatements, queryDetails) => {
716
- const { queryType, queryModel, queryInstructions } = queryDetails;
717
- if (!["add", "set", "remove"].includes(queryType)) return;
718
- if (!SYSTEM_MODEL_SLUGS.includes(queryModel)) return;
719
- const instructionName = mappedInstructions[queryType];
635
+ var PLURAL_MODEL_ENTITIES = {
636
+ field: "fields",
637
+ index: "indexes",
638
+ trigger: "triggers",
639
+ preset: "presets"
640
+ };
641
+ var transformMetaQuery = (models, dependencyStatements, statementParams, query) => {
642
+ const { queryType } = splitQuery(query);
643
+ let action = queryType;
644
+ let entity = "model";
645
+ let queryInstructions;
646
+ if (query.create) {
647
+ const init = query.create.model;
648
+ const details = "to" in query.create ? { slug: init, ...query.create.to } : init;
649
+ queryInstructions = {
650
+ to: details
651
+ };
652
+ }
653
+ if (query.drop) {
654
+ queryInstructions = {
655
+ with: { slug: query.drop.model }
656
+ };
657
+ }
658
+ if (query.alter) {
659
+ const modelSlugTest = query.alter.model;
660
+ if ("to" in query.alter) {
661
+ queryInstructions = {
662
+ with: { slug: modelSlugTest },
663
+ to: query.alter.to
664
+ };
665
+ } else {
666
+ action = Object.keys(query.alter).filter(
667
+ (key) => key !== "model"
668
+ )[0];
669
+ const details = query.alter[action];
670
+ entity = Object.keys(details)[0];
671
+ let jsonSlug = details[entity];
672
+ let jsonValue2;
673
+ if ("create" in query.alter) {
674
+ const item = query.alter.create[entity];
675
+ jsonSlug = item.slug || `${entity}Slug`;
676
+ jsonValue2 = { slug: jsonSlug, ...item };
677
+ queryInstructions = {
678
+ to: {
679
+ model: { slug: modelSlugTest },
680
+ ...jsonValue2
681
+ }
682
+ };
683
+ }
684
+ if ("alter" in query.alter) {
685
+ jsonValue2 = query.alter.alter.to;
686
+ queryInstructions = {
687
+ with: { model: { slug: modelSlugTest }, slug: jsonSlug },
688
+ to: jsonValue2
689
+ };
690
+ }
691
+ if ("drop" in query.alter) {
692
+ queryInstructions = {
693
+ with: { model: { slug: modelSlugTest }, slug: jsonSlug }
694
+ };
695
+ }
696
+ }
697
+ }
698
+ if (!queryInstructions) return query;
699
+ const instructionName = mappedInstructions[action];
720
700
  const instructionList = queryInstructions[instructionName];
721
- const kind = getModelBySlug(SYSTEM_MODELS, queryModel).pluralSlug;
722
701
  let tableAction = "ALTER";
723
- let queryTypeReadable = null;
724
- switch (queryType) {
725
- case "add": {
726
- if (kind === "models" || kind === "indexes" || kind === "triggers") {
702
+ let actionReadable = null;
703
+ switch (action) {
704
+ case "create": {
705
+ if (entity === "model" || entity === "index" || entity === "trigger") {
727
706
  tableAction = "CREATE";
728
707
  }
729
- queryTypeReadable = "creating";
708
+ actionReadable = "creating";
730
709
  break;
731
710
  }
732
- case "set": {
733
- if (kind === "models") tableAction = "ALTER";
734
- queryTypeReadable = "updating";
711
+ case "alter": {
712
+ if (entity === "model") tableAction = "ALTER";
713
+ actionReadable = "updating";
735
714
  break;
736
715
  }
737
- case "remove": {
738
- if (kind === "models" || kind === "indexes" || kind === "triggers") {
716
+ case "drop": {
717
+ if (entity === "model" || entity === "index" || entity === "trigger") {
739
718
  tableAction = "DROP";
740
719
  }
741
- queryTypeReadable = "deleting";
720
+ actionReadable = "deleting";
742
721
  break;
743
722
  }
744
723
  }
745
724
  const slug = instructionList?.slug?.being || instructionList?.slug;
746
725
  const modelInstruction = instructionList?.model;
747
726
  const modelSlug = modelInstruction?.slug?.being || modelInstruction?.slug;
748
- const usableSlug = kind === "models" ? slug : modelSlug;
727
+ const usableSlug = entity === "model" ? slug : modelSlug;
749
728
  const tableName = convertToSnakeCase(pluralize(usableSlug));
750
- const targetModel = kind === "models" && queryType === "add" ? null : getModelBySlug(models, usableSlug);
751
- if (kind === "indexes") {
729
+ const targetModel = entity === "model" && action === "create" ? null : getModelBySlug(models, usableSlug);
730
+ const statement = `${tableAction} TABLE "${tableName}"`;
731
+ if (entity === "model") {
732
+ let queryTypeDetails;
733
+ if (action === "create") {
734
+ const modelWithFields = addDefaultModelFields(queryInstructions.to, true);
735
+ const modelWithPresets = addDefaultModelPresets(models, modelWithFields);
736
+ const { fields } = modelWithPresets;
737
+ const columns = fields.map((field) => getFieldStatement(models, modelWithPresets, field)).filter(Boolean);
738
+ dependencyStatements.push({
739
+ statement: `${statement} (${columns.join(", ")})`,
740
+ params: []
741
+ });
742
+ models.push(modelWithPresets);
743
+ queryTypeDetails = { to: modelWithPresets };
744
+ }
745
+ if (action === "alter") {
746
+ const modelWithFields = addDefaultModelFields(queryInstructions.to, false);
747
+ const modelWithPresets = addDefaultModelPresets(models, modelWithFields);
748
+ const newSlug = modelWithPresets.pluralSlug;
749
+ if (newSlug) {
750
+ const newTable = convertToSnakeCase(newSlug);
751
+ dependencyStatements.push({
752
+ statement: `${statement} RENAME TO "${newTable}"`,
753
+ params: []
754
+ });
755
+ }
756
+ Object.assign(targetModel, modelWithPresets);
757
+ queryTypeDetails = {
758
+ with: {
759
+ slug: usableSlug
760
+ },
761
+ to: modelWithPresets
762
+ };
763
+ }
764
+ if (action === "drop") {
765
+ models.splice(models.indexOf(targetModel), 1);
766
+ dependencyStatements.push({ statement, params: [] });
767
+ queryTypeDetails = {
768
+ with: { slug: usableSlug }
769
+ };
770
+ }
771
+ const queryTypeAction = action === "create" ? "add" : action === "alter" ? "set" : "remove";
772
+ return {
773
+ [queryTypeAction]: {
774
+ model: queryTypeDetails
775
+ }
776
+ };
777
+ }
778
+ if (entity === "field") {
779
+ if (action === "create") {
780
+ if (!instructionList.type) instructionList.type = "string";
781
+ dependencyStatements.push({
782
+ statement: `${statement} ADD COLUMN ${getFieldStatement(models, targetModel, instructionList)}`,
783
+ params: []
784
+ });
785
+ } else if (action === "alter") {
786
+ const newSlug = queryInstructions.to?.slug;
787
+ if (newSlug) {
788
+ dependencyStatements.push({
789
+ statement: `${statement} RENAME COLUMN "${slug}" TO "${newSlug}"`,
790
+ params: []
791
+ });
792
+ }
793
+ } else if (action === "drop") {
794
+ dependencyStatements.push({
795
+ statement: `${statement} DROP COLUMN "${slug}"`,
796
+ params: []
797
+ });
798
+ }
799
+ }
800
+ if (entity === "index") {
752
801
  const indexName = convertToSnakeCase(slug);
753
802
  const unique = instructionList?.unique;
754
803
  const filterQuery = instructionList?.filter;
755
804
  const fields = instructionList?.fields;
756
805
  const params = [];
757
806
  let statement2 = `${tableAction}${unique ? " UNIQUE" : ""} INDEX "${indexName}"`;
758
- if (queryType === "add") {
807
+ if (action === "create") {
759
808
  const model = targetModel;
760
809
  const columns = fields.map((field) => {
761
810
  let fieldSelector = "";
@@ -780,23 +829,22 @@ var addModelQueries = (models, dependencyStatements, queryDetails) => {
780
829
  }
781
830
  }
782
831
  dependencyStatements.push({ statement: statement2, params });
783
- return;
784
832
  }
785
- if (kind === "triggers") {
833
+ if (entity === "trigger") {
786
834
  const triggerName = convertToSnakeCase(slug);
787
835
  const params = [];
788
836
  let statement2 = `${tableAction} TRIGGER "${triggerName}"`;
789
- if (queryType === "add") {
837
+ if (action === "create") {
790
838
  const currentModel = targetModel;
791
- const { when, action } = instructionList;
792
- const statementParts = [`${when} ${action}`];
839
+ const { when, action: action2 } = instructionList;
840
+ const statementParts = [`${when} ${action2}`];
793
841
  const effectQueries = instructionList?.effects;
794
842
  const filterQuery = instructionList?.filter;
795
843
  const fields = instructionList?.fields;
796
844
  if (fields) {
797
- if (action !== "UPDATE") {
845
+ if (action2 !== "UPDATE") {
798
846
  throw new RoninError({
799
- message: `When ${queryTypeReadable} ${kind}, targeting specific fields requires the \`UPDATE\` action.`,
847
+ message: `When ${actionReadable} ${PLURAL_MODEL_ENTITIES[entity]}, targeting specific fields requires the \`UPDATE\` action.`,
800
848
  code: "INVALID_MODEL_VALUE",
801
849
  fields: ["action"]
802
850
  });
@@ -807,11 +855,11 @@ var addModelQueries = (models, dependencyStatements, queryDetails) => {
807
855
  statementParts.push(`OF (${fieldSelectors.join(", ")})`);
808
856
  }
809
857
  statementParts.push("ON", `"${tableName}"`);
810
- if (filterQuery || effectQueries.some((query) => findInObject(query, RONIN_MODEL_SYMBOLS.FIELD))) {
858
+ if (filterQuery || effectQueries.some((query2) => findInObject(query2, RONIN_MODEL_SYMBOLS.FIELD))) {
811
859
  statementParts.push("FOR EACH ROW");
812
860
  }
813
861
  if (filterQuery) {
814
- const tableAlias = action === "DELETE" ? RONIN_MODEL_SYMBOLS.FIELD_PARENT_OLD : RONIN_MODEL_SYMBOLS.FIELD_PARENT_NEW;
862
+ const tableAlias = action2 === "DELETE" ? RONIN_MODEL_SYMBOLS.FIELD_PARENT_OLD : RONIN_MODEL_SYMBOLS.FIELD_PARENT_NEW;
815
863
  const withStatement = handleWith(
816
864
  models,
817
865
  { ...currentModel, tableAlias },
@@ -832,57 +880,23 @@ var addModelQueries = (models, dependencyStatements, queryDetails) => {
832
880
  statement2 += ` ${statementParts.join(" ")}`;
833
881
  }
834
882
  dependencyStatements.push({ statement: statement2, params });
835
- return;
836
- }
837
- const statement = `${tableAction} TABLE "${tableName}"`;
838
- if (kind === "models") {
839
- if (queryType === "add") {
840
- const newModel = queryInstructions.to;
841
- const { fields } = newModel;
842
- const columns = fields.map((field) => getFieldStatement(models, newModel, field)).filter(Boolean);
843
- dependencyStatements.push({
844
- statement: `${statement} (${columns.join(", ")})`,
845
- params: []
846
- });
847
- models.push(newModel);
848
- } else if (queryType === "set") {
849
- const newSlug = queryInstructions.to?.pluralSlug;
850
- if (newSlug) {
851
- const newTable = convertToSnakeCase(newSlug);
852
- dependencyStatements.push({
853
- statement: `${statement} RENAME TO "${newTable}"`,
854
- params: []
855
- });
856
- }
857
- Object.assign(targetModel, queryInstructions.to);
858
- } else if (queryType === "remove") {
859
- models.splice(models.indexOf(targetModel), 1);
860
- dependencyStatements.push({ statement, params: [] });
861
- }
862
- return;
863
883
  }
864
- if (kind === "fields") {
865
- if (queryType === "add") {
866
- if (!instructionList.type) instructionList.type = "string";
867
- dependencyStatements.push({
868
- statement: `${statement} ADD COLUMN ${getFieldStatement(models, targetModel, instructionList)}`,
869
- params: []
870
- });
871
- } else if (queryType === "set") {
872
- const newSlug = queryInstructions.to?.slug;
873
- if (newSlug) {
874
- dependencyStatements.push({
875
- statement: `${statement} RENAME COLUMN "${slug}" TO "${newSlug}"`,
876
- params: []
877
- });
884
+ const pluralType = PLURAL_MODEL_ENTITIES[entity];
885
+ const jsonAction = action === "create" ? "insert" : action === "alter" ? "patch" : "remove";
886
+ const jsonValue = action === "create" ? { ...instructionList, model: void 0 } : action === "alter" ? queryInstructions.to : null;
887
+ let json = `json_${jsonAction}(${RONIN_MODEL_SYMBOLS.FIELD}${pluralType}, '$.${slug}'`;
888
+ if (jsonValue) json += `, ${prepareStatementValue(statementParams, jsonValue)}`;
889
+ json += ")";
890
+ return {
891
+ set: {
892
+ model: {
893
+ with: { slug: usableSlug },
894
+ to: {
895
+ [pluralType]: { [RONIN_MODEL_SYMBOLS.EXPRESSION]: json }
896
+ }
878
897
  }
879
- } else if (queryType === "remove") {
880
- dependencyStatements.push({
881
- statement: `${statement} DROP COLUMN "${slug}"`,
882
- params: []
883
- });
884
898
  }
885
- }
899
+ };
886
900
  };
887
901
 
888
902
  // src/instructions/before-after.ts
@@ -1381,122 +1395,6 @@ var compileQueryInput = (query, models, statementParams, options) => {
1381
1395
  };
1382
1396
  };
1383
1397
 
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
1398
  // src/index.ts
1501
1399
  var compileQueries = (queries, models, options) => {
1502
1400
  const modelList = addSystemModels(models).map((model) => {
@@ -1508,15 +1406,17 @@ var compileQueries = (queries, models, options) => {
1508
1406
  const dependencyStatements = [];
1509
1407
  const mainStatements = [];
1510
1408
  for (const query of queries) {
1409
+ const statementValues = options?.inlineParams ? null : [];
1511
1410
  const transformedQuery = transformMetaQuery(
1512
1411
  modelListWithPresets,
1513
1412
  dependencyStatements,
1413
+ statementValues,
1514
1414
  query
1515
1415
  );
1516
1416
  const result = compileQueryInput(
1517
1417
  transformedQuery,
1518
1418
  modelListWithPresets,
1519
- options?.inlineParams ? null : []
1419
+ statementValues
1520
1420
  );
1521
1421
  dependencyStatements.push(...result.dependencies);
1522
1422
  mainStatements.push(result.main);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ronin/compiler",
3
- "version": "0.8.3",
3
+ "version": "0.8.5",
4
4
  "type": "module",
5
5
  "description": "Compiles RONIN queries to SQL statements.",
6
6
  "publishConfig": {