@adep/cli 0.0.3 → 0.0.4

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.
@@ -0,0 +1,692 @@
1
+ // packages/runtime/src/functions/runtime/worker-entry.ts
2
+ import { parentPort, workerData } from "node:worker_threads";
3
+ import { createRequire } from "node:module";
4
+ import { join } from "node:path";
5
+
6
+ // packages/runtime/src/functions/runtime/cloud-container.ts
7
+ var KNOWN_CAPABILITY_HINTS = {
8
+ db: {
9
+ code: "DB_NOT_PROVISIONED",
10
+ message: "\u9879\u76EE\u6570\u636E\u5E93\u5C1A\u672A\u5F00\u542F\uFF1A\u8BF7\u5230\u9879\u76EE\u8BBE\u7F6E\u542F\u52A8\u6570\u636E\u5E93\uFF08DB_NOT_PROVISIONED\uFF09"
11
+ },
12
+ storage: {
13
+ code: "STORAGE_NOT_AVAILABLE",
14
+ message: "\u6587\u4EF6\u5B58\u50A8\u5C1A\u672A\u5F00\u542F\uFF1A\u8BF7\u5230\u9879\u76EE\u8BBE\u7F6E\u5F00\u542F\u6587\u4EF6\u5B58\u50A8\uFF08STORAGE_NOT_AVAILABLE\uFF09"
15
+ },
16
+ fetch: {
17
+ code: "FN_FETCH_DISABLED",
18
+ message: "\u6C99\u7BB1\u7F51\u7EDC\u672A\u5F00\u542F\uFF1A\u8BF7\u914D\u7F6E FUNCTIONS_FETCH_ALLOWLIST \u767D\u540D\u5355\u540E\u91CD\u542F\uFF08FN_FETCH_DISABLED\uFF09"
19
+ },
20
+ realtime: {
21
+ code: "REALTIME_NOT_AVAILABLE",
22
+ message: "\u5B9E\u65F6\u901A\u9053\u672A\u88C5\u914D\uFF1Arealtime \u57DF\u672A\u88C5\u8F7D\uFF08\u68C0\u67E5\u90E8\u7F72\u5F62\u6001\u4E0E Redis \u914D\u7F6E\uFF09\uFF08REALTIME_NOT_AVAILABLE\uFF09"
23
+ }
24
+ };
25
+ var CapabilityNotRegisteredError = class extends Error {
26
+ code;
27
+ constructor(code, message) {
28
+ super(message);
29
+ this.code = code;
30
+ this.name = "CapabilityNotRegisteredError";
31
+ }
32
+ };
33
+ function createCloud(registrations) {
34
+ const store = registrations;
35
+ return new Proxy(
36
+ {},
37
+ {
38
+ get(_target, prop) {
39
+ if (typeof prop !== "string") return void 0;
40
+ if (!store.has(prop)) {
41
+ const hint = KNOWN_CAPABILITY_HINTS[prop];
42
+ throw new CapabilityNotRegisteredError(
43
+ hint?.code ?? "CAPABILITY_NOT_REGISTERED",
44
+ hint?.message ?? `\u80FD\u529B "${prop}" \u672A\u6CE8\u518C\uFF1A\u8BF7\u5728\u51FD\u6570\u6240\u5728\u9879\u76EE\u5B89\u88C5\u5BF9\u5E94\u80FD\u529B`
45
+ );
46
+ }
47
+ return store.get(prop);
48
+ },
49
+ has: () => true
50
+ // 支持 'db' in ctx.cloud 形态
51
+ }
52
+ );
53
+ }
54
+ function createCloudContainer() {
55
+ const registry = /* @__PURE__ */ new Map();
56
+ const names = /* @__PURE__ */ new Set();
57
+ let cloud = null;
58
+ const rebuild = () => {
59
+ cloud = createCloud(registry);
60
+ };
61
+ rebuild();
62
+ return {
63
+ register(name, impl) {
64
+ registry.set(name, impl);
65
+ names.add(name);
66
+ rebuild();
67
+ },
68
+ unregister(name) {
69
+ registry.delete(name);
70
+ names.delete(name);
71
+ rebuild();
72
+ },
73
+ get names() {
74
+ return [...names];
75
+ },
76
+ get cloud() {
77
+ return cloud;
78
+ }
79
+ };
80
+ }
81
+
82
+ // packages/runtime/src/functions/runtime/sandbox.ts
83
+ import vm from "node:vm";
84
+ import * as nodeModule from "node:module";
85
+
86
+ // packages/runtime/src/functions/runtime/exports.ts
87
+ function transformModule(code) {
88
+ let out = code;
89
+ const named = [];
90
+ out = out.replace(/(^|\n)(\s*)export\s+default\s+/g, "$1$2module.default = ");
91
+ out = out.replace(
92
+ /import\s*\{([^}]*)\}\s*from\s*(['"][^'"]*['"])[ \t]*;?/g,
93
+ (_match, names, source) => `const {${names}} = require(${source})`
94
+ );
95
+ out = out.replace(
96
+ /import\s*\*\s*as\s*([A-Za-z_$][\w$]*)\s*from\s*(['"][^'"]*['"])[ \t]*;?/g,
97
+ (_match, name, source) => `const ${name} = require(${source})`
98
+ );
99
+ out = out.replace(
100
+ /import\s+([A-Za-z_$][\w$]*)\s+from\s*(['"][^'"]*['"])[ \t]*;?/g,
101
+ (_match, name, source) => `const ${name} = require(${source})`
102
+ );
103
+ out = out.replace(
104
+ /export\s+(const|let|var)\s+([A-Za-z_$][\w$]*)/g,
105
+ (_match, kw, name) => {
106
+ named.push(name);
107
+ return `${kw} ${name}`;
108
+ }
109
+ );
110
+ out = out.replace(
111
+ /export\s+(async\s+)?function\s*\*?\s*([A-Za-z_$][\w$]*)/g,
112
+ (_match, asyncKw, name) => {
113
+ named.push(name);
114
+ return `${asyncKw ?? ""}function ${name}`;
115
+ }
116
+ );
117
+ out = out.replace(/export\s+class\s+([A-Za-z_$][\w$]*)/g, (_match, name) => {
118
+ named.push(name);
119
+ return `class ${name}`;
120
+ });
121
+ if (named.length > 0) {
122
+ out += `
123
+ ;Object.assign(exports, { ${named.join(", ")} })`;
124
+ }
125
+ return out;
126
+ }
127
+
128
+ // packages/runtime/src/functions/runtime/sandbox.ts
129
+ var bunTranspiler;
130
+ function transpile(code) {
131
+ const bun = globalThis["Bun"];
132
+ if (bun?.Transpiler !== void 0) {
133
+ bunTranspiler ??= new bun.Transpiler({ loader: "ts" });
134
+ return bunTranspiler.transformSync(code);
135
+ }
136
+ const stripTypeScriptTypes2 = nodeModule.stripTypeScriptTypes;
137
+ if (typeof stripTypeScriptTypes2 === "function") {
138
+ return stripTypeScriptTypes2(code, { mode: "strip" });
139
+ }
140
+ return code;
141
+ }
142
+ function transformExports(code) {
143
+ return transformModule(code);
144
+ }
145
+ var SANDBOX_BUILTIN_REJECTED = "FN_SANDBOX_BUILTIN_BLOCKED";
146
+ function resolveModulePath(fromDir, request, files) {
147
+ if (!request.startsWith("./") && !request.startsWith("../")) return null;
148
+ const base = joinPosix(fromDir, request);
149
+ const candidates = [base, `${base}.ts`, `${base}.js`, `${base}/index.ts`, `${base}/index.js`];
150
+ for (const candidate of candidates) {
151
+ const normalized = normalizePosix(candidate);
152
+ if (files[normalized] !== void 0) return normalized;
153
+ }
154
+ return null;
155
+ }
156
+ function joinPosix(dir, request) {
157
+ const parts = [...dir.split("/"), ...request.split("/")];
158
+ const stack = [];
159
+ for (const part of parts) {
160
+ if (part === "" || part === ".") continue;
161
+ if (part === "..") stack.pop();
162
+ else stack.push(part);
163
+ }
164
+ return stack.join("/");
165
+ }
166
+ function normalizePosix(p) {
167
+ return joinPosix("", p);
168
+ }
169
+ function loadModule(path, files, sandboxGlobals, cache, resolveBare, bareCache) {
170
+ const cached = cache.get(path);
171
+ if (cached !== void 0) return cached;
172
+ const source = files[path];
173
+ if (source === void 0) {
174
+ throw new Error(`\u6A21\u5757\u4E0D\u5B58\u5728\uFF1A${path}`);
175
+ }
176
+ const exports = {};
177
+ cache.set(path, exports);
178
+ const dir = path.includes("/") ? path.slice(0, path.lastIndexOf("/")) : "";
179
+ const module = { exports, default: void 0 };
180
+ const require2 = (request) => {
181
+ const resolved = resolveModulePath(dir, request, files);
182
+ if (resolved !== null) {
183
+ return loadModule(resolved, files, sandboxGlobals, cache, resolveBare, bareCache);
184
+ }
185
+ if (resolveBare !== void 0 && !request.startsWith("./") && !request.startsWith("../")) {
186
+ const cachedModule = bareCache?.get(request);
187
+ if (cachedModule !== void 0) return cachedModule;
188
+ const loaded = resolveBare(request);
189
+ bareCache?.set(request, loaded);
190
+ return loaded;
191
+ }
192
+ const error = new Error(
193
+ `\u6C99\u7BB1\u62D2\u7EDD\u8BE5\u5F15\u7528\uFF1A"${request}"\u3002\u51FD\u6570\u5185\u53EA\u80FD require \u9879\u76EE\u5185\u7684\u76F8\u5BF9\u8DEF\u5F84\u6587\u4EF6\uFF08FN_SANDBOX_BUILTIN_BLOCKED\uFF09`
194
+ );
195
+ error.code = SANDBOX_BUILTIN_REJECTED;
196
+ throw error;
197
+ };
198
+ let transformed;
199
+ try {
200
+ transformed = transformExports(transpile(source));
201
+ } catch (error) {
202
+ const rawMessage = error instanceof Error ? error.message : String(error);
203
+ const stack = error.stack;
204
+ const line = typeof stack === "string" ? /(?:^|\n):(\d+)(?:\n|$)/.exec(stack)?.[1] : void 0;
205
+ const location = line === void 0 ? path : `${path}:${line}`;
206
+ const wrapped = new Error(`\u6E90\u7801\u8BED\u6CD5\u9519\u8BEF\uFF08${location}\uFF09\uFF1A${rawMessage}`, { cause: error });
207
+ const code = error.code;
208
+ if (typeof code === "string") wrapped.code = code;
209
+ throw wrapped;
210
+ }
211
+ const wrapper = vm.runInNewContext(
212
+ `(function (module, exports, require) { ${transformed}
213
+ })`,
214
+ vm.createContext({ ...sandboxGlobals }),
215
+ { filename: path }
216
+ );
217
+ wrapper(module, exports, require2);
218
+ if (module.default !== void 0 && exports["default"] === void 0) {
219
+ exports["default"] = module.default;
220
+ }
221
+ return exports;
222
+ }
223
+ function loadFunctionModule(files, entry, sandboxGlobals, resolveBare) {
224
+ const cache = /* @__PURE__ */ new Map();
225
+ const bareCache = /* @__PURE__ */ new Map();
226
+ const entryExports = loadModule(entry, files, sandboxGlobals, cache, resolveBare, bareCache);
227
+ const handler = entryExports["default"];
228
+ if (typeof handler !== "function") {
229
+ throw new Error(`\u5165\u53E3\u6587\u4EF6 ${entry} \u7F3A\u5C11 default \u5BFC\u51FA\u7684\u51FD\u6570`);
230
+ }
231
+ return { handler };
232
+ }
233
+
234
+ // packages/runtime/src/functions/runtime/sandbox-fetch.ts
235
+ var SandboxFetchError = class extends Error {
236
+ code;
237
+ constructor(code, message) {
238
+ super(message);
239
+ this.name = "SandboxFetchError";
240
+ this.code = code;
241
+ }
242
+ };
243
+ var DEFAULT_MAX_RESPONSE_BYTES = 100 * 1024 * 1024;
244
+ var defaultFetch = (url, init) => (
245
+ // 真实 Response 与内部 ResponseLike 结构性一致;getReader 的多态签名差异属纯类型问题,运行语义等价。
246
+ globalThis.fetch(url, init)
247
+ );
248
+ function isHostAllowed(host, rules) {
249
+ const h = host.toLocaleLowerCase();
250
+ return rules.some((raw) => {
251
+ const rule = raw.trim().toLocaleLowerCase();
252
+ if (rule.startsWith("*.")) {
253
+ const base = rule.slice(2);
254
+ return h === base || h.endsWith(`.${base}`);
255
+ }
256
+ return h === rule;
257
+ });
258
+ }
259
+ var FORBIDDEN = (url) => new SandboxFetchError(
260
+ "FN_FETCH_FORBIDDEN",
261
+ `cloud.fetch \u62D2\u7EDD\u8BBF\u95EE "${url}"\uFF1A\u8BE5\u4E3B\u673A\u4E0D\u5728\u6C99\u7BB1\u7F51\u7EDC\u767D\u540D\u5355\u5185\uFF08FN_FETCH_FORBIDDEN\uFF09`
262
+ );
263
+ var TOO_LARGE = new SandboxFetchError(
264
+ "FN_FETCH_TOO_LARGE",
265
+ "cloud.fetch \u54CD\u5E94\u4F53\u8D85\u8FC7\u4E0A\u9650\uFF08FN_FETCH_TOO_LARGE\uFF09"
266
+ );
267
+ function headersToRecord(headers) {
268
+ const out = {};
269
+ if (headers === void 0 || headers === null) return out;
270
+ if (typeof headers.forEach === "function") {
271
+ ;
272
+ headers.forEach((value, key) => {
273
+ out[String(key).toLocaleLowerCase()] = String(value);
274
+ });
275
+ return out;
276
+ }
277
+ for (const [key, value] of Object.entries(headers)) {
278
+ out[key.toLocaleLowerCase()] = String(value);
279
+ }
280
+ return out;
281
+ }
282
+ function contentLength(res) {
283
+ const headers = res.headers;
284
+ if (headers === void 0 || headers === null) return null;
285
+ if (typeof headers.get === "function") {
286
+ const raw2 = headers.get?.("content-length");
287
+ if (raw2 === void 0 || raw2 === null || raw2.trim() === "") return null;
288
+ const n2 = Number(raw2);
289
+ return Number.isFinite(n2) && n2 >= 0 ? n2 : null;
290
+ }
291
+ const record = headers;
292
+ const raw = record["content-length"] ?? record["Content-Length"];
293
+ if (raw === void 0 || raw === null) return null;
294
+ const n = Number(raw);
295
+ return Number.isFinite(n) && n >= 0 ? n : null;
296
+ }
297
+ function concatChunks(chunks, total) {
298
+ const merged = new Uint8Array(total);
299
+ let offset = 0;
300
+ for (const chunk of chunks) {
301
+ merged.set(chunk, offset);
302
+ offset += chunk.byteLength;
303
+ }
304
+ return merged;
305
+ }
306
+ async function readBodyBytes(res, maxBytes) {
307
+ if (maxBytes > 0) {
308
+ const cl = contentLength(res);
309
+ if (cl !== null && cl > maxBytes) throw TOO_LARGE;
310
+ }
311
+ const body = res.body;
312
+ if (body !== void 0 && body !== null) {
313
+ const reader = body.getReader();
314
+ const chunks = [];
315
+ let total = 0;
316
+ for (; ; ) {
317
+ const { done, value } = await reader.read();
318
+ if (done) break;
319
+ if (value !== void 0) {
320
+ total += value.byteLength;
321
+ if (maxBytes > 0 && total > maxBytes) throw TOO_LARGE;
322
+ chunks.push(value);
323
+ }
324
+ }
325
+ return concatChunks(chunks, total);
326
+ }
327
+ if (typeof res.arrayBuffer === "function") {
328
+ const buffer = await res.arrayBuffer();
329
+ const bytes2 = new Uint8Array(buffer);
330
+ if (maxBytes > 0 && bytes2.byteLength > maxBytes) throw TOO_LARGE;
331
+ return bytes2;
332
+ }
333
+ const text = await res.text();
334
+ const bytes = encoder.encode(text);
335
+ if (maxBytes > 0 && bytes.byteLength > maxBytes) throw TOO_LARGE;
336
+ return bytes;
337
+ }
338
+ var encoder = new TextEncoder();
339
+ function errorMessageOf(error) {
340
+ if (error instanceof Error) return error.message;
341
+ return String(error);
342
+ }
343
+ function normalizeResponse(res, maxBytes) {
344
+ let cached = null;
345
+ let cachedPromise = null;
346
+ const readCached = () => {
347
+ if (cached !== null) return Promise.resolve(cached);
348
+ cachedPromise ??= readBodyBytes(res, maxBytes).then((bytes) => {
349
+ cached = bytes;
350
+ return bytes;
351
+ });
352
+ return cachedPromise;
353
+ };
354
+ const read = () => readCached();
355
+ return {
356
+ ok: res.ok,
357
+ status: res.status,
358
+ statusText: res.statusText,
359
+ headers: headersToRecord(res.headers),
360
+ text: async () => decoder.decode(await read()),
361
+ arrayBuffer: async () => bufferViewToArrayBuffer(await read()),
362
+ json: async () => JSON.parse(decoder.decode(await read()))
363
+ };
364
+ }
365
+ var decoder = new TextDecoder();
366
+ function bufferViewToArrayBuffer(bytes) {
367
+ return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
368
+ }
369
+ function createSandboxFetch(options) {
370
+ const fetchImpl = options.fetchImpl ?? defaultFetch;
371
+ const { allowlist, timeoutMs } = options;
372
+ const maxBytes = options.maxResponseBytes ?? DEFAULT_MAX_RESPONSE_BYTES;
373
+ return async (url, init) => {
374
+ let parsed;
375
+ try {
376
+ parsed = new URL(url);
377
+ } catch {
378
+ throw new SandboxFetchError("FN_FETCH_INVALID_URL", `cloud.fetch \u6536\u5230\u975E\u6CD5 URL"${url}"`);
379
+ }
380
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") throw FORBIDDEN(url);
381
+ if (!isHostAllowed(parsed.hostname, allowlist)) throw FORBIDDEN(url);
382
+ const controller = new AbortController();
383
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
384
+ const signals = [controller.signal];
385
+ if (init?.signal !== void 0) signals.push(init.signal);
386
+ const signal = signals.length === 1 ? signals[0] : AbortSignal.any(signals);
387
+ try {
388
+ let res;
389
+ try {
390
+ res = await fetchImpl(url, { ...init, signal });
391
+ } catch (error) {
392
+ if (controller.signal.aborted) {
393
+ throw new SandboxFetchError(
394
+ "FN_FETCH_TIMEOUT",
395
+ `cloud.fetch \u8BF7\u6C42\u8D85\u65F6\uFF08\u8D85\u8FC7 ${timeoutMs}ms\uFF09`
396
+ );
397
+ }
398
+ if (init?.signal?.aborted === true) {
399
+ throw new SandboxFetchError("FN_FETCH_ABORTED", "cloud.fetch \u8BF7\u6C42\u88AB\u8C03\u7528\u65B9\u4E2D\u6B62");
400
+ }
401
+ throw new SandboxFetchError(
402
+ "FN_FETCH_FAILED",
403
+ `cloud.fetch \u8BF7\u6C42\u5931\u8D25\uFF1A${errorMessageOf(error)}`
404
+ );
405
+ }
406
+ return normalizeResponse(res, maxBytes);
407
+ } finally {
408
+ clearTimeout(timer);
409
+ }
410
+ };
411
+ }
412
+
413
+ // packages/runtime/src/shared/capability-keys.ts
414
+ var RPC_CAPABILITY_KEY = "__adepRpc";
415
+ var CHAIN_CAPABILITY_KEY = "__adepChain";
416
+ var DB_RPC = {
417
+ /** 直通方法(如 query):`(method=query, args=[sql, params])`。 */
418
+ query: "query",
419
+ /** 读取 owned 表变更流(DB-006):`(method=changes, args=[table, query])`。 */
420
+ changes: "changes",
421
+ /** 开启事务:`begin → txId`。 */
422
+ begin: "begin",
423
+ /** 提交事务:`commit, args=[txId]`。 */
424
+ commit: "commit",
425
+ /** 回滚事务:`rollback, args=[txId]`。 */
426
+ rollback: "rollback",
427
+ /** 执行一条链:`chain, args=[ChainRequest]`。 */
428
+ chain: "chain"
429
+ };
430
+
431
+ // packages/runtime/src/functions/runtime/chain.ts
432
+ function isChainCapability(value) {
433
+ if (typeof value !== "object" || value === null) return false;
434
+ const spec = value[CHAIN_CAPABILITY_KEY];
435
+ return typeof spec === "object" && spec !== null && Array.isArray(spec.stepMethods) && Array.isArray(spec.terminalMethods);
436
+ }
437
+ function createChainClient(capability, port, pending, nextId, spec) {
438
+ const call = (method, args) => new Promise((resolve, reject) => {
439
+ const id = nextId();
440
+ pending.set(id, { resolve, reject });
441
+ port.postMessage({ type: "rpc", id, capability, method, args });
442
+ });
443
+ const makeChainable = (rootArgs, steps, txId) => new Proxy(
444
+ {},
445
+ {
446
+ get(_target, prop) {
447
+ if (typeof prop !== "string") return void 0;
448
+ if (spec.stepMethods.includes(prop)) {
449
+ return (...args) => makeChainable(rootArgs, [...steps, { method: prop, args }], txId);
450
+ }
451
+ if (spec.terminalMethods.includes(prop)) {
452
+ return (...args) => call(DB_RPC.chain, [
453
+ {
454
+ rootArgs,
455
+ steps,
456
+ terminal: prop,
457
+ terminalArgs: args,
458
+ ...txId === void 0 ? {} : { txId }
459
+ }
460
+ ]);
461
+ }
462
+ return void 0;
463
+ }
464
+ }
465
+ );
466
+ const makeRoot = (txId) => new Proxy(
467
+ {},
468
+ {
469
+ get(_target, prop) {
470
+ if (typeof prop !== "string") return void 0;
471
+ if (prop === spec.rootMethod) {
472
+ return (...rootArgs) => makeChainable(rootArgs, [], txId);
473
+ }
474
+ if (spec.directMethods.includes(prop)) {
475
+ return (...args) => call(prop, args);
476
+ }
477
+ if (prop === spec.transactionMethod) {
478
+ return (fn) => orchestrateTransaction(fn, txId);
479
+ }
480
+ return void 0;
481
+ }
482
+ }
483
+ );
484
+ const orchestrateTransaction = async (fn, _outerTxId) => {
485
+ const txId = await call(DB_RPC.begin, []);
486
+ const tx = makeRoot(txId);
487
+ const settle = async (commit) => {
488
+ await call(commit ? DB_RPC.commit : DB_RPC.rollback, [txId]).catch(() => void 0);
489
+ };
490
+ try {
491
+ const result = await fn(tx);
492
+ await settle(true);
493
+ return result;
494
+ } catch (error) {
495
+ await settle(false);
496
+ throw error;
497
+ }
498
+ };
499
+ return makeRoot(void 0);
500
+ }
501
+
502
+ // packages/runtime/src/functions/deps/manifest.ts
503
+ function splitBareSpecifier(request) {
504
+ if (request.startsWith("@")) {
505
+ const segments = request.split("/");
506
+ return segments.slice(0, 2).join("/");
507
+ }
508
+ return request.split("/")[0];
509
+ }
510
+
511
+ // packages/runtime/src/functions/runtime/worker-entry.ts
512
+ function isRpcCapability(value) {
513
+ return typeof value === "object" && value !== null && value[RPC_CAPABILITY_KEY] === true;
514
+ }
515
+ function createRpcClient(capability, port, pending, nextId) {
516
+ return new Proxy(
517
+ {},
518
+ {
519
+ get(_target, method) {
520
+ if (typeof method !== "string") return void 0;
521
+ return (...args) => {
522
+ const id = nextId();
523
+ return new Promise((resolve, reject) => {
524
+ pending.set(id, { resolve, reject });
525
+ port.postMessage({ type: "rpc", id, capability, method, args });
526
+ });
527
+ };
528
+ }
529
+ }
530
+ );
531
+ }
532
+ function errorMessageOf2(error) {
533
+ if (error instanceof Error) return error.message;
534
+ if (typeof error === "object" && error !== null && "message" in error) {
535
+ const message = error.message;
536
+ if (typeof message === "string") return message;
537
+ }
538
+ return String(error);
539
+ }
540
+ function escapeRegExp(text) {
541
+ return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
542
+ }
543
+ function firstUserFrame(stack, files) {
544
+ for (const key of Object.keys(files)) {
545
+ const match = new RegExp(
546
+ `(?<![\\w$/.])${escapeRegExp(key)}:(\\d+)(?::(\\d+))?(?::(\\d+))?`
547
+ ).exec(stack);
548
+ if (match !== null) {
549
+ return match[2] === void 0 ? `${key}:${match[1]}` : `${key}:${match[1]}:${match[2]}`;
550
+ }
551
+ }
552
+ return void 0;
553
+ }
554
+ function errorMessageWithLocation(error, files) {
555
+ const message = errorMessageOf2(error);
556
+ const stack = error.stack;
557
+ if (typeof stack !== "string") return message;
558
+ const frame = firstUserFrame(stack, files);
559
+ return frame === void 0 ? message : `${message}\uFF08${frame}\uFF09`;
560
+ }
561
+ function createBareResolver(deps) {
562
+ const platformRequire = createRequire(import.meta.url);
563
+ const depsRequire = deps.dir === null ? null : createRequire(join(deps.dir, "__deps__.js"));
564
+ return (request) => {
565
+ const root = splitBareSpecifier(request);
566
+ if (deps.builtin.includes(root)) return platformRequire(request);
567
+ if (deps.custom.includes(root)) {
568
+ if (depsRequire === null) {
569
+ throw new Error(`\u4F9D\u8D56 "${root}" \u672A\u88C5\u8F7D\uFF1A\u9879\u76EE\u4F9D\u8D56\u76EE\u5F55\u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u53D1\u5E03\u51FD\u6570\u89E6\u53D1\u4F9D\u8D56\u88C5\u8F7D`);
570
+ }
571
+ try {
572
+ return depsRequire(request);
573
+ } catch (error2) {
574
+ const message = errorMessageOf2(error2);
575
+ throw new Error(
576
+ `\u4F9D\u8D56 "${request}" \u88C5\u8F7D\u5931\u8D25\uFF08\u76EE\u5F55 ${deps.dir}\uFF09\uFF1A\u8BF7\u91CD\u65B0\u53D1\u5E03\u51FD\u6570\u4EE5\u89E6\u53D1\u4F9D\u8D56\u5B89\u88C5\u3002\u539F\u56E0\uFF1A${message}`,
577
+ { cause: error2 }
578
+ );
579
+ }
580
+ }
581
+ const error = new Error(
582
+ `\u6C99\u7BB1\u62D2\u7EDD\u8BE5\u5F15\u7528\uFF1A"${request}"\u3002\u4EC5\u5141\u8BB8\u76F8\u5BF9\u8DEF\u5F84\u6587\u4EF6\u4E0E\u5DF2\u58F0\u660E\u7684\u4F9D\u8D56\uFF08\u5185\u7F6E\u767D\u540D\u5355\u6216 package.json\uFF09\uFF0C\u88F8\u6A21\u5757 "${root}" \u672A\u58F0\u660E\uFF08FN_SANDBOX_BUILTIN_BLOCKED\uFF09`
583
+ );
584
+ error.code = SANDBOX_BUILTIN_REJECTED;
585
+ throw error;
586
+ };
587
+ }
588
+ function runWorker(input, port) {
589
+ const emit = (level, args) => {
590
+ port.postMessage({ type: "log", level, message: args.map(String).join(" ") });
591
+ };
592
+ const forwardedConsole = {
593
+ log: (...args) => emit("log", args),
594
+ error: (...args) => emit("error", args),
595
+ warn: (...args) => emit("warn", args)
596
+ };
597
+ const container = createCloudContainer();
598
+ const pending = /* @__PURE__ */ new Map();
599
+ let rpcId = 0;
600
+ port.on?.((message) => {
601
+ const reply = message;
602
+ if (reply?.type !== "rpc-response" || typeof reply.id !== "number") return;
603
+ const entry = pending.get(reply.id);
604
+ if (entry === void 0) return;
605
+ pending.delete(reply.id);
606
+ if (reply.ok === true) entry.resolve(reply.result);
607
+ else entry.reject(new Error(reply.error ?? "RPC \u80FD\u529B\u8C03\u7528\u5931\u8D25"));
608
+ });
609
+ for (const capability of input.capabilities ?? []) {
610
+ container.register(
611
+ capability.name,
612
+ isChainCapability(capability.value) ? createChainClient(
613
+ capability.name,
614
+ port,
615
+ pending,
616
+ () => ++rpcId,
617
+ capability.value[CHAIN_CAPABILITY_KEY]
618
+ ) : isRpcCapability(capability.value) ? createRpcClient(capability.name, port, pending, () => ++rpcId) : capability.value
619
+ );
620
+ }
621
+ const sandboxGlobals = {
622
+ console: forwardedConsole
623
+ };
624
+ if (input.env !== void 0) {
625
+ sandboxGlobals["process"] = { env: input.env };
626
+ }
627
+ if (input.fetch !== void 0) {
628
+ const sandboxFetch = createSandboxFetch({
629
+ allowlist: input.fetch.allowlist,
630
+ timeoutMs: input.fetch.timeoutMs,
631
+ ...input.fetch.maxResponseBytes === void 0 ? {} : { maxResponseBytes: input.fetch.maxResponseBytes }
632
+ });
633
+ sandboxGlobals["fetch"] = sandboxFetch;
634
+ container.register("fetch", sandboxFetch);
635
+ }
636
+ const ctx = {
637
+ method: input.request.method,
638
+ path: input.request.path,
639
+ query: input.request.query,
640
+ headers: input.request.headers,
641
+ ...input.request.body === void 0 ? {} : { body: input.request.body },
642
+ files: input.request.files ?? [],
643
+ cloud: container.cloud,
644
+ user: input.request.user ?? null
645
+ };
646
+ try {
647
+ const { handler } = loadFunctionModule(
648
+ input.files,
649
+ input.entry,
650
+ sandboxGlobals,
651
+ input.deps === void 0 ? void 0 : createBareResolver(input.deps)
652
+ );
653
+ const result = Promise.resolve(handler(ctx));
654
+ void result.then(
655
+ (value) => {
656
+ port.postMessage({ type: "result", body: value === void 0 ? null : value });
657
+ return void 0;
658
+ },
659
+ (error) => {
660
+ port.postMessage({
661
+ type: "error",
662
+ message: errorMessageWithLocation(error, input.files),
663
+ code: error.code,
664
+ // FN-011:函数抛错可携带 status(4xx/5xx),透传给执行器落 ExecutorError.status。
665
+ status: error.status
666
+ });
667
+ return void 0;
668
+ }
669
+ );
670
+ } catch (error) {
671
+ port.postMessage({
672
+ type: "error",
673
+ message: errorMessageWithLocation(error, input.files),
674
+ code: error.code,
675
+ status: error.status
676
+ });
677
+ }
678
+ }
679
+ var workerPort = parentPort;
680
+ if (workerPort !== null && workerData !== void 0) {
681
+ const port = {
682
+ // eslint-disable-next-line unicorn/require-post-message-target-origin -- node worker_threads 无 targetOrigin 语义
683
+ postMessage: (message) => workerPort.postMessage(message),
684
+ on: (listener) => {
685
+ workerPort.on("message", (value) => listener(value));
686
+ }
687
+ };
688
+ runWorker(workerData, port);
689
+ }
690
+ export {
691
+ runWorker
692
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adep/cli",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "type": "module",
5
5
  "description": "`adep` 命令行工具包位:登录 / 初始化 / 本地调试 / 部署 / 数据库维护 / 云存储 / 静态托管 / 微前端组件(widget),实现见任务单 CLI-001 ~ CLI-003 与 FE-002",
6
6
  "bin": {