@adep/cli 0.0.9 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ var __export = (target, all) => {
9
9
  __defProp(target, name, { get: all[name], enumerable: true });
10
10
  };
11
11
 
12
- // packages/cli/src/config.ts
12
+ // src/config.ts
13
13
  function resolvePaths(env = process.env) {
14
14
  const home = env["ADEP_HOME"] ?? `${env["HOME"] ?? ""}/.adep`;
15
15
  return { home, credentialsFile: `${home}/credentials` };
@@ -18,12 +18,12 @@ function resolveServer(env = process.env) {
18
18
  return (env["ADEP_SERVER"] ?? "https://adep.jajabjbj.top").replace(/\/+$/, "");
19
19
  }
20
20
  var init_config = __esm({
21
- "packages/cli/src/config.ts"() {
21
+ "src/config.ts"() {
22
22
  "use strict";
23
23
  }
24
24
  });
25
25
 
26
- // packages/cli/src/credentials.ts
26
+ // src/credentials.ts
27
27
  import { mkdir, open, readFile, rm, stat } from "node:fs/promises";
28
28
  import { dirname } from "node:path";
29
29
  async function saveCredentials(paths, credentials) {
@@ -70,15 +70,15 @@ function decodeToken(encoded) {
70
70
  return Buffer.from(encoded, "base64").toString("utf8");
71
71
  }
72
72
  var init_credentials = __esm({
73
- "packages/cli/src/credentials.ts"() {
73
+ "src/credentials.ts"() {
74
74
  "use strict";
75
75
  }
76
76
  });
77
77
 
78
- // packages/cli/src/offline/errors.ts
78
+ // src/offline/errors.ts
79
79
  var NetworkRequiredError;
80
80
  var init_errors = __esm({
81
- "packages/cli/src/offline/errors.ts"() {
81
+ "src/offline/errors.ts"() {
82
82
  "use strict";
83
83
  NetworkRequiredError = class extends Error {
84
84
  command;
@@ -93,7 +93,7 @@ var init_errors = __esm({
93
93
  }
94
94
  });
95
95
 
96
- // packages/cli/src/offline/net.ts
96
+ // src/offline/net.ts
97
97
  var net_exports = {};
98
98
  __export(net_exports, {
99
99
  isOffline: () => isOffline,
@@ -136,7 +136,7 @@ async function requireNetwork(command) {
136
136
  }
137
137
  var PROBE_TTL_MS, PROBE_URL, PROBE_TIMEOUT_MS, cachedResult;
138
138
  var init_net = __esm({
139
- "packages/cli/src/offline/net.ts"() {
139
+ "src/offline/net.ts"() {
140
140
  "use strict";
141
141
  init_errors();
142
142
  PROBE_TTL_MS = 3e4;
@@ -146,7 +146,7 @@ var init_net = __esm({
146
146
  }
147
147
  });
148
148
 
149
- // packages/cli/src/auth.ts
149
+ // src/auth.ts
150
150
  function sessionCookieOf(setCookie) {
151
151
  const line = setCookie.find(
152
152
  (entry) => entry.startsWith("better-auth.session_token=") && !/max-age=0/i.test(entry)
@@ -217,7 +217,7 @@ async function logout(paths) {
217
217
  }
218
218
  var CliError;
219
219
  var init_auth = __esm({
220
- "packages/cli/src/auth.ts"() {
220
+ "src/auth.ts"() {
221
221
  "use strict";
222
222
  init_credentials();
223
223
  init_net();
@@ -232,7 +232,140 @@ var init_auth = __esm({
232
232
  }
233
233
  });
234
234
 
235
- // packages/cli/src/prompt.ts
235
+ // ../../shared/sdk/adep-config.ts
236
+ function typeNameOf(value) {
237
+ if (value === null) return "null";
238
+ if (Array.isArray(value)) return "array";
239
+ return typeof value;
240
+ }
241
+ function asRecord(value) {
242
+ if (value === null || Array.isArray(value) || typeof value !== "object") return null;
243
+ return value;
244
+ }
245
+ function asStringRecord(value) {
246
+ const rec = asRecord(value);
247
+ if (rec === null) return null;
248
+ for (const v of Object.values(rec)) {
249
+ if (typeof v !== "string") return null;
250
+ }
251
+ return rec;
252
+ }
253
+ function parseAdepConfig(raw) {
254
+ if (raw === null || raw === void 0) {
255
+ return { ok: true, data: { ...DEFAULT_ADEP_CONFIG } };
256
+ }
257
+ if (typeof raw !== "object" || Array.isArray(raw)) {
258
+ return {
259
+ ok: false,
260
+ errors: [`adep.config.ts \u7684 default export \u5FC5\u987B\u662F\u5BF9\u8C61\uFF0C\u6536\u5230 ${typeNameOf(raw)}`]
261
+ };
262
+ }
263
+ const errors = [];
264
+ const input = raw;
265
+ const data = { ...DEFAULT_ADEP_CONFIG };
266
+ if (input.name !== void 0) {
267
+ if (typeof input.name !== "string") {
268
+ errors.push(`name \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\uFF0C\u6536\u5230 ${typeNameOf(input.name)}`);
269
+ } else {
270
+ data.name = input.name;
271
+ }
272
+ }
273
+ if (input.functionsDir !== void 0) {
274
+ if (typeof input.functionsDir !== "string") {
275
+ errors.push(`functionsDir \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\uFF0C\u6536\u5230 ${typeNameOf(input.functionsDir)}`);
276
+ } else {
277
+ data.functionsDir = input.functionsDir;
278
+ }
279
+ }
280
+ if (input.functions_prefix !== void 0) {
281
+ if (typeof input.functions_prefix !== "string") {
282
+ errors.push(`functions_prefix \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\uFF0C\u6536\u5230 ${typeNameOf(input.functions_prefix)}`);
283
+ } else {
284
+ data.functions_prefix = input.functions_prefix;
285
+ }
286
+ }
287
+ if (input.frontend !== void 0) {
288
+ const rec = asRecord(input.frontend);
289
+ if (rec === null) {
290
+ errors.push(`frontend \u5FC5\u987B\u662F\u5BF9\u8C61\uFF0C\u6536\u5230 ${typeNameOf(input.frontend)}`);
291
+ } else {
292
+ data.frontend = rec;
293
+ }
294
+ }
295
+ if (input.environment !== void 0) {
296
+ const rec = asStringRecord(input.environment);
297
+ if (rec === null) {
298
+ errors.push(
299
+ `environment \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u5230\u5B57\u7B26\u4E32\u7684\u6620\u5C04\uFF08Record<string, string>\uFF09\uFF0C\u6536\u5230 ${typeNameOf(input.environment)}`
300
+ );
301
+ } else {
302
+ data.environment = rec;
303
+ }
304
+ }
305
+ if (input.runtime !== void 0) {
306
+ const rec = asRecord(input.runtime);
307
+ if (rec === null) {
308
+ errors.push(`runtime \u5FC5\u987B\u662F\u5BF9\u8C61\uFF0C\u6536\u5230 ${typeNameOf(input.runtime)}`);
309
+ } else {
310
+ data.runtime = rec;
311
+ }
312
+ }
313
+ if (errors.length > 0) return { ok: false, errors };
314
+ return { ok: true, data };
315
+ }
316
+ function renderTsValue(value) {
317
+ if (value === null) return "null";
318
+ if (typeof value === "string") return `'${value}'`;
319
+ if (typeof value === "boolean") return value ? "true" : "false";
320
+ if (typeof value === "number") return String(value);
321
+ if (Array.isArray(value)) return `[${value.map(renderTsValue).join(", ")}]`;
322
+ if (typeof value === "object") {
323
+ const entries = Object.entries(value).map(([k, v]) => `${k}: ${renderTsValue(v)}`).join(", ");
324
+ return `{ ${entries} }`;
325
+ }
326
+ return String(value);
327
+ }
328
+ function renderAdepConfig(config, options = {}) {
329
+ const functionsDir = config.functionsDir ?? DEFAULT_ADEP_CONFIG.functionsDir;
330
+ const functionsPrefix = config.functions_prefix ?? DEFAULT_ADEP_CONFIG.functions_prefix;
331
+ const lines = [];
332
+ if (options.header !== void 0 && options.header.length > 0) {
333
+ lines.push(options.header);
334
+ }
335
+ lines.push("export default {");
336
+ if (config.name !== void 0) lines.push(` name: '${config.name}',`);
337
+ lines.push(` functionsDir: '${functionsDir}',`);
338
+ lines.push(` functions_prefix: '${functionsPrefix}',`);
339
+ if (config.frontend !== void 0) {
340
+ lines.push(` frontend: ${renderTsValue(config.frontend)},`);
341
+ }
342
+ if (config.environment !== void 0) {
343
+ lines.push(` environment: ${renderTsValue(config.environment)},`);
344
+ }
345
+ if (config.runtime !== void 0) {
346
+ lines.push(` runtime: ${renderTsValue(config.runtime)},`);
347
+ }
348
+ if (options.extraFields !== void 0) {
349
+ for (const [key, value] of Object.entries(options.extraFields)) {
350
+ lines.push(` ${key}: ${renderTsValue(value)},`);
351
+ }
352
+ }
353
+ lines.push("}");
354
+ return `${lines.join("\n")}
355
+ `;
356
+ }
357
+ var DEFAULT_ADEP_CONFIG;
358
+ var init_adep_config = __esm({
359
+ "../../shared/sdk/adep-config.ts"() {
360
+ "use strict";
361
+ DEFAULT_ADEP_CONFIG = {
362
+ functionsDir: "functions",
363
+ functions_prefix: "/api"
364
+ };
365
+ }
366
+ });
367
+
368
+ // src/prompt.ts
236
369
  var prompt_exports = {};
237
370
  __export(prompt_exports, {
238
371
  createPrompt: () => createPrompt
@@ -263,7 +396,7 @@ function createPrompt(input = process.stdin) {
263
396
  }
264
397
  var MutedStream;
265
398
  var init_prompt = __esm({
266
- "packages/cli/src/prompt.ts"() {
399
+ "src/prompt.ts"() {
267
400
  "use strict";
268
401
  MutedStream = class extends Writable {
269
402
  write(_chunk, ...rest) {
@@ -274,10 +407,10 @@ var init_prompt = __esm({
274
407
  }
275
408
  });
276
409
 
277
- // packages/runtime/src/shared/capability-keys.ts
410
+ // ../runtime/src/shared/capability-keys.ts
278
411
  var RPC_CAPABILITY_KEY, CHAIN_CAPABILITY_KEY, DB_RPC, REALTIME_CAPABILITY_CODES, REALTIME_CAPABILITY_METHODS;
279
412
  var init_capability_keys = __esm({
280
- "packages/runtime/src/shared/capability-keys.ts"() {
413
+ "../runtime/src/shared/capability-keys.ts"() {
281
414
  "use strict";
282
415
  RPC_CAPABILITY_KEY = "__adepRpc";
283
416
  CHAIN_CAPABILITY_KEY = "__adepChain";
@@ -312,7 +445,7 @@ var init_capability_keys = __esm({
312
445
  }
313
446
  });
314
447
 
315
- // packages/runtime/src/shared/executor-runtime.ts
448
+ // ../runtime/src/shared/executor-runtime.ts
316
449
  function isHttpStatus(status) {
317
450
  return typeof status === "number" && Number.isInteger(status) && status >= 400 && status <= 599;
318
451
  }
@@ -321,7 +454,7 @@ function normalizeHttpStatus(status) {
321
454
  }
322
455
  var ExecutorError, TIMEOUT_CODE, OOM_CODE, DEFAULT_TIMEOUT_MS, DEFAULT_MEMORY_LIMIT_MB;
323
456
  var init_executor_runtime = __esm({
324
- "packages/runtime/src/shared/executor-runtime.ts"() {
457
+ "../runtime/src/shared/executor-runtime.ts"() {
325
458
  "use strict";
326
459
  ExecutorError = class extends Error {
327
460
  constructor(status, code, message) {
@@ -338,18 +471,18 @@ var init_executor_runtime = __esm({
338
471
  }
339
472
  });
340
473
 
341
- // packages/runtime/src/functions/runtime/executor.ts
474
+ // ../runtime/src/functions/runtime/executor.ts
342
475
  var init_executor = __esm({
343
- "packages/runtime/src/functions/runtime/executor.ts"() {
476
+ "../runtime/src/functions/runtime/executor.ts"() {
344
477
  "use strict";
345
478
  init_executor_runtime();
346
479
  }
347
480
  });
348
481
 
349
- // packages/runtime/src/functions/domain.ts
482
+ // ../runtime/src/functions/domain.ts
350
483
  var MAX_TOTAL_SOURCE_BYTES, FnError;
351
484
  var init_domain = __esm({
352
- "packages/runtime/src/functions/domain.ts"() {
485
+ "../runtime/src/functions/domain.ts"() {
353
486
  "use strict";
354
487
  MAX_TOTAL_SOURCE_BYTES = 256 * 1024;
355
488
  FnError = class extends Error {
@@ -365,7 +498,7 @@ var init_domain = __esm({
365
498
  }
366
499
  });
367
500
 
368
- // packages/runtime/src/functions/deps/manifest.ts
501
+ // ../runtime/src/functions/deps/manifest.ts
369
502
  import { createHash } from "node:crypto";
370
503
  function isVersionRangeSpec(spec) {
371
504
  if (spec === "*" || spec === "latest") return true;
@@ -446,7 +579,7 @@ function depsKeyOf(dependencies) {
446
579
  }
447
580
  var PACKAGE_NAME_PATTERN, COMPARATOR_PATTERN, MANIFEST_MAX_DEPS;
448
581
  var init_manifest = __esm({
449
- "packages/runtime/src/functions/deps/manifest.ts"() {
582
+ "../runtime/src/functions/deps/manifest.ts"() {
450
583
  "use strict";
451
584
  init_domain();
452
585
  PACKAGE_NAME_PATTERN = /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-._~]+$/;
@@ -455,7 +588,7 @@ var init_manifest = __esm({
455
588
  }
456
589
  });
457
590
 
458
- // packages/runtime/src/functions/deps/resolve.ts
591
+ // ../runtime/src/functions/deps/resolve.ts
459
592
  import { resolve as resolve2 } from "node:path";
460
593
  function resolveExecutionDeps(config, projectId, manifestContent) {
461
594
  const manifest = tryParseManifestDependencies(manifestContent);
@@ -469,13 +602,13 @@ function resolveExecutionDeps(config, projectId, manifestContent) {
469
602
  };
470
603
  }
471
604
  var init_resolve = __esm({
472
- "packages/runtime/src/functions/deps/resolve.ts"() {
605
+ "../runtime/src/functions/deps/resolve.ts"() {
473
606
  "use strict";
474
607
  init_manifest();
475
608
  }
476
609
  });
477
610
 
478
- // packages/runtime/src/functions/runtime/worker-executor.ts
611
+ // ../runtime/src/functions/runtime/worker-executor.ts
479
612
  import { readFileSync } from "node:fs";
480
613
  import { fileURLToPath, pathToFileURL } from "node:url";
481
614
  import { dirname as dirname3, join as join2 } from "node:path";
@@ -518,7 +651,7 @@ function rpcReply(worker, id, ok, payload) {
518
651
  }
519
652
  var WorkerFunctionExecutor;
520
653
  var init_worker_executor = __esm({
521
- "packages/runtime/src/functions/runtime/worker-executor.ts"() {
654
+ "../runtime/src/functions/runtime/worker-executor.ts"() {
522
655
  "use strict";
523
656
  init_executor();
524
657
  init_resolve();
@@ -535,7 +668,7 @@ var init_worker_executor = __esm({
535
668
  const entry = input.entry ?? "index.ts";
536
669
  const deps = this.depsConfig === void 0 ? void 0 : resolveExecutionDeps(this.depsConfig, input.project.id, input.files["package.json"]);
537
670
  const logs = [];
538
- return new Promise((resolve11, reject) => {
671
+ return new Promise((resolve12, reject) => {
539
672
  let worker;
540
673
  try {
541
674
  worker = new Worker(resolveWorkerEntry(), {
@@ -597,7 +730,7 @@ var init_worker_executor = __esm({
597
730
  if (message.type === "result") {
598
731
  clearTimeout(timer);
599
732
  void worker.terminate();
600
- resolve11({ body: message.body, logs });
733
+ resolve12({ body: message.body, logs });
601
734
  return;
602
735
  }
603
736
  if (message.type === "error") {
@@ -632,13 +765,13 @@ var init_worker_executor = __esm({
632
765
  }
633
766
  });
634
767
 
635
- // packages/runtime/src/database/builder/dialect.ts
768
+ // ../runtime/src/database/builder/dialect.ts
636
769
  function dialectFor(driver) {
637
770
  return driver.engine === "pg" ? postgresDialect : sqliteDialect;
638
771
  }
639
772
  var sqliteDialect, postgresDialect;
640
773
  var init_dialect = __esm({
641
- "packages/runtime/src/database/builder/dialect.ts"() {
774
+ "../runtime/src/database/builder/dialect.ts"() {
642
775
  "use strict";
643
776
  sqliteDialect = {
644
777
  name: "sqlite",
@@ -657,7 +790,7 @@ var init_dialect = __esm({
657
790
  }
658
791
  });
659
792
 
660
- // packages/runtime/src/database/provision/identifier.ts
793
+ // ../runtime/src/database/provision/identifier.ts
661
794
  function assertIdentifier(name) {
662
795
  if (!IDENTIFIER_PATTERN.test(name)) {
663
796
  throw new DbError(
@@ -673,7 +806,7 @@ function quoteIdentifier(name) {
673
806
  }
674
807
  var DbError, IDENTIFIER_PATTERN;
675
808
  var init_identifier = __esm({
676
- "packages/runtime/src/database/provision/identifier.ts"() {
809
+ "../runtime/src/database/provision/identifier.ts"() {
677
810
  "use strict";
678
811
  DbError = class extends Error {
679
812
  constructor(status, code, message) {
@@ -687,7 +820,7 @@ var init_identifier = __esm({
687
820
  }
688
821
  });
689
822
 
690
- // packages/runtime/src/database/builder/guards.ts
823
+ // ../runtime/src/database/builder/guards.ts
691
824
  function unsafeOperation(message) {
692
825
  return new DbError(400, "DB_UNSAFE_OP", message);
693
826
  }
@@ -711,13 +844,13 @@ function assertReadOnlyQuery(sql) {
711
844
  }
712
845
  }
713
846
  var init_guards = __esm({
714
- "packages/runtime/src/database/builder/guards.ts"() {
847
+ "../runtime/src/database/builder/guards.ts"() {
715
848
  "use strict";
716
849
  init_identifier();
717
850
  }
718
851
  });
719
852
 
720
- // packages/runtime/src/database/builder/owned.ts
853
+ // ../runtime/src/database/builder/owned.ts
721
854
  function changeLogTable(table) {
722
855
  const name = `${CHANGE_LOG_PREFIX}${table}`;
723
856
  assertIdentifier(name);
@@ -828,7 +961,7 @@ async function readChanges(driver, table, query = {}) {
828
961
  }
829
962
  var OWNED_PK, OWNED_OWNER_KEY, CHANGE_LOG_PREFIX;
830
963
  var init_owned = __esm({
831
- "packages/runtime/src/database/builder/owned.ts"() {
964
+ "../runtime/src/database/builder/owned.ts"() {
832
965
  "use strict";
833
966
  init_identifier();
834
967
  init_dialect();
@@ -839,7 +972,7 @@ var init_owned = __esm({
839
972
  }
840
973
  });
841
974
 
842
- // packages/runtime/src/database/builder/ulid.ts
975
+ // ../runtime/src/database/builder/ulid.ts
843
976
  function encodeTime(now) {
844
977
  let ts = Math.trunc(now);
845
978
  let out = "";
@@ -901,7 +1034,7 @@ function ulid(now = Date.now()) {
901
1034
  }
902
1035
  var ENCODING, TIME_LEN, RANDOM_LEN, lastTime, lastRandom;
903
1036
  var init_ulid = __esm({
904
- "packages/runtime/src/database/builder/ulid.ts"() {
1037
+ "../runtime/src/database/builder/ulid.ts"() {
905
1038
  "use strict";
906
1039
  ENCODING = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
907
1040
  TIME_LEN = 10;
@@ -911,7 +1044,7 @@ var init_ulid = __esm({
911
1044
  }
912
1045
  });
913
1046
 
914
- // packages/runtime/src/database/builder/table.ts
1047
+ // ../runtime/src/database/builder/table.ts
915
1048
  function pushParam(params, dialect, value) {
916
1049
  params.push(value);
917
1050
  return dialect.placeholder(params.length - 1);
@@ -1219,7 +1352,7 @@ function createTableBuilder(table, driver, dialect, options = {}) {
1219
1352
  }
1220
1353
  var OPERATORS, LIST_OPERATORS;
1221
1354
  var init_table = __esm({
1222
- "packages/runtime/src/database/builder/table.ts"() {
1355
+ "../runtime/src/database/builder/table.ts"() {
1223
1356
  "use strict";
1224
1357
  init_identifier();
1225
1358
  init_guards();
@@ -1240,7 +1373,7 @@ var init_table = __esm({
1240
1373
  }
1241
1374
  });
1242
1375
 
1243
- // packages/runtime/src/database/builder/index.ts
1376
+ // ../runtime/src/database/builder/index.ts
1244
1377
  function createCloudDb(driver, options = {}) {
1245
1378
  const dialect = options.dialect ?? dialectFor(driver);
1246
1379
  let txState = TX_STATES.get(driver);
@@ -1294,7 +1427,7 @@ function createCloudDb(driver, options = {}) {
1294
1427
  }
1295
1428
  var TX_STATES;
1296
1429
  var init_builder = __esm({
1297
- "packages/runtime/src/database/builder/index.ts"() {
1430
+ "../runtime/src/database/builder/index.ts"() {
1298
1431
  "use strict";
1299
1432
  init_dialect();
1300
1433
  init_guards();
@@ -1304,7 +1437,7 @@ var init_builder = __esm({
1304
1437
  }
1305
1438
  });
1306
1439
 
1307
- // packages/runtime/src/database/sdk/cloud.ts
1440
+ // ../runtime/src/database/sdk/cloud.ts
1308
1441
  function errorWithCode(error) {
1309
1442
  const code = typeof error === "object" && error !== null && typeof error.code === "string" ? error.code : void 0;
1310
1443
  if (code !== void 0 && error instanceof Error) {
@@ -1400,7 +1533,7 @@ function createDbCapability(driver, options = {}) {
1400
1533
  }
1401
1534
  var CLOUD_DB_SPEC, WRITE_TERMINALS;
1402
1535
  var init_cloud = __esm({
1403
- "packages/runtime/src/database/sdk/cloud.ts"() {
1536
+ "../runtime/src/database/sdk/cloud.ts"() {
1404
1537
  "use strict";
1405
1538
  init_capability_keys();
1406
1539
  init_builder();
@@ -1417,7 +1550,7 @@ var init_cloud = __esm({
1417
1550
  }
1418
1551
  });
1419
1552
 
1420
- // packages/cli/src/sim/sql-engine.ts
1553
+ // src/sim/sql-engine.ts
1421
1554
  function ident(raw) {
1422
1555
  return raw.trim().replace(/^"|"$/g, "").trim();
1423
1556
  }
@@ -1582,7 +1715,7 @@ function project(rows, selectRaw) {
1582
1715
  }
1583
1716
  var SimDbError, ParamCursor, SimSqlEngine;
1584
1717
  var init_sql_engine = __esm({
1585
- "packages/cli/src/sim/sql-engine.ts"() {
1718
+ "src/sim/sql-engine.ts"() {
1586
1719
  "use strict";
1587
1720
  SimDbError = class extends Error {
1588
1721
  constructor(code, message) {
@@ -1841,7 +1974,7 @@ var init_sql_engine = __esm({
1841
1974
  }
1842
1975
  });
1843
1976
 
1844
- // packages/cli/src/sim/db.ts
1977
+ // src/sim/db.ts
1845
1978
  function toProjectDriver(engine) {
1846
1979
  return {
1847
1980
  engine: "sqlite",
@@ -1861,14 +1994,14 @@ function createSimDbCapability(options = {}) {
1861
1994
  return { bundle, engine, driver };
1862
1995
  }
1863
1996
  var init_db = __esm({
1864
- "packages/cli/src/sim/db.ts"() {
1997
+ "src/sim/db.ts"() {
1865
1998
  "use strict";
1866
1999
  init_cloud();
1867
2000
  init_sql_engine();
1868
2001
  }
1869
2002
  });
1870
2003
 
1871
- // packages/runtime/src/storage/driver.ts
2004
+ // ../runtime/src/storage/driver.ts
1872
2005
  function assertSafeStoragePath(path) {
1873
2006
  if (typeof path !== "string" || path.length === 0) {
1874
2007
  throw new StorageError(400, STORAGE_CODES.invalidPath, "\u5B58\u50A8\u8DEF\u5F84\u4E0D\u80FD\u4E3A\u7A7A");
@@ -1896,7 +2029,7 @@ function assertSafeStoragePath(path) {
1896
2029
  }
1897
2030
  var PROJECT_QUOTA_BYTES, StorageError, STORAGE_CODES;
1898
2031
  var init_driver = __esm({
1899
- "packages/runtime/src/storage/driver.ts"() {
2032
+ "../runtime/src/storage/driver.ts"() {
1900
2033
  "use strict";
1901
2034
  PROJECT_QUOTA_BYTES = 1024 * 1024 * 1024;
1902
2035
  StorageError = class extends Error {
@@ -1915,7 +2048,7 @@ var init_driver = __esm({
1915
2048
  }
1916
2049
  });
1917
2050
 
1918
- // packages/runtime/src/storage/hmac-sha256.ts
2051
+ // ../runtime/src/storage/hmac-sha256.ts
1919
2052
  function compress(h, block, w) {
1920
2053
  for (let i = 0; i < 16; i += 1) {
1921
2054
  const j = i * 4;
@@ -2010,7 +2143,7 @@ function hmacSha256Hex(key, message) {
2010
2143
  }
2011
2144
  var K, rotr;
2012
2145
  var init_hmac_sha256 = __esm({
2013
- "packages/runtime/src/storage/hmac-sha256.ts"() {
2146
+ "../runtime/src/storage/hmac-sha256.ts"() {
2014
2147
  "use strict";
2015
2148
  K = new Uint32Array([
2016
2149
  1116352408,
@@ -2082,7 +2215,7 @@ var init_hmac_sha256 = __esm({
2082
2215
  }
2083
2216
  });
2084
2217
 
2085
- // packages/runtime/src/storage/signature.ts
2218
+ // ../runtime/src/storage/signature.ts
2086
2219
  function sign(secret, projectId, path, expires) {
2087
2220
  const payload = `${projectId}|${path}|${expires}`;
2088
2221
  return hmacSha256Hex(secret, payload);
@@ -2095,7 +2228,7 @@ function signDownloadUrl(config, projectId, path, ttlSeconds = DEFAULT_SIGN_TTL_
2095
2228
  }
2096
2229
  var DEFAULT_SIGN_TTL_SECONDS, SIGN_EXPIRES_KEY, SIGN_SIGNATURE_KEY;
2097
2230
  var init_signature = __esm({
2098
- "packages/runtime/src/storage/signature.ts"() {
2231
+ "../runtime/src/storage/signature.ts"() {
2099
2232
  "use strict";
2100
2233
  init_hmac_sha256();
2101
2234
  DEFAULT_SIGN_TTL_SECONDS = 15 * 60;
@@ -2104,7 +2237,7 @@ var init_signature = __esm({
2104
2237
  }
2105
2238
  });
2106
2239
 
2107
- // packages/runtime/src/storage/cloud.ts
2240
+ // ../runtime/src/storage/cloud.ts
2108
2241
  function asBytes(data) {
2109
2242
  if (typeof data === "string") return new TextEncoder().encode(data);
2110
2243
  if (data instanceof ArrayBuffer) return new Uint8Array(data);
@@ -2163,7 +2296,7 @@ function createStorageCapability(driver, signer, projectId) {
2163
2296
  }
2164
2297
  var DEFAULT_VISIBILITY;
2165
2298
  var init_cloud2 = __esm({
2166
- "packages/runtime/src/storage/cloud.ts"() {
2299
+ "../runtime/src/storage/cloud.ts"() {
2167
2300
  "use strict";
2168
2301
  init_capability_keys();
2169
2302
  init_driver();
@@ -2172,7 +2305,7 @@ var init_cloud2 = __esm({
2172
2305
  }
2173
2306
  });
2174
2307
 
2175
- // packages/runtime/src/storage/driver/local.ts
2308
+ // ../runtime/src/storage/driver/local.ts
2176
2309
  import { mkdir as mkdir3, readFile as readFile2, readdir, rm as rm2, stat as stat3, unlink, writeFile as writeFile2 } from "node:fs/promises";
2177
2310
  import { dirname as dirname4, join as join3 } from "node:path";
2178
2311
  function createLocalStorageDriver(options) {
@@ -2379,14 +2512,14 @@ function createLocalStorageDriver(options) {
2379
2512
  }
2380
2513
  var META_SUFFIX;
2381
2514
  var init_local = __esm({
2382
- "packages/runtime/src/storage/driver/local.ts"() {
2515
+ "../runtime/src/storage/driver/local.ts"() {
2383
2516
  "use strict";
2384
2517
  init_driver();
2385
2518
  META_SUFFIX = ".adep-meta.json";
2386
2519
  }
2387
2520
  });
2388
2521
 
2389
- // packages/cli/src/sim/storage.ts
2522
+ // src/sim/storage.ts
2390
2523
  import { join as join4 } from "node:path";
2391
2524
  function createSimStorageCapability(options) {
2392
2525
  const dir = join4(options.cwd, ".adep", "sim", "storage");
@@ -2399,14 +2532,14 @@ function createSimStorageCapability(options) {
2399
2532
  return { bundle, driver };
2400
2533
  }
2401
2534
  var init_storage = __esm({
2402
- "packages/cli/src/sim/storage.ts"() {
2535
+ "src/sim/storage.ts"() {
2403
2536
  "use strict";
2404
2537
  init_cloud2();
2405
2538
  init_local();
2406
2539
  }
2407
2540
  });
2408
2541
 
2409
- // packages/cli/src/sim/realtime.ts
2542
+ // src/sim/realtime.ts
2410
2543
  function realtimeError(code, message) {
2411
2544
  return new Error(`[${code}] ${message}`);
2412
2545
  }
@@ -2487,7 +2620,7 @@ function createSimRealtimeCapability() {
2487
2620
  }
2488
2621
  var SimRealtime, MAX_BUFFERED_MESSAGES, MAX_SUBSCRIPTIONS, REALTIME_CODES;
2489
2622
  var init_realtime = __esm({
2490
- "packages/cli/src/sim/realtime.ts"() {
2623
+ "src/sim/realtime.ts"() {
2491
2624
  "use strict";
2492
2625
  init_capability_keys();
2493
2626
  SimRealtime = class {
@@ -2535,7 +2668,7 @@ var init_realtime = __esm({
2535
2668
  }
2536
2669
  });
2537
2670
 
2538
- // packages/cli/src/sim/runtime.ts
2671
+ // src/sim/runtime.ts
2539
2672
  import { mkdir as mkdir4, readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
2540
2673
  import { dirname as dirname5, join as join5 } from "node:path";
2541
2674
  function simDir(cwd) {
@@ -2600,7 +2733,7 @@ async function createSimRuntime(options) {
2600
2733
  };
2601
2734
  }
2602
2735
  var init_runtime = __esm({
2603
- "packages/cli/src/sim/runtime.ts"() {
2736
+ "src/sim/runtime.ts"() {
2604
2737
  "use strict";
2605
2738
  init_db();
2606
2739
  init_storage();
@@ -2608,7 +2741,7 @@ var init_runtime = __esm({
2608
2741
  }
2609
2742
  });
2610
2743
 
2611
- // packages/cli/src/sim/env.ts
2744
+ // src/sim/env.ts
2612
2745
  import { readFile as readFile4 } from "node:fs/promises";
2613
2746
  import { join as join6 } from "node:path";
2614
2747
  function parseEnv(content) {
@@ -2641,12 +2774,12 @@ async function loadSimEnv(cwd, config = {}) {
2641
2774
  return merged;
2642
2775
  }
2643
2776
  var init_env = __esm({
2644
- "packages/cli/src/sim/env.ts"() {
2777
+ "src/sim/env.ts"() {
2645
2778
  "use strict";
2646
2779
  }
2647
2780
  });
2648
2781
 
2649
- // packages/cli/src/sim/invoke.ts
2782
+ // src/sim/invoke.ts
2650
2783
  function resolveFunctionEntry(files, fnName) {
2651
2784
  const flat = `${fnName}.ts`;
2652
2785
  if (files[flat] !== void 0) return flat;
@@ -2699,15 +2832,15 @@ function createSimInvokeHandler(options) {
2699
2832
  };
2700
2833
  }
2701
2834
  var init_invoke = __esm({
2702
- "packages/cli/src/sim/invoke.ts"() {
2835
+ "src/sim/invoke.ts"() {
2703
2836
  "use strict";
2704
2837
  }
2705
2838
  });
2706
2839
 
2707
- // packages/cli/src/sim/boundary.ts
2840
+ // src/sim/boundary.ts
2708
2841
  var SIM_BOUNDARIES;
2709
2842
  var init_boundary = __esm({
2710
- "packages/cli/src/sim/boundary.ts"() {
2843
+ "src/sim/boundary.ts"() {
2711
2844
  "use strict";
2712
2845
  SIM_BOUNDARIES = [
2713
2846
  {
@@ -2739,7 +2872,59 @@ var init_boundary = __esm({
2739
2872
  }
2740
2873
  });
2741
2874
 
2742
- // packages/cli/src/dev.ts
2875
+ // src/ts-config.ts
2876
+ import { stat as stat4, readFile as readFile5 } from "node:fs/promises";
2877
+ import { join as join7 } from "node:path";
2878
+ async function loadAdepConfigModule(cwd) {
2879
+ const configPath = join7(cwd, "adep.config.ts");
2880
+ try {
2881
+ await stat4(configPath);
2882
+ } catch {
2883
+ return null;
2884
+ }
2885
+ let rawDefault;
2886
+ try {
2887
+ const bun = globalThis.Bun;
2888
+ if (bun !== void 0) {
2889
+ const mod = await import(configPath);
2890
+ rawDefault = mod.default;
2891
+ } else {
2892
+ const { transform } = await import("esbuild");
2893
+ const source = await readFile5(configPath, "utf8");
2894
+ const { code } = await transform(source, {
2895
+ loader: "ts",
2896
+ format: "esm",
2897
+ target: "node22"
2898
+ });
2899
+ const url = `data:text/javascript;base64,${Buffer.from(code).toString("base64")}`;
2900
+ const mod = await import(url);
2901
+ rawDefault = mod.default;
2902
+ }
2903
+ } catch (error) {
2904
+ const reason = error instanceof Error ? error.message : String(error);
2905
+ const message = `adep.config.ts \u52A0\u8F7D\u5931\u8D25\uFF1A${reason}`;
2906
+ process.stderr.write(`\u9519\u8BEF\uFF1A${message}
2907
+ `);
2908
+ throw new Error(message, { cause: error });
2909
+ }
2910
+ const result = parseAdepConfig(rawDefault);
2911
+ if (!result.ok) {
2912
+ const message = `adep.config.ts \u6821\u9A8C\u5931\u8D25\uFF1A
2913
+ ${result.errors.map((e) => ` - ${e}`).join("\n")}`;
2914
+ process.stderr.write(`${message}
2915
+ `);
2916
+ throw new Error(message);
2917
+ }
2918
+ return result.data;
2919
+ }
2920
+ var init_ts_config = __esm({
2921
+ "src/ts-config.ts"() {
2922
+ "use strict";
2923
+ init_adep_config();
2924
+ }
2925
+ });
2926
+
2927
+ // src/dev.ts
2743
2928
  var dev_exports = {};
2744
2929
  __export(dev_exports, {
2745
2930
  loadConfig: () => loadConfig,
@@ -2749,28 +2934,16 @@ __export(dev_exports, {
2749
2934
  });
2750
2935
  import { createServer } from "node:http";
2751
2936
  import { watch } from "node:fs";
2752
- import { mkdir as mkdir5, readdir as readdir2, readFile as readFile5, stat as stat4, writeFile as writeFile4 } from "node:fs/promises";
2753
- import { basename, join as join7, resolve as resolve3 } from "node:path";
2937
+ import { mkdir as mkdir5, readdir as readdir2, readFile as readFile6, writeFile as writeFile4 } from "node:fs/promises";
2938
+ import { basename, join as join8, resolve as resolve3 } from "node:path";
2754
2939
  async function loadConfig(cwd) {
2755
2940
  const name = basename(resolve3(cwd));
2756
- const configPath = join7(cwd, "adep.config.ts");
2757
- try {
2758
- await stat4(configPath);
2759
- } catch {
2760
- return { name, functionsDir: "functions", functionsPrefix: "" };
2761
- }
2762
- const bun = globalThis.Bun;
2763
- if (bun === void 0) return { name, functionsDir: "functions", functionsPrefix: "" };
2764
- try {
2765
- const mod = await import(configPath);
2766
- return {
2767
- name: mod.default?.name ?? name,
2768
- functionsDir: mod.default?.functionsDir ?? "functions",
2769
- functionsPrefix: mod.default?.functions_prefix ?? ""
2770
- };
2771
- } catch {
2772
- return { name, functionsDir: "functions", functionsPrefix: "" };
2773
- }
2941
+ const config = await loadAdepConfigModule(cwd);
2942
+ return {
2943
+ name: config?.name ?? name,
2944
+ functionsDir: config?.functionsDir ?? "functions",
2945
+ functionsPrefix: config?.functions_prefix ?? ""
2946
+ };
2774
2947
  }
2775
2948
  function parseEnvFile(content) {
2776
2949
  const env = {};
@@ -2796,11 +2969,11 @@ async function collectFunctions(dir) {
2796
2969
  }
2797
2970
  for (const entry of entries) {
2798
2971
  const rel = prefix.length === 0 ? entry.name : `${prefix}/${entry.name}`;
2799
- const full = join7(sub, entry.name);
2972
+ const full = join8(sub, entry.name);
2800
2973
  if (entry.isDirectory()) {
2801
2974
  await walk(full, rel);
2802
2975
  } else if (entry.isFile() && entry.name.endsWith(".ts")) {
2803
- files[rel] = await readFile5(full, "utf8");
2976
+ files[rel] = await readFile6(full, "utf8");
2804
2977
  }
2805
2978
  }
2806
2979
  };
@@ -2863,8 +3036,8 @@ function printBoundaries(log) {
2863
3036
  }
2864
3037
  }
2865
3038
  async function ensureGitignore(cwd) {
2866
- const gitignorePath = join7(cwd, ".gitignore");
2867
- const existing = await readFile5(gitignorePath, "utf8").catch(() => "");
3039
+ const gitignorePath = join8(cwd, ".gitignore");
3040
+ const existing = await readFile6(gitignorePath, "utf8").catch(() => "");
2868
3041
  if (existing.split(/\r?\n/).includes(".adep/")) return;
2869
3042
  await writeFile4(gitignorePath, `${existing.replace(/\n+$/, "")}
2870
3043
  .adep/
@@ -2875,7 +3048,10 @@ async function startDevServer(options) {
2875
3048
  const log = options.log ?? ((line) => process.stdout.write(`${line}
2876
3049
  `));
2877
3050
  const config = await loadConfig(cwd);
2878
- const functionsDir = join7(cwd, config.functionsDir);
3051
+ if (options.prefix !== void 0) {
3052
+ config.functionsPrefix = options.prefix.replace(/^\/+|\/+$/g, "");
3053
+ }
3054
+ const functionsDir = join8(cwd, config.functionsDir);
2879
3055
  const coldStartAt = Date.now();
2880
3056
  const executor = new WorkerFunctionExecutor();
2881
3057
  await mkdir5(functionsDir, { recursive: true });
@@ -2893,12 +3069,12 @@ async function startDevServer(options) {
2893
3069
  const reload = async () => {
2894
3070
  const [nextFiles, envText2] = await Promise.all([
2895
3071
  collectFunctions(functionsDir),
2896
- readFile5(join7(cwd, ".env.local"), "utf8").catch(() => "")
3072
+ readFile6(join8(cwd, ".env.local"), "utf8").catch(() => "")
2897
3073
  ]);
2898
3074
  files = nextFiles;
2899
3075
  env = parseEnvFile(envText2);
2900
3076
  };
2901
- const envText = await readFile5(join7(cwd, ".env.local"), "utf8").catch(() => "");
3077
+ const envText = await readFile6(join8(cwd, ".env.local"), "utf8").catch(() => "");
2902
3078
  env = parseEnvFile(envText);
2903
3079
  let debounceTimer;
2904
3080
  let watcher;
@@ -2995,10 +3171,28 @@ async function startDevServer(options) {
2995
3171
  void handle(req, res);
2996
3172
  });
2997
3173
  const port = options.port ?? 8787;
3174
+ const disposeAfterListenError = async () => {
3175
+ if (debounceTimer !== void 0) clearTimeout(debounceTimer);
3176
+ try {
3177
+ watcher?.close();
3178
+ } catch {
3179
+ }
3180
+ try {
3181
+ await executor.dispose();
3182
+ } catch {
3183
+ }
3184
+ try {
3185
+ await runtime.dispose();
3186
+ } catch {
3187
+ }
3188
+ };
2998
3189
  await new Promise((resolveListen, rejectListen) => {
2999
- server.once("error", rejectListen);
3190
+ const onListenError = (error) => {
3191
+ void disposeAfterListenError().finally(() => rejectListen(error));
3192
+ };
3193
+ server.once("error", onListenError);
3000
3194
  server.listen(port, "127.0.0.1", () => {
3001
- server.off("error", rejectListen);
3195
+ server.off("error", onListenError);
3002
3196
  resolveListen();
3003
3197
  });
3004
3198
  });
@@ -3006,8 +3200,9 @@ async function startDevServer(options) {
3006
3200
  const actualPort = typeof address === "object" && address !== null ? address.port : port;
3007
3201
  const baseUrl = `http://127.0.0.1:${actualPort}`;
3008
3202
  const coldStartMs = Date.now() - coldStartAt;
3203
+ const curlPath = config.functionsPrefix.length === 0 ? "/hello" : `/${config.functionsPrefix}/hello`;
3009
3204
  log(`[adep] dev server listening on ${baseUrl}\uFF08\u6A21\u62DF\u8FD0\u884C\u65F6\uFF0C\u51B7\u542F\u52A8 ${coldStartMs}ms\uFF09`);
3010
- log(`[adep] curl \u793A\u4F8B\uFF1Acurl ${baseUrl}/hello`);
3205
+ log(`[adep] curl \u793A\u4F8B\uFF1Acurl ${baseUrl}${curlPath}`);
3011
3206
  printBoundaries(log);
3012
3207
  log(`[adep] \u6A21\u62DF\u6570\u636E\u76EE\u5F55\uFF1A${simDir(cwd)}`);
3013
3208
  return {
@@ -3023,7 +3218,7 @@ async function startDevServer(options) {
3023
3218
  };
3024
3219
  }
3025
3220
  var init_dev = __esm({
3026
- "packages/cli/src/dev.ts"() {
3221
+ "src/dev.ts"() {
3027
3222
  "use strict";
3028
3223
  init_executor();
3029
3224
  init_worker_executor();
@@ -3031,10 +3226,11 @@ var init_dev = __esm({
3031
3226
  init_env();
3032
3227
  init_invoke();
3033
3228
  init_boundary();
3229
+ init_ts_config();
3034
3230
  }
3035
3231
  });
3036
3232
 
3037
- // packages/cli/src/serve/banner.ts
3233
+ // src/serve/banner.ts
3038
3234
  function isLoopback(host) {
3039
3235
  return host === "127.0.0.1" || host === "localhost" || host === "::1" || host === "[::1]";
3040
3236
  }
@@ -3093,12 +3289,12 @@ function renderBanner(options) {
3093
3289
  return lines.join("\n");
3094
3290
  }
3095
3291
  var init_banner = __esm({
3096
- "packages/cli/src/serve/banner.ts"() {
3292
+ "src/serve/banner.ts"() {
3097
3293
  "use strict";
3098
3294
  }
3099
3295
  });
3100
3296
 
3101
- // packages/cli/src/serve/server.ts
3297
+ // src/serve/server.ts
3102
3298
  var server_exports = {};
3103
3299
  __export(server_exports, {
3104
3300
  isLoopback: () => isLoopback,
@@ -3106,8 +3302,8 @@ __export(server_exports, {
3106
3302
  });
3107
3303
  import { createServer as createServer2 } from "node:http";
3108
3304
  import { watch as watch2 } from "node:fs";
3109
- import { mkdir as mkdir6, readdir as readdir3, readFile as readFile6, stat as stat5 } from "node:fs/promises";
3110
- import { join as join8, relative, resolve as resolve4 } from "node:path";
3305
+ import { mkdir as mkdir6, readdir as readdir3, readFile as readFile7, stat as stat5 } from "node:fs/promises";
3306
+ import { join as join9, relative, resolve as resolve4 } from "node:path";
3111
3307
  function envNumber(name) {
3112
3308
  const raw = process.env[name];
3113
3309
  if (raw === void 0 || raw.trim() === "") return void 0;
@@ -3129,11 +3325,11 @@ async function collectFunctions2(dir) {
3129
3325
  }
3130
3326
  for (const entry of entries) {
3131
3327
  const rel = prefix.length === 0 ? entry.name : `${prefix}/${entry.name}`;
3132
- const full = join8(sub, entry.name);
3328
+ const full = join9(sub, entry.name);
3133
3329
  if (entry.isDirectory()) {
3134
3330
  await walk(full, rel);
3135
3331
  } else if (entry.isFile() && entry.name.endsWith(".ts")) {
3136
- files[rel] = await readFile6(full, "utf8");
3332
+ files[rel] = await readFile7(full, "utf8");
3137
3333
  }
3138
3334
  }
3139
3335
  };
@@ -3178,7 +3374,7 @@ async function startServeServer(options) {
3178
3374
  options.staticDir ?? envString("ADEP_SERVE_STATIC_DIR") ?? "public"
3179
3375
  );
3180
3376
  const config = await loadConfig(cwd);
3181
- const functionsDir = join8(cwd, config.functionsDir);
3377
+ const functionsDir = join9(cwd, config.functionsDir);
3182
3378
  let hasStatic = false;
3183
3379
  try {
3184
3380
  const publicStat = await stat5(staticDir);
@@ -3188,7 +3384,7 @@ async function startServeServer(options) {
3188
3384
  }
3189
3385
  let files = await collectFunctions2(functionsDir);
3190
3386
  let functionNames = listFunctionNames(files);
3191
- const envText = await readFile6(join8(cwd, ".env.local"), "utf8").catch(() => "");
3387
+ const envText = await readFile7(join9(cwd, ".env.local"), "utf8").catch(() => "");
3192
3388
  let env = parseEnvFile(envText);
3193
3389
  let simEnv = await loadSimEnv(cwd).catch(() => ({}));
3194
3390
  const runtime = await createSimRuntime({
@@ -3205,7 +3401,7 @@ async function startServeServer(options) {
3205
3401
  const reload = async () => {
3206
3402
  const [nextFiles, envLocalText] = await Promise.all([
3207
3403
  collectFunctions2(functionsDir),
3208
- readFile6(join8(cwd, ".env.local"), "utf8").catch(() => "")
3404
+ readFile7(join9(cwd, ".env.local"), "utf8").catch(() => "")
3209
3405
  ]);
3210
3406
  files = nextFiles;
3211
3407
  env = parseEnvFile(envLocalText);
@@ -3274,16 +3470,16 @@ async function startServeServer(options) {
3274
3470
  const serveStatic = async (pathname, res) => {
3275
3471
  if (!hasStatic) return false;
3276
3472
  const safePath = pathname.replace(/\.\.\//g, "").replace(/^\//, "");
3277
- const filePath = join8(staticDir, safePath);
3278
- const resolvedPath = safePath === "" || safePath === "/" ? join8(filePath, "index.html") : filePath;
3473
+ const filePath = join9(staticDir, safePath);
3474
+ const resolvedPath = safePath === "" || safePath === "/" ? join9(filePath, "index.html") : filePath;
3279
3475
  try {
3280
3476
  const fileStat = await stat5(resolvedPath);
3281
3477
  if (fileStat.isDirectory()) {
3282
- const indexPath = join8(resolvedPath, "index.html");
3478
+ const indexPath = join9(resolvedPath, "index.html");
3283
3479
  try {
3284
3480
  const indexStat = await stat5(indexPath);
3285
3481
  if (indexStat.isFile()) {
3286
- const content2 = await readFile6(indexPath);
3482
+ const content2 = await readFile7(indexPath);
3287
3483
  res.writeHead(200, { "content-type": contentTypeFor(indexPath) });
3288
3484
  res.end(content2);
3289
3485
  return true;
@@ -3292,7 +3488,7 @@ async function startServeServer(options) {
3292
3488
  }
3293
3489
  return false;
3294
3490
  }
3295
- const content = await readFile6(resolvedPath);
3491
+ const content = await readFile7(resolvedPath);
3296
3492
  res.writeHead(200, { "content-type": contentTypeFor(resolvedPath) });
3297
3493
  res.end(content);
3298
3494
  return true;
@@ -3426,7 +3622,7 @@ async function startServeServer(options) {
3426
3622
  }
3427
3623
  var MIME_TYPES;
3428
3624
  var init_server = __esm({
3429
- "packages/cli/src/serve/server.ts"() {
3625
+ "src/serve/server.ts"() {
3430
3626
  "use strict";
3431
3627
  init_executor();
3432
3628
  init_worker_executor();
@@ -3459,7 +3655,7 @@ var init_server = __esm({
3459
3655
  }
3460
3656
  });
3461
3657
 
3462
- // packages/cli/src/client.ts
3658
+ // src/client.ts
3463
3659
  var client_exports = {};
3464
3660
  __export(client_exports, {
3465
3661
  createClient: () => createClient,
@@ -3552,7 +3748,7 @@ async function resolveSlug(cwd, slug) {
3552
3748
  return config.name;
3553
3749
  }
3554
3750
  var init_client = __esm({
3555
- "packages/cli/src/client.ts"() {
3751
+ "src/client.ts"() {
3556
3752
  "use strict";
3557
3753
  init_auth();
3558
3754
  init_credentials();
@@ -3560,15 +3756,15 @@ var init_client = __esm({
3560
3756
  }
3561
3757
  });
3562
3758
 
3563
- // packages/cli/src/deploy.ts
3759
+ // src/deploy.ts
3564
3760
  var deploy_exports = {};
3565
3761
  __export(deploy_exports, {
3566
3762
  collectEntries: () => collectEntries,
3567
3763
  deploy: () => deploy
3568
3764
  });
3569
3765
  import { createHash as createHash2 } from "node:crypto";
3570
- import { readdir as readdir4, readFile as readFile7 } from "node:fs/promises";
3571
- import { join as join9, resolve as resolve5, basename as basename2 } from "node:path";
3766
+ import { readdir as readdir4, readFile as readFile8 } from "node:fs/promises";
3767
+ import { join as join10, resolve as resolve5, basename as basename2 } from "node:path";
3572
3768
  function functionUrlBase(prefix) {
3573
3769
  const raw = (prefix ?? "/api").trim();
3574
3770
  const normalized = raw === "/" ? "/" : raw.replace(/\/+$/, "");
@@ -3584,7 +3780,7 @@ async function collectEntries(functionsDir) {
3584
3780
  return entries;
3585
3781
  }
3586
3782
  for (const name of names) {
3587
- entries[name] = await readFile7(join9(functionsDir, `${name}.ts`), "utf8");
3783
+ entries[name] = await readFile8(join10(functionsDir, `${name}.ts`), "utf8");
3588
3784
  }
3589
3785
  return entries;
3590
3786
  }
@@ -3599,7 +3795,7 @@ async function deploy(paths, options) {
3599
3795
  const cwd = resolve5(options.cwd);
3600
3796
  const config = await loadConfig(cwd);
3601
3797
  const slug = options.slug ?? config.name;
3602
- const functionsDir = options.functionsDir === void 0 ? join9(cwd, config.functionsDir) : resolve5(cwd, options.functionsDir);
3798
+ const functionsDir = options.functionsDir === void 0 ? join10(cwd, config.functionsDir) : resolve5(cwd, options.functionsDir);
3603
3799
  const local = await collectEntries(functionsDir);
3604
3800
  if (Object.keys(local).length === 0) {
3605
3801
  throw new CliError("NO_FUNCTIONS", `${functionsDir} \u4E0B\u6CA1\u6709\u51FD\u6570\u6587\u4EF6`);
@@ -3668,7 +3864,7 @@ async function deploy(paths, options) {
3668
3864
  };
3669
3865
  }
3670
3866
  var init_deploy = __esm({
3671
- "packages/cli/src/deploy.ts"() {
3867
+ "src/deploy.ts"() {
3672
3868
  "use strict";
3673
3869
  init_auth();
3674
3870
  init_client();
@@ -3677,1388 +3873,1396 @@ var init_deploy = __esm({
3677
3873
  }
3678
3874
  });
3679
3875
 
3680
- // packages/cli/src/projects.ts
3681
- var projects_exports = {};
3682
- __export(projects_exports, {
3683
- projectsCreate: () => projectsCreate,
3684
- projectsInfo: () => projectsInfo,
3685
- projectsList: () => projectsList
3876
+ // src/export/client.ts
3877
+ var client_exports2 = {};
3878
+ __export(client_exports2, {
3879
+ createExportApiClient: () => createExportApiClient
3686
3880
  });
3687
- function requireSlug(slug, hint) {
3688
- if (slug === void 0 || slug.trim().length === 0) {
3689
- throw new CliError("INVALID_SLUG", `\u7F3A\u5C11\u9879\u76EE slug\uFF1A${hint}`);
3690
- }
3691
- return slug.trim();
3692
- }
3693
- async function projectsCreate(paths, options) {
3694
- await requireNetworkGuard();
3695
- const client = await createClient(paths);
3696
- const slug = requireSlug(options.slug, "adep projects create <slug>");
3697
- const name = options.name ?? slug;
3698
- const body = { slug, name };
3699
- if (options.spaceId !== void 0) body.spaceId = options.spaceId;
3700
- const created = await client.request(
3701
- "/api/v1/projects",
3702
- { body },
3703
- "PROJECT_CREATE_FAILED"
3704
- );
3705
- if (created.url === void 0 || created.url.length === 0) {
3706
- throw new CliError("PROJECT_CREATE_FAILED", "\u5E73\u53F0\u672A\u8FD4\u56DE\u9879\u76EE\u5730\u5740\uFF0C\u65E0\u6CD5\u8F93\u51FA\u5B50\u57DF URL");
3707
- }
3708
- return created;
3881
+ import { writeFile as writeFile5 } from "node:fs/promises";
3882
+ function toExportJob(view) {
3883
+ return {
3884
+ id: view.id,
3885
+ status: view.status,
3886
+ progress: view.progress,
3887
+ createdAt: view.createdAt,
3888
+ ...view.stage === void 0 ? {} : { stage: view.stage },
3889
+ ...view.error === void 0 ? {} : { error: view.error },
3890
+ ...view.downloadUrl === void 0 ? {} : { downloadUrl: view.downloadUrl },
3891
+ ...view.bundleSize === void 0 ? {} : { bundleSize: view.bundleSize },
3892
+ ...view.completedAt === void 0 ? {} : { completedAt: view.completedAt }
3893
+ };
3709
3894
  }
3710
- async function projectsList(paths) {
3711
- await requireNetworkGuard();
3895
+ async function createExportApiClient(paths) {
3712
3896
  const client = await createClient(paths);
3713
- const result = await client.request(
3714
- "/api/v1/projects",
3715
- {},
3716
- "PROJECT_LIST_FAILED"
3717
- );
3718
- return result.projects;
3719
- }
3720
- async function projectsInfo(paths, options) {
3721
- await requireNetworkGuard();
3722
- const slug = requireSlug(options.slug, "adep projects info <slug>");
3723
- const projects = await projectsList(paths);
3724
- const match = projects.find((project2) => project2.slug === slug);
3725
- if (match === void 0) {
3726
- throw new CliError("PROJECT_NOT_FOUND", `\u9879\u76EE "${slug}" \u4E0D\u5B58\u5728\u6216\u4F60\u6CA1\u6709\u8BBF\u95EE\u6743\u9650`);
3727
- }
3728
- return match;
3729
- }
3730
- async function requireNetworkGuard() {
3731
- const { requireNetwork: requireNetwork2 } = await Promise.resolve().then(() => (init_net(), net_exports));
3732
- await requireNetwork2("adep projects");
3897
+ return {
3898
+ async triggerExport(projectId, options) {
3899
+ const view = await client.request(
3900
+ `/api/v1/projects/${encodeURIComponent(projectId)}/export`,
3901
+ {
3902
+ method: "POST",
3903
+ body: {
3904
+ withData: options.withData,
3905
+ withSource: options.withSource,
3906
+ ...options.withoutSource === true ? { withoutSource: true } : {}
3907
+ }
3908
+ },
3909
+ "EXPORT_TRIGGER_FAILED"
3910
+ );
3911
+ return toExportJob(view);
3912
+ },
3913
+ async getJobStatus(jobId) {
3914
+ const view = await client.request(
3915
+ `/api/v1/exports/${encodeURIComponent(jobId)}`,
3916
+ {},
3917
+ "EXPORT_STATUS_FAILED"
3918
+ );
3919
+ return toExportJob(view);
3920
+ },
3921
+ async downloadBundle(jobId, outputPath) {
3922
+ const download = await client.request(
3923
+ `/api/v1/exports/${encodeURIComponent(jobId)}/download`,
3924
+ {},
3925
+ "EXPORT_DOWNLOAD_FAILED"
3926
+ );
3927
+ if (download.downloadUrl.length === 0) {
3928
+ throw new CliError("EXPORT_BUNDLE_UNAVAILABLE", "\u5BFC\u51FA\u4EA7\u7269\u4E0B\u8F7D URL \u4E3A\u7A7A\uFF0C\u4EA7\u7269\u53EF\u80FD\u5C1A\u4E0D\u53EF\u7528");
3929
+ }
3930
+ const response = await client.download(download.downloadUrl, "EXPORT_DOWNLOAD_FAILED");
3931
+ const bytes = Buffer.from(await response.arrayBuffer());
3932
+ await writeFile5(outputPath, bytes);
3933
+ return { path: outputPath, size: bytes.length };
3934
+ }
3935
+ };
3733
3936
  }
3734
- var init_projects = __esm({
3735
- "packages/cli/src/projects.ts"() {
3937
+ var init_client2 = __esm({
3938
+ "src/export/client.ts"() {
3736
3939
  "use strict";
3737
3940
  init_auth();
3738
3941
  init_client();
3739
3942
  }
3740
3943
  });
3741
3944
 
3742
- // packages/cli/src/functions.ts
3743
- var functions_exports = {};
3744
- __export(functions_exports, {
3745
- functionsDeploy: () => functionsDeploy,
3746
- functionsList: () => functionsList,
3747
- functionsLogs: () => functionsLogs
3748
- });
3749
- import { resolve as resolve6 } from "node:path";
3750
- async function functionsDeploy(paths, options) {
3751
- const startedAt = Date.now();
3752
- const result = await deploy(paths, {
3753
- cwd: options.cwd,
3754
- ...options.slug === void 0 ? {} : { slug: options.slug },
3755
- ...options.dir === void 0 ? {} : { functionsDir: resolve6(options.cwd, options.dir) },
3756
- silent: true
3757
- });
3758
- return { ...result, elapsedSeconds: (Date.now() - startedAt) / 1e3 };
3945
+ // ../../shared/deploy-bundle/zip.ts
3946
+ function zipRead(buf) {
3947
+ const r = new Reader(buf);
3948
+ const eocd = findEocd(buf);
3949
+ if (eocd < 0) throw new ZipFormatError("\u627E\u4E0D\u5230 EOCD \u7B7E\u540D");
3950
+ const total = r.u16(eocd + 10);
3951
+ const centralOffset = r.u32(eocd + 16);
3952
+ const decoder = new TextDecoder();
3953
+ const out = /* @__PURE__ */ new Map();
3954
+ let cursor = centralOffset;
3955
+ for (let i = 0; i < total; i++) {
3956
+ if (cursor + 46 > buf.length) throw new ZipFormatError("\u4E2D\u592E\u76EE\u5F55\u8BB0\u5F55\u8D8A\u754C");
3957
+ if (r.u32(cursor) !== SIG_CENTRAL) throw new ZipFormatError("\u4E2D\u592E\u76EE\u5F55\u7B7E\u540D\u4E0D\u5339\u914D");
3958
+ const method = r.u16(cursor + 10);
3959
+ if (method !== 0) throw new ZipFormatError("\u4EC5\u652F\u6301 store \u578B\u6761\u76EE\u8BFB\u53D6");
3960
+ const compSize = r.u32(cursor + 20);
3961
+ const nameLen = r.u16(cursor + 28);
3962
+ const extraLen = r.u16(cursor + 30);
3963
+ const commentLen = r.u16(cursor + 32);
3964
+ const localHeaderOffset = r.u32(cursor + 42);
3965
+ if (localHeaderOffset + 30 > buf.length) throw new ZipFormatError("\u672C\u5730\u5934\u504F\u79FB\u8D8A\u754C");
3966
+ const name = decoder.decode(r.slice(cursor + 46, nameLen));
3967
+ const localNameLen = r.u16(localHeaderOffset + 26);
3968
+ const localExtraLen = r.u16(localHeaderOffset + 28);
3969
+ const dataStart = localHeaderOffset + 30 + localNameLen + localExtraLen;
3970
+ if (dataStart + compSize > buf.length) throw new ZipFormatError("\u6761\u76EE\u6570\u636E\u8D8A\u754C");
3971
+ if (!out.has(name)) out.set(name, r.slice(dataStart, compSize));
3972
+ cursor += 46 + nameLen + extraLen + commentLen;
3973
+ }
3974
+ return out;
3759
3975
  }
3760
- async function functionsList(paths, options) {
3761
- const client = await createClient(paths);
3762
- const project2 = await resolveProject(client, options);
3763
- const result = await client.request(
3764
- `/api/v1/projects/${project2.id}/functions`,
3765
- {},
3766
- "FUNCTION_LIST_FAILED"
3767
- );
3768
- const prefix = project2.functionsPrefix ?? "/api";
3769
- const prefixBase = prefix.trim() === "/" ? "" : prefix.trim().replace(/\/+$/, "");
3770
- return {
3771
- projectId: project2.id,
3772
- slug: project2.slug,
3773
- baseUrl: `${project2.url.replace(/\/+$/, "")}${prefixBase}`,
3774
- functions: result.functions
3775
- };
3776
- }
3777
- async function functionsLogs(paths, options) {
3778
- if (options.name === void 0 || options.name.trim().length === 0) {
3779
- throw new CliError("INVALID_ARGUMENT", "\u7F3A\u5C11\u51FD\u6570\u540D\uFF1Aadep functions logs <name>");
3780
- }
3781
- const client = await createClient(paths);
3782
- const project2 = await resolveProject(client, options);
3783
- const listed = await client.request(
3784
- `/api/v1/projects/${project2.id}/functions`,
3785
- {},
3786
- "FUNCTION_LIST_FAILED"
3787
- );
3788
- const target = listed.functions.find((fn) => fn.name === options.name);
3789
- if (target === void 0) {
3790
- throw new CliError("FN_NOT_FOUND", `\u51FD\u6570 "${options.name}" \u4E0D\u5B58\u5728\u4E8E\u9879\u76EE "${project2.slug}"`);
3791
- }
3792
- const tail = options.tail === void 0 ? "" : `?tail=${encodeURIComponent(String(options.tail))}`;
3793
- const result = await client.request(
3794
- `/api/v1/functions/${target.id}/logs${tail}`,
3795
- {},
3796
- "FUNCTION_LOGS_FAILED"
3797
- );
3798
- return { functionId: target.id, name: target.name, logs: result.logs };
3799
- }
3800
- async function resolveProject(client, options) {
3801
- const slug = await resolveSlug(resolve6(options.cwd), options.slug);
3802
- const projects = await projectsListFrom(client);
3803
- const match = projects.find((project2) => project2.slug === slug);
3804
- if (match === void 0) {
3805
- throw new CliError(
3806
- "PROJECT_NOT_FOUND",
3807
- `\u5E73\u53F0\u9879\u76EE "${slug}" \u4E0D\u5B58\u5728\u6216\u4F60\u6CA1\u6709\u8BBF\u95EE\u6743\u9650\uFF1A\u5148\u6267\u884C adep projects create ${slug}`
3808
- );
3976
+ function findEocd(buf) {
3977
+ const view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
3978
+ const min = Math.max(0, buf.length - 65557);
3979
+ for (let i = buf.length - 22; i >= min; i--) {
3980
+ if (view.getUint32(i, true) === SIG_EOCD) return i;
3809
3981
  }
3810
- return match;
3811
- }
3812
- async function projectsListFrom(client) {
3813
- const result = await client.request("/api/v1/projects", {}, "PROJECT_LIST_FAILED");
3814
- return result.projects;
3982
+ return -1;
3815
3983
  }
3816
- var init_functions = __esm({
3817
- "packages/cli/src/functions.ts"() {
3984
+ var SIG_CENTRAL, SIG_EOCD, CRC_TABLE, Reader, ZipFormatError;
3985
+ var init_zip = __esm({
3986
+ "../../shared/deploy-bundle/zip.ts"() {
3818
3987
  "use strict";
3819
- init_auth();
3820
- init_client();
3821
- init_deploy();
3988
+ SIG_CENTRAL = 33639248;
3989
+ SIG_EOCD = 101010256;
3990
+ CRC_TABLE = (() => {
3991
+ const table = new Uint32Array(256);
3992
+ for (let i = 0; i < 256; i++) {
3993
+ let c = i;
3994
+ for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
3995
+ table[i] = c >>> 0;
3996
+ }
3997
+ return table;
3998
+ })();
3999
+ Reader = class {
4000
+ constructor(buf) {
4001
+ this.buf = buf;
4002
+ this.view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
4003
+ }
4004
+ view;
4005
+ u16(offset) {
4006
+ return this.view.getUint16(offset, true);
4007
+ }
4008
+ u32(offset) {
4009
+ return this.view.getUint32(offset, true);
4010
+ }
4011
+ slice(start, length) {
4012
+ return this.buf.subarray(start, start + length);
4013
+ }
4014
+ };
4015
+ ZipFormatError = class extends Error {
4016
+ constructor(message) {
4017
+ super(`[appexport] \u975E\u6CD5 zip\uFF1A${message}`);
4018
+ this.name = "ZipFormatError";
4019
+ }
4020
+ };
3822
4021
  }
3823
4022
  });
3824
4023
 
3825
- // packages/cli/src/mcp.ts
3826
- var mcp_exports = {};
3827
- __export(mcp_exports, {
3828
- mcpList: () => mcpList,
3829
- mcpPublish: () => mcpPublish,
3830
- mcpUnpublish: () => mcpUnpublish
4024
+ // src/export/fs.ts
4025
+ var fs_exports = {};
4026
+ __export(fs_exports, {
4027
+ createExportFileSystem: () => createExportFileSystem
3831
4028
  });
3832
- import { resolve as resolve7 } from "node:path";
3833
- async function mcpPublish(paths, options) {
3834
- const fn = requireFunctionName(options.fn);
3835
- const client = await createClient(paths);
3836
- const project2 = await resolveProject2(client, options);
3837
- const target = await resolveFunction(client, project2, fn);
3838
- const body = {};
3839
- if (options.toolName !== void 0 && options.toolName.trim().length > 0) {
3840
- body.toolName = options.toolName.trim();
3841
- }
3842
- if (options.description !== void 0 && options.description.length > 0) {
3843
- body.description = options.description;
3844
- }
3845
- const tool = await client.request(
3846
- `/api/v1/functions/${target.id}/mcp-publish`,
3847
- { method: "POST", ...Object.keys(body).length === 0 ? {} : { body } },
3848
- "MCP_PUBLISH_FAILED"
3849
- );
3850
- return { projectId: project2.id, tool };
3851
- }
3852
- async function mcpUnpublish(paths, options) {
3853
- const fn = requireFunctionName(options.fn);
3854
- const client = await createClient(paths);
3855
- const project2 = await resolveProject2(client, options);
3856
- const target = await resolveFunction(client, project2, fn);
3857
- const toolName = options.toolName?.trim() || fn;
3858
- const result = await client.request(
3859
- `/api/v1/functions/${target.id}/mcp-publish?tool=${encodeURIComponent(toolName)}`,
3860
- { method: "DELETE" },
3861
- "MCP_UNPUBLISH_FAILED"
3862
- );
3863
- return { projectId: project2.id, toolName, removed: result.unpublished === true };
3864
- }
3865
- async function mcpList(paths, options) {
3866
- const client = await createClient(paths);
3867
- const project2 = await resolveProject2(client, options);
3868
- const prefix = project2.functionsPrefix ?? "/api";
3869
- const prefixBase = prefix.trim() === "/" ? "" : prefix.trim().replace(/\/+$/, "");
3870
- const endpoint = `${project2.url.replace(/\/+$/, "")}${prefixBase}/mcp`;
3871
- let response;
3872
- try {
3873
- response = await fetch(endpoint, {
3874
- method: "POST",
3875
- headers: { "content-type": "application/json", cookie: client.cookie },
3876
- body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "tools/list" })
3877
- });
3878
- } catch (error) {
3879
- throw new CliError(
3880
- "SERVER_UNREACHABLE",
3881
- `\u65E0\u6CD5\u8FDE\u63A5 MCP \u7AEF\u70B9 ${endpoint}\uFF1A${error instanceof Error ? error.message : String(error)}`
3882
- );
3883
- }
3884
- const parsed = await response.json().catch(() => null);
3885
- if (!response.ok) {
3886
- const envelope = parsed ?? null;
3887
- throw new CliError(
3888
- envelope?.error?.code ?? "MCP_LIST_FAILED",
3889
- envelope?.error?.message ?? `MCP \u7AEF\u70B9\u8FD4\u56DE HTTP ${response.status}`
3890
- );
3891
- }
3892
- const rpcError = parsed?.error;
3893
- if (rpcError !== void 0) {
3894
- throw new CliError(
3895
- rpcError.code ?? "MCP_LIST_FAILED",
3896
- rpcError.message ?? "MCP tools/list \u5931\u8D25"
3897
- );
3898
- }
3899
- return {
3900
- projectId: project2.id,
3901
- slug: project2.slug,
3902
- endpoint,
3903
- tools: parsed?.result?.tools ?? []
3904
- };
3905
- }
3906
- function requireFunctionName(fn) {
3907
- if (fn === void 0 || fn.trim().length === 0) {
3908
- throw new CliError("INVALID_ARGUMENT", "\u7F3A\u5C11\u51FD\u6570\u540D\uFF1Aadep mcp publish --function <fn>");
3909
- }
3910
- return fn.trim();
3911
- }
3912
- async function resolveProject2(client, options) {
3913
- const slug = await resolveSlug(resolve7(options.cwd), options.slug);
3914
- const listed = await client.request("/api/v1/projects", {}, "PROJECT_LIST_FAILED");
3915
- const match = listed.projects.find((project2) => project2.slug === slug);
3916
- if (match === void 0) {
3917
- throw new CliError(
3918
- "PROJECT_NOT_FOUND",
3919
- `\u5E73\u53F0\u9879\u76EE "${slug}" \u4E0D\u5B58\u5728\u6216\u4F60\u6CA1\u6709\u8BBF\u95EE\u6743\u9650\uFF1A\u5148\u6267\u884C adep projects create ${slug}`
3920
- );
3921
- }
4029
+ import { mkdir as mkdir7, readFile as readFile9, rm as rm3, stat as stat6, writeFile as writeFile6 } from "node:fs/promises";
4030
+ import { dirname as dirname6, join as join11 } from "node:path";
4031
+ function createExportFileSystem() {
3922
4032
  return {
3923
- id: match.id,
3924
- slug: match.slug,
3925
- url: match.url,
3926
- ...match.functionsPrefix === void 0 ? {} : { functionsPrefix: match.functionsPrefix }
4033
+ readFile: (path) => readFile9(path),
4034
+ writeFile: (path, content) => writeFile6(path, content),
4035
+ // 同时用于清理解压临时目录(${zip}.tmp 是个目录)——递归强制删除,缺失不报错。
4036
+ deleteFile: async (path) => {
4037
+ await rm3(path, { recursive: true, force: true });
4038
+ },
4039
+ fileExists: async (path) => {
4040
+ try {
4041
+ await stat6(path);
4042
+ return true;
4043
+ } catch {
4044
+ return false;
4045
+ }
4046
+ },
4047
+ mkdir: async (path) => {
4048
+ await mkdir7(path, { recursive: true });
4049
+ },
4050
+ unzip: async (zipPath, targetDir) => {
4051
+ const entries = zipRead(await readFile9(zipPath));
4052
+ for (const [name, data] of entries) {
4053
+ const dest = join11(targetDir, name);
4054
+ await mkdir7(dirname6(dest), { recursive: true });
4055
+ await writeFile6(dest, data);
4056
+ }
4057
+ }
3927
4058
  };
3928
4059
  }
3929
- async function resolveFunction(client, project2, name) {
3930
- const listed = await client.request(`/api/v1/projects/${project2.id}/functions`, {}, "FUNCTION_LIST_FAILED");
3931
- const target = listed.functions.find((fn) => fn.name === name);
3932
- if (target === void 0) {
3933
- throw new CliError("FN_NOT_FOUND", `\u51FD\u6570 "${name}" \u4E0D\u5B58\u5728\u4E8E\u9879\u76EE "${project2.slug}"`);
3934
- }
3935
- return { id: target.id, name: target.name };
3936
- }
3937
- var init_mcp = __esm({
3938
- "packages/cli/src/mcp.ts"() {
4060
+ var init_fs = __esm({
4061
+ "src/export/fs.ts"() {
3939
4062
  "use strict";
3940
- init_auth();
3941
- init_client();
4063
+ init_zip();
3942
4064
  }
3943
4065
  });
3944
4066
 
3945
- // packages/cli/src/doctor.ts
3946
- var doctor_exports = {};
3947
- __export(doctor_exports, {
3948
- formatDoctorReport: () => formatDoctorReport,
3949
- runDoctor: () => runDoctor
4067
+ // ../../shared/deploy-bundle/manifest.ts
4068
+ var CURRENT_SCHEMA_VERSION, BundleContentKind, ALLOWED_CONTENT_KINDS;
4069
+ var init_manifest2 = __esm({
4070
+ "../../shared/deploy-bundle/manifest.ts"() {
4071
+ "use strict";
4072
+ CURRENT_SCHEMA_VERSION = 2;
4073
+ BundleContentKind = {
4074
+ /** 云函数代码与配置。 */
4075
+ Functions: "functions",
4076
+ /** 数据库 schema 与种子数据。 */
4077
+ Database: "database",
4078
+ /** 前端静态资源。 */
4079
+ Web: "web",
4080
+ /** 运行时配置(Dockerfile / docker-compose.yml)。 */
4081
+ Runtime: "runtime",
4082
+ /** 启动 / 备份 / 恢复脚本。 */
4083
+ Scripts: "scripts",
4084
+ /** 文档(README / 部署手册)。 */
4085
+ Docs: "docs"
4086
+ };
4087
+ ALLOWED_CONTENT_KINDS = Object.values(BundleContentKind);
4088
+ }
3950
4089
  });
3951
- import { stat as stat6 } from "node:fs/promises";
3952
- async function probeServer(server) {
3953
- const controller = new AbortController();
3954
- const timer = setTimeout(() => controller.abort(), SERVER_PROBE_TIMEOUT_MS);
3955
- try {
3956
- const response = await fetch(`${server}/api/v1/health`, { signal: controller.signal });
3957
- return { reachable: true, status: response.status };
3958
- } catch (error) {
4090
+
4091
+ // ../../shared/deploy-bundle/validate.ts
4092
+ function validateBundleManifest(manifest) {
4093
+ const errors = [];
4094
+ const warnings = [];
4095
+ if (typeof manifest !== "object" || manifest === null) {
3959
4096
  return {
3960
- reachable: false,
3961
- error: error instanceof Error ? error.message : String(error)
4097
+ valid: false,
4098
+ errors: [{ code: "INVALID_TYPE", message: "Manifest \u5FC5\u987B\u662F\u5BF9\u8C61" }],
4099
+ warnings: []
3962
4100
  };
3963
- } finally {
3964
- clearTimeout(timer);
3965
4101
  }
3966
- }
3967
- async function credentialMode(file) {
3968
- try {
3969
- const info = await stat6(file);
3970
- return (info.mode & 511).toString(8).padStart(3, "0");
3971
- } catch {
3972
- return void 0;
4102
+ const m = manifest;
4103
+ const schemaVersion = m.schemaVersion;
4104
+ if (typeof schemaVersion !== "number" || !Number.isInteger(schemaVersion)) {
4105
+ errors.push({
4106
+ code: "INVALID_SCHEMA_VERSION",
4107
+ message: "schemaVersion \u5FC5\u987B\u662F\u6574\u6570",
4108
+ field: "schemaVersion"
4109
+ });
4110
+ } else if (schemaVersion > CURRENT_SCHEMA_VERSION) {
4111
+ errors.push({
4112
+ code: "SCHEMA_VERSION_TOO_HIGH",
4113
+ message: `schemaVersion ${schemaVersion} \u9AD8\u4E8E\u5F53\u524D\u652F\u6301\u7248\u672C ${CURRENT_SCHEMA_VERSION}\uFF0C\u9700\u5347\u7EA7\u5BFC\u51FA\u7AEF`,
4114
+ field: "schemaVersion"
4115
+ });
4116
+ } else if (schemaVersion < CURRENT_SCHEMA_VERSION) {
4117
+ warnings.push({
4118
+ code: "SCHEMA_VERSION_LOW",
4119
+ message: `schemaVersion ${schemaVersion} \u4F4E\u4E8E\u5F53\u524D\u7248\u672C ${CURRENT_SCHEMA_VERSION}\uFF0C\u5EFA\u8BAE\u91CD\u65B0\u5BFC\u51FA`,
4120
+ field: "schemaVersion"
4121
+ });
3973
4122
  }
3974
- }
3975
- async function runDoctor(paths) {
3976
- const credentials = await loadCredentials(paths);
3977
- const server = credentials?.server ?? resolveServer();
3978
- const mode = await credentialMode(paths.credentialsFile);
3979
- const offline = await isOffline();
3980
- const health = await probeServer(server);
3981
- const report = {
3982
- server,
3983
- credentials: {
3984
- file: paths.credentialsFile,
3985
- present: credentials !== null,
3986
- ...mode === void 0 ? {} : { mode }
3987
- },
3988
- network: { offline },
3989
- serverHealth: health,
3990
- offlineCommands: [...OFFLINE_COMMANDS],
3991
- boundaries: SIM_BOUNDARIES.map((b) => ({ kind: b.kind, title: b.title, detail: b.detail }))
3992
- };
3993
- if (credentials !== null) report.credentials.email = credentials.email;
3994
- if (mode !== void 0 && mode !== "600") {
3995
- report.credentials.warning = `\u6743\u9650 ${mode} \u5BBD\u4E8E 0600\uFF0C\u5EFA\u8BAE chmod 600 ${paths.credentialsFile}`;
4123
+ if (typeof m.platformVersion !== "string" || m.platformVersion.trim() === "") {
4124
+ errors.push({
4125
+ code: "MISSING_PLATFORM_VERSION",
4126
+ message: "platformVersion \u5FC5\u987B\u975E\u7A7A",
4127
+ field: "platformVersion"
4128
+ });
3996
4129
  }
3997
- return report;
3998
- }
3999
- function formatDoctorReport(report) {
4000
- const lines = ["adep doctor \xB7 \u73AF\u5883\u81EA\u68C0", ""];
4001
- lines.push("\u51ED\u636E\u4E0E\u8EAB\u4EFD");
4002
- if (report.credentials.present) {
4003
- lines.push(` \u2713 \u5DF2\u767B\u5F55 ${report.credentials.email ?? "(\u672A\u77E5\u90AE\u7BB1)"} @ ${report.server}`);
4004
- lines.push(
4005
- ` \xB7 \u51ED\u636E\u6587\u4EF6 ${report.credentials.file}\uFF08${report.credentials.mode ?? "\u6743\u9650\u672A\u77E5"}\uFF09`
4006
- );
4007
- if (report.credentials.warning !== void 0) lines.push(` ! ${report.credentials.warning}`);
4130
+ if (typeof m.project !== "object" || m.project === null) {
4131
+ errors.push({
4132
+ code: "MISSING_PROJECT",
4133
+ message: "project \u5FC5\u987B\u662F\u5BF9\u8C61",
4134
+ field: "project"
4135
+ });
4008
4136
  } else {
4009
- lines.push(` \u2717 \u672A\u767B\u5F55\uFF08\u65E0 ${report.credentials.file}\uFF09`);
4010
- lines.push(" \u63D0\u793A\uFF1A\u5148\u6267\u884C adep login");
4137
+ const project2 = m.project;
4138
+ if (typeof project2.id !== "string" || project2.id.trim() === "") {
4139
+ errors.push({
4140
+ code: "MISSING_PROJECT_ID",
4141
+ message: "project.id \u5FC5\u987B\u975E\u7A7A",
4142
+ field: "project.id"
4143
+ });
4144
+ }
4145
+ if (typeof project2.name !== "string" || project2.name.trim() === "") {
4146
+ errors.push({
4147
+ code: "MISSING_PROJECT_NAME",
4148
+ message: "project.name \u5FC5\u987B\u975E\u7A7A",
4149
+ field: "project.name"
4150
+ });
4151
+ }
4152
+ if (typeof project2.slug !== "string" || project2.slug.trim() === "") {
4153
+ errors.push({
4154
+ code: "MISSING_PROJECT_SLUG",
4155
+ message: "project.slug \u5FC5\u987B\u975E\u7A7A",
4156
+ field: "project.slug"
4157
+ });
4158
+ }
4159
+ if (typeof project2.version !== "number" || !Number.isInteger(project2.version) || project2.version < 1) {
4160
+ errors.push({
4161
+ code: "INVALID_PROJECT_VERSION",
4162
+ message: "project.version \u5FC5\u987B\u662F\u6B63\u6574\u6570",
4163
+ field: "project.version"
4164
+ });
4165
+ }
4011
4166
  }
4012
- lines.push("", "\u7F51\u7EDC\u4E0E\u670D\u52A1\u7AEF");
4013
- lines.push(
4014
- report.network.offline ? " \u2717 \u5916\u7F51\u4E0D\u53EF\u8FBE\uFF08\u4F9D\u8D56\u5B89\u88C5 / \u90E8\u7F72\u7B49\u547D\u4EE4\u5C06\u660E\u786E\u5931\u8D25\uFF09" : " \u2713 \u5916\u7F51\u53EF\u8FBE"
4015
- );
4016
- if (report.serverHealth.reachable) {
4017
- lines.push(` \u2713 \u5E73\u53F0\u53EF\u8FBE ${report.server}\uFF08/api/v1/health \u2192 ${report.serverHealth.status}\uFF09`);
4167
+ if (!Array.isArray(m.contents)) {
4168
+ errors.push({
4169
+ code: "MISSING_CONTENTS",
4170
+ message: "contents \u5FC5\u987B\u662F\u6570\u7EC4",
4171
+ field: "contents"
4172
+ });
4173
+ } else if (m.contents.length === 0) {
4174
+ errors.push({
4175
+ code: "EMPTY_CONTENTS",
4176
+ message: "contents \u4E0D\u80FD\u4E3A\u7A7A",
4177
+ field: "contents"
4178
+ });
4018
4179
  } else {
4019
- lines.push(
4020
- ` \u2717 \u5E73\u53F0\u4E0D\u53EF\u8FBE ${report.server}\uFF1A${report.serverHealth.error ?? "\u65E0\u5E94\u7B54"}`,
4021
- " \u63D0\u793A\uFF1A\u68C0\u67E5 ADEP_SERVER / \u767B\u5F55\u65F6\u7684 --server\uFF0C\u6216\u5148\u8D77\u672C\u5730 pnpm run dev"
4022
- );
4180
+ m.contents.forEach((content, index) => {
4181
+ validateContent(content, index, errors, warnings);
4182
+ });
4023
4183
  }
4024
- lines.push("", "\u79BB\u7EBF\u53EF\u7528\u8303\u56F4\uFF08\u65AD\u7F51\u65F6\u4ECD\u53EF\u6267\u884C\uFF09");
4025
- for (const command of report.offlineCommands) lines.push(` \xB7 ${command}`);
4026
- lines.push("", "\u672C\u5730\u6A21\u62DF\u8FD0\u884C\u65F6\u7684\u80FD\u529B\u8FB9\u754C\uFF08\u4E0E adep dev \u542F\u52A8\u6A2A\u5E45\u540C\u6E90\uFF09");
4027
- for (const boundary of report.boundaries) {
4028
- lines.push(` \xB7 [${boundary.kind}] ${boundary.title}\uFF1A${boundary.detail}`);
4184
+ if (typeof m.runtime !== "object" || m.runtime === null) {
4185
+ errors.push({
4186
+ code: "MISSING_RUNTIME",
4187
+ message: "runtime \u5FC5\u987B\u662F\u5BF9\u8C61",
4188
+ field: "runtime"
4189
+ });
4190
+ } else {
4191
+ const runtime = m.runtime;
4192
+ if (typeof runtime.engine !== "string" || runtime.engine.trim() === "") {
4193
+ errors.push({
4194
+ code: "MISSING_ENGINE",
4195
+ message: "runtime.engine \u5FC5\u987B\u975E\u7A7A",
4196
+ field: "runtime.engine"
4197
+ });
4198
+ }
4199
+ if (typeof runtime.engineVersion !== "string" || runtime.engineVersion.trim() === "") {
4200
+ errors.push({
4201
+ code: "MISSING_ENGINE_VERSION",
4202
+ message: "runtime.engineVersion \u5FC5\u987B\u975E\u7A7A",
4203
+ field: "runtime.engineVersion"
4204
+ });
4205
+ }
4206
+ if (typeof runtime.port !== "number" || !Number.isInteger(runtime.port) || runtime.port < 1 || runtime.port > 65535) {
4207
+ errors.push({
4208
+ code: "INVALID_PORT",
4209
+ message: "runtime.port \u5FC5\u987B\u662F 1-65535 \u7684\u6574\u6570",
4210
+ field: "runtime.port"
4211
+ });
4212
+ }
4213
+ if (typeof runtime.startCommand !== "string" || runtime.startCommand.trim() === "") {
4214
+ errors.push({
4215
+ code: "MISSING_START_COMMAND",
4216
+ message: "runtime.startCommand \u5FC5\u987B\u975E\u7A7A",
4217
+ field: "runtime.startCommand"
4218
+ });
4219
+ }
4029
4220
  }
4030
- return lines;
4031
- }
4032
- var SERVER_PROBE_TIMEOUT_MS, OFFLINE_COMMANDS;
4033
- var init_doctor = __esm({
4034
- "packages/cli/src/doctor.ts"() {
4035
- "use strict";
4036
- init_credentials();
4037
- init_config();
4038
- init_boundary();
4039
- init_net();
4040
- SERVER_PROBE_TIMEOUT_MS = 5e3;
4041
- OFFLINE_COMMANDS = [
4042
- "adep init",
4043
- "adep dev",
4044
- "adep serve",
4045
- "adep db\uFF08\u672C\u5730\u6A21\u62DF\uFF09",
4046
- "adep doctor"
4047
- ];
4221
+ if (typeof m.exportedAt !== "string" || m.exportedAt.trim() === "") {
4222
+ errors.push({
4223
+ code: "MISSING_EXPORTED_AT",
4224
+ message: "exportedAt \u5FC5\u987B\u975E\u7A7A",
4225
+ field: "exportedAt"
4226
+ });
4227
+ } else {
4228
+ const date = new Date(m.exportedAt);
4229
+ if (Number.isNaN(date.getTime())) {
4230
+ errors.push({
4231
+ code: "INVALID_EXPORTED_AT",
4232
+ message: "exportedAt \u5FC5\u987B\u662F\u6709\u6548\u7684 ISO 8601 \u65F6\u95F4",
4233
+ field: "exportedAt"
4234
+ });
4235
+ }
4048
4236
  }
4049
- });
4050
-
4051
- // packages/cli/src/db.ts
4052
- var db_exports = {};
4053
- __export(db_exports, {
4054
- dbExec: () => dbExec,
4055
- dbRollback: () => dbRollback,
4056
- dbSnapshotCreate: () => dbSnapshotCreate,
4057
- dbSnapshotList: () => dbSnapshotList,
4058
- dbSnapshotRestore: () => dbSnapshotRestore,
4059
- dbStart: () => dbStart,
4060
- dbStatus: () => dbStatus,
4061
- dbStop: () => dbStop
4062
- });
4063
- import { resolve as resolve8 } from "node:path";
4064
- async function open2(paths, options) {
4065
- const client = await createClient(paths);
4066
- const project2 = await resolveSlug(resolve8(options.cwd), options.slug);
4067
- return { client, project: project2 };
4068
- }
4069
- async function dbStart(paths, options) {
4070
- const { client, project: project2 } = await open2(paths, options);
4071
- return client.request(`/api/v1/projects/${project2}/database`, { method: "POST" });
4072
- }
4073
- async function dbStatus(paths, options) {
4074
- const { client, project: project2 } = await open2(paths, options);
4075
- return client.request(`/api/v1/projects/${project2}/database`);
4076
- }
4077
- async function dbStop(paths, options) {
4078
- const { client, project: project2 } = await open2(paths, options);
4079
- return client.request(`/api/v1/projects/${project2}/database`, {
4080
- method: "DELETE"
4081
- });
4082
- }
4083
- async function dbExec(paths, options) {
4084
- const { client, project: project2 } = await open2(paths, options);
4085
- return client.request(
4086
- `/api/v1/projects/${project2}/database/console/sql`,
4087
- {
4088
- method: "POST",
4089
- body: {
4090
- sql: options.sql,
4091
- ...options.params === void 0 ? {} : { params: options.params },
4092
- ...options.confirmTable === void 0 ? {} : { confirmTable: options.confirmTable }
4093
- }
4094
- },
4095
- "SQL_EXEC_FAILED"
4096
- );
4237
+ return {
4238
+ valid: errors.length === 0,
4239
+ errors,
4240
+ warnings
4241
+ };
4097
4242
  }
4098
- async function dbSnapshotList(paths, options) {
4099
- const { client, project: project2 } = await open2(paths, options);
4100
- return client.request(
4101
- `/api/v1/projects/${project2}/database/snapshots`
4102
- );
4103
- }
4104
- async function dbSnapshotCreate(paths, options) {
4105
- const { client, project: project2 } = await open2(paths, options);
4106
- return client.request(`/api/v1/projects/${project2}/database/snapshots`, {
4107
- method: "POST"
4108
- });
4109
- }
4110
- async function dbSnapshotRestore(paths, options) {
4111
- const { client, project: project2 } = await open2(paths, options);
4112
- return client.request(
4113
- `/api/v1/projects/${project2}/database/snapshots/${options.snapshotId}/restore`,
4114
- { method: "POST" }
4115
- );
4116
- }
4117
- async function dbRollback(paths, options) {
4118
- const { client, project: project2 } = await open2(paths, options);
4119
- return client.request(
4120
- `/api/v1/projects/${project2}/database/rollback`,
4121
- { method: "POST", body: { to: options.to } }
4122
- );
4123
- }
4124
- var init_db2 = __esm({
4125
- "packages/cli/src/db.ts"() {
4126
- "use strict";
4127
- init_client();
4243
+ function validateContent(content, index, errors, _warnings) {
4244
+ if (typeof content !== "object" || content === null) {
4245
+ errors.push({
4246
+ code: "INVALID_CONTENT",
4247
+ message: `contents[${index}] \u5FC5\u987B\u662F\u5BF9\u8C61`,
4248
+ field: `contents[${index}]`
4249
+ });
4250
+ return;
4128
4251
  }
4129
- });
4130
-
4131
- // packages/cli/src/storage.ts
4132
- var storage_exports = {};
4133
- __export(storage_exports, {
4134
- contentTypeOf: () => contentTypeOf,
4135
- storageDownload: () => storageDownload,
4136
- storageList: () => storageList,
4137
- storageRemove: () => storageRemove,
4138
- storageUpload: () => storageUpload
4139
- });
4140
- import { mkdir as mkdir7, readFile as readFile8, stat as stat7, writeFile as writeFile5 } from "node:fs/promises";
4141
- import { basename as basename3, dirname as dirname6, extname, join as join10, resolve as resolve9 } from "node:path";
4142
- async function open3(paths, options) {
4143
- const client = await createClient(paths);
4144
- const project2 = await resolveSlug(resolve9(options.cwd), options.slug);
4145
- return { client, project: project2 };
4146
- }
4147
- function contentTypeOf(path) {
4148
- const map = {
4149
- ".html": "text/html; charset=utf-8",
4150
- ".htm": "text/html; charset=utf-8",
4151
- ".css": "text/css; charset=utf-8",
4152
- ".js": "text/javascript; charset=utf-8",
4153
- ".mjs": "text/javascript; charset=utf-8",
4154
- ".json": "application/json; charset=utf-8",
4155
- ".png": "image/png",
4156
- ".jpg": "image/jpeg",
4157
- ".jpeg": "image/jpeg",
4158
- ".gif": "image/gif",
4159
- ".svg": "image/svg+xml",
4160
- ".webp": "image/webp",
4161
- ".ico": "image/x-icon",
4162
- ".txt": "text/plain; charset=utf-8",
4163
- ".md": "text/markdown; charset=utf-8",
4164
- ".xml": "application/xml",
4165
- ".wasm": "application/wasm",
4166
- ".pdf": "application/pdf",
4167
- ".zip": "application/zip",
4168
- ".woff": "font/woff",
4169
- ".woff2": "font/woff2",
4170
- ".ttf": "font/ttf",
4171
- ".otf": "font/otf"
4172
- };
4173
- return map[extname(path).toLowerCase()] ?? "application/octet-stream";
4174
- }
4175
- async function storageUpload(paths, options) {
4176
- const { client, project: project2 } = await open3(paths, options);
4177
- const local = resolve9(options.file);
4178
- const info = await stat7(local).catch(() => null);
4179
- if (info === null || !info.isFile()) {
4180
- throw new CliError("FILE_NOT_FOUND", `\u672C\u5730\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${local}`);
4252
+ const c = content;
4253
+ if (typeof c.path !== "string" || c.path.trim() === "") {
4254
+ errors.push({
4255
+ code: "MISSING_CONTENT_PATH",
4256
+ message: `contents[${index}].path \u5FC5\u987B\u975E\u7A7A`,
4257
+ field: `contents[${index}].path`
4258
+ });
4181
4259
  }
4182
- const visibility = options.visibility ?? "private";
4183
- const bytes = await readFile8(local);
4184
- const form = new FormData();
4185
- form.set("path", options.path);
4186
- form.set("visibility", visibility);
4187
- form.set(
4188
- "file",
4189
- new Blob([bytes], { type: contentTypeOf(options.path) }),
4190
- basename3(local)
4191
- );
4192
- const response = await client.upload(
4193
- `/api/v1/projects/${project2}/files`,
4194
- form,
4195
- "STORAGE_UPLOAD_FAILED"
4196
- );
4197
- const body = await response.json();
4198
- return { ...body.file, ...body.signedUrl === void 0 ? {} : { signedUrl: body.signedUrl } };
4199
- }
4200
- async function storageList(paths, options) {
4201
- const { client, project: project2 } = await open3(paths, options);
4202
- const query = options.prefix === void 0 ? "" : `?prefix=${encodeURIComponent(options.prefix)}`;
4203
- const body = await client.request(
4204
- `/api/v1/projects/${project2}/files${query}`
4205
- );
4206
- return { project: project2, files: body.files };
4207
- }
4208
- async function resolveDownloadUrl(client, project2, path) {
4209
- const body = await client.request(
4210
- `/api/v1/projects/${project2}/files?prefix=${encodeURIComponent(path)}`
4211
- );
4212
- const entry = body.files.find((file) => file.path === path);
4213
- const url = entry?.url ?? entry?.signedUrl;
4214
- if (entry === void 0 || url === void 0 || url.length === 0) {
4215
- throw new CliError("STORAGE_NOT_FOUND", `\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${path}`);
4260
+ if (typeof c.sha256 !== "string" || c.sha256.trim() === "") {
4261
+ errors.push({
4262
+ code: "MISSING_CONTENT_SHA256",
4263
+ message: `contents[${index}].sha256 \u5FC5\u987B\u975E\u7A7A`,
4264
+ field: `contents[${index}].sha256`
4265
+ });
4266
+ } else if (!/^[a-fA-F0-9]{64}$/.test(c.sha256)) {
4267
+ errors.push({
4268
+ code: "INVALID_SHA256_FORMAT",
4269
+ message: `contents[${index}].sha256 \u5FC5\u987B\u662F 64 \u5B57\u7B26\u5341\u516D\u8FDB\u5236`,
4270
+ field: `contents[${index}].sha256`
4271
+ });
4272
+ }
4273
+ if (typeof c.kind !== "string" || c.kind.trim() === "") {
4274
+ errors.push({
4275
+ code: "MISSING_CONTENT_KIND",
4276
+ message: `contents[${index}].kind \u5FC5\u987B\u975E\u7A7A`,
4277
+ field: `contents[${index}].kind`
4278
+ });
4279
+ } else if (!ALLOWED_CONTENT_KINDS.includes(c.kind)) {
4280
+ errors.push({
4281
+ code: "INVALID_CONTENT_KIND",
4282
+ message: `contents[${index}].kind "${c.kind}" \u4E0D\u5728\u5141\u8BB8\u5217\u8868\u5185\uFF0C\u5141\u8BB8\u503C\uFF1A${ALLOWED_CONTENT_KINDS.join(", ")}`,
4283
+ field: `contents[${index}].kind`
4284
+ });
4216
4285
  }
4217
- return url;
4218
- }
4219
- async function storageDownload(paths, options) {
4220
- const { client, project: project2 } = await open3(paths, options);
4221
- const url = await resolveDownloadUrl(client, project2, options.path);
4222
- const response = await client.download(url, "STORAGE_DOWNLOAD_FAILED");
4223
- const bytes = Buffer.from(await response.arrayBuffer());
4224
- const output = resolve9(options.output ?? join10(resolve9(options.cwd), basename3(options.path)));
4225
- await mkdir7(dirname6(output), { recursive: true });
4226
- await writeFile5(output, bytes);
4227
- return { path: options.path, output, size: bytes.length };
4228
4286
  }
4229
- async function storageRemove(paths, options) {
4230
- const { client, project: project2 } = await open3(paths, options);
4231
- return client.request(
4232
- `/api/v1/projects/${project2}/files/${encodeURIComponent(options.path)}`,
4233
- { method: "DELETE" }
4234
- );
4287
+ function verifyContents(contents, actualContents, hashFunction) {
4288
+ const errors = [];
4289
+ const warnings = [];
4290
+ for (const content of contents) {
4291
+ const actual = actualContents.get(content.path);
4292
+ if (actual === void 0) {
4293
+ errors.push({
4294
+ code: "CONTENT_NOT_FOUND",
4295
+ message: `\u5185\u5BB9\u7269 ${content.path} \u5728\u5B9E\u9645\u5305\u4E2D\u4E0D\u5B58\u5728`,
4296
+ field: `contents[${content.path}]`
4297
+ });
4298
+ continue;
4299
+ }
4300
+ const actualHash = hashFunction(actual);
4301
+ if (actualHash.toLowerCase() !== content.sha256.toLowerCase()) {
4302
+ errors.push({
4303
+ code: "CHECKSUM_MISMATCH",
4304
+ message: `\u5185\u5BB9\u7269 ${content.path} \u7684\u6821\u9A8C\u548C\u4E0D\u5339\u914D\uFF1A\u671F\u671B ${content.sha256}\uFF0C\u5B9E\u9645 ${actualHash}`,
4305
+ field: `contents[${content.path}].sha256`
4306
+ });
4307
+ }
4308
+ }
4309
+ for (const path of actualContents.keys()) {
4310
+ if (!contents.some((c) => c.path === path)) {
4311
+ warnings.push({
4312
+ code: "UNDECLARED_CONTENT",
4313
+ message: `\u5B9E\u9645\u5305\u4E2D\u5B58\u5728 Manifest \u672A\u58F0\u660E\u7684\u5185\u5BB9\uFF1A${path}`,
4314
+ field: `contents[${path}]`
4315
+ });
4316
+ }
4317
+ }
4318
+ return {
4319
+ valid: errors.length === 0,
4320
+ errors,
4321
+ warnings
4322
+ };
4235
4323
  }
4236
- var init_storage2 = __esm({
4237
- "packages/cli/src/storage.ts"() {
4324
+ var init_validate = __esm({
4325
+ "../../shared/deploy-bundle/validate.ts"() {
4238
4326
  "use strict";
4239
- init_client();
4240
- init_auth();
4327
+ init_manifest2();
4241
4328
  }
4242
4329
  });
4243
4330
 
4244
- // packages/cli/src/hosting.ts
4245
- var hosting_exports = {};
4246
- __export(hosting_exports, {
4247
- hostingConfig: () => hostingConfig,
4248
- hostingDeploy: () => hostingDeploy,
4249
- hostingInfo: () => hostingInfo,
4250
- hostingPull: () => hostingPull
4331
+ // src/export/command.ts
4332
+ var command_exports = {};
4333
+ __export(command_exports, {
4334
+ ExportCommand: () => ExportCommand
4251
4335
  });
4252
- import { readdir as readdir5, readFile as readFile9, stat as stat8 } from "node:fs/promises";
4253
- import { dirname as dirname7, join as join11, relative as relative2, resolve as resolve10, sep } from "node:path";
4254
- async function open4(paths, options) {
4255
- const client = await createClient(paths);
4256
- const project2 = await resolveSlug(resolve10(options.cwd), options.slug);
4257
- return { client, project: project2 };
4258
- }
4259
- async function hostingInfo(paths, options) {
4260
- const { client, project: project2 } = await open4(paths, options);
4261
- const body = await client.request(`/api/v1/projects/${project2}/hosting`);
4262
- return {
4263
- config: body.config,
4264
- siteUrl: body.siteUrl,
4265
- files: body.files ?? []
4266
- };
4267
- }
4268
- async function collectSiteFiles(dir) {
4269
- const root = resolve10(dir);
4270
- const files = /* @__PURE__ */ new Map();
4271
- const walk = async (sub) => {
4272
- let entries;
4273
- try {
4274
- entries = await readdir5(sub, { withFileTypes: true });
4275
- } catch {
4276
- return;
4277
- }
4278
- for (const entry of entries) {
4279
- const full = join11(sub, entry.name);
4280
- if (entry.isDirectory()) {
4281
- await walk(full);
4282
- } else if (entry.isFile()) {
4283
- const rel = relative2(root, full).split(sep).join("/");
4284
- files.set(rel, full);
4336
+ import { createHash as createHash3 } from "node:crypto";
4337
+ var ExportCommand;
4338
+ var init_command = __esm({
4339
+ "src/export/command.ts"() {
4340
+ "use strict";
4341
+ init_validate();
4342
+ ExportCommand = class {
4343
+ constructor(apiClient, fs, pollInterval = 2e3, maxPollAttempts = 300) {
4344
+ this.apiClient = apiClient;
4345
+ this.fs = fs;
4346
+ this.pollInterval = pollInterval;
4347
+ this.maxPollAttempts = maxPollAttempts;
4285
4348
  }
4286
- }
4287
- };
4288
- await walk(root);
4289
- return files;
4290
- }
4291
- async function hostingDeploy(paths, options) {
4292
- const { client, project: project2 } = await open4(paths, options);
4293
- const log = options.log ?? ((line) => process.stdout.write(`${line}
4294
- `));
4295
- const files = await collectSiteFiles(options.dir);
4296
- if (files.size === 0) {
4297
- throw new CliError("NO_SITE_FILES", `\u7AD9\u70B9\u76EE\u5F55\u4E3A\u7A7A\uFF1A${resolve10(options.dir)}`);
4298
- }
4299
- const uploaded = [];
4300
- for (const [rel, full] of files) {
4301
- log(`[adep] \u4E0A\u4F20 site/${rel}`);
4302
- const info2 = await stat8(full);
4303
- const bytes = await readFile9(full);
4304
- const form = new FormData();
4305
- form.set("path", `site/${rel}`);
4306
- form.set("visibility", "public");
4307
- form.set(
4308
- "file",
4309
- new Blob([bytes], { type: contentTypeOf(rel) }),
4310
- rel.split("/").pop()
4311
- );
4312
- await client.upload(`/api/v1/projects/${project2}/files`, form, "HOSTING_UPLOAD_FAILED");
4313
- uploaded.push({ path: `site/${rel}`, size: info2.size });
4349
+ /**
4350
+ * 执行导出命令。
4351
+ *
4352
+ * @param options 命令选项
4353
+ * @returns 导出结果
4354
+ */
4355
+ async execute(options) {
4356
+ const projectId = options.project ?? "default";
4357
+ const outputDir = options.out ?? "./exports";
4358
+ const jsonOutput = options.json ?? false;
4359
+ try {
4360
+ if (!jsonOutput) {
4361
+ console.log(`\u89E6\u53D1\u5BFC\u51FA\uFF1A\u9879\u76EE ${projectId}`);
4362
+ }
4363
+ const job = await this.apiClient.triggerExport(projectId, {
4364
+ withData: options.withData,
4365
+ withSource: options.withSource,
4366
+ withoutSource: options.withoutSource
4367
+ });
4368
+ if (!jsonOutput) {
4369
+ console.log(`\u5BFC\u51FA\u4EFB\u52A1\u5DF2\u521B\u5EFA\uFF1A${job.id}`);
4370
+ }
4371
+ const completedJob = await this.pollJobStatus(job.id, jsonOutput);
4372
+ if (completedJob.status === "failed") {
4373
+ return {
4374
+ success: false,
4375
+ jobId: job.id,
4376
+ status: "failed",
4377
+ error: completedJob.error ?? "\u5BFC\u51FA\u5931\u8D25"
4378
+ };
4379
+ }
4380
+ if (!jsonOutput) {
4381
+ console.log("\u4E0B\u8F7D\u5BFC\u51FA\u4EA7\u7269...");
4382
+ }
4383
+ const outputPath = `${outputDir}/${projectId}-export-${Date.now()}.zip`;
4384
+ await this.fs.mkdir(outputDir);
4385
+ const downloadResult = await this.apiClient.downloadBundle(job.id, outputPath);
4386
+ if (!jsonOutput) {
4387
+ console.log(`\u4EA7\u7269\u5DF2\u4E0B\u8F7D\uFF1A${downloadResult.path}\uFF08${this.formatSize(downloadResult.size)}\uFF09`);
4388
+ }
4389
+ if (!jsonOutput) {
4390
+ console.log("\u6267\u884C manifest \u81EA\u68C0...");
4391
+ }
4392
+ const manifest = await this.verifyManifest(downloadResult.path);
4393
+ if (!jsonOutput) {
4394
+ this.printContentList(manifest);
4395
+ }
4396
+ return {
4397
+ success: true,
4398
+ jobId: job.id,
4399
+ status: "completed",
4400
+ downloadPath: downloadResult.path,
4401
+ manifest: {
4402
+ projectName: manifest.project.name,
4403
+ platformVersion: manifest.platformVersion,
4404
+ exportedAt: manifest.exportedAt,
4405
+ contents: this.countContents(manifest.contents)
4406
+ }
4407
+ };
4408
+ } catch (error) {
4409
+ const message = error instanceof Error ? error.message : "unknown_error";
4410
+ if (message.includes("ECONNREFUSED") || message.includes("ENOTFOUND") || message.includes("network")) {
4411
+ return {
4412
+ success: false,
4413
+ error: `\u5E73\u53F0\u7AEF\u70B9\u4E0D\u53EF\u8FBE\uFF1A${message}\u3002\u8BF7\u68C0\u67E5\u7F51\u7EDC\u8FDE\u63A5\u548C\u5E73\u53F0\u5730\u5740\u914D\u7F6E\uFF0C\u7136\u540E\u91CD\u8BD5\u3002`
4414
+ };
4415
+ }
4416
+ return {
4417
+ success: false,
4418
+ error: message
4419
+ };
4420
+ }
4421
+ }
4422
+ /**
4423
+ * 轮询任务状态。
4424
+ *
4425
+ * @param jobId 任务 ID
4426
+ * @param jsonOutput 是否 JSON 输出
4427
+ * @returns 完成的任务
4428
+ */
4429
+ async pollJobStatus(jobId, jsonOutput) {
4430
+ let attempts = 0;
4431
+ let lastProgress = -1;
4432
+ while (attempts < this.maxPollAttempts) {
4433
+ const job = await this.apiClient.getJobStatus(jobId);
4434
+ if (!jsonOutput && job.progress !== lastProgress) {
4435
+ const stage = job.stage ? `\uFF08${job.stage}\uFF09` : "";
4436
+ console.log(`\u8FDB\u5EA6\uFF1A${job.progress}%${stage}`);
4437
+ lastProgress = job.progress;
4438
+ }
4439
+ if (job.status === "completed" || job.status === "failed") {
4440
+ return job;
4441
+ }
4442
+ attempts++;
4443
+ await this.sleep(this.pollInterval);
4444
+ }
4445
+ throw new Error(`\u5BFC\u51FA\u4EFB\u52A1\u8D85\u65F6\uFF1A\u8F6E\u8BE2 ${this.maxPollAttempts} \u6B21\u540E\u4ECD\u672A\u5B8C\u6210`);
4446
+ }
4447
+ /**
4448
+ * 验证 Manifest:解压 → 契约校验 → 逐项 sha256 校验 → 清理临时目录。
4449
+ *
4450
+ * 逐项校验与导出端同法:内容物以 latin1 承载(逐字节双射,二进制条目不被解码改写),
4451
+ * 比对时对原字节做真实 sha256;任一不匹配即判定包损坏并抛错,不静默放行。
4452
+ * 无论成功失败,`${zip}.tmp` 临时目录都在 finally 里删除,不留残余。
4453
+ *
4454
+ * @param zipPath ZIP 文件路径
4455
+ * @returns Manifest
4456
+ */
4457
+ async verifyManifest(zipPath) {
4458
+ const tempDir = `${zipPath}.tmp`;
4459
+ try {
4460
+ await this.fs.mkdir(tempDir);
4461
+ await this.fs.unzip(zipPath, tempDir);
4462
+ const manifestPath = `${tempDir}/manifest.json`;
4463
+ if (!await this.fs.fileExists(manifestPath)) {
4464
+ throw new Error("manifest.json \u4E0D\u5B58\u5728\uFF0C\u5305\u53EF\u80FD\u5DF2\u635F\u574F");
4465
+ }
4466
+ const manifestContent = await this.fs.readFile(manifestPath);
4467
+ const manifest = JSON.parse(manifestContent.toString("utf-8"));
4468
+ const validationResult = validateBundleManifest(manifest);
4469
+ if (!validationResult.valid) {
4470
+ const errors = validationResult.errors.map((e) => `${e.field ?? ""}: ${e.message}`).join("\n");
4471
+ throw new Error(`manifest \u6821\u9A8C\u5931\u8D25\uFF1A
4472
+ ${errors}`);
4473
+ }
4474
+ const actual = /* @__PURE__ */ new Map();
4475
+ for (const content of manifest.contents) {
4476
+ const filePath = `${tempDir}/${content.path}`;
4477
+ if (await this.fs.fileExists(filePath)) {
4478
+ const bytes = await this.fs.readFile(filePath);
4479
+ actual.set(content.path, bytes.toString("latin1"));
4480
+ }
4481
+ }
4482
+ const contentResult = verifyContents(
4483
+ manifest.contents,
4484
+ actual,
4485
+ (text) => createHash3("sha256").update(Buffer.from(text, "latin1")).digest("hex")
4486
+ );
4487
+ if (!contentResult.valid) {
4488
+ const detail = contentResult.errors.map((e) => e.message).join("\n");
4489
+ throw new Error(`\u5185\u5BB9\u7269\u6821\u9A8C\u548C\u4E0D\u5339\u914D\uFF1A
4490
+ ${detail}`);
4491
+ }
4492
+ return manifest;
4493
+ } finally {
4494
+ await this.fs.deleteFile(tempDir);
4495
+ }
4496
+ }
4497
+ /**
4498
+ * 统计内容物数量。
4499
+ *
4500
+ * @param contents 内容物列表
4501
+ * @returns 统计结果
4502
+ */
4503
+ countContents(contents) {
4504
+ return {
4505
+ functions: contents.filter((c) => c.kind === "functions").length,
4506
+ database: contents.filter((c) => c.kind === "database").length,
4507
+ web: contents.filter((c) => c.kind === "web").length,
4508
+ runtime: contents.filter((c) => c.kind === "runtime").length,
4509
+ scripts: contents.filter((c) => c.kind === "scripts").length,
4510
+ docs: contents.filter((c) => c.kind === "docs").length,
4511
+ total: contents.length
4512
+ };
4513
+ }
4514
+ /**
4515
+ * 打印内容清单。
4516
+ *
4517
+ * @param manifest Manifest
4518
+ */
4519
+ printContentList(manifest) {
4520
+ const counts = this.countContents(manifest.contents);
4521
+ console.log("");
4522
+ console.log("==========================================");
4523
+ console.log("\u5BFC\u51FA\u5185\u5BB9\u6E05\u5355");
4524
+ console.log("==========================================");
4525
+ console.log(`\u9879\u76EE\uFF1A${manifest.project.name}`);
4526
+ console.log(`\u5E73\u53F0\u7248\u672C\uFF1A${manifest.platformVersion}`);
4527
+ console.log(`\u5BFC\u51FA\u65F6\u95F4\uFF1A${manifest.exportedAt}`);
4528
+ console.log("");
4529
+ console.log(`\u51FD\u6570\u6587\u4EF6\uFF1A${counts.functions}`);
4530
+ console.log(`\u6570\u636E\u5E93\u6587\u4EF6\uFF1A${counts.database}`);
4531
+ console.log(`\u524D\u7AEF\u6587\u4EF6\uFF1A${counts.web}`);
4532
+ console.log(`\u8FD0\u884C\u65F6\u6587\u4EF6\uFF1A${counts.runtime}`);
4533
+ console.log(`\u811A\u672C\u6587\u4EF6\uFF1A${counts.scripts}`);
4534
+ console.log(`\u6587\u6863\u6587\u4EF6\uFF1A${counts.docs}`);
4535
+ console.log(`\u603B\u6587\u4EF6\u6570\uFF1A${counts.total}`);
4536
+ console.log("==========================================");
4537
+ }
4538
+ /**
4539
+ * 格式化文件大小。
4540
+ *
4541
+ * @param bytes 字节数
4542
+ * @returns 格式化后的大小
4543
+ */
4544
+ formatSize(bytes) {
4545
+ if (bytes < 1024) return `${bytes} B`;
4546
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
4547
+ if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
4548
+ return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
4549
+ }
4550
+ /**
4551
+ * 睡眠指定毫秒数。
4552
+ *
4553
+ * @param ms 毫秒数
4554
+ */
4555
+ sleep(ms) {
4556
+ return new Promise((resolve12) => setTimeout(resolve12, ms));
4557
+ }
4558
+ };
4314
4559
  }
4315
- const config = await client.request(
4316
- `/api/v1/projects/${project2}/hosting`,
4560
+ });
4561
+
4562
+ // src/db.ts
4563
+ var db_exports = {};
4564
+ __export(db_exports, {
4565
+ dbExec: () => dbExec,
4566
+ dbRollback: () => dbRollback,
4567
+ dbSnapshotCreate: () => dbSnapshotCreate,
4568
+ dbSnapshotList: () => dbSnapshotList,
4569
+ dbSnapshotRestore: () => dbSnapshotRestore,
4570
+ dbStart: () => dbStart,
4571
+ dbStatus: () => dbStatus,
4572
+ dbStop: () => dbStop
4573
+ });
4574
+ import { resolve as resolve7 } from "node:path";
4575
+ async function open2(paths, options) {
4576
+ const client = await createClient(paths);
4577
+ const project2 = await resolveSlug(resolve7(options.cwd), options.slug);
4578
+ return { client, project: project2 };
4579
+ }
4580
+ async function dbStart(paths, options) {
4581
+ const { client, project: project2 } = await open2(paths, options);
4582
+ return client.request(`/api/v1/projects/${project2}/database`, { method: "POST" });
4583
+ }
4584
+ async function dbStatus(paths, options) {
4585
+ const { client, project: project2 } = await open2(paths, options);
4586
+ return client.request(`/api/v1/projects/${project2}/database`);
4587
+ }
4588
+ async function dbStop(paths, options) {
4589
+ const { client, project: project2 } = await open2(paths, options);
4590
+ return client.request(`/api/v1/projects/${project2}/database`, {
4591
+ method: "DELETE"
4592
+ });
4593
+ }
4594
+ async function dbExec(paths, options) {
4595
+ const { client, project: project2 } = await open2(paths, options);
4596
+ return client.request(
4597
+ `/api/v1/projects/${project2}/database/console/sql`,
4317
4598
  {
4318
- method: "PUT",
4319
- body: options.spa === void 0 ? { enabled: true } : { enabled: true, spaMode: options.spa }
4320
- }
4599
+ method: "POST",
4600
+ body: {
4601
+ sql: options.sql,
4602
+ ...options.params === void 0 ? {} : { params: options.params },
4603
+ ...options.confirmTable === void 0 ? {} : { confirmTable: options.confirmTable }
4604
+ }
4605
+ },
4606
+ "SQL_EXEC_FAILED"
4321
4607
  );
4322
- const info = await hostingInfo(paths, options);
4323
- return { config: config.config, siteUrl: info.siteUrl, uploaded };
4324
4608
  }
4325
- async function hostingPull(paths, options) {
4326
- const { client } = await open4(paths, options);
4327
- const log = options.log ?? ((line) => process.stdout.write(`${line}
4328
- `));
4329
- const info = await hostingInfo(paths, options);
4330
- const outputDir = resolve10(options.output ?? resolve10(options.cwd));
4331
- const { mkdir: mkdir9, writeFile: writeFile8 } = await import("node:fs/promises");
4332
- const files = [];
4333
- for (const entry of info.files) {
4334
- if (entry.visibility !== "public" || entry.path === HOSTING_CONFIG_PATH) continue;
4335
- const url = entry.url;
4336
- if (url === void 0 || url.length === 0) continue;
4337
- log(`[adep] \u4E0B\u8F7D ${entry.path}`);
4338
- const response = await client.download(url, "HOSTING_DOWNLOAD_FAILED");
4339
- const bytes = Buffer.from(await response.arrayBuffer());
4340
- const rel = entry.path.replace(/^site\//, "");
4341
- const target = join11(outputDir, ...rel.split("/"));
4342
- await mkdir9(dirname7(target), { recursive: true });
4343
- await writeFile8(target, bytes);
4344
- files.push({ path: entry.path, size: bytes.length });
4609
+ async function dbSnapshotList(paths, options) {
4610
+ const { client, project: project2 } = await open2(paths, options);
4611
+ return client.request(
4612
+ `/api/v1/projects/${project2}/database/snapshots`
4613
+ );
4614
+ }
4615
+ async function dbSnapshotCreate(paths, options) {
4616
+ const { client, project: project2 } = await open2(paths, options);
4617
+ return client.request(`/api/v1/projects/${project2}/database/snapshots`, {
4618
+ method: "POST"
4619
+ });
4620
+ }
4621
+ async function dbSnapshotRestore(paths, options) {
4622
+ const { client, project: project2 } = await open2(paths, options);
4623
+ return client.request(
4624
+ `/api/v1/projects/${project2}/database/snapshots/${options.snapshotId}/restore`,
4625
+ { method: "POST" }
4626
+ );
4627
+ }
4628
+ async function dbRollback(paths, options) {
4629
+ const { client, project: project2 } = await open2(paths, options);
4630
+ return client.request(
4631
+ `/api/v1/projects/${project2}/database/rollback`,
4632
+ { method: "POST", body: { to: options.to } }
4633
+ );
4634
+ }
4635
+ var init_db2 = __esm({
4636
+ "src/db.ts"() {
4637
+ "use strict";
4638
+ init_client();
4345
4639
  }
4346
- return { siteUrl: info.siteUrl, outputDir, files };
4640
+ });
4641
+
4642
+ // src/storage.ts
4643
+ var storage_exports = {};
4644
+ __export(storage_exports, {
4645
+ contentTypeOf: () => contentTypeOf,
4646
+ storageDownload: () => storageDownload,
4647
+ storageList: () => storageList,
4648
+ storageRemove: () => storageRemove,
4649
+ storageUpload: () => storageUpload
4650
+ });
4651
+ import { mkdir as mkdir8, readFile as readFile10, stat as stat7, writeFile as writeFile7 } from "node:fs/promises";
4652
+ import { basename as basename3, dirname as dirname7, extname, join as join12, resolve as resolve8 } from "node:path";
4653
+ async function open3(paths, options) {
4654
+ const client = await createClient(paths);
4655
+ const project2 = await resolveSlug(resolve8(options.cwd), options.slug);
4656
+ return { client, project: project2 };
4657
+ }
4658
+ function contentTypeOf(path) {
4659
+ const map = {
4660
+ ".html": "text/html; charset=utf-8",
4661
+ ".htm": "text/html; charset=utf-8",
4662
+ ".css": "text/css; charset=utf-8",
4663
+ ".js": "text/javascript; charset=utf-8",
4664
+ ".mjs": "text/javascript; charset=utf-8",
4665
+ ".json": "application/json; charset=utf-8",
4666
+ ".png": "image/png",
4667
+ ".jpg": "image/jpeg",
4668
+ ".jpeg": "image/jpeg",
4669
+ ".gif": "image/gif",
4670
+ ".svg": "image/svg+xml",
4671
+ ".webp": "image/webp",
4672
+ ".ico": "image/x-icon",
4673
+ ".txt": "text/plain; charset=utf-8",
4674
+ ".md": "text/markdown; charset=utf-8",
4675
+ ".xml": "application/xml",
4676
+ ".wasm": "application/wasm",
4677
+ ".pdf": "application/pdf",
4678
+ ".zip": "application/zip",
4679
+ ".woff": "font/woff",
4680
+ ".woff2": "font/woff2",
4681
+ ".ttf": "font/ttf",
4682
+ ".otf": "font/otf"
4683
+ };
4684
+ return map[extname(path).toLowerCase()] ?? "application/octet-stream";
4685
+ }
4686
+ async function storageUpload(paths, options) {
4687
+ const { client, project: project2 } = await open3(paths, options);
4688
+ const local = resolve8(options.file);
4689
+ const info = await stat7(local).catch(() => null);
4690
+ if (info === null || !info.isFile()) {
4691
+ throw new CliError("FILE_NOT_FOUND", `\u672C\u5730\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${local}`);
4692
+ }
4693
+ const visibility = options.visibility ?? "private";
4694
+ const bytes = await readFile10(local);
4695
+ const form = new FormData();
4696
+ form.set("path", options.path);
4697
+ form.set("visibility", visibility);
4698
+ form.set(
4699
+ "file",
4700
+ new Blob([bytes], { type: contentTypeOf(options.path) }),
4701
+ basename3(local)
4702
+ );
4703
+ const response = await client.upload(
4704
+ `/api/v1/projects/${project2}/files`,
4705
+ form,
4706
+ "STORAGE_UPLOAD_FAILED"
4707
+ );
4708
+ const body = await response.json();
4709
+ return { ...body.file, ...body.signedUrl === void 0 ? {} : { signedUrl: body.signedUrl } };
4710
+ }
4711
+ async function storageList(paths, options) {
4712
+ const { client, project: project2 } = await open3(paths, options);
4713
+ const query = options.prefix === void 0 ? "" : `?prefix=${encodeURIComponent(options.prefix)}`;
4714
+ const body = await client.request(
4715
+ `/api/v1/projects/${project2}/files${query}`
4716
+ );
4717
+ return { project: project2, files: body.files };
4718
+ }
4719
+ async function resolveDownloadUrl(client, project2, path) {
4720
+ const body = await client.request(
4721
+ `/api/v1/projects/${project2}/files?prefix=${encodeURIComponent(path)}`
4722
+ );
4723
+ const entry = body.files.find((file) => file.path === path);
4724
+ const url = entry?.url ?? entry?.signedUrl;
4725
+ if (entry === void 0 || url === void 0 || url.length === 0) {
4726
+ throw new CliError("STORAGE_NOT_FOUND", `\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${path}`);
4727
+ }
4728
+ return url;
4729
+ }
4730
+ async function storageDownload(paths, options) {
4731
+ const { client, project: project2 } = await open3(paths, options);
4732
+ const url = await resolveDownloadUrl(client, project2, options.path);
4733
+ const response = await client.download(url, "STORAGE_DOWNLOAD_FAILED");
4734
+ const bytes = Buffer.from(await response.arrayBuffer());
4735
+ const output = resolve8(options.output ?? join12(resolve8(options.cwd), basename3(options.path)));
4736
+ await mkdir8(dirname7(output), { recursive: true });
4737
+ await writeFile7(output, bytes);
4738
+ return { path: options.path, output, size: bytes.length };
4347
4739
  }
4348
- async function hostingConfig(paths, options) {
4349
- const { client, project: project2 } = await open4(paths, options);
4350
- const body = {};
4351
- if (options.enabled !== void 0) body["enabled"] = options.enabled;
4352
- if (options.spa !== void 0) body["spaMode"] = options.spa;
4353
- const result = await client.request(
4354
- `/api/v1/projects/${project2}/hosting`,
4355
- { method: "PUT", body }
4740
+ async function storageRemove(paths, options) {
4741
+ const { client, project: project2 } = await open3(paths, options);
4742
+ return client.request(
4743
+ `/api/v1/projects/${project2}/files/${encodeURIComponent(options.path)}`,
4744
+ { method: "DELETE" }
4356
4745
  );
4357
- return result.config;
4358
4746
  }
4359
- var HOSTING_CONFIG_PATH;
4360
- var init_hosting = __esm({
4361
- "packages/cli/src/hosting.ts"() {
4747
+ var init_storage2 = __esm({
4748
+ "src/storage.ts"() {
4362
4749
  "use strict";
4363
4750
  init_client();
4364
4751
  init_auth();
4365
- init_storage2();
4366
- HOSTING_CONFIG_PATH = "site/.hosting.json";
4367
4752
  }
4368
4753
  });
4369
4754
 
4370
- // packages/cli/src/export/client.ts
4371
- var client_exports2 = {};
4372
- __export(client_exports2, {
4373
- createExportApiClient: () => createExportApiClient
4374
- });
4375
- import { writeFile as writeFile6 } from "node:fs/promises";
4376
- function toExportJob(view) {
4377
- return {
4378
- id: view.id,
4379
- status: view.status,
4380
- progress: view.progress,
4381
- createdAt: view.createdAt,
4382
- ...view.stage === void 0 ? {} : { stage: view.stage },
4383
- ...view.error === void 0 ? {} : { error: view.error },
4384
- ...view.downloadUrl === void 0 ? {} : { downloadUrl: view.downloadUrl },
4385
- ...view.bundleSize === void 0 ? {} : { bundleSize: view.bundleSize },
4386
- ...view.completedAt === void 0 ? {} : { completedAt: view.completedAt }
4387
- };
4388
- }
4389
- async function createExportApiClient(paths) {
4390
- const client = await createClient(paths);
4391
- return {
4392
- async triggerExport(projectId, options) {
4393
- const view = await client.request(
4394
- `/api/v1/projects/${encodeURIComponent(projectId)}/export`,
4395
- { method: "POST", body: { withData: options.withData, withSource: options.withSource } },
4396
- "EXPORT_TRIGGER_FAILED"
4397
- );
4398
- return toExportJob(view);
4399
- },
4400
- async getJobStatus(jobId) {
4401
- const view = await client.request(
4402
- `/api/v1/exports/${encodeURIComponent(jobId)}`,
4403
- {},
4404
- "EXPORT_STATUS_FAILED"
4405
- );
4406
- return toExportJob(view);
4407
- },
4408
- async downloadBundle(jobId, outputPath) {
4409
- const download = await client.request(
4410
- `/api/v1/exports/${encodeURIComponent(jobId)}/download`,
4411
- {},
4412
- "EXPORT_DOWNLOAD_FAILED"
4413
- );
4414
- if (download.downloadUrl.length === 0) {
4415
- throw new CliError("EXPORT_BUNDLE_UNAVAILABLE", "\u5BFC\u51FA\u4EA7\u7269\u4E0B\u8F7D URL \u4E3A\u7A7A\uFF0C\u4EA7\u7269\u53EF\u80FD\u5C1A\u4E0D\u53EF\u7528");
4416
- }
4417
- const response = await client.download(download.downloadUrl, "EXPORT_DOWNLOAD_FAILED");
4418
- const bytes = Buffer.from(await response.arrayBuffer());
4419
- await writeFile6(outputPath, bytes);
4420
- return { path: outputPath, size: bytes.length };
4421
- }
4422
- };
4423
- }
4424
- var init_client2 = __esm({
4425
- "packages/cli/src/export/client.ts"() {
4426
- "use strict";
4427
- init_auth();
4428
- init_client();
4429
- }
4755
+ // src/doctor.ts
4756
+ var doctor_exports = {};
4757
+ __export(doctor_exports, {
4758
+ formatDoctorReport: () => formatDoctorReport,
4759
+ runDoctor: () => runDoctor
4430
4760
  });
4431
-
4432
- // shared/deploy-bundle/zip.ts
4433
- function zipRead(buf) {
4434
- const r = new Reader(buf);
4435
- const eocd = findEocd(buf);
4436
- if (eocd < 0) throw new ZipFormatError("\u627E\u4E0D\u5230 EOCD \u7B7E\u540D");
4437
- const total = r.u16(eocd + 10);
4438
- const centralOffset = r.u32(eocd + 16);
4439
- const decoder = new TextDecoder();
4440
- const out = /* @__PURE__ */ new Map();
4441
- let cursor = centralOffset;
4442
- for (let i = 0; i < total; i++) {
4443
- if (cursor + 46 > buf.length) throw new ZipFormatError("\u4E2D\u592E\u76EE\u5F55\u8BB0\u5F55\u8D8A\u754C");
4444
- if (r.u32(cursor) !== SIG_CENTRAL) throw new ZipFormatError("\u4E2D\u592E\u76EE\u5F55\u7B7E\u540D\u4E0D\u5339\u914D");
4445
- const method = r.u16(cursor + 10);
4446
- if (method !== 0) throw new ZipFormatError("\u4EC5\u652F\u6301 store \u578B\u6761\u76EE\u8BFB\u53D6");
4447
- const compSize = r.u32(cursor + 20);
4448
- const nameLen = r.u16(cursor + 28);
4449
- const extraLen = r.u16(cursor + 30);
4450
- const commentLen = r.u16(cursor + 32);
4451
- const localHeaderOffset = r.u32(cursor + 42);
4452
- if (localHeaderOffset + 30 > buf.length) throw new ZipFormatError("\u672C\u5730\u5934\u504F\u79FB\u8D8A\u754C");
4453
- const name = decoder.decode(r.slice(cursor + 46, nameLen));
4454
- const localNameLen = r.u16(localHeaderOffset + 26);
4455
- const localExtraLen = r.u16(localHeaderOffset + 28);
4456
- const dataStart = localHeaderOffset + 30 + localNameLen + localExtraLen;
4457
- if (dataStart + compSize > buf.length) throw new ZipFormatError("\u6761\u76EE\u6570\u636E\u8D8A\u754C");
4458
- if (!out.has(name)) out.set(name, r.slice(dataStart, compSize));
4459
- cursor += 46 + nameLen + extraLen + commentLen;
4761
+ import { stat as stat8 } from "node:fs/promises";
4762
+ async function probeServer(server) {
4763
+ const controller = new AbortController();
4764
+ const timer = setTimeout(() => controller.abort(), SERVER_PROBE_TIMEOUT_MS);
4765
+ try {
4766
+ const response = await fetch(`${server}/api/v1/health`, { signal: controller.signal });
4767
+ return { reachable: true, status: response.status };
4768
+ } catch (error) {
4769
+ return {
4770
+ reachable: false,
4771
+ error: error instanceof Error ? error.message : String(error)
4772
+ };
4773
+ } finally {
4774
+ clearTimeout(timer);
4460
4775
  }
4461
- return out;
4462
4776
  }
4463
- function findEocd(buf) {
4464
- const view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
4465
- const min = Math.max(0, buf.length - 65557);
4466
- for (let i = buf.length - 22; i >= min; i--) {
4467
- if (view.getUint32(i, true) === SIG_EOCD) return i;
4777
+ async function credentialMode(file) {
4778
+ try {
4779
+ const info = await stat8(file);
4780
+ return (info.mode & 511).toString(8).padStart(3, "0");
4781
+ } catch {
4782
+ return void 0;
4468
4783
  }
4469
- return -1;
4470
4784
  }
4471
- var SIG_CENTRAL, SIG_EOCD, CRC_TABLE, Reader, ZipFormatError;
4472
- var init_zip = __esm({
4473
- "shared/deploy-bundle/zip.ts"() {
4474
- "use strict";
4475
- SIG_CENTRAL = 33639248;
4476
- SIG_EOCD = 101010256;
4477
- CRC_TABLE = (() => {
4478
- const table = new Uint32Array(256);
4479
- for (let i = 0; i < 256; i++) {
4480
- let c = i;
4481
- for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
4482
- table[i] = c >>> 0;
4483
- }
4484
- return table;
4485
- })();
4486
- Reader = class {
4487
- constructor(buf) {
4488
- this.buf = buf;
4489
- this.view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
4490
- }
4491
- view;
4492
- u16(offset) {
4493
- return this.view.getUint16(offset, true);
4494
- }
4495
- u32(offset) {
4496
- return this.view.getUint32(offset, true);
4497
- }
4498
- slice(start, length) {
4499
- return this.buf.subarray(start, start + length);
4500
- }
4501
- };
4502
- ZipFormatError = class extends Error {
4503
- constructor(message) {
4504
- super(`[appexport] \u975E\u6CD5 zip\uFF1A${message}`);
4505
- this.name = "ZipFormatError";
4506
- }
4507
- };
4508
- }
4509
- });
4510
-
4511
- // packages/cli/src/export/fs.ts
4512
- var fs_exports = {};
4513
- __export(fs_exports, {
4514
- createExportFileSystem: () => createExportFileSystem
4515
- });
4516
- import { mkdir as mkdir8, readFile as readFile10, rm as rm3, stat as stat9, writeFile as writeFile7 } from "node:fs/promises";
4517
- import { dirname as dirname8, join as join12 } from "node:path";
4518
- function createExportFileSystem() {
4519
- return {
4520
- readFile: (path) => readFile10(path),
4521
- writeFile: (path, content) => writeFile7(path, content),
4522
- // 同时用于清理解压临时目录(${zip}.tmp 是个目录)——递归强制删除,缺失不报错。
4523
- deleteFile: async (path) => {
4524
- await rm3(path, { recursive: true, force: true });
4525
- },
4526
- fileExists: async (path) => {
4527
- try {
4528
- await stat9(path);
4529
- return true;
4530
- } catch {
4531
- return false;
4532
- }
4533
- },
4534
- mkdir: async (path) => {
4535
- await mkdir8(path, { recursive: true });
4785
+ async function runDoctor(paths) {
4786
+ const credentials = await loadCredentials(paths);
4787
+ const server = credentials?.server ?? resolveServer();
4788
+ const mode = await credentialMode(paths.credentialsFile);
4789
+ const offline = await isOffline();
4790
+ const health = await probeServer(server);
4791
+ const report = {
4792
+ server,
4793
+ credentials: {
4794
+ file: paths.credentialsFile,
4795
+ present: credentials !== null,
4796
+ ...mode === void 0 ? {} : { mode }
4536
4797
  },
4537
- unzip: async (zipPath, targetDir) => {
4538
- const entries = zipRead(await readFile10(zipPath));
4539
- for (const [name, data] of entries) {
4540
- const dest = join12(targetDir, name);
4541
- await mkdir8(dirname8(dest), { recursive: true });
4542
- await writeFile7(dest, data);
4543
- }
4544
- }
4798
+ network: { offline },
4799
+ serverHealth: health,
4800
+ offlineCommands: [...OFFLINE_COMMANDS],
4801
+ boundaries: SIM_BOUNDARIES.map((b) => ({ kind: b.kind, title: b.title, detail: b.detail }))
4545
4802
  };
4803
+ if (credentials !== null) report.credentials.email = credentials.email;
4804
+ if (mode !== void 0 && mode !== "600") {
4805
+ report.credentials.warning = `\u6743\u9650 ${mode} \u5BBD\u4E8E 0600\uFF0C\u5EFA\u8BAE chmod 600 ${paths.credentialsFile}`;
4806
+ }
4807
+ return report;
4546
4808
  }
4547
- var init_fs = __esm({
4548
- "packages/cli/src/export/fs.ts"() {
4549
- "use strict";
4550
- init_zip();
4809
+ function formatDoctorReport(report) {
4810
+ const lines = ["adep doctor \xB7 \u73AF\u5883\u81EA\u68C0", ""];
4811
+ lines.push("\u51ED\u636E\u4E0E\u8EAB\u4EFD");
4812
+ if (report.credentials.present) {
4813
+ lines.push(` \u2713 \u5DF2\u767B\u5F55 ${report.credentials.email ?? "(\u672A\u77E5\u90AE\u7BB1)"} @ ${report.server}`);
4814
+ lines.push(
4815
+ ` \xB7 \u51ED\u636E\u6587\u4EF6 ${report.credentials.file}\uFF08${report.credentials.mode ?? "\u6743\u9650\u672A\u77E5"}\uFF09`
4816
+ );
4817
+ if (report.credentials.warning !== void 0) lines.push(` ! ${report.credentials.warning}`);
4818
+ } else {
4819
+ lines.push(` \u2717 \u672A\u767B\u5F55\uFF08\u65E0 ${report.credentials.file}\uFF09`);
4820
+ lines.push(" \u63D0\u793A\uFF1A\u5148\u6267\u884C adep login");
4551
4821
  }
4552
- });
4553
-
4554
- // shared/deploy-bundle/manifest.ts
4555
- var CURRENT_SCHEMA_VERSION, BundleContentKind, ALLOWED_CONTENT_KINDS;
4556
- var init_manifest2 = __esm({
4557
- "shared/deploy-bundle/manifest.ts"() {
4822
+ lines.push("", "\u7F51\u7EDC\u4E0E\u670D\u52A1\u7AEF");
4823
+ lines.push(
4824
+ report.network.offline ? " \u2717 \u5916\u7F51\u4E0D\u53EF\u8FBE\uFF08\u4F9D\u8D56\u5B89\u88C5 / \u90E8\u7F72\u7B49\u547D\u4EE4\u5C06\u660E\u786E\u5931\u8D25\uFF09" : " \u2713 \u5916\u7F51\u53EF\u8FBE"
4825
+ );
4826
+ if (report.serverHealth.reachable) {
4827
+ lines.push(` \u2713 \u5E73\u53F0\u53EF\u8FBE ${report.server}\uFF08/api/v1/health \u2192 ${report.serverHealth.status}\uFF09`);
4828
+ } else {
4829
+ lines.push(
4830
+ ` \u2717 \u5E73\u53F0\u4E0D\u53EF\u8FBE ${report.server}\uFF1A${report.serverHealth.error ?? "\u65E0\u5E94\u7B54"}`,
4831
+ " \u63D0\u793A\uFF1A\u68C0\u67E5 ADEP_SERVER / \u767B\u5F55\u65F6\u7684 --server\uFF0C\u6216\u5148\u8D77\u672C\u5730 pnpm run dev"
4832
+ );
4833
+ }
4834
+ lines.push("", "\u79BB\u7EBF\u53EF\u7528\u8303\u56F4\uFF08\u65AD\u7F51\u65F6\u4ECD\u53EF\u6267\u884C\uFF09");
4835
+ for (const command of report.offlineCommands) lines.push(` \xB7 ${command}`);
4836
+ lines.push("", "\u672C\u5730\u6A21\u62DF\u8FD0\u884C\u65F6\u7684\u80FD\u529B\u8FB9\u754C\uFF08\u4E0E adep dev \u542F\u52A8\u6A2A\u5E45\u540C\u6E90\uFF09");
4837
+ for (const boundary of report.boundaries) {
4838
+ lines.push(` \xB7 [${boundary.kind}] ${boundary.title}\uFF1A${boundary.detail}`);
4839
+ }
4840
+ return lines;
4841
+ }
4842
+ var SERVER_PROBE_TIMEOUT_MS, OFFLINE_COMMANDS;
4843
+ var init_doctor = __esm({
4844
+ "src/doctor.ts"() {
4558
4845
  "use strict";
4559
- CURRENT_SCHEMA_VERSION = 1;
4560
- BundleContentKind = {
4561
- /** 云函数代码与配置。 */
4562
- Functions: "functions",
4563
- /** 数据库 schema 与种子数据。 */
4564
- Database: "database",
4565
- /** 前端静态资源。 */
4566
- Web: "web",
4567
- /** 运行时配置(Dockerfile / docker-compose.yml)。 */
4568
- Runtime: "runtime",
4569
- /** 启动 / 备份 / 恢复脚本。 */
4570
- Scripts: "scripts",
4571
- /** 文档(README / 部署手册)。 */
4572
- Docs: "docs"
4573
- };
4574
- ALLOWED_CONTENT_KINDS = Object.values(BundleContentKind);
4846
+ init_credentials();
4847
+ init_config();
4848
+ init_boundary();
4849
+ init_net();
4850
+ SERVER_PROBE_TIMEOUT_MS = 5e3;
4851
+ OFFLINE_COMMANDS = [
4852
+ "adep init",
4853
+ "adep dev",
4854
+ "adep serve",
4855
+ "adep db\uFF08\u672C\u5730\u6A21\u62DF\uFF09",
4856
+ "adep doctor"
4857
+ ];
4575
4858
  }
4576
4859
  });
4577
4860
 
4578
- // shared/deploy-bundle/validate.ts
4579
- function validateBundleManifest(manifest) {
4580
- const errors = [];
4581
- const warnings = [];
4582
- if (typeof manifest !== "object" || manifest === null) {
4583
- return {
4584
- valid: false,
4585
- errors: [{ code: "INVALID_TYPE", message: "Manifest \u5FC5\u987B\u662F\u5BF9\u8C61" }],
4586
- warnings: []
4587
- };
4861
+ // src/mcp.ts
4862
+ var mcp_exports = {};
4863
+ __export(mcp_exports, {
4864
+ mcpList: () => mcpList,
4865
+ mcpPublish: () => mcpPublish,
4866
+ mcpUnpublish: () => mcpUnpublish
4867
+ });
4868
+ import { resolve as resolve9 } from "node:path";
4869
+ async function mcpPublish(paths, options) {
4870
+ const fn = requireFunctionName(options.fn);
4871
+ const client = await createClient(paths);
4872
+ const project2 = await resolveProject(client, options);
4873
+ const target = await resolveFunction(client, project2, fn);
4874
+ const body = {};
4875
+ if (options.toolName !== void 0 && options.toolName.trim().length > 0) {
4876
+ body.toolName = options.toolName.trim();
4588
4877
  }
4589
- const m = manifest;
4590
- const schemaVersion = m.schemaVersion;
4591
- if (typeof schemaVersion !== "number" || !Number.isInteger(schemaVersion)) {
4592
- errors.push({
4593
- code: "INVALID_SCHEMA_VERSION",
4594
- message: "schemaVersion \u5FC5\u987B\u662F\u6574\u6570",
4595
- field: "schemaVersion"
4596
- });
4597
- } else if (schemaVersion > CURRENT_SCHEMA_VERSION) {
4598
- errors.push({
4599
- code: "SCHEMA_VERSION_TOO_HIGH",
4600
- message: `schemaVersion ${schemaVersion} \u9AD8\u4E8E\u5F53\u524D\u652F\u6301\u7248\u672C ${CURRENT_SCHEMA_VERSION}\uFF0C\u9700\u5347\u7EA7\u5BFC\u51FA\u7AEF`,
4601
- field: "schemaVersion"
4602
- });
4603
- } else if (schemaVersion < CURRENT_SCHEMA_VERSION) {
4604
- warnings.push({
4605
- code: "SCHEMA_VERSION_LOW",
4606
- message: `schemaVersion ${schemaVersion} \u4F4E\u4E8E\u5F53\u524D\u7248\u672C ${CURRENT_SCHEMA_VERSION}\uFF0C\u5EFA\u8BAE\u91CD\u65B0\u5BFC\u51FA`,
4607
- field: "schemaVersion"
4608
- });
4878
+ if (options.description !== void 0 && options.description.length > 0) {
4879
+ body.description = options.description;
4609
4880
  }
4610
- if (typeof m.platformVersion !== "string" || m.platformVersion.trim() === "") {
4611
- errors.push({
4612
- code: "MISSING_PLATFORM_VERSION",
4613
- message: "platformVersion \u5FC5\u987B\u975E\u7A7A",
4614
- field: "platformVersion"
4881
+ const tool = await client.request(
4882
+ `/api/v1/functions/${target.id}/mcp-publish`,
4883
+ { method: "POST", ...Object.keys(body).length === 0 ? {} : { body } },
4884
+ "MCP_PUBLISH_FAILED"
4885
+ );
4886
+ return { projectId: project2.id, tool };
4887
+ }
4888
+ async function mcpUnpublish(paths, options) {
4889
+ const fn = requireFunctionName(options.fn);
4890
+ const client = await createClient(paths);
4891
+ const project2 = await resolveProject(client, options);
4892
+ const target = await resolveFunction(client, project2, fn);
4893
+ const toolName = options.toolName?.trim() || fn;
4894
+ const result = await client.request(
4895
+ `/api/v1/functions/${target.id}/mcp-publish?tool=${encodeURIComponent(toolName)}`,
4896
+ { method: "DELETE" },
4897
+ "MCP_UNPUBLISH_FAILED"
4898
+ );
4899
+ return { projectId: project2.id, toolName, removed: result.unpublished === true };
4900
+ }
4901
+ async function mcpList(paths, options) {
4902
+ const client = await createClient(paths);
4903
+ const project2 = await resolveProject(client, options);
4904
+ const prefix = project2.functionsPrefix ?? "/api";
4905
+ const prefixBase = prefix.trim() === "/" ? "" : prefix.trim().replace(/\/+$/, "");
4906
+ const endpoint = `${project2.url.replace(/\/+$/, "")}${prefixBase}/mcp`;
4907
+ let response;
4908
+ try {
4909
+ response = await fetch(endpoint, {
4910
+ method: "POST",
4911
+ headers: { "content-type": "application/json", cookie: client.cookie },
4912
+ body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "tools/list" })
4615
4913
  });
4914
+ } catch (error) {
4915
+ throw new CliError(
4916
+ "SERVER_UNREACHABLE",
4917
+ `\u65E0\u6CD5\u8FDE\u63A5 MCP \u7AEF\u70B9 ${endpoint}\uFF1A${error instanceof Error ? error.message : String(error)}`
4918
+ );
4616
4919
  }
4617
- if (typeof m.project !== "object" || m.project === null) {
4618
- errors.push({
4619
- code: "MISSING_PROJECT",
4620
- message: "project \u5FC5\u987B\u662F\u5BF9\u8C61",
4621
- field: "project"
4622
- });
4623
- } else {
4624
- const project2 = m.project;
4625
- if (typeof project2.id !== "string" || project2.id.trim() === "") {
4626
- errors.push({
4627
- code: "MISSING_PROJECT_ID",
4628
- message: "project.id \u5FC5\u987B\u975E\u7A7A",
4629
- field: "project.id"
4630
- });
4631
- }
4632
- if (typeof project2.name !== "string" || project2.name.trim() === "") {
4633
- errors.push({
4634
- code: "MISSING_PROJECT_NAME",
4635
- message: "project.name \u5FC5\u987B\u975E\u7A7A",
4636
- field: "project.name"
4637
- });
4638
- }
4639
- if (typeof project2.slug !== "string" || project2.slug.trim() === "") {
4640
- errors.push({
4641
- code: "MISSING_PROJECT_SLUG",
4642
- message: "project.slug \u5FC5\u987B\u975E\u7A7A",
4643
- field: "project.slug"
4644
- });
4645
- }
4646
- if (typeof project2.version !== "number" || !Number.isInteger(project2.version) || project2.version < 1) {
4647
- errors.push({
4648
- code: "INVALID_PROJECT_VERSION",
4649
- message: "project.version \u5FC5\u987B\u662F\u6B63\u6574\u6570",
4650
- field: "project.version"
4651
- });
4652
- }
4920
+ const parsed = await response.json().catch(() => null);
4921
+ if (!response.ok) {
4922
+ const envelope = parsed ?? null;
4923
+ throw new CliError(
4924
+ envelope?.error?.code ?? "MCP_LIST_FAILED",
4925
+ envelope?.error?.message ?? `MCP \u7AEF\u70B9\u8FD4\u56DE HTTP ${response.status}`
4926
+ );
4653
4927
  }
4654
- if (!Array.isArray(m.contents)) {
4655
- errors.push({
4656
- code: "MISSING_CONTENTS",
4657
- message: "contents \u5FC5\u987B\u662F\u6570\u7EC4",
4658
- field: "contents"
4659
- });
4660
- } else if (m.contents.length === 0) {
4661
- errors.push({
4662
- code: "EMPTY_CONTENTS",
4663
- message: "contents \u4E0D\u80FD\u4E3A\u7A7A",
4664
- field: "contents"
4665
- });
4666
- } else {
4667
- m.contents.forEach((content, index) => {
4668
- validateContent(content, index, errors, warnings);
4669
- });
4928
+ const rpcError = parsed?.error;
4929
+ if (rpcError !== void 0) {
4930
+ throw new CliError(
4931
+ rpcError.code ?? "MCP_LIST_FAILED",
4932
+ rpcError.message ?? "MCP tools/list \u5931\u8D25"
4933
+ );
4670
4934
  }
4671
- if (typeof m.runtime !== "object" || m.runtime === null) {
4672
- errors.push({
4673
- code: "MISSING_RUNTIME",
4674
- message: "runtime \u5FC5\u987B\u662F\u5BF9\u8C61",
4675
- field: "runtime"
4676
- });
4677
- } else {
4678
- const runtime = m.runtime;
4679
- if (typeof runtime.engine !== "string" || runtime.engine.trim() === "") {
4680
- errors.push({
4681
- code: "MISSING_ENGINE",
4682
- message: "runtime.engine \u5FC5\u987B\u975E\u7A7A",
4683
- field: "runtime.engine"
4684
- });
4685
- }
4686
- if (typeof runtime.engineVersion !== "string" || runtime.engineVersion.trim() === "") {
4687
- errors.push({
4688
- code: "MISSING_ENGINE_VERSION",
4689
- message: "runtime.engineVersion \u5FC5\u987B\u975E\u7A7A",
4690
- field: "runtime.engineVersion"
4691
- });
4692
- }
4693
- if (typeof runtime.port !== "number" || !Number.isInteger(runtime.port) || runtime.port < 1 || runtime.port > 65535) {
4694
- errors.push({
4695
- code: "INVALID_PORT",
4696
- message: "runtime.port \u5FC5\u987B\u662F 1-65535 \u7684\u6574\u6570",
4697
- field: "runtime.port"
4698
- });
4699
- }
4700
- if (typeof runtime.startCommand !== "string" || runtime.startCommand.trim() === "") {
4701
- errors.push({
4702
- code: "MISSING_START_COMMAND",
4703
- message: "runtime.startCommand \u5FC5\u987B\u975E\u7A7A",
4704
- field: "runtime.startCommand"
4705
- });
4706
- }
4935
+ return {
4936
+ projectId: project2.id,
4937
+ slug: project2.slug,
4938
+ endpoint,
4939
+ tools: parsed?.result?.tools ?? []
4940
+ };
4941
+ }
4942
+ function requireFunctionName(fn) {
4943
+ if (fn === void 0 || fn.trim().length === 0) {
4944
+ throw new CliError("INVALID_ARGUMENT", "\u7F3A\u5C11\u51FD\u6570\u540D\uFF1Aadep mcp publish --function <fn>");
4945
+ }
4946
+ return fn.trim();
4947
+ }
4948
+ async function resolveProject(client, options) {
4949
+ const slug = await resolveSlug(resolve9(options.cwd), options.slug);
4950
+ const listed = await client.request("/api/v1/projects", {}, "PROJECT_LIST_FAILED");
4951
+ const match = listed.projects.find((project2) => project2.slug === slug);
4952
+ if (match === void 0) {
4953
+ throw new CliError(
4954
+ "PROJECT_NOT_FOUND",
4955
+ `\u5E73\u53F0\u9879\u76EE "${slug}" \u4E0D\u5B58\u5728\u6216\u4F60\u6CA1\u6709\u8BBF\u95EE\u6743\u9650\uFF1A\u5148\u6267\u884C adep projects create ${slug}`
4956
+ );
4957
+ }
4958
+ return {
4959
+ id: match.id,
4960
+ slug: match.slug,
4961
+ url: match.url,
4962
+ ...match.functionsPrefix === void 0 ? {} : { functionsPrefix: match.functionsPrefix }
4963
+ };
4964
+ }
4965
+ async function resolveFunction(client, project2, name) {
4966
+ const listed = await client.request(`/api/v1/projects/${project2.id}/functions`, {}, "FUNCTION_LIST_FAILED");
4967
+ const target = listed.functions.find((fn) => fn.name === name);
4968
+ if (target === void 0) {
4969
+ throw new CliError("FN_NOT_FOUND", `\u51FD\u6570 "${name}" \u4E0D\u5B58\u5728\u4E8E\u9879\u76EE "${project2.slug}"`);
4970
+ }
4971
+ return { id: target.id, name: target.name };
4972
+ }
4973
+ var init_mcp = __esm({
4974
+ "src/mcp.ts"() {
4975
+ "use strict";
4976
+ init_auth();
4977
+ init_client();
4707
4978
  }
4708
- if (typeof m.exportedAt !== "string" || m.exportedAt.trim() === "") {
4709
- errors.push({
4710
- code: "MISSING_EXPORTED_AT",
4711
- message: "exportedAt \u5FC5\u987B\u975E\u7A7A",
4712
- field: "exportedAt"
4713
- });
4714
- } else {
4715
- const date = new Date(m.exportedAt);
4716
- if (Number.isNaN(date.getTime())) {
4717
- errors.push({
4718
- code: "INVALID_EXPORTED_AT",
4719
- message: "exportedAt \u5FC5\u987B\u662F\u6709\u6548\u7684 ISO 8601 \u65F6\u95F4",
4720
- field: "exportedAt"
4721
- });
4722
- }
4979
+ });
4980
+
4981
+ // src/projects.ts
4982
+ var projects_exports = {};
4983
+ __export(projects_exports, {
4984
+ projectsCreate: () => projectsCreate,
4985
+ projectsInfo: () => projectsInfo,
4986
+ projectsList: () => projectsList
4987
+ });
4988
+ function requireSlug(slug, hint) {
4989
+ if (slug === void 0 || slug.trim().length === 0) {
4990
+ throw new CliError("INVALID_SLUG", `\u7F3A\u5C11\u9879\u76EE slug\uFF1A${hint}`);
4723
4991
  }
4724
- return {
4725
- valid: errors.length === 0,
4726
- errors,
4727
- warnings
4728
- };
4992
+ return slug.trim();
4729
4993
  }
4730
- function validateContent(content, index, errors, _warnings) {
4731
- if (typeof content !== "object" || content === null) {
4732
- errors.push({
4733
- code: "INVALID_CONTENT",
4734
- message: `contents[${index}] \u5FC5\u987B\u662F\u5BF9\u8C61`,
4735
- field: `contents[${index}]`
4736
- });
4737
- return;
4994
+ async function projectsCreate(paths, options) {
4995
+ await requireNetworkGuard();
4996
+ const client = await createClient(paths);
4997
+ const slug = requireSlug(options.slug, "adep projects create <slug>");
4998
+ const name = options.name ?? slug;
4999
+ const body = { slug, name };
5000
+ if (options.spaceId !== void 0) body.spaceId = options.spaceId;
5001
+ const created = await client.request(
5002
+ "/api/v1/projects",
5003
+ { body },
5004
+ "PROJECT_CREATE_FAILED"
5005
+ );
5006
+ if (created.url === void 0 || created.url.length === 0) {
5007
+ throw new CliError("PROJECT_CREATE_FAILED", "\u5E73\u53F0\u672A\u8FD4\u56DE\u9879\u76EE\u5730\u5740\uFF0C\u65E0\u6CD5\u8F93\u51FA\u5B50\u57DF URL");
4738
5008
  }
4739
- const c = content;
4740
- if (typeof c.path !== "string" || c.path.trim() === "") {
4741
- errors.push({
4742
- code: "MISSING_CONTENT_PATH",
4743
- message: `contents[${index}].path \u5FC5\u987B\u975E\u7A7A`,
4744
- field: `contents[${index}].path`
4745
- });
5009
+ return created;
5010
+ }
5011
+ async function projectsList(paths) {
5012
+ await requireNetworkGuard();
5013
+ const client = await createClient(paths);
5014
+ const result = await client.request(
5015
+ "/api/v1/projects",
5016
+ {},
5017
+ "PROJECT_LIST_FAILED"
5018
+ );
5019
+ return result.projects;
5020
+ }
5021
+ async function projectsInfo(paths, options) {
5022
+ await requireNetworkGuard();
5023
+ const slug = requireSlug(options.slug, "adep projects info <slug>");
5024
+ const projects = await projectsList(paths);
5025
+ const match = projects.find((project2) => project2.slug === slug);
5026
+ if (match === void 0) {
5027
+ throw new CliError("PROJECT_NOT_FOUND", `\u9879\u76EE "${slug}" \u4E0D\u5B58\u5728\u6216\u4F60\u6CA1\u6709\u8BBF\u95EE\u6743\u9650`);
4746
5028
  }
4747
- if (typeof c.sha256 !== "string" || c.sha256.trim() === "") {
4748
- errors.push({
4749
- code: "MISSING_CONTENT_SHA256",
4750
- message: `contents[${index}].sha256 \u5FC5\u987B\u975E\u7A7A`,
4751
- field: `contents[${index}].sha256`
4752
- });
4753
- } else if (!/^[a-fA-F0-9]{64}$/.test(c.sha256)) {
4754
- errors.push({
4755
- code: "INVALID_SHA256_FORMAT",
4756
- message: `contents[${index}].sha256 \u5FC5\u987B\u662F 64 \u5B57\u7B26\u5341\u516D\u8FDB\u5236`,
4757
- field: `contents[${index}].sha256`
4758
- });
5029
+ return match;
5030
+ }
5031
+ async function requireNetworkGuard() {
5032
+ const { requireNetwork: requireNetwork2 } = await Promise.resolve().then(() => (init_net(), net_exports));
5033
+ await requireNetwork2("adep projects");
5034
+ }
5035
+ var init_projects = __esm({
5036
+ "src/projects.ts"() {
5037
+ "use strict";
5038
+ init_auth();
5039
+ init_client();
4759
5040
  }
4760
- if (typeof c.kind !== "string" || c.kind.trim() === "") {
4761
- errors.push({
4762
- code: "MISSING_CONTENT_KIND",
4763
- message: `contents[${index}].kind \u5FC5\u987B\u975E\u7A7A`,
4764
- field: `contents[${index}].kind`
4765
- });
4766
- } else if (!ALLOWED_CONTENT_KINDS.includes(c.kind)) {
4767
- errors.push({
4768
- code: "INVALID_CONTENT_KIND",
4769
- message: `contents[${index}].kind "${c.kind}" \u4E0D\u5728\u5141\u8BB8\u5217\u8868\u5185\uFF0C\u5141\u8BB8\u503C\uFF1A${ALLOWED_CONTENT_KINDS.join(", ")}`,
4770
- field: `contents[${index}].kind`
4771
- });
5041
+ });
5042
+
5043
+ // src/functions.ts
5044
+ var functions_exports = {};
5045
+ __export(functions_exports, {
5046
+ functionsDeploy: () => functionsDeploy,
5047
+ functionsList: () => functionsList,
5048
+ functionsLogs: () => functionsLogs
5049
+ });
5050
+ import { resolve as resolve10 } from "node:path";
5051
+ async function functionsDeploy(paths, options) {
5052
+ const startedAt = Date.now();
5053
+ const result = await deploy(paths, {
5054
+ cwd: options.cwd,
5055
+ ...options.slug === void 0 ? {} : { slug: options.slug },
5056
+ ...options.dir === void 0 ? {} : { functionsDir: resolve10(options.cwd, options.dir) },
5057
+ silent: true
5058
+ });
5059
+ return { ...result, elapsedSeconds: (Date.now() - startedAt) / 1e3 };
5060
+ }
5061
+ async function functionsList(paths, options) {
5062
+ const client = await createClient(paths);
5063
+ const project2 = await resolveProject2(client, options);
5064
+ const result = await client.request(
5065
+ `/api/v1/projects/${project2.id}/functions`,
5066
+ {},
5067
+ "FUNCTION_LIST_FAILED"
5068
+ );
5069
+ const prefix = project2.functionsPrefix ?? "/api";
5070
+ const prefixBase = prefix.trim() === "/" ? "" : prefix.trim().replace(/\/+$/, "");
5071
+ return {
5072
+ projectId: project2.id,
5073
+ slug: project2.slug,
5074
+ baseUrl: `${project2.url.replace(/\/+$/, "")}${prefixBase}`,
5075
+ functions: result.functions
5076
+ };
5077
+ }
5078
+ async function functionsLogs(paths, options) {
5079
+ if (options.name === void 0 || options.name.trim().length === 0) {
5080
+ throw new CliError("INVALID_ARGUMENT", "\u7F3A\u5C11\u51FD\u6570\u540D\uFF1Aadep functions logs <name>");
5081
+ }
5082
+ const client = await createClient(paths);
5083
+ const project2 = await resolveProject2(client, options);
5084
+ const listed = await client.request(
5085
+ `/api/v1/projects/${project2.id}/functions`,
5086
+ {},
5087
+ "FUNCTION_LIST_FAILED"
5088
+ );
5089
+ const target = listed.functions.find((fn) => fn.name === options.name);
5090
+ if (target === void 0) {
5091
+ throw new CliError("FN_NOT_FOUND", `\u51FD\u6570 "${options.name}" \u4E0D\u5B58\u5728\u4E8E\u9879\u76EE "${project2.slug}"`);
4772
5092
  }
5093
+ const tail = options.tail === void 0 ? "" : `?tail=${encodeURIComponent(String(options.tail))}`;
5094
+ const result = await client.request(
5095
+ `/api/v1/functions/${target.id}/logs${tail}`,
5096
+ {},
5097
+ "FUNCTION_LOGS_FAILED"
5098
+ );
5099
+ return { functionId: target.id, name: target.name, logs: result.logs };
4773
5100
  }
4774
- function verifyContents(contents, actualContents, hashFunction) {
4775
- const errors = [];
4776
- const warnings = [];
4777
- for (const content of contents) {
4778
- const actual = actualContents.get(content.path);
4779
- if (actual === void 0) {
4780
- errors.push({
4781
- code: "CONTENT_NOT_FOUND",
4782
- message: `\u5185\u5BB9\u7269 ${content.path} \u5728\u5B9E\u9645\u5305\u4E2D\u4E0D\u5B58\u5728`,
4783
- field: `contents[${content.path}]`
4784
- });
4785
- continue;
4786
- }
4787
- const actualHash = hashFunction(actual);
4788
- if (actualHash.toLowerCase() !== content.sha256.toLowerCase()) {
4789
- errors.push({
4790
- code: "CHECKSUM_MISMATCH",
4791
- message: `\u5185\u5BB9\u7269 ${content.path} \u7684\u6821\u9A8C\u548C\u4E0D\u5339\u914D\uFF1A\u671F\u671B ${content.sha256}\uFF0C\u5B9E\u9645 ${actualHash}`,
4792
- field: `contents[${content.path}].sha256`
4793
- });
4794
- }
5101
+ async function resolveProject2(client, options) {
5102
+ const slug = await resolveSlug(resolve10(options.cwd), options.slug);
5103
+ const projects = await projectsListFrom(client);
5104
+ const match = projects.find((project2) => project2.slug === slug);
5105
+ if (match === void 0) {
5106
+ throw new CliError(
5107
+ "PROJECT_NOT_FOUND",
5108
+ `\u5E73\u53F0\u9879\u76EE "${slug}" \u4E0D\u5B58\u5728\u6216\u4F60\u6CA1\u6709\u8BBF\u95EE\u6743\u9650\uFF1A\u5148\u6267\u884C adep projects create ${slug}`
5109
+ );
4795
5110
  }
4796
- for (const path of actualContents.keys()) {
4797
- if (!contents.some((c) => c.path === path)) {
4798
- warnings.push({
4799
- code: "UNDECLARED_CONTENT",
4800
- message: `\u5B9E\u9645\u5305\u4E2D\u5B58\u5728 Manifest \u672A\u58F0\u660E\u7684\u5185\u5BB9\uFF1A${path}`,
4801
- field: `contents[${path}]`
4802
- });
4803
- }
5111
+ return match;
5112
+ }
5113
+ async function projectsListFrom(client) {
5114
+ const result = await client.request("/api/v1/projects", {}, "PROJECT_LIST_FAILED");
5115
+ return result.projects;
5116
+ }
5117
+ var init_functions = __esm({
5118
+ "src/functions.ts"() {
5119
+ "use strict";
5120
+ init_auth();
5121
+ init_client();
5122
+ init_deploy();
4804
5123
  }
5124
+ });
5125
+
5126
+ // src/hosting.ts
5127
+ var hosting_exports = {};
5128
+ __export(hosting_exports, {
5129
+ hostingConfig: () => hostingConfig,
5130
+ hostingDeploy: () => hostingDeploy,
5131
+ hostingInfo: () => hostingInfo,
5132
+ hostingPull: () => hostingPull
5133
+ });
5134
+ import { readdir as readdir5, readFile as readFile11, stat as stat9 } from "node:fs/promises";
5135
+ import { dirname as dirname8, join as join13, relative as relative2, resolve as resolve11, sep } from "node:path";
5136
+ async function open4(paths, options) {
5137
+ const client = await createClient(paths);
5138
+ const project2 = await resolveSlug(resolve11(options.cwd), options.slug);
5139
+ return { client, project: project2 };
5140
+ }
5141
+ async function hostingInfo(paths, options) {
5142
+ const { client, project: project2 } = await open4(paths, options);
5143
+ const body = await client.request(`/api/v1/projects/${project2}/hosting`);
4805
5144
  return {
4806
- valid: errors.length === 0,
4807
- errors,
4808
- warnings
5145
+ config: body.config,
5146
+ siteUrl: body.siteUrl,
5147
+ files: body.files ?? []
5148
+ };
5149
+ }
5150
+ async function collectSiteFiles(dir) {
5151
+ const root = resolve11(dir);
5152
+ const files = /* @__PURE__ */ new Map();
5153
+ const walk = async (sub) => {
5154
+ let entries;
5155
+ try {
5156
+ entries = await readdir5(sub, { withFileTypes: true });
5157
+ } catch {
5158
+ return;
5159
+ }
5160
+ for (const entry of entries) {
5161
+ const full = join13(sub, entry.name);
5162
+ if (entry.isDirectory()) {
5163
+ await walk(full);
5164
+ } else if (entry.isFile()) {
5165
+ const rel = relative2(root, full).split(sep).join("/");
5166
+ files.set(rel, full);
5167
+ }
5168
+ }
4809
5169
  };
5170
+ await walk(root);
5171
+ return files;
4810
5172
  }
4811
- var init_validate = __esm({
4812
- "shared/deploy-bundle/validate.ts"() {
4813
- "use strict";
4814
- init_manifest2();
5173
+ async function hostingDeploy(paths, options) {
5174
+ const { client, project: project2 } = await open4(paths, options);
5175
+ const log = options.log ?? ((line) => process.stdout.write(`${line}
5176
+ `));
5177
+ const files = await collectSiteFiles(options.dir);
5178
+ if (files.size === 0) {
5179
+ throw new CliError("NO_SITE_FILES", `\u7AD9\u70B9\u76EE\u5F55\u4E3A\u7A7A\uFF1A${resolve11(options.dir)}`);
4815
5180
  }
4816
- });
4817
-
4818
- // packages/cli/src/export/command.ts
4819
- var command_exports = {};
4820
- __export(command_exports, {
4821
- ExportCommand: () => ExportCommand
4822
- });
4823
- import { createHash as createHash3 } from "node:crypto";
4824
- var ExportCommand;
4825
- var init_command = __esm({
4826
- "packages/cli/src/export/command.ts"() {
4827
- "use strict";
4828
- init_validate();
4829
- ExportCommand = class {
4830
- constructor(apiClient, fs, pollInterval = 2e3, maxPollAttempts = 300) {
4831
- this.apiClient = apiClient;
4832
- this.fs = fs;
4833
- this.pollInterval = pollInterval;
4834
- this.maxPollAttempts = maxPollAttempts;
4835
- }
4836
- /**
4837
- * 执行导出命令。
4838
- *
4839
- * @param options 命令选项
4840
- * @returns 导出结果
4841
- */
4842
- async execute(options) {
4843
- const projectId = options.project ?? "default";
4844
- const outputDir = options.out ?? "./exports";
4845
- const jsonOutput = options.json ?? false;
4846
- try {
4847
- if (!jsonOutput) {
4848
- console.log(`\u89E6\u53D1\u5BFC\u51FA\uFF1A\u9879\u76EE ${projectId}`);
4849
- }
4850
- const job = await this.apiClient.triggerExport(projectId, {
4851
- withData: options.withData,
4852
- withSource: options.withSource
4853
- });
4854
- if (!jsonOutput) {
4855
- console.log(`\u5BFC\u51FA\u4EFB\u52A1\u5DF2\u521B\u5EFA\uFF1A${job.id}`);
4856
- }
4857
- const completedJob = await this.pollJobStatus(job.id, jsonOutput);
4858
- if (completedJob.status === "failed") {
4859
- return {
4860
- success: false,
4861
- jobId: job.id,
4862
- status: "failed",
4863
- error: completedJob.error ?? "\u5BFC\u51FA\u5931\u8D25"
4864
- };
4865
- }
4866
- if (!jsonOutput) {
4867
- console.log("\u4E0B\u8F7D\u5BFC\u51FA\u4EA7\u7269...");
4868
- }
4869
- const outputPath = `${outputDir}/${projectId}-export-${Date.now()}.zip`;
4870
- await this.fs.mkdir(outputDir);
4871
- const downloadResult = await this.apiClient.downloadBundle(job.id, outputPath);
4872
- if (!jsonOutput) {
4873
- console.log(`\u4EA7\u7269\u5DF2\u4E0B\u8F7D\uFF1A${downloadResult.path}\uFF08${this.formatSize(downloadResult.size)}\uFF09`);
4874
- }
4875
- if (!jsonOutput) {
4876
- console.log("\u6267\u884C manifest \u81EA\u68C0...");
4877
- }
4878
- const manifest = await this.verifyManifest(downloadResult.path);
4879
- if (!jsonOutput) {
4880
- this.printContentList(manifest);
4881
- }
4882
- return {
4883
- success: true,
4884
- jobId: job.id,
4885
- status: "completed",
4886
- downloadPath: downloadResult.path,
4887
- manifest: {
4888
- projectName: manifest.project.name,
4889
- platformVersion: manifest.platformVersion,
4890
- exportedAt: manifest.exportedAt,
4891
- contents: this.countContents(manifest.contents)
4892
- }
4893
- };
4894
- } catch (error) {
4895
- const message = error instanceof Error ? error.message : "unknown_error";
4896
- if (message.includes("ECONNREFUSED") || message.includes("ENOTFOUND") || message.includes("network")) {
4897
- return {
4898
- success: false,
4899
- error: `\u5E73\u53F0\u7AEF\u70B9\u4E0D\u53EF\u8FBE\uFF1A${message}\u3002\u8BF7\u68C0\u67E5\u7F51\u7EDC\u8FDE\u63A5\u548C\u5E73\u53F0\u5730\u5740\u914D\u7F6E\uFF0C\u7136\u540E\u91CD\u8BD5\u3002`
4900
- };
4901
- }
4902
- return {
4903
- success: false,
4904
- error: message
4905
- };
4906
- }
4907
- }
4908
- /**
4909
- * 轮询任务状态。
4910
- *
4911
- * @param jobId 任务 ID
4912
- * @param jsonOutput 是否 JSON 输出
4913
- * @returns 完成的任务
4914
- */
4915
- async pollJobStatus(jobId, jsonOutput) {
4916
- let attempts = 0;
4917
- let lastProgress = -1;
4918
- while (attempts < this.maxPollAttempts) {
4919
- const job = await this.apiClient.getJobStatus(jobId);
4920
- if (!jsonOutput && job.progress !== lastProgress) {
4921
- const stage = job.stage ? `\uFF08${job.stage}\uFF09` : "";
4922
- console.log(`\u8FDB\u5EA6\uFF1A${job.progress}%${stage}`);
4923
- lastProgress = job.progress;
4924
- }
4925
- if (job.status === "completed" || job.status === "failed") {
4926
- return job;
4927
- }
4928
- attempts++;
4929
- await this.sleep(this.pollInterval);
4930
- }
4931
- throw new Error(`\u5BFC\u51FA\u4EFB\u52A1\u8D85\u65F6\uFF1A\u8F6E\u8BE2 ${this.maxPollAttempts} \u6B21\u540E\u4ECD\u672A\u5B8C\u6210`);
4932
- }
4933
- /**
4934
- * 验证 Manifest:解压 → 契约校验 → 逐项 sha256 校验 → 清理临时目录。
4935
- *
4936
- * 逐项校验与导出端同法:内容物以 latin1 承载(逐字节双射,二进制条目不被解码改写),
4937
- * 比对时对原字节做真实 sha256;任一不匹配即判定包损坏并抛错,不静默放行。
4938
- * 无论成功失败,`${zip}.tmp` 临时目录都在 finally 里删除,不留残余。
4939
- *
4940
- * @param zipPath ZIP 文件路径
4941
- * @returns Manifest
4942
- */
4943
- async verifyManifest(zipPath) {
4944
- const tempDir = `${zipPath}.tmp`;
4945
- try {
4946
- await this.fs.mkdir(tempDir);
4947
- await this.fs.unzip(zipPath, tempDir);
4948
- const manifestPath = `${tempDir}/manifest.json`;
4949
- if (!await this.fs.fileExists(manifestPath)) {
4950
- throw new Error("manifest.json \u4E0D\u5B58\u5728\uFF0C\u5305\u53EF\u80FD\u5DF2\u635F\u574F");
4951
- }
4952
- const manifestContent = await this.fs.readFile(manifestPath);
4953
- const manifest = JSON.parse(manifestContent.toString("utf-8"));
4954
- const validationResult = validateBundleManifest(manifest);
4955
- if (!validationResult.valid) {
4956
- const errors = validationResult.errors.map((e) => `${e.field ?? ""}: ${e.message}`).join("\n");
4957
- throw new Error(`manifest \u6821\u9A8C\u5931\u8D25\uFF1A
4958
- ${errors}`);
4959
- }
4960
- const actual = /* @__PURE__ */ new Map();
4961
- for (const content of manifest.contents) {
4962
- const filePath = `${tempDir}/${content.path}`;
4963
- if (await this.fs.fileExists(filePath)) {
4964
- const bytes = await this.fs.readFile(filePath);
4965
- actual.set(content.path, bytes.toString("latin1"));
4966
- }
4967
- }
4968
- const contentResult = verifyContents(
4969
- manifest.contents,
4970
- actual,
4971
- (text) => createHash3("sha256").update(Buffer.from(text, "latin1")).digest("hex")
4972
- );
4973
- if (!contentResult.valid) {
4974
- const detail = contentResult.errors.map((e) => e.message).join("\n");
4975
- throw new Error(`\u5185\u5BB9\u7269\u6821\u9A8C\u548C\u4E0D\u5339\u914D\uFF1A
4976
- ${detail}`);
4977
- }
4978
- return manifest;
4979
- } finally {
4980
- await this.fs.deleteFile(tempDir);
4981
- }
4982
- }
4983
- /**
4984
- * 统计内容物数量。
4985
- *
4986
- * @param contents 内容物列表
4987
- * @returns 统计结果
4988
- */
4989
- countContents(contents) {
4990
- return {
4991
- functions: contents.filter((c) => c.kind === "functions").length,
4992
- database: contents.filter((c) => c.kind === "database").length,
4993
- web: contents.filter((c) => c.kind === "web").length,
4994
- runtime: contents.filter((c) => c.kind === "runtime").length,
4995
- scripts: contents.filter((c) => c.kind === "scripts").length,
4996
- docs: contents.filter((c) => c.kind === "docs").length,
4997
- total: contents.length
4998
- };
4999
- }
5000
- /**
5001
- * 打印内容清单。
5002
- *
5003
- * @param manifest Manifest
5004
- */
5005
- printContentList(manifest) {
5006
- const counts = this.countContents(manifest.contents);
5007
- console.log("");
5008
- console.log("==========================================");
5009
- console.log("\u5BFC\u51FA\u5185\u5BB9\u6E05\u5355");
5010
- console.log("==========================================");
5011
- console.log(`\u9879\u76EE\uFF1A${manifest.project.name}`);
5012
- console.log(`\u5E73\u53F0\u7248\u672C\uFF1A${manifest.platformVersion}`);
5013
- console.log(`\u5BFC\u51FA\u65F6\u95F4\uFF1A${manifest.exportedAt}`);
5014
- console.log("");
5015
- console.log(`\u51FD\u6570\u6587\u4EF6\uFF1A${counts.functions}`);
5016
- console.log(`\u6570\u636E\u5E93\u6587\u4EF6\uFF1A${counts.database}`);
5017
- console.log(`\u524D\u7AEF\u6587\u4EF6\uFF1A${counts.web}`);
5018
- console.log(`\u8FD0\u884C\u65F6\u6587\u4EF6\uFF1A${counts.runtime}`);
5019
- console.log(`\u811A\u672C\u6587\u4EF6\uFF1A${counts.scripts}`);
5020
- console.log(`\u6587\u6863\u6587\u4EF6\uFF1A${counts.docs}`);
5021
- console.log(`\u603B\u6587\u4EF6\u6570\uFF1A${counts.total}`);
5022
- console.log("==========================================");
5023
- }
5024
- /**
5025
- * 格式化文件大小。
5026
- *
5027
- * @param bytes 字节数
5028
- * @returns 格式化后的大小
5029
- */
5030
- formatSize(bytes) {
5031
- if (bytes < 1024) return `${bytes} B`;
5032
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
5033
- if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
5034
- return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
5035
- }
5036
- /**
5037
- * 睡眠指定毫秒数。
5038
- *
5039
- * @param ms 毫秒数
5040
- */
5041
- sleep(ms) {
5042
- return new Promise((resolve11) => setTimeout(resolve11, ms));
5043
- }
5044
- };
5181
+ const uploaded = [];
5182
+ for (const [rel, full] of files) {
5183
+ log(`[adep] \u4E0A\u4F20 site/${rel}`);
5184
+ const info2 = await stat9(full);
5185
+ const bytes = await readFile11(full);
5186
+ const form = new FormData();
5187
+ form.set("path", `site/${rel}`);
5188
+ form.set("visibility", "public");
5189
+ form.set(
5190
+ "file",
5191
+ new Blob([bytes], { type: contentTypeOf(rel) }),
5192
+ rel.split("/").pop()
5193
+ );
5194
+ await client.upload(`/api/v1/projects/${project2}/files`, form, "HOSTING_UPLOAD_FAILED");
5195
+ uploaded.push({ path: `site/${rel}`, size: info2.size });
5196
+ }
5197
+ const config = await client.request(
5198
+ `/api/v1/projects/${project2}/hosting`,
5199
+ {
5200
+ method: "PUT",
5201
+ body: options.spa === void 0 ? { enabled: true } : { enabled: true, spaMode: options.spa }
5202
+ }
5203
+ );
5204
+ const info = await hostingInfo(paths, options);
5205
+ return { config: config.config, siteUrl: info.siteUrl, uploaded };
5206
+ }
5207
+ async function hostingPull(paths, options) {
5208
+ const { client } = await open4(paths, options);
5209
+ const log = options.log ?? ((line) => process.stdout.write(`${line}
5210
+ `));
5211
+ const info = await hostingInfo(paths, options);
5212
+ const outputDir = resolve11(options.output ?? resolve11(options.cwd));
5213
+ const { mkdir: mkdir9, writeFile: writeFile8 } = await import("node:fs/promises");
5214
+ const files = [];
5215
+ for (const entry of info.files) {
5216
+ if (entry.visibility !== "public" || entry.path === HOSTING_CONFIG_PATH) continue;
5217
+ const url = entry.url;
5218
+ if (url === void 0 || url.length === 0) continue;
5219
+ log(`[adep] \u4E0B\u8F7D ${entry.path}`);
5220
+ const response = await client.download(url, "HOSTING_DOWNLOAD_FAILED");
5221
+ const bytes = Buffer.from(await response.arrayBuffer());
5222
+ const rel = entry.path.replace(/^site\//, "");
5223
+ const target = join13(outputDir, ...rel.split("/"));
5224
+ await mkdir9(dirname8(target), { recursive: true });
5225
+ await writeFile8(target, bytes);
5226
+ files.push({ path: entry.path, size: bytes.length });
5227
+ }
5228
+ return { siteUrl: info.siteUrl, outputDir, files };
5229
+ }
5230
+ async function hostingConfig(paths, options) {
5231
+ const { client, project: project2 } = await open4(paths, options);
5232
+ const body = {};
5233
+ if (options.enabled !== void 0) body["enabled"] = options.enabled;
5234
+ if (options.spa !== void 0) body["spaMode"] = options.spa;
5235
+ const result = await client.request(
5236
+ `/api/v1/projects/${project2}/hosting`,
5237
+ { method: "PUT", body }
5238
+ );
5239
+ return result.config;
5240
+ }
5241
+ var HOSTING_CONFIG_PATH;
5242
+ var init_hosting = __esm({
5243
+ "src/hosting.ts"() {
5244
+ "use strict";
5245
+ init_client();
5246
+ init_auth();
5247
+ init_storage2();
5248
+ HOSTING_CONFIG_PATH = "site/.hosting.json";
5045
5249
  }
5046
5250
  });
5047
5251
 
5048
- // packages/cli/src/cli.ts
5252
+ // src/cli.ts
5049
5253
  init_config();
5050
5254
  import { Command } from "commander";
5051
5255
  import { createRequire as createRequire2 } from "node:module";
5052
5256
 
5053
- // packages/cli/src/output.ts
5257
+ // src/output.ts
5054
5258
  init_auth();
5055
5259
 
5056
- // packages/cli/src/init.ts
5260
+ // src/init.ts
5057
5261
  import { mkdir as mkdir2, stat as stat2, writeFile } from "node:fs/promises";
5058
5262
  import { createRequire } from "node:module";
5059
5263
  import { dirname as dirname2, join, resolve } from "node:path";
5060
5264
 
5061
- // shared/sdk/adep-env.ts
5265
+ // ../../shared/sdk/adep-env.ts
5062
5266
  var ADEP_ENV_DTS = `/**
5063
5267
  * 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
5064
5268
  *
@@ -5334,7 +5538,109 @@ var ADEP_TSCONFIG_JSON = `{
5334
5538
  }
5335
5539
  `;
5336
5540
 
5337
- // shared/sdk/web-project-template.ts
5541
+ // src/init.ts
5542
+ init_adep_config();
5543
+
5544
+ // ../../shared/sdk/web-project-template.ts
5545
+ var WEB_DEPENDENCIES = {
5546
+ vue: "^3.3.4"
5547
+ };
5548
+ var WEB_DEV_DEPENDENCIES = {
5549
+ vite: "^4.4.0",
5550
+ "@vitejs/plugin-vue": "^4.3.0",
5551
+ // vite 内部动态 import('esbuild-wasm'),必须在 package.json 显式声明才能被 Nodebox 解析
5552
+ "esbuild-wasm": "0.18.20"
5553
+ };
5554
+ var WEB_FN_PROXY_SCRIPT = `(function () {
5555
+ if (window.__adepFnProxyInstalled) return;
5556
+ window.__adepFnProxyInstalled = true;
5557
+ var ORIGINAL_FETCH = window.fetch.bind(window);
5558
+ var pending = {};
5559
+ var nextId = 1;
5560
+ var TIMEOUT_MS = 15000;
5561
+
5562
+ window.addEventListener("message", function (event) {
5563
+ var data = event.data;
5564
+ if (!data || data.__adepFnResponse !== true) return;
5565
+ var entry = pending[data.id];
5566
+ if (!entry) return;
5567
+ delete pending[data.id];
5568
+ clearTimeout(entry.timer);
5569
+ var headers;
5570
+ try { headers = new Headers(data.headers || {}); }
5571
+ catch (e) { headers = new Headers({ "content-type": "text/plain" }); }
5572
+ var body = data.body == null ? null : data.body;
5573
+ try {
5574
+ entry.resolve(new Response(body, { status: data.status || 200, statusText: "", headers: headers }));
5575
+ } catch (e2) {
5576
+ entry.resolve(new Response(String(body), { status: data.status || 200, headers: { "content-type": "text/plain" } }));
5577
+ }
5578
+ });
5579
+
5580
+ function readBody(input, init) {
5581
+ if (typeof Request !== "undefined" && input instanceof Request) {
5582
+ return input.text().catch(function () { return null; });
5583
+ }
5584
+ var body = init && init.body !== undefined ? init.body : input;
5585
+ if (body == null) return Promise.resolve(null);
5586
+ if (typeof body === "string") return Promise.resolve(body);
5587
+ if (typeof ArrayBuffer !== "undefined" && body instanceof ArrayBuffer) {
5588
+ return Promise.resolve(new TextDecoder().decode(body));
5589
+ }
5590
+ if (typeof Blob !== "undefined" && body instanceof Blob) return body.text();
5591
+ if (typeof URLSearchParams !== "undefined" && body instanceof URLSearchParams) {
5592
+ return Promise.resolve(body.toString());
5593
+ }
5594
+ try { return Promise.resolve(String(body)); } catch (e) { return Promise.resolve(null); }
5595
+ }
5596
+
5597
+ function collectHeaders(input, init) {
5598
+ var out = {};
5599
+ try { input.headers.forEach(function (v, k) { out[k] = v; }); } catch (e) {}
5600
+ if (init && init.headers) {
5601
+ try { new Headers(init.headers).forEach(function (v, k) { out[k] = v; }); } catch (e2) {}
5602
+ }
5603
+ return out;
5604
+ }
5605
+
5606
+ window.fetch = function (input, init) {
5607
+ var urlStr;
5608
+ var method;
5609
+ var headers = {};
5610
+ var isRequest = typeof Request !== "undefined" && input instanceof Request;
5611
+ if (isRequest) {
5612
+ urlStr = String(input.url);
5613
+ method = (init && init.method) || input.method || "GET";
5614
+ headers = collectHeaders(input, init);
5615
+ } else if (typeof input === "string" || (typeof URL !== "undefined" && input instanceof URL)) {
5616
+ urlStr = String(input);
5617
+ method = (init && init.method) || "GET";
5618
+ try { new Headers(init && init.headers || {}).forEach(function (v, k) { headers[k] = v; }); } catch (e) {}
5619
+ } else {
5620
+ return ORIGINAL_FETCH(input, init);
5621
+ }
5622
+ var u;
5623
+ try { u = new URL(urlStr, document.baseURI); }
5624
+ catch (e) { return ORIGINAL_FETCH(input, init); }
5625
+ if (u.pathname.indexOf("/api/") !== 0 && u.pathname !== "/api") {
5626
+ return ORIGINAL_FETCH(input, init);
5627
+ }
5628
+ if (window.parent === window) return ORIGINAL_FETCH(input, init);
5629
+ method = (method || "GET").toUpperCase();
5630
+ var target = u.pathname + u.search;
5631
+ return readBody(input, init).then(function (textBody) {
5632
+ return new Promise(function (resolve) {
5633
+ var id = nextId++;
5634
+ var timer = setTimeout(function () {
5635
+ delete pending[id];
5636
+ resolve(new Response('{"error":{"code":"FN_PROXY_TIMEOUT","message":"\\u4e91\\u51fd\\u6570\\u6267\\u884c\\u8d85\\u65f6"}}', { status: 504, headers: { "content-type": "application/json" } }));
5637
+ }, TIMEOUT_MS);
5638
+ pending[id] = { resolve: resolve, timer: timer };
5639
+ window.parent.postMessage({ __adepFnRequest: true, id: id, method: method, url: target, headers: headers, body: textBody }, "*");
5640
+ });
5641
+ });
5642
+ };
5643
+ })();`;
5338
5644
  function webProjectFiles() {
5339
5645
  return [
5340
5646
  {
@@ -5345,13 +5651,8 @@ function webProjectFiles() {
5345
5651
  version: "0.0.0",
5346
5652
  type: "module",
5347
5653
  scripts: { dev: "vite" },
5348
- dependencies: { vue: "^3.3.4" },
5349
- devDependencies: {
5350
- vite: "^4.4.0",
5351
- "@vitejs/plugin-vue": "^4.3.0",
5352
- // vite 内部动态 import('esbuild-wasm'),必须在 package.json 显式声明才能被 Nodebox 解析
5353
- "esbuild-wasm": "0.18.20"
5354
- }
5654
+ dependencies: WEB_DEPENDENCIES,
5655
+ devDependencies: WEB_DEV_DEPENDENCIES
5355
5656
  },
5356
5657
  null,
5357
5658
  2
@@ -5378,12 +5679,37 @@ function webProjectFiles() {
5378
5679
  {
5379
5680
  path: "vite.config.ts",
5380
5681
  content: [
5381
- `// web/vite.config.ts \u2014\u2014 \u6807\u51C6 Vite \u914D\u7F6E\uFF08Vue 3 \u63D2\u4EF6\uFF09\u3002`,
5682
+ `// web/vite.config.ts \u2014\u2014 \u6807\u51C6 Vite \u914D\u7F6E\uFF08Vue 3 \u63D2\u4EF6\uFF09+ Web IDE \u9884\u89C8\u4E91\u51FD\u6570\u4EE3\u7406\u3002`,
5683
+ `// \u4E0B\u9762\u7684 adepFunctionsPlugin \u4EC5\u5728 Nodebox \u771F vite \u9884\u89C8\u4E0B\u751F\u6548\uFF1Adev \u65F6\u628A fetch \u62E6\u622A\u5668\u6CE8\u5165`,
5684
+ `// index.html\uFF0C\u9884\u89C8\u91CC fetch('/api/*') \u7ECF postMessage \u8F6C\u53D1\u5230 IDE \u4E3B\u7EBF\u7A0B\u6267\u884C\u5F53\u524D\u9879\u76EE\u4E91\u51FD\u6570\u8349\u7A3F\u3002`,
5685
+ `// \uFF08\u6D4F\u89C8\u5668\u5185 vite-dev \u9884\u89C8\u7531 @adep/web-container \u5728 buildDocument \u91CC\u6CE8\u5165\u540C\u4E00\u4EFD\u811A\u672C\u3002\uFF09`,
5382
5686
  `import { defineConfig } from 'vite'`,
5383
5687
  `import vue from '@vitejs/plugin-vue'`,
5384
5688
  ``,
5689
+ `// \u6CE8\u610F\uFF1AFN_PROXY_SCRIPT \u4E0E packages/web-container/src/function-fetch-proxy.ts \u7684`,
5690
+ `// FN_FETCH_INTERCEPTOR_SCRIPT \u5FC5\u987B\u9010\u5B57\u4E00\u81F4\uFF08\u4E24\u5904\u590D\u5236\u7C98\u8D34\uFF0C\u6539\u62E6\u622A\u5668\u52A1\u5FC5\u540C\u6B65\uFF09\u3002`,
5691
+ `const FN_PROXY_SCRIPT = \`${WEB_FN_PROXY_SCRIPT}\``,
5692
+ ``,
5693
+ `const adepFunctionsPlugin = {`,
5694
+ ` name: 'adep-fn-proxy',`,
5695
+ ` configureServer(server) {`,
5696
+ ` server.middlewares.use((req, res, next) => {`,
5697
+ ` const pathname = (req.url ?? '').split('?')[0]`,
5698
+ ` if (pathname === '/@adep/fn-proxy.js') {`,
5699
+ ` res.setHeader('content-type', 'application/javascript; charset=utf-8')`,
5700
+ ` res.end(FN_PROXY_SCRIPT)`,
5701
+ ` return`,
5702
+ ` }`,
5703
+ ` next()`,
5704
+ ` })`,
5705
+ ` },`,
5706
+ ` transformIndexHtml(html) {`,
5707
+ ` return html.replace('</head>', '<script src="/@adep/fn-proxy.js"></script></head>')`,
5708
+ ` },`,
5709
+ `}`,
5710
+ ``,
5385
5711
  `export default defineConfig({`,
5386
- ` plugins: [vue()],`,
5712
+ ` plugins: [vue(), adepFunctionsPlugin],`,
5387
5713
  `})`,
5388
5714
  ``
5389
5715
  ].join("\n")
@@ -5436,8 +5762,11 @@ function webProjectFiles() {
5436
5762
  }
5437
5763
  ];
5438
5764
  }
5765
+ function webSrcFiles() {
5766
+ return webProjectFiles().filter((file) => file.path.startsWith("src/"));
5767
+ }
5439
5768
 
5440
- // packages/cli/src/init.ts
5769
+ // src/init.ts
5441
5770
  var TEMPLATE_NAMES = ["empty", "function", "fullstack"];
5442
5771
  var InitError = class extends Error {
5443
5772
  constructor(code, message) {
@@ -5448,38 +5777,34 @@ var InitError = class extends Error {
5448
5777
  };
5449
5778
  var requireJson = createRequire(import.meta.url);
5450
5779
  var CLI_VERSION = requireJson("../package.json").version;
5451
- var ADEP_CONFIG = (name, template) => `// adep \u9879\u76EE\u914D\u7F6E\uFF1ACLI\uFF08dev / serve / deploy\uFF09\u6309 default export \u8BFB\u53D6\u3002
5780
+ var ADEP_CONFIG_HEADER = `// adep \u9879\u76EE\u914D\u7F6E\uFF1ACLI\uFF08dev / serve / deploy\uFF09\u4E0E\u4E91\u51FD\u6570 vite \u63D2\u4EF6\u6309 default export \u8BFB\u53D6\u3002
5452
5781
  // - name\uFF1A\u9879\u76EE\u6807\u8BC6\uFF08deploy / db \u7B49\u547D\u4EE4\u7684\u7F3A\u7701 project slug\uFF09
5453
5782
  // - template\uFF1A\u811A\u624B\u67B6\u6A21\u677F\uFF08empty / function / fullstack\uFF0Cinit \u65F6\u786E\u5B9A\uFF09
5454
5783
  // - functionsDir\uFF1A\u4E91\u51FD\u6570\u76EE\u5F55\uFF08dev / serve / deploy \u8BFB\u53D6\uFF0C\u7F3A\u7701 functions/\uFF09
5455
- // - functions_prefix\uFF1A\u672C\u5730\u8C03\u8BD5\u8DEF\u7531\u524D\u7F00\u3002\u914D\u7F6E\u540E dev \u8BBF\u95EE\u8DEF\u5F84\u4E3A /{prefix}/{fnName}\u3001
5456
- // serve \u4E3A /api/{prefix}/{fnName}\uFF1B\u7559\u7A7A\u5219\u4FDD\u6301 /{fnName} \u4E0E /api/{fnName}\u3002
5457
- // \u8FB9\u754C\uFF1A\u53EA\u5F71\u54CD\u672C\u5730 HTTP \u5165\u53E3\u8DEF\u7531\uFF1B\u51FD\u6570\u4E92\u8C03\uFF08ctx.cloud.invoke\uFF09\u4E0E\u7EBF\u4E0A\u90E8\u7F72\u8DEF\u5F84\u6309\u51FD\u6570\u540D\uFF0C\u4E0D\u53D7\u5F71\u54CD\u3002
5458
- export default {
5459
- name: '${name}',
5460
- template: '${template}',
5461
- functionsDir: 'functions',
5462
- functions_prefix: '',
5463
- }
5464
- `;
5784
+ // - functions_prefix\uFF1A\u4E91\u51FD\u6570\u8DEF\u7531\u524D\u7F00\uFF0C**\u9ED8\u8BA4 /api**\uFF08\u4E0E\u7EBF\u4E0A\u51FD\u6570\u8DEF\u7531 /api/{fn} \u5BF9\u9F50\uFF09\u3002
5785
+ // dev \u8BBF\u95EE\u8DEF\u5F84\u4E3A /{prefix}/{fnName}\uFF08\u5982 /api/hello\uFF09\uFF1Bserve \u4E3A /api/{prefix}/{fnName}\u3002
5786
+ // vite \u63D2\u4EF6\uFF08vite.config.ts \u7684 adep()\uFF09\u6309\u6B64\u524D\u7F00\u628A\u524D\u7AEF /{prefix}/* \u8BF7\u6C42\u4EE3\u7406\u5230\u4E91\u51FD\u6570\u3002
5787
+ // \u8FB9\u754C\uFF1A\u53EA\u5F71\u54CD\u672C\u5730 HTTP \u5165\u53E3\u8DEF\u7531\uFF1B\u51FD\u6570\u4E92\u8C03\uFF08ctx.cloud.invoke\uFF09\u4E0E\u7EBF\u4E0A\u90E8\u7F72\u8DEF\u5F84\u6309\u51FD\u6570\u540D\uFF0C\u4E0D\u53D7\u5F71\u54CD\u3002`;
5465
5788
  var PACKAGE_JSON = (name, template) => {
5466
5789
  const pkg = {
5467
5790
  name,
5468
5791
  version: "0.1.0",
5469
5792
  private: true,
5470
5793
  type: "module",
5471
- description: `AgentDeploy \u5168\u6808\u9879\u76EE\uFF08\u6A21\u677F\uFF1A${template}\uFF09\u2014\u2014functions/ \u4E91\u51FD\u6570 + web/ \u524D\u7AEF\u5DE5\u7A0B + database/ \u6570\u636E\u5E93`,
5794
+ description: `AgentDeploy \u5168\u6808\u9879\u76EE\uFF08\u6A21\u677F\uFF1A${template}\uFF09\u2014\u2014functions/ \u4E91\u51FD\u6570 + web/src/ \u524D\u7AEF\u6E90\u7801 + site/ \u524D\u7AEF\u6784\u5EFA\u4EA7\u7269`,
5472
5795
  scripts: {
5473
- dev: "adep dev",
5796
+ dev: "vite",
5797
+ build: "vite build",
5798
+ "site:deploy": "adep hosting deploy site --spa",
5474
5799
  serve: "adep serve",
5475
5800
  deploy: "adep deploy",
5476
- "web:dev": "cd web && npm install && npm run dev",
5477
- "web:build": "cd web && npm install && npm run build",
5478
5801
  doctor: "adep doctor"
5479
5802
  },
5480
5803
  dependencies: {
5481
- "@adep/cli": CLI_VERSION
5804
+ "@adep/cli": CLI_VERSION,
5805
+ ...WEB_DEPENDENCIES
5482
5806
  },
5807
+ devDependencies: WEB_DEV_DEPENDENCIES,
5483
5808
  engines: {
5484
5809
  node: ">=18",
5485
5810
  bun: ">=1.0"
@@ -5494,32 +5819,52 @@ AgentDeploy \u5168\u6808\u9879\u76EE\uFF08\u6A21\u677F\uFF1A${template}\uFF09\u3
5494
5819
 
5495
5820
  ## \u5E38\u7528\u547D\u4EE4
5496
5821
 
5497
- - \`pnpm dev\`\uFF08= \`adep dev\`\uFF09\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
5498
- - \`pnpm serve\`\uFF08= \`adep serve\`\uFF09\uFF1A\u5F00\u53D1\u6001\u670D\u52A1\u5668\uFF08\u51FD\u6570 /api/{fn} + /healthz + \u9759\u6001\u6258\u7BA1 + \u524D\u7AEF\u9884\u89C8\uFF09
5499
- - \`pnpm deploy\`\uFF08= \`adep deploy\`\uFF09\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
5500
- - \`pnpm web:dev\`\uFF1A\u524D\u7AEF\u5DE5\u7A0B\u672C\u5730\u5F00\u53D1\uFF08cd web && vite\uFF09
5501
- - \`pnpm web:build\`\uFF1A\u524D\u7AEF\u5DE5\u7A0B\u6784\u5EFA
5822
+ - \`pnpm dev\`\uFF08= \`vite\`\uFF09\uFF1A**\u5168\u6808\u5F00\u53D1**\u2014\u2014vite \u542F\u52A8\u524D\u7AEF\uFF08HMR\uFF09\uFF0C\u4E91\u51FD\u6570 vite \u63D2\u4EF6\u5185\u7F6E
5823
+ \`adep dev\` \u5E76\u628A \`/api/*\` \u8BF7\u6C42\u4EE3\u7406\u5230\u4E91\u51FD\u6570\uFF0C\u4E00\u4E2A\u547D\u4EE4\u8C03\u8BD5\u524D\u7AEF + \u51FD\u6570
5824
+ \uFF08\`curl http://localhost:5173/api/hello\`\uFF09\u3002
5825
+ - \`pnpm build\`\uFF08= \`vite build\`\uFF09\uFF1A\u6784\u5EFA\u524D\u7AEF \u2192 \`site/\`\uFF08\u4E91\u51FD\u6570\u5DE5\u7A0B\u7AD9\u70B9\u6258\u7BA1\u76EE\u5F55\uFF09\u3002
5826
+ - \`pnpm site:deploy\`\uFF08= \`adep hosting deploy site --spa\`\uFF09\uFF1A\u628A \`site/\` \u4E0A\u4F20\u5230\u5E73\u53F0
5827
+ \u9759\u6001\u6258\u7BA1\u5E76\u5F00\u542F SPA \u56DE\u9000\uFF0C\u8F93\u51FA\u7AD9\u70B9\u5730\u5740\u3002
5828
+ - \`pnpm serve\`\uFF08= \`adep serve\`\uFF09\uFF1A\u5F00\u53D1\u6001\u670D\u52A1\u5668\uFF08\u51FD\u6570 /api/{prefix}/{fn} + /healthz + \u9759\u6001\u6258\u7BA1\uFF09
5829
+ - \`pnpm deploy\`\uFF08= \`adep deploy\`\uFF09\uFF1A\u589E\u91CF\u90E8\u7F72\u4E91\u51FD\u6570\uFF08\u5BF9\u6BD4\u8FDC\u7AEF\u54C8\u5E0C \u2192 \u4EC5\u4E0A\u4F20\u53D8\u66F4 \u2192 \u53D1\u5E03 \u2192 \u8F93\u51FA\u8BBF\u95EE\u57DF\u540D\uFF09
5502
5830
  - \`pnpm doctor\`\uFF08= \`adep doctor\`\uFF09\uFF1A\u672C\u5730\u73AF\u5883\u79BB\u7EBF\u8BCA\u65AD
5503
5831
 
5504
5832
  ## \u76EE\u5F55\u7ED3\u6784
5505
5833
 
5506
- - \`package.json\`\uFF1A\u5E94\u7528\u5B9A\u4E49\uFF08\u58F0\u660E @adep/cli \u7248\u672C\u4F9D\u8D56\u4E0E\u5E38\u7528 scripts\uFF1B\u4E0E\u5BFC\u51FA\u7684\u79BB\u7EBF\u90E8\u7F72\u5305\u540C\u6784\uFF09
5507
- - \`adep.config.ts\`\uFF1A\u9879\u76EE\u914D\u7F6E\uFF08name / template / functionsDir / functions_prefix\uFF09
5834
+ - \`package.json\`\uFF1A\u5E94\u7528\u5B9A\u4E49\uFF08@adep/cli + \u524D\u7AEF\u4F9D\u8D56\u540C\u6839\u58F0\u660E\uFF1Bvite \u5DE5\u7A0B\u6839\u5728\u9879\u76EE\u6839\u76EE\u5F55\uFF09
5835
+ - \`vite.config.ts\`\uFF1Avite \u914D\u7F6E\uFF08vue \u63D2\u4EF6 + \`adep()\` \u4E91\u51FD\u6570\u63D2\u4EF6\uFF1Bbuild.outDir = site/\uFF09
5836
+ - \`index.html\`\uFF1Avite \u5165\u53E3\uFF08\u5F15\u7528 \`/web/src/main.ts\`\uFF09
5837
+ - \`adep.config.ts\`\uFF1A\u9879\u76EE\u914D\u7F6E\uFF08name / template / functionsDir / functions_prefix\uFF0C\u9ED8\u8BA4 /api\uFF09
5508
5838
  - \`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
5509
- - \`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
5839
+ - \`web/src/\`\uFF1A\u524D\u7AEF\u6E90\u7801\uFF08Vue 3\uFF1B\u4E0E Web IDE \u7684 \`web/\` \u5DE5\u7A0B\u5171\u7528\u540C\u4E00\u4EFD \`src/\`\uFF09
5840
+ - \`site/\`\uFF1A\`vite build\` \u7684\u524D\u7AEF\u6784\u5EFA\u4EA7\u7269\uFF08\u7AD9\u70B9\u6258\u7BA1\u76EE\u5F55\uFF0C\`adep hosting deploy site\` \u4E0A\u4F20\uFF1B\u5DF2 gitignore\uFF09
5510
5841
  - \`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
5511
- - \`tsconfig.json\`\uFF1A\u4E91\u51FD\u6570 TypeScript \u7F16\u8F91\u5668\u914D\u7F6E\uFF08strict + noEmit\uFF09
5842
+ - \`tsconfig.json\`\uFF1ATypeScript \u7F16\u8F91\u5668\u914D\u7F6E\uFF08strict + noEmit\uFF09
5512
5843
  - \`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
5513
5844
 
5514
- ## \u672C\u5730\u51FD\u6570\u8DEF\u7531\u524D\u7F00\uFF08functions_prefix\uFF09
5845
+ ## \u5168\u6808\u5F00\u53D1\uFF08vite + \u4E91\u51FD\u6570\u4EE3\u7406\uFF09
5846
+
5847
+ \`pnpm dev\` \u542F\u52A8 vite \u540E\uFF0C\u4E91\u51FD\u6570\u63D2\u4EF6\u81EA\u52A8\u505A\u4E24\u4EF6\u4E8B\uFF1A
5848
+ 1. \u5728 vite \u8FDB\u7A0B\u5185\u542F\u52A8 \`adep dev\`\uFF08\u6A21\u62DF\u8FD0\u884C\u65F6\uFF0C\u51FD\u6570\u70ED\u91CD\u8F7D\u3001\`.env.local\`\u3001cloud.db/storage/realtime \u5168\u53EF\u7528\uFF09\uFF1B
5849
+ 2. \u628A \`/{functions_prefix}/*\` \u8BF7\u6C42\u4EE3\u7406\u5230\u4E91\u51FD\u6570\u2014\u2014\`adep.config.ts\` \u9ED8\u8BA4
5850
+ \`functions_prefix: '/api'\`\uFF0C\u56E0\u6B64\u524D\u7AEF \`fetch('/api/hello')\` \u5373\u8C03\u7528 \`functions/hello.ts\`\uFF0C
5851
+ \u4E0E\u7EBF\u4E0A\u90E8\u7F72\u540E\u7684\u51FD\u6570\u8DEF\u7531 \`/api/{fn}\` \u4E00\u81F4\u3002
5515
5852
 
5516
- \`adep.config.ts\` \u7684 \`functions_prefix\` \u63A7\u5236\u672C\u5730\u8C03\u8BD5\u8DEF\u7531\u524D\u7F00\uFF08\u9ED8\u8BA4\u7A7A\uFF09\uFF1A
5517
- - \u914D\u7F6E \`functions_prefix: 'api'\` \u540E\uFF1A\`adep dev\` \u8BBF\u95EE \`/{fnName}\` \u2192 \`/api/{fnName}\`\uFF1B
5518
- \`adep serve\` \u8BBF\u95EE \`/api/{fnName}\` \u2192 \`/api/api/{fnName}\`\uFF08\u524D\u7F00\u62FC\u63A5\uFF09\u3002
5519
- - \u7559\u7A7A\uFF1A\`adep dev\` \u4E3A \`/{fnName}\`\uFF0C\`adep serve\` \u4E3A \`/api/{fnName}\`\u3002
5853
+ ## \u4E91\u51FD\u6570\u8DEF\u7531\u524D\u7F00\uFF08functions_prefix\uFF09
5854
+
5855
+ \`adep.config.ts\` \u7684 \`functions_prefix\`\uFF08\u9ED8\u8BA4 \`/api\`\uFF09\uFF1A
5856
+ - \`adep dev\`\uFF1A\`/{prefix}/{fn}\`\uFF0C\u5982 \`/api/hello\`\uFF1Bvite \u63D2\u4EF6\u6309\u540C\u4E00\u524D\u7F00\u4EE3\u7406\u3002
5857
+ - \`adep serve\`\uFF1A\`/api/{prefix}/{fn}\`\uFF08\u524D\u7F00\u62FC\u63A5\uFF09\u3002
5520
5858
  - **\u8FB9\u754C**\uFF1A\u53EA\u5F71\u54CD\u672C\u5730 HTTP \u5165\u53E3\uFF1B\u51FD\u6570\u4E92\u8C03 \`ctx.cloud.invoke('name')\` \u4E0E\u7EBF\u4E0A\u90E8\u7F72\u8DEF\u5F84\u6309\u51FD\u6570\u540D\uFF0C
5521
5859
  \u4E0D\u968F\u524D\u7F00\u53D8\u5316\uFF08\u4E0E\u7EBF\u4E0A\u540C\u6784\uFF09\u3002
5522
5860
 
5861
+ ## \u7AD9\u70B9\u6258\u7BA1\uFF08\u6784\u5EFA \u2192 \u4E0A\u4F20 \u2192 \u4E0A\u7EBF\uFF09
5862
+
5863
+ 1. \`pnpm build\`\uFF1Avite \u6784\u5EFA\u524D\u7AEF\u5230 \`site/\`\uFF08\u7AD9\u70B9\u6258\u7BA1\u76EE\u5F55\uFF09\u3002
5864
+ 2. \`pnpm site:deploy\`\uFF1A\`adep hosting deploy site --spa\` \u9012\u5F52\u4E0A\u4F20 \`site/\` \u5230\u5E73\u53F0\u9759\u6001\u6258\u7BA1
5865
+ \uFF08site/ \u524D\u7F00\uFF09\uFF0C\u6253\u5F00\u6258\u7BA1\u5F00\u5173\u5E76\u542F\u7528 SPA \u56DE\u9000\uFF0C\u8FD4\u56DE\u7AD9\u70B9\u5730\u5740\u3002
5866
+ \uFF08\u7B49\u4EF7\u547D\u4EE4\uFF1A\`npx adep hosting deploy site --spa\`\uFF1B\u67E5\u770B\uFF1A\`npx adep hosting info\`\uFF09
5867
+
5523
5868
  ## \u4E91\u51FD\u6570\u7C7B\u578B\u63D0\u793A
5524
5869
 
5525
5870
  \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
@@ -5528,19 +5873,18 @@ AgentDeploy \u5168\u6808\u9879\u76EE\uFF08\u6A21\u677F\uFF1A${template}\uFF09\u3
5528
5873
 
5529
5874
  ## \u6A21\u677F\u8BF4\u660E\uFF08adep init\uFF09
5530
5875
 
5531
- - \`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
5876
+ - \`adep init <name>\`\uFF1A\u9ED8\u8BA4 \`fullstack\` \u6A21\u677F\uFF08functions/ + web/src/ \u524D\u7AEF\u6E90\u7801 + database/\uFF09
5532
5877
  - \`adep init <name> -t function\`\uFF1A\u4EC5\u4E91\u51FD\u6570\uFF08\u5355\u4E2A\u793A\u4F8B\u51FD\u6570\uFF09
5533
5878
  - \`adep init <name> -t empty\`\uFF1A\u7A7A\u6A21\u677F\uFF08\u4EC5\u9879\u76EE\u9AA8\u67B6\uFF09
5534
5879
  - \`adep init --list\`\uFF1A\u4ECE\u5E73\u53F0 /api/v1/templates \u5217\u51FA\u53EF\u7528\u6A21\u677F
5535
5880
  - \`adep init --list -s <server>\`\uFF1A\u6307\u5B9A\u5E73\u53F0\u5730\u5740
5536
5881
 
5537
- ## \u524D\u7AEF\u5DE5\u7A0B\uFF08web/\uFF09
5882
+ ## \u524D\u7AEF\u6E90\u7801\uFF08web/src/\uFF09
5538
5883
 
5539
- \`web/\` \u662F\u6807\u51C6 Vite + Vue 3 \u5DE5\u7A0B\uFF0C\u4E0E Web IDE \u5185\u521B\u5EFA\u7684\u9879\u76EE\u5B8C\u5168\u540C\u6784\uFF1A
5540
- \`index.html\` / \`package.json\` / \`vite.config.ts\` / \`src/main.ts\` / \`src/App.vue\`\u3002
5541
- \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
5884
+ \`web/src/\` \u5B58\u653E\u524D\u7AEF\u6E90\u7801\uFF08\`main.ts\` / \`App.vue\`\uFF09\uFF0C\u4E0E Web IDE \u5185 \`web/\` \u5DE5\u7A0B\u7684 \`src/\`
5885
+ \u5B8C\u5168\u540C\u6784\uFF1Bvite \u5DE5\u7A0B\u6839\u5728\u9879\u76EE\u6839\u76EE\u5F55\uFF08\`vite.config.ts\` / \`index.html\` / \`package.json\`\uFF09\u3002
5542
5886
  `;
5543
- var HELLO_FUNCTION = `// \u793A\u4F8B\u51FD\u6570\uFF1Aadep deploy \u540E\u7ECF https://<project-slug>.<platform-domain>/hello \u89E6\u53D1\u3002
5887
+ var HELLO_FUNCTION = `// \u793A\u4F8B\u51FD\u6570\uFF1Aadep deploy \u540E\u7ECF https://<project-slug>.<platform-domain>/api/hello \u89E6\u53D1\u3002
5544
5888
  // \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
5545
5889
  //\uFF08ctx \u5951\u7EA6\u89C1 adep.d.ts\uFF1Amethod / path / query / headers / body / files / user / cloud.*\uFF09\u3002
5546
5890
  export default async (ctx: AdepContext) => {
@@ -5551,11 +5895,39 @@ export default async (ctx: AdepContext) => {
5551
5895
  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
5552
5896
  // \u9ED8\u8BA4\u5BFC\u51FA (ctx: AdepContext) => Response \u5F62\u72B6\u7684\u5904\u7406\u5668\uFF08\u5951\u7EA6\u89C1 adep.d.ts\uFF09\u3002
5553
5897
  `;
5554
- 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
5898
+ 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/src/\uFF0C\u914D\u7F6E\u89C1 adep.config.ts\u3002
5555
5899
  `;
5556
5900
  var SCHEMA_SQL = `-- AgentDeploy \u9879\u76EE\u6570\u636E\u5E93\u7ED3\u6784\uFF08\u5360\u4F4D\uFF09\u3002
5557
5901
  -- \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
5558
5902
  `;
5903
+ var INDEX_HTML = `<!doctype html>
5904
+ <html lang="zh-CN">
5905
+ <head>
5906
+ <meta charset="utf-8" />
5907
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
5908
+ <title>adep web</title>
5909
+ </head>
5910
+ <body>
5911
+ <div id="app"></div>
5912
+ <script type="module" src="/web/src/main.ts"></script>
5913
+ </body>
5914
+ </html>
5915
+ `;
5916
+ var VITE_CONFIG = `// vite.config.ts \u2014\u2014 \u9879\u76EE\u6839 vite \u914D\u7F6E\uFF08CLI-014 \u5168\u6808\u5F00\u53D1\u4F53\u9A8C\uFF09\u3002
5917
+ // adep() \u662F @adep/cli \u7684\u4E91\u51FD\u6570 vite \u63D2\u4EF6\uFF1A\u5185\u7F6E adep dev server \u5E76\u6309 adep.config.ts \u7684
5918
+ // functions_prefix\uFF08\u9ED8\u8BA4 /api\uFF09\u628A /api/* \u8BF7\u6C42\u4EE3\u7406\u5230\u4E91\u51FD\u6570\u2014\u2014vite dev \u5373\u53EF\u8C03\u8BD5\u524D\u7AEF + \u51FD\u6570\u3002
5919
+ import { defineConfig } from 'vite'
5920
+ import vue from '@vitejs/plugin-vue'
5921
+ import adep from '@adep/cli/vite'
5922
+
5923
+ export default defineConfig({
5924
+ plugins: [vue(), adep()],
5925
+ build: {
5926
+ // \u524D\u7AEF\u6784\u5EFA\u4EA7\u7269 \u2192 site/\uFF08\u4E91\u51FD\u6570\u5DE5\u7A0B\u7AD9\u70B9\u6258\u7BA1\u76EE\u5F55\uFF1Bpnpm site:deploy \u4E0A\u4F20\u90E8\u7F72\uFF09
5927
+ outDir: 'site',
5928
+ },
5929
+ })
5930
+ `;
5559
5931
  async function initProject(cwd, name, template) {
5560
5932
  if (!/^[a-z][a-z0-9-]{0,62}$/.test(name)) {
5561
5933
  throw new InitError(
@@ -5580,14 +5952,22 @@ async function initProject(cwd, name, template) {
5580
5952
  throw new InitError("DIR_EXISTS", `\u76EE\u5F55 ${projectPath} \u5DF2\u5B58\u5728\uFF1A\u8BF7\u6362\u4E00\u4E2A\u540D\u5B57\u6216\u5148\u5220\u9664`);
5581
5953
  }
5582
5954
  const files = [
5583
- // 根 package.json:应用定义(声明 @adep/cli 版本依赖与 scripts;与导出的离线部署包同构)。
5955
+ // 根 package.json:应用定义(@adep/cli + 前端依赖同根声明;与导出的离线部署包同构键集)。
5584
5956
  { path: "package.json", content: PACKAGE_JSON(name, template) },
5585
- { path: "adep.config.ts", content: ADEP_CONFIG(name, template) },
5957
+ // adep.config.ts:经 shared/sdk/adep-config renderAdepConfig 渲染(schema 唯一真相源)。
5958
+ // template 是 init 元数据(不在 AdepConfig 中),经 extraFields 传入。
5959
+ {
5960
+ path: "adep.config.ts",
5961
+ content: renderAdepConfig(
5962
+ { name, functionsDir: "functions", functions_prefix: "/api" },
5963
+ { header: ADEP_CONFIG_HEADER, extraFields: { template } }
5964
+ )
5965
+ },
5586
5966
  // 云函数 TypeScript 类型提示:tsconfig 把 adep.d.ts 纳入 include,写 ctx: AdepContext 即有补全。
5587
5967
  { path: "tsconfig.json", content: ADEP_TSCONFIG_JSON },
5588
5968
  { path: "adep.d.ts", content: ADEP_ENV_DTS },
5589
5969
  { path: "README.md", content: README(name, template) },
5590
- { path: ".gitignore", content: "node_modules/\ndata/\n.adep/\nweb/node_modules/\n" }
5970
+ { path: ".gitignore", content: "node_modules/\ndata/\n.adep/\nsite/\n" }
5591
5971
  ];
5592
5972
  if (template === "function") {
5593
5973
  files.push({ path: "functions/hello.ts", content: HELLO_FUNCTION });
@@ -5596,7 +5976,9 @@ async function initProject(cwd, name, template) {
5596
5976
  files.push({ path: "functions/hello.ts", content: HELLO_FUNCTION });
5597
5977
  files.push({ path: "functions/README.md", content: FUNCTION_INDEX });
5598
5978
  files.push({ path: "database/schema.sql", content: SCHEMA_SQL });
5599
- for (const file of webProjectFiles()) {
5979
+ files.push({ path: "index.html", content: INDEX_HTML });
5980
+ files.push({ path: "vite.config.ts", content: VITE_CONFIG });
5981
+ for (const file of webSrcFiles()) {
5600
5982
  files.push({ path: `web/${file.path}`, content: file.content });
5601
5983
  }
5602
5984
  } else {
@@ -5613,7 +5995,7 @@ async function initProject(cwd, name, template) {
5613
5995
  return { projectPath, files: files.map((file) => file.path) };
5614
5996
  }
5615
5997
 
5616
- // packages/cli/src/output.ts
5998
+ // src/output.ts
5617
5999
  function isCommandError(error) {
5618
6000
  return error instanceof CliError || error instanceof InitError;
5619
6001
  }
@@ -5694,7 +6076,7 @@ function formatSeconds(seconds) {
5694
6076
  return `${Math.max(0.1, Math.round(seconds * 10) / 10)}s`;
5695
6077
  }
5696
6078
 
5697
- // packages/cli/src/commands/context.ts
6079
+ // src/commands/context.ts
5698
6080
  function createCliContext(deps) {
5699
6081
  const { output, paths, cwd, json } = deps;
5700
6082
  return {
@@ -5705,7 +6087,7 @@ function createCliContext(deps) {
5705
6087
  };
5706
6088
  }
5707
6089
 
5708
- // packages/cli/src/commands/auth.ts
6090
+ // src/commands/auth.ts
5709
6091
  init_auth();
5710
6092
  init_config();
5711
6093
  function registerAuth(program2, ctx) {
@@ -5752,10 +6134,10 @@ function registerAuth(program2, ctx) {
5752
6134
  });
5753
6135
  }
5754
6136
 
5755
- // packages/cli/src/commands/init.ts
6137
+ // src/commands/init.ts
5756
6138
  init_config();
5757
6139
 
5758
- // packages/cli/src/templates.ts
6140
+ // src/templates.ts
5759
6141
  init_auth();
5760
6142
  async function fetchTemplates(server) {
5761
6143
  let response;
@@ -5782,7 +6164,7 @@ async function fetchTemplates(server) {
5782
6164
  return templates ?? [];
5783
6165
  }
5784
6166
 
5785
- // packages/cli/src/commands/init.ts
6167
+ // src/commands/init.ts
5786
6168
  function registerInit(program2, ctx) {
5787
6169
  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(
5788
6170
  "-s, --server <url>",
@@ -5819,7 +6201,7 @@ function registerInit(program2, ctx) {
5819
6201
  );
5820
6202
  }
5821
6203
 
5822
- // packages/cli/src/commands/dev.ts
6204
+ // src/commands/dev.ts
5823
6205
  function registerDevServers(program2, ctx) {
5824
6206
  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) => {
5825
6207
  const command = ctx.io("dev");
@@ -5857,7 +6239,123 @@ function registerDevServers(program2, ctx) {
5857
6239
  });
5858
6240
  }
5859
6241
 
5860
- // packages/cli/src/commands/deploy.ts
6242
+ // src/commands/publish.ts
6243
+ init_auth();
6244
+ init_client();
6245
+ init_deploy();
6246
+ import { resolve as resolve6 } from "node:path";
6247
+ async function resolveProjectId(client, cwd, slug) {
6248
+ const resolvedSlug = await resolveSlug(resolve6(cwd), slug);
6249
+ const listed = await client.request("/api/v1/projects", {}, "PROJECT_LIST_FAILED");
6250
+ const match = listed.projects.find((project2) => project2.slug === resolvedSlug);
6251
+ if (match === void 0) {
6252
+ throw new CliError(
6253
+ "PROJECT_NOT_FOUND",
6254
+ `\u5E73\u53F0\u9879\u76EE "${resolvedSlug}" \u4E0D\u5B58\u5728\u6216\u4F60\u6CA1\u6709\u8BBF\u95EE\u6743\u9650\uFF1A\u5148\u6267\u884C adep projects create ${resolvedSlug}`
6255
+ );
6256
+ }
6257
+ return { id: match.id, slug: match.slug };
6258
+ }
6259
+ async function publishFrontend(paths, options) {
6260
+ const log = options.silent === true ? () => void 0 : options.log ?? ((line) => process.stdout.write(`${line}
6261
+ `));
6262
+ const client = await createClient(paths);
6263
+ const project2 = await resolveProjectId(client, options.cwd, options.slug);
6264
+ log(`[adep] \u89E6\u53D1\u5E73\u53F0\u4FA7\u524D\u7AEF\u6784\u5EFA\uFF08\u9879\u76EE ${project2.slug}\uFF09\u2026`);
6265
+ const published = await client.request(
6266
+ `/api/v1/projects/${project2.id}/frontend/publish`,
6267
+ { method: "POST" },
6268
+ "FRONTEND_PUBLISH_FAILED"
6269
+ );
6270
+ const versions = await client.request(
6271
+ `/api/v1/projects/${project2.id}/frontend/versions`,
6272
+ {},
6273
+ "FRONTEND_VERSIONS_FAILED"
6274
+ );
6275
+ return {
6276
+ version: published.version,
6277
+ hash: published.hash,
6278
+ createdAt: published.createdAt,
6279
+ reused: published.reused,
6280
+ siteUrl: versions.siteUrl
6281
+ };
6282
+ }
6283
+ async function publishFunctions(paths, options) {
6284
+ const startedAt = Date.now();
6285
+ const result = await deploy(paths, {
6286
+ cwd: options.cwd,
6287
+ ...options.slug === void 0 ? {} : { slug: options.slug },
6288
+ silent: options.silent ?? false,
6289
+ ...options.log === void 0 ? {} : { log: options.log }
6290
+ });
6291
+ const elapsedSeconds = (Date.now() - startedAt) / 1e3;
6292
+ const deployedCount = result.functions.filter((fn) => fn.action !== "none").length;
6293
+ return { ...result, elapsedSeconds, deployedCount };
6294
+ }
6295
+ async function runPublish(paths, io, cwd, flags) {
6296
+ const scope = flags.only === void 0 ? "fullstack" : flags.only;
6297
+ if (flags.only !== void 0 && flags.only !== "functions" && flags.only !== "frontend") {
6298
+ throw new CliError("INVALID_SCOPE", `--only \u987B\u4E3A functions \u6216 frontend\uFF0C\u6536\u5230 "${flags.only}"`);
6299
+ }
6300
+ const wantFunctions = scope === "fullstack" || scope === "functions";
6301
+ const wantFrontend = scope === "fullstack" || scope === "frontend";
6302
+ const result = { scope };
6303
+ if (wantFunctions) {
6304
+ result.functions = await publishFunctions(paths, {
6305
+ cwd,
6306
+ ...flags.project === void 0 ? {} : { slug: flags.project },
6307
+ silent: io.json,
6308
+ log: (line) => io.line(line)
6309
+ });
6310
+ }
6311
+ if (wantFrontend) {
6312
+ result.frontend = await publishFrontend(paths, {
6313
+ cwd,
6314
+ ...flags.project === void 0 ? {} : { slug: flags.project },
6315
+ silent: io.json,
6316
+ log: (line) => io.line(line)
6317
+ });
6318
+ }
6319
+ return result;
6320
+ }
6321
+ function renderPublish(data) {
6322
+ const result = data;
6323
+ const lines = [];
6324
+ if (result.functions !== void 0) {
6325
+ for (const fn of result.functions.functions) {
6326
+ lines.push(`${fn.name} v${fn.version} ${fn.url}`);
6327
+ }
6328
+ if (result.functions.noChanges) {
6329
+ lines.push(
6330
+ `\u2713 no changes \xB7 ${result.functions.functions.length} functions up to date in ${formatSeconds(result.functions.elapsedSeconds)}`
6331
+ );
6332
+ } else {
6333
+ lines.push(
6334
+ `\u2713 ${result.functions.deployedCount} functions deployed in ${formatSeconds(result.functions.elapsedSeconds)}`
6335
+ );
6336
+ }
6337
+ }
6338
+ if (result.frontend !== void 0) {
6339
+ const fe = result.frontend;
6340
+ const status = fe.reused ? `\uFF08\u590D\u7528 v${fe.version}\uFF0C\u65E0\u53D8\u66F4\uFF09` : `v${fe.version}`;
6341
+ lines.push(`\u2713 frontend built ${status} \xB7 ${fe.siteUrl}`);
6342
+ }
6343
+ return lines;
6344
+ }
6345
+ function registerPublish(program2, ctx) {
6346
+ program2.command("publish").description("\u5168\u6808\u53D1\u5E03\uFF1A\u51FD\u6570\u90E8\u7F72 + \u524D\u7AEF\u6784\u5EFA\u6258\u7BA1\uFF08--only functions|frontend \u53EF\u5355\u72EC\u53D1\u5E03\u4E00\u4FA7\uFF09").option(
6347
+ "--only <scope>",
6348
+ "\u4EC5\u53D1\u5E03\u4E00\u4FA7\uFF1Afunctions\uFF08\u53EA\u90E8\u7F72\u4E91\u51FD\u6570\uFF09| frontend\uFF08\u53EA\u6784\u5EFA\u6258\u7BA1\u524D\u7AEF\uFF09\uFF1B\u7F3A\u7701\u5168\u6808\u53D1\u5E03"
6349
+ ).option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").action(async (flags) => {
6350
+ const command = ctx.io("publish");
6351
+ await command.run(async () => {
6352
+ const result = await runPublish(ctx.paths, command, ctx.cwd, flags);
6353
+ command.ok(result, renderPublish);
6354
+ });
6355
+ });
6356
+ }
6357
+
6358
+ // src/commands/deploy.ts
5861
6359
  async function runDeploy(paths, io, cwd, slug, dir) {
5862
6360
  const { deploy: deploy2 } = await Promise.resolve().then(() => (init_deploy(), deploy_exports));
5863
6361
  const startedAt = Date.now();
@@ -5887,178 +6385,58 @@ async function runDeploy(paths, io, cwd, slug, dir) {
5887
6385
  });
5888
6386
  }
5889
6387
  function registerDeploy(program2, ctx) {
5890
- 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) => {
6388
+ program2.command("deploy").description(
6389
+ "[deprecated] \u63A8\u8350\u4F7F\u7528 adep publish\u3002\u589E\u91CF\u90E8\u7F72\u51FD\u6570\uFF1A\u5BF9\u6BD4\u8FDC\u7AEF\u54C8\u5E0C \u2192 \u4EC5\u4E0A\u4F20\u53D8\u66F4 \u2192 \u53D1\u5E03 \u2192 \u8F93\u51FA\u8BBF\u95EE\u57DF\u540D"
6390
+ ).option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").action(async (flags) => {
5891
6391
  const command = ctx.io("deploy");
6392
+ if (!command.json) {
6393
+ process.stderr.write(
6394
+ "\u63D0\u793A\uFF1Aadep deploy \u5DF2\u5E9F\u5F03\uFF0C\u63A8\u8350\u4F7F\u7528 adep publish\uFF08\u5168\u6808\u53D1\u5E03\uFF09\u6216 adep publish --only functions\uFF08\u4EC5\u51FD\u6570\uFF09\n"
6395
+ );
6396
+ }
5892
6397
  await command.run(() => runDeploy(ctx.paths, command, ctx.cwd, flags.project));
5893
6398
  });
5894
6399
  }
5895
6400
 
5896
- // packages/cli/src/commands/projects.ts
5897
- function registerProjects(program2, ctx) {
5898
- 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");
5899
- 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) => {
5900
- const command = ctx.io("projects create");
5901
- await command.run(async () => {
5902
- const { projectsCreate: projectsCreate2 } = await Promise.resolve().then(() => (init_projects(), projects_exports));
5903
- const created = await projectsCreate2(ctx.paths, {
5904
- slug,
5905
- ...flags.name === void 0 ? {} : { name: flags.name },
5906
- ...flags.space === void 0 ? {} : { spaceId: flags.space }
5907
- });
5908
- command.ok(created, (data) => `\u2713 Project created \xB7 ${data.url}`);
5909
- });
5910
- });
5911
- projects.command("list").description("\u5217\u51FA\u5F53\u524D\u7528\u6237\u53EF\u8BBF\u95EE\u7684\u9879\u76EE").action(async () => {
5912
- const command = ctx.io("projects list");
5913
- await command.run(async () => {
5914
- const { projectsList: projectsList2 } = await Promise.resolve().then(() => (init_projects(), projects_exports));
5915
- const list = await projectsList2(ctx.paths);
5916
- command.ok({ projects: list }, (data) => {
5917
- const projectsData = data.projects;
5918
- if (projectsData.length === 0) return "\uFF08\u8FD8\u6CA1\u6709\u9879\u76EE\uFF1Aadep projects create <slug>\uFF09";
5919
- return projectsData.map((p) => `${p.slug} ${p.name} ${p.url}`);
5920
- });
5921
- });
5922
- });
5923
- 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) => {
5924
- const command = ctx.io("projects info");
5925
- await command.run(async () => {
5926
- const { projectsInfo: projectsInfo2 } = await Promise.resolve().then(() => (init_projects(), projects_exports));
5927
- const project2 = await projectsInfo2(ctx.paths, { slug });
5928
- command.ok(project2, (data) => {
5929
- const p = data;
5930
- return `${p.id} ${p.slug} ${p.name} ${p.url}`;
5931
- });
5932
- });
5933
- });
5934
- }
5935
-
5936
- // packages/cli/src/commands/functions.ts
5937
- init_auth();
5938
- function registerFunctions(program2, ctx) {
5939
- const functions = program2.command("functions").description("\u4E91\u51FD\u6570\uFF1A\u90E8\u7F72\uFF08\u53EF\u6307\u5B9A\u76EE\u5F55\uFF09/ \u5217\u51FA / \u67E5\u65E5\u5FD7");
5940
- functions.command("deploy").description(
5941
- "\u90E8\u7F72\u51FD\u6570\u76EE\u5F55\uFF08`adep deploy` \u7684\u547D\u4EE4\u65CF\u5165\u53E3\uFF1Bdir \u8986\u76D6 adep.config.ts \u7684 functionsDir\uFF09"
5942
- ).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) => {
5943
- const command = ctx.io("functions deploy");
5944
- await command.run(() => runDeploy(ctx.paths, command, ctx.cwd, flags.project, dir));
5945
- });
5946
- 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) => {
5947
- const command = ctx.io("functions list");
5948
- await command.run(async () => {
5949
- const { functionsList: functionsList2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
5950
- const result = await functionsList2(ctx.paths, {
5951
- cwd: ctx.cwd,
5952
- ...flags.project === void 0 ? {} : { slug: flags.project }
5953
- });
5954
- command.ok(result, (data) => {
5955
- const r = data;
5956
- if (r.functions.length === 0) return "\uFF08\u8BE5\u9879\u76EE\u4E0B\u8FD8\u6CA1\u6709\u51FD\u6570\uFF09";
5957
- return r.functions.map((fn) => `${fn.name} ${r.baseUrl}/${fn.name}`);
5958
- });
5959
- });
5960
- });
5961
- 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) => {
5962
- const command = ctx.io("functions logs");
5963
- await command.run(async () => {
5964
- const { functionsLogs: functionsLogs2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
5965
- const tail = flags.tail === void 0 ? void 0 : Number(flags.tail);
5966
- if (tail !== void 0 && (!Number.isFinite(tail) || tail <= 0)) {
5967
- throw new CliError("INVALID_TAIL", `--tail \u987B\u4E3A\u6B63\u6574\u6570\uFF0C\u6536\u5230 "${flags.tail}"`);
5968
- }
5969
- const result = await functionsLogs2(ctx.paths, {
5970
- cwd: ctx.cwd,
5971
- name,
5972
- ...tail === void 0 ? {} : { tail },
5973
- ...flags.project === void 0 ? {} : { slug: flags.project }
5974
- });
5975
- command.ok(result, (data) => {
5976
- const r = data;
5977
- if (r.logs.length === 0) {
5978
- 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`;
5979
- }
5980
- return r.logs.map((log) => `${log.at} [${log.level}] ${log.message}`);
5981
- });
5982
- });
5983
- });
5984
- }
5985
-
5986
- // packages/cli/src/commands/mcp.ts
5987
- function registerMcp(program2, ctx) {
5988
- const mcp = program2.command("mcp").description("MCP Tool\uFF1A\u628A\u4E91\u51FD\u6570\u53D1\u5E03\u4E3A\u5DE5\u5177 / \u53D6\u6D88\u53D1\u5E03 / \u5217\u51FA");
5989
- 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(
5990
- "--description <text>",
5991
- "\u8986\u76D6\u9762\u5411 Agent \u7684\u5DE5\u5177\u63CF\u8FF0\uFF08\u7F3A\u7701\u7528\u6E90\u7801 @description / \u63A8\u5BFC\u63CF\u8FF0\uFF09"
5992
- ).option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").action(
6401
+ // src/commands/export.ts
6402
+ function registerExport(program2, ctx) {
6403
+ 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", "[\u5DF2\u5E9F\u5F03] \u542B\u6E90\u7801\u5DF2\u4E3A\u9ED8\u8BA4\u884C\u4E3A\uFF1B\u4FDD\u7559\u4E0D\u62A5\u9519\uFF0C\u4EC5\u63D0\u793A\uFF0C\u5C06\u5728\u672A\u6765\u7248\u672C\u79FB\u9664").option(
6404
+ "--without-source",
6405
+ "\u51FA\u7EAF\u4EA7\u7269\u5305\uFF1A\u4E0D\u5305\u542B\u51FD\u6570\u6E90\u7801\u4E0E web/src/ \u524D\u7AEF\u6E90\u7801\uFF08\u4EC5 site/ \u9884\u6784\u5EFA\u4EA7\u7269\uFF09"
6406
+ ).option("--out <dir>", "\u8F93\u51FA\u76EE\u5F55\uFF08\u7F3A\u7701 ./exports\uFF09").action(
5993
6407
  async (flags) => {
5994
- const command = ctx.io("mcp publish");
6408
+ const command = ctx.io("export");
5995
6409
  await command.run(async () => {
5996
- const { mcpPublish: mcpPublish2 } = await Promise.resolve().then(() => (init_mcp(), mcp_exports));
5997
- const result = await mcpPublish2(ctx.paths, {
5998
- cwd: ctx.cwd,
5999
- fn: flags.function,
6000
- ...flags.name === void 0 ? {} : { toolName: flags.name },
6001
- ...flags.description === void 0 ? {} : { description: flags.description },
6002
- ...flags.project === void 0 ? {} : { slug: flags.project }
6003
- });
6004
- command.ok(result, (data) => {
6005
- const r = data;
6006
- return `\u2713 MCP tool published \xB7 ${r.tool.name}`;
6410
+ const { createExportApiClient: createExportApiClient2 } = await Promise.resolve().then(() => (init_client2(), client_exports2));
6411
+ const { createExportFileSystem: createExportFileSystem2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
6412
+ const { ExportCommand: ExportCommand2 } = await Promise.resolve().then(() => (init_command(), command_exports));
6413
+ const { resolveSlug: resolveSlug2 } = await Promise.resolve().then(() => (init_client(), client_exports));
6414
+ if (flags.withSource === true) {
6415
+ process.stderr.write(
6416
+ "adep: --with-source \u5DF2\u4E3A\u9ED8\u8BA4\u884C\u4E3A\uFF08\u5BFC\u51FA\u5305\u9ED8\u8BA4\u542B\u51FD\u6570\u6E90\u7801\u4E0E web/src/ \u524D\u7AEF\u6E90\u7801\uFF09\uFF0C\u8BE5\u9009\u9879\u5C06\u5728\u672A\u6765\u7248\u672C\u79FB\u9664\n"
6417
+ );
6418
+ }
6419
+ const project2 = await resolveSlug2(ctx.cwd, flags.project);
6420
+ const apiClient = await createExportApiClient2(ctx.paths);
6421
+ const exportCommand = new ExportCommand2(apiClient, createExportFileSystem2());
6422
+ const result = await exportCommand.execute({
6423
+ project: project2,
6424
+ ...flags.withData === true ? { withData: true } : {},
6425
+ ...flags.withoutSource === true ? { withoutSource: true } : {},
6426
+ ...flags.out === void 0 ? {} : { out: flags.out },
6427
+ json: command.json
6007
6428
  });
6429
+ if (!result.success) {
6430
+ command.fail("EXPORT_FAILED", result.error ?? "\u5BFC\u51FA\u5931\u8D25");
6431
+ return;
6432
+ }
6433
+ command.ok(result);
6008
6434
  });
6009
6435
  }
6010
6436
  );
6011
- 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) => {
6012
- const command = ctx.io("mcp unpublish");
6013
- await command.run(async () => {
6014
- const { mcpUnpublish: mcpUnpublish2 } = await Promise.resolve().then(() => (init_mcp(), mcp_exports));
6015
- const result = await mcpUnpublish2(ctx.paths, {
6016
- cwd: ctx.cwd,
6017
- fn: flags.function,
6018
- ...flags.name === void 0 ? {} : { toolName: flags.name },
6019
- ...flags.project === void 0 ? {} : { slug: flags.project }
6020
- });
6021
- command.ok(result, (data) => {
6022
- const r = data;
6023
- 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`;
6024
- });
6025
- });
6026
- });
6027
- 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) => {
6028
- const command = ctx.io("mcp list");
6029
- await command.run(async () => {
6030
- const { mcpList: mcpList2 } = await Promise.resolve().then(() => (init_mcp(), mcp_exports));
6031
- const result = await mcpList2(ctx.paths, {
6032
- cwd: ctx.cwd,
6033
- ...flags.project === void 0 ? {} : { slug: flags.project }
6034
- });
6035
- command.ok(result, (data) => {
6036
- const r = data;
6037
- const lines = [`\u7AEF\u70B9\uFF1A${r.endpoint}`];
6038
- if (r.tools.length === 0) {
6039
- lines.push("\uFF08\u8FD8\u6CA1\u6709\u5DF2\u53D1\u5E03\u7684 MCP tool\uFF1Aadep mcp publish --function <fn>\uFF09");
6040
- } else {
6041
- for (const tool of r.tools) lines.push(`${tool.name} ${tool.description ?? ""}`);
6042
- }
6043
- return lines;
6044
- });
6045
- });
6046
- });
6047
- }
6048
-
6049
- // packages/cli/src/commands/doctor.ts
6050
- function registerDoctor(program2, ctx) {
6051
- 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 () => {
6052
- const command = ctx.io("doctor");
6053
- await command.run(async () => {
6054
- const { runDoctor: runDoctor2, formatDoctorReport: formatDoctorReport2 } = await Promise.resolve().then(() => (init_doctor(), doctor_exports));
6055
- const report = await runDoctor2(ctx.paths);
6056
- command.ok(report, () => formatDoctorReport2(report));
6057
- });
6058
- });
6059
6437
  }
6060
6438
 
6061
- // packages/cli/src/commands/db.ts
6439
+ // src/commands/db.ts
6062
6440
  function registerDb(program2, ctx) {
6063
6441
  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");
6064
6442
  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) => {
@@ -6187,7 +6565,7 @@ function registerDb(program2, ctx) {
6187
6565
  });
6188
6566
  }
6189
6567
 
6190
- // packages/cli/src/commands/storage.ts
6568
+ // src/commands/storage.ts
6191
6569
  function registerStorage(program2, ctx) {
6192
6570
  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");
6193
6571
  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(
@@ -6261,7 +6639,177 @@ function registerStorage(program2, ctx) {
6261
6639
  });
6262
6640
  }
6263
6641
 
6264
- // packages/cli/src/commands/hosting.ts
6642
+ // src/commands/doctor.ts
6643
+ function registerDoctor(program2, ctx) {
6644
+ 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 () => {
6645
+ const command = ctx.io("doctor");
6646
+ await command.run(async () => {
6647
+ const { runDoctor: runDoctor2, formatDoctorReport: formatDoctorReport2 } = await Promise.resolve().then(() => (init_doctor(), doctor_exports));
6648
+ const report = await runDoctor2(ctx.paths);
6649
+ command.ok(report, () => formatDoctorReport2(report));
6650
+ });
6651
+ });
6652
+ }
6653
+
6654
+ // src/commands/mcp.ts
6655
+ function registerMcp(program2, ctx) {
6656
+ const mcp = program2.command("mcp").description("MCP Tool\uFF1A\u628A\u4E91\u51FD\u6570\u53D1\u5E03\u4E3A\u5DE5\u5177 / \u53D6\u6D88\u53D1\u5E03 / \u5217\u51FA");
6657
+ 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(
6658
+ "--description <text>",
6659
+ "\u8986\u76D6\u9762\u5411 Agent \u7684\u5DE5\u5177\u63CF\u8FF0\uFF08\u7F3A\u7701\u7528\u6E90\u7801 @description / \u63A8\u5BFC\u63CF\u8FF0\uFF09"
6660
+ ).option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").action(
6661
+ async (flags) => {
6662
+ const command = ctx.io("mcp publish");
6663
+ await command.run(async () => {
6664
+ const { mcpPublish: mcpPublish2 } = await Promise.resolve().then(() => (init_mcp(), mcp_exports));
6665
+ const result = await mcpPublish2(ctx.paths, {
6666
+ cwd: ctx.cwd,
6667
+ fn: flags.function,
6668
+ ...flags.name === void 0 ? {} : { toolName: flags.name },
6669
+ ...flags.description === void 0 ? {} : { description: flags.description },
6670
+ ...flags.project === void 0 ? {} : { slug: flags.project }
6671
+ });
6672
+ command.ok(result, (data) => {
6673
+ const r = data;
6674
+ return `\u2713 MCP tool published \xB7 ${r.tool.name}`;
6675
+ });
6676
+ });
6677
+ }
6678
+ );
6679
+ 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) => {
6680
+ const command = ctx.io("mcp unpublish");
6681
+ await command.run(async () => {
6682
+ const { mcpUnpublish: mcpUnpublish2 } = await Promise.resolve().then(() => (init_mcp(), mcp_exports));
6683
+ const result = await mcpUnpublish2(ctx.paths, {
6684
+ cwd: ctx.cwd,
6685
+ fn: flags.function,
6686
+ ...flags.name === void 0 ? {} : { toolName: flags.name },
6687
+ ...flags.project === void 0 ? {} : { slug: flags.project }
6688
+ });
6689
+ command.ok(result, (data) => {
6690
+ const r = data;
6691
+ 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`;
6692
+ });
6693
+ });
6694
+ });
6695
+ 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) => {
6696
+ const command = ctx.io("mcp list");
6697
+ await command.run(async () => {
6698
+ const { mcpList: mcpList2 } = await Promise.resolve().then(() => (init_mcp(), mcp_exports));
6699
+ const result = await mcpList2(ctx.paths, {
6700
+ cwd: ctx.cwd,
6701
+ ...flags.project === void 0 ? {} : { slug: flags.project }
6702
+ });
6703
+ command.ok(result, (data) => {
6704
+ const r = data;
6705
+ const lines = [`\u7AEF\u70B9\uFF1A${r.endpoint}`];
6706
+ if (r.tools.length === 0) {
6707
+ lines.push("\uFF08\u8FD8\u6CA1\u6709\u5DF2\u53D1\u5E03\u7684 MCP tool\uFF1Aadep mcp publish --function <fn>\uFF09");
6708
+ } else {
6709
+ for (const tool of r.tools) lines.push(`${tool.name} ${tool.description ?? ""}`);
6710
+ }
6711
+ return lines;
6712
+ });
6713
+ });
6714
+ });
6715
+ }
6716
+
6717
+ // src/commands/projects.ts
6718
+ function registerProjects(program2, ctx) {
6719
+ 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");
6720
+ 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) => {
6721
+ const command = ctx.io("projects create");
6722
+ await command.run(async () => {
6723
+ const { projectsCreate: projectsCreate2 } = await Promise.resolve().then(() => (init_projects(), projects_exports));
6724
+ const created = await projectsCreate2(ctx.paths, {
6725
+ slug,
6726
+ ...flags.name === void 0 ? {} : { name: flags.name },
6727
+ ...flags.space === void 0 ? {} : { spaceId: flags.space }
6728
+ });
6729
+ command.ok(created, (data) => `\u2713 Project created \xB7 ${data.url}`);
6730
+ });
6731
+ });
6732
+ projects.command("list").description("\u5217\u51FA\u5F53\u524D\u7528\u6237\u53EF\u8BBF\u95EE\u7684\u9879\u76EE").action(async () => {
6733
+ const command = ctx.io("projects list");
6734
+ await command.run(async () => {
6735
+ const { projectsList: projectsList2 } = await Promise.resolve().then(() => (init_projects(), projects_exports));
6736
+ const list = await projectsList2(ctx.paths);
6737
+ command.ok({ projects: list }, (data) => {
6738
+ const projectsData = data.projects;
6739
+ if (projectsData.length === 0) return "\uFF08\u8FD8\u6CA1\u6709\u9879\u76EE\uFF1Aadep projects create <slug>\uFF09";
6740
+ return projectsData.map((p) => `${p.slug} ${p.name} ${p.url}`);
6741
+ });
6742
+ });
6743
+ });
6744
+ 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) => {
6745
+ const command = ctx.io("projects info");
6746
+ await command.run(async () => {
6747
+ const { projectsInfo: projectsInfo2 } = await Promise.resolve().then(() => (init_projects(), projects_exports));
6748
+ const project2 = await projectsInfo2(ctx.paths, { slug });
6749
+ command.ok(project2, (data) => {
6750
+ const p = data;
6751
+ return `${p.id} ${p.slug} ${p.name} ${p.url}`;
6752
+ });
6753
+ });
6754
+ });
6755
+ }
6756
+
6757
+ // src/commands/functions.ts
6758
+ init_auth();
6759
+ function registerFunctions(program2, ctx) {
6760
+ const functions = program2.command("functions").description("\u4E91\u51FD\u6570\uFF1A\u90E8\u7F72\uFF08\u53EF\u6307\u5B9A\u76EE\u5F55\uFF09/ \u5217\u51FA / \u67E5\u65E5\u5FD7");
6761
+ functions.command("deploy").description(
6762
+ "[deprecated] \u63A8\u8350\u4F7F\u7528 adep publish --only functions\u3002\u90E8\u7F72\u51FD\u6570\u76EE\u5F55\uFF08dir \u8986\u76D6 adep.config.ts \u7684 functionsDir\uFF09"
6763
+ ).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) => {
6764
+ const command = ctx.io("functions deploy");
6765
+ if (!command.json) {
6766
+ process.stderr.write(
6767
+ "\u63D0\u793A\uFF1Aadep functions deploy \u5DF2\u5E9F\u5F03\uFF0C\u63A8\u8350\u4F7F\u7528 adep publish --only functions\n"
6768
+ );
6769
+ }
6770
+ await command.run(() => runDeploy(ctx.paths, command, ctx.cwd, flags.project, dir));
6771
+ });
6772
+ 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) => {
6773
+ const command = ctx.io("functions list");
6774
+ await command.run(async () => {
6775
+ const { functionsList: functionsList2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
6776
+ const result = await functionsList2(ctx.paths, {
6777
+ cwd: ctx.cwd,
6778
+ ...flags.project === void 0 ? {} : { slug: flags.project }
6779
+ });
6780
+ command.ok(result, (data) => {
6781
+ const r = data;
6782
+ if (r.functions.length === 0) return "\uFF08\u8BE5\u9879\u76EE\u4E0B\u8FD8\u6CA1\u6709\u51FD\u6570\uFF09";
6783
+ return r.functions.map((fn) => `${fn.name} ${r.baseUrl}/${fn.name}`);
6784
+ });
6785
+ });
6786
+ });
6787
+ 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) => {
6788
+ const command = ctx.io("functions logs");
6789
+ await command.run(async () => {
6790
+ const { functionsLogs: functionsLogs2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
6791
+ const tail = flags.tail === void 0 ? void 0 : Number(flags.tail);
6792
+ if (tail !== void 0 && (!Number.isFinite(tail) || tail <= 0)) {
6793
+ throw new CliError("INVALID_TAIL", `--tail \u987B\u4E3A\u6B63\u6574\u6570\uFF0C\u6536\u5230 "${flags.tail}"`);
6794
+ }
6795
+ const result = await functionsLogs2(ctx.paths, {
6796
+ cwd: ctx.cwd,
6797
+ name,
6798
+ ...tail === void 0 ? {} : { tail },
6799
+ ...flags.project === void 0 ? {} : { slug: flags.project }
6800
+ });
6801
+ command.ok(result, (data) => {
6802
+ const r = data;
6803
+ if (r.logs.length === 0) {
6804
+ 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`;
6805
+ }
6806
+ return r.logs.map((log) => `${log.at} [${log.level}] ${log.message}`);
6807
+ });
6808
+ });
6809
+ });
6810
+ }
6811
+
6812
+ // src/commands/hosting.ts
6265
6813
  init_auth();
6266
6814
  function parseBool(raw) {
6267
6815
  if (raw === void 0) return void 0;
@@ -6289,8 +6837,15 @@ function registerHosting(program2, ctx) {
6289
6837
  });
6290
6838
  });
6291
6839
  });
6292
- 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) => {
6840
+ hosting.command("deploy").description(
6841
+ "[deprecated] \u63A8\u8350\u4F7F\u7528 adep publish --only frontend\u3002\u90E8\u7F72\u672C\u5730\u76EE\u5F55\u4E3A\u9759\u6001\u7AD9\u70B9\uFF1A\u9012\u5F52\u4E0A\u4F20\u5230 site/ \u5E76\u6253\u5F00\u6258\u7BA1"
6842
+ ).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) => {
6293
6843
  const command = ctx.io("hosting deploy");
6844
+ if (!command.json) {
6845
+ process.stderr.write(
6846
+ "\u63D0\u793A\uFF1Aadep hosting deploy \u5DF2\u5E9F\u5F03\uFF0C\u63A8\u8350\u4F7F\u7528 adep publish --only frontend\uFF08\u5E73\u53F0\u4FA7\u6784\u5EFA web/ \u8349\u7A3F\uFF09\uFF1B\u5982\u786E\u9700\u4E0A\u4F20\u9884\u6784\u5EFA\u76EE\u5F55\uFF0C\u4ECD\u53EF\u7EE7\u7EED\u4F7F\u7528\u672C\u547D\u4EE4\n"
6847
+ );
6848
+ }
6294
6849
  await command.run(async () => {
6295
6850
  const { hostingDeploy: hostingDeploy2 } = await Promise.resolve().then(() => (init_hosting(), hosting_exports));
6296
6851
  const result = await hostingDeploy2(ctx.paths, {
@@ -6340,37 +6895,7 @@ function registerHosting(program2, ctx) {
6340
6895
  });
6341
6896
  }
6342
6897
 
6343
- // packages/cli/src/commands/export.ts
6344
- function registerExport(program2, ctx) {
6345
- 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(
6346
- async (flags) => {
6347
- const command = ctx.io("export");
6348
- await command.run(async () => {
6349
- const { createExportApiClient: createExportApiClient2 } = await Promise.resolve().then(() => (init_client2(), client_exports2));
6350
- const { createExportFileSystem: createExportFileSystem2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
6351
- const { ExportCommand: ExportCommand2 } = await Promise.resolve().then(() => (init_command(), command_exports));
6352
- const { resolveSlug: resolveSlug2 } = await Promise.resolve().then(() => (init_client(), client_exports));
6353
- const project2 = await resolveSlug2(ctx.cwd, flags.project);
6354
- const apiClient = await createExportApiClient2(ctx.paths);
6355
- const exportCommand = new ExportCommand2(apiClient, createExportFileSystem2());
6356
- const result = await exportCommand.execute({
6357
- project: project2,
6358
- ...flags.withData === true ? { withData: true } : {},
6359
- ...flags.withSource === true ? { withSource: true } : {},
6360
- ...flags.out === void 0 ? {} : { out: flags.out },
6361
- json: command.json
6362
- });
6363
- if (!result.success) {
6364
- command.fail("EXPORT_FAILED", result.error ?? "\u5BFC\u51FA\u5931\u8D25");
6365
- return;
6366
- }
6367
- command.ok(result);
6368
- });
6369
- }
6370
- );
6371
- }
6372
-
6373
- // packages/cli/src/cli.ts
6898
+ // src/cli.ts
6374
6899
  var requireJson2 = createRequire2(import.meta.url);
6375
6900
  var APP_VERSION = requireJson2("../package.json").version;
6376
6901
  function buildProgram(options = {}) {
@@ -6383,21 +6908,22 @@ function buildProgram(options = {}) {
6383
6908
  program2.option("--json", "\u4EE5\u673A\u5668\u53EF\u8BFB JSON \u8F93\u51FA\uFF08Agent / \u811A\u672C\u8C03\u7528\uFF09", false);
6384
6909
  const jsonMode = () => program2.opts()["json"] === true;
6385
6910
  const ctx = createCliContext({ output, paths, cwd, json: jsonMode });
6386
- registerAuth(program2, ctx);
6387
6911
  registerInit(program2, ctx);
6388
6912
  registerDevServers(program2, ctx);
6913
+ registerPublish(program2, ctx);
6914
+ registerExport(program2, ctx);
6915
+ registerDb(program2, ctx);
6916
+ registerStorage(program2, ctx);
6917
+ registerDoctor(program2, ctx);
6918
+ registerAuth(program2, ctx);
6919
+ registerMcp(program2, ctx);
6389
6920
  registerDeploy(program2, ctx);
6390
6921
  registerProjects(program2, ctx);
6391
6922
  registerFunctions(program2, ctx);
6392
- registerMcp(program2, ctx);
6393
- registerDoctor(program2, ctx);
6394
- registerDb(program2, ctx);
6395
- registerStorage(program2, ctx);
6396
6923
  registerHosting(program2, ctx);
6397
- registerExport(program2, ctx);
6398
6924
  return program2;
6399
6925
  }
6400
6926
 
6401
- // packages/cli/src/index.ts
6927
+ // src/index.ts
6402
6928
  var program = buildProgram();
6403
6929
  await program.parseAsync(process.argv);