@adep/cli 0.3.1 → 0.4.1

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
@@ -15,7 +15,7 @@ function resolvePaths(env = process.env) {
15
15
  return { home, credentialsFile: `${home}/credentials` };
16
16
  }
17
17
  function resolveServer(env = process.env) {
18
- return (env["ADEP_SERVER"] ?? "https://adep.jajabjbj.top").replace(/\/+$/, "");
18
+ return (env["ADEP_SERVER"] ?? "https://adep.top").replace(/\/+$/, "");
19
19
  }
20
20
  function resolveElectronMirror(env = process.env) {
21
21
  return env["ELECTRON_MIRROR"] ?? DEFAULT_ELECTRON_MIRROR;
@@ -23736,13 +23736,67 @@ var init_demo = __esm({
23736
23736
  });
23737
23737
 
23738
23738
  // packages/runtime/src/functions/runtime/exports.ts
23739
+ function keepLineCount(matched, lead) {
23740
+ const consumed = matched.split("\n").length - 1;
23741
+ const kept = lead === "\n" ? 1 : 0;
23742
+ return "\n".repeat(Math.max(0, consumed - kept));
23743
+ }
23744
+ function parseSpecifier(part) {
23745
+ const asMatch = /^([A-Za-z_$][\w$]*)\s+as\s+([A-Za-z_$][\w$]*)$/.exec(part);
23746
+ if (asMatch !== null) {
23747
+ const [, local, exported] = asMatch;
23748
+ if (local !== void 0 && exported !== void 0) return [local, exported];
23749
+ }
23750
+ return /^[A-Za-z_$][\w$]*$/.test(part) ? [part, part] : null;
23751
+ }
23752
+ function namedImportsToDestructure(clause) {
23753
+ const parts = [];
23754
+ for (const raw of clause.split(",")) {
23755
+ const part = raw.trim();
23756
+ if (part === "") continue;
23757
+ const spec = parseSpecifier(part);
23758
+ if (spec === null) {
23759
+ throw new Error(`\u4E0D\u652F\u6301\u7684\u5177\u540D\u5BFC\u5165\u5F62\u6001\uFF1A"${part}"\uFF08\u6C99\u7BB1\u5B50\u96C6\u4EC5\u63A5\u53D7 a \u6216 a as b\uFF09`);
23760
+ }
23761
+ parts.push(spec[0] === spec[1] ? spec[0] : `${spec[0]}: ${spec[1]}`);
23762
+ }
23763
+ return parts;
23764
+ }
23765
+ function parseExportClause(clause) {
23766
+ const entries = [];
23767
+ for (const raw of clause.split(",")) {
23768
+ const part = raw.trim();
23769
+ if (part === "") continue;
23770
+ const spec = parseSpecifier(part);
23771
+ if (spec === null) {
23772
+ throw new Error(`\u4E0D\u652F\u6301\u7684\u518D\u5BFC\u51FA\u5B50\u53E5\uFF1A"${part}"\uFF08\u6C99\u7BB1\u5B50\u96C6\u4EC5\u63A5\u53D7 a \u6216 a as b\uFF09`);
23773
+ }
23774
+ entries.push({ local: spec[0], exported: spec[1] });
23775
+ }
23776
+ return entries;
23777
+ }
23739
23778
  function transformModule(code) {
23740
23779
  let out = code;
23741
23780
  const named = [];
23781
+ const starReexports = [];
23782
+ let tempSeq = 0;
23783
+ const nextTemp = () => `__adep_reexport_${tempSeq++}`;
23742
23784
  out = out.replace(/(^|\n)(\s*)export\s+default\s+/g, "$1$2module.default = ");
23743
23785
  out = out.replace(
23744
23786
  /import\s*\{([^}]*)\}\s*from\s*(['"][^'"]*['"])[ \t]*;?/g,
23745
- (_match, names, source) => `const {${names}} = require(${source})`
23787
+ (matched, clause, source) => {
23788
+ const parts = namedImportsToDestructure(clause);
23789
+ const pad = keepLineCount(matched, "");
23790
+ return parts.length === 0 ? `require(${source})${pad}` : `const { ${parts.join(", ")} } = require(${source})${pad}`;
23791
+ }
23792
+ );
23793
+ out = out.replace(
23794
+ /import\s+([A-Za-z_$][\w$]*)\s*,\s*\{([^}]*)\}\s*from\s*(['"][^'"]*['"])[ \t]*;?/g,
23795
+ (matched, name, clause, source) => {
23796
+ const parts = namedImportsToDestructure(clause);
23797
+ const pad = keepLineCount(matched, "");
23798
+ return parts.length === 0 ? `const ${name} = require(${source})${pad}` : `const ${name} = require(${source}), { ${parts.join(", ")} } = ${name}${pad}`;
23799
+ }
23746
23800
  );
23747
23801
  out = out.replace(
23748
23802
  /import\s*\*\s*as\s*([A-Za-z_$][\w$]*)\s*from\s*(['"][^'"]*['"])[ \t]*;?/g,
@@ -23752,27 +23806,67 @@ function transformModule(code) {
23752
23806
  /import\s+([A-Za-z_$][\w$]*)\s+from\s*(['"][^'"]*['"])[ \t]*;?/g,
23753
23807
  (_match, name, source) => `const ${name} = require(${source})`
23754
23808
  );
23809
+ out = out.replace(
23810
+ /(^|\n)([ \t]*)import\s*(['"][^'"]*['"])[ \t]*;?/g,
23811
+ (_match, lead, indent, source) => `${lead}${indent}require(${source})`
23812
+ );
23813
+ out = out.replace(
23814
+ /(^|\n)([ \t]*)export\s*\{([^}]*)\}[ \t]*(?:\n[ \t]*(?=from\b))?(?:from\s*(['"][^'"]*['"]))?[ \t]*;?/g,
23815
+ (matched, lead, indent, clause, source) => {
23816
+ const pad = keepLineCount(matched, lead);
23817
+ const entries = parseExportClause(clause);
23818
+ if (entries.length === 0) return `${lead}${indent}${pad}`;
23819
+ if (source === void 0) {
23820
+ named.push(...entries);
23821
+ return `${lead}${indent}${pad}`;
23822
+ }
23823
+ const temp = nextTemp();
23824
+ for (const entry of entries) {
23825
+ named.push({ local: `${temp}.${entry.local}`, exported: entry.exported });
23826
+ }
23827
+ return `${lead}${indent}const ${temp} = require(${source})${pad}`;
23828
+ }
23829
+ );
23830
+ out = out.replace(
23831
+ /(^|\n)([ \t]*)export\s*\*[ \t]*(?:as[ \t]+([A-Za-z_$][\w$]*)[ \t]*)?\s*from\s*(['"][^'"]*['"])[ \t]*;?/g,
23832
+ (matched, lead, indent, ns, source) => {
23833
+ const pad = keepLineCount(matched, lead);
23834
+ const temp = nextTemp();
23835
+ if (ns === void 0) starReexports.push(temp);
23836
+ else named.push({ local: temp, exported: ns });
23837
+ return `${lead}${indent}const ${temp} = require(${source})${pad}`;
23838
+ }
23839
+ );
23755
23840
  out = out.replace(
23756
23841
  /export\s+(const|let|var)\s+([A-Za-z_$][\w$]*)/g,
23757
23842
  (_match, kw, name) => {
23758
- named.push(name);
23843
+ named.push({ local: name, exported: name });
23759
23844
  return `${kw} ${name}`;
23760
23845
  }
23761
23846
  );
23762
23847
  out = out.replace(
23763
23848
  /export\s+(async\s+)?function\s*\*?\s*([A-Za-z_$][\w$]*)/g,
23764
23849
  (_match, asyncKw, name) => {
23765
- named.push(name);
23850
+ named.push({ local: name, exported: name });
23766
23851
  return `${asyncKw ?? ""}function ${name}`;
23767
23852
  }
23768
23853
  );
23769
23854
  out = out.replace(/export\s+class\s+([A-Za-z_$][\w$]*)/g, (_match, name) => {
23770
- named.push(name);
23855
+ named.push({ local: name, exported: name });
23771
23856
  return `class ${name}`;
23772
23857
  });
