spice-js 2.7.14 → 2.7.16
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/build/models/SpiceModel.js +32 -10
- package/package.json +1 -1
- package/src/models/SpiceModel.js +29 -10
|
@@ -1248,6 +1248,15 @@ class SpiceModel {
|
|
|
1248
1248
|
return t.startsWith("`") ? t : q(t);
|
|
1249
1249
|
});
|
|
1250
1250
|
return q(this.type) + "." + safeParts.join(".");
|
|
1251
|
+
} // For protected aliases (joined resources), return the base table's column (IDs)
|
|
1252
|
+
// instead of the joined resource itself. The JOIN is only for WHERE filtering,
|
|
1253
|
+
// and the serializer will map the IDs later.
|
|
1254
|
+
|
|
1255
|
+
|
|
1256
|
+
var unquotedCol = col.replace(/`/g, "");
|
|
1257
|
+
|
|
1258
|
+
if (protectedSet.has(unquotedCol)) {
|
|
1259
|
+
return q(this.type) + "." + q(unquotedCol);
|
|
1251
1260
|
}
|
|
1252
1261
|
|
|
1253
1262
|
if (!col.includes(".") && !col.startsWith("`")) {
|
|
@@ -1290,34 +1299,42 @@ class SpiceModel {
|
|
|
1290
1299
|
}
|
|
1291
1300
|
|
|
1292
1301
|
extractNestings(string, localType) {
|
|
1293
|
-
var returnVal = []; //
|
|
1294
|
-
//
|
|
1302
|
+
var returnVal = []; // Extract loop variables from ANY/EVERY expressions
|
|
1303
|
+
// Loop variables (e.g., "vote" in "EVERY vote IN committee_votes") should be excluded
|
|
1304
|
+
// But the collection being iterated (e.g., "committee_votes") should be INCLUDED
|
|
1305
|
+
// if it's a joinable mapped property - buildJoinMetadata will filter non-joinables
|
|
1295
1306
|
|
|
1296
1307
|
var anyEveryRegex = /(ANY|EVERY)\s+(\w+)\s+IN\s+`?(\w+)`?/gi;
|
|
1297
1308
|
var anyEveryMatch;
|
|
1298
1309
|
var loopVariables = new Set();
|
|
1299
|
-
var
|
|
1310
|
+
var anyEveryCollections = new Set();
|
|
1300
1311
|
|
|
1301
1312
|
while ((anyEveryMatch = anyEveryRegex.exec(string)) !== null) {
|
|
1302
|
-
loopVariables.add(anyEveryMatch[2]); // e.g., "
|
|
1313
|
+
loopVariables.add(anyEveryMatch[2]); // e.g., "vote" - exclude from nestings
|
|
1303
1314
|
|
|
1304
|
-
|
|
1305
|
-
} // Now extract dot notation patterns, but skip loop variables
|
|
1315
|
+
anyEveryCollections.add(anyEveryMatch[3]); // e.g., "committee_votes" - include in nestings
|
|
1316
|
+
} // Now extract dot notation patterns, but skip loop variables
|
|
1306
1317
|
|
|
1307
1318
|
|
|
1308
1319
|
var regex = /(`?\w+`?)\.(`?\w+`?)/g;
|
|
1309
1320
|
var match;
|
|
1310
1321
|
|
|
1311
1322
|
while ((match = regex.exec(string)) !== null) {
|
|
1312
|
-
var first = match[1].replace(/`/g, ""); // Skip if it's the local type
|
|
1323
|
+
var first = match[1].replace(/`/g, ""); // Skip if it's the local type or a loop variable from ANY/EVERY
|
|
1313
1324
|
|
|
1314
|
-
if (first !== localType && !loopVariables.has(first)
|
|
1325
|
+
if (first !== localType && !loopVariables.has(first)) {
|
|
1315
1326
|
returnVal.push(first);
|
|
1316
1327
|
}
|
|
1317
|
-
} //
|
|
1318
|
-
//
|
|
1328
|
+
} // Add collections from ANY/EVERY expressions as potential nestings
|
|
1329
|
+
// buildJoinMetadata will filter out non-joinable ones (embedded arrays vs mapped collections)
|
|
1319
1330
|
|
|
1320
1331
|
|
|
1332
|
+
for (var collection of anyEveryCollections) {
|
|
1333
|
+
if (collection !== localType) {
|
|
1334
|
+
returnVal.push(collection);
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1321
1338
|
return [...new Set(returnVal)];
|
|
1322
1339
|
}
|
|
1323
1340
|
|
|
@@ -1460,6 +1477,11 @@ class SpiceModel {
|
|
|
1460
1477
|
|
|
1461
1478
|
if (tableName === this.type && match) {
|
|
1462
1479
|
return col;
|
|
1480
|
+
} // If column is already backtick-quoted, return as-is
|
|
1481
|
+
|
|
1482
|
+
|
|
1483
|
+
if (col.startsWith("`") && col.endsWith("`")) {
|
|
1484
|
+
return col;
|
|
1463
1485
|
}
|
|
1464
1486
|
|
|
1465
1487
|
return "`" + col + "`";
|
package/package.json
CHANGED
package/src/models/SpiceModel.js
CHANGED
|
@@ -1064,6 +1064,14 @@ export default class SpiceModel {
|
|
|
1064
1064
|
return `${q(this.type)}.${safeParts.join(".")}`;
|
|
1065
1065
|
}
|
|
1066
1066
|
|
|
1067
|
+
// For protected aliases (joined resources), return the base table's column (IDs)
|
|
1068
|
+
// instead of the joined resource itself. The JOIN is only for WHERE filtering,
|
|
1069
|
+
// and the serializer will map the IDs later.
|
|
1070
|
+
const unquotedCol = col.replace(/`/g, "");
|
|
1071
|
+
if (protectedSet.has(unquotedCol)) {
|
|
1072
|
+
return `${q(this.type)}.${q(unquotedCol)}`;
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1067
1075
|
if (!col.includes(".") && !col.startsWith("`")) {
|
|
1068
1076
|
return q(col);
|
|
1069
1077
|
}
|
|
@@ -1110,32 +1118,39 @@ export default class SpiceModel {
|
|
|
1110
1118
|
extractNestings(string, localType) {
|
|
1111
1119
|
let returnVal = [];
|
|
1112
1120
|
|
|
1113
|
-
//
|
|
1114
|
-
//
|
|
1121
|
+
// Extract loop variables from ANY/EVERY expressions
|
|
1122
|
+
// Loop variables (e.g., "vote" in "EVERY vote IN committee_votes") should be excluded
|
|
1123
|
+
// But the collection being iterated (e.g., "committee_votes") should be INCLUDED
|
|
1124
|
+
// if it's a joinable mapped property - buildJoinMetadata will filter non-joinables
|
|
1115
1125
|
let anyEveryRegex = /(ANY|EVERY)\s+(\w+)\s+IN\s+`?(\w+)`?/gi;
|
|
1116
1126
|
let anyEveryMatch;
|
|
1117
1127
|
const loopVariables = new Set();
|
|
1118
|
-
const
|
|
1128
|
+
const anyEveryCollections = new Set();
|
|
1119
1129
|
|
|
1120
1130
|
while ((anyEveryMatch = anyEveryRegex.exec(string)) !== null) {
|
|
1121
|
-
loopVariables.add(anyEveryMatch[2]); // e.g., "
|
|
1122
|
-
|
|
1131
|
+
loopVariables.add(anyEveryMatch[2]); // e.g., "vote" - exclude from nestings
|
|
1132
|
+
anyEveryCollections.add(anyEveryMatch[3]); // e.g., "committee_votes" - include in nestings
|
|
1123
1133
|
}
|
|
1124
1134
|
|
|
1125
|
-
// Now extract dot notation patterns, but skip loop variables
|
|
1135
|
+
// Now extract dot notation patterns, but skip loop variables
|
|
1126
1136
|
let regex = /(`?\w+`?)\.(`?\w+`?)/g;
|
|
1127
1137
|
let match;
|
|
1128
1138
|
|
|
1129
1139
|
while ((match = regex.exec(string)) !== null) {
|
|
1130
1140
|
let first = match[1].replace(/`/g, "");
|
|
1131
|
-
// Skip if it's the local type
|
|
1132
|
-
if (first !== localType && !loopVariables.has(first)
|
|
1141
|
+
// Skip if it's the local type or a loop variable from ANY/EVERY
|
|
1142
|
+
if (first !== localType && !loopVariables.has(first)) {
|
|
1133
1143
|
returnVal.push(first);
|
|
1134
1144
|
}
|
|
1135
1145
|
}
|
|
1136
1146
|
|
|
1137
|
-
//
|
|
1138
|
-
//
|
|
1147
|
+
// Add collections from ANY/EVERY expressions as potential nestings
|
|
1148
|
+
// buildJoinMetadata will filter out non-joinable ones (embedded arrays vs mapped collections)
|
|
1149
|
+
for (const collection of anyEveryCollections) {
|
|
1150
|
+
if (collection !== localType) {
|
|
1151
|
+
returnVal.push(collection);
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1139
1154
|
|
|
1140
1155
|
return [...new Set(returnVal)];
|
|
1141
1156
|
}
|
|
@@ -1292,6 +1307,10 @@ export default class SpiceModel {
|
|
|
1292
1307
|
return col;
|
|
1293
1308
|
}
|
|
1294
1309
|
|
|
1310
|
+
// If column is already backtick-quoted, return as-is
|
|
1311
|
+
if (col.startsWith("`") && col.endsWith("`")) {
|
|
1312
|
+
return col;
|
|
1313
|
+
}
|
|
1295
1314
|
return `\`${col}\``;
|
|
1296
1315
|
});
|
|
1297
1316
|
|