@ronin/compiler 0.4.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
package/dist/index.js CHANGED
@@ -96,19 +96,19 @@ var splitQuery = (query) => {
96
96
  };
97
97
 
98
98
  // src/utils/statement.ts
99
- var prepareStatementValue = (statementValues, value) => {
99
+ var prepareStatementValue = (statementParams, value) => {
100
100
  if (value === null) return "NULL";
101
- if (!statementValues) return JSON.stringify(value);
101
+ if (!statementParams) return JSON.stringify(value);
102
102
  let formattedValue = value;
103
103
  if (Array.isArray(value) || isObject(value)) {
104
104
  formattedValue = JSON.stringify(value);
105
105
  } else if (typeof value === "boolean") {
106
106
  formattedValue = value ? 1 : 0;
107
107
  }
108
- const index = statementValues.push(formattedValue);
108
+ const index = statementParams.push(formattedValue);
109
109
  return `?${index}`;
110
110
  };
111
- var composeFieldValues = (schemas, schema, statementValues, instructionName, value, options) => {
111
+ var composeFieldValues = (schemas, schema, statementParams, instructionName, value, options) => {
112
112
  const { field: schemaField, fieldSelector: selector } = getFieldFromSchema(
113
113
  schema,
114
114
  options.fieldSlug,
@@ -123,8 +123,8 @@ var composeFieldValues = (schemas, schema, statementValues, instructionName, val
123
123
  conditionValue = `(${compileQueryInput(
124
124
  value[RONIN_SCHEMA_SYMBOLS.QUERY],
125
125
  schemas,
126
- statementValues
127
- ).readStatement})`;
126
+ statementParams
127
+ ).main.statement})`;
128
128
  } else if (typeof value === "string" && value.startsWith(RONIN_SCHEMA_SYMBOLS.FIELD)) {
129
129
  let targetTable = `"${options.rootTable}"`;
130
130
  let toReplace = RONIN_SCHEMA_SYMBOLS.FIELD;
@@ -140,21 +140,21 @@ var composeFieldValues = (schemas, schema, statementValues, instructionName, val
140
140
  } else if (schemaField.type === "json" && instructionName === "to") {
141
141
  conditionSelector = `"${schemaField.slug}"`;
142
142
  if (collectStatementValue) {
143
- const preparedValue = prepareStatementValue(statementValues, value);
143
+ const preparedValue = prepareStatementValue(statementParams, value);
144
144
  conditionValue = `IIF(${conditionSelector} IS NULL, ${preparedValue}, json_patch(${conditionSelector}, ${preparedValue}))`;
145
145
  }
146
146
  } else if (collectStatementValue) {
147
- conditionValue = prepareStatementValue(statementValues, value);
147
+ conditionValue = prepareStatementValue(statementParams, value);
148
148
  }
149
149
  if (options.type === "fields") return conditionSelector;
150
150
  if (options.type === "values") return conditionValue;
151
151
  return `${conditionSelector} ${WITH_CONDITIONS[options.condition || "being"](conditionValue, value)}`;
152
152
  };
153
- var composeConditions = (schemas, schema, statementValues, instructionName, value, options) => {
153
+ var composeConditions = (schemas, schema, statementParams, instructionName, value, options) => {
154
154
  const isNested = isObject(value) && Object.keys(value).length > 0;
155
155
  if (isNested && Object.keys(value).every((key) => key in WITH_CONDITIONS)) {
156
156
  const conditions = Object.entries(value).map(
157
- ([conditionType, checkValue]) => composeConditions(schemas, schema, statementValues, instructionName, checkValue, {
157
+ ([conditionType, checkValue]) => composeConditions(schemas, schema, statementParams, instructionName, checkValue, {
158
158
  ...options,
159
159
  condition: conditionType
160
160
  })
@@ -175,7 +175,7 @@ var composeConditions = (schemas, schema, statementValues, instructionName, valu
175
175
  return composeFieldValues(
176
176
  schemas,
177
177
  schema,
178
- statementValues,
178
+ statementParams,
179
179
  instructionName,
180
180
  value,
181
181
  { ...options, fieldSlug: options.fieldSlug }
@@ -204,7 +204,7 @@ var composeConditions = (schemas, schema, statementValues, instructionName, valu
204
204
  return composeConditions(
205
205
  schemas,
206
206
  schema,
207
- statementValues,
207
+ statementParams,
208
208
  instructionName,
209
209
  recordTarget,
210
210
  options
@@ -214,7 +214,7 @@ var composeConditions = (schemas, schema, statementValues, instructionName, valu
214
214
  if (isNested) {
215
215
  const conditions = Object.entries(value).map(([field, value2]) => {
216
216
  const nestedFieldSlug = options.fieldSlug ? `${options.fieldSlug}.${field}` : field;
217
- return composeConditions(schemas, schema, statementValues, instructionName, value2, {
217
+ return composeConditions(schemas, schema, statementParams, instructionName, value2, {
218
218
  ...options,
219
219
  fieldSlug: nestedFieldSlug
220
220
  });
@@ -228,7 +228,7 @@ var composeConditions = (schemas, schema, statementValues, instructionName, valu
228
228
  (filter) => composeConditions(
229
229
  schemas,
230
230
  schema,
231
- statementValues,
231
+ statementParams,
232
232
  instructionName,
233
233
  filter,
234
234
  options
@@ -287,11 +287,11 @@ var WITH_CONDITIONS = {
287
287
  lessThan: (value) => `< ${value}`,
288
288
  lessOrEqual: (value) => `<= ${value}`
289
289
  };
290
- var handleWith = (schemas, schema, statementValues, instruction, rootTable) => {
290
+ var handleWith = (schemas, schema, statementParams, instruction, rootTable) => {
291
291
  const subStatement = composeConditions(
292
292
  schemas,
293
293
  schema,
294
- statementValues,
294
+ statementParams,
295
295
  "with",
296
296
  instruction,
297
297
  { rootTable }
@@ -317,7 +317,7 @@ var getTableForSchema = (schema) => {
317
317
  return convertToSnakeCase(schema.pluralSlug);
318
318
  };
319
319
  var composeMetaSchemaSlug = (suffix) => convertToCamelCase(`ronin_${suffix}`);
320
- var composeAssociationSchemaSlug = (schema, field) => composeMetaSchemaSlug(`${schema.pluralSlug}_${field.slug}`);
320
+ var composeAssociationSchemaSlug = (schema, field) => composeMetaSchemaSlug(`${schema.slug}_${field.slug}`);
321
321
  var getFieldSelector = (field, fieldPath, rootTable) => {
322
322
  const symbol = rootTable?.startsWith(RONIN_SCHEMA_SYMBOLS.FIELD) ? `${rootTable.replace(RONIN_SCHEMA_SYMBOLS.FIELD, "").slice(0, -1)}.` : "";
323
323
  const tablePrefix = symbol || (rootTable ? `"${rootTable}".` : "");
@@ -352,6 +352,53 @@ var getFieldFromSchema = (schema, fieldPath, instructionName, rootTable) => {
352
352
  const fieldSelector = getFieldSelector(schemaField, fieldPath, rootTable);
353
353
  return { field: schemaField, fieldSelector };
354
354
  };
355
+ var slugToName = (slug) => {
356
+ const name = slug.replace(/([a-z])([A-Z])/g, "$1 $2");
357
+ return title(name);
358
+ };
359
+ var VOWELS = ["a", "e", "i", "o", "u"];
360
+ var pluralize = (word) => {
361
+ const lastLetter = word.slice(-1).toLowerCase();
362
+ const secondLastLetter = word.slice(-2, -1).toLowerCase();
363
+ if (lastLetter === "y" && !VOWELS.includes(secondLastLetter)) {
364
+ return `${word.slice(0, -1)}ies`;
365
+ }
366
+ if (lastLetter === "s" || word.slice(-2).toLowerCase() === "ch" || word.slice(-2).toLowerCase() === "sh" || word.slice(-2).toLowerCase() === "ex") {
367
+ return `${word}es`;
368
+ }
369
+ return `${word}s`;
370
+ };
371
+ var schemaSettings = [
372
+ ["pluralSlug", "slug", pluralize],
373
+ ["name", "slug", slugToName],
374
+ ["pluralName", "pluralSlug", slugToName],
375
+ ["idPrefix", "slug", (slug) => slug.slice(0, 3)]
376
+ ];
377
+ var addDefaultSchemaFields = (schema, isNew) => {
378
+ const copiedSchema = { ...schema };
379
+ for (const [setting, base, generator] of schemaSettings) {
380
+ if (copiedSchema[setting] || !copiedSchema[base]) continue;
381
+ copiedSchema[setting] = generator(copiedSchema[base]);
382
+ }
383
+ const newFields = copiedSchema.fields || [];
384
+ if (isNew || newFields.length > 0) {
385
+ if (!copiedSchema.identifiers) copiedSchema.identifiers = {};
386
+ if (!copiedSchema.identifiers.name) {
387
+ const suitableField = newFields.find(
388
+ (field) => field.type === "string" && field.required === true && ["name"].includes(field.slug)
389
+ );
390
+ copiedSchema.identifiers.name = suitableField?.slug || "id";
391
+ }
392
+ if (!copiedSchema.identifiers.slug) {
393
+ const suitableField = newFields.find(
394
+ (field) => field.type === "string" && field.unique === true && field.required === true && ["slug", "handle"].includes(field.slug)
395
+ );
396
+ copiedSchema.identifiers.slug = suitableField?.slug || "id";
397
+ }
398
+ copiedSchema.fields = [...SYSTEM_FIELDS, ...newFields];
399
+ }
400
+ return copiedSchema;
401
+ };
355
402
  var SYSTEM_FIELDS = [
356
403
  {
357
404
  name: "ID",
@@ -392,16 +439,12 @@ var SYSTEM_FIELDS = [
392
439
  ];
393
440
  var SYSTEM_SCHEMAS = [
394
441
  {
395
- name: "Schema",
396
- pluralName: "Schemas",
397
442
  slug: "schema",
398
- pluralSlug: "schemas",
399
443
  identifiers: {
400
444
  name: "name",
401
445
  slug: "slug"
402
446
  },
403
447
  fields: [
404
- ...SYSTEM_FIELDS,
405
448
  { slug: "name", type: "string" },
406
449
  { slug: "pluralName", type: "string" },
407
450
  { slug: "slug", type: "string" },
@@ -412,20 +455,18 @@ var SYSTEM_SCHEMAS = [
412
455
  { slug: "identifiers.slug", type: "string" },
413
456
  { slug: "fields", type: "json" },
414
457
  { slug: "indexes", type: "json" },
415
- { slug: "triggers", type: "json" }
458
+ { slug: "triggers", type: "json" },
459
+ { slug: "including", type: "json" },
460
+ { slug: "for", type: "json" }
416
461
  ]
417
462
  },
418
463
  {
419
- name: "Field",
420
- pluralName: "Fields",
421
464
  slug: "field",
422
- pluralSlug: "fields",
423
465
  identifiers: {
424
466
  name: "name",
425
467
  slug: "slug"
426
468
  },
427
469
  fields: [
428
- ...SYSTEM_FIELDS,
429
470
  { slug: "name", type: "string" },
430
471
  { slug: "slug", type: "string", required: true },
431
472
  { slug: "type", type: "string", required: true },
@@ -448,16 +489,12 @@ var SYSTEM_SCHEMAS = [
448
489
  ]
449
490
  },
450
491
  {
451
- name: "Index",
452
- pluralName: "Indexes",
453
492
  slug: "index",
454
- pluralSlug: "indexes",
455
493
  identifiers: {
456
494
  name: "slug",
457
495
  slug: "slug"
458
496
  },
459
497
  fields: [
460
- ...SYSTEM_FIELDS,
461
498
  { slug: "slug", type: "string", required: true },
462
499
  {
463
500
  slug: "schema",
@@ -470,16 +507,12 @@ var SYSTEM_SCHEMAS = [
470
507
  ]
471
508
  },
472
509
  {
473
- name: "Trigger",
474
- pluralName: "Triggers",
475
510
  slug: "trigger",
476
- pluralSlug: "triggers",
477
511
  identifiers: {
478
512
  name: "slug",
479
513
  slug: "slug"
480
514
  },
481
515
  fields: [
482
- ...SYSTEM_FIELDS,
483
516
  { slug: "slug", type: "string", required: true },
484
517
  { slug: "schema", type: "reference", target: { slug: "schema" }, required: true },
485
518
  { slug: "cause", type: "string", required: true },
@@ -487,85 +520,89 @@ var SYSTEM_SCHEMAS = [
487
520
  { slug: "effects", type: "json", required: true }
488
521
  ]
489
522
  }
490
- ];
523
+ ].map((schema) => addDefaultSchemaFields(schema, true));
491
524
  var SYSTEM_SCHEMA_SLUGS = SYSTEM_SCHEMAS.flatMap(({ slug, pluralSlug }) => [
492
525
  slug,
493
526
  pluralSlug
494
527
  ]);
495
- var prepareSchema = (schema) => {
496
- const copiedSchema = { ...schema };
497
- if (!copiedSchema.pluralSlug) copiedSchema.pluralSlug = pluralize(copiedSchema.slug);
498
- if (!copiedSchema.name) copiedSchema.name = slugToName(copiedSchema.slug);
499
- if (!copiedSchema.pluralName)
500
- copiedSchema.pluralName = slugToName(copiedSchema.pluralSlug);
501
- if (!copiedSchema.idPrefix) copiedSchema.idPrefix = copiedSchema.slug.slice(0, 3);
502
- if (!copiedSchema.identifiers) copiedSchema.identifiers = {};
503
- if (!copiedSchema.identifiers.name) copiedSchema.identifiers.name = "id";
504
- if (!copiedSchema.identifiers.slug) copiedSchema.identifiers.slug = "id";
505
- return copiedSchema;
506
- };
507
528
  var addSystemSchemas = (schemas) => {
508
- const list = [...SYSTEM_SCHEMAS, ...schemas].map(prepareSchema);
509
- for (const schema of list) {
510
- const defaultIncluding = {};
529
+ const associativeSchemas = schemas.flatMap((schema) => {
530
+ const addedSchemas = [];
511
531
  for (const field of schema.fields || []) {
512
532
  if (field.type === "reference" && !field.slug.startsWith("ronin.")) {
513
- const relatedSchema = getSchemaBySlug(list, field.target.slug);
533
+ const relatedSchema = getSchemaBySlug(schemas, field.target.slug);
514
534
  let fieldSlug = relatedSchema.slug;
515
535
  if (field.kind === "many") {
516
536
  fieldSlug = composeAssociationSchemaSlug(schema, field);
517
- list.push({
537
+ addedSchemas.push({
518
538
  pluralSlug: fieldSlug,
519
539
  slug: fieldSlug,
520
- identifiers: {
521
- name: "id",
522
- slug: "id"
523
- },
524
540
  fields: [
525
541
  {
526
542
  slug: "source",
527
543
  type: "reference",
528
- target: schema
544
+ target: { slug: schema.slug }
529
545
  },
530
546
  {
531
547
  slug: "target",
532
548
  type: "reference",
533
- target: relatedSchema
549
+ target: { slug: relatedSchema.slug }
534
550
  }
535
551
  ]
536
552
  });
537
553
  }
538
- defaultIncluding[field.slug] = {
539
- get: {
540
- [fieldSlug]: {
541
- with: {
542
- // Compare the `id` field of the related schema to the reference field on
543
- // the root schema (`field.slug`).
544
- id: `${RONIN_SCHEMA_SYMBOLS.FIELD}${field.slug}`
545
- }
554
+ }
555
+ }
556
+ return addedSchemas;
557
+ });
558
+ return [...SYSTEM_SCHEMAS, ...associativeSchemas, ...schemas];
559
+ };
560
+ var addDefaultSchemaShortcuts = (list, schema) => {
561
+ const defaultIncluding = {};
562
+ for (const field of schema.fields || []) {
563
+ if (field.type === "reference" && !field.slug.startsWith("ronin.")) {
564
+ const relatedSchema = getSchemaBySlug(list, field.target.slug);
565
+ let fieldSlug = relatedSchema.slug;
566
+ if (field.kind === "many") {
567
+ fieldSlug = composeAssociationSchemaSlug(schema, field);
568
+ }
569
+ defaultIncluding[field.slug] = {
570
+ get: {
571
+ [fieldSlug]: {
572
+ with: {
573
+ // Compare the `id` field of the related schema to the reference field on
574
+ // the root schema (`field.slug`).
575
+ id: `${RONIN_SCHEMA_SYMBOLS.FIELD}${field.slug}`
546
576
  }
547
577
  }
548
- };
549
- const relatedSchemaToModify = getSchemaBySlug(list, field.target.slug);
550
- if (!relatedSchemaToModify) throw new Error("Missing related schema");
551
- relatedSchemaToModify.including = {
552
- [schema.pluralSlug]: {
553
- get: {
554
- [schema.pluralSlug]: {
555
- with: {
556
- [field.slug]: `${RONIN_SCHEMA_SYMBOLS.FIELD}id`
557
- }
558
- }
559
- }
560
- },
561
- ...relatedSchemaToModify.including
562
- };
563
- }
578
+ }
579
+ };
564
580
  }
565
- schema.fields = [...SYSTEM_FIELDS, ...schema.fields || []];
581
+ }
582
+ const childSchemas = list.map((subSchema) => {
583
+ const field = subSchema.fields?.find((field2) => {
584
+ return field2.type === "reference" && field2.target.slug === schema.slug;
585
+ });
586
+ if (!field) return null;
587
+ return { schema: subSchema, field };
588
+ }).filter((match) => match !== null);
589
+ for (const childMatch of childSchemas) {
590
+ const { schema: childSchema, field: childField } = childMatch;
591
+ const pluralSlug = childSchema.pluralSlug;
592
+ defaultIncluding[pluralSlug] = {
593
+ get: {
594
+ [pluralSlug]: {
595
+ with: {
596
+ [childField.slug]: `${RONIN_SCHEMA_SYMBOLS.FIELD}id`
597
+ }
598
+ }
599
+ }
600
+ };
601
+ }
602
+ if (Object.keys(defaultIncluding).length > 0) {
566
603
  schema.including = { ...defaultIncluding, ...schema.including };
567
604
  }
568
- return list;
605
+ return schema;
569
606
  };
570
607
  var mappedInstructions = {
571
608
  create: "to",
@@ -601,7 +638,7 @@ var getFieldStatement = (field) => {
601
638
  }
602
639
  return statement;
603
640
  };
604
- var addSchemaQueries = (schemas, statementValues, queryDetails, writeStatements) => {
641
+ var addSchemaQueries = (schemas, queryDetails, dependencyStatements) => {
605
642
  const {
606
643
  queryType,
607
644
  querySchema,
@@ -653,30 +690,33 @@ var addSchemaQueries = (schemas, statementValues, queryDetails, writeStatements)
653
690
  fields: ["schema.slug"]
654
691
  });
655
692
  }
656
- const tableName = convertToSnakeCase(pluralize(kind === "schemas" ? slug : schemaSlug));
693
+ const usableSlug = kind === "schemas" ? slug : schemaSlug;
694
+ const tableName = convertToSnakeCase(pluralize(usableSlug));
695
+ const targetSchema = kind === "schemas" && queryType === "create" ? null : getSchemaBySlug(schemas, usableSlug);
657
696
  if (kind === "indexes") {
658
697
  const indexName = convertToSnakeCase(slug);
659
698
  const unique = instructionList?.unique;
660
699
  const filterQuery = instructionList?.filter;
700
+ const params = [];
661
701
  let statement2 = `${tableAction}${unique ? " UNIQUE" : ""} INDEX "${indexName}"`;
662
702
  if (queryType === "create") {
663
703
  statement2 += ` ON "${tableName}"`;
664
704
  if (filterQuery) {
665
- const targetSchema = getSchemaBySlug(schemas, schemaSlug);
666
705
  const withStatement = handleWith(
667
706
  schemas,
668
707
  targetSchema,
669
- statementValues,
708
+ params,
670
709
  filterQuery
671
710
  );
672
711
  statement2 += ` WHERE (${withStatement})`;
673
712
  }
674
713
  }
675
- writeStatements.push(statement2);
714
+ dependencyStatements.push({ statement: statement2, params });
676
715
  return queryInstructions;
677
716
  }
678
717
  if (kind === "triggers") {
679
718
  const triggerName = convertToSnakeCase(slug);
719
+ const params = [];
680
720
  let statement2 = `${tableAction} TRIGGER "${triggerName}"`;
681
721
  if (queryType === "create") {
682
722
  const cause = slugToName(instructionList?.cause).toUpperCase();
@@ -687,48 +727,61 @@ var addSchemaQueries = (schemas, statementValues, queryDetails, writeStatements)
687
727
  statementParts.push("FOR EACH ROW");
688
728
  }
689
729
  if (filterQuery) {
690
- const targetSchema = getSchemaBySlug(schemas, schemaSlug);
691
730
  const tablePlaceholder = cause.endsWith("DELETE") ? RONIN_SCHEMA_SYMBOLS.FIELD_OLD : RONIN_SCHEMA_SYMBOLS.FIELD_NEW;
692
731
  const withStatement = handleWith(
693
732
  schemas,
694
733
  targetSchema,
695
- statementValues,
734
+ params,
696
735
  filterQuery,
697
736
  tablePlaceholder
698
737
  );
699
738
  statementParts.push("WHEN", `(${withStatement})`);
700
739
  }
701
740
  const effectStatements = effectQueries.map((effectQuery) => {
702
- return compileQueryInput(effectQuery, schemas, statementValues, {
703
- disableReturning: true
704
- }).readStatement;
741
+ return compileQueryInput(effectQuery, schemas, params, {
742
+ returning: false
743
+ }).main.statement;
705
744
  });
706
745
  if (effectStatements.length > 1) statementParts.push("BEGIN");
707
746
  statementParts.push(effectStatements.join("; "));
708
747
  if (effectStatements.length > 1) statementParts.push("END");
709
748
  statement2 += ` ${statementParts.join(" ")}`;
710
749
  }
711
- writeStatements.push(statement2);
750
+ dependencyStatements.push({ statement: statement2, params });
712
751
  return queryInstructions;
713
752
  }
714
- let statement = `${tableAction} TABLE "${tableName}"`;
753
+ const statement = `${tableAction} TABLE "${tableName}"`;
715
754
  if (kind === "schemas") {
716
- const providedFields = instructionList?.fields || [];
717
- const fields = [...SYSTEM_FIELDS, ...providedFields];
718
755
  if (queryType === "create" || queryType === "set") {
719
- queryInstructions.to = prepareSchema(queryInstructions.to);
756
+ const schemaWithFields = addDefaultSchemaFields(
757
+ queryInstructions.to,
758
+ queryType === "create"
759
+ );
760
+ const schemaWithShortcuts = addDefaultSchemaShortcuts(schemas, schemaWithFields);
761
+ queryInstructions.to = schemaWithShortcuts;
720
762
  }
721
763
  if (queryType === "create") {
764
+ const { fields } = queryInstructions.to;
722
765
  const columns = fields.map(getFieldStatement).filter(Boolean);
723
- statement += ` (${columns.join(", ")})`;
766
+ dependencyStatements.push({
767
+ statement: `${statement} (${columns.join(", ")})`,
768
+ params: []
769
+ });
770
+ schemas.push(queryInstructions.to);
724
771
  } else if (queryType === "set") {
725
772
  const newSlug = queryInstructions.to?.pluralSlug;
726
773
  if (newSlug) {
727
774
  const newTable = convertToSnakeCase(newSlug);
728
- statement += ` RENAME TO "${newTable}"`;
775
+ dependencyStatements.push({
776
+ statement: `${statement} RENAME TO "${newTable}"`,
777
+ params: []
778
+ });
729
779
  }
780
+ Object.assign(targetSchema, queryInstructions.to);
781
+ } else if (queryType === "drop") {
782
+ schemas.splice(schemas.indexOf(targetSchema), 1);
783
+ dependencyStatements.push({ statement, params: [] });
730
784
  }
731
- writeStatements.push(statement);
732
785
  return queryInstructions;
733
786
  }
734
787
  if (kind === "fields") {
@@ -740,52 +793,51 @@ var addSchemaQueries = (schemas, statementValues, queryDetails, writeStatements)
740
793
  fields: ["type"]
741
794
  });
742
795
  }
743
- statement += ` ADD COLUMN ${getFieldStatement(instructionList)}`;
796
+ dependencyStatements.push({
797
+ statement: `${statement} ADD COLUMN ${getFieldStatement(instructionList)}`,
798
+ params: []
799
+ });
744
800
  } else if (queryType === "set") {
745
801
  const newSlug = queryInstructions.to?.slug;
746
802
  if (newSlug) {
747
- statement += ` RENAME COLUMN "${slug}" TO "${newSlug}"`;
803
+ dependencyStatements.push({
804
+ statement: `${statement} RENAME COLUMN "${slug}" TO "${newSlug}"`,
805
+ params: []
806
+ });
748
807
  }
749
808
  } else if (queryType === "drop") {
750
- statement += ` DROP COLUMN "${slug}"`;
809
+ dependencyStatements.push({
810
+ statement: `${statement} DROP COLUMN "${slug}"`,
811
+ params: []
812
+ });
751
813
  }
752
- writeStatements.push(statement);
753
814
  }
754
815
  return queryInstructions;
755
816
  };
756
- var slugToName = (slug) => {
757
- const name = slug.replace(/([a-z])([A-Z])/g, "$1 $2");
758
- return title(name);
759
- };
760
- var VOWELS = ["a", "e", "i", "o", "u"];
761
- var pluralize = (word) => {
762
- const lastLetter = word.slice(-1).toLowerCase();
763
- const secondLastLetter = word.slice(-2, -1).toLowerCase();
764
- if (lastLetter === "y" && !VOWELS.includes(secondLastLetter)) {
765
- return `${word.slice(0, -1)}ies`;
766
- }
767
- if (lastLetter === "s" || word.slice(-2).toLowerCase() === "ch" || word.slice(-2).toLowerCase() === "sh" || word.slice(-2).toLowerCase() === "ex") {
768
- return `${word}es`;
769
- }
770
- return `${word}s`;
771
- };
772
817
 
773
818
  // src/instructions/before-after.ts
774
819
  var CURSOR_SEPARATOR = ",";
775
820
  var CURSOR_NULL_PLACEHOLDER = "RONIN_NULL";
776
- var handleBeforeOrAfter = (schema, statementValues, instructions, rootTable) => {
821
+ var handleBeforeOrAfter = (schema, statementParams, instructions, rootTable) => {
777
822
  if (!(instructions.before || instructions.after)) {
778
823
  throw new RoninError({
779
824
  message: "The `before` or `after` instruction must not be empty.",
780
- code: "MISSING_INSTRUCTION",
781
- queries: null
825
+ code: "MISSING_INSTRUCTION"
782
826
  });
783
827
  }
784
828
  if (instructions.before && instructions.after) {
785
829
  throw new RoninError({
786
830
  message: "The `before` and `after` instructions cannot co-exist. Choose one.",
787
- code: "MUTUALLY_EXCLUSIVE_INSTRUCTIONS",
788
- queries: null
831
+ code: "MUTUALLY_EXCLUSIVE_INSTRUCTIONS"
832
+ });
833
+ }
834
+ if (!instructions.limitedTo) {
835
+ let message = "When providing a pagination cursor in the `before` or `after`";
836
+ message += " instruction, a `limitedTo` instruction must be provided as well, to";
837
+ message += " define the page size.";
838
+ throw new RoninError({
839
+ message,
840
+ code: "MISSING_INSTRUCTION"
789
841
  });
790
842
  }
791
843
  const { ascending = [], descending = [] } = instructions.orderedBy || {};
@@ -799,15 +851,15 @@ var handleBeforeOrAfter = (schema, statementValues, instructions, rootTable) =>
799
851
  }
800
852
  const { field } = getFieldFromSchema(schema, key, "orderedBy");
801
853
  if (field.type === "boolean") {
802
- return prepareStatementValue(statementValues, value === "true");
854
+ return prepareStatementValue(statementParams, value === "true");
803
855
  }
804
856
  if (field.type === "number") {
805
- return prepareStatementValue(statementValues, Number.parseInt(value));
857
+ return prepareStatementValue(statementParams, Number.parseInt(value));
806
858
  }
807
859
  if (field.type === "date") {
808
860
  return `'${new Date(Number.parseInt(value)).toJSON()}'`;
809
861
  }
810
- return prepareStatementValue(statementValues, value);
862
+ return prepareStatementValue(statementParams, value);
811
863
  });
812
864
  const compareOperators = [
813
865
  // Reverse the comparison operators if we're querying for records before.
@@ -850,7 +902,7 @@ var handleBeforeOrAfter = (schema, statementValues, instructions, rootTable) =>
850
902
  };
851
903
 
852
904
  // src/instructions/for.ts
853
- var handleFor = (schemas, schema, statementValues, instruction, rootTable) => {
905
+ var handleFor = (schemas, schema, statementParams, instruction, rootTable) => {
854
906
  let statement = "";
855
907
  if (!instruction) return statement;
856
908
  for (const shortcut in instruction) {
@@ -871,7 +923,7 @@ var handleFor = (schemas, schema, statementValues, instruction, rootTable) => {
871
923
  const subStatement = composeConditions(
872
924
  schemas,
873
925
  schema,
874
- statementValues,
926
+ statementParams,
875
927
  "for",
876
928
  replacedForFilter,
877
929
  { rootTable }
@@ -882,7 +934,7 @@ var handleFor = (schemas, schema, statementValues, instruction, rootTable) => {
882
934
  };
883
935
 
884
936
  // src/instructions/including.ts
885
- var handleIncluding = (schemas, statementValues, schema, instruction, rootTable) => {
937
+ var handleIncluding = (schemas, statementParams, schema, instruction, rootTable) => {
886
938
  let statement = "";
887
939
  let rootTableSubQuery;
888
940
  let rootTableName = rootTable;
@@ -916,9 +968,9 @@ var handleIncluding = (schemas, statementValues, schema, instruction, rootTable)
916
968
  }
917
969
  },
918
970
  schemas,
919
- statementValues
971
+ statementParams
920
972
  );
921
- relatedTableSelector = `(${subSelect.readStatement})`;
973
+ relatedTableSelector = `(${subSelect.main.statement})`;
922
974
  }
923
975
  statement += `${joinType} JOIN ${relatedTableSelector} as ${tableAlias}`;
924
976
  if (joinType === "LEFT") {
@@ -929,7 +981,7 @@ var handleIncluding = (schemas, statementValues, schema, instruction, rootTable)
929
981
  const subStatement = composeConditions(
930
982
  schemas,
931
983
  relatedSchema,
932
- statementValues,
984
+ statementParams,
933
985
  "including",
934
986
  queryInstructions?.with,
935
987
  {
@@ -945,9 +997,10 @@ var handleIncluding = (schemas, statementValues, schema, instruction, rootTable)
945
997
 
946
998
  // src/instructions/limited-to.ts
947
999
  var handleLimitedTo = (single, instruction) => {
948
- const pageSize = instruction || 100;
949
- const finalPageSize = pageSize + 1;
950
- return `LIMIT ${single ? "1" : finalPageSize} `;
1000
+ let amount;
1001
+ if (instruction) amount = instruction + 1;
1002
+ if (single) amount = 1;
1003
+ return `LIMIT ${amount} `;
951
1004
  };
952
1005
 
953
1006
  // src/instructions/ordered-by.ts
@@ -983,7 +1036,7 @@ var handleOrderedBy = (schema, instruction, rootTable) => {
983
1036
  };
984
1037
 
985
1038
  // src/instructions/selecting.ts
986
- var handleSelecting = (schema, statementValues, instructions) => {
1039
+ var handleSelecting = (schema, statementParams, instructions) => {
987
1040
  let statement = instructions.selecting ? instructions.selecting.map((slug) => {
988
1041
  return getFieldFromSchema(schema, slug, "selecting").fieldSelector;
989
1042
  }).join(", ") : "*";
@@ -994,14 +1047,14 @@ var handleSelecting = (schema, statementValues, instructions) => {
994
1047
  ).filter(([_, value]) => {
995
1048
  return !(isObject(value) && Object.hasOwn(value, RONIN_SCHEMA_SYMBOLS.QUERY));
996
1049
  }).map(([key, value]) => {
997
- return `${prepareStatementValue(statementValues, value)} as "${key}"`;
1050
+ return `${prepareStatementValue(statementParams, value)} as "${key}"`;
998
1051
  }).join(", ");
999
1052
  }
1000
1053
  return statement;
1001
1054
  };
1002
1055
 
1003
1056
  // src/instructions/to.ts
1004
- var handleTo = (schemas, schema, statementValues, queryType, writeStatements, instructions, rootTable) => {
1057
+ var handleTo = (schemas, schema, statementParams, queryType, dependencyStatements, instructions, rootTable) => {
1005
1058
  const currentTime = (/* @__PURE__ */ new Date()).toISOString();
1006
1059
  const { with: withInstruction, to: toInstruction } = instructions;
1007
1060
  const defaultFields = {};
@@ -1043,7 +1096,7 @@ var handleTo = (schemas, schema, statementValues, queryType, writeStatements, in
1043
1096
  ...subQueryInstructions.including
1044
1097
  };
1045
1098
  }
1046
- return compileQueryInput(subQuery, schemas, statementValues).readStatement;
1099
+ return compileQueryInput(subQuery, schemas, statementParams).main.statement;
1047
1100
  }
1048
1101
  Object.assign(toInstruction, defaultFields);
1049
1102
  for (const fieldSlug in toInstruction) {
@@ -1059,29 +1112,28 @@ var handleTo = (schemas, schema, statementValues, queryType, writeStatements, in
1059
1112
  const source = queryType === "create" ? { id: toInstruction.id } : withInstruction;
1060
1113
  const recordDetails = { source };
1061
1114
  if (value) recordDetails.target = value;
1062
- const { readStatement } = compileQueryInput(
1115
+ return compileQueryInput(
1063
1116
  {
1064
1117
  [subQueryType]: {
1065
1118
  [associativeSchemaSlug]: subQueryType === "create" ? { to: recordDetails } : { with: recordDetails }
1066
1119
  }
1067
1120
  },
1068
1121
  schemas,
1069
- statementValues,
1070
- { disableReturning: true }
1071
- );
1072
- return readStatement;
1122
+ [],
1123
+ { returning: false }
1124
+ ).main;
1073
1125
  };
1074
1126
  if (Array.isArray(fieldValue)) {
1075
- writeStatements.push(composeStatement("drop"));
1127
+ dependencyStatements.push(composeStatement("drop"));
1076
1128
  for (const record of fieldValue) {
1077
- writeStatements.push(composeStatement("create", record));
1129
+ dependencyStatements.push(composeStatement("create", record));
1078
1130
  }
1079
1131
  } else if (isObject(fieldValue)) {
1080
1132
  for (const recordToAdd of fieldValue.containing || []) {
1081
- writeStatements.push(composeStatement("create", recordToAdd));
1133
+ dependencyStatements.push(composeStatement("create", recordToAdd));
1082
1134
  }
1083
1135
  for (const recordToRemove of fieldValue.notContaining || []) {
1084
- writeStatements.push(composeStatement("drop", recordToRemove));
1136
+ dependencyStatements.push(composeStatement("drop", recordToRemove));
1085
1137
  }
1086
1138
  }
1087
1139
  }
@@ -1089,7 +1141,7 @@ var handleTo = (schemas, schema, statementValues, queryType, writeStatements, in
1089
1141
  let statement = composeConditions(
1090
1142
  schemas,
1091
1143
  schema,
1092
- statementValues,
1144
+ statementParams,
1093
1145
  "to",
1094
1146
  toInstruction,
1095
1147
  {
@@ -1101,7 +1153,7 @@ var handleTo = (schemas, schema, statementValues, queryType, writeStatements, in
1101
1153
  const deepStatement = composeConditions(
1102
1154
  schemas,
1103
1155
  schema,
1104
- statementValues,
1156
+ statementParams,
1105
1157
  "to",
1106
1158
  toInstruction,
1107
1159
  {
@@ -1117,22 +1169,21 @@ var handleTo = (schemas, schema, statementValues, queryType, writeStatements, in
1117
1169
  };
1118
1170
 
1119
1171
  // src/utils/index.ts
1120
- var compileQueryInput = (query, defaultSchemas, statementValues, options) => {
1172
+ var compileQueryInput = (query, schemas, statementParams, options) => {
1121
1173
  const parsedQuery = splitQuery(query);
1122
1174
  const { queryType, querySchema, queryInstructions } = parsedQuery;
1123
- const schemas = addSystemSchemas(defaultSchemas);
1124
1175
  const schema = getSchemaBySlug(schemas, querySchema);
1125
1176
  const single = querySchema !== schema.pluralSlug;
1126
1177
  let instructions = formatIdentifiers(schema, queryInstructions);
1127
1178
  let table = getTableForSchema(schema);
1128
- const writeStatements = [];
1179
+ const dependencyStatements = [];
1180
+ const returning = options?.returning ?? true;
1129
1181
  instructions = addSchemaQueries(
1130
1182
  schemas,
1131
- statementValues,
1132
1183
  { queryType, querySchema, queryInstructions: instructions },
1133
- writeStatements
1184
+ dependencyStatements
1134
1185
  );
1135
- const columns = handleSelecting(schema, statementValues, {
1186
+ const columns = handleSelecting(schema, statementParams, {
1136
1187
  selecting: instructions?.selecting,
1137
1188
  including: instructions?.including
1138
1189
  });
@@ -1161,7 +1212,7 @@ var compileQueryInput = (query, defaultSchemas, statementValues, options) => {
1161
1212
  statement: including,
1162
1213
  rootTableSubQuery,
1163
1214
  rootTableName
1164
- } = handleIncluding(schemas, statementValues, schema, instructions?.including, table);
1215
+ } = handleIncluding(schemas, statementParams, schema, instructions?.including, table);
1165
1216
  if (rootTableSubQuery && rootTableName) {
1166
1217
  table = rootTableName;
1167
1218
  statement += `(${rootTableSubQuery}) as ${rootTableName} `;
@@ -1184,9 +1235,9 @@ var compileQueryInput = (query, defaultSchemas, statementValues, options) => {
1184
1235
  const toStatement = handleTo(
1185
1236
  schemas,
1186
1237
  schema,
1187
- statementValues,
1238
+ statementParams,
1188
1239
  queryType,
1189
- writeStatements,
1240
+ dependencyStatements,
1190
1241
  { with: instructions.with, to: instructions.to },
1191
1242
  isJoining ? table : void 0
1192
1243
  );
@@ -1197,7 +1248,7 @@ var compileQueryInput = (query, defaultSchemas, statementValues, options) => {
1197
1248
  const withStatement = handleWith(
1198
1249
  schemas,
1199
1250
  schema,
1200
- statementValues,
1251
+ statementParams,
1201
1252
  instructions?.with,
1202
1253
  isJoining ? table : void 0
1203
1254
  );
@@ -1207,13 +1258,13 @@ var compileQueryInput = (query, defaultSchemas, statementValues, options) => {
1207
1258
  const forStatement = handleFor(
1208
1259
  schemas,
1209
1260
  schema,
1210
- statementValues,
1261
+ statementParams,
1211
1262
  instructions?.for,
1212
1263
  isJoining ? table : void 0
1213
1264
  );
1214
1265
  if (forStatement.length > 0) conditions.push(forStatement);
1215
1266
  }
1216
- if ((queryType === "get" || queryType === "count") && !single) {
1267
+ if ((queryType === "get" || queryType === "count") && !single && instructions?.limitedTo) {
1217
1268
  instructions = instructions || {};
1218
1269
  instructions.orderedBy = instructions.orderedBy || {};
1219
1270
  instructions.orderedBy.ascending = instructions.orderedBy.ascending || [];
@@ -1235,12 +1286,13 @@ var compileQueryInput = (query, defaultSchemas, statementValues, options) => {
1235
1286
  }
1236
1287
  const beforeAndAfterStatement = handleBeforeOrAfter(
1237
1288
  schema,
1238
- statementValues,
1289
+ statementParams,
1239
1290
  {
1240
1291
  before: instructions.before,
1241
1292
  after: instructions.after,
1242
1293
  with: instructions.with,
1243
- orderedBy: instructions.orderedBy
1294
+ orderedBy: instructions.orderedBy,
1295
+ limitedTo: instructions.limitedTo
1244
1296
  },
1245
1297
  isJoining ? table : void 0
1246
1298
  );
@@ -1261,25 +1313,44 @@ var compileQueryInput = (query, defaultSchemas, statementValues, options) => {
1261
1313
  );
1262
1314
  statement += `${orderedByStatement} `;
1263
1315
  }
1264
- if (queryType === "get" && !isJoiningMultipleRows) {
1316
+ if (queryType === "get" && !isJoiningMultipleRows && (single || instructions?.limitedTo)) {
1265
1317
  statement += handleLimitedTo(single, instructions?.limitedTo);
1266
1318
  }
1267
- if (["create", "set", "drop"].includes(queryType) && !options?.disableReturning) {
1319
+ if (["create", "set", "drop"].includes(queryType) && returning) {
1268
1320
  statement += "RETURNING * ";
1269
1321
  }
1270
- const finalStatement = statement.trimEnd();
1322
+ const mainStatement = {
1323
+ statement: statement.trimEnd(),
1324
+ params: statementParams || []
1325
+ };
1326
+ if (returning) mainStatement.returning = true;
1271
1327
  return {
1272
- writeStatements,
1273
- readStatement: finalStatement,
1274
- values: statementValues || []
1328
+ dependencies: dependencyStatements,
1329
+ main: mainStatement
1275
1330
  };
1276
1331
  };
1277
1332
 
1278
1333
  // src/index.ts
1279
- var compileQuery = (query, schemas, options) => {
1280
- const statementValues = options?.inlineValues ? null : [];
1281
- return compileQueryInput(query, schemas, statementValues);
1334
+ var compileQueries = (queries, schemas, options) => {
1335
+ const schemaList = addSystemSchemas(schemas).map((schema) => {
1336
+ return addDefaultSchemaFields(schema, true);
1337
+ });
1338
+ const schemaListWithShortcuts = schemaList.map((schema) => {
1339
+ return addDefaultSchemaShortcuts(schemaList, schema);
1340
+ });
1341
+ const dependencyStatements = [];
1342
+ const mainStatements = [];
1343
+ for (const query of queries) {
1344
+ const result = compileQueryInput(
1345
+ query,
1346
+ schemaListWithShortcuts,
1347
+ options?.inlineValues ? null : []
1348
+ );
1349
+ dependencyStatements.push(...result.dependencies);
1350
+ mainStatements.push(result.main);
1351
+ }
1352
+ return [...dependencyStatements, ...mainStatements];
1282
1353
  };
1283
1354
  export {
1284
- compileQuery
1355
+ compileQueries
1285
1356
  };