@ronin/compiler 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -39,7 +39,7 @@ You will just need to make sure that, once you [create a pull request](https://d
39
39
  The programmatic API of the RONIN compiler looks like this:
40
40
 
41
41
  ```typescript
42
- import { compileQueryInput } from '@ronin/compiler';
42
+ import { compileQuery } from '@ronin/compiler';
43
43
 
44
44
  const query = {
45
45
  get: {
@@ -53,12 +53,27 @@ const schemas = [
53
53
  },
54
54
  ];
55
55
 
56
- const { writeStatements, readStatement } = compileQueryInput(query, schemas);
56
+ const { writeStatements, readStatement } = compileQuery(query, schemas);
57
57
 
58
58
  console.log(readStatement);
59
59
  // SELECT * FROM "accounts" ORDER BY "ronin.createdAt" DESC LIMIT 101
60
60
  ```
61
61
 
62
+ #### Options
63
+
64
+ To fine-tune the behavior of the compiler, you can pass the following options:
65
+
66
+ ```typescript
67
+ compileQuery(query, schemas, {
68
+ // Instead of returning an array of values for every statement (which allows for
69
+ // preventing SQL injections), all values are inlined directly into the SQL strings.
70
+ // This option should only be used if the generated SQL will be manually verified.
71
+ inlineValues: true
72
+ });
73
+ ```
74
+
75
+ #### Transpilation
76
+
62
77
  In order to be compatible with a wide range of projects, the source code of the `compiler` repo needs to be compiled (transpiled) whenever you make changes to it. To automate this, you can keep this command running in your terminal:
63
78
 
64
79
  ```bash
package/dist/index.d.ts CHANGED
@@ -18940,9 +18940,9 @@ interface Schema {
18940
18940
  pluralName?: string;
18941
18941
  slug: string;
18942
18942
  pluralSlug?: string;
18943
- identifiers?: {
18944
- title?: string;
18945
- slug?: string;
18943
+ identifiers: {
18944
+ name: string;
18945
+ slug: string;
18946
18946
  };
18947
18947
  idPrefix?: string;
18948
18948
  including?: Record<string, Query>;
@@ -18951,6 +18951,10 @@ interface Schema {
18951
18951
  indexes?: Array<SchemaIndex>;
18952
18952
  triggers?: Array<SchemaTrigger>;
18953
18953
  }
18954
+ type PublicSchema = Omit<Partial<Schema>, 'slug' | 'identifiers'> & {
18955
+ slug: Required<Schema['slug']>;
18956
+ identifiers?: Partial<Schema['identifiers']>;
18957
+ };
18954
18958
 
18955
18959
  /**
18956
18960
  * Composes an SQL statement for a provided RONIN query.
@@ -18961,13 +18965,12 @@ interface Schema {
18961
18965
  *
18962
18966
  * @returns The composed SQL statement.
18963
18967
  */
18964
- declare const compileQueryInput: (query: Query, defaultSchemas: Array<Schema>, options?: {
18965
- statementValues: Array<unknown>;
18966
- disableReturning?: boolean;
18968
+ declare const compileQuery: (query: Query, schemas: Array<PublicSchema>, options?: {
18969
+ inlineValues?: boolean;
18967
18970
  }) => {
18968
18971
  writeStatements: Array<string>;
18969
18972
  readStatement: string;
18970
18973
  values: Array<unknown>;
18971
18974
  };
18972
18975
 
18973
- export { type CombinedInstructions, type CountInstructions, type CountQuery, type CreateInstructions, type CreateQuery, type DropInstructions, type DropQuery, type GetInstructions, type GetQuery, type IncludingInstruction, type Instructions, type OrderedByInstrucion, type Query, type QueryInstructionType, type QueryPaginationOptions, type QuerySchemaType, type QueryType, type Schema, type SchemaField, type SchemaFieldReference, type SchemaFieldReferenceAction, type SetInstructions, type SetQuery, type WithInstruction, compileQueryInput };
18976
+ export { type CombinedInstructions, type CountInstructions, type CountQuery, type CreateInstructions, type CreateQuery, type DropInstructions, type DropQuery, type GetInstructions, type GetQuery, type IncludingInstruction, type Instructions, type OrderedByInstrucion, type Query, type QueryInstructionType, type QueryPaginationOptions, type QuerySchemaType, type QueryType, type PublicSchema as Schema, type SchemaField, type SchemaIndex, type SchemaTrigger, type SetInstructions, type SetQuery, type WithInstruction, compileQuery };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- // src/utils/index.ts
1
+ // src/utils/helpers.ts
2
2
  import { init as cuid } from "@paralleldrive/cuid2";
3
3
  var RONIN_SCHEMA_SYMBOLS = {
4
4
  // Represents a sub query.
@@ -33,7 +33,7 @@ var DOUBLE_QUOTE_REGEX = /"/g;
33
33
  var AMPERSAND_REGEX = /\s*&+\s*/g;
34
34
  var SPECIAL_CHARACTERS_REGEX = /[^\w\s-]+/g;
35
35
  var SPLIT_REGEX = /(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|[\s.\-_]+/;
36
- var generateRecordId = (prefix) => `${prefix || "rec"}_${cuid({ length: 16 })()}`;
36
+ var generateRecordId = (prefix) => `${prefix}_${cuid({ length: 16 })()}`;
37
37
  var capitalize = (str) => {
38
38
  if (!str || str.length === 0) return "";
39
39
  return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
@@ -96,8 +96,9 @@ var splitQuery = (query) => {
96
96
  };
97
97
 
98
98
  // src/utils/statement.ts
99
- var prepareStatementValue = (statementValues, value, bindNull = false) => {
100
- if (!bindNull && value === null) return "NULL";
99
+ var prepareStatementValue = (statementValues, value) => {
100
+ if (value === null) return "NULL";
101
+ if (!statementValues) return JSON.stringify(value);
101
102
  let formattedValue = value;
102
103
  if (Array.isArray(value) || isObject(value)) {
103
104
  formattedValue = JSON.stringify(value);
@@ -122,7 +123,7 @@ var composeFieldValues = (schemas, schema, statementValues, instructionName, val
122
123
  conditionValue = `(${compileQueryInput(
123
124
  value[RONIN_SCHEMA_SYMBOLS.QUERY],
124
125
  schemas,
125
- { statementValues }
126
+ statementValues
126
127
  ).readStatement})`;
127
128
  } else if (typeof value === "string" && value.startsWith(RONIN_SCHEMA_SYMBOLS.FIELD)) {
128
129
  let targetTable = `"${options.rootTable}"`;
@@ -139,11 +140,11 @@ var composeFieldValues = (schemas, schema, statementValues, instructionName, val
139
140
  } else if (schemaField.type === "json" && instructionName === "to") {
140
141
  conditionSelector = `"${schemaField.slug}"`;
141
142
  if (collectStatementValue) {
142
- const preparedValue = prepareStatementValue(statementValues, value, false);
143
+ const preparedValue = prepareStatementValue(statementValues, value);
143
144
  conditionValue = `IIF(${conditionSelector} IS NULL, ${preparedValue}, json_patch(${conditionSelector}, ${preparedValue}))`;
144
145
  }
145
146
  } else if (collectStatementValue) {
146
- conditionValue = prepareStatementValue(statementValues, value, false);
147
+ conditionValue = prepareStatementValue(statementValues, value);
147
148
  }
148
149
  if (options.type === "fields") return conditionSelector;
149
150
  if (options.type === "values") return conditionValue;
@@ -250,10 +251,10 @@ var formatIdentifiers = ({ identifiers }, queryInstructions) => {
250
251
  return queryInstructions;
251
252
  const newNestedInstructions = { ...nestedInstructions };
252
253
  for (const oldKey of Object.keys(newNestedInstructions)) {
253
- if (oldKey !== "titleIdentifier" && oldKey !== "slugIdentifier") continue;
254
- const identifierName = oldKey === "titleIdentifier" ? "title" : "slug";
254
+ if (oldKey !== "nameIdentifier" && oldKey !== "slugIdentifier") continue;
255
+ const identifierName = oldKey === "nameIdentifier" ? "name" : "slug";
255
256
  const value = newNestedInstructions[oldKey];
256
- const newKey = identifiers?.[identifierName] || "id";
257
+ const newKey = identifiers[identifierName];
257
258
  newNestedInstructions[newKey] = value;
258
259
  delete newNestedInstructions[oldKey];
259
260
  }
@@ -395,6 +396,10 @@ var SYSTEM_SCHEMAS = [
395
396
  pluralName: "Schemas",
396
397
  slug: "schema",
397
398
  pluralSlug: "schemas",
399
+ identifiers: {
400
+ name: "name",
401
+ slug: "slug"
402
+ },
398
403
  fields: [
399
404
  ...SYSTEM_FIELDS,
400
405
  { slug: "name", type: "string" },
@@ -403,7 +408,7 @@ var SYSTEM_SCHEMAS = [
403
408
  { slug: "pluralSlug", type: "string" },
404
409
  { slug: "idPrefix", type: "string" },
405
410
  { slug: "identifiers", type: "group" },
406
- { slug: "identifiers.title", type: "string" },
411
+ { slug: "identifiers.name", type: "string" },
407
412
  { slug: "identifiers.slug", type: "string" },
408
413
  { slug: "fields", type: "json" },
409
414
  { slug: "indexes", type: "json" },
@@ -415,6 +420,10 @@ var SYSTEM_SCHEMAS = [
415
420
  pluralName: "Fields",
416
421
  slug: "field",
417
422
  pluralSlug: "fields",
423
+ identifiers: {
424
+ name: "name",
425
+ slug: "slug"
426
+ },
418
427
  fields: [
419
428
  ...SYSTEM_FIELDS,
420
429
  { slug: "name", type: "string" },
@@ -443,6 +452,10 @@ var SYSTEM_SCHEMAS = [
443
452
  pluralName: "Indexes",
444
453
  slug: "index",
445
454
  pluralSlug: "indexes",
455
+ identifiers: {
456
+ name: "slug",
457
+ slug: "slug"
458
+ },
446
459
  fields: [
447
460
  ...SYSTEM_FIELDS,
448
461
  { slug: "slug", type: "string", required: true },
@@ -461,6 +474,10 @@ var SYSTEM_SCHEMAS = [
461
474
  pluralName: "Triggers",
462
475
  slug: "trigger",
463
476
  pluralSlug: "triggers",
477
+ identifiers: {
478
+ name: "slug",
479
+ slug: "slug"
480
+ },
464
481
  fields: [
465
482
  ...SYSTEM_FIELDS,
466
483
  { slug: "slug", type: "string", required: true },
@@ -481,6 +498,10 @@ var prepareSchema = (schema) => {
481
498
  if (!copiedSchema.name) copiedSchema.name = slugToName(copiedSchema.slug);
482
499
  if (!copiedSchema.pluralName)
483
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";
484
505
  return copiedSchema;
485
506
  };
486
507
  var addSystemSchemas = (schemas) => {
@@ -496,6 +517,10 @@ var addSystemSchemas = (schemas) => {
496
517
  list.push({
497
518
  pluralSlug: fieldSlug,
498
519
  slug: fieldSlug,
520
+ identifiers: {
521
+ name: "id",
522
+ slug: "id"
523
+ },
499
524
  fields: [
500
525
  {
501
526
  slug: "source",
@@ -577,9 +602,14 @@ var getFieldStatement = (field) => {
577
602
  return statement;
578
603
  };
579
604
  var addSchemaQueries = (schemas, statementValues, queryDetails, writeStatements) => {
580
- const { queryType, querySchema, queryInstructions } = queryDetails;
581
- if (!["create", "set", "drop"].includes(queryType)) return;
582
- if (!SYSTEM_SCHEMA_SLUGS.includes(querySchema)) return;
605
+ const {
606
+ queryType,
607
+ querySchema,
608
+ queryInstructions: queryInstructionsRaw
609
+ } = queryDetails;
610
+ const queryInstructions = queryInstructionsRaw;
611
+ if (!["create", "set", "drop"].includes(queryType)) return queryInstructions;
612
+ if (!SYSTEM_SCHEMA_SLUGS.includes(querySchema)) return queryInstructions;
583
613
  const instructionName = mappedInstructions[queryType];
584
614
  const instructionList = queryInstructions[instructionName];
585
615
  const kind = getSchemaBySlug(SYSTEM_SCHEMAS, querySchema).pluralSlug;
@@ -643,7 +673,7 @@ var addSchemaQueries = (schemas, statementValues, queryDetails, writeStatements)
643
673
  }
644
674
  }
645
675
  writeStatements.push(statement2);
646
- return;
676
+ return queryInstructions;
647
677
  }
648
678
  if (kind === "triggers") {
649
679
  const triggerName = convertToSnakeCase(slug);
@@ -669,8 +699,7 @@ var addSchemaQueries = (schemas, statementValues, queryDetails, writeStatements)
669
699
  statementParts.push("WHEN", `(${withStatement})`);
670
700
  }
671
701
  const effectStatements = effectQueries.map((effectQuery) => {
672
- return compileQueryInput(effectQuery, schemas, {
673
- statementValues,
702
+ return compileQueryInput(effectQuery, schemas, statementValues, {
674
703
  disableReturning: true
675
704
  }).readStatement;
676
705
  });
@@ -680,23 +709,27 @@ var addSchemaQueries = (schemas, statementValues, queryDetails, writeStatements)
680
709
  statement2 += ` ${statementParts.join(" ")}`;
681
710
  }
682
711
  writeStatements.push(statement2);
683
- return;
712
+ return queryInstructions;
684
713
  }
685
714
  let statement = `${tableAction} TABLE "${tableName}"`;
686
715
  if (kind === "schemas") {
687
- const fields = [...SYSTEM_FIELDS];
716
+ const providedFields = instructionList?.fields || [];
717
+ const fields = [...SYSTEM_FIELDS, ...providedFields];
718
+ if (queryType === "create" || queryType === "set") {
719
+ queryInstructions.to = prepareSchema(queryInstructions.to);
720
+ }
688
721
  if (queryType === "create") {
689
722
  const columns = fields.map(getFieldStatement).filter(Boolean);
690
723
  statement += ` (${columns.join(", ")})`;
691
724
  } else if (queryType === "set") {
692
- const newSlug = queryInstructions.to?.slug;
725
+ const newSlug = queryInstructions.to?.pluralSlug;
693
726
  if (newSlug) {
694
- const newTable = convertToSnakeCase(pluralize(newSlug));
727
+ const newTable = convertToSnakeCase(newSlug);
695
728
  statement += ` RENAME TO "${newTable}"`;
696
729
  }
697
730
  }
698
731
  writeStatements.push(statement);
699
- return;
732
+ return queryInstructions;
700
733
  }
701
734
  if (kind === "fields") {
702
735
  if (queryType === "create") {
@@ -718,6 +751,7 @@ var addSchemaQueries = (schemas, statementValues, queryDetails, writeStatements)
718
751
  }
719
752
  writeStatements.push(statement);
720
753
  }
754
+ return queryInstructions;
721
755
  };
722
756
  var slugToName = (slug) => {
723
757
  const name = slug.replace(/([a-z])([A-Z])/g, "$1 $2");
@@ -882,7 +916,7 @@ var handleIncluding = (schemas, statementValues, schema, instruction, rootTable)
882
916
  }
883
917
  },
884
918
  schemas,
885
- { statementValues }
919
+ statementValues
886
920
  );
887
921
  relatedTableSelector = `(${subSelect.readStatement})`;
888
922
  }
@@ -1009,9 +1043,7 @@ var handleTo = (schemas, schema, statementValues, queryType, writeStatements, in
1009
1043
  ...subQueryInstructions.including
1010
1044
  };
1011
1045
  }
1012
- return compileQueryInput(subQuery, schemas, {
1013
- statementValues
1014
- }).readStatement;
1046
+ return compileQueryInput(subQuery, schemas, statementValues).readStatement;
1015
1047
  }
1016
1048
  Object.assign(toInstruction, defaultFields);
1017
1049
  for (const fieldSlug in toInstruction) {
@@ -1034,7 +1066,8 @@ var handleTo = (schemas, schema, statementValues, queryType, writeStatements, in
1034
1066
  }
1035
1067
  },
1036
1068
  schemas,
1037
- { statementValues, disableReturning: true }
1069
+ statementValues,
1070
+ { disableReturning: true }
1038
1071
  );
1039
1072
  return readStatement;
1040
1073
  };
@@ -1083,8 +1116,8 @@ var handleTo = (schemas, schema, statementValues, queryType, writeStatements, in
1083
1116
  return statement;
1084
1117
  };
1085
1118
 
1086
- // src/index.ts
1087
- var compileQueryInput = (query, defaultSchemas, options) => {
1119
+ // src/utils/index.ts
1120
+ var compileQueryInput = (query, defaultSchemas, statementValues, options) => {
1088
1121
  const parsedQuery = splitQuery(query);
1089
1122
  const { queryType, querySchema, queryInstructions } = parsedQuery;
1090
1123
  const schemas = addSystemSchemas(defaultSchemas);
@@ -1092,9 +1125,13 @@ var compileQueryInput = (query, defaultSchemas, options) => {
1092
1125
  const single = querySchema !== schema.pluralSlug;
1093
1126
  let instructions = formatIdentifiers(schema, queryInstructions);
1094
1127
  let table = getTableForSchema(schema);
1095
- const statementValues = options?.statementValues || [];
1096
1128
  const writeStatements = [];
1097
- addSchemaQueries(schemas, statementValues, parsedQuery, writeStatements);
1129
+ instructions = addSchemaQueries(
1130
+ schemas,
1131
+ statementValues,
1132
+ { queryType, querySchema, queryInstructions: instructions },
1133
+ writeStatements
1134
+ );
1098
1135
  const columns = handleSelecting(schema, statementValues, {
1099
1136
  selecting: instructions?.selecting,
1100
1137
  including: instructions?.including
@@ -1234,9 +1271,15 @@ var compileQueryInput = (query, defaultSchemas, options) => {
1234
1271
  return {
1235
1272
  writeStatements,
1236
1273
  readStatement: finalStatement,
1237
- values: statementValues
1274
+ values: statementValues || []
1238
1275
  };
1239
1276
  };
1277
+
1278
+ // src/index.ts
1279
+ var compileQuery = (query, schemas, options) => {
1280
+ const statementValues = options?.inlineValues ? null : [];
1281
+ return compileQueryInput(query, schemas, statementValues);
1282
+ };
1240
1283
  export {
1241
- compileQueryInput
1284
+ compileQuery
1242
1285
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ronin/compiler",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "description": "Compiles RONIN queries to SQL statements.",
6
6
  "publishConfig": {