@adep/cli 0.0.1 → 0.0.2
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 +102 -1
- package/dist/index.js +2352 -279
- package/package.json +8 -13
- package/src/index.ts +0 -8
package/dist/index.js
CHANGED
|
@@ -61,6 +61,77 @@ var init_credentials = __esm({
|
|
|
61
61
|
}
|
|
62
62
|
});
|
|
63
63
|
|
|
64
|
+
// packages/cli/src/offline/errors.ts
|
|
65
|
+
var NetworkRequiredError;
|
|
66
|
+
var init_errors = __esm({
|
|
67
|
+
"packages/cli/src/offline/errors.ts"() {
|
|
68
|
+
"use strict";
|
|
69
|
+
NetworkRequiredError = class extends Error {
|
|
70
|
+
command;
|
|
71
|
+
reason;
|
|
72
|
+
constructor(command, reason) {
|
|
73
|
+
super(`\`${command}\` \u9700\u8981\u8054\u7F51\uFF1A${reason} \xB7 \u79BB\u7EBF\u53EF\u7528\u8303\u56F4\u89C1 \`adep doctor\``);
|
|
74
|
+
this.name = "NetworkRequiredError";
|
|
75
|
+
this.command = command;
|
|
76
|
+
this.reason = reason;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// packages/cli/src/offline/net.ts
|
|
83
|
+
var net_exports = {};
|
|
84
|
+
__export(net_exports, {
|
|
85
|
+
isOffline: () => isOffline,
|
|
86
|
+
requireNetwork: () => requireNetwork,
|
|
87
|
+
resetProbeCache: () => resetProbeCache
|
|
88
|
+
});
|
|
89
|
+
async function isOffline() {
|
|
90
|
+
const now = Date.now();
|
|
91
|
+
if (cachedResult !== null && now - cachedResult.timestamp < PROBE_TTL_MS) {
|
|
92
|
+
return cachedResult.offline;
|
|
93
|
+
}
|
|
94
|
+
let offline = true;
|
|
95
|
+
try {
|
|
96
|
+
const controller = new AbortController();
|
|
97
|
+
const timer = setTimeout(() => controller.abort(), PROBE_TIMEOUT_MS);
|
|
98
|
+
try {
|
|
99
|
+
const res = await fetch(PROBE_URL, {
|
|
100
|
+
method: "HEAD",
|
|
101
|
+
signal: controller.signal
|
|
102
|
+
});
|
|
103
|
+
offline = false;
|
|
104
|
+
void res;
|
|
105
|
+
} finally {
|
|
106
|
+
clearTimeout(timer);
|
|
107
|
+
}
|
|
108
|
+
} catch {
|
|
109
|
+
offline = true;
|
|
110
|
+
}
|
|
111
|
+
cachedResult = { offline, timestamp: now };
|
|
112
|
+
return offline;
|
|
113
|
+
}
|
|
114
|
+
function resetProbeCache() {
|
|
115
|
+
cachedResult = null;
|
|
116
|
+
}
|
|
117
|
+
async function requireNetwork(command) {
|
|
118
|
+
const offline = await isOffline();
|
|
119
|
+
if (offline) {
|
|
120
|
+
throw new NetworkRequiredError(command, "\u5F53\u524D\u7F51\u7EDC\u4E0D\u53EF\u8FBE\uFF08\u63A2\u6D4B registry.npmjs.org \u5931\u8D25\uFF09");
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
var PROBE_TTL_MS, PROBE_URL, PROBE_TIMEOUT_MS, cachedResult;
|
|
124
|
+
var init_net = __esm({
|
|
125
|
+
"packages/cli/src/offline/net.ts"() {
|
|
126
|
+
"use strict";
|
|
127
|
+
init_errors();
|
|
128
|
+
PROBE_TTL_MS = 3e4;
|
|
129
|
+
PROBE_URL = "https://registry.npmjs.org/";
|
|
130
|
+
PROBE_TIMEOUT_MS = 5e3;
|
|
131
|
+
cachedResult = null;
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
64
135
|
// packages/cli/src/auth.ts
|
|
65
136
|
function sessionCookieOf(setCookie) {
|
|
66
137
|
const line = setCookie.find(
|
|
@@ -72,6 +143,7 @@ function sessionCookieOf(setCookie) {
|
|
|
72
143
|
return line.split(";")[0];
|
|
73
144
|
}
|
|
74
145
|
async function login(paths, input) {
|
|
146
|
+
await requireNetwork("adep login");
|
|
75
147
|
const server = input.server.replace(/\/+$/, "");
|
|
76
148
|
let response;
|
|
77
149
|
try {
|
|
@@ -98,6 +170,7 @@ async function login(paths, input) {
|
|
|
98
170
|
return { email: input.email };
|
|
99
171
|
}
|
|
100
172
|
async function whoami(paths) {
|
|
173
|
+
await requireNetwork("adep whoami");
|
|
101
174
|
const credentials = await loadCredentials(paths);
|
|
102
175
|
if (credentials === null) {
|
|
103
176
|
throw new CliError("NOT_LOGGED_IN", "\u672A\u767B\u5F55\uFF1A\u8BF7\u5148\u6267\u884C adep login");
|
|
@@ -133,6 +206,7 @@ var init_auth = __esm({
|
|
|
133
206
|
"packages/cli/src/auth.ts"() {
|
|
134
207
|
"use strict";
|
|
135
208
|
init_credentials();
|
|
209
|
+
init_net();
|
|
136
210
|
CliError = class extends Error {
|
|
137
211
|
constructor(code, message, exitCode = 1) {
|
|
138
212
|
super(message);
|
|
@@ -144,6 +218,20 @@ var init_auth = __esm({
|
|
|
144
218
|
}
|
|
145
219
|
});
|
|
146
220
|
|
|
221
|
+
// packages/cli/src/config.ts
|
|
222
|
+
function resolvePaths(env = process.env) {
|
|
223
|
+
const home = env["ADEP_HOME"] ?? `${env["HOME"] ?? ""}/.adep`;
|
|
224
|
+
return { home, credentialsFile: `${home}/credentials` };
|
|
225
|
+
}
|
|
226
|
+
function resolveServer(env = process.env) {
|
|
227
|
+
return (env["ADEP_SERVER"] ?? "https://adep.jajabjbj.top").replace(/\/+$/, "");
|
|
228
|
+
}
|
|
229
|
+
var init_config = __esm({
|
|
230
|
+
"packages/cli/src/config.ts"() {
|
|
231
|
+
"use strict";
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
|
|
147
235
|
// packages/cli/src/widget/build.ts
|
|
148
236
|
import { createHash } from "node:crypto";
|
|
149
237
|
import { join as join2, resolve as resolve2 } from "node:path";
|
|
@@ -454,50 +542,8 @@ var init_init = __esm({
|
|
|
454
542
|
}
|
|
455
543
|
});
|
|
456
544
|
|
|
457
|
-
// packages/cli/src/prompt.ts
|
|
458
|
-
var prompt_exports = {};
|
|
459
|
-
__export(prompt_exports, {
|
|
460
|
-
createPrompt: () => createPrompt
|
|
461
|
-
});
|
|
462
|
-
import { createInterface } from "node:readline/promises";
|
|
463
|
-
import { Writable } from "node:stream";
|
|
464
|
-
function createPrompt(input = process.stdin) {
|
|
465
|
-
const rl = createInterface({ input, output: process.stdout, terminal: true });
|
|
466
|
-
let muted = null;
|
|
467
|
-
return {
|
|
468
|
-
async ask(question) {
|
|
469
|
-
const answer = await rl.question(question);
|
|
470
|
-
return answer.trim();
|
|
471
|
-
},
|
|
472
|
-
async askHidden(question) {
|
|
473
|
-
muted = createInterface({ input, output: new MutedStream(), terminal: true });
|
|
474
|
-
const answer = await muted.question(question);
|
|
475
|
-
muted.close();
|
|
476
|
-
muted = null;
|
|
477
|
-
process.stdout.write("\n");
|
|
478
|
-
return answer.trim();
|
|
479
|
-
},
|
|
480
|
-
close() {
|
|
481
|
-
muted?.close();
|
|
482
|
-
rl.close();
|
|
483
|
-
}
|
|
484
|
-
};
|
|
485
|
-
}
|
|
486
|
-
var MutedStream;
|
|
487
|
-
var init_prompt = __esm({
|
|
488
|
-
"packages/cli/src/prompt.ts"() {
|
|
489
|
-
"use strict";
|
|
490
|
-
MutedStream = class extends Writable {
|
|
491
|
-
write(_chunk, ...rest) {
|
|
492
|
-
void rest;
|
|
493
|
-
return true;
|
|
494
|
-
}
|
|
495
|
-
};
|
|
496
|
-
}
|
|
497
|
-
});
|
|
498
|
-
|
|
499
545
|
// packages/runtime/src/shared/capability-keys.ts
|
|
500
|
-
var RPC_CAPABILITY_KEY, CHAIN_CAPABILITY_KEY, DB_RPC;
|
|
546
|
+
var RPC_CAPABILITY_KEY, CHAIN_CAPABILITY_KEY, DB_RPC, REALTIME_CAPABILITY_CODES, REALTIME_CAPABILITY_METHODS;
|
|
501
547
|
var init_capability_keys = __esm({
|
|
502
548
|
"packages/runtime/src/shared/capability-keys.ts"() {
|
|
503
549
|
"use strict";
|
|
@@ -517,6 +563,20 @@ var init_capability_keys = __esm({
|
|
|
517
563
|
/** 执行一条链:`chain, args=[ChainRequest]`。 */
|
|
518
564
|
chain: "chain"
|
|
519
565
|
};
|
|
566
|
+
REALTIME_CAPABILITY_CODES = {
|
|
567
|
+
invalidMethod: "REALTIME_INVALID_METHOD",
|
|
568
|
+
unsupportedArg: "REALTIME_UNSUPPORTED_ARG",
|
|
569
|
+
subscriptionNotFound: "REALTIME_SUBSCRIPTION_NOT_FOUND",
|
|
570
|
+
tooManySubscriptions: "REALTIME_TOO_MANY_SUBSCRIPTIONS",
|
|
571
|
+
/** 线上独有:订阅授权策略(RT-002 `SubscriptionPolicy`)拒绝该 channel。 */
|
|
572
|
+
channelDenied: "REALTIME_CHANNEL_DENIED"
|
|
573
|
+
};
|
|
574
|
+
REALTIME_CAPABILITY_METHODS = [
|
|
575
|
+
"publish",
|
|
576
|
+
"subscribe",
|
|
577
|
+
"receive",
|
|
578
|
+
"unsubscribe"
|
|
579
|
+
];
|
|
520
580
|
}
|
|
521
581
|
});
|
|
522
582
|
|
|
@@ -743,7 +803,7 @@ var init_worker_executor = __esm({
|
|
|
743
803
|
const entry = input.entry ?? "index.ts";
|
|
744
804
|
const deps = this.depsConfig === void 0 ? void 0 : resolveExecutionDeps(this.depsConfig, input.project.id, input.files["package.json"]);
|
|
745
805
|
const logs = [];
|
|
746
|
-
return new Promise((
|
|
806
|
+
return new Promise((resolve15, reject) => {
|
|
747
807
|
let worker;
|
|
748
808
|
try {
|
|
749
809
|
worker = new Worker(resolveWorkerEntry(), {
|
|
@@ -805,7 +865,7 @@ var init_worker_executor = __esm({
|
|
|
805
865
|
if (message.type === "result") {
|
|
806
866
|
clearTimeout(timer);
|
|
807
867
|
void worker.terminate();
|
|
808
|
-
|
|
868
|
+
resolve15({ body: message.body, logs });
|
|
809
869
|
return;
|
|
810
870
|
}
|
|
811
871
|
if (message.type === "error") {
|
|
@@ -1048,7 +1108,6 @@ var init_owned = __esm({
|
|
|
1048
1108
|
});
|
|
1049
1109
|
|
|
1050
1110
|
// packages/runtime/src/database/builder/ulid.ts
|
|
1051
|
-
import { randomFillSync } from "node:crypto";
|
|
1052
1111
|
function encodeTime(now) {
|
|
1053
1112
|
let ts = Math.trunc(now);
|
|
1054
1113
|
let out = "";
|
|
@@ -1084,6 +1143,16 @@ function incrBase32(prev) {
|
|
|
1084
1143
|
}
|
|
1085
1144
|
return chars.join("");
|
|
1086
1145
|
}
|
|
1146
|
+
function randomFill(bytes) {
|
|
1147
|
+
const source = globalThis.crypto;
|
|
1148
|
+
if (source !== void 0 && typeof source.getRandomValues === "function") {
|
|
1149
|
+
return source.getRandomValues(bytes);
|
|
1150
|
+
}
|
|
1151
|
+
for (let i = 0; i < bytes.length; i += 1) {
|
|
1152
|
+
bytes[i] = Math.floor(Math.random() * 256);
|
|
1153
|
+
}
|
|
1154
|
+
return bytes;
|
|
1155
|
+
}
|
|
1087
1156
|
function ulid(now = Date.now()) {
|
|
1088
1157
|
const time = encodeTime(now);
|
|
1089
1158
|
let random;
|
|
@@ -1092,7 +1161,7 @@ function ulid(now = Date.now()) {
|
|
|
1092
1161
|
} else {
|
|
1093
1162
|
lastTime = now;
|
|
1094
1163
|
const bytes = new Uint8Array(10);
|
|
1095
|
-
|
|
1164
|
+
randomFill(bytes);
|
|
1096
1165
|
random = encodeRandom(bytes);
|
|
1097
1166
|
}
|
|
1098
1167
|
lastRandom = random;
|
|
@@ -1504,7 +1573,6 @@ var init_builder = __esm({
|
|
|
1504
1573
|
});
|
|
1505
1574
|
|
|
1506
1575
|
// packages/runtime/src/database/sdk/cloud.ts
|
|
1507
|
-
import { randomUUID } from "node:crypto";
|
|
1508
1576
|
function errorWithCode(error) {
|
|
1509
1577
|
const code = typeof error === "object" && error !== null && typeof error.code === "string" ? error.code : void 0;
|
|
1510
1578
|
if (code !== void 0 && error instanceof Error) {
|
|
@@ -1563,7 +1631,7 @@ function createDbCapability(driver, options = {}) {
|
|
|
1563
1631
|
case DB_RPC.begin: {
|
|
1564
1632
|
if (activeTxs.size > 0) throw unsafeOperation("\u4E0D\u5141\u8BB8\u5D4C\u5957\u4E8B\u52A1");
|
|
1565
1633
|
await driver.run("BEGIN");
|
|
1566
|
-
const txId = randomUUID();
|
|
1634
|
+
const txId = crypto.randomUUID();
|
|
1567
1635
|
activeTxs.set(txId, true);
|
|
1568
1636
|
return txId;
|
|
1569
1637
|
}
|
|
@@ -2115,11 +2183,177 @@ var init_driver = __esm({
|
|
|
2115
2183
|
}
|
|
2116
2184
|
});
|
|
2117
2185
|
|
|
2186
|
+
// packages/runtime/src/storage/hmac-sha256.ts
|
|
2187
|
+
function compress(h, block, w) {
|
|
2188
|
+
for (let i = 0; i < 16; i += 1) {
|
|
2189
|
+
const j = i * 4;
|
|
2190
|
+
w[i] = (block[j] ?? 0) << 24 | (block[j + 1] ?? 0) << 16 | (block[j + 2] ?? 0) << 8 | (block[j + 3] ?? 0);
|
|
2191
|
+
}
|
|
2192
|
+
for (let i = 16; i < 64; i += 1) {
|
|
2193
|
+
const s0 = rotr(w[i - 15], 7) ^ rotr(w[i - 15], 18) ^ w[i - 15] >>> 3;
|
|
2194
|
+
const s1 = rotr(w[i - 2], 17) ^ rotr(w[i - 2], 19) ^ w[i - 2] >>> 10;
|
|
2195
|
+
w[i] = w[i - 16] + s0 + w[i - 7] + s1 | 0;
|
|
2196
|
+
}
|
|
2197
|
+
let [a, b, c, d, e, f, g, hh] = [h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7]];
|
|
2198
|
+
for (let i = 0; i < 64; i += 1) {
|
|
2199
|
+
const S1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
|
|
2200
|
+
const ch = e & f ^ ~e & g;
|
|
2201
|
+
const t1 = hh + S1 + ch + K[i] + w[i] | 0;
|
|
2202
|
+
const S0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
|
|
2203
|
+
const maj = a & b ^ a & c ^ b & c;
|
|
2204
|
+
const t2 = S0 + maj | 0;
|
|
2205
|
+
hh = g;
|
|
2206
|
+
g = f;
|
|
2207
|
+
f = e;
|
|
2208
|
+
e = d + t1 | 0;
|
|
2209
|
+
d = c;
|
|
2210
|
+
c = b;
|
|
2211
|
+
b = a;
|
|
2212
|
+
a = t1 + t2 | 0;
|
|
2213
|
+
}
|
|
2214
|
+
h[0] = h[0] + a | 0;
|
|
2215
|
+
h[1] = h[1] + b | 0;
|
|
2216
|
+
h[2] = h[2] + c | 0;
|
|
2217
|
+
h[3] = h[3] + d | 0;
|
|
2218
|
+
h[4] = h[4] + e | 0;
|
|
2219
|
+
h[5] = h[5] + f | 0;
|
|
2220
|
+
h[6] = h[6] + g | 0;
|
|
2221
|
+
h[7] = h[7] + hh | 0;
|
|
2222
|
+
}
|
|
2223
|
+
function sha256(data) {
|
|
2224
|
+
const h = new Uint32Array([
|
|
2225
|
+
1779033703,
|
|
2226
|
+
3144134277,
|
|
2227
|
+
1013904242,
|
|
2228
|
+
2773480762,
|
|
2229
|
+
1359893119,
|
|
2230
|
+
2600822924,
|
|
2231
|
+
528734635,
|
|
2232
|
+
1541459225
|
|
2233
|
+
]);
|
|
2234
|
+
const bitLength = data.length * 8;
|
|
2235
|
+
const paddedLength = Math.ceil((data.length + 9) / 64) * 64;
|
|
2236
|
+
const padded = new Uint8Array(paddedLength);
|
|
2237
|
+
padded.set(data);
|
|
2238
|
+
padded[data.length] = 128;
|
|
2239
|
+
const view = new DataView(padded.buffer);
|
|
2240
|
+
view.setUint32(paddedLength - 4, bitLength >>> 0, false);
|
|
2241
|
+
view.setUint32(paddedLength - 8, Math.floor(bitLength / 4294967296), false);
|
|
2242
|
+
const w = new Uint32Array(64);
|
|
2243
|
+
for (let offset = 0; offset < paddedLength; offset += 64) {
|
|
2244
|
+
compress(h, padded.subarray(offset, offset + 64), w);
|
|
2245
|
+
}
|
|
2246
|
+
const out = new Uint8Array(32);
|
|
2247
|
+
const outView = new DataView(out.buffer);
|
|
2248
|
+
for (let i = 0; i < 8; i += 1) outView.setUint32(i * 4, h[i], false);
|
|
2249
|
+
return out;
|
|
2250
|
+
}
|
|
2251
|
+
function toBytes(input) {
|
|
2252
|
+
if (typeof input !== "string") return input;
|
|
2253
|
+
return new TextEncoder().encode(input);
|
|
2254
|
+
}
|
|
2255
|
+
function hmacSha256(key, message) {
|
|
2256
|
+
const blockSize = 64;
|
|
2257
|
+
let keyBytes = toBytes(key);
|
|
2258
|
+
if (keyBytes.length > blockSize) keyBytes = sha256(keyBytes);
|
|
2259
|
+
const padded = new Uint8Array(blockSize);
|
|
2260
|
+
padded.set(keyBytes);
|
|
2261
|
+
const inner = new Uint8Array(blockSize);
|
|
2262
|
+
const outer = new Uint8Array(blockSize);
|
|
2263
|
+
for (let i = 0; i < blockSize; i += 1) {
|
|
2264
|
+
inner[i] = padded[i] ^ 54;
|
|
2265
|
+
outer[i] = padded[i] ^ 92;
|
|
2266
|
+
}
|
|
2267
|
+
const innerInput = new Uint8Array(blockSize + toBytes(message).length);
|
|
2268
|
+
innerInput.set(inner);
|
|
2269
|
+
innerInput.set(toBytes(message), blockSize);
|
|
2270
|
+
const innerHash = sha256(innerInput);
|
|
2271
|
+
const outerInput = new Uint8Array(blockSize + 32);
|
|
2272
|
+
outerInput.set(outer);
|
|
2273
|
+
outerInput.set(innerHash, blockSize);
|
|
2274
|
+
return sha256(outerInput);
|
|
2275
|
+
}
|
|
2276
|
+
function hmacSha256Hex(key, message) {
|
|
2277
|
+
return [...hmacSha256(key, message)].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
2278
|
+
}
|
|
2279
|
+
var K, rotr;
|
|
2280
|
+
var init_hmac_sha256 = __esm({
|
|
2281
|
+
"packages/runtime/src/storage/hmac-sha256.ts"() {
|
|
2282
|
+
"use strict";
|
|
2283
|
+
K = new Uint32Array([
|
|
2284
|
+
1116352408,
|
|
2285
|
+
1899447441,
|
|
2286
|
+
3049323471,
|
|
2287
|
+
3921009573,
|
|
2288
|
+
961987163,
|
|
2289
|
+
1508970993,
|
|
2290
|
+
2453635748,
|
|
2291
|
+
2870763221,
|
|
2292
|
+
3624381080,
|
|
2293
|
+
310598401,
|
|
2294
|
+
607225278,
|
|
2295
|
+
1426881987,
|
|
2296
|
+
1925078388,
|
|
2297
|
+
2162078206,
|
|
2298
|
+
2614888103,
|
|
2299
|
+
3248222580,
|
|
2300
|
+
3835390401,
|
|
2301
|
+
4022224774,
|
|
2302
|
+
264347078,
|
|
2303
|
+
604807628,
|
|
2304
|
+
770255983,
|
|
2305
|
+
1249150122,
|
|
2306
|
+
1555081692,
|
|
2307
|
+
1996064986,
|
|
2308
|
+
2554220882,
|
|
2309
|
+
2821834349,
|
|
2310
|
+
2952996808,
|
|
2311
|
+
3210313671,
|
|
2312
|
+
3336571891,
|
|
2313
|
+
3584528711,
|
|
2314
|
+
113926993,
|
|
2315
|
+
338241895,
|
|
2316
|
+
666307205,
|
|
2317
|
+
773529912,
|
|
2318
|
+
1294757372,
|
|
2319
|
+
1396182291,
|
|
2320
|
+
1695183700,
|
|
2321
|
+
1986661051,
|
|
2322
|
+
2177026350,
|
|
2323
|
+
2456956037,
|
|
2324
|
+
2730485921,
|
|
2325
|
+
2820302411,
|
|
2326
|
+
3259730800,
|
|
2327
|
+
3345764771,
|
|
2328
|
+
3516065817,
|
|
2329
|
+
3600352804,
|
|
2330
|
+
4094571909,
|
|
2331
|
+
275423344,
|
|
2332
|
+
430227734,
|
|
2333
|
+
506948616,
|
|
2334
|
+
659060556,
|
|
2335
|
+
883997877,
|
|
2336
|
+
958139571,
|
|
2337
|
+
1322822218,
|
|
2338
|
+
1537002063,
|
|
2339
|
+
1747873779,
|
|
2340
|
+
1955562222,
|
|
2341
|
+
2024104815,
|
|
2342
|
+
2227730452,
|
|
2343
|
+
2361852424,
|
|
2344
|
+
2428436474,
|
|
2345
|
+
2756734187,
|
|
2346
|
+
3204031479,
|
|
2347
|
+
3329325298
|
|
2348
|
+
]);
|
|
2349
|
+
rotr = (x, n) => x >>> n | x << 32 - n;
|
|
2350
|
+
}
|
|
2351
|
+
});
|
|
2352
|
+
|
|
2118
2353
|
// packages/runtime/src/storage/signature.ts
|
|
2119
|
-
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
2120
2354
|
function sign(secret, projectId, path, expires) {
|
|
2121
2355
|
const payload = `${projectId}|${path}|${expires}`;
|
|
2122
|
-
return
|
|
2356
|
+
return hmacSha256Hex(secret, payload);
|
|
2123
2357
|
}
|
|
2124
2358
|
function signDownloadUrl(config, projectId, path, ttlSeconds = DEFAULT_SIGN_TTL_SECONDS) {
|
|
2125
2359
|
const expires = Math.floor(Date.now() / 1e3) + ttlSeconds;
|
|
@@ -2131,6 +2365,7 @@ var DEFAULT_SIGN_TTL_SECONDS, SIGN_EXPIRES_KEY, SIGN_SIGNATURE_KEY;
|
|
|
2131
2365
|
var init_signature = __esm({
|
|
2132
2366
|
"packages/runtime/src/storage/signature.ts"() {
|
|
2133
2367
|
"use strict";
|
|
2368
|
+
init_hmac_sha256();
|
|
2134
2369
|
DEFAULT_SIGN_TTL_SECONDS = 15 * 60;
|
|
2135
2370
|
SIGN_EXPIRES_KEY = "x-expires";
|
|
2136
2371
|
SIGN_SIGNATURE_KEY = "x-signature";
|
|
@@ -2360,7 +2595,7 @@ function createLocalStorageDriver(options) {
|
|
|
2360
2595
|
}
|
|
2361
2596
|
const root = bucketDir(projectId);
|
|
2362
2597
|
const metas = [];
|
|
2363
|
-
const walk = async (dir,
|
|
2598
|
+
const walk = async (dir, relative3) => {
|
|
2364
2599
|
let entries;
|
|
2365
2600
|
try {
|
|
2366
2601
|
entries = await readdir(dir, { withFileTypes: true });
|
|
@@ -2371,7 +2606,7 @@ function createLocalStorageDriver(options) {
|
|
|
2371
2606
|
for (const entry of entries) {
|
|
2372
2607
|
if (entry.name.endsWith(META_SUFFIX)) continue;
|
|
2373
2608
|
const full = join5(dir, entry.name);
|
|
2374
|
-
const rel =
|
|
2609
|
+
const rel = relative3 === "" ? entry.name : `${relative3}/${entry.name}`;
|
|
2375
2610
|
if (entry.isFile()) {
|
|
2376
2611
|
if (prefix !== void 0 && !rel.startsWith(prefix)) continue;
|
|
2377
2612
|
tasks.push(
|
|
@@ -2440,10 +2675,89 @@ var init_storage = __esm({
|
|
|
2440
2675
|
});
|
|
2441
2676
|
|
|
2442
2677
|
// packages/cli/src/sim/realtime.ts
|
|
2443
|
-
|
|
2678
|
+
function realtimeError(code, message) {
|
|
2679
|
+
return new Error(`[${code}] ${message}`);
|
|
2680
|
+
}
|
|
2681
|
+
function createSimRealtimeCapability() {
|
|
2682
|
+
const sim = new SimRealtime();
|
|
2683
|
+
const buffers = /* @__PURE__ */ new Map();
|
|
2684
|
+
const disposers = /* @__PURE__ */ new Map();
|
|
2685
|
+
let seq = 0;
|
|
2686
|
+
const handler = async (method, args) => {
|
|
2687
|
+
switch (method) {
|
|
2688
|
+
case "publish": {
|
|
2689
|
+
if (args.length > 2) {
|
|
2690
|
+
throw realtimeError(
|
|
2691
|
+
REALTIME_CODES.unsupportedArg,
|
|
2692
|
+
"\u672C\u5730\u5355\u8FDB\u7A0B\u5185\u5B58\u5E7F\u64AD\u65E0\u8FDE\u63A5\u8EAB\u4EFD\uFF0C\u4E0D\u652F\u6301 publish \u7684 except \u5B9E\u53C2"
|
|
2693
|
+
);
|
|
2694
|
+
}
|
|
2695
|
+
const [channel, data] = args;
|
|
2696
|
+
return sim.publish(channel, data);
|
|
2697
|
+
}
|
|
2698
|
+
case "subscribe": {
|
|
2699
|
+
if (buffers.size >= MAX_SUBSCRIPTIONS) {
|
|
2700
|
+
throw realtimeError(
|
|
2701
|
+
REALTIME_CODES.tooManySubscriptions,
|
|
2702
|
+
`\u672C\u5730\u8BA2\u9605\u6570\u5DF2\u8FBE\u4E0A\u9650 ${String(MAX_SUBSCRIPTIONS)}\uFF0C\u8BF7\u5148 unsubscribe`
|
|
2703
|
+
);
|
|
2704
|
+
}
|
|
2705
|
+
const [channel] = args;
|
|
2706
|
+
seq += 1;
|
|
2707
|
+
const id = `sub-${String(seq)}`;
|
|
2708
|
+
const buffer = [];
|
|
2709
|
+
const off = sim.subscribe(channel, (msg) => {
|
|
2710
|
+
buffer.push(msg);
|
|
2711
|
+
if (buffer.length > MAX_BUFFERED_MESSAGES) buffer.shift();
|
|
2712
|
+
});
|
|
2713
|
+
buffers.set(id, buffer);
|
|
2714
|
+
disposers.set(id, off);
|
|
2715
|
+
return { subscription: id, channel };
|
|
2716
|
+
}
|
|
2717
|
+
case "receive": {
|
|
2718
|
+
const buffer = buffers.get(args[0]);
|
|
2719
|
+
if (buffer === void 0) {
|
|
2720
|
+
throw realtimeError(
|
|
2721
|
+
REALTIME_CODES.subscriptionNotFound,
|
|
2722
|
+
`\u672C\u5730\u8BA2\u9605 "${String(args[0])}" \u4E0D\u5B58\u5728\u6216\u5DF2\u9000\u8BA2`
|
|
2723
|
+
);
|
|
2724
|
+
}
|
|
2725
|
+
return buffer.splice(0, buffer.length);
|
|
2726
|
+
}
|
|
2727
|
+
case "unsubscribe": {
|
|
2728
|
+
const id = args[0];
|
|
2729
|
+
const off = disposers.get(id);
|
|
2730
|
+
if (off === void 0) {
|
|
2731
|
+
throw realtimeError(
|
|
2732
|
+
REALTIME_CODES.subscriptionNotFound,
|
|
2733
|
+
`\u672C\u5730\u8BA2\u9605 "${id}" \u4E0D\u5B58\u5728\u6216\u5DF2\u9000\u8BA2`
|
|
2734
|
+
);
|
|
2735
|
+
}
|
|
2736
|
+
off();
|
|
2737
|
+
disposers.delete(id);
|
|
2738
|
+
buffers.delete(id);
|
|
2739
|
+
return { removed: true };
|
|
2740
|
+
}
|
|
2741
|
+
default:
|
|
2742
|
+
throw realtimeError(
|
|
2743
|
+
REALTIME_CODES.invalidMethod,
|
|
2744
|
+
`\u672A\u77E5\u7684 cloud.realtime \u65B9\u6CD5 "${method}"\uFF08\u53EF\u7528\uFF1A${REALTIME_CAPABILITY_METHODS.join(" / ")}\uFF09`
|
|
2745
|
+
);
|
|
2746
|
+
}
|
|
2747
|
+
};
|
|
2748
|
+
return {
|
|
2749
|
+
bundle: {
|
|
2750
|
+
capabilities: [{ name: "realtime", value: { [RPC_CAPABILITY_KEY]: true } }],
|
|
2751
|
+
rpcHandlers: { realtime: handler }
|
|
2752
|
+
},
|
|
2753
|
+
realtime: sim
|
|
2754
|
+
};
|
|
2755
|
+
}
|
|
2756
|
+
var SimRealtime, MAX_BUFFERED_MESSAGES, MAX_SUBSCRIPTIONS, REALTIME_CODES;
|
|
2444
2757
|
var init_realtime = __esm({
|
|
2445
2758
|
"packages/cli/src/sim/realtime.ts"() {
|
|
2446
2759
|
"use strict";
|
|
2760
|
+
init_capability_keys();
|
|
2447
2761
|
SimRealtime = class {
|
|
2448
2762
|
seq = 0;
|
|
2449
2763
|
subscribers = /* @__PURE__ */ new Map();
|
|
@@ -2483,6 +2797,9 @@ var init_realtime = __esm({
|
|
|
2483
2797
|
return this.subscribers.size;
|
|
2484
2798
|
}
|
|
2485
2799
|
};
|
|
2800
|
+
MAX_BUFFERED_MESSAGES = 64;
|
|
2801
|
+
MAX_SUBSCRIPTIONS = 64;
|
|
2802
|
+
REALTIME_CODES = REALTIME_CAPABILITY_CODES;
|
|
2486
2803
|
}
|
|
2487
2804
|
});
|
|
2488
2805
|
|
|
@@ -2538,12 +2855,12 @@ async function createSimRuntime(options) {
|
|
|
2538
2855
|
...options.baseUrl === void 0 ? {} : { baseUrl: options.baseUrl },
|
|
2539
2856
|
projectId: options.projectId ?? "local"
|
|
2540
2857
|
});
|
|
2541
|
-
const
|
|
2542
|
-
const bundle = mergeBundles([db.bundle, storage.bundle]);
|
|
2858
|
+
const simRealtime = createSimRealtimeCapability();
|
|
2859
|
+
const bundle = mergeBundles([db.bundle, storage.bundle, simRealtime.bundle]);
|
|
2543
2860
|
await db.engine.load();
|
|
2544
2861
|
return {
|
|
2545
2862
|
bundle,
|
|
2546
|
-
realtime,
|
|
2863
|
+
realtime: simRealtime.realtime,
|
|
2547
2864
|
db,
|
|
2548
2865
|
dispose: async () => {
|
|
2549
2866
|
await db.driver.close();
|
|
@@ -2647,7 +2964,12 @@ var init_boundary = __esm({
|
|
|
2647
2964
|
{
|
|
2648
2965
|
kind: "diff",
|
|
2649
2966
|
title: "\u65E0\u8DE8\u5B9E\u4F8B\u5E7F\u64AD",
|
|
2650
|
-
detail: "realtime \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"
|
|
2967
|
+
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"
|
|
2968
|
+
},
|
|
2969
|
+
{
|
|
2970
|
+
kind: "capability",
|
|
2971
|
+
title: "publish \u4E0D\u652F\u6301 except",
|
|
2972
|
+
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"
|
|
2651
2973
|
},
|
|
2652
2974
|
{
|
|
2653
2975
|
kind: "capability",
|
|
@@ -2928,6 +3250,11 @@ var init_dev = __esm({
|
|
|
2928
3250
|
});
|
|
2929
3251
|
|
|
2930
3252
|
// packages/cli/src/client.ts
|
|
3253
|
+
var client_exports = {};
|
|
3254
|
+
__export(client_exports, {
|
|
3255
|
+
createClient: () => createClient,
|
|
3256
|
+
resolveSlug: () => resolveSlug
|
|
3257
|
+
});
|
|
2931
3258
|
async function envelopeError(response, fallbackCode, parsed) {
|
|
2932
3259
|
const payload = parsed ?? null;
|
|
2933
3260
|
return new CliError(
|
|
@@ -3050,13 +3377,14 @@ function sha256Hex(content) {
|
|
|
3050
3377
|
return createHash3("sha256").update(content).digest("hex");
|
|
3051
3378
|
}
|
|
3052
3379
|
async function deploy(paths, options) {
|
|
3053
|
-
|
|
3380
|
+
await requireNetwork("adep deploy");
|
|
3381
|
+
const log = options.silent === true ? () => void 0 : options.log ?? ((line) => process.stdout.write(`${line}
|
|
3054
3382
|
`));
|
|
3055
3383
|
const client = await createClient(paths);
|
|
3056
3384
|
const cwd = resolve6(options.cwd);
|
|
3057
3385
|
const config = await loadConfig(cwd);
|
|
3058
3386
|
const slug = options.slug ?? config.name;
|
|
3059
|
-
const functionsDir = join10(cwd, config.functionsDir);
|
|
3387
|
+
const functionsDir = options.functionsDir === void 0 ? join10(cwd, config.functionsDir) : resolve6(cwd, options.functionsDir);
|
|
3060
3388
|
const local = await collectEntries(functionsDir);
|
|
3061
3389
|
if (Object.keys(local).length === 0) {
|
|
3062
3390
|
throw new CliError("NO_FUNCTIONS", `${functionsDir} \u4E0B\u6CA1\u6709\u51FD\u6570\u6587\u4EF6`);
|
|
@@ -3128,120 +3456,926 @@ var init_deploy = __esm({
|
|
|
3128
3456
|
init_auth();
|
|
3129
3457
|
init_client();
|
|
3130
3458
|
init_dev();
|
|
3459
|
+
init_net();
|
|
3131
3460
|
}
|
|
3132
3461
|
});
|
|
3133
3462
|
|
|
3134
|
-
// packages/cli/src/
|
|
3135
|
-
var
|
|
3136
|
-
__export(
|
|
3137
|
-
|
|
3138
|
-
dbRollback: () => dbRollback,
|
|
3139
|
-
dbSnapshotCreate: () => dbSnapshotCreate,
|
|
3140
|
-
dbSnapshotList: () => dbSnapshotList,
|
|
3141
|
-
dbSnapshotRestore: () => dbSnapshotRestore,
|
|
3142
|
-
dbStart: () => dbStart,
|
|
3143
|
-
dbStatus: () => dbStatus,
|
|
3144
|
-
dbStop: () => dbStop
|
|
3463
|
+
// packages/cli/src/prompt.ts
|
|
3464
|
+
var prompt_exports = {};
|
|
3465
|
+
__export(prompt_exports, {
|
|
3466
|
+
createPrompt: () => createPrompt
|
|
3145
3467
|
});
|
|
3146
|
-
import {
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
const
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
async
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
}
|
|
3156
|
-
async function dbStatus(paths, options) {
|
|
3157
|
-
const { client, project: project2 } = await open2(paths, options);
|
|
3158
|
-
return client.request(`/api/v1/projects/${project2}/database`);
|
|
3159
|
-
}
|
|
3160
|
-
async function dbStop(paths, options) {
|
|
3161
|
-
const { client, project: project2 } = await open2(paths, options);
|
|
3162
|
-
return client.request(`/api/v1/projects/${project2}/database`, {
|
|
3163
|
-
method: "DELETE"
|
|
3164
|
-
});
|
|
3165
|
-
}
|
|
3166
|
-
async function dbExec(paths, options) {
|
|
3167
|
-
const { client, project: project2 } = await open2(paths, options);
|
|
3168
|
-
return client.request(
|
|
3169
|
-
`/api/v1/projects/${project2}/database/console/sql`,
|
|
3170
|
-
{
|
|
3171
|
-
method: "POST",
|
|
3172
|
-
body: {
|
|
3173
|
-
sql: options.sql,
|
|
3174
|
-
...options.params === void 0 ? {} : { params: options.params },
|
|
3175
|
-
...options.confirmTable === void 0 ? {} : { confirmTable: options.confirmTable }
|
|
3176
|
-
}
|
|
3468
|
+
import { createInterface } from "node:readline/promises";
|
|
3469
|
+
import { Writable } from "node:stream";
|
|
3470
|
+
function createPrompt(input = process.stdin) {
|
|
3471
|
+
const rl = createInterface({ input, output: process.stdout, terminal: true });
|
|
3472
|
+
let muted = null;
|
|
3473
|
+
return {
|
|
3474
|
+
async ask(question) {
|
|
3475
|
+
const answer = await rl.question(question);
|
|
3476
|
+
return answer.trim();
|
|
3177
3477
|
},
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
});
|
|
3192
|
-
}
|
|
3193
|
-
async function dbSnapshotRestore(paths, options) {
|
|
3194
|
-
const { client, project: project2 } = await open2(paths, options);
|
|
3195
|
-
return client.request(
|
|
3196
|
-
`/api/v1/projects/${project2}/database/snapshots/${options.snapshotId}/restore`,
|
|
3197
|
-
{ method: "POST" }
|
|
3198
|
-
);
|
|
3199
|
-
}
|
|
3200
|
-
async function dbRollback(paths, options) {
|
|
3201
|
-
const { client, project: project2 } = await open2(paths, options);
|
|
3202
|
-
return client.request(
|
|
3203
|
-
`/api/v1/projects/${project2}/database/rollback`,
|
|
3204
|
-
{ method: "POST", body: { to: options.to } }
|
|
3205
|
-
);
|
|
3478
|
+
async askHidden(question) {
|
|
3479
|
+
muted = createInterface({ input, output: new MutedStream(), terminal: true });
|
|
3480
|
+
const answer = await muted.question(question);
|
|
3481
|
+
muted.close();
|
|
3482
|
+
muted = null;
|
|
3483
|
+
process.stdout.write("\n");
|
|
3484
|
+
return answer.trim();
|
|
3485
|
+
},
|
|
3486
|
+
close() {
|
|
3487
|
+
muted?.close();
|
|
3488
|
+
rl.close();
|
|
3489
|
+
}
|
|
3490
|
+
};
|
|
3206
3491
|
}
|
|
3207
|
-
var
|
|
3208
|
-
|
|
3492
|
+
var MutedStream;
|
|
3493
|
+
var init_prompt = __esm({
|
|
3494
|
+
"packages/cli/src/prompt.ts"() {
|
|
3209
3495
|
"use strict";
|
|
3210
|
-
|
|
3496
|
+
MutedStream = class extends Writable {
|
|
3497
|
+
write(_chunk, ...rest) {
|
|
3498
|
+
void rest;
|
|
3499
|
+
return true;
|
|
3500
|
+
}
|
|
3501
|
+
};
|
|
3211
3502
|
}
|
|
3212
3503
|
});
|
|
3213
3504
|
|
|
3214
|
-
// packages/cli/src/
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3505
|
+
// packages/cli/src/serve/banner.ts
|
|
3506
|
+
function isLoopback(host) {
|
|
3507
|
+
return host === "127.0.0.1" || host === "localhost" || host === "::1" || host === "[::1]";
|
|
3508
|
+
}
|
|
3509
|
+
function renderBanner(options) {
|
|
3510
|
+
const { host, port, projectName, functions, hasStatic, staticDir = "public/" } = options;
|
|
3511
|
+
const baseUrl = `http://${host}:${port}`;
|
|
3512
|
+
const loopback = isLoopback(host);
|
|
3513
|
+
const lines = [];
|
|
3514
|
+
lines.push("");
|
|
3515
|
+
lines.push("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
|
|
3516
|
+
lines.push("\u2551 adep serve \u2014 \u5F00\u53D1\u6001\u670D\u52A1\u5668 \u2551");
|
|
3517
|
+
lines.push("\u2551 \u26A0 \u8FD9\u4E0D\u662F\u751F\u4EA7\u670D\u52A1\u5668\uFF0C\u4E0D\u63D0\u4F9B TLS / \u96C6\u7FA4 / \u4F18\u96C5\u91CD\u542F \u2551");
|
|
3518
|
+
lines.push("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D");
|
|
3519
|
+
lines.push("");
|
|
3520
|
+
lines.push(` \u9879\u76EE: ${projectName}`);
|
|
3521
|
+
lines.push(` \u5730\u5740: ${baseUrl}`);
|
|
3522
|
+
lines.push(` \u7ED1\u5B9A: ${host}${loopback ? "\uFF08\u4EC5\u672C\u673A\u53EF\u8BBF\u95EE\uFF09" : "\uFF08\u26A0 \u5BF9\u5916\u66B4\u9732\uFF09"}`);
|
|
3523
|
+
lines.push("");
|
|
3524
|
+
lines.push(" \u80FD\u529B:");
|
|
3525
|
+
if (functions.length > 0) {
|
|
3526
|
+
lines.push(
|
|
3527
|
+
` - \u51FD\u6570\u8DEF\u7531: ${baseUrl}/api/{fn}\uFF08${functions.length} \u4E2A\u51FD\u6570: ${functions.join(", ")}\uFF09`
|
|
3528
|
+
);
|
|
3529
|
+
} else {
|
|
3530
|
+
lines.push(" - \u51FD\u6570\u8DEF\u7531: \u65E0\uFF08functions/ \u76EE\u5F55\u4E3A\u7A7A\uFF09");
|
|
3531
|
+
}
|
|
3532
|
+
if (hasStatic) {
|
|
3533
|
+
lines.push(` - \u9759\u6001\u6258\u7BA1: ${baseUrl}/ \u2192 ${staticDir}`);
|
|
3534
|
+
} else {
|
|
3535
|
+
lines.push(` - \u9759\u6001\u6258\u7BA1: \u65E0\uFF08${staticDir} \u76EE\u5F55\u4E0D\u5B58\u5728\uFF09`);
|
|
3536
|
+
}
|
|
3537
|
+
lines.push(" - \u7EC4\u4EF6\u9884\u89C8: Widget / Page \u4EA7\u7269\uFF08\u5982\u5DF2\u6784\u5EFA\uFF09");
|
|
3538
|
+
lines.push(` - \u5065\u5EB7\u68C0\u67E5: ${baseUrl}/healthz`);
|
|
3539
|
+
lines.push("");
|
|
3540
|
+
lines.push(" \u8FB9\u754C\uFF08\u5F00\u53D1\u6001\u9ED8\u8BA4\u503C\uFF0C\u4E0D\u53EF\u5728\u6B64\u6A21\u5F0F\u4E0B\u5F00\u542F\uFF09:");
|
|
3541
|
+
lines.push(" - \u65E0\u9274\u6743\uFF1A\u4EFB\u4F55\u4EBA\u53EF\u8C03\u7528\u6240\u6709\u51FD\u6570");
|
|
3542
|
+
lines.push(" - \u65E0\u9650\u6D41\uFF1A\u65E0 QPS / \u5E76\u53D1\u9650\u5236");
|
|
3543
|
+
lines.push(" - \u65E0\u914D\u989D\uFF1A\u65E0\u8C03\u7528\u6B21\u6570 / \u8D44\u6E90\u7528\u91CF\u9650\u5236");
|
|
3544
|
+
lines.push(" - \u65E0 TLS\uFF1A\u660E\u6587 HTTP\uFF0C\u4E0D\u652F\u6301 HTTPS");
|
|
3545
|
+
lines.push(" - \u65E0\u96C6\u7FA4\uFF1A\u5355\u8FDB\u7A0B\uFF0C\u4E0D\u652F\u6301\u591A\u5B9E\u4F8B");
|
|
3546
|
+
lines.push(" - \u65E0\u4F18\u96C5\u91CD\u542F\uFF1A\u8FDB\u7A0B\u9000\u51FA\u5373\u4E2D\u65AD");
|
|
3547
|
+
lines.push("");
|
|
3548
|
+
if (!loopback) {
|
|
3549
|
+
lines.push(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
|
|
3550
|
+
lines.push(" \u2502 \u26A0\u26A0\u26A0 \u5BF9\u5916\u66B4\u9732\u8B66\u544A \u2502");
|
|
3551
|
+
lines.push(" \u2502 \u2502");
|
|
3552
|
+
lines.push(` \u2502 \u5F53\u524D\u7ED1\u5B9A ${host.padEnd(43)}\u2502`);
|
|
3553
|
+
lines.push(" \u2502 \u5C40\u57DF\u7F51/\u516C\u7F51\u5185\u4EFB\u4F55\u4EBA\u90FD\u53EF\u8BBF\u95EE\u4F60\u7684\u51FD\u6570\u4E0E\u6570\u636E\u3002 \u2502");
|
|
3554
|
+
lines.push(" \u2502 \u65E0\u9274\u6743\u3001\u65E0\u9650\u6D41\u3001\u65E0\u914D\u989D\u2014\u2014\u8BF7\u52FF\u5728\u4E0D\u53EF\u4FE1\u7F51\u7EDC\u4E2D\u4F7F\u7528\u3002 \u2502");
|
|
3555
|
+
lines.push(" \u2502 \u2502");
|
|
3556
|
+
lines.push(" \u2502 \u9700\u8981\u751F\u4EA7\u90E8\u7F72\uFF1F\u4F7F\u7528 `adep deploy` \u90E8\u7F72\u5230\u5E73\u53F0\u3002 \u2502");
|
|
3557
|
+
lines.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
|
|
3558
|
+
lines.push("");
|
|
3559
|
+
}
|
|
3560
|
+
lines.push(" \u6309 Ctrl+C \u505C\u6B62\u670D\u52A1\u5668\u3002");
|
|
3561
|
+
lines.push("");
|
|
3562
|
+
return lines.join("\n");
|
|
3563
|
+
}
|
|
3564
|
+
var init_banner = __esm({
|
|
3565
|
+
"packages/cli/src/serve/banner.ts"() {
|
|
3566
|
+
"use strict";
|
|
3567
|
+
}
|
|
3222
3568
|
});
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
}
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3569
|
+
|
|
3570
|
+
// packages/cli/src/serve/server.ts
|
|
3571
|
+
var server_exports = {};
|
|
3572
|
+
__export(server_exports, {
|
|
3573
|
+
isLoopback: () => isLoopback,
|
|
3574
|
+
startServeServer: () => startServeServer
|
|
3575
|
+
});
|
|
3576
|
+
import { createServer as createServer2 } from "node:http";
|
|
3577
|
+
import { readdir as readdir4, readFile as readFile7, stat as stat6 } from "node:fs/promises";
|
|
3578
|
+
import { join as join11, relative, resolve as resolve7 } from "node:path";
|
|
3579
|
+
function envNumber(name) {
|
|
3580
|
+
const raw = process.env[name];
|
|
3581
|
+
if (raw === void 0 || raw.trim() === "") return void 0;
|
|
3582
|
+
const value = Number(raw);
|
|
3583
|
+
return Number.isInteger(value) && value >= 0 ? value : void 0;
|
|
3584
|
+
}
|
|
3585
|
+
function envString(name) {
|
|
3586
|
+
const raw = process.env[name];
|
|
3587
|
+
return raw === void 0 || raw.trim() === "" ? void 0 : raw.trim();
|
|
3588
|
+
}
|
|
3589
|
+
async function collectFunctions2(dir) {
|
|
3590
|
+
const files = {};
|
|
3591
|
+
const walk = async (sub, prefix) => {
|
|
3592
|
+
let entries;
|
|
3593
|
+
try {
|
|
3594
|
+
entries = await readdir4(sub, { withFileTypes: true });
|
|
3595
|
+
} catch {
|
|
3596
|
+
return;
|
|
3597
|
+
}
|
|
3598
|
+
for (const entry of entries) {
|
|
3599
|
+
const rel = prefix.length === 0 ? entry.name : `${prefix}/${entry.name}`;
|
|
3600
|
+
const full = join11(sub, entry.name);
|
|
3601
|
+
if (entry.isDirectory()) {
|
|
3602
|
+
await walk(full, rel);
|
|
3603
|
+
} else if (entry.isFile() && entry.name.endsWith(".ts")) {
|
|
3604
|
+
files[rel] = await readFile7(full, "utf8");
|
|
3605
|
+
}
|
|
3606
|
+
}
|
|
3607
|
+
};
|
|
3608
|
+
await walk(dir, "");
|
|
3609
|
+
return files;
|
|
3610
|
+
}
|
|
3611
|
+
function bodyOf2(req) {
|
|
3612
|
+
return new Promise((resolveBody, rejectBody) => {
|
|
3613
|
+
const chunks = [];
|
|
3614
|
+
req.on("data", (chunk) => chunks.push(chunk));
|
|
3615
|
+
req.on("end", () => {
|
|
3616
|
+
const raw = Buffer.concat(chunks).toString("utf8");
|
|
3617
|
+
if (raw.length === 0) {
|
|
3618
|
+
resolveBody(void 0);
|
|
3619
|
+
return;
|
|
3620
|
+
}
|
|
3621
|
+
try {
|
|
3622
|
+
resolveBody(JSON.parse(raw));
|
|
3623
|
+
} catch {
|
|
3624
|
+
resolveBody(raw);
|
|
3625
|
+
}
|
|
3626
|
+
});
|
|
3627
|
+
req.on("error", rejectBody);
|
|
3628
|
+
});
|
|
3629
|
+
}
|
|
3630
|
+
function writeJson2(res, status, payload) {
|
|
3631
|
+
res.writeHead(status, { "content-type": "application/json" });
|
|
3632
|
+
res.end(JSON.stringify(payload));
|
|
3633
|
+
}
|
|
3634
|
+
function contentTypeFor(path) {
|
|
3635
|
+
const ext = path.slice(path.lastIndexOf(".")).toLowerCase();
|
|
3636
|
+
return MIME_TYPES[ext] ?? "application/octet-stream";
|
|
3637
|
+
}
|
|
3638
|
+
async function startServeServer(options) {
|
|
3639
|
+
const cwd = resolve7(options.cwd);
|
|
3640
|
+
const log = options.log ?? ((line) => process.stdout.write(`${line}
|
|
3641
|
+
`));
|
|
3642
|
+
const host = options.host ?? envString("HOST") ?? "127.0.0.1";
|
|
3643
|
+
const port = options.port ?? envNumber("PORT") ?? 8787;
|
|
3644
|
+
const staticDir = resolve7(
|
|
3645
|
+
cwd,
|
|
3646
|
+
options.staticDir ?? envString("ADEP_SERVE_STATIC_DIR") ?? "public"
|
|
3647
|
+
);
|
|
3648
|
+
const config = await loadConfig(cwd);
|
|
3649
|
+
const functionsDir = join11(cwd, config.functionsDir);
|
|
3650
|
+
let hasStatic = false;
|
|
3651
|
+
try {
|
|
3652
|
+
const publicStat = await stat6(staticDir);
|
|
3653
|
+
hasStatic = publicStat.isDirectory();
|
|
3654
|
+
} catch {
|
|
3655
|
+
hasStatic = false;
|
|
3656
|
+
}
|
|
3657
|
+
const files = await collectFunctions2(functionsDir);
|
|
3658
|
+
const functionNames = Object.keys(files).filter((f) => f.endsWith(".ts")).map((f) => f.slice(0, -3));
|
|
3659
|
+
const envText = await readFile7(join11(cwd, ".env.local"), "utf8").catch(() => "");
|
|
3660
|
+
const env = parseEnvFile(envText);
|
|
3661
|
+
const simEnv = await loadSimEnv(cwd).catch(() => ({}));
|
|
3662
|
+
const runtime = await createSimRuntime({
|
|
3663
|
+
cwd,
|
|
3664
|
+
projectId: "local",
|
|
3665
|
+
baseUrl: `http://${host}:${port}`,
|
|
3666
|
+
log
|
|
3667
|
+
});
|
|
3668
|
+
const executor = new WorkerFunctionExecutor();
|
|
3669
|
+
const dbBundle = runtime.bundle;
|
|
3670
|
+
const invokeHandler = createSimInvokeHandler({ executor, files });
|
|
3671
|
+
const buildInput = async (fnName, url, req) => {
|
|
3672
|
+
const query = {};
|
|
3673
|
+
for (const key of new Set(url.searchParams.keys())) {
|
|
3674
|
+
const values = url.searchParams.getAll(key);
|
|
3675
|
+
query[key] = values.length > 1 ? values.join(",") : values[0] ?? "";
|
|
3676
|
+
}
|
|
3677
|
+
const headers = {};
|
|
3678
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
3679
|
+
if (typeof value === "string") headers[key] = value;
|
|
3680
|
+
}
|
|
3681
|
+
const body = req.method === "GET" || req.method === "HEAD" ? void 0 : await bodyOf2(req);
|
|
3682
|
+
const hasEnv = Object.keys(env).length > 0 || Object.keys(simEnv).length > 0;
|
|
3683
|
+
const mergedEnv = { ...simEnv, ...env };
|
|
3684
|
+
return {
|
|
3685
|
+
project: { id: "local", slug: config.name },
|
|
3686
|
+
fn: { id: fnName, name: fnName },
|
|
3687
|
+
files,
|
|
3688
|
+
entry: `${fnName}.ts`,
|
|
3689
|
+
request: {
|
|
3690
|
+
method: req.method ?? "GET",
|
|
3691
|
+
path: url.pathname,
|
|
3692
|
+
query,
|
|
3693
|
+
headers,
|
|
3694
|
+
...body === void 0 ? {} : { body }
|
|
3695
|
+
},
|
|
3696
|
+
capabilities: dbBundle.capabilities,
|
|
3697
|
+
rpcHandlers: {
|
|
3698
|
+
...dbBundle.rpcHandlers,
|
|
3699
|
+
invoke: invokeHandler
|
|
3700
|
+
},
|
|
3701
|
+
timeoutMs: 1e4,
|
|
3702
|
+
...hasEnv ? { env: mergedEnv } : {}
|
|
3703
|
+
};
|
|
3704
|
+
};
|
|
3705
|
+
const serveStatic = async (pathname, res) => {
|
|
3706
|
+
if (!hasStatic) return false;
|
|
3707
|
+
const safePath = pathname.replace(/\.\.\//g, "").replace(/^\//, "");
|
|
3708
|
+
const filePath = join11(staticDir, safePath);
|
|
3709
|
+
const resolvedPath = safePath === "" || safePath === "/" ? join11(filePath, "index.html") : filePath;
|
|
3710
|
+
try {
|
|
3711
|
+
const fileStat = await stat6(resolvedPath);
|
|
3712
|
+
if (fileStat.isDirectory()) {
|
|
3713
|
+
const indexPath = join11(resolvedPath, "index.html");
|
|
3714
|
+
try {
|
|
3715
|
+
const indexStat = await stat6(indexPath);
|
|
3716
|
+
if (indexStat.isFile()) {
|
|
3717
|
+
const content2 = await readFile7(indexPath);
|
|
3718
|
+
res.writeHead(200, { "content-type": contentTypeFor(indexPath) });
|
|
3719
|
+
res.end(content2);
|
|
3720
|
+
return true;
|
|
3721
|
+
}
|
|
3722
|
+
} catch {
|
|
3723
|
+
}
|
|
3724
|
+
return false;
|
|
3725
|
+
}
|
|
3726
|
+
const content = await readFile7(resolvedPath);
|
|
3727
|
+
res.writeHead(200, { "content-type": contentTypeFor(resolvedPath) });
|
|
3728
|
+
res.end(content);
|
|
3729
|
+
return true;
|
|
3730
|
+
} catch {
|
|
3731
|
+
return false;
|
|
3732
|
+
}
|
|
3733
|
+
};
|
|
3734
|
+
const handle = async (req, res) => {
|
|
3735
|
+
const url = new URL(req.url ?? "/", `http://${host}:${port}`);
|
|
3736
|
+
const pathname = url.pathname;
|
|
3737
|
+
if (pathname === "/api" || pathname.startsWith("/api/")) {
|
|
3738
|
+
const fnName = pathname === "/api" ? "" : pathname.slice("/api/".length).split("/")[0];
|
|
3739
|
+
if (fnName === void 0 || fnName.length === 0) {
|
|
3740
|
+
writeJson2(res, 400, {
|
|
3741
|
+
error: { code: "FN_NAME_REQUIRED", message: "\u4EE5 /api/{fnName} \u8C03\u7528\u51FD\u6570" }
|
|
3742
|
+
});
|
|
3743
|
+
return;
|
|
3744
|
+
}
|
|
3745
|
+
const entry = `${fnName}.ts`;
|
|
3746
|
+
const source = files[entry];
|
|
3747
|
+
if (source === void 0) {
|
|
3748
|
+
log(`[serve] ${req.method ?? "GET"} ${pathname} -> 404\uFF08\u51FD\u6570\u4E0D\u5B58\u5728\uFF09`);
|
|
3749
|
+
writeJson2(res, 404, { error: { code: "FN_NOT_FOUND", message: `\u51FD\u6570 "${fnName}" \u4E0D\u5B58\u5728` } });
|
|
3750
|
+
return;
|
|
3751
|
+
}
|
|
3752
|
+
const input = await buildInput(fnName, url, req);
|
|
3753
|
+
const startedAt = performance.now();
|
|
3754
|
+
try {
|
|
3755
|
+
const result = await executor.execute(input);
|
|
3756
|
+
const durationMs = Math.round(performance.now() - startedAt);
|
|
3757
|
+
log(`[serve] ${req.method ?? "GET"} ${pathname} -> 200 ${durationMs}ms`);
|
|
3758
|
+
writeJson2(res, 200, result.body === void 0 ? null : result.body);
|
|
3759
|
+
} catch (error) {
|
|
3760
|
+
const durationMs = Math.round(performance.now() - startedAt);
|
|
3761
|
+
if (error instanceof ExecutorError) {
|
|
3762
|
+
log(
|
|
3763
|
+
`[serve] ${req.method ?? "GET"} ${pathname} -> ${error.status} ${durationMs}ms (${error.code})`
|
|
3764
|
+
);
|
|
3765
|
+
writeJson2(res, error.status, { error: { code: error.code, message: error.message } });
|
|
3766
|
+
return;
|
|
3767
|
+
}
|
|
3768
|
+
log(`[serve] ${req.method ?? "GET"} ${pathname} -> 500 ${durationMs}ms`);
|
|
3769
|
+
writeJson2(res, 500, {
|
|
3770
|
+
error: {
|
|
3771
|
+
code: "FN_EXEC_ERROR",
|
|
3772
|
+
message: error instanceof Error ? error.message : "\u51FD\u6570\u6267\u884C\u5931\u8D25"
|
|
3773
|
+
}
|
|
3774
|
+
});
|
|
3775
|
+
}
|
|
3776
|
+
return;
|
|
3777
|
+
}
|
|
3778
|
+
if (pathname === "/healthz") {
|
|
3779
|
+
writeJson2(res, 200, {
|
|
3780
|
+
status: "ok",
|
|
3781
|
+
service: "adep-serve",
|
|
3782
|
+
project: config.name
|
|
3783
|
+
});
|
|
3784
|
+
return;
|
|
3785
|
+
}
|
|
3786
|
+
const served = await serveStatic(pathname, res);
|
|
3787
|
+
if (served) return;
|
|
3788
|
+
if (pathname.startsWith("/_preview/")) {
|
|
3789
|
+
const widgetName = pathname.slice("/_preview/".length).split("/")[0];
|
|
3790
|
+
if (widgetName !== void 0 && widgetName.length > 0) {
|
|
3791
|
+
const widgetDir = join11(cwd, ".adep", "widgets", widgetName);
|
|
3792
|
+
try {
|
|
3793
|
+
const widgetStat = await stat6(widgetDir);
|
|
3794
|
+
if (widgetStat.isDirectory()) {
|
|
3795
|
+
const indexPath = join11(widgetDir, "index.html");
|
|
3796
|
+
try {
|
|
3797
|
+
const content = await readFile7(indexPath, "utf8");
|
|
3798
|
+
res.writeHead(200, { "content-type": "text/html; charset=utf-8" });
|
|
3799
|
+
res.end(content);
|
|
3800
|
+
return;
|
|
3801
|
+
} catch {
|
|
3802
|
+
}
|
|
3803
|
+
}
|
|
3804
|
+
} catch {
|
|
3805
|
+
}
|
|
3806
|
+
}
|
|
3807
|
+
writeJson2(res, 404, { error: { code: "WIDGET_NOT_FOUND", message: "\u7EC4\u4EF6\u4EA7\u7269\u4E0D\u5B58\u5728" } });
|
|
3808
|
+
return;
|
|
3809
|
+
}
|
|
3810
|
+
if (pathname === "/" || pathname === "") {
|
|
3811
|
+
writeJson2(res, 200, {
|
|
3812
|
+
service: "adep-serve",
|
|
3813
|
+
mode: "development",
|
|
3814
|
+
project: config.name,
|
|
3815
|
+
functions: functionNames,
|
|
3816
|
+
static: hasStatic,
|
|
3817
|
+
endpoints: {
|
|
3818
|
+
functions: "/api/{fn}",
|
|
3819
|
+
static: `/ \u2192 ${staticDir}`,
|
|
3820
|
+
preview: "/_preview/{widget}",
|
|
3821
|
+
healthz: "/healthz"
|
|
3822
|
+
},
|
|
3823
|
+
warning: "\u8FD9\u662F\u5F00\u53D1\u6001\u670D\u52A1\u5668\uFF0C\u4E0D\u662F\u751F\u4EA7\u670D\u52A1\u5668"
|
|
3824
|
+
});
|
|
3825
|
+
return;
|
|
3826
|
+
}
|
|
3827
|
+
writeJson2(res, 404, { error: { code: "NOT_FOUND", message: `\u8DEF\u5F84 "${pathname}" \u4E0D\u5B58\u5728` } });
|
|
3828
|
+
};
|
|
3829
|
+
const server = createServer2((req, res) => {
|
|
3830
|
+
void handle(req, res).catch((error) => {
|
|
3831
|
+
log(`[serve] \u672A\u5904\u7406\u9519\u8BEF: ${error instanceof Error ? error.message : String(error)}`);
|
|
3832
|
+
if (!res.headersSent) {
|
|
3833
|
+
writeJson2(res, 500, { error: { code: "INTERNAL_ERROR", message: "\u670D\u52A1\u5668\u5185\u90E8\u9519\u8BEF" } });
|
|
3834
|
+
}
|
|
3835
|
+
});
|
|
3836
|
+
});
|
|
3837
|
+
const actualPort = await new Promise((resolveListen, rejectListen) => {
|
|
3838
|
+
server.once("error", rejectListen);
|
|
3839
|
+
server.listen(port, host, () => {
|
|
3840
|
+
server.off("error", rejectListen);
|
|
3841
|
+
const addr = server.address();
|
|
3842
|
+
if (addr === null || typeof addr === "string") {
|
|
3843
|
+
resolveListen(port);
|
|
3844
|
+
} else {
|
|
3845
|
+
resolveListen(addr.port);
|
|
3846
|
+
}
|
|
3847
|
+
});
|
|
3848
|
+
});
|
|
3849
|
+
const banner = renderBanner({
|
|
3850
|
+
host,
|
|
3851
|
+
port: actualPort,
|
|
3852
|
+
projectName: config.name,
|
|
3853
|
+
functions: functionNames,
|
|
3854
|
+
hasStatic,
|
|
3855
|
+
staticDir: relative(cwd, staticDir).length > 0 ? relative(cwd, staticDir) : staticDir
|
|
3856
|
+
});
|
|
3857
|
+
log(banner);
|
|
3858
|
+
return {
|
|
3859
|
+
port: actualPort,
|
|
3860
|
+
host,
|
|
3861
|
+
baseUrl: `http://${host}:${actualPort}`,
|
|
3862
|
+
close: async () => {
|
|
3863
|
+
await new Promise((resolveClose) => {
|
|
3864
|
+
server.close(() => resolveClose());
|
|
3865
|
+
});
|
|
3866
|
+
}
|
|
3867
|
+
};
|
|
3868
|
+
}
|
|
3869
|
+
var MIME_TYPES;
|
|
3870
|
+
var init_server = __esm({
|
|
3871
|
+
"packages/cli/src/serve/server.ts"() {
|
|
3872
|
+
"use strict";
|
|
3873
|
+
init_executor();
|
|
3874
|
+
init_worker_executor();
|
|
3875
|
+
init_runtime();
|
|
3876
|
+
init_env();
|
|
3877
|
+
init_invoke();
|
|
3878
|
+
init_dev();
|
|
3879
|
+
init_banner();
|
|
3880
|
+
MIME_TYPES = {
|
|
3881
|
+
".html": "text/html; charset=utf-8",
|
|
3882
|
+
".htm": "text/html; charset=utf-8",
|
|
3883
|
+
".css": "text/css; charset=utf-8",
|
|
3884
|
+
".js": "application/javascript; charset=utf-8",
|
|
3885
|
+
".mjs": "application/javascript; charset=utf-8",
|
|
3886
|
+
".json": "application/json; charset=utf-8",
|
|
3887
|
+
".png": "image/png",
|
|
3888
|
+
".jpg": "image/jpeg",
|
|
3889
|
+
".jpeg": "image/jpeg",
|
|
3890
|
+
".gif": "image/gif",
|
|
3891
|
+
".svg": "image/svg+xml",
|
|
3892
|
+
".ico": "image/x-icon",
|
|
3893
|
+
".woff": "font/woff",
|
|
3894
|
+
".woff2": "font/woff2",
|
|
3895
|
+
".ttf": "font/ttf",
|
|
3896
|
+
".txt": "text/plain; charset=utf-8",
|
|
3897
|
+
".md": "text/markdown; charset=utf-8",
|
|
3898
|
+
".pdf": "application/pdf",
|
|
3899
|
+
".map": "application/json"
|
|
3900
|
+
};
|
|
3901
|
+
}
|
|
3902
|
+
});
|
|
3903
|
+
|
|
3904
|
+
// packages/cli/src/projects.ts
|
|
3905
|
+
var projects_exports = {};
|
|
3906
|
+
__export(projects_exports, {
|
|
3907
|
+
projectsCreate: () => projectsCreate,
|
|
3908
|
+
projectsInfo: () => projectsInfo,
|
|
3909
|
+
projectsList: () => projectsList
|
|
3910
|
+
});
|
|
3911
|
+
function requireSlug(slug, hint) {
|
|
3912
|
+
if (slug === void 0 || slug.trim().length === 0) {
|
|
3913
|
+
throw new CliError("INVALID_SLUG", `\u7F3A\u5C11\u9879\u76EE slug\uFF1A${hint}`);
|
|
3914
|
+
}
|
|
3915
|
+
return slug.trim();
|
|
3916
|
+
}
|
|
3917
|
+
async function projectsCreate(paths, options) {
|
|
3918
|
+
await requireNetworkGuard();
|
|
3919
|
+
const client = await createClient(paths);
|
|
3920
|
+
const slug = requireSlug(options.slug, "adep projects create <slug>");
|
|
3921
|
+
const name = options.name ?? slug;
|
|
3922
|
+
const body = { slug, name };
|
|
3923
|
+
if (options.spaceId !== void 0) body.spaceId = options.spaceId;
|
|
3924
|
+
const created = await client.request(
|
|
3925
|
+
"/api/v1/projects",
|
|
3926
|
+
{ body },
|
|
3927
|
+
"PROJECT_CREATE_FAILED"
|
|
3928
|
+
);
|
|
3929
|
+
if (created.url === void 0 || created.url.length === 0) {
|
|
3930
|
+
throw new CliError("PROJECT_CREATE_FAILED", "\u5E73\u53F0\u672A\u8FD4\u56DE\u9879\u76EE\u5730\u5740\uFF0C\u65E0\u6CD5\u8F93\u51FA\u5B50\u57DF URL");
|
|
3931
|
+
}
|
|
3932
|
+
return created;
|
|
3933
|
+
}
|
|
3934
|
+
async function projectsList(paths) {
|
|
3935
|
+
await requireNetworkGuard();
|
|
3936
|
+
const client = await createClient(paths);
|
|
3937
|
+
const result = await client.request(
|
|
3938
|
+
"/api/v1/projects",
|
|
3939
|
+
{},
|
|
3940
|
+
"PROJECT_LIST_FAILED"
|
|
3941
|
+
);
|
|
3942
|
+
return result.projects;
|
|
3943
|
+
}
|
|
3944
|
+
async function projectsInfo(paths, options) {
|
|
3945
|
+
await requireNetworkGuard();
|
|
3946
|
+
const slug = requireSlug(options.slug, "adep projects info <slug>");
|
|
3947
|
+
const projects = await projectsList(paths);
|
|
3948
|
+
const match = projects.find((project2) => project2.slug === slug);
|
|
3949
|
+
if (match === void 0) {
|
|
3950
|
+
throw new CliError("PROJECT_NOT_FOUND", `\u9879\u76EE "${slug}" \u4E0D\u5B58\u5728\u6216\u4F60\u6CA1\u6709\u8BBF\u95EE\u6743\u9650`);
|
|
3951
|
+
}
|
|
3952
|
+
return match;
|
|
3953
|
+
}
|
|
3954
|
+
async function requireNetworkGuard() {
|
|
3955
|
+
const { requireNetwork: requireNetwork2 } = await Promise.resolve().then(() => (init_net(), net_exports));
|
|
3956
|
+
await requireNetwork2("adep projects");
|
|
3957
|
+
}
|
|
3958
|
+
var init_projects = __esm({
|
|
3959
|
+
"packages/cli/src/projects.ts"() {
|
|
3960
|
+
"use strict";
|
|
3961
|
+
init_auth();
|
|
3962
|
+
init_client();
|
|
3963
|
+
}
|
|
3964
|
+
});
|
|
3965
|
+
|
|
3966
|
+
// packages/cli/src/functions.ts
|
|
3967
|
+
var functions_exports = {};
|
|
3968
|
+
__export(functions_exports, {
|
|
3969
|
+
functionsDeploy: () => functionsDeploy,
|
|
3970
|
+
functionsList: () => functionsList,
|
|
3971
|
+
functionsLogs: () => functionsLogs
|
|
3972
|
+
});
|
|
3973
|
+
import { resolve as resolve8 } from "node:path";
|
|
3974
|
+
async function functionsDeploy(paths, options) {
|
|
3975
|
+
const startedAt = Date.now();
|
|
3976
|
+
const result = await deploy(paths, {
|
|
3977
|
+
cwd: options.cwd,
|
|
3978
|
+
...options.slug === void 0 ? {} : { slug: options.slug },
|
|
3979
|
+
...options.dir === void 0 ? {} : { functionsDir: resolve8(options.cwd, options.dir) },
|
|
3980
|
+
silent: true
|
|
3981
|
+
});
|
|
3982
|
+
return { ...result, elapsedSeconds: (Date.now() - startedAt) / 1e3 };
|
|
3983
|
+
}
|
|
3984
|
+
async function functionsList(paths, options) {
|
|
3985
|
+
const client = await createClient(paths);
|
|
3986
|
+
const project2 = await resolveProject(client, options);
|
|
3987
|
+
const result = await client.request(
|
|
3988
|
+
`/api/v1/projects/${project2.id}/functions`,
|
|
3989
|
+
{},
|
|
3990
|
+
"FUNCTION_LIST_FAILED"
|
|
3991
|
+
);
|
|
3992
|
+
return {
|
|
3993
|
+
projectId: project2.id,
|
|
3994
|
+
slug: project2.slug,
|
|
3995
|
+
baseUrl: project2.url,
|
|
3996
|
+
functions: result.functions
|
|
3997
|
+
};
|
|
3998
|
+
}
|
|
3999
|
+
async function functionsLogs(paths, options) {
|
|
4000
|
+
if (options.name === void 0 || options.name.trim().length === 0) {
|
|
4001
|
+
throw new CliError("INVALID_ARGUMENT", "\u7F3A\u5C11\u51FD\u6570\u540D\uFF1Aadep functions logs <name>");
|
|
4002
|
+
}
|
|
4003
|
+
const client = await createClient(paths);
|
|
4004
|
+
const project2 = await resolveProject(client, options);
|
|
4005
|
+
const listed = await client.request(
|
|
4006
|
+
`/api/v1/projects/${project2.id}/functions`,
|
|
4007
|
+
{},
|
|
4008
|
+
"FUNCTION_LIST_FAILED"
|
|
4009
|
+
);
|
|
4010
|
+
const target = listed.functions.find((fn) => fn.name === options.name);
|
|
4011
|
+
if (target === void 0) {
|
|
4012
|
+
throw new CliError("FN_NOT_FOUND", `\u51FD\u6570 "${options.name}" \u4E0D\u5B58\u5728\u4E8E\u9879\u76EE "${project2.slug}"`);
|
|
4013
|
+
}
|
|
4014
|
+
const tail = options.tail === void 0 ? "" : `?tail=${encodeURIComponent(String(options.tail))}`;
|
|
4015
|
+
const result = await client.request(
|
|
4016
|
+
`/api/v1/functions/${target.id}/logs${tail}`,
|
|
4017
|
+
{},
|
|
4018
|
+
"FUNCTION_LOGS_FAILED"
|
|
4019
|
+
);
|
|
4020
|
+
return { functionId: target.id, name: target.name, logs: result.logs };
|
|
4021
|
+
}
|
|
4022
|
+
async function resolveProject(client, options) {
|
|
4023
|
+
const slug = await resolveSlug(resolve8(options.cwd), options.slug);
|
|
4024
|
+
const projects = await projectsListFrom(client);
|
|
4025
|
+
const match = projects.find((project2) => project2.slug === slug);
|
|
4026
|
+
if (match === void 0) {
|
|
4027
|
+
throw new CliError(
|
|
4028
|
+
"PROJECT_NOT_FOUND",
|
|
4029
|
+
`\u5E73\u53F0\u9879\u76EE "${slug}" \u4E0D\u5B58\u5728\u6216\u4F60\u6CA1\u6709\u8BBF\u95EE\u6743\u9650\uFF1A\u5148\u6267\u884C adep projects create ${slug}`
|
|
4030
|
+
);
|
|
4031
|
+
}
|
|
4032
|
+
return match;
|
|
4033
|
+
}
|
|
4034
|
+
async function projectsListFrom(client) {
|
|
4035
|
+
const result = await client.request("/api/v1/projects", {}, "PROJECT_LIST_FAILED");
|
|
4036
|
+
return result.projects;
|
|
4037
|
+
}
|
|
4038
|
+
var init_functions = __esm({
|
|
4039
|
+
"packages/cli/src/functions.ts"() {
|
|
4040
|
+
"use strict";
|
|
4041
|
+
init_auth();
|
|
4042
|
+
init_client();
|
|
4043
|
+
init_deploy();
|
|
4044
|
+
}
|
|
4045
|
+
});
|
|
4046
|
+
|
|
4047
|
+
// packages/cli/src/mcp.ts
|
|
4048
|
+
var mcp_exports = {};
|
|
4049
|
+
__export(mcp_exports, {
|
|
4050
|
+
mcpList: () => mcpList,
|
|
4051
|
+
mcpPublish: () => mcpPublish,
|
|
4052
|
+
mcpUnpublish: () => mcpUnpublish
|
|
4053
|
+
});
|
|
4054
|
+
import { resolve as resolve9 } from "node:path";
|
|
4055
|
+
async function mcpPublish(paths, options) {
|
|
4056
|
+
const fn = requireFunctionName(options.fn);
|
|
4057
|
+
const client = await createClient(paths);
|
|
4058
|
+
const project2 = await resolveProject2(client, options);
|
|
4059
|
+
const target = await resolveFunction(client, project2, fn);
|
|
4060
|
+
const body = {};
|
|
4061
|
+
if (options.toolName !== void 0 && options.toolName.trim().length > 0) {
|
|
4062
|
+
body.toolName = options.toolName.trim();
|
|
4063
|
+
}
|
|
4064
|
+
if (options.description !== void 0 && options.description.length > 0) {
|
|
4065
|
+
body.description = options.description;
|
|
4066
|
+
}
|
|
4067
|
+
const tool = await client.request(
|
|
4068
|
+
`/api/v1/functions/${target.id}/mcp-publish`,
|
|
4069
|
+
{ method: "POST", ...Object.keys(body).length === 0 ? {} : { body } },
|
|
4070
|
+
"MCP_PUBLISH_FAILED"
|
|
4071
|
+
);
|
|
4072
|
+
return { projectId: project2.id, tool };
|
|
4073
|
+
}
|
|
4074
|
+
async function mcpUnpublish(paths, options) {
|
|
4075
|
+
const fn = requireFunctionName(options.fn);
|
|
4076
|
+
const client = await createClient(paths);
|
|
4077
|
+
const project2 = await resolveProject2(client, options);
|
|
4078
|
+
const target = await resolveFunction(client, project2, fn);
|
|
4079
|
+
const toolName = options.toolName?.trim() || fn;
|
|
4080
|
+
const result = await client.request(
|
|
4081
|
+
`/api/v1/functions/${target.id}/mcp-publish?tool=${encodeURIComponent(toolName)}`,
|
|
4082
|
+
{ method: "DELETE" },
|
|
4083
|
+
"MCP_UNPUBLISH_FAILED"
|
|
4084
|
+
);
|
|
4085
|
+
return { projectId: project2.id, toolName, removed: result.unpublished === true };
|
|
4086
|
+
}
|
|
4087
|
+
async function mcpList(paths, options) {
|
|
4088
|
+
const client = await createClient(paths);
|
|
4089
|
+
const project2 = await resolveProject2(client, options);
|
|
4090
|
+
const endpoint = `${project2.url.replace(/\/+$/, "")}/mcp`;
|
|
4091
|
+
let response;
|
|
4092
|
+
try {
|
|
4093
|
+
response = await fetch(endpoint, {
|
|
4094
|
+
method: "POST",
|
|
4095
|
+
headers: { "content-type": "application/json", cookie: client.cookie },
|
|
4096
|
+
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "tools/list" })
|
|
4097
|
+
});
|
|
4098
|
+
} catch (error) {
|
|
4099
|
+
throw new CliError(
|
|
4100
|
+
"SERVER_UNREACHABLE",
|
|
4101
|
+
`\u65E0\u6CD5\u8FDE\u63A5 MCP \u7AEF\u70B9 ${endpoint}\uFF1A${error instanceof Error ? error.message : String(error)}`
|
|
4102
|
+
);
|
|
4103
|
+
}
|
|
4104
|
+
const parsed = await response.json().catch(() => null);
|
|
4105
|
+
if (!response.ok) {
|
|
4106
|
+
const envelope = parsed ?? null;
|
|
4107
|
+
throw new CliError(
|
|
4108
|
+
envelope?.error?.code ?? "MCP_LIST_FAILED",
|
|
4109
|
+
envelope?.error?.message ?? `MCP \u7AEF\u70B9\u8FD4\u56DE HTTP ${response.status}`
|
|
4110
|
+
);
|
|
4111
|
+
}
|
|
4112
|
+
const rpcError = parsed?.error;
|
|
4113
|
+
if (rpcError !== void 0) {
|
|
4114
|
+
throw new CliError(
|
|
4115
|
+
rpcError.code ?? "MCP_LIST_FAILED",
|
|
4116
|
+
rpcError.message ?? "MCP tools/list \u5931\u8D25"
|
|
4117
|
+
);
|
|
4118
|
+
}
|
|
4119
|
+
return {
|
|
4120
|
+
projectId: project2.id,
|
|
4121
|
+
slug: project2.slug,
|
|
4122
|
+
endpoint,
|
|
4123
|
+
tools: parsed?.result?.tools ?? []
|
|
4124
|
+
};
|
|
4125
|
+
}
|
|
4126
|
+
function requireFunctionName(fn) {
|
|
4127
|
+
if (fn === void 0 || fn.trim().length === 0) {
|
|
4128
|
+
throw new CliError("INVALID_ARGUMENT", "\u7F3A\u5C11\u51FD\u6570\u540D\uFF1Aadep mcp publish --function <fn>");
|
|
4129
|
+
}
|
|
4130
|
+
return fn.trim();
|
|
4131
|
+
}
|
|
4132
|
+
async function resolveProject2(client, options) {
|
|
4133
|
+
const slug = await resolveSlug(resolve9(options.cwd), options.slug);
|
|
4134
|
+
const listed = await client.request("/api/v1/projects", {}, "PROJECT_LIST_FAILED");
|
|
4135
|
+
const match = listed.projects.find((project2) => project2.slug === slug);
|
|
4136
|
+
if (match === void 0) {
|
|
4137
|
+
throw new CliError(
|
|
4138
|
+
"PROJECT_NOT_FOUND",
|
|
4139
|
+
`\u5E73\u53F0\u9879\u76EE "${slug}" \u4E0D\u5B58\u5728\u6216\u4F60\u6CA1\u6709\u8BBF\u95EE\u6743\u9650\uFF1A\u5148\u6267\u884C adep projects create ${slug}`
|
|
4140
|
+
);
|
|
4141
|
+
}
|
|
4142
|
+
return { id: match.id, slug: match.slug, url: match.url };
|
|
4143
|
+
}
|
|
4144
|
+
async function resolveFunction(client, project2, name) {
|
|
4145
|
+
const listed = await client.request(`/api/v1/projects/${project2.id}/functions`, {}, "FUNCTION_LIST_FAILED");
|
|
4146
|
+
const target = listed.functions.find((fn) => fn.name === name);
|
|
4147
|
+
if (target === void 0) {
|
|
4148
|
+
throw new CliError("FN_NOT_FOUND", `\u51FD\u6570 "${name}" \u4E0D\u5B58\u5728\u4E8E\u9879\u76EE "${project2.slug}"`);
|
|
4149
|
+
}
|
|
4150
|
+
return { id: target.id, name: target.name };
|
|
4151
|
+
}
|
|
4152
|
+
var init_mcp = __esm({
|
|
4153
|
+
"packages/cli/src/mcp.ts"() {
|
|
4154
|
+
"use strict";
|
|
4155
|
+
init_auth();
|
|
4156
|
+
init_client();
|
|
4157
|
+
}
|
|
4158
|
+
});
|
|
4159
|
+
|
|
4160
|
+
// packages/cli/src/doctor.ts
|
|
4161
|
+
var doctor_exports = {};
|
|
4162
|
+
__export(doctor_exports, {
|
|
4163
|
+
formatDoctorReport: () => formatDoctorReport,
|
|
4164
|
+
runDoctor: () => runDoctor
|
|
4165
|
+
});
|
|
4166
|
+
import { stat as stat7 } from "node:fs/promises";
|
|
4167
|
+
async function probeServer(server) {
|
|
4168
|
+
const controller = new AbortController();
|
|
4169
|
+
const timer = setTimeout(() => controller.abort(), SERVER_PROBE_TIMEOUT_MS);
|
|
4170
|
+
try {
|
|
4171
|
+
const response = await fetch(`${server}/api/v1/health`, { signal: controller.signal });
|
|
4172
|
+
return { reachable: true, status: response.status };
|
|
4173
|
+
} catch (error) {
|
|
4174
|
+
return {
|
|
4175
|
+
reachable: false,
|
|
4176
|
+
error: error instanceof Error ? error.message : String(error)
|
|
4177
|
+
};
|
|
4178
|
+
} finally {
|
|
4179
|
+
clearTimeout(timer);
|
|
4180
|
+
}
|
|
4181
|
+
}
|
|
4182
|
+
async function credentialMode(file) {
|
|
4183
|
+
try {
|
|
4184
|
+
const info = await stat7(file);
|
|
4185
|
+
return (info.mode & 511).toString(8).padStart(3, "0");
|
|
4186
|
+
} catch {
|
|
4187
|
+
return void 0;
|
|
4188
|
+
}
|
|
4189
|
+
}
|
|
4190
|
+
async function runDoctor(paths) {
|
|
4191
|
+
const credentials = await loadCredentials(paths);
|
|
4192
|
+
const server = credentials?.server ?? resolveServer();
|
|
4193
|
+
const mode = await credentialMode(paths.credentialsFile);
|
|
4194
|
+
const offline = await isOffline();
|
|
4195
|
+
const health = await probeServer(server);
|
|
4196
|
+
const report = {
|
|
4197
|
+
server,
|
|
4198
|
+
credentials: {
|
|
4199
|
+
file: paths.credentialsFile,
|
|
4200
|
+
present: credentials !== null,
|
|
4201
|
+
...mode === void 0 ? {} : { mode }
|
|
4202
|
+
},
|
|
4203
|
+
network: { offline },
|
|
4204
|
+
serverHealth: health,
|
|
4205
|
+
offlineCommands: [...OFFLINE_COMMANDS],
|
|
4206
|
+
boundaries: SIM_BOUNDARIES.map((b) => ({ kind: b.kind, title: b.title, detail: b.detail }))
|
|
4207
|
+
};
|
|
4208
|
+
if (credentials !== null) report.credentials.email = credentials.email;
|
|
4209
|
+
if (mode !== void 0 && mode !== "600") {
|
|
4210
|
+
report.credentials.warning = `\u6743\u9650 ${mode} \u5BBD\u4E8E 0600\uFF0C\u5EFA\u8BAE chmod 600 ${paths.credentialsFile}`;
|
|
4211
|
+
}
|
|
4212
|
+
return report;
|
|
4213
|
+
}
|
|
4214
|
+
function formatDoctorReport(report) {
|
|
4215
|
+
const lines = ["adep doctor \xB7 \u73AF\u5883\u81EA\u68C0", ""];
|
|
4216
|
+
lines.push("\u51ED\u636E\u4E0E\u8EAB\u4EFD");
|
|
4217
|
+
if (report.credentials.present) {
|
|
4218
|
+
lines.push(` \u2713 \u5DF2\u767B\u5F55 ${report.credentials.email ?? "(\u672A\u77E5\u90AE\u7BB1)"} @ ${report.server}`);
|
|
4219
|
+
lines.push(
|
|
4220
|
+
` \xB7 \u51ED\u636E\u6587\u4EF6 ${report.credentials.file}\uFF08${report.credentials.mode ?? "\u6743\u9650\u672A\u77E5"}\uFF09`
|
|
4221
|
+
);
|
|
4222
|
+
if (report.credentials.warning !== void 0) lines.push(` ! ${report.credentials.warning}`);
|
|
4223
|
+
} else {
|
|
4224
|
+
lines.push(` \u2717 \u672A\u767B\u5F55\uFF08\u65E0 ${report.credentials.file}\uFF09`);
|
|
4225
|
+
lines.push(" \u63D0\u793A\uFF1A\u5148\u6267\u884C adep login");
|
|
4226
|
+
}
|
|
4227
|
+
lines.push("", "\u7F51\u7EDC\u4E0E\u670D\u52A1\u7AEF");
|
|
4228
|
+
lines.push(
|
|
4229
|
+
report.network.offline ? " \u2717 \u5916\u7F51\u4E0D\u53EF\u8FBE\uFF08\u4F9D\u8D56\u5B89\u88C5 / \u90E8\u7F72\u7B49\u547D\u4EE4\u5C06\u660E\u786E\u5931\u8D25\uFF09" : " \u2713 \u5916\u7F51\u53EF\u8FBE"
|
|
4230
|
+
);
|
|
4231
|
+
if (report.serverHealth.reachable) {
|
|
4232
|
+
lines.push(` \u2713 \u5E73\u53F0\u53EF\u8FBE ${report.server}\uFF08/api/v1/health \u2192 ${report.serverHealth.status}\uFF09`);
|
|
4233
|
+
} else {
|
|
4234
|
+
lines.push(
|
|
4235
|
+
` \u2717 \u5E73\u53F0\u4E0D\u53EF\u8FBE ${report.server}\uFF1A${report.serverHealth.error ?? "\u65E0\u5E94\u7B54"}`,
|
|
4236
|
+
" \u63D0\u793A\uFF1A\u68C0\u67E5 ADEP_SERVER / \u767B\u5F55\u65F6\u7684 --server\uFF0C\u6216\u5148\u8D77\u672C\u5730 pnpm run dev"
|
|
4237
|
+
);
|
|
4238
|
+
}
|
|
4239
|
+
lines.push("", "\u79BB\u7EBF\u53EF\u7528\u8303\u56F4\uFF08\u65AD\u7F51\u65F6\u4ECD\u53EF\u6267\u884C\uFF09");
|
|
4240
|
+
for (const command of report.offlineCommands) lines.push(` \xB7 ${command}`);
|
|
4241
|
+
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");
|
|
4242
|
+
for (const boundary of report.boundaries) {
|
|
4243
|
+
lines.push(` \xB7 [${boundary.kind}] ${boundary.title}\uFF1A${boundary.detail}`);
|
|
4244
|
+
}
|
|
4245
|
+
return lines;
|
|
4246
|
+
}
|
|
4247
|
+
var SERVER_PROBE_TIMEOUT_MS, OFFLINE_COMMANDS;
|
|
4248
|
+
var init_doctor = __esm({
|
|
4249
|
+
"packages/cli/src/doctor.ts"() {
|
|
4250
|
+
"use strict";
|
|
4251
|
+
init_credentials();
|
|
4252
|
+
init_config();
|
|
4253
|
+
init_boundary();
|
|
4254
|
+
init_net();
|
|
4255
|
+
SERVER_PROBE_TIMEOUT_MS = 5e3;
|
|
4256
|
+
OFFLINE_COMMANDS = [
|
|
4257
|
+
"adep init",
|
|
4258
|
+
"adep dev",
|
|
4259
|
+
"adep serve",
|
|
4260
|
+
"adep widget init",
|
|
4261
|
+
"adep widget dev",
|
|
4262
|
+
"adep db\uFF08\u672C\u5730\u6A21\u62DF\uFF09",
|
|
4263
|
+
"adep doctor"
|
|
4264
|
+
];
|
|
4265
|
+
}
|
|
4266
|
+
});
|
|
4267
|
+
|
|
4268
|
+
// packages/cli/src/db.ts
|
|
4269
|
+
var db_exports = {};
|
|
4270
|
+
__export(db_exports, {
|
|
4271
|
+
dbExec: () => dbExec,
|
|
4272
|
+
dbRollback: () => dbRollback,
|
|
4273
|
+
dbSnapshotCreate: () => dbSnapshotCreate,
|
|
4274
|
+
dbSnapshotList: () => dbSnapshotList,
|
|
4275
|
+
dbSnapshotRestore: () => dbSnapshotRestore,
|
|
4276
|
+
dbStart: () => dbStart,
|
|
4277
|
+
dbStatus: () => dbStatus,
|
|
4278
|
+
dbStop: () => dbStop
|
|
4279
|
+
});
|
|
4280
|
+
import { resolve as resolve10 } from "node:path";
|
|
4281
|
+
async function open2(paths, options) {
|
|
4282
|
+
const client = await createClient(paths);
|
|
4283
|
+
const project2 = await resolveSlug(resolve10(options.cwd), options.slug);
|
|
4284
|
+
return { client, project: project2 };
|
|
4285
|
+
}
|
|
4286
|
+
async function dbStart(paths, options) {
|
|
4287
|
+
const { client, project: project2 } = await open2(paths, options);
|
|
4288
|
+
return client.request(`/api/v1/projects/${project2}/database`, { method: "POST" });
|
|
4289
|
+
}
|
|
4290
|
+
async function dbStatus(paths, options) {
|
|
4291
|
+
const { client, project: project2 } = await open2(paths, options);
|
|
4292
|
+
return client.request(`/api/v1/projects/${project2}/database`);
|
|
4293
|
+
}
|
|
4294
|
+
async function dbStop(paths, options) {
|
|
4295
|
+
const { client, project: project2 } = await open2(paths, options);
|
|
4296
|
+
return client.request(`/api/v1/projects/${project2}/database`, {
|
|
4297
|
+
method: "DELETE"
|
|
4298
|
+
});
|
|
4299
|
+
}
|
|
4300
|
+
async function dbExec(paths, options) {
|
|
4301
|
+
const { client, project: project2 } = await open2(paths, options);
|
|
4302
|
+
return client.request(
|
|
4303
|
+
`/api/v1/projects/${project2}/database/console/sql`,
|
|
4304
|
+
{
|
|
4305
|
+
method: "POST",
|
|
4306
|
+
body: {
|
|
4307
|
+
sql: options.sql,
|
|
4308
|
+
...options.params === void 0 ? {} : { params: options.params },
|
|
4309
|
+
...options.confirmTable === void 0 ? {} : { confirmTable: options.confirmTable }
|
|
4310
|
+
}
|
|
4311
|
+
},
|
|
4312
|
+
"SQL_EXEC_FAILED"
|
|
4313
|
+
);
|
|
4314
|
+
}
|
|
4315
|
+
async function dbSnapshotList(paths, options) {
|
|
4316
|
+
const { client, project: project2 } = await open2(paths, options);
|
|
4317
|
+
return client.request(
|
|
4318
|
+
`/api/v1/projects/${project2}/database/snapshots`
|
|
4319
|
+
);
|
|
4320
|
+
}
|
|
4321
|
+
async function dbSnapshotCreate(paths, options) {
|
|
4322
|
+
const { client, project: project2 } = await open2(paths, options);
|
|
4323
|
+
return client.request(`/api/v1/projects/${project2}/database/snapshots`, {
|
|
4324
|
+
method: "POST"
|
|
4325
|
+
});
|
|
4326
|
+
}
|
|
4327
|
+
async function dbSnapshotRestore(paths, options) {
|
|
4328
|
+
const { client, project: project2 } = await open2(paths, options);
|
|
4329
|
+
return client.request(
|
|
4330
|
+
`/api/v1/projects/${project2}/database/snapshots/${options.snapshotId}/restore`,
|
|
4331
|
+
{ method: "POST" }
|
|
4332
|
+
);
|
|
4333
|
+
}
|
|
4334
|
+
async function dbRollback(paths, options) {
|
|
4335
|
+
const { client, project: project2 } = await open2(paths, options);
|
|
4336
|
+
return client.request(
|
|
4337
|
+
`/api/v1/projects/${project2}/database/rollback`,
|
|
4338
|
+
{ method: "POST", body: { to: options.to } }
|
|
4339
|
+
);
|
|
4340
|
+
}
|
|
4341
|
+
var init_db2 = __esm({
|
|
4342
|
+
"packages/cli/src/db.ts"() {
|
|
4343
|
+
"use strict";
|
|
4344
|
+
init_client();
|
|
4345
|
+
}
|
|
4346
|
+
});
|
|
4347
|
+
|
|
4348
|
+
// packages/cli/src/storage.ts
|
|
4349
|
+
var storage_exports = {};
|
|
4350
|
+
__export(storage_exports, {
|
|
4351
|
+
contentTypeOf: () => contentTypeOf,
|
|
4352
|
+
storageDownload: () => storageDownload,
|
|
4353
|
+
storageList: () => storageList,
|
|
4354
|
+
storageRemove: () => storageRemove,
|
|
4355
|
+
storageUpload: () => storageUpload
|
|
4356
|
+
});
|
|
4357
|
+
import { mkdir as mkdir7, readFile as readFile8, stat as stat8, writeFile as writeFile6 } from "node:fs/promises";
|
|
4358
|
+
import { basename as basename3, dirname as dirname7, extname, join as join12, resolve as resolve11 } from "node:path";
|
|
4359
|
+
async function open3(paths, options) {
|
|
4360
|
+
const client = await createClient(paths);
|
|
4361
|
+
const project2 = await resolveSlug(resolve11(options.cwd), options.slug);
|
|
4362
|
+
return { client, project: project2 };
|
|
4363
|
+
}
|
|
4364
|
+
function contentTypeOf(path) {
|
|
4365
|
+
const map = {
|
|
4366
|
+
".html": "text/html; charset=utf-8",
|
|
4367
|
+
".htm": "text/html; charset=utf-8",
|
|
4368
|
+
".css": "text/css; charset=utf-8",
|
|
4369
|
+
".js": "text/javascript; charset=utf-8",
|
|
4370
|
+
".mjs": "text/javascript; charset=utf-8",
|
|
4371
|
+
".json": "application/json; charset=utf-8",
|
|
4372
|
+
".png": "image/png",
|
|
4373
|
+
".jpg": "image/jpeg",
|
|
4374
|
+
".jpeg": "image/jpeg",
|
|
4375
|
+
".gif": "image/gif",
|
|
4376
|
+
".svg": "image/svg+xml",
|
|
4377
|
+
".webp": "image/webp",
|
|
4378
|
+
".ico": "image/x-icon",
|
|
3245
4379
|
".txt": "text/plain; charset=utf-8",
|
|
3246
4380
|
".md": "text/markdown; charset=utf-8",
|
|
3247
4381
|
".xml": "application/xml",
|
|
@@ -3257,13 +4391,13 @@ function contentTypeOf(path) {
|
|
|
3257
4391
|
}
|
|
3258
4392
|
async function storageUpload(paths, options) {
|
|
3259
4393
|
const { client, project: project2 } = await open3(paths, options);
|
|
3260
|
-
const local =
|
|
3261
|
-
const info = await
|
|
4394
|
+
const local = resolve11(options.file);
|
|
4395
|
+
const info = await stat8(local).catch(() => null);
|
|
3262
4396
|
if (info === null || !info.isFile()) {
|
|
3263
4397
|
throw new CliError("FILE_NOT_FOUND", `\u672C\u5730\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${local}`);
|
|
3264
4398
|
}
|
|
3265
4399
|
const visibility = options.visibility ?? "private";
|
|
3266
|
-
const bytes = await
|
|
4400
|
+
const bytes = await readFile8(local);
|
|
3267
4401
|
const form = new FormData();
|
|
3268
4402
|
form.set("path", options.path);
|
|
3269
4403
|
form.set("visibility", visibility);
|
|
@@ -3304,7 +4438,7 @@ async function storageDownload(paths, options) {
|
|
|
3304
4438
|
const url = await resolveDownloadUrl(client, project2, options.path);
|
|
3305
4439
|
const response = await client.download(url, "STORAGE_DOWNLOAD_FAILED");
|
|
3306
4440
|
const bytes = Buffer.from(await response.arrayBuffer());
|
|
3307
|
-
const output =
|
|
4441
|
+
const output = resolve11(options.output ?? join12(resolve11(options.cwd), basename3(options.path)));
|
|
3308
4442
|
await mkdir7(dirname7(output), { recursive: true });
|
|
3309
4443
|
await writeFile6(output, bytes);
|
|
3310
4444
|
return { path: options.path, output, size: bytes.length };
|
|
@@ -3332,11 +4466,11 @@ __export(hosting_exports, {
|
|
|
3332
4466
|
hostingInfo: () => hostingInfo,
|
|
3333
4467
|
hostingPull: () => hostingPull
|
|
3334
4468
|
});
|
|
3335
|
-
import { readdir as
|
|
3336
|
-
import { dirname as dirname8, join as
|
|
4469
|
+
import { readdir as readdir5, readFile as readFile9, stat as stat9 } from "node:fs/promises";
|
|
4470
|
+
import { dirname as dirname8, join as join13, relative as relative2, resolve as resolve12, sep } from "node:path";
|
|
3337
4471
|
async function open4(paths, options) {
|
|
3338
4472
|
const client = await createClient(paths);
|
|
3339
|
-
const project2 = await resolveSlug(
|
|
4473
|
+
const project2 = await resolveSlug(resolve12(options.cwd), options.slug);
|
|
3340
4474
|
return { client, project: project2 };
|
|
3341
4475
|
}
|
|
3342
4476
|
async function hostingInfo(paths, options) {
|
|
@@ -3349,104 +4483,782 @@ async function hostingInfo(paths, options) {
|
|
|
3349
4483
|
};
|
|
3350
4484
|
}
|
|
3351
4485
|
async function collectSiteFiles(dir) {
|
|
3352
|
-
const root =
|
|
4486
|
+
const root = resolve12(dir);
|
|
3353
4487
|
const files = /* @__PURE__ */ new Map();
|
|
3354
4488
|
const walk = async (sub) => {
|
|
3355
4489
|
let entries;
|
|
3356
4490
|
try {
|
|
3357
|
-
entries = await
|
|
4491
|
+
entries = await readdir5(sub, { withFileTypes: true });
|
|
3358
4492
|
} catch {
|
|
3359
4493
|
return;
|
|
3360
4494
|
}
|
|
3361
4495
|
for (const entry of entries) {
|
|
3362
|
-
const full =
|
|
4496
|
+
const full = join13(sub, entry.name);
|
|
3363
4497
|
if (entry.isDirectory()) {
|
|
3364
4498
|
await walk(full);
|
|
3365
4499
|
} else if (entry.isFile()) {
|
|
3366
|
-
const rel =
|
|
4500
|
+
const rel = relative2(root, full).split(sep).join("/");
|
|
3367
4501
|
files.set(rel, full);
|
|
3368
4502
|
}
|
|
3369
4503
|
}
|
|
3370
4504
|
};
|
|
3371
|
-
await walk(root);
|
|
3372
|
-
return files;
|
|
4505
|
+
await walk(root);
|
|
4506
|
+
return files;
|
|
4507
|
+
}
|
|
4508
|
+
async function hostingDeploy(paths, options) {
|
|
4509
|
+
const { client, project: project2 } = await open4(paths, options);
|
|
4510
|
+
const log = options.log ?? ((line) => process.stdout.write(`${line}
|
|
4511
|
+
`));
|
|
4512
|
+
const files = await collectSiteFiles(options.dir);
|
|
4513
|
+
if (files.size === 0) {
|
|
4514
|
+
throw new CliError("NO_SITE_FILES", `\u7AD9\u70B9\u76EE\u5F55\u4E3A\u7A7A\uFF1A${resolve12(options.dir)}`);
|
|
4515
|
+
}
|
|
4516
|
+
const uploaded = [];
|
|
4517
|
+
for (const [rel, full] of files) {
|
|
4518
|
+
log(`[adep] \u4E0A\u4F20 site/${rel}`);
|
|
4519
|
+
const info2 = await stat9(full);
|
|
4520
|
+
const bytes = await readFile9(full);
|
|
4521
|
+
const form = new FormData();
|
|
4522
|
+
form.set("path", `site/${rel}`);
|
|
4523
|
+
form.set("visibility", "public");
|
|
4524
|
+
form.set(
|
|
4525
|
+
"file",
|
|
4526
|
+
new Blob([bytes], { type: contentTypeOf(rel) }),
|
|
4527
|
+
rel.split("/").pop()
|
|
4528
|
+
);
|
|
4529
|
+
await client.upload(`/api/v1/projects/${project2}/files`, form, "HOSTING_UPLOAD_FAILED");
|
|
4530
|
+
uploaded.push({ path: `site/${rel}`, size: info2.size });
|
|
4531
|
+
}
|
|
4532
|
+
const config = await client.request(
|
|
4533
|
+
`/api/v1/projects/${project2}/hosting`,
|
|
4534
|
+
{
|
|
4535
|
+
method: "PUT",
|
|
4536
|
+
body: options.spa === void 0 ? { enabled: true } : { enabled: true, spaMode: options.spa }
|
|
4537
|
+
}
|
|
4538
|
+
);
|
|
4539
|
+
const info = await hostingInfo(paths, options);
|
|
4540
|
+
return { config: config.config, siteUrl: info.siteUrl, uploaded };
|
|
4541
|
+
}
|
|
4542
|
+
async function hostingPull(paths, options) {
|
|
4543
|
+
const { client } = await open4(paths, options);
|
|
4544
|
+
const log = options.log ?? ((line) => process.stdout.write(`${line}
|
|
4545
|
+
`));
|
|
4546
|
+
const info = await hostingInfo(paths, options);
|
|
4547
|
+
const outputDir = resolve12(options.output ?? resolve12(options.cwd));
|
|
4548
|
+
const { mkdir: mkdir9, writeFile: writeFile9 } = await import("node:fs/promises");
|
|
4549
|
+
const files = [];
|
|
4550
|
+
for (const entry of info.files) {
|
|
4551
|
+
if (entry.visibility !== "public" || entry.path === HOSTING_CONFIG_PATH) continue;
|
|
4552
|
+
const url = entry.url;
|
|
4553
|
+
if (url === void 0 || url.length === 0) continue;
|
|
4554
|
+
log(`[adep] \u4E0B\u8F7D ${entry.path}`);
|
|
4555
|
+
const response = await client.download(url, "HOSTING_DOWNLOAD_FAILED");
|
|
4556
|
+
const bytes = Buffer.from(await response.arrayBuffer());
|
|
4557
|
+
const rel = entry.path.replace(/^site\//, "");
|
|
4558
|
+
const target = join13(outputDir, ...rel.split("/"));
|
|
4559
|
+
await mkdir9(dirname8(target), { recursive: true });
|
|
4560
|
+
await writeFile9(target, bytes);
|
|
4561
|
+
files.push({ path: entry.path, size: bytes.length });
|
|
4562
|
+
}
|
|
4563
|
+
return { siteUrl: info.siteUrl, outputDir, files };
|
|
4564
|
+
}
|
|
4565
|
+
async function hostingConfig(paths, options) {
|
|
4566
|
+
const { client, project: project2 } = await open4(paths, options);
|
|
4567
|
+
const body = {};
|
|
4568
|
+
if (options.enabled !== void 0) body["enabled"] = options.enabled;
|
|
4569
|
+
if (options.spa !== void 0) body["spaMode"] = options.spa;
|
|
4570
|
+
const result = await client.request(
|
|
4571
|
+
`/api/v1/projects/${project2}/hosting`,
|
|
4572
|
+
{ method: "PUT", body }
|
|
4573
|
+
);
|
|
4574
|
+
return result.config;
|
|
4575
|
+
}
|
|
4576
|
+
var HOSTING_CONFIG_PATH;
|
|
4577
|
+
var init_hosting = __esm({
|
|
4578
|
+
"packages/cli/src/hosting.ts"() {
|
|
4579
|
+
"use strict";
|
|
4580
|
+
init_client();
|
|
4581
|
+
init_auth();
|
|
4582
|
+
init_storage2();
|
|
4583
|
+
HOSTING_CONFIG_PATH = "site/.hosting.json";
|
|
4584
|
+
}
|
|
4585
|
+
});
|
|
4586
|
+
|
|
4587
|
+
// packages/cli/src/export/client.ts
|
|
4588
|
+
var client_exports2 = {};
|
|
4589
|
+
__export(client_exports2, {
|
|
4590
|
+
createExportApiClient: () => createExportApiClient
|
|
4591
|
+
});
|
|
4592
|
+
import { writeFile as writeFile7 } from "node:fs/promises";
|
|
4593
|
+
function toExportJob(view) {
|
|
4594
|
+
return {
|
|
4595
|
+
id: view.id,
|
|
4596
|
+
status: view.status,
|
|
4597
|
+
progress: view.progress,
|
|
4598
|
+
createdAt: view.createdAt,
|
|
4599
|
+
...view.stage === void 0 ? {} : { stage: view.stage },
|
|
4600
|
+
...view.error === void 0 ? {} : { error: view.error },
|
|
4601
|
+
...view.downloadUrl === void 0 ? {} : { downloadUrl: view.downloadUrl },
|
|
4602
|
+
...view.bundleSize === void 0 ? {} : { bundleSize: view.bundleSize },
|
|
4603
|
+
...view.completedAt === void 0 ? {} : { completedAt: view.completedAt }
|
|
4604
|
+
};
|
|
4605
|
+
}
|
|
4606
|
+
async function createExportApiClient(paths) {
|
|
4607
|
+
const client = await createClient(paths);
|
|
4608
|
+
return {
|
|
4609
|
+
async triggerExport(projectId, options) {
|
|
4610
|
+
const view = await client.request(
|
|
4611
|
+
`/api/v1/projects/${encodeURIComponent(projectId)}/export`,
|
|
4612
|
+
{ method: "POST", body: { withData: options.withData, withSource: options.withSource } },
|
|
4613
|
+
"EXPORT_TRIGGER_FAILED"
|
|
4614
|
+
);
|
|
4615
|
+
return toExportJob(view);
|
|
4616
|
+
},
|
|
4617
|
+
async getJobStatus(jobId) {
|
|
4618
|
+
const view = await client.request(
|
|
4619
|
+
`/api/v1/exports/${encodeURIComponent(jobId)}`,
|
|
4620
|
+
{},
|
|
4621
|
+
"EXPORT_STATUS_FAILED"
|
|
4622
|
+
);
|
|
4623
|
+
return toExportJob(view);
|
|
4624
|
+
},
|
|
4625
|
+
async downloadBundle(jobId, outputPath) {
|
|
4626
|
+
const download = await client.request(
|
|
4627
|
+
`/api/v1/exports/${encodeURIComponent(jobId)}/download`,
|
|
4628
|
+
{},
|
|
4629
|
+
"EXPORT_DOWNLOAD_FAILED"
|
|
4630
|
+
);
|
|
4631
|
+
if (download.downloadUrl.length === 0) {
|
|
4632
|
+
throw new CliError("EXPORT_BUNDLE_UNAVAILABLE", "\u5BFC\u51FA\u4EA7\u7269\u4E0B\u8F7D URL \u4E3A\u7A7A\uFF0C\u4EA7\u7269\u53EF\u80FD\u5C1A\u4E0D\u53EF\u7528");
|
|
4633
|
+
}
|
|
4634
|
+
const response = await client.download(download.downloadUrl, "EXPORT_DOWNLOAD_FAILED");
|
|
4635
|
+
const bytes = Buffer.from(await response.arrayBuffer());
|
|
4636
|
+
await writeFile7(outputPath, bytes);
|
|
4637
|
+
return { path: outputPath, size: bytes.length };
|
|
4638
|
+
}
|
|
4639
|
+
};
|
|
4640
|
+
}
|
|
4641
|
+
var init_client2 = __esm({
|
|
4642
|
+
"packages/cli/src/export/client.ts"() {
|
|
4643
|
+
"use strict";
|
|
4644
|
+
init_auth();
|
|
4645
|
+
init_client();
|
|
4646
|
+
}
|
|
4647
|
+
});
|
|
4648
|
+
|
|
4649
|
+
// shared/deploy-bundle/zip.ts
|
|
4650
|
+
function zipRead(buf) {
|
|
4651
|
+
const r = new Reader(buf);
|
|
4652
|
+
const eocd = findEocd(buf);
|
|
4653
|
+
if (eocd < 0) throw new ZipFormatError("\u627E\u4E0D\u5230 EOCD \u7B7E\u540D");
|
|
4654
|
+
const total = r.u16(eocd + 10);
|
|
4655
|
+
const centralOffset = r.u32(eocd + 16);
|
|
4656
|
+
const decoder = new TextDecoder();
|
|
4657
|
+
const out = /* @__PURE__ */ new Map();
|
|
4658
|
+
let cursor = centralOffset;
|
|
4659
|
+
for (let i = 0; i < total; i++) {
|
|
4660
|
+
if (cursor + 46 > buf.length) throw new ZipFormatError("\u4E2D\u592E\u76EE\u5F55\u8BB0\u5F55\u8D8A\u754C");
|
|
4661
|
+
if (r.u32(cursor) !== SIG_CENTRAL) throw new ZipFormatError("\u4E2D\u592E\u76EE\u5F55\u7B7E\u540D\u4E0D\u5339\u914D");
|
|
4662
|
+
const method = r.u16(cursor + 10);
|
|
4663
|
+
if (method !== 0) throw new ZipFormatError("\u4EC5\u652F\u6301 store \u578B\u6761\u76EE\u8BFB\u53D6");
|
|
4664
|
+
const compSize = r.u32(cursor + 20);
|
|
4665
|
+
const nameLen = r.u16(cursor + 28);
|
|
4666
|
+
const extraLen = r.u16(cursor + 30);
|
|
4667
|
+
const commentLen = r.u16(cursor + 32);
|
|
4668
|
+
const localHeaderOffset = r.u32(cursor + 42);
|
|
4669
|
+
if (localHeaderOffset + 30 > buf.length) throw new ZipFormatError("\u672C\u5730\u5934\u504F\u79FB\u8D8A\u754C");
|
|
4670
|
+
const name = decoder.decode(r.slice(cursor + 46, nameLen));
|
|
4671
|
+
const localNameLen = r.u16(localHeaderOffset + 26);
|
|
4672
|
+
const localExtraLen = r.u16(localHeaderOffset + 28);
|
|
4673
|
+
const dataStart = localHeaderOffset + 30 + localNameLen + localExtraLen;
|
|
4674
|
+
if (dataStart + compSize > buf.length) throw new ZipFormatError("\u6761\u76EE\u6570\u636E\u8D8A\u754C");
|
|
4675
|
+
if (!out.has(name)) out.set(name, r.slice(dataStart, compSize));
|
|
4676
|
+
cursor += 46 + nameLen + extraLen + commentLen;
|
|
4677
|
+
}
|
|
4678
|
+
return out;
|
|
4679
|
+
}
|
|
4680
|
+
function findEocd(buf) {
|
|
4681
|
+
const view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
4682
|
+
const min = Math.max(0, buf.length - 65557);
|
|
4683
|
+
for (let i = buf.length - 22; i >= min; i--) {
|
|
4684
|
+
if (view.getUint32(i, true) === SIG_EOCD) return i;
|
|
4685
|
+
}
|
|
4686
|
+
return -1;
|
|
4687
|
+
}
|
|
4688
|
+
var SIG_CENTRAL, SIG_EOCD, CRC_TABLE, Reader, ZipFormatError;
|
|
4689
|
+
var init_zip = __esm({
|
|
4690
|
+
"shared/deploy-bundle/zip.ts"() {
|
|
4691
|
+
"use strict";
|
|
4692
|
+
SIG_CENTRAL = 33639248;
|
|
4693
|
+
SIG_EOCD = 101010256;
|
|
4694
|
+
CRC_TABLE = (() => {
|
|
4695
|
+
const table = new Uint32Array(256);
|
|
4696
|
+
for (let i = 0; i < 256; i++) {
|
|
4697
|
+
let c = i;
|
|
4698
|
+
for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
4699
|
+
table[i] = c >>> 0;
|
|
4700
|
+
}
|
|
4701
|
+
return table;
|
|
4702
|
+
})();
|
|
4703
|
+
Reader = class {
|
|
4704
|
+
constructor(buf) {
|
|
4705
|
+
this.buf = buf;
|
|
4706
|
+
this.view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
4707
|
+
}
|
|
4708
|
+
view;
|
|
4709
|
+
u16(offset) {
|
|
4710
|
+
return this.view.getUint16(offset, true);
|
|
4711
|
+
}
|
|
4712
|
+
u32(offset) {
|
|
4713
|
+
return this.view.getUint32(offset, true);
|
|
4714
|
+
}
|
|
4715
|
+
slice(start, length) {
|
|
4716
|
+
return this.buf.subarray(start, start + length);
|
|
4717
|
+
}
|
|
4718
|
+
};
|
|
4719
|
+
ZipFormatError = class extends Error {
|
|
4720
|
+
constructor(message) {
|
|
4721
|
+
super(`[appexport] \u975E\u6CD5 zip\uFF1A${message}`);
|
|
4722
|
+
this.name = "ZipFormatError";
|
|
4723
|
+
}
|
|
4724
|
+
};
|
|
4725
|
+
}
|
|
4726
|
+
});
|
|
4727
|
+
|
|
4728
|
+
// packages/cli/src/export/fs.ts
|
|
4729
|
+
var fs_exports = {};
|
|
4730
|
+
__export(fs_exports, {
|
|
4731
|
+
createExportFileSystem: () => createExportFileSystem
|
|
4732
|
+
});
|
|
4733
|
+
import { mkdir as mkdir8, readFile as readFile10, rm as rm3, stat as stat10, writeFile as writeFile8 } from "node:fs/promises";
|
|
4734
|
+
import { dirname as dirname9, join as join14 } from "node:path";
|
|
4735
|
+
function createExportFileSystem() {
|
|
4736
|
+
return {
|
|
4737
|
+
readFile: (path) => readFile10(path),
|
|
4738
|
+
writeFile: (path, content) => writeFile8(path, content),
|
|
4739
|
+
// 同时用于清理解压临时目录(${zip}.tmp 是个目录)——递归强制删除,缺失不报错。
|
|
4740
|
+
deleteFile: async (path) => {
|
|
4741
|
+
await rm3(path, { recursive: true, force: true });
|
|
4742
|
+
},
|
|
4743
|
+
fileExists: async (path) => {
|
|
4744
|
+
try {
|
|
4745
|
+
await stat10(path);
|
|
4746
|
+
return true;
|
|
4747
|
+
} catch {
|
|
4748
|
+
return false;
|
|
4749
|
+
}
|
|
4750
|
+
},
|
|
4751
|
+
mkdir: async (path) => {
|
|
4752
|
+
await mkdir8(path, { recursive: true });
|
|
4753
|
+
},
|
|
4754
|
+
unzip: async (zipPath, targetDir) => {
|
|
4755
|
+
const entries = zipRead(await readFile10(zipPath));
|
|
4756
|
+
for (const [name, data] of entries) {
|
|
4757
|
+
const dest = join14(targetDir, name);
|
|
4758
|
+
await mkdir8(dirname9(dest), { recursive: true });
|
|
4759
|
+
await writeFile8(dest, data);
|
|
4760
|
+
}
|
|
4761
|
+
}
|
|
4762
|
+
};
|
|
4763
|
+
}
|
|
4764
|
+
var init_fs = __esm({
|
|
4765
|
+
"packages/cli/src/export/fs.ts"() {
|
|
4766
|
+
"use strict";
|
|
4767
|
+
init_zip();
|
|
4768
|
+
}
|
|
4769
|
+
});
|
|
4770
|
+
|
|
4771
|
+
// shared/deploy-bundle/manifest.ts
|
|
4772
|
+
var CURRENT_SCHEMA_VERSION, BundleContentKind, ALLOWED_CONTENT_KINDS;
|
|
4773
|
+
var init_manifest2 = __esm({
|
|
4774
|
+
"shared/deploy-bundle/manifest.ts"() {
|
|
4775
|
+
"use strict";
|
|
4776
|
+
CURRENT_SCHEMA_VERSION = 1;
|
|
4777
|
+
BundleContentKind = {
|
|
4778
|
+
/** 云函数代码与配置。 */
|
|
4779
|
+
Functions: "functions",
|
|
4780
|
+
/** 数据库 schema 与种子数据。 */
|
|
4781
|
+
Database: "database",
|
|
4782
|
+
/** 前端静态资源。 */
|
|
4783
|
+
Web: "web",
|
|
4784
|
+
/** 运行时配置(Dockerfile / docker-compose.yml)。 */
|
|
4785
|
+
Runtime: "runtime",
|
|
4786
|
+
/** 启动 / 备份 / 恢复脚本。 */
|
|
4787
|
+
Scripts: "scripts",
|
|
4788
|
+
/** 文档(README / 部署手册)。 */
|
|
4789
|
+
Docs: "docs"
|
|
4790
|
+
};
|
|
4791
|
+
ALLOWED_CONTENT_KINDS = Object.values(BundleContentKind);
|
|
4792
|
+
}
|
|
4793
|
+
});
|
|
4794
|
+
|
|
4795
|
+
// shared/deploy-bundle/validate.ts
|
|
4796
|
+
function validateBundleManifest(manifest) {
|
|
4797
|
+
const errors = [];
|
|
4798
|
+
const warnings = [];
|
|
4799
|
+
if (typeof manifest !== "object" || manifest === null) {
|
|
4800
|
+
return {
|
|
4801
|
+
valid: false,
|
|
4802
|
+
errors: [{ code: "INVALID_TYPE", message: "Manifest \u5FC5\u987B\u662F\u5BF9\u8C61" }],
|
|
4803
|
+
warnings: []
|
|
4804
|
+
};
|
|
4805
|
+
}
|
|
4806
|
+
const m = manifest;
|
|
4807
|
+
const schemaVersion = m.schemaVersion;
|
|
4808
|
+
if (typeof schemaVersion !== "number" || !Number.isInteger(schemaVersion)) {
|
|
4809
|
+
errors.push({
|
|
4810
|
+
code: "INVALID_SCHEMA_VERSION",
|
|
4811
|
+
message: "schemaVersion \u5FC5\u987B\u662F\u6574\u6570",
|
|
4812
|
+
field: "schemaVersion"
|
|
4813
|
+
});
|
|
4814
|
+
} else if (schemaVersion > CURRENT_SCHEMA_VERSION) {
|
|
4815
|
+
errors.push({
|
|
4816
|
+
code: "SCHEMA_VERSION_TOO_HIGH",
|
|
4817
|
+
message: `schemaVersion ${schemaVersion} \u9AD8\u4E8E\u5F53\u524D\u652F\u6301\u7248\u672C ${CURRENT_SCHEMA_VERSION}\uFF0C\u9700\u5347\u7EA7\u5BFC\u51FA\u7AEF`,
|
|
4818
|
+
field: "schemaVersion"
|
|
4819
|
+
});
|
|
4820
|
+
} else if (schemaVersion < CURRENT_SCHEMA_VERSION) {
|
|
4821
|
+
warnings.push({
|
|
4822
|
+
code: "SCHEMA_VERSION_LOW",
|
|
4823
|
+
message: `schemaVersion ${schemaVersion} \u4F4E\u4E8E\u5F53\u524D\u7248\u672C ${CURRENT_SCHEMA_VERSION}\uFF0C\u5EFA\u8BAE\u91CD\u65B0\u5BFC\u51FA`,
|
|
4824
|
+
field: "schemaVersion"
|
|
4825
|
+
});
|
|
4826
|
+
}
|
|
4827
|
+
if (typeof m.platformVersion !== "string" || m.platformVersion.trim() === "") {
|
|
4828
|
+
errors.push({
|
|
4829
|
+
code: "MISSING_PLATFORM_VERSION",
|
|
4830
|
+
message: "platformVersion \u5FC5\u987B\u975E\u7A7A",
|
|
4831
|
+
field: "platformVersion"
|
|
4832
|
+
});
|
|
4833
|
+
}
|
|
4834
|
+
if (typeof m.project !== "object" || m.project === null) {
|
|
4835
|
+
errors.push({
|
|
4836
|
+
code: "MISSING_PROJECT",
|
|
4837
|
+
message: "project \u5FC5\u987B\u662F\u5BF9\u8C61",
|
|
4838
|
+
field: "project"
|
|
4839
|
+
});
|
|
4840
|
+
} else {
|
|
4841
|
+
const project2 = m.project;
|
|
4842
|
+
if (typeof project2.id !== "string" || project2.id.trim() === "") {
|
|
4843
|
+
errors.push({
|
|
4844
|
+
code: "MISSING_PROJECT_ID",
|
|
4845
|
+
message: "project.id \u5FC5\u987B\u975E\u7A7A",
|
|
4846
|
+
field: "project.id"
|
|
4847
|
+
});
|
|
4848
|
+
}
|
|
4849
|
+
if (typeof project2.name !== "string" || project2.name.trim() === "") {
|
|
4850
|
+
errors.push({
|
|
4851
|
+
code: "MISSING_PROJECT_NAME",
|
|
4852
|
+
message: "project.name \u5FC5\u987B\u975E\u7A7A",
|
|
4853
|
+
field: "project.name"
|
|
4854
|
+
});
|
|
4855
|
+
}
|
|
4856
|
+
if (typeof project2.slug !== "string" || project2.slug.trim() === "") {
|
|
4857
|
+
errors.push({
|
|
4858
|
+
code: "MISSING_PROJECT_SLUG",
|
|
4859
|
+
message: "project.slug \u5FC5\u987B\u975E\u7A7A",
|
|
4860
|
+
field: "project.slug"
|
|
4861
|
+
});
|
|
4862
|
+
}
|
|
4863
|
+
if (typeof project2.version !== "number" || !Number.isInteger(project2.version) || project2.version < 1) {
|
|
4864
|
+
errors.push({
|
|
4865
|
+
code: "INVALID_PROJECT_VERSION",
|
|
4866
|
+
message: "project.version \u5FC5\u987B\u662F\u6B63\u6574\u6570",
|
|
4867
|
+
field: "project.version"
|
|
4868
|
+
});
|
|
4869
|
+
}
|
|
4870
|
+
}
|
|
4871
|
+
if (!Array.isArray(m.contents)) {
|
|
4872
|
+
errors.push({
|
|
4873
|
+
code: "MISSING_CONTENTS",
|
|
4874
|
+
message: "contents \u5FC5\u987B\u662F\u6570\u7EC4",
|
|
4875
|
+
field: "contents"
|
|
4876
|
+
});
|
|
4877
|
+
} else if (m.contents.length === 0) {
|
|
4878
|
+
errors.push({
|
|
4879
|
+
code: "EMPTY_CONTENTS",
|
|
4880
|
+
message: "contents \u4E0D\u80FD\u4E3A\u7A7A",
|
|
4881
|
+
field: "contents"
|
|
4882
|
+
});
|
|
4883
|
+
} else {
|
|
4884
|
+
m.contents.forEach((content, index) => {
|
|
4885
|
+
validateContent(content, index, errors, warnings);
|
|
4886
|
+
});
|
|
4887
|
+
}
|
|
4888
|
+
if (typeof m.runtime !== "object" || m.runtime === null) {
|
|
4889
|
+
errors.push({
|
|
4890
|
+
code: "MISSING_RUNTIME",
|
|
4891
|
+
message: "runtime \u5FC5\u987B\u662F\u5BF9\u8C61",
|
|
4892
|
+
field: "runtime"
|
|
4893
|
+
});
|
|
4894
|
+
} else {
|
|
4895
|
+
const runtime = m.runtime;
|
|
4896
|
+
if (typeof runtime.engine !== "string" || runtime.engine.trim() === "") {
|
|
4897
|
+
errors.push({
|
|
4898
|
+
code: "MISSING_ENGINE",
|
|
4899
|
+
message: "runtime.engine \u5FC5\u987B\u975E\u7A7A",
|
|
4900
|
+
field: "runtime.engine"
|
|
4901
|
+
});
|
|
4902
|
+
}
|
|
4903
|
+
if (typeof runtime.engineVersion !== "string" || runtime.engineVersion.trim() === "") {
|
|
4904
|
+
errors.push({
|
|
4905
|
+
code: "MISSING_ENGINE_VERSION",
|
|
4906
|
+
message: "runtime.engineVersion \u5FC5\u987B\u975E\u7A7A",
|
|
4907
|
+
field: "runtime.engineVersion"
|
|
4908
|
+
});
|
|
4909
|
+
}
|
|
4910
|
+
if (typeof runtime.port !== "number" || !Number.isInteger(runtime.port) || runtime.port < 1 || runtime.port > 65535) {
|
|
4911
|
+
errors.push({
|
|
4912
|
+
code: "INVALID_PORT",
|
|
4913
|
+
message: "runtime.port \u5FC5\u987B\u662F 1-65535 \u7684\u6574\u6570",
|
|
4914
|
+
field: "runtime.port"
|
|
4915
|
+
});
|
|
4916
|
+
}
|
|
4917
|
+
if (typeof runtime.startCommand !== "string" || runtime.startCommand.trim() === "") {
|
|
4918
|
+
errors.push({
|
|
4919
|
+
code: "MISSING_START_COMMAND",
|
|
4920
|
+
message: "runtime.startCommand \u5FC5\u987B\u975E\u7A7A",
|
|
4921
|
+
field: "runtime.startCommand"
|
|
4922
|
+
});
|
|
4923
|
+
}
|
|
4924
|
+
}
|
|
4925
|
+
if (typeof m.exportedAt !== "string" || m.exportedAt.trim() === "") {
|
|
4926
|
+
errors.push({
|
|
4927
|
+
code: "MISSING_EXPORTED_AT",
|
|
4928
|
+
message: "exportedAt \u5FC5\u987B\u975E\u7A7A",
|
|
4929
|
+
field: "exportedAt"
|
|
4930
|
+
});
|
|
4931
|
+
} else {
|
|
4932
|
+
const date = new Date(m.exportedAt);
|
|
4933
|
+
if (Number.isNaN(date.getTime())) {
|
|
4934
|
+
errors.push({
|
|
4935
|
+
code: "INVALID_EXPORTED_AT",
|
|
4936
|
+
message: "exportedAt \u5FC5\u987B\u662F\u6709\u6548\u7684 ISO 8601 \u65F6\u95F4",
|
|
4937
|
+
field: "exportedAt"
|
|
4938
|
+
});
|
|
4939
|
+
}
|
|
4940
|
+
}
|
|
4941
|
+
return {
|
|
4942
|
+
valid: errors.length === 0,
|
|
4943
|
+
errors,
|
|
4944
|
+
warnings
|
|
4945
|
+
};
|
|
3373
4946
|
}
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
4947
|
+
function validateContent(content, index, errors, _warnings) {
|
|
4948
|
+
if (typeof content !== "object" || content === null) {
|
|
4949
|
+
errors.push({
|
|
4950
|
+
code: "INVALID_CONTENT",
|
|
4951
|
+
message: `contents[${index}] \u5FC5\u987B\u662F\u5BF9\u8C61`,
|
|
4952
|
+
field: `contents[${index}]`
|
|
4953
|
+
});
|
|
4954
|
+
return;
|
|
3381
4955
|
}
|
|
3382
|
-
const
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
form.set("visibility", "public");
|
|
3390
|
-
form.set(
|
|
3391
|
-
"file",
|
|
3392
|
-
new Blob([bytes], { type: contentTypeOf(rel) }),
|
|
3393
|
-
rel.split("/").pop()
|
|
3394
|
-
);
|
|
3395
|
-
await client.upload(`/api/v1/projects/${project2}/files`, form, "HOSTING_UPLOAD_FAILED");
|
|
3396
|
-
uploaded.push({ path: `site/${rel}`, size: info2.size });
|
|
4956
|
+
const c = content;
|
|
4957
|
+
if (typeof c.path !== "string" || c.path.trim() === "") {
|
|
4958
|
+
errors.push({
|
|
4959
|
+
code: "MISSING_CONTENT_PATH",
|
|
4960
|
+
message: `contents[${index}].path \u5FC5\u987B\u975E\u7A7A`,
|
|
4961
|
+
field: `contents[${index}].path`
|
|
4962
|
+
});
|
|
3397
4963
|
}
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
}
|
|
3404
|
-
)
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
}
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
const rel = entry.path.replace(/^site\//, "");
|
|
3424
|
-
const target = join12(outputDir, ...rel.split("/"));
|
|
3425
|
-
await mkdir8(dirname8(target), { recursive: true });
|
|
3426
|
-
await writeFile7(target, bytes);
|
|
3427
|
-
files.push({ path: entry.path, size: bytes.length });
|
|
4964
|
+
if (typeof c.sha256 !== "string" || c.sha256.trim() === "") {
|
|
4965
|
+
errors.push({
|
|
4966
|
+
code: "MISSING_CONTENT_SHA256",
|
|
4967
|
+
message: `contents[${index}].sha256 \u5FC5\u987B\u975E\u7A7A`,
|
|
4968
|
+
field: `contents[${index}].sha256`
|
|
4969
|
+
});
|
|
4970
|
+
} else if (!/^[a-fA-F0-9]{64}$/.test(c.sha256)) {
|
|
4971
|
+
errors.push({
|
|
4972
|
+
code: "INVALID_SHA256_FORMAT",
|
|
4973
|
+
message: `contents[${index}].sha256 \u5FC5\u987B\u662F 64 \u5B57\u7B26\u5341\u516D\u8FDB\u5236`,
|
|
4974
|
+
field: `contents[${index}].sha256`
|
|
4975
|
+
});
|
|
4976
|
+
}
|
|
4977
|
+
if (typeof c.kind !== "string" || c.kind.trim() === "") {
|
|
4978
|
+
errors.push({
|
|
4979
|
+
code: "MISSING_CONTENT_KIND",
|
|
4980
|
+
message: `contents[${index}].kind \u5FC5\u987B\u975E\u7A7A`,
|
|
4981
|
+
field: `contents[${index}].kind`
|
|
4982
|
+
});
|
|
4983
|
+
} else if (!ALLOWED_CONTENT_KINDS.includes(c.kind)) {
|
|
4984
|
+
errors.push({
|
|
4985
|
+
code: "INVALID_CONTENT_KIND",
|
|
4986
|
+
message: `contents[${index}].kind "${c.kind}" \u4E0D\u5728\u5141\u8BB8\u5217\u8868\u5185\uFF0C\u5141\u8BB8\u503C\uFF1A${ALLOWED_CONTENT_KINDS.join(", ")}`,
|
|
4987
|
+
field: `contents[${index}].kind`
|
|
4988
|
+
});
|
|
3428
4989
|
}
|
|
3429
|
-
return { siteUrl: info.siteUrl, outputDir, files };
|
|
3430
4990
|
}
|
|
3431
|
-
|
|
3432
|
-
const
|
|
3433
|
-
const
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
4991
|
+
function verifyContents(contents, actualContents, hashFunction) {
|
|
4992
|
+
const errors = [];
|
|
4993
|
+
const warnings = [];
|
|
4994
|
+
for (const content of contents) {
|
|
4995
|
+
const actual = actualContents.get(content.path);
|
|
4996
|
+
if (actual === void 0) {
|
|
4997
|
+
errors.push({
|
|
4998
|
+
code: "CONTENT_NOT_FOUND",
|
|
4999
|
+
message: `\u5185\u5BB9\u7269 ${content.path} \u5728\u5B9E\u9645\u5305\u4E2D\u4E0D\u5B58\u5728`,
|
|
5000
|
+
field: `contents[${content.path}]`
|
|
5001
|
+
});
|
|
5002
|
+
continue;
|
|
5003
|
+
}
|
|
5004
|
+
const actualHash = hashFunction(actual);
|
|
5005
|
+
if (actualHash.toLowerCase() !== content.sha256.toLowerCase()) {
|
|
5006
|
+
errors.push({
|
|
5007
|
+
code: "CHECKSUM_MISMATCH",
|
|
5008
|
+
message: `\u5185\u5BB9\u7269 ${content.path} \u7684\u6821\u9A8C\u548C\u4E0D\u5339\u914D\uFF1A\u671F\u671B ${content.sha256}\uFF0C\u5B9E\u9645 ${actualHash}`,
|
|
5009
|
+
field: `contents[${content.path}].sha256`
|
|
5010
|
+
});
|
|
5011
|
+
}
|
|
5012
|
+
}
|
|
5013
|
+
for (const path of actualContents.keys()) {
|
|
5014
|
+
if (!contents.some((c) => c.path === path)) {
|
|
5015
|
+
warnings.push({
|
|
5016
|
+
code: "UNDECLARED_CONTENT",
|
|
5017
|
+
message: `\u5B9E\u9645\u5305\u4E2D\u5B58\u5728 Manifest \u672A\u58F0\u660E\u7684\u5185\u5BB9\uFF1A${path}`,
|
|
5018
|
+
field: `contents[${path}]`
|
|
5019
|
+
});
|
|
5020
|
+
}
|
|
5021
|
+
}
|
|
5022
|
+
return {
|
|
5023
|
+
valid: errors.length === 0,
|
|
5024
|
+
errors,
|
|
5025
|
+
warnings
|
|
5026
|
+
};
|
|
3441
5027
|
}
|
|
3442
|
-
var
|
|
3443
|
-
|
|
3444
|
-
"packages/cli/src/hosting.ts"() {
|
|
5028
|
+
var init_validate = __esm({
|
|
5029
|
+
"shared/deploy-bundle/validate.ts"() {
|
|
3445
5030
|
"use strict";
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
5031
|
+
init_manifest2();
|
|
5032
|
+
}
|
|
5033
|
+
});
|
|
5034
|
+
|
|
5035
|
+
// packages/cli/src/export/command.ts
|
|
5036
|
+
var command_exports = {};
|
|
5037
|
+
__export(command_exports, {
|
|
5038
|
+
ExportCommand: () => ExportCommand
|
|
5039
|
+
});
|
|
5040
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
5041
|
+
var ExportCommand;
|
|
5042
|
+
var init_command = __esm({
|
|
5043
|
+
"packages/cli/src/export/command.ts"() {
|
|
5044
|
+
"use strict";
|
|
5045
|
+
init_validate();
|
|
5046
|
+
ExportCommand = class {
|
|
5047
|
+
constructor(apiClient, fs, pollInterval = 2e3, maxPollAttempts = 300) {
|
|
5048
|
+
this.apiClient = apiClient;
|
|
5049
|
+
this.fs = fs;
|
|
5050
|
+
this.pollInterval = pollInterval;
|
|
5051
|
+
this.maxPollAttempts = maxPollAttempts;
|
|
5052
|
+
}
|
|
5053
|
+
/**
|
|
5054
|
+
* 执行导出命令。
|
|
5055
|
+
*
|
|
5056
|
+
* @param options 命令选项
|
|
5057
|
+
* @returns 导出结果
|
|
5058
|
+
*/
|
|
5059
|
+
async execute(options) {
|
|
5060
|
+
const projectId = options.project ?? "default";
|
|
5061
|
+
const outputDir = options.out ?? "./exports";
|
|
5062
|
+
const jsonOutput = options.json ?? false;
|
|
5063
|
+
try {
|
|
5064
|
+
if (!jsonOutput) {
|
|
5065
|
+
console.log(`\u89E6\u53D1\u5BFC\u51FA\uFF1A\u9879\u76EE ${projectId}`);
|
|
5066
|
+
}
|
|
5067
|
+
const job = await this.apiClient.triggerExport(projectId, {
|
|
5068
|
+
withData: options.withData,
|
|
5069
|
+
withSource: options.withSource
|
|
5070
|
+
});
|
|
5071
|
+
if (!jsonOutput) {
|
|
5072
|
+
console.log(`\u5BFC\u51FA\u4EFB\u52A1\u5DF2\u521B\u5EFA\uFF1A${job.id}`);
|
|
5073
|
+
}
|
|
5074
|
+
const completedJob = await this.pollJobStatus(job.id, jsonOutput);
|
|
5075
|
+
if (completedJob.status === "failed") {
|
|
5076
|
+
return {
|
|
5077
|
+
success: false,
|
|
5078
|
+
jobId: job.id,
|
|
5079
|
+
status: "failed",
|
|
5080
|
+
error: completedJob.error ?? "\u5BFC\u51FA\u5931\u8D25"
|
|
5081
|
+
};
|
|
5082
|
+
}
|
|
5083
|
+
if (!jsonOutput) {
|
|
5084
|
+
console.log("\u4E0B\u8F7D\u5BFC\u51FA\u4EA7\u7269...");
|
|
5085
|
+
}
|
|
5086
|
+
const outputPath = `${outputDir}/${projectId}-export-${Date.now()}.zip`;
|
|
5087
|
+
await this.fs.mkdir(outputDir);
|
|
5088
|
+
const downloadResult = await this.apiClient.downloadBundle(job.id, outputPath);
|
|
5089
|
+
if (!jsonOutput) {
|
|
5090
|
+
console.log(`\u4EA7\u7269\u5DF2\u4E0B\u8F7D\uFF1A${downloadResult.path}\uFF08${this.formatSize(downloadResult.size)}\uFF09`);
|
|
5091
|
+
}
|
|
5092
|
+
if (!jsonOutput) {
|
|
5093
|
+
console.log("\u6267\u884C manifest \u81EA\u68C0...");
|
|
5094
|
+
}
|
|
5095
|
+
const manifest = await this.verifyManifest(downloadResult.path);
|
|
5096
|
+
if (!jsonOutput) {
|
|
5097
|
+
this.printContentList(manifest);
|
|
5098
|
+
}
|
|
5099
|
+
return {
|
|
5100
|
+
success: true,
|
|
5101
|
+
jobId: job.id,
|
|
5102
|
+
status: "completed",
|
|
5103
|
+
downloadPath: downloadResult.path,
|
|
5104
|
+
manifest: {
|
|
5105
|
+
projectName: manifest.project.name,
|
|
5106
|
+
platformVersion: manifest.platformVersion,
|
|
5107
|
+
exportedAt: manifest.exportedAt,
|
|
5108
|
+
contents: this.countContents(manifest.contents)
|
|
5109
|
+
}
|
|
5110
|
+
};
|
|
5111
|
+
} catch (error) {
|
|
5112
|
+
const message = error instanceof Error ? error.message : "unknown_error";
|
|
5113
|
+
if (message.includes("ECONNREFUSED") || message.includes("ENOTFOUND") || message.includes("network")) {
|
|
5114
|
+
return {
|
|
5115
|
+
success: false,
|
|
5116
|
+
error: `\u5E73\u53F0\u7AEF\u70B9\u4E0D\u53EF\u8FBE\uFF1A${message}\u3002\u8BF7\u68C0\u67E5\u7F51\u7EDC\u8FDE\u63A5\u548C\u5E73\u53F0\u5730\u5740\u914D\u7F6E\uFF0C\u7136\u540E\u91CD\u8BD5\u3002`
|
|
5117
|
+
};
|
|
5118
|
+
}
|
|
5119
|
+
return {
|
|
5120
|
+
success: false,
|
|
5121
|
+
error: message
|
|
5122
|
+
};
|
|
5123
|
+
}
|
|
5124
|
+
}
|
|
5125
|
+
/**
|
|
5126
|
+
* 轮询任务状态。
|
|
5127
|
+
*
|
|
5128
|
+
* @param jobId 任务 ID
|
|
5129
|
+
* @param jsonOutput 是否 JSON 输出
|
|
5130
|
+
* @returns 完成的任务
|
|
5131
|
+
*/
|
|
5132
|
+
async pollJobStatus(jobId, jsonOutput) {
|
|
5133
|
+
let attempts = 0;
|
|
5134
|
+
let lastProgress = -1;
|
|
5135
|
+
while (attempts < this.maxPollAttempts) {
|
|
5136
|
+
const job = await this.apiClient.getJobStatus(jobId);
|
|
5137
|
+
if (!jsonOutput && job.progress !== lastProgress) {
|
|
5138
|
+
const stage = job.stage ? `\uFF08${job.stage}\uFF09` : "";
|
|
5139
|
+
console.log(`\u8FDB\u5EA6\uFF1A${job.progress}%${stage}`);
|
|
5140
|
+
lastProgress = job.progress;
|
|
5141
|
+
}
|
|
5142
|
+
if (job.status === "completed" || job.status === "failed") {
|
|
5143
|
+
return job;
|
|
5144
|
+
}
|
|
5145
|
+
attempts++;
|
|
5146
|
+
await this.sleep(this.pollInterval);
|
|
5147
|
+
}
|
|
5148
|
+
throw new Error(`\u5BFC\u51FA\u4EFB\u52A1\u8D85\u65F6\uFF1A\u8F6E\u8BE2 ${this.maxPollAttempts} \u6B21\u540E\u4ECD\u672A\u5B8C\u6210`);
|
|
5149
|
+
}
|
|
5150
|
+
/**
|
|
5151
|
+
* 验证 Manifest:解压 → 契约校验 → 逐项 sha256 校验 → 清理临时目录。
|
|
5152
|
+
*
|
|
5153
|
+
* 逐项校验与导出端同法:内容物以 latin1 承载(逐字节双射,二进制条目不被解码改写),
|
|
5154
|
+
* 比对时对原字节做真实 sha256;任一不匹配即判定包损坏并抛错,不静默放行。
|
|
5155
|
+
* 无论成功失败,`${zip}.tmp` 临时目录都在 finally 里删除,不留残余。
|
|
5156
|
+
*
|
|
5157
|
+
* @param zipPath ZIP 文件路径
|
|
5158
|
+
* @returns Manifest
|
|
5159
|
+
*/
|
|
5160
|
+
async verifyManifest(zipPath) {
|
|
5161
|
+
const tempDir = `${zipPath}.tmp`;
|
|
5162
|
+
try {
|
|
5163
|
+
await this.fs.mkdir(tempDir);
|
|
5164
|
+
await this.fs.unzip(zipPath, tempDir);
|
|
5165
|
+
const manifestPath = `${tempDir}/manifest.json`;
|
|
5166
|
+
if (!await this.fs.fileExists(manifestPath)) {
|
|
5167
|
+
throw new Error("manifest.json \u4E0D\u5B58\u5728\uFF0C\u5305\u53EF\u80FD\u5DF2\u635F\u574F");
|
|
5168
|
+
}
|
|
5169
|
+
const manifestContent = await this.fs.readFile(manifestPath);
|
|
5170
|
+
const manifest = JSON.parse(manifestContent.toString("utf-8"));
|
|
5171
|
+
const validationResult = validateBundleManifest(manifest);
|
|
5172
|
+
if (!validationResult.valid) {
|
|
5173
|
+
const errors = validationResult.errors.map((e) => `${e.field ?? ""}: ${e.message}`).join("\n");
|
|
5174
|
+
throw new Error(`manifest \u6821\u9A8C\u5931\u8D25\uFF1A
|
|
5175
|
+
${errors}`);
|
|
5176
|
+
}
|
|
5177
|
+
const actual = /* @__PURE__ */ new Map();
|
|
5178
|
+
for (const content of manifest.contents) {
|
|
5179
|
+
const filePath = `${tempDir}/${content.path}`;
|
|
5180
|
+
if (await this.fs.fileExists(filePath)) {
|
|
5181
|
+
const bytes = await this.fs.readFile(filePath);
|
|
5182
|
+
actual.set(content.path, bytes.toString("latin1"));
|
|
5183
|
+
}
|
|
5184
|
+
}
|
|
5185
|
+
const contentResult = verifyContents(
|
|
5186
|
+
manifest.contents,
|
|
5187
|
+
actual,
|
|
5188
|
+
(text) => createHash4("sha256").update(Buffer.from(text, "latin1")).digest("hex")
|
|
5189
|
+
);
|
|
5190
|
+
if (!contentResult.valid) {
|
|
5191
|
+
const detail = contentResult.errors.map((e) => e.message).join("\n");
|
|
5192
|
+
throw new Error(`\u5185\u5BB9\u7269\u6821\u9A8C\u548C\u4E0D\u5339\u914D\uFF1A
|
|
5193
|
+
${detail}`);
|
|
5194
|
+
}
|
|
5195
|
+
return manifest;
|
|
5196
|
+
} finally {
|
|
5197
|
+
await this.fs.deleteFile(tempDir);
|
|
5198
|
+
}
|
|
5199
|
+
}
|
|
5200
|
+
/**
|
|
5201
|
+
* 统计内容物数量。
|
|
5202
|
+
*
|
|
5203
|
+
* @param contents 内容物列表
|
|
5204
|
+
* @returns 统计结果
|
|
5205
|
+
*/
|
|
5206
|
+
countContents(contents) {
|
|
5207
|
+
return {
|
|
5208
|
+
functions: contents.filter((c) => c.kind === "functions").length,
|
|
5209
|
+
database: contents.filter((c) => c.kind === "database").length,
|
|
5210
|
+
web: contents.filter((c) => c.kind === "web").length,
|
|
5211
|
+
runtime: contents.filter((c) => c.kind === "runtime").length,
|
|
5212
|
+
scripts: contents.filter((c) => c.kind === "scripts").length,
|
|
5213
|
+
docs: contents.filter((c) => c.kind === "docs").length,
|
|
5214
|
+
total: contents.length
|
|
5215
|
+
};
|
|
5216
|
+
}
|
|
5217
|
+
/**
|
|
5218
|
+
* 打印内容清单。
|
|
5219
|
+
*
|
|
5220
|
+
* @param manifest Manifest
|
|
5221
|
+
*/
|
|
5222
|
+
printContentList(manifest) {
|
|
5223
|
+
const counts = this.countContents(manifest.contents);
|
|
5224
|
+
console.log("");
|
|
5225
|
+
console.log("==========================================");
|
|
5226
|
+
console.log("\u5BFC\u51FA\u5185\u5BB9\u6E05\u5355");
|
|
5227
|
+
console.log("==========================================");
|
|
5228
|
+
console.log(`\u9879\u76EE\uFF1A${manifest.project.name}`);
|
|
5229
|
+
console.log(`\u5E73\u53F0\u7248\u672C\uFF1A${manifest.platformVersion}`);
|
|
5230
|
+
console.log(`\u5BFC\u51FA\u65F6\u95F4\uFF1A${manifest.exportedAt}`);
|
|
5231
|
+
console.log("");
|
|
5232
|
+
console.log(`\u51FD\u6570\u6587\u4EF6\uFF1A${counts.functions}`);
|
|
5233
|
+
console.log(`\u6570\u636E\u5E93\u6587\u4EF6\uFF1A${counts.database}`);
|
|
5234
|
+
console.log(`\u524D\u7AEF\u6587\u4EF6\uFF1A${counts.web}`);
|
|
5235
|
+
console.log(`\u8FD0\u884C\u65F6\u6587\u4EF6\uFF1A${counts.runtime}`);
|
|
5236
|
+
console.log(`\u811A\u672C\u6587\u4EF6\uFF1A${counts.scripts}`);
|
|
5237
|
+
console.log(`\u6587\u6863\u6587\u4EF6\uFF1A${counts.docs}`);
|
|
5238
|
+
console.log(`\u603B\u6587\u4EF6\u6570\uFF1A${counts.total}`);
|
|
5239
|
+
console.log("==========================================");
|
|
5240
|
+
}
|
|
5241
|
+
/**
|
|
5242
|
+
* 格式化文件大小。
|
|
5243
|
+
*
|
|
5244
|
+
* @param bytes 字节数
|
|
5245
|
+
* @returns 格式化后的大小
|
|
5246
|
+
*/
|
|
5247
|
+
formatSize(bytes) {
|
|
5248
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
5249
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
5250
|
+
if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
5251
|
+
return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
|
|
5252
|
+
}
|
|
5253
|
+
/**
|
|
5254
|
+
* 睡眠指定毫秒数。
|
|
5255
|
+
*
|
|
5256
|
+
* @param ms 毫秒数
|
|
5257
|
+
*/
|
|
5258
|
+
sleep(ms) {
|
|
5259
|
+
return new Promise((resolve15) => setTimeout(resolve15, ms));
|
|
5260
|
+
}
|
|
5261
|
+
};
|
|
3450
5262
|
}
|
|
3451
5263
|
});
|
|
3452
5264
|
|
|
@@ -3456,23 +5268,23 @@ __export(dev_exports2, {
|
|
|
3456
5268
|
loadWidgetProject: () => loadWidgetProject,
|
|
3457
5269
|
startWidgetDev: () => startWidgetDev
|
|
3458
5270
|
});
|
|
3459
|
-
import { createServer as
|
|
5271
|
+
import { createServer as createServer3 } from "node:http";
|
|
3460
5272
|
import { watch as watch2 } from "node:fs";
|
|
3461
|
-
import { readFile as
|
|
3462
|
-
import { join as
|
|
5273
|
+
import { readFile as readFile11, stat as stat11 } from "node:fs/promises";
|
|
5274
|
+
import { join as join15, resolve as resolve13 } from "node:path";
|
|
3463
5275
|
async function loadWidgetProject(cwd) {
|
|
3464
5276
|
const fallback = {
|
|
3465
5277
|
name: "widget",
|
|
3466
5278
|
framework: "vue3"
|
|
3467
5279
|
};
|
|
3468
|
-
const manifestPath =
|
|
5280
|
+
const manifestPath = join15(resolve13(cwd), "manifest.json");
|
|
3469
5281
|
try {
|
|
3470
|
-
await
|
|
5282
|
+
await stat11(manifestPath);
|
|
3471
5283
|
} catch {
|
|
3472
5284
|
return fallback;
|
|
3473
5285
|
}
|
|
3474
5286
|
try {
|
|
3475
|
-
const raw = await
|
|
5287
|
+
const raw = await readFile11(manifestPath, "utf8");
|
|
3476
5288
|
const parsed = JSON.parse(raw);
|
|
3477
5289
|
return {
|
|
3478
5290
|
name: typeof parsed["name"] === "string" ? parsed["name"] : fallback.name,
|
|
@@ -3547,7 +5359,7 @@ function sandboxHtml(name, framework) {
|
|
|
3547
5359
|
`;
|
|
3548
5360
|
}
|
|
3549
5361
|
async function startWidgetDev(options) {
|
|
3550
|
-
const cwd =
|
|
5362
|
+
const cwd = resolve13(options.cwd);
|
|
3551
5363
|
const log = options.log ?? ((line) => process.stdout.write(`${line}
|
|
3552
5364
|
`));
|
|
3553
5365
|
const project2 = await loadWidgetProject(cwd);
|
|
@@ -3598,14 +5410,14 @@ data: ${version}
|
|
|
3598
5410
|
}
|
|
3599
5411
|
const readTheme = async () => {
|
|
3600
5412
|
try {
|
|
3601
|
-
return await
|
|
5413
|
+
return await readFile11(join15(cwd, "src", "theme.css"), "utf8");
|
|
3602
5414
|
} catch {
|
|
3603
5415
|
return null;
|
|
3604
5416
|
}
|
|
3605
5417
|
};
|
|
3606
5418
|
const readProps = async () => {
|
|
3607
5419
|
try {
|
|
3608
|
-
return await
|
|
5420
|
+
return await readFile11(join15(cwd, "src", "mock-props.json"), "utf8");
|
|
3609
5421
|
} catch {
|
|
3610
5422
|
return null;
|
|
3611
5423
|
}
|
|
@@ -3657,7 +5469,7 @@ data: ${version}
|
|
|
3657
5469
|
}
|
|
3658
5470
|
res.writeHead(404).end("not found");
|
|
3659
5471
|
};
|
|
3660
|
-
const server =
|
|
5472
|
+
const server = createServer3((req, res) => {
|
|
3661
5473
|
void handle(req, res);
|
|
3662
5474
|
});
|
|
3663
5475
|
await new Promise((resolveListen, rejectListen) => {
|
|
@@ -3694,18 +5506,18 @@ var publish_exports = {};
|
|
|
3694
5506
|
__export(publish_exports, {
|
|
3695
5507
|
publishWidget: () => publishWidget
|
|
3696
5508
|
});
|
|
3697
|
-
import { readFile as
|
|
3698
|
-
import { basename as basename4, join as
|
|
5509
|
+
import { readFile as readFile12 } from "node:fs/promises";
|
|
5510
|
+
import { basename as basename4, join as join16, resolve as resolve14 } from "node:path";
|
|
3699
5511
|
async function publishWidget(paths, options) {
|
|
3700
5512
|
const log = options.log ?? ((line) => process.stdout.write(`${line}
|
|
3701
5513
|
`));
|
|
3702
5514
|
const client = await createClient(paths);
|
|
3703
|
-
const root =
|
|
5515
|
+
const root = resolve14(options.cwd);
|
|
3704
5516
|
const project2 = await loadWidgetProject(root);
|
|
3705
5517
|
const framework = options.framework ?? project2.framework;
|
|
3706
5518
|
let version = "0.1.0";
|
|
3707
5519
|
try {
|
|
3708
|
-
const pkg = JSON.parse(await
|
|
5520
|
+
const pkg = JSON.parse(await readFile12(join16(root, "package.json"), "utf8"));
|
|
3709
5521
|
if (typeof pkg["version"] === "string" && pkg["version"].length > 0) version = pkg["version"];
|
|
3710
5522
|
} catch {
|
|
3711
5523
|
version = "0.1.0";
|
|
@@ -3742,18 +5554,10 @@ var init_publish = __esm({
|
|
|
3742
5554
|
|
|
3743
5555
|
// packages/cli/src/cli.ts
|
|
3744
5556
|
init_auth();
|
|
5557
|
+
init_config();
|
|
3745
5558
|
import { Command } from "commander";
|
|
3746
5559
|
import { createRequire } from "node:module";
|
|
3747
5560
|
|
|
3748
|
-
// packages/cli/src/config.ts
|
|
3749
|
-
function resolvePaths(env = process.env) {
|
|
3750
|
-
const home = env["ADEP_HOME"] ?? `${env["HOME"] ?? ""}/.adep`;
|
|
3751
|
-
return { home, credentialsFile: `${home}/credentials` };
|
|
3752
|
-
}
|
|
3753
|
-
function resolveServer(env = process.env) {
|
|
3754
|
-
return (env["ADEP_SERVER"] ?? "https://adep.jajabjbj.top").replace(/\/+$/, "");
|
|
3755
|
-
}
|
|
3756
|
-
|
|
3757
5561
|
// packages/cli/src/init.ts
|
|
3758
5562
|
import { mkdir as mkdir2, stat as stat2, writeFile } from "node:fs/promises";
|
|
3759
5563
|
import { dirname as dirname2, join, resolve } from "node:path";
|
|
@@ -3864,6 +5668,9 @@ init_build();
|
|
|
3864
5668
|
init_init();
|
|
3865
5669
|
var requireJson = createRequire(import.meta.url);
|
|
3866
5670
|
var APP_VERSION = requireJson("../package.json").version;
|
|
5671
|
+
function needsRelogin(error) {
|
|
5672
|
+
return error.code === "NOT_LOGGED_IN" || error.code === "AUTH_UNAUTHORIZED";
|
|
5673
|
+
}
|
|
3867
5674
|
function emitError(output, command, json, error) {
|
|
3868
5675
|
if (error instanceof CliError || error instanceof InitError || error instanceof WidgetError || error instanceof WidgetInitError) {
|
|
3869
5676
|
if (json) {
|
|
@@ -3875,8 +5682,9 @@ function emitError(output, command, json, error) {
|
|
|
3875
5682
|
})
|
|
3876
5683
|
);
|
|
3877
5684
|
} else {
|
|
3878
|
-
|
|
3879
|
-
|
|
5685
|
+
const withCode = error.message.includes(error.code) || error.code.length === 0 ? error.message : `${error.message}\uFF08${error.code}\uFF09`;
|
|
5686
|
+
output(`\u9519\u8BEF\uFF1A${withCode}`);
|
|
5687
|
+
if (error instanceof CliError && needsRelogin(error)) {
|
|
3880
5688
|
output("\u63D0\u793A\uFF1A\u5148\u6267\u884C adep login");
|
|
3881
5689
|
}
|
|
3882
5690
|
}
|
|
@@ -3917,6 +5725,45 @@ function parseBool(raw) {
|
|
|
3917
5725
|
if (raw === "false") return false;
|
|
3918
5726
|
throw new CliError("INVALID_BOOLEAN", `\u5E03\u5C14\u53C2\u6570\u987B\u4E3A true \u6216 false\uFF0C\u6536\u5230 "${raw}"`);
|
|
3919
5727
|
}
|
|
5728
|
+
function formatSeconds(seconds) {
|
|
5729
|
+
return `${Math.max(0.1, Math.round(seconds * 10) / 10)}s`;
|
|
5730
|
+
}
|
|
5731
|
+
async function runDeploy(paths, output, json, cwd, slug, dir) {
|
|
5732
|
+
const { deploy: deploy2 } = await Promise.resolve().then(() => (init_deploy(), deploy_exports));
|
|
5733
|
+
const startedAt = Date.now();
|
|
5734
|
+
const result = await deploy2(paths, {
|
|
5735
|
+
cwd,
|
|
5736
|
+
...slug === void 0 ? {} : { slug },
|
|
5737
|
+
...dir === void 0 ? {} : { functionsDir: dir },
|
|
5738
|
+
// --json 下逐函数进度会破坏「stdout 恰好一个 JSON 对象」的信封约定(PRD §2.5.3)。
|
|
5739
|
+
silent: json,
|
|
5740
|
+
// 人读模式的进度也走注入的 output:deploy 内部缺省会直写 process.stdout,
|
|
5741
|
+
// 那会让带 sink 的调用方漏收这部分行。
|
|
5742
|
+
log: (line) => output(line)
|
|
5743
|
+
});
|
|
5744
|
+
const elapsedSeconds = (Date.now() - startedAt) / 1e3;
|
|
5745
|
+
const deployedCount = result.functions.filter((fn) => fn.action !== "none").length;
|
|
5746
|
+
if (json) {
|
|
5747
|
+
output(
|
|
5748
|
+
JSON.stringify({
|
|
5749
|
+
ok: true,
|
|
5750
|
+
command: "deploy",
|
|
5751
|
+
data: { ...result, elapsedSeconds, deployedCount }
|
|
5752
|
+
})
|
|
5753
|
+
);
|
|
5754
|
+
return;
|
|
5755
|
+
}
|
|
5756
|
+
for (const fn of result.functions) {
|
|
5757
|
+
output(`${fn.name} v${fn.version} ${fn.url}`);
|
|
5758
|
+
}
|
|
5759
|
+
if (result.noChanges) {
|
|
5760
|
+
output(
|
|
5761
|
+
`\u2713 no changes \xB7 ${result.functions.length} functions up to date in ${formatSeconds(elapsedSeconds)}`
|
|
5762
|
+
);
|
|
5763
|
+
return;
|
|
5764
|
+
}
|
|
5765
|
+
output(`\u2713 ${deployedCount} functions deployed in ${formatSeconds(elapsedSeconds)}`);
|
|
5766
|
+
}
|
|
3920
5767
|
function buildProgram(options = {}) {
|
|
3921
5768
|
const output = options.output ?? ((line) => process.stdout.write(`${line}
|
|
3922
5769
|
`));
|
|
@@ -4022,25 +5869,212 @@ function buildProgram(options = {}) {
|
|
|
4022
5869
|
emitError(output, "dev", jsonMode(), error);
|
|
4023
5870
|
}
|
|
4024
5871
|
});
|
|
5872
|
+
program2.command("serve").description(
|
|
5873
|
+
"\u5F00\u53D1\u6001\u670D\u52A1\u5668\uFF1A\u51FD\u6570 /api/{fn} + /healthz + \u9759\u6001\u6258\u7BA1 + \u7EC4\u4EF6\u9884\u89C8\uFF08\u9ED8\u8BA4\u4EC5\u56DE\u73AF\uFF0C\u4E0D\u662F\u751F\u4EA7\u670D\u52A1\u5668\uFF09"
|
|
5874
|
+
).option("-p, --port <port>", "\u76D1\u542C\u7AEF\u53E3\uFF08\u7F3A\u7701\u53D6 PORT \u73AF\u5883\u53D8\u91CF\uFF0C\u518D\u7F3A\u7701 8787\uFF09").option(
|
|
5875
|
+
"-H, --host <host>",
|
|
5876
|
+
"\u76D1\u542C\u5730\u5740\uFF08\u7F3A\u7701\u53D6 HOST \u73AF\u5883\u53D8\u91CF\uFF0C\u518D\u7F3A\u7701 127.0.0.1\uFF1B\u7ED1\u5B9A\u975E\u56DE\u73AF\u65F6\u7ED9\u51FA\u5BF9\u5916\u66B4\u9732\u8B66\u544A\uFF09"
|
|
5877
|
+
).option(
|
|
5878
|
+
"--static <dir>",
|
|
5879
|
+
"\u9759\u6001\u6258\u7BA1\u76EE\u5F55\uFF08\u7F3A\u7701\u53D6 ADEP_SERVE_STATIC_DIR\uFF0C\u518D\u7F3A\u7701 public/\uFF1B\u81EA\u6258\u7BA1\u90E8\u7F72\u5305\u6307\u5411\u5305\u5185 web/\uFF09"
|
|
5880
|
+
).action(async (flags) => {
|
|
5881
|
+
try {
|
|
5882
|
+
const { startServeServer: startServeServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
|
|
5883
|
+
await startServeServer2({
|
|
5884
|
+
cwd,
|
|
5885
|
+
...flags.port === void 0 ? {} : { port: Number(flags.port) },
|
|
5886
|
+
...flags.host === void 0 ? {} : { host: flags.host },
|
|
5887
|
+
...flags.static === void 0 ? {} : { staticDir: flags.static }
|
|
5888
|
+
});
|
|
5889
|
+
await new Promise(() => void 0);
|
|
5890
|
+
} catch (error) {
|
|
5891
|
+
emitError(output, "serve", jsonMode(), error);
|
|
5892
|
+
}
|
|
5893
|
+
});
|
|
4025
5894
|
program2.command("deploy").description("\u589E\u91CF\u90E8\u7F72\uFF1A\u5BF9\u6BD4\u8FDC\u7AEF\u54C8\u5E0C \u2192 \u4EC5\u4E0A\u4F20\u53D8\u66F4 \u2192 \u53D1\u5E03 \u2192 \u8F93\u51FA\u8BBF\u95EE\u57DF\u540D").option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").action(async (flags) => {
|
|
4026
5895
|
try {
|
|
4027
|
-
|
|
4028
|
-
|
|
5896
|
+
await runDeploy(paths, output, jsonMode(), cwd, flags.project);
|
|
5897
|
+
} catch (error) {
|
|
5898
|
+
emitError(output, "deploy", jsonMode(), error);
|
|
5899
|
+
}
|
|
5900
|
+
});
|
|
5901
|
+
const projects = program2.command("projects").description("\u9879\u76EE\uFF1A\u521B\u5EFA / \u5217\u51FA / \u67E5\u770B\uFF08\u5B50\u57DF\u5730\u5740\u7531\u5E73\u53F0\u56DE\u663E\uFF0C\u4E0D\u5728 CLI \u4FA7\u62FC\uFF09");
|
|
5902
|
+
projects.command("create").description("\u521B\u5EFA\u9879\u76EE\u5E76\u8F93\u51FA\u5B50\u57DF\u5730\u5740").argument("<slug>", "\u9879\u76EE slug\uFF08\u5168\u5C40\u552F\u4E00\uFF0C\u5373\u5B50\u57DF\u540D\uFF09").option("-n, --name <name>", "\u9879\u76EE\u5C55\u793A\u540D\uFF08\u7F3A\u7701\u53D6 slug\uFF09").option("--space <spaceId>", "\u5F52\u5C5E\u7A7A\u95F4\uFF08\u7F3A\u7701\u4E2A\u4EBA\u7A7A\u95F4\uFF09").action(async (slug, flags) => {
|
|
5903
|
+
try {
|
|
5904
|
+
const { projectsCreate: projectsCreate2 } = await Promise.resolve().then(() => (init_projects(), projects_exports));
|
|
5905
|
+
const created = await projectsCreate2(paths, {
|
|
5906
|
+
slug,
|
|
5907
|
+
...flags.name === void 0 ? {} : { name: flags.name },
|
|
5908
|
+
...flags.space === void 0 ? {} : { spaceId: flags.space }
|
|
5909
|
+
});
|
|
5910
|
+
if (jsonMode()) {
|
|
5911
|
+
output(JSON.stringify({ ok: true, command: "projects create", data: created }));
|
|
5912
|
+
} else {
|
|
5913
|
+
output(`\u2713 Project created \xB7 ${created.url}`);
|
|
5914
|
+
}
|
|
5915
|
+
} catch (error) {
|
|
5916
|
+
emitError(output, "projects create", jsonMode(), error);
|
|
5917
|
+
}
|
|
5918
|
+
});
|
|
5919
|
+
projects.command("list").description("\u5217\u51FA\u5F53\u524D\u7528\u6237\u53EF\u8BBF\u95EE\u7684\u9879\u76EE").action(async () => {
|
|
5920
|
+
try {
|
|
5921
|
+
const { projectsList: projectsList2 } = await Promise.resolve().then(() => (init_projects(), projects_exports));
|
|
5922
|
+
const list = await projectsList2(paths);
|
|
5923
|
+
if (jsonMode()) {
|
|
5924
|
+
output(JSON.stringify({ ok: true, command: "projects list", data: { projects: list } }));
|
|
5925
|
+
} else {
|
|
5926
|
+
if (list.length === 0) output("\uFF08\u8FD8\u6CA1\u6709\u9879\u76EE\uFF1Aadep projects create <slug>\uFF09");
|
|
5927
|
+
for (const project2 of list) output(`${project2.slug} ${project2.name} ${project2.url}`);
|
|
5928
|
+
}
|
|
5929
|
+
} catch (error) {
|
|
5930
|
+
emitError(output, "projects list", jsonMode(), error);
|
|
5931
|
+
}
|
|
5932
|
+
});
|
|
5933
|
+
projects.command("info").description("\u67E5\u770B\u5355\u4E2A\u9879\u76EE\u7684 id / slug / \u5B50\u57DF\u5730\u5740").argument("<slug>", "\u9879\u76EE slug").action(async (slug) => {
|
|
5934
|
+
try {
|
|
5935
|
+
const { projectsInfo: projectsInfo2 } = await Promise.resolve().then(() => (init_projects(), projects_exports));
|
|
5936
|
+
const project2 = await projectsInfo2(paths, { slug });
|
|
5937
|
+
if (jsonMode()) {
|
|
5938
|
+
output(JSON.stringify({ ok: true, command: "projects info", data: project2 }));
|
|
5939
|
+
} else {
|
|
5940
|
+
output(`${project2.id} ${project2.slug} ${project2.name} ${project2.url}`);
|
|
5941
|
+
}
|
|
5942
|
+
} catch (error) {
|
|
5943
|
+
emitError(output, "projects info", jsonMode(), error);
|
|
5944
|
+
}
|
|
5945
|
+
});
|
|
5946
|
+
const functions = program2.command("functions").description("\u4E91\u51FD\u6570\uFF1A\u90E8\u7F72\uFF08\u53EF\u6307\u5B9A\u76EE\u5F55\uFF09/ \u5217\u51FA / \u67E5\u65E5\u5FD7");
|
|
5947
|
+
functions.command("deploy").description(
|
|
5948
|
+
"\u90E8\u7F72\u51FD\u6570\u76EE\u5F55\uFF08`adep deploy` \u7684\u547D\u4EE4\u65CF\u5165\u53E3\uFF1Bdir \u8986\u76D6 adep.config.ts \u7684 functionsDir\uFF09"
|
|
5949
|
+
).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) => {
|
|
5950
|
+
try {
|
|
5951
|
+
await runDeploy(paths, output, jsonMode(), cwd, flags.project, dir);
|
|
5952
|
+
} catch (error) {
|
|
5953
|
+
emitError(output, "functions deploy", jsonMode(), error);
|
|
5954
|
+
}
|
|
5955
|
+
});
|
|
5956
|
+
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) => {
|
|
5957
|
+
try {
|
|
5958
|
+
const { functionsList: functionsList2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
|
|
5959
|
+
const result = await functionsList2(paths, {
|
|
4029
5960
|
cwd,
|
|
4030
5961
|
...flags.project === void 0 ? {} : { slug: flags.project }
|
|
4031
5962
|
});
|
|
4032
5963
|
if (jsonMode()) {
|
|
4033
|
-
output(JSON.stringify({ ok: true, command: "
|
|
5964
|
+
output(JSON.stringify({ ok: true, command: "functions list", data: result }));
|
|
4034
5965
|
} else {
|
|
4035
|
-
if (result.
|
|
4036
|
-
output("no changes\uFF1A\u5168\u90E8\u51FD\u6570\u4E0E\u5DF2\u53D1\u5E03\u7248\u672C\u4E00\u81F4\uFF0C\u672A\u4EA7\u751F\u65B0\u7248\u672C");
|
|
4037
|
-
}
|
|
5966
|
+
if (result.functions.length === 0) output("\uFF08\u8BE5\u9879\u76EE\u4E0B\u8FD8\u6CA1\u6709\u51FD\u6570\uFF09");
|
|
4038
5967
|
for (const fn of result.functions) {
|
|
4039
|
-
output(`${fn.name}
|
|
5968
|
+
output(`${fn.name} ${result.baseUrl}/${fn.name}`);
|
|
4040
5969
|
}
|
|
4041
5970
|
}
|
|
4042
5971
|
} catch (error) {
|
|
4043
|
-
emitError(output, "
|
|
5972
|
+
emitError(output, "functions list", jsonMode(), error);
|
|
5973
|
+
}
|
|
5974
|
+
});
|
|
5975
|
+
functions.command("logs").description("\u67E5\u8BE2\u51FD\u6570\u6700\u8FD1\u6267\u884C\u65E5\u5FD7\uFF08\u7F13\u51B2\u5728\u5E73\u53F0\u8FDB\u7A0B\u5185\uFF0C\u672A\u6267\u884C\u8FC7\u7684\u51FD\u6570\u4E3A\u7A7A\uFF09").argument("<name>", "\u51FD\u6570\u540D").option("--tail <count>", "\u53D6\u6700\u8FD1\u591A\u5C11\u6761\uFF08\u7F3A\u7701 100\uFF0C\u670D\u52A1\u7AEF\u6709\u4E0A\u9650\uFF09").option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").action(async (name, flags) => {
|
|
5976
|
+
try {
|
|
5977
|
+
const { functionsLogs: functionsLogs2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
|
|
5978
|
+
const tail = flags.tail === void 0 ? void 0 : Number(flags.tail);
|
|
5979
|
+
if (tail !== void 0 && (!Number.isFinite(tail) || tail <= 0)) {
|
|
5980
|
+
throw new CliError("INVALID_TAIL", `--tail \u987B\u4E3A\u6B63\u6574\u6570\uFF0C\u6536\u5230 "${flags.tail}"`);
|
|
5981
|
+
}
|
|
5982
|
+
const result = await functionsLogs2(paths, {
|
|
5983
|
+
cwd,
|
|
5984
|
+
name,
|
|
5985
|
+
...tail === void 0 ? {} : { tail },
|
|
5986
|
+
...flags.project === void 0 ? {} : { slug: flags.project }
|
|
5987
|
+
});
|
|
5988
|
+
if (jsonMode()) {
|
|
5989
|
+
output(JSON.stringify({ ok: true, command: "functions logs", data: result }));
|
|
5990
|
+
} else {
|
|
5991
|
+
if (result.logs.length === 0) {
|
|
5992
|
+
output(`\uFF08\u51FD\u6570 ${name} \u6682\u65E0\u6267\u884C\u65E5\u5FD7\uFF1A\u5148\u7528 adep deploy \u53D1\u5E03\u5E76\u7ECF\u7F51\u5173\u6216\u8C03\u8BD5\u9762\u677F\u6267\u884C\u4E00\u6B21\uFF09`);
|
|
5993
|
+
}
|
|
5994
|
+
for (const log of result.logs) output(`${log.at} [${log.level}] ${log.message}`);
|
|
5995
|
+
}
|
|
5996
|
+
} catch (error) {
|
|
5997
|
+
emitError(output, "functions logs", jsonMode(), error);
|
|
5998
|
+
}
|
|
5999
|
+
});
|
|
6000
|
+
const mcp = program2.command("mcp").description("MCP Tool\uFF1A\u628A\u4E91\u51FD\u6570\u53D1\u5E03\u4E3A\u5DE5\u5177 / \u53D6\u6D88\u53D1\u5E03 / \u5217\u51FA");
|
|
6001
|
+
mcp.command("publish").description("\u53D1\u5E03\u4E91\u51FD\u6570\u4E3A\u9879\u76EE MCP Tool\uFF08Tool \u540D\u7F3A\u7701\u53D6\u51FD\u6570\u540D\uFF0C--name \u53EF\u8986\u76D6\uFF09").requiredOption("--function <fn>", "\u8981\u53D1\u5E03\u7684\u51FD\u6570\u540D").option("--name <tool>", "\u6CE8\u518C\u7684 Tool \u540D\uFF08\u7F3A\u7701\u53D6\u51FD\u6570\u540D\uFF09").option(
|
|
6002
|
+
"--description <text>",
|
|
6003
|
+
"\u8986\u76D6\u9762\u5411 Agent \u7684\u5DE5\u5177\u63CF\u8FF0\uFF08\u7F3A\u7701\u7528\u6E90\u7801 @description / \u63A8\u5BFC\u63CF\u8FF0\uFF09"
|
|
6004
|
+
).option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").action(
|
|
6005
|
+
async (flags) => {
|
|
6006
|
+
try {
|
|
6007
|
+
const { mcpPublish: mcpPublish2 } = await Promise.resolve().then(() => (init_mcp(), mcp_exports));
|
|
6008
|
+
const result = await mcpPublish2(paths, {
|
|
6009
|
+
cwd,
|
|
6010
|
+
fn: flags.function,
|
|
6011
|
+
...flags.name === void 0 ? {} : { toolName: flags.name },
|
|
6012
|
+
...flags.description === void 0 ? {} : { description: flags.description },
|
|
6013
|
+
...flags.project === void 0 ? {} : { slug: flags.project }
|
|
6014
|
+
});
|
|
6015
|
+
if (jsonMode()) {
|
|
6016
|
+
output(JSON.stringify({ ok: true, command: "mcp publish", data: result }));
|
|
6017
|
+
} else {
|
|
6018
|
+
output(`\u2713 MCP tool published \xB7 ${result.tool.name}`);
|
|
6019
|
+
}
|
|
6020
|
+
} catch (error) {
|
|
6021
|
+
emitError(output, "mcp publish", jsonMode(), error);
|
|
6022
|
+
}
|
|
6023
|
+
}
|
|
6024
|
+
);
|
|
6025
|
+
mcp.command("unpublish").description("\u53D6\u6D88\u53D1\u5E03\u4E91\u51FD\u6570\u5BF9\u5E94\u7684 MCP Tool\uFF08\u7ACB\u5373\u4ECE\u9879\u76EE tools/list \u79FB\u9664\uFF09").requiredOption("--function <fn>", "\u51FD\u6570\u540D").option("--name <tool>", "\u5DF2\u6CE8\u518C\u7684 Tool \u540D\uFF08\u7F3A\u7701\u53D6\u51FD\u6570\u540D\uFF1B\u53D1\u5E03\u65F6\u7528\u4E86\u522B\u540D\u624D\u9700\u7ED9\u51FA\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) => {
|
|
6026
|
+
try {
|
|
6027
|
+
const { mcpUnpublish: mcpUnpublish2 } = await Promise.resolve().then(() => (init_mcp(), mcp_exports));
|
|
6028
|
+
const result = await mcpUnpublish2(paths, {
|
|
6029
|
+
cwd,
|
|
6030
|
+
fn: flags.function,
|
|
6031
|
+
...flags.name === void 0 ? {} : { toolName: flags.name },
|
|
6032
|
+
...flags.project === void 0 ? {} : { slug: flags.project }
|
|
6033
|
+
});
|
|
6034
|
+
if (jsonMode()) {
|
|
6035
|
+
output(JSON.stringify({ ok: true, command: "mcp unpublish", data: result }));
|
|
6036
|
+
} else if (result.removed) {
|
|
6037
|
+
output(`\u2713 MCP tool unpublished \xB7 ${result.toolName}`);
|
|
6038
|
+
} else {
|
|
6039
|
+
output(`\uFF08\u9879\u76EE\u672A\u53D1\u5E03\u540D\u4E3A ${result.toolName} \u7684 MCP tool\uFF0C\u65E0\u9700\u53D6\u6D88\uFF09`);
|
|
6040
|
+
}
|
|
6041
|
+
} catch (error) {
|
|
6042
|
+
emitError(output, "mcp unpublish", jsonMode(), error);
|
|
6043
|
+
}
|
|
6044
|
+
});
|
|
6045
|
+
mcp.command("list").description("\u5217\u51FA\u9879\u76EE\u5DF2\u53D1\u5E03\u7684 MCP Tool \u4E0E\u7AEF\u70B9\u5730\u5740\uFF08\u8BFB\u9879\u76EE /mcp \u7684 tools/list\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) => {
|
|
6046
|
+
try {
|
|
6047
|
+
const { mcpList: mcpList2 } = await Promise.resolve().then(() => (init_mcp(), mcp_exports));
|
|
6048
|
+
const result = await mcpList2(paths, {
|
|
6049
|
+
cwd,
|
|
6050
|
+
...flags.project === void 0 ? {} : { slug: flags.project }
|
|
6051
|
+
});
|
|
6052
|
+
if (jsonMode()) {
|
|
6053
|
+
output(JSON.stringify({ ok: true, command: "mcp list", data: result }));
|
|
6054
|
+
} else {
|
|
6055
|
+
output(`\u7AEF\u70B9\uFF1A${result.endpoint}`);
|
|
6056
|
+
if (result.tools.length === 0) {
|
|
6057
|
+
output("\uFF08\u8FD8\u6CA1\u6709\u5DF2\u53D1\u5E03\u7684 MCP tool\uFF1Aadep mcp publish --function <fn>\uFF09");
|
|
6058
|
+
}
|
|
6059
|
+
for (const tool of result.tools) {
|
|
6060
|
+
output(`${tool.name} ${tool.description ?? ""}`);
|
|
6061
|
+
}
|
|
6062
|
+
}
|
|
6063
|
+
} catch (error) {
|
|
6064
|
+
emitError(output, "mcp list", jsonMode(), error);
|
|
6065
|
+
}
|
|
6066
|
+
});
|
|
6067
|
+
program2.command("doctor").description("\u73AF\u5883\u81EA\u68C0\uFF1A\u51ED\u636E\u72B6\u6001 / \u5E73\u53F0\u53EF\u8FBE\u6027 / \u79BB\u7EBF\u53EF\u7528\u8303\u56F4\uFF08\u8865\u9F50\u65AD\u7F51\u6587\u6848\u5F15\u7528\u7684\u60AC\u7A7A\u547D\u4EE4\uFF09").action(async () => {
|
|
6068
|
+
try {
|
|
6069
|
+
const { runDoctor: runDoctor2, formatDoctorReport: formatDoctorReport2 } = await Promise.resolve().then(() => (init_doctor(), doctor_exports));
|
|
6070
|
+
const report = await runDoctor2(paths);
|
|
6071
|
+
if (jsonMode()) {
|
|
6072
|
+
output(JSON.stringify({ ok: true, command: "doctor", data: report }));
|
|
6073
|
+
} else {
|
|
6074
|
+
for (const line of formatDoctorReport2(report)) output(line);
|
|
6075
|
+
}
|
|
6076
|
+
} catch (error) {
|
|
6077
|
+
emitError(output, "doctor", jsonMode(), error);
|
|
4044
6078
|
}
|
|
4045
6079
|
});
|
|
4046
6080
|
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").option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09");
|
|
@@ -4361,6 +6395,45 @@ function buildProgram(options = {}) {
|
|
|
4361
6395
|
emitError(output, "hosting config", jsonMode(), error);
|
|
4362
6396
|
}
|
|
4363
6397
|
});
|
|
6398
|
+
program2.command("export").description("\u5BFC\u51FA\u81EA\u6258\u7BA1\u90E8\u7F72\u5305\uFF1A\u89E6\u53D1\u957F\u4EFB\u52A1 \u2192 \u8F6E\u8BE2\u8FDB\u5EA6 \u2192 \u4E0B\u8F7D zip \u2192 manifest \u9010\u9879\u81EA\u68C0").option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").option("--with-data", "\u5305\u542B\u6570\u636E\u5E93\u884C\u6570\u636E\uFF08\u7F3A\u7701\u4EC5 schema\uFF09").option("--with-source", "\u5305\u542B\u51FD\u6570\u6E90\u7801\uFF08\u7F3A\u7701\u5E73\u53F0\u5DF2\u542B\uFF0C\u663E\u5F0F\u7F6E\u6B64\u4E0D\u6539\u53D8\u9ED8\u8BA4\uFF09").option("--out <dir>", "\u8F93\u51FA\u76EE\u5F55\uFF08\u7F3A\u7701 ./exports\uFF09").action(
|
|
6399
|
+
async (flags) => {
|
|
6400
|
+
try {
|
|
6401
|
+
const { createExportApiClient: createExportApiClient2 } = await Promise.resolve().then(() => (init_client2(), client_exports2));
|
|
6402
|
+
const { createExportFileSystem: createExportFileSystem2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
|
|
6403
|
+
const { ExportCommand: ExportCommand2 } = await Promise.resolve().then(() => (init_command(), command_exports));
|
|
6404
|
+
const { resolveSlug: resolveSlug2 } = await Promise.resolve().then(() => (init_client(), client_exports));
|
|
6405
|
+
const project2 = await resolveSlug2(cwd, flags.project);
|
|
6406
|
+
const apiClient = await createExportApiClient2(paths);
|
|
6407
|
+
const command = new ExportCommand2(apiClient, createExportFileSystem2());
|
|
6408
|
+
const result = await command.execute({
|
|
6409
|
+
project: project2,
|
|
6410
|
+
...flags.withData === true ? { withData: true } : {},
|
|
6411
|
+
...flags.withSource === true ? { withSource: true } : {},
|
|
6412
|
+
...flags.out === void 0 ? {} : { out: flags.out },
|
|
6413
|
+
json: jsonMode()
|
|
6414
|
+
});
|
|
6415
|
+
if (jsonMode()) {
|
|
6416
|
+
if (result.success) {
|
|
6417
|
+
output(JSON.stringify({ ok: true, command: "export", data: result }));
|
|
6418
|
+
} else {
|
|
6419
|
+
output(
|
|
6420
|
+
JSON.stringify({
|
|
6421
|
+
ok: false,
|
|
6422
|
+
command: "export",
|
|
6423
|
+
error: { code: "EXPORT_FAILED", message: result.error ?? "\u5BFC\u51FA\u5931\u8D25" }
|
|
6424
|
+
})
|
|
6425
|
+
);
|
|
6426
|
+
process.exitCode = 1;
|
|
6427
|
+
}
|
|
6428
|
+
} else if (!result.success) {
|
|
6429
|
+
output(`\u9519\u8BEF\uFF1A${result.error ?? "\u5BFC\u51FA\u5931\u8D25"}`);
|
|
6430
|
+
process.exitCode = 1;
|
|
6431
|
+
}
|
|
6432
|
+
} catch (error) {
|
|
6433
|
+
emitError(output, "export", jsonMode(), error);
|
|
6434
|
+
}
|
|
6435
|
+
}
|
|
6436
|
+
);
|
|
4364
6437
|
const widget = program2.command("widget").description("\u5FAE\u524D\u7AEF\u7EC4\u4EF6\uFF08widget\uFF09\uFF1A\u811A\u624B\u67B6 / \u672C\u5730\u6C99\u7BB1 / \u53D1\u5E03");
|
|
4365
6438
|
widget.command("init").description("\u521D\u59CB\u5316 widget \u5DE5\u7A0B\uFF08\u6A21\u677F\uFF1Avue3-ts / react-ts\uFF09").argument("<name>", "widget \u540D\u79F0\uFF08\u5C0F\u5199\u5B57\u6BCD\u5F00\u5934\uFF0C\u4EC5\u5C0F\u5199\u5B57\u6BCD/\u6570\u5B57/\u8FDE\u5B57\u7B26\uFF09").option("-t, --template <template>", "\u6A21\u677F\uFF1Avue3-ts | react-ts", "vue3-ts").action(async (name, flags) => {
|
|
4366
6439
|
try {
|