@adep/cli 0.1.8 → 0.1.10
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 +7 -1
- package/dist/index.js +685 -323
- package/dist/vite.js +461 -135
- package/dist/worker-entry.js +19 -12
- package/package.json +4 -4
package/dist/vite.js
CHANGED
|
@@ -4,8 +4,8 @@ import { adepPlugin } from "@adep/vite-plugin";
|
|
|
4
4
|
// packages/cli/src/dev.ts
|
|
5
5
|
import { createServer } from "node:http";
|
|
6
6
|
import { watch } from "node:fs";
|
|
7
|
-
import { mkdir as mkdir3,
|
|
8
|
-
import { basename, join as
|
|
7
|
+
import { mkdir as mkdir3, readFile as readFile6, writeFile as writeFile3 } from "node:fs/promises";
|
|
8
|
+
import { basename, join as join9, resolve as resolve2 } from "node:path";
|
|
9
9
|
|
|
10
10
|
// packages/runtime/src/shared/capability-keys.ts
|
|
11
11
|
var RPC_CAPABILITY_KEY = "__adepRpc";
|
|
@@ -1106,7 +1106,7 @@ function createDbCapability(driver, options = {}) {
|
|
|
1106
1106
|
};
|
|
1107
1107
|
}
|
|
1108
1108
|
|
|
1109
|
-
// packages/
|
|
1109
|
+
// packages/runtime/src/sim/sql-engine.ts
|
|
1110
1110
|
var SimDbError = class extends Error {
|
|
1111
1111
|
constructor(code, message) {
|
|
1112
1112
|
super(message);
|
|
@@ -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) {
|
|
@@ -1146,7 +1147,7 @@ function parseCreateTable(ddl) {
|
|
|
1146
1147
|
);
|
|
1147
1148
|
if (m === null) return null;
|
|
1148
1149
|
const name = ident(m[1]);
|
|
1149
|
-
const body = m[
|
|
1150
|
+
const body = m[3];
|
|
1150
1151
|
const columns = [];
|
|
1151
1152
|
for (const part of body.split(",")) {
|
|
1152
1153
|
const tokens = part.trim().split(/\s+/);
|
|
@@ -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;
|
|
1199
|
+
}
|
|
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);
|
|
1202
1262
|
}
|
|
1203
|
-
function matchWhere(
|
|
1204
|
-
return clauses.every((c) => matchValue(row[c.column], c));
|
|
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;
|
|
@@ -1236,9 +1458,9 @@ function matchValue(value, clause) {
|
|
|
1236
1458
|
const right = clause.value;
|
|
1237
1459
|
switch (op) {
|
|
1238
1460
|
case "=":
|
|
1239
|
-
return left === right;
|
|
1461
|
+
return left !== null && right !== null && left === right;
|
|
1240
1462
|
case "!=":
|
|
1241
|
-
return left !== right;
|
|
1463
|
+
return left !== null && right !== null && left !== right;
|
|
1242
1464
|
case ">":
|
|
1243
1465
|
return left !== null && right !== null && left > right;
|
|
1244
1466
|
case ">=":
|
|
@@ -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
|
}
|
|
@@ -1698,6 +1973,19 @@ function assertSafeStoragePath(path) {
|
|
|
1698
1973
|
}
|
|
1699
1974
|
return path;
|
|
1700
1975
|
}
|
|
1976
|
+
function assertStoragePrefix(prefix) {
|
|
1977
|
+
if (prefix !== void 0 && prefix !== "") {
|
|
1978
|
+
const segments = prefix.split("/");
|
|
1979
|
+
if (prefix.startsWith("/") || /[\\]/.test(prefix) || segments.some((segment) => segment === "..")) {
|
|
1980
|
+
throw new StorageError(
|
|
1981
|
+
400,
|
|
1982
|
+
STORAGE_CODES.invalidPath,
|
|
1983
|
+
`\u975E\u6CD5\u524D\u7F00 "${prefix}"\uFF08\u7981\u6B62 / \u5F00\u5934\u3001\u53CD\u659C\u6760\u6216 .. \u7A7F\u8D8A\uFF09`
|
|
1984
|
+
);
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
return prefix ?? "";
|
|
1988
|
+
}
|
|
1701
1989
|
|
|
1702
1990
|
// packages/runtime/src/storage/hmac-sha256.ts
|
|
1703
1991
|
var K = new Uint32Array([
|
|
@@ -2081,16 +2369,7 @@ function createLocalStorageDriver(options) {
|
|
|
2081
2369
|
await unlink(metaPath(projectId, path)).catch(() => void 0);
|
|
2082
2370
|
},
|
|
2083
2371
|
async list(projectId, prefix) {
|
|
2084
|
-
|
|
2085
|
-
const segments = prefix.split("/");
|
|
2086
|
-
if (prefix.startsWith("/") || /[\\]/.test(prefix) || segments.some((segment) => segment === "..")) {
|
|
2087
|
-
throw new StorageError(
|
|
2088
|
-
400,
|
|
2089
|
-
STORAGE_CODES.invalidPath,
|
|
2090
|
-
`\u975E\u6CD5\u524D\u7F00 "${prefix}"\uFF08\u7981\u6B62 / \u5F00\u5934\u3001\u53CD\u659C\u6760\u6216 .. \u7A7F\u8D8A\uFF09`
|
|
2091
|
-
);
|
|
2092
|
-
}
|
|
2093
|
-
}
|
|
2372
|
+
assertStoragePrefix(prefix);
|
|
2094
2373
|
const root = bucketDir(projectId);
|
|
2095
2374
|
const metas = [];
|
|
2096
2375
|
const walk = async (dir, relative) => {
|
|
@@ -2156,7 +2435,7 @@ function createSimStorageCapability(options) {
|
|
|
2156
2435
|
return { bundle, driver };
|
|
2157
2436
|
}
|
|
2158
2437
|
|
|
2159
|
-
// packages/
|
|
2438
|
+
// packages/runtime/src/sim/realtime.ts
|
|
2160
2439
|
var SimRealtime = class {
|
|
2161
2440
|
seq = 0;
|
|
2162
2441
|
subscribers = /* @__PURE__ */ new Map();
|
|
@@ -2278,10 +2557,7 @@ function createSimRealtimeCapability() {
|
|
|
2278
2557
|
};
|
|
2279
2558
|
}
|
|
2280
2559
|
|
|
2281
|
-
// packages/
|
|
2282
|
-
function simDir(cwd) {
|
|
2283
|
-
return join4(cwd, ".adep", "sim");
|
|
2284
|
-
}
|
|
2560
|
+
// packages/runtime/src/sim/merge.ts
|
|
2285
2561
|
function mergeBundles(bundles) {
|
|
2286
2562
|
const capabilities = [];
|
|
2287
2563
|
const byName = /* @__PURE__ */ new Map();
|
|
@@ -2301,6 +2577,11 @@ function mergeBundles(bundles) {
|
|
|
2301
2577
|
}
|
|
2302
2578
|
return { capabilities, rpcHandlers };
|
|
2303
2579
|
}
|
|
2580
|
+
|
|
2581
|
+
// packages/cli/src/sim/runtime.ts
|
|
2582
|
+
function simDir(cwd) {
|
|
2583
|
+
return join4(cwd, ".adep", "sim");
|
|
2584
|
+
}
|
|
2304
2585
|
function jsonStorage(cwd) {
|
|
2305
2586
|
const file = join4(simDir(cwd), "db.json");
|
|
2306
2587
|
return {
|
|
@@ -2416,12 +2697,21 @@ function createSimInvokeHandler(options) {
|
|
|
2416
2697
|
};
|
|
2417
2698
|
}
|
|
2418
2699
|
|
|
2419
|
-
//
|
|
2420
|
-
var
|
|
2421
|
-
var
|
|
2422
|
-
|
|
2423
|
-
|
|
2700
|
+
// shared/builtin-deps.ts
|
|
2701
|
+
var CF_COMPAT_SPECIFIER = "@adep/cf-compat";
|
|
2702
|
+
var STATE_OBJECTS_SPECIFIER = "@adep/runtime/state-objects";
|
|
2703
|
+
var BUILTIN_DEPS = [
|
|
2704
|
+
CF_COMPAT_SPECIFIER,
|
|
2705
|
+
STATE_OBJECTS_SPECIFIER,
|
|
2706
|
+
"axios",
|
|
2707
|
+
"lodash",
|
|
2708
|
+
"dayjs",
|
|
2709
|
+
"zod"
|
|
2424
2710
|
];
|
|
2711
|
+
var BUILTIN_DEPS_CSV = BUILTIN_DEPS.join(",");
|
|
2712
|
+
|
|
2713
|
+
// packages/cli/src/builtin-deps.ts
|
|
2714
|
+
var LOCAL_BUILTIN_DEPS = [CF_COMPAT_SPECIFIER, STATE_OBJECTS_SPECIFIER];
|
|
2425
2715
|
|
|
2426
2716
|
// packages/cli/src/sim/boundary.ts
|
|
2427
2717
|
var SIM_BOUNDARIES = [
|
|
@@ -3057,9 +3347,9 @@ function loadFunctionModule(files, entry, sandboxGlobals, resolveBare) {
|
|
|
3057
3347
|
|
|
3058
3348
|
// packages/runtime/src/state-objects/loader.ts
|
|
3059
3349
|
var STATE_OBJECTS_ENTRY = "state-objects.ts";
|
|
3060
|
-
var
|
|
3350
|
+
var STATE_OBJECTS_SPECIFIER2 = "@adep/runtime/state-objects";
|
|
3061
3351
|
function resolveStateObjectSpecifier(request) {
|
|
3062
|
-
if (request ===
|
|
3352
|
+
if (request === STATE_OBJECTS_SPECIFIER2) return { StateObject };
|
|
3063
3353
|
return void 0;
|
|
3064
3354
|
}
|
|
3065
3355
|
function defaultStateSandboxGlobals() {
|
|
@@ -3381,6 +3671,19 @@ function createSandboxFetch(options) {
|
|
|
3381
3671
|
};
|
|
3382
3672
|
}
|
|
3383
3673
|
|
|
3674
|
+
// packages/runtime/src/functions/runtime/rpc-wire.ts
|
|
3675
|
+
function wireRpcResponses(port, pending) {
|
|
3676
|
+
port.on?.((message) => {
|
|
3677
|
+
const reply = message;
|
|
3678
|
+
if (reply?.type !== "rpc-response" || typeof reply.id !== "number") return;
|
|
3679
|
+
const entry = pending.get(reply.id);
|
|
3680
|
+
if (entry === void 0) return;
|
|
3681
|
+
pending.delete(reply.id);
|
|
3682
|
+
if (reply.ok === true) entry.resolve(reply.result);
|
|
3683
|
+
else entry.reject(new Error(reply.error ?? "RPC \u80FD\u529B\u8C03\u7528\u5931\u8D25"));
|
|
3684
|
+
});
|
|
3685
|
+
}
|
|
3686
|
+
|
|
3384
3687
|
// packages/runtime/src/functions/runtime/chain.ts
|
|
3385
3688
|
function isChainCapability(value) {
|
|
3386
3689
|
if (typeof value !== "object" || value === null) return false;
|
|
@@ -3452,6 +3755,11 @@ function createChainClient(capability, port, pending, nextId, spec) {
|
|
|
3452
3755
|
return makeRoot(void 0);
|
|
3453
3756
|
}
|
|
3454
3757
|
|
|
3758
|
+
// packages/runtime/src/shared/regexp.ts
|
|
3759
|
+
function escapeRegExp(text) {
|
|
3760
|
+
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3761
|
+
}
|
|
3762
|
+
|
|
3455
3763
|
// packages/runtime/src/functions/runtime/worker-entry.ts
|
|
3456
3764
|
function isRpcCapability(value) {
|
|
3457
3765
|
return typeof value === "object" && value !== null && value[RPC_CAPABILITY_KEY] === true;
|
|
@@ -3481,9 +3789,6 @@ function errorMessageOf2(error) {
|
|
|
3481
3789
|
}
|
|
3482
3790
|
return String(error);
|
|
3483
3791
|
}
|
|
3484
|
-
function escapeRegExp(text) {
|
|
3485
|
-
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3486
|
-
}
|
|
3487
3792
|
function firstUserFrame(stack, files) {
|
|
3488
3793
|
for (const key of Object.keys(files)) {
|
|
3489
3794
|
const match = new RegExp(
|
|
@@ -3542,15 +3847,7 @@ function runWorker(input, port) {
|
|
|
3542
3847
|
const container = createCloudContainer();
|
|
3543
3848
|
const pending = /* @__PURE__ */ new Map();
|
|
3544
3849
|
let rpcId = 0;
|
|
3545
|
-
port
|
|
3546
|
-
const reply = message;
|
|
3547
|
-
if (reply?.type !== "rpc-response" || typeof reply.id !== "number") return;
|
|
3548
|
-
const entry = pending.get(reply.id);
|
|
3549
|
-
if (entry === void 0) return;
|
|
3550
|
-
pending.delete(reply.id);
|
|
3551
|
-
if (reply.ok === true) entry.resolve(reply.result);
|
|
3552
|
-
else entry.reject(new Error(reply.error ?? "RPC \u80FD\u529B\u8C03\u7528\u5931\u8D25"));
|
|
3553
|
-
});
|
|
3850
|
+
wireRpcResponses(port, pending);
|
|
3554
3851
|
for (const capability of input.capabilities ?? []) {
|
|
3555
3852
|
container.register(
|
|
3556
3853
|
capability.name,
|
|
@@ -3656,32 +3953,39 @@ if (workerPort !== null && workerData !== void 0) {
|
|
|
3656
3953
|
runWorker(workerData, port);
|
|
3657
3954
|
}
|
|
3658
3955
|
|
|
3659
|
-
// packages/cli/src/dev.ts
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3956
|
+
// packages/cli/src/dev-shared.ts
|
|
3957
|
+
import { readdir as readdir2, readFile as readFile5 } from "node:fs/promises";
|
|
3958
|
+
import { join as join8 } from "node:path";
|
|
3959
|
+
var BEARER_TOKEN_RE = /^Bearer\s+(.+)$/i;
|
|
3960
|
+
function bearerUserResolverFromEnv() {
|
|
3961
|
+
const raw = process.env.ADEP_AUTH_ISSUER;
|
|
3962
|
+
if (raw === void 0 || raw.trim() === "") return void 0;
|
|
3963
|
+
return createBearerUserResolver(raw.trim());
|
|
3964
|
+
}
|
|
3965
|
+
function createBearerUserResolver(issuer) {
|
|
3966
|
+
const userinfoUrl = `${issuer.replace(/\/+$/, "")}/oauth/userinfo`;
|
|
3967
|
+
return async (headers) => {
|
|
3968
|
+
const match = BEARER_TOKEN_RE.exec((headers["authorization"] ?? "").trim());
|
|
3969
|
+
const token = match?.[1]?.trim();
|
|
3970
|
+
if (token === void 0 || token === "") return null;
|
|
3971
|
+
try {
|
|
3972
|
+
const res = await fetch(userinfoUrl, { headers: { authorization: `Bearer ${token}` } });
|
|
3973
|
+
if (!res.ok) return null;
|
|
3974
|
+
const claims = await res.json();
|
|
3975
|
+
if (typeof claims.sub !== "string" || claims.sub.length === 0) return null;
|
|
3976
|
+
return {
|
|
3977
|
+
id: claims.sub,
|
|
3978
|
+
...typeof claims.name === "string" ? { name: claims.name } : {},
|
|
3979
|
+
...typeof claims.email === "string" ? { email: claims.email } : {}
|
|
3980
|
+
};
|
|
3981
|
+
} catch {
|
|
3982
|
+
return null;
|
|
3983
|
+
}
|
|
3668
3984
|
};
|
|
3669
3985
|
}
|
|
3670
|
-
function parseEnvFile(content) {
|
|
3671
|
-
const env = {};
|
|
3672
|
-
for (const raw of content.split(/\r?\n/)) {
|
|
3673
|
-
const line = raw.trim();
|
|
3674
|
-
if (line.length === 0 || line.startsWith("#")) continue;
|
|
3675
|
-
const eq = line.indexOf("=");
|
|
3676
|
-
if (eq === -1) continue;
|
|
3677
|
-
const key = line.slice(0, eq).trim();
|
|
3678
|
-
if (key.length === 0) continue;
|
|
3679
|
-
env[key] = line.slice(eq + 1).trim();
|
|
3680
|
-
}
|
|
3681
|
-
return env;
|
|
3682
|
-
}
|
|
3683
3986
|
async function collectFunctions(dir) {
|
|
3684
3987
|
const files = {};
|
|
3988
|
+
const isRuntimeSource = (name) => (name.endsWith(".ts") || name.endsWith(".js")) && !name.endsWith(".d.ts") && !name.endsWith(".test.ts");
|
|
3685
3989
|
const walk = async (sub, prefix) => {
|
|
3686
3990
|
let entries;
|
|
3687
3991
|
try {
|
|
@@ -3694,7 +3998,7 @@ async function collectFunctions(dir) {
|
|
|
3694
3998
|
const full = join8(sub, entry.name);
|
|
3695
3999
|
if (entry.isDirectory()) {
|
|
3696
4000
|
await walk(full, rel);
|
|
3697
|
-
} else if (entry.isFile() && entry.name
|
|
4001
|
+
} else if (entry.isFile() && isRuntimeSource(entry.name)) {
|
|
3698
4002
|
files[rel] = await readFile5(full, "utf8");
|
|
3699
4003
|
}
|
|
3700
4004
|
}
|
|
@@ -3721,6 +4025,42 @@ function bodyOf(req) {
|
|
|
3721
4025
|
req.on("error", rejectBody);
|
|
3722
4026
|
});
|
|
3723
4027
|
}
|
|
4028
|
+
function writeJson(res, status, payload) {
|
|
4029
|
+
res.writeHead(status, { "content-type": "application/json" });
|
|
4030
|
+
res.end(JSON.stringify(payload));
|
|
4031
|
+
}
|
|
4032
|
+
async function requestInput(url, req, readBody) {
|
|
4033
|
+
const query = {};
|
|
4034
|
+
for (const key of new Set(url.searchParams.keys())) {
|
|
4035
|
+
const values = url.searchParams.getAll(key);
|
|
4036
|
+
query[key] = values.length > 1 ? values.join(",") : values[0] ?? "";
|
|
4037
|
+
}
|
|
4038
|
+
const headers = {};
|
|
4039
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
4040
|
+
if (typeof value === "string") headers[key] = value;
|
|
4041
|
+
}
|
|
4042
|
+
const body = req.method === "GET" || req.method === "HEAD" ? void 0 : await readBody(req);
|
|
4043
|
+
return {
|
|
4044
|
+
method: req.method ?? "GET",
|
|
4045
|
+
path: url.pathname,
|
|
4046
|
+
query,
|
|
4047
|
+
headers,
|
|
4048
|
+
...body === void 0 ? {} : { body }
|
|
4049
|
+
};
|
|
4050
|
+
}
|
|
4051
|
+
|
|
4052
|
+
// packages/cli/src/dev.ts
|
|
4053
|
+
async function loadConfig(cwd) {
|
|
4054
|
+
const name = basename(resolve2(cwd));
|
|
4055
|
+
const config = await loadAdepConfigModule(cwd);
|
|
4056
|
+
return {
|
|
4057
|
+
name: config?.name ?? name,
|
|
4058
|
+
functionsDir: config?.functionsDir ?? "functions",
|
|
4059
|
+
functionsPrefix: config?.functions_prefix ?? "",
|
|
4060
|
+
...config?.environment === void 0 ? {} : { environment: config.environment }
|
|
4061
|
+
};
|
|
4062
|
+
}
|
|
4063
|
+
var parseEnvFile = parseEnv;
|
|
3724
4064
|
function resolveRouteFnName(pathname, prefix) {
|
|
3725
4065
|
const segments = pathname.split("/").filter((segment) => segment.length > 0);
|
|
3726
4066
|
const normalizedPrefix = prefix.replace(/^\/+|\/+$/g, "");
|
|
@@ -3747,10 +4087,6 @@ function resolveRouteFnName(pathname, prefix) {
|
|
|
3747
4087
|
}
|
|
3748
4088
|
return { fnName: second };
|
|
3749
4089
|
}
|
|
3750
|
-
function writeJson(res, status, payload) {
|
|
3751
|
-
res.writeHead(status, { "content-type": "application/json" });
|
|
3752
|
-
res.end(JSON.stringify(payload));
|
|
3753
|
-
}
|
|
3754
4090
|
function printBoundaries(log) {
|
|
3755
4091
|
log("[adep] \u80FD\u529B\u8FB9\u754C\uFF08\u6A21\u62DF\u8FD0\u884C\u65F6\u53EA\u66FF\u6362\u4F20\u8F93/\u6301\u4E45\u5316\uFF0C\u4E0D\u6539\u5199\u8BED\u4E49\uFF09\uFF1A");
|
|
3756
4092
|
for (const b of SIM_BOUNDARIES) {
|
|
@@ -3758,8 +4094,8 @@ function printBoundaries(log) {
|
|
|
3758
4094
|
}
|
|
3759
4095
|
}
|
|
3760
4096
|
async function ensureGitignore(cwd) {
|
|
3761
|
-
const gitignorePath =
|
|
3762
|
-
const existing = await
|
|
4097
|
+
const gitignorePath = join9(cwd, ".gitignore");
|
|
4098
|
+
const existing = await readFile6(gitignorePath, "utf8").catch(() => "");
|
|
3763
4099
|
if (existing.split(/\r?\n/).includes(".adep/")) return;
|
|
3764
4100
|
await writeFile3(gitignorePath, `${existing.replace(/\n+$/, "")}
|
|
3765
4101
|
.adep/
|
|
@@ -3773,8 +4109,9 @@ async function startDevServer(options) {
|
|
|
3773
4109
|
if (options.prefix !== void 0) {
|
|
3774
4110
|
config.functionsPrefix = options.prefix.replace(/^\/+|\/+$/g, "");
|
|
3775
4111
|
}
|
|
3776
|
-
const functionsDir =
|
|
4112
|
+
const functionsDir = join9(cwd, config.functionsDir);
|
|
3777
4113
|
const coldStartAt = Date.now();
|
|
4114
|
+
const bearerUser = bearerUserResolverFromEnv();
|
|
3778
4115
|
const executor = new WorkerFunctionExecutor({
|
|
3779
4116
|
deps: { rootDir: cwd, builtin: LOCAL_BUILTIN_DEPS }
|
|
3780
4117
|
});
|
|
@@ -3865,12 +4202,12 @@ async function startDevServer(options) {
|
|
|
3865
4202
|
const reload = async () => {
|
|
3866
4203
|
const [nextFiles, envText2] = await Promise.all([
|
|
3867
4204
|
collectFunctions(functionsDir),
|
|
3868
|
-
|
|
4205
|
+
readFile6(join9(cwd, ".env.local"), "utf8").catch(() => "")
|
|
3869
4206
|
]);
|
|
3870
4207
|
files = nextFiles;
|
|
3871
4208
|
env = { ...config.environment, ...parseEnvFile(envText2) };
|
|
3872
4209
|
};
|
|
3873
|
-
const envText = await
|
|
4210
|
+
const envText = await readFile6(join9(cwd, ".env.local"), "utf8").catch(() => "");
|
|
3874
4211
|
env = { ...config.environment, ...parseEnvFile(envText) };
|
|
3875
4212
|
let debounceTimer;
|
|
3876
4213
|
let watcher;
|
|
@@ -3885,29 +4222,15 @@ async function startDevServer(options) {
|
|
|
3885
4222
|
watcher = void 0;
|
|
3886
4223
|
}
|
|
3887
4224
|
const buildInput = async (fnName, entry, url, req) => {
|
|
3888
|
-
const query = {};
|
|
3889
|
-
for (const key of new Set(url.searchParams.keys())) {
|
|
3890
|
-
const values = url.searchParams.getAll(key);
|
|
3891
|
-
query[key] = values.length > 1 ? values.join(",") : values[0] ?? "";
|
|
3892
|
-
}
|
|
3893
|
-
const headers = {};
|
|
3894
|
-
for (const [key, value] of Object.entries(req.headers)) {
|
|
3895
|
-
if (typeof value === "string") headers[key] = value;
|
|
3896
|
-
}
|
|
3897
|
-
const body = req.method === "GET" || req.method === "HEAD" ? void 0 : await bodyOf(req);
|
|
3898
4225
|
const hasEnv = Object.keys(env).length > 0;
|
|
4226
|
+
const request = await requestInput(url, req, bodyOf);
|
|
4227
|
+
if (bearerUser !== void 0) request.user = await bearerUser(request.headers);
|
|
3899
4228
|
return {
|
|
3900
4229
|
project: { id: "local", slug: config.name },
|
|
3901
4230
|
fn: { id: fnName, name: fnName },
|
|
3902
4231
|
files,
|
|
3903
4232
|
entry,
|
|
3904
|
-
request
|
|
3905
|
-
method: req.method ?? "GET",
|
|
3906
|
-
path: url.pathname,
|
|
3907
|
-
query,
|
|
3908
|
-
headers,
|
|
3909
|
-
...body === void 0 ? {} : { body }
|
|
3910
|
-
},
|
|
4233
|
+
request,
|
|
3911
4234
|
// 模拟运行时能力:db / storage / realtime 各自只读复用线上装配,语义一致。
|
|
3912
4235
|
capabilities: dbBundle.capabilities,
|
|
3913
4236
|
rpcHandlers: {
|
|
@@ -4044,6 +4367,9 @@ async function startDevServer(options) {
|
|
|
4044
4367
|
log(`[adep] dev server listening on ${baseUrl}\uFF08\u6A21\u62DF\u8FD0\u884C\u65F6\uFF0C\u51B7\u542F\u52A8 ${coldStartMs}ms\uFF09`);
|
|
4045
4368
|
log(`[adep] curl \u793A\u4F8B\uFF1Acurl ${baseUrl}${curlPath}`);
|
|
4046
4369
|
printBoundaries(log);
|
|
4370
|
+
if (bearerUser !== void 0) {
|
|
4371
|
+
log(`[adep] \u767B\u5F55\u5373\u670D\u52A1\uFF1AADEP_AUTH_ISSUER \u5DF2\u914D\u7F6E\uFF0CBearer token \u5C06\u89E3\u6790\u4E3A\u7528\u6237\u8EAB\u4EFD\uFF08userinfo \u7AEF\u70B9\uFF09`);
|
|
4372
|
+
}
|
|
4047
4373
|
log(`[adep] \u6A21\u62DF\u6570\u636E\u76EE\u5F55\uFF1A${simDir(cwd)}`);
|
|
4048
4374
|
startStateAlarmScheduler();
|
|
4049
4375
|
return {
|