@ronin/compiler 0.10.1 → 0.10.2-leo-ron-1083-experimental-211
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +18 -1
- package/dist/index.d.ts +12 -3
- package/dist/index.js +76 -5
- package/package.json +1 -1
package/README.md
CHANGED
@@ -103,7 +103,24 @@ new Transaction(queries, {
|
|
103
103
|
// Instead of returning an array of parameters for every statement (which allows for
|
104
104
|
// preventing SQL injections), all parameters are inlined directly into the SQL strings.
|
105
105
|
// This option should only be used if the generated SQL will be manually verified.
|
106
|
-
inlineParams: true
|
106
|
+
inlineParams: true,
|
107
|
+
|
108
|
+
// By default, in the generated SQL statements, the compiler does not alias columns if
|
109
|
+
// multiple different tables with the same column names are being joined. Only the table
|
110
|
+
// names themselves are aliased.
|
111
|
+
//
|
112
|
+
// This ensures the cleanest possible SQL statements in conjunction with the default
|
113
|
+
// behavior of SQLite (and all other SQL databases), where the result of a statement is
|
114
|
+
// a list (array) of values, which are inherently not prone to conflicts.
|
115
|
+
//
|
116
|
+
// If the driver being used instead returns an object for every row, the driver must
|
117
|
+
// ensure the uniqueness of every key in that object, which means prefixing duplicated
|
118
|
+
// column names with the name of the respective table, if multiple tables are joined.
|
119
|
+
// Drivers that return objects for rows offer this behavior as an option that is
|
120
|
+
// usually called "expand columns". If the driver being used does not offer such an
|
121
|
+
// option, you can instead activate the option in the compiler, which results in longer
|
122
|
+
// SQL statements because any duplicated column name is aliased.
|
123
|
+
expandColumns: true
|
107
124
|
});
|
108
125
|
```
|
109
126
|
|
package/dist/index.d.ts
CHANGED
@@ -6005,13 +6005,22 @@ type AmountResult = {
|
|
6005
6005
|
};
|
6006
6006
|
type Result = SingleRecordResult | MultipleRecordResult | AmountResult;
|
6007
6007
|
|
6008
|
+
interface TransactionOptions {
|
6009
|
+
/** A list of models that already exist in the database. */
|
6010
|
+
models?: Array<PublicModel>;
|
6011
|
+
/**
|
6012
|
+
* Place statement parameters directly inside the statement strings instead of
|
6013
|
+
* separating them out into a dedicated `params` array.
|
6014
|
+
*/
|
6015
|
+
inlineParams?: boolean;
|
6016
|
+
/** Alias column names that are duplicated when joining multiple tables. */
|
6017
|
+
expandColumns?: boolean;
|
6018
|
+
}
|
6008
6019
|
declare class Transaction {
|
6009
6020
|
statements: Array<Statement>;
|
6010
6021
|
models: Array<Model>;
|
6011
6022
|
private queries;
|
6012
|
-
constructor(queries: Array<Query>, options?:
|
6013
|
-
models?: Array<PublicModel>;
|
6014
|
-
});
|
6023
|
+
constructor(queries: Array<Query>, options?: TransactionOptions);
|
6015
6024
|
/**
|
6016
6025
|
* Composes SQL statements for the provided RONIN queries.
|
6017
6026
|
*
|
package/dist/index.js
CHANGED
@@ -102,6 +102,9 @@ var expand = (obj) => {
|
|
102
102
|
return res;
|
103
103
|
}, {});
|
104
104
|
};
|
105
|
+
var getProperty = (obj, path) => {
|
106
|
+
return path.split(".").reduce((acc, key) => acc?.[key], obj);
|
107
|
+
};
|
105
108
|
var splitQuery = (query) => {
|
106
109
|
const queryType = Object.keys(query)[0];
|
107
110
|
const queryModel = Object.keys(query[queryType])[0];
|
@@ -939,9 +942,24 @@ var transformMetaQuery = (models, dependencyStatements, statementParams, query)
|
|
939
942
|
};
|
940
943
|
};
|
941
944
|
|
942
|
-
// src/
|
945
|
+
// src/utils/pagination.ts
|
943
946
|
var CURSOR_SEPARATOR = ",";
|
944
947
|
var CURSOR_NULL_PLACEHOLDER = "RONIN_NULL";
|
948
|
+
var generatePaginationCursor = (model, orderedBy, record) => {
|
949
|
+
const { ascending = [], descending = [] } = orderedBy || {};
|
950
|
+
const keys = [...ascending, ...descending];
|
951
|
+
if (keys.length === 0) keys.push("ronin.createdAt");
|
952
|
+
const cursors = keys.map((fieldSlug) => {
|
953
|
+
const property = getProperty(record, fieldSlug);
|
954
|
+
if (property === null || property === void 0) return CURSOR_NULL_PLACEHOLDER;
|
955
|
+
const { field } = getFieldFromModel(model, fieldSlug, "orderedBy");
|
956
|
+
if (field.type === "date") return new Date(property).getTime();
|
957
|
+
return property;
|
958
|
+
});
|
959
|
+
return cursors.map((cursor) => encodeURIComponent(String(cursor))).join(CURSOR_SEPARATOR);
|
960
|
+
};
|
961
|
+
|
962
|
+
// src/instructions/before-after.ts
|
945
963
|
var handleBeforeOrAfter = (model, statementParams, instructions) => {
|
946
964
|
if (!(instructions.before || instructions.after)) {
|
947
965
|
throw new RoninError({
|
@@ -1212,6 +1230,11 @@ var handleTo = (models, model, statementParams, queryType, dependencyStatements,
|
|
1212
1230
|
if (symbol?.type === "query") {
|
1213
1231
|
let { queryModel: subQueryModelSlug, queryInstructions: subQueryInstructions } = splitQuery(symbol.value);
|
1214
1232
|
const subQueryModel = getModelBySlug(models, subQueryModelSlug);
|
1233
|
+
if (subQueryInstructions?.selecting) {
|
1234
|
+
const currentFields = new Set(subQueryInstructions.selecting);
|
1235
|
+
currentFields.add("id");
|
1236
|
+
subQueryInstructions.selecting = Array.from(currentFields);
|
1237
|
+
}
|
1215
1238
|
const subQuerySelectedFields = subQueryInstructions?.selecting;
|
1216
1239
|
const subQueryIncludedFields = subQueryInstructions?.including;
|
1217
1240
|
const subQueryFields = [
|
@@ -1234,7 +1257,19 @@ var handleTo = (models, model, statementParams, queryType, dependencyStatements,
|
|
1234
1257
|
...subQueryInstructions.including
|
1235
1258
|
};
|
1236
1259
|
}
|
1237
|
-
|
1260
|
+
let statement2 = "";
|
1261
|
+
if (subQuerySelectedFields) {
|
1262
|
+
const selectedFields = [
|
1263
|
+
...subQueryFields,
|
1264
|
+
...defaultFieldsToAdd.map(([key]) => key)
|
1265
|
+
];
|
1266
|
+
const columns = selectedFields.map((field) => {
|
1267
|
+
return getFieldFromModel(model, field, "to").fieldSelector;
|
1268
|
+
});
|
1269
|
+
statement2 = `(${columns.join(", ")}) `;
|
1270
|
+
}
|
1271
|
+
statement2 += compileQueryInput(symbol.value, models, statementParams).main.statement;
|
1272
|
+
return statement2;
|
1238
1273
|
}
|
1239
1274
|
Object.assign(toInstruction, defaultFields);
|
1240
1275
|
for (const fieldSlug in toInstruction) {
|
@@ -1498,11 +1533,47 @@ var Transaction = class {
|
|
1498
1533
|
return expand(formattedRecord);
|
1499
1534
|
}
|
1500
1535
|
prepareResults(results) {
|
1501
|
-
|
1536
|
+
const relevantResults = results.filter((_, index) => {
|
1537
|
+
return this.statements[index].returning;
|
1538
|
+
});
|
1539
|
+
return relevantResults.map((result, index) => {
|
1502
1540
|
const query = this.queries.at(-index);
|
1503
|
-
const { queryModel } = splitQuery(query);
|
1541
|
+
const { queryType, queryModel, queryInstructions } = splitQuery(query);
|
1504
1542
|
const model = getModelBySlug(this.models, queryModel);
|
1505
|
-
|
1543
|
+
if (queryType === "count") {
|
1544
|
+
return { amount: result[0]["COUNT(*)"] };
|
1545
|
+
}
|
1546
|
+
const single = queryModel !== model.pluralSlug;
|
1547
|
+
if (single) {
|
1548
|
+
return { record: this.formatRecord(model, result[0]) };
|
1549
|
+
}
|
1550
|
+
const pageSize = queryInstructions?.limitedTo;
|
1551
|
+
const output = {
|
1552
|
+
records: result.map((resultItem) => {
|
1553
|
+
return this.formatRecord(model, resultItem);
|
1554
|
+
})
|
1555
|
+
};
|
1556
|
+
if (pageSize && output.records.length > 0) {
|
1557
|
+
if (queryInstructions?.before || queryInstructions?.after) {
|
1558
|
+
const direction = queryInstructions?.before ? "moreAfter" : "moreBefore";
|
1559
|
+
const firstRecord = output.records[0];
|
1560
|
+
output[direction] = generatePaginationCursor(
|
1561
|
+
model,
|
1562
|
+
queryInstructions.orderedBy,
|
1563
|
+
firstRecord
|
1564
|
+
);
|
1565
|
+
}
|
1566
|
+
if (output.records.length > pageSize) {
|
1567
|
+
const direction = queryInstructions?.before ? "moreBefore" : "moreAfter";
|
1568
|
+
const lastRecord = output.records.pop();
|
1569
|
+
output[direction] = generatePaginationCursor(
|
1570
|
+
model,
|
1571
|
+
queryInstructions.orderedBy,
|
1572
|
+
lastRecord
|
1573
|
+
);
|
1574
|
+
}
|
1575
|
+
}
|
1576
|
+
return output;
|
1506
1577
|
});
|
1507
1578
|
}
|
1508
1579
|
};
|