@ronin/compiler 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,19 +1,23 @@
1
1
  // src/utils/helpers.ts
2
2
  import { init as cuid } from "@paralleldrive/cuid2";
3
- var RONIN_SCHEMA_SYMBOLS = {
3
+ var RONIN_MODEL_SYMBOLS = {
4
4
  // Represents a sub query.
5
5
  QUERY: "__RONIN_QUERY",
6
- // Represents the value of a field in a schema.
6
+ // Represents an expression that should be evaluated.
7
+ EXPRESSION: "__RONIN_EXPRESSION",
8
+ // Represents the value of a field in the model.
7
9
  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_",
10
+ // Represents the value of a field in the model of a parent query.
11
+ FIELD_PARENT: "__RONIN_FIELD_PARENT_",
12
+ // Represents the old value of a field in the parent model. Used for triggers.
13
+ FIELD_PARENT_OLD: "__RONIN_FIELD_PARENT_OLD_",
14
+ // Represents the new value of a field in the parent model. Used for triggers.
15
+ FIELD_PARENT_NEW: "__RONIN_FIELD_PARENT_NEW_",
12
16
  // Represents a value provided to a query preset.
13
17
  VALUE: "__RONIN_VALUE"
14
18
  };
15
- var RONIN_SCHEMA_FIELD_REGEX = new RegExp(
16
- `${RONIN_SCHEMA_SYMBOLS.FIELD}[a-zA-Z0-9]+`,
19
+ var RONIN_MODEL_FIELD_REGEX = new RegExp(
20
+ `${RONIN_MODEL_SYMBOLS.FIELD}[_a-zA-Z0-9]+`,
17
21
  "g"
18
22
  );
19
23
  var RoninError = class extends Error {
@@ -94,9 +98,9 @@ var expand = (obj) => {
94
98
  };
95
99
  var splitQuery = (query) => {
96
100
  const queryType = Object.keys(query)[0];
97
- const querySchema = Object.keys(query[queryType])[0];
98
- const queryInstructions = query[queryType][querySchema];
99
- return { queryType, querySchema, queryInstructions };
101
+ const queryModel = Object.keys(query[queryType])[0];
102
+ const queryInstructions = query[queryType][queryModel];
103
+ return { queryType, queryModel, queryInstructions };
100
104
  };
101
105
 
102
106
  // src/utils/statement.ts
@@ -112,39 +116,44 @@ var prepareStatementValue = (statementParams, value) => {
112
116
  const index = statementParams.push(formattedValue);
113
117
  return `?${index}`;
114
118
  };
115
- var composeFieldValues = (schemas, schema, statementParams, instructionName, value, options) => {
116
- const { field: schemaField, fieldSelector: selector } = getFieldFromSchema(
117
- schema,
119
+ var parseFieldExpression = (model, instructionName, expression, parentModel) => {
120
+ return expression.replace(RONIN_MODEL_FIELD_REGEX, (match) => {
121
+ let toReplace = RONIN_MODEL_SYMBOLS.FIELD;
122
+ let rootModel = model;
123
+ if (match.startsWith(RONIN_MODEL_SYMBOLS.FIELD_PARENT)) {
124
+ rootModel = parentModel;
125
+ toReplace = RONIN_MODEL_SYMBOLS.FIELD_PARENT;
126
+ if (match.startsWith(RONIN_MODEL_SYMBOLS.FIELD_PARENT_OLD)) {
127
+ rootModel.tableAlias = toReplace = RONIN_MODEL_SYMBOLS.FIELD_PARENT_OLD;
128
+ } else if (match.startsWith(RONIN_MODEL_SYMBOLS.FIELD_PARENT_NEW)) {
129
+ rootModel.tableAlias = toReplace = RONIN_MODEL_SYMBOLS.FIELD_PARENT_NEW;
130
+ }
131
+ }
132
+ const fieldSlug = match.replace(toReplace, "");
133
+ const field = getFieldFromModel(rootModel, fieldSlug, instructionName);
134
+ return field.fieldSelector;
135
+ });
136
+ };
137
+ var composeFieldValues = (models, model, statementParams, instructionName, value, options) => {
138
+ const { fieldSelector: conditionSelector } = getFieldFromModel(
139
+ model,
118
140
  options.fieldSlug,
119
- instructionName,
120
- options.rootTable
141
+ instructionName
121
142
  );
122
143
  const collectStatementValue = options.type !== "fields";
123
- let conditionSelector = selector;
144
+ const symbol = getSymbol(value);
124
145
  let conditionValue = value;
125
- if (getSubQuery(value) && collectStatementValue) {
126
- conditionValue = `(${compileQueryInput(
127
- value[RONIN_SCHEMA_SYMBOLS.QUERY],
128
- schemas,
129
- statementParams
130
- ).main.statement})`;
131
- } else if (typeof value === "string" && value.startsWith(RONIN_SCHEMA_SYMBOLS.FIELD)) {
132
- let targetTable = `"${options.rootTable}"`;
133
- let toReplace = RONIN_SCHEMA_SYMBOLS.FIELD;
134
- if (value.startsWith(RONIN_SCHEMA_SYMBOLS.FIELD_OLD)) {
135
- targetTable = "OLD";
136
- toReplace = RONIN_SCHEMA_SYMBOLS.FIELD_OLD;
137
- } else if (value.startsWith(RONIN_SCHEMA_SYMBOLS.FIELD_NEW)) {
138
- targetTable = "NEW";
139
- toReplace = RONIN_SCHEMA_SYMBOLS.FIELD_NEW;
146
+ if (symbol) {
147
+ if (symbol?.type === "expression") {
148
+ conditionValue = parseFieldExpression(
149
+ model,
150
+ instructionName,
151
+ symbol.value,
152
+ options.parentModel
153
+ );
140
154
  }
141
- conditionSelector = `${options.customTable ? `"${options.customTable}".` : ""}"${schemaField.slug}"`;
142
- conditionValue = `${targetTable}."${value.replace(toReplace, "")}"`;
143
- } else if (schemaField.type === "json" && instructionName === "to") {
144
- conditionSelector = `"${schemaField.slug}"`;
145
- if (collectStatementValue) {
146
- const preparedValue = prepareStatementValue(statementParams, value);
147
- conditionValue = `IIF(${conditionSelector} IS NULL, ${preparedValue}, json_patch(${conditionSelector}, ${preparedValue}))`;
155
+ if (symbol.type === "query" && collectStatementValue) {
156
+ conditionValue = `(${compileQueryInput(symbol.value, models, statementParams).main.statement})`;
148
157
  }
149
158
  } else if (collectStatementValue) {
150
159
  conditionValue = prepareStatementValue(statementParams, value);
@@ -153,11 +162,11 @@ var composeFieldValues = (schemas, schema, statementParams, instructionName, val
153
162
  if (options.type === "values") return conditionValue;
154
163
  return `${conditionSelector} ${WITH_CONDITIONS[options.condition || "being"](conditionValue, value)}`;
155
164
  };
156
- var composeConditions = (schemas, schema, statementParams, instructionName, value, options) => {
165
+ var composeConditions = (models, model, statementParams, instructionName, value, options) => {
157
166
  const isNested = isObject(value) && Object.keys(value).length > 0;
158
167
  if (isNested && Object.keys(value).every((key) => key in WITH_CONDITIONS)) {
159
168
  const conditions = Object.entries(value).map(
160
- ([conditionType, checkValue]) => composeConditions(schemas, schema, statementParams, instructionName, checkValue, {
169
+ ([conditionType, checkValue]) => composeConditions(models, model, statementParams, instructionName, checkValue, {
161
170
  ...options,
162
171
  condition: conditionType
163
172
  })
@@ -165,47 +174,42 @@ var composeConditions = (schemas, schema, statementParams, instructionName, valu
165
174
  return conditions.join(" AND ");
166
175
  }
167
176
  if (options.fieldSlug) {
168
- const fieldDetails = getFieldFromSchema(
169
- schema,
170
- options.fieldSlug,
171
- instructionName,
172
- options.rootTable
173
- );
174
- const { field: schemaField } = fieldDetails;
175
- const consumeJSON = schemaField.type === "json" && instructionName === "to";
176
- if (!(isObject(value) || Array.isArray(value)) || getSubQuery(value) || consumeJSON) {
177
+ const fieldDetails = getFieldFromModel(model, options.fieldSlug, instructionName);
178
+ const { field: modelField } = fieldDetails;
179
+ const consumeJSON = modelField.type === "json" && instructionName === "to";
180
+ if (!(isObject(value) || Array.isArray(value)) || getSymbol(value) || consumeJSON) {
177
181
  return composeFieldValues(
178
- schemas,
179
- schema,
182
+ models,
183
+ model,
180
184
  statementParams,
181
185
  instructionName,
182
186
  value,
183
187
  { ...options, fieldSlug: options.fieldSlug }
184
188
  );
185
189
  }
186
- if (schemaField.type === "reference" && isNested) {
190
+ if (modelField.type === "reference" && isNested) {
187
191
  const keys = Object.keys(value);
188
192
  const values = Object.values(value);
189
193
  let recordTarget;
190
194
  if (keys.length === 1 && keys[0] === "id") {
191
195
  recordTarget = values[0];
192
196
  } else {
193
- const relatedSchema = getSchemaBySlug(schemas, schemaField.target.slug);
197
+ const relatedModel = getModelBySlug(models, modelField.target.slug);
194
198
  const subQuery = {
195
199
  get: {
196
- [relatedSchema.slug]: {
200
+ [relatedModel.slug]: {
197
201
  with: value,
198
202
  selecting: ["id"]
199
203
  }
200
204
  }
201
205
  };
202
206
  recordTarget = {
203
- [RONIN_SCHEMA_SYMBOLS.QUERY]: subQuery
207
+ [RONIN_MODEL_SYMBOLS.QUERY]: subQuery
204
208
  };
205
209
  }
206
210
  return composeConditions(
207
- schemas,
208
- schema,
211
+ models,
212
+ model,
209
213
  statementParams,
210
214
  instructionName,
211
215
  recordTarget,
@@ -216,7 +220,7 @@ var composeConditions = (schemas, schema, statementParams, instructionName, valu
216
220
  if (isNested) {
217
221
  const conditions = Object.entries(value).map(([field, value2]) => {
218
222
  const nestedFieldSlug = options.fieldSlug ? `${options.fieldSlug}.${field}` : field;
219
- return composeConditions(schemas, schema, statementParams, instructionName, value2, {
223
+ return composeConditions(models, model, statementParams, instructionName, value2, {
220
224
  ...options,
221
225
  fieldSlug: nestedFieldSlug
222
226
  });
@@ -227,14 +231,7 @@ var composeConditions = (schemas, schema, statementParams, instructionName, valu
227
231
  }
228
232
  if (Array.isArray(value)) {
229
233
  const conditions = value.map(
230
- (filter) => composeConditions(
231
- schemas,
232
- schema,
233
- statementParams,
234
- instructionName,
235
- filter,
236
- options
237
- )
234
+ (filter) => composeConditions(models, model, statementParams, instructionName, filter, options)
238
235
  );
239
236
  return conditions.join(" OR ");
240
237
  }
@@ -265,8 +262,22 @@ var formatIdentifiers = ({ identifiers }, queryInstructions) => {
265
262
  [type]: newNestedInstructions
266
263
  };
267
264
  };
268
- var getSubQuery = (value) => {
269
- return isObject(value) ? value[RONIN_SCHEMA_SYMBOLS.QUERY] || null : null;
265
+ var getSymbol = (value) => {
266
+ if (!isObject(value)) return null;
267
+ const objectValue = value;
268
+ if (RONIN_MODEL_SYMBOLS.QUERY in objectValue) {
269
+ return {
270
+ type: "query",
271
+ value: objectValue[RONIN_MODEL_SYMBOLS.QUERY]
272
+ };
273
+ }
274
+ if (RONIN_MODEL_SYMBOLS.EXPRESSION in objectValue) {
275
+ return {
276
+ type: "expression",
277
+ value: objectValue[RONIN_MODEL_SYMBOLS.EXPRESSION]
278
+ };
279
+ }
280
+ return null;
270
281
  };
271
282
 
272
283
  // src/instructions/with.ts
@@ -292,41 +303,37 @@ var WITH_CONDITIONS = {
292
303
  lessThan: (value) => `< ${value}`,
293
304
  lessOrEqual: (value) => `<= ${value}`
294
305
  };
295
- var handleWith = (schemas, schema, statementParams, instruction, rootTable) => {
306
+ var handleWith = (models, model, statementParams, instruction, parentModel) => {
296
307
  const subStatement = composeConditions(
297
- schemas,
298
- schema,
308
+ models,
309
+ model,
299
310
  statementParams,
300
311
  "with",
301
312
  instruction,
302
- { rootTable }
313
+ { parentModel }
303
314
  );
304
315
  return `(${subStatement})`;
305
316
  };
306
317
 
307
- // src/utils/schema.ts
318
+ // src/utils/model.ts
308
319
  import title from "title";
309
- var getSchemaBySlug = (schemas, slug) => {
310
- const schema = schemas.find((schema2) => {
311
- return schema2.slug === slug || schema2.pluralSlug === slug;
320
+ var getModelBySlug = (models, slug) => {
321
+ const model = models.find((model2) => {
322
+ return model2.slug === slug || model2.pluralSlug === slug;
312
323
  });
313
- if (!schema) {
324
+ if (!model) {
314
325
  throw new RoninError({
315
- message: `No matching schema with either Slug or Plural Slug of "${slug}" could be found.`,
316
- code: "SCHEMA_NOT_FOUND"
326
+ message: `No matching model with either Slug or Plural Slug of "${slug}" could be found.`,
327
+ code: "MODEL_NOT_FOUND"
317
328
  });
318
329
  }
319
- return schema;
320
- };
321
- var getTableForSchema = (schema) => {
322
- return convertToSnakeCase(schema.pluralSlug);
330
+ return model;
323
331
  };
324
- var composeMetaSchemaSlug = (suffix) => convertToCamelCase(`ronin_${suffix}`);
325
- var composeAssociationSchemaSlug = (schema, field) => composeMetaSchemaSlug(`${schema.slug}_${field.slug}`);
326
- var getFieldSelector = (field, fieldPath, rootTable) => {
327
- const symbol = rootTable?.startsWith(RONIN_SCHEMA_SYMBOLS.FIELD) ? `${rootTable.replace(RONIN_SCHEMA_SYMBOLS.FIELD, "").slice(0, -1)}.` : "";
328
- const tablePrefix = symbol || (rootTable ? `"${rootTable}".` : "");
329
- if (field.type === "json") {
332
+ var composeAssociationModelSlug = (model, field) => convertToCamelCase(`ronin_link_${model.slug}_${field.slug}`);
333
+ var getFieldSelector = (model, field, fieldPath, instructionName) => {
334
+ const symbol = model.tableAlias?.startsWith(RONIN_MODEL_SYMBOLS.FIELD_PARENT) ? `${model.tableAlias.replace(RONIN_MODEL_SYMBOLS.FIELD_PARENT, "").slice(0, -1)}.` : "";
335
+ const tablePrefix = symbol || (model.tableAlias ? `"${model.tableAlias}".` : "");
336
+ if (field.type === "json" && instructionName !== "to") {
330
337
  const dotParts = fieldPath.split(".");
331
338
  const columnName = tablePrefix + dotParts.shift();
332
339
  const jsonField = dotParts.join(".");
@@ -334,28 +341,33 @@ var getFieldSelector = (field, fieldPath, rootTable) => {
334
341
  }
335
342
  return `${tablePrefix}"${fieldPath}"`;
336
343
  };
337
- var getFieldFromSchema = (schema, fieldPath, instructionName, rootTable) => {
344
+ var getFieldFromModel = (model, fieldPath, instructionName) => {
338
345
  const errorPrefix = `Field "${fieldPath}" defined for \`${instructionName}\``;
339
- const schemaFields = schema.fields || [];
340
- let schemaField;
346
+ const modelFields = model.fields || [];
347
+ let modelField;
341
348
  if (fieldPath.includes(".")) {
342
- schemaField = schemaFields.find((field) => field.slug === fieldPath.split(".")[0]);
343
- if (schemaField?.type === "json") {
344
- const fieldSelector2 = getFieldSelector(schemaField, fieldPath, rootTable);
345
- return { field: schemaField, fieldSelector: fieldSelector2 };
349
+ modelField = modelFields.find((field) => field.slug === fieldPath.split(".")[0]);
350
+ if (modelField?.type === "json") {
351
+ const fieldSelector2 = getFieldSelector(
352
+ model,
353
+ modelField,
354
+ fieldPath,
355
+ instructionName
356
+ );
357
+ return { field: modelField, fieldSelector: fieldSelector2 };
346
358
  }
347
359
  }
348
- schemaField = schemaFields.find((field) => field.slug === fieldPath);
349
- if (!schemaField) {
360
+ modelField = modelFields.find((field) => field.slug === fieldPath);
361
+ if (!modelField) {
350
362
  throw new RoninError({
351
- message: `${errorPrefix} does not exist in schema "${schema.name}".`,
363
+ message: `${errorPrefix} does not exist in model "${model.name}".`,
352
364
  code: "FIELD_NOT_FOUND",
353
365
  field: fieldPath,
354
366
  queries: null
355
367
  });
356
368
  }
357
- const fieldSelector = getFieldSelector(schemaField, fieldPath, rootTable);
358
- return { field: schemaField, fieldSelector };
369
+ const fieldSelector = getFieldSelector(model, modelField, fieldPath, instructionName);
370
+ return { field: modelField, fieldSelector };
359
371
  };
360
372
  var slugToName = (slug) => {
361
373
  const name = slug.replace(/([a-z])([A-Z])/g, "$1 $2");
@@ -373,36 +385,37 @@ var pluralize = (word) => {
373
385
  }
374
386
  return `${word}s`;
375
387
  };
376
- var schemaSettings = [
388
+ var modelSettings = [
377
389
  ["pluralSlug", "slug", pluralize],
378
390
  ["name", "slug", slugToName],
379
391
  ["pluralName", "pluralSlug", slugToName],
380
- ["idPrefix", "slug", (slug) => slug.slice(0, 3)]
392
+ ["idPrefix", "slug", (slug) => slug.slice(0, 3)],
393
+ ["table", "pluralSlug", convertToSnakeCase]
381
394
  ];
382
- var addDefaultSchemaFields = (schema, isNew) => {
383
- const copiedSchema = { ...schema };
384
- for (const [setting, base, generator] of schemaSettings) {
385
- if (copiedSchema[setting] || !copiedSchema[base]) continue;
386
- copiedSchema[setting] = generator(copiedSchema[base]);
395
+ var addDefaultModelFields = (model, isNew) => {
396
+ const copiedModel = { ...model };
397
+ for (const [setting, base, generator] of modelSettings) {
398
+ if (copiedModel[setting] || !copiedModel[base]) continue;
399
+ copiedModel[setting] = generator(copiedModel[base]);
387
400
  }
388
- const newFields = copiedSchema.fields || [];
401
+ const newFields = copiedModel.fields || [];
389
402
  if (isNew || newFields.length > 0) {
390
- if (!copiedSchema.identifiers) copiedSchema.identifiers = {};
391
- if (!copiedSchema.identifiers.name) {
403
+ if (!copiedModel.identifiers) copiedModel.identifiers = {};
404
+ if (!copiedModel.identifiers.name) {
392
405
  const suitableField = newFields.find(
393
406
  (field) => field.type === "string" && field.required === true && ["name"].includes(field.slug)
394
407
  );
395
- copiedSchema.identifiers.name = suitableField?.slug || "id";
408
+ copiedModel.identifiers.name = suitableField?.slug || "id";
396
409
  }
397
- if (!copiedSchema.identifiers.slug) {
410
+ if (!copiedModel.identifiers.slug) {
398
411
  const suitableField = newFields.find(
399
412
  (field) => field.type === "string" && field.unique === true && field.required === true && ["slug", "handle"].includes(field.slug)
400
413
  );
401
- copiedSchema.identifiers.slug = suitableField?.slug || "id";
414
+ copiedModel.identifiers.slug = suitableField?.slug || "id";
402
415
  }
403
- copiedSchema.fields = [...SYSTEM_FIELDS, ...newFields];
416
+ copiedModel.fields = [...SYSTEM_FIELDS, ...newFields];
404
417
  }
405
- return copiedSchema;
418
+ return copiedModel;
406
419
  };
407
420
  var SYSTEM_FIELDS = [
408
421
  {
@@ -442,9 +455,9 @@ var SYSTEM_FIELDS = [
442
455
  slug: "ronin.updatedBy"
443
456
  }
444
457
  ];
445
- var SYSTEM_SCHEMAS = [
458
+ var SYSTEM_MODELS = [
446
459
  {
447
- slug: "schema",
460
+ slug: "model",
448
461
  identifiers: {
449
462
  name: "name",
450
463
  slug: "slug"
@@ -455,6 +468,7 @@ var SYSTEM_SCHEMAS = [
455
468
  { slug: "slug", type: "string" },
456
469
  { slug: "pluralSlug", type: "string" },
457
470
  { slug: "idPrefix", type: "string" },
471
+ { slug: "table", type: "string" },
458
472
  { slug: "identifiers", type: "group" },
459
473
  { slug: "identifiers.name", type: "string" },
460
474
  { slug: "identifiers.slug", type: "string" },
@@ -475,9 +489,9 @@ var SYSTEM_SCHEMAS = [
475
489
  { slug: "slug", type: "string", required: true },
476
490
  { slug: "type", type: "string", required: true },
477
491
  {
478
- slug: "schema",
492
+ slug: "model",
479
493
  type: "reference",
480
- target: { slug: "schema" },
494
+ target: { slug: "model" },
481
495
  required: true
482
496
  },
483
497
  { slug: "required", type: "boolean" },
@@ -485,7 +499,7 @@ var SYSTEM_SCHEMAS = [
485
499
  { slug: "unique", type: "boolean" },
486
500
  { slug: "autoIncrement", type: "boolean" },
487
501
  // Only allowed for fields of type "reference".
488
- { slug: "target", type: "reference", target: { slug: "schema" } },
502
+ { slug: "target", type: "reference", target: { slug: "model" } },
489
503
  { slug: "kind", type: "string" },
490
504
  { slug: "actions", type: "group" },
491
505
  { slug: "actions.onDelete", type: "string" },
@@ -501,9 +515,9 @@ var SYSTEM_SCHEMAS = [
501
515
  fields: [
502
516
  { slug: "slug", type: "string", required: true },
503
517
  {
504
- slug: "schema",
518
+ slug: "model",
505
519
  type: "reference",
506
- target: { slug: "schema" },
520
+ target: { slug: "model" },
507
521
  required: true
508
522
  },
509
523
  { slug: "unique", type: "boolean" },
@@ -520,9 +534,9 @@ var SYSTEM_SCHEMAS = [
520
534
  fields: [
521
535
  { slug: "slug", type: "string", required: true },
522
536
  {
523
- slug: "schema",
537
+ slug: "model",
524
538
  type: "reference",
525
- target: { slug: "schema" },
539
+ target: { slug: "model" },
526
540
  required: true
527
541
  },
528
542
  { slug: "when", type: "string", required: true },
@@ -537,71 +551,71 @@ var SYSTEM_SCHEMAS = [
537
551
  fields: [
538
552
  { slug: "slug", type: "string", required: true },
539
553
  {
540
- slug: "schema",
554
+ slug: "model",
541
555
  type: "reference",
542
- target: { slug: "schema" },
556
+ target: { slug: "model" },
543
557
  required: true
544
558
  },
545
559
  { slug: "instructions", type: "json", required: true }
546
560
  ]
547
561
  }
548
- ].map((schema) => addDefaultSchemaFields(schema, true));
549
- var SYSTEM_SCHEMA_SLUGS = SYSTEM_SCHEMAS.flatMap(({ slug, pluralSlug }) => [
562
+ ].map((model) => addDefaultModelFields(model, true));
563
+ var SYSTEM_MODEL_SLUGS = SYSTEM_MODELS.flatMap(({ slug, pluralSlug }) => [
550
564
  slug,
551
565
  pluralSlug
552
566
  ]);
553
- var addSystemSchemas = (schemas) => {
554
- const associativeSchemas = schemas.flatMap((schema) => {
555
- const addedSchemas = [];
556
- for (const field of schema.fields || []) {
567
+ var addSystemModels = (models) => {
568
+ const associativeModels = models.flatMap((model) => {
569
+ const addedModels = [];
570
+ for (const field of model.fields || []) {
557
571
  if (field.type === "reference" && !field.slug.startsWith("ronin.")) {
558
- const relatedSchema = getSchemaBySlug(schemas, field.target.slug);
559
- let fieldSlug = relatedSchema.slug;
572
+ const relatedModel = getModelBySlug(models, field.target.slug);
573
+ let fieldSlug = relatedModel.slug;
560
574
  if (field.kind === "many") {
561
- fieldSlug = composeAssociationSchemaSlug(schema, field);
562
- addedSchemas.push({
575
+ fieldSlug = composeAssociationModelSlug(model, field);
576
+ addedModels.push({
563
577
  pluralSlug: fieldSlug,
564
578
  slug: fieldSlug,
579
+ associationSlug: field.slug,
565
580
  fields: [
566
581
  {
567
582
  slug: "source",
568
583
  type: "reference",
569
- target: { slug: schema.slug }
584
+ target: { slug: model.slug }
570
585
  },
571
586
  {
572
587
  slug: "target",
573
588
  type: "reference",
574
- target: { slug: relatedSchema.slug }
589
+ target: { slug: relatedModel.slug }
575
590
  }
576
591
  ]
577
592
  });
578
593
  }
579
594
  }
580
595
  }
581
- return addedSchemas;
596
+ return addedModels;
582
597
  });
583
- return [...SYSTEM_SCHEMAS, ...associativeSchemas, ...schemas];
598
+ return [...SYSTEM_MODELS, ...associativeModels, ...models];
584
599
  };
585
- var addDefaultSchemaPresets = (list, schema) => {
600
+ var addDefaultModelPresets = (list, model) => {
586
601
  const defaultPresets = [];
587
- for (const field of schema.fields || []) {
602
+ for (const field of model.fields || []) {
588
603
  if (field.type === "reference" && !field.slug.startsWith("ronin.")) {
589
- const relatedSchema = getSchemaBySlug(list, field.target.slug);
590
- let fieldSlug = relatedSchema.slug;
591
- if (field.kind === "many") {
592
- fieldSlug = composeAssociationSchemaSlug(schema, field);
593
- }
604
+ const relatedModel = getModelBySlug(list, field.target.slug);
605
+ if (field.kind === "many") continue;
594
606
  defaultPresets.push({
595
607
  instructions: {
596
608
  including: {
597
609
  [field.slug]: {
598
- [RONIN_SCHEMA_SYMBOLS.QUERY]: {
610
+ [RONIN_MODEL_SYMBOLS.QUERY]: {
599
611
  get: {
600
- [fieldSlug]: {
612
+ [relatedModel.slug]: {
601
613
  with: {
602
- // Compare the `id` field of the related schema to the reference field on
603
- // the root schema (`field.slug`).
604
- id: `${RONIN_SCHEMA_SYMBOLS.FIELD}${field.slug}`
614
+ // Compare the `id` field of the related model to the reference field on
615
+ // the root model (`field.slug`).
616
+ id: {
617
+ [RONIN_MODEL_SYMBOLS.EXPRESSION]: `${RONIN_MODEL_SYMBOLS.FIELD_PARENT}${field.slug}`
618
+ }
605
619
  }
606
620
  }
607
621
  }
@@ -613,25 +627,28 @@ var addDefaultSchemaPresets = (list, schema) => {
613
627
  });
614
628
  }
615
629
  }
616
- const childSchemas = list.map((subSchema) => {
617
- const field = subSchema.fields?.find((field2) => {
618
- return field2.type === "reference" && field2.target.slug === schema.slug;
630
+ const childModels = list.map((subModel) => {
631
+ const field = subModel.fields?.find((field2) => {
632
+ return field2.type === "reference" && field2.target.slug === model.slug;
619
633
  });
620
634
  if (!field) return null;
621
- return { schema: subSchema, field };
635
+ return { model: subModel, field };
622
636
  }).filter((match) => match !== null);
623
- for (const childMatch of childSchemas) {
624
- const { schema: childSchema, field: childField } = childMatch;
625
- const pluralSlug = childSchema.pluralSlug;
637
+ for (const childMatch of childModels) {
638
+ const { model: childModel, field: childField } = childMatch;
639
+ const pluralSlug = childModel.pluralSlug;
640
+ const presetSlug = childModel.associationSlug || pluralSlug;
626
641
  defaultPresets.push({
627
642
  instructions: {
628
643
  including: {
629
- [pluralSlug]: {
630
- [RONIN_SCHEMA_SYMBOLS.QUERY]: {
644
+ [presetSlug]: {
645
+ [RONIN_MODEL_SYMBOLS.QUERY]: {
631
646
  get: {
632
647
  [pluralSlug]: {
633
648
  with: {
634
- [childField.slug]: `${RONIN_SCHEMA_SYMBOLS.FIELD}id`
649
+ [childField.slug]: {
650
+ [RONIN_MODEL_SYMBOLS.EXPRESSION]: `${RONIN_MODEL_SYMBOLS.FIELD_PARENT}id`
651
+ }
635
652
  }
636
653
  }
637
654
  }
@@ -639,13 +656,13 @@ var addDefaultSchemaPresets = (list, schema) => {
639
656
  }
640
657
  }
641
658
  },
642
- slug: pluralSlug
659
+ slug: presetSlug
643
660
  });
644
661
  }
645
662
  if (Object.keys(defaultPresets).length > 0) {
646
- schema.presets = [...defaultPresets, ...schema.presets || []];
663
+ model.presets = [...defaultPresets, ...model.presets || []];
647
664
  }
648
- return schema;
665
+ return model;
649
666
  };
650
667
  var mappedInstructions = {
651
668
  create: "to",
@@ -681,35 +698,31 @@ var getFieldStatement = (field) => {
681
698
  }
682
699
  return statement;
683
700
  };
684
- var addSchemaQueries = (schemas, queryDetails, dependencyStatements) => {
685
- const {
686
- queryType,
687
- querySchema,
688
- queryInstructions: queryInstructionsRaw
689
- } = queryDetails;
701
+ var addModelQueries = (models, queryDetails, dependencyStatements) => {
702
+ const { queryType, queryModel, queryInstructions: queryInstructionsRaw } = queryDetails;
690
703
  const queryInstructions = queryInstructionsRaw;
691
704
  if (!["create", "set", "drop"].includes(queryType)) return queryInstructions;
692
- if (!SYSTEM_SCHEMA_SLUGS.includes(querySchema)) return queryInstructions;
705
+ if (!SYSTEM_MODEL_SLUGS.includes(queryModel)) return queryInstructions;
693
706
  const instructionName = mappedInstructions[queryType];
694
707
  const instructionList = queryInstructions[instructionName];
695
- const kind = getSchemaBySlug(SYSTEM_SCHEMAS, querySchema).pluralSlug;
708
+ const kind = getModelBySlug(SYSTEM_MODELS, queryModel).pluralSlug;
696
709
  let tableAction = "ALTER";
697
710
  let queryTypeReadable = null;
698
711
  switch (queryType) {
699
712
  case "create": {
700
- if (kind === "schemas" || kind === "indexes" || kind === "triggers") {
713
+ if (kind === "models" || kind === "indexes" || kind === "triggers") {
701
714
  tableAction = "CREATE";
702
715
  }
703
716
  queryTypeReadable = "creating";
704
717
  break;
705
718
  }
706
719
  case "set": {
707
- if (kind === "schemas") tableAction = "ALTER";
720
+ if (kind === "models") tableAction = "ALTER";
708
721
  queryTypeReadable = "updating";
709
722
  break;
710
723
  }
711
724
  case "drop": {
712
- if (kind === "schemas" || kind === "indexes" || kind === "triggers") {
725
+ if (kind === "models" || kind === "indexes" || kind === "triggers") {
713
726
  tableAction = "DROP";
714
727
  }
715
728
  queryTypeReadable = "deleting";
@@ -724,18 +737,18 @@ var addSchemaQueries = (schemas, queryDetails, dependencyStatements) => {
724
737
  fields: ["slug"]
725
738
  });
726
739
  }
727
- const schemaInstruction = instructionList?.schema;
728
- const schemaSlug = schemaInstruction?.slug?.being || schemaInstruction?.slug;
729
- if (kind !== "schemas" && !schemaSlug) {
740
+ const modelInstruction = instructionList?.model;
741
+ const modelSlug = modelInstruction?.slug?.being || modelInstruction?.slug;
742
+ if (kind !== "models" && !modelSlug) {
730
743
  throw new RoninError({
731
- message: `When ${queryTypeReadable} ${kind}, a \`schema.slug\` field must be provided in the \`${instructionName}\` instruction.`,
744
+ message: `When ${queryTypeReadable} ${kind}, a \`model.slug\` field must be provided in the \`${instructionName}\` instruction.`,
732
745
  code: "MISSING_FIELD",
733
- fields: ["schema.slug"]
746
+ fields: ["model.slug"]
734
747
  });
735
748
  }
736
- const usableSlug = kind === "schemas" ? slug : schemaSlug;
749
+ const usableSlug = kind === "models" ? slug : modelSlug;
737
750
  const tableName = convertToSnakeCase(pluralize(usableSlug));
738
- const targetSchema = kind === "schemas" && queryType === "create" ? null : getSchemaBySlug(schemas, usableSlug);
751
+ const targetModel = kind === "models" && queryType === "create" ? null : getModelBySlug(models, usableSlug);
739
752
  if (kind === "indexes") {
740
753
  const indexName = convertToSnakeCase(slug);
741
754
  const unique = instructionList?.unique;
@@ -744,16 +757,13 @@ var addSchemaQueries = (schemas, queryDetails, dependencyStatements) => {
744
757
  const params = [];
745
758
  let statement2 = `${tableAction}${unique ? " UNIQUE" : ""} INDEX "${indexName}"`;
746
759
  if (queryType === "create") {
747
- const schema = targetSchema;
760
+ const model = targetModel;
748
761
  const columns = fields.map((field) => {
749
762
  let fieldSelector = "";
750
763
  if ("slug" in field) {
751
- ({ fieldSelector } = getFieldFromSchema(schema, field.slug, "to"));
764
+ ({ fieldSelector } = getFieldFromModel(model, field.slug, "to"));
752
765
  } else if ("expression" in field) {
753
- fieldSelector = field.expression.replace(RONIN_SCHEMA_FIELD_REGEX, (match) => {
754
- const fieldSlug = match.replace(RONIN_SCHEMA_SYMBOLS.FIELD, "");
755
- return getFieldFromSchema(schema, fieldSlug, "to").fieldSelector;
756
- });
766
+ fieldSelector = parseFieldExpression(model, "to", field.expression, model);
757
767
  }
758
768
  if (field.collation) fieldSelector += ` COLLATE ${field.collation}`;
759
769
  if (field.order) fieldSelector += ` ${field.order}`;
@@ -762,8 +772,8 @@ var addSchemaQueries = (schemas, queryDetails, dependencyStatements) => {
762
772
  statement2 += ` ON "${tableName}" (${columns.join(", ")})`;
763
773
  if (filterQuery) {
764
774
  const withStatement = handleWith(
765
- schemas,
766
- targetSchema,
775
+ models,
776
+ targetModel,
767
777
  params,
768
778
  filterQuery
769
779
  );
@@ -778,6 +788,7 @@ var addSchemaQueries = (schemas, queryDetails, dependencyStatements) => {
778
788
  const params = [];
779
789
  let statement2 = `${tableAction} TRIGGER "${triggerName}"`;
780
790
  if (queryType === "create") {
791
+ const currentModel = targetModel;
781
792
  const { when, action } = instructionList;
782
793
  const statementParts = [`${when} ${action}`];
783
794
  const effectQueries = instructionList?.effects;
@@ -787,33 +798,33 @@ var addSchemaQueries = (schemas, queryDetails, dependencyStatements) => {
787
798
  if (action !== "UPDATE") {
788
799
  throw new RoninError({
789
800
  message: `When ${queryTypeReadable} ${kind}, targeting specific fields requires the \`UPDATE\` action.`,
790
- code: "INVALID_SCHEMA_VALUE",
801
+ code: "INVALID_MODEL_VALUE",
791
802
  fields: ["action"]
792
803
  });
793
804
  }
794
805
  const fieldSelectors = fields.map((field) => {
795
- return getFieldFromSchema(targetSchema, field.slug, "to").fieldSelector;
806
+ return getFieldFromModel(currentModel, field.slug, "to").fieldSelector;
796
807
  });
797
808
  statementParts.push(`OF (${fieldSelectors.join(", ")})`);
798
809
  }
799
810
  statementParts.push("ON", `"${tableName}"`);
800
- if (filterQuery || effectQueries.some((query) => findInObject(query, RONIN_SCHEMA_SYMBOLS.FIELD))) {
811
+ if (filterQuery || effectQueries.some((query) => findInObject(query, RONIN_MODEL_SYMBOLS.FIELD))) {
801
812
  statementParts.push("FOR EACH ROW");
802
813
  }
803
814
  if (filterQuery) {
804
- const tablePlaceholder = action === "DELETE" ? RONIN_SCHEMA_SYMBOLS.FIELD_OLD : RONIN_SCHEMA_SYMBOLS.FIELD_NEW;
815
+ const tableAlias = action === "DELETE" ? RONIN_MODEL_SYMBOLS.FIELD_PARENT_OLD : RONIN_MODEL_SYMBOLS.FIELD_PARENT_NEW;
805
816
  const withStatement = handleWith(
806
- schemas,
807
- targetSchema,
817
+ models,
818
+ { ...currentModel, tableAlias },
808
819
  params,
809
- filterQuery,
810
- tablePlaceholder
820
+ filterQuery
811
821
  );
812
822
  statementParts.push("WHEN", `(${withStatement})`);
813
823
  }
814
824
  const effectStatements = effectQueries.map((effectQuery) => {
815
- return compileQueryInput(effectQuery, schemas, params, {
816
- returning: false
825
+ return compileQueryInput(effectQuery, models, params, {
826
+ returning: false,
827
+ parentModel: currentModel
817
828
  }).main.statement;
818
829
  });
819
830
  if (effectStatements.length > 1) statementParts.push("BEGIN");
@@ -825,14 +836,14 @@ var addSchemaQueries = (schemas, queryDetails, dependencyStatements) => {
825
836
  return queryInstructions;
826
837
  }
827
838
  const statement = `${tableAction} TABLE "${tableName}"`;
828
- if (kind === "schemas") {
839
+ if (kind === "models") {
829
840
  if (queryType === "create" || queryType === "set") {
830
- const schemaWithFields = addDefaultSchemaFields(
841
+ const modelWithFields = addDefaultModelFields(
831
842
  queryInstructions.to,
832
843
  queryType === "create"
833
844
  );
834
- const schemaWithPresets = addDefaultSchemaPresets(schemas, schemaWithFields);
835
- queryInstructions.to = schemaWithPresets;
845
+ const modelWithPresets = addDefaultModelPresets(models, modelWithFields);
846
+ queryInstructions.to = modelWithPresets;
836
847
  }
837
848
  if (queryType === "create") {
838
849
  const { fields } = queryInstructions.to;
@@ -841,7 +852,7 @@ var addSchemaQueries = (schemas, queryDetails, dependencyStatements) => {
841
852
  statement: `${statement} (${columns.join(", ")})`,
842
853
  params: []
843
854
  });
844
- schemas.push(queryInstructions.to);
855
+ models.push(queryInstructions.to);
845
856
  } else if (queryType === "set") {
846
857
  const newSlug = queryInstructions.to?.pluralSlug;
847
858
  if (newSlug) {
@@ -851,9 +862,9 @@ var addSchemaQueries = (schemas, queryDetails, dependencyStatements) => {
851
862
  params: []
852
863
  });
853
864
  }
854
- Object.assign(targetSchema, queryInstructions.to);
865
+ Object.assign(targetModel, queryInstructions.to);
855
866
  } else if (queryType === "drop") {
856
- schemas.splice(schemas.indexOf(targetSchema), 1);
867
+ models.splice(models.indexOf(targetModel), 1);
857
868
  dependencyStatements.push({ statement, params: [] });
858
869
  }
859
870
  return queryInstructions;
@@ -892,7 +903,7 @@ var addSchemaQueries = (schemas, queryDetails, dependencyStatements) => {
892
903
  // src/instructions/before-after.ts
893
904
  var CURSOR_SEPARATOR = ",";
894
905
  var CURSOR_NULL_PLACEHOLDER = "RONIN_NULL";
895
- var handleBeforeOrAfter = (schema, statementParams, instructions, rootTable) => {
906
+ var handleBeforeOrAfter = (model, statementParams, instructions) => {
896
907
  if (!(instructions.before || instructions.after)) {
897
908
  throw new RoninError({
898
909
  message: "The `before` or `after` instruction must not be empty.",
@@ -923,7 +934,7 @@ var handleBeforeOrAfter = (schema, statementParams, instructions, rootTable) =>
923
934
  if (value === CURSOR_NULL_PLACEHOLDER) {
924
935
  return "NULL";
925
936
  }
926
- const { field } = getFieldFromSchema(schema, key, "orderedBy");
937
+ const { field } = getFieldFromModel(model, key, "orderedBy");
927
938
  if (field.type === "boolean") {
928
939
  return prepareStatementValue(statementParams, value === "true");
929
940
  }
@@ -949,12 +960,7 @@ var handleBeforeOrAfter = (schema, statementParams, instructions, rootTable) =>
949
960
  for (let j = 0; j <= i; j++) {
950
961
  const key = keys[j];
951
962
  const value = values[j];
952
- let { field, fieldSelector } = getFieldFromSchema(
953
- schema,
954
- key,
955
- "orderedBy",
956
- rootTable
957
- );
963
+ let { field, fieldSelector } = getFieldFromModel(model, key, "orderedBy");
958
964
  if (j === i) {
959
965
  const closingParentheses = ")".repeat(condition.length);
960
966
  const operator = value === "NULL" ? "IS NOT" : compareOperators[j];
@@ -976,14 +982,14 @@ var handleBeforeOrAfter = (schema, statementParams, instructions, rootTable) =>
976
982
  };
977
983
 
978
984
  // src/instructions/for.ts
979
- var handleFor = (schema, instructions) => {
985
+ var handleFor = (model, instructions) => {
980
986
  const normalizedFor = Array.isArray(instructions.for) ? Object.fromEntries(instructions.for.map((presetSlug) => [presetSlug, null])) : instructions.for;
981
987
  for (const presetSlug in normalizedFor) {
982
988
  const arg = normalizedFor[presetSlug];
983
- const preset = schema.presets?.find((preset2) => preset2.slug === presetSlug);
989
+ const preset = model.presets?.find((preset2) => preset2.slug === presetSlug);
984
990
  if (!preset) {
985
991
  throw new RoninError({
986
- message: `Preset "${presetSlug}" does not exist in schema "${schema.name}".`,
992
+ message: `Preset "${presetSlug}" does not exist in model "${model.name}".`,
987
993
  code: "PRESET_NOT_FOUND"
988
994
  });
989
995
  }
@@ -991,8 +997,8 @@ var handleFor = (schema, instructions) => {
991
997
  if (arg !== null) {
992
998
  findInObject(
993
999
  replacedForFilter,
994
- RONIN_SCHEMA_SYMBOLS.VALUE,
995
- (match) => match.replace(RONIN_SCHEMA_SYMBOLS.VALUE, arg)
1000
+ RONIN_MODEL_SYMBOLS.VALUE,
1001
+ (match) => match.replace(RONIN_MODEL_SYMBOLS.VALUE, arg)
996
1002
  );
997
1003
  }
998
1004
  for (const subInstruction in replacedForFilter) {
@@ -1023,20 +1029,19 @@ var handleFor = (schema, instructions) => {
1023
1029
  };
1024
1030
 
1025
1031
  // src/instructions/including.ts
1026
- var handleIncluding = (schemas, statementParams, instruction, rootTable) => {
1032
+ var handleIncluding = (models, model, statementParams, instruction) => {
1027
1033
  let statement = "";
1028
- let rootTableSubQuery;
1029
- let rootTableName = rootTable;
1034
+ let tableSubQuery;
1030
1035
  for (const ephemeralFieldSlug in instruction) {
1031
- const includingQuery = getSubQuery(instruction[ephemeralFieldSlug]);
1032
- if (!includingQuery) continue;
1033
- const { queryType, querySchema, queryInstructions } = splitQuery(includingQuery);
1036
+ const symbol = getSymbol(instruction[ephemeralFieldSlug]);
1037
+ if (symbol?.type !== "query") continue;
1038
+ const { queryType, queryModel, queryInstructions } = splitQuery(symbol.value);
1034
1039
  let modifiableQueryInstructions = queryInstructions;
1035
- const relatedSchema = getSchemaBySlug(schemas, querySchema);
1040
+ const relatedModel = getModelBySlug(models, queryModel);
1036
1041
  let joinType = "LEFT";
1037
- let relatedTableSelector = `"${getTableForSchema(relatedSchema)}"`;
1042
+ let relatedTableSelector = `"${relatedModel.table}"`;
1038
1043
  const tableAlias = `including_${ephemeralFieldSlug}`;
1039
- const single = querySchema !== relatedSchema.pluralSlug;
1044
+ const single = queryModel !== relatedModel.pluralSlug;
1040
1045
  if (!modifiableQueryInstructions?.with) {
1041
1046
  joinType = "CROSS";
1042
1047
  if (single) {
@@ -1048,35 +1053,35 @@ var handleIncluding = (schemas, statementParams, instruction, rootTable) => {
1048
1053
  const subSelect = compileQueryInput(
1049
1054
  {
1050
1055
  [queryType]: {
1051
- [querySchema]: modifiableQueryInstructions
1056
+ [queryModel]: modifiableQueryInstructions
1052
1057
  }
1053
1058
  },
1054
- schemas,
1059
+ models,
1055
1060
  statementParams
1056
1061
  );
1057
1062
  relatedTableSelector = `(${subSelect.main.statement})`;
1058
1063
  }
1059
1064
  statement += `${joinType} JOIN ${relatedTableSelector} as ${tableAlias}`;
1065
+ model.tableAlias = model.table;
1060
1066
  if (joinType === "LEFT") {
1061
1067
  if (!single) {
1062
- rootTableSubQuery = `SELECT * FROM "${rootTable}" LIMIT 1`;
1063
- rootTableName = `sub_${rootTable}`;
1068
+ tableSubQuery = `SELECT * FROM "${model.table}" LIMIT 1`;
1069
+ model.tableAlias = `sub_${model.table}`;
1064
1070
  }
1065
1071
  const subStatement = composeConditions(
1066
- schemas,
1067
- relatedSchema,
1072
+ models,
1073
+ { ...relatedModel, tableAlias },
1068
1074
  statementParams,
1069
1075
  "including",
1070
1076
  queryInstructions?.with,
1071
1077
  {
1072
- rootTable: rootTableName,
1073
- customTable: tableAlias
1078
+ parentModel: model
1074
1079
  }
1075
1080
  );
1076
1081
  statement += ` ON (${subStatement})`;
1077
1082
  }
1078
1083
  }
1079
- return { statement, rootTableSubQuery, rootTableName };
1084
+ return { statement, tableSubQuery };
1080
1085
  };
1081
1086
 
1082
1087
  // src/instructions/limited-to.ts
@@ -1088,46 +1093,43 @@ var handleLimitedTo = (single, instruction) => {
1088
1093
  };
1089
1094
 
1090
1095
  // src/instructions/ordered-by.ts
1091
- var handleOrderedBy = (schema, instruction, rootTable) => {
1096
+ var handleOrderedBy = (model, instruction) => {
1092
1097
  let statement = "";
1093
- for (const field of instruction.ascending || []) {
1094
- const { field: schemaField, fieldSelector } = getFieldFromSchema(
1095
- schema,
1096
- field,
1097
- "orderedBy.ascending",
1098
- rootTable
1099
- );
1098
+ const items = [
1099
+ ...(instruction.ascending || []).map((value) => ({ value, order: "ASC" })),
1100
+ ...(instruction.descending || []).map((value) => ({ value, order: "DESC" }))
1101
+ ];
1102
+ for (const item of items) {
1100
1103
  if (statement.length > 0) {
1101
1104
  statement += ", ";
1102
1105
  }
1103
- const caseInsensitiveStatement = schemaField.type === "string" ? " COLLATE NOCASE" : "";
1104
- statement += `${fieldSelector}${caseInsensitiveStatement} ASC`;
1105
- }
1106
- for (const field of instruction.descending || []) {
1107
- const { field: schemaField, fieldSelector } = getFieldFromSchema(
1108
- schema,
1109
- field,
1110
- "orderedBy.descending",
1111
- rootTable
1112
- );
1113
- if (statement.length > 0) {
1114
- statement += ", ";
1106
+ const symbol = getSymbol(item.value);
1107
+ const instructionName = item.order === "ASC" ? "orderedBy.ascending" : "orderedBy.descending";
1108
+ if (symbol?.type === "expression") {
1109
+ statement += `(${parseFieldExpression(model, instructionName, symbol.value)}) ${item.order}`;
1110
+ continue;
1115
1111
  }
1116
- const caseInsensitiveStatement = schemaField.type === "string" ? " COLLATE NOCASE" : "";
1117
- statement += `${fieldSelector}${caseInsensitiveStatement} DESC`;
1112
+ const { field: modelField, fieldSelector } = getFieldFromModel(
1113
+ model,
1114
+ item.value,
1115
+ instructionName
1116
+ );
1117
+ const caseInsensitiveStatement = modelField.type === "string" ? " COLLATE NOCASE" : "";
1118
+ statement += `${fieldSelector}${caseInsensitiveStatement} ${item.order}`;
1118
1119
  }
1119
1120
  return `ORDER BY ${statement}`;
1120
1121
  };
1121
1122
 
1122
1123
  // src/instructions/selecting.ts
1123
- var handleSelecting = (schema, statementParams, instructions) => {
1124
+ var handleSelecting = (model, statementParams, instructions) => {
1124
1125
  let isJoining = false;
1125
1126
  let statement = instructions.selecting ? instructions.selecting.map((slug) => {
1126
- return getFieldFromSchema(schema, slug, "selecting").fieldSelector;
1127
+ return getFieldFromModel(model, slug, "selecting").fieldSelector;
1127
1128
  }).join(", ") : "*";
1128
1129
  if (instructions.including) {
1129
1130
  const filteredObject = Object.entries(instructions.including).filter(([_, value]) => {
1130
- const hasQuery = getSubQuery(value);
1131
+ const symbol = getSymbol(value);
1132
+ const hasQuery = symbol?.type === "query";
1131
1133
  if (hasQuery) isJoining = true;
1132
1134
  return !hasQuery;
1133
1135
  });
@@ -1143,12 +1145,12 @@ var handleSelecting = (schema, statementParams, instructions) => {
1143
1145
  };
1144
1146
 
1145
1147
  // src/instructions/to.ts
1146
- var handleTo = (schemas, schema, statementParams, queryType, dependencyStatements, instructions, rootTable) => {
1148
+ var handleTo = (models, model, statementParams, queryType, dependencyStatements, instructions, parentModel) => {
1147
1149
  const currentTime = (/* @__PURE__ */ new Date()).toISOString();
1148
1150
  const { with: withInstruction, to: toInstruction } = instructions;
1149
1151
  const defaultFields = {};
1150
1152
  if (queryType === "create") {
1151
- defaultFields.id = toInstruction.id || generateRecordId(schema.idPrefix);
1153
+ defaultFields.id = toInstruction.id || generateRecordId(model.idPrefix);
1152
1154
  }
1153
1155
  defaultFields.ronin = {
1154
1156
  // If records are being created, set their creation time.
@@ -1158,20 +1160,20 @@ var handleTo = (schemas, schema, statementParams, queryType, dependencyStatement
1158
1160
  // Allow for overwriting the default values provided above.
1159
1161
  ...toInstruction.ronin
1160
1162
  };
1161
- const subQuery = getSubQuery(toInstruction);
1162
- if (subQuery) {
1163
- let { querySchema: subQuerySchemaSlug, queryInstructions: subQueryInstructions } = splitQuery(subQuery);
1164
- const subQuerySchema = getSchemaBySlug(schemas, subQuerySchemaSlug);
1163
+ const symbol = getSymbol(toInstruction);
1164
+ if (symbol?.type === "query") {
1165
+ let { queryModel: subQueryModelSlug, queryInstructions: subQueryInstructions } = splitQuery(symbol.value);
1166
+ const subQueryModel = getModelBySlug(models, subQueryModelSlug);
1165
1167
  const subQuerySelectedFields = subQueryInstructions?.selecting;
1166
1168
  const subQueryIncludedFields = subQueryInstructions?.including;
1167
1169
  const subQueryFields = [
1168
- ...subQuerySelectedFields || (subQuerySchema.fields || []).map((field) => field.slug),
1170
+ ...subQuerySelectedFields || (subQueryModel.fields || []).map((field) => field.slug),
1169
1171
  ...subQueryIncludedFields ? Object.keys(
1170
1172
  flatten(subQueryIncludedFields || {})
1171
1173
  ) : []
1172
1174
  ];
1173
1175
  for (const field of subQueryFields || []) {
1174
- getFieldFromSchema(schema, field, "to");
1176
+ getFieldFromModel(model, field, "to");
1175
1177
  }
1176
1178
  const defaultFieldsToAdd = subQuerySelectedFields ? Object.entries(flatten(defaultFields)).filter(([key]) => {
1177
1179
  return !subQuerySelectedFields.includes(key);
@@ -1184,18 +1186,15 @@ var handleTo = (schemas, schema, statementParams, queryType, dependencyStatement
1184
1186
  ...subQueryInstructions.including
1185
1187
  };
1186
1188
  }
1187
- return compileQueryInput(subQuery, schemas, statementParams).main.statement;
1189
+ return compileQueryInput(symbol.value, models, statementParams).main.statement;
1188
1190
  }
1189
1191
  Object.assign(toInstruction, defaultFields);
1190
1192
  for (const fieldSlug in toInstruction) {
1191
1193
  const fieldValue = toInstruction[fieldSlug];
1192
- const fieldDetails = getFieldFromSchema(schema, fieldSlug, "to");
1194
+ const fieldDetails = getFieldFromModel(model, fieldSlug, "to");
1193
1195
  if (fieldDetails.field.type === "reference" && fieldDetails.field.kind === "many") {
1194
1196
  delete toInstruction[fieldSlug];
1195
- const associativeSchemaSlug = composeAssociationSchemaSlug(
1196
- schema,
1197
- fieldDetails.field
1198
- );
1197
+ const associativeModelSlug = composeAssociationModelSlug(model, fieldDetails.field);
1199
1198
  const composeStatement = (subQueryType, value) => {
1200
1199
  const source = queryType === "create" ? { id: toInstruction.id } : withInstruction;
1201
1200
  const recordDetails = { source };
@@ -1203,10 +1202,10 @@ var handleTo = (schemas, schema, statementParams, queryType, dependencyStatement
1203
1202
  return compileQueryInput(
1204
1203
  {
1205
1204
  [subQueryType]: {
1206
- [associativeSchemaSlug]: subQueryType === "create" ? { to: recordDetails } : { with: recordDetails }
1205
+ [associativeModelSlug]: subQueryType === "create" ? { to: recordDetails } : { with: recordDetails }
1207
1206
  }
1208
1207
  },
1209
- schemas,
1208
+ models,
1210
1209
  [],
1211
1210
  { returning: false }
1212
1211
  ).main;
@@ -1226,26 +1225,19 @@ var handleTo = (schemas, schema, statementParams, queryType, dependencyStatement
1226
1225
  }
1227
1226
  }
1228
1227
  }
1229
- let statement = composeConditions(
1230
- schemas,
1231
- schema,
1232
- statementParams,
1233
- "to",
1234
- toInstruction,
1235
- {
1236
- rootTable,
1237
- type: queryType === "create" ? "fields" : void 0
1238
- }
1239
- );
1228
+ let statement = composeConditions(models, model, statementParams, "to", toInstruction, {
1229
+ parentModel,
1230
+ type: queryType === "create" ? "fields" : void 0
1231
+ });
1240
1232
  if (queryType === "create") {
1241
1233
  const deepStatement = composeConditions(
1242
- schemas,
1243
- schema,
1234
+ models,
1235
+ model,
1244
1236
  statementParams,
1245
1237
  "to",
1246
1238
  toInstruction,
1247
1239
  {
1248
- rootTable,
1240
+ parentModel,
1249
1241
  type: "values"
1250
1242
  }
1251
1243
  );
@@ -1257,24 +1249,23 @@ var handleTo = (schemas, schema, statementParams, queryType, dependencyStatement
1257
1249
  };
1258
1250
 
1259
1251
  // src/utils/index.ts
1260
- var compileQueryInput = (query, schemas, statementParams, options) => {
1252
+ var compileQueryInput = (query, models, statementParams, options) => {
1261
1253
  const parsedQuery = splitQuery(query);
1262
- const { queryType, querySchema, queryInstructions } = parsedQuery;
1263
- const schema = getSchemaBySlug(schemas, querySchema);
1264
- const single = querySchema !== schema.pluralSlug;
1265
- let instructions = formatIdentifiers(schema, queryInstructions);
1266
- let table = getTableForSchema(schema);
1254
+ const { queryType, queryModel, queryInstructions } = parsedQuery;
1255
+ const model = getModelBySlug(models, queryModel);
1256
+ const single = queryModel !== model.pluralSlug;
1257
+ let instructions = formatIdentifiers(model, queryInstructions);
1267
1258
  const dependencyStatements = [];
1268
1259
  const returning = options?.returning ?? true;
1269
- instructions = addSchemaQueries(
1270
- schemas,
1271
- { queryType, querySchema, queryInstructions: instructions },
1260
+ instructions = addModelQueries(
1261
+ models,
1262
+ { queryType, queryModel, queryInstructions: instructions },
1272
1263
  dependencyStatements
1273
1264
  );
1274
1265
  if (instructions && Object.hasOwn(instructions, "for")) {
1275
- instructions = handleFor(schema, instructions);
1266
+ instructions = handleFor(model, instructions);
1276
1267
  }
1277
- const { columns, isJoining } = handleSelecting(schema, statementParams, {
1268
+ const { columns, isJoining } = handleSelecting(model, statementParams, {
1278
1269
  selecting: instructions?.selecting,
1279
1270
  including: instructions?.including
1280
1271
  });
@@ -1298,21 +1289,21 @@ var compileQueryInput = (query, schemas, statementParams, options) => {
1298
1289
  }
1299
1290
  let isJoiningMultipleRows = false;
1300
1291
  if (isJoining) {
1301
- const {
1302
- statement: including,
1303
- rootTableSubQuery,
1304
- rootTableName
1305
- } = handleIncluding(schemas, statementParams, instructions?.including, table);
1306
- if (rootTableSubQuery && rootTableName) {
1307
- table = rootTableName;
1308
- statement += `(${rootTableSubQuery}) as ${rootTableName} `;
1292
+ const { statement: including, tableSubQuery } = handleIncluding(
1293
+ models,
1294
+ model,
1295
+ statementParams,
1296
+ instructions?.including
1297
+ );
1298
+ if (tableSubQuery) {
1299
+ statement += `(${tableSubQuery}) as ${model.tableAlias} `;
1309
1300
  isJoiningMultipleRows = true;
1310
1301
  } else {
1311
- statement += `"${table}" `;
1302
+ statement += `"${model.table}" `;
1312
1303
  }
1313
1304
  statement += `${including} `;
1314
1305
  } else {
1315
- statement += `"${table}" `;
1306
+ statement += `"${model.table}" `;
1316
1307
  }
1317
1308
  if (queryType === "create" || queryType === "set") {
1318
1309
  if (!isObject(instructions.to) || Object.keys(instructions.to).length === 0) {
@@ -1323,24 +1314,24 @@ var compileQueryInput = (query, schemas, statementParams, options) => {
1323
1314
  });
1324
1315
  }
1325
1316
  const toStatement = handleTo(
1326
- schemas,
1327
- schema,
1317
+ models,
1318
+ model,
1328
1319
  statementParams,
1329
1320
  queryType,
1330
1321
  dependencyStatements,
1331
1322
  { with: instructions.with, to: instructions.to },
1332
- isJoining ? table : void 0
1323
+ options?.parentModel
1333
1324
  );
1334
1325
  statement += `${toStatement} `;
1335
1326
  }
1336
1327
  const conditions = [];
1337
1328
  if (queryType !== "create" && instructions && Object.hasOwn(instructions, "with")) {
1338
1329
  const withStatement = handleWith(
1339
- schemas,
1340
- schema,
1330
+ models,
1331
+ model,
1341
1332
  statementParams,
1342
1333
  instructions?.with,
1343
- isJoining ? table : void 0
1334
+ options?.parentModel
1344
1335
  );
1345
1336
  if (withStatement.length > 0) conditions.push(withStatement);
1346
1337
  }
@@ -1364,18 +1355,13 @@ var compileQueryInput = (query, schemas, statementParams, options) => {
1364
1355
  queries: [query]
1365
1356
  });
1366
1357
  }
1367
- const beforeAndAfterStatement = handleBeforeOrAfter(
1368
- schema,
1369
- statementParams,
1370
- {
1371
- before: instructions.before,
1372
- after: instructions.after,
1373
- with: instructions.with,
1374
- orderedBy: instructions.orderedBy,
1375
- limitedTo: instructions.limitedTo
1376
- },
1377
- isJoining ? table : void 0
1378
- );
1358
+ const beforeAndAfterStatement = handleBeforeOrAfter(model, statementParams, {
1359
+ before: instructions.before,
1360
+ after: instructions.after,
1361
+ with: instructions.with,
1362
+ orderedBy: instructions.orderedBy,
1363
+ limitedTo: instructions.limitedTo
1364
+ });
1379
1365
  conditions.push(beforeAndAfterStatement);
1380
1366
  }
1381
1367
  if (conditions.length > 0) {
@@ -1386,11 +1372,7 @@ var compileQueryInput = (query, schemas, statementParams, options) => {
1386
1372
  }
1387
1373
  }
1388
1374
  if (instructions?.orderedBy) {
1389
- const orderedByStatement = handleOrderedBy(
1390
- schema,
1391
- instructions.orderedBy,
1392
- isJoining ? table : void 0
1393
- );
1375
+ const orderedByStatement = handleOrderedBy(model, instructions.orderedBy);
1394
1376
  statement += `${orderedByStatement} `;
1395
1377
  }
1396
1378
  if (queryType === "get" && !isJoiningMultipleRows && (single || instructions?.limitedTo)) {
@@ -1411,19 +1393,19 @@ var compileQueryInput = (query, schemas, statementParams, options) => {
1411
1393
  };
1412
1394
 
1413
1395
  // src/index.ts
1414
- var compileQueries = (queries, schemas, options) => {
1415
- const schemaList = addSystemSchemas(schemas).map((schema) => {
1416
- return addDefaultSchemaFields(schema, true);
1396
+ var compileQueries = (queries, models, options) => {
1397
+ const modelList = addSystemModels(models).map((model) => {
1398
+ return addDefaultModelFields(model, true);
1417
1399
  });
1418
- const schemaListWithPresets = schemaList.map((schema) => {
1419
- return addDefaultSchemaPresets(schemaList, schema);
1400
+ const modelListWithPresets = modelList.map((model) => {
1401
+ return addDefaultModelPresets(modelList, model);
1420
1402
  });
1421
1403
  const dependencyStatements = [];
1422
1404
  const mainStatements = [];
1423
1405
  for (const query of queries) {
1424
1406
  const result = compileQueryInput(
1425
1407
  query,
1426
- schemaListWithPresets,
1408
+ modelListWithPresets,
1427
1409
  options?.inlineParams ? null : []
1428
1410
  );
1429
1411
  dependencyStatements.push(...result.dependencies);