@adep/cli 0.1.15 → 0.1.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/dist/index.js +338 -16
- package/dist/vite.js +14 -2
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -2693,6 +2693,14 @@ function hmacSha256(key, message) {
|
|
|
2693
2693
|
function hmacSha256Hex(key, message) {
|
|
2694
2694
|
return [...hmacSha256(key, message)].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
2695
2695
|
}
|
|
2696
|
+
function constantTimeEqual(a, b) {
|
|
2697
|
+
if (a.length !== b.length) return false;
|
|
2698
|
+
let diff = 0;
|
|
2699
|
+
for (let i = 0; i < a.length; i += 1) {
|
|
2700
|
+
diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
2701
|
+
}
|
|
2702
|
+
return diff === 0;
|
|
2703
|
+
}
|
|
2696
2704
|
var K, rotr;
|
|
2697
2705
|
var init_hmac_sha256 = __esm({
|
|
2698
2706
|
"packages/runtime/src/storage/hmac-sha256.ts"() {
|
|
@@ -2778,6 +2786,22 @@ function signDownloadUrl(config, projectId, path, ttlSeconds = DEFAULT_SIGN_TTL_
|
|
|
2778
2786
|
const signature = sign(config.secret, projectId, path, expires);
|
|
2779
2787
|
return `${base}?${SIGN_EXPIRES_KEY}=${expires}&${SIGN_SIGNATURE_KEY}=${signature}`;
|
|
2780
2788
|
}
|
|
2789
|
+
function verifyDownloadSignature(config, projectId, path, query, nowSeconds2 = Math.floor(Date.now() / 1e3)) {
|
|
2790
|
+
const expiresRaw = query.expires;
|
|
2791
|
+
const signatureRaw = query.signature;
|
|
2792
|
+
if (typeof expiresRaw !== "string" || typeof signatureRaw !== "string") {
|
|
2793
|
+
return { ok: false, reason: "missing" };
|
|
2794
|
+
}
|
|
2795
|
+
if (!/^\d{1,15}$/.test(expiresRaw)) return { ok: false, reason: "malformed" };
|
|
2796
|
+
const expires = Number(expiresRaw);
|
|
2797
|
+
if (!Number.isFinite(expires)) return { ok: false, reason: "malformed" };
|
|
2798
|
+
if (nowSeconds2 > expires) return { ok: false, reason: "expired" };
|
|
2799
|
+
const expected = sign(config.secret, projectId, path, expires);
|
|
2800
|
+
if (!constantTimeEqual(signatureRaw, expected)) {
|
|
2801
|
+
return { ok: false, reason: "invalid" };
|
|
2802
|
+
}
|
|
2803
|
+
return { ok: true };
|
|
2804
|
+
}
|
|
2781
2805
|
var DEFAULT_SIGN_TTL_SECONDS, SIGN_EXPIRES_KEY, SIGN_SIGNATURE_KEY;
|
|
2782
2806
|
var init_signature = __esm({
|
|
2783
2807
|
"packages/runtime/src/storage/signature.ts"() {
|
|
@@ -3006,7 +3030,7 @@ function createLocalStorageDriver(options) {
|
|
|
3006
3030
|
assertStoragePrefix(prefix);
|
|
3007
3031
|
const root = bucketDir(projectId);
|
|
3008
3032
|
const metas = [];
|
|
3009
|
-
const walk = async (dir,
|
|
3033
|
+
const walk = async (dir, relative7) => {
|
|
3010
3034
|
let entries;
|
|
3011
3035
|
try {
|
|
3012
3036
|
entries = await readdir3(dir, { withFileTypes: true });
|
|
@@ -3017,7 +3041,7 @@ function createLocalStorageDriver(options) {
|
|
|
3017
3041
|
for (const entry of entries) {
|
|
3018
3042
|
if (entry.name.endsWith(META_SUFFIX)) continue;
|
|
3019
3043
|
const full = join6(dir, entry.name);
|
|
3020
|
-
const rel =
|
|
3044
|
+
const rel = relative7 === "" ? entry.name : `${relative7}/${entry.name}`;
|
|
3021
3045
|
if (entry.isFile()) {
|
|
3022
3046
|
if (prefix !== void 0 && !rel.startsWith(prefix)) continue;
|
|
3023
3047
|
tasks.push(
|
|
@@ -3071,17 +3095,19 @@ function createSimStorageCapability(options) {
|
|
|
3071
3095
|
const dir = join7(options.cwd, ".adep", "sim", "storage");
|
|
3072
3096
|
const driver = createLocalStorageDriver({ dir });
|
|
3073
3097
|
const signer = {
|
|
3074
|
-
secret: options.secret ??
|
|
3098
|
+
secret: options.secret ?? SIM_SIGN_SECRET,
|
|
3075
3099
|
baseUrl: options.baseUrl ?? "http://127.0.0.1:8787"
|
|
3076
3100
|
};
|
|
3077
3101
|
const bundle = createStorageCapability(driver, signer, options.projectId ?? "sim-project");
|
|
3078
3102
|
return { bundle, driver };
|
|
3079
3103
|
}
|
|
3104
|
+
var SIM_SIGN_SECRET;
|
|
3080
3105
|
var init_storage = __esm({
|
|
3081
3106
|
"packages/cli/src/sim/storage.ts"() {
|
|
3082
3107
|
"use strict";
|
|
3083
3108
|
init_cloud2();
|
|
3084
3109
|
init_local();
|
|
3110
|
+
SIM_SIGN_SECRET = "adep-sim-secret";
|
|
3085
3111
|
}
|
|
3086
3112
|
});
|
|
3087
3113
|
|
|
@@ -3281,6 +3307,8 @@ async function createSimRuntime(options) {
|
|
|
3281
3307
|
bundle,
|
|
3282
3308
|
realtime: simRealtime.realtime,
|
|
3283
3309
|
db,
|
|
3310
|
+
/** 存储句柄(serve 的签名文件下载路由用它读对象;bundle 里的 capability 是同一驱动的 RPC 面)。 */
|
|
3311
|
+
storage,
|
|
3284
3312
|
dispose: async () => {
|
|
3285
3313
|
await db.driver.close();
|
|
3286
3314
|
}
|
|
@@ -3395,15 +3423,19 @@ var init_invoke = __esm({
|
|
|
3395
3423
|
});
|
|
3396
3424
|
|
|
3397
3425
|
// shared/builtin-deps.ts
|
|
3398
|
-
var CF_COMPAT_SPECIFIER, STATE_OBJECTS_SPECIFIER, BUILTIN_DEPS, BUILTIN_DEPS_CSV;
|
|
3426
|
+
var CF_COMPAT_SPECIFIER, STATE_OBJECTS_SPECIFIER, CRYPTO_SPECIFIER, ROUTE_SPECIFIER, BUILTIN_DEPS, BUILTIN_DEPS_CSV;
|
|
3399
3427
|
var init_builtin_deps = __esm({
|
|
3400
3428
|
"shared/builtin-deps.ts"() {
|
|
3401
3429
|
"use strict";
|
|
3402
3430
|
CF_COMPAT_SPECIFIER = "@adep/cf-compat";
|
|
3403
3431
|
STATE_OBJECTS_SPECIFIER = "@adep/runtime/state-objects";
|
|
3432
|
+
CRYPTO_SPECIFIER = "@adep/crypto";
|
|
3433
|
+
ROUTE_SPECIFIER = "@adep/runtime/route";
|
|
3404
3434
|
BUILTIN_DEPS = [
|
|
3405
3435
|
CF_COMPAT_SPECIFIER,
|
|
3406
3436
|
STATE_OBJECTS_SPECIFIER,
|
|
3437
|
+
CRYPTO_SPECIFIER,
|
|
3438
|
+
ROUTE_SPECIFIER,
|
|
3407
3439
|
"axios",
|
|
3408
3440
|
"lodash",
|
|
3409
3441
|
"dayjs",
|
|
@@ -3419,7 +3451,12 @@ var init_builtin_deps2 = __esm({
|
|
|
3419
3451
|
"packages/cli/src/builtin-deps.ts"() {
|
|
3420
3452
|
"use strict";
|
|
3421
3453
|
init_builtin_deps();
|
|
3422
|
-
LOCAL_BUILTIN_DEPS = [
|
|
3454
|
+
LOCAL_BUILTIN_DEPS = [
|
|
3455
|
+
CF_COMPAT_SPECIFIER,
|
|
3456
|
+
STATE_OBJECTS_SPECIFIER,
|
|
3457
|
+
CRYPTO_SPECIFIER,
|
|
3458
|
+
ROUTE_SPECIFIER
|
|
3459
|
+
];
|
|
3423
3460
|
}
|
|
3424
3461
|
});
|
|
3425
3462
|
|
|
@@ -5338,7 +5375,7 @@ function splitSqlStatements(source) {
|
|
|
5338
5375
|
const lines = source.split("\n");
|
|
5339
5376
|
for (const rawLine of lines) {
|
|
5340
5377
|
const trimmed = rawLine.trim();
|
|
5341
|
-
if (trimmed.length === 0 || trimmed.startsWith("--")) continue;
|
|
5378
|
+
if (!inQuote && (trimmed.length === 0 || trimmed.startsWith("--"))) continue;
|
|
5342
5379
|
for (let i = 0; i < rawLine.length; i++) {
|
|
5343
5380
|
const ch = rawLine[i];
|
|
5344
5381
|
if (inQuote) {
|
|
@@ -5367,7 +5404,7 @@ function splitSqlStatements(source) {
|
|
|
5367
5404
|
}
|
|
5368
5405
|
buffer += ch;
|
|
5369
5406
|
}
|
|
5370
|
-
buffer += " ";
|
|
5407
|
+
buffer += inQuote ? "\n" : " ";
|
|
5371
5408
|
}
|
|
5372
5409
|
if (inQuote) {
|
|
5373
5410
|
throw new Error(`SQL \u8FC1\u79FB\u6587\u4EF6\u5F15\u53F7\u672A\u95ED\u5408\uFF1A${buffer.trim().slice(0, 80)}\u2026`);
|
|
@@ -5844,9 +5881,66 @@ async function startServeServer(options) {
|
|
|
5844
5881
|
return false;
|
|
5845
5882
|
}
|
|
5846
5883
|
};
|
|
5884
|
+
const serveSignedFile = async (req, res, url, projectId, path) => {
|
|
5885
|
+
const driver = runtime.storage.driver;
|
|
5886
|
+
try {
|
|
5887
|
+
const meta = await driver.getMeta(projectId, path);
|
|
5888
|
+
if (meta.visibility === "private") {
|
|
5889
|
+
const verification = verifyDownloadSignature(
|
|
5890
|
+
{ secret: SIM_SIGN_SECRET, baseUrl: "" },
|
|
5891
|
+
projectId,
|
|
5892
|
+
path,
|
|
5893
|
+
{
|
|
5894
|
+
expires: url.searchParams.get(SIGN_EXPIRES_KEY) ?? void 0,
|
|
5895
|
+
signature: url.searchParams.get(SIGN_SIGNATURE_KEY) ?? void 0
|
|
5896
|
+
}
|
|
5897
|
+
);
|
|
5898
|
+
if (!verification.ok) {
|
|
5899
|
+
const message = verification.reason === "expired" ? "\u7B7E\u540D URL \u5DF2\u8FC7\u671F\uFF1A\u8BF7\u91CD\u65B0\u751F\u6210\uFF0815 \u5206\u949F\u6709\u6548\uFF09" : verification.reason === "missing" ? "\u79C1\u6709\u6587\u4EF6\u9700\u8981\u7B7E\u540D URL \u624D\u80FD\u8BBF\u95EE" : "\u7B7E\u540D\u65E0\u6548\uFF1AURL \u53EF\u80FD\u88AB\u7BE1\u6539";
|
|
5900
|
+
writeJson(res, 403, { error: { code: "STORAGE_SIGNATURE_INVALID", message } });
|
|
5901
|
+
log(`[serve] ${req.method ?? "GET"} ${url.pathname} -> 403 (${verification.reason})`);
|
|
5902
|
+
return true;
|
|
5903
|
+
}
|
|
5904
|
+
}
|
|
5905
|
+
const { data } = await driver.get(projectId, path);
|
|
5906
|
+
res.writeHead(200, {
|
|
5907
|
+
"content-type": meta.contentType ?? "application/octet-stream",
|
|
5908
|
+
"content-length": String(meta.size),
|
|
5909
|
+
"cache-control": meta.visibility === "public" ? "public, max-age=3600" : "private, no-store"
|
|
5910
|
+
});
|
|
5911
|
+
res.end(data);
|
|
5912
|
+
log(`[serve] ${req.method ?? "GET"} ${url.pathname} -> 200\uFF08\u6587\u4EF6\u4E0B\u8F7D ${meta.size}B\uFF09`);
|
|
5913
|
+
} catch (error) {
|
|
5914
|
+
if (error instanceof StorageError) {
|
|
5915
|
+
writeJson(res, error.status, { error: { code: error.code, message: error.message } });
|
|
5916
|
+
log(`[serve] ${req.method ?? "GET"} ${url.pathname} -> ${error.status} (${error.code})`);
|
|
5917
|
+
return true;
|
|
5918
|
+
}
|
|
5919
|
+
writeJson(res, 500, {
|
|
5920
|
+
error: {
|
|
5921
|
+
code: "FILE_DOWNLOAD_ERROR",
|
|
5922
|
+
message: error instanceof Error ? error.message : "\u6587\u4EF6\u4E0B\u8F7D\u5931\u8D25"
|
|
5923
|
+
}
|
|
5924
|
+
});
|
|
5925
|
+
log(`[serve] ${req.method ?? "GET"} ${url.pathname} -> 500\uFF08\u6587\u4EF6\u4E0B\u8F7D\u5F02\u5E38\uFF09`);
|
|
5926
|
+
}
|
|
5927
|
+
return true;
|
|
5928
|
+
};
|
|
5929
|
+
const SIGNED_FILES_ROUTE = /^\/api\/v1\/projects\/([^/]+)\/files\/([^/]+)$/;
|
|
5847
5930
|
const handle = async (req, res) => {
|
|
5848
5931
|
const url = new URL(req.url ?? "/", `http://${host}:${port}`);
|
|
5849
5932
|
const pathname = url.pathname;
|
|
5933
|
+
const filesMatch = SIGNED_FILES_ROUTE.exec(pathname);
|
|
5934
|
+
if (filesMatch !== null && (req.method === "GET" || req.method === "HEAD")) {
|
|
5935
|
+
await serveSignedFile(
|
|
5936
|
+
req,
|
|
5937
|
+
res,
|
|
5938
|
+
url,
|
|
5939
|
+
decodeURIComponent(filesMatch[1]),
|
|
5940
|
+
decodeURIComponent(filesMatch[2])
|
|
5941
|
+
);
|
|
5942
|
+
return;
|
|
5943
|
+
}
|
|
5850
5944
|
const normalizedPrefix = config.functionsPrefix.replace(/^\/+|\/+$/g, "");
|
|
5851
5945
|
const fnRest = normalizedPrefix.length > 0 ? pathname === `/${normalizedPrefix}` || pathname.startsWith(`/${normalizedPrefix}/`) ? pathname.slice(normalizedPrefix.length + 1) : null : pathname === "/api" ? "" : pathname.startsWith("/api/") ? pathname.slice("/api/".length) : null;
|
|
5852
5946
|
if (fnRest !== null) {
|
|
@@ -5994,9 +6088,12 @@ var init_server = __esm({
|
|
|
5994
6088
|
init_executor();
|
|
5995
6089
|
init_http_envelope();
|
|
5996
6090
|
init_worker_executor();
|
|
6091
|
+
init_signature();
|
|
6092
|
+
init_driver();
|
|
5997
6093
|
init_builtin_deps2();
|
|
5998
6094
|
init_db2();
|
|
5999
6095
|
init_runtime();
|
|
6096
|
+
init_storage();
|
|
6000
6097
|
init_env();
|
|
6001
6098
|
init_invoke();
|
|
6002
6099
|
init_dev();
|
|
@@ -7172,6 +7269,189 @@ var init_storage2 = __esm({
|
|
|
7172
7269
|
}
|
|
7173
7270
|
});
|
|
7174
7271
|
|
|
7272
|
+
// packages/cli/src/sandbox-scan.ts
|
|
7273
|
+
import { readdir as readdir7, readFile as readFile16 } from "node:fs/promises";
|
|
7274
|
+
import { join as join20, relative as relative5, sep as sep3 } from "node:path";
|
|
7275
|
+
function extractSpecifiers(line) {
|
|
7276
|
+
const out = [];
|
|
7277
|
+
const patterns = [
|
|
7278
|
+
/\bfrom\s+['"]([^'"]+)['"]/g,
|
|
7279
|
+
// import x from '<spec>' / export … from '<spec>'
|
|
7280
|
+
/\brequire\s*\(\s*['"]([^'"]+)['"]\s*\)/g,
|
|
7281
|
+
/\bimport\s*\(\s*['"]([^'"]+)['"]\s*\)/g,
|
|
7282
|
+
/^\s*import\s+['"]([^'"]+)['"]/g
|
|
7283
|
+
// 副作用导入 import '<spec>'
|
|
7284
|
+
];
|
|
7285
|
+
for (const pattern of patterns) {
|
|
7286
|
+
for (const match of line.matchAll(pattern)) {
|
|
7287
|
+
const spec = match[1];
|
|
7288
|
+
if (spec !== void 0) out.push(spec);
|
|
7289
|
+
}
|
|
7290
|
+
}
|
|
7291
|
+
return out;
|
|
7292
|
+
}
|
|
7293
|
+
function classify(specifier) {
|
|
7294
|
+
if (specifier.startsWith("node:")) {
|
|
7295
|
+
const bare = specifier.slice("node:".length);
|
|
7296
|
+
const root = bare.split("/")[0];
|
|
7297
|
+
const suggestion = BUILTIN_SUGGESTIONS[specifier] ?? BUILTIN_SUGGESTIONS[`node:${root}`];
|
|
7298
|
+
return {
|
|
7299
|
+
code: "NODE_BUILTIN",
|
|
7300
|
+
message: `\u6C99\u7BB1\u6CA1\u6709 node \u5185\u7F6E\u6A21\u5757\uFF0C'${specifier}' \u5728\u53D1\u5E03\u540E\u8FD0\u884C\u65F6\u4F1A\u629B ERR_MODULE_NOT_FOUND\uFF08\u672C\u5730 adep dev \u80FD\u8DD1\uFF0C\u56E0\u4E3A\u5BBF\u4E3B\u5C31\u662F Node\uFF09\u3002${suggestion ?? `\u8BF7\u79FB\u9664\u5BF9 ${root} \u7684\u4F9D\u8D56\u3002`}`
|
|
7301
|
+
};
|
|
7302
|
+
}
|
|
7303
|
+
if (NODE_BUILTINS.has(specifier)) {
|
|
7304
|
+
return {
|
|
7305
|
+
code: "NODE_BUILTIN",
|
|
7306
|
+
message: `\u6C99\u7BB1\u6CA1\u6709 node \u5185\u7F6E\u6A21\u5757\uFF0C'${specifier}' \u5728\u53D1\u5E03\u540E\u8FD0\u884C\u65F6\u4F1A\u629B ERR_MODULE_NOT_FOUND\u3002${BUILTIN_SUGGESTIONS[specifier] ?? `\u8BF7\u79FB\u9664\u5BF9 ${specifier} \u7684\u4F9D\u8D56\u3002`}`
|
|
7307
|
+
};
|
|
7308
|
+
}
|
|
7309
|
+
if (NATIVE_ADDON_PACKAGES.has(specifier)) {
|
|
7310
|
+
return {
|
|
7311
|
+
code: "NATIVE_ADDON",
|
|
7312
|
+
message: `'${specifier}' \u9700\u8981\u539F\u751F C++ \u6269\u5C55\uFF0C\u4E91\u51FD\u6570\u6C99\u7BB1\u65E0\u6CD5\u52A0\u8F7D\uFF08\u4E5F\u4E0D\u662F registry \u767D\u540D\u5355\u80FD\u89E3\u51B3\u7684\u95EE\u9898\uFF09\u3002\u8BF7\u6362\u7EAF JS \u5B9E\u73B0\uFF08\u5982 bcrypt\u2192@adep/crypto \u7684 hashPassword\u3001sharp\u2192\u6784\u5EFA\u671F\u9884\u5904\u7406\u56FE\u7247\uFF09\u3002`
|
|
7313
|
+
};
|
|
7314
|
+
}
|
|
7315
|
+
return null;
|
|
7316
|
+
}
|
|
7317
|
+
async function scanFunctionSources(rootDir, functionsDir) {
|
|
7318
|
+
const base = join20(rootDir, functionsDir);
|
|
7319
|
+
const findings = [];
|
|
7320
|
+
async function walk(current) {
|
|
7321
|
+
let entries;
|
|
7322
|
+
try {
|
|
7323
|
+
entries = await readdir7(current, { withFileTypes: true });
|
|
7324
|
+
} catch {
|
|
7325
|
+
return;
|
|
7326
|
+
}
|
|
7327
|
+
for (const entry of entries) {
|
|
7328
|
+
const abs = join20(current, entry.name);
|
|
7329
|
+
if (entry.isDirectory()) {
|
|
7330
|
+
if (SKIP_DIRS.has(entry.name)) continue;
|
|
7331
|
+
await walk(abs);
|
|
7332
|
+
continue;
|
|
7333
|
+
}
|
|
7334
|
+
if (!entry.isFile()) continue;
|
|
7335
|
+
if (!SOURCE_EXTENSIONS.some((ext) => entry.name.endsWith(ext))) continue;
|
|
7336
|
+
if (entry.name.endsWith(".d.ts")) continue;
|
|
7337
|
+
let content;
|
|
7338
|
+
try {
|
|
7339
|
+
content = await readFile16(abs, "utf8");
|
|
7340
|
+
} catch {
|
|
7341
|
+
continue;
|
|
7342
|
+
}
|
|
7343
|
+
if (content.length > MAX_SCAN_BYTES) continue;
|
|
7344
|
+
const relPath = relative5(rootDir, abs).split(sep3).join("/");
|
|
7345
|
+
const lines = content.split("\n");
|
|
7346
|
+
for (const [index, line] of lines.entries()) {
|
|
7347
|
+
const trimmed = line.trim();
|
|
7348
|
+
if (trimmed.startsWith("//") || trimmed.startsWith("*") || trimmed.startsWith("/*")) continue;
|
|
7349
|
+
for (const specifier of extractSpecifiers(line)) {
|
|
7350
|
+
const hit = classify(specifier);
|
|
7351
|
+
if (hit !== null) {
|
|
7352
|
+
findings.push({
|
|
7353
|
+
file: relPath,
|
|
7354
|
+
line: index + 1,
|
|
7355
|
+
code: hit.code,
|
|
7356
|
+
specifier,
|
|
7357
|
+
message: hit.message
|
|
7358
|
+
});
|
|
7359
|
+
}
|
|
7360
|
+
}
|
|
7361
|
+
}
|
|
7362
|
+
}
|
|
7363
|
+
}
|
|
7364
|
+
await walk(base);
|
|
7365
|
+
return findings;
|
|
7366
|
+
}
|
|
7367
|
+
var NODE_BUILTINS, NATIVE_ADDON_PACKAGES, BUILTIN_SUGGESTIONS, SOURCE_EXTENSIONS, SKIP_DIRS, MAX_SCAN_BYTES;
|
|
7368
|
+
var init_sandbox_scan = __esm({
|
|
7369
|
+
"packages/cli/src/sandbox-scan.ts"() {
|
|
7370
|
+
"use strict";
|
|
7371
|
+
NODE_BUILTINS = /* @__PURE__ */ new Set([
|
|
7372
|
+
"assert",
|
|
7373
|
+
"async_hooks",
|
|
7374
|
+
"buffer",
|
|
7375
|
+
"child_process",
|
|
7376
|
+
"cluster",
|
|
7377
|
+
"console",
|
|
7378
|
+
"constants",
|
|
7379
|
+
"crypto",
|
|
7380
|
+
"dgram",
|
|
7381
|
+
"diagnostics_channel",
|
|
7382
|
+
"dns",
|
|
7383
|
+
"domain",
|
|
7384
|
+
"events",
|
|
7385
|
+
"fs",
|
|
7386
|
+
"http",
|
|
7387
|
+
"http2",
|
|
7388
|
+
"https",
|
|
7389
|
+
"inspector",
|
|
7390
|
+
"module",
|
|
7391
|
+
"net",
|
|
7392
|
+
"os",
|
|
7393
|
+
"path",
|
|
7394
|
+
"perf_hooks",
|
|
7395
|
+
"process",
|
|
7396
|
+
"punycode",
|
|
7397
|
+
"querystring",
|
|
7398
|
+
"readline",
|
|
7399
|
+
"repl",
|
|
7400
|
+
"stream",
|
|
7401
|
+
"string_decoder",
|
|
7402
|
+
"sys",
|
|
7403
|
+
"timers",
|
|
7404
|
+
"tls",
|
|
7405
|
+
"trace_events",
|
|
7406
|
+
"tty",
|
|
7407
|
+
"url",
|
|
7408
|
+
"util",
|
|
7409
|
+
"v8",
|
|
7410
|
+
"vm",
|
|
7411
|
+
"wasi",
|
|
7412
|
+
"worker_threads",
|
|
7413
|
+
"zlib"
|
|
7414
|
+
]);
|
|
7415
|
+
NATIVE_ADDON_PACKAGES = /* @__PURE__ */ new Set([
|
|
7416
|
+
"bcrypt",
|
|
7417
|
+
"better-sqlite3",
|
|
7418
|
+
"sqlite3",
|
|
7419
|
+
"sharp",
|
|
7420
|
+
"canvas",
|
|
7421
|
+
"argon2",
|
|
7422
|
+
"node-gyp",
|
|
7423
|
+
"farmhash",
|
|
7424
|
+
"xxhash-addon",
|
|
7425
|
+
"zeromq",
|
|
7426
|
+
"grpc",
|
|
7427
|
+
"@grpc/grpc-js",
|
|
7428
|
+
"leveldown",
|
|
7429
|
+
"rocksdb",
|
|
7430
|
+
"node-canvas",
|
|
7431
|
+
"microtime",
|
|
7432
|
+
"sodium-native",
|
|
7433
|
+
"re2"
|
|
7434
|
+
]);
|
|
7435
|
+
BUILTIN_SUGGESTIONS = {
|
|
7436
|
+
"node:crypto": "\u7528 WebCrypto\uFF08\u6C99\u7BB1\u5DF2\u6CE8\u5165 crypto\uFF09\u6216 @adep/crypto \u7684 signJwt / hashPassword / encryptSecret",
|
|
7437
|
+
crypto: "\u7528 WebCrypto\uFF08\u6C99\u7BB1\u5DF2\u6CE8\u5165 crypto\uFF09\u6216 @adep/crypto",
|
|
7438
|
+
"node:fs": "\u6C99\u7BB1\u65E0\u6587\u4EF6\u7CFB\u7EDF\uFF1B\u9879\u76EE\u6570\u636E\u8D70 ctx.cloud.db\uFF0C\u6587\u4EF6\u8D70 ctx.cloud.storage",
|
|
7439
|
+
fs: "\u6C99\u7BB1\u65E0\u6587\u4EF6\u7CFB\u7EDF\uFF1B\u9879\u76EE\u6570\u636E\u8D70 ctx.cloud.db\uFF0C\u6587\u4EF6\u8D70 ctx.cloud.storage",
|
|
7440
|
+
"node:path": "\u624B\u5199\u5B57\u7B26\u4E32\u62FC\u63A5\uFF08\u6C99\u7BB1\u91CC\u7684\u8DEF\u5F84\u90FD\u662F POSIX \u5F62\u5F0F\uFF09",
|
|
7441
|
+
path: "\u624B\u5199\u5B57\u7B26\u4E32\u62FC\u63A5\uFF08\u6C99\u7BB1\u91CC\u7684\u8DEF\u5F84\u90FD\u662F POSIX \u5F62\u5F0F\uFF09",
|
|
7442
|
+
"node:buffer": "\u7528 Uint8Array + TextEncoder/TextDecoder\uFF08\u6C99\u7BB1\u5DF2\u6CE8\u5165\uFF09",
|
|
7443
|
+
buffer: "\u7528 Uint8Array + TextEncoder/TextDecoder\uFF08\u6C99\u7BB1\u5DF2\u6CE8\u5165\uFF09",
|
|
7444
|
+
"node:process": "\u73AF\u5883\u53D8\u91CF\u8D70 ctx.env\uFF08adep.config.ts \u7684 environment\uFF09",
|
|
7445
|
+
process: "\u73AF\u5883\u53D8\u91CF\u8D70 ctx.env\uFF08adep.config.ts \u7684 environment\uFF09",
|
|
7446
|
+
"node:stream": "\u7528\u6C99\u7BB1\u6CE8\u5165\u7684 ReadableStream / WritableStream / TransformStream",
|
|
7447
|
+
stream: "\u7528\u6C99\u7BB1\u6CE8\u5165\u7684 ReadableStream / WritableStream / TransformStream"
|
|
7448
|
+
};
|
|
7449
|
+
SOURCE_EXTENSIONS = [".ts", ".js", ".mjs", ".cjs", ".tsx", ".jsx"];
|
|
7450
|
+
SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", "__tests__", "dist", ".git", ".adep", "coverage"]);
|
|
7451
|
+
MAX_SCAN_BYTES = 512 * 1024;
|
|
7452
|
+
}
|
|
7453
|
+
});
|
|
7454
|
+
|
|
7175
7455
|
// packages/cli/src/doctor.ts
|
|
7176
7456
|
var doctor_exports = {};
|
|
7177
7457
|
__export(doctor_exports, {
|
|
@@ -7202,12 +7482,13 @@ async function credentialMode(file) {
|
|
|
7202
7482
|
return void 0;
|
|
7203
7483
|
}
|
|
7204
7484
|
}
|
|
7205
|
-
async function runDoctor(paths) {
|
|
7485
|
+
async function runDoctor(paths, cwd = process.cwd()) {
|
|
7206
7486
|
const credentials = await loadCredentials(paths);
|
|
7207
7487
|
const server = credentials?.server ?? resolveServer();
|
|
7208
7488
|
const mode = await credentialMode(paths.credentialsFile);
|
|
7209
7489
|
const offline = await isOffline();
|
|
7210
7490
|
const health = await probeServer(server);
|
|
7491
|
+
const sandbox = await scanSandbox(cwd);
|
|
7211
7492
|
const report = {
|
|
7212
7493
|
server,
|
|
7213
7494
|
credentials: {
|
|
@@ -7218,7 +7499,8 @@ async function runDoctor(paths) {
|
|
|
7218
7499
|
network: { offline },
|
|
7219
7500
|
serverHealth: health,
|
|
7220
7501
|
offlineCommands: [...OFFLINE_COMMANDS],
|
|
7221
|
-
boundaries: SIM_BOUNDARIES.map((b) => ({ kind: b.kind, title: b.title, detail: b.detail }))
|
|
7502
|
+
boundaries: SIM_BOUNDARIES.map((b) => ({ kind: b.kind, title: b.title, detail: b.detail })),
|
|
7503
|
+
sandbox
|
|
7222
7504
|
};
|
|
7223
7505
|
if (credentials !== null) report.credentials.email = credentials.email;
|
|
7224
7506
|
if (mode !== void 0 && mode !== "600") {
|
|
@@ -7226,6 +7508,22 @@ async function runDoctor(paths) {
|
|
|
7226
7508
|
}
|
|
7227
7509
|
return report;
|
|
7228
7510
|
}
|
|
7511
|
+
async function scanSandbox(cwd) {
|
|
7512
|
+
let functionsDir = "functions";
|
|
7513
|
+
try {
|
|
7514
|
+
const config = await loadAdepConfigModule(cwd);
|
|
7515
|
+
if (config?.functionsDir !== void 0 && config.functionsDir.length > 0) {
|
|
7516
|
+
functionsDir = config.functionsDir;
|
|
7517
|
+
}
|
|
7518
|
+
} catch {
|
|
7519
|
+
}
|
|
7520
|
+
try {
|
|
7521
|
+
const findings = await scanFunctionSources(cwd, functionsDir);
|
|
7522
|
+
return { functionsDir, findings };
|
|
7523
|
+
} catch {
|
|
7524
|
+
return { functionsDir: null, findings: [] };
|
|
7525
|
+
}
|
|
7526
|
+
}
|
|
7229
7527
|
function formatDoctorReport(report) {
|
|
7230
7528
|
const lines = ["adep doctor \xB7 \u73AF\u5883\u81EA\u68C0", ""];
|
|
7231
7529
|
lines.push("\u51ED\u636E\u4E0E\u8EAB\u4EFD");
|
|
@@ -7253,6 +7551,28 @@ function formatDoctorReport(report) {
|
|
|
7253
7551
|
}
|
|
7254
7552
|
lines.push("", "\u79BB\u7EBF\u53EF\u7528\u8303\u56F4\uFF08\u65AD\u7F51\u65F6\u4ECD\u53EF\u6267\u884C\uFF09");
|
|
7255
7553
|
for (const command of report.offlineCommands) lines.push(` \xB7 ${command}`);
|
|
7554
|
+
lines.push("", "\u4E91\u51FD\u6570\u6C99\u7BB1\u517C\u5BB9\u6027\uFF08\u53D1\u5E03\u524D\u5C31\u80FD\u6539\uFF0C\u522B\u7B49\u8FD0\u884C\u65F6\u70B8\uFF09");
|
|
7555
|
+
if (report.sandbox.functionsDir === null) {
|
|
7556
|
+
lines.push(" \xB7 \u672A\u627E\u5230\u51FD\u6570\u76EE\u5F55\uFF0C\u8DF3\u8FC7\u626B\u63CF");
|
|
7557
|
+
} else if (report.sandbox.findings.length === 0) {
|
|
7558
|
+
lines.push(` \u2713 ${report.sandbox.functionsDir}/ \u5185\u672A\u53D1\u73B0 node \u5185\u7F6E\u6A21\u5757 / \u539F\u751F addon \u4F9D\u8D56`);
|
|
7559
|
+
} else {
|
|
7560
|
+
const byFile = /* @__PURE__ */ new Map();
|
|
7561
|
+
for (const finding of report.sandbox.findings) {
|
|
7562
|
+
const list = byFile.get(finding.file) ?? [];
|
|
7563
|
+
list.push(finding);
|
|
7564
|
+
byFile.set(finding.file, list);
|
|
7565
|
+
}
|
|
7566
|
+
lines.push(
|
|
7567
|
+
` \u2717 \u53D1\u73B0 ${report.sandbox.findings.length} \u5904\u6C99\u7BB1\u4E0D\u517C\u5BB9\uFF08\u672C\u5730 adep dev \u80FD\u8DD1\uFF0C\u53D1\u5E03\u540E\u4F1A\u5931\u8D25\uFF09\uFF1A`
|
|
7568
|
+
);
|
|
7569
|
+
for (const [file, findingList] of byFile) {
|
|
7570
|
+
for (const finding of findingList) {
|
|
7571
|
+
lines.push(` ${file}:${finding.line} [${finding.code}] ${finding.specifier}`);
|
|
7572
|
+
lines.push(` ${finding.message}`);
|
|
7573
|
+
}
|
|
7574
|
+
}
|
|
7575
|
+
}
|
|
7256
7576
|
lines.push("", "\u672C\u5730\u6A21\u62DF\u8FD0\u884C\u65F6\u7684\u80FD\u529B\u8FB9\u754C\uFF08\u4E0E adep dev \u542F\u52A8\u6A2A\u5E45\u540C\u6E90\uFF09");
|
|
7257
7577
|
for (const boundary of report.boundaries) {
|
|
7258
7578
|
lines.push(` \xB7 [${boundary.kind}] ${boundary.title}\uFF1A${boundary.detail}`);
|
|
@@ -7267,6 +7587,8 @@ var init_doctor = __esm({
|
|
|
7267
7587
|
init_config();
|
|
7268
7588
|
init_boundary();
|
|
7269
7589
|
init_net();
|
|
7590
|
+
init_sandbox_scan();
|
|
7591
|
+
init_ts_config();
|
|
7270
7592
|
SERVER_PROBE_TIMEOUT_MS = 5e3;
|
|
7271
7593
|
OFFLINE_COMMANDS = [
|
|
7272
7594
|
"adep init",
|
|
@@ -7639,8 +7961,8 @@ __export(hosting_exports, {
|
|
|
7639
7961
|
hostingInfo: () => hostingInfo,
|
|
7640
7962
|
hostingPull: () => hostingPull
|
|
7641
7963
|
});
|
|
7642
|
-
import { readdir as
|
|
7643
|
-
import { dirname as dirname11, join as
|
|
7964
|
+
import { readdir as readdir8, readFile as readFile17, stat as stat13 } from "node:fs/promises";
|
|
7965
|
+
import { dirname as dirname11, join as join21, relative as relative6, resolve as resolve14, sep as sep4 } from "node:path";
|
|
7644
7966
|
async function open4(paths, options) {
|
|
7645
7967
|
const client = await createClient(paths);
|
|
7646
7968
|
const project2 = await resolveSlug(resolve14(options.cwd), options.slug);
|
|
@@ -7661,16 +7983,16 @@ async function collectSiteFiles(dir) {
|
|
|
7661
7983
|
const walk = async (sub) => {
|
|
7662
7984
|
let entries;
|
|
7663
7985
|
try {
|
|
7664
|
-
entries = await
|
|
7986
|
+
entries = await readdir8(sub, { withFileTypes: true });
|
|
7665
7987
|
} catch {
|
|
7666
7988
|
return;
|
|
7667
7989
|
}
|
|
7668
7990
|
for (const entry of entries) {
|
|
7669
|
-
const full =
|
|
7991
|
+
const full = join21(sub, entry.name);
|
|
7670
7992
|
if (entry.isDirectory()) {
|
|
7671
7993
|
await walk(full);
|
|
7672
7994
|
} else if (entry.isFile()) {
|
|
7673
|
-
const rel =
|
|
7995
|
+
const rel = relative6(root, full).split(sep4).join("/");
|
|
7674
7996
|
files.set(rel, full);
|
|
7675
7997
|
}
|
|
7676
7998
|
}
|
|
@@ -7690,7 +8012,7 @@ async function hostingDeploy(paths, options) {
|
|
|
7690
8012
|
for (const [rel, full] of files) {
|
|
7691
8013
|
log(`[adep] \u4E0A\u4F20 site/${rel}`);
|
|
7692
8014
|
const info2 = await stat13(full);
|
|
7693
|
-
const bytes = await
|
|
8015
|
+
const bytes = await readFile17(full);
|
|
7694
8016
|
const form = new FormData();
|
|
7695
8017
|
form.set("path", `site/${rel}`);
|
|
7696
8018
|
form.set("visibility", "public");
|
|
@@ -7728,7 +8050,7 @@ async function hostingPull(paths, options) {
|
|
|
7728
8050
|
const response = await client.download(url, "HOSTING_DOWNLOAD_FAILED");
|
|
7729
8051
|
const bytes = Buffer.from(await response.arrayBuffer());
|
|
7730
8052
|
const rel = entry.path.replace(/^site\//, "");
|
|
7731
|
-
const target =
|
|
8053
|
+
const target = join21(outputDir, ...rel.split("/"));
|
|
7732
8054
|
await mkdir12(dirname11(target), { recursive: true });
|
|
7733
8055
|
await writeFile10(target, bytes);
|
|
7734
8056
|
files.push({ path: entry.path, size: bytes.length });
|
package/dist/vite.js
CHANGED
|
@@ -2438,11 +2438,12 @@ function createLocalStorageDriver(options) {
|
|
|
2438
2438
|
}
|
|
2439
2439
|
|
|
2440
2440
|
// packages/cli/src/sim/storage.ts
|
|
2441
|
+
var SIM_SIGN_SECRET = "adep-sim-secret";
|
|
2441
2442
|
function createSimStorageCapability(options) {
|
|
2442
2443
|
const dir = join3(options.cwd, ".adep", "sim", "storage");
|
|
2443
2444
|
const driver = createLocalStorageDriver({ dir });
|
|
2444
2445
|
const signer = {
|
|
2445
|
-
secret: options.secret ??
|
|
2446
|
+
secret: options.secret ?? SIM_SIGN_SECRET,
|
|
2446
2447
|
baseUrl: options.baseUrl ?? "http://127.0.0.1:8787"
|
|
2447
2448
|
};
|
|
2448
2449
|
const bundle = createStorageCapability(driver, signer, options.projectId ?? "sim-project");
|
|
@@ -2631,6 +2632,8 @@ async function createSimRuntime(options) {
|
|
|
2631
2632
|
bundle,
|
|
2632
2633
|
realtime: simRealtime.realtime,
|
|
2633
2634
|
db,
|
|
2635
|
+
/** 存储句柄(serve 的签名文件下载路由用它读对象;bundle 里的 capability 是同一驱动的 RPC 面)。 */
|
|
2636
|
+
storage,
|
|
2634
2637
|
dispose: async () => {
|
|
2635
2638
|
await db.driver.close();
|
|
2636
2639
|
}
|
|
@@ -2726,9 +2729,13 @@ function createSimInvokeHandler(options) {
|
|
|
2726
2729
|
// shared/builtin-deps.ts
|
|
2727
2730
|
var CF_COMPAT_SPECIFIER = "@adep/cf-compat";
|
|
2728
2731
|
var STATE_OBJECTS_SPECIFIER = "@adep/runtime/state-objects";
|
|
2732
|
+
var CRYPTO_SPECIFIER = "@adep/crypto";
|
|
2733
|
+
var ROUTE_SPECIFIER = "@adep/runtime/route";
|
|
2729
2734
|
var BUILTIN_DEPS = [
|
|
2730
2735
|
CF_COMPAT_SPECIFIER,
|
|
2731
2736
|
STATE_OBJECTS_SPECIFIER,
|
|
2737
|
+
CRYPTO_SPECIFIER,
|
|
2738
|
+
ROUTE_SPECIFIER,
|
|
2732
2739
|
"axios",
|
|
2733
2740
|
"lodash",
|
|
2734
2741
|
"dayjs",
|
|
@@ -2737,7 +2744,12 @@ var BUILTIN_DEPS = [
|
|
|
2737
2744
|
var BUILTIN_DEPS_CSV = BUILTIN_DEPS.join(",");
|
|
2738
2745
|
|
|
2739
2746
|
// packages/cli/src/builtin-deps.ts
|
|
2740
|
-
var LOCAL_BUILTIN_DEPS = [
|
|
2747
|
+
var LOCAL_BUILTIN_DEPS = [
|
|
2748
|
+
CF_COMPAT_SPECIFIER,
|
|
2749
|
+
STATE_OBJECTS_SPECIFIER,
|
|
2750
|
+
CRYPTO_SPECIFIER,
|
|
2751
|
+
ROUTE_SPECIFIER
|
|
2752
|
+
];
|
|
2741
2753
|
|
|
2742
2754
|
// packages/cli/src/sim/boundary.ts
|
|
2743
2755
|
var SIM_BOUNDARIES = [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adep/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.16",
|
|
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,10 +21,11 @@
|
|
|
21
21
|
"commander": "14.0.2",
|
|
22
22
|
"esbuild": "0.25.12",
|
|
23
23
|
"@adep/cf-compat": "0.1.1",
|
|
24
|
-
"@adep/
|
|
24
|
+
"@adep/runtime": "0.2.7",
|
|
25
|
+
"@adep/crypto": "0.1.0",
|
|
26
|
+
"@adep/vite-plugin": "0.1.7"
|
|
25
27
|
},
|
|
26
28
|
"devDependencies": {
|
|
27
|
-
"@adep/runtime": "0.2.6",
|
|
28
29
|
"@adep/types": "0.2.3"
|
|
29
30
|
},
|
|
30
31
|
"scripts": {
|