@adep/cli 0.0.5 → 0.0.7

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.
Files changed (3) hide show
  1. package/README.md +45 -50
  2. package/dist/index.js +1518 -1706
  3. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -9,6 +9,20 @@ var __export = (target, all) => {
9
9
  __defProp(target, name, { get: all[name], enumerable: true });
10
10
  };
11
11
 
12
+ // packages/cli/src/config.ts
13
+ function resolvePaths(env = process.env) {
14
+ const home = env["ADEP_HOME"] ?? `${env["HOME"] ?? ""}/.adep`;
15
+ return { home, credentialsFile: `${home}/credentials` };
16
+ }
17
+ function resolveServer(env = process.env) {
18
+ return (env["ADEP_SERVER"] ?? "https://adep.jajabjbj.top").replace(/\/+$/, "");
19
+ }
20
+ var init_config = __esm({
21
+ "packages/cli/src/config.ts"() {
22
+ "use strict";
23
+ }
24
+ });
25
+
12
26
  // packages/cli/src/credentials.ts
13
27
  import { mkdir, open, readFile, rm, stat } from "node:fs/promises";
14
28
  import { dirname } from "node:path";
@@ -218,327 +232,45 @@ var init_auth = __esm({
218
232
  }
219
233
  });
220
234
 
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
-
235
- // packages/cli/src/widget/build.ts
236
- import { createHash } from "node:crypto";
237
- import { join as join2, resolve as resolve2 } from "node:path";
238
- import { build as esbuildBuild } from "esbuild";
239
- async function buildWidget(options) {
240
- const root = resolve2(options.cwd);
241
- const entry = join2(root, options.entry ?? "src/index.ts");
242
- const result = await esbuildBuild({
243
- entryPoints: [entry],
244
- bundle: true,
245
- write: false,
246
- format: "esm",
247
- target: ["es2020"],
248
- logLevel: "error",
249
- loader: { ".ts": "ts", ".tsx": "tsx", ".js": "js", ".jsx": "jsx" },
250
- ...options.framework === "react" ? { jsx: "automatic", jsxImportSource: "react" } : {}
251
- });
252
- const text = result.outputFiles?.[0]?.text ?? "";
253
- if (text.length === 0) {
254
- throw new WidgetError("EMPTY_BUILD", "\u6784\u5EFA\u4EA7\u7269\u4E3A\u7A7A\uFF1A\u8BF7\u68C0\u67E5 widget \u5165\u53E3\u662F\u5426\u6B63\u786E");
255
- }
256
- const hash = createHash("sha256").update(text).digest("hex");
257
- return { text, hash };
258
- }
259
- var WidgetError;
260
- var init_build = __esm({
261
- "packages/cli/src/widget/build.ts"() {
262
- "use strict";
263
- WidgetError = class extends Error {
264
- constructor(code, message) {
265
- super(message);
266
- this.code = code;
267
- this.name = "WidgetError";
268
- }
269
- };
270
- }
235
+ // packages/cli/src/prompt.ts
236
+ var prompt_exports = {};
237
+ __export(prompt_exports, {
238
+ createPrompt: () => createPrompt
271
239
  });
272
-
273
- // packages/cli/src/widget/templates.ts
274
- function vue3Files(name) {
275
- return {
276
- ...TS_BASE(),
277
- "manifest.json": MANIFEST(name, "vue3"),
278
- "package.json": `{
279
- "name": "${name}",
280
- "version": "0.1.0",
281
- "private": true,
282
- "type": "module",
283
- "scripts": {
284
- "typecheck": "tsc --noEmit",
285
- "dev": "adep widget dev",
286
- "widget:publish": "adep widget publish -p"
287
- },
288
- "dependencies": {
289
- "vue": "^3.5.0",
290
- "@adep/types": "workspace:*"
291
- },
292
- "devDependencies": {
293
- "typescript": "^5.5.0"
294
- }
295
- }
296
- `,
297
- "src/theme.css": THEME_CSS,
298
- "src/App.ts": `import { defineComponent, h } from 'vue'
299
-
300
- /** \u7EC4\u4EF6 props \u4E0E manifest.json \u7684 props schema \u5BF9\u9F50\uFF08contracts/ \u6821\u9A8C\u5B57\u6BB5\u5B50\u96C6\uFF09\u3002 */
301
- export const App = defineComponent({
302
- name: 'HelloVue',
303
- props: {
304
- title: { type: String, default: 'Hello' },
305
- },
306
- setup(props) {
307
- return () =>
308
- h('div', { style: { padding: 'var(--adep-space-4)' } }, [
309
- h('h2', { style: { color: 'var(--adep-color-accent)' } }, props.title),
310
- h(
311
- 'p',
312
- { style: { color: 'var(--adep-color-text-secondary)' } },
313
- 'Vue 3 \u6E32\u67D3\u51FD\u6570\u7EC4\u4EF6\u3002\u4E3B\u9898\u53D8\u91CF\u4E0E\u9274\u6743 token \u7531\u5BBF\u4E3B\u6CE8\u5165\u3002'
314
- ),
315
- ])
316
- },
317
- })
318
- `,
319
- "src/index.ts": `// Widget \u8FD0\u884C\u65F6\u5165\u53E3\uFF08FE-002\uFF09\u3002\u5BFC\u51FA HarnessWidgetRuntime \u4E09\u4EF6\u5957\uFF1A
320
- // __harness / mount(host, ctx) / unmount(host)\u3002
321
- // \u7EC4\u4EF6\u4EE5\u6E32\u67D3\u51FD\u6570\u7F16\u5199\uFF08\u975E SFC\uFF09\uFF0Cesbuild \u514D\u63D2\u4EF6\u76F4\u7F16\uFF08M3 MVP\uFF1B.vue SFC \u8D70 Vite \u5C5E\u4E8C\u671F\uFF09\u3002
322
- import { createApp, type App as VueApp } from 'vue'
323
- import type { HarnessMountHost, HarnessWidgetContext } from '@adep/types'
324
- import { App } from './App'
325
-
326
- // \u5BBF\u4E3B \u2192 \u6302\u8F7D\u7684 app \u5F15\u7528\uFF0Cunmount \u65F6\u7528\u5B8C\u91CA\u653E\uFF08WeakMap \u4E0D\u963B\u6B62\u5BBF\u4E3B\u56DE\u6536\uFF09\u3002
327
- const mounted = new WeakMap<object, { app: VueApp; root: HTMLElement }>()
328
-
329
- export const __harness = true as const
330
-
331
- export function mount(host: HarnessMountHost, ctx: HarnessWidgetContext): void {
332
- const root = document.createElement('div')
333
- host.appendChild(root)
334
- const app = createApp(App, ctx.props as never)
335
- app.mount(root)
336
- mounted.set(host, { app, root })
337
- }
338
-
339
- export function unmount(host: HarnessMountHost): void {
340
- const entry = mounted.get(host)
341
- if (entry === undefined) return
342
- entry.app.unmount()
343
- host.removeChild(entry.root)
344
- mounted.delete(host)
345
- }
346
- `,
347
- "src/mock-props.json": MOCK_PROPS
348
- };
349
- }
350
- function reactFiles(name) {
240
+ import { createInterface } from "node:readline/promises";
241
+ import { Writable } from "node:stream";
242
+ function createPrompt(input = process.stdin) {
243
+ const rl = createInterface({ input, output: process.stdout, terminal: true });
244
+ let muted = null;
351
245
  return {
352
- ...TS_BASE(),
353
- "manifest.json": MANIFEST(name, "react"),
354
- "package.json": `{
355
- "name": "${name}",
356
- "version": "0.1.0",
357
- "private": true,
358
- "type": "module",
359
- "scripts": {
360
- "typecheck": "tsc --noEmit",
361
- "dev": "adep widget dev",
362
- "widget:publish": "adep widget publish -p"
363
- },
364
- "dependencies": {
365
- "react": "^18.3.0",
366
- "react-dom": "^18.3.0",
367
- "@adep/types": "workspace:*"
368
- },
369
- "devDependencies": {
370
- "@types/react": "^18.3.0",
371
- "@types/react-dom": "^18.3.0",
372
- "typescript": "^5.5.0"
373
- }
374
- }
375
- `,
376
- "src/theme.css": THEME_CSS,
377
- "src/App.tsx": `import type { CSSProperties } from 'react'
378
-
379
- /** \u7EC4\u4EF6 props \u4E0E manifest.json \u7684 props schema \u5BF9\u9F50\uFF08contracts/ \u6821\u9A8C\u5B57\u6BB5\u5B50\u96C6\uFF09\u3002 */
380
- export interface WidgetProps {
381
- title: string
382
- }
383
-
384
- const styleRoot: CSSProperties = { padding: 'var(--adep-space-4)' }
385
- const styleTitle: CSSProperties = { color: 'var(--adep-color-accent)', margin: 0 }
386
- const styleDesc: CSSProperties = { color: 'var(--adep-color-text-secondary)' }
387
-
388
- export default function App(props: WidgetProps): React.JSX.Element {
389
- return (
390
- <div style={styleRoot}>
391
- <h2 style={styleTitle}>{props.title}</h2>
392
- <p style={styleDesc}>React 18 \u7EC4\u4EF6\u3002\u4E3B\u9898\u53D8\u91CF\u4E0E\u9274\u6743 token \u7531\u5BBF\u4E3B\u6CE8\u5165\u3002</p>
393
- </div>
394
- )
395
- }
396
- `,
397
- "src/index.tsx": `// Widget \u8FD0\u884C\u65F6\u5165\u53E3\uFF08FE-002\uFF09\u3002\u5BFC\u51FA HarnessWidgetRuntime \u4E09\u4EF6\u5957\uFF1A
398
- // __harness / mount(host, ctx) / unmount(host)\u3002
399
- import { createRoot, type Root } from 'react-dom/client'
400
- import type { HarnessMountHost, HarnessWidgetContext } from '@adep/types'
401
- import App from './App'
402
-
403
- const mounted = new WeakMap<object, { root: Root; host: HTMLElement }>()
404
-
405
- export const __harness = true as const
406
-
407
- export function mount(host: HarnessMountHost, ctx: HarnessWidgetContext): void {
408
- const container = document.createElement('div')
409
- host.appendChild(container)
410
- const root = createRoot(container)
411
- root.render(<App {...(ctx.props as never)} />)
412
- mounted.set(host, { root, host: container })
413
- }
414
-
415
- export function unmount(host: HarnessMountHost): void {
416
- const entry = mounted.get(host)
417
- if (entry === undefined) return
418
- entry.root.unmount()
419
- host.removeChild(entry.host)
420
- mounted.delete(host)
421
- }
422
- `,
423
- "src/mock-props.json": MOCK_PROPS
424
- };
425
- }
426
- function widgetTemplateFiles(name, template) {
427
- return template === "react-ts" ? reactFiles(name) : vue3Files(name);
428
- }
429
- var WIDGET_TEMPLATES, TS_BASE, MANIFEST, THEME_CSS, MOCK_PROPS;
430
- var init_templates = __esm({
431
- "packages/cli/src/widget/templates.ts"() {
432
- "use strict";
433
- WIDGET_TEMPLATES = ["vue3-ts", "react-ts"];
434
- TS_BASE = () => ({
435
- "tsconfig.json": `{
436
- "compilerOptions": {
437
- "target": "ES2020",
438
- "module": "ESNext",
439
- "moduleResolution": "Bundler",
440
- "strict": true,
441
- "jsx": "react-jsx",
442
- "skipLibCheck": true,
443
- "noEmit": true
444
- },
445
- "include": ["src"]
446
- }
447
- `,
448
- "README.md": `# <widget>
449
-
450
- AgentDeploy \u5FAE\u524D\u7AEF\u7EC4\u4EF6\uFF08widget\uFF09\u3002
451
-
452
- - \`adep widget dev\`\uFF1A\u672C\u5730\u5BBF\u4E3B\u6C99\u7BB1\uFF08\u4E3B\u9898\u53D8\u91CF + mock props + token \u6CE8\u5165 + \u70ED\u66F4\u65B0\uFF09
453
- - \`adep widget publish -p <project-slug>\`\uFF1A\u6309\u6846\u67B6\u6784\u5EFA \u2192 \u4E0A\u4F20\u5E73\u53F0\u9759\u6001\u8D44\u6E90 \u2192 \u7248\u672C\u5316\u8F93\u51FA URL
454
-
455
- > \u7EC4\u4EF6\u5165\u53E3\u5BFC\u51FA \`__harness\` / \`mount(host, ctx)\` / \`unmount(host)\`\uFF0C\u5951\u7EA6\u89C1
456
- > \`@adep/types\` \u7684 HarnessWidgetRuntime\uFF1B\u5BBF\u4E3B\u7528 \`<RemoteWidget>\` \u6309\u9700\u62C9\u53D6\u3002
457
- `,
458
- ".gitignore": "node_modules/\n.adep/\ndist/\n"
459
- });
460
- MANIFEST = (name, framework) => `{
461
- "name": "${name}",
462
- "framework": "${framework}",
463
- "props": {
464
- "type": "object",
465
- "properties": {
466
- "title": { "type": "string" }
246
+ async ask(question) {
247
+ const answer = await rl.question(question);
248
+ return answer.trim();
467
249
  },
468
- "required": ["title"]
469
- },
470
- "entry": "../dist/index.js"
471
- }
472
- `;
473
- THEME_CSS = `/* \u8BBE\u8BA1\u7CFB\u7EDF\u4E3B\u9898\u53D8\u91CF\uFF1A\u5BBF\u4E3B\u7ECF CSS Variables \u6CE8\u5165\uFF08FE-002 widget dev\uFF09\u3002
474
- \u672C\u5730\u6C99\u7BB1\u7F3A\u7701\u4EE5\u4E0B\u503C\uFF1B\u90E8\u7F72\u540E\u7531 Web IDE / \u5BBF\u4E3B\u4FA7\u6CE8\u5165\u540C\u540D\u5B57\u7684\u53D8\u91CF\u8986\u76D6\u3002 */
475
- :root {
476
- --adep-color-accent: #3370ff;
477
- --adep-color-text: #1f2329;
478
- --adep-color-text-secondary: #4c5561;
479
- --adep-space-4: 16px;
480
- }
481
- `;
482
- MOCK_PROPS = `{
483
- "title": "Hello from mock props"
484
- }
485
- `;
486
- }
487
- });
488
-
489
- // packages/cli/src/widget/init.ts
490
- var init_exports = {};
491
- __export(init_exports, {
492
- WIDGET_TEMPLATES: () => WIDGET_TEMPLATES,
493
- WidgetInitError: () => WidgetInitError,
494
- initWidget: () => initWidget
495
- });
496
- import { mkdir as mkdir3, stat as stat3, writeFile as writeFile2 } from "node:fs/promises";
497
- import { dirname as dirname3, join as join3, resolve as resolve3 } from "node:path";
498
- async function initWidget(cwd, name, template) {
499
- if (!WIDGET_NAME_RE.test(name)) {
500
- throw new WidgetInitError(
501
- "INVALID_NAME",
502
- `widget \u540D "${name}" \u4E0D\u5408\u6CD5\uFF1A\u9700\u4EE5\u5C0F\u5199\u5B57\u6BCD\u5F00\u5934\uFF0C\u4EC5\u542B\u5C0F\u5199\u5B57\u6BCD / \u6570\u5B57 / \u8FDE\u5B57\u7B26`
503
- );
504
- }
505
- if (!WIDGET_TEMPLATES.includes(template)) {
506
- throw new WidgetInitError("INVALID_TEMPLATE", `\u672A\u77E5\u6A21\u677F "${template}"\uFF1A\u53EF\u9009 vue3-ts | react-ts`);
507
- }
508
- const projectPath = resolve3(cwd, name);
509
- let existing;
510
- try {
511
- existing = await stat3(projectPath);
512
- } catch {
513
- existing = null;
514
- }
515
- if (existing !== null) {
516
- throw new WidgetInitError("DIR_EXISTS", `\u76EE\u5F55 ${projectPath} \u5DF2\u5B58\u5728\uFF1A\u8BF7\u6362\u4E00\u4E2A\u540D\u5B57\u6216\u5148\u5220\u9664`);
517
- }
518
- const files = widgetTemplateFiles(name, template);
519
- await mkdir3(projectPath, { recursive: true });
520
- await Promise.all(
521
- Object.entries(files).map(async ([rel, content]) => {
522
- const target = join3(projectPath, rel);
523
- await mkdir3(dirname3(target), { recursive: true });
524
- await writeFile2(target, content);
525
- })
526
- );
527
- return { projectPath, files: Object.keys(files).toSorted() };
250
+ async askHidden(question) {
251
+ muted = createInterface({ input, output: new MutedStream(), terminal: true });
252
+ const answer = await muted.question(question);
253
+ muted.close();
254
+ muted = null;
255
+ process.stdout.write("\n");
256
+ return answer.trim();
257
+ },
258
+ close() {
259
+ muted?.close();
260
+ rl.close();
261
+ }
262
+ };
528
263
  }
529
- var WidgetInitError, WIDGET_NAME_RE;
530
- var init_init = __esm({
531
- "packages/cli/src/widget/init.ts"() {
264
+ var MutedStream;
265
+ var init_prompt = __esm({
266
+ "packages/cli/src/prompt.ts"() {
532
267
  "use strict";
533
- init_templates();
534
- WidgetInitError = class extends Error {
535
- constructor(code, message) {
536
- super(message);
537
- this.code = code;
538
- this.name = "WidgetInitError";
268
+ MutedStream = class extends Writable {
269
+ write(_chunk, ...rest) {
270
+ void rest;
271
+ return true;
539
272
  }
540
273
  };
541
- WIDGET_NAME_RE = /^[a-z][a-z0-9-]{0,62}$/;
542
274
  }
543
275
  });
544
276
 
@@ -634,7 +366,7 @@ var init_domain = __esm({
634
366
  });
635
367
 
636
368
  // packages/runtime/src/functions/deps/manifest.ts
637
- import { createHash as createHash2 } from "node:crypto";
369
+ import { createHash } from "node:crypto";
638
370
  function isVersionRangeSpec(spec) {
639
371
  if (spec === "*" || spec === "latest") return true;
640
372
  const unions = spec.split("||");
@@ -710,7 +442,7 @@ function classifyDependencies(dependencies, builtin) {
710
442
  }
711
443
  function depsKeyOf(dependencies) {
712
444
  const canonical = Object.entries(dependencies).map(([name, version]) => `${name}@${version}`).toSorted().join("\n");
713
- return createHash2("sha256").update(canonical).digest("hex").slice(0, 16);
445
+ return createHash("sha256").update(canonical).digest("hex").slice(0, 16);
714
446
  }
715
447
  var PACKAGE_NAME_PATTERN, COMPARATOR_PATTERN, MANIFEST_MAX_DEPS;
716
448
  var init_manifest = __esm({
@@ -724,14 +456,14 @@ var init_manifest = __esm({
724
456
  });
725
457
 
726
458
  // packages/runtime/src/functions/deps/resolve.ts
727
- import { resolve as resolve4 } from "node:path";
459
+ import { resolve as resolve2 } from "node:path";
728
460
  function resolveExecutionDeps(config, projectId, manifestContent) {
729
461
  const manifest = tryParseManifestDependencies(manifestContent);
730
462
  const { customDeps } = classifyDependencies(manifest, config.builtin);
731
463
  const custom = Object.keys(customDeps);
732
464
  return {
733
465
  // 绝对化(相对进程 cwd,与 installer 侧 resolve(rootDir) 同基准):worker 的 createRequire 需要确定路径
734
- dir: custom.length === 0 ? null : resolve4(config.rootDir, projectId, depsKeyOf(customDeps)),
466
+ dir: custom.length === 0 ? null : resolve2(config.rootDir, projectId, depsKeyOf(customDeps)),
735
467
  builtin: [...config.builtin],
736
468
  custom
737
469
  };
@@ -746,22 +478,22 @@ var init_resolve = __esm({
746
478
  // packages/runtime/src/functions/runtime/worker-executor.ts
747
479
  import { readFileSync } from "node:fs";
748
480
  import { fileURLToPath, pathToFileURL } from "node:url";
749
- import { dirname as dirname4, join as join4 } from "node:path";
481
+ import { dirname as dirname3, join as join2 } from "node:path";
750
482
  import { Worker } from "node:worker_threads";
751
483
  function resolveWorkerEntry(baseDir = fileURLToPath(new URL(".", import.meta.url))) {
752
484
  const candidates = [
753
- join4(baseDir, "worker-entry.js"),
754
- join4(baseDir, "worker-entry.ts"),
755
- join4(baseDir, "domains/functions/runtime/worker-entry.js"),
756
- join4(baseDir, "domains/functions/runtime/worker-entry.ts")
485
+ join2(baseDir, "worker-entry.js"),
486
+ join2(baseDir, "worker-entry.ts"),
487
+ join2(baseDir, "domains/functions/runtime/worker-entry.js"),
488
+ join2(baseDir, "domains/functions/runtime/worker-entry.ts")
757
489
  ];
758
490
  let current = baseDir;
759
491
  for (let depth = 0; depth < 8; depth += 1) {
760
492
  candidates.push(
761
- join4(current, "packages/runtime/src/functions/runtime/worker-entry.js"),
762
- join4(current, "packages/runtime/src/functions/runtime/worker-entry.ts")
493
+ join2(current, "packages/runtime/src/functions/runtime/worker-entry.js"),
494
+ join2(current, "packages/runtime/src/functions/runtime/worker-entry.ts")
763
495
  );
764
- const parent = dirname4(current);
496
+ const parent = dirname3(current);
765
497
  if (parent === current) break;
766
498
  current = parent;
767
499
  }
@@ -803,7 +535,7 @@ var init_worker_executor = __esm({
803
535
  const entry = input.entry ?? "index.ts";
804
536
  const deps = this.depsConfig === void 0 ? void 0 : resolveExecutionDeps(this.depsConfig, input.project.id, input.files["package.json"]);
805
537
  const logs = [];
806
- return new Promise((resolve15, reject) => {
538
+ return new Promise((resolve11, reject) => {
807
539
  let worker;
808
540
  try {
809
541
  worker = new Worker(resolveWorkerEntry(), {
@@ -865,7 +597,7 @@ var init_worker_executor = __esm({
865
597
  if (message.type === "result") {
866
598
  clearTimeout(timer);
867
599
  void worker.terminate();
868
- resolve15({ body: message.body, logs });
600
+ resolve11({ body: message.body, logs });
869
601
  return;
870
602
  }
871
603
  if (message.type === "error") {
@@ -2441,13 +2173,13 @@ var init_cloud2 = __esm({
2441
2173
  });
2442
2174
 
2443
2175
  // packages/runtime/src/storage/driver/local.ts
2444
- import { mkdir as mkdir4, readFile as readFile2, readdir, rm as rm2, stat as stat4, unlink, writeFile as writeFile3 } from "node:fs/promises";
2445
- import { dirname as dirname5, join as join5 } from "node:path";
2176
+ import { mkdir as mkdir3, readFile as readFile2, readdir, rm as rm2, stat as stat3, unlink, writeFile as writeFile2 } from "node:fs/promises";
2177
+ import { dirname as dirname4, join as join3 } from "node:path";
2446
2178
  function createLocalStorageDriver(options) {
2447
2179
  const quotaBytes = options.quotaBytes ?? PROJECT_QUOTA_BYTES;
2448
- const bucketDir = (projectId) => join5(options.dir, projectId);
2449
- const objectPath = (projectId, path) => join5(bucketDir(projectId), path);
2450
- const metaPath = (projectId, path) => join5(dirname5(objectPath(projectId, path)), `${path.split("/").pop() ?? ""}${META_SUFFIX}`);
2180
+ const bucketDir = (projectId) => join3(options.dir, projectId);
2181
+ const objectPath = (projectId, path) => join3(bucketDir(projectId), path);
2182
+ const metaPath = (projectId, path) => join3(dirname4(objectPath(projectId, path)), `${path.split("/").pop() ?? ""}${META_SUFFIX}`);
2451
2183
  const readStoredMeta = async (projectId, path) => {
2452
2184
  const raw = await readFile2(metaPath(projectId, path), "utf8");
2453
2185
  return JSON.parse(raw);
@@ -2459,7 +2191,7 @@ function createLocalStorageDriver(options) {
2459
2191
  updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
2460
2192
  ...meta.contentType === void 0 ? {} : { contentType: meta.contentType }
2461
2193
  };
2462
- await writeFile3(metaPath(projectId, path), JSON.stringify(payload), "utf8");
2194
+ await writeFile2(metaPath(projectId, path), JSON.stringify(payload), "utf8");
2463
2195
  };
2464
2196
  const totalSize = async (projectId) => {
2465
2197
  const root = bucketDir(projectId);
@@ -2473,14 +2205,14 @@ function createLocalStorageDriver(options) {
2473
2205
  }
2474
2206
  const tasks = [];
2475
2207
  for (const entry of entries) {
2476
- const full = join5(dir, entry.name);
2208
+ const full = join3(dir, entry.name);
2477
2209
  if (entry.isDirectory()) {
2478
2210
  tasks.push(walk(full));
2479
2211
  } else if (entry.isFile() && !entry.name.endsWith(META_SUFFIX)) {
2480
2212
  tasks.push(
2481
2213
  (async () => {
2482
2214
  try {
2483
- const info = await stat4(full);
2215
+ const info = await stat3(full);
2484
2216
  total += info.size;
2485
2217
  } catch {
2486
2218
  }
@@ -2502,7 +2234,7 @@ function createLocalStorageDriver(options) {
2502
2234
  const used = await totalSize(projectId);
2503
2235
  let existingSize = 0;
2504
2236
  try {
2505
- existingSize = (await stat4(objectPath(projectId, path))).size;
2237
+ existingSize = (await stat3(objectPath(projectId, path))).size;
2506
2238
  } catch {
2507
2239
  existingSize = 0;
2508
2240
  }
@@ -2517,8 +2249,8 @@ function createLocalStorageDriver(options) {
2517
2249
  );
2518
2250
  }
2519
2251
  const dest = objectPath(projectId, path);
2520
- await mkdir4(dirname5(dest), { recursive: true });
2521
- await writeFile3(dest, data);
2252
+ await mkdir3(dirname4(dest), { recursive: true });
2253
+ await writeFile2(dest, data);
2522
2254
  await writeStoredMeta(projectId, path, {
2523
2255
  visibility: putOptions.visibility,
2524
2256
  size: data.byteLength,
@@ -2572,7 +2304,7 @@ function createLocalStorageDriver(options) {
2572
2304
  assertSafeStoragePath(path);
2573
2305
  let exists = true;
2574
2306
  try {
2575
- await stat4(objectPath(projectId, path));
2307
+ await stat3(objectPath(projectId, path));
2576
2308
  } catch {
2577
2309
  exists = false;
2578
2310
  }
@@ -2605,7 +2337,7 @@ function createLocalStorageDriver(options) {
2605
2337
  const tasks = [];
2606
2338
  for (const entry of entries) {
2607
2339
  if (entry.name.endsWith(META_SUFFIX)) continue;
2608
- const full = join5(dir, entry.name);
2340
+ const full = join3(dir, entry.name);
2609
2341
  const rel = relative3 === "" ? entry.name : `${relative3}/${entry.name}`;
2610
2342
  if (entry.isFile()) {
2611
2343
  if (prefix !== void 0 && !rel.startsWith(prefix)) continue;
@@ -2655,9 +2387,9 @@ var init_local = __esm({
2655
2387
  });
2656
2388
 
2657
2389
  // packages/cli/src/sim/storage.ts
2658
- import { join as join6 } from "node:path";
2390
+ import { join as join4 } from "node:path";
2659
2391
  function createSimStorageCapability(options) {
2660
- const dir = join6(options.cwd, ".adep", "sim", "storage");
2392
+ const dir = join4(options.cwd, ".adep", "sim", "storage");
2661
2393
  const driver = createLocalStorageDriver({ dir });
2662
2394
  const signer = {
2663
2395
  secret: options.secret ?? "adep-sim-secret",
@@ -2804,10 +2536,10 @@ var init_realtime = __esm({
2804
2536
  });
2805
2537
 
2806
2538
  // packages/cli/src/sim/runtime.ts
2807
- import { mkdir as mkdir5, readFile as readFile3, writeFile as writeFile4 } from "node:fs/promises";
2808
- import { dirname as dirname6, join as join7 } from "node:path";
2539
+ import { mkdir as mkdir4, readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
2540
+ import { dirname as dirname5, join as join5 } from "node:path";
2809
2541
  function simDir(cwd) {
2810
- return join7(cwd, ".adep", "sim");
2542
+ return join5(cwd, ".adep", "sim");
2811
2543
  }
2812
2544
  function mergeBundles(bundles) {
2813
2545
  const capabilities = [];
@@ -2829,7 +2561,7 @@ function mergeBundles(bundles) {
2829
2561
  return { capabilities, rpcHandlers };
2830
2562
  }
2831
2563
  function jsonStorage(cwd) {
2832
- const file = join7(simDir(cwd), "db.json");
2564
+ const file = join5(simDir(cwd), "db.json");
2833
2565
  return {
2834
2566
  async load() {
2835
2567
  try {
@@ -2840,8 +2572,8 @@ function jsonStorage(cwd) {
2840
2572
  }
2841
2573
  },
2842
2574
  async save(tables) {
2843
- await mkdir5(dirname6(file), { recursive: true });
2844
- await writeFile4(file, JSON.stringify(tables), "utf8");
2575
+ await mkdir4(dirname5(file), { recursive: true });
2576
+ await writeFile3(file, JSON.stringify(tables), "utf8");
2845
2577
  }
2846
2578
  };
2847
2579
  }
@@ -2878,7 +2610,7 @@ var init_runtime = __esm({
2878
2610
 
2879
2611
  // packages/cli/src/sim/env.ts
2880
2612
  import { readFile as readFile4 } from "node:fs/promises";
2881
- import { join as join8 } from "node:path";
2613
+ import { join as join6 } from "node:path";
2882
2614
  function parseEnv(content) {
2883
2615
  const env = {};
2884
2616
  for (const raw of content.split(/\r?\n/)) {
@@ -2893,8 +2625,8 @@ function parseEnv(content) {
2893
2625
  return env;
2894
2626
  }
2895
2627
  async function loadSimEnv(cwd, config = {}) {
2896
- const envRoot = await readFile4(join8(cwd, ".env"), "utf8").catch(() => "");
2897
- const envLocal = await readFile4(join8(cwd, ".env.local"), "utf8").catch(() => "");
2628
+ const envRoot = await readFile4(join6(cwd, ".env"), "utf8").catch(() => "");
2629
+ const envLocal = await readFile4(join6(cwd, ".env.local"), "utf8").catch(() => "");
2898
2630
  const merged = { ...parseEnv(envRoot), ...parseEnv(envLocal) };
2899
2631
  for (const secret of config.secrets ?? []) {
2900
2632
  if (merged[secret] !== void 0) continue;
@@ -2926,9 +2658,9 @@ function listFunctionNames(files) {
2926
2658
  const names = /* @__PURE__ */ new Set();
2927
2659
  for (const key of Object.keys(files)) {
2928
2660
  const parts = key.split("/");
2929
- if (parts.length === 1 && parts[0]?.endsWith(".ts")) {
2661
+ if (parts.length === 1 && parts[0] !== void 0 && parts[0].endsWith(".ts")) {
2930
2662
  names.add(parts[0].slice(0, -3));
2931
- } else if (parts.length === 2 && parts[1] === "index.ts") {
2663
+ } else if (parts.length === 2 && parts[1] === "index.ts" && parts[0] !== void 0) {
2932
2664
  names.add(parts[0]);
2933
2665
  }
2934
2666
  }
@@ -3016,13 +2748,13 @@ __export(dev_exports, {
3016
2748
  });
3017
2749
  import { createServer } from "node:http";
3018
2750
  import { watch } from "node:fs";
3019
- import { mkdir as mkdir6, readdir as readdir2, readFile as readFile5, stat as stat5, writeFile as writeFile5 } from "node:fs/promises";
3020
- import { basename, join as join9, resolve as resolve5 } from "node:path";
2751
+ import { mkdir as mkdir5, readdir as readdir2, readFile as readFile5, stat as stat4, writeFile as writeFile4 } from "node:fs/promises";
2752
+ import { basename, join as join7, resolve as resolve3 } from "node:path";
3021
2753
  async function loadConfig(cwd) {
3022
- const name = basename(resolve5(cwd));
3023
- const configPath = join9(cwd, "adep.config.ts");
2754
+ const name = basename(resolve3(cwd));
2755
+ const configPath = join7(cwd, "adep.config.ts");
3024
2756
  try {
3025
- await stat5(configPath);
2757
+ await stat4(configPath);
3026
2758
  } catch {
3027
2759
  return { name, functionsDir: "functions" };
3028
2760
  }
@@ -3062,7 +2794,7 @@ async function collectFunctions(dir) {
3062
2794
  }
3063
2795
  for (const entry of entries) {
3064
2796
  const rel = prefix.length === 0 ? entry.name : `${prefix}/${entry.name}`;
3065
- const full = join9(sub, entry.name);
2797
+ const full = join7(sub, entry.name);
3066
2798
  if (entry.isDirectory()) {
3067
2799
  await walk(full, rel);
3068
2800
  } else if (entry.isFile() && entry.name.endsWith(".ts")) {
@@ -3103,22 +2835,22 @@ function printBoundaries(log) {
3103
2835
  }
3104
2836
  }
3105
2837
  async function ensureGitignore(cwd) {
3106
- const gitignorePath = join9(cwd, ".gitignore");
2838
+ const gitignorePath = join7(cwd, ".gitignore");
3107
2839
  const existing = await readFile5(gitignorePath, "utf8").catch(() => "");
3108
2840
  if (existing.split(/\r?\n/).includes(".adep/")) return;
3109
- await writeFile5(gitignorePath, `${existing.replace(/\n+$/, "")}
2841
+ await writeFile4(gitignorePath, `${existing.replace(/\n+$/, "")}
3110
2842
  .adep/
3111
2843
  `, "utf8");
3112
2844
  }
3113
2845
  async function startDevServer(options) {
3114
- const cwd = resolve5(options.cwd);
2846
+ const cwd = resolve3(options.cwd);
3115
2847
  const log = options.log ?? ((line) => process.stdout.write(`${line}
3116
2848
  `));
3117
2849
  const config = await loadConfig(cwd);
3118
- const functionsDir = join9(cwd, config.functionsDir);
2850
+ const functionsDir = join7(cwd, config.functionsDir);
3119
2851
  const coldStartAt = Date.now();
3120
2852
  const executor = new WorkerFunctionExecutor();
3121
- await mkdir6(functionsDir, { recursive: true });
2853
+ await mkdir5(functionsDir, { recursive: true });
3122
2854
  const runtime = await createSimRuntime({
3123
2855
  cwd,
3124
2856
  projectId: "local",
@@ -3133,12 +2865,12 @@ async function startDevServer(options) {
3133
2865
  const reload = async () => {
3134
2866
  const [nextFiles, envText2] = await Promise.all([
3135
2867
  collectFunctions(functionsDir),
3136
- readFile5(join9(cwd, ".env.local"), "utf8").catch(() => "")
2868
+ readFile5(join7(cwd, ".env.local"), "utf8").catch(() => "")
3137
2869
  ]);
3138
2870
  files = nextFiles;
3139
2871
  env = parseEnvFile(envText2);
3140
2872
  };
3141
- const envText = await readFile5(join9(cwd, ".env.local"), "utf8").catch(() => "");
2873
+ const envText = await readFile5(join7(cwd, ".env.local"), "utf8").catch(() => "");
3142
2874
  env = parseEnvFile(envText);
3143
2875
  let debounceTimer;
3144
2876
  let watcher;
@@ -3270,321 +3002,68 @@ var init_dev = __esm({
3270
3002
  }
3271
3003
  });
3272
3004
 
3273
- // packages/cli/src/client.ts
3274
- var client_exports = {};
3275
- __export(client_exports, {
3276
- createClient: () => createClient,
3277
- resolveSlug: () => resolveSlug
3278
- });
3279
- async function envelopeError(response, fallbackCode, parsed) {
3280
- const payload = parsed ?? null;
3281
- return new CliError(
3282
- payload?.error?.code ?? fallbackCode,
3283
- payload?.error?.message ?? `\u5E73\u53F0\u8FD4\u56DE HTTP ${response.status}`
3284
- );
3005
+ // packages/cli/src/serve/banner.ts
3006
+ function isLoopback(host) {
3007
+ return host === "127.0.0.1" || host === "localhost" || host === "::1" || host === "[::1]";
3285
3008
  }
3286
- async function parseBody(response) {
3287
- const text = await response.text();
3288
- if (text.length === 0) return null;
3289
- try {
3290
- return JSON.parse(text);
3291
- } catch {
3292
- return null;
3009
+ function renderBanner(options) {
3010
+ const { host, port, projectName, functions, hasStatic, staticDir = "public/" } = options;
3011
+ const baseUrl = `http://${host}:${port}`;
3012
+ const loopback = isLoopback(host);
3013
+ const lines = [];
3014
+ lines.push("");
3015
+ 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");
3016
+ lines.push("\u2551 adep serve \u2014 \u5F00\u53D1\u6001\u670D\u52A1\u5668 \u2551");
3017
+ lines.push("\u2551 \u26A0 \u8FD9\u4E0D\u662F\u751F\u4EA7\u670D\u52A1\u5668\uFF0C\u4E0D\u63D0\u4F9B TLS / \u96C6\u7FA4 / \u4F18\u96C5\u91CD\u542F \u2551");
3018
+ 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");
3019
+ lines.push("");
3020
+ lines.push(` \u9879\u76EE: ${projectName}`);
3021
+ lines.push(` \u5730\u5740: ${baseUrl}`);
3022
+ lines.push(` \u7ED1\u5B9A: ${host}${loopback ? "\uFF08\u4EC5\u672C\u673A\u53EF\u8BBF\u95EE\uFF09" : "\uFF08\u26A0 \u5BF9\u5916\u66B4\u9732\uFF09"}`);
3023
+ lines.push("");
3024
+ lines.push(" \u80FD\u529B:");
3025
+ if (functions.length > 0) {
3026
+ lines.push(
3027
+ ` - \u51FD\u6570\u8DEF\u7531: ${baseUrl}/api/{fn}\uFF08${functions.length} \u4E2A\u51FD\u6570: ${functions.join(", ")}\uFF09`
3028
+ );
3029
+ } else {
3030
+ lines.push(" - \u51FD\u6570\u8DEF\u7531: \u65E0\uFF08functions/ \u76EE\u5F55\u4E3A\u7A7A\uFF09");
3031
+ }
3032
+ if (hasStatic) {
3033
+ lines.push(` - \u9759\u6001\u6258\u7BA1: ${baseUrl}/ \u2192 ${staticDir}`);
3034
+ } else {
3035
+ lines.push(` - \u9759\u6001\u6258\u7BA1: \u65E0\uFF08${staticDir} \u76EE\u5F55\u4E0D\u5B58\u5728\uFF09`);
3036
+ }
3037
+ lines.push(" - \u7EC4\u4EF6\u9884\u89C8: Widget / Page \u4EA7\u7269\uFF08\u5982\u5DF2\u6784\u5EFA\uFF09");
3038
+ lines.push(` - \u5065\u5EB7\u68C0\u67E5: ${baseUrl}/healthz`);
3039
+ lines.push("");
3040
+ lines.push(" \u8FB9\u754C\uFF08\u5F00\u53D1\u6001\u9ED8\u8BA4\u503C\uFF0C\u4E0D\u53EF\u5728\u6B64\u6A21\u5F0F\u4E0B\u5F00\u542F\uFF09:");
3041
+ lines.push(" - \u65E0\u9274\u6743\uFF1A\u4EFB\u4F55\u4EBA\u53EF\u8C03\u7528\u6240\u6709\u51FD\u6570");
3042
+ lines.push(" - \u65E0\u9650\u6D41\uFF1A\u65E0 QPS / \u5E76\u53D1\u9650\u5236");
3043
+ lines.push(" - \u65E0\u914D\u989D\uFF1A\u65E0\u8C03\u7528\u6B21\u6570 / \u8D44\u6E90\u7528\u91CF\u9650\u5236");
3044
+ lines.push(" - \u65E0 TLS\uFF1A\u660E\u6587 HTTP\uFF0C\u4E0D\u652F\u6301 HTTPS");
3045
+ lines.push(" - \u65E0\u96C6\u7FA4\uFF1A\u5355\u8FDB\u7A0B\uFF0C\u4E0D\u652F\u6301\u591A\u5B9E\u4F8B");
3046
+ lines.push(" - \u65E0\u4F18\u96C5\u91CD\u542F\uFF1A\u8FDB\u7A0B\u9000\u51FA\u5373\u4E2D\u65AD");
3047
+ lines.push("");
3048
+ if (!loopback) {
3049
+ 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");
3050
+ lines.push(" \u2502 \u26A0\u26A0\u26A0 \u5BF9\u5916\u66B4\u9732\u8B66\u544A \u2502");
3051
+ lines.push(" \u2502 \u2502");
3052
+ lines.push(` \u2502 \u5F53\u524D\u7ED1\u5B9A ${host.padEnd(43)}\u2502`);
3053
+ 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");
3054
+ 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");
3055
+ lines.push(" \u2502 \u2502");
3056
+ lines.push(" \u2502 \u9700\u8981\u751F\u4EA7\u90E8\u7F72\uFF1F\u4F7F\u7528 `adep deploy` \u90E8\u7F72\u5230\u5E73\u53F0\u3002 \u2502");
3057
+ 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");
3058
+ lines.push("");
3293
3059
  }
3060
+ lines.push(" \u6309 Ctrl+C \u505C\u6B62\u670D\u52A1\u5668\u3002");
3061
+ lines.push("");
3062
+ return lines.join("\n");
3294
3063
  }
3295
- async function createClient(paths) {
3296
- const credentials = await loadCredentials(paths);
3297
- if (credentials === null) {
3298
- throw new CliError("NOT_LOGGED_IN", "\u672A\u767B\u5F55\uFF1A\u8BF7\u5148\u6267\u884C adep login");
3299
- }
3300
- const server = credentials.server;
3301
- const cookie = `better-auth.session_token=${decodeToken(credentials.encodedToken)}`;
3302
- const request = async (path, init = {}, fallbackCode = "API_REQUEST_FAILED") => {
3303
- const method = init.method ?? (init.body === void 0 ? "GET" : "POST");
3304
- let response;
3305
- try {
3306
- response = await fetch(`${server}${path}`, {
3307
- method,
3308
- headers: { "content-type": "application/json", cookie },
3309
- ...init.body === void 0 ? {} : { body: JSON.stringify(init.body) }
3310
- });
3311
- } catch (error) {
3312
- throw new CliError(
3313
- "SERVER_UNREACHABLE",
3314
- `\u65E0\u6CD5\u8FDE\u63A5\u5E73\u53F0 ${server}\uFF1A${error instanceof Error ? error.message : String(error)}`
3315
- );
3316
- }
3317
- const parsed = await parseBody(response);
3318
- if (response.status < 200 || response.status >= 300) {
3319
- throw await envelopeError(response, fallbackCode, parsed);
3320
- }
3321
- return parsed;
3322
- };
3323
- const upload = async (path, form, fallbackCode = "UPLOAD_FAILED") => {
3324
- let response;
3325
- try {
3326
- response = await fetch(`${server}${path}`, {
3327
- method: "POST",
3328
- headers: { cookie },
3329
- body: form
3330
- });
3331
- } catch (error) {
3332
- throw new CliError(
3333
- "SERVER_UNREACHABLE",
3334
- `\u65E0\u6CD5\u8FDE\u63A5\u5E73\u53F0 ${server}\uFF1A${error instanceof Error ? error.message : String(error)}`
3335
- );
3336
- }
3337
- if (response.status < 200 || response.status >= 300) {
3338
- throw await envelopeError(response, fallbackCode, await parseBody(response));
3339
- }
3340
- return response;
3341
- };
3342
- const download = async (url, fallbackCode = "DOWNLOAD_FAILED") => {
3343
- const target = url.startsWith("http") ? url : `${server}${url}`;
3344
- let response;
3345
- try {
3346
- response = await fetch(target, { headers: { cookie } });
3347
- } catch (error) {
3348
- throw new CliError(
3349
- "SERVER_UNREACHABLE",
3350
- `\u65E0\u6CD5\u8FDE\u63A5\u5E73\u53F0 ${server}\uFF1A${error instanceof Error ? error.message : String(error)}`
3351
- );
3352
- }
3353
- if (response.status < 200 || response.status >= 300) {
3354
- throw await envelopeError(response, fallbackCode, await parseBody(response));
3355
- }
3356
- return response;
3357
- };
3358
- return { server, cookie, request, upload, download };
3359
- }
3360
- async function resolveSlug(cwd, slug) {
3361
- if (slug !== void 0 && slug.length > 0) return slug;
3362
- const config = await loadConfig(cwd);
3363
- return config.name;
3364
- }
3365
- var init_client = __esm({
3366
- "packages/cli/src/client.ts"() {
3367
- "use strict";
3368
- init_auth();
3369
- init_credentials();
3370
- init_dev();
3371
- }
3372
- });
3373
-
3374
- // packages/cli/src/deploy.ts
3375
- var deploy_exports = {};
3376
- __export(deploy_exports, {
3377
- collectEntries: () => collectEntries,
3378
- deploy: () => deploy
3379
- });
3380
- import { createHash as createHash3 } from "node:crypto";
3381
- import { readdir as readdir3, readFile as readFile6 } from "node:fs/promises";
3382
- import { join as join10, resolve as resolve6, basename as basename2 } from "node:path";
3383
- async function collectEntries(functionsDir) {
3384
- const entries = {};
3385
- let names;
3386
- try {
3387
- const dirents = await readdir3(functionsDir, { withFileTypes: true });
3388
- names = dirents.filter((entry) => entry.isFile() && entry.name.endsWith(".ts")).map((entry) => basename2(entry.name, ".ts")).toSorted();
3389
- } catch {
3390
- return entries;
3391
- }
3392
- for (const name of names) {
3393
- entries[name] = await readFile6(join10(functionsDir, `${name}.ts`), "utf8");
3394
- }
3395
- return entries;
3396
- }
3397
- function sha256Hex(content) {
3398
- return createHash3("sha256").update(content).digest("hex");
3399
- }
3400
- async function deploy(paths, options) {
3401
- await requireNetwork("adep deploy");
3402
- const log = options.silent === true ? () => void 0 : options.log ?? ((line) => process.stdout.write(`${line}
3403
- `));
3404
- const client = await createClient(paths);
3405
- const cwd = resolve6(options.cwd);
3406
- const config = await loadConfig(cwd);
3407
- const slug = options.slug ?? config.name;
3408
- const functionsDir = options.functionsDir === void 0 ? join10(cwd, config.functionsDir) : resolve6(cwd, options.functionsDir);
3409
- const local = await collectEntries(functionsDir);
3410
- if (Object.keys(local).length === 0) {
3411
- throw new CliError("NO_FUNCTIONS", `${functionsDir} \u4E0B\u6CA1\u6709\u51FD\u6570\u6587\u4EF6`);
3412
- }
3413
- const remote = await client.request(
3414
- "/api/v1/deploy/diff",
3415
- {
3416
- body: {
3417
- slug,
3418
- functions: Object.entries(local).map(([name, content]) => ({
3419
- name,
3420
- files: { "index.ts": sha256Hex(content) }
3421
- }))
3422
- }
3423
- },
3424
- "DEPLOY_FAILED"
3425
- );
3426
- const baseUrl = `${remote.scheme}://${remote.slug}.${remote.domain}`;
3427
- const deployed = [];
3428
- for (const item of remote.functions) {
3429
- const content = local[item.name];
3430
- if (item.action === "none") {
3431
- deployed.push({
3432
- name: item.name,
3433
- action: "none",
3434
- version: item.version ?? 0,
3435
- url: `${baseUrl}/${item.name}`
3436
- });
3437
- continue;
3438
- }
3439
- log(`[adep] \u90E8\u7F72 ${item.name}\uFF08${item.action === "create" ? "\u65B0\u5EFA" : "\u53D8\u66F4"}\uFF09`);
3440
- let functionId = item.id;
3441
- if (functionId === null) {
3442
- const created = await client.request(
3443
- `/api/v1/projects/${remote.projectId}/functions`,
3444
- {
3445
- body: { name: item.name, files: { "index.ts": content } }
3446
- }
3447
- );
3448
- functionId = created.id;
3449
- } else {
3450
- await client.request(`/api/v1/projects/${remote.projectId}/functions/${item.name}`, {
3451
- method: "PATCH",
3452
- body: { files: { "index.ts": content } }
3453
- });
3454
- }
3455
- const published = await client.request(
3456
- `/api/v1/functions/${functionId}/publish`,
3457
- { method: "POST" }
3458
- );
3459
- deployed.push({
3460
- name: item.name,
3461
- action: item.action,
3462
- version: published.version,
3463
- url: `${baseUrl}/${item.name}`
3464
- });
3465
- }
3466
- return {
3467
- projectId: remote.projectId,
3468
- slug: remote.slug,
3469
- baseUrl,
3470
- noChanges: deployed.every((function_) => function_.action === "none"),
3471
- functions: deployed
3472
- };
3473
- }
3474
- var init_deploy = __esm({
3475
- "packages/cli/src/deploy.ts"() {
3476
- "use strict";
3477
- init_auth();
3478
- init_client();
3479
- init_dev();
3480
- init_net();
3481
- }
3482
- });
3483
-
3484
- // packages/cli/src/prompt.ts
3485
- var prompt_exports = {};
3486
- __export(prompt_exports, {
3487
- createPrompt: () => createPrompt
3488
- });
3489
- import { createInterface } from "node:readline/promises";
3490
- import { Writable } from "node:stream";
3491
- function createPrompt(input = process.stdin) {
3492
- const rl = createInterface({ input, output: process.stdout, terminal: true });
3493
- let muted = null;
3494
- return {
3495
- async ask(question) {
3496
- const answer = await rl.question(question);
3497
- return answer.trim();
3498
- },
3499
- async askHidden(question) {
3500
- muted = createInterface({ input, output: new MutedStream(), terminal: true });
3501
- const answer = await muted.question(question);
3502
- muted.close();
3503
- muted = null;
3504
- process.stdout.write("\n");
3505
- return answer.trim();
3506
- },
3507
- close() {
3508
- muted?.close();
3509
- rl.close();
3510
- }
3511
- };
3512
- }
3513
- var MutedStream;
3514
- var init_prompt = __esm({
3515
- "packages/cli/src/prompt.ts"() {
3516
- "use strict";
3517
- MutedStream = class extends Writable {
3518
- write(_chunk, ...rest) {
3519
- void rest;
3520
- return true;
3521
- }
3522
- };
3523
- }
3524
- });
3525
-
3526
- // packages/cli/src/serve/banner.ts
3527
- function isLoopback(host) {
3528
- return host === "127.0.0.1" || host === "localhost" || host === "::1" || host === "[::1]";
3529
- }
3530
- function renderBanner(options) {
3531
- const { host, port, projectName, functions, hasStatic, staticDir = "public/" } = options;
3532
- const baseUrl = `http://${host}:${port}`;
3533
- const loopback = isLoopback(host);
3534
- const lines = [];
3535
- lines.push("");
3536
- 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");
3537
- lines.push("\u2551 adep serve \u2014 \u5F00\u53D1\u6001\u670D\u52A1\u5668 \u2551");
3538
- lines.push("\u2551 \u26A0 \u8FD9\u4E0D\u662F\u751F\u4EA7\u670D\u52A1\u5668\uFF0C\u4E0D\u63D0\u4F9B TLS / \u96C6\u7FA4 / \u4F18\u96C5\u91CD\u542F \u2551");
3539
- 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");
3540
- lines.push("");
3541
- lines.push(` \u9879\u76EE: ${projectName}`);
3542
- lines.push(` \u5730\u5740: ${baseUrl}`);
3543
- lines.push(` \u7ED1\u5B9A: ${host}${loopback ? "\uFF08\u4EC5\u672C\u673A\u53EF\u8BBF\u95EE\uFF09" : "\uFF08\u26A0 \u5BF9\u5916\u66B4\u9732\uFF09"}`);
3544
- lines.push("");
3545
- lines.push(" \u80FD\u529B:");
3546
- if (functions.length > 0) {
3547
- lines.push(
3548
- ` - \u51FD\u6570\u8DEF\u7531: ${baseUrl}/api/{fn}\uFF08${functions.length} \u4E2A\u51FD\u6570: ${functions.join(", ")}\uFF09`
3549
- );
3550
- } else {
3551
- lines.push(" - \u51FD\u6570\u8DEF\u7531: \u65E0\uFF08functions/ \u76EE\u5F55\u4E3A\u7A7A\uFF09");
3552
- }
3553
- if (hasStatic) {
3554
- lines.push(` - \u9759\u6001\u6258\u7BA1: ${baseUrl}/ \u2192 ${staticDir}`);
3555
- } else {
3556
- lines.push(` - \u9759\u6001\u6258\u7BA1: \u65E0\uFF08${staticDir} \u76EE\u5F55\u4E0D\u5B58\u5728\uFF09`);
3557
- }
3558
- lines.push(" - \u7EC4\u4EF6\u9884\u89C8: Widget / Page \u4EA7\u7269\uFF08\u5982\u5DF2\u6784\u5EFA\uFF09");
3559
- lines.push(` - \u5065\u5EB7\u68C0\u67E5: ${baseUrl}/healthz`);
3560
- lines.push("");
3561
- lines.push(" \u8FB9\u754C\uFF08\u5F00\u53D1\u6001\u9ED8\u8BA4\u503C\uFF0C\u4E0D\u53EF\u5728\u6B64\u6A21\u5F0F\u4E0B\u5F00\u542F\uFF09:");
3562
- lines.push(" - \u65E0\u9274\u6743\uFF1A\u4EFB\u4F55\u4EBA\u53EF\u8C03\u7528\u6240\u6709\u51FD\u6570");
3563
- lines.push(" - \u65E0\u9650\u6D41\uFF1A\u65E0 QPS / \u5E76\u53D1\u9650\u5236");
3564
- lines.push(" - \u65E0\u914D\u989D\uFF1A\u65E0\u8C03\u7528\u6B21\u6570 / \u8D44\u6E90\u7528\u91CF\u9650\u5236");
3565
- lines.push(" - \u65E0 TLS\uFF1A\u660E\u6587 HTTP\uFF0C\u4E0D\u652F\u6301 HTTPS");
3566
- lines.push(" - \u65E0\u96C6\u7FA4\uFF1A\u5355\u8FDB\u7A0B\uFF0C\u4E0D\u652F\u6301\u591A\u5B9E\u4F8B");
3567
- lines.push(" - \u65E0\u4F18\u96C5\u91CD\u542F\uFF1A\u8FDB\u7A0B\u9000\u51FA\u5373\u4E2D\u65AD");
3568
- lines.push("");
3569
- if (!loopback) {
3570
- 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");
3571
- lines.push(" \u2502 \u26A0\u26A0\u26A0 \u5BF9\u5916\u66B4\u9732\u8B66\u544A \u2502");
3572
- lines.push(" \u2502 \u2502");
3573
- lines.push(` \u2502 \u5F53\u524D\u7ED1\u5B9A ${host.padEnd(43)}\u2502`);
3574
- 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");
3575
- 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");
3576
- lines.push(" \u2502 \u2502");
3577
- lines.push(" \u2502 \u9700\u8981\u751F\u4EA7\u90E8\u7F72\uFF1F\u4F7F\u7528 `adep deploy` \u90E8\u7F72\u5230\u5E73\u53F0\u3002 \u2502");
3578
- 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");
3579
- lines.push("");
3580
- }
3581
- lines.push(" \u6309 Ctrl+C \u505C\u6B62\u670D\u52A1\u5668\u3002");
3582
- lines.push("");
3583
- return lines.join("\n");
3584
- }
3585
- var init_banner = __esm({
3586
- "packages/cli/src/serve/banner.ts"() {
3587
- "use strict";
3064
+ var init_banner = __esm({
3065
+ "packages/cli/src/serve/banner.ts"() {
3066
+ "use strict";
3588
3067
  }
3589
3068
  });
3590
3069
 
@@ -3595,8 +3074,9 @@ __export(server_exports, {
3595
3074
  startServeServer: () => startServeServer
3596
3075
  });
3597
3076
  import { createServer as createServer2 } from "node:http";
3598
- import { readdir as readdir4, readFile as readFile7, stat as stat6 } from "node:fs/promises";
3599
- import { join as join11, relative, resolve as resolve7 } from "node:path";
3077
+ import { watch as watch2 } from "node:fs";
3078
+ import { mkdir as mkdir6, readdir as readdir3, readFile as readFile6, stat as stat5 } from "node:fs/promises";
3079
+ import { join as join8, relative, resolve as resolve4 } from "node:path";
3600
3080
  function envNumber(name) {
3601
3081
  const raw = process.env[name];
3602
3082
  if (raw === void 0 || raw.trim() === "") return void 0;
@@ -3612,17 +3092,17 @@ async function collectFunctions2(dir) {
3612
3092
  const walk = async (sub, prefix) => {
3613
3093
  let entries;
3614
3094
  try {
3615
- entries = await readdir4(sub, { withFileTypes: true });
3095
+ entries = await readdir3(sub, { withFileTypes: true });
3616
3096
  } catch {
3617
3097
  return;
3618
3098
  }
3619
3099
  for (const entry of entries) {
3620
3100
  const rel = prefix.length === 0 ? entry.name : `${prefix}/${entry.name}`;
3621
- const full = join11(sub, entry.name);
3101
+ const full = join8(sub, entry.name);
3622
3102
  if (entry.isDirectory()) {
3623
3103
  await walk(full, rel);
3624
3104
  } else if (entry.isFile() && entry.name.endsWith(".ts")) {
3625
- files[rel] = await readFile7(full, "utf8");
3105
+ files[rel] = await readFile6(full, "utf8");
3626
3106
  }
3627
3107
  }
3628
3108
  };
@@ -3657,29 +3137,29 @@ function contentTypeFor(path) {
3657
3137
  return MIME_TYPES[ext] ?? "application/octet-stream";
3658
3138
  }
3659
3139
  async function startServeServer(options) {
3660
- const cwd = resolve7(options.cwd);
3140
+ const cwd = resolve4(options.cwd);
3661
3141
  const log = options.log ?? ((line) => process.stdout.write(`${line}
3662
3142
  `));
3663
3143
  const host = options.host ?? envString("HOST") ?? "127.0.0.1";
3664
3144
  const port = options.port ?? envNumber("PORT") ?? 8787;
3665
- const staticDir = resolve7(
3145
+ const staticDir = resolve4(
3666
3146
  cwd,
3667
3147
  options.staticDir ?? envString("ADEP_SERVE_STATIC_DIR") ?? "public"
3668
3148
  );
3669
3149
  const config = await loadConfig(cwd);
3670
- const functionsDir = join11(cwd, config.functionsDir);
3150
+ const functionsDir = join8(cwd, config.functionsDir);
3671
3151
  let hasStatic = false;
3672
3152
  try {
3673
- const publicStat = await stat6(staticDir);
3153
+ const publicStat = await stat5(staticDir);
3674
3154
  hasStatic = publicStat.isDirectory();
3675
3155
  } catch {
3676
3156
  hasStatic = false;
3677
3157
  }
3678
- const files = await collectFunctions2(functionsDir);
3679
- const functionNames = listFunctionNames(files);
3680
- const envText = await readFile7(join11(cwd, ".env.local"), "utf8").catch(() => "");
3681
- const env = parseEnvFile(envText);
3682
- const simEnv = await loadSimEnv(cwd).catch(() => ({}));
3158
+ let files = await collectFunctions2(functionsDir);
3159
+ let functionNames = listFunctionNames(files);
3160
+ const envText = await readFile6(join8(cwd, ".env.local"), "utf8").catch(() => "");
3161
+ let env = parseEnvFile(envText);
3162
+ let simEnv = await loadSimEnv(cwd).catch(() => ({}));
3683
3163
  const runtime = await createSimRuntime({
3684
3164
  cwd,
3685
3165
  projectId: "local",
@@ -3688,7 +3168,44 @@ async function startServeServer(options) {
3688
3168
  });
3689
3169
  const executor = new WorkerFunctionExecutor();
3690
3170
  const dbBundle = runtime.bundle;
3691
- const invokeHandler = createSimInvokeHandler({ executor, files });
3171
+ let invokeHandler = createSimInvokeHandler({ executor, files });
3172
+ let stopWatch;
3173
+ if (options.watch === true) {
3174
+ const reload = async () => {
3175
+ const [nextFiles, envLocalText] = await Promise.all([
3176
+ collectFunctions2(functionsDir),
3177
+ readFile6(join8(cwd, ".env.local"), "utf8").catch(() => "")
3178
+ ]);
3179
+ files = nextFiles;
3180
+ env = parseEnvFile(envLocalText);
3181
+ simEnv = await loadSimEnv(cwd).catch(() => ({}));
3182
+ invokeHandler = createSimInvokeHandler({ executor, files });
3183
+ functionNames = listFunctionNames(files);
3184
+ log(`[serve] \u70ED\u91CD\u8F7D\uFF1A\u68C0\u6D4B\u5230\u53D8\u66F4\uFF0C\u5DF2\u91CD\u65B0\u52A0\u8F7D ${functionNames.length} \u4E2A\u51FD\u6570`);
3185
+ };
3186
+ let debounceTimer;
3187
+ const watchers = [];
3188
+ const scheduleReload = () => {
3189
+ if (debounceTimer !== void 0) clearTimeout(debounceTimer);
3190
+ debounceTimer = setTimeout(() => {
3191
+ void reload();
3192
+ }, 120);
3193
+ };
3194
+ await mkdir6(functionsDir, { recursive: true }).catch(() => void 0);
3195
+ try {
3196
+ watchers.push(watch2(functionsDir, { recursive: true }, scheduleReload));
3197
+ } catch {
3198
+ log("[serve] \u8B66\u544A\uFF1Afunctions/ \u9012\u5F52\u76D1\u542C\u4E0D\u53EF\u7528\uFF0C\u70ED\u91CD\u8F7D\u5173\u95ED\uFF08\u670D\u52A1\u6B63\u5E38\u8FD0\u884C\uFF09");
3199
+ }
3200
+ try {
3201
+ watchers.push(watch2(cwd, scheduleReload));
3202
+ } catch {
3203
+ }
3204
+ stopWatch = () => {
3205
+ if (debounceTimer !== void 0) clearTimeout(debounceTimer);
3206
+ for (const watcher of watchers) watcher.close();
3207
+ };
3208
+ }
3692
3209
  const buildInput = async (fnName, entry, url, req) => {
3693
3210
  const query = {};
3694
3211
  for (const key of new Set(url.searchParams.keys())) {
@@ -3726,16 +3243,16 @@ async function startServeServer(options) {
3726
3243
  const serveStatic = async (pathname, res) => {
3727
3244
  if (!hasStatic) return false;
3728
3245
  const safePath = pathname.replace(/\.\.\//g, "").replace(/^\//, "");
3729
- const filePath = join11(staticDir, safePath);
3730
- const resolvedPath = safePath === "" || safePath === "/" ? join11(filePath, "index.html") : filePath;
3246
+ const filePath = join8(staticDir, safePath);
3247
+ const resolvedPath = safePath === "" || safePath === "/" ? join8(filePath, "index.html") : filePath;
3731
3248
  try {
3732
- const fileStat = await stat6(resolvedPath);
3249
+ const fileStat = await stat5(resolvedPath);
3733
3250
  if (fileStat.isDirectory()) {
3734
- const indexPath = join11(resolvedPath, "index.html");
3251
+ const indexPath = join8(resolvedPath, "index.html");
3735
3252
  try {
3736
- const indexStat = await stat6(indexPath);
3253
+ const indexStat = await stat5(indexPath);
3737
3254
  if (indexStat.isFile()) {
3738
- const content2 = await readFile7(indexPath);
3255
+ const content2 = await readFile6(indexPath);
3739
3256
  res.writeHead(200, { "content-type": contentTypeFor(indexPath) });
3740
3257
  res.end(content2);
3741
3258
  return true;
@@ -3744,7 +3261,7 @@ async function startServeServer(options) {
3744
3261
  }
3745
3262
  return false;
3746
3263
  }
3747
- const content = await readFile7(resolvedPath);
3264
+ const content = await readFile6(resolvedPath);
3748
3265
  res.writeHead(200, { "content-type": contentTypeFor(resolvedPath) });
3749
3266
  res.end(content);
3750
3267
  return true;
@@ -3775,6 +3292,9 @@ async function startServeServer(options) {
3775
3292
  const result = await executor.execute(input);
3776
3293
  const durationMs = Math.round(performance.now() - startedAt);
3777
3294
  log(`[serve] ${req.method ?? "GET"} ${pathname} -> 200 ${durationMs}ms`);
3295
+ if (options.watch === true) {
3296
+ for (const line of result.logs) log(`[serve] ${line}`);
3297
+ }
3778
3298
  writeJson2(res, 200, result.body === void 0 ? null : result.body);
3779
3299
  } catch (error) {
3780
3300
  const durationMs = Math.round(performance.now() - startedAt);
@@ -3801,123 +3321,322 @@ async function startServeServer(options) {
3801
3321
  service: "adep-serve",
3802
3322
  project: config.name
3803
3323
  });
3804
- return;
3324
+ return;
3325
+ }
3326
+ const served = await serveStatic(pathname, res);
3327
+ if (served) return;
3328
+ if (pathname === "/" || pathname === "") {
3329
+ writeJson2(res, 200, {
3330
+ service: "adep-serve",
3331
+ mode: "development",
3332
+ project: config.name,
3333
+ functions: functionNames,
3334
+ static: hasStatic,
3335
+ endpoints: {
3336
+ functions: "/api/{fn}",
3337
+ static: `/ \u2192 ${staticDir}`,
3338
+ healthz: "/healthz"
3339
+ },
3340
+ warning: "\u8FD9\u662F\u5F00\u53D1\u6001\u670D\u52A1\u5668\uFF0C\u4E0D\u662F\u751F\u4EA7\u670D\u52A1\u5668"
3341
+ });
3342
+ return;
3343
+ }
3344
+ writeJson2(res, 404, { error: { code: "NOT_FOUND", message: `\u8DEF\u5F84 "${pathname}" \u4E0D\u5B58\u5728` } });
3345
+ };
3346
+ const server = createServer2((req, res) => {
3347
+ void handle(req, res).catch((error) => {
3348
+ log(`[serve] \u672A\u5904\u7406\u9519\u8BEF: ${error instanceof Error ? error.message : String(error)}`);
3349
+ if (!res.headersSent) {
3350
+ writeJson2(res, 500, { error: { code: "INTERNAL_ERROR", message: "\u670D\u52A1\u5668\u5185\u90E8\u9519\u8BEF" } });
3351
+ }
3352
+ });
3353
+ });
3354
+ const actualPort = await new Promise((resolveListen, rejectListen) => {
3355
+ server.once("error", rejectListen);
3356
+ server.listen(port, host, () => {
3357
+ server.off("error", rejectListen);
3358
+ const addr = server.address();
3359
+ if (addr === null || typeof addr === "string") {
3360
+ resolveListen(port);
3361
+ } else {
3362
+ resolveListen(addr.port);
3363
+ }
3364
+ });
3365
+ });
3366
+ const banner = renderBanner({
3367
+ host,
3368
+ port: actualPort,
3369
+ projectName: config.name,
3370
+ functions: functionNames,
3371
+ hasStatic,
3372
+ staticDir: relative(cwd, staticDir).length > 0 ? relative(cwd, staticDir) : staticDir
3373
+ });
3374
+ log(banner);
3375
+ if (options.watch === true) {
3376
+ log(`[serve] \u70ED\u91CD\u8F7D\u5DF2\u5F00\u542F\uFF1A\u6539 functions/ \u4E0E .env* \u5373\u751F\u6548\uFF0C\u51FD\u6570 console \u8F93\u51FA\u76F4\u8FBE\u7EC8\u7AEF\uFF08--watch\uFF09`);
3377
+ }
3378
+ return {
3379
+ port: actualPort,
3380
+ host,
3381
+ baseUrl: `http://${host}:${actualPort}`,
3382
+ close: async () => {
3383
+ stopWatch?.();
3384
+ await new Promise((resolveClose) => {
3385
+ server.close(() => resolveClose());
3386
+ });
3387
+ }
3388
+ };
3389
+ }
3390
+ var MIME_TYPES;
3391
+ var init_server = __esm({
3392
+ "packages/cli/src/serve/server.ts"() {
3393
+ "use strict";
3394
+ init_executor();
3395
+ init_worker_executor();
3396
+ init_runtime();
3397
+ init_env();
3398
+ init_invoke();
3399
+ init_dev();
3400
+ init_banner();
3401
+ MIME_TYPES = {
3402
+ ".html": "text/html; charset=utf-8",
3403
+ ".htm": "text/html; charset=utf-8",
3404
+ ".css": "text/css; charset=utf-8",
3405
+ ".js": "application/javascript; charset=utf-8",
3406
+ ".mjs": "application/javascript; charset=utf-8",
3407
+ ".json": "application/json; charset=utf-8",
3408
+ ".png": "image/png",
3409
+ ".jpg": "image/jpeg",
3410
+ ".jpeg": "image/jpeg",
3411
+ ".gif": "image/gif",
3412
+ ".svg": "image/svg+xml",
3413
+ ".ico": "image/x-icon",
3414
+ ".woff": "font/woff",
3415
+ ".woff2": "font/woff2",
3416
+ ".ttf": "font/ttf",
3417
+ ".txt": "text/plain; charset=utf-8",
3418
+ ".md": "text/markdown; charset=utf-8",
3419
+ ".pdf": "application/pdf",
3420
+ ".map": "application/json"
3421
+ };
3422
+ }
3423
+ });
3424
+
3425
+ // packages/cli/src/client.ts
3426
+ var client_exports = {};
3427
+ __export(client_exports, {
3428
+ createClient: () => createClient,
3429
+ resolveSlug: () => resolveSlug
3430
+ });
3431
+ async function envelopeError(response, fallbackCode, parsed) {
3432
+ const payload = parsed ?? null;
3433
+ return new CliError(
3434
+ payload?.error?.code ?? fallbackCode,
3435
+ payload?.error?.message ?? `\u5E73\u53F0\u8FD4\u56DE HTTP ${response.status}`
3436
+ );
3437
+ }
3438
+ async function parseBody(response) {
3439
+ const text = await response.text();
3440
+ if (text.length === 0) return null;
3441
+ try {
3442
+ return JSON.parse(text);
3443
+ } catch {
3444
+ return null;
3445
+ }
3446
+ }
3447
+ async function createClient(paths) {
3448
+ const credentials = await loadCredentials(paths);
3449
+ if (credentials === null) {
3450
+ throw new CliError("NOT_LOGGED_IN", "\u672A\u767B\u5F55\uFF1A\u8BF7\u5148\u6267\u884C adep login");
3451
+ }
3452
+ const server = credentials.server;
3453
+ const cookie = `better-auth.session_token=${decodeToken(credentials.encodedToken)}`;
3454
+ const request = async (path, init = {}, fallbackCode = "API_REQUEST_FAILED") => {
3455
+ const method = init.method ?? (init.body === void 0 ? "GET" : "POST");
3456
+ let response;
3457
+ try {
3458
+ response = await fetch(`${server}${path}`, {
3459
+ method,
3460
+ headers: { "content-type": "application/json", cookie },
3461
+ ...init.body === void 0 ? {} : { body: JSON.stringify(init.body) }
3462
+ });
3463
+ } catch (error) {
3464
+ throw new CliError(
3465
+ "SERVER_UNREACHABLE",
3466
+ `\u65E0\u6CD5\u8FDE\u63A5\u5E73\u53F0 ${server}\uFF1A${error instanceof Error ? error.message : String(error)}`
3467
+ );
3468
+ }
3469
+ const parsed = await parseBody(response);
3470
+ if (response.status < 200 || response.status >= 300) {
3471
+ throw await envelopeError(response, fallbackCode, parsed);
3472
+ }
3473
+ return parsed;
3474
+ };
3475
+ const upload = async (path, form, fallbackCode = "UPLOAD_FAILED") => {
3476
+ let response;
3477
+ try {
3478
+ response = await fetch(`${server}${path}`, {
3479
+ method: "POST",
3480
+ headers: { cookie },
3481
+ body: form
3482
+ });
3483
+ } catch (error) {
3484
+ throw new CliError(
3485
+ "SERVER_UNREACHABLE",
3486
+ `\u65E0\u6CD5\u8FDE\u63A5\u5E73\u53F0 ${server}\uFF1A${error instanceof Error ? error.message : String(error)}`
3487
+ );
3488
+ }
3489
+ if (response.status < 200 || response.status >= 300) {
3490
+ throw await envelopeError(response, fallbackCode, await parseBody(response));
3491
+ }
3492
+ return response;
3493
+ };
3494
+ const download = async (url, fallbackCode = "DOWNLOAD_FAILED") => {
3495
+ const target = url.startsWith("http") ? url : `${server}${url}`;
3496
+ let response;
3497
+ try {
3498
+ response = await fetch(target, { headers: { cookie } });
3499
+ } catch (error) {
3500
+ throw new CliError(
3501
+ "SERVER_UNREACHABLE",
3502
+ `\u65E0\u6CD5\u8FDE\u63A5\u5E73\u53F0 ${server}\uFF1A${error instanceof Error ? error.message : String(error)}`
3503
+ );
3504
+ }
3505
+ if (response.status < 200 || response.status >= 300) {
3506
+ throw await envelopeError(response, fallbackCode, await parseBody(response));
3507
+ }
3508
+ return response;
3509
+ };
3510
+ return { server, cookie, request, upload, download };
3511
+ }
3512
+ async function resolveSlug(cwd, slug) {
3513
+ if (slug !== void 0 && slug.length > 0) return slug;
3514
+ const config = await loadConfig(cwd);
3515
+ return config.name;
3516
+ }
3517
+ var init_client = __esm({
3518
+ "packages/cli/src/client.ts"() {
3519
+ "use strict";
3520
+ init_auth();
3521
+ init_credentials();
3522
+ init_dev();
3523
+ }
3524
+ });
3525
+
3526
+ // packages/cli/src/deploy.ts
3527
+ var deploy_exports = {};
3528
+ __export(deploy_exports, {
3529
+ collectEntries: () => collectEntries,
3530
+ deploy: () => deploy
3531
+ });
3532
+ import { createHash as createHash2 } from "node:crypto";
3533
+ import { readdir as readdir4, readFile as readFile7 } from "node:fs/promises";
3534
+ import { join as join9, resolve as resolve5, basename as basename2 } from "node:path";
3535
+ function functionUrlBase(prefix) {
3536
+ const raw = (prefix ?? "/api").trim();
3537
+ const normalized = raw === "/" ? "/" : raw.replace(/\/+$/, "");
3538
+ return normalized === "/" ? "" : normalized;
3539
+ }
3540
+ async function collectEntries(functionsDir) {
3541
+ const entries = {};
3542
+ let names;
3543
+ try {
3544
+ const dirents = await readdir4(functionsDir, { withFileTypes: true });
3545
+ names = dirents.filter((entry) => entry.isFile() && entry.name.endsWith(".ts")).map((entry) => basename2(entry.name, ".ts")).toSorted();
3546
+ } catch {
3547
+ return entries;
3548
+ }
3549
+ for (const name of names) {
3550
+ entries[name] = await readFile7(join9(functionsDir, `${name}.ts`), "utf8");
3551
+ }
3552
+ return entries;
3553
+ }
3554
+ function sha256Hex(content) {
3555
+ return createHash2("sha256").update(content).digest("hex");
3556
+ }
3557
+ async function deploy(paths, options) {
3558
+ await requireNetwork("adep deploy");
3559
+ const log = options.silent === true ? () => void 0 : options.log ?? ((line) => process.stdout.write(`${line}
3560
+ `));
3561
+ const client = await createClient(paths);
3562
+ const cwd = resolve5(options.cwd);
3563
+ const config = await loadConfig(cwd);
3564
+ const slug = options.slug ?? config.name;
3565
+ const functionsDir = options.functionsDir === void 0 ? join9(cwd, config.functionsDir) : resolve5(cwd, options.functionsDir);
3566
+ const local = await collectEntries(functionsDir);
3567
+ if (Object.keys(local).length === 0) {
3568
+ throw new CliError("NO_FUNCTIONS", `${functionsDir} \u4E0B\u6CA1\u6709\u51FD\u6570\u6587\u4EF6`);
3569
+ }
3570
+ const remote = await client.request(
3571
+ "/api/v1/deploy/diff",
3572
+ {
3573
+ body: {
3574
+ slug,
3575
+ functions: Object.entries(local).map(([name, content]) => ({
3576
+ name,
3577
+ files: { "index.ts": sha256Hex(content) }
3578
+ }))
3579
+ }
3580
+ },
3581
+ "DEPLOY_FAILED"
3582
+ );
3583
+ const baseUrl = `${remote.scheme}://${remote.slug}.${remote.domain}`;
3584
+ const prefixBase = functionUrlBase(remote.functionsPrefix);
3585
+ const functionUrl = (name) => `${baseUrl}${prefixBase}/${name}`;
3586
+ const deployed = [];
3587
+ for (const item of remote.functions) {
3588
+ const content = local[item.name];
3589
+ if (item.action === "none") {
3590
+ deployed.push({
3591
+ name: item.name,
3592
+ action: "none",
3593
+ version: item.version ?? 0,
3594
+ url: functionUrl(item.name)
3595
+ });
3596
+ continue;
3805
3597
  }
3806
- const served = await serveStatic(pathname, res);
3807
- if (served) return;
3808
- if (pathname.startsWith("/_preview/")) {
3809
- const widgetName = pathname.slice("/_preview/".length).split("/")[0];
3810
- if (widgetName !== void 0 && widgetName.length > 0) {
3811
- const widgetDir = join11(cwd, ".adep", "widgets", widgetName);
3812
- try {
3813
- const widgetStat = await stat6(widgetDir);
3814
- if (widgetStat.isDirectory()) {
3815
- const indexPath = join11(widgetDir, "index.html");
3816
- try {
3817
- const content = await readFile7(indexPath, "utf8");
3818
- res.writeHead(200, { "content-type": "text/html; charset=utf-8" });
3819
- res.end(content);
3820
- return;
3821
- } catch {
3822
- }
3823
- }
3824
- } catch {
3598
+ log(`[adep] \u90E8\u7F72 ${item.name}\uFF08${item.action === "create" ? "\u65B0\u5EFA" : "\u53D8\u66F4"}\uFF09`);
3599
+ let functionId = item.id;
3600
+ if (functionId === null) {
3601
+ const created = await client.request(
3602
+ `/api/v1/projects/${remote.projectId}/functions`,
3603
+ {
3604
+ body: { name: item.name, files: { "index.ts": content } }
3825
3605
  }
3826
- }
3827
- writeJson2(res, 404, { error: { code: "WIDGET_NOT_FOUND", message: "\u7EC4\u4EF6\u4EA7\u7269\u4E0D\u5B58\u5728" } });
3828
- return;
3829
- }
3830
- if (pathname === "/" || pathname === "") {
3831
- writeJson2(res, 200, {
3832
- service: "adep-serve",
3833
- mode: "development",
3834
- project: config.name,
3835
- functions: functionNames,
3836
- static: hasStatic,
3837
- endpoints: {
3838
- functions: "/api/{fn}",
3839
- static: `/ \u2192 ${staticDir}`,
3840
- preview: "/_preview/{widget}",
3841
- healthz: "/healthz"
3842
- },
3843
- warning: "\u8FD9\u662F\u5F00\u53D1\u6001\u670D\u52A1\u5668\uFF0C\u4E0D\u662F\u751F\u4EA7\u670D\u52A1\u5668"
3606
+ );
3607
+ functionId = created.id;
3608
+ } else {
3609
+ await client.request(`/api/v1/projects/${remote.projectId}/functions/${item.name}`, {
3610
+ method: "PATCH",
3611
+ body: { files: { "index.ts": content } }
3844
3612
  });
3845
- return;
3846
3613
  }
3847
- writeJson2(res, 404, { error: { code: "NOT_FOUND", message: `\u8DEF\u5F84 "${pathname}" \u4E0D\u5B58\u5728` } });
3848
- };
3849
- const server = createServer2((req, res) => {
3850
- void handle(req, res).catch((error) => {
3851
- log(`[serve] \u672A\u5904\u7406\u9519\u8BEF: ${error instanceof Error ? error.message : String(error)}`);
3852
- if (!res.headersSent) {
3853
- writeJson2(res, 500, { error: { code: "INTERNAL_ERROR", message: "\u670D\u52A1\u5668\u5185\u90E8\u9519\u8BEF" } });
3854
- }
3855
- });
3856
- });
3857
- const actualPort = await new Promise((resolveListen, rejectListen) => {
3858
- server.once("error", rejectListen);
3859
- server.listen(port, host, () => {
3860
- server.off("error", rejectListen);
3861
- const addr = server.address();
3862
- if (addr === null || typeof addr === "string") {
3863
- resolveListen(port);
3864
- } else {
3865
- resolveListen(addr.port);
3866
- }
3614
+ const published = await client.request(
3615
+ `/api/v1/functions/${functionId}/publish`,
3616
+ { method: "POST" }
3617
+ );
3618
+ deployed.push({
3619
+ name: item.name,
3620
+ action: item.action,
3621
+ version: published.version,
3622
+ url: functionUrl(item.name)
3867
3623
  });
3868
- });
3869
- const banner = renderBanner({
3870
- host,
3871
- port: actualPort,
3872
- projectName: config.name,
3873
- functions: functionNames,
3874
- hasStatic,
3875
- staticDir: relative(cwd, staticDir).length > 0 ? relative(cwd, staticDir) : staticDir
3876
- });
3877
- log(banner);
3624
+ }
3878
3625
  return {
3879
- port: actualPort,
3880
- host,
3881
- baseUrl: `http://${host}:${actualPort}`,
3882
- close: async () => {
3883
- await new Promise((resolveClose) => {
3884
- server.close(() => resolveClose());
3885
- });
3886
- }
3626
+ projectId: remote.projectId,
3627
+ slug: remote.slug,
3628
+ baseUrl,
3629
+ noChanges: deployed.every((function_) => function_.action === "none"),
3630
+ functions: deployed
3887
3631
  };
3888
3632
  }
3889
- var MIME_TYPES;
3890
- var init_server = __esm({
3891
- "packages/cli/src/serve/server.ts"() {
3633
+ var init_deploy = __esm({
3634
+ "packages/cli/src/deploy.ts"() {
3892
3635
  "use strict";
3893
- init_executor();
3894
- init_worker_executor();
3895
- init_runtime();
3896
- init_env();
3897
- init_invoke();
3636
+ init_auth();
3637
+ init_client();
3898
3638
  init_dev();
3899
- init_banner();
3900
- MIME_TYPES = {
3901
- ".html": "text/html; charset=utf-8",
3902
- ".htm": "text/html; charset=utf-8",
3903
- ".css": "text/css; charset=utf-8",
3904
- ".js": "application/javascript; charset=utf-8",
3905
- ".mjs": "application/javascript; charset=utf-8",
3906
- ".json": "application/json; charset=utf-8",
3907
- ".png": "image/png",
3908
- ".jpg": "image/jpeg",
3909
- ".jpeg": "image/jpeg",
3910
- ".gif": "image/gif",
3911
- ".svg": "image/svg+xml",
3912
- ".ico": "image/x-icon",
3913
- ".woff": "font/woff",
3914
- ".woff2": "font/woff2",
3915
- ".ttf": "font/ttf",
3916
- ".txt": "text/plain; charset=utf-8",
3917
- ".md": "text/markdown; charset=utf-8",
3918
- ".pdf": "application/pdf",
3919
- ".map": "application/json"
3920
- };
3639
+ init_net();
3921
3640
  }
3922
3641
  });
3923
3642
 
@@ -3990,13 +3709,13 @@ __export(functions_exports, {
3990
3709
  functionsList: () => functionsList,
3991
3710
  functionsLogs: () => functionsLogs
3992
3711
  });
3993
- import { resolve as resolve8 } from "node:path";
3712
+ import { resolve as resolve6 } from "node:path";
3994
3713
  async function functionsDeploy(paths, options) {
3995
3714
  const startedAt = Date.now();
3996
3715
  const result = await deploy(paths, {
3997
3716
  cwd: options.cwd,
3998
3717
  ...options.slug === void 0 ? {} : { slug: options.slug },
3999
- ...options.dir === void 0 ? {} : { functionsDir: resolve8(options.cwd, options.dir) },
3718
+ ...options.dir === void 0 ? {} : { functionsDir: resolve6(options.cwd, options.dir) },
4000
3719
  silent: true
4001
3720
  });
4002
3721
  return { ...result, elapsedSeconds: (Date.now() - startedAt) / 1e3 };
@@ -4009,10 +3728,12 @@ async function functionsList(paths, options) {
4009
3728
  {},
4010
3729
  "FUNCTION_LIST_FAILED"
4011
3730
  );
3731
+ const prefix = project2.functionsPrefix ?? "/api";
3732
+ const prefixBase = prefix.trim() === "/" ? "" : prefix.trim().replace(/\/+$/, "");
4012
3733
  return {
4013
3734
  projectId: project2.id,
4014
3735
  slug: project2.slug,
4015
- baseUrl: project2.url,
3736
+ baseUrl: `${project2.url.replace(/\/+$/, "")}${prefixBase}`,
4016
3737
  functions: result.functions
4017
3738
  };
4018
3739
  }
@@ -4040,7 +3761,7 @@ async function functionsLogs(paths, options) {
4040
3761
  return { functionId: target.id, name: target.name, logs: result.logs };
4041
3762
  }
4042
3763
  async function resolveProject(client, options) {
4043
- const slug = await resolveSlug(resolve8(options.cwd), options.slug);
3764
+ const slug = await resolveSlug(resolve6(options.cwd), options.slug);
4044
3765
  const projects = await projectsListFrom(client);
4045
3766
  const match = projects.find((project2) => project2.slug === slug);
4046
3767
  if (match === void 0) {
@@ -4071,7 +3792,7 @@ __export(mcp_exports, {
4071
3792
  mcpPublish: () => mcpPublish,
4072
3793
  mcpUnpublish: () => mcpUnpublish
4073
3794
  });
4074
- import { resolve as resolve9 } from "node:path";
3795
+ import { resolve as resolve7 } from "node:path";
4075
3796
  async function mcpPublish(paths, options) {
4076
3797
  const fn = requireFunctionName(options.fn);
4077
3798
  const client = await createClient(paths);
@@ -4107,7 +3828,9 @@ async function mcpUnpublish(paths, options) {
4107
3828
  async function mcpList(paths, options) {
4108
3829
  const client = await createClient(paths);
4109
3830
  const project2 = await resolveProject2(client, options);
4110
- const endpoint = `${project2.url.replace(/\/+$/, "")}/mcp`;
3831
+ const prefix = project2.functionsPrefix ?? "/api";
3832
+ const prefixBase = prefix.trim() === "/" ? "" : prefix.trim().replace(/\/+$/, "");
3833
+ const endpoint = `${project2.url.replace(/\/+$/, "")}${prefixBase}/mcp`;
4111
3834
  let response;
4112
3835
  try {
4113
3836
  response = await fetch(endpoint, {
@@ -4150,7 +3873,7 @@ function requireFunctionName(fn) {
4150
3873
  return fn.trim();
4151
3874
  }
4152
3875
  async function resolveProject2(client, options) {
4153
- const slug = await resolveSlug(resolve9(options.cwd), options.slug);
3876
+ const slug = await resolveSlug(resolve7(options.cwd), options.slug);
4154
3877
  const listed = await client.request("/api/v1/projects", {}, "PROJECT_LIST_FAILED");
4155
3878
  const match = listed.projects.find((project2) => project2.slug === slug);
4156
3879
  if (match === void 0) {
@@ -4159,7 +3882,12 @@ async function resolveProject2(client, options) {
4159
3882
  `\u5E73\u53F0\u9879\u76EE "${slug}" \u4E0D\u5B58\u5728\u6216\u4F60\u6CA1\u6709\u8BBF\u95EE\u6743\u9650\uFF1A\u5148\u6267\u884C adep projects create ${slug}`
4160
3883
  );
4161
3884
  }
4162
- return { id: match.id, slug: match.slug, url: match.url };
3885
+ return {
3886
+ id: match.id,
3887
+ slug: match.slug,
3888
+ url: match.url,
3889
+ ...match.functionsPrefix === void 0 ? {} : { functionsPrefix: match.functionsPrefix }
3890
+ };
4163
3891
  }
4164
3892
  async function resolveFunction(client, project2, name) {
4165
3893
  const listed = await client.request(`/api/v1/projects/${project2.id}/functions`, {}, "FUNCTION_LIST_FAILED");
@@ -4183,7 +3911,7 @@ __export(doctor_exports, {
4183
3911
  formatDoctorReport: () => formatDoctorReport,
4184
3912
  runDoctor: () => runDoctor
4185
3913
  });
4186
- import { stat as stat7 } from "node:fs/promises";
3914
+ import { stat as stat6 } from "node:fs/promises";
4187
3915
  async function probeServer(server) {
4188
3916
  const controller = new AbortController();
4189
3917
  const timer = setTimeout(() => controller.abort(), SERVER_PROBE_TIMEOUT_MS);
@@ -4201,7 +3929,7 @@ async function probeServer(server) {
4201
3929
  }
4202
3930
  async function credentialMode(file) {
4203
3931
  try {
4204
- const info = await stat7(file);
3932
+ const info = await stat6(file);
4205
3933
  return (info.mode & 511).toString(8).padStart(3, "0");
4206
3934
  } catch {
4207
3935
  return void 0;
@@ -4277,8 +4005,6 @@ var init_doctor = __esm({
4277
4005
  "adep init",
4278
4006
  "adep dev",
4279
4007
  "adep serve",
4280
- "adep widget init",
4281
- "adep widget dev",
4282
4008
  "adep db\uFF08\u672C\u5730\u6A21\u62DF\uFF09",
4283
4009
  "adep doctor"
4284
4010
  ];
@@ -4297,10 +4023,10 @@ __export(db_exports, {
4297
4023
  dbStatus: () => dbStatus,
4298
4024
  dbStop: () => dbStop
4299
4025
  });
4300
- import { resolve as resolve10 } from "node:path";
4026
+ import { resolve as resolve8 } from "node:path";
4301
4027
  async function open2(paths, options) {
4302
4028
  const client = await createClient(paths);
4303
- const project2 = await resolveSlug(resolve10(options.cwd), options.slug);
4029
+ const project2 = await resolveSlug(resolve8(options.cwd), options.slug);
4304
4030
  return { client, project: project2 };
4305
4031
  }
4306
4032
  async function dbStart(paths, options) {
@@ -4374,11 +4100,11 @@ __export(storage_exports, {
4374
4100
  storageRemove: () => storageRemove,
4375
4101
  storageUpload: () => storageUpload
4376
4102
  });
4377
- import { mkdir as mkdir7, readFile as readFile8, stat as stat8, writeFile as writeFile6 } from "node:fs/promises";
4378
- import { basename as basename3, dirname as dirname7, extname, join as join12, resolve as resolve11 } from "node:path";
4103
+ import { mkdir as mkdir7, readFile as readFile8, stat as stat7, writeFile as writeFile5 } from "node:fs/promises";
4104
+ import { basename as basename3, dirname as dirname6, extname, join as join10, resolve as resolve9 } from "node:path";
4379
4105
  async function open3(paths, options) {
4380
4106
  const client = await createClient(paths);
4381
- const project2 = await resolveSlug(resolve11(options.cwd), options.slug);
4107
+ const project2 = await resolveSlug(resolve9(options.cwd), options.slug);
4382
4108
  return { client, project: project2 };
4383
4109
  }
4384
4110
  function contentTypeOf(path) {
@@ -4411,8 +4137,8 @@ function contentTypeOf(path) {
4411
4137
  }
4412
4138
  async function storageUpload(paths, options) {
4413
4139
  const { client, project: project2 } = await open3(paths, options);
4414
- const local = resolve11(options.file);
4415
- const info = await stat8(local).catch(() => null);
4140
+ const local = resolve9(options.file);
4141
+ const info = await stat7(local).catch(() => null);
4416
4142
  if (info === null || !info.isFile()) {
4417
4143
  throw new CliError("FILE_NOT_FOUND", `\u672C\u5730\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${local}`);
4418
4144
  }
@@ -4458,9 +4184,9 @@ async function storageDownload(paths, options) {
4458
4184
  const url = await resolveDownloadUrl(client, project2, options.path);
4459
4185
  const response = await client.download(url, "STORAGE_DOWNLOAD_FAILED");
4460
4186
  const bytes = Buffer.from(await response.arrayBuffer());
4461
- const output = resolve11(options.output ?? join12(resolve11(options.cwd), basename3(options.path)));
4462
- await mkdir7(dirname7(output), { recursive: true });
4463
- await writeFile6(output, bytes);
4187
+ const output = resolve9(options.output ?? join10(resolve9(options.cwd), basename3(options.path)));
4188
+ await mkdir7(dirname6(output), { recursive: true });
4189
+ await writeFile5(output, bytes);
4464
4190
  return { path: options.path, output, size: bytes.length };
4465
4191
  }
4466
4192
  async function storageRemove(paths, options) {
@@ -4486,11 +4212,11 @@ __export(hosting_exports, {
4486
4212
  hostingInfo: () => hostingInfo,
4487
4213
  hostingPull: () => hostingPull
4488
4214
  });
4489
- import { readdir as readdir5, readFile as readFile9, stat as stat9 } from "node:fs/promises";
4490
- import { dirname as dirname8, join as join13, relative as relative2, resolve as resolve12, sep } from "node:path";
4215
+ import { readdir as readdir5, readFile as readFile9, stat as stat8 } from "node:fs/promises";
4216
+ import { dirname as dirname7, join as join11, relative as relative2, resolve as resolve10, sep } from "node:path";
4491
4217
  async function open4(paths, options) {
4492
4218
  const client = await createClient(paths);
4493
- const project2 = await resolveSlug(resolve12(options.cwd), options.slug);
4219
+ const project2 = await resolveSlug(resolve10(options.cwd), options.slug);
4494
4220
  return { client, project: project2 };
4495
4221
  }
4496
4222
  async function hostingInfo(paths, options) {
@@ -4503,7 +4229,7 @@ async function hostingInfo(paths, options) {
4503
4229
  };
4504
4230
  }
4505
4231
  async function collectSiteFiles(dir) {
4506
- const root = resolve12(dir);
4232
+ const root = resolve10(dir);
4507
4233
  const files = /* @__PURE__ */ new Map();
4508
4234
  const walk = async (sub) => {
4509
4235
  let entries;
@@ -4513,7 +4239,7 @@ async function collectSiteFiles(dir) {
4513
4239
  return;
4514
4240
  }
4515
4241
  for (const entry of entries) {
4516
- const full = join13(sub, entry.name);
4242
+ const full = join11(sub, entry.name);
4517
4243
  if (entry.isDirectory()) {
4518
4244
  await walk(full);
4519
4245
  } else if (entry.isFile()) {
@@ -4531,12 +4257,12 @@ async function hostingDeploy(paths, options) {
4531
4257
  `));
4532
4258
  const files = await collectSiteFiles(options.dir);
4533
4259
  if (files.size === 0) {
4534
- throw new CliError("NO_SITE_FILES", `\u7AD9\u70B9\u76EE\u5F55\u4E3A\u7A7A\uFF1A${resolve12(options.dir)}`);
4260
+ throw new CliError("NO_SITE_FILES", `\u7AD9\u70B9\u76EE\u5F55\u4E3A\u7A7A\uFF1A${resolve10(options.dir)}`);
4535
4261
  }
4536
4262
  const uploaded = [];
4537
4263
  for (const [rel, full] of files) {
4538
4264
  log(`[adep] \u4E0A\u4F20 site/${rel}`);
4539
- const info2 = await stat9(full);
4265
+ const info2 = await stat8(full);
4540
4266
  const bytes = await readFile9(full);
4541
4267
  const form = new FormData();
4542
4268
  form.set("path", `site/${rel}`);
@@ -4564,8 +4290,8 @@ async function hostingPull(paths, options) {
4564
4290
  const log = options.log ?? ((line) => process.stdout.write(`${line}
4565
4291
  `));
4566
4292
  const info = await hostingInfo(paths, options);
4567
- const outputDir = resolve12(options.output ?? resolve12(options.cwd));
4568
- const { mkdir: mkdir9, writeFile: writeFile9 } = await import("node:fs/promises");
4293
+ const outputDir = resolve10(options.output ?? resolve10(options.cwd));
4294
+ const { mkdir: mkdir9, writeFile: writeFile8 } = await import("node:fs/promises");
4569
4295
  const files = [];
4570
4296
  for (const entry of info.files) {
4571
4297
  if (entry.visibility !== "public" || entry.path === HOSTING_CONFIG_PATH) continue;
@@ -4575,9 +4301,9 @@ async function hostingPull(paths, options) {
4575
4301
  const response = await client.download(url, "HOSTING_DOWNLOAD_FAILED");
4576
4302
  const bytes = Buffer.from(await response.arrayBuffer());
4577
4303
  const rel = entry.path.replace(/^site\//, "");
4578
- const target = join13(outputDir, ...rel.split("/"));
4579
- await mkdir9(dirname8(target), { recursive: true });
4580
- await writeFile9(target, bytes);
4304
+ const target = join11(outputDir, ...rel.split("/"));
4305
+ await mkdir9(dirname7(target), { recursive: true });
4306
+ await writeFile8(target, bytes);
4581
4307
  files.push({ path: entry.path, size: bytes.length });
4582
4308
  }
4583
4309
  return { siteUrl: info.siteUrl, outputDir, files };
@@ -4609,7 +4335,7 @@ var client_exports2 = {};
4609
4335
  __export(client_exports2, {
4610
4336
  createExportApiClient: () => createExportApiClient
4611
4337
  });
4612
- import { writeFile as writeFile7 } from "node:fs/promises";
4338
+ import { writeFile as writeFile6 } from "node:fs/promises";
4613
4339
  function toExportJob(view) {
4614
4340
  return {
4615
4341
  id: view.id,
@@ -4653,7 +4379,7 @@ async function createExportApiClient(paths) {
4653
4379
  }
4654
4380
  const response = await client.download(download.downloadUrl, "EXPORT_DOWNLOAD_FAILED");
4655
4381
  const bytes = Buffer.from(await response.arrayBuffer());
4656
- await writeFile7(outputPath, bytes);
4382
+ await writeFile6(outputPath, bytes);
4657
4383
  return { path: outputPath, size: bytes.length };
4658
4384
  }
4659
4385
  };
@@ -4750,19 +4476,19 @@ var fs_exports = {};
4750
4476
  __export(fs_exports, {
4751
4477
  createExportFileSystem: () => createExportFileSystem
4752
4478
  });
4753
- import { mkdir as mkdir8, readFile as readFile10, rm as rm3, stat as stat10, writeFile as writeFile8 } from "node:fs/promises";
4754
- import { dirname as dirname9, join as join14 } from "node:path";
4479
+ import { mkdir as mkdir8, readFile as readFile10, rm as rm3, stat as stat9, writeFile as writeFile7 } from "node:fs/promises";
4480
+ import { dirname as dirname8, join as join12 } from "node:path";
4755
4481
  function createExportFileSystem() {
4756
4482
  return {
4757
4483
  readFile: (path) => readFile10(path),
4758
- writeFile: (path, content) => writeFile8(path, content),
4484
+ writeFile: (path, content) => writeFile7(path, content),
4759
4485
  // 同时用于清理解压临时目录(${zip}.tmp 是个目录)——递归强制删除,缺失不报错。
4760
4486
  deleteFile: async (path) => {
4761
4487
  await rm3(path, { recursive: true, force: true });
4762
4488
  },
4763
4489
  fileExists: async (path) => {
4764
4490
  try {
4765
- await stat10(path);
4491
+ await stat9(path);
4766
4492
  return true;
4767
4493
  } catch {
4768
4494
  return false;
@@ -4774,9 +4500,9 @@ function createExportFileSystem() {
4774
4500
  unzip: async (zipPath, targetDir) => {
4775
4501
  const entries = zipRead(await readFile10(zipPath));
4776
4502
  for (const [name, data] of entries) {
4777
- const dest = join14(targetDir, name);
4778
- await mkdir8(dirname9(dest), { recursive: true });
4779
- await writeFile8(dest, data);
4503
+ const dest = join12(targetDir, name);
4504
+ await mkdir8(dirname8(dest), { recursive: true });
4505
+ await writeFile7(dest, data);
4780
4506
  }
4781
4507
  }
4782
4508
  };
@@ -5057,7 +4783,7 @@ var command_exports = {};
5057
4783
  __export(command_exports, {
5058
4784
  ExportCommand: () => ExportCommand
5059
4785
  });
5060
- import { createHash as createHash4 } from "node:crypto";
4786
+ import { createHash as createHash3 } from "node:crypto";
5061
4787
  var ExportCommand;
5062
4788
  var init_command = __esm({
5063
4789
  "packages/cli/src/export/command.ts"() {
@@ -5205,7 +4931,7 @@ ${errors}`);
5205
4931
  const contentResult = verifyContents(
5206
4932
  manifest.contents,
5207
4933
  actual,
5208
- (text) => createHash4("sha256").update(Buffer.from(text, "latin1")).digest("hex")
4934
+ (text) => createHash3("sha256").update(Buffer.from(text, "latin1")).digest("hex")
5209
4935
  );
5210
4936
  if (!contentResult.valid) {
5211
4937
  const detail = contentResult.errors.map((e) => e.message).join("\n");
@@ -5276,311 +5002,405 @@ ${detail}`);
5276
5002
  * @param ms 毫秒数
5277
5003
  */
5278
5004
  sleep(ms) {
5279
- return new Promise((resolve15) => setTimeout(resolve15, ms));
5005
+ return new Promise((resolve11) => setTimeout(resolve11, ms));
5280
5006
  }
5281
5007
  };
5282
5008
  }
5283
5009
  });
5284
5010
 
5285
- // packages/cli/src/widget/dev.ts
5286
- var dev_exports2 = {};
5287
- __export(dev_exports2, {
5288
- loadWidgetProject: () => loadWidgetProject,
5289
- startWidgetDev: () => startWidgetDev
5290
- });
5291
- import { createServer as createServer3 } from "node:http";
5292
- import { watch as watch2 } from "node:fs";
5293
- import { readFile as readFile11, stat as stat11 } from "node:fs/promises";
5294
- import { join as join15, resolve as resolve13 } from "node:path";
5295
- async function loadWidgetProject(cwd) {
5296
- const fallback = {
5297
- name: "widget",
5298
- framework: "vue3"
5299
- };
5300
- const manifestPath = join15(resolve13(cwd), "manifest.json");
5301
- try {
5302
- await stat11(manifestPath);
5303
- } catch {
5304
- return fallback;
5305
- }
5306
- try {
5307
- const raw = await readFile11(manifestPath, "utf8");
5308
- const parsed = JSON.parse(raw);
5309
- return {
5310
- name: typeof parsed["name"] === "string" ? parsed["name"] : fallback.name,
5311
- framework: parsed["framework"] === "react" ? "react" : "vue3"
5312
- };
5313
- } catch {
5314
- return fallback;
5315
- }
5316
- }
5317
- function sandboxHtml(name, framework) {
5318
- return `<!doctype html>
5319
- <html>
5320
- <head>
5321
- <meta charset="utf-8" />
5322
- <title>adep widget dev \u2014 ${name}</title>
5323
- <link rel="stylesheet" href="/__widget/theme.css" />
5324
- <style>
5325
- body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background: #f5f6f7; margin: 0; padding: 24px; }
5326
- #toolbar { display: flex; gap: 12px; align-items: center; font-size: 13px; color: #4c5561; margin-bottom: 16px; }
5327
- #toolbar .dot { width: 8px; height: 8px; border-radius: 50%; background: #99a2ad; }
5328
- #toolbar .dot.on { background: #16a34a; }
5329
- #sandbox { background: #fff; border: 1px solid #e5e6eb; border-radius: 8px; min-height: 120px; }
5330
- code { background: #eef0f3; padding: 2px 6px; border-radius: 4px; }
5331
- </style>
5332
- </head>
5333
- <body>
5334
- <div id="toolbar"><span id="status"><span class="dot" id="dot"></span> sandbox connecting\u2026</span></div>
5335
- <div id="sandbox"></div>
5336
- <script type="module">
5337
- const q = new URLSearchParams(location.search)
5338
- const token = q.get('token') ?? ''
5339
- document.getElementById('status').textContent = 'token: ' + (token ? 'injected' : '(none)')
5340
- const hostEl = document.getElementById('sandbox')
5341
- const host = hostEl.attachShadow({ mode: 'open' })
5342
- let version = 0
5011
+ // packages/cli/src/cli.ts
5012
+ init_config();
5013
+ import { Command } from "commander";
5014
+ import { createRequire } from "node:module";
5343
5015
 
5344
- async function load(v) {
5345
- host.textContent = ''
5346
- let props = {}
5347
- try { props = await (await fetch('/__widget/mock-props')).json() } catch { props = {} }
5348
- const mod = await import('/__widget/index.js?v=' + v)
5349
- mod.mount(host, {
5350
- widgetName: '${name}',
5351
- framework: '${framework}',
5352
- props,
5353
- host: {
5354
- getProjectId: () => 'local-dev',
5355
- invokeFunction: async () => ({})
5356
- }
5357
- })
5358
- }
5016
+ // packages/cli/src/output.ts
5017
+ init_auth();
5359
5018
 
5360
- function markConnected() {
5361
- const dot = document.getElementById('dot')
5362
- dot.classList.add('on')
5363
- document.getElementById('status').firstChild.textContent = 'sandbox live \u2014 watch src/\uFF0C\u4FDD\u5B58\u540E\u81EA\u52A8\u70ED\u66F4\u65B0 '
5364
- }
5019
+ // packages/cli/src/init.ts
5020
+ import { mkdir as mkdir2, stat as stat2, writeFile } from "node:fs/promises";
5021
+ import { dirname as dirname2, join, resolve } from "node:path";
5365
5022
 
5366
- const es = new EventSource('/__widget/events')
5367
- es.addEventListener('rebuild', (e) => {
5368
- version = Number(e.data) || 0
5369
- load(version).catch((err) => { console.error(err); host.textContent = 'mount error: ' + err.message })
5370
- })
5371
- es.addEventListener('open', (e) => {
5372
- e.preventDefault()
5373
- markConnected()
5374
- if (version === 0) load(0)
5375
- })
5376
- </script>
5377
- </body>
5378
- </html>
5379
- `;
5023
+ // shared/sdk/adep-env.ts
5024
+ var ADEP_ENV_DTS = `/**
5025
+ * AgentDeploy \u4E91\u51FD\u6570\u5F00\u53D1\u73AF\u5883\u7C7B\u578B\u58F0\u660E\uFF08\u90E8\u7F72\u5305 / adep init \u751F\u6210\uFF0C\u8BF7\u52FF\u624B\u6539\uFF09\u3002
5026
+ *
5027
+ * \u672C\u6587\u4EF6\u662F @adep/types \u7684\u6E90\u7801\u6587\u672C\u955C\u50CF\uFF1A\u4E3A\u51FD\u6570\u6E90\u7801\u91CC\u7684 ctx \u63D0\u4F9B method/path/query/
5028
+ * headers/body/files/user \u4E0E cloud.db / cloud.storage / cloud.fetch / cloud.realtime \u7684\u5B8C\u6574\u8865\u5168\u3002
5029
+ * \u5168\u5C40 ctx \u4E0E AdepContext \u662F\u5F00\u53D1\u671F\u4E0A\u4E0B\u6587\uFF08\u7F16\u8F91\u5668\u8865\u5168\u7528\uFF09\uFF1B\u51FD\u6570\u8FD0\u884C\u671F\u7ECF\u53C2\u6570\u6CE8\u5165\uFF0C\u4E0D\u8BFB\u53D6\u5168\u5C40\u3002
5030
+ * \u7C7B\u578B\u5951\u7EA6\u7684\u5355\u4E00\u771F\u76F8\u6E90\u89C1 packages/types\uFF08\u4EFB\u52A1\u5355 CORE-006\uFF09\u3002
5031
+ */
5032
+
5033
+ /* ---------- HTTP \u89E6\u53D1\u4E0A\u4E0B\u6587\uFF08FunctionContext \u955C\u50CF\uFF09 ---------- */
5034
+
5035
+ type AdepHttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS'
5036
+
5037
+ /* ---------- \u6587\u4EF6\u4E0E\u5B58\u50A8\uFF08CloudStorage \u955C\u50CF\uFF09 ---------- */
5038
+
5039
+ /** multipart \u4E0A\u4F20\u7684\u6587\u4EF6\uFF08\u51FD\u6570 HTTP \u89E6\u53D1\u65F6 ctx.files \u4E2D\u7684\u5355\u4E2A\u6587\u4EF6\uFF09\u3002 */
5040
+ interface AdepFunctionFile {
5041
+ /** \u5BA2\u6237\u7AEF\u63D0\u4F9B\u7684\u6587\u4EF6\u540D\uFF08\u542B\u6269\u5C55\u540D\uFF09\u3002 */
5042
+ name: string
5043
+ /** MIME \u7C7B\u578B\u3002 */
5044
+ type: string
5045
+ /** \u5B57\u8282\u6570\u3002 */
5046
+ size: number
5047
+ data: Uint8Array
5380
5048
  }
5381
- async function startWidgetDev(options) {
5382
- const cwd = resolve13(options.cwd);
5383
- const log = options.log ?? ((line) => process.stdout.write(`${line}
5384
- `));
5385
- const project2 = await loadWidgetProject(cwd);
5386
- const framework = options.framework ?? project2.framework;
5387
- let state = { text: "", version: 0 };
5388
- const rebuild = async () => {
5389
- const built = await buildWidget({ cwd, framework });
5390
- const next = { text: built.text, version: state.version + 1 };
5391
- state = next;
5392
- return next;
5393
- };
5394
- try {
5395
- await rebuild();
5396
- } catch (error) {
5397
- throw new WidgetError(
5398
- "BUILD_FAILED",
5399
- `widget \u6784\u5EFA\u5931\u8D25\uFF1A${error instanceof Error ? error.message : String(error)}`
5400
- );
5401
- }
5402
- const clients = /* @__PURE__ */ new Set();
5403
- const broadcast = (version) => {
5404
- for (const res of clients) {
5405
- res.write(`event: rebuild
5406
- data: ${version}
5407
5049
 
5408
- `);
5409
- }
5410
- };
5411
- let debounceTimer;
5412
- let watcher;
5413
- try {
5414
- watcher = watch2(cwd, { recursive: true }, () => {
5415
- if (debounceTimer !== void 0) clearTimeout(debounceTimer);
5416
- debounceTimer = setTimeout(() => {
5417
- void buildWidget({ cwd, framework }).then((built) => {
5418
- const next = { text: built.text, version: state.version + 1 };
5419
- state = next;
5420
- broadcast(next.version);
5421
- log(`[adep] widget rebuilt v${next.version}`);
5422
- return void 0;
5423
- }).catch((error) => {
5424
- log(`[adep] rebuild failed: ${error instanceof Error ? error.message : String(error)}`);
5425
- });
5426
- }, 120);
5427
- });
5428
- } catch {
5429
- watcher = void 0;
5430
- }
5431
- const readTheme = async () => {
5432
- try {
5433
- return await readFile11(join15(cwd, "src", "theme.css"), "utf8");
5434
- } catch {
5435
- return null;
5436
- }
5437
- };
5438
- const readProps = async () => {
5439
- try {
5440
- return await readFile11(join15(cwd, "src", "mock-props.json"), "utf8");
5441
- } catch {
5442
- return null;
5443
- }
5444
- };
5445
- const handle = async (req, res) => {
5446
- const url = new URL(req.url ?? "/", "http://127.0.0.1");
5447
- if (url.pathname === "/") {
5448
- res.writeHead(200, { "content-type": "text/html; charset=utf-8" });
5449
- res.end(sandboxHtml(project2.name, framework));
5450
- return;
5451
- }
5452
- if (url.pathname === "/__widget/index.js") {
5453
- const version = url.searchParams.get("v");
5454
- if (version !== null && Number(version) > state.version) {
5455
- await rebuild().catch(() => void 0);
5456
- }
5457
- res.writeHead(200, { "content-type": "application/javascript; charset=utf-8" });
5458
- res.end(state.text);
5459
- return;
5460
- }
5461
- if (url.pathname === "/__widget/theme.css") {
5462
- const css = await readTheme();
5463
- if (css === null) {
5464
- res.writeHead(404).end("not found");
5465
- return;
5466
- }
5467
- res.writeHead(200, { "content-type": "text/css; charset=utf-8" });
5468
- res.end(css);
5469
- return;
5470
- }
5471
- if (url.pathname === "/__widget/mock-props") {
5472
- const props = await readProps();
5473
- res.writeHead(200, { "content-type": "application/json; charset=utf-8" });
5474
- res.end(props ?? "{}");
5475
- return;
5476
- }
5477
- if (url.pathname === "/__widget/events") {
5478
- res.writeHead(200, {
5479
- "content-type": "text/event-stream",
5480
- "cache-control": "no-cache",
5481
- connection: "keep-alive"
5482
- });
5483
- res.write(": connected\n\n");
5484
- clients.add(res);
5485
- req.on("close", () => {
5486
- clients.delete(res);
5487
- });
5488
- return;
5489
- }
5490
- res.writeHead(404).end("not found");
5491
- };
5492
- const server = createServer3((req, res) => {
5493
- void handle(req, res);
5494
- });
5495
- await new Promise((resolveListen, rejectListen) => {
5496
- server.once("error", rejectListen);
5497
- server.listen(options.port ?? 8788, "127.0.0.1", () => {
5498
- server.off("error", rejectListen);
5499
- resolveListen();
5500
- });
5501
- });
5502
- const address = server.address();
5503
- const port = typeof address === "object" && address !== null ? address.port : options.port ?? 8788;
5504
- const baseUrl = `http://127.0.0.1:${port}`;
5505
- return {
5506
- port,
5507
- baseUrl,
5508
- close: async () => {
5509
- if (debounceTimer !== void 0) clearTimeout(debounceTimer);
5510
- watcher?.close();
5511
- for (const res of clients) res.end();
5512
- clients.clear();
5513
- await new Promise((resolveClose) => server.close(() => resolveClose()));
5514
- }
5515
- };
5050
+ /** \u4E0A\u4F20\u6570\u636E\uFF1A\u6587\u672C\u3001\u4E8C\u8FDB\u5236\u3001\u6216\u76F4\u63A5\u900F\u4F20\u8BF7\u6C42\u91CC\u7684\u6587\u4EF6\u5BF9\u8C61\u3002 */
5051
+ type AdepStorageUploadData = string | Uint8Array | ArrayBuffer | AdepFunctionFile
5052
+
5053
+ type AdepFileVisibility = 'public' | 'private'
5054
+
5055
+ /** \u4E0A\u4F20 / \u5217\u4E3E\u8FD4\u56DE\u7684\u6587\u4EF6\u5143\u6570\u636E\uFF08\u4E0D\u542B\u5185\u5BB9\uFF09\u3002 */
5056
+ interface AdepStoredFile {
5057
+ /** \u6876\u5185\u76F8\u5BF9\u8DEF\u5F84\uFF0C\u5982 avatars/avatar.png\u3002 */
5058
+ path: string
5059
+ size: number
5060
+ contentType?: string
5061
+ visibility: AdepFileVisibility
5062
+ /** ISO 8601 \u65F6\u95F4\u6233\u3002 */
5063
+ updatedAt?: string
5064
+ }
5065
+
5066
+ interface AdepCloudStorage {
5067
+ /** \u4E0A\u4F20 / \u8986\u76D6\u6587\u4EF6\uFF1B\u8DEF\u5F84\u975E\u6CD5\uFF08\u7A7F\u8D8A\u3001\u8D85\u9650\uFF09\u7531\u5B9E\u73B0\u629B\u9519\u3002 */
5068
+ upload(path: string, data: AdepStorageUploadData): Promise<AdepStoredFile>
5069
+ /** \u8BFB\u53D6\u6587\u4EF6\u5185\u5BB9\uFF1B\u4E0D\u5B58\u5728\u65F6\u629B STORAGE_NOT_FOUND\u3002 */
5070
+ get(path: string): Promise<Uint8Array>
5071
+ /** \u5220\u9664\u6587\u4EF6\uFF1B\u4E0D\u5B58\u5728\u65F6\u629B STORAGE_NOT_FOUND\u3002 */
5072
+ remove(path: string): Promise<void>
5073
+ /** \u6309\u524D\u7F00\u5217\u4E3E\uFF08\u7F3A\u7701\u5168\u6876\uFF09\u3002 */
5074
+ list(prefix?: string): Promise<AdepStoredFile[]>
5075
+ /** \u751F\u6210\u7B7E\u540D URL\uFF08private \u6587\u4EF6\u7684\u5916\u53D1\u901A\u9053\uFF09\uFF1B\u7F3A\u7701 TTL 15 \u5206\u949F\u3002 */
5076
+ getSignedUrl(path: string, ttlSeconds?: number): Promise<string>
5077
+ }
5078
+
5079
+ /* ---------- \u6570\u636E\u5E93\uFF08CloudDb \u955C\u50CF\uFF09 ---------- */
5080
+
5081
+ /** \u53EF\u7ED1\u5B9A\u5230 SQLite \u7684\u53C2\u6570\u503C\u3002 */
5082
+ type AdepSqlValue = string | number | bigint | boolean | null | Uint8Array
5083
+
5084
+ /** where(col, op, value) \u652F\u6301\u7684\u6BD4\u8F83\u7B26\u3002 */
5085
+ type AdepSqlOperator = '=' | '!=' | '>' | '>=' | '<' | '<=' | 'like' | 'in' | 'not in'
5086
+
5087
+ /** \u4E00\u884C\u67E5\u8BE2\u7ED3\u679C\u3002\u5217\u7C7B\u578B\u7F16\u8BD1\u671F\u672A\u77E5\uFF08\u8FD0\u884C\u65F6\u5EFA\u8868\uFF09\uFF0C\u7531\u7528\u6237\u4EE3\u7801\u81EA\u884C\u6536\u7A84\u3002 */
5088
+ type AdepRow = Record<string, unknown>
5089
+
5090
+ /** owned \u8868\u53D8\u66F4\u64CD\u4F5C\u7C7B\u578B\u3002 */
5091
+ type AdepChangeOp = 'insert' | 'update' | 'delete'
5092
+
5093
+ /** owned \u8868 __changes \u53D8\u66F4\u6D41\u8BB0\u5F55\uFF08\u8FFD\u52A0\u5F0F\u3001\u53EF\u91CD\u653E\uFF1Bbefore/after \u4E3A\u6574\u884C\uFF0C\u672A\u6D89\u53CA\u4FA7\u4E3A null\uFF09\u3002 */
5094
+ interface AdepChangeRecord {
5095
+ /** \u8868\u5185\u81EA\u589E\u5E8F\u53F7\uFF08\u65F6\u95F4\u5347\u5E8F\uFF0C\u91CD\u653E\u987A\u5E8F\u4F9D\u636E\uFF09\u3002 */
5096
+ seq: number
5097
+ /** \u53D8\u66F4\u65F6\u95F4\uFF08ISO 8601\uFF09\u3002 */
5098
+ ts: string
5099
+ op: AdepChangeOp
5100
+ /** \u884C\u4E3B\u952E\uFF08ULID\uFF09\u3002 */
5101
+ id: string
5102
+ /** \u884C\u5F52\u5C5E\u5206\u533A\uFF08null = \u672A\u5F52\u5C5E\uFF09\u3002 */
5103
+ ownerKey: string | null
5104
+ /** \u53D8\u66F4\u524D\u6574\u884C\uFF08insert \u4E3A null\uFF09\u3002 */
5105
+ before: AdepRow | null
5106
+ /** \u53D8\u66F4\u540E\u6574\u884C\uFF08delete \u4E3A null\uFF09\u3002 */
5107
+ after: AdepRow | null
5108
+ }
5109
+
5110
+ /** cloud.db.changes(table, query) \u7684\u8FC7\u6EE4\u6761\u4EF6\uFF08\u5168\u90E8\u53EF\u9009\uFF09\u3002 */
5111
+ interface AdepChangeQuery {
5112
+ /** \u53EA\u53D6 seq > afterSeq\uFF08\u589E\u91CF\u62C9\u53D6 / \u6536\u4EF6\u6279\u6B21\uFF09\u3002 */
5113
+ afterSeq?: number
5114
+ /** \u53EA\u53D6\u67D0\u5206\u533A\u884C\uFF1Bnull = \u53EA\u53D6\u672A\u5F52\u5C5E\u884C\uFF08\u7F3A\u7701\u4E0D\u8FC7\u6EE4\uFF09\u3002 */
5115
+ ownerKey?: string | null
5116
+ /** \u6700\u591A\u8FD4\u56DE\u6761\u6570\uFF08\u914D\u5408 afterSeq \u505A\u5206\u9875\uFF09\u3002 */
5117
+ limit?: number
5118
+ }
5119
+
5120
+ /**
5121
+ * \u5355\u8868\u94FE\u5F0F Builder\u3002\u6240\u6709\u94FE\u5F0F\u65B9\u6CD5\u8FD4\u56DE\u65B0 Builder\uFF08\u4E0D\u53EF\u53D8\uFF09\uFF0C\u7EC8\u503C\u65B9\u6CD5
5122
+ * \uFF08get/first/count/insert/update/delete\uFF09\u8FD4\u56DE Promise\u3002\u590D\u7528\u540C\u4E00 Builder
5123
+ * \u5B9E\u4F8B\u6D3E\u751F\u591A\u4E2A\u67E5\u8BE2\u662F\u5B89\u5168\u7684\uFF08\u5B9E\u73B0\u4E0D\u5F97\u6709\u5171\u4EAB\u53EF\u53D8\u72B6\u6001\uFF09\u3002
5124
+ */
5125
+ interface AdepCloudDbTable {
5126
+ /** \u9650\u5B9A\u8FD4\u56DE\u5217\uFF1B\u4E0D\u8C03\u5373 select *\u3002 */
5127
+ select(...columns: string[]): AdepCloudDbTable
5128
+ /** \u58F0\u660E\u4E3A owned \u8868\uFF08DB-006\uFF09\uFF1A\u5199\u5165\u81EA\u52A8\u751F\u6210 ULID \u4E3B\u952E + \u8FFD\u52A0 __changes \u53D8\u66F4\u6D41\u3002 */
5129
+ owned(): AdepCloudDbTable
5130
+ /** \u7B49\u503C\u8FC7\u6EE4\uFF1Awhere('status', 'active')\u3002 */
5131
+ where(column: string, value: AdepSqlValue): AdepCloudDbTable
5132
+ /** \u5E26\u64CD\u4F5C\u7B26\u8FC7\u6EE4\uFF1Awhere('age', '>', 18)\u3002 */
5133
+ where(
5134
+ column: string,
5135
+ operator: AdepSqlOperator,
5136
+ value: AdepSqlValue | readonly AdepSqlValue[]
5137
+ ): AdepCloudDbTable
5138
+ orderBy(column: string, direction?: 'asc' | 'desc'): AdepCloudDbTable
5139
+ limit(n: number): AdepCloudDbTable
5140
+ offset(n: number): AdepCloudDbTable
5141
+ /** \u7ED3\u679C\u6570\u7EC4\uFF08\u53EF\u80FD\u4E3A\u7A7A\uFF09\u3002 */
5142
+ get(): Promise<AdepRow[]>
5143
+ /** \u9996\u884C\u6216 null\u3002 */
5144
+ first(): Promise<AdepRow | null>
5145
+ /** \u884C\u6570\uFF08\u5FFD\u7565 select/orderBy\uFF09\u3002 */
5146
+ count(): Promise<number>
5147
+ /** \u63D2\u5165\u4E00\u884C\uFF1Bwhere \u5BF9\u63D2\u5165\u65E0\u610F\u4E49\u3002 */
5148
+ insert(row: Record<string, AdepSqlValue>): Promise<void>
5149
+ /** \u6279\u91CF\u63D2\u5165\u3002 */
5150
+ insertMany(rows: ReadonlyArray<Record<string, AdepSqlValue>>): Promise<void>
5151
+ /** \u66F4\u65B0\uFF08\u5FC5\u987B\u5148 where\uFF0C\u5426\u5219 DB_UNSAFE_OP\uFF09\uFF1B\u8FD4\u56DE\u53D7\u5F71\u54CD\u884C\u6570\u3002 */
5152
+ update(values: Record<string, AdepSqlValue>): Promise<number>
5153
+ /** \u5220\u9664\uFF08\u5FC5\u987B\u5148 where\uFF0C\u5426\u5219 DB_UNSAFE_OP\uFF09\uFF1B\u8FD4\u56DE\u53D7\u5F71\u54CD\u884C\u6570\u3002 */
5154
+ delete(): Promise<number>
5155
+ }
5156
+
5157
+ /** \u9879\u76EE\u6570\u636E\u5E93\u53E5\u67C4\uFF08\u95ED\u5305\u5C01\u88C5\uFF1A\u4E0D\u66B4\u9732\u8FDE\u63A5\u4E32\u3001schema \u540D\uFF09\u3002 */
5158
+ interface AdepCloudDb {
5159
+ /** \u6253\u5F00\u5355\u8868 Builder\u3002\u8868\u540D\u7531\u8FD0\u884C\u65F6\u767D\u540D\u5355\u6821\u9A8C\u3002 */
5160
+ table(name: string): AdepCloudDbTable
5161
+ /** \u4E8B\u52A1\uFF1Afn \u6536\u5230\u540C\u5F62\u72B6\u7684\u53D7\u63A7\u4E8B\u52A1\u53E5\u67C4\uFF1B\u629B\u9519\u5373\u6574\u4F53\u56DE\u6EDA\u3002\u4E8B\u52A1\u5185\u7981\u6B62\u4E8B\u52A1\u5916\u53E5\u67C4\u5199\u672C\u5E93\u3002 */
5162
+ transaction<T>(fn: (tx: AdepCloudDb) => Promise<T>): Promise<T>
5163
+ /** \u53D7\u63A7\u88F8 SQL\uFF1Bparams \u5FC5\u586B\uFF08\u65E0\u53C2\u4F20 []\uFF09\uFF0C\u5355\u8BED\u53E5\uFF0C\u7981\u591A\u8BED\u53E5\u5806\u53E0\u3002 */
5164
+ query(sql: string, params: readonly AdepSqlValue[]): Promise<AdepRow[]>
5165
+ /** \u8BFB\u53D6 owned \u8868 __changes \u53D8\u66F4\u6D41\uFF08\u6309 seq \u5347\u5E8F\uFF0C\u53EF\u91CD\u653E\uFF09\u3002 */
5166
+ changes(table: string, query?: AdepChangeQuery): Promise<AdepChangeRecord[]>
5167
+ }
5168
+
5169
+ /* ---------- \u53D7\u63A7\u7F51\u7EDC\uFF08CloudFetch \u955C\u50CF\uFF09 ---------- */
5170
+
5171
+ /** cloud.fetch \u8BF7\u6C42\u9009\u9879\uFF08\u53D7\u63A7\u5B50\u96C6\uFF0Cbody \u9650\u5236\u4E3A\u5B57\u7B26\u4E32/JSON\uFF0C\u4E8C\u8FDB\u5236\u4E0A\u4F20\u4E0D\u5728\u672C\u80FD\u529B\u8303\u56F4\uFF09\u3002 */
5172
+ interface AdepCloudFetchInit {
5173
+ method?: string
5174
+ /** \u8BF7\u6C42\u5934\uFF08\u5C0F\u5199\u5316\u540E\u9010\u6761\u900F\u4F20\uFF09\u3002 */
5175
+ headers?: Record<string, string>
5176
+ body?: string
5177
+ /** \u8C03\u7528\u65B9\u4E2D\u6B62\u4FE1\u53F7\uFF08\u4E0E\u5E73\u53F0\u8D85\u65F6\u53E0\u52A0\uFF0C\u4E8C\u8005\u4EFB\u4E00\u89E6\u53D1\u5373\u4E2D\u6B62\uFF09\u3002 */
5178
+ signal?: AbortSignal
5179
+ }
5180
+
5181
+ /** cloud.fetch \u7684\u7ED3\u6784\u5316\u54CD\u5E94\uFF08\u6587\u672C/JSON/\u4E8C\u8FDB\u5236\u8BFB\u53D6\u53D7\u54CD\u5E94\u4F53\u4E0A\u9650\u7EA6\u675F\uFF09\u3002 */
5182
+ interface AdepCloudFetchResponse {
5183
+ ok: boolean
5184
+ status: number
5185
+ statusText: string
5186
+ /** \u5F52\u4E00\u5316\u54CD\u5E94\u5934\uFF08\u952E\u5C0F\u5199\uFF09\u3002 */
5187
+ headers: Record<string, string>
5188
+ text(): Promise<string>
5189
+ json(): Promise<unknown>
5190
+ arrayBuffer(): Promise<ArrayBuffer>
5191
+ }
5192
+
5193
+ /** cloud.fetch\uFF1A\u53D7\u63A7\u7684 HTTPS \u8BF7\u6C42\u3002URL \u4E3B\u673A\u4E0D\u5728\u767D\u540D\u5355\u5219\u629B FN_FETCH_FORBIDDEN\u3002 */
5194
+ type AdepCloudFetch = (url: string, init?: AdepCloudFetchInit) => Promise<AdepCloudFetchResponse>
5195
+
5196
+ /* ---------- \u5B9E\u65F6\u901A\u9053\uFF08CloudRealtime \u955C\u50CF\uFF09 ---------- */
5197
+
5198
+ /** \u4E00\u6761\u901A\u9053\u6D88\u606F\uFF08\u4E0E @adep/types \u7684 RealtimeChannelMessage \u5BF9\u9F50\uFF09\u3002 */
5199
+ interface AdepRealtimeChannelMessage {
5200
+ channel: string
5201
+ seq: number
5202
+ data: unknown
5203
+ publishedAt: string
5204
+ publisher?: string
5516
5205
  }
5517
- var init_dev2 = __esm({
5518
- "packages/cli/src/widget/dev.ts"() {
5519
- "use strict";
5520
- init_build();
5521
- }
5522
- });
5523
5206
 
5524
- // packages/cli/src/widget/publish.ts
5525
- var publish_exports = {};
5526
- __export(publish_exports, {
5527
- publishWidget: () => publishWidget
5528
- });
5529
- import { readFile as readFile12 } from "node:fs/promises";
5530
- import { basename as basename4, join as join16, resolve as resolve14 } from "node:path";
5531
- async function publishWidget(paths, options) {
5532
- const log = options.log ?? ((line) => process.stdout.write(`${line}
5533
- `));
5534
- const client = await createClient(paths);
5535
- const root = resolve14(options.cwd);
5536
- const project2 = await loadWidgetProject(root);
5537
- const framework = options.framework ?? project2.framework;
5538
- let version = "0.1.0";
5539
- try {
5540
- const pkg = JSON.parse(await readFile12(join16(root, "package.json"), "utf8"));
5541
- if (typeof pkg["version"] === "string" && pkg["version"].length > 0) version = pkg["version"];
5542
- } catch {
5543
- version = "0.1.0";
5544
- }
5545
- const name = project2.name === "widget" ? basename4(root) : project2.name;
5546
- log(`[adep] \u6784\u5EFA ${name}\uFF08${framework}\uFF09v${version} \u2026`);
5547
- const built = await buildWidget({ cwd: root, framework });
5548
- const path = `widgets/${name}/${version}/index.js`;
5549
- const form = new FormData();
5550
- form.set("path", path);
5551
- form.set("visibility", "public");
5552
- form.set("file", new Blob([built.text], { type: "text/javascript" }), "index.js");
5553
- await client.upload(`/api/v1/projects/${options.project}/files`, form, "PUBLISH_UPLOAD_FAILED");
5554
- const prefix = encodeURIComponent(`widgets/${name}/${version}/`);
5555
- const listing = await client.request(
5556
- `/api/v1/projects/${options.project}/files?prefix=${prefix}`
5557
- );
5558
- const entry = (listing.files ?? []).find((file) => file.path?.endsWith("index.js"));
5559
- const url = entry?.url;
5560
- if (typeof url !== "string" || url.length === 0) {
5561
- throw new WidgetError("URL_MISSING", "\u4E0A\u4F20\u6210\u529F\u4F46\u65E0\u6CD5\u89E3\u6790\u4EA7\u7269 URL\uFF0C\u8BF7\u68C0\u67E5\u5E73\u53F0\u5B58\u50A8\u914D\u7F6E");
5562
- }
5563
- log(`[adep] \u5DF2\u53D1\u5E03 ${name} v${version}\uFF08hash ${built.hash.slice(0, 8)}\u2026\uFF09`);
5564
- return { name, version, framework, url, hash: built.hash };
5207
+ /** publish \u56DE\u6267\uFF1Adelivered = \u5B9E\u9645\u547D\u4E2D\u7684\u8BA2\u9605\u8FDE\u63A5\u6570\uFF08\u5C3D\u529B\u6295\u9012\uFF0C0 \u662F\u5408\u6CD5\u7ED3\u679C\uFF09\u3002 */
5208
+ interface AdepCloudRealtimeReceipt {
5209
+ delivered: number
5565
5210
  }
5566
- var init_publish = __esm({
5567
- "packages/cli/src/widget/publish.ts"() {
5568
- "use strict";
5569
- init_client();
5570
- init_build();
5571
- init_dev2();
5572
- }
5573
- });
5574
5211
 
5575
- // packages/cli/src/cli.ts
5576
- init_auth();
5577
- init_config();
5578
- import { Command } from "commander";
5579
- import { createRequire } from "node:module";
5212
+ /** subscribe \u56DE\u6267\uFF1Asubscription \u662F\u540E\u7EED receive / unsubscribe \u7684\u53E5\u67C4\u3002 */
5213
+ interface AdepCloudRealtimeSubscription {
5214
+ subscription: string
5215
+ channel: string
5216
+ }
5217
+
5218
+ /**
5219
+ * cloud.realtime\uFF1A\u51FD\u6570\u5185\u6536\u53D1\u5B9E\u65F6\u901A\u9053\u6D88\u606F\u3002
5220
+ * \u26A0\uFE0F subscribe / receive \u662F\u8F6E\u8BE2\u53D6\u4EF6\u800C\u975E\u56DE\u8C03\u8BA2\u9605\uFF08RPC \u53C2\u6570\u8D70\u7ED3\u6784\u5316\u514B\u9686\uFF0C\u4F20\u4E0D\u4E86\u51FD\u6570\uFF09\u3002
5221
+ */
5222
+ interface AdepCloudRealtime {
5223
+ /** except \u4EC5\u7EBF\u4E0A\u652F\u6301\uFF08\u4E0D\u56DE\u53D1\u7ED9\u8BE5\u8FDE\u63A5\uFF09\uFF1B\u672C\u5730 adep dev \u4F20\u7B2C\u4E09\u53C2\u4F1A fail loud\u3002 */
5224
+ publish(channel: string, data: unknown, except?: string): Promise<AdepCloudRealtimeReceipt>
5225
+ subscribe(channel: string): Promise<AdepCloudRealtimeSubscription>
5226
+ receive(subscription: string): Promise<AdepRealtimeChannelMessage[]>
5227
+ unsubscribe(subscription: string): Promise<{ removed: true }>
5228
+ }
5229
+
5230
+ /* ---------- \u80FD\u529B\u6302\u8F7D\u70B9\uFF08Cloud / CapabilityRegistry \u955C\u50CF\uFF09 ---------- */
5231
+
5232
+ /** \u5DF2\u6CE8\u518C\u80FD\u529B\u540D \u2192 \u5B9E\u73B0\u5951\u7EA6\u7684\u6620\u5C04\u3002\u8BBF\u95EE\u672A\u6CE8\u518C\u80FD\u529B\u8FD0\u884C\u65F6\u629B\u5E26\u53EF\u64CD\u4F5C\u63D0\u793A\u7684\u9519\u8BEF\u3002 */
5233
+ interface AdepCapabilityRegistry {
5234
+ db: AdepCloudDb
5235
+ storage: AdepCloudStorage
5236
+ /** \u6C99\u7BB1\u53D7\u63A7\u7F51\u7EDC\uFF08GAME-007\uFF09\uFF1A\u672A\u914D\u7F6E\u767D\u540D\u5355\u65F6\u4E0D\u6CE8\u5165\uFF08\u65E0\u7F51\u7EDC\u5B89\u5168\u9ED8\u8BA4\uFF09\u3002 */
5237
+ fetch: AdepCloudFetch
5238
+ /** \u5B9E\u65F6\u901A\u9053\uFF08FN-020\uFF09\uFF1A\u9879\u76EE\u88C5\u914D realtime \u57DF\u5373\u6CE8\u5165\uFF1B\u8F6E\u8BE2\u8BED\u4E49\u89C1 AdepCloudRealtime\u3002 */
5239
+ realtime: AdepCloudRealtime
5240
+ }
5241
+
5242
+ /** \u7528\u6237\u51FD\u6570\u4FA7\u7684 ctx.cloud\uFF1A\u53EA\u80FD\u8BBF\u95EE\u80FD\u529B\u3002\u5DF2\u77E5\u80FD\u529B\u6709\u7CBE\u786E\u8865\u5168\uFF1B\u81EA\u5B9A\u4E49\u80FD\u529B\u7ECF\u7D22\u5F15\u7B7E\u540D\u8BBF\u95EE\u3002 */
5243
+ type AdepCloud = {
5244
+ readonly [K in keyof AdepCapabilityRegistry]: AdepCapabilityRegistry[K]
5245
+ } & {
5246
+ // \u547D\u540D\u5C5E\u6027\u7ED9\u51FA\u7CBE\u786E\u8865\u5168\uFF1B\u7D22\u5F15\u7B7E\u540D\u653E\u884C\u81EA\u5B9A\u4E49\u80FD\u529B\u8BBF\u95EE\uFF08\u8FD0\u884C\u65F6\u672A\u6CE8\u518C\u5373\u629B\u9519\uFF09\u3002
5247
+ readonly [capability: string]: unknown
5248
+ }
5249
+
5250
+ /* ---------- \u8C03\u7528\u8005\u8EAB\u4EFD\uFF08ExecutorUser \u955C\u50CF\uFF09 ---------- */
5251
+
5252
+ /** \u6267\u884C\u8005\u8EAB\u4EFD\u6295\u5F71\uFF1A\u7F51\u5173\u89E3\u6790\u4F1A\u8BDD\u540E\u6CE8\u5165\uFF1Bnull = \u533F\u540D / \u672A\u6CE8\u5165\uFF08\u900F\u4F20\u4FE1\u606F\uFF0C\u975E\u5F3A\u5236\u95E8\uFF09\u3002 */
5253
+ interface AdepExecutorUser {
5254
+ /** \u5E73\u53F0\u7528\u6237 id\uFF08= better-auth session.user.id\uFF09\u3002 */
5255
+ id: string
5256
+ email?: string
5257
+ name?: string
5258
+ }
5259
+
5260
+ /* ---------- \u5168\u5C40 ctx\uFF08FunctionContext \u955C\u50CF\uFF09 ---------- */
5261
+
5262
+ interface AdepContext {
5263
+ /** \u8BF7\u6C42\u65B9\u6CD5\u3002 */
5264
+ readonly method: AdepHttpMethod
5265
+ /** \u89E6\u53D1\u8DEF\u5F84\uFF08\u4E0D\u542B host\uFF09\uFF0C\u5982 /hello\u3002 */
5266
+ readonly path: string
5267
+ /** \u89E3\u6790\u540E\u7684 query\uFF1B\u540C\u540D\u591A\u503C\u6536\u4E3A\u6570\u7EC4\u3002 */
5268
+ readonly query: Readonly<Record<string, string | readonly string[]>>
5269
+ /** \u8BF7\u6C42\u5934\uFF08\u952E\u4E3A\u5C0F\u5199\uFF09\u3002 */
5270
+ readonly headers: Readonly<Record<string, string>>
5271
+ /** \u8BF7\u6C42\u4F53\uFF1B\u5F62\u72B6\u7531\u7528\u6237\u7528\u7C7B\u578B\u65AD\u8A00\u6536\u7A84\uFF08\u5982 ctx.body as { name: string }\uFF09\u3002 */
5272
+ readonly body: unknown
5273
+ /** multipart \u4E0A\u4F20\u7684\u6587\u4EF6\uFF08\u65E0\u6587\u4EF6\u65F6\u4E3A\u7A7A\u6570\u7EC4\uFF09\u3002 */
5274
+ readonly files: readonly AdepFunctionFile[]
5275
+ /** \u5E73\u53F0\u80FD\u529B\u6302\u8F7D\u70B9\uFF1Acloud.db / cloud.storage / cloud.fetch / cloud.realtime\u3002 */
5276
+ readonly cloud: AdepCloud
5277
+ /** \u8C03\u7528\u8005\u8EAB\u4EFD\u6295\u5F71\uFF1Bnull = \u533F\u540D / \u672A\u6CE8\u5165\u3002 */
5278
+ readonly user: AdepExecutorUser | null
5279
+ }
5280
+
5281
+ /** \u5168\u5C40\u5F00\u53D1\u671F\u4E0A\u4E0B\u6587\uFF08\u7F16\u8F91\u5668\u8865\u5168\u7528\uFF1B\u51FD\u6570\u8FD0\u884C\u671F\u7ECF\u53C2\u6570\u6CE8\u5165\uFF0C\u4E0D\u8BFB\u53D6\u5168\u5C40\uFF09\u3002 */
5282
+ declare const ctx: AdepContext
5283
+ `;
5284
+ var ADEP_TSCONFIG_JSON = `{
5285
+ "compilerOptions": {
5286
+ "target": "ES2021",
5287
+ "module": "ESNext",
5288
+ "moduleResolution": "Bundler",
5289
+ "strict": true,
5290
+ "noEmit": true,
5291
+ "skipLibCheck": true,
5292
+ "types": [],
5293
+ "lib": ["ES2021", "DOM"]
5294
+ },
5295
+ "include": ["**/*.ts", "**/*.d.ts"]
5296
+ }
5297
+ `;
5298
+
5299
+ // shared/sdk/web-project-template.ts
5300
+ function webProjectFiles() {
5301
+ return [
5302
+ {
5303
+ path: "package.json",
5304
+ content: JSON.stringify(
5305
+ {
5306
+ name: "adep-web",
5307
+ version: "0.0.0",
5308
+ type: "module",
5309
+ scripts: { dev: "vite" },
5310
+ dependencies: { vue: "^3.3.4" },
5311
+ devDependencies: {
5312
+ vite: "^4.4.0",
5313
+ "@vitejs/plugin-vue": "^4.3.0",
5314
+ // vite 内部动态 import('esbuild-wasm'),必须在 package.json 显式声明才能被 Nodebox 解析
5315
+ "esbuild-wasm": "0.18.20"
5316
+ }
5317
+ },
5318
+ null,
5319
+ 2
5320
+ )
5321
+ },
5322
+ {
5323
+ path: "index.html",
5324
+ content: [
5325
+ `<!doctype html>`,
5326
+ `<html lang="zh-CN">`,
5327
+ `<head>`,
5328
+ ` <meta charset="utf-8" />`,
5329
+ ` <meta name="viewport" content="width=device-width, initial-scale=1" />`,
5330
+ ` <title>adep web</title>`,
5331
+ `</head>`,
5332
+ `<body>`,
5333
+ ` <div id="app"></div>`,
5334
+ ` <script type="module" src="/src/main.ts"></script>`,
5335
+ `</body>`,
5336
+ `</html>`,
5337
+ ``
5338
+ ].join("\n")
5339
+ },
5340
+ {
5341
+ path: "vite.config.ts",
5342
+ content: [
5343
+ `// web/vite.config.ts \u2014\u2014 \u6807\u51C6 Vite \u914D\u7F6E\uFF08Vue 3 \u63D2\u4EF6\uFF09\u3002`,
5344
+ `import { defineConfig } from 'vite'`,
5345
+ `import vue from '@vitejs/plugin-vue'`,
5346
+ ``,
5347
+ `export default defineConfig({`,
5348
+ ` plugins: [vue()],`,
5349
+ `})`,
5350
+ ``
5351
+ ].join("\n")
5352
+ },
5353
+ {
5354
+ path: "src/main.ts",
5355
+ content: [
5356
+ `// web/src/main.ts \u2014\u2014 \u5E94\u7528\u5165\u53E3\uFF08Vue 3 + Vite\uFF09\u3002`,
5357
+ `// \u5F00\u53D1\uFF1A\u5E95\u90E8\u300C\u6D4F\u89C8\u5668\u7EC8\u7AEF\u300D\u8FD0\u884C npm run dev\uFF08\u6216\u7B49 Nodebox \u81EA\u52A8\u62C9\u8D77\uFF09\uFF0C\u4FDD\u5B58\u540E\u9884\u89C8 HMR \u5237\u65B0\u3002`,
5358
+ `import { createApp } from 'vue'`,
5359
+ `import App from './App.vue'`,
5360
+ ``,
5361
+ `createApp(App).mount('#app')`,
5362
+ ``
5363
+ ].join("\n")
5364
+ },
5365
+ {
5366
+ path: "src/App.vue",
5367
+ content: [
5368
+ `<script setup lang="ts">`,
5369
+ `import { ref } from 'vue'`,
5370
+ ``,
5371
+ `const title = ref('adep web')`,
5372
+ `const clicks = ref(0)`,
5373
+ `</script>`,
5374
+ ``,
5375
+ `<template>`,
5376
+ ` <main>`,
5377
+ ` <h1>{{ title }}</h1>`,
5378
+ ` <p>\u5728 web/src/App.vue \u91CC\u7F16\u8F91\uFF0C\u4FDD\u5B58\u540E\u9884\u89C8\u81EA\u52A8\u5237\u65B0\uFF08HMR\uFF09\u3002</p>`,
5379
+ ` <button @click="clicks++">clicks: {{ clicks }}</button>`,
5380
+ ` </main>`,
5381
+ `</template>`,
5382
+ ``,
5383
+ `<style scoped>`,
5384
+ `main {`,
5385
+ ` margin: 24px;`,
5386
+ ` font-family: system-ui, -apple-system, sans-serif;`,
5387
+ `}`,
5388
+ `button {`,
5389
+ ` padding: 6px 14px;`,
5390
+ ` border: 1px solid #6366f1;`,
5391
+ ` border-radius: 6px;`,
5392
+ ` background: #eef2ff;`,
5393
+ ` cursor: pointer;`,
5394
+ `}`,
5395
+ `</style>`,
5396
+ ``
5397
+ ].join("\n")
5398
+ }
5399
+ ];
5400
+ }
5580
5401
 
5581
5402
  // packages/cli/src/init.ts
5582
- import { mkdir as mkdir2, stat as stat2, writeFile } from "node:fs/promises";
5583
- import { dirname as dirname2, join, resolve } from "node:path";
5403
+ var TEMPLATE_NAMES = ["empty", "function", "fullstack"];
5584
5404
  var InitError = class extends Error {
5585
5405
  constructor(code, message) {
5586
5406
  super(message);
@@ -5596,23 +5416,58 @@ export default {
5596
5416
  `;
5597
5417
  var README = (name, template) => `# ${name}
5598
5418
 
5599
- AgentDeploy \u9879\u76EE\uFF08\u6A21\u677F\uFF1A${template}\uFF09\u3002
5419
+ AgentDeploy \u5168\u6808\u9879\u76EE\uFF08\u6A21\u677F\uFF1A${template}\uFF09\u3002
5600
5420
 
5601
- - \`adep dev\`\uFF1A\u672C\u5730\u8C03\u8BD5\uFF08CLI-002 \u4EA4\u4ED8\uFF09
5602
- - \`adep deploy\`\uFF1A\u53D1\u5E03\uFF08CLI-003 \u4EA4\u4ED8\uFF09
5421
+ ## \u5E38\u7528\u547D\u4EE4
5422
+
5423
+ - \`adep dev\`\uFF1A\u672C\u5730\u8C03\u8BD5\uFF08\u76D1\u542C functions/\uFF0C\u652F\u6301\u70ED\u91CD\u8F7D\uFF0C\u9ED8\u8BA4 http://127.0.0.1:8787/<fnName>\uFF09
5424
+ - \`adep deploy\`\uFF1A\u589E\u91CF\u90E8\u7F72\uFF08\u5BF9\u6BD4\u8FDC\u7AEF\u54C8\u5E0C \u2192 \u4EC5\u4E0A\u4F20\u53D8\u66F4 \u2192 \u53D1\u5E03 \u2192 \u8F93\u51FA\u8BBF\u95EE\u57DF\u540D\uFF09
5425
+ - \`adep serve\`\uFF1A\u5F00\u53D1\u6001\u670D\u52A1\u5668\uFF08\u51FD\u6570 /api/{fn} + /healthz + \u9759\u6001\u6258\u7BA1 + \u524D\u7AEF\u9884\u89C8\uFF09
5426
+
5427
+ ## \u76EE\u5F55\u7ED3\u6784
5428
+
5429
+ - \`adep.config.ts\`\uFF1A\u9879\u76EE\u6807\u8BC6\uFF08dev / deploy \u6309\u6B64\u8BC6\u522B\uFF09
5430
+ - \`functions/\`\uFF1A\u4E91\u51FD\u6570\u76EE\u5F55\uFF08\u6BCF\u4E2A\u6587\u4EF6 = \u4E00\u4E2A\u51FD\u6570\uFF0C\u9ED8\u8BA4\u5BFC\u51FA \`(ctx: AdepContext) => Response\`\uFF09
5431
+ - \`web/\`\uFF1A\u524D\u7AEF\u5DE5\u7A0B\uFF08\u6807\u51C6 Vite + Vue 3\uFF1B\u4E0E Web IDE \u9879\u76EE\u540C\u6784\uFF0C\u53EF\u6574\u76EE\u5F55\u5BFC\u51FA\u4E8C\u6B21\u5F00\u53D1\uFF09
5432
+ - \`database/schema.sql\`\uFF1A\u6570\u636E\u5E93\u7ED3\u6784\uFF08\u8868\u7531\u5E73\u53F0\u63A7\u5236\u53F0 / \`adep db\` \u7BA1\u7406\uFF0C\u6B64\u5904\u4E3A\u7ED3\u6784\u8BB0\u5F55\uFF09
5433
+ - \`tsconfig.json\`\uFF1A\u4E91\u51FD\u6570 TypeScript \u7F16\u8F91\u5668\u914D\u7F6E\uFF08strict + noEmit\uFF09
5434
+ - \`adep.d.ts\`\uFF1A\u4E91\u51FD\u6570\u4E0A\u4E0B\u6587\u73AF\u5883\u7C7B\u578B\u58F0\u660E\uFF08\`ctx: AdepContext\` \u8865\u5168\uFF0C\u65E0\u9700\u88C5\u4F9D\u8D56\uFF09
5435
+
5436
+ ## \u4E91\u51FD\u6570\u7C7B\u578B\u63D0\u793A
5437
+
5438
+ \u7528 VSCode \u6253\u5F00\u672C\u76EE\u5F55\uFF0C\u4EFB\u610F \`functions/**\` \u4E0B\u7684 TS \u6587\u4EF6\u5373\u53EF\u83B7\u5F97 \`AdepContext\` / \`ctx.cloud.*\` \u8865\u5168\uFF1A
5439
+ \`tsconfig.json\` \u4F1A\u628A \`adep.d.ts\` \u7EB3\u5165 include\uFF0C\u51FD\u6570\u53C2\u6570\u5199 \`ctx: AdepContext\` \u5373\u53EF\u3002
5440
+ \`ctx\` \u4E0E \`AdepContext\` \u662F\u5168\u5C40\u5F00\u53D1\u671F\u58F0\u660E\uFF0C\u51FD\u6570\u8FD0\u884C\u671F\u7ECF\u53C2\u6570\u6CE8\u5165\uFF08\u4E0D\u8BFB\u53D6\u5168\u5C40\uFF09\u3002
5441
+
5442
+ ## \u6A21\u677F\u8BF4\u660E\uFF08adep init\uFF09
5443
+
5444
+ - \`adep init <name>\`\uFF1A\u9ED8\u8BA4 \`fullstack\` \u6A21\u677F\uFF08functions/ + web/ \u524D\u7AEF\u5DE5\u7A0B + database/\uFF0C\u4E0E Web IDE \u9879\u76EE\u540C\u6784\uFF09
5445
+ - \`adep init <name> -t function\`\uFF1A\u4EC5\u4E91\u51FD\u6570\uFF08\u5355\u4E2A\u793A\u4F8B\u51FD\u6570\uFF09
5446
+ - \`adep init <name> -t empty\`\uFF1A\u7A7A\u6A21\u677F\uFF08\u4EC5\u9879\u76EE\u9AA8\u67B6\uFF09
5447
+ - \`adep init --list\`\uFF1A\u4ECE\u5E73\u53F0 /api/v1/templates \u5217\u51FA\u53EF\u7528\u6A21\u677F
5448
+ - \`adep init --list -s <server>\`\uFF1A\u6307\u5B9A\u5E73\u53F0\u5730\u5740
5449
+
5450
+ ## \u524D\u7AEF\u5DE5\u7A0B\uFF08web/\uFF09
5451
+
5452
+ \`web/\` \u662F\u6807\u51C6 Vite + Vue 3 \u5DE5\u7A0B\uFF0C\u4E0E Web IDE \u5185\u521B\u5EFA\u7684\u9879\u76EE\u5B8C\u5168\u540C\u6784\uFF1A
5453
+ \`index.html\` / \`package.json\` / \`vite.config.ts\` / \`src/main.ts\` / \`src/App.vue\`\u3002
5454
+ \u672C\u5730\u5F00\u53D1\uFF1A\`cd web && npm install && npm run dev\`\uFF1B\u90E8\u7F72\u7531 \`adep deploy\` \u7EDF\u4E00\u6784\u5EFA\u53D1\u5E03\u3002
5603
5455
  `;
5604
5456
  var HELLO_FUNCTION = `// \u793A\u4F8B\u51FD\u6570\uFF1Aadep deploy \u540E\u7ECF https://<project-slug>.<platform-domain>/hello \u89E6\u53D1\u3002
5605
- // \u7528\u6237\u51FD\u6570\u5373 functions/ \u4E0B\u7684\u72EC\u7ACB\u6587\u4EF6\uFF0C\u9ED8\u8BA4\u5BFC\u51FA (ctx) => Response \u5F62\u72B6\u7684\u5904\u7406\u5668
5606
- //\uFF08ctx \u5951\u7EA6\u89C1\u5E73\u53F0\u7684 FunctionContext\uFF1Amethod / path / query / headers / body / cloud.*\uFF09\u3002
5607
- export default async (ctx) => {
5457
+ // \u7528\u6237\u51FD\u6570\u5373 functions/ \u4E0B\u7684\u72EC\u7ACB\u6587\u4EF6\uFF0C\u9ED8\u8BA4\u5BFC\u51FA (ctx: AdepContext) => Response \u5F62\u72B6\u7684\u5904\u7406\u5668
5458
+ //\uFF08ctx \u5951\u7EA6\u89C1 adep.d.ts\uFF1Amethod / path / query / headers / body / files / user / cloud.*\uFF09\u3002
5459
+ export default async (ctx: AdepContext) => {
5608
5460
  const name = (ctx.query['name'] as string | undefined) ?? 'world'
5609
5461
  return { message: \`hello \${name}\` }
5610
5462
  }
5611
5463
  `;
5612
5464
  var FUNCTION_INDEX = `// \u51FD\u6570\u6A21\u5757\u5165\u53E3\uFF1A\u9879\u76EE\u91CC\u7684\u6BCF\u4E2A\u51FD\u6570\u662F functions/ \u4E0B\u7684\u72EC\u7ACB\u6587\u4EF6\uFF0C
5613
- // \u9ED8\u8BA4\u5BFC\u51FA (ctx) => Response \u5F62\u72B6\u7684\u5904\u7406\u5668\uFF08\u5951\u7EA6\u89C1 @adep/types \u7684 FunctionContext\uFF09\u3002
5465
+ // \u9ED8\u8BA4\u5BFC\u51FA (ctx: AdepContext) => Response \u5F62\u72B6\u7684\u5904\u7406\u5668\uFF08\u5951\u7EA6\u89C1 adep.d.ts\uFF09\u3002
5466
+ `;
5467
+ var EMPTY_INDEX = `// AgentDeploy \u9879\u76EE\u5165\u53E3\u3002\u6A21\u677F\u6682\u65E0\u66F4\u591A\u5185\u5BB9\u2014\u2014\u51FD\u6570\u653E functions/\uFF0C\u524D\u7AEF\u653E web/\uFF0C\u914D\u7F6E\u89C1 adep.config.ts\u3002
5614
5468
  `;
5615
- var EMPTY_INDEX = `// AgentDeploy \u9879\u76EE\u5165\u53E3\u3002M1 \u4E2D\u6A21\u677F\u6682\u65E0\u66F4\u591A\u5185\u5BB9\u2014\u2014\u51FD\u6570\u653E functions/\uFF0C\u914D\u7F6E\u89C1 adep.config.ts\u3002
5469
+ var SCHEMA_SQL = `-- AgentDeploy \u9879\u76EE\u6570\u636E\u5E93\u7ED3\u6784\uFF08\u5360\u4F4D\uFF09\u3002
5470
+ -- \u8868\u7ED3\u6784\u8BF7\u5728\u5E73\u53F0\u63A7\u5236\u53F0\u300C\u6570\u636E\u5E93\u300D\u6216\u672C\u5730 \`adep db\` \u4E2D\u521B\u5EFA\u540E\u56DE\u586B\uFF0C\u4FDD\u6301\u4E0E\u7EBF\u4E0A schema \u4E00\u81F4\u3002
5616
5471
  `;
5617
5472
  async function initProject(cwd, name, template) {
5618
5473
  if (!/^[a-z][a-z0-9-]{0,62}$/.test(name)) {
@@ -5621,6 +5476,12 @@ async function initProject(cwd, name, template) {
5621
5476
  `\u9879\u76EE\u540D "${name}" \u4E0D\u5408\u6CD5\uFF1A\u9700\u4EE5\u5C0F\u5199\u5B57\u6BCD\u5F00\u5934\uFF0C\u4EC5\u542B\u5C0F\u5199\u5B57\u6BCD / \u6570\u5B57 / \u8FDE\u5B57\u7B26`
5622
5477
  );
5623
5478
  }
5479
+ if (!TEMPLATE_NAMES.includes(template)) {
5480
+ throw new InitError(
5481
+ "INVALID_TEMPLATE",
5482
+ `\u672A\u77E5\u6A21\u677F "${template}"\uFF1A\u53EF\u9009 ${TEMPLATE_NAMES.join(" | ")}`
5483
+ );
5484
+ }
5624
5485
  const projectPath = resolve(cwd, name);
5625
5486
  let existing;
5626
5487
  try {
@@ -5633,14 +5494,23 @@ async function initProject(cwd, name, template) {
5633
5494
  }
5634
5495
  const files = [
5635
5496
  { path: "adep.config.ts", content: ADEP_CONFIG(name, template) },
5636
- { path: "README.md", content: README(name, template) }
5497
+ // 云函数 TypeScript 类型提示:tsconfig 把 adep.d.ts 纳入 include,写 ctx: AdepContext 即有补全。
5498
+ { path: "tsconfig.json", content: ADEP_TSCONFIG_JSON },
5499
+ { path: "adep.d.ts", content: ADEP_ENV_DTS },
5500
+ { path: "README.md", content: README(name, template) },
5501
+ { path: ".gitignore", content: "node_modules/\ndata/\n.adep/\nweb/node_modules/\n" }
5637
5502
  ];
5638
5503
  if (template === "function") {
5639
5504
  files.push({ path: "functions/hello.ts", content: HELLO_FUNCTION });
5640
5505
  files.push({ path: "functions/README.md", content: FUNCTION_INDEX });
5641
- files.push({ path: ".gitignore", content: "node_modules/\ndata/\n.adep/\n" });
5506
+ } else if (template === "fullstack") {
5507
+ files.push({ path: "functions/hello.ts", content: HELLO_FUNCTION });
5508
+ files.push({ path: "functions/README.md", content: FUNCTION_INDEX });
5509
+ files.push({ path: "database/schema.sql", content: SCHEMA_SQL });
5510
+ for (const file of webProjectFiles()) {
5511
+ files.push({ path: `web/${file.path}`, content: file.content });
5512
+ }
5642
5513
  } else {
5643
- files.push({ path: ".gitignore", content: "node_modules/\ndata/\n.adep/\n" });
5644
5514
  files.push({ path: "README-EMPTY.md", content: EMPTY_INDEX });
5645
5515
  }
5646
5516
  await mkdir2(projectPath, { recursive: true });
@@ -5654,62 +5524,56 @@ async function initProject(cwd, name, template) {
5654
5524
  return { projectPath, files: files.map((file) => file.path) };
5655
5525
  }
5656
5526
 
5657
- // packages/cli/src/templates.ts
5658
- init_auth();
5659
- async function fetchTemplates(server) {
5660
- let response;
5661
- try {
5662
- response = await fetch(`${server}/api/v1/templates`);
5663
- } catch (error) {
5664
- throw new CliError(
5665
- "SERVER_UNREACHABLE",
5666
- `\u65E0\u6CD5\u8FDE\u63A5\u5E73\u53F0 ${server}\uFF1A${error instanceof Error ? error.message : String(error)}`
5667
- );
5668
- }
5669
- const text = await response.text();
5670
- let parsed = null;
5671
- try {
5672
- parsed = text.length === 0 ? null : JSON.parse(text);
5673
- } catch {
5674
- parsed = null;
5675
- }
5676
- if (response.status < 200 || response.status >= 300) {
5677
- const msg = parsed?.error;
5678
- throw new CliError("TEMPLATE_LIST_FAILED", msg ?? `\u5E73\u53F0\u8FD4\u56DE HTTP ${response.status}`);
5679
- }
5680
- const templates = parsed?.templates;
5681
- return templates ?? [];
5527
+ // packages/cli/src/output.ts
5528
+ function isCommandError(error) {
5529
+ return error instanceof CliError || error instanceof InitError;
5682
5530
  }
5683
-
5684
- // packages/cli/src/cli.ts
5685
- init_build();
5686
- init_init();
5687
- var requireJson = createRequire(import.meta.url);
5688
- var APP_VERSION = requireJson("../package.json").version;
5689
5531
  function needsRelogin(error) {
5690
5532
  return error.code === "NOT_LOGGED_IN" || error.code === "AUTH_UNAUTHORIZED";
5691
5533
  }
5692
- function emitError(output, command, json, error) {
5693
- if (error instanceof CliError || error instanceof InitError || error instanceof WidgetError || error instanceof WidgetInitError) {
5534
+ function toLines(value) {
5535
+ return Array.isArray(value) ? value : [value];
5536
+ }
5537
+ function createCommandIO(command, output, json) {
5538
+ const ok = (data, render) => {
5539
+ if (json) {
5540
+ output(JSON.stringify({ ok: true, command, data }));
5541
+ return;
5542
+ }
5543
+ if (render !== void 0) for (const lineValue of toLines(render(data))) output(lineValue);
5544
+ };
5545
+ const line = (text) => {
5546
+ if (!json) output(text);
5547
+ };
5548
+ const raw = (text) => {
5549
+ output(text);
5550
+ };
5551
+ const fail = (code, message) => {
5552
+ if (json) output(JSON.stringify({ ok: false, command, error: { code, message } }));
5553
+ else output(`\u9519\u8BEF\uFF1A${message}`);
5554
+ process.exitCode = 1;
5555
+ };
5556
+ const err = (error) => {
5557
+ if (!isCommandError(error)) throw error;
5694
5558
  if (json) {
5695
5559
  output(
5696
- JSON.stringify({
5697
- ok: false,
5698
- command,
5699
- error: { code: error.code, message: error.message }
5700
- })
5560
+ JSON.stringify({ ok: false, command, error: { code: error.code, message: error.message } })
5701
5561
  );
5702
5562
  } else {
5703
5563
  const withCode = error.message.includes(error.code) || error.code.length === 0 ? error.message : `${error.message}\uFF08${error.code}\uFF09`;
5704
5564
  output(`\u9519\u8BEF\uFF1A${withCode}`);
5705
- if (error instanceof CliError && needsRelogin(error)) {
5706
- output("\u63D0\u793A\uFF1A\u5148\u6267\u884C adep login");
5707
- }
5565
+ if (error instanceof CliError && needsRelogin(error)) output("\u63D0\u793A\uFF1A\u5148\u6267\u884C adep login");
5708
5566
  }
5709
5567
  process.exitCode = 1;
5710
- return;
5711
- }
5712
- throw error;
5568
+ };
5569
+ const run = async (fn) => {
5570
+ try {
5571
+ await fn();
5572
+ } catch (error) {
5573
+ err(error);
5574
+ }
5575
+ };
5576
+ return { json, ok, line, raw, fail, err, run };
5713
5577
  }
5714
5578
  function formatBytes(bytes) {
5715
5579
  if (bytes < 1024) return `${bytes} B`;
@@ -5730,69 +5594,35 @@ function formatTable(columns, rows) {
5730
5594
  widths[index] = Math.max(widths[index], cell.length);
5731
5595
  });
5732
5596
  }
5733
- const line = (cells) => cells.map((cell, index) => cell.padEnd(widths[index] ?? 0)).join(" ").trimEnd();
5597
+ const contentLine = (cells) => cells.map((cell, index) => cell.padEnd(widths[index] ?? 0)).join(" ").trimEnd();
5734
5598
  const parts = [
5735
- line(columns),
5736
- ...rows.map((row) => line(columns.map((c) => String(row[c] ?? ""))))
5599
+ contentLine(columns),
5600
+ ...rows.map((row) => contentLine(columns.map((c) => String(row[c] ?? ""))))
5737
5601
  ];
5738
5602
  return parts.join("\n");
5739
5603
  }
5740
- function parseBool(raw) {
5741
- if (raw === void 0) return void 0;
5742
- if (raw === "true") return true;
5743
- if (raw === "false") return false;
5744
- throw new CliError("INVALID_BOOLEAN", `\u5E03\u5C14\u53C2\u6570\u987B\u4E3A true \u6216 false\uFF0C\u6536\u5230 "${raw}"`);
5745
- }
5746
5604
  function formatSeconds(seconds) {
5747
5605
  return `${Math.max(0.1, Math.round(seconds * 10) / 10)}s`;
5748
5606
  }
5749
- async function runDeploy(paths, output, json, cwd, slug, dir) {
5750
- const { deploy: deploy2 } = await Promise.resolve().then(() => (init_deploy(), deploy_exports));
5751
- const startedAt = Date.now();
5752
- const result = await deploy2(paths, {
5607
+
5608
+ // packages/cli/src/commands/context.ts
5609
+ function createCliContext(deps) {
5610
+ const { output, paths, cwd, json } = deps;
5611
+ return {
5612
+ output,
5613
+ paths,
5753
5614
  cwd,
5754
- ...slug === void 0 ? {} : { slug },
5755
- ...dir === void 0 ? {} : { functionsDir: dir },
5756
- // --json 下逐函数进度会破坏「stdout 恰好一个 JSON 对象」的信封约定(PRD §2.5.3)。
5757
- silent: json,
5758
- // 人读模式的进度也走注入的 output:deploy 内部缺省会直写 process.stdout,
5759
- // 那会让带 sink 的调用方漏收这部分行。
5760
- log: (line) => output(line)
5761
- });
5762
- const elapsedSeconds = (Date.now() - startedAt) / 1e3;
5763
- const deployedCount = result.functions.filter((fn) => fn.action !== "none").length;
5764
- if (json) {
5765
- output(
5766
- JSON.stringify({
5767
- ok: true,
5768
- command: "deploy",
5769
- data: { ...result, elapsedSeconds, deployedCount }
5770
- })
5771
- );
5772
- return;
5773
- }
5774
- for (const fn of result.functions) {
5775
- output(`${fn.name} v${fn.version} ${fn.url}`);
5776
- }
5777
- if (result.noChanges) {
5778
- output(
5779
- `\u2713 no changes \xB7 ${result.functions.length} functions up to date in ${formatSeconds(elapsedSeconds)}`
5780
- );
5781
- return;
5782
- }
5783
- output(`\u2713 ${deployedCount} functions deployed in ${formatSeconds(elapsedSeconds)}`);
5615
+ io: (command) => createCommandIO(command, output, json())
5616
+ };
5784
5617
  }
5785
- function buildProgram(options = {}) {
5786
- const output = options.output ?? ((line) => process.stdout.write(`${line}
5787
- `));
5788
- const paths = options.paths ?? resolvePaths();
5789
- const cwd = options.cwd ?? process.cwd();
5790
- const program2 = new Command();
5791
- program2.name("adep").description("AgentDeploy CLI").version(APP_VERSION);
5792
- program2.option("--json", "\u4EE5\u673A\u5668\u53EF\u8BFB JSON \u8F93\u51FA\uFF08Agent / \u811A\u672C\u8C03\u7528\uFF09", false);
5793
- const jsonMode = () => program2.opts()["json"] === true;
5618
+
5619
+ // packages/cli/src/commands/auth.ts
5620
+ init_auth();
5621
+ init_config();
5622
+ function registerAuth(program2, ctx) {
5794
5623
  program2.command("login").description("\u767B\u5F55\u5E73\u53F0\uFF08better-auth \u90AE\u7BB1\u5BC6\u7801\u767B\u5F55\uFF1B\u8BBE\u5907\u6388\u6743\u6D41\u5F52 CORE \u57DF\u540E\u7EED\u4EFB\u52A1\uFF09").option("-s, --server <url>", "\u5E73\u53F0\u5730\u5740\uFF08\u7F3A\u7701\u8BFB\u53D6 ADEP_SERVER \u6216 http://localhost:3000\uFF09").option("-e, --email <email>", "\u767B\u5F55\u90AE\u7BB1").option("-p, --password <password>", "\u767B\u5F55\u5BC6\u7801\uFF08\u6CE8\u610F shell \u5386\u53F2\uFF1B\u7F3A\u7701\u4EA4\u4E92\u8F93\u5165\uFF09").action(async (flags) => {
5795
- try {
5624
+ const command = ctx.io("login");
5625
+ await command.run(async () => {
5796
5626
  const server = flags.server ?? resolveServer();
5797
5627
  let email = flags.email;
5798
5628
  let password = flags.password;
@@ -5803,89 +5633,113 @@ function buildProgram(options = {}) {
5803
5633
  password = password ?? await prompt.askHidden("\u5BC6\u7801\uFF1A");
5804
5634
  prompt.close();
5805
5635
  }
5806
- const result = await login(paths, {
5636
+ const result = await login(ctx.paths, {
5807
5637
  server,
5808
5638
  email,
5809
5639
  password
5810
5640
  });
5811
- if (jsonMode()) {
5812
- output(JSON.stringify({ ok: true, command: "login", data: result }));
5813
- } else {
5814
- output(`\u5DF2\u767B\u5F55\uFF1A${result.email}\uFF08\u51ED\u636E\u5DF2\u5199\u5165 ${paths.credentialsFile}\uFF0C\u6743\u9650 0600\uFF09`);
5815
- }
5816
- } catch (error) {
5817
- emitError(output, "login", jsonMode(), error);
5818
- }
5641
+ command.ok(result, (data) => {
5642
+ const d = data;
5643
+ return `\u5DF2\u767B\u5F55\uFF1A${d.email}\uFF08\u51ED\u636E\u5DF2\u5199\u5165 ${ctx.paths.credentialsFile}\uFF0C\u6743\u9650 0600\uFF09`;
5644
+ });
5645
+ });
5819
5646
  });
5820
5647
  program2.command("whoami").description("\u663E\u793A\u5F53\u524D\u767B\u5F55\u8EAB\u4EFD").action(async () => {
5821
- try {
5822
- const result = await whoami(paths);
5823
- if (jsonMode()) {
5824
- output(JSON.stringify({ ok: true, command: "whoami", data: result }));
5825
- } else {
5826
- output(`${result.email} @ ${result.server}`);
5827
- }
5828
- } catch (error) {
5829
- emitError(output, "whoami", jsonMode(), error);
5830
- }
5648
+ const command = ctx.io("whoami");
5649
+ await command.run(async () => {
5650
+ const result = await whoami(ctx.paths);
5651
+ command.ok(result, (data) => {
5652
+ const d = data;
5653
+ return `${d.email} @ ${d.server}`;
5654
+ });
5655
+ });
5831
5656
  });
5832
5657
  program2.command("logout").description("\u767B\u51FA\u5E76\u6E05\u9664\u672C\u5730\u51ED\u636E").action(async () => {
5833
- try {
5834
- await logout(paths);
5835
- if (jsonMode()) {
5836
- output(JSON.stringify({ ok: true, command: "logout", data: { done: true } }));
5837
- } else {
5838
- output("\u5DF2\u767B\u51FA");
5839
- }
5840
- } catch (error) {
5841
- emitError(output, "logout", jsonMode(), error);
5842
- }
5658
+ const command = ctx.io("logout");
5659
+ await command.run(async () => {
5660
+ await logout(ctx.paths);
5661
+ command.ok({ done: true }, () => "\u5DF2\u767B\u51FA");
5662
+ });
5843
5663
  });
5844
- program2.command("init").description("\u521D\u59CB\u5316\u9879\u76EE\uFF08\u6A21\u677F\uFF1Aempty / function\uFF09\uFF0C\u6216 --list \u4ECE\u5E73\u53F0\u53D6\u6A21\u677F\u6E05\u5355").argument("[name]", "\u9879\u76EE\u76EE\u5F55\u540D\uFF08\u914D\u5408 --list \u65F6\u53EF\u7701\u7565\uFF09").option("-t, --template <template>", "\u6A21\u677F\uFF1Aempty | function", "function").option("-l, --list", "\u4ECE\u5E73\u53F0 /api/v1/templates \u5217\u51FA\u53EF\u7528\u6A21\u677F\uFF08\u4E0D\u811A\u624B\u67B6\uFF09", false).option(
5664
+ }
5665
+
5666
+ // packages/cli/src/commands/init.ts
5667
+ init_config();
5668
+
5669
+ // packages/cli/src/templates.ts
5670
+ init_auth();
5671
+ async function fetchTemplates(server) {
5672
+ let response;
5673
+ try {
5674
+ response = await fetch(`${server}/api/v1/templates`);
5675
+ } catch (error) {
5676
+ throw new CliError(
5677
+ "SERVER_UNREACHABLE",
5678
+ `\u65E0\u6CD5\u8FDE\u63A5\u5E73\u53F0 ${server}\uFF1A${error instanceof Error ? error.message : String(error)}`
5679
+ );
5680
+ }
5681
+ const text = await response.text();
5682
+ let parsed = null;
5683
+ try {
5684
+ parsed = text.length === 0 ? null : JSON.parse(text);
5685
+ } catch {
5686
+ parsed = null;
5687
+ }
5688
+ if (response.status < 200 || response.status >= 300) {
5689
+ const msg = parsed?.error;
5690
+ throw new CliError("TEMPLATE_LIST_FAILED", msg ?? `\u5E73\u53F0\u8FD4\u56DE HTTP ${response.status}`);
5691
+ }
5692
+ const templates = parsed?.templates;
5693
+ return templates ?? [];
5694
+ }
5695
+
5696
+ // packages/cli/src/commands/init.ts
5697
+ function registerInit(program2, ctx) {
5698
+ program2.command("init").description("\u521D\u59CB\u5316\u9879\u76EE\uFF08\u6A21\u677F\uFF1Aempty / function / fullstack\uFF09\uFF0C\u6216 --list \u4ECE\u5E73\u53F0\u53D6\u6A21\u677F\u6E05\u5355").argument("[name]", "\u9879\u76EE\u76EE\u5F55\u540D\uFF08\u914D\u5408 --list \u65F6\u53EF\u7701\u7565\uFF09").option("-t, --template <template>", "\u6A21\u677F\uFF1Aempty | function | fullstack", "fullstack").option("-l, --list", "\u4ECE\u5E73\u53F0 /api/v1/templates \u5217\u51FA\u53EF\u7528\u6A21\u677F\uFF08\u4E0D\u811A\u624B\u67B6\uFF09", false).option(
5845
5699
  "-s, --server <url>",
5846
5700
  "\u5E73\u53F0\u5730\u5740\uFF08--list \u7528\uFF1B\u7F3A\u7701\u8BFB ADEP_SERVER \u6216 http://localhost:3000\uFF09"
5847
5701
  ).action(
5848
5702
  async (name, flags) => {
5849
- try {
5703
+ const command = ctx.io("init");
5704
+ await command.run(async () => {
5850
5705
  if (flags.list === true) {
5851
5706
  const server = flags.server ?? resolveServer();
5852
5707
  const templates = await fetchTemplates(server);
5853
- if (jsonMode()) {
5854
- output(JSON.stringify({ ok: true, command: "init", data: { templates } }));
5855
- } else {
5856
- for (const tpl of templates) {
5857
- output(`${tpl.code} ${tpl.name} ${tpl.description ?? ""}`);
5858
- }
5859
- }
5708
+ command.ok(
5709
+ { templates },
5710
+ (data) => data.templates.map(
5711
+ (tpl) => `${tpl.code} ${tpl.name} ${tpl.description ?? ""}`
5712
+ )
5713
+ );
5860
5714
  return;
5861
5715
  }
5862
5716
  if (name === void 0) {
5863
5717
  throw new InitError("MISSING_NAME", "\u9700\u7ED9\u51FA\u9879\u76EE\u540D\uFF0C\u6216\u4F7F\u7528 --list \u5217\u51FA\u5E73\u53F0\u53EF\u7528\u6A21\u677F");
5864
5718
  }
5865
5719
  const template = flags.template;
5866
- if (!["empty", "function"].includes(template)) {
5867
- throw new InitError("INVALID_TEMPLATE", `\u672A\u77E5\u6A21\u677F "${template}"\uFF1A\u53EF\u9009 empty | function`);
5868
- }
5869
- const result = await initProject(cwd, name, template);
5870
- if (jsonMode()) {
5871
- output(JSON.stringify({ ok: true, command: "init", data: result }));
5872
- } else {
5873
- output(`\u5DF2\u521B\u5EFA ${result.projectPath}`);
5720
+ if (!TEMPLATE_NAMES.includes(template)) {
5721
+ throw new InitError(
5722
+ "INVALID_TEMPLATE",
5723
+ `\u672A\u77E5\u6A21\u677F "${template}"\uFF1A\u53EF\u9009 ${TEMPLATE_NAMES.join(" | ")}`
5724
+ );
5874
5725
  }
5875
- } catch (error) {
5876
- emitError(output, "init", jsonMode(), error);
5877
- }
5726
+ const result = await initProject(ctx.cwd, name, template);
5727
+ command.ok(result, (data) => `\u5DF2\u521B\u5EFA ${data.projectPath}`);
5728
+ });
5878
5729
  }
5879
5730
  );
5731
+ }
5732
+
5733
+ // packages/cli/src/commands/dev.ts
5734
+ function registerDevServers(program2, ctx) {
5880
5735
  program2.command("dev").description("\u672C\u5730\u8C03\u8BD5\uFF1A\u76D1\u542C functions/ \u70ED\u91CD\u8F7D\uFF0Chttp://localhost:<port>/<fnName>").option("-p, --port <port>", "\u76D1\u542C\u7AEF\u53E3\uFF08\u7F3A\u7701 8787\uFF09", "8787").action(async (flags) => {
5881
- try {
5736
+ const command = ctx.io("dev");
5737
+ await command.run(async () => {
5882
5738
  const { startDevServer: startDevServer2 } = await Promise.resolve().then(() => (init_dev(), dev_exports));
5883
- const started = await startDevServer2({ cwd, port: Number(flags.port ?? "8787") });
5884
- output(`[adep] dev server listening on ${started.baseUrl}\uFF08Ctrl-C \u9000\u51FA\uFF09`);
5739
+ const started = await startDevServer2({ cwd: ctx.cwd, port: Number(flags.port ?? "8787") });
5740
+ command.raw(`[adep] dev server listening on ${started.baseUrl}\uFF08Ctrl-C \u9000\u51FA\uFF09`);
5885
5741
  await new Promise(() => void 0);
5886
- } catch (error) {
5887
- emitError(output, "dev", jsonMode(), error);
5888
- }
5742
+ });
5889
5743
  });
5890
5744
  program2.command("serve").description(
5891
5745
  "\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"
@@ -5895,605 +5749,563 @@ function buildProgram(options = {}) {
5895
5749
  ).option(
5896
5750
  "--static <dir>",
5897
5751
  "\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"
5752
+ ).option(
5753
+ "--watch",
5754
+ "\u70ED\u91CD\u8F7D\uFF1A\u76D1\u542C functions/ \u4E0E .env* \u53D8\u66F4\u81EA\u52A8\u751F\u6548\uFF0C\u51FD\u6570 console \u8F93\u51FA\u76F4\u8FBE\u7EC8\u7AEF\uFF08\u5F00\u53D1\u6001\u8C03\u8BD5\u7528\uFF09"
5898
5755
  ).action(async (flags) => {
5899
- try {
5756
+ const command = ctx.io("serve");
5757
+ await command.run(async () => {
5900
5758
  const { startServeServer: startServeServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
5901
5759
  await startServeServer2({
5902
- cwd,
5760
+ cwd: ctx.cwd,
5903
5761
  ...flags.port === void 0 ? {} : { port: Number(flags.port) },
5904
5762
  ...flags.host === void 0 ? {} : { host: flags.host },
5905
- ...flags.static === void 0 ? {} : { staticDir: flags.static }
5763
+ ...flags.static === void 0 ? {} : { staticDir: flags.static },
5764
+ ...flags.watch === void 0 ? {} : { watch: true }
5906
5765
  });
5907
5766
  await new Promise(() => void 0);
5908
- } catch (error) {
5909
- emitError(output, "serve", jsonMode(), error);
5910
- }
5767
+ });
5911
5768
  });
5912
- 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) => {
5913
- try {
5914
- await runDeploy(paths, output, jsonMode(), cwd, flags.project);
5915
- } catch (error) {
5916
- emitError(output, "deploy", jsonMode(), error);
5769
+ }
5770
+
5771
+ // packages/cli/src/commands/deploy.ts
5772
+ async function runDeploy(paths, io, cwd, slug, dir) {
5773
+ const { deploy: deploy2 } = await Promise.resolve().then(() => (init_deploy(), deploy_exports));
5774
+ const startedAt = Date.now();
5775
+ const result = await deploy2(paths, {
5776
+ cwd,
5777
+ ...slug === void 0 ? {} : { slug },
5778
+ ...dir === void 0 ? {} : { functionsDir: dir },
5779
+ // --json 下逐函数进度会破坏「stdout 恰好一个 JSON 对象」的信封约定(PRD §2.5.3)。
5780
+ silent: io.json,
5781
+ // 人读模式的进度也走注入的 io:deploy 内部缺省会直写 process.stdout,
5782
+ // 那会让带 sink 的调用方漏收这部分行。
5783
+ log: (line) => io.line(line)
5784
+ });
5785
+ const elapsedSeconds = (Date.now() - startedAt) / 1e3;
5786
+ const deployedCount = result.functions.filter((fn) => fn.action !== "none").length;
5787
+ io.ok({ ...result, elapsedSeconds, deployedCount }, (data) => {
5788
+ const r = data;
5789
+ const lines = r.functions.map((fn) => `${fn.name} v${fn.version} ${fn.url}`);
5790
+ if (r.noChanges) {
5791
+ lines.push(
5792
+ `\u2713 no changes \xB7 ${r.functions.length} functions up to date in ${formatSeconds(r.elapsedSeconds)}`
5793
+ );
5794
+ } else {
5795
+ lines.push(`\u2713 ${r.deployedCount} functions deployed in ${formatSeconds(r.elapsedSeconds)}`);
5917
5796
  }
5797
+ return lines;
5798
+ });
5799
+ }
5800
+ function registerDeploy(program2, ctx) {
5801
+ 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) => {
5802
+ const command = ctx.io("deploy");
5803
+ await command.run(() => runDeploy(ctx.paths, command, ctx.cwd, flags.project));
5918
5804
  });
5805
+ }
5806
+
5807
+ // packages/cli/src/commands/projects.ts
5808
+ function registerProjects(program2, ctx) {
5919
5809
  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");
5920
5810
  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) => {
5921
- try {
5811
+ const command = ctx.io("projects create");
5812
+ await command.run(async () => {
5922
5813
  const { projectsCreate: projectsCreate2 } = await Promise.resolve().then(() => (init_projects(), projects_exports));
5923
- const created = await projectsCreate2(paths, {
5814
+ const created = await projectsCreate2(ctx.paths, {
5924
5815
  slug,
5925
5816
  ...flags.name === void 0 ? {} : { name: flags.name },
5926
5817
  ...flags.space === void 0 ? {} : { spaceId: flags.space }
5927
5818
  });
5928
- if (jsonMode()) {
5929
- output(JSON.stringify({ ok: true, command: "projects create", data: created }));
5930
- } else {
5931
- output(`\u2713 Project created \xB7 ${created.url}`);
5932
- }
5933
- } catch (error) {
5934
- emitError(output, "projects create", jsonMode(), error);
5935
- }
5819
+ command.ok(created, (data) => `\u2713 Project created \xB7 ${data.url}`);
5820
+ });
5936
5821
  });
5937
5822
  projects.command("list").description("\u5217\u51FA\u5F53\u524D\u7528\u6237\u53EF\u8BBF\u95EE\u7684\u9879\u76EE").action(async () => {
5938
- try {
5823
+ const command = ctx.io("projects list");
5824
+ await command.run(async () => {
5939
5825
  const { projectsList: projectsList2 } = await Promise.resolve().then(() => (init_projects(), projects_exports));
5940
- const list = await projectsList2(paths);
5941
- if (jsonMode()) {
5942
- output(JSON.stringify({ ok: true, command: "projects list", data: { projects: list } }));
5943
- } else {
5944
- if (list.length === 0) output("\uFF08\u8FD8\u6CA1\u6709\u9879\u76EE\uFF1Aadep projects create <slug>\uFF09");
5945
- for (const project2 of list) output(`${project2.slug} ${project2.name} ${project2.url}`);
5946
- }
5947
- } catch (error) {
5948
- emitError(output, "projects list", jsonMode(), error);
5949
- }
5826
+ const list = await projectsList2(ctx.paths);
5827
+ command.ok({ projects: list }, (data) => {
5828
+ const projectsData = data.projects;
5829
+ if (projectsData.length === 0) return "\uFF08\u8FD8\u6CA1\u6709\u9879\u76EE\uFF1Aadep projects create <slug>\uFF09";
5830
+ return projectsData.map((p) => `${p.slug} ${p.name} ${p.url}`);
5831
+ });
5832
+ });
5950
5833
  });
5951
5834
  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) => {
5952
- try {
5835
+ const command = ctx.io("projects info");
5836
+ await command.run(async () => {
5953
5837
  const { projectsInfo: projectsInfo2 } = await Promise.resolve().then(() => (init_projects(), projects_exports));
5954
- const project2 = await projectsInfo2(paths, { slug });
5955
- if (jsonMode()) {
5956
- output(JSON.stringify({ ok: true, command: "projects info", data: project2 }));
5957
- } else {
5958
- output(`${project2.id} ${project2.slug} ${project2.name} ${project2.url}`);
5959
- }
5960
- } catch (error) {
5961
- emitError(output, "projects info", jsonMode(), error);
5962
- }
5838
+ const project2 = await projectsInfo2(ctx.paths, { slug });
5839
+ command.ok(project2, (data) => {
5840
+ const p = data;
5841
+ return `${p.id} ${p.slug} ${p.name} ${p.url}`;
5842
+ });
5843
+ });
5963
5844
  });
5845
+ }
5846
+
5847
+ // packages/cli/src/commands/functions.ts
5848
+ init_auth();
5849
+ function registerFunctions(program2, ctx) {
5964
5850
  const functions = program2.command("functions").description("\u4E91\u51FD\u6570\uFF1A\u90E8\u7F72\uFF08\u53EF\u6307\u5B9A\u76EE\u5F55\uFF09/ \u5217\u51FA / \u67E5\u65E5\u5FD7");
5965
5851
  functions.command("deploy").description(
5966
5852
  "\u90E8\u7F72\u51FD\u6570\u76EE\u5F55\uFF08`adep deploy` \u7684\u547D\u4EE4\u65CF\u5165\u53E3\uFF1Bdir \u8986\u76D6 adep.config.ts \u7684 functionsDir\uFF09"
5967
5853
  ).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) => {
5968
- try {
5969
- await runDeploy(paths, output, jsonMode(), cwd, flags.project, dir);
5970
- } catch (error) {
5971
- emitError(output, "functions deploy", jsonMode(), error);
5972
- }
5854
+ const command = ctx.io("functions deploy");
5855
+ await command.run(() => runDeploy(ctx.paths, command, ctx.cwd, flags.project, dir));
5973
5856
  });
5974
5857
  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) => {
5975
- try {
5858
+ const command = ctx.io("functions list");
5859
+ await command.run(async () => {
5976
5860
  const { functionsList: functionsList2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
5977
- const result = await functionsList2(paths, {
5978
- cwd,
5861
+ const result = await functionsList2(ctx.paths, {
5862
+ cwd: ctx.cwd,
5979
5863
  ...flags.project === void 0 ? {} : { slug: flags.project }
5980
5864
  });
5981
- if (jsonMode()) {
5982
- output(JSON.stringify({ ok: true, command: "functions list", data: result }));
5983
- } else {
5984
- if (result.functions.length === 0) output("\uFF08\u8BE5\u9879\u76EE\u4E0B\u8FD8\u6CA1\u6709\u51FD\u6570\uFF09");
5985
- for (const fn of result.functions) {
5986
- output(`${fn.name} ${result.baseUrl}/${fn.name}`);
5987
- }
5988
- }
5989
- } catch (error) {
5990
- emitError(output, "functions list", jsonMode(), error);
5991
- }
5865
+ command.ok(result, (data) => {
5866
+ const r = data;
5867
+ if (r.functions.length === 0) return "\uFF08\u8BE5\u9879\u76EE\u4E0B\u8FD8\u6CA1\u6709\u51FD\u6570\uFF09";
5868
+ return r.functions.map((fn) => `${fn.name} ${r.baseUrl}/${fn.name}`);
5869
+ });
5870
+ });
5992
5871
  });
5993
5872
  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) => {
5994
- try {
5873
+ const command = ctx.io("functions logs");
5874
+ await command.run(async () => {
5995
5875
  const { functionsLogs: functionsLogs2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
5996
5876
  const tail = flags.tail === void 0 ? void 0 : Number(flags.tail);
5997
5877
  if (tail !== void 0 && (!Number.isFinite(tail) || tail <= 0)) {
5998
5878
  throw new CliError("INVALID_TAIL", `--tail \u987B\u4E3A\u6B63\u6574\u6570\uFF0C\u6536\u5230 "${flags.tail}"`);
5999
5879
  }
6000
- const result = await functionsLogs2(paths, {
6001
- cwd,
5880
+ const result = await functionsLogs2(ctx.paths, {
5881
+ cwd: ctx.cwd,
6002
5882
  name,
6003
5883
  ...tail === void 0 ? {} : { tail },
6004
5884
  ...flags.project === void 0 ? {} : { slug: flags.project }
6005
5885
  });
6006
- if (jsonMode()) {
6007
- output(JSON.stringify({ ok: true, command: "functions logs", data: result }));
6008
- } else {
6009
- if (result.logs.length === 0) {
6010
- 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`);
5886
+ command.ok(result, (data) => {
5887
+ const r = data;
5888
+ if (r.logs.length === 0) {
5889
+ return `\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`;
6011
5890
  }
6012
- for (const log of result.logs) output(`${log.at} [${log.level}] ${log.message}`);
6013
- }
6014
- } catch (error) {
6015
- emitError(output, "functions logs", jsonMode(), error);
6016
- }
5891
+ return r.logs.map((log) => `${log.at} [${log.level}] ${log.message}`);
5892
+ });
5893
+ });
6017
5894
  });
5895
+ }
5896
+
5897
+ // packages/cli/src/commands/mcp.ts
5898
+ function registerMcp(program2, ctx) {
6018
5899
  const mcp = program2.command("mcp").description("MCP Tool\uFF1A\u628A\u4E91\u51FD\u6570\u53D1\u5E03\u4E3A\u5DE5\u5177 / \u53D6\u6D88\u53D1\u5E03 / \u5217\u51FA");
6019
5900
  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(
6020
5901
  "--description <text>",
6021
5902
  "\u8986\u76D6\u9762\u5411 Agent \u7684\u5DE5\u5177\u63CF\u8FF0\uFF08\u7F3A\u7701\u7528\u6E90\u7801 @description / \u63A8\u5BFC\u63CF\u8FF0\uFF09"
6022
5903
  ).option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").action(
6023
5904
  async (flags) => {
6024
- try {
5905
+ const command = ctx.io("mcp publish");
5906
+ await command.run(async () => {
6025
5907
  const { mcpPublish: mcpPublish2 } = await Promise.resolve().then(() => (init_mcp(), mcp_exports));
6026
- const result = await mcpPublish2(paths, {
6027
- cwd,
5908
+ const result = await mcpPublish2(ctx.paths, {
5909
+ cwd: ctx.cwd,
6028
5910
  fn: flags.function,
6029
5911
  ...flags.name === void 0 ? {} : { toolName: flags.name },
6030
5912
  ...flags.description === void 0 ? {} : { description: flags.description },
6031
5913
  ...flags.project === void 0 ? {} : { slug: flags.project }
6032
5914
  });
6033
- if (jsonMode()) {
6034
- output(JSON.stringify({ ok: true, command: "mcp publish", data: result }));
6035
- } else {
6036
- output(`\u2713 MCP tool published \xB7 ${result.tool.name}`);
6037
- }
6038
- } catch (error) {
6039
- emitError(output, "mcp publish", jsonMode(), error);
6040
- }
5915
+ command.ok(result, (data) => {
5916
+ const r = data;
5917
+ return `\u2713 MCP tool published \xB7 ${r.tool.name}`;
5918
+ });
5919
+ });
6041
5920
  }
6042
5921
  );
6043
5922
  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) => {
6044
- try {
5923
+ const command = ctx.io("mcp unpublish");
5924
+ await command.run(async () => {
6045
5925
  const { mcpUnpublish: mcpUnpublish2 } = await Promise.resolve().then(() => (init_mcp(), mcp_exports));
6046
- const result = await mcpUnpublish2(paths, {
6047
- cwd,
5926
+ const result = await mcpUnpublish2(ctx.paths, {
5927
+ cwd: ctx.cwd,
6048
5928
  fn: flags.function,
6049
5929
  ...flags.name === void 0 ? {} : { toolName: flags.name },
6050
5930
  ...flags.project === void 0 ? {} : { slug: flags.project }
6051
5931
  });
6052
- if (jsonMode()) {
6053
- output(JSON.stringify({ ok: true, command: "mcp unpublish", data: result }));
6054
- } else if (result.removed) {
6055
- output(`\u2713 MCP tool unpublished \xB7 ${result.toolName}`);
6056
- } else {
6057
- output(`\uFF08\u9879\u76EE\u672A\u53D1\u5E03\u540D\u4E3A ${result.toolName} \u7684 MCP tool\uFF0C\u65E0\u9700\u53D6\u6D88\uFF09`);
6058
- }
6059
- } catch (error) {
6060
- emitError(output, "mcp unpublish", jsonMode(), error);
6061
- }
5932
+ command.ok(result, (data) => {
5933
+ const r = data;
5934
+ return r.removed ? `\u2713 MCP tool unpublished \xB7 ${r.toolName}` : `\uFF08\u9879\u76EE\u672A\u53D1\u5E03\u540D\u4E3A ${r.toolName} \u7684 MCP tool\uFF0C\u65E0\u9700\u53D6\u6D88\uFF09`;
5935
+ });
5936
+ });
6062
5937
  });
6063
5938
  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) => {
6064
- try {
5939
+ const command = ctx.io("mcp list");
5940
+ await command.run(async () => {
6065
5941
  const { mcpList: mcpList2 } = await Promise.resolve().then(() => (init_mcp(), mcp_exports));
6066
- const result = await mcpList2(paths, {
6067
- cwd,
5942
+ const result = await mcpList2(ctx.paths, {
5943
+ cwd: ctx.cwd,
6068
5944
  ...flags.project === void 0 ? {} : { slug: flags.project }
6069
5945
  });
6070
- if (jsonMode()) {
6071
- output(JSON.stringify({ ok: true, command: "mcp list", data: result }));
6072
- } else {
6073
- output(`\u7AEF\u70B9\uFF1A${result.endpoint}`);
6074
- if (result.tools.length === 0) {
6075
- output("\uFF08\u8FD8\u6CA1\u6709\u5DF2\u53D1\u5E03\u7684 MCP tool\uFF1Aadep mcp publish --function <fn>\uFF09");
6076
- }
6077
- for (const tool of result.tools) {
6078
- output(`${tool.name} ${tool.description ?? ""}`);
5946
+ command.ok(result, (data) => {
5947
+ const r = data;
5948
+ const lines = [`\u7AEF\u70B9\uFF1A${r.endpoint}`];
5949
+ if (r.tools.length === 0) {
5950
+ lines.push("\uFF08\u8FD8\u6CA1\u6709\u5DF2\u53D1\u5E03\u7684 MCP tool\uFF1Aadep mcp publish --function <fn>\uFF09");
5951
+ } else {
5952
+ for (const tool of r.tools) lines.push(`${tool.name} ${tool.description ?? ""}`);
6079
5953
  }
6080
- }
6081
- } catch (error) {
6082
- emitError(output, "mcp list", jsonMode(), error);
6083
- }
5954
+ return lines;
5955
+ });
5956
+ });
6084
5957
  });
5958
+ }
5959
+
5960
+ // packages/cli/src/commands/doctor.ts
5961
+ function registerDoctor(program2, ctx) {
6085
5962
  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 () => {
6086
- try {
5963
+ const command = ctx.io("doctor");
5964
+ await command.run(async () => {
6087
5965
  const { runDoctor: runDoctor2, formatDoctorReport: formatDoctorReport2 } = await Promise.resolve().then(() => (init_doctor(), doctor_exports));
6088
- const report = await runDoctor2(paths);
6089
- if (jsonMode()) {
6090
- output(JSON.stringify({ ok: true, command: "doctor", data: report }));
6091
- } else {
6092
- for (const line of formatDoctorReport2(report)) output(line);
6093
- }
6094
- } catch (error) {
6095
- emitError(output, "doctor", jsonMode(), error);
6096
- }
5966
+ const report = await runDoctor2(ctx.paths);
5967
+ command.ok(report, () => formatDoctorReport2(report));
5968
+ });
6097
5969
  });
5970
+ }
5971
+
5972
+ // packages/cli/src/commands/db.ts
5973
+ function registerDb(program2, ctx) {
6098
5974
  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");
6099
5975
  db.command("start").description("\u542F\u52A8\u9879\u76EE\u6570\u636E\u5E93\uFF08\u5DF2\u5B58\u5728\u5219\u91CD\u65B0\u6FC0\u6D3B\uFF0C\u4E0D\u91CD\u5EFA\u6570\u636E\uFF09").option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").action(async (flags) => {
6100
- try {
5976
+ const command = ctx.io("db start");
5977
+ await command.run(async () => {
6101
5978
  const { dbStart: dbStart2 } = await Promise.resolve().then(() => (init_db2(), db_exports));
6102
- const result = await dbStart2(paths, {
6103
- cwd,
5979
+ const result = await dbStart2(ctx.paths, {
5980
+ cwd: ctx.cwd,
6104
5981
  ...flags.project === void 0 ? {} : { slug: flags.project }
6105
5982
  });
6106
- if (jsonMode()) {
6107
- output(JSON.stringify({ ok: true, command: "db start", data: result }));
6108
- } else {
6109
- output(
6110
- `\u6570\u636E\u5E93\u5DF2\u5C31\u7EEA\uFF1A${result.projectId}\uFF08${result.journalMode}\uFF0C${result.usage.tableCount} \u8868 / ${result.usage.rowCount} \u884C / ${formatBytes(result.usage.sizeBytes)}\uFF09`
6111
- );
6112
- }
6113
- } catch (error) {
6114
- emitError(output, "db start", jsonMode(), error);
6115
- }
5983
+ command.ok(result, (data) => {
5984
+ const r = data;
5985
+ return `\u6570\u636E\u5E93\u5DF2\u5C31\u7EEA\uFF1A${r.projectId}\uFF08${r.journalMode}\uFF0C${r.usage.tableCount} \u8868 / ${r.usage.rowCount} \u884C / ${formatBytes(r.usage.sizeBytes)}\uFF09`;
5986
+ });
5987
+ });
6116
5988
  });
6117
5989
  db.command("status").description("\u67E5\u8BE2\u9879\u76EE\u6570\u636E\u5E93\u72B6\u6001\u4E0E\u7528\u91CF\uFF08\u4F53\u79EF / \u8868\u6570 / \u884C\u6570\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) => {
6118
- try {
5990
+ const command = ctx.io("db status");
5991
+ await command.run(async () => {
6119
5992
  const { dbStatus: dbStatus2 } = await Promise.resolve().then(() => (init_db2(), db_exports));
6120
- const result = await dbStatus2(paths, {
6121
- cwd,
5993
+ const result = await dbStatus2(ctx.paths, {
5994
+ cwd: ctx.cwd,
6122
5995
  ...flags.project === void 0 ? {} : { slug: flags.project }
6123
5996
  });
6124
- if (jsonMode()) {
6125
- output(JSON.stringify({ ok: true, command: "db status", data: result }));
6126
- } else {
6127
- output(
6128
- `\u72B6\u6001\uFF1A${result.status}\uFF08${result.projectId}\uFF0C${result.usage.tableCount} \u8868 / ${result.usage.rowCount} \u884C / ${formatBytes(result.usage.sizeBytes)}\uFF09`
6129
- );
6130
- }
6131
- } catch (error) {
6132
- emitError(output, "db status", jsonMode(), error);
6133
- }
5997
+ command.ok(result, (data) => {
5998
+ const r = data;
5999
+ return `\u72B6\u6001\uFF1A${r.status}\uFF08${r.projectId}\uFF0C${r.usage.tableCount} \u8868 / ${r.usage.rowCount} \u884C / ${formatBytes(r.usage.sizeBytes)}\uFF09`;
6000
+ });
6001
+ });
6134
6002
  });
6135
6003
  db.command("stop").description("\u505C\u6B62\u9879\u76EE\u6570\u636E\u5E93\uFF08\u8FDE\u63A5\u5173\u95ED\u5E76\u6807\u8BB0\uFF1B\u6587\u4EF6\u4FDD\u7559\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) => {
6136
- try {
6004
+ const command = ctx.io("db stop");
6005
+ await command.run(async () => {
6137
6006
  const { dbStop: dbStop2 } = await Promise.resolve().then(() => (init_db2(), db_exports));
6138
- const result = await dbStop2(paths, {
6139
- cwd,
6007
+ const result = await dbStop2(ctx.paths, {
6008
+ cwd: ctx.cwd,
6140
6009
  ...flags.project === void 0 ? {} : { slug: flags.project }
6141
6010
  });
6142
- if (jsonMode()) {
6143
- output(JSON.stringify({ ok: true, command: "db stop", data: result }));
6144
- } else {
6145
- output(`\u6570\u636E\u5E93\u5DF2\u505C\u6B62\uFF1A${result.status}`);
6146
- }
6147
- } catch (error) {
6148
- emitError(output, "db stop", jsonMode(), error);
6149
- }
6011
+ command.ok(result, (data) => `\u6570\u636E\u5E93\u5DF2\u505C\u6B62\uFF1A${data.status}`);
6012
+ });
6150
6013
  });
6151
6014
  db.command("exec").description("\u6267\u884C\u5355\u6761 SQL\uFF08\u5199 / \u7834\u574F\u6027\u8BED\u53E5\u9700 --confirm-table \u4E8C\u6B21\u786E\u8BA4\uFF09").option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").requiredOption("--sql <sql>", "\u5F85\u6267\u884C SQL").option("--confirm-table <table>", "\u7834\u574F\u6027\u64CD\u4F5C\u7684\u76EE\u6807\u8868\u540D\uFF08\u4E8C\u6B21\u786E\u8BA4\uFF09").action(async (flags) => {
6152
- try {
6015
+ const command = ctx.io("db exec");
6016
+ await command.run(async () => {
6153
6017
  const { dbExec: dbExec2 } = await Promise.resolve().then(() => (init_db2(), db_exports));
6154
- const result = await dbExec2(paths, {
6155
- cwd,
6018
+ const result = await dbExec2(ctx.paths, {
6019
+ cwd: ctx.cwd,
6156
6020
  sql: flags.sql,
6157
6021
  ...flags.project === void 0 ? {} : { slug: flags.project },
6158
6022
  ...flags.confirmTable === void 0 ? {} : { confirmTable: flags.confirmTable }
6159
6023
  });
6160
- if (jsonMode()) {
6161
- output(JSON.stringify({ ok: true, command: "db exec", data: result }));
6162
- } else {
6163
- if (result.columns.length > 0) {
6164
- output(formatTable(result.columns, result.rows));
6165
- if (result.truncated) output(`\uFF08\u7ED3\u679C\u5DF2\u622A\u65AD\u5230 ${result.rows.length} \u884C\uFF09`);
6166
- } else if (result.changes > 0) {
6167
- output(`${result.changes} \u884C\u53D7\u5F71\u54CD`);
6024
+ command.ok(result, (data) => {
6025
+ const r = data;
6026
+ const lines = [];
6027
+ if (r.columns.length > 0) {
6028
+ lines.push(formatTable(r.columns, r.rows));
6029
+ if (r.truncated) lines.push(`\uFF08\u7ED3\u679C\u5DF2\u622A\u65AD\u5230 ${r.rows.length} \u884C\uFF09`);
6030
+ } else if (r.changes > 0) {
6031
+ lines.push(`${r.changes} \u884C\u53D7\u5F71\u54CD`);
6168
6032
  } else {
6169
- output("\u8BED\u53E5\u6267\u884C\u6210\u529F\uFF08\u65E0\u8FD4\u56DE\u884C\uFF09");
6033
+ lines.push("\u8BED\u53E5\u6267\u884C\u6210\u529F\uFF08\u65E0\u8FD4\u56DE\u884C\uFF09");
6170
6034
  }
6171
- output(`\u8017\u65F6 ${result.elapsedMs}ms`);
6172
- }
6173
- } catch (error) {
6174
- emitError(output, "db exec", jsonMode(), error);
6175
- }
6035
+ lines.push(`\u8017\u65F6 ${r.elapsedMs}ms`);
6036
+ return lines;
6037
+ });
6038
+ });
6176
6039
  });
6177
6040
  const snapshot = db.command("snapshot").description("\u6570\u636E\u5E93\u5FEB\u7167\uFF08\u4ED8\u8D39\u6863\u4F4D\uFF09\uFF1A\u5217\u51FA\uFF08\u7F3A\u7701\uFF09/ \u521B\u5EFA / \u8FD8\u539F");
6178
6041
  snapshot.command("list").description("\u5217\u51FA\u9879\u76EE\u6570\u636E\u5E93\u5FEB\u7167\uFF08\u6309\u521B\u5EFA\u65F6\u95F4\u5012\u5E8F\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) => {
6179
- try {
6042
+ const command = ctx.io("db snapshot list");
6043
+ await command.run(async () => {
6180
6044
  const { dbSnapshotList: dbSnapshotList2 } = await Promise.resolve().then(() => (init_db2(), db_exports));
6181
- const result = await dbSnapshotList2(paths, {
6182
- cwd,
6045
+ const result = await dbSnapshotList2(ctx.paths, {
6046
+ cwd: ctx.cwd,
6183
6047
  ...flags.project === void 0 ? {} : { slug: flags.project }
6184
6048
  });
6185
- if (jsonMode()) {
6186
- output(JSON.stringify({ ok: true, command: "db snapshot list", data: result }));
6187
- } else {
6188
- if (result.snapshots.length === 0) {
6189
- output("\u6682\u65E0\u5FEB\u7167");
6190
- }
6191
- for (const snap of result.snapshots) {
6192
- output(
6193
- `${snap.id} ${snap.type} ${snap.plan} ${formatBytes(snap.sizeBytes)} ${snap.createdAt}`
6194
- );
6195
- }
6196
- }
6197
- } catch (error) {
6198
- emitError(output, "db snapshot list", jsonMode(), error);
6199
- }
6049
+ command.ok(result, (data) => {
6050
+ const r = data;
6051
+ if (r.snapshots.length === 0) return "\u6682\u65E0\u5FEB\u7167";
6052
+ return r.snapshots.map(
6053
+ (snap) => `${snap.id} ${snap.type} ${snap.plan} ${formatBytes(snap.sizeBytes)} ${snap.createdAt}`
6054
+ );
6055
+ });
6056
+ });
6200
6057
  });
6201
6058
  snapshot.command("create").description("\u521B\u5EFA\u624B\u52A8\u6570\u636E\u5E93\u5FEB\u7167\uFF08\u514D\u8D39\u7248\u5E73\u53F0\u8FD4\u56DE 403 \u6743\u76CA\u672A\u5F00\u653E\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) => {
6202
- try {
6059
+ const command = ctx.io("db snapshot create");
6060
+ await command.run(async () => {
6203
6061
  const { dbSnapshotCreate: dbSnapshotCreate2 } = await Promise.resolve().then(() => (init_db2(), db_exports));
6204
- const result = await dbSnapshotCreate2(paths, {
6205
- cwd,
6062
+ const result = await dbSnapshotCreate2(ctx.paths, {
6063
+ cwd: ctx.cwd,
6206
6064
  ...flags.project === void 0 ? {} : { slug: flags.project }
6207
6065
  });
6208
- if (jsonMode()) {
6209
- output(JSON.stringify({ ok: true, command: "db snapshot create", data: result }));
6210
- } else {
6211
- output(`\u5FEB\u7167\u5DF2\u521B\u5EFA\uFF1A${result.id}\uFF08${result.plan}\uFF0C${formatBytes(result.sizeBytes)}\uFF09`);
6212
- }
6213
- } catch (error) {
6214
- emitError(output, "db snapshot create", jsonMode(), error);
6215
- }
6066
+ command.ok(result, (data) => {
6067
+ const r = data;
6068
+ return `\u5FEB\u7167\u5DF2\u521B\u5EFA\uFF1A${r.id}\uFF08${r.plan}\uFF0C${formatBytes(r.sizeBytes)}\uFF09`;
6069
+ });
6070
+ });
6216
6071
  });
6217
6072
  snapshot.command("restore").description("\u6574\u4F53\u8FD8\u539F\u6570\u636E\u5E93\u5230\u5FEB\u7167\u65F6\u523B\uFF08\u4ED8\u8D39\u6863\u4F4D\uFF09").argument("<snapshotId>", "\u5FEB\u7167 id").option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").action(async (snapshotId, flags) => {
6218
- try {
6073
+ const command = ctx.io("db snapshot restore");
6074
+ await command.run(async () => {
6219
6075
  const { dbSnapshotRestore: dbSnapshotRestore2 } = await Promise.resolve().then(() => (init_db2(), db_exports));
6220
- const result = await dbSnapshotRestore2(paths, {
6221
- cwd,
6076
+ const result = await dbSnapshotRestore2(ctx.paths, {
6077
+ cwd: ctx.cwd,
6222
6078
  snapshotId,
6223
6079
  ...flags.project === void 0 ? {} : { slug: flags.project }
6224
6080
  });
6225
- if (jsonMode()) {
6226
- output(JSON.stringify({ ok: true, command: "db snapshot restore", data: result }));
6227
- } else {
6228
- output(`\u5DF2\u8FD8\u539F\u5230\u5FEB\u7167 ${result.snapshotId}`);
6229
- }
6230
- } catch (error) {
6231
- emitError(output, "db snapshot restore", jsonMode(), error);
6232
- }
6081
+ command.ok(result, (data) => `\u5DF2\u8FD8\u539F\u5230\u5FEB\u7167 ${data.snapshotId}`);
6082
+ });
6233
6083
  });
6234
6084
  db.command("rollback").description("\u65F6\u95F4\u70B9\u56DE\u6EDA\u5230\u6307\u5B9A\u65F6\u523B\uFF08\u56E2\u961F\u7248\uFF1B\u57FA\u4E8E\u53D8\u66F4\u6D41\u91CD\u653E\uFF09").option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").requiredOption("--to <iso-time>", "\u56DE\u6EDA\u76EE\u6807\u65F6\u523B\uFF08ISO 8601\uFF09").action(async (flags) => {
6235
- try {
6085
+ const command = ctx.io("db rollback");
6086
+ await command.run(async () => {
6236
6087
  const { dbRollback: dbRollback2 } = await Promise.resolve().then(() => (init_db2(), db_exports));
6237
- const result = await dbRollback2(paths, {
6238
- cwd,
6088
+ const result = await dbRollback2(ctx.paths, {
6089
+ cwd: ctx.cwd,
6239
6090
  to: flags.to,
6240
6091
  ...flags.project === void 0 ? {} : { slug: flags.project }
6241
6092
  });
6242
- if (jsonMode()) {
6243
- output(JSON.stringify({ ok: true, command: "db rollback", data: result }));
6244
- } else {
6245
- output(`\u5DF2\u56DE\u6EDA\u5230 ${result.to}\uFF08\u91CD\u653E ${result.reverted} \u6761\u53D8\u66F4\uFF09`);
6246
- }
6247
- } catch (error) {
6248
- emitError(output, "db rollback", jsonMode(), error);
6249
- }
6093
+ command.ok(result, (data) => {
6094
+ const r = data;
6095
+ return `\u5DF2\u56DE\u6EDA\u5230 ${r.to}\uFF08\u91CD\u653E ${r.reverted} \u6761\u53D8\u66F4\uFF09`;
6096
+ });
6097
+ });
6250
6098
  });
6099
+ }
6100
+
6101
+ // packages/cli/src/commands/storage.ts
6102
+ function registerStorage(program2, ctx) {
6251
6103
  const storage = program2.command("storage").description("\u4E91\u5B58\u50A8 / \u6587\u4EF6\u5B58\u50A8\uFF1A\u4E0A\u4F20 / \u4E0B\u8F7D / \u5217\u8868 / \u5220\u9664").option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09");
6252
6104
  storage.command("upload").description("\u4E0A\u4F20\u5355\u4E2A\u6587\u4EF6\uFF08multipart\uFF1B\u5355\u6587\u4EF6 \u2264 50MB\uFF09").argument("<file>", "\u672C\u5730\u6587\u4EF6\u8DEF\u5F84").requiredOption("--path <remote-path>", "\u6876\u5185\u76EE\u6807\u8DEF\u5F84\uFF08\u5982 avatars/a.png\uFF09").option(
6253
6105
  "--visibility <public|private>",
6254
6106
  "public \u76F4\u8FDE / private \u7B7E\u540D\uFF08\u7F3A\u7701 private\uFF09",
6255
6107
  "private"
6256
6108
  ).option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").action(async (file, flags) => {
6257
- try {
6109
+ const command = ctx.io("storage upload");
6110
+ await command.run(async () => {
6258
6111
  const { storageUpload: storageUpload2 } = await Promise.resolve().then(() => (init_storage2(), storage_exports));
6259
- const result = await storageUpload2(paths, {
6260
- cwd,
6112
+ const result = await storageUpload2(ctx.paths, {
6113
+ cwd: ctx.cwd,
6261
6114
  file,
6262
6115
  path: flags.path,
6263
6116
  visibility: flags.visibility === "public" ? "public" : "private",
6264
6117
  ...flags.project === void 0 ? {} : { slug: flags.project }
6265
6118
  });
6266
- if (jsonMode()) {
6267
- output(JSON.stringify({ ok: true, command: "storage upload", data: result }));
6268
- } else {
6269
- output(`\u5DF2\u4E0A\u4F20 ${result.path}\uFF08${result.visibility}\uFF0C${formatBytes(result.size)}\uFF09`);
6270
- if (result.signedUrl !== void 0) output(`\u7B7E\u540D URL\uFF1A${result.signedUrl}`);
6271
- }
6272
- } catch (error) {
6273
- emitError(output, "storage upload", jsonMode(), error);
6274
- }
6119
+ command.ok(result, (data) => {
6120
+ const r = data;
6121
+ const lines = [`\u5DF2\u4E0A\u4F20 ${r.path}\uFF08${r.visibility}\uFF0C${formatBytes(r.size)}\uFF09`];
6122
+ if (r.signedUrl !== void 0) lines.push(`\u7B7E\u540D URL\uFF1A${r.signedUrl}`);
6123
+ return lines;
6124
+ });
6125
+ });
6275
6126
  });
6276
6127
  storage.command("download").description("\u4E0B\u8F7D\u6587\u4EF6\u5230\u672C\u5730\uFF08public \u76F4\u8FDE / private \u7B7E\u540D URL\uFF09").argument("<remote-path>", "\u6876\u5185\u6587\u4EF6\u8DEF\u5F84").option("-o, --output <file>", "\u672C\u5730\u8F93\u51FA\u8DEF\u5F84\uFF08\u7F3A\u7701\u5199\u5230 cwd\uFF09").option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").action(async (remotePath, flags) => {
6277
- try {
6128
+ const command = ctx.io("storage download");
6129
+ await command.run(async () => {
6278
6130
  const { storageDownload: storageDownload2 } = await Promise.resolve().then(() => (init_storage2(), storage_exports));
6279
- const result = await storageDownload2(paths, {
6280
- cwd,
6131
+ const result = await storageDownload2(ctx.paths, {
6132
+ cwd: ctx.cwd,
6281
6133
  path: remotePath,
6282
6134
  ...flags.output === void 0 ? {} : { output: flags.output },
6283
6135
  ...flags.project === void 0 ? {} : { slug: flags.project }
6284
6136
  });
6285
- if (jsonMode()) {
6286
- output(JSON.stringify({ ok: true, command: "storage download", data: result }));
6287
- } else {
6288
- output(`\u5DF2\u4E0B\u8F7D ${result.path} \u2192 ${result.output}\uFF08${formatBytes(result.size)}\uFF09`);
6289
- }
6290
- } catch (error) {
6291
- emitError(output, "storage download", jsonMode(), error);
6292
- }
6137
+ command.ok(result, (data) => {
6138
+ const r = data;
6139
+ return `\u5DF2\u4E0B\u8F7D ${r.path} \u2192 ${r.output}\uFF08${formatBytes(r.size)}\uFF09`;
6140
+ });
6141
+ });
6293
6142
  });
6294
6143
  storage.command("ls").description("\u5217\u51FA\u9879\u76EE\u6587\u4EF6\uFF08\u6309\u524D\u7F00\u8FC7\u6EE4\uFF1Bpublic \u9644\u76F4\u8FDE url\u3001private \u9644\u7B7E\u540D url\uFF09").option("--prefix <prefix>", "\u6309\u524D\u7F00\u8FC7\u6EE4").option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").action(async (flags) => {
6295
- try {
6144
+ const command = ctx.io("storage ls");
6145
+ await command.run(async () => {
6296
6146
  const { storageList: storageList2 } = await Promise.resolve().then(() => (init_storage2(), storage_exports));
6297
- const result = await storageList2(paths, {
6298
- cwd,
6147
+ const result = await storageList2(ctx.paths, {
6148
+ cwd: ctx.cwd,
6299
6149
  ...flags.prefix === void 0 ? {} : { prefix: flags.prefix },
6300
6150
  ...flags.project === void 0 ? {} : { slug: flags.project }
6301
6151
  });
6302
- if (jsonMode()) {
6303
- output(JSON.stringify({ ok: true, command: "storage ls", data: result }));
6304
- } else {
6305
- if (result.files.length === 0) {
6306
- output("\uFF08\u65E0\u6587\u4EF6\uFF09");
6307
- }
6308
- for (const file of result.files) {
6309
- output(
6310
- `${file.path} ${file.visibility} ${formatBytes(file.size)} ${file.url ?? file.signedUrl ?? ""}`
6311
- );
6312
- }
6313
- }
6314
- } catch (error) {
6315
- emitError(output, "storage ls", jsonMode(), error);
6316
- }
6152
+ command.ok(result, (data) => {
6153
+ const r = data;
6154
+ if (r.files.length === 0) return "\uFF08\u65E0\u6587\u4EF6\uFF09";
6155
+ return r.files.map(
6156
+ (file) => `${file.path} ${file.visibility} ${formatBytes(file.size)} ${file.url ?? file.signedUrl ?? ""}`
6157
+ );
6158
+ });
6159
+ });
6317
6160
  });
6318
6161
  storage.command("rm").description("\u5220\u9664\u6587\u4EF6\uFF08\u4EC5\u9879\u76EE\u6240\u6709\u8005\uFF09").argument("<remote-path>", "\u6876\u5185\u6587\u4EF6\u8DEF\u5F84").option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").action(async (remotePath, flags) => {
6319
- try {
6162
+ const command = ctx.io("storage rm");
6163
+ await command.run(async () => {
6320
6164
  const { storageRemove: storageRemove2 } = await Promise.resolve().then(() => (init_storage2(), storage_exports));
6321
- const result = await storageRemove2(paths, {
6322
- cwd,
6165
+ const result = await storageRemove2(ctx.paths, {
6166
+ cwd: ctx.cwd,
6323
6167
  path: remotePath,
6324
6168
  ...flags.project === void 0 ? {} : { slug: flags.project }
6325
6169
  });
6326
- if (jsonMode()) {
6327
- output(JSON.stringify({ ok: true, command: "storage rm", data: result }));
6328
- } else {
6329
- output(`\u5DF2\u5220\u9664 ${remotePath}`);
6330
- }
6331
- } catch (error) {
6332
- emitError(output, "storage rm", jsonMode(), error);
6333
- }
6170
+ command.ok(result, () => `\u5DF2\u5220\u9664 ${remotePath}`);
6171
+ });
6334
6172
  });
6173
+ }
6174
+
6175
+ // packages/cli/src/commands/hosting.ts
6176
+ init_auth();
6177
+ function parseBool(raw) {
6178
+ if (raw === void 0) return void 0;
6179
+ if (raw === "true") return true;
6180
+ if (raw === "false") return false;
6181
+ throw new CliError("INVALID_BOOLEAN", `\u5E03\u5C14\u53C2\u6570\u987B\u4E3A true \u6216 false\uFF0C\u6536\u5230 "${raw}"`);
6182
+ }
6183
+ function registerHosting(program2, ctx) {
6335
6184
  const hosting = program2.command("hosting").description("\u9759\u6001\u6258\u7BA1\uFF1A\u67E5\u770B / \u90E8\u7F72 / \u62C9\u53D6 / \u914D\u7F6E").option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09");
6336
6185
  hosting.command("info").description("\u67E5\u770B\u9759\u6001\u6258\u7BA1\u914D\u7F6E\u3001\u7AD9\u70B9\u5730\u5740\u4E0E\u6587\u4EF6\u6811").option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").action(async (flags) => {
6337
- try {
6186
+ const command = ctx.io("hosting info");
6187
+ await command.run(async () => {
6338
6188
  const { hostingInfo: hostingInfo2 } = await Promise.resolve().then(() => (init_hosting(), hosting_exports));
6339
- const result = await hostingInfo2(paths, {
6340
- cwd,
6189
+ const result = await hostingInfo2(ctx.paths, {
6190
+ cwd: ctx.cwd,
6341
6191
  ...flags.project === void 0 ? {} : { slug: flags.project }
6342
6192
  });
6343
- if (jsonMode()) {
6344
- output(JSON.stringify({ ok: true, command: "hosting info", data: result }));
6345
- } else {
6346
- output(
6347
- `\u7AD9\u70B9\uFF1A${result.siteUrl}\uFF08\u6258\u7BA1 ${result.config.enabled ? "\u5F00" : "\u5173"}\uFF0CSPA \u56DE\u9000 ${result.config.spaMode ? "\u5F00" : "\u5173"}\uFF09`
6348
- );
6349
- for (const file of result.files) {
6350
- output(`${file.path} ${formatBytes(file.size)}`);
6351
- }
6352
- }
6353
- } catch (error) {
6354
- emitError(output, "hosting info", jsonMode(), error);
6355
- }
6193
+ command.ok(result, (data) => {
6194
+ const r = data;
6195
+ const lines = [
6196
+ `\u7AD9\u70B9\uFF1A${r.siteUrl}\uFF08\u6258\u7BA1 ${r.config.enabled ? "\u5F00" : "\u5173"}\uFF0CSPA \u56DE\u9000 ${r.config.spaMode ? "\u5F00" : "\u5173"}\uFF09`
6197
+ ];
6198
+ for (const file of r.files) lines.push(`${file.path} ${formatBytes(file.size)}`);
6199
+ return lines;
6200
+ });
6201
+ });
6356
6202
  });
6357
6203
  hosting.command("deploy").description("\u90E8\u7F72\u672C\u5730\u76EE\u5F55\u4E3A\u9759\u6001\u7AD9\u70B9\uFF1A\u9012\u5F52\u4E0A\u4F20\u5230 site/ \u5E76\u6253\u5F00\u6258\u7BA1").argument("<dir>", "\u672C\u5730\u7AD9\u70B9\u76EE\u5F55").option("--spa", "\u6253\u5F00\u6258\u7BA1\u5E76\u542F\u7528 SPA \u56DE\u9000\uFF08\u7F3A\u7701\u4EC5\u6253\u5F00\u6258\u7BA1\uFF09", false).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) => {
6358
- try {
6204
+ const command = ctx.io("hosting deploy");
6205
+ await command.run(async () => {
6359
6206
  const { hostingDeploy: hostingDeploy2 } = await Promise.resolve().then(() => (init_hosting(), hosting_exports));
6360
- const result = await hostingDeploy2(paths, {
6361
- cwd,
6207
+ const result = await hostingDeploy2(ctx.paths, {
6208
+ cwd: ctx.cwd,
6362
6209
  dir,
6363
6210
  ...flags.spa === true ? { spa: true } : {},
6364
6211
  ...flags.project === void 0 ? {} : { slug: flags.project }
6365
6212
  });
6366
- if (jsonMode()) {
6367
- output(JSON.stringify({ ok: true, command: "hosting deploy", data: result }));
6368
- } else {
6369
- output(
6370
- `\u7AD9\u70B9\u5DF2\u4E0A\u7EBF\uFF1A${result.siteUrl}\uFF08${result.uploaded.length} \u4E2A\u6587\u4EF6\uFF0CSPA \u56DE\u9000 ${result.config.spaMode ? "\u5F00" : "\u5173"}\uFF09`
6371
- );
6372
- }
6373
- } catch (error) {
6374
- emitError(output, "hosting deploy", jsonMode(), error);
6375
- }
6213
+ command.ok(result, (data) => {
6214
+ const r = data;
6215
+ return `\u7AD9\u70B9\u5DF2\u4E0A\u7EBF\uFF1A${r.siteUrl}\uFF08${r.uploaded.length} \u4E2A\u6587\u4EF6\uFF0CSPA \u56DE\u9000 ${r.config.spaMode ? "\u5F00" : "\u5173"}\uFF09`;
6216
+ });
6217
+ });
6376
6218
  });
6377
6219
  hosting.command("pull").description("\u62C9\u53D6\u7AD9\u70B9\u516C\u5F00\u6587\u4EF6\u5230\u672C\u5730\u76EE\u5F55\uFF08\u8DF3\u8FC7\u6258\u7BA1\u914D\u7F6E\uFF09").option("-o, --output <dir>", "\u672C\u5730\u8F93\u51FA\u76EE\u5F55\uFF08\u7F3A\u7701\u5199\u5230 cwd\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) => {
6378
- try {
6220
+ const command = ctx.io("hosting pull");
6221
+ await command.run(async () => {
6379
6222
  const { hostingPull: hostingPull2 } = await Promise.resolve().then(() => (init_hosting(), hosting_exports));
6380
- const result = await hostingPull2(paths, {
6381
- cwd,
6223
+ const result = await hostingPull2(ctx.paths, {
6224
+ cwd: ctx.cwd,
6382
6225
  ...flags.output === void 0 ? {} : { output: flags.output },
6383
6226
  ...flags.project === void 0 ? {} : { slug: flags.project }
6384
6227
  });
6385
- if (jsonMode()) {
6386
- output(JSON.stringify({ ok: true, command: "hosting pull", data: result }));
6387
- } else {
6388
- output(
6389
- `\u5DF2\u62C9\u53D6 ${result.files.length} \u4E2A\u6587\u4EF6 \u2192 ${result.outputDir}\uFF08\u7AD9\u70B9\uFF1A${result.siteUrl}\uFF09`
6390
- );
6391
- }
6392
- } catch (error) {
6393
- emitError(output, "hosting pull", jsonMode(), error);
6394
- }
6228
+ command.ok(result, (data) => {
6229
+ const r = data;
6230
+ return `\u5DF2\u62C9\u53D6 ${r.files.length} \u4E2A\u6587\u4EF6 \u2192 ${r.outputDir}\uFF08\u7AD9\u70B9\uFF1A${r.siteUrl}\uFF09`;
6231
+ });
6232
+ });
6395
6233
  });
6396
6234
  hosting.command("config").description("\u66F4\u65B0\u9759\u6001\u6258\u7BA1\u914D\u7F6E\uFF08\u6258\u7BA1\u5F00\u5173 / SPA \u56DE\u9000\u6A21\u5F0F\uFF0C\u5E42\u7B49\uFF09").option("--enabled <true|false>", "\u6258\u7BA1\u5F00\u5173").option("--spa <true|false>", "SPA \u56DE\u9000\u6A21\u5F0F").option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").action(async (flags) => {
6397
- try {
6235
+ const command = ctx.io("hosting config");
6236
+ await command.run(async () => {
6398
6237
  const { hostingConfig: hostingConfig2 } = await Promise.resolve().then(() => (init_hosting(), hosting_exports));
6399
6238
  const enabled = parseBool(flags.enabled);
6400
6239
  const spa = parseBool(flags.spa);
6401
- const config = await hostingConfig2(paths, {
6402
- cwd,
6240
+ const config = await hostingConfig2(ctx.paths, {
6241
+ cwd: ctx.cwd,
6403
6242
  ...enabled === void 0 ? {} : { enabled },
6404
6243
  ...spa === void 0 ? {} : { spa },
6405
6244
  ...flags.project === void 0 ? {} : { slug: flags.project }
6406
6245
  });
6407
- if (jsonMode()) {
6408
- output(JSON.stringify({ ok: true, command: "hosting config", data: { config } }));
6409
- } else {
6410
- output(`\u6258\u7BA1 ${config.enabled ? "\u5F00" : "\u5173"}\uFF0CSPA \u56DE\u9000 ${config.spaMode ? "\u5F00" : "\u5173"}`);
6411
- }
6412
- } catch (error) {
6413
- emitError(output, "hosting config", jsonMode(), error);
6414
- }
6246
+ command.ok({ config }, (data) => {
6247
+ const c = data.config;
6248
+ return `\u6258\u7BA1 ${c.enabled ? "\u5F00" : "\u5173"}\uFF0CSPA \u56DE\u9000 ${c.spaMode ? "\u5F00" : "\u5173"}`;
6249
+ });
6250
+ });
6415
6251
  });
6252
+ }
6253
+
6254
+ // packages/cli/src/commands/export.ts
6255
+ function registerExport(program2, ctx) {
6416
6256
  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(
6417
6257
  async (flags) => {
6418
- try {
6258
+ const command = ctx.io("export");
6259
+ await command.run(async () => {
6419
6260
  const { createExportApiClient: createExportApiClient2 } = await Promise.resolve().then(() => (init_client2(), client_exports2));
6420
6261
  const { createExportFileSystem: createExportFileSystem2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
6421
6262
  const { ExportCommand: ExportCommand2 } = await Promise.resolve().then(() => (init_command(), command_exports));
6422
6263
  const { resolveSlug: resolveSlug2 } = await Promise.resolve().then(() => (init_client(), client_exports));
6423
- const project2 = await resolveSlug2(cwd, flags.project);
6424
- const apiClient = await createExportApiClient2(paths);
6425
- const command = new ExportCommand2(apiClient, createExportFileSystem2());
6426
- const result = await command.execute({
6264
+ const project2 = await resolveSlug2(ctx.cwd, flags.project);
6265
+ const apiClient = await createExportApiClient2(ctx.paths);
6266
+ const exportCommand = new ExportCommand2(apiClient, createExportFileSystem2());
6267
+ const result = await exportCommand.execute({
6427
6268
  project: project2,
6428
6269
  ...flags.withData === true ? { withData: true } : {},
6429
6270
  ...flags.withSource === true ? { withSource: true } : {},
6430
6271
  ...flags.out === void 0 ? {} : { out: flags.out },
6431
- json: jsonMode()
6272
+ json: command.json
6432
6273
  });
6433
- if (jsonMode()) {
6434
- if (result.success) {
6435
- output(JSON.stringify({ ok: true, command: "export", data: result }));
6436
- } else {
6437
- output(
6438
- JSON.stringify({
6439
- ok: false,
6440
- command: "export",
6441
- error: { code: "EXPORT_FAILED", message: result.error ?? "\u5BFC\u51FA\u5931\u8D25" }
6442
- })
6443
- );
6444
- process.exitCode = 1;
6445
- }
6446
- } else if (!result.success) {
6447
- output(`\u9519\u8BEF\uFF1A${result.error ?? "\u5BFC\u51FA\u5931\u8D25"}`);
6448
- process.exitCode = 1;
6274
+ if (!result.success) {
6275
+ command.fail("EXPORT_FAILED", result.error ?? "\u5BFC\u51FA\u5931\u8D25");
6276
+ return;
6449
6277
  }
6450
- } catch (error) {
6451
- emitError(output, "export", jsonMode(), error);
6452
- }
6453
- }
6454
- );
6455
- const widget = program2.command("widget").description("\u5FAE\u524D\u7AEF\u7EC4\u4EF6\uFF08widget\uFF09\uFF1A\u811A\u624B\u67B6 / \u672C\u5730\u6C99\u7BB1 / \u53D1\u5E03");
6456
- 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) => {
6457
- try {
6458
- const { initWidget: initWidget2 } = await Promise.resolve().then(() => (init_init(), init_exports));
6459
- const result = await initWidget2(cwd, name, flags.template);
6460
- if (jsonMode()) {
6461
- output(JSON.stringify({ ok: true, command: "widget init", data: result }));
6462
- } else {
6463
- output(`\u5DF2\u521B\u5EFA widget ${result.projectPath}`);
6464
- }
6465
- } catch (error) {
6466
- emitError(output, "widget init", jsonMode(), error);
6467
- }
6468
- });
6469
- widget.command("dev").description("\u672C\u5730\u5BBF\u4E3B\u6C99\u7BB1\uFF1A\u4E3B\u9898\u53D8\u91CF + mock props + token \u6CE8\u5165 + \u70ED\u66F4\u65B0").option("-p, --port <port>", "\u76D1\u542C\u7AEF\u53E3\uFF08\u7F3A\u7701 8788\uFF09", "8788").action(async (flags) => {
6470
- try {
6471
- const { startWidgetDev: startWidgetDev2 } = await Promise.resolve().then(() => (init_dev2(), dev_exports2));
6472
- const started = await startWidgetDev2({ cwd, port: Number(flags.port ?? "8788") });
6473
- output(
6474
- `[adep] widget dev sandbox on ${started.baseUrl}\uFF08?token=<...> \u6CE8\u5165\u9274\u6743 token\uFF1BCtrl-C \u9000\u51FA\uFF09`
6475
- );
6476
- await new Promise(() => void 0);
6477
- } catch (error) {
6478
- emitError(output, "widget dev", jsonMode(), error);
6479
- }
6480
- });
6481
- widget.command("publish").description("\u6309\u6846\u67B6\u6784\u5EFA \u2192 \u4E0A\u4F20\u5E73\u53F0\u9759\u6001\u8D44\u6E90 \u2192 \u7248\u672C\u5316\u8F93\u51FA URL").requiredOption("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug").action(async (flags) => {
6482
- try {
6483
- const { publishWidget: publishWidget2 } = await Promise.resolve().then(() => (init_publish(), publish_exports));
6484
- const result = await publishWidget2(paths, {
6485
- cwd,
6486
- project: flags.project
6278
+ command.ok(result);
6487
6279
  });
6488
- if (jsonMode()) {
6489
- output(JSON.stringify({ ok: true, command: "widget publish", data: result }));
6490
- } else {
6491
- output(`${result.name} v${result.version} ${result.url}`);
6492
- }
6493
- } catch (error) {
6494
- emitError(output, "widget publish", jsonMode(), error);
6495
6280
  }
6496
- });
6281
+ );
6282
+ }
6283
+
6284
+ // packages/cli/src/cli.ts
6285
+ var requireJson = createRequire(import.meta.url);
6286
+ var APP_VERSION = requireJson("../package.json").version;
6287
+ function buildProgram(options = {}) {
6288
+ const output = options.output ?? ((line) => process.stdout.write(`${line}
6289
+ `));
6290
+ const paths = options.paths ?? resolvePaths();
6291
+ const cwd = options.cwd ?? process.cwd();
6292
+ const program2 = new Command();
6293
+ program2.name("adep").description("AgentDeploy CLI").version(APP_VERSION);
6294
+ program2.option("--json", "\u4EE5\u673A\u5668\u53EF\u8BFB JSON \u8F93\u51FA\uFF08Agent / \u811A\u672C\u8C03\u7528\uFF09", false);
6295
+ const jsonMode = () => program2.opts()["json"] === true;
6296
+ const ctx = createCliContext({ output, paths, cwd, json: jsonMode });
6297
+ registerAuth(program2, ctx);
6298
+ registerInit(program2, ctx);
6299
+ registerDevServers(program2, ctx);
6300
+ registerDeploy(program2, ctx);
6301
+ registerProjects(program2, ctx);
6302
+ registerFunctions(program2, ctx);
6303
+ registerMcp(program2, ctx);
6304
+ registerDoctor(program2, ctx);
6305
+ registerDb(program2, ctx);
6306
+ registerStorage(program2, ctx);
6307
+ registerHosting(program2, ctx);
6308
+ registerExport(program2, ctx);
6497
6309
  return program2;
6498
6310
  }
6499
6311