@adep/cli 0.1.15 → 0.1.17
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 +5 -0
- package/dist/index.js +1118 -709
- package/dist/vite.js +312 -37
- 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, relative8) => {
|
|
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 = relative8 === "" ? entry.name : `${relative8}/${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
|
}
|
|
@@ -3298,185 +3326,665 @@ var init_runtime = __esm({
|
|
|
3298
3326
|
}
|
|
3299
3327
|
});
|
|
3300
3328
|
|
|
3301
|
-
// packages/cli/src/
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
env[key] = line.slice(eq + 1).trim();
|
|
3314
|
-
}
|
|
3315
|
-
return env;
|
|
3329
|
+
// packages/cli/src/client.ts
|
|
3330
|
+
var client_exports = {};
|
|
3331
|
+
__export(client_exports, {
|
|
3332
|
+
createClient: () => createClient,
|
|
3333
|
+
resolveSlug: () => resolveSlug
|
|
3334
|
+
});
|
|
3335
|
+
async function envelopeError(response, fallbackCode, parsed) {
|
|
3336
|
+
const payload = parsed ?? null;
|
|
3337
|
+
return new CliError(
|
|
3338
|
+
payload?.error?.code ?? fallbackCode,
|
|
3339
|
+
payload?.error?.message ?? `\u5E73\u53F0\u8FD4\u56DE HTTP ${response.status}`
|
|
3340
|
+
);
|
|
3316
3341
|
}
|
|
3317
|
-
async function
|
|
3318
|
-
const
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
merged[secret] = process.env[secret];
|
|
3325
|
-
continue;
|
|
3326
|
-
}
|
|
3327
|
-
throw new Error(
|
|
3328
|
-
`secret "${secret}" \u672A\u914D\u7F6E\uFF1A\u8BF7\u5728 .env.local \u6DFB\u52A0 ${secret}=<value>\uFF0C\u6216\u7528\u73AF\u5883\u53D8\u91CF\u5BFC\u51FA\u540E\u91CD\u8BD5 adep dev\uFF08\u6A21\u62DF\u73AF\u5883\u6C38\u4E0D\u843D\u76D8\u8BE5\u503C\uFF09`
|
|
3329
|
-
);
|
|
3342
|
+
async function parseBody(response) {
|
|
3343
|
+
const text = await response.text();
|
|
3344
|
+
if (text.length === 0) return null;
|
|
3345
|
+
try {
|
|
3346
|
+
return JSON.parse(text);
|
|
3347
|
+
} catch {
|
|
3348
|
+
return null;
|
|
3330
3349
|
}
|
|
3331
|
-
return merged;
|
|
3332
3350
|
}
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3351
|
+
async function createClient(paths) {
|
|
3352
|
+
const credentials = await loadCredentials(paths);
|
|
3353
|
+
if (credentials === null) {
|
|
3354
|
+
throw new CliError("NOT_LOGGED_IN", "\u672A\u767B\u5F55\uFF1A\u8BF7\u5148\u6267\u884C adep login");
|
|
3336
3355
|
}
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
}
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
} else if (parts.length === 2 && parts[1] === "index.ts" && parts[0] !== void 0) {
|
|
3354
|
-
names.add(parts[0]);
|
|
3356
|
+
const server = credentials.server;
|
|
3357
|
+
const cookie = sessionCookieHeader(credentials);
|
|
3358
|
+
const request = async (path, init = {}, fallbackCode = "API_REQUEST_FAILED") => {
|
|
3359
|
+
const method = init.method ?? (init.body === void 0 ? "GET" : "POST");
|
|
3360
|
+
let response;
|
|
3361
|
+
try {
|
|
3362
|
+
response = await fetch(`${server}${path}`, {
|
|
3363
|
+
method,
|
|
3364
|
+
headers: { "content-type": "application/json", cookie },
|
|
3365
|
+
...init.body === void 0 ? {} : { body: JSON.stringify(init.body) }
|
|
3366
|
+
});
|
|
3367
|
+
} catch (error) {
|
|
3368
|
+
throw new CliError(
|
|
3369
|
+
"SERVER_UNREACHABLE",
|
|
3370
|
+
`\u65E0\u6CD5\u8FDE\u63A5\u5E73\u53F0 ${server}\uFF1A${error instanceof Error ? error.message : String(error)}`
|
|
3371
|
+
);
|
|
3355
3372
|
}
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
function createSimInvokeHandler(options) {
|
|
3360
|
-
return async (method, args) => {
|
|
3361
|
-
if (method !== "invoke") {
|
|
3362
|
-
throw new Error(`\u672A\u77E5\u7684 cloud.invoke \u65B9\u6CD5 "${method}"`);
|
|
3373
|
+
const parsed = await parseBody(response);
|
|
3374
|
+
if (response.status < 200 || response.status >= 300) {
|
|
3375
|
+
throw await envelopeError(response, fallbackCode, parsed);
|
|
3363
3376
|
}
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3377
|
+
return parsed;
|
|
3378
|
+
};
|
|
3379
|
+
const upload = async (path, form, fallbackCode = "UPLOAD_FAILED") => {
|
|
3380
|
+
let response;
|
|
3381
|
+
try {
|
|
3382
|
+
response = await fetch(`${server}${path}`, {
|
|
3383
|
+
method: "POST",
|
|
3384
|
+
headers: { cookie },
|
|
3385
|
+
body: form
|
|
3386
|
+
});
|
|
3387
|
+
} catch (error) {
|
|
3388
|
+
throw new CliError(
|
|
3389
|
+
"SERVER_UNREACHABLE",
|
|
3390
|
+
`\u65E0\u6CD5\u8FDE\u63A5\u5E73\u53F0 ${server}\uFF1A${error instanceof Error ? error.message : String(error)}`
|
|
3391
|
+
);
|
|
3367
3392
|
}
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
throw new Error(`\u76EE\u6807\u51FD\u6570 "${input.name}" \u4E0D\u5B58\u5728`);
|
|
3393
|
+
if (response.status < 200 || response.status >= 300) {
|
|
3394
|
+
throw await envelopeError(response, fallbackCode, await parseBody(response));
|
|
3371
3395
|
}
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
return
|
|
3396
|
+
return response;
|
|
3397
|
+
};
|
|
3398
|
+
const download = async (url, fallbackCode = "DOWNLOAD_FAILED") => {
|
|
3399
|
+
const target = url.startsWith("http") ? url : `${server}${url}`;
|
|
3400
|
+
let response;
|
|
3401
|
+
try {
|
|
3402
|
+
response = await fetch(target, { headers: { cookie } });
|
|
3403
|
+
} catch (error) {
|
|
3404
|
+
throw new CliError(
|
|
3405
|
+
"SERVER_UNREACHABLE",
|
|
3406
|
+
`\u65E0\u6CD5\u8FDE\u63A5\u5E73\u53F0 ${server}\uFF1A${error instanceof Error ? error.message : String(error)}`
|
|
3407
|
+
);
|
|
3408
|
+
}
|
|
3409
|
+
if (response.status < 200 || response.status >= 300) {
|
|
3410
|
+
throw await envelopeError(response, fallbackCode, await parseBody(response));
|
|
3411
|
+
}
|
|
3412
|
+
return response;
|
|
3389
3413
|
};
|
|
3414
|
+
return { server, cookie, request, upload, download };
|
|
3390
3415
|
}
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
}
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
var CF_COMPAT_SPECIFIER, STATE_OBJECTS_SPECIFIER, BUILTIN_DEPS, BUILTIN_DEPS_CSV;
|
|
3399
|
-
var init_builtin_deps = __esm({
|
|
3400
|
-
"shared/builtin-deps.ts"() {
|
|
3401
|
-
"use strict";
|
|
3402
|
-
CF_COMPAT_SPECIFIER = "@adep/cf-compat";
|
|
3403
|
-
STATE_OBJECTS_SPECIFIER = "@adep/runtime/state-objects";
|
|
3404
|
-
BUILTIN_DEPS = [
|
|
3405
|
-
CF_COMPAT_SPECIFIER,
|
|
3406
|
-
STATE_OBJECTS_SPECIFIER,
|
|
3407
|
-
"axios",
|
|
3408
|
-
"lodash",
|
|
3409
|
-
"dayjs",
|
|
3410
|
-
"zod"
|
|
3411
|
-
];
|
|
3412
|
-
BUILTIN_DEPS_CSV = BUILTIN_DEPS.join(",");
|
|
3413
|
-
}
|
|
3414
|
-
});
|
|
3415
|
-
|
|
3416
|
-
// packages/cli/src/builtin-deps.ts
|
|
3417
|
-
var LOCAL_BUILTIN_DEPS;
|
|
3418
|
-
var init_builtin_deps2 = __esm({
|
|
3419
|
-
"packages/cli/src/builtin-deps.ts"() {
|
|
3416
|
+
async function resolveSlug(cwd, slug) {
|
|
3417
|
+
if (slug !== void 0 && slug.length > 0) return slug;
|
|
3418
|
+
const config = await loadConfig(cwd);
|
|
3419
|
+
return config.name;
|
|
3420
|
+
}
|
|
3421
|
+
var init_client = __esm({
|
|
3422
|
+
"packages/cli/src/client.ts"() {
|
|
3420
3423
|
"use strict";
|
|
3421
|
-
|
|
3422
|
-
|
|
3424
|
+
init_auth();
|
|
3425
|
+
init_credentials();
|
|
3426
|
+
init_dev();
|
|
3423
3427
|
}
|
|
3424
3428
|
});
|
|
3425
3429
|
|
|
3426
|
-
// packages/cli/src/
|
|
3427
|
-
var
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
title: "\u65E0\u8DE8\u5B9E\u4F8B\u5E7F\u64AD",
|
|
3440
|
-
detail: "cloud.realtime \u5DF2\u6CE8\u5165\uFF0C\u4F46\u4E3A\u5355\u8FDB\u7A0B\u5185\u5B58\u5E7F\u64AD\uFF1A\u4E0D\u652F\u6301\u8DE8\u8FDB\u7A0B / \u8DE8\u5B9E\u4F8B\uFF0C\u7EBF\u4E0A\u591A\u5B9E\u4F8B\u8BED\u4E49\u4E0D\u540C\u3002"
|
|
3441
|
-
},
|
|
3442
|
-
{
|
|
3443
|
-
kind: "capability",
|
|
3444
|
-
title: "publish \u4E0D\u652F\u6301 except",
|
|
3445
|
-
detail: "\u672C\u5730\u4E0D\u5EFA WS \u63E1\u624B\u3001\u65E0\u8FDE\u63A5\u8EAB\u4EFD\uFF0C\u6545 cloud.realtime.publish \u7684 except\uFF08\u4E0D\u53D1\u56DE\u53D1\u9001\u8005\uFF09\u65E0\u4ECE\u5B9E\u73B0\uFF0C\u4F20\u5165\u5373\u62A5\u9519\u3002"
|
|
3446
|
-
},
|
|
3447
|
-
{
|
|
3448
|
-
kind: "capability",
|
|
3449
|
-
title: "\u65E0\u9650\u989D\u7B49\u4EF7",
|
|
3450
|
-
detail: "\u672C\u5730\u4E0D\u6267\u884C\u8BA1\u91CF / \u914D\u989D\u95E8\u7981\uFF08\u4E0D\u6309\u51FD\u6570\u8C03\u7528\u3001\u6D41\u91CF\u3001\u63A8\u9001\u8BA1\u6570\uFF09\uFF0C\u9650\u989D\u8BED\u4E49\u4EC5\u7EBF\u4E0A\u751F\u6548\u3002"
|
|
3451
|
-
},
|
|
3452
|
-
{
|
|
3453
|
-
kind: "diff",
|
|
3454
|
-
title: "\u4E0D\u8BA1\u91CF",
|
|
3455
|
-
detail: "\u672C\u6A21\u62DF\u8FD0\u884C\u65F6\u4E0D\u4EA7\u51FA\u8BA1\u91CF\u4E8B\u4EF6\uFF0C\u4E5F\u4E0D\u5199 billing\uFF1B\u79BB\u7EBF\u5F00\u53D1\u4E0D\u8BA1\u8D39\u3002"
|
|
3456
|
-
}
|
|
3457
|
-
];
|
|
3458
|
-
}
|
|
3430
|
+
// packages/cli/src/db.ts
|
|
3431
|
+
var db_exports = {};
|
|
3432
|
+
__export(db_exports, {
|
|
3433
|
+
dbExec: () => dbExec,
|
|
3434
|
+
dbMigrate: () => dbMigrate,
|
|
3435
|
+
dbRollback: () => dbRollback,
|
|
3436
|
+
dbSnapshotCreate: () => dbSnapshotCreate,
|
|
3437
|
+
dbSnapshotList: () => dbSnapshotList,
|
|
3438
|
+
dbSnapshotRestore: () => dbSnapshotRestore,
|
|
3439
|
+
dbStart: () => dbStart,
|
|
3440
|
+
dbStatus: () => dbStatus,
|
|
3441
|
+
dbStop: () => dbStop,
|
|
3442
|
+
splitSqlStatements: () => splitSqlStatements
|
|
3459
3443
|
});
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
}
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3444
|
+
import { readFile as readFile6 } from "node:fs/promises";
|
|
3445
|
+
import { resolve as resolve4 } from "node:path";
|
|
3446
|
+
async function open2(paths, options) {
|
|
3447
|
+
const client = await createClient(paths);
|
|
3448
|
+
const project2 = await resolveSlug(resolve4(options.cwd), options.slug);
|
|
3449
|
+
return { client, project: project2 };
|
|
3450
|
+
}
|
|
3451
|
+
async function dbStart(paths, options) {
|
|
3452
|
+
const { client, project: project2 } = await open2(paths, options);
|
|
3453
|
+
return client.request(`/api/v1/projects/${project2}/database`, { method: "POST" });
|
|
3454
|
+
}
|
|
3455
|
+
async function dbStatus(paths, options) {
|
|
3456
|
+
const { client, project: project2 } = await open2(paths, options);
|
|
3457
|
+
return client.request(`/api/v1/projects/${project2}/database`);
|
|
3458
|
+
}
|
|
3459
|
+
async function dbStop(paths, options) {
|
|
3460
|
+
const { client, project: project2 } = await open2(paths, options);
|
|
3461
|
+
return client.request(`/api/v1/projects/${project2}/database`, {
|
|
3462
|
+
method: "DELETE"
|
|
3463
|
+
});
|
|
3464
|
+
}
|
|
3465
|
+
async function dbExec(paths, options) {
|
|
3466
|
+
const { client, project: project2 } = await open2(paths, options);
|
|
3467
|
+
return client.request(
|
|
3468
|
+
`/api/v1/projects/${project2}/database/console/sql`,
|
|
3469
|
+
{
|
|
3470
|
+
method: "POST",
|
|
3471
|
+
body: {
|
|
3472
|
+
sql: options.sql,
|
|
3473
|
+
...options.params === void 0 ? {} : { params: options.params },
|
|
3474
|
+
...options.confirmTable === void 0 ? {} : { confirmTable: options.confirmTable }
|
|
3475
|
+
}
|
|
3476
|
+
},
|
|
3477
|
+
"SQL_EXEC_FAILED"
|
|
3478
|
+
);
|
|
3479
|
+
}
|
|
3480
|
+
async function dbSnapshotList(paths, options) {
|
|
3481
|
+
const { client, project: project2 } = await open2(paths, options);
|
|
3482
|
+
return client.request(
|
|
3483
|
+
`/api/v1/projects/${project2}/database/snapshots`
|
|
3484
|
+
);
|
|
3485
|
+
}
|
|
3486
|
+
async function dbSnapshotCreate(paths, options) {
|
|
3487
|
+
const { client, project: project2 } = await open2(paths, options);
|
|
3488
|
+
return client.request(`/api/v1/projects/${project2}/database/snapshots`, {
|
|
3489
|
+
method: "POST"
|
|
3490
|
+
});
|
|
3491
|
+
}
|
|
3492
|
+
async function dbSnapshotRestore(paths, options) {
|
|
3493
|
+
const { client, project: project2 } = await open2(paths, options);
|
|
3494
|
+
return client.request(
|
|
3495
|
+
`/api/v1/projects/${project2}/database/snapshots/${options.snapshotId}/restore`,
|
|
3496
|
+
{ method: "POST" }
|
|
3497
|
+
);
|
|
3498
|
+
}
|
|
3499
|
+
async function dbRollback(paths, options) {
|
|
3500
|
+
const { client, project: project2 } = await open2(paths, options);
|
|
3501
|
+
return client.request(
|
|
3502
|
+
`/api/v1/projects/${project2}/database/rollback`,
|
|
3503
|
+
{ method: "POST", body: { to: options.to } }
|
|
3504
|
+
);
|
|
3505
|
+
}
|
|
3506
|
+
function splitSqlStatements(source) {
|
|
3507
|
+
const statements = [];
|
|
3508
|
+
let buffer = "";
|
|
3509
|
+
let inQuote = false;
|
|
3510
|
+
const lines = source.split("\n");
|
|
3511
|
+
for (const rawLine of lines) {
|
|
3512
|
+
const trimmed = rawLine.trim();
|
|
3513
|
+
if (!inQuote && (trimmed.length === 0 || trimmed.startsWith("--"))) continue;
|
|
3514
|
+
for (let i = 0; i < rawLine.length; i++) {
|
|
3515
|
+
const ch = rawLine[i];
|
|
3516
|
+
if (inQuote) {
|
|
3517
|
+
if (ch === "'") {
|
|
3518
|
+
if (rawLine[i + 1] === "'") {
|
|
3519
|
+
buffer += ch + rawLine[i + 1];
|
|
3520
|
+
i++;
|
|
3521
|
+
continue;
|
|
3522
|
+
}
|
|
3523
|
+
inQuote = false;
|
|
3524
|
+
}
|
|
3525
|
+
buffer += ch;
|
|
3526
|
+
continue;
|
|
3527
|
+
}
|
|
3528
|
+
if (ch === "'") {
|
|
3529
|
+
inQuote = true;
|
|
3530
|
+
buffer += ch;
|
|
3531
|
+
continue;
|
|
3532
|
+
}
|
|
3533
|
+
if (ch === "-" && rawLine[i + 1] === "-") break;
|
|
3534
|
+
if (ch === ";") {
|
|
3535
|
+
const statement = buffer.trim();
|
|
3536
|
+
if (statement.length > 0) statements.push(statement);
|
|
3537
|
+
buffer = "";
|
|
3538
|
+
continue;
|
|
3539
|
+
}
|
|
3540
|
+
buffer += ch;
|
|
3541
|
+
}
|
|
3542
|
+
buffer += inQuote ? "\n" : " ";
|
|
3543
|
+
}
|
|
3544
|
+
if (inQuote) {
|
|
3545
|
+
throw new Error(`SQL \u8FC1\u79FB\u6587\u4EF6\u5F15\u53F7\u672A\u95ED\u5408\uFF1A${buffer.trim().slice(0, 80)}\u2026`);
|
|
3546
|
+
}
|
|
3547
|
+
const tail = buffer.trim();
|
|
3548
|
+
if (tail.length > 0) statements.push(tail);
|
|
3549
|
+
return statements;
|
|
3550
|
+
}
|
|
3551
|
+
async function dbMigrate(paths, options) {
|
|
3552
|
+
const source = await readFile6(resolve4(options.file), "utf8");
|
|
3553
|
+
const statements = splitSqlStatements(source);
|
|
3554
|
+
if (statements.length === 0) {
|
|
3555
|
+
throw new Error(`\u8FC1\u79FB\u6587\u4EF6\u6CA1\u6709\u53EF\u6267\u884C\u8BED\u53E5\uFF1A${options.file}`);
|
|
3556
|
+
}
|
|
3557
|
+
const { project: project2 } = await open2(paths, options);
|
|
3558
|
+
const applied = [];
|
|
3559
|
+
const changes = [];
|
|
3560
|
+
for (const statement of statements) {
|
|
3561
|
+
try {
|
|
3562
|
+
const result = await dbExec(paths, {
|
|
3563
|
+
cwd: options.cwd,
|
|
3564
|
+
...options.slug === void 0 ? {} : { slug: options.slug },
|
|
3565
|
+
sql: statement
|
|
3566
|
+
});
|
|
3567
|
+
applied.push(statement);
|
|
3568
|
+
changes.push(result.changes);
|
|
3569
|
+
} catch (error) {
|
|
3570
|
+
const code = error instanceof CliError ? error.code : "MIGRATE_FAILED";
|
|
3571
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3572
|
+
return {
|
|
3573
|
+
projectId: project2,
|
|
3574
|
+
applied,
|
|
3575
|
+
changes,
|
|
3576
|
+
failed: { statement, code, message }
|
|
3577
|
+
};
|
|
3578
|
+
}
|
|
3579
|
+
}
|
|
3580
|
+
return { projectId: project2, applied, changes };
|
|
3581
|
+
}
|
|
3582
|
+
var init_db2 = __esm({
|
|
3583
|
+
"packages/cli/src/db.ts"() {
|
|
3584
|
+
"use strict";
|
|
3585
|
+
init_auth();
|
|
3586
|
+
init_client();
|
|
3587
|
+
}
|
|
3588
|
+
});
|
|
3589
|
+
|
|
3590
|
+
// packages/cli/src/serve/sqlite-driver.ts
|
|
3591
|
+
import { mkdir as mkdir7 } from "node:fs/promises";
|
|
3592
|
+
import { dirname as dirname8, resolve as resolve5 } from "node:path";
|
|
3593
|
+
function isBun(versions) {
|
|
3594
|
+
return versions["bun"] !== void 0 && versions["bun"] !== "";
|
|
3595
|
+
}
|
|
3596
|
+
function detectSqliteRuntime(versions = process.versions) {
|
|
3597
|
+
if (isBun(versions)) return "bun";
|
|
3598
|
+
const raw = versions["node"];
|
|
3599
|
+
if (raw === void 0) return null;
|
|
3600
|
+
const [majorText, minorText] = raw.split(".");
|
|
3601
|
+
const major = Number(majorText);
|
|
3602
|
+
const minor = Number(minorText ?? "0");
|
|
3603
|
+
if (!Number.isInteger(major) || !Number.isInteger(minor)) return null;
|
|
3604
|
+
if (major > NODE_SQLITE_MIN.major) return "node";
|
|
3605
|
+
if (major === NODE_SQLITE_MIN.major && minor >= NODE_SQLITE_MIN.minor) return "node";
|
|
3606
|
+
return null;
|
|
3607
|
+
}
|
|
3608
|
+
function sqliteModuleName(runtime) {
|
|
3609
|
+
return runtime === "bun" ? "bun:sqlite" : "node:sqlite";
|
|
3610
|
+
}
|
|
3611
|
+
function sqliteUnavailableReason(versions = process.versions) {
|
|
3612
|
+
const current = isBun(versions) ? `Bun ${versions["bun"] ?? ""}`.trim() : `Node ${versions["node"] ?? "\u672A\u77E5"}`;
|
|
3613
|
+
return `\u5F53\u524D\u8FD0\u884C\u65F6 ${current} \u4E0D\u63D0\u4F9B SQLite \u5185\u5EFA\u6A21\u5757\uFF08\u9700\u8981 Bun \u6216 Node \u2265 ${NODE_SQLITE_MIN.major}.${NODE_SQLITE_MIN.minor}\uFF09`;
|
|
3614
|
+
}
|
|
3615
|
+
function sqliteRuntimeRequirementMessage(versions = process.versions) {
|
|
3616
|
+
return `--db sqlite \u9700\u8981 Bun\uFF08\u5185\u7F6E bun:sqlite\uFF09\u6216 Node \u2265 ${NODE_SQLITE_MIN.major}.${NODE_SQLITE_MIN.minor}\uFF08\u5185\u7F6E node:sqlite\uFF09\uFF1B${sqliteUnavailableReason(versions)}\u3002\u8BF7\u6539\u7528 \`--db sim\`\uFF08\u5185\u7F6E\u6A21\u62DF\u5F15\u64CE\uFF0C\u65E0\u9700\u989D\u5916\u8FD0\u884C\u65F6\uFF09\uFF0C\u6216\u5347\u7EA7 Node / \u7528 Bun \u8FD0\u884C\u3002`;
|
|
3617
|
+
}
|
|
3618
|
+
async function openSqliteProjectDriver(file, options = {}) {
|
|
3619
|
+
const runtime = options.runtime ?? detectSqliteRuntime();
|
|
3620
|
+
if (runtime === null) throw new Error(sqliteRuntimeRequirementMessage());
|
|
3621
|
+
const moduleName = sqliteModuleName(runtime);
|
|
3622
|
+
const ctorName = runtime === "bun" ? "Database" : "DatabaseSync";
|
|
3623
|
+
let mod;
|
|
3624
|
+
try {
|
|
3625
|
+
const specifier = moduleName;
|
|
3626
|
+
mod = await import(
|
|
3627
|
+
/* @vite-ignore */
|
|
3628
|
+
specifier
|
|
3629
|
+
);
|
|
3630
|
+
} catch (error) {
|
|
3631
|
+
throw new Error(
|
|
3632
|
+
`${sqliteRuntimeRequirementMessage()}
|
|
3633
|
+
\uFF08\u8F7D\u5165 ${moduleName} \u5931\u8D25\uFF1A${error instanceof Error ? error.message : String(error)}\uFF09`,
|
|
3634
|
+
{ cause: error }
|
|
3635
|
+
);
|
|
3636
|
+
}
|
|
3637
|
+
const Ctor = mod[ctorName];
|
|
3638
|
+
if (Ctor === void 0) {
|
|
3639
|
+
throw new Error(`${moduleName} \u672A\u5BFC\u51FA ${ctorName}\uFF1A\u5F53\u524D\u8FD0\u884C\u65F6\u7684 SQLite \u5185\u5EFA\u6A21\u5757\u4E0D\u53EF\u7528`);
|
|
3640
|
+
}
|
|
3641
|
+
const target = file === ":memory:" ? file : resolve5(file);
|
|
3642
|
+
if (target !== ":memory:") await mkdir7(dirname8(target), { recursive: true });
|
|
3643
|
+
const database = new Ctor(target);
|
|
3644
|
+
database.exec("PRAGMA journal_mode = WAL; PRAGMA foreign_keys = ON;");
|
|
3645
|
+
return {
|
|
3646
|
+
engine: "sqlite",
|
|
3647
|
+
async run(sql, params = []) {
|
|
3648
|
+
if (params.length === 0) {
|
|
3649
|
+
database.exec(sql);
|
|
3650
|
+
return { changes: 0 };
|
|
3651
|
+
}
|
|
3652
|
+
const result = database.prepare(sql).run(...params);
|
|
3653
|
+
return { changes: Number(result.changes) };
|
|
3654
|
+
},
|
|
3655
|
+
async all(sql, params = []) {
|
|
3656
|
+
const statement = database.prepare(sql);
|
|
3657
|
+
statement.setReturnArrays?.(false);
|
|
3658
|
+
return statement.all(...params);
|
|
3659
|
+
},
|
|
3660
|
+
async get(sql, params = []) {
|
|
3661
|
+
const statement = database.prepare(sql);
|
|
3662
|
+
statement.setReturnArrays?.(false);
|
|
3663
|
+
const row = statement.get(...params);
|
|
3664
|
+
return row ?? null;
|
|
3665
|
+
},
|
|
3666
|
+
async close() {
|
|
3667
|
+
database.close();
|
|
3668
|
+
}
|
|
3669
|
+
};
|
|
3670
|
+
}
|
|
3671
|
+
var NODE_SQLITE_MIN;
|
|
3672
|
+
var init_sqlite_driver = __esm({
|
|
3673
|
+
"packages/cli/src/serve/sqlite-driver.ts"() {
|
|
3674
|
+
"use strict";
|
|
3675
|
+
NODE_SQLITE_MIN = { major: 22, minor: 5 };
|
|
3676
|
+
}
|
|
3677
|
+
});
|
|
3678
|
+
|
|
3679
|
+
// packages/cli/src/serve/db-mode.ts
|
|
3680
|
+
import { readFile as readFile7 } from "node:fs/promises";
|
|
3681
|
+
import { join as join9, relative as relative2, resolve as resolve6 } from "node:path";
|
|
3682
|
+
function isServeDbMode(value) {
|
|
3683
|
+
return SERVE_DB_MODES.includes(value.trim().toLowerCase());
|
|
3684
|
+
}
|
|
3685
|
+
function parseServeDbMode(raw, source) {
|
|
3686
|
+
const value = raw.trim().toLowerCase();
|
|
3687
|
+
if (!isServeDbMode(value)) {
|
|
3688
|
+
throw new Error(
|
|
3689
|
+
`${source} \u7684\u6570\u636E\u5E93\u6A21\u5F0F "${raw}" \u65E0\u6548\uFF1A\u53EA\u652F\u6301 ${SERVE_DB_MODES.join(" | ")}\uFF08sim = \u5185\u7F6E\u6A21\u62DF\u5F15\u64CE\u4E0E .adep/sim/db.json\uFF1Bsqlite = \u771F\u5B9E SQLite \u5E93\u6587\u4EF6\uFF09`
|
|
3690
|
+
);
|
|
3691
|
+
}
|
|
3692
|
+
return value;
|
|
3693
|
+
}
|
|
3694
|
+
function resolveServeDbMode(explicit) {
|
|
3695
|
+
if (explicit !== void 0) return parseServeDbMode(explicit, "--db");
|
|
3696
|
+
const fromEnv = process.env["ADEP_SERVE_DB"];
|
|
3697
|
+
if (fromEnv !== void 0 && fromEnv.trim() !== "") {
|
|
3698
|
+
return parseServeDbMode(fromEnv, "ADEP_SERVE_DB");
|
|
3699
|
+
}
|
|
3700
|
+
return DEFAULT_SERVE_DB_MODE;
|
|
3701
|
+
}
|
|
3702
|
+
function resolveServeDbFile(cwd, explicit) {
|
|
3703
|
+
const raw = explicit ?? envDbFile() ?? DEFAULT_SQLITE_DB_FILE;
|
|
3704
|
+
return raw === ":memory:" ? raw : resolve6(cwd, raw);
|
|
3705
|
+
}
|
|
3706
|
+
function envDbFile() {
|
|
3707
|
+
const raw = process.env["ADEP_SERVE_DB_FILE"];
|
|
3708
|
+
return raw === void 0 || raw.trim() === "" ? void 0 : raw.trim();
|
|
3709
|
+
}
|
|
3710
|
+
function displayPath(cwd, target) {
|
|
3711
|
+
if (target === ":memory:") return target;
|
|
3712
|
+
const rel = relative2(cwd, target);
|
|
3713
|
+
return rel.startsWith("..") ? target : rel;
|
|
3714
|
+
}
|
|
3715
|
+
function simDbTarget(cwd) {
|
|
3716
|
+
return displayPath(cwd, join9(simDir(cwd), "db.json"));
|
|
3717
|
+
}
|
|
3718
|
+
function resolveLocalDbTarget(cwd, options) {
|
|
3719
|
+
const mode = resolveServeDbMode(options.db);
|
|
3720
|
+
return {
|
|
3721
|
+
mode,
|
|
3722
|
+
file: mode === "sqlite" ? resolveServeDbFile(cwd, options.dbFile) : null
|
|
3723
|
+
};
|
|
3724
|
+
}
|
|
3725
|
+
async function openLocalDbDriver(target, options) {
|
|
3726
|
+
if (target.mode === "sim" || target.file === null) {
|
|
3727
|
+
return { mode: "sim", file: null, module: null, driver: null };
|
|
3728
|
+
}
|
|
3729
|
+
const simTarget = simDbTarget(options.cwd);
|
|
3730
|
+
const runtimeName = detectSqliteRuntime();
|
|
3731
|
+
if (runtimeName === null) {
|
|
3732
|
+
options.log(
|
|
3733
|
+
`[${options.tag}] \u8B66\u544A\uFF1A${sqliteUnavailableReason()}\uFF0C\u5DF2\u81EA\u52A8\u964D\u7EA7\u4E3A sim \u6A21\u5F0F\uFF08\u5185\u7F6E\u6A21\u62DF\u5F15\u64CE\uFF0C\u5E93 ${simTarget}\uFF09\u3002\u5982\u9700\u771F\u5B9E SQLite\uFF0C\u8BF7\u7528 Bun \u6216\u5347\u7EA7 Node \u540E\u91CD\u8BD5\u3002`
|
|
3734
|
+
);
|
|
3735
|
+
return { mode: "sim", file: null, module: null, driver: null };
|
|
3736
|
+
}
|
|
3737
|
+
try {
|
|
3738
|
+
const driver = await openSqliteProjectDriver(target.file, { runtime: runtimeName });
|
|
3739
|
+
return {
|
|
3740
|
+
mode: "sqlite",
|
|
3741
|
+
file: target.file,
|
|
3742
|
+
module: sqliteModuleName(runtimeName),
|
|
3743
|
+
driver
|
|
3744
|
+
};
|
|
3745
|
+
} catch (error) {
|
|
3746
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
3747
|
+
options.log(
|
|
3748
|
+
`[${options.tag}] \u8B66\u544A\uFF1A\u6253\u5F00 SQLite \u5E93\u5931\u8D25\uFF08${detail}\uFF09\uFF0C\u5DF2\u81EA\u52A8\u964D\u7EA7\u4E3A sim \u6A21\u5F0F\uFF08\u5185\u7F6E\u6A21\u62DF\u5F15\u64CE\uFF0C\u5E93 ${simTarget}\uFF09\u3002`
|
|
3749
|
+
);
|
|
3750
|
+
return { mode: "sim", file: null, module: null, driver: null };
|
|
3751
|
+
}
|
|
3752
|
+
}
|
|
3753
|
+
async function applyLocalSchema(driver, options) {
|
|
3754
|
+
const { schemaFile, mode, tag, cwd, log } = options;
|
|
3755
|
+
const schemaPath = resolve6(cwd, schemaFile);
|
|
3756
|
+
const schemaSource = await readFile7(schemaPath, "utf8").catch((error) => {
|
|
3757
|
+
if (error.code === "ENOENT") {
|
|
3758
|
+
throw new Error(`schema \u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${schemaPath}`);
|
|
3759
|
+
}
|
|
3760
|
+
throw error;
|
|
3761
|
+
});
|
|
3762
|
+
const statements = splitSqlStatements(schemaSource);
|
|
3763
|
+
let applied = 0;
|
|
3764
|
+
let skipped = 0;
|
|
3765
|
+
for (const [index, statement] of statements.entries()) {
|
|
3766
|
+
try {
|
|
3767
|
+
await driver.run(statement);
|
|
3768
|
+
applied += 1;
|
|
3769
|
+
} catch (error) {
|
|
3770
|
+
const isUnsupported = error instanceof Error && "code" in error && error.code === "DB_UNSAFE_OP";
|
|
3771
|
+
if (mode === "sim" && isUnsupported) {
|
|
3772
|
+
skipped += 1;
|
|
3773
|
+
log(`[${tag}] \u8DF3\u8FC7 schema \u8BED\u53E5\uFF08sim \u5F15\u64CE\u4E0D\u652F\u6301\uFF09\uFF1A${statement.slice(0, 60)}\u2026`);
|
|
3774
|
+
continue;
|
|
3775
|
+
}
|
|
3776
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
3777
|
+
throw new Error(
|
|
3778
|
+
`schema \u8BED\u53E5\u6267\u884C\u5931\u8D25\uFF08--schema ${schemaFile}\uFF0C\u7B2C ${index + 1} \u6761\uFF0Cdb \u6A21\u5F0F ${mode}\uFF09\uFF1A${detail}
|
|
3779
|
+
\u8BED\u53E5\uFF1A${statement.slice(0, 200)}` + (mode === "sqlite" ? "\n\uFF08sqlite \u6A21\u5F0F\u4E0D\u505A\u8BED\u53E5\u8DF3\u8FC7\uFF1B\u5982\u9700\u8DF3\u8FC7\u8BED\u4E49\u8BF7\u6539\u7528 --db sim\uFF09" : ""),
|
|
3780
|
+
{ cause: error }
|
|
3781
|
+
);
|
|
3782
|
+
}
|
|
3783
|
+
}
|
|
3784
|
+
const skipNote = skipped > 0 ? `\uFF0C\u8DF3\u8FC7 ${skipped} \u6761` : "";
|
|
3785
|
+
log(`[${tag}] \u5DF2\u5E94\u7528\u6570\u636E\u5E93\u7ED3\u6784\uFF08--schema ${schemaFile}\uFF09\uFF1A${applied} \u6761\u8BED\u53E5${skipNote}`);
|
|
3786
|
+
}
|
|
3787
|
+
var SERVE_DB_MODES, DEFAULT_SERVE_DB_MODE, DEFAULT_SQLITE_DB_FILE;
|
|
3788
|
+
var init_db_mode = __esm({
|
|
3789
|
+
"packages/cli/src/serve/db-mode.ts"() {
|
|
3790
|
+
"use strict";
|
|
3791
|
+
init_db2();
|
|
3792
|
+
init_runtime();
|
|
3793
|
+
init_sqlite_driver();
|
|
3794
|
+
SERVE_DB_MODES = ["sim", "sqlite"];
|
|
3795
|
+
DEFAULT_SERVE_DB_MODE = "sqlite";
|
|
3796
|
+
DEFAULT_SQLITE_DB_FILE = ".adep/data/project.sqlite";
|
|
3797
|
+
}
|
|
3798
|
+
});
|
|
3799
|
+
|
|
3800
|
+
// packages/cli/src/sim/env.ts
|
|
3801
|
+
import { readFile as readFile8 } from "node:fs/promises";
|
|
3802
|
+
import { join as join10 } from "node:path";
|
|
3803
|
+
function parseEnv(content) {
|
|
3804
|
+
const env = {};
|
|
3805
|
+
for (const raw of content.split(/\r?\n/)) {
|
|
3806
|
+
const line = raw.trim();
|
|
3807
|
+
if (line.length === 0 || line.startsWith("#")) continue;
|
|
3808
|
+
const eq = line.indexOf("=");
|
|
3809
|
+
if (eq === -1) continue;
|
|
3810
|
+
const key = line.slice(0, eq).trim();
|
|
3811
|
+
if (key.length === 0) continue;
|
|
3812
|
+
env[key] = line.slice(eq + 1).trim();
|
|
3813
|
+
}
|
|
3814
|
+
return env;
|
|
3815
|
+
}
|
|
3816
|
+
async function loadSimEnv(cwd, config = {}) {
|
|
3817
|
+
const envRoot = await readFile8(join10(cwd, ".env"), "utf8").catch(() => "");
|
|
3818
|
+
const envLocal = await readFile8(join10(cwd, ".env.local"), "utf8").catch(() => "");
|
|
3819
|
+
const merged = { ...parseEnv(envRoot), ...parseEnv(envLocal) };
|
|
3820
|
+
for (const secret of config.secrets ?? []) {
|
|
3821
|
+
if (merged[secret] !== void 0) continue;
|
|
3822
|
+
if (process.env[secret] !== void 0) {
|
|
3823
|
+
merged[secret] = process.env[secret];
|
|
3824
|
+
continue;
|
|
3825
|
+
}
|
|
3826
|
+
throw new Error(
|
|
3827
|
+
`secret "${secret}" \u672A\u914D\u7F6E\uFF1A\u8BF7\u5728 .env.local \u6DFB\u52A0 ${secret}=<value>\uFF0C\u6216\u7528\u73AF\u5883\u53D8\u91CF\u5BFC\u51FA\u540E\u91CD\u8BD5 adep dev\uFF08\u6A21\u62DF\u73AF\u5883\u6C38\u4E0D\u843D\u76D8\u8BE5\u503C\uFF09`
|
|
3828
|
+
);
|
|
3829
|
+
}
|
|
3830
|
+
return merged;
|
|
3831
|
+
}
|
|
3832
|
+
var init_env = __esm({
|
|
3833
|
+
"packages/cli/src/sim/env.ts"() {
|
|
3834
|
+
"use strict";
|
|
3835
|
+
}
|
|
3836
|
+
});
|
|
3837
|
+
|
|
3838
|
+
// packages/cli/src/sim/invoke.ts
|
|
3839
|
+
function resolveFunctionEntry(files, fnName) {
|
|
3840
|
+
const flat = `${fnName}.ts`;
|
|
3841
|
+
if (files[flat] !== void 0) return flat;
|
|
3842
|
+
const directory = `${fnName}/index.ts`;
|
|
3843
|
+
if (files[directory] !== void 0) return directory;
|
|
3844
|
+
return void 0;
|
|
3845
|
+
}
|
|
3846
|
+
function listFunctionNames(files) {
|
|
3847
|
+
const names = /* @__PURE__ */ new Set();
|
|
3848
|
+
for (const key of Object.keys(files)) {
|
|
3849
|
+
const parts = key.split("/");
|
|
3850
|
+
if (parts.length === 1 && parts[0] !== void 0 && parts[0].endsWith(".ts")) {
|
|
3851
|
+
names.add(parts[0].slice(0, -3));
|
|
3852
|
+
} else if (parts.length === 2 && parts[1] === "index.ts" && parts[0] !== void 0) {
|
|
3853
|
+
names.add(parts[0]);
|
|
3854
|
+
}
|
|
3855
|
+
}
|
|
3856
|
+
return [...names];
|
|
3857
|
+
}
|
|
3858
|
+
function createSimInvokeHandler(options) {
|
|
3859
|
+
return async (method, args) => {
|
|
3860
|
+
if (method !== "invoke") {
|
|
3861
|
+
throw new Error(`\u672A\u77E5\u7684 cloud.invoke \u65B9\u6CD5 "${method}"`);
|
|
3862
|
+
}
|
|
3863
|
+
const input = args[0];
|
|
3864
|
+
if (typeof input?.name !== "string" || input.name.length === 0) {
|
|
3865
|
+
throw new Error("cloud.invoke \u9700\u8981\u76EE\u6807\u51FD\u6570\u540D\uFF08InvokeInput.name\uFF09");
|
|
3866
|
+
}
|
|
3867
|
+
const targetEntry = resolveFunctionEntry(options.files, input.name);
|
|
3868
|
+
if (targetEntry === void 0) {
|
|
3869
|
+
throw new Error(`\u76EE\u6807\u51FD\u6570 "${input.name}" \u4E0D\u5B58\u5728`);
|
|
3870
|
+
}
|
|
3871
|
+
const executeInput = {
|
|
3872
|
+
project: { id: "local", slug: "local" },
|
|
3873
|
+
fn: { id: input.name, name: input.name },
|
|
3874
|
+
files: options.files,
|
|
3875
|
+
entry: targetEntry,
|
|
3876
|
+
request: {
|
|
3877
|
+
method: "POST",
|
|
3878
|
+
path: `/${input.name}`,
|
|
3879
|
+
query: input.query ?? {},
|
|
3880
|
+
headers: {},
|
|
3881
|
+
...input.body === void 0 ? {} : { body: input.body }
|
|
3882
|
+
},
|
|
3883
|
+
timeoutMs: 1e4,
|
|
3884
|
+
...options.env === void 0 ? {} : { env: options.env }
|
|
3885
|
+
};
|
|
3886
|
+
const result = await options.executor.execute(executeInput);
|
|
3887
|
+
return result.body;
|
|
3888
|
+
};
|
|
3889
|
+
}
|
|
3890
|
+
var init_invoke = __esm({
|
|
3891
|
+
"packages/cli/src/sim/invoke.ts"() {
|
|
3892
|
+
"use strict";
|
|
3893
|
+
}
|
|
3894
|
+
});
|
|
3895
|
+
|
|
3896
|
+
// shared/builtin-deps.ts
|
|
3897
|
+
var CF_COMPAT_SPECIFIER, STATE_OBJECTS_SPECIFIER, CRYPTO_SPECIFIER, ROUTE_SPECIFIER, BUILTIN_DEPS, BUILTIN_DEPS_CSV;
|
|
3898
|
+
var init_builtin_deps = __esm({
|
|
3899
|
+
"shared/builtin-deps.ts"() {
|
|
3900
|
+
"use strict";
|
|
3901
|
+
CF_COMPAT_SPECIFIER = "@adep/cf-compat";
|
|
3902
|
+
STATE_OBJECTS_SPECIFIER = "@adep/runtime/state-objects";
|
|
3903
|
+
CRYPTO_SPECIFIER = "@adep/crypto";
|
|
3904
|
+
ROUTE_SPECIFIER = "@adep/runtime/route";
|
|
3905
|
+
BUILTIN_DEPS = [
|
|
3906
|
+
CF_COMPAT_SPECIFIER,
|
|
3907
|
+
STATE_OBJECTS_SPECIFIER,
|
|
3908
|
+
CRYPTO_SPECIFIER,
|
|
3909
|
+
ROUTE_SPECIFIER,
|
|
3910
|
+
"axios",
|
|
3911
|
+
"lodash",
|
|
3912
|
+
"dayjs",
|
|
3913
|
+
"zod"
|
|
3914
|
+
];
|
|
3915
|
+
BUILTIN_DEPS_CSV = BUILTIN_DEPS.join(",");
|
|
3916
|
+
}
|
|
3917
|
+
});
|
|
3918
|
+
|
|
3919
|
+
// packages/cli/src/builtin-deps.ts
|
|
3920
|
+
var LOCAL_BUILTIN_DEPS;
|
|
3921
|
+
var init_builtin_deps2 = __esm({
|
|
3922
|
+
"packages/cli/src/builtin-deps.ts"() {
|
|
3923
|
+
"use strict";
|
|
3924
|
+
init_builtin_deps();
|
|
3925
|
+
LOCAL_BUILTIN_DEPS = [
|
|
3926
|
+
CF_COMPAT_SPECIFIER,
|
|
3927
|
+
STATE_OBJECTS_SPECIFIER,
|
|
3928
|
+
CRYPTO_SPECIFIER,
|
|
3929
|
+
ROUTE_SPECIFIER
|
|
3930
|
+
];
|
|
3931
|
+
}
|
|
3932
|
+
});
|
|
3933
|
+
|
|
3934
|
+
// packages/cli/src/sim/boundary.ts
|
|
3935
|
+
var SIM_BOUNDARIES;
|
|
3936
|
+
var init_boundary = __esm({
|
|
3937
|
+
"packages/cli/src/sim/boundary.ts"() {
|
|
3938
|
+
"use strict";
|
|
3939
|
+
SIM_BOUNDARIES = [
|
|
3940
|
+
{
|
|
3941
|
+
kind: "capability",
|
|
3942
|
+
title: "\u89E6\u53D1\u5668\u4E0D\u81EA\u52A8\u6267\u884C",
|
|
3943
|
+
detail: "\u5B9A\u65F6 / \u4E8B\u4EF6\u89E6\u53D1\u5668\u53EA\u767B\u8BB0\uFF0C\u4E0D\u7531\u6A21\u62DF\u5668\u81EA\u52A8\u89E6\u53D1\uFF08\u672C\u5730\u4EE5\u624B\u5DE5 HTTP \u8C03\u7528\u66FF\u4EE3\uFF09\u3002"
|
|
3944
|
+
},
|
|
3945
|
+
{
|
|
3946
|
+
kind: "diff",
|
|
3947
|
+
title: "\u65E0\u8DE8\u5B9E\u4F8B\u5E7F\u64AD",
|
|
3948
|
+
detail: "cloud.realtime \u5DF2\u6CE8\u5165\uFF0C\u4F46\u4E3A\u5355\u8FDB\u7A0B\u5185\u5B58\u5E7F\u64AD\uFF1A\u4E0D\u652F\u6301\u8DE8\u8FDB\u7A0B / \u8DE8\u5B9E\u4F8B\uFF0C\u7EBF\u4E0A\u591A\u5B9E\u4F8B\u8BED\u4E49\u4E0D\u540C\u3002"
|
|
3949
|
+
},
|
|
3950
|
+
{
|
|
3951
|
+
kind: "capability",
|
|
3952
|
+
title: "publish \u4E0D\u652F\u6301 except",
|
|
3953
|
+
detail: "\u672C\u5730\u4E0D\u5EFA WS \u63E1\u624B\u3001\u65E0\u8FDE\u63A5\u8EAB\u4EFD\uFF0C\u6545 cloud.realtime.publish \u7684 except\uFF08\u4E0D\u53D1\u56DE\u53D1\u9001\u8005\uFF09\u65E0\u4ECE\u5B9E\u73B0\uFF0C\u4F20\u5165\u5373\u62A5\u9519\u3002"
|
|
3954
|
+
},
|
|
3955
|
+
{
|
|
3956
|
+
kind: "capability",
|
|
3957
|
+
title: "\u65E0\u9650\u989D\u7B49\u4EF7",
|
|
3958
|
+
detail: "\u672C\u5730\u4E0D\u6267\u884C\u8BA1\u91CF / \u914D\u989D\u95E8\u7981\uFF08\u4E0D\u6309\u51FD\u6570\u8C03\u7528\u3001\u6D41\u91CF\u3001\u63A8\u9001\u8BA1\u6570\uFF09\uFF0C\u9650\u989D\u8BED\u4E49\u4EC5\u7EBF\u4E0A\u751F\u6548\u3002"
|
|
3959
|
+
},
|
|
3960
|
+
{
|
|
3961
|
+
kind: "diff",
|
|
3962
|
+
title: "\u4E0D\u8BA1\u91CF",
|
|
3963
|
+
detail: "\u672C\u6A21\u62DF\u8FD0\u884C\u65F6\u4E0D\u4EA7\u51FA\u8BA1\u91CF\u4E8B\u4EF6\uFF0C\u4E5F\u4E0D\u5199 billing\uFF1B\u79BB\u7EBF\u5F00\u53D1\u4E0D\u8BA1\u8D39\u3002"
|
|
3964
|
+
}
|
|
3965
|
+
];
|
|
3966
|
+
}
|
|
3967
|
+
});
|
|
3968
|
+
|
|
3969
|
+
// packages/cli/src/ts-config.ts
|
|
3970
|
+
import { stat as stat6, readFile as readFile9 } from "node:fs/promises";
|
|
3971
|
+
import { join as join11 } from "node:path";
|
|
3972
|
+
async function loadAdepConfigModule(cwd) {
|
|
3973
|
+
const configPath = join11(cwd, "adep.config.ts");
|
|
3974
|
+
try {
|
|
3975
|
+
await stat6(configPath);
|
|
3976
|
+
} catch {
|
|
3977
|
+
return null;
|
|
3978
|
+
}
|
|
3979
|
+
let rawDefault;
|
|
3980
|
+
try {
|
|
3981
|
+
const bun = globalThis.Bun;
|
|
3474
3982
|
if (bun !== void 0) {
|
|
3475
3983
|
const mod = await import(configPath);
|
|
3476
3984
|
rawDefault = mod.default;
|
|
3477
3985
|
} else {
|
|
3478
3986
|
const { transform } = await import("esbuild");
|
|
3479
|
-
const source = await
|
|
3987
|
+
const source = await readFile9(configPath, "utf8");
|
|
3480
3988
|
const { code } = await transform(source, {
|
|
3481
3989
|
loader: "ts",
|
|
3482
3990
|
format: "esm",
|
|
@@ -4424,7 +4932,7 @@ var init_chain = __esm({
|
|
|
4424
4932
|
// packages/runtime/src/functions/runtime/worker-entry.ts
|
|
4425
4933
|
import { parentPort, workerData } from "node:worker_threads";
|
|
4426
4934
|
import { createRequire } from "node:module";
|
|
4427
|
-
import { join as
|
|
4935
|
+
import { join as join12 } from "node:path";
|
|
4428
4936
|
function isRpcCapability(value) {
|
|
4429
4937
|
return typeof value === "object" && value !== null && value[RPC_CAPABILITY_KEY] === true;
|
|
4430
4938
|
}
|
|
@@ -4473,7 +4981,7 @@ function errorMessageWithLocation(error, files) {
|
|
|
4473
4981
|
}
|
|
4474
4982
|
function createBareResolver(deps) {
|
|
4475
4983
|
const platformRequire = createRequire(import.meta.url);
|
|
4476
|
-
const depsRequire = deps.dir === null ? null : createRequire(
|
|
4984
|
+
const depsRequire = deps.dir === null ? null : createRequire(join12(deps.dir, "__deps__.js"));
|
|
4477
4985
|
return (request) => {
|
|
4478
4986
|
if (deps.builtin.includes(request)) return platformRequire(request);
|
|
4479
4987
|
const root = splitBareSpecifier(request);
|
|
@@ -4664,8 +5172,8 @@ var init_shared_source = __esm({
|
|
|
4664
5172
|
});
|
|
4665
5173
|
|
|
4666
5174
|
// packages/cli/src/dev-shared.ts
|
|
4667
|
-
import { readdir as readdir4, readFile as
|
|
4668
|
-
import { join as
|
|
5175
|
+
import { readdir as readdir4, readFile as readFile10 } from "node:fs/promises";
|
|
5176
|
+
import { join as join13 } from "node:path";
|
|
4669
5177
|
function bearerUserResolverFromEnv() {
|
|
4670
5178
|
const raw = process.env.ADEP_AUTH_ISSUER;
|
|
4671
5179
|
if (raw === void 0 || raw.trim() === "") return void 0;
|
|
@@ -4706,11 +5214,11 @@ async function collectFunctions(dir) {
|
|
|
4706
5214
|
}
|
|
4707
5215
|
for (const entry of entries) {
|
|
4708
5216
|
const rel = prefix.length === 0 ? entry.name : `${prefix}/${entry.name}`;
|
|
4709
|
-
const full =
|
|
5217
|
+
const full = join13(sub, entry.name);
|
|
4710
5218
|
if (entry.isDirectory()) {
|
|
4711
5219
|
await walk(full, rel);
|
|
4712
5220
|
} else if (entry.isFile() && isRuntimeSource(entry.name)) {
|
|
4713
|
-
files[rel] = await
|
|
5221
|
+
files[rel] = await readFile10(full, "utf8");
|
|
4714
5222
|
}
|
|
4715
5223
|
}
|
|
4716
5224
|
};
|
|
@@ -4798,10 +5306,10 @@ __export(dev_exports, {
|
|
|
4798
5306
|
});
|
|
4799
5307
|
import { createServer } from "node:http";
|
|
4800
5308
|
import { watch } from "node:fs";
|
|
4801
|
-
import { mkdir as
|
|
4802
|
-
import { basename as basename2, join as
|
|
5309
|
+
import { mkdir as mkdir8, readFile as readFile11, writeFile as writeFile6 } from "node:fs/promises";
|
|
5310
|
+
import { basename as basename2, join as join14, resolve as resolve7 } from "node:path";
|
|
4803
5311
|
async function loadConfig(cwd) {
|
|
4804
|
-
const name = basename2(
|
|
5312
|
+
const name = basename2(resolve7(cwd));
|
|
4805
5313
|
const config = await loadAdepConfigModule(cwd);
|
|
4806
5314
|
return {
|
|
4807
5315
|
name: config?.name ?? name,
|
|
@@ -4843,34 +5351,49 @@ function printBoundaries(log) {
|
|
|
4843
5351
|
}
|
|
4844
5352
|
}
|
|
4845
5353
|
async function ensureGitignore(cwd) {
|
|
4846
|
-
const gitignorePath =
|
|
4847
|
-
const existing = await
|
|
5354
|
+
const gitignorePath = join14(cwd, ".gitignore");
|
|
5355
|
+
const existing = await readFile11(gitignorePath, "utf8").catch(() => "");
|
|
4848
5356
|
if (existing.split(/\r?\n/).includes(".adep/")) return;
|
|
4849
5357
|
await writeFile6(gitignorePath, `${existing.replace(/\n+$/, "")}
|
|
4850
5358
|
.adep/
|
|
4851
5359
|
`, "utf8");
|
|
4852
5360
|
}
|
|
4853
5361
|
async function startDevServer(options) {
|
|
4854
|
-
const cwd =
|
|
5362
|
+
const cwd = resolve7(options.cwd);
|
|
4855
5363
|
const log = options.log ?? ((line) => process.stdout.write(`${line}
|
|
4856
5364
|
`));
|
|
4857
5365
|
const config = await loadConfig(cwd);
|
|
4858
5366
|
if (options.prefix !== void 0) {
|
|
4859
5367
|
config.functionsPrefix = options.prefix.replace(/^\/+|\/+$/g, "");
|
|
4860
5368
|
}
|
|
4861
|
-
const functionsDir =
|
|
5369
|
+
const functionsDir = join14(cwd, config.functionsDir);
|
|
4862
5370
|
const coldStartAt = Date.now();
|
|
5371
|
+
const dbTarget = resolveLocalDbTarget(cwd, {
|
|
5372
|
+
...options.db === void 0 ? {} : { db: options.db },
|
|
5373
|
+
...options.dbFile === void 0 ? {} : { dbFile: options.dbFile }
|
|
5374
|
+
});
|
|
4863
5375
|
const bearerUser = bearerUserResolverFromEnv();
|
|
4864
5376
|
const executor = new WorkerFunctionExecutor({
|
|
4865
5377
|
deps: { rootDir: cwd, builtin: LOCAL_BUILTIN_DEPS }
|
|
4866
5378
|
});
|
|
4867
|
-
await
|
|
5379
|
+
await mkdir8(functionsDir, { recursive: true });
|
|
5380
|
+
const db = await openLocalDbDriver(dbTarget, { cwd, tag: "adep", log });
|
|
4868
5381
|
const runtime = await createSimRuntime({
|
|
4869
5382
|
cwd,
|
|
4870
5383
|
projectId: "local",
|
|
4871
5384
|
baseUrl: `http://127.0.0.1:${options.port ?? 8787}`,
|
|
4872
|
-
log
|
|
5385
|
+
log,
|
|
5386
|
+
...db.driver === null ? {} : { driver: db.driver }
|
|
4873
5387
|
});
|
|
5388
|
+
if (options.schemaFile !== void 0) {
|
|
5389
|
+
await applyLocalSchema(runtime.db.driver, {
|
|
5390
|
+
cwd,
|
|
5391
|
+
schemaFile: options.schemaFile,
|
|
5392
|
+
mode: db.mode,
|
|
5393
|
+
tag: "adep",
|
|
5394
|
+
log
|
|
5395
|
+
});
|
|
5396
|
+
}
|
|
4874
5397
|
await ensureGitignore(cwd);
|
|
4875
5398
|
let files = mergeSharedIntoFunctions(await collectFunctions(functionsDir));
|
|
4876
5399
|
let env = {
|
|
@@ -4951,12 +5474,12 @@ async function startDevServer(options) {
|
|
|
4951
5474
|
const reload = async () => {
|
|
4952
5475
|
const [nextFiles, envText2] = await Promise.all([
|
|
4953
5476
|
collectFunctions(functionsDir).then(mergeSharedIntoFunctions),
|
|
4954
|
-
|
|
5477
|
+
readFile11(join14(cwd, ".env.local"), "utf8").catch(() => "")
|
|
4955
5478
|
]);
|
|
4956
5479
|
files = nextFiles;
|
|
4957
5480
|
env = { ...config.environment, ...parseEnvFile(envText2) };
|
|
4958
5481
|
};
|
|
4959
|
-
const envText = await
|
|
5482
|
+
const envText = await readFile11(join14(cwd, ".env.local"), "utf8").catch(() => "");
|
|
4960
5483
|
env = { ...config.environment, ...parseEnvFile(envText) };
|
|
4961
5484
|
let debounceTimer;
|
|
4962
5485
|
let watcher;
|
|
@@ -5113,13 +5636,17 @@ async function startDevServer(options) {
|
|
|
5113
5636
|
const baseUrl = `http://127.0.0.1:${actualPort}`;
|
|
5114
5637
|
const coldStartMs = Date.now() - coldStartAt;
|
|
5115
5638
|
const curlPath = config.functionsPrefix.length === 0 ? "/hello" : `/${config.functionsPrefix}/hello`;
|
|
5116
|
-
|
|
5639
|
+
const dbLabel = db.mode === "sqlite" ? `SQLite \u771F\u5B9E\u5E93${db.module === null ? "" : `\uFF08${db.module}\uFF09`}` : "sim \u5F15\u64CE\uFF08\u5185\u7F6E\u6A21\u62DF\uFF09";
|
|
5640
|
+
const dbTargetText = db.file === null ? simDbTarget(cwd) : displayPath(cwd, db.file);
|
|
5641
|
+
log(
|
|
5642
|
+
`[adep] dev server listening on ${baseUrl}\uFF08\u672C\u5730\u8FD0\u884C\u65F6 / ${dbLabel}\uFF0C\u51B7\u542F\u52A8 ${coldStartMs}ms\uFF09`
|
|
5643
|
+
);
|
|
5117
5644
|
log(`[adep] curl \u793A\u4F8B\uFF1Acurl ${baseUrl}${curlPath}`);
|
|
5118
5645
|
printBoundaries(log);
|
|
5119
5646
|
if (bearerUser !== void 0) {
|
|
5120
5647
|
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`);
|
|
5121
5648
|
}
|
|
5122
|
-
log(`[adep] \
|
|
5649
|
+
log(`[adep] \u6570\u636E\u5E93\uFF1A${dbLabel} \u2192 ${dbTargetText}`);
|
|
5123
5650
|
startStateAlarmScheduler();
|
|
5124
5651
|
return {
|
|
5125
5652
|
port: actualPort,
|
|
@@ -5142,6 +5669,7 @@ var init_dev = __esm({
|
|
|
5142
5669
|
init_http_envelope();
|
|
5143
5670
|
init_worker_executor();
|
|
5144
5671
|
init_runtime();
|
|
5672
|
+
init_db_mode();
|
|
5145
5673
|
init_env();
|
|
5146
5674
|
init_invoke();
|
|
5147
5675
|
init_builtin_deps2();
|
|
@@ -5154,267 +5682,6 @@ var init_dev = __esm({
|
|
|
5154
5682
|
}
|
|
5155
5683
|
});
|
|
5156
5684
|
|
|
5157
|
-
// packages/cli/src/client.ts
|
|
5158
|
-
var client_exports = {};
|
|
5159
|
-
__export(client_exports, {
|
|
5160
|
-
createClient: () => createClient,
|
|
5161
|
-
resolveSlug: () => resolveSlug
|
|
5162
|
-
});
|
|
5163
|
-
async function envelopeError(response, fallbackCode, parsed) {
|
|
5164
|
-
const payload = parsed ?? null;
|
|
5165
|
-
return new CliError(
|
|
5166
|
-
payload?.error?.code ?? fallbackCode,
|
|
5167
|
-
payload?.error?.message ?? `\u5E73\u53F0\u8FD4\u56DE HTTP ${response.status}`
|
|
5168
|
-
);
|
|
5169
|
-
}
|
|
5170
|
-
async function parseBody(response) {
|
|
5171
|
-
const text = await response.text();
|
|
5172
|
-
if (text.length === 0) return null;
|
|
5173
|
-
try {
|
|
5174
|
-
return JSON.parse(text);
|
|
5175
|
-
} catch {
|
|
5176
|
-
return null;
|
|
5177
|
-
}
|
|
5178
|
-
}
|
|
5179
|
-
async function createClient(paths) {
|
|
5180
|
-
const credentials = await loadCredentials(paths);
|
|
5181
|
-
if (credentials === null) {
|
|
5182
|
-
throw new CliError("NOT_LOGGED_IN", "\u672A\u767B\u5F55\uFF1A\u8BF7\u5148\u6267\u884C adep login");
|
|
5183
|
-
}
|
|
5184
|
-
const server = credentials.server;
|
|
5185
|
-
const cookie = sessionCookieHeader(credentials);
|
|
5186
|
-
const request = async (path, init = {}, fallbackCode = "API_REQUEST_FAILED") => {
|
|
5187
|
-
const method = init.method ?? (init.body === void 0 ? "GET" : "POST");
|
|
5188
|
-
let response;
|
|
5189
|
-
try {
|
|
5190
|
-
response = await fetch(`${server}${path}`, {
|
|
5191
|
-
method,
|
|
5192
|
-
headers: { "content-type": "application/json", cookie },
|
|
5193
|
-
...init.body === void 0 ? {} : { body: JSON.stringify(init.body) }
|
|
5194
|
-
});
|
|
5195
|
-
} catch (error) {
|
|
5196
|
-
throw new CliError(
|
|
5197
|
-
"SERVER_UNREACHABLE",
|
|
5198
|
-
`\u65E0\u6CD5\u8FDE\u63A5\u5E73\u53F0 ${server}\uFF1A${error instanceof Error ? error.message : String(error)}`
|
|
5199
|
-
);
|
|
5200
|
-
}
|
|
5201
|
-
const parsed = await parseBody(response);
|
|
5202
|
-
if (response.status < 200 || response.status >= 300) {
|
|
5203
|
-
throw await envelopeError(response, fallbackCode, parsed);
|
|
5204
|
-
}
|
|
5205
|
-
return parsed;
|
|
5206
|
-
};
|
|
5207
|
-
const upload = async (path, form, fallbackCode = "UPLOAD_FAILED") => {
|
|
5208
|
-
let response;
|
|
5209
|
-
try {
|
|
5210
|
-
response = await fetch(`${server}${path}`, {
|
|
5211
|
-
method: "POST",
|
|
5212
|
-
headers: { cookie },
|
|
5213
|
-
body: form
|
|
5214
|
-
});
|
|
5215
|
-
} catch (error) {
|
|
5216
|
-
throw new CliError(
|
|
5217
|
-
"SERVER_UNREACHABLE",
|
|
5218
|
-
`\u65E0\u6CD5\u8FDE\u63A5\u5E73\u53F0 ${server}\uFF1A${error instanceof Error ? error.message : String(error)}`
|
|
5219
|
-
);
|
|
5220
|
-
}
|
|
5221
|
-
if (response.status < 200 || response.status >= 300) {
|
|
5222
|
-
throw await envelopeError(response, fallbackCode, await parseBody(response));
|
|
5223
|
-
}
|
|
5224
|
-
return response;
|
|
5225
|
-
};
|
|
5226
|
-
const download = async (url, fallbackCode = "DOWNLOAD_FAILED") => {
|
|
5227
|
-
const target = url.startsWith("http") ? url : `${server}${url}`;
|
|
5228
|
-
let response;
|
|
5229
|
-
try {
|
|
5230
|
-
response = await fetch(target, { headers: { cookie } });
|
|
5231
|
-
} catch (error) {
|
|
5232
|
-
throw new CliError(
|
|
5233
|
-
"SERVER_UNREACHABLE",
|
|
5234
|
-
`\u65E0\u6CD5\u8FDE\u63A5\u5E73\u53F0 ${server}\uFF1A${error instanceof Error ? error.message : String(error)}`
|
|
5235
|
-
);
|
|
5236
|
-
}
|
|
5237
|
-
if (response.status < 200 || response.status >= 300) {
|
|
5238
|
-
throw await envelopeError(response, fallbackCode, await parseBody(response));
|
|
5239
|
-
}
|
|
5240
|
-
return response;
|
|
5241
|
-
};
|
|
5242
|
-
return { server, cookie, request, upload, download };
|
|
5243
|
-
}
|
|
5244
|
-
async function resolveSlug(cwd, slug) {
|
|
5245
|
-
if (slug !== void 0 && slug.length > 0) return slug;
|
|
5246
|
-
const config = await loadConfig(cwd);
|
|
5247
|
-
return config.name;
|
|
5248
|
-
}
|
|
5249
|
-
var init_client = __esm({
|
|
5250
|
-
"packages/cli/src/client.ts"() {
|
|
5251
|
-
"use strict";
|
|
5252
|
-
init_auth();
|
|
5253
|
-
init_credentials();
|
|
5254
|
-
init_dev();
|
|
5255
|
-
}
|
|
5256
|
-
});
|
|
5257
|
-
|
|
5258
|
-
// packages/cli/src/db.ts
|
|
5259
|
-
var db_exports = {};
|
|
5260
|
-
__export(db_exports, {
|
|
5261
|
-
dbExec: () => dbExec,
|
|
5262
|
-
dbMigrate: () => dbMigrate,
|
|
5263
|
-
dbRollback: () => dbRollback,
|
|
5264
|
-
dbSnapshotCreate: () => dbSnapshotCreate,
|
|
5265
|
-
dbSnapshotList: () => dbSnapshotList,
|
|
5266
|
-
dbSnapshotRestore: () => dbSnapshotRestore,
|
|
5267
|
-
dbStart: () => dbStart,
|
|
5268
|
-
dbStatus: () => dbStatus,
|
|
5269
|
-
dbStop: () => dbStop,
|
|
5270
|
-
splitSqlStatements: () => splitSqlStatements
|
|
5271
|
-
});
|
|
5272
|
-
import { readFile as readFile10 } from "node:fs/promises";
|
|
5273
|
-
import { resolve as resolve5 } from "node:path";
|
|
5274
|
-
async function open2(paths, options) {
|
|
5275
|
-
const client = await createClient(paths);
|
|
5276
|
-
const project2 = await resolveSlug(resolve5(options.cwd), options.slug);
|
|
5277
|
-
return { client, project: project2 };
|
|
5278
|
-
}
|
|
5279
|
-
async function dbStart(paths, options) {
|
|
5280
|
-
const { client, project: project2 } = await open2(paths, options);
|
|
5281
|
-
return client.request(`/api/v1/projects/${project2}/database`, { method: "POST" });
|
|
5282
|
-
}
|
|
5283
|
-
async function dbStatus(paths, options) {
|
|
5284
|
-
const { client, project: project2 } = await open2(paths, options);
|
|
5285
|
-
return client.request(`/api/v1/projects/${project2}/database`);
|
|
5286
|
-
}
|
|
5287
|
-
async function dbStop(paths, options) {
|
|
5288
|
-
const { client, project: project2 } = await open2(paths, options);
|
|
5289
|
-
return client.request(`/api/v1/projects/${project2}/database`, {
|
|
5290
|
-
method: "DELETE"
|
|
5291
|
-
});
|
|
5292
|
-
}
|
|
5293
|
-
async function dbExec(paths, options) {
|
|
5294
|
-
const { client, project: project2 } = await open2(paths, options);
|
|
5295
|
-
return client.request(
|
|
5296
|
-
`/api/v1/projects/${project2}/database/console/sql`,
|
|
5297
|
-
{
|
|
5298
|
-
method: "POST",
|
|
5299
|
-
body: {
|
|
5300
|
-
sql: options.sql,
|
|
5301
|
-
...options.params === void 0 ? {} : { params: options.params },
|
|
5302
|
-
...options.confirmTable === void 0 ? {} : { confirmTable: options.confirmTable }
|
|
5303
|
-
}
|
|
5304
|
-
},
|
|
5305
|
-
"SQL_EXEC_FAILED"
|
|
5306
|
-
);
|
|
5307
|
-
}
|
|
5308
|
-
async function dbSnapshotList(paths, options) {
|
|
5309
|
-
const { client, project: project2 } = await open2(paths, options);
|
|
5310
|
-
return client.request(
|
|
5311
|
-
`/api/v1/projects/${project2}/database/snapshots`
|
|
5312
|
-
);
|
|
5313
|
-
}
|
|
5314
|
-
async function dbSnapshotCreate(paths, options) {
|
|
5315
|
-
const { client, project: project2 } = await open2(paths, options);
|
|
5316
|
-
return client.request(`/api/v1/projects/${project2}/database/snapshots`, {
|
|
5317
|
-
method: "POST"
|
|
5318
|
-
});
|
|
5319
|
-
}
|
|
5320
|
-
async function dbSnapshotRestore(paths, options) {
|
|
5321
|
-
const { client, project: project2 } = await open2(paths, options);
|
|
5322
|
-
return client.request(
|
|
5323
|
-
`/api/v1/projects/${project2}/database/snapshots/${options.snapshotId}/restore`,
|
|
5324
|
-
{ method: "POST" }
|
|
5325
|
-
);
|
|
5326
|
-
}
|
|
5327
|
-
async function dbRollback(paths, options) {
|
|
5328
|
-
const { client, project: project2 } = await open2(paths, options);
|
|
5329
|
-
return client.request(
|
|
5330
|
-
`/api/v1/projects/${project2}/database/rollback`,
|
|
5331
|
-
{ method: "POST", body: { to: options.to } }
|
|
5332
|
-
);
|
|
5333
|
-
}
|
|
5334
|
-
function splitSqlStatements(source) {
|
|
5335
|
-
const statements = [];
|
|
5336
|
-
let buffer = "";
|
|
5337
|
-
let inQuote = false;
|
|
5338
|
-
const lines = source.split("\n");
|
|
5339
|
-
for (const rawLine of lines) {
|
|
5340
|
-
const trimmed = rawLine.trim();
|
|
5341
|
-
if (trimmed.length === 0 || trimmed.startsWith("--")) continue;
|
|
5342
|
-
for (let i = 0; i < rawLine.length; i++) {
|
|
5343
|
-
const ch = rawLine[i];
|
|
5344
|
-
if (inQuote) {
|
|
5345
|
-
if (ch === "'") {
|
|
5346
|
-
if (rawLine[i + 1] === "'") {
|
|
5347
|
-
buffer += ch + rawLine[i + 1];
|
|
5348
|
-
i++;
|
|
5349
|
-
continue;
|
|
5350
|
-
}
|
|
5351
|
-
inQuote = false;
|
|
5352
|
-
}
|
|
5353
|
-
buffer += ch;
|
|
5354
|
-
continue;
|
|
5355
|
-
}
|
|
5356
|
-
if (ch === "'") {
|
|
5357
|
-
inQuote = true;
|
|
5358
|
-
buffer += ch;
|
|
5359
|
-
continue;
|
|
5360
|
-
}
|
|
5361
|
-
if (ch === "-" && rawLine[i + 1] === "-") break;
|
|
5362
|
-
if (ch === ";") {
|
|
5363
|
-
const statement = buffer.trim();
|
|
5364
|
-
if (statement.length > 0) statements.push(statement);
|
|
5365
|
-
buffer = "";
|
|
5366
|
-
continue;
|
|
5367
|
-
}
|
|
5368
|
-
buffer += ch;
|
|
5369
|
-
}
|
|
5370
|
-
buffer += " ";
|
|
5371
|
-
}
|
|
5372
|
-
if (inQuote) {
|
|
5373
|
-
throw new Error(`SQL \u8FC1\u79FB\u6587\u4EF6\u5F15\u53F7\u672A\u95ED\u5408\uFF1A${buffer.trim().slice(0, 80)}\u2026`);
|
|
5374
|
-
}
|
|
5375
|
-
const tail = buffer.trim();
|
|
5376
|
-
if (tail.length > 0) statements.push(tail);
|
|
5377
|
-
return statements;
|
|
5378
|
-
}
|
|
5379
|
-
async function dbMigrate(paths, options) {
|
|
5380
|
-
const source = await readFile10(resolve5(options.file), "utf8");
|
|
5381
|
-
const statements = splitSqlStatements(source);
|
|
5382
|
-
if (statements.length === 0) {
|
|
5383
|
-
throw new Error(`\u8FC1\u79FB\u6587\u4EF6\u6CA1\u6709\u53EF\u6267\u884C\u8BED\u53E5\uFF1A${options.file}`);
|
|
5384
|
-
}
|
|
5385
|
-
const { project: project2 } = await open2(paths, options);
|
|
5386
|
-
const applied = [];
|
|
5387
|
-
const changes = [];
|
|
5388
|
-
for (const statement of statements) {
|
|
5389
|
-
try {
|
|
5390
|
-
const result = await dbExec(paths, {
|
|
5391
|
-
cwd: options.cwd,
|
|
5392
|
-
...options.slug === void 0 ? {} : { slug: options.slug },
|
|
5393
|
-
sql: statement
|
|
5394
|
-
});
|
|
5395
|
-
applied.push(statement);
|
|
5396
|
-
changes.push(result.changes);
|
|
5397
|
-
} catch (error) {
|
|
5398
|
-
const code = error instanceof CliError ? error.code : "MIGRATE_FAILED";
|
|
5399
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
5400
|
-
return {
|
|
5401
|
-
projectId: project2,
|
|
5402
|
-
applied,
|
|
5403
|
-
changes,
|
|
5404
|
-
failed: { statement, code, message }
|
|
5405
|
-
};
|
|
5406
|
-
}
|
|
5407
|
-
}
|
|
5408
|
-
return { projectId: project2, applied, changes };
|
|
5409
|
-
}
|
|
5410
|
-
var init_db2 = __esm({
|
|
5411
|
-
"packages/cli/src/db.ts"() {
|
|
5412
|
-
"use strict";
|
|
5413
|
-
init_auth();
|
|
5414
|
-
init_client();
|
|
5415
|
-
}
|
|
5416
|
-
});
|
|
5417
|
-
|
|
5418
5685
|
// packages/cli/src/serve/banner.ts
|
|
5419
5686
|
function isLoopback(host) {
|
|
5420
5687
|
return host === "127.0.0.1" || host === "localhost" || host === "::1" || host === "[::1]";
|
|
@@ -5483,135 +5750,6 @@ var init_banner = __esm({
|
|
|
5483
5750
|
}
|
|
5484
5751
|
});
|
|
5485
5752
|
|
|
5486
|
-
// packages/cli/src/serve/db-mode.ts
|
|
5487
|
-
import { resolve as resolve6 } from "node:path";
|
|
5488
|
-
function isServeDbMode(value) {
|
|
5489
|
-
return SERVE_DB_MODES.includes(value.trim().toLowerCase());
|
|
5490
|
-
}
|
|
5491
|
-
function parseServeDbMode(raw, source) {
|
|
5492
|
-
const value = raw.trim().toLowerCase();
|
|
5493
|
-
if (!isServeDbMode(value)) {
|
|
5494
|
-
throw new Error(
|
|
5495
|
-
`${source} \u7684\u6570\u636E\u5E93\u6A21\u5F0F "${raw}" \u65E0\u6548\uFF1A\u53EA\u652F\u6301 ${SERVE_DB_MODES.join(" | ")}\uFF08sim = \u5185\u7F6E\u6A21\u62DF\u5F15\u64CE\u4E0E .adep/sim/db.json\uFF1Bsqlite = \u771F\u5B9E SQLite \u5E93\u6587\u4EF6\uFF09`
|
|
5496
|
-
);
|
|
5497
|
-
}
|
|
5498
|
-
return value;
|
|
5499
|
-
}
|
|
5500
|
-
function resolveServeDbMode(explicit) {
|
|
5501
|
-
if (explicit !== void 0) return parseServeDbMode(explicit, "--db");
|
|
5502
|
-
const fromEnv = process.env["ADEP_SERVE_DB"];
|
|
5503
|
-
if (fromEnv !== void 0 && fromEnv.trim() !== "") {
|
|
5504
|
-
return parseServeDbMode(fromEnv, "ADEP_SERVE_DB");
|
|
5505
|
-
}
|
|
5506
|
-
return DEFAULT_SERVE_DB_MODE;
|
|
5507
|
-
}
|
|
5508
|
-
function resolveServeDbFile(cwd, explicit) {
|
|
5509
|
-
const raw = explicit ?? envDbFile() ?? DEFAULT_SQLITE_DB_FILE;
|
|
5510
|
-
return raw === ":memory:" ? raw : resolve6(cwd, raw);
|
|
5511
|
-
}
|
|
5512
|
-
function envDbFile() {
|
|
5513
|
-
const raw = process.env["ADEP_SERVE_DB_FILE"];
|
|
5514
|
-
return raw === void 0 || raw.trim() === "" ? void 0 : raw.trim();
|
|
5515
|
-
}
|
|
5516
|
-
var SERVE_DB_MODES, DEFAULT_SERVE_DB_MODE, DEFAULT_SQLITE_DB_FILE;
|
|
5517
|
-
var init_db_mode = __esm({
|
|
5518
|
-
"packages/cli/src/serve/db-mode.ts"() {
|
|
5519
|
-
"use strict";
|
|
5520
|
-
SERVE_DB_MODES = ["sim", "sqlite"];
|
|
5521
|
-
DEFAULT_SERVE_DB_MODE = "sqlite";
|
|
5522
|
-
DEFAULT_SQLITE_DB_FILE = ".adep/data/project.sqlite";
|
|
5523
|
-
}
|
|
5524
|
-
});
|
|
5525
|
-
|
|
5526
|
-
// packages/cli/src/serve/sqlite-driver.ts
|
|
5527
|
-
import { mkdir as mkdir8 } from "node:fs/promises";
|
|
5528
|
-
import { dirname as dirname8, resolve as resolve7 } from "node:path";
|
|
5529
|
-
function isBun(versions) {
|
|
5530
|
-
return versions["bun"] !== void 0 && versions["bun"] !== "";
|
|
5531
|
-
}
|
|
5532
|
-
function detectSqliteRuntime(versions = process.versions) {
|
|
5533
|
-
if (isBun(versions)) return "bun";
|
|
5534
|
-
const raw = versions["node"];
|
|
5535
|
-
if (raw === void 0) return null;
|
|
5536
|
-
const [majorText, minorText] = raw.split(".");
|
|
5537
|
-
const major = Number(majorText);
|
|
5538
|
-
const minor = Number(minorText ?? "0");
|
|
5539
|
-
if (!Number.isInteger(major) || !Number.isInteger(minor)) return null;
|
|
5540
|
-
if (major > NODE_SQLITE_MIN.major) return "node";
|
|
5541
|
-
if (major === NODE_SQLITE_MIN.major && minor >= NODE_SQLITE_MIN.minor) return "node";
|
|
5542
|
-
return null;
|
|
5543
|
-
}
|
|
5544
|
-
function sqliteModuleName(runtime) {
|
|
5545
|
-
return runtime === "bun" ? "bun:sqlite" : "node:sqlite";
|
|
5546
|
-
}
|
|
5547
|
-
function sqliteUnavailableReason(versions = process.versions) {
|
|
5548
|
-
const current = isBun(versions) ? `Bun ${versions["bun"] ?? ""}`.trim() : `Node ${versions["node"] ?? "\u672A\u77E5"}`;
|
|
5549
|
-
return `\u5F53\u524D\u8FD0\u884C\u65F6 ${current} \u4E0D\u63D0\u4F9B SQLite \u5185\u5EFA\u6A21\u5757\uFF08\u9700\u8981 Bun \u6216 Node \u2265 ${NODE_SQLITE_MIN.major}.${NODE_SQLITE_MIN.minor}\uFF09`;
|
|
5550
|
-
}
|
|
5551
|
-
function sqliteRuntimeRequirementMessage(versions = process.versions) {
|
|
5552
|
-
return `--db sqlite \u9700\u8981 Bun\uFF08\u5185\u7F6E bun:sqlite\uFF09\u6216 Node \u2265 ${NODE_SQLITE_MIN.major}.${NODE_SQLITE_MIN.minor}\uFF08\u5185\u7F6E node:sqlite\uFF09\uFF1B${sqliteUnavailableReason(versions)}\u3002\u8BF7\u6539\u7528 \`--db sim\`\uFF08\u5185\u7F6E\u6A21\u62DF\u5F15\u64CE\uFF0C\u65E0\u9700\u989D\u5916\u8FD0\u884C\u65F6\uFF09\uFF0C\u6216\u5347\u7EA7 Node / \u7528 Bun \u8FD0\u884C\u3002`;
|
|
5553
|
-
}
|
|
5554
|
-
async function openSqliteProjectDriver(file, options = {}) {
|
|
5555
|
-
const runtime = options.runtime ?? detectSqliteRuntime();
|
|
5556
|
-
if (runtime === null) throw new Error(sqliteRuntimeRequirementMessage());
|
|
5557
|
-
const moduleName = sqliteModuleName(runtime);
|
|
5558
|
-
const ctorName = runtime === "bun" ? "Database" : "DatabaseSync";
|
|
5559
|
-
let mod;
|
|
5560
|
-
try {
|
|
5561
|
-
const specifier = moduleName;
|
|
5562
|
-
mod = await import(
|
|
5563
|
-
/* @vite-ignore */
|
|
5564
|
-
specifier
|
|
5565
|
-
);
|
|
5566
|
-
} catch (error) {
|
|
5567
|
-
throw new Error(
|
|
5568
|
-
`${sqliteRuntimeRequirementMessage()}
|
|
5569
|
-
\uFF08\u8F7D\u5165 ${moduleName} \u5931\u8D25\uFF1A${error instanceof Error ? error.message : String(error)}\uFF09`,
|
|
5570
|
-
{ cause: error }
|
|
5571
|
-
);
|
|
5572
|
-
}
|
|
5573
|
-
const Ctor = mod[ctorName];
|
|
5574
|
-
if (Ctor === void 0) {
|
|
5575
|
-
throw new Error(`${moduleName} \u672A\u5BFC\u51FA ${ctorName}\uFF1A\u5F53\u524D\u8FD0\u884C\u65F6\u7684 SQLite \u5185\u5EFA\u6A21\u5757\u4E0D\u53EF\u7528`);
|
|
5576
|
-
}
|
|
5577
|
-
const target = file === ":memory:" ? file : resolve7(file);
|
|
5578
|
-
if (target !== ":memory:") await mkdir8(dirname8(target), { recursive: true });
|
|
5579
|
-
const database = new Ctor(target);
|
|
5580
|
-
database.exec("PRAGMA journal_mode = WAL; PRAGMA foreign_keys = ON;");
|
|
5581
|
-
return {
|
|
5582
|
-
engine: "sqlite",
|
|
5583
|
-
async run(sql, params = []) {
|
|
5584
|
-
if (params.length === 0) {
|
|
5585
|
-
database.exec(sql);
|
|
5586
|
-
return { changes: 0 };
|
|
5587
|
-
}
|
|
5588
|
-
const result = database.prepare(sql).run(...params);
|
|
5589
|
-
return { changes: Number(result.changes) };
|
|
5590
|
-
},
|
|
5591
|
-
async all(sql, params = []) {
|
|
5592
|
-
const statement = database.prepare(sql);
|
|
5593
|
-
statement.setReturnArrays?.(false);
|
|
5594
|
-
return statement.all(...params);
|
|
5595
|
-
},
|
|
5596
|
-
async get(sql, params = []) {
|
|
5597
|
-
const statement = database.prepare(sql);
|
|
5598
|
-
statement.setReturnArrays?.(false);
|
|
5599
|
-
const row = statement.get(...params);
|
|
5600
|
-
return row ?? null;
|
|
5601
|
-
},
|
|
5602
|
-
async close() {
|
|
5603
|
-
database.close();
|
|
5604
|
-
}
|
|
5605
|
-
};
|
|
5606
|
-
}
|
|
5607
|
-
var NODE_SQLITE_MIN;
|
|
5608
|
-
var init_sqlite_driver = __esm({
|
|
5609
|
-
"packages/cli/src/serve/sqlite-driver.ts"() {
|
|
5610
|
-
"use strict";
|
|
5611
|
-
NODE_SQLITE_MIN = { major: 22, minor: 5 };
|
|
5612
|
-
}
|
|
5613
|
-
});
|
|
5614
|
-
|
|
5615
5753
|
// packages/cli/src/serve/server.ts
|
|
5616
5754
|
var server_exports = {};
|
|
5617
5755
|
__export(server_exports, {
|
|
@@ -5621,8 +5759,8 @@ __export(server_exports, {
|
|
|
5621
5759
|
});
|
|
5622
5760
|
import { createServer as createServer2 } from "node:http";
|
|
5623
5761
|
import { watch as watch2 } from "node:fs";
|
|
5624
|
-
import { mkdir as mkdir9, readFile as
|
|
5625
|
-
import { extname, join as
|
|
5762
|
+
import { mkdir as mkdir9, readFile as readFile12, stat as stat7 } from "node:fs/promises";
|
|
5763
|
+
import { extname, join as join15, relative as relative3, resolve as resolve8 } from "node:path";
|
|
5626
5764
|
function envNumber(name) {
|
|
5627
5765
|
const raw = process.env[name];
|
|
5628
5766
|
if (raw === void 0 || raw.trim() === "") return void 0;
|
|
@@ -5640,11 +5778,6 @@ function contentTypeFor(path) {
|
|
|
5640
5778
|
const ext = path.slice(path.lastIndexOf(".")).toLowerCase();
|
|
5641
5779
|
return MIME_TYPES[ext] ?? "application/octet-stream";
|
|
5642
5780
|
}
|
|
5643
|
-
function displayPath(cwd, target) {
|
|
5644
|
-
if (target === ":memory:") return target;
|
|
5645
|
-
const rel = relative2(cwd, target);
|
|
5646
|
-
return rel.startsWith("..") ? target : rel;
|
|
5647
|
-
}
|
|
5648
5781
|
async function startServeServer(options) {
|
|
5649
5782
|
const cwd = resolve8(options.cwd);
|
|
5650
5783
|
const log = options.log ?? ((line) => process.stdout.write(`${line}
|
|
@@ -5655,10 +5788,12 @@ async function startServeServer(options) {
|
|
|
5655
5788
|
cwd,
|
|
5656
5789
|
options.staticDir ?? envString("ADEP_SERVE_STATIC_DIR") ?? "public"
|
|
5657
5790
|
);
|
|
5658
|
-
|
|
5659
|
-
|
|
5791
|
+
const dbTarget = resolveLocalDbTarget(cwd, {
|
|
5792
|
+
...options.db === void 0 ? {} : { db: options.db },
|
|
5793
|
+
...options.dbFile === void 0 ? {} : { dbFile: options.dbFile }
|
|
5794
|
+
});
|
|
5660
5795
|
const config = await loadConfig(cwd);
|
|
5661
|
-
const functionsDir =
|
|
5796
|
+
const functionsDir = join15(cwd, config.functionsDir);
|
|
5662
5797
|
const bearerUser = bearerUserResolverFromEnv();
|
|
5663
5798
|
let hasStatic = false;
|
|
5664
5799
|
try {
|
|
@@ -5670,76 +5805,28 @@ async function startServeServer(options) {
|
|
|
5670
5805
|
const loadFunctionFiles = async () => mergeSharedIntoFunctions(await collectFunctions(functionsDir));
|
|
5671
5806
|
let files = await loadFunctionFiles();
|
|
5672
5807
|
let functionNames = listFunctionNames(files);
|
|
5673
|
-
const envText = await
|
|
5808
|
+
const envText = await readFile12(join15(cwd, ".env.local"), "utf8").catch(() => "");
|
|
5674
5809
|
let env = parseEnvFile(envText);
|
|
5675
5810
|
let simEnv = await loadSimEnv(cwd).catch(() => ({}));
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
if (runtimeName === null) {
|
|
5681
|
-
log(
|
|
5682
|
-
`[serve] \u8B66\u544A\uFF1A${sqliteUnavailableReason()}\uFF0C\u5DF2\u81EA\u52A8\u964D\u7EA7\u4E3A sim \u6A21\u5F0F\uFF08\u5185\u7F6E\u6A21\u62DF\u5F15\u64CE\uFF0C\u5E93 ${displayPath(cwd, join14(simDir(cwd), "db.json"))}\uFF09\u3002\u5982\u9700\u771F\u5B9E SQLite\uFF0C\u8BF7\u7528 Bun \u6216\u5347\u7EA7 Node \u540E\u91CD\u8BD5\u3002`
|
|
5683
|
-
);
|
|
5684
|
-
dbMode = "sim";
|
|
5685
|
-
sqliteFile = null;
|
|
5686
|
-
} else {
|
|
5687
|
-
sqliteModule = sqliteModuleName(runtimeName);
|
|
5688
|
-
try {
|
|
5689
|
-
sqliteDriver = await openSqliteProjectDriver(sqliteFile, { runtime: runtimeName });
|
|
5690
|
-
} catch (error) {
|
|
5691
|
-
const detail = error instanceof Error ? error.message : String(error);
|
|
5692
|
-
log(
|
|
5693
|
-
`[serve] \u8B66\u544A\uFF1A\u6253\u5F00 SQLite \u5E93\u5931\u8D25\uFF08${detail}\uFF09\uFF0C\u5DF2\u81EA\u52A8\u964D\u7EA7\u4E3A sim \u6A21\u5F0F\uFF08\u5185\u7F6E\u6A21\u62DF\u5F15\u64CE\uFF0C\u5E93 ${displayPath(cwd, join14(simDir(cwd), "db.json"))}\uFF09\u3002`
|
|
5694
|
-
);
|
|
5695
|
-
sqliteModule = null;
|
|
5696
|
-
sqliteDriver = null;
|
|
5697
|
-
sqliteFile = null;
|
|
5698
|
-
dbMode = "sim";
|
|
5699
|
-
}
|
|
5700
|
-
}
|
|
5701
|
-
}
|
|
5811
|
+
const db = await openLocalDbDriver(dbTarget, { cwd, tag: "serve", log });
|
|
5812
|
+
const dbMode = db.mode;
|
|
5813
|
+
const sqliteFile = db.file;
|
|
5814
|
+
const sqliteModule = db.module;
|
|
5702
5815
|
const runtime = await createSimRuntime({
|
|
5703
5816
|
cwd,
|
|
5704
5817
|
projectId: "local",
|
|
5705
5818
|
baseUrl: `http://${host}:${port}`,
|
|
5706
5819
|
log,
|
|
5707
|
-
...
|
|
5820
|
+
...db.driver === null ? {} : { driver: db.driver }
|
|
5708
5821
|
});
|
|
5709
5822
|
if (options.schemaFile !== void 0) {
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
|
|
5717
|
-
}
|
|
5718
|
-
);
|
|
5719
|
-
const statements = splitSqlStatements(schemaSource);
|
|
5720
|
-
let applied = 0;
|
|
5721
|
-
let skipped = 0;
|
|
5722
|
-
for (const [index, statement] of statements.entries()) {
|
|
5723
|
-
try {
|
|
5724
|
-
await runtime.db.driver.run(statement);
|
|
5725
|
-
applied += 1;
|
|
5726
|
-
} catch (error) {
|
|
5727
|
-
const isUnsupported = error instanceof Error && "code" in error && error.code === "DB_UNSAFE_OP";
|
|
5728
|
-
if (dbMode === "sim" && isUnsupported) {
|
|
5729
|
-
skipped += 1;
|
|
5730
|
-
log(`[serve] \u8DF3\u8FC7 schema \u8BED\u53E5\uFF08sim \u5F15\u64CE\u4E0D\u652F\u6301\uFF09\uFF1A${statement.slice(0, 60)}\u2026`);
|
|
5731
|
-
continue;
|
|
5732
|
-
}
|
|
5733
|
-
const detail = error instanceof Error ? error.message : String(error);
|
|
5734
|
-
throw new Error(
|
|
5735
|
-
`schema \u8BED\u53E5\u6267\u884C\u5931\u8D25\uFF08--schema ${options.schemaFile}\uFF0C\u7B2C ${index + 1} \u6761\uFF0Cdb \u6A21\u5F0F ${dbMode}\uFF09\uFF1A${detail}
|
|
5736
|
-
\u8BED\u53E5\uFF1A${statement.slice(0, 200)}` + (dbMode === "sqlite" ? "\n\uFF08sqlite \u6A21\u5F0F\u4E0D\u505A\u8BED\u53E5\u8DF3\u8FC7\uFF1B\u5982\u9700\u8DF3\u8FC7\u8BED\u4E49\u8BF7\u6539\u7528 --db sim\uFF09" : ""),
|
|
5737
|
-
{ cause: error }
|
|
5738
|
-
);
|
|
5739
|
-
}
|
|
5740
|
-
}
|
|
5741
|
-
const skipNote = skipped > 0 ? `\uFF0C\u8DF3\u8FC7 ${skipped} \u6761` : "";
|
|
5742
|
-
log(`[serve] \u5DF2\u5E94\u7528\u6570\u636E\u5E93\u7ED3\u6784\uFF08--schema ${options.schemaFile}\uFF09\uFF1A${applied} \u6761\u8BED\u53E5${skipNote}`);
|
|
5823
|
+
await applyLocalSchema(runtime.db.driver, {
|
|
5824
|
+
cwd,
|
|
5825
|
+
schemaFile: options.schemaFile,
|
|
5826
|
+
mode: dbMode,
|
|
5827
|
+
tag: "serve",
|
|
5828
|
+
log
|
|
5829
|
+
});
|
|
5743
5830
|
}
|
|
5744
5831
|
const executor = new WorkerFunctionExecutor({
|
|
5745
5832
|
deps: { rootDir: cwd, builtin: LOCAL_BUILTIN_DEPS }
|
|
@@ -5751,7 +5838,7 @@ async function startServeServer(options) {
|
|
|
5751
5838
|
const reload = async () => {
|
|
5752
5839
|
const [nextFiles, envLocalText] = await Promise.all([
|
|
5753
5840
|
loadFunctionFiles(),
|
|
5754
|
-
|
|
5841
|
+
readFile12(join15(cwd, ".env.local"), "utf8").catch(() => "")
|
|
5755
5842
|
]);
|
|
5756
5843
|
files = nextFiles;
|
|
5757
5844
|
env = parseEnvFile(envLocalText);
|
|
@@ -5806,16 +5893,16 @@ async function startServeServer(options) {
|
|
|
5806
5893
|
const serveStatic = async (pathname, res) => {
|
|
5807
5894
|
if (!hasStatic) return false;
|
|
5808
5895
|
const safePath = pathname.replace(/\.\.\//g, "").replace(/^\//, "");
|
|
5809
|
-
const filePath =
|
|
5810
|
-
const resolvedPath = safePath === "" || safePath === "/" ?
|
|
5896
|
+
const filePath = join15(staticDir, safePath);
|
|
5897
|
+
const resolvedPath = safePath === "" || safePath === "/" ? join15(filePath, "index.html") : filePath;
|
|
5811
5898
|
try {
|
|
5812
5899
|
const fileStat = await stat7(resolvedPath);
|
|
5813
5900
|
if (fileStat.isDirectory()) {
|
|
5814
|
-
const indexPath =
|
|
5901
|
+
const indexPath = join15(resolvedPath, "index.html");
|
|
5815
5902
|
try {
|
|
5816
5903
|
const indexStat = await stat7(indexPath);
|
|
5817
5904
|
if (indexStat.isFile()) {
|
|
5818
|
-
const content2 = await
|
|
5905
|
+
const content2 = await readFile12(indexPath);
|
|
5819
5906
|
res.writeHead(200, { "content-type": contentTypeFor(indexPath) });
|
|
5820
5907
|
res.end(content2);
|
|
5821
5908
|
return true;
|
|
@@ -5824,7 +5911,7 @@ async function startServeServer(options) {
|
|
|
5824
5911
|
}
|
|
5825
5912
|
return false;
|
|
5826
5913
|
}
|
|
5827
|
-
const content = await
|
|
5914
|
+
const content = await readFile12(resolvedPath);
|
|
5828
5915
|
res.writeHead(200, { "content-type": contentTypeFor(resolvedPath) });
|
|
5829
5916
|
res.end(content);
|
|
5830
5917
|
return true;
|
|
@@ -5833,7 +5920,7 @@ async function startServeServer(options) {
|
|
|
5833
5920
|
const ext = extname(pathname);
|
|
5834
5921
|
if (ext === "" || ext === ".html") {
|
|
5835
5922
|
try {
|
|
5836
|
-
const indexContent = await
|
|
5923
|
+
const indexContent = await readFile12(join15(staticDir, "index.html"));
|
|
5837
5924
|
res.writeHead(200, { "content-type": "text/html; charset=utf-8" });
|
|
5838
5925
|
res.end(indexContent);
|
|
5839
5926
|
return true;
|
|
@@ -5844,9 +5931,66 @@ async function startServeServer(options) {
|
|
|
5844
5931
|
return false;
|
|
5845
5932
|
}
|
|
5846
5933
|
};
|
|
5934
|
+
const serveSignedFile = async (req, res, url, projectId, path) => {
|
|
5935
|
+
const driver = runtime.storage.driver;
|
|
5936
|
+
try {
|
|
5937
|
+
const meta = await driver.getMeta(projectId, path);
|
|
5938
|
+
if (meta.visibility === "private") {
|
|
5939
|
+
const verification = verifyDownloadSignature(
|
|
5940
|
+
{ secret: SIM_SIGN_SECRET, baseUrl: "" },
|
|
5941
|
+
projectId,
|
|
5942
|
+
path,
|
|
5943
|
+
{
|
|
5944
|
+
expires: url.searchParams.get(SIGN_EXPIRES_KEY) ?? void 0,
|
|
5945
|
+
signature: url.searchParams.get(SIGN_SIGNATURE_KEY) ?? void 0
|
|
5946
|
+
}
|
|
5947
|
+
);
|
|
5948
|
+
if (!verification.ok) {
|
|
5949
|
+
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";
|
|
5950
|
+
writeJson(res, 403, { error: { code: "STORAGE_SIGNATURE_INVALID", message } });
|
|
5951
|
+
log(`[serve] ${req.method ?? "GET"} ${url.pathname} -> 403 (${verification.reason})`);
|
|
5952
|
+
return true;
|
|
5953
|
+
}
|
|
5954
|
+
}
|
|
5955
|
+
const { data } = await driver.get(projectId, path);
|
|
5956
|
+
res.writeHead(200, {
|
|
5957
|
+
"content-type": meta.contentType ?? "application/octet-stream",
|
|
5958
|
+
"content-length": String(meta.size),
|
|
5959
|
+
"cache-control": meta.visibility === "public" ? "public, max-age=3600" : "private, no-store"
|
|
5960
|
+
});
|
|
5961
|
+
res.end(data);
|
|
5962
|
+
log(`[serve] ${req.method ?? "GET"} ${url.pathname} -> 200\uFF08\u6587\u4EF6\u4E0B\u8F7D ${meta.size}B\uFF09`);
|
|
5963
|
+
} catch (error) {
|
|
5964
|
+
if (error instanceof StorageError) {
|
|
5965
|
+
writeJson(res, error.status, { error: { code: error.code, message: error.message } });
|
|
5966
|
+
log(`[serve] ${req.method ?? "GET"} ${url.pathname} -> ${error.status} (${error.code})`);
|
|
5967
|
+
return true;
|
|
5968
|
+
}
|
|
5969
|
+
writeJson(res, 500, {
|
|
5970
|
+
error: {
|
|
5971
|
+
code: "FILE_DOWNLOAD_ERROR",
|
|
5972
|
+
message: error instanceof Error ? error.message : "\u6587\u4EF6\u4E0B\u8F7D\u5931\u8D25"
|
|
5973
|
+
}
|
|
5974
|
+
});
|
|
5975
|
+
log(`[serve] ${req.method ?? "GET"} ${url.pathname} -> 500\uFF08\u6587\u4EF6\u4E0B\u8F7D\u5F02\u5E38\uFF09`);
|
|
5976
|
+
}
|
|
5977
|
+
return true;
|
|
5978
|
+
};
|
|
5979
|
+
const SIGNED_FILES_ROUTE = /^\/api\/v1\/projects\/([^/]+)\/files\/([^/]+)$/;
|
|
5847
5980
|
const handle = async (req, res) => {
|
|
5848
5981
|
const url = new URL(req.url ?? "/", `http://${host}:${port}`);
|
|
5849
5982
|
const pathname = url.pathname;
|
|
5983
|
+
const filesMatch = SIGNED_FILES_ROUTE.exec(pathname);
|
|
5984
|
+
if (filesMatch !== null && (req.method === "GET" || req.method === "HEAD")) {
|
|
5985
|
+
await serveSignedFile(
|
|
5986
|
+
req,
|
|
5987
|
+
res,
|
|
5988
|
+
url,
|
|
5989
|
+
decodeURIComponent(filesMatch[1]),
|
|
5990
|
+
decodeURIComponent(filesMatch[2])
|
|
5991
|
+
);
|
|
5992
|
+
return;
|
|
5993
|
+
}
|
|
5850
5994
|
const normalizedPrefix = config.functionsPrefix.replace(/^\/+|\/+$/g, "");
|
|
5851
5995
|
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
5996
|
if (fnRest !== null) {
|
|
@@ -5921,7 +6065,7 @@ async function startServeServer(options) {
|
|
|
5921
6065
|
functions: functionNames,
|
|
5922
6066
|
static: hasStatic,
|
|
5923
6067
|
// CLI-020:当前数据面(换模式即换库,这里让脚本/e2e 有可断言的读数)。
|
|
5924
|
-
db: sqliteFile === null ? { mode: "sim", file:
|
|
6068
|
+
db: sqliteFile === null ? { mode: "sim", file: simDbTarget(cwd) } : { mode: "sqlite", file: displayPath(cwd, sqliteFile), driver: sqliteModule },
|
|
5925
6069
|
endpoints: {
|
|
5926
6070
|
functions: "/api/{fn}",
|
|
5927
6071
|
static: `/ \u2192 ${staticDir}`,
|
|
@@ -5960,9 +6104,9 @@ async function startServeServer(options) {
|
|
|
5960
6104
|
functions: functionNames,
|
|
5961
6105
|
functionsPrefix: config.functionsPrefix,
|
|
5962
6106
|
hasStatic,
|
|
5963
|
-
staticDir:
|
|
6107
|
+
staticDir: relative3(cwd, staticDir).length > 0 ? relative3(cwd, staticDir) : staticDir,
|
|
5964
6108
|
dbMode,
|
|
5965
|
-
dbTarget: sqliteFile === null ?
|
|
6109
|
+
dbTarget: sqliteFile === null ? simDbTarget(cwd) : displayPath(cwd, sqliteFile),
|
|
5966
6110
|
...sqliteModule === null ? {} : { dbDriver: sqliteModule }
|
|
5967
6111
|
});
|
|
5968
6112
|
log(banner);
|
|
@@ -5994,15 +6138,16 @@ var init_server = __esm({
|
|
|
5994
6138
|
init_executor();
|
|
5995
6139
|
init_http_envelope();
|
|
5996
6140
|
init_worker_executor();
|
|
6141
|
+
init_signature();
|
|
6142
|
+
init_driver();
|
|
5997
6143
|
init_builtin_deps2();
|
|
5998
|
-
init_db2();
|
|
5999
6144
|
init_runtime();
|
|
6145
|
+
init_storage();
|
|
6000
6146
|
init_env();
|
|
6001
6147
|
init_invoke();
|
|
6002
6148
|
init_dev();
|
|
6003
6149
|
init_banner();
|
|
6004
6150
|
init_db_mode();
|
|
6005
|
-
init_sqlite_driver();
|
|
6006
6151
|
init_dev_shared();
|
|
6007
6152
|
MIME_TYPES = {
|
|
6008
6153
|
".html": "text/html; charset=utf-8",
|
|
@@ -6037,8 +6182,8 @@ __export(deploy_exports, {
|
|
|
6037
6182
|
deploy: () => deploy
|
|
6038
6183
|
});
|
|
6039
6184
|
import { createHash as createHash2 } from "node:crypto";
|
|
6040
|
-
import { readdir as readdir5, readFile as
|
|
6041
|
-
import { join as
|
|
6185
|
+
import { readdir as readdir5, readFile as readFile13 } from "node:fs/promises";
|
|
6186
|
+
import { join as join16, resolve as resolve9, basename as basename3, relative as relative4, sep } from "node:path";
|
|
6042
6187
|
function functionUrlBase(prefix) {
|
|
6043
6188
|
const raw = (prefix ?? "/api").trim();
|
|
6044
6189
|
const normalized = raw === "/" ? "/" : raw.replace(/\/+$/, "");
|
|
@@ -6064,10 +6209,10 @@ async function collectFunctionFiles(functionsDir) {
|
|
|
6064
6209
|
if (conflicting.length > 0) throw new AmbiguousFunctionError(functionsDir, conflicting);
|
|
6065
6210
|
const out = {};
|
|
6066
6211
|
for (const name of flatNames) {
|
|
6067
|
-
out[name] = { [`${name}.ts`]: await
|
|
6212
|
+
out[name] = { [`${name}.ts`]: await readFile13(join16(functionsDir, `${name}.ts`), "utf8") };
|
|
6068
6213
|
}
|
|
6069
6214
|
for (const name of dirNames) {
|
|
6070
|
-
const files = await collectFunctionDir(
|
|
6215
|
+
const files = await collectFunctionDir(join16(functionsDir, name));
|
|
6071
6216
|
if (files["index.ts"] === void 0) continue;
|
|
6072
6217
|
out[name] = files;
|
|
6073
6218
|
}
|
|
@@ -6086,11 +6231,11 @@ async function collectFunctionDir(absDir) {
|
|
|
6086
6231
|
const rel = prefix === "" ? entry.name : `${prefix}/${entry.name}`;
|
|
6087
6232
|
if (entry.isDirectory()) {
|
|
6088
6233
|
if (entry.name === "__tests__" || IGNORED_DIRS.has(entry.name)) continue;
|
|
6089
|
-
await walk(
|
|
6234
|
+
await walk(join16(dir, entry.name), rel);
|
|
6090
6235
|
continue;
|
|
6091
6236
|
}
|
|
6092
6237
|
if (!isRuntimeSource2(entry.name)) continue;
|
|
6093
|
-
files[rel] = await
|
|
6238
|
+
files[rel] = await readFile13(join16(dir, entry.name), "utf8");
|
|
6094
6239
|
}
|
|
6095
6240
|
};
|
|
6096
6241
|
await walk(absDir, "");
|
|
@@ -6100,7 +6245,7 @@ function sha256Hex(content) {
|
|
|
6100
6245
|
return createHash2("sha256").update(content).digest("hex");
|
|
6101
6246
|
}
|
|
6102
6247
|
async function collectShared(functionsDir) {
|
|
6103
|
-
const sharedDir =
|
|
6248
|
+
const sharedDir = join16(functionsDir, "_shared");
|
|
6104
6249
|
const files = {};
|
|
6105
6250
|
const walk = async (dir) => {
|
|
6106
6251
|
let entries;
|
|
@@ -6112,13 +6257,13 @@ async function collectShared(functionsDir) {
|
|
|
6112
6257
|
for (const entry of entries) {
|
|
6113
6258
|
if (entry.isDirectory()) {
|
|
6114
6259
|
if (entry.name === "__tests__" || entry.name === "node_modules") continue;
|
|
6115
|
-
await walk(
|
|
6260
|
+
await walk(join16(dir, entry.name));
|
|
6116
6261
|
continue;
|
|
6117
6262
|
}
|
|
6118
6263
|
if (!isRuntimeSource2(entry.name)) continue;
|
|
6119
|
-
const full =
|
|
6120
|
-
const rel =
|
|
6121
|
-
files[`${SHARED_SOURCE_ROOT3}${rel}`] = await
|
|
6264
|
+
const full = join16(dir, entry.name);
|
|
6265
|
+
const rel = relative4(sharedDir, full).split(sep).join("/");
|
|
6266
|
+
files[`${SHARED_SOURCE_ROOT3}${rel}`] = await readFile13(full, "utf8");
|
|
6122
6267
|
}
|
|
6123
6268
|
};
|
|
6124
6269
|
await walk(sharedDir);
|
|
@@ -6132,7 +6277,7 @@ async function deploy(paths, options) {
|
|
|
6132
6277
|
const cwd = resolve9(options.cwd);
|
|
6133
6278
|
const config = await loadConfig(cwd);
|
|
6134
6279
|
const slug = options.slug ?? config.name;
|
|
6135
|
-
const functionsDir = options.functionsDir === void 0 ?
|
|
6280
|
+
const functionsDir = options.functionsDir === void 0 ? join16(cwd, config.functionsDir) : resolve9(cwd, options.functionsDir);
|
|
6136
6281
|
const local = await collectFunctionFiles(functionsDir);
|
|
6137
6282
|
if (Object.keys(local).length === 0) {
|
|
6138
6283
|
throw new CliError("NO_FUNCTIONS", `${functionsDir} \u4E0B\u6CA1\u6709\u51FD\u6570\u6587\u4EF6`);
|
|
@@ -6204,7 +6349,12 @@ async function deploy(paths, options) {
|
|
|
6204
6349
|
}
|
|
6205
6350
|
const published = await client.request(
|
|
6206
6351
|
`/api/v1/functions/${functionId}/publish`,
|
|
6207
|
-
{
|
|
6352
|
+
{
|
|
6353
|
+
method: "POST",
|
|
6354
|
+
// FN-013:显式 body 而非省略——`force: false` 与 `undefined` 在服务端语义相同,
|
|
6355
|
+
// 但显式传值让「这次发布是否放行过警告」在请求层面可审计。
|
|
6356
|
+
body: { force: options.force === true }
|
|
6357
|
+
}
|
|
6208
6358
|
);
|
|
6209
6359
|
deployed.push({
|
|
6210
6360
|
name: item.name,
|
|
@@ -6263,8 +6413,8 @@ var frontend_exports = {};
|
|
|
6263
6413
|
__export(frontend_exports, {
|
|
6264
6414
|
frontendSync: () => frontendSync
|
|
6265
6415
|
});
|
|
6266
|
-
import { readdir as readdir6, readFile as
|
|
6267
|
-
import { join as
|
|
6416
|
+
import { readdir as readdir6, readFile as readFile14, stat as stat8 } from "node:fs/promises";
|
|
6417
|
+
import { join as join17, relative as relative5, sep as sep2 } from "node:path";
|
|
6268
6418
|
async function resolveProjectId(client, cwd, slug) {
|
|
6269
6419
|
const resolvedSlug = await resolveSlug(cwd, slug);
|
|
6270
6420
|
const listed = await client.request("/api/v1/projects", {}, "PROJECT_LIST_FAILED");
|
|
@@ -6284,20 +6434,21 @@ async function collectFiles(root, dir) {
|
|
|
6284
6434
|
for (const entry of entries) {
|
|
6285
6435
|
if (entry.isDirectory()) {
|
|
6286
6436
|
if (IGNORED_DIRS2.has(entry.name)) continue;
|
|
6287
|
-
const nested = await collectFiles(root,
|
|
6437
|
+
const nested = await collectFiles(root, join17(dir, entry.name));
|
|
6288
6438
|
for (const [path, content] of nested.files) files.set(path, content);
|
|
6289
6439
|
skipped.push(...nested.skipped);
|
|
6290
6440
|
continue;
|
|
6291
6441
|
}
|
|
6292
|
-
|
|
6293
|
-
const
|
|
6442
|
+
if (IGNORED_FILES.has(entry.name)) continue;
|
|
6443
|
+
const full = join17(dir, entry.name);
|
|
6444
|
+
const rel = relative5(root, full).split(sep2).join("/");
|
|
6294
6445
|
const info = await stat8(full);
|
|
6295
6446
|
if (info.size > 1024 * 1024) {
|
|
6296
6447
|
skipped.push(rel);
|
|
6297
6448
|
continue;
|
|
6298
6449
|
}
|
|
6299
6450
|
try {
|
|
6300
|
-
const content = await
|
|
6451
|
+
const content = await readFile14(full, "utf8");
|
|
6301
6452
|
if (content.includes("\0")) {
|
|
6302
6453
|
skipped.push(rel);
|
|
6303
6454
|
continue;
|
|
@@ -6312,7 +6463,7 @@ async function collectFiles(root, dir) {
|
|
|
6312
6463
|
async function frontendSync(paths, options) {
|
|
6313
6464
|
const log = options.silent === true ? () => void 0 : options.log ?? ((line) => process.stdout.write(`${line}
|
|
6314
6465
|
`));
|
|
6315
|
-
const webDir = options.dir ??
|
|
6466
|
+
const webDir = options.dir ?? join17(options.cwd, "web");
|
|
6316
6467
|
const rootStat = await stat8(webDir).catch(() => null);
|
|
6317
6468
|
if (rootStat === null || !rootStat.isDirectory()) {
|
|
6318
6469
|
throw new CliError(
|
|
@@ -6359,7 +6510,7 @@ async function frontendSync(paths, options) {
|
|
|
6359
6510
|
}
|
|
6360
6511
|
return { projectId: project2.id, uploaded: files.size, skipped, totalBytes };
|
|
6361
6512
|
}
|
|
6362
|
-
var MAX_FILES, MAX_TOTAL_SOURCE_BYTES2, FILE_PATH_PATTERN, IGNORED_DIRS2;
|
|
6513
|
+
var MAX_FILES, MAX_TOTAL_SOURCE_BYTES2, FILE_PATH_PATTERN, IGNORED_DIRS2, IGNORED_FILES;
|
|
6363
6514
|
var init_frontend = __esm({
|
|
6364
6515
|
"packages/cli/src/frontend.ts"() {
|
|
6365
6516
|
"use strict";
|
|
@@ -6370,6 +6521,14 @@ var init_frontend = __esm({
|
|
|
6370
6521
|
MAX_TOTAL_SOURCE_BYTES2 = FRONTEND_DRAFT_MAX_TOTAL_SOURCE_BYTES;
|
|
6371
6522
|
FILE_PATH_PATTERN = FRONTEND_DRAFT_FILE_PATH_PATTERN;
|
|
6372
6523
|
IGNORED_DIRS2 = /* @__PURE__ */ new Set(["node_modules", "dist", ".git", ".adep", ".vite", "coverage"]);
|
|
6524
|
+
IGNORED_FILES = /* @__PURE__ */ new Set([
|
|
6525
|
+
"package-lock.json",
|
|
6526
|
+
"npm-shrinkwrap.json",
|
|
6527
|
+
"yarn.lock",
|
|
6528
|
+
"pnpm-lock.yaml",
|
|
6529
|
+
"bun.lockb",
|
|
6530
|
+
"bun.lock"
|
|
6531
|
+
]);
|
|
6373
6532
|
}
|
|
6374
6533
|
});
|
|
6375
6534
|
|
|
@@ -6526,11 +6685,11 @@ var fs_exports = {};
|
|
|
6526
6685
|
__export(fs_exports, {
|
|
6527
6686
|
createExportFileSystem: () => createExportFileSystem
|
|
6528
6687
|
});
|
|
6529
|
-
import { mkdir as mkdir10, readFile as
|
|
6530
|
-
import { dirname as dirname9, join as
|
|
6688
|
+
import { mkdir as mkdir10, readFile as readFile15, rm as rm3, stat as stat10, writeFile as writeFile8 } from "node:fs/promises";
|
|
6689
|
+
import { dirname as dirname9, join as join19 } from "node:path";
|
|
6531
6690
|
function createExportFileSystem() {
|
|
6532
6691
|
return {
|
|
6533
|
-
readFile: (path) =>
|
|
6692
|
+
readFile: (path) => readFile15(path),
|
|
6534
6693
|
writeFile: (path, content) => writeFile8(path, content),
|
|
6535
6694
|
// 同时用于清理解压临时目录(${zip}.tmp 是个目录)——递归强制删除,缺失不报错。
|
|
6536
6695
|
deleteFile: async (path) => {
|
|
@@ -6548,9 +6707,9 @@ function createExportFileSystem() {
|
|
|
6548
6707
|
await mkdir10(path, { recursive: true });
|
|
6549
6708
|
},
|
|
6550
6709
|
unzip: async (zipPath, targetDir) => {
|
|
6551
|
-
const entries = zipRead(await
|
|
6710
|
+
const entries = zipRead(await readFile15(zipPath));
|
|
6552
6711
|
for (const [name, data] of entries) {
|
|
6553
|
-
const dest =
|
|
6712
|
+
const dest = join19(targetDir, name);
|
|
6554
6713
|
await mkdir10(dirname9(dest), { recursive: true });
|
|
6555
6714
|
await writeFile8(dest, data);
|
|
6556
6715
|
}
|
|
@@ -7068,8 +7227,8 @@ __export(storage_exports, {
|
|
|
7068
7227
|
storageRemove: () => storageRemove,
|
|
7069
7228
|
storageUpload: () => storageUpload
|
|
7070
7229
|
});
|
|
7071
|
-
import { mkdir as mkdir11, readFile as
|
|
7072
|
-
import { basename as basename4, dirname as dirname10, extname as extname2, join as
|
|
7230
|
+
import { mkdir as mkdir11, readFile as readFile16, stat as stat11, writeFile as writeFile9 } from "node:fs/promises";
|
|
7231
|
+
import { basename as basename4, dirname as dirname10, extname as extname2, join as join20, resolve as resolve11 } from "node:path";
|
|
7073
7232
|
async function open3(paths, options) {
|
|
7074
7233
|
const client = await createClient(paths);
|
|
7075
7234
|
const project2 = await resolveSlug(resolve11(options.cwd), options.slug);
|
|
@@ -7111,7 +7270,7 @@ async function storageUpload(paths, options) {
|
|
|
7111
7270
|
throw new CliError("FILE_NOT_FOUND", `\u672C\u5730\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${local}`);
|
|
7112
7271
|
}
|
|
7113
7272
|
const visibility = options.visibility ?? "private";
|
|
7114
|
-
const bytes = await
|
|
7273
|
+
const bytes = await readFile16(local);
|
|
7115
7274
|
const form = new FormData();
|
|
7116
7275
|
form.set("path", options.path);
|
|
7117
7276
|
form.set("visibility", visibility);
|
|
@@ -7152,7 +7311,7 @@ async function storageDownload(paths, options) {
|
|
|
7152
7311
|
const url = await resolveDownloadUrl(client, project2, options.path);
|
|
7153
7312
|
const response = await client.download(url, "STORAGE_DOWNLOAD_FAILED");
|
|
7154
7313
|
const bytes = Buffer.from(await response.arrayBuffer());
|
|
7155
|
-
const output = resolve11(options.output ??
|
|
7314
|
+
const output = resolve11(options.output ?? join20(resolve11(options.cwd), basename4(options.path)));
|
|
7156
7315
|
await mkdir11(dirname10(output), { recursive: true });
|
|
7157
7316
|
await writeFile9(output, bytes);
|
|
7158
7317
|
return { path: options.path, output, size: bytes.length };
|
|
@@ -7172,6 +7331,189 @@ var init_storage2 = __esm({
|
|
|
7172
7331
|
}
|
|
7173
7332
|
});
|
|
7174
7333
|
|
|
7334
|
+
// packages/cli/src/sandbox-scan.ts
|
|
7335
|
+
import { readdir as readdir7, readFile as readFile17 } from "node:fs/promises";
|
|
7336
|
+
import { join as join21, relative as relative6, sep as sep3 } from "node:path";
|
|
7337
|
+
function extractSpecifiers(line) {
|
|
7338
|
+
const out = [];
|
|
7339
|
+
const patterns = [
|
|
7340
|
+
/\bfrom\s+['"]([^'"]+)['"]/g,
|
|
7341
|
+
// import x from '<spec>' / export … from '<spec>'
|
|
7342
|
+
/\brequire\s*\(\s*['"]([^'"]+)['"]\s*\)/g,
|
|
7343
|
+
/\bimport\s*\(\s*['"]([^'"]+)['"]\s*\)/g,
|
|
7344
|
+
/^\s*import\s+['"]([^'"]+)['"]/g
|
|
7345
|
+
// 副作用导入 import '<spec>'
|
|
7346
|
+
];
|
|
7347
|
+
for (const pattern of patterns) {
|
|
7348
|
+
for (const match of line.matchAll(pattern)) {
|
|
7349
|
+
const spec = match[1];
|
|
7350
|
+
if (spec !== void 0) out.push(spec);
|
|
7351
|
+
}
|
|
7352
|
+
}
|
|
7353
|
+
return out;
|
|
7354
|
+
}
|
|
7355
|
+
function classify(specifier) {
|
|
7356
|
+
if (specifier.startsWith("node:")) {
|
|
7357
|
+
const bare = specifier.slice("node:".length);
|
|
7358
|
+
const root = bare.split("/")[0];
|
|
7359
|
+
const suggestion = BUILTIN_SUGGESTIONS[specifier] ?? BUILTIN_SUGGESTIONS[`node:${root}`];
|
|
7360
|
+
return {
|
|
7361
|
+
code: "NODE_BUILTIN",
|
|
7362
|
+
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`}`
|
|
7363
|
+
};
|
|
7364
|
+
}
|
|
7365
|
+
if (NODE_BUILTINS.has(specifier)) {
|
|
7366
|
+
return {
|
|
7367
|
+
code: "NODE_BUILTIN",
|
|
7368
|
+
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`}`
|
|
7369
|
+
};
|
|
7370
|
+
}
|
|
7371
|
+
if (NATIVE_ADDON_PACKAGES.has(specifier)) {
|
|
7372
|
+
return {
|
|
7373
|
+
code: "NATIVE_ADDON",
|
|
7374
|
+
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`
|
|
7375
|
+
};
|
|
7376
|
+
}
|
|
7377
|
+
return null;
|
|
7378
|
+
}
|
|
7379
|
+
async function scanFunctionSources(rootDir, functionsDir) {
|
|
7380
|
+
const base = join21(rootDir, functionsDir);
|
|
7381
|
+
const findings = [];
|
|
7382
|
+
async function walk(current) {
|
|
7383
|
+
let entries;
|
|
7384
|
+
try {
|
|
7385
|
+
entries = await readdir7(current, { withFileTypes: true });
|
|
7386
|
+
} catch {
|
|
7387
|
+
return;
|
|
7388
|
+
}
|
|
7389
|
+
for (const entry of entries) {
|
|
7390
|
+
const abs = join21(current, entry.name);
|
|
7391
|
+
if (entry.isDirectory()) {
|
|
7392
|
+
if (SKIP_DIRS.has(entry.name)) continue;
|
|
7393
|
+
await walk(abs);
|
|
7394
|
+
continue;
|
|
7395
|
+
}
|
|
7396
|
+
if (!entry.isFile()) continue;
|
|
7397
|
+
if (!SOURCE_EXTENSIONS.some((ext) => entry.name.endsWith(ext))) continue;
|
|
7398
|
+
if (entry.name.endsWith(".d.ts")) continue;
|
|
7399
|
+
let content;
|
|
7400
|
+
try {
|
|
7401
|
+
content = await readFile17(abs, "utf8");
|
|
7402
|
+
} catch {
|
|
7403
|
+
continue;
|
|
7404
|
+
}
|
|
7405
|
+
if (content.length > MAX_SCAN_BYTES) continue;
|
|
7406
|
+
const relPath = relative6(rootDir, abs).split(sep3).join("/");
|
|
7407
|
+
const lines = content.split("\n");
|
|
7408
|
+
for (const [index, line] of lines.entries()) {
|
|
7409
|
+
const trimmed = line.trim();
|
|
7410
|
+
if (trimmed.startsWith("//") || trimmed.startsWith("*") || trimmed.startsWith("/*")) continue;
|
|
7411
|
+
for (const specifier of extractSpecifiers(line)) {
|
|
7412
|
+
const hit = classify(specifier);
|
|
7413
|
+
if (hit !== null) {
|
|
7414
|
+
findings.push({
|
|
7415
|
+
file: relPath,
|
|
7416
|
+
line: index + 1,
|
|
7417
|
+
code: hit.code,
|
|
7418
|
+
specifier,
|
|
7419
|
+
message: hit.message
|
|
7420
|
+
});
|
|
7421
|
+
}
|
|
7422
|
+
}
|
|
7423
|
+
}
|
|
7424
|
+
}
|
|
7425
|
+
}
|
|
7426
|
+
await walk(base);
|
|
7427
|
+
return findings;
|
|
7428
|
+
}
|
|
7429
|
+
var NODE_BUILTINS, NATIVE_ADDON_PACKAGES, BUILTIN_SUGGESTIONS, SOURCE_EXTENSIONS, SKIP_DIRS, MAX_SCAN_BYTES;
|
|
7430
|
+
var init_sandbox_scan = __esm({
|
|
7431
|
+
"packages/cli/src/sandbox-scan.ts"() {
|
|
7432
|
+
"use strict";
|
|
7433
|
+
NODE_BUILTINS = /* @__PURE__ */ new Set([
|
|
7434
|
+
"assert",
|
|
7435
|
+
"async_hooks",
|
|
7436
|
+
"buffer",
|
|
7437
|
+
"child_process",
|
|
7438
|
+
"cluster",
|
|
7439
|
+
"console",
|
|
7440
|
+
"constants",
|
|
7441
|
+
"crypto",
|
|
7442
|
+
"dgram",
|
|
7443
|
+
"diagnostics_channel",
|
|
7444
|
+
"dns",
|
|
7445
|
+
"domain",
|
|
7446
|
+
"events",
|
|
7447
|
+
"fs",
|
|
7448
|
+
"http",
|
|
7449
|
+
"http2",
|
|
7450
|
+
"https",
|
|
7451
|
+
"inspector",
|
|
7452
|
+
"module",
|
|
7453
|
+
"net",
|
|
7454
|
+
"os",
|
|
7455
|
+
"path",
|
|
7456
|
+
"perf_hooks",
|
|
7457
|
+
"process",
|
|
7458
|
+
"punycode",
|
|
7459
|
+
"querystring",
|
|
7460
|
+
"readline",
|
|
7461
|
+
"repl",
|
|
7462
|
+
"stream",
|
|
7463
|
+
"string_decoder",
|
|
7464
|
+
"sys",
|
|
7465
|
+
"timers",
|
|
7466
|
+
"tls",
|
|
7467
|
+
"trace_events",
|
|
7468
|
+
"tty",
|
|
7469
|
+
"url",
|
|
7470
|
+
"util",
|
|
7471
|
+
"v8",
|
|
7472
|
+
"vm",
|
|
7473
|
+
"wasi",
|
|
7474
|
+
"worker_threads",
|
|
7475
|
+
"zlib"
|
|
7476
|
+
]);
|
|
7477
|
+
NATIVE_ADDON_PACKAGES = /* @__PURE__ */ new Set([
|
|
7478
|
+
"bcrypt",
|
|
7479
|
+
"better-sqlite3",
|
|
7480
|
+
"sqlite3",
|
|
7481
|
+
"sharp",
|
|
7482
|
+
"canvas",
|
|
7483
|
+
"argon2",
|
|
7484
|
+
"node-gyp",
|
|
7485
|
+
"farmhash",
|
|
7486
|
+
"xxhash-addon",
|
|
7487
|
+
"zeromq",
|
|
7488
|
+
"grpc",
|
|
7489
|
+
"@grpc/grpc-js",
|
|
7490
|
+
"leveldown",
|
|
7491
|
+
"rocksdb",
|
|
7492
|
+
"node-canvas",
|
|
7493
|
+
"microtime",
|
|
7494
|
+
"sodium-native",
|
|
7495
|
+
"re2"
|
|
7496
|
+
]);
|
|
7497
|
+
BUILTIN_SUGGESTIONS = {
|
|
7498
|
+
"node:crypto": "\u7528 WebCrypto\uFF08\u6C99\u7BB1\u5DF2\u6CE8\u5165 crypto\uFF09\u6216 @adep/crypto \u7684 signJwt / hashPassword / encryptSecret",
|
|
7499
|
+
crypto: "\u7528 WebCrypto\uFF08\u6C99\u7BB1\u5DF2\u6CE8\u5165 crypto\uFF09\u6216 @adep/crypto",
|
|
7500
|
+
"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",
|
|
7501
|
+
fs: "\u6C99\u7BB1\u65E0\u6587\u4EF6\u7CFB\u7EDF\uFF1B\u9879\u76EE\u6570\u636E\u8D70 ctx.cloud.db\uFF0C\u6587\u4EF6\u8D70 ctx.cloud.storage",
|
|
7502
|
+
"node:path": "\u624B\u5199\u5B57\u7B26\u4E32\u62FC\u63A5\uFF08\u6C99\u7BB1\u91CC\u7684\u8DEF\u5F84\u90FD\u662F POSIX \u5F62\u5F0F\uFF09",
|
|
7503
|
+
path: "\u624B\u5199\u5B57\u7B26\u4E32\u62FC\u63A5\uFF08\u6C99\u7BB1\u91CC\u7684\u8DEF\u5F84\u90FD\u662F POSIX \u5F62\u5F0F\uFF09",
|
|
7504
|
+
"node:buffer": "\u7528 Uint8Array + TextEncoder/TextDecoder\uFF08\u6C99\u7BB1\u5DF2\u6CE8\u5165\uFF09",
|
|
7505
|
+
buffer: "\u7528 Uint8Array + TextEncoder/TextDecoder\uFF08\u6C99\u7BB1\u5DF2\u6CE8\u5165\uFF09",
|
|
7506
|
+
"node:process": "\u73AF\u5883\u53D8\u91CF\u8D70 ctx.env\uFF08adep.config.ts \u7684 environment\uFF09",
|
|
7507
|
+
process: "\u73AF\u5883\u53D8\u91CF\u8D70 ctx.env\uFF08adep.config.ts \u7684 environment\uFF09",
|
|
7508
|
+
"node:stream": "\u7528\u6C99\u7BB1\u6CE8\u5165\u7684 ReadableStream / WritableStream / TransformStream",
|
|
7509
|
+
stream: "\u7528\u6C99\u7BB1\u6CE8\u5165\u7684 ReadableStream / WritableStream / TransformStream"
|
|
7510
|
+
};
|
|
7511
|
+
SOURCE_EXTENSIONS = [".ts", ".js", ".mjs", ".cjs", ".tsx", ".jsx"];
|
|
7512
|
+
SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", "__tests__", "dist", ".git", ".adep", "coverage"]);
|
|
7513
|
+
MAX_SCAN_BYTES = 512 * 1024;
|
|
7514
|
+
}
|
|
7515
|
+
});
|
|
7516
|
+
|
|
7175
7517
|
// packages/cli/src/doctor.ts
|
|
7176
7518
|
var doctor_exports = {};
|
|
7177
7519
|
__export(doctor_exports, {
|
|
@@ -7202,12 +7544,13 @@ async function credentialMode(file) {
|
|
|
7202
7544
|
return void 0;
|
|
7203
7545
|
}
|
|
7204
7546
|
}
|
|
7205
|
-
async function runDoctor(paths) {
|
|
7547
|
+
async function runDoctor(paths, cwd = process.cwd()) {
|
|
7206
7548
|
const credentials = await loadCredentials(paths);
|
|
7207
7549
|
const server = credentials?.server ?? resolveServer();
|
|
7208
7550
|
const mode = await credentialMode(paths.credentialsFile);
|
|
7209
7551
|
const offline = await isOffline();
|
|
7210
7552
|
const health = await probeServer(server);
|
|
7553
|
+
const sandbox = await scanSandbox(cwd);
|
|
7211
7554
|
const report = {
|
|
7212
7555
|
server,
|
|
7213
7556
|
credentials: {
|
|
@@ -7218,7 +7561,8 @@ async function runDoctor(paths) {
|
|
|
7218
7561
|
network: { offline },
|
|
7219
7562
|
serverHealth: health,
|
|
7220
7563
|
offlineCommands: [...OFFLINE_COMMANDS],
|
|
7221
|
-
boundaries: SIM_BOUNDARIES.map((b) => ({ kind: b.kind, title: b.title, detail: b.detail }))
|
|
7564
|
+
boundaries: SIM_BOUNDARIES.map((b) => ({ kind: b.kind, title: b.title, detail: b.detail })),
|
|
7565
|
+
sandbox
|
|
7222
7566
|
};
|
|
7223
7567
|
if (credentials !== null) report.credentials.email = credentials.email;
|
|
7224
7568
|
if (mode !== void 0 && mode !== "600") {
|
|
@@ -7226,6 +7570,22 @@ async function runDoctor(paths) {
|
|
|
7226
7570
|
}
|
|
7227
7571
|
return report;
|
|
7228
7572
|
}
|
|
7573
|
+
async function scanSandbox(cwd) {
|
|
7574
|
+
let functionsDir = "functions";
|
|
7575
|
+
try {
|
|
7576
|
+
const config = await loadAdepConfigModule(cwd);
|
|
7577
|
+
if (config?.functionsDir !== void 0 && config.functionsDir.length > 0) {
|
|
7578
|
+
functionsDir = config.functionsDir;
|
|
7579
|
+
}
|
|
7580
|
+
} catch {
|
|
7581
|
+
}
|
|
7582
|
+
try {
|
|
7583
|
+
const findings = await scanFunctionSources(cwd, functionsDir);
|
|
7584
|
+
return { functionsDir, findings };
|
|
7585
|
+
} catch {
|
|
7586
|
+
return { functionsDir: null, findings: [] };
|
|
7587
|
+
}
|
|
7588
|
+
}
|
|
7229
7589
|
function formatDoctorReport(report) {
|
|
7230
7590
|
const lines = ["adep doctor \xB7 \u73AF\u5883\u81EA\u68C0", ""];
|
|
7231
7591
|
lines.push("\u51ED\u636E\u4E0E\u8EAB\u4EFD");
|
|
@@ -7253,6 +7613,28 @@ function formatDoctorReport(report) {
|
|
|
7253
7613
|
}
|
|
7254
7614
|
lines.push("", "\u79BB\u7EBF\u53EF\u7528\u8303\u56F4\uFF08\u65AD\u7F51\u65F6\u4ECD\u53EF\u6267\u884C\uFF09");
|
|
7255
7615
|
for (const command of report.offlineCommands) lines.push(` \xB7 ${command}`);
|
|
7616
|
+
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");
|
|
7617
|
+
if (report.sandbox.functionsDir === null) {
|
|
7618
|
+
lines.push(" \xB7 \u672A\u627E\u5230\u51FD\u6570\u76EE\u5F55\uFF0C\u8DF3\u8FC7\u626B\u63CF");
|
|
7619
|
+
} else if (report.sandbox.findings.length === 0) {
|
|
7620
|
+
lines.push(` \u2713 ${report.sandbox.functionsDir}/ \u5185\u672A\u53D1\u73B0 node \u5185\u7F6E\u6A21\u5757 / \u539F\u751F addon \u4F9D\u8D56`);
|
|
7621
|
+
} else {
|
|
7622
|
+
const byFile = /* @__PURE__ */ new Map();
|
|
7623
|
+
for (const finding of report.sandbox.findings) {
|
|
7624
|
+
const list = byFile.get(finding.file) ?? [];
|
|
7625
|
+
list.push(finding);
|
|
7626
|
+
byFile.set(finding.file, list);
|
|
7627
|
+
}
|
|
7628
|
+
lines.push(
|
|
7629
|
+
` \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`
|
|
7630
|
+
);
|
|
7631
|
+
for (const [file, findingList] of byFile) {
|
|
7632
|
+
for (const finding of findingList) {
|
|
7633
|
+
lines.push(` ${file}:${finding.line} [${finding.code}] ${finding.specifier}`);
|
|
7634
|
+
lines.push(` ${finding.message}`);
|
|
7635
|
+
}
|
|
7636
|
+
}
|
|
7637
|
+
}
|
|
7256
7638
|
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
7639
|
for (const boundary of report.boundaries) {
|
|
7258
7640
|
lines.push(` \xB7 [${boundary.kind}] ${boundary.title}\uFF1A${boundary.detail}`);
|
|
@@ -7267,6 +7649,8 @@ var init_doctor = __esm({
|
|
|
7267
7649
|
init_config();
|
|
7268
7650
|
init_boundary();
|
|
7269
7651
|
init_net();
|
|
7652
|
+
init_sandbox_scan();
|
|
7653
|
+
init_ts_config();
|
|
7270
7654
|
SERVER_PROBE_TIMEOUT_MS = 5e3;
|
|
7271
7655
|
OFFLINE_COMMANDS = [
|
|
7272
7656
|
"adep init",
|
|
@@ -7639,8 +8023,8 @@ __export(hosting_exports, {
|
|
|
7639
8023
|
hostingInfo: () => hostingInfo,
|
|
7640
8024
|
hostingPull: () => hostingPull
|
|
7641
8025
|
});
|
|
7642
|
-
import { readdir as
|
|
7643
|
-
import { dirname as dirname11, join as
|
|
8026
|
+
import { readdir as readdir8, readFile as readFile18, stat as stat13 } from "node:fs/promises";
|
|
8027
|
+
import { dirname as dirname11, join as join22, relative as relative7, resolve as resolve14, sep as sep4 } from "node:path";
|
|
7644
8028
|
async function open4(paths, options) {
|
|
7645
8029
|
const client = await createClient(paths);
|
|
7646
8030
|
const project2 = await resolveSlug(resolve14(options.cwd), options.slug);
|
|
@@ -7661,16 +8045,16 @@ async function collectSiteFiles(dir) {
|
|
|
7661
8045
|
const walk = async (sub) => {
|
|
7662
8046
|
let entries;
|
|
7663
8047
|
try {
|
|
7664
|
-
entries = await
|
|
8048
|
+
entries = await readdir8(sub, { withFileTypes: true });
|
|
7665
8049
|
} catch {
|
|
7666
8050
|
return;
|
|
7667
8051
|
}
|
|
7668
8052
|
for (const entry of entries) {
|
|
7669
|
-
const full =
|
|
8053
|
+
const full = join22(sub, entry.name);
|
|
7670
8054
|
if (entry.isDirectory()) {
|
|
7671
8055
|
await walk(full);
|
|
7672
8056
|
} else if (entry.isFile()) {
|
|
7673
|
-
const rel =
|
|
8057
|
+
const rel = relative7(root, full).split(sep4).join("/");
|
|
7674
8058
|
files.set(rel, full);
|
|
7675
8059
|
}
|
|
7676
8060
|
}
|
|
@@ -7690,7 +8074,7 @@ async function hostingDeploy(paths, options) {
|
|
|
7690
8074
|
for (const [rel, full] of files) {
|
|
7691
8075
|
log(`[adep] \u4E0A\u4F20 site/${rel}`);
|
|
7692
8076
|
const info2 = await stat13(full);
|
|
7693
|
-
const bytes = await
|
|
8077
|
+
const bytes = await readFile18(full);
|
|
7694
8078
|
const form = new FormData();
|
|
7695
8079
|
form.set("path", `site/${rel}`);
|
|
7696
8080
|
form.set("visibility", "public");
|
|
@@ -7728,7 +8112,7 @@ async function hostingPull(paths, options) {
|
|
|
7728
8112
|
const response = await client.download(url, "HOSTING_DOWNLOAD_FAILED");
|
|
7729
8113
|
const bytes = Buffer.from(await response.arrayBuffer());
|
|
7730
8114
|
const rel = entry.path.replace(/^site\//, "");
|
|
7731
|
-
const target =
|
|
8115
|
+
const target = join22(outputDir, ...rel.split("/"));
|
|
7732
8116
|
await mkdir12(dirname11(target), { recursive: true });
|
|
7733
8117
|
await writeFile10(target, bytes);
|
|
7734
8118
|
files.push({ path: entry.path, size: bytes.length });
|
|
@@ -12274,11 +12658,28 @@ function registerImport(program2, ctx) {
|
|
|
12274
12658
|
|
|
12275
12659
|
// packages/cli/src/commands/dev.ts
|
|
12276
12660
|
function registerDevServers(program2, ctx) {
|
|
12277
|
-
program2.command("dev").description("\u672C\u5730\u8C03\u8BD5\uFF1A\u76D1\u542C functions/ \u70ED\u91CD\u8F7D\uFF0Chttp://localhost:<port>/<fnName>").option("-p, --port <port>", "\u76D1\u542C\u7AEF\u53E3\uFF08\u7F3A\u7701 8787\uFF09", "8787").
|
|
12661
|
+
program2.command("dev").description("\u672C\u5730\u8C03\u8BD5\uFF1A\u76D1\u542C functions/ \u70ED\u91CD\u8F7D\uFF0Chttp://localhost:<port>/<fnName>").option("-p, --port <port>", "\u76D1\u542C\u7AEF\u53E3\uFF08\u7F3A\u7701 8787\uFF09", "8787").option(
|
|
12662
|
+
"--db <mode>",
|
|
12663
|
+
"\u6570\u636E\u5E93\u6A21\u5F0F\uFF1Asqlite\uFF08\u7F3A\u7701\uFF0C\u771F\u5B9E SQLite \u5E93\u6587\u4EF6\uFF0C\u9700 Bun \u6216 Node \u2265 22.5\uFF1B\u8FD0\u884C\u65F6\u4E0D\u652F\u6301\u6216\u6253\u5F00\u5931\u8D25\u65F6\u81EA\u52A8\u964D\u7EA7 sim\uFF09| sim\uFF08\u5185\u7F6E\u6A21\u62DF\u5F15\u64CE + .adep/sim/db.json\uFF09"
|
|
12664
|
+
).option(
|
|
12665
|
+
"--db-file <path>",
|
|
12666
|
+
"sqlite \u6A21\u5F0F\u7684\u5E93\u6587\u4EF6\uFF08\u7F3A\u7701\u53D6 ADEP_SERVE_DB_FILE\uFF0C\u518D\u7F3A\u7701 .adep/data/project.sqlite\uFF09"
|
|
12667
|
+
).option(
|
|
12668
|
+
"--schema <file>",
|
|
12669
|
+
"\u6570\u636E\u5E93\u7ED3\u6784\u6587\u4EF6\uFF1A\u542F\u52A8\u65F6\u5BF9\u672C\u5730\u5E93\u9010\u6761\u5E94\u7528\uFF08\u5EFA\u8868\u8BED\u53E5\u5EFA\u8BAE IF NOT EXISTS\uFF0C\u5E42\u7B49\u53EF\u91CD\u590D\u542F\u52A8\uFF09"
|
|
12670
|
+
).action(async (flags) => {
|
|
12278
12671
|
const command = ctx.io("dev");
|
|
12279
12672
|
await command.run(async () => {
|
|
12280
12673
|
const { startDevServer: startDevServer2 } = await Promise.resolve().then(() => (init_dev(), dev_exports));
|
|
12281
|
-
const started = await startDevServer2({
|
|
12674
|
+
const started = await startDevServer2({
|
|
12675
|
+
cwd: ctx.cwd,
|
|
12676
|
+
port: Number(flags.port ?? "8787"),
|
|
12677
|
+
// 缺省值一律交给 startDevServer 定档(旗标 > ADEP_SERVE_DB > 内置缺省),
|
|
12678
|
+
// 与 `adep serve` 同一条纪律:commander 的缺省值不该盖掉环境变量。
|
|
12679
|
+
...flags.db === void 0 ? {} : { db: flags.db },
|
|
12680
|
+
...flags.dbFile === void 0 ? {} : { dbFile: flags.dbFile },
|
|
12681
|
+
...flags.schema === void 0 ? {} : { schemaFile: flags.schema }
|
|
12682
|
+
});
|
|
12282
12683
|
command.raw(`[adep] dev server listening on ${started.baseUrl}\uFF08Ctrl-C \u9000\u51FA\uFF09`);
|
|
12283
12684
|
await new Promise(() => void 0);
|
|
12284
12685
|
});
|
|
@@ -12333,7 +12734,7 @@ init_auth();
|
|
|
12333
12734
|
init_client();
|
|
12334
12735
|
init_deploy();
|
|
12335
12736
|
import { stat as stat9 } from "node:fs/promises";
|
|
12336
|
-
import { join as
|
|
12737
|
+
import { join as join18, resolve as resolve10 } from "node:path";
|
|
12337
12738
|
async function resolveProjectId2(client, cwd, slug) {
|
|
12338
12739
|
const resolvedSlug = await resolveSlug(resolve10(cwd), slug);
|
|
12339
12740
|
const listed = await client.request("/api/v1/projects", {}, "PROJECT_LIST_FAILED");
|
|
@@ -12376,7 +12777,8 @@ async function publishFunctions(paths, options) {
|
|
|
12376
12777
|
cwd: options.cwd,
|
|
12377
12778
|
...options.slug === void 0 ? {} : { slug: options.slug },
|
|
12378
12779
|
silent: options.silent ?? false,
|
|
12379
|
-
...options.log === void 0 ? {} : { log: options.log }
|
|
12780
|
+
...options.log === void 0 ? {} : { log: options.log },
|
|
12781
|
+
...options.force === void 0 ? {} : { force: options.force }
|
|
12380
12782
|
});
|
|
12381
12783
|
const elapsedSeconds = (Date.now() - startedAt) / 1e3;
|
|
12382
12784
|
const deployedCount = result.functions.filter((fn) => fn.action !== "none").length;
|
|
@@ -12395,11 +12797,12 @@ async function runPublish(paths, io, cwd, flags) {
|
|
|
12395
12797
|
cwd,
|
|
12396
12798
|
...flags.project === void 0 ? {} : { slug: flags.project },
|
|
12397
12799
|
silent: io.json,
|
|
12398
|
-
log: (line) => io.line(line)
|
|
12800
|
+
log: (line) => io.line(line),
|
|
12801
|
+
...flags.force === void 0 ? {} : { force: flags.force }
|
|
12399
12802
|
});
|
|
12400
12803
|
}
|
|
12401
12804
|
if (wantFrontend) {
|
|
12402
|
-
const webDir =
|
|
12805
|
+
const webDir = join18(cwd, "web");
|
|
12403
12806
|
const webStat = await stat9(webDir).catch(() => null);
|
|
12404
12807
|
if (webStat !== null && webStat.isDirectory()) {
|
|
12405
12808
|
const { frontendSync: frontendSync2 } = await Promise.resolve().then(() => (init_frontend(), frontend_exports));
|
|
@@ -12447,7 +12850,10 @@ function registerPublish(program2, ctx) {
|
|
|
12447
12850
|
program2.command("publish").description("\u5168\u6808\u53D1\u5E03\uFF1A\u51FD\u6570\u90E8\u7F72 + \u524D\u7AEF\u6784\u5EFA\u6258\u7BA1\uFF08--only functions|frontend \u53EF\u5355\u72EC\u53D1\u5E03\u4E00\u4FA7\uFF09").option(
|
|
12448
12851
|
"--only <scope>",
|
|
12449
12852
|
"\u4EC5\u53D1\u5E03\u4E00\u4FA7\uFF1Afunctions\uFF08\u53EA\u90E8\u7F72\u4E91\u51FD\u6570\uFF09| frontend\uFF08\u53EA\u6784\u5EFA\u6258\u7BA1\u524D\u7AEF\uFF09\uFF1B\u7F3A\u7701\u5168\u6808\u53D1\u5E03"
|
|
12450
|
-
).option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").
|
|
12853
|
+
).option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").option(
|
|
12854
|
+
"--force",
|
|
12855
|
+
"\u653E\u884C warn \u7EA7\u5BC6\u94A5\u5F15\u7528\u547D\u4E2D\uFF08FN-013\uFF1B\u6E90\u7801\u5F15\u7528\u4E86\u5DF2\u914D\u7F6E\u7684 secret \u73AF\u5883\u53D8\u91CF\u540D\u65F6\u53D1\u5E03\u88AB\u963B\u65AD\uFF0C\u786E\u8BA4\u975E\u6CC4\u6F0F\u540E\u7528\u672C\u65D7\u6807\u653E\u884C\uFF0C\u670D\u52A1\u7AEF\u843D\u5BA1\u8BA1\uFF09"
|
|
12856
|
+
).action(async (flags) => {
|
|
12451
12857
|
const command = ctx.io("publish");
|
|
12452
12858
|
await command.run(async () => {
|
|
12453
12859
|
const result = await runPublish(ctx.paths, command, ctx.cwd, flags);
|
|
@@ -12457,13 +12863,14 @@ function registerPublish(program2, ctx) {
|
|
|
12457
12863
|
}
|
|
12458
12864
|
|
|
12459
12865
|
// packages/cli/src/commands/deploy.ts
|
|
12460
|
-
async function runDeploy(paths, io, cwd, slug, dir) {
|
|
12866
|
+
async function runDeploy(paths, io, cwd, slug, dir, force) {
|
|
12461
12867
|
const { deploy: deploy2 } = await Promise.resolve().then(() => (init_deploy(), deploy_exports));
|
|
12462
12868
|
const startedAt = Date.now();
|
|
12463
12869
|
const result = await deploy2(paths, {
|
|
12464
12870
|
cwd,
|
|
12465
12871
|
...slug === void 0 ? {} : { slug },
|
|
12466
12872
|
...dir === void 0 ? {} : { functionsDir: dir },
|
|
12873
|
+
...force === void 0 ? {} : { force },
|
|
12467
12874
|
// --json 下逐函数进度会破坏「stdout 恰好一个 JSON 对象」的信封约定(PRD §2.5.3)。
|
|
12468
12875
|
silent: io.json,
|
|
12469
12876
|
// 人读模式的进度也走注入的 io:deploy 内部缺省会直写 process.stdout,
|
|
@@ -12488,14 +12895,14 @@ async function runDeploy(paths, io, cwd, slug, dir) {
|
|
|
12488
12895
|
function registerDeploy(program2, ctx) {
|
|
12489
12896
|
program2.command("deploy").description(
|
|
12490
12897
|
"[deprecated] \u63A8\u8350\u4F7F\u7528 adep publish\u3002\u589E\u91CF\u90E8\u7F72\u51FD\u6570\uFF1A\u5BF9\u6BD4\u8FDC\u7AEF\u54C8\u5E0C \u2192 \u4EC5\u4E0A\u4F20\u53D8\u66F4 \u2192 \u53D1\u5E03 \u2192 \u8F93\u51FA\u8BBF\u95EE\u57DF\u540D"
|
|
12491
|
-
).option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").action(async (flags) => {
|
|
12898
|
+
).option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").option("--force", "\u653E\u884C warn \u7EA7\u5BC6\u94A5\u5F15\u7528\u547D\u4E2D\uFF08FN-013\uFF1B\u786E\u8BA4\u975E\u6CC4\u6F0F\u540E\u7528\uFF0C\u670D\u52A1\u7AEF\u843D\u5BA1\u8BA1\uFF09").action(async (flags) => {
|
|
12492
12899
|
const command = ctx.io("deploy");
|
|
12493
12900
|
if (!command.json) {
|
|
12494
12901
|
process.stderr.write(
|
|
12495
12902
|
"\u63D0\u793A\uFF1Aadep deploy \u5DF2\u5E9F\u5F03\uFF0C\u63A8\u8350\u4F7F\u7528 adep publish\uFF08\u5168\u6808\u53D1\u5E03\uFF09\u6216 adep publish --only functions\uFF08\u4EC5\u51FD\u6570\uFF09\n"
|
|
12496
12903
|
);
|
|
12497
12904
|
}
|
|
12498
|
-
await command.run(() => runDeploy(ctx.paths, command, ctx.cwd, flags.project));
|
|
12905
|
+
await command.run(() => runDeploy(ctx.paths, command, ctx.cwd, flags.project, void 0, flags.force));
|
|
12499
12906
|
});
|
|
12500
12907
|
}
|
|
12501
12908
|
|
|
@@ -12539,7 +12946,7 @@ function registerExport(program2, ctx) {
|
|
|
12539
12946
|
|
|
12540
12947
|
// packages/cli/src/commands/db.ts
|
|
12541
12948
|
function registerDb(program2, ctx) {
|
|
12542
|
-
const db = program2.command("db").description("\u9879\u76EE\u6570\u636E\u5E93\u7EF4\u62A4\uFF1A\u542F\u52A8 / \u72B6\u6001 / \u505C\u6B62 / SQL / \u5FEB\u7167 / \u56DE\u6EDA")
|
|
12949
|
+
const db = program2.command("db").description("\u9879\u76EE\u6570\u636E\u5E93\u7EF4\u62A4\uFF1A\u542F\u52A8 / \u72B6\u6001 / \u505C\u6B62 / SQL / \u5FEB\u7167 / \u56DE\u6EDA");
|
|
12543
12950
|
db.command("start").description("\u542F\u52A8\u9879\u76EE\u6570\u636E\u5E93\uFF08\u5DF2\u5B58\u5728\u5219\u91CD\u65B0\u6FC0\u6D3B\uFF0C\u4E0D\u91CD\u5EFA\u6570\u636E\uFF09").option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").action(async (flags) => {
|
|
12544
12951
|
const command = ctx.io("db start");
|
|
12545
12952
|
await command.run(async () => {
|
|
@@ -12690,7 +13097,7 @@ function registerDb(program2, ctx) {
|
|
|
12690
13097
|
|
|
12691
13098
|
// packages/cli/src/commands/frontend.ts
|
|
12692
13099
|
function registerFrontend(program2, ctx) {
|
|
12693
|
-
const frontend = program2.command("frontend").description("\u524D\u7AEF\u8349\u7A3F\u7EF4\u62A4\uFF1Async\uFF08\u672C\u5730 web/ \u2192 \u5E73\u53F0\u8349\u7A3F\uFF09")
|
|
13100
|
+
const frontend = program2.command("frontend").description("\u524D\u7AEF\u8349\u7A3F\u7EF4\u62A4\uFF1Async\uFF08\u672C\u5730 web/ \u2192 \u5E73\u53F0\u8349\u7A3F\uFF09");
|
|
12694
13101
|
frontend.command("sync").description("\u4E0A\u4F20\u672C\u5730 web/ \u6E90\u7801\u4E3A\u5E73\u53F0\u524D\u7AEF\u8349\u7A3F\uFF08\u6574\u7EC4\u66FF\u6362\uFF1Bpublish \u5168\u6808\u65F6\u81EA\u52A8\u6267\u884C\uFF09").option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").option("-d, --dir <dir>", "\u672C\u5730\u524D\u7AEF\u6E90\u7801\u76EE\u5F55\uFF08\u7F3A\u7701 cwd/web\uFF09").action(async (flags) => {
|
|
12695
13102
|
const command = ctx.io("frontend sync");
|
|
12696
13103
|
await command.run(async () => {
|
|
@@ -12712,7 +13119,7 @@ function registerFrontend(program2, ctx) {
|
|
|
12712
13119
|
|
|
12713
13120
|
// packages/cli/src/commands/storage.ts
|
|
12714
13121
|
function registerStorage(program2, ctx) {
|
|
12715
|
-
const storage = program2.command("storage").description("\u4E91\u5B58\u50A8 / \u6587\u4EF6\u5B58\u50A8\uFF1A\u4E0A\u4F20 / \u4E0B\u8F7D / \u5217\u8868 / \u5220\u9664")
|
|
13122
|
+
const storage = program2.command("storage").description("\u4E91\u5B58\u50A8 / \u6587\u4EF6\u5B58\u50A8\uFF1A\u4E0A\u4F20 / \u4E0B\u8F7D / \u5217\u8868 / \u5220\u9664");
|
|
12716
13123
|
storage.command("upload").description("\u4E0A\u4F20\u5355\u4E2A\u6587\u4EF6\uFF08multipart\uFF1B\u5355\u6587\u4EF6 \u2264 50MB\uFF09").argument("<file>", "\u672C\u5730\u6587\u4EF6\u8DEF\u5F84").requiredOption("--path <remote-path>", "\u6876\u5185\u76EE\u6807\u8DEF\u5F84\uFF08\u5982 avatars/a.png\uFF09").option(
|
|
12717
13124
|
"--visibility <public|private>",
|
|
12718
13125
|
"public \u76F4\u8FDE / private \u7B7E\u540D\uFF08\u7F3A\u7701 private\uFF09",
|
|
@@ -12997,14 +13404,16 @@ function registerFunctions(program2, ctx) {
|
|
|
12997
13404
|
const functions = program2.command("functions").description("\u4E91\u51FD\u6570\uFF1A\u90E8\u7F72\uFF08\u53EF\u6307\u5B9A\u76EE\u5F55\uFF09/ \u5217\u51FA / \u67E5\u65E5\u5FD7");
|
|
12998
13405
|
functions.command("deploy").description(
|
|
12999
13406
|
"[deprecated] \u63A8\u8350\u4F7F\u7528 adep publish --only functions\u3002\u90E8\u7F72\u51FD\u6570\u76EE\u5F55\uFF08dir \u8986\u76D6 adep.config.ts \u7684 functionsDir\uFF09"
|
|
13000
|
-
).argument("[dir]", "\u51FD\u6570\u76EE\u5F55\uFF08\u76F8\u5BF9\u9879\u76EE\u6839\u6216\u7EDD\u5BF9\u8DEF\u5F84\uFF0C\u7F3A\u7701\u53D6\u914D\u7F6E\u91CC\u7684 functionsDir\uFF09").option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").action(async (dir, flags) => {
|
|
13407
|
+
).argument("[dir]", "\u51FD\u6570\u76EE\u5F55\uFF08\u76F8\u5BF9\u9879\u76EE\u6839\u6216\u7EDD\u5BF9\u8DEF\u5F84\uFF0C\u7F3A\u7701\u53D6\u914D\u7F6E\u91CC\u7684 functionsDir\uFF09").option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").option("--force", "\u653E\u884C warn \u7EA7\u5BC6\u94A5\u5F15\u7528\u547D\u4E2D\uFF08FN-013\uFF1B\u786E\u8BA4\u975E\u6CC4\u6F0F\u540E\u7528\uFF0C\u670D\u52A1\u7AEF\u843D\u5BA1\u8BA1\uFF09").action(async (dir, flags) => {
|
|
13001
13408
|
const command = ctx.io("functions deploy");
|
|
13002
13409
|
if (!command.json) {
|
|
13003
13410
|
process.stderr.write(
|
|
13004
13411
|
"\u63D0\u793A\uFF1Aadep functions deploy \u5DF2\u5E9F\u5F03\uFF0C\u63A8\u8350\u4F7F\u7528 adep publish --only functions\n"
|
|
13005
13412
|
);
|
|
13006
13413
|
}
|
|
13007
|
-
await command.run(
|
|
13414
|
+
await command.run(
|
|
13415
|
+
() => runDeploy(ctx.paths, command, ctx.cwd, flags.project, dir, flags.force)
|
|
13416
|
+
);
|
|
13008
13417
|
});
|
|
13009
13418
|
functions.command("list").description("\u5217\u51FA\u9879\u76EE\u4E0B\u7684\u4E91\u51FD\u6570\uFF08\u542B\u516C\u7F51\u8BBF\u95EE\u524D\u7F00\uFF09").option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").action(async (flags) => {
|
|
13010
13419
|
const command = ctx.io("functions list");
|
|
@@ -13055,7 +13464,7 @@ function parseBool(raw) {
|
|
|
13055
13464
|
throw new CliError("INVALID_BOOLEAN", `\u5E03\u5C14\u53C2\u6570\u987B\u4E3A true \u6216 false\uFF0C\u6536\u5230 "${raw}"`);
|
|
13056
13465
|
}
|
|
13057
13466
|
function registerHosting(program2, ctx) {
|
|
13058
|
-
const hosting = program2.command("hosting").description("\u9759\u6001\u6258\u7BA1\uFF1A\u67E5\u770B / \u90E8\u7F72 / \u62C9\u53D6 / \u914D\u7F6E")
|
|
13467
|
+
const hosting = program2.command("hosting").description("\u9759\u6001\u6258\u7BA1\uFF1A\u67E5\u770B / \u90E8\u7F72 / \u62C9\u53D6 / \u914D\u7F6E");
|
|
13059
13468
|
hosting.command("info").description("\u67E5\u770B\u9759\u6001\u6258\u7BA1\u914D\u7F6E\u3001\u7AD9\u70B9\u5730\u5740\u4E0E\u6587\u4EF6\u6811").option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").action(async (flags) => {
|
|
13060
13469
|
const command = ctx.io("hosting info");
|
|
13061
13470
|
await command.run(async () => {
|