@ronin/compiler 0.2.2 → 0.3.1

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.
Files changed (3) hide show
  1. package/dist/index.d.ts +14264 -2
  2. package/dist/index.js +300 -205
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,8 +1,15 @@
1
1
  // src/utils/index.ts
2
2
  import { init as cuid } from "@paralleldrive/cuid2";
3
3
  var RONIN_SCHEMA_SYMBOLS = {
4
+ // Represents a sub query.
4
5
  QUERY: "__RONIN_QUERY",
6
+ // Represents the value of a field in a schema.
5
7
  FIELD: "__RONIN_FIELD_",
8
+ // Represents the old value of a field in a schema. Used for triggers.
9
+ FIELD_OLD: "__RONIN_FIELD_OLD_",
10
+ // Represents the new value of a field in a schema. Used for triggers.
11
+ FIELD_NEW: "__RONIN_FIELD_NEW_",
12
+ // Represents a value provided to a query preset.
6
13
  VALUE: "__RONIN_VALUE"
7
14
  };
8
15
  var RoninError = class extends Error {
@@ -44,15 +51,22 @@ var convertToCamelCase = (str) => {
44
51
  return sanitize(str).split(SPLIT_REGEX).map((part, index) => index === 0 ? part.toLowerCase() : capitalize(part)).join("");
45
52
  };
46
53
  var isObject = (value) => value != null && typeof value === "object" && Array.isArray(value) === false;
47
- var replaceInObject = (obj, pattern, replacer) => {
54
+ var findInObject = (obj, pattern, replacer) => {
55
+ let found = false;
48
56
  for (const key in obj) {
49
57
  const value = obj[key];
50
58
  if (isObject(value)) {
51
- replaceInObject(value, pattern, replacer);
59
+ found = findInObject(value, pattern, replacer);
52
60
  } else if (typeof value === "string" && value.startsWith(pattern)) {
53
- obj[key] = value.replace(pattern, replacer);
61
+ found = true;
62
+ if (replacer) {
63
+ obj[key] = value.replace(pattern, replacer);
64
+ } else {
65
+ return found;
66
+ }
54
67
  }
55
68
  }
69
+ return found;
56
70
  };
57
71
  var flatten = (obj, prefix = "", res = {}) => {
58
72
  for (const key in obj) {
@@ -81,6 +95,209 @@ var splitQuery = (query) => {
81
95
  return { queryType, querySchema, queryInstructions };
82
96
  };
83
97
 
98
+ // src/utils/statement.ts
99
+ var prepareStatementValue = (statementValues, value, bindNull = false) => {
100
+ if (!bindNull && value === null) return "NULL";
101
+ let formattedValue = value;
102
+ if (Array.isArray(value) || isObject(value)) {
103
+ formattedValue = JSON.stringify(value);
104
+ } else if (typeof value === "boolean") {
105
+ formattedValue = value ? 1 : 0;
106
+ }
107
+ const index = statementValues.push(formattedValue);
108
+ return `?${index}`;
109
+ };
110
+ var composeFieldValues = (schemas, schema, statementValues, instructionName, value, options) => {
111
+ const { field: schemaField, fieldSelector: selector } = getFieldFromSchema(
112
+ schema,
113
+ options.fieldSlug,
114
+ instructionName,
115
+ options.rootTable
116
+ );
117
+ const isSubQuery = isObject(value) && Object.hasOwn(value, RONIN_SCHEMA_SYMBOLS.QUERY);
118
+ const collectStatementValue = options.type !== "fields";
119
+ let conditionSelector = selector;
120
+ let conditionValue = value;
121
+ if (isSubQuery && collectStatementValue) {
122
+ conditionValue = `(${compileQueryInput(
123
+ value[RONIN_SCHEMA_SYMBOLS.QUERY],
124
+ schemas,
125
+ { statementValues }
126
+ ).readStatement})`;
127
+ } else if (typeof value === "string" && value.startsWith(RONIN_SCHEMA_SYMBOLS.FIELD)) {
128
+ let targetTable = `"${options.rootTable}"`;
129
+ let toReplace = RONIN_SCHEMA_SYMBOLS.FIELD;
130
+ if (value.startsWith(RONIN_SCHEMA_SYMBOLS.FIELD_OLD)) {
131
+ targetTable = "OLD";
132
+ toReplace = RONIN_SCHEMA_SYMBOLS.FIELD_OLD;
133
+ } else if (value.startsWith(RONIN_SCHEMA_SYMBOLS.FIELD_NEW)) {
134
+ targetTable = "NEW";
135
+ toReplace = RONIN_SCHEMA_SYMBOLS.FIELD_NEW;
136
+ }
137
+ conditionSelector = `${options.customTable ? `"${options.customTable}".` : ""}"${schemaField.slug}"`;
138
+ conditionValue = `${targetTable}."${value.replace(toReplace, "")}"`;
139
+ } else if (schemaField.type === "json" && instructionName === "to") {
140
+ conditionSelector = `"${schemaField.slug}"`;
141
+ if (collectStatementValue) {
142
+ const preparedValue = prepareStatementValue(statementValues, value, false);
143
+ conditionValue = `IIF(${conditionSelector} IS NULL, ${preparedValue}, json_patch(${conditionSelector}, ${preparedValue}))`;
144
+ }
145
+ } else if (collectStatementValue) {
146
+ conditionValue = prepareStatementValue(statementValues, value, false);
147
+ }
148
+ if (options.type === "fields") return conditionSelector;
149
+ if (options.type === "values") return conditionValue;
150
+ return `${conditionSelector} ${WITH_CONDITIONS[options.condition || "being"](conditionValue, value)}`;
151
+ };
152
+ var composeConditions = (schemas, schema, statementValues, instructionName, value, options) => {
153
+ const isNested = isObject(value) && Object.keys(value).length > 0;
154
+ if (isNested && Object.keys(value).every((key) => key in WITH_CONDITIONS)) {
155
+ const conditions = Object.entries(value).map(
156
+ ([conditionType, checkValue]) => composeConditions(schemas, schema, statementValues, instructionName, checkValue, {
157
+ ...options,
158
+ condition: conditionType
159
+ })
160
+ );
161
+ return conditions.join(" AND ");
162
+ }
163
+ if (options.fieldSlug) {
164
+ const fieldDetails = getFieldFromSchema(
165
+ schema,
166
+ options.fieldSlug,
167
+ instructionName,
168
+ options.rootTable
169
+ );
170
+ const { field: schemaField } = fieldDetails;
171
+ const consumeJSON = schemaField.type === "json" && instructionName === "to";
172
+ const isSubQuery = isNested && Object.hasOwn(value, RONIN_SCHEMA_SYMBOLS.QUERY);
173
+ if (!(isObject(value) || Array.isArray(value)) || isSubQuery || consumeJSON) {
174
+ return composeFieldValues(
175
+ schemas,
176
+ schema,
177
+ statementValues,
178
+ instructionName,
179
+ value,
180
+ { ...options, fieldSlug: options.fieldSlug }
181
+ );
182
+ }
183
+ if (schemaField.type === "reference" && isNested) {
184
+ const keys = Object.keys(value);
185
+ const values = Object.values(value);
186
+ let recordTarget;
187
+ if (keys.length === 1 && keys[0] === "id") {
188
+ recordTarget = values[0];
189
+ } else {
190
+ const relatedSchema = getSchemaBySlug(schemas, schemaField.target.slug);
191
+ const subQuery = {
192
+ get: {
193
+ [relatedSchema.slug]: {
194
+ with: value,
195
+ selecting: ["id"]
196
+ }
197
+ }
198
+ };
199
+ recordTarget = {
200
+ [RONIN_SCHEMA_SYMBOLS.QUERY]: subQuery
201
+ };
202
+ }
203
+ return composeConditions(
204
+ schemas,
205
+ schema,
206
+ statementValues,
207
+ instructionName,
208
+ recordTarget,
209
+ options
210
+ );
211
+ }
212
+ }
213
+ if (isNested) {
214
+ const conditions = Object.entries(value).map(([field, value2]) => {
215
+ const nestedFieldSlug = options.fieldSlug ? `${options.fieldSlug}.${field}` : field;
216
+ return composeConditions(schemas, schema, statementValues, instructionName, value2, {
217
+ ...options,
218
+ fieldSlug: nestedFieldSlug
219
+ });
220
+ });
221
+ const joiner = instructionName === "to" ? ", " : " AND ";
222
+ if (instructionName === "to") return `${conditions.join(joiner)}`;
223
+ return conditions.length === 1 ? conditions[0] : options.fieldSlug ? `(${conditions.join(joiner)})` : conditions.join(joiner);
224
+ }
225
+ if (Array.isArray(value)) {
226
+ const conditions = value.map(
227
+ (filter) => composeConditions(
228
+ schemas,
229
+ schema,
230
+ statementValues,
231
+ instructionName,
232
+ filter,
233
+ options
234
+ )
235
+ );
236
+ return conditions.join(" OR ");
237
+ }
238
+ throw new RoninError({
239
+ message: `The \`with\` instruction must not contain an empty field. The following fields are empty: \`${options.fieldSlug}\`. If you meant to query by an empty field, try using \`null\` instead.`,
240
+ code: "INVALID_WITH_VALUE",
241
+ queries: null
242
+ });
243
+ };
244
+ var formatIdentifiers = ({ identifiers }, queryInstructions) => {
245
+ if (!queryInstructions) return queryInstructions;
246
+ const type = "with" in queryInstructions ? "with" : null;
247
+ if (!type) return queryInstructions;
248
+ const nestedInstructions = queryInstructions[type];
249
+ if (!nestedInstructions || Array.isArray(nestedInstructions))
250
+ return queryInstructions;
251
+ const newNestedInstructions = { ...nestedInstructions };
252
+ for (const oldKey of Object.keys(newNestedInstructions)) {
253
+ if (oldKey !== "titleIdentifier" && oldKey !== "slugIdentifier") continue;
254
+ const identifierName = oldKey === "titleIdentifier" ? "title" : "slug";
255
+ const value = newNestedInstructions[oldKey];
256
+ const newKey = identifiers?.[identifierName] || "id";
257
+ newNestedInstructions[newKey] = value;
258
+ delete newNestedInstructions[oldKey];
259
+ }
260
+ return {
261
+ ...queryInstructions,
262
+ [type]: newNestedInstructions
263
+ };
264
+ };
265
+
266
+ // src/instructions/with.ts
267
+ var getMatcher = (value, negative) => {
268
+ if (negative) {
269
+ if (value === null) return "IS NOT";
270
+ return "!=";
271
+ }
272
+ if (value === null) return "IS";
273
+ return "=";
274
+ };
275
+ var WITH_CONDITIONS = {
276
+ being: (value, baseValue) => `${getMatcher(baseValue, false)} ${value}`,
277
+ notBeing: (value, baseValue) => `${getMatcher(baseValue, true)} ${value}`,
278
+ startingWith: (value) => `LIKE ${value}%`,
279
+ notStartingWith: (value) => `NOT LIKE ${value}%`,
280
+ endingWith: (value) => `LIKE %${value}`,
281
+ notEndingWith: (value) => `NOT LIKE %${value}`,
282
+ containing: (value) => `LIKE %${value}%`,
283
+ notContaining: (value) => `NOT LIKE %${value}%`,
284
+ greaterThan: (value) => `> ${value}`,
285
+ greaterOrEqual: (value) => `>= ${value}`,
286
+ lessThan: (value) => `< ${value}`,
287
+ lessOrEqual: (value) => `<= ${value}`
288
+ };
289
+ var handleWith = (schemas, schema, statementValues, instruction, rootTable) => {
290
+ const subStatement = composeConditions(
291
+ schemas,
292
+ schema,
293
+ statementValues,
294
+ "with",
295
+ instruction,
296
+ { rootTable }
297
+ );
298
+ return `(${subStatement})`;
299
+ };
300
+
84
301
  // src/utils/schema.ts
85
302
  import title from "title";
86
303
  var getSchemaBySlug = (schemas, slug) => {
@@ -101,7 +318,8 @@ var getTableForSchema = (schema) => {
101
318
  var composeMetaSchemaSlug = (suffix) => convertToCamelCase(`ronin_${suffix}`);
102
319
  var composeAssociationSchemaSlug = (schema, field) => composeMetaSchemaSlug(`${schema.pluralSlug}_${field.slug}`);
103
320
  var getFieldSelector = (field, fieldPath, rootTable) => {
104
- const tablePrefix = rootTable ? `"${rootTable}".` : "";
321
+ const symbol = rootTable?.startsWith(RONIN_SCHEMA_SYMBOLS.FIELD) ? `${rootTable.replace(RONIN_SCHEMA_SYMBOLS.FIELD, "").slice(0, -1)}.` : "";
322
+ const tablePrefix = symbol || (rootTable ? `"${rootTable}".` : "");
105
323
  if (field.type === "json") {
106
324
  const dotParts = fieldPath.split(".");
107
325
  const columnName = tablePrefix + dotParts.shift();
@@ -186,7 +404,10 @@ var SYSTEM_SCHEMAS = [
186
404
  { slug: "idPrefix", type: "string" },
187
405
  { slug: "identifiers", type: "group" },
188
406
  { slug: "identifiers.title", type: "string" },
189
- { slug: "identifiers.slug", type: "string" }
407
+ { slug: "identifiers.slug", type: "string" },
408
+ { slug: "fields", type: "json" },
409
+ { slug: "indexes", type: "json" },
410
+ { slug: "triggers", type: "json" }
190
411
  ]
191
412
  },
192
413
  {
@@ -234,6 +455,20 @@ var SYSTEM_SCHEMAS = [
234
455
  { slug: "unique", type: "boolean" },
235
456
  { slug: "filter", type: "json" }
236
457
  ]
458
+ },
459
+ {
460
+ name: "Trigger",
461
+ pluralName: "Triggers",
462
+ slug: "trigger",
463
+ pluralSlug: "triggers",
464
+ fields: [
465
+ ...SYSTEM_FIELDS,
466
+ { slug: "slug", type: "string", required: true },
467
+ { slug: "schema", type: "reference", target: { slug: "schema" }, required: true },
468
+ { slug: "cause", type: "string", required: true },
469
+ { slug: "filter", type: "json" },
470
+ { slug: "effects", type: "json", required: true }
471
+ ]
237
472
  }
238
473
  ];
239
474
  var SYSTEM_SCHEMA_SLUGS = SYSTEM_SCHEMAS.flatMap(({ slug, pluralSlug }) => [
@@ -341,7 +576,7 @@ var getFieldStatement = (field) => {
341
576
  }
342
577
  return statement;
343
578
  };
344
- var addSchemaQueries = (queryDetails, writeStatements) => {
579
+ var addSchemaQueries = (schemas, statementValues, queryDetails, writeStatements) => {
345
580
  const { queryType, querySchema, queryInstructions } = queryDetails;
346
581
  if (!["create", "set", "drop"].includes(queryType)) return;
347
582
  if (!SYSTEM_SCHEMA_SLUGS.includes(querySchema)) return;
@@ -352,7 +587,9 @@ var addSchemaQueries = (queryDetails, writeStatements) => {
352
587
  let queryTypeReadable = null;
353
588
  switch (queryType) {
354
589
  case "create": {
355
- if (kind === "schemas" || kind === "indexes") tableAction = "CREATE";
590
+ if (kind === "schemas" || kind === "indexes" || kind === "triggers") {
591
+ tableAction = "CREATE";
592
+ }
356
593
  queryTypeReadable = "creating";
357
594
  break;
358
595
  }
@@ -362,7 +599,9 @@ var addSchemaQueries = (queryDetails, writeStatements) => {
362
599
  break;
363
600
  }
364
601
  case "drop": {
365
- if (kind === "schemas" || kind === "indexes") tableAction = "DROP";
602
+ if (kind === "schemas" || kind === "indexes" || kind === "triggers") {
603
+ tableAction = "DROP";
604
+ }
366
605
  queryTypeReadable = "deleting";
367
606
  break;
368
607
  }
@@ -388,8 +627,58 @@ var addSchemaQueries = (queryDetails, writeStatements) => {
388
627
  if (kind === "indexes") {
389
628
  const indexName = convertToSnakeCase(slug);
390
629
  const unique = instructionList?.unique;
630
+ const filterQuery = instructionList?.filter;
391
631
  let statement2 = `${tableAction}${unique ? " UNIQUE" : ""} INDEX "${indexName}"`;
392
- if (queryType === "create") statement2 += ` ON "${tableName}"`;
632
+ if (queryType === "create") {
633
+ statement2 += ` ON "${tableName}"`;
634
+ if (filterQuery) {
635
+ const targetSchema = getSchemaBySlug(schemas, schemaSlug);
636
+ const withStatement = handleWith(
637
+ schemas,
638
+ targetSchema,
639
+ statementValues,
640
+ filterQuery
641
+ );
642
+ statement2 += ` WHERE (${withStatement})`;
643
+ }
644
+ }
645
+ writeStatements.push(statement2);
646
+ return;
647
+ }
648
+ if (kind === "triggers") {
649
+ const triggerName = convertToSnakeCase(slug);
650
+ let statement2 = `${tableAction} TRIGGER "${triggerName}"`;
651
+ if (queryType === "create") {
652
+ const cause = slugToName(instructionList?.cause).toUpperCase();
653
+ const statementParts = [cause, "ON", `"${tableName}"`];
654
+ const effectQueries = instructionList?.effects;
655
+ const filterQuery = instructionList?.filter;
656
+ if (filterQuery || effectQueries.some((query) => findInObject(query, RONIN_SCHEMA_SYMBOLS.FIELD))) {
657
+ statementParts.push("FOR EACH ROW");
658
+ }
659
+ if (filterQuery) {
660
+ const targetSchema = getSchemaBySlug(schemas, schemaSlug);
661
+ const tablePlaceholder = cause.endsWith("DELETE") ? RONIN_SCHEMA_SYMBOLS.FIELD_OLD : RONIN_SCHEMA_SYMBOLS.FIELD_NEW;
662
+ const withStatement = handleWith(
663
+ schemas,
664
+ targetSchema,
665
+ statementValues,
666
+ filterQuery,
667
+ tablePlaceholder
668
+ );
669
+ statementParts.push("WHEN", `(${withStatement})`);
670
+ }
671
+ const effectStatements = effectQueries.map((effectQuery) => {
672
+ return compileQueryInput(effectQuery, schemas, {
673
+ statementValues,
674
+ disableReturning: true
675
+ }).readStatement;
676
+ });
677
+ if (effectStatements.length > 1) statementParts.push("BEGIN");
678
+ statementParts.push(effectStatements.join("; "));
679
+ if (effectStatements.length > 1) statementParts.push("END");
680
+ statement2 += ` ${statementParts.join(" ")}`;
681
+ }
393
682
  writeStatements.push(statement2);
394
683
  return;
395
684
  }
@@ -447,200 +736,6 @@ var pluralize = (word) => {
447
736
  return `${word}s`;
448
737
  };
449
738
 
450
- // src/instructions/with.ts
451
- var getMatcher = (value, negative) => {
452
- if (negative) {
453
- if (value === null) return "IS NOT";
454
- return "!=";
455
- }
456
- if (value === null) return "IS";
457
- return "=";
458
- };
459
- var WITH_CONDITIONS = {
460
- being: (value, baseValue) => `${getMatcher(baseValue, false)} ${value}`,
461
- notBeing: (value, baseValue) => `${getMatcher(baseValue, true)} ${value}`,
462
- startingWith: (value) => `LIKE ${value}%`,
463
- notStartingWith: (value) => `NOT LIKE ${value}%`,
464
- endingWith: (value) => `LIKE %${value}`,
465
- notEndingWith: (value) => `NOT LIKE %${value}`,
466
- containing: (value) => `LIKE %${value}%`,
467
- notContaining: (value) => `NOT LIKE %${value}%`,
468
- greaterThan: (value) => `> ${value}`,
469
- greaterOrEqual: (value) => `>= ${value}`,
470
- lessThan: (value) => `< ${value}`,
471
- lessOrEqual: (value) => `<= ${value}`
472
- };
473
- var handleWith = (schemas, schema, statementValues, instruction, rootTable) => {
474
- const subStatement = composeConditions(
475
- schemas,
476
- schema,
477
- statementValues,
478
- "with",
479
- instruction,
480
- { rootTable }
481
- );
482
- return `(${subStatement})`;
483
- };
484
-
485
- // src/utils/statement.ts
486
- var prepareStatementValue = (statementValues, value, bindNull = false) => {
487
- if (!bindNull && value === null) return "NULL";
488
- let formattedValue = value;
489
- if (Array.isArray(value) || isObject(value)) {
490
- formattedValue = JSON.stringify(value);
491
- } else if (typeof value === "boolean") {
492
- formattedValue = value ? 1 : 0;
493
- }
494
- const index = statementValues.push(formattedValue);
495
- return `?${index}`;
496
- };
497
- var composeFieldValues = (schemas, schema, statementValues, instructionName, value, options) => {
498
- const { field: schemaField, fieldSelector: selector } = getFieldFromSchema(
499
- schema,
500
- options.fieldSlug,
501
- instructionName,
502
- options.rootTable
503
- );
504
- const isSubQuery = isObject(value) && Object.hasOwn(value, RONIN_SCHEMA_SYMBOLS.QUERY);
505
- const collectStatementValue = options.type !== "fields";
506
- let conditionSelector = selector;
507
- let conditionValue = value;
508
- if (isSubQuery && collectStatementValue) {
509
- conditionValue = `(${compileQueryInput(
510
- value[RONIN_SCHEMA_SYMBOLS.QUERY],
511
- schemas,
512
- { statementValues }
513
- ).readStatement})`;
514
- } else if (typeof value === "string" && value.startsWith(RONIN_SCHEMA_SYMBOLS.FIELD)) {
515
- conditionSelector = `"${options.customTable}"."${schemaField.slug}"`;
516
- conditionValue = `"${options.rootTable}"."${value.replace(RONIN_SCHEMA_SYMBOLS.FIELD, "")}"`;
517
- } else if (schemaField.type === "json" && instructionName === "to") {
518
- conditionSelector = `"${schemaField.slug}"`;
519
- if (collectStatementValue) {
520
- const preparedValue = prepareStatementValue(statementValues, value, false);
521
- conditionValue = `IIF(${conditionSelector} IS NULL, ${preparedValue}, json_patch(${conditionSelector}, ${preparedValue}))`;
522
- }
523
- } else if (collectStatementValue) {
524
- conditionValue = prepareStatementValue(statementValues, value, false);
525
- }
526
- if (options.type === "fields") return conditionSelector;
527
- if (options.type === "values") return conditionValue;
528
- return `${conditionSelector} ${WITH_CONDITIONS[options.condition || "being"](conditionValue, value)}`;
529
- };
530
- var composeConditions = (schemas, schema, statementValues, instructionName, value, options) => {
531
- const isNested = isObject(value) && Object.keys(value).length > 0;
532
- if (isNested && Object.keys(value).every((key) => key in WITH_CONDITIONS)) {
533
- const conditions = Object.entries(value).map(
534
- ([conditionType, checkValue]) => composeConditions(schemas, schema, statementValues, instructionName, checkValue, {
535
- ...options,
536
- condition: conditionType
537
- })
538
- );
539
- return conditions.join(" AND ");
540
- }
541
- if (options.fieldSlug) {
542
- const fieldDetails = getFieldFromSchema(
543
- schema,
544
- options.fieldSlug,
545
- instructionName,
546
- options.rootTable
547
- );
548
- const { field: schemaField } = fieldDetails;
549
- const consumeJSON = schemaField.type === "json" && instructionName === "to";
550
- const isSubQuery = isNested && Object.hasOwn(value, RONIN_SCHEMA_SYMBOLS.QUERY);
551
- if (!(isObject(value) || Array.isArray(value)) || isSubQuery || consumeJSON) {
552
- return composeFieldValues(
553
- schemas,
554
- schema,
555
- statementValues,
556
- instructionName,
557
- value,
558
- { ...options, fieldSlug: options.fieldSlug }
559
- );
560
- }
561
- if (schemaField.type === "reference" && isNested) {
562
- const keys = Object.keys(value);
563
- const values = Object.values(value);
564
- let recordTarget;
565
- if (keys.length === 1 && keys[0] === "id") {
566
- recordTarget = values[0];
567
- } else {
568
- const relatedSchema = getSchemaBySlug(schemas, schemaField.target.slug);
569
- const subQuery = {
570
- get: {
571
- [relatedSchema.slug]: {
572
- with: value,
573
- selecting: ["id"]
574
- }
575
- }
576
- };
577
- recordTarget = {
578
- [RONIN_SCHEMA_SYMBOLS.QUERY]: subQuery
579
- };
580
- }
581
- return composeConditions(
582
- schemas,
583
- schema,
584
- statementValues,
585
- instructionName,
586
- recordTarget,
587
- options
588
- );
589
- }
590
- }
591
- if (isNested) {
592
- const conditions = Object.entries(value).map(([field, value2]) => {
593
- const nestedFieldSlug = options.fieldSlug ? `${options.fieldSlug}.${field}` : field;
594
- return composeConditions(schemas, schema, statementValues, instructionName, value2, {
595
- ...options,
596
- fieldSlug: nestedFieldSlug
597
- });
598
- });
599
- const joiner = instructionName === "to" ? ", " : " AND ";
600
- if (instructionName === "to") return `${conditions.join(joiner)}`;
601
- return conditions.length === 1 ? conditions[0] : options.fieldSlug ? `(${conditions.join(joiner)})` : conditions.join(joiner);
602
- }
603
- if (Array.isArray(value)) {
604
- const conditions = value.map(
605
- (filter) => composeConditions(
606
- schemas,
607
- schema,
608
- statementValues,
609
- instructionName,
610
- filter,
611
- options
612
- )
613
- );
614
- return conditions.join(" OR ");
615
- }
616
- throw new RoninError({
617
- message: `The \`with\` instruction must not contain an empty field. The following fields are empty: \`${options.fieldSlug}\`. If you meant to query by an empty field, try using \`null\` instead.`,
618
- code: "INVALID_WITH_VALUE",
619
- queries: null
620
- });
621
- };
622
- var formatIdentifiers = ({ identifiers }, queryInstructions) => {
623
- if (!queryInstructions) return queryInstructions;
624
- const type = "with" in queryInstructions ? "with" : null;
625
- if (!type) return queryInstructions;
626
- const nestedInstructions = queryInstructions[type];
627
- if (!nestedInstructions || Array.isArray(nestedInstructions))
628
- return queryInstructions;
629
- const newNestedInstructions = { ...nestedInstructions };
630
- for (const oldKey of Object.keys(newNestedInstructions)) {
631
- if (oldKey !== "titleIdentifier" && oldKey !== "slugIdentifier") continue;
632
- const identifierName = oldKey === "titleIdentifier" ? "title" : "slug";
633
- const value = newNestedInstructions[oldKey];
634
- const newKey = identifiers?.[identifierName] || "id";
635
- newNestedInstructions[newKey] = value;
636
- delete newNestedInstructions[oldKey];
637
- }
638
- return {
639
- ...queryInstructions,
640
- [type]: newNestedInstructions
641
- };
642
- };
643
-
644
739
  // src/instructions/before-after.ts
645
740
  var CURSOR_SEPARATOR = ",";
646
741
  var CURSOR_NULL_PLACEHOLDER = "RONIN_NULL";
@@ -734,7 +829,7 @@ var handleFor = (schemas, schema, statementValues, instruction, rootTable) => {
734
829
  });
735
830
  }
736
831
  const replacedForFilter = structuredClone(forFilter);
737
- replaceInObject(
832
+ findInObject(
738
833
  replacedForFilter,
739
834
  RONIN_SCHEMA_SYMBOLS.VALUE,
740
835
  (match) => match.replace(RONIN_SCHEMA_SYMBOLS.VALUE, args)
@@ -999,7 +1094,7 @@ var compileQueryInput = (query, defaultSchemas, options) => {
999
1094
  let table = getTableForSchema(schema);
1000
1095
  const statementValues = options?.statementValues || [];
1001
1096
  const writeStatements = [];
1002
- addSchemaQueries(parsedQuery, writeStatements);
1097
+ addSchemaQueries(schemas, statementValues, parsedQuery, writeStatements);
1003
1098
  const columns = handleSelecting(schema, statementValues, {
1004
1099
  selecting: instructions?.selecting,
1005
1100
  including: instructions?.including
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ronin/compiler",
3
- "version": "0.2.2",
3
+ "version": "0.3.1",
4
4
  "type": "module",
5
5
  "description": "Compiles RONIN queries to SQL statements.",
6
6
  "publishConfig": {