@adep/cli 0.1.9 → 0.1.11
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/README.md +2 -0
- package/dist/index.js +3189 -2422
- package/dist/vite.js +378 -49
- package/package.json +4 -3
package/dist/vite.js
CHANGED
|
@@ -1138,6 +1138,7 @@ function stripQuotes(raw) {
|
|
|
1138
1138
|
const t = raw.trim();
|
|
1139
1139
|
if (/^'.*'$/.test(t)) return t.slice(1, -1);
|
|
1140
1140
|
if (/^".*"$/.test(t)) return t.slice(1, -1);
|
|
1141
|
+
if (/^NULL$/i.test(t)) return null;
|
|
1141
1142
|
return t;
|
|
1142
1143
|
}
|
|
1143
1144
|
function parseCreateTable(ddl) {
|
|
@@ -1158,50 +1159,109 @@ function parseCreateTable(ddl) {
|
|
|
1158
1159
|
}
|
|
1159
1160
|
return { name, columns };
|
|
1160
1161
|
}
|
|
1161
|
-
function
|
|
1162
|
-
const
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
const inner = rhs.replace(/^\(|\)$/g, "");
|
|
1185
|
-
const items = splitListItems(inner);
|
|
1186
|
-
const list = items.map((item) => {
|
|
1187
|
-
if (item.trim() === "?") return cursor.take();
|
|
1188
|
-
return stripQuotes(item);
|
|
1189
|
-
});
|
|
1190
|
-
clauses.push({ column: col, operator: op, value: list, list: true });
|
|
1162
|
+
function splitTopLevel(raw, token) {
|
|
1163
|
+
const parts = [];
|
|
1164
|
+
let depth = 0;
|
|
1165
|
+
let inQuote = false;
|
|
1166
|
+
let buffer = "";
|
|
1167
|
+
const n = raw.length;
|
|
1168
|
+
const isTokenAt = (i) => {
|
|
1169
|
+
const word = raw.slice(i, i + token.length);
|
|
1170
|
+
if (word.toUpperCase() !== token) return false;
|
|
1171
|
+
const before = i === 0 ? "" : raw[i - 1] ?? "";
|
|
1172
|
+
const after = raw[i + token.length] ?? "";
|
|
1173
|
+
return !/[A-Za-z0-9_.]/.test(before) && !/[A-Za-z0-9_.]/.test(after);
|
|
1174
|
+
};
|
|
1175
|
+
for (let i = 0; i < n; i += 1) {
|
|
1176
|
+
const ch = raw[i] ?? "";
|
|
1177
|
+
if (ch === "'") {
|
|
1178
|
+
if (inQuote && raw[i + 1] === "'") {
|
|
1179
|
+
buffer += ch + (raw[i + 1] ?? "");
|
|
1180
|
+
i += 1;
|
|
1181
|
+
continue;
|
|
1182
|
+
}
|
|
1183
|
+
inQuote = !inQuote;
|
|
1184
|
+
buffer += ch;
|
|
1191
1185
|
continue;
|
|
1192
1186
|
}
|
|
1193
|
-
|
|
1194
|
-
if (
|
|
1195
|
-
|
|
1187
|
+
if (!inQuote && ch === "(") depth += 1;
|
|
1188
|
+
else if (!inQuote && ch === ")") depth -= 1;
|
|
1189
|
+
if (!inQuote && depth === 0 && isTokenAt(i)) {
|
|
1190
|
+
parts.push(buffer);
|
|
1191
|
+
buffer = "";
|
|
1192
|
+
i += token.length - 1;
|
|
1196
1193
|
} else {
|
|
1197
|
-
|
|
1194
|
+
buffer += ch;
|
|
1198
1195
|
}
|
|
1199
|
-
clauses.push({ column: col, operator: op, value, list: false });
|
|
1200
1196
|
}
|
|
1201
|
-
|
|
1197
|
+
parts.push(buffer);
|
|
1198
|
+
return parts;
|
|
1202
1199
|
}
|
|
1203
|
-
function
|
|
1204
|
-
|
|
1200
|
+
function unqualifyColumn(raw) {
|
|
1201
|
+
const t = raw.trim();
|
|
1202
|
+
const dot = t.lastIndexOf(".");
|
|
1203
|
+
if (dot > 0 && /^[A-Za-z_][A-Za-z0-9_]*\./.test(t)) return t.slice(dot + 1);
|
|
1204
|
+
return t;
|
|
1205
|
+
}
|
|
1206
|
+
function parseLeftJoins(tail) {
|
|
1207
|
+
const joins = [];
|
|
1208
|
+
const re = /LEFT\s+JOIN\s+((?:"[^"]+")|([A-Za-z_][A-Za-z0-9_]*))\s+([A-Za-z_][A-Za-z0-9_]*)\s+ON\s+([A-Za-z_][A-Za-z0-9_.]*)\s*=\s*([A-Za-z_][A-Za-z0-9_.]*)/gi;
|
|
1209
|
+
let m;
|
|
1210
|
+
while ((m = re.exec(tail)) !== null) {
|
|
1211
|
+
joins.push({
|
|
1212
|
+
table: ident(m[1] ?? ""),
|
|
1213
|
+
alias: m[3] ?? "",
|
|
1214
|
+
leftCol: unqualifyColumn(m[4] ?? ""),
|
|
1215
|
+
rightCol: unqualifyColumn(m[5] ?? "")
|
|
1216
|
+
});
|
|
1217
|
+
}
|
|
1218
|
+
return joins;
|
|
1219
|
+
}
|
|
1220
|
+
function parseWhereClauses(whereRaw, cursor) {
|
|
1221
|
+
const parseAndGroup = (andRaw) => {
|
|
1222
|
+
const clauses = [];
|
|
1223
|
+
for (const part of splitTopLevel(andRaw, "AND")) {
|
|
1224
|
+
const t = part.trim();
|
|
1225
|
+
if (t.length === 0) continue;
|
|
1226
|
+
if (/\bIS\s+NULL\b/i.test(t)) {
|
|
1227
|
+
clauses.push({ column: unqualifyColumn(ident(t.split(/\s+IS\s+NULL\b/i)[0] ?? "")), operator: "IS NULL", value: null, list: false });
|
|
1228
|
+
continue;
|
|
1229
|
+
}
|
|
1230
|
+
if (/\bIS\s+NOT\s+NULL\b/i.test(t)) {
|
|
1231
|
+
clauses.push({ column: unqualifyColumn(ident(t.split(/\s+IS\s+NOT\s+NULL\b/i)[0] ?? "")), operator: "IS NOT NULL", value: null, list: false });
|
|
1232
|
+
continue;
|
|
1233
|
+
}
|
|
1234
|
+
const opMatch = /^\s*((?:"[^"]+")|([A-Za-z_][A-Za-z0-9_.]*))\s*(=|!=|>=|<=|>|<|like|in|not\s+in)\s*(.+)$/i.exec(
|
|
1235
|
+
t
|
|
1236
|
+
);
|
|
1237
|
+
if (opMatch === null) continue;
|
|
1238
|
+
const col = unqualifyColumn(ident(opMatch[1] ?? ""));
|
|
1239
|
+
const op = (opMatch[3] ?? opMatch[2] ?? "").toLowerCase();
|
|
1240
|
+
const rhs = (opMatch[4] ?? "").trim();
|
|
1241
|
+
if (op === "in" || op === "not in") {
|
|
1242
|
+
const inner = rhs.replace(/^\(|\)$/g, "");
|
|
1243
|
+
const items = splitListItems(inner);
|
|
1244
|
+
const list = items.map((item) => {
|
|
1245
|
+
if (item.trim() === "?") return cursor.take();
|
|
1246
|
+
return stripQuotes(item);
|
|
1247
|
+
});
|
|
1248
|
+
clauses.push({ column: col, operator: op, value: list, list: true });
|
|
1249
|
+
continue;
|
|
1250
|
+
}
|
|
1251
|
+
let value;
|
|
1252
|
+
if (rhs === "?") {
|
|
1253
|
+
value = cursor.take();
|
|
1254
|
+
} else {
|
|
1255
|
+
value = stripQuotes(rhs);
|
|
1256
|
+
}
|
|
1257
|
+
clauses.push({ column: col, operator: op, value, list: false });
|
|
1258
|
+
}
|
|
1259
|
+
return clauses;
|
|
1260
|
+
};
|
|
1261
|
+
return splitTopLevel(whereRaw, "OR").map((group) => group.trim()).filter((group) => group.length > 0).map(parseAndGroup);
|
|
1262
|
+
}
|
|
1263
|
+
function matchWhere(groups, row) {
|
|
1264
|
+
return groups.some((clauses) => clauses.every((c) => matchValue(row[c.column], c)));
|
|
1205
1265
|
}
|
|
1206
1266
|
function splitListItems(inner) {
|
|
1207
1267
|
const items = [];
|
|
@@ -1221,6 +1281,168 @@ function splitListItems(inner) {
|
|
|
1221
1281
|
items.push(buffer);
|
|
1222
1282
|
return items;
|
|
1223
1283
|
}
|
|
1284
|
+
var ExcludedRef = class {
|
|
1285
|
+
constructor(column) {
|
|
1286
|
+
this.column = column;
|
|
1287
|
+
}
|
|
1288
|
+
};
|
|
1289
|
+
var ColumnRef = class {
|
|
1290
|
+
constructor(column) {
|
|
1291
|
+
this.column = column;
|
|
1292
|
+
}
|
|
1293
|
+
};
|
|
1294
|
+
var ExprRef = class {
|
|
1295
|
+
constructor(source) {
|
|
1296
|
+
this.source = source;
|
|
1297
|
+
}
|
|
1298
|
+
};
|
|
1299
|
+
function resolveSetValue(value, existing, row) {
|
|
1300
|
+
if (value instanceof ExcludedRef) return row[value.column];
|
|
1301
|
+
if (value instanceof ColumnRef) return existing[value.column];
|
|
1302
|
+
if (value instanceof ExprRef) return evalArithmetic(value.source, existing, row);
|
|
1303
|
+
return value;
|
|
1304
|
+
}
|
|
1305
|
+
function evalArithmetic(src, existing, row) {
|
|
1306
|
+
const num = (v) => {
|
|
1307
|
+
const n2 = Number(v);
|
|
1308
|
+
return Number.isFinite(n2) ? n2 : 0;
|
|
1309
|
+
};
|
|
1310
|
+
let i = 0;
|
|
1311
|
+
const n = src.length;
|
|
1312
|
+
const skip = () => {
|
|
1313
|
+
while (i < n && /\s/.test(src[i] ?? "")) i += 1;
|
|
1314
|
+
};
|
|
1315
|
+
const peek = () => {
|
|
1316
|
+
skip();
|
|
1317
|
+
return i < n ? src[i] ?? "" : null;
|
|
1318
|
+
};
|
|
1319
|
+
const parseIdent = () => {
|
|
1320
|
+
skip();
|
|
1321
|
+
const m = /^([A-Za-z_][A-Za-z0-9_]*)/.exec(src.slice(i));
|
|
1322
|
+
if (m === null) return null;
|
|
1323
|
+
i += (m[1] ?? "").length;
|
|
1324
|
+
skip();
|
|
1325
|
+
let col = ident(m[1] ?? "");
|
|
1326
|
+
let excluded = false;
|
|
1327
|
+
if (src[i] === ".") {
|
|
1328
|
+
const m2 = /^\.([A-Za-z_][A-Za-z0-9_]*)/.exec(src.slice(i));
|
|
1329
|
+
if (m2 !== null) {
|
|
1330
|
+
i += (m2[0] ?? "").length;
|
|
1331
|
+
if (col.toLowerCase() === "excluded") excluded = true;
|
|
1332
|
+
col = ident(m2[1] ?? "");
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
return { col, excluded };
|
|
1336
|
+
};
|
|
1337
|
+
const parseFactor = () => {
|
|
1338
|
+
const ch = peek();
|
|
1339
|
+
if (ch === "(") {
|
|
1340
|
+
i += 1;
|
|
1341
|
+
const v = parseExpr();
|
|
1342
|
+
skip();
|
|
1343
|
+
if (src[i] === ")") i += 1;
|
|
1344
|
+
return v;
|
|
1345
|
+
}
|
|
1346
|
+
const numMatch = /^(\d+(?:\.\d+)?)/.exec(src.slice(i));
|
|
1347
|
+
if (numMatch !== null) {
|
|
1348
|
+
i += (numMatch[1] ?? "").length;
|
|
1349
|
+
return Number(numMatch[1]);
|
|
1350
|
+
}
|
|
1351
|
+
const id = parseIdent();
|
|
1352
|
+
if (id !== null) {
|
|
1353
|
+
const v = id.excluded ? row[id.col] : existing[id.col];
|
|
1354
|
+
return num(v);
|
|
1355
|
+
}
|
|
1356
|
+
return 0;
|
|
1357
|
+
};
|
|
1358
|
+
const parseTerm = () => {
|
|
1359
|
+
let v = parseFactor();
|
|
1360
|
+
for (; ; ) {
|
|
1361
|
+
const ch = peek();
|
|
1362
|
+
if (ch !== "*" && ch !== "/") return v;
|
|
1363
|
+
i += 1;
|
|
1364
|
+
const rhs = parseFactor();
|
|
1365
|
+
v = ch === "*" ? v * rhs : rhs === 0 ? v : v / rhs;
|
|
1366
|
+
}
|
|
1367
|
+
};
|
|
1368
|
+
const parseExpr = () => {
|
|
1369
|
+
let v = parseTerm();
|
|
1370
|
+
for (; ; ) {
|
|
1371
|
+
const ch = peek();
|
|
1372
|
+
if (ch !== "+" && ch !== "-") return v;
|
|
1373
|
+
i += 1;
|
|
1374
|
+
const rhs = parseTerm();
|
|
1375
|
+
v = ch === "+" ? v + rhs : v - rhs;
|
|
1376
|
+
}
|
|
1377
|
+
};
|
|
1378
|
+
return parseExpr();
|
|
1379
|
+
}
|
|
1380
|
+
function splitInsertTuples(body) {
|
|
1381
|
+
const tuples = [];
|
|
1382
|
+
let i = 0;
|
|
1383
|
+
const n = body.length;
|
|
1384
|
+
while (i < n) {
|
|
1385
|
+
while (i < n && (body[i] === " " || body[i] === " " || body[i] === "\n" || body[i] === "\r" || body[i] === ",")) {
|
|
1386
|
+
i += 1;
|
|
1387
|
+
}
|
|
1388
|
+
if (i >= n) break;
|
|
1389
|
+
if (body[i] !== "(") {
|
|
1390
|
+
return { tuples, conflict: body.slice(i).trim() };
|
|
1391
|
+
}
|
|
1392
|
+
let depth = 0;
|
|
1393
|
+
let j = i;
|
|
1394
|
+
for (; j < n; j += 1) {
|
|
1395
|
+
if (body[j] === "(") depth += 1;
|
|
1396
|
+
else if (body[j] === ")") {
|
|
1397
|
+
depth -= 1;
|
|
1398
|
+
if (depth === 0) break;
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
if (j >= n) return { tuples, conflict: null };
|
|
1402
|
+
tuples.push(body.slice(i + 1, j));
|
|
1403
|
+
i = j + 1;
|
|
1404
|
+
}
|
|
1405
|
+
return { tuples, conflict: null };
|
|
1406
|
+
}
|
|
1407
|
+
function parseConflictClause(clause, cursor, fallbackCols) {
|
|
1408
|
+
const m = /^ON\s+CONFLICT(?:\s*\(([^)]*)\))?\s+DO\s+(UPDATE\s+SET\s+([\s\S]+)|NOTHING\s*)$/i.exec(
|
|
1409
|
+
clause.trim()
|
|
1410
|
+
);
|
|
1411
|
+
if (m === null) {
|
|
1412
|
+
throw new SimDbError("DB_UNSAFE_OP", `\u65E0\u6CD5\u89E3\u6790 ON CONFLICT \u5B50\u53E5\uFF1A${clause.trim().slice(0, 60)}\u2026`);
|
|
1413
|
+
}
|
|
1414
|
+
const colsRaw = m[1];
|
|
1415
|
+
const cols = colsRaw === void 0 ? fallbackCols : colsRaw.split(",").map(ident);
|
|
1416
|
+
if (cols.length === 0) throw new SimDbError("DB_UNSAFE_OP", "ON CONFLICT \u51B2\u7A81\u5217\u4E3A\u7A7A");
|
|
1417
|
+
const action = m[2] ?? "";
|
|
1418
|
+
if (/^NOTHING/i.test(action)) return { cols, sets: [] };
|
|
1419
|
+
const setRaw = m[3] ?? "";
|
|
1420
|
+
const sets = splitListItems(setRaw).map((part) => {
|
|
1421
|
+
const eq = /^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*([\s\S]+)$/i.exec(part.trim());
|
|
1422
|
+
if (eq === null) {
|
|
1423
|
+
throw new SimDbError("DB_UNSAFE_OP", `\u65E0\u6CD5\u89E3\u6790 SET \u8D4B\u503C\uFF1A${part.trim().slice(0, 60)}\u2026`);
|
|
1424
|
+
}
|
|
1425
|
+
const col = ident(eq[1] ?? "");
|
|
1426
|
+
const rhs = (eq[2] ?? "").trim();
|
|
1427
|
+
let value;
|
|
1428
|
+
if (rhs === "?") {
|
|
1429
|
+
value = cursor.take();
|
|
1430
|
+
} else {
|
|
1431
|
+
const ex = /^excluded\.([A-Za-z_][A-Za-z0-9_]*)$/i.exec(rhs);
|
|
1432
|
+
if (ex !== null) {
|
|
1433
|
+
value = new ExcludedRef(ident(ex[1] ?? ""));
|
|
1434
|
+
} else if (/^([A-Za-z_][A-Za-z0-9_]*)$/.test(rhs) && !/^NULL$/i.test(rhs)) {
|
|
1435
|
+
value = new ColumnRef(ident(rhs));
|
|
1436
|
+
} else if (/^'.*'$/.test(rhs) || /^".*"$/.test(rhs) || /^NULL$/i.test(rhs)) {
|
|
1437
|
+
value = stripQuotes(rhs);
|
|
1438
|
+
} else {
|
|
1439
|
+
value = new ExprRef(rhs);
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
return { col, value };
|
|
1443
|
+
});
|
|
1444
|
+
return { cols, sets };
|
|
1445
|
+
}
|
|
1224
1446
|
function matchValue(value, clause) {
|
|
1225
1447
|
const op = clause.operator;
|
|
1226
1448
|
if (op === "IS NULL") return value === null || value === void 0;
|
|
@@ -1374,16 +1596,36 @@ var SimSqlEngine = class {
|
|
|
1374
1596
|
const valueBody = match[4].trim();
|
|
1375
1597
|
const cursor = new ParamCursor(params);
|
|
1376
1598
|
const table = this.ensureTable(tableName);
|
|
1599
|
+
const { tuples, conflict } = splitInsertTuples(valueBody);
|
|
1600
|
+
if (tuples.length === 0) throw new SimDbError("DB_UNSAFE_OP", "INSERT \u7F3A\u5C11 VALUES \u5143\u7EC4");
|
|
1601
|
+
const conflictSpec = conflict === null ? null : parseConflictClause(
|
|
1602
|
+
conflict,
|
|
1603
|
+
cursor,
|
|
1604
|
+
table.columns.filter((c) => c.primaryKey).map((c) => c.name)
|
|
1605
|
+
);
|
|
1377
1606
|
let inserted = 0;
|
|
1378
|
-
for (const
|
|
1379
|
-
const
|
|
1380
|
-
const values = splitListItems(inner).map(
|
|
1607
|
+
for (const tuple of tuples) {
|
|
1608
|
+
const values = splitListItems(tuple).map(
|
|
1381
1609
|
(item) => item.trim() === "?" ? cursor.take() : stripQuotes(item)
|
|
1382
1610
|
);
|
|
1383
1611
|
const row = {};
|
|
1384
1612
|
cols.forEach((col, i) => {
|
|
1385
1613
|
row[col] = values[i] ?? null;
|
|
1386
1614
|
});
|
|
1615
|
+
if (conflictSpec !== null) {
|
|
1616
|
+
const existing = table.rows.find(
|
|
1617
|
+
(r) => conflictSpec.cols.every((c) => r[c] === row[c])
|
|
1618
|
+
);
|
|
1619
|
+
if (existing !== void 0) {
|
|
1620
|
+
const oldRow = { ...existing };
|
|
1621
|
+
for (const set of conflictSpec.sets) {
|
|
1622
|
+
existing[set.col] = resolveSetValue(set.value, oldRow, row);
|
|
1623
|
+
}
|
|
1624
|
+
inserted += 1;
|
|
1625
|
+
void this.persist();
|
|
1626
|
+
continue;
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1387
1629
|
this.applyAutoincrement(table, row);
|
|
1388
1630
|
table.rows.push(row);
|
|
1389
1631
|
inserted += 1;
|
|
@@ -1452,6 +1694,20 @@ var SimSqlEngine = class {
|
|
|
1452
1694
|
return project(this.catalog(), selectRaw);
|
|
1453
1695
|
}
|
|
1454
1696
|
const table = this.ensureTable(tableName);
|
|
1697
|
+
let rows = table.rows;
|
|
1698
|
+
const joins = parseLeftJoins(tail);
|
|
1699
|
+
if (joins.length > 0) {
|
|
1700
|
+
rows = table.rows.map((row) => {
|
|
1701
|
+
const merged = { ...row };
|
|
1702
|
+
for (const j of joins) {
|
|
1703
|
+
const joined = this.tables[j.table]?.rows.find((jr) => jr[j.leftCol] === merged[j.rightCol]);
|
|
1704
|
+
if (joined !== void 0) {
|
|
1705
|
+
for (const [k, v] of Object.entries(joined)) merged[`${j.alias}.${k}`] = v;
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
return merged;
|
|
1709
|
+
});
|
|
1710
|
+
}
|
|
1455
1711
|
const whereMatch = /\bWHERE\b/i.exec(tail);
|
|
1456
1712
|
const orderMatch = /\bORDER\s+BY\b/i.exec(tail);
|
|
1457
1713
|
const limitMatch = /\bLIMIT\b/i.exec(tail);
|
|
@@ -1460,7 +1716,6 @@ var SimSqlEngine = class {
|
|
|
1460
1716
|
whereMatch.index + whereMatch[0].length,
|
|
1461
1717
|
indexAfter(whereMatch.index, [orderMatch, limitMatch, offsetMatch], tail)
|
|
1462
1718
|
);
|
|
1463
|
-
let rows = table.rows;
|
|
1464
1719
|
if (whereRaw.trim().length > 0) {
|
|
1465
1720
|
const clauses = parseWhereClauses(whereRaw, cursor);
|
|
1466
1721
|
rows = rows.filter((row) => matchWhere(clauses, row));
|
|
@@ -1470,9 +1725,9 @@ var SimSqlEngine = class {
|
|
|
1470
1725
|
orderMatch.index + orderMatch[0].length,
|
|
1471
1726
|
indexAfter(orderMatch.index, [limitMatch, offsetMatch], tail)
|
|
1472
1727
|
);
|
|
1473
|
-
const oc = /^\s*((?:"[^"]+")|([A-Za-z_][A-Za-z0-9_]*))\s+(asc|desc)/i.exec(orderRaw);
|
|
1728
|
+
const oc = /^\s*((?:"[^"]+")|([A-Za-z_][A-Za-z0-9_.]*))\s+(asc|desc)/i.exec(orderRaw);
|
|
1474
1729
|
if (oc !== null) {
|
|
1475
|
-
const col = ident(oc[1]);
|
|
1730
|
+
const col = unqualifyColumn(ident(oc[1]));
|
|
1476
1731
|
const dir = oc[3].toLowerCase();
|
|
1477
1732
|
rows = [...rows].toSorted((a, b) => {
|
|
1478
1733
|
const av = a[col];
|
|
@@ -1517,6 +1772,15 @@ function indexAfter(start, matches, tail) {
|
|
|
1517
1772
|
const end = candidates.length === 0 ? -1 : Math.min(...candidates);
|
|
1518
1773
|
return end === -1 ? tail.length : end;
|
|
1519
1774
|
}
|
|
1775
|
+
function parseSelectItem(raw) {
|
|
1776
|
+
const t = raw.trim();
|
|
1777
|
+
const as = /\s+AS\s+([A-Za-z_][A-Za-z0-9_]*)$/i.exec(t);
|
|
1778
|
+
let name = as === null ? t : t.slice(0, as.index).trim();
|
|
1779
|
+
if (unqualifyColumn(name) === "*") return { name: "", qualified: "", alias: "", star: true };
|
|
1780
|
+
const qualified = /^[A-Za-z_][A-Za-z0-9_]*\.[A-Za-z_][A-Za-z0-9_]*$/.test(name) ? ident(name) : "";
|
|
1781
|
+
const plain = unqualifyColumn(ident(name));
|
|
1782
|
+
return { name: plain, qualified, alias: as === null ? plain : ident(as[1] ?? ""), star: false };
|
|
1783
|
+
}
|
|
1520
1784
|
function project(rows, selectRaw) {
|
|
1521
1785
|
if (/^count\s*\(\s*\*/i.test(selectRaw) || /^count\s*\(\s*1\)/i.test(selectRaw)) {
|
|
1522
1786
|
const alias = selectRaw.match(/\bAS\s+([A-Za-z_][A-Za-z0-9_]*)/i)?.[1] ?? "n";
|
|
@@ -1527,10 +1791,21 @@ function project(rows, selectRaw) {
|
|
|
1527
1791
|
return [{ [constMatch[2]]: Number(constMatch[1]) }];
|
|
1528
1792
|
}
|
|
1529
1793
|
if (selectRaw.trim() === "*") return rows;
|
|
1530
|
-
const
|
|
1794
|
+
const items = selectRaw.split(",").map(parseSelectItem);
|
|
1795
|
+
const valueOf = (row, item) => item.qualified !== "" && row[item.qualified] !== void 0 ? row[item.qualified] : row[item.name];
|
|
1796
|
+
if (items.some((item) => item.star)) {
|
|
1797
|
+
return rows.map((row) => {
|
|
1798
|
+
const out = { ...row };
|
|
1799
|
+
for (const item of items) {
|
|
1800
|
+
if (item.star) continue;
|
|
1801
|
+
out[item.alias] = valueOf(row, item);
|
|
1802
|
+
}
|
|
1803
|
+
return out;
|
|
1804
|
+
});
|
|
1805
|
+
}
|
|
1531
1806
|
return rows.map((row) => {
|
|
1532
1807
|
const out = {};
|
|
1533
|
-
for (const
|
|
1808
|
+
for (const item of items) out[item.alias] = valueOf(row, item);
|
|
1534
1809
|
return out;
|
|
1535
1810
|
});
|
|
1536
1811
|
}
|
|
@@ -2389,6 +2664,18 @@ function resolveFunctionEntry(files, fnName) {
|
|
|
2389
2664
|
if (files[directory] !== void 0) return directory;
|
|
2390
2665
|
return void 0;
|
|
2391
2666
|
}
|
|
2667
|
+
function listFunctionNames(files) {
|
|
2668
|
+
const names = /* @__PURE__ */ new Set();
|
|
2669
|
+
for (const key of Object.keys(files)) {
|
|
2670
|
+
const parts = key.split("/");
|
|
2671
|
+
if (parts.length === 1 && parts[0] !== void 0 && parts[0].endsWith(".ts")) {
|
|
2672
|
+
names.add(parts[0].slice(0, -3));
|
|
2673
|
+
} else if (parts.length === 2 && parts[1] === "index.ts" && parts[0] !== void 0) {
|
|
2674
|
+
names.add(parts[0]);
|
|
2675
|
+
}
|
|
2676
|
+
}
|
|
2677
|
+
return [...names];
|
|
2678
|
+
}
|
|
2392
2679
|
function createSimInvokeHandler(options) {
|
|
2393
2680
|
return async (method, args) => {
|
|
2394
2681
|
if (method !== "invoke") {
|
|
@@ -3681,6 +3968,27 @@ if (workerPort !== null && workerData !== void 0) {
|
|
|
3681
3968
|
// packages/cli/src/dev-shared.ts
|
|
3682
3969
|
import { readdir as readdir2, readFile as readFile5 } from "node:fs/promises";
|
|
3683
3970
|
import { join as join8 } from "node:path";
|
|
3971
|
+
|
|
3972
|
+
// packages/runtime/src/shared/function-source.ts
|
|
3973
|
+
var SHARED_SOURCE_ROOT = "functions/_shared/";
|
|
3974
|
+
var FUNCTION_SHARED_DIR = "_shared/";
|
|
3975
|
+
function mergeSharedSource(files, shared) {
|
|
3976
|
+
const merged = { ...files };
|
|
3977
|
+
for (const file of shared) {
|
|
3978
|
+
if (!file.path.startsWith(SHARED_SOURCE_ROOT)) continue;
|
|
3979
|
+
const rel = file.path.slice(SHARED_SOURCE_ROOT.length);
|
|
3980
|
+
if (rel === "") continue;
|
|
3981
|
+
merged[`${FUNCTION_SHARED_DIR}${rel}`] = file.content;
|
|
3982
|
+
}
|
|
3983
|
+
return merged;
|
|
3984
|
+
}
|
|
3985
|
+
|
|
3986
|
+
// shared/shared-source.ts
|
|
3987
|
+
var FUNCTION_SHARED_DIR2 = "_shared";
|
|
3988
|
+
var SHARED_SOURCE_ROOT2 = `functions/${FUNCTION_SHARED_DIR2}/`;
|
|
3989
|
+
var FUNCTION_SHARED_MAX_TOTAL_BYTES = 256 * 1024;
|
|
3990
|
+
|
|
3991
|
+
// packages/cli/src/dev-shared.ts
|
|
3684
3992
|
var BEARER_TOKEN_RE = /^Bearer\s+(.+)$/i;
|
|
3685
3993
|
function bearerUserResolverFromEnv() {
|
|
3686
3994
|
const raw = process.env.ADEP_AUTH_ISSUER;
|
|
@@ -3708,6 +4016,9 @@ function createBearerUserResolver(issuer) {
|
|
|
3708
4016
|
}
|
|
3709
4017
|
};
|
|
3710
4018
|
}
|
|
4019
|
+
function isRuntimeSource(name) {
|
|
4020
|
+
return (name.endsWith(".ts") || name.endsWith(".js")) && !name.endsWith(".d.ts") && !name.endsWith(".test.ts");
|
|
4021
|
+
}
|
|
3711
4022
|
async function collectFunctions(dir) {
|
|
3712
4023
|
const files = {};
|
|
3713
4024
|
const walk = async (sub, prefix) => {
|
|
@@ -3722,7 +4033,7 @@ async function collectFunctions(dir) {
|
|
|
3722
4033
|
const full = join8(sub, entry.name);
|
|
3723
4034
|
if (entry.isDirectory()) {
|
|
3724
4035
|
await walk(full, rel);
|
|
3725
|
-
} else if (entry.isFile() && entry.name
|
|
4036
|
+
} else if (entry.isFile() && isRuntimeSource(entry.name)) {
|
|
3726
4037
|
files[rel] = await readFile5(full, "utf8");
|
|
3727
4038
|
}
|
|
3728
4039
|
}
|
|
@@ -3730,6 +4041,24 @@ async function collectFunctions(dir) {
|
|
|
3730
4041
|
await walk(dir, "");
|
|
3731
4042
|
return files;
|
|
3732
4043
|
}
|
|
4044
|
+
function mergeSharedIntoFunctions(files) {
|
|
4045
|
+
const shared = [];
|
|
4046
|
+
for (const [path, content] of Object.entries(files)) {
|
|
4047
|
+
if (!path.startsWith(`${FUNCTION_SHARED_DIR2}/`)) continue;
|
|
4048
|
+
shared.push({
|
|
4049
|
+
path: `${SHARED_SOURCE_ROOT2}${path.slice(FUNCTION_SHARED_DIR2.length + 1)}`,
|
|
4050
|
+
content
|
|
4051
|
+
});
|
|
4052
|
+
}
|
|
4053
|
+
if (shared.length === 0) return files;
|
|
4054
|
+
const inFunction = mergeSharedSource({}, shared);
|
|
4055
|
+
const out = { ...files };
|
|
4056
|
+
for (const name of listFunctionNames(files)) {
|
|
4057
|
+
if (name.startsWith("_") || files[`${name}/index.ts`] === void 0) continue;
|
|
4058
|
+
for (const [rel, content] of Object.entries(inFunction)) out[`${name}/${rel}`] = content;
|
|
4059
|
+
}
|
|
4060
|
+
return out;
|
|
4061
|
+
}
|
|
3733
4062
|
function bodyOf(req) {
|
|
3734
4063
|
return new Promise((resolveBody, rejectBody) => {
|
|
3735
4064
|
const chunks = [];
|
|
@@ -3847,7 +4176,7 @@ async function startDevServer(options) {
|
|
|
3847
4176
|
log
|
|
3848
4177
|
});
|
|
3849
4178
|
await ensureGitignore(cwd);
|
|
3850
|
-
let files = await collectFunctions(functionsDir);
|
|
4179
|
+
let files = mergeSharedIntoFunctions(await collectFunctions(functionsDir));
|
|
3851
4180
|
let env = {
|
|
3852
4181
|
...config.environment,
|
|
3853
4182
|
...await loadSimEnv(cwd).catch(() => ({}))
|
|
@@ -3925,7 +4254,7 @@ async function startDevServer(options) {
|
|
|
3925
4254
|
};
|
|
3926
4255
|
const reload = async () => {
|
|
3927
4256
|
const [nextFiles, envText2] = await Promise.all([
|
|
3928
|
-
collectFunctions(functionsDir),
|
|
4257
|
+
collectFunctions(functionsDir).then(mergeSharedIntoFunctions),
|
|
3929
4258
|
readFile6(join9(cwd, ".env.local"), "utf8").catch(() => "")
|
|
3930
4259
|
]);
|
|
3931
4260
|
files = nextFiles;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adep/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "`adep` 命令行工具包位:登录 / 初始化 / 本地调试 / 部署 / 数据库维护 / 云存储 / 静态托管 / 微前端组件(widget),实现见任务单 CLI-001 ~ CLI-003 与 FE-002;子路径 `@adep/cli/vite` 提供云函数 vite 插件(CLI-014)",
|
|
6
6
|
"bin": {
|
|
@@ -21,15 +21,16 @@
|
|
|
21
21
|
"commander": "14.0.2",
|
|
22
22
|
"esbuild": "0.25.12",
|
|
23
23
|
"@adep/cf-compat": "0.1.1",
|
|
24
|
-
"@adep/vite-plugin": "0.1.
|
|
24
|
+
"@adep/vite-plugin": "0.1.5"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"@adep/runtime": "0.2.
|
|
27
|
+
"@adep/runtime": "0.2.5",
|
|
28
28
|
"@adep/types": "0.2.3"
|
|
29
29
|
},
|
|
30
30
|
"scripts": {
|
|
31
31
|
"test": "vitest run",
|
|
32
32
|
"init": "bun run src/index.ts init --template fullstack example1",
|
|
33
|
+
"gen:templates": "bun run scripts/build-templates.mjs",
|
|
33
34
|
"build": "bun run ../../scripts/build-package.ts cli"
|
|
34
35
|
}
|
|
35
36
|
}
|