23773
- if (named.length > 0) {
23858
+ for (const temp of starReexports) {
23859
+ out += `
23860
+ ;Object.keys(${temp}).forEach((k) => { if (k !== 'default') exports[k] = ${temp}[k] })`;
23861
+ }
23862
+ const byExported = /* @__PURE__ */ new Map();
23863
+ for (const entry of named) byExported.set(entry.exported, entry.local);
23864
+ if (byExported.size > 0) {
23865
+ const picks = [...byExported].map(
23866
+ ([exported, local]) => local === exported ? exported : `${exported}: ${local}`
23867
+ );
23774
23868
  out += `
23775
- ;Object.assign(exports, { ${named.join(", ")} })`;
23869
+ ;Object.assign(exports, { ${picks.join(", ")} })`;
23776
23870
  }
23777
23871
  return out;
23778
23872
  }
@@ -23782,6 +23876,16 @@ var init_exports = __esm({
23782
23876
  }
23783
23877
  });
23784
23878
 
23879
+ // packages/runtime/src/shared/regexp.ts
23880
+ function escapeRegExp(text) {
23881
+ return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
23882
+ }
23883
+ var init_regexp = __esm({
23884
+ "packages/runtime/src/shared/regexp.ts"() {
23885
+ "use strict";
23886
+ }
23887
+ });
23888
+
23785
23889
  // packages/runtime/src/functions/runtime/sandbox.ts
23786
23890
  import vm from "node:vm";
23787
23891
  import * as nodeModule from "node:module";
@@ -23800,6 +23904,28 @@ function transpile(code) {
23800
23904
  function transformExports(code) {
23801
23905
  return transformModule(code);
23802
23906
  }
23907
+ function realmValue(value) {
23908
+ return { [REALM_VALUE_KEY]: value };
23909
+ }
23910
+ function isRealmValue(value) {
23911
+ return typeof value === "object" && value !== null && REALM_VALUE_KEY in value;
23912
+ }
23913
+ function createSandboxContext(sandboxGlobals) {
23914
+ const direct = {};
23915
+ const realmEntries = {};
23916
+ for (const [key, value] of Object.entries(sandboxGlobals)) {
23917
+ if (isRealmValue(value)) realmEntries[key] = value[REALM_VALUE_KEY];
23918
+ else direct[key] = value;
23919
+ }
23920
+ const context = vm.createContext(direct, { codeGeneration: { strings: false, wasm: false } });
23921
+ if (Object.keys(realmEntries).length > 0) {
23922
+ const literal2 = JSON.stringify(JSON.stringify(realmEntries));
23923
+ vm.runInContext(`Object.assign(globalThis, JSON.parse(${literal2}))`, context, {
23924
+ filename: "<sandbox-realm-globals>"
23925
+ });
23926
+ }
23927
+ return context;
23928
+ }
23803
23929
  function resolveModulePath(fromDir, request, files) {
23804
23930
  if (!request.startsWith("./") && !request.startsWith("../")) return null;
23805
23931
  const base = joinPosix(fromDir, request);
@@ -23823,6 +23949,21 @@ function joinPosix(dir, request) {
23823
23949
  function normalizePosix(p) {
23824
23950
  return joinPosix("", p);
23825
23951
  }
23952
+ function errorLineIn(stack, path) {
23953
+ const own = new RegExp(`${escapeRegExp(path)}:(\\d+)`).exec(stack);
23954
+ if (own !== null) return own[1];
23955
+ return /(?:^|\n):(\d+)(?:\n|$)/.exec(stack)?.[1];
23956
+ }
23957
+ function syntaxErrorWithLocation(error51, path) {
23958
+ const rawMessage = error51 instanceof Error ? error51.message : String(error51);
23959
+ const stack = error51.stack;
23960
+ const line = typeof stack === "string" ? errorLineIn(stack, path) : void 0;
23961
+ const location = line === void 0 ? path : `${path}:${line}`;
23962
+ const wrapped = new Error(`\u6E90\u7801\u8BED\u6CD5\u9519\u8BEF\uFF08${location}\uFF09\uFF1A${rawMessage}`, { cause: error51 });
23963
+ const code = error51.code;
23964
+ if (typeof code === "string") wrapped.code = code;
23965
+ return wrapped;
23966
+ }
23826
23967
  function loadModule(path, files, sandboxGlobals, cache, resolveBare, bareCache) {
23827
23968
  const cached2 = cache.get(path);
23828
23969
  if (cached2 !== void 0) return cached2;
@@ -23856,21 +23997,20 @@ function loadModule(path, files, sandboxGlobals, cache, resolveBare, bareCache)
23856
23997
  try {
23857
23998
  transformed = transformExports(transpile(source));
23858
23999
  } catch (error51) {
23859
- const rawMessage = error51 instanceof Error ? error51.message : String(error51);
23860
- const stack = error51.stack;
23861
- const line = typeof stack === "string" ? /(?:^|\n):(\d+)(?:\n|$)/.exec(stack)?.[1] : void 0;
23862
- const location = line === void 0 ? path : `${path}:${line}`;
23863
- const wrapped = new Error(`\u6E90\u7801\u8BED\u6CD5\u9519\u8BEF\uFF08${location}\uFF09\uFF1A${rawMessage}`, { cause: error51 });
23864
- const code = error51.code;
23865
- if (typeof code === "string") wrapped.code = code;
23866
- throw wrapped;
23867
- }
23868
- const wrapper = vm.runInNewContext(
23869
- `(function (module, exports, require) { ${transformed}
24000
+ throw syntaxErrorWithLocation(error51, path);
24001
+ }
24002
+ const context = createSandboxContext(sandboxGlobals);
24003
+ let wrapper;
24004
+ try {
24005
+ wrapper = vm.runInContext(
24006
+ `(function (module, exports, require) { ${transformed}
23870
24007
  })`,
23871
- vm.createContext({ ...sandboxGlobals }),
23872
- { filename: path }
23873
- );
24008
+ context,
24009
+ { filename: path }
24010
+ );
24011
+ } catch (error51) {
24012
+ throw syntaxErrorWithLocation(error51, path);
24013
+ }
23874
24014
  wrapper(module, exports, require2);
23875
24015
  if (module.default !== void 0 && exports["default"] === void 0) {
23876
24016
  exports["default"] = module.default;
@@ -23887,12 +24027,14 @@ function loadFunctionModule(files, entry, sandboxGlobals, resolveBare) {
23887
24027
  }
23888
24028
  return { handler };
23889
24029
  }
23890
- var bunTranspiler, SANDBOX_BUILTIN_REJECTED;
24030
+ var bunTranspiler, SANDBOX_BUILTIN_REJECTED, REALM_VALUE_KEY;
23891
24031
  var init_sandbox = __esm({
23892
24032
  "packages/runtime/src/functions/runtime/sandbox.ts"() {
23893
24033
  "use strict";
23894
24034
  init_exports();
24035
+ init_regexp();
23895
24036
  SANDBOX_BUILTIN_REJECTED = "FN_SANDBOX_BUILTIN_BLOCKED";
24037
+ REALM_VALUE_KEY = "__adepRealmValue";
23896
24038
  }
23897
24039
  });
23898
24040
 
@@ -24091,18 +24233,24 @@ function headersToRecord(headers) {
24091
24233
  }
24092
24234
  return out;
24093
24235
  }
24094
- function contentLength(res) {
24095
- const headers = res.headers;
24236
+ function headerValue(headers, name) {
24096
24237
  if (headers === void 0 || headers === null) return null;
24238
+ let raw;
24097
24239
  if (typeof headers.get === "function") {
24098
- const raw2 = headers.get?.("content-length");
24099
- if (raw2 === void 0 || raw2 === null || raw2.trim() === "") return null;
24100
- const n2 = Number(raw2);
24101
- return Number.isFinite(n2) && n2 >= 0 ? n2 : null;
24102
- }
24103
- const record2 = headers;
24104
- const raw = record2["content-length"] ?? record2["Content-Length"];
24105
- if (raw === void 0 || raw === null) return null;
24240
+ raw = headers.get?.(name);
24241
+ } else {
24242
+ const record2 = headers;
24243
+ raw = record2[name.toLocaleLowerCase()] ?? record2[name];
24244
+ }
24245
+ if (raw === void 0 || raw === null || raw.trim() === "") return null;
24246
+ return raw;
24247
+ }
24248
+ function contentLength(res) {
24249
+ const raw = headerValue(
24250
+ res.headers,
24251
+ "content-length"
24252
+ );
24253
+ if (raw === null) return null;
24106
24254
  const n = Number(raw);
24107
24255
  return Number.isFinite(n) && n >= 0 ? n : null;
24108
24256
  }
@@ -24180,46 +24328,74 @@ function createSandboxFetch(options) {
24180
24328
  const fetchImpl = options.fetchImpl ?? defaultFetch;
24181
24329
  const { allowlist, timeoutMs } = options;
24182
24330
  const maxBytes = options.maxResponseBytes ?? DEFAULT_MAX_RESPONSE_BYTES;
24183
- return async (url2, init) => {
24331
+ const maxRedirects = Math.max(0, options.maxRedirects ?? DEFAULT_MAX_REDIRECTS);
24332
+ const guard = (raw) => {
24184
24333
  let parsed;
24185
24334
  try {
24186
- parsed = new URL(url2);
24335
+ parsed = new URL(raw);
24187
24336
  } catch {
24188
- throw new SandboxFetchError("FN_FETCH_INVALID_URL", `cloud.fetch \u6536\u5230\u975E\u6CD5 URL"${url2}"`);
24337
+ throw new SandboxFetchError("FN_FETCH_INVALID_URL", `cloud.fetch \u6536\u5230\u975E\u6CD5 URL"${raw}"`);
24189
24338
  }
24190
- if (parsed.protocol !== "https:" && parsed.protocol !== "http:") throw FORBIDDEN(url2);
24191
- if (!isHostAllowed(parsed.hostname, allowlist)) throw FORBIDDEN(url2);
24339
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") throw FORBIDDEN(raw);
24340
+ if (!isHostAllowed(parsed.hostname, allowlist)) throw FORBIDDEN(raw);
24341
+ return parsed;
24342
+ };
24343
+ const fetchOnce = async (url2, init) => {
24192
24344
  const controller = new AbortController();
24193
24345
  const timer = setTimeout(() => controller.abort(), timeoutMs);
24194
24346
  const signals = [controller.signal];
24195
24347
  if (init?.signal !== void 0) signals.push(init.signal);
24196
24348
  const signal = signals.length === 1 ? signals[0] : AbortSignal.any(signals);
24349
+ const request = {
24350
+ ...init,
24351
+ signal,
24352
+ redirect: "manual"
24353
+ };
24197
24354
  try {
24198
- let res;
24199
- try {
24200
- res = await fetchImpl(url2, { ...init, signal });
24201
- } catch (error51) {
24202
- if (controller.signal.aborted) {
24203
- throw new SandboxFetchError(
24204
- "FN_FETCH_TIMEOUT",
24205
- `cloud.fetch \u8BF7\u6C42\u8D85\u65F6\uFF08\u8D85\u8FC7 ${timeoutMs}ms\uFF09`
24206
- );
24207
- }
24208
- if (init?.signal?.aborted === true) {
24209
- throw new SandboxFetchError("FN_FETCH_ABORTED", "cloud.fetch \u8BF7\u6C42\u88AB\u8C03\u7528\u65B9\u4E2D\u6B62");
24210
- }
24211
- throw new SandboxFetchError(
24212
- "FN_FETCH_FAILED",
24213
- `cloud.fetch \u8BF7\u6C42\u5931\u8D25\uFF1A${errorMessageOf(error51)}`
24214
- );
24355
+ return await fetchImpl(url2, request);
24356
+ } catch (error51) {
24357
+ if (controller.signal.aborted) {
24358
+ throw new SandboxFetchError("FN_FETCH_TIMEOUT", `cloud.fetch \u8BF7\u6C42\u8D85\u65F6\uFF08\u8D85\u8FC7 ${timeoutMs}ms\uFF09`);
24215
24359
  }
24216
- return normalizeResponse(res, maxBytes);
24360
+ if (init?.signal?.aborted === true) {
24361
+ throw new SandboxFetchError("FN_FETCH_ABORTED", "cloud.fetch \u8BF7\u6C42\u88AB\u8C03\u7528\u65B9\u4E2D\u6B62");
24362
+ }
24363
+ throw new SandboxFetchError(
24364
+ "FN_FETCH_FAILED",
24365
+ `cloud.fetch \u8BF7\u6C42\u5931\u8D25\uFF1A${errorMessageOf(error51)}`
24366
+ );
24217
24367
  } finally {
24218
24368
  clearTimeout(timer);
24219
24369
  }
24220
24370
  };
24371
+ return async (url2, init) => {
24372
+ let target = guard(url2);
24373
+ let currentInit = init === void 0 ? void 0 : { ...init };
24374
+ let lastRes = null;
24375
+ for (let hop = 0; hop <= maxRedirects; hop++) {
24376
+ const res = await fetchOnce(target.href, currentInit);
24377
+ const location = REDIRECT_STATUSES.has(res.status) ? headerValue(res.headers, "location") : null;
24378
+ if (location === null || hop === maxRedirects) {
24379
+ lastRes = res;
24380
+ break;
24381
+ }
24382
+ let next;
24383
+ try {
24384
+ next = new URL(location, target.href);
24385
+ } catch {
24386
+ lastRes = res;
24387
+ break;
24388
+ }
24389
+ if (res.status !== 307 && res.status !== 308 && currentInit !== void 0) {
24390
+ currentInit.method = "GET";
24391
+ delete currentInit.body;
24392
+ }
24393
+ target = guard(next.href);
24394
+ }
24395
+ return normalizeResponse(lastRes, maxBytes);
24396
+ };
24221
24397
  }
24222
- var SandboxFetchError, DEFAULT_MAX_RESPONSE_BYTES, defaultFetch, FORBIDDEN, TOO_LARGE, encoder, decoder;
24398
+ var SandboxFetchError, DEFAULT_MAX_RESPONSE_BYTES, DEFAULT_MAX_REDIRECTS, REDIRECT_STATUSES, defaultFetch, FORBIDDEN, TOO_LARGE, encoder, decoder;
24223
24399
  var init_sandbox_fetch = __esm({
24224
24400
  "packages/runtime/src/functions/runtime/sandbox-fetch.ts"() {
24225
24401
  "use strict";
@@ -24232,6 +24408,8 @@ var init_sandbox_fetch = __esm({
24232
24408
  }
24233
24409
  };
24234
24410
  DEFAULT_MAX_RESPONSE_BYTES = 100 * 1024 * 1024;
24411
+ DEFAULT_MAX_REDIRECTS = 5;
24412
+ REDIRECT_STATUSES = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
24235
24413
  defaultFetch = (url2, init) => (
24236
24414
  // 真实 Response 与内部 ResponseLike 结构性一致;getReader 的多态签名差异属纯类型问题,运行语义等价。
24237
24415
  globalThis.fetch(url2, init)
@@ -24400,16 +24578,6 @@ var init_chain = __esm({
24400
24578
  }
24401
24579
  });
24402
24580
 
24403
- // packages/runtime/src/shared/regexp.ts
24404
- function escapeRegExp(text) {
24405
- return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
24406
- }
24407
- var init_regexp = __esm({
24408
- "packages/runtime/src/shared/regexp.ts"() {
24409
- "use strict";
24410
- }
24411
- });
24412
-
24413
24581
  // packages/runtime/src/functions/runtime/worker-entry.ts
24414
24582
  import { parentPort, workerData } from "node:worker_threads";
24415
24583
  import { createRequire } from "node:module";
@@ -24422,12 +24590,35 @@ function errorMessageOf2(error51) {
24422
24590
  }
24423
24591
  return String(error51);
24424
24592
  }
24593
+ async function normalizeResultBody(value) {
24594
+ if (!(value instanceof Response)) return value;
24595
+ const contentType = value.headers.get("content-type") ?? "";
24596
+ const text = await value.text();
24597
+ let payload = text;
24598
+ if (contentType.includes("application/json")) {
24599
+ try {
24600
+ payload = text === "" ? null : JSON.parse(text);
24601
+ } catch {
24602
+ payload = text;
24603
+ }
24604
+ }
24605
+ const headers = {};
24606
+ value.headers.forEach((headerValue2, key) => {
24607
+ headers[key] = headerValue2;
24608
+ });
24609
+ return { __adepHttp: { status: value.status, body: payload, headers } };
24610
+ }
24425
24611
  function firstUserFrame(stack, files) {
24426
- for (const key of Object.keys(files)) {
24427
- const match = new RegExp(
24428
- `(?<![\\w$/.])${escapeRegExp(key)}:(\\d+)(?::(\\d+))?(?::(\\d+))?`
24429
- ).exec(stack);
24430
- if (match !== null) {
24612
+ const patterns = Object.keys(files).map(
24613
+ (key) => [
24614
+ key,
24615
+ new RegExp(`(?<![\\w$/.])${escapeRegExp(key)}:(\\d+)(?::(\\d+))?(?::(\\d+))?`)
24616
+ ]
24617
+ );
24618
+ for (const line of stack.split("\n")) {
24619
+ for (const [key, pattern] of patterns) {
24620
+ const match = pattern.exec(line);
24621
+ if (match === null) continue;
24431
24622
  return match[2] === void 0 ? `${key}:${match[1]}` : `${key}:${match[1]}:${match[2]}`;
24432
24623
  }
24433
24624
  }
@@ -24438,7 +24629,8 @@ function errorMessageWithLocation(error51, files) {
24438
24629
  const stack = error51.stack;
24439
24630
  if (typeof stack !== "string") return message;
24440
24631
  const frame = firstUserFrame(stack, files);
24441
- return frame === void 0 ? message : `${message}\uFF08${frame}\uFF09`;
24632
+ if (frame === void 0 || message.includes(`\uFF08${frame}\uFF09`)) return message;
24633
+ return `${message}\uFF08${frame}\uFF09`;
24442
24634
  }
24443
24635
  function createBareResolver(deps) {
24444
24636
  const platformRequire = createRequire(import.meta.url);
@@ -24519,7 +24711,7 @@ function runWorker(input, port) {
24519
24711
  structuredClone
24520
24712
  };
24521
24713
  if (input.env !== void 0) {
24522
- sandboxGlobals["process"] = { env: input.env };
24714
+ sandboxGlobals["process"] = realmValue({ env: input.env });
24523
24715
  }
24524
24716
  if (input.fetch !== void 0) {
24525
24717
  const sandboxFetch = createSandboxFetch({
@@ -24551,8 +24743,20 @@ function runWorker(input, port) {
24551
24743
  const result = Promise.resolve(handler(ctx));
24552
24744
  void result.then(
24553
24745
  (value) => {
24554
- port.postMessage({ type: "result", body: value === void 0 ? null : value });
24555
- return void 0;
24746
+ return normalizeResultBody(value).then(
24747
+ (body) => {
24748
+ port.postMessage({ type: "result", body: body === void 0 ? null : body });
24749
+ return void 0;
24750
+ },
24751
+ (error51) => {
24752
+ port.postMessage({
24753
+ type: "error",
24754
+ message: `\u51FD\u6570\u8FD4\u56DE\u7684 Response \u89E3\u5305\u5931\u8D25\uFF1A${errorMessageOf2(error51)}`,
24755
+ code: "FN_RESPONSE_UNWRAP_FAILED"
24756
+ });
24757
+ return void 0;
24758
+ }
24759
+ );
24556
24760
  },
24557
24761
  (error51) => {
24558
24762
  port.postMessage({
@@ -25322,6 +25526,7 @@ __export(app_build_exports, {
25322
25526
  bindVersion: () => bindVersion,
25323
25527
  buildDesktopApp: () => buildDesktopApp,
25324
25528
  collectFunctionNames: () => collectFunctionNames,
25529
+ compareByCodeUnit: () => compareByCodeUnit,
25325
25530
  computeBundleVersion: () => computeBundleVersion,
25326
25531
  createAppBuildApi: () => createAppBuildApi,
25327
25532
  findArtifacts: () => findArtifacts,
@@ -25343,6 +25548,9 @@ import { createHash as createHash2 } from "node:crypto";
25343
25548
  import { copyFile, mkdir as mkdir9, mkdtemp, readFile as readFile12, readdir as readdir5, rm as rm3, stat as stat8, writeFile as writeFile8 } from "node:fs/promises";
25344
25549
  import { tmpdir } from "node:os";
25345
25550
  import { basename as basename2, dirname as dirname10, join as join16, posix, relative as relative2, resolve as resolve8 } from "node:path";
25551
+ function compareByCodeUnit(left, right) {
25552
+ return left < right ? -1 : left > right ? 1 : 0;
25553
+ }
25346
25554
  function normalizePlatform(input) {
25347
25555
  if (input === void 0 || input.length === 0) {
25348
25556
  if (process.platform === "darwin" || process.platform === "win32" || process.platform === "linux") {
@@ -25402,7 +25610,7 @@ async function readShellConfig(shellDir) {
25402
25610
  return { raw, config: config2 };
25403
25611
  }
25404
25612
  function computeBundleVersion(manifest) {
25405
- const siteEntries = manifest.contents.filter((content) => content.path.startsWith(SITE_PREFIX)).toSorted((left, right) => left.path.localeCompare(right.path));
25613
+ const siteEntries = manifest.contents.filter((content) => content.path.startsWith(SITE_PREFIX)).toSorted((left, right) => compareByCodeUnit(left.path, right.path));
25406
25614
  const fingerprint = createHash2("sha256").update(siteEntries.map((content) => `${content.path}:${content.sha256}`).join("\n")).digest("hex").slice(0, 12);
25407
25615
  return `${manifest.project.version}.${fingerprint}`;
25408
25616
  }
@@ -25418,7 +25626,7 @@ function collectFunctionNames(manifest) {
25418
25626
  if (name.length === 0 || name === FUNCTION_SHARED_DIR) continue;
25419
25627
  names.add(name);
25420
25628
  }
25421
- return [...names].toSorted((left, right) => left.localeCompare(right));
25629
+ return [...names].toSorted(compareByCodeUnit);
25422
25630
  }
25423
25631
  function readManifest(entries, options) {
25424
25632
  const raw = entries.get("manifest.json");
@@ -25483,7 +25691,10 @@ function verifySiteContents(manifest, entries) {
25483
25691
  );
25484
25692
  if (!result.valid) {
25485
25693
  const detail = result.errors.map((item) => item.message).join("; ");
25486
- throw new InitError("APP_BUNDLE_INTEGRITY", `\u5BFC\u51FA\u5305 site/ \u5185\u5BB9\u7269\u6821\u9A8C\u548C\u4E0D\u5339\u914D\uFF08\u5305\u5DF2\u635F\u574F\uFF09\uFF1A${detail}`);
25694
+ throw new InitError(
25695
+ "APP_BUNDLE_INTEGRITY",
25696
+ `\u5BFC\u51FA\u5305 site/ \u5185\u5BB9\u7269\u6821\u9A8C\u548C\u4E0D\u5339\u914D\uFF08\u5305\u5DF2\u635F\u574F\uFF09\uFF1A${detail}`
25697
+ );
25487
25698
  }
25488
25699
  }
25489
25700
  async function writeSiteTree(shellDir, site) {
@@ -25549,7 +25760,8 @@ function missingMobileDepsError(shellDir, platform) {
25549
25760
  async function assertShellPackagerReady(shellDir, platform, prepareOnly) {
25550
25761
  if (prepareOnly) return;
25551
25762
  if (platform === "ios") {
25552
- if (!await pathExists(join16(shellDir, "ios", "App"))) throw missingMobileDepsError(shellDir, "ios");
25763
+ if (!await pathExists(join16(shellDir, "ios", "App")))
25764
+ throw missingMobileDepsError(shellDir, "ios");
25553
25765
  return;
25554
25766
  }
25555
25767
  if (platform === "android") {
@@ -25686,10 +25898,10 @@ async function findArtifacts(shellDir, outDir, platform) {
25686
25898
  }
25687
25899
  };
25688
25900
  await walk(outDir, 1);
25689
- return found.toSorted((left, right) => left.localeCompare(right));
25901
+ return found.toSorted(compareByCodeUnit);
25690
25902
  }
25691
25903
  function topAssets(written) {
25692
- return [...written].toSorted((left, right) => right.size - left.size || left.path.localeCompare(right.path)).slice(0, TOP_ASSETS_LIMIT);
25904
+ return [...written].toSorted((left, right) => right.size - left.size || compareByCodeUnit(left.path, right.path)).slice(0, TOP_ASSETS_LIMIT);
25693
25905
  }
25694
25906
  function mismatchWarning(config2, server) {
25695
25907
  if (server === void 0 || server.length === 0) return [];
@@ -26840,46 +27052,296 @@ var init_deploy = __esm({
26840
27052
  }
26841
27053
  });
26842
27054
 
26843
- // shared/frontend-draft.ts
26844
- var FRONTEND_DRAFT_FILE_PATH_PATTERN, FRONTEND_DRAFT_MAX_TOTAL_SOURCE_BYTES, FRONTEND_DRAFT_MAX_FILES;
26845
- var init_frontend_draft = __esm({
26846
- "shared/frontend-draft.ts"() {
27055
+ // packages/cli/src/storage.ts
27056
+ var storage_exports = {};
27057
+ __export(storage_exports, {
27058
+ contentTypeOf: () => contentTypeOf,
27059
+ storageDownload: () => storageDownload,
27060
+ storageList: () => storageList,
27061
+ storageRemove: () => storageRemove,
27062
+ storageUpload: () => storageUpload
27063
+ });
27064
+ import { mkdir as mkdir13, readFile as readFile18, stat as stat12, writeFile as writeFile11 } from "node:fs/promises";
27065
+ import { basename as basename5, dirname as dirname13, extname as extname2, join as join22, resolve as resolve13 } from "node:path";
27066
+ async function open3(paths, options) {
27067
+ const client = await createClient(paths);
27068
+ const project2 = await resolveSlug(resolve13(options.cwd), options.slug);
27069
+ return { client, project: project2 };
27070
+ }
27071
+ function contentTypeOf(path) {
27072
+ const map2 = {
27073
+ ".html": "text/html; charset=utf-8",
27074
+ ".htm": "text/html; charset=utf-8",
27075
+ ".css": "text/css; charset=utf-8",
27076
+ ".js": "text/javascript; charset=utf-8",
27077
+ ".mjs": "text/javascript; charset=utf-8",
27078
+ ".json": "application/json; charset=utf-8",
27079
+ ".png": "image/png",
27080
+ ".jpg": "image/jpeg",
27081
+ ".jpeg": "image/jpeg",
27082
+ ".gif": "image/gif",
27083
+ ".svg": "image/svg+xml",
27084
+ ".webp": "image/webp",
27085
+ ".ico": "image/x-icon",
27086
+ ".txt": "text/plain; charset=utf-8",
27087
+ ".md": "text/markdown; charset=utf-8",
27088
+ ".xml": "application/xml",
27089
+ ".wasm": "application/wasm",
27090
+ ".pdf": "application/pdf",
27091
+ ".zip": "application/zip",
27092
+ ".woff": "font/woff",
27093
+ ".woff2": "font/woff2",
27094
+ ".ttf": "font/ttf",
27095
+ ".otf": "font/otf"
27096
+ };
27097
+ return map2[extname2(path).toLowerCase()] ?? "application/octet-stream";
27098
+ }
27099
+ async function storageUpload(paths, options) {
27100
+ const { client, project: project2 } = await open3(paths, options);
27101
+ const local = resolve13(options.file);
27102
+ const info = await stat12(local).catch(() => null);
27103
+ if (info === null || !info.isFile()) {
27104
+ throw new CliError("FILE_NOT_FOUND", `\u672C\u5730\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${local}`);
27105
+ }
27106
+ const visibility = options.visibility ?? "private";
27107
+ const bytes = await readFile18(local);
27108
+ const form = new FormData();
27109
+ form.set("path", options.path);
27110
+ form.set("visibility", visibility);
27111
+ form.set(
27112
+ "file",
27113
+ new Blob([bytes], { type: contentTypeOf(options.path) }),
27114
+ basename5(local)
27115
+ );
27116
+ const response = await client.upload(
27117
+ `/api/v1/projects/${project2}/files`,
27118
+ form,
27119
+ "STORAGE_UPLOAD_FAILED"
27120
+ );
27121
+ const body = await response.json();
27122
+ return { ...body.file, ...body.signedUrl === void 0 ? {} : { signedUrl: body.signedUrl } };
27123
+ }
27124
+ async function storageList(paths, options) {
27125
+ const { client, project: project2 } = await open3(paths, options);
27126
+ const query = options.prefix === void 0 ? "" : `?prefix=${encodeURIComponent(options.prefix)}`;
27127
+ const body = await client.request(
27128
+ `/api/v1/projects/${project2}/files${query}`
27129
+ );
27130
+ return { project: project2, files: body.files };
27131
+ }
27132
+ async function resolveDownloadUrl(client, project2, path) {
27133
+ const body = await client.request(
27134
+ `/api/v1/projects/${project2}/files?prefix=${encodeURIComponent(path)}`
27135
+ );
27136
+ const entry = body.files.find((file2) => file2.path === path);
27137
+ const url2 = entry?.url ?? entry?.signedUrl;
27138
+ if (entry === void 0 || url2 === void 0 || url2.length === 0) {
27139
+ throw new CliError("STORAGE_NOT_FOUND", `\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${path}`);
27140
+ }
27141
+ return url2;
27142
+ }
27143
+ async function storageDownload(paths, options) {
27144
+ const { client, project: project2 } = await open3(paths, options);
27145
+ const url2 = await resolveDownloadUrl(client, project2, options.path);
27146
+ const response = await client.download(url2, "STORAGE_DOWNLOAD_FAILED");
27147
+ const bytes = Buffer.from(await response.arrayBuffer());
27148
+ const output = resolve13(options.output ?? join22(resolve13(options.cwd), basename5(options.path)));
27149
+ await mkdir13(dirname13(output), { recursive: true });
27150
+ await writeFile11(output, bytes);
27151
+ return { path: options.path, output, size: bytes.length };
27152
+ }
27153
+ async function storageRemove(paths, options) {
27154
+ const { client, project: project2 } = await open3(paths, options);
27155
+ return client.request(
27156
+ `/api/v1/projects/${project2}/files/${encodeURIComponent(options.path)}`,
27157
+ { method: "DELETE" }
27158
+ );
27159
+ }
27160
+ var init_storage2 = __esm({
27161
+ "packages/cli/src/storage.ts"() {
26847
27162
  "use strict";
26848
- FRONTEND_DRAFT_FILE_PATH_PATTERN = /^[a-zA-Z0-9._][a-zA-Z0-9._/-]*$/;
26849
- FRONTEND_DRAFT_MAX_TOTAL_SOURCE_BYTES = 512 * 1024;
26850
- FRONTEND_DRAFT_MAX_FILES = 100;
27163
+ init_client();
27164
+ init_auth();
26851
27165
  }
26852
27166
  });
26853
27167
 
26854
- // packages/cli/src/frontend.ts
26855
- var frontend_exports = {};
26856
- __export(frontend_exports, {
26857
- frontendSync: () => frontendSync
27168
+ // packages/cli/src/hosting.ts
27169
+ var hosting_exports = {};
27170
+ __export(hosting_exports, {
27171
+ hostingConfig: () => hostingConfig,
27172
+ hostingDeploy: () => hostingDeploy,
27173
+ hostingInfo: () => hostingInfo,
27174
+ hostingPull: () => hostingPull
26858
27175
  });
26859
- import { readdir as readdir8, readFile as readFile18, stat as stat12 } from "node:fs/promises";
26860
- import { join as join22, relative as relative6, sep as sep2 } from "node:path";
26861
- async function collectFiles(root, dir) {
27176
+ import { readdir as readdir8, readFile as readFile19, stat as stat13 } from "node:fs/promises";
27177
+ import { dirname as dirname14, join as join23, relative as relative6, resolve as resolve14, sep as sep2 } from "node:path";
27178
+ async function open4(paths, options) {
27179
+ const client = await createClient(paths);
27180
+ const project2 = await resolveSlug(resolve14(options.cwd), options.slug);
27181
+ return { client, project: project2 };
27182
+ }
27183
+ async function hostingInfo(paths, options) {
27184
+ const { client, project: project2 } = await open4(paths, options);
27185
+ const body = await client.request(`/api/v1/projects/${project2}/hosting`);
27186
+ return {
27187
+ config: body.config,
27188
+ siteUrl: body.siteUrl,
27189
+ files: body.files ?? []
27190
+ };
27191
+ }
27192
+ async function collectSiteFiles(dir) {
27193
+ const root = resolve14(dir);
26862
27194
  const files = /* @__PURE__ */ new Map();
26863
- const skipped = [];
26864
- const entries = await readdir8(dir, { withFileTypes: true });
26865
- for (const entry of entries) {
26866
- if (entry.isDirectory()) {
26867
- if (IGNORED_DIRS2.has(entry.name)) continue;
26868
- const nested = await collectFiles(root, join22(dir, entry.name));
26869
- for (const [path, content] of nested.files) files.set(path, content);
26870
- skipped.push(...nested.skipped);
26871
- continue;
27195
+ const walk = async (sub) => {
27196
+ let entries;
27197
+ try {
27198
+ entries = await readdir8(sub, { withFileTypes: true });
27199
+ } catch {
27200
+ return;
27201
+ }
27202
+ for (const entry of entries) {
27203
+ const full = join23(sub, entry.name);
27204
+ if (entry.isDirectory()) {
27205
+ await walk(full);
27206
+ } else if (entry.isFile()) {
27207
+ const rel = relative6(root, full).split(sep2).join("/");
27208
+ files.set(rel, full);
27209
+ }
27210
+ }
27211
+ };
27212
+ await walk(root);
27213
+ return files;
27214
+ }
27215
+ async function hostingDeploy(paths, options) {
27216
+ const { client, project: project2 } = await open4(paths, options);
27217
+ const log = options.log ?? ((line) => process.stdout.write(`${line}
27218
+ `));
27219
+ const files = await collectSiteFiles(options.dir);
27220
+ if (files.size === 0) {
27221
+ throw new CliError("NO_SITE_FILES", `\u7AD9\u70B9\u76EE\u5F55\u4E3A\u7A7A\uFF1A${resolve14(options.dir)}`);
27222
+ }
27223
+ const uploaded = [];
27224
+ for (const [rel, full] of files) {
27225
+ log(`[adep] \u4E0A\u4F20 site/${rel}`);
27226
+ const info2 = await stat13(full);
27227
+ const bytes = await readFile19(full);
27228
+ const form = new FormData();
27229
+ form.set("path", `site/${rel}`);
27230
+ form.set("visibility", "public");
27231
+ form.set(
27232
+ "file",
27233
+ new Blob([bytes], { type: contentTypeOf(rel) }),
27234
+ rel.split("/").pop()
27235
+ );
27236
+ await client.upload(`/api/v1/projects/${project2}/files`, form, "HOSTING_UPLOAD_FAILED");
27237
+ uploaded.push({ path: `site/${rel}`, size: info2.size });
27238
+ }
27239
+ const config2 = await client.request(
27240
+ `/api/v1/projects/${project2}/hosting`,
27241
+ {
27242
+ method: "PUT",
27243
+ body: options.spa === void 0 ? { enabled: true } : { enabled: true, spaMode: options.spa }
27244
+ }
27245
+ );
27246
+ const info = await hostingInfo(paths, options);
27247
+ return { config: config2.config, siteUrl: info.siteUrl, uploaded };
27248
+ }
27249
+ async function hostingPull(paths, options) {
27250
+ const { client } = await open4(paths, options);
27251
+ const log = options.log ?? ((line) => process.stdout.write(`${line}
27252
+ `));
27253
+ const info = await hostingInfo(paths, options);
27254
+ const outputDir = resolve14(options.output ?? resolve14(options.cwd));
27255
+ const { mkdir: mkdir15, writeFile: writeFile13 } = await import("node:fs/promises");
27256
+ const files = [];
27257
+ for (const entry of info.files) {
27258
+ if (entry.visibility !== "public" || entry.path === HOSTING_CONFIG_PATH) continue;
27259
+ const url2 = entry.url;
27260
+ if (url2 === void 0 || url2.length === 0) continue;
27261
+ log(`[adep] \u4E0B\u8F7D ${entry.path}`);
27262
+ const response = await client.download(url2, "HOSTING_DOWNLOAD_FAILED");
27263
+ const bytes = Buffer.from(await response.arrayBuffer());
27264
+ const rel = entry.path.replace(/^site\//, "");
27265
+ const target = join23(outputDir, ...rel.split("/"));
27266
+ await mkdir15(dirname14(target), { recursive: true });
27267
+ await writeFile13(target, bytes);
27268
+ files.push({ path: entry.path, size: bytes.length });
27269
+ }
27270
+ return { siteUrl: info.siteUrl, outputDir, files };
27271
+ }
27272
+ async function hostingConfig(paths, options) {
27273
+ const { client, project: project2 } = await open4(paths, options);
27274
+ const body = {};
27275
+ if (options.enabled !== void 0) body["enabled"] = options.enabled;
27276
+ if (options.spa !== void 0) body["spaMode"] = options.spa;
27277
+ const result = await client.request(
27278
+ `/api/v1/projects/${project2}/hosting`,
27279
+ { method: "PUT", body }
27280
+ );
27281
+ return result.config;
27282
+ }
27283
+ var HOSTING_CONFIG_PATH;
27284
+ var init_hosting = __esm({
27285
+ "packages/cli/src/hosting.ts"() {
27286
+ "use strict";
27287
+ init_client();
27288
+ init_auth();
27289
+ init_storage2();
27290
+ HOSTING_CONFIG_PATH = "site/.hosting.json";
27291
+ }
27292
+ });
27293
+
27294
+ // shared/frontend-draft.ts
27295
+ var FRONTEND_DRAFT_FILE_PATH_PATTERN, FRONTEND_DRAFT_MAX_TOTAL_SOURCE_BYTES, FRONTEND_DRAFT_MAX_FILES, FRONTEND_TRANSFORM_EXTENSIONS;
27296
+ var init_frontend_draft = __esm({
27297
+ "shared/frontend-draft.ts"() {
27298
+ "use strict";
27299
+ FRONTEND_DRAFT_FILE_PATH_PATTERN = /^[a-zA-Z0-9._][a-zA-Z0-9._/-]*$/;
27300
+ FRONTEND_DRAFT_MAX_TOTAL_SOURCE_BYTES = 512 * 1024;
27301
+ FRONTEND_DRAFT_MAX_FILES = 100;
27302
+ FRONTEND_TRANSFORM_EXTENSIONS = [
27303
+ ".ts",
27304
+ ".tsx",
27305
+ ".jsx",
27306
+ ".vue",
27307
+ ".scss",
27308
+ ".sass",
27309
+ ".less",
27310
+ ".styl"
27311
+ ];
27312
+ }
27313
+ });
27314
+
27315
+ // packages/cli/src/frontend.ts
27316
+ var frontend_exports = {};
27317
+ __export(frontend_exports, {
27318
+ frontendSync: () => frontendSync,
27319
+ isStaticFrontendDir: () => isStaticFrontendDir
27320
+ });
27321
+ import { readdir as readdir9, readFile as readFile20, stat as stat14 } from "node:fs/promises";
27322
+ import { join as join24, relative as relative7, sep as sep3 } from "node:path";
27323
+ async function collectFiles(root, dir) {
27324
+ const files = /* @__PURE__ */ new Map();
27325
+ const skipped = [];
27326
+ const entries = await readdir9(dir, { withFileTypes: true });
27327
+ for (const entry of entries) {
27328
+ if (entry.isDirectory()) {
27329
+ if (IGNORED_DIRS2.has(entry.name)) continue;
27330
+ const nested = await collectFiles(root, join24(dir, entry.name));
27331
+ for (const [path, content] of nested.files) files.set(path, content);
27332
+ skipped.push(...nested.skipped);
27333
+ continue;
26872
27334
  }
26873
27335
  if (IGNORED_FILES.has(entry.name)) continue;
26874
- const full = join22(dir, entry.name);
26875
- const rel = relative6(root, full).split(sep2).join("/");
26876
- const info = await stat12(full);
27336
+ const full = join24(dir, entry.name);
27337
+ const rel = relative7(root, full).split(sep3).join("/");
27338
+ const info = await stat14(full);
26877
27339
  if (info.size > 1024 * 1024) {
26878
27340
  skipped.push(rel);
26879
27341
  continue;
26880
27342
  }
26881
27343
  try {
26882
- const content = await readFile18(full, "utf8");
27344
+ const content = await readFile20(full, "utf8");
26883
27345
  if (content.includes("\0")) {
26884
27346
  skipped.push(rel);
26885
27347
  continue;
@@ -26894,8 +27356,8 @@ async function collectFiles(root, dir) {
26894
27356
  async function frontendSync(paths, options) {
26895
27357
  const log = options.silent === true ? () => void 0 : options.log ?? ((line) => process.stdout.write(`${line}
26896
27358
  `));
26897
- const webDir = options.dir ?? join22(options.cwd, "web");
26898
- const rootStat = await stat12(webDir).catch(() => null);
27359
+ const webDir = options.dir ?? join24(options.cwd, "web");
27360
+ const rootStat = await stat14(webDir).catch(() => null);
26899
27361
  if (rootStat === null || !rootStat.isDirectory()) {
26900
27362
  throw new CliError(
26901
27363
  "FRONTEND_DIR_MISSING",
@@ -26941,6 +27403,35 @@ async function frontendSync(paths, options) {
26941
27403
  }
26942
27404
  return { projectId: project2.id, uploaded: files.size, skipped, totalBytes };
26943
27405
  }
27406
+ function declaresBuildScript(pkgJson) {
27407
+ if (pkgJson === void 0) return false;
27408
+ let scripts;
27409
+ try {
27410
+ scripts = JSON.parse(pkgJson)["scripts"];
27411
+ } catch {
27412
+ return false;
27413
+ }
27414
+ if (typeof scripts !== "object" || scripts === null || Array.isArray(scripts)) return false;
27415
+ const build = scripts["build"];
27416
+ return typeof build === "string" && build.trim().length > 0;
27417
+ }
27418
+ async function isStaticFrontendDir(dir) {
27419
+ const pkg = await readFile20(join24(dir, "package.json"), "utf8").catch(() => void 0);
27420
+ if (declaresBuildScript(pkg)) return false;
27421
+ const walk = async (sub) => {
27422
+ const entries = await readdir9(sub, { withFileTypes: true });
27423
+ for (const entry of entries) {
27424
+ if (entry.isDirectory()) {
27425
+ if (IGNORED_DIRS2.has(entry.name)) continue;
27426
+ if (!await walk(join24(sub, entry.name))) return false;
27427
+ continue;
27428
+ }
27429
+ if (FRONTEND_TRANSFORM_EXTENSIONS.some((ext) => entry.name.endsWith(ext))) return false;
27430
+ }
27431
+ return true;
27432
+ };
27433
+ return walk(dir);
27434
+ }
26944
27435
  var MAX_FILES, MAX_TOTAL_SOURCE_BYTES2, FILE_PATH_PATTERN, IGNORED_DIRS2, IGNORED_FILES;
26945
27436
  var init_frontend = __esm({
26946
27437
  "packages/cli/src/frontend.ts"() {
@@ -26968,33 +27459,33 @@ var fs_exports = {};
26968
27459
  __export(fs_exports, {
26969
27460
  createExportFileSystem: () => createExportFileSystem
26970
27461
  });
26971
- import { mkdir as mkdir13, readFile as readFile19, rm as rm5, stat as stat14, writeFile as writeFile11 } from "node:fs/promises";
26972
- import { dirname as dirname13, join as join24 } from "node:path";
27462
+ import { mkdir as mkdir14, readFile as readFile21, rm as rm5, stat as stat16, writeFile as writeFile12 } from "node:fs/promises";
27463
+ import { dirname as dirname15, join as join26 } from "node:path";
26973
27464
  function createExportFileSystem() {
26974
27465
  return {
26975
- readFile: (path) => readFile19(path),
26976
- writeFile: (path, content) => writeFile11(path, content),
27466
+ readFile: (path) => readFile21(path),
27467
+ writeFile: (path, content) => writeFile12(path, content),
26977
27468
  // 同时用于清理解压临时目录(${zip}.tmp 是个目录)——递归强制删除,缺失不报错。
26978
27469
  deleteFile: async (path) => {
26979
27470
  await rm5(path, { recursive: true, force: true });
26980
27471
  },
26981
27472
  fileExists: async (path) => {
26982
27473
  try {
26983
- await stat14(path);
27474
+ await stat16(path);
26984
27475
  return true;
26985
27476
  } catch {
26986
27477
  return false;
26987
27478
  }
26988
27479
  },
26989
27480
  mkdir: async (path) => {
26990
- await mkdir13(path, { recursive: true });
27481
+ await mkdir14(path, { recursive: true });
26991
27482
  },
26992
27483
  unzip: async (zipPath, targetDir) => {
26993
- const entries = zipRead(await readFile19(zipPath));
27484
+ const entries = zipRead(await readFile21(zipPath));
26994
27485
  for (const [name, data] of entries) {
26995
- const dest = join24(targetDir, name);
26996
- await mkdir13(dirname13(dest), { recursive: true });
26997
- await writeFile11(dest, data);
27486
+ const dest = join26(targetDir, name);
27487
+ await mkdir14(dirname15(dest), { recursive: true });
27488
+ await writeFile12(dest, data);
26998
27489
  }
26999
27490
  }
27000
27491
  };
@@ -27237,122 +27728,9 @@ ${detail}`);
27237
27728
  }
27238
27729
  });
27239
27730
 
27240
- // packages/cli/src/storage.ts
27241
- var storage_exports = {};
27242
- __export(storage_exports, {
27243
- contentTypeOf: () => contentTypeOf,
27244
- storageDownload: () => storageDownload,
27245
- storageList: () => storageList,
27246
- storageRemove: () => storageRemove,
27247
- storageUpload: () => storageUpload
27248
- });
27249
- import { mkdir as mkdir14, readFile as readFile20, stat as stat15, writeFile as writeFile12 } from "node:fs/promises";
27250
- import { basename as basename5, dirname as dirname14, extname as extname2, join as join25, resolve as resolve14 } from "node:path";
27251
- async function open3(paths, options) {
27252
- const client = await createClient(paths);
27253
- const project2 = await resolveSlug(resolve14(options.cwd), options.slug);
27254
- return { client, project: project2 };
27255
- }
27256
- function contentTypeOf(path) {
27257
- const map2 = {
27258
- ".html": "text/html; charset=utf-8",
27259
- ".htm": "text/html; charset=utf-8",
27260
- ".css": "text/css; charset=utf-8",
27261
- ".js": "text/javascript; charset=utf-8",
27262
- ".mjs": "text/javascript; charset=utf-8",
27263
- ".json": "application/json; charset=utf-8",
27264
- ".png": "image/png",
27265
- ".jpg": "image/jpeg",
27266
- ".jpeg": "image/jpeg",
27267
- ".gif": "image/gif",
27268
- ".svg": "image/svg+xml",
27269
- ".webp": "image/webp",
27270
- ".ico": "image/x-icon",
27271
- ".txt": "text/plain; charset=utf-8",
27272
- ".md": "text/markdown; charset=utf-8",
27273
- ".xml": "application/xml",
27274
- ".wasm": "application/wasm",
27275
- ".pdf": "application/pdf",
27276
- ".zip": "application/zip",
27277
- ".woff": "font/woff",
27278
- ".woff2": "font/woff2",
27279
- ".ttf": "font/ttf",
27280
- ".otf": "font/otf"
27281
- };
27282
- return map2[extname2(path).toLowerCase()] ?? "application/octet-stream";
27283
- }
27284
- async function storageUpload(paths, options) {
27285
- const { client, project: project2 } = await open3(paths, options);
27286
- const local = resolve14(options.file);
27287
- const info = await stat15(local).catch(() => null);
27288
- if (info === null || !info.isFile()) {
27289
- throw new CliError("FILE_NOT_FOUND", `\u672C\u5730\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${local}`);
27290
- }
27291
- const visibility = options.visibility ?? "private";
27292
- const bytes = await readFile20(local);
27293
- const form = new FormData();
27294
- form.set("path", options.path);
27295
- form.set("visibility", visibility);
27296
- form.set(
27297
- "file",
27298
- new Blob([bytes], { type: contentTypeOf(options.path) }),
27299
- basename5(local)
27300
- );
27301
- const response = await client.upload(
27302
- `/api/v1/projects/${project2}/files`,
27303
- form,
27304
- "STORAGE_UPLOAD_FAILED"
27305
- );
27306
- const body = await response.json();
27307
- return { ...body.file, ...body.signedUrl === void 0 ? {} : { signedUrl: body.signedUrl } };
27308
- }
27309
- async function storageList(paths, options) {
27310
- const { client, project: project2 } = await open3(paths, options);
27311
- const query = options.prefix === void 0 ? "" : `?prefix=${encodeURIComponent(options.prefix)}`;
27312
- const body = await client.request(
27313
- `/api/v1/projects/${project2}/files${query}`
27314
- );
27315
- return { project: project2, files: body.files };
27316
- }
27317
- async function resolveDownloadUrl(client, project2, path) {
27318
- const body = await client.request(
27319
- `/api/v1/projects/${project2}/files?prefix=${encodeURIComponent(path)}`
27320
- );
27321
- const entry = body.files.find((file2) => file2.path === path);
27322
- const url2 = entry?.url ?? entry?.signedUrl;
27323
- if (entry === void 0 || url2 === void 0 || url2.length === 0) {
27324
- throw new CliError("STORAGE_NOT_FOUND", `\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${path}`);
27325
- }
27326
- return url2;
27327
- }
27328
- async function storageDownload(paths, options) {
27329
- const { client, project: project2 } = await open3(paths, options);
27330
- const url2 = await resolveDownloadUrl(client, project2, options.path);
27331
- const response = await client.download(url2, "STORAGE_DOWNLOAD_FAILED");
27332
- const bytes = Buffer.from(await response.arrayBuffer());
27333
- const output = resolve14(options.output ?? join25(resolve14(options.cwd), basename5(options.path)));
27334
- await mkdir14(dirname14(output), { recursive: true });
27335
- await writeFile12(output, bytes);
27336
- return { path: options.path, output, size: bytes.length };
27337
- }
27338
- async function storageRemove(paths, options) {
27339
- const { client, project: project2 } = await open3(paths, options);
27340
- return client.request(
27341
- `/api/v1/projects/${project2}/files/${encodeURIComponent(options.path)}`,
27342
- { method: "DELETE" }
27343
- );
27344
- }
27345
- var init_storage2 = __esm({
27346
- "packages/cli/src/storage.ts"() {
27347
- "use strict";
27348
- init_client();
27349
- init_auth();
27350
- }
27351
- });
27352
-
27353
27731
  // packages/cli/src/sandbox-scan.ts
27354
- import { readdir as readdir9, readFile as readFile21 } from "node:fs/promises";
27355
- import { join as join26, relative as relative7, sep as sep3 } from "node:path";
27732
+ import { readdir as readdir10, readFile as readFile22 } from "node:fs/promises";
27733
+ import { join as join27, relative as relative8, sep as sep4 } from "node:path";
27356
27734
  function extractSpecifiers(line) {
27357
27735
  const out = [];
27358
27736
  const patterns = [
@@ -27396,17 +27774,17 @@ function classify(specifier) {
27396
27774
  return null;
27397
27775
  }
27398
27776
  async function scanFunctionSources(rootDir, functionsDir) {
27399
- const base = join26(rootDir, functionsDir);
27777
+ const base = join27(rootDir, functionsDir);
27400
27778
  const findings = [];
27401
27779
  async function walk(current) {
27402
27780
  let entries;
27403
27781
  try {
27404
- entries = await readdir9(current, { withFileTypes: true });
27782
+ entries = await readdir10(current, { withFileTypes: true });
27405
27783
  } catch {
27406
27784
  return;
27407
27785
  }
27408
27786
  for (const entry of entries) {
27409
- const abs = join26(current, entry.name);
27787
+ const abs = join27(current, entry.name);
27410
27788
  if (entry.isDirectory()) {
27411
27789
  if (SKIP_DIRS.has(entry.name)) continue;
27412
27790
  await walk(abs);
@@ -27417,12 +27795,12 @@ async function scanFunctionSources(rootDir, functionsDir) {
27417
27795
  if (entry.name.endsWith(".d.ts")) continue;
27418
27796
  let content;
27419
27797
  try {
27420
- content = await readFile21(abs, "utf8");
27798
+ content = await readFile22(abs, "utf8");
27421
27799
  } catch {
27422
27800
  continue;
27423
27801
  }
27424
27802
  if (content.length > MAX_SCAN_BYTES) continue;
27425
- const relPath = relative7(rootDir, abs).split(sep3).join("/");
27803
+ const relPath = relative8(rootDir, abs).split(sep4).join("/");
27426
27804
  const lines = content.split("\n");
27427
27805
  for (const [index, line] of lines.entries()) {
27428
27806
  const trimmed = line.trim();
@@ -27539,7 +27917,7 @@ __export(doctor_exports, {
27539
27917
  formatDoctorReport: () => formatDoctorReport,
27540
27918
  runDoctor: () => runDoctor
27541
27919
  });
27542
- import { stat as stat16 } from "node:fs/promises";
27920
+ import { stat as stat17 } from "node:fs/promises";
27543
27921
  async function probeServer(server) {
27544
27922
  const controller = new AbortController();
27545
27923
  const timer = setTimeout(() => controller.abort(), SERVER_PROBE_TIMEOUT_MS);
@@ -27557,7 +27935,7 @@ async function probeServer(server) {
27557
27935
  }
27558
27936
  async function credentialMode(file2) {
27559
27937
  try {
27560
- const info = await stat16(file2);
27938
+ const info = await stat17(file2);
27561
27939
  return (info.mode & 511).toString(8).padStart(3, "0");
27562
27940
  } catch {
27563
27941
  return void 0;
@@ -27688,7 +28066,7 @@ __export(mcp_exports, {
27688
28066
  mcpPublish: () => mcpPublish,
27689
28067
  mcpUnpublish: () => mcpUnpublish
27690
28068
  });
27691
- import { resolve as resolve15 } from "node:path";
28069
+ import { resolve as resolve16 } from "node:path";
27692
28070
  async function mcpPublish(paths, options) {
27693
28071
  const fn = requireFunctionName(options.fn);
27694
28072
  const client = await createClient(paths);
@@ -27769,7 +28147,7 @@ function requireFunctionName(fn) {
27769
28147
  return fn.trim();
27770
28148
  }
27771
28149
  async function resolveProject(client, options) {
27772
- const slug = await resolveSlug(resolve15(options.cwd), options.slug);
28150
+ const slug = await resolveSlug(resolve16(options.cwd), options.slug);
27773
28151
  const listed = await client.request("/api/v1/projects", {}, "PROJECT_LIST_FAILED");
27774
28152
  const match = listed.projects.find((project2) => project2.slug === slug);
27775
28153
  if (match === void 0) {
@@ -27954,7 +28332,7 @@ __export(functions_exports, {
27954
28332
  functionsList: () => functionsList,
27955
28333
  functionsLogs: () => functionsLogs
27956
28334
  });
27957
- import { resolve as resolve16 } from "node:path";
28335
+ import { resolve as resolve17 } from "node:path";
27958
28336
  async function functionsList(paths, options) {
27959
28337
  const client = await createClient(paths);
27960
28338
  const project2 = await resolveProject2(client, options);
@@ -27996,7 +28374,7 @@ async function functionsLogs(paths, options) {
27996
28374
  return { functionId: target.id, name: target.name, logs: result.logs };
27997
28375
  }
27998
28376
  async function resolveProject2(client, options) {
27999
- const slug = await resolveSlug(resolve16(options.cwd), options.slug);
28377
+ const slug = await resolveSlug(resolve17(options.cwd), options.slug);
28000
28378
  const projects = await projectsListFrom(client);
28001
28379
  const match = projects.find((project2) => project2.slug === slug);
28002
28380
  if (match === void 0) {
@@ -28019,132 +28397,6 @@ var init_functions = __esm({
28019
28397
  }
28020
28398
  });
28021
28399
 
28022
- // packages/cli/src/hosting.ts
28023
- var hosting_exports = {};
28024
- __export(hosting_exports, {
28025
- hostingConfig: () => hostingConfig,
28026
- hostingDeploy: () => hostingDeploy,
28027
- hostingInfo: () => hostingInfo,
28028
- hostingPull: () => hostingPull
28029
- });
28030
- import { readdir as readdir10, readFile as readFile22, stat as stat17 } from "node:fs/promises";
28031
- import { dirname as dirname15, join as join27, relative as relative8, resolve as resolve17, sep as sep4 } from "node:path";
28032
- async function open4(paths, options) {
28033
- const client = await createClient(paths);
28034
- const project2 = await resolveSlug(resolve17(options.cwd), options.slug);
28035
- return { client, project: project2 };
28036
- }
28037
- async function hostingInfo(paths, options) {
28038
- const { client, project: project2 } = await open4(paths, options);
28039
- const body = await client.request(`/api/v1/projects/${project2}/hosting`);
28040
- return {
28041
- config: body.config,
28042
- siteUrl: body.siteUrl,
28043
- files: body.files ?? []
28044
- };
28045
- }
28046
- async function collectSiteFiles(dir) {
28047
- const root = resolve17(dir);
28048
- const files = /* @__PURE__ */ new Map();
28049
- const walk = async (sub) => {
28050
- let entries;
28051
- try {
28052
- entries = await readdir10(sub, { withFileTypes: true });
28053
- } catch {
28054
- return;
28055
- }
28056
- for (const entry of entries) {
28057
- const full = join27(sub, entry.name);
28058
- if (entry.isDirectory()) {
28059
- await walk(full);
28060
- } else if (entry.isFile()) {
28061
- const rel = relative8(root, full).split(sep4).join("/");
28062
- files.set(rel, full);
28063
- }
28064
- }
28065
- };
28066
- await walk(root);
28067
- return files;
28068
- }
28069
- async function hostingDeploy(paths, options) {
28070
- const { client, project: project2 } = await open4(paths, options);
28071
- const log = options.log ?? ((line) => process.stdout.write(`${line}
28072
- `));
28073
- const files = await collectSiteFiles(options.dir);
28074
- if (files.size === 0) {
28075
- throw new CliError("NO_SITE_FILES", `\u7AD9\u70B9\u76EE\u5F55\u4E3A\u7A7A\uFF1A${resolve17(options.dir)}`);
28076
- }
28077
- const uploaded = [];
28078
- for (const [rel, full] of files) {
28079
- log(`[adep] \u4E0A\u4F20 site/${rel}`);
28080
- const info2 = await stat17(full);
28081
- const bytes = await readFile22(full);
28082
- const form = new FormData();
28083
- form.set("path", `site/${rel}`);
28084
- form.set("visibility", "public");
28085
- form.set(
28086
- "file",
28087
- new Blob([bytes], { type: contentTypeOf(rel) }),
28088
- rel.split("/").pop()
28089
- );
28090
- await client.upload(`/api/v1/projects/${project2}/files`, form, "HOSTING_UPLOAD_FAILED");
28091
- uploaded.push({ path: `site/${rel}`, size: info2.size });
28092
- }
28093
- const config2 = await client.request(
28094
- `/api/v1/projects/${project2}/hosting`,
28095
- {
28096
- method: "PUT",
28097
- body: options.spa === void 0 ? { enabled: true } : { enabled: true, spaMode: options.spa }
28098
- }
28099
- );
28100
- const info = await hostingInfo(paths, options);
28101
- return { config: config2.config, siteUrl: info.siteUrl, uploaded };
28102
- }
28103
- async function hostingPull(paths, options) {
28104
- const { client } = await open4(paths, options);
28105
- const log = options.log ?? ((line) => process.stdout.write(`${line}
28106
- `));
28107
- const info = await hostingInfo(paths, options);
28108
- const outputDir = resolve17(options.output ?? resolve17(options.cwd));
28109
- const { mkdir: mkdir15, writeFile: writeFile13 } = await import("node:fs/promises");
28110
- const files = [];
28111
- for (const entry of info.files) {
28112
- if (entry.visibility !== "public" || entry.path === HOSTING_CONFIG_PATH) continue;
28113
- const url2 = entry.url;
28114
- if (url2 === void 0 || url2.length === 0) continue;
28115
- log(`[adep] \u4E0B\u8F7D ${entry.path}`);
28116
- const response = await client.download(url2, "HOSTING_DOWNLOAD_FAILED");
28117
- const bytes = Buffer.from(await response.arrayBuffer());
28118
- const rel = entry.path.replace(/^site\//, "");
28119
- const target = join27(outputDir, ...rel.split("/"));
28120
- await mkdir15(dirname15(target), { recursive: true });
28121
- await writeFile13(target, bytes);
28122
- files.push({ path: entry.path, size: bytes.length });
28123
- }
28124
- return { siteUrl: info.siteUrl, outputDir, files };
28125
- }
28126
- async function hostingConfig(paths, options) {
28127
- const { client, project: project2 } = await open4(paths, options);
28128
- const body = {};
28129
- if (options.enabled !== void 0) body["enabled"] = options.enabled;
28130
- if (options.spa !== void 0) body["spaMode"] = options.spa;
28131
- const result = await client.request(
28132
- `/api/v1/projects/${project2}/hosting`,
28133
- { method: "PUT", body }
28134
- );
28135
- return result.config;
28136
- }
28137
- var HOSTING_CONFIG_PATH;
28138
- var init_hosting = __esm({
28139
- "packages/cli/src/hosting.ts"() {
28140
- "use strict";
28141
- init_client();
28142
- init_auth();
28143
- init_storage2();
28144
- HOSTING_CONFIG_PATH = "site/.hosting.json";
28145
- }
28146
- });
28147
-
28148
28400
  // packages/cli/src/cli.ts
28149
28401
  init_config();
28150
28402
  import { Command } from "commander";
@@ -28253,7 +28505,7 @@ function createCliContext(deps) {
28253
28505
  init_auth();
28254
28506
  init_config();
28255
28507
  function registerAuth(program2, ctx) {
28256
- program2.command("login").description("\u767B\u5F55\u5E73\u53F0\uFF1A\u7F3A\u7701\u6253\u5F00\u6D4F\u89C8\u5668\u7528\u7F51\u9875\u6388\u6743\u767B\u5F55\uFF1B-e/-p \u8D70\u90AE\u7BB1\u5BC6\u7801\u76F4\u767B\uFF08CI / \u65E0\u6D4F\u89C8\u5668\uFF09").option("-s, --server <url>", "\u5E73\u53F0\u5730\u5740\uFF08\u7F3A\u7701\u8BFB\u53D6 ADEP_SERVER \u6216 https://adep.jajabjbj.top\uFF09").option("-e, --email <email>", "\u767B\u5F55\u90AE\u7BB1\uFF08\u4E0E -p \u4E00\u8D77\u8D70\u5BC6\u7801\u76F4\u767B\uFF0C\u4E0D\u53D1\u8D77\u6D4F\u89C8\u5668\u6D41\u7A0B\uFF09").option("-p, --password <password>", "\u767B\u5F55\u5BC6\u7801\uFF08\u6CE8\u610F shell \u5386\u53F2\uFF1B\u7F3A\u7701\u4EA4\u4E92\u8F93\u5165\uFF09").option("--no-browser", "\u4E0D\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF1A\u53EA\u6253\u5370\u9A8C\u8BC1\u7801\u4E0E\u94FE\u63A5\uFF0C\u7531\u4F60\u624B\u5DE5\u8BBF\u95EE\uFF08SSH / \u65E0\u684C\u9762\uFF09").action(
28508
+ program2.command("login").description("\u767B\u5F55\u5E73\u53F0\uFF1A\u7F3A\u7701\u6253\u5F00\u6D4F\u89C8\u5668\u7528\u7F51\u9875\u6388\u6743\u767B\u5F55\uFF1B-e/-p \u8D70\u90AE\u7BB1\u5BC6\u7801\u76F4\u767B\uFF08CI / \u65E0\u6D4F\u89C8\u5668\uFF09").option("-s, --server <url>", "\u5E73\u53F0\u5730\u5740\uFF08\u7F3A\u7701\u8BFB\u53D6 ADEP_SERVER \u6216 https://adep.top\uFF09").option("-e, --email <email>", "\u767B\u5F55\u90AE\u7BB1\uFF08\u4E0E -p \u4E00\u8D77\u8D70\u5BC6\u7801\u76F4\u767B\uFF0C\u4E0D\u53D1\u8D77\u6D4F\u89C8\u5668\u6D41\u7A0B\uFF09").option("-p, --password <password>", "\u767B\u5F55\u5BC6\u7801\uFF08\u6CE8\u610F shell \u5386\u53F2\uFF1B\u7F3A\u7701\u4EA4\u4E92\u8F93\u5165\uFF09").option("--no-browser", "\u4E0D\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF1A\u53EA\u6253\u5370\u9A8C\u8BC1\u7801\u4E0E\u94FE\u63A5\uFF0C\u7531\u4F60\u624B\u5DE5\u8BBF\u95EE\uFF08SSH / \u65E0\u684C\u9762\uFF09").action(
28257
28509
  async (flags) => {
28258
28510
  const command = ctx.io("login");
28259
28511
  await command.run(async () => {
@@ -28680,7 +28932,10 @@ async function writeOfflineTree(shellDir, collected) {
28680
28932
  function readFunctionsIndex(entries) {
28681
28933
  const raw = entries.get(OFFLINE_BUNDLE_PATHS.functionsIndex);
28682
28934
  if (raw === void 0) {
28683
- throw new InitError("APP_OFFLINE_BUNDLE_INVALID", "\u79BB\u7EBF\u5305\u7F3A\u5C11 functions/index.json\uFF08\u4EA7\u7269\u5DF2\u635F\u574F\uFF09");
28935
+ throw new InitError(
28936
+ "APP_OFFLINE_BUNDLE_INVALID",
28937
+ "\u79BB\u7EBF\u5305\u7F3A\u5C11 functions/index.json\uFF08\u4EA7\u7269\u5DF2\u635F\u574F\uFF09"
28938
+ );
28684
28939
  }
28685
28940
  let parsed;
28686
28941
  try {
@@ -28693,7 +28948,10 @@ function readFunctionsIndex(entries) {
28693
28948
  }
28694
28949
  const body = parsed;
28695
28950
  if (!Array.isArray(body.functions)) {
28696
- throw new InitError("APP_OFFLINE_BUNDLE_INVALID", "\u79BB\u7EBF\u5305 functions/index.json \u7F3A\u5C11 functions \u6570\u7EC4");
28951
+ throw new InitError(
28952
+ "APP_OFFLINE_BUNDLE_INVALID",
28953
+ "\u79BB\u7EBF\u5305 functions/index.json \u7F3A\u5C11 functions \u6570\u7EC4"
28954
+ );
28697
28955
  }
28698
28956
  return body.functions.map((entry, index) => {
28699
28957
  if (typeof entry.name !== "string" || entry.name === "") {
@@ -28728,7 +28986,9 @@ async function waitForOfflineBuild(api, projectId, jobId, pollIntervalMs, maxPol
28728
28986
  }
28729
28987
  }
28730
28988
  function offlineBundleFingerprint(manifest) {
28731
- const entries = [...manifest.contents].toSorted((left, right) => left.path.localeCompare(right.path));
28989
+ const entries = [...manifest.contents].toSorted(
28990
+ (left, right) => compareByCodeUnit(left.path, right.path)
28991
+ );
28732
28992
  return createHash3("sha256").update(entries.map((content) => `${content.path}:${content.sha256}`).join("\n")).digest("hex").slice(0, 12);
28733
28993
  }
28734
28994
  async function buildOfflineApp(options, deps) {
@@ -28865,7 +29125,10 @@ async function createAppOfflineBuildApi(paths, cwd) {
28865
29125
  );
28866
29126
  const downloadUrl = envelope.downloadUrl;
28867
29127
  if (typeof downloadUrl !== "string" || downloadUrl.length === 0) {
28868
- throw new CliError("APP_OFFLINE_BUNDLE_UNAVAILABLE", "\u79BB\u7EBF\u5305\u4E0B\u8F7D URL \u4E3A\u7A7A\uFF0C\u4EA7\u7269\u53EF\u80FD\u5C1A\u4E0D\u53EF\u7528");
29128
+ throw new CliError(
29129
+ "APP_OFFLINE_BUNDLE_UNAVAILABLE",
29130
+ "\u79BB\u7EBF\u5305\u4E0B\u8F7D URL \u4E3A\u7A7A\uFF0C\u4EA7\u7269\u53EF\u80FD\u5C1A\u4E0D\u53EF\u7528"
29131
+ );
28869
29132
  }
28870
29133
  const response = await client.download(downloadUrl, "APP_OFFLINE_BUILD_DOWNLOAD_FAILED");
28871
29134
  const bytes = Buffer.from(await response.arrayBuffer());
@@ -28915,7 +29178,7 @@ function registerApp(program2, ctx) {
28915
29178
  const app = program2.command("app").description("\u684C\u9762 / \u79FB\u52A8\u5E94\u7528\u58F3\u5DE5\u7A0B\uFF08\u5F53\u524D\u652F\u6301\uFF1Ainit / build\uFF09");
28916
29179
  app.command("init").description("\u751F\u6210\u58F3\u5DE5\u7A0B\uFF1A--platform desktop\uFF08\u7F3A\u7701\uFF0CElectron\uFF09| mobile\uFF08Capacitor \u79FB\u52A8\u58F3\uFF09").requiredOption("-p, --project <slug>", "\u5E73\u53F0\u9879\u76EE slug\uFF08\u5FC5\u586B\uFF1B\u4E91\u51FD\u6570\u7ECF\u8BE5\u9879\u76EE\u7684 /api/* \u6267\u884C\uFF09").requiredOption("-n, --name <\u5E94\u7528\u540D>", "\u5E94\u7528\u663E\u793A\u540D\uFF08\u5FC5\u586B\uFF1B\u7A97\u53E3\u6807\u9898 / \u5B89\u88C5\u5305 productName / \u79FB\u52A8\u7AEF\u663E\u793A\u540D\uFF09").option("--dir <\u76EE\u5F55>", "\u76EE\u6807\u76EE\u5F55\uFF08\u7F3A\u7701 ./<slug>-app\uFF09").option("--platform <\u58F3>", "desktop\uFF08\u7F3A\u7701\uFF0CElectron \u684C\u9762\u58F3\uFF09| mobile\uFF08Capacitor \u79FB\u52A8\u58F3\uFF0CAPP-009\uFF09").option(
28917
29180
  "-s, --server <url>",
28918
- "\u5E73\u53F0\u5730\u5740\uFF08\u7F3A\u7701\u5F53\u524D\u767B\u5F55\u5E73\u53F0\uFF0C\u6216 ADEP_SERVER / https://adep.jajabjbj.top\uFF09"
29181
+ "\u5E73\u53F0\u5730\u5740\uFF08\u7F3A\u7701\u5F53\u524D\u767B\u5F55\u5E73\u53F0\uFF0C\u6216 ADEP_SERVER / https://adep.top\uFF09"
28919
29182
  ).action(
28920
29183
  async (flags) => {
28921
29184
  const command = ctx.io("app init");
@@ -29830,10 +30093,10 @@ function registerDevServers(program2, ctx) {
29830
30093
  init_auth();
29831
30094
  init_client();
29832
30095
  init_deploy();
29833
- import { stat as stat13 } from "node:fs/promises";
29834
- import { join as join23, resolve as resolve13 } from "node:path";
30096
+ import { stat as stat15 } from "node:fs/promises";
30097
+ import { join as join25, resolve as resolve15 } from "node:path";
29835
30098
  async function resolveProjectId2(client, cwd, slug) {
29836
- const resolvedSlug = await resolveSlug(resolve13(cwd), slug);
30099
+ const resolvedSlug = await resolveSlug(resolve15(cwd), slug);
29837
30100
  const listed = await client.request("/api/v1/projects", {}, "PROJECT_LIST_FAILED");
29838
30101
  const match = listed.projects.find((project2) => project2.slug === resolvedSlug);
29839
30102
  if (match === void 0) {
@@ -29868,6 +30131,29 @@ async function publishFrontend(paths, options) {
29868
30131
  siteUrl: versions.siteUrl
29869
30132
  };
29870
30133
  }
30134
+ async function publishStaticFrontend(paths, options) {
30135
+ const webDir = join25(options.cwd, "web");
30136
+ const indexStat = await stat15(join25(webDir, "index.html")).catch(() => null);
30137
+ if (indexStat === null || !indexStat.isFile()) {
30138
+ throw new CliError(
30139
+ "FRONTEND_NO_PAGE",
30140
+ `\u7EAF\u9759\u6001\u53D1\u5E03\u7F3A\u5C11\u7AD9\u70B9\u5165\u53E3\uFF1A${webDir}/index.html \u4E0D\u5B58\u5728\uFF08\u6784\u5EFA\u578B\u5DE5\u7A0B\u8BF7\u5728 web/package.json \u58F0\u660E scripts.build\uFF09`
30141
+ );
30142
+ }
30143
+ const { hostingDeploy: hostingDeploy2 } = await Promise.resolve().then(() => (init_hosting(), hosting_exports));
30144
+ const result = await hostingDeploy2(paths, {
30145
+ cwd: options.cwd,
30146
+ dir: webDir,
30147
+ ...options.slug === void 0 ? {} : { slug: options.slug },
30148
+ ...options.log === void 0 ? {} : { log: options.log }
30149
+ });
30150
+ return {
30151
+ mode: "static",
30152
+ siteUrl: result.siteUrl,
30153
+ uploaded: result.uploaded.length,
30154
+ spaMode: result.config.spaMode
30155
+ };
30156
+ }
29871
30157
  async function publishFunctions(paths, options) {
29872
30158
  const startedAt = Date.now();
29873
30159
  const result = await deploy(paths, {
@@ -29899,23 +30185,40 @@ async function runPublish(paths, io, cwd, flags) {
29899
30185
  });
29900
30186
  }
29901
30187
  if (wantFrontend) {
29902
- const webDir = join23(cwd, "web");
29903
- const webStat = await stat13(webDir).catch(() => null);
30188
+ const webDir = join25(cwd, "web");
30189
+ const webStat = await stat15(webDir).catch(() => null);
29904
30190
  if (webStat !== null && webStat.isDirectory()) {
29905
- const { frontendSync: frontendSync2 } = await Promise.resolve().then(() => (init_frontend(), frontend_exports));
29906
- await frontendSync2(paths, {
30191
+ const { isStaticFrontendDir: isStaticFrontendDir2 } = await Promise.resolve().then(() => (init_frontend(), frontend_exports));
30192
+ if (await isStaticFrontendDir2(webDir)) {
30193
+ result.frontend = await publishStaticFrontend(paths, {
30194
+ cwd,
30195
+ ...flags.project === void 0 ? {} : { slug: flags.project },
30196
+ silent: io.json,
30197
+ log: (line) => io.line(line)
30198
+ });
30199
+ } else {
30200
+ const { frontendSync: frontendSync2 } = await Promise.resolve().then(() => (init_frontend(), frontend_exports));
30201
+ await frontendSync2(paths, {
30202
+ cwd,
30203
+ ...flags.project === void 0 ? {} : { slug: flags.project },
30204
+ silent: io.json,
30205
+ log: (line) => io.line(line)
30206
+ });
30207
+ result.frontend = await publishFrontend(paths, {
30208
+ cwd,
30209
+ ...flags.project === void 0 ? {} : { slug: flags.project },
30210
+ silent: io.json,
30211
+ log: (line) => io.line(line)
30212
+ });
30213
+ }
30214
+ } else {
30215
+ result.frontend = await publishFrontend(paths, {
29907
30216
  cwd,
29908
30217
  ...flags.project === void 0 ? {} : { slug: flags.project },
29909
30218
  silent: io.json,
29910
30219
  log: (line) => io.line(line)
29911
30220
  });
29912
30221
  }
29913
- result.frontend = await publishFrontend(paths, {
29914
- cwd,
29915
- ...flags.project === void 0 ? {} : { slug: flags.project },
29916
- silent: io.json,
29917
- log: (line) => io.line(line)
29918
- });
29919
30222
  }
29920
30223
  return result;
29921
30224
  }
@@ -29938,15 +30241,21 @@ function renderPublish(data) {
29938
30241
  }
29939
30242
  if (result.frontend !== void 0) {
29940
30243
  const fe = result.frontend;
29941
- const status = fe.reused ? `\uFF08\u590D\u7528 v${fe.version}\uFF0C\u65E0\u53D8\u66F4\uFF09` : `v${fe.version}`;
29942
- lines.push(`\u2713 frontend built ${status} \xB7 ${fe.siteUrl}`);
30244
+ if (fe.mode === "static") {
30245
+ lines.push(
30246
+ `\u2713 frontend published\uFF08\u9759\u6001\u76F4\u901A ${fe.uploaded} \u4E2A\u6587\u4EF6\uFF0CSPA \u56DE\u9000 ${fe.spaMode ? "\u5F00" : "\u5173"}\uFF09 \xB7 ${fe.siteUrl}`
30247
+ );
30248
+ } else {
30249
+ const status = fe.reused ? `\uFF08\u590D\u7528 v${fe.version}\uFF0C\u65E0\u53D8\u66F4\uFF09` : `v${fe.version}`;
30250
+ lines.push(`\u2713 frontend built ${status} \xB7 ${fe.siteUrl}`);
30251
+ }
29943
30252
  }
29944
30253
  return lines;
29945
30254
  }
29946
30255
  function registerPublish(program2, ctx) {
29947
30256
  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(
29948
30257
  "--only <scope>",
29949
- "\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"
30258
+ "\u4EC5\u53D1\u5E03\u4E00\u4FA7\uFF1Afunctions\uFF08\u53EA\u90E8\u7F72\u4E91\u51FD\u6570\uFF09| frontend\uFF08\u53EA\u6784\u5EFA\u6258\u7BA1\u524D\u7AEF\uFF1B\u7EAF\u9759\u6001\u7AD9\u81EA\u52A8\u76F4\u901A\u6258\u7BA1\u901A\u9053\uFF09\uFF1B\u7F3A\u7701\u5168\u6808\u53D1\u5E03"
29950
30259
  ).option("-p, --project <slug>", "\u76EE\u6807\u5E73\u53F0\u9879\u76EE slug\uFF08\u7F3A\u7701\u53D6 adep.config.ts \u7684 name\uFF09").option(
29951
30260
  "--force",
29952
30261
  "\u653E\u884C warn \u7EA7\u5BC6\u94A5\u5F15\u7528\u547D\u4E2D\uFF08FN-013\uFF1B\u6E90\u7801\u5F15\u7528\u4E86\u5DF2\u914D\u7F6E\u7684 secret \u73AF\u5883\u53D8\u91CF\u540D\u65F6\u53D1\u5E03\u88AB\u963B\u65AD\uFF0C\u786E\u8BA4\u975E\u6CC4\u6F0F\u540E\u7528\u672C\u65D7\u6807\u653E\u884C\uFF0C\u670D\u52A1\u7AEF\u843D\u5BA1\u8BA1\uFF09"