@adep/cli 0.4.6 → 0.4.11

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/vite.js CHANGED
@@ -1090,6 +1090,20 @@ var CLOUD_DB_SPEC = {
1090
1090
  };
1091
1091
  var WRITE_TERMINALS = /* @__PURE__ */ new Set(["insert", "insertMany", "update", "delete"]);
1092
1092
  function errorWithCode(error) {
1093
+ if (error instanceof Error) {
1094
+ const sqlite = /no such table: (\S+)/.exec(error.message);
1095
+ if (sqlite !== null) {
1096
+ return new Error(
1097
+ `[DB_TABLE_MISSING] \u9879\u76EE\u5E93\u5DF2\u542F\u52A8\u4F46\u7F3A\u8868 "${sqlite[1]}"\uFF1A\u8BF7\u6267\u884C adep db migrate <schema.sql> \u5EFA\u8868\uFF08\u53D1\u5E03\u4E0D\u542B\u5EFA\u8868\uFF09\u3002\u539F\u59CB\u9519\u8BEF\uFF1A${error.message}`
1098
+ );
1099
+ }
1100
+ const pg = /relation "([^"]+)" does not exist/.exec(error.message);
1101
+ if (pg !== null) {
1102
+ return new Error(
1103
+ `[DB_TABLE_MISSING] \u9879\u76EE\u5E93\u5DF2\u542F\u52A8\u4F46\u7F3A\u8868\uFF08\u6216\u5173\u7CFB\uFF09"${pg[1]}"\uFF1A\u8BF7\u6267\u884C adep db migrate <schema.sql> \u5EFA\u8868\uFF08\u53D1\u5E03\u4E0D\u542B\u5EFA\u8868\uFF09\u3002\u539F\u59CB\u9519\u8BEF\uFF1A${error.message}`
1104
+ );
1105
+ }
1106
+ }
1093
1107
  const code = typeof error === "object" && error !== null && typeof error.code === "string" ? error.code : void 0;
1094
1108
  if (code !== void 0 && error instanceof Error) {
1095
1109
  return new Error(`[${code}] ${error.message}`);
@@ -2742,7 +2756,7 @@ async function createSimRuntime(options) {
2742
2756
  import { readFile as readFile3 } from "node:fs/promises";
2743
2757
  import { join as join5, relative, resolve as resolve3 } from "node:path";
2744
2758
 
2745
- // packages/cli/src/db.ts
2759
+ // packages/runtime/src/shared/sql-split.ts
2746
2760
  function splitSqlStatements(source) {
2747
2761
  const statements = [];
2748
2762
  let buffer = "";
@@ -2751,12 +2765,13 @@ function splitSqlStatements(source) {
2751
2765
  for (const rawLine of lines) {
2752
2766
  const trimmed = rawLine.trim();
2753
2767
  if (!inQuote && (trimmed.length === 0 || trimmed.startsWith("--"))) continue;
2754
- for (let i = 0; i < rawLine.length; i++) {
2755
- const ch = rawLine[i];
2768
+ const scanLine = inQuote ? rawLine : trimmed;
2769
+ for (let i = 0; i < scanLine.length; i++) {
2770
+ const ch = scanLine[i];
2756
2771
  if (inQuote) {
2757
2772
  if (ch === "'") {
2758
- if (rawLine[i + 1] === "'") {
2759
- buffer += ch + rawLine[i + 1];
2773
+ if (scanLine[i + 1] === "'") {
2774
+ buffer += ch + scanLine[i + 1];
2760
2775
  i++;
2761
2776
  continue;
2762
2777
  }
@@ -2770,7 +2785,7 @@ function splitSqlStatements(source) {
2770
2785
  buffer += ch;
2771
2786
  continue;
2772
2787
  }
2773
- if (ch === "-" && rawLine[i + 1] === "-") break;
2788
+ if (ch === "-" && scanLine[i + 1] === "-") break;
2774
2789
  if (ch === ";") {
2775
2790
  const statement = buffer.trim();
2776
2791
  if (statement.length > 0) statements.push(statement);
@@ -2779,10 +2794,14 @@ function splitSqlStatements(source) {
2779
2794
  }
2780
2795
  buffer += ch;
2781
2796
  }
2782
- buffer += inQuote ? "\n" : " ";
2797
+ if (inQuote) {
2798
+ buffer += "\n";
2799
+ } else if (buffer.length > 0 && !/\s$/.test(buffer)) {
2800
+ buffer += " ";
2801
+ }
2783
2802
  }
2784
2803
  if (inQuote) {
2785
- throw new Error(`SQL \u8FC1\u79FB\u6587\u4EF6\u5F15\u53F7\u672A\u95ED\u5408\uFF1A${buffer.trim().slice(0, 80)}\u2026`);
2804
+ throw new Error(`SQL \u811A\u672C\u5F15\u53F7\u672A\u95ED\u5408\uFF1A${buffer.trim().slice(0, 80)}\u2026`);
2786
2805
  }
2787
2806
  const tail = buffer.trim();
2788
2807
  if (tail.length > 0) statements.push(tail);
@@ -4842,12 +4861,120 @@ function mergeSharedSource(files, shared) {
4842
4861
  return merged;
4843
4862
  }
4844
4863
 
4864
+ // packages/runtime/src/shared/multipart.ts
4865
+ var MultipartParseError = class extends Error {
4866
+ constructor(message) {
4867
+ super(message);
4868
+ this.name = "MultipartParseError";
4869
+ }
4870
+ };
4871
+ function extractBoundary(contentType) {
4872
+ const match = /boundary\s*=\s*(?:"([^"]+)"|([^;\s]+))/i.exec(contentType);
4873
+ if (match === null) {
4874
+ throw new MultipartParseError("Content-Type \u7F3A\u5C11 boundary \u53C2\u6570\uFF0C\u65E0\u6CD5\u89E3\u6790 multipart \u8BF7\u6C42\u4F53");
4875
+ }
4876
+ const boundary = match[1] ?? match[2];
4877
+ if (boundary === void 0 || boundary.length === 0) {
4878
+ throw new MultipartParseError("Content-Type \u7684 boundary \u4E3A\u7A7A");
4879
+ }
4880
+ return boundary;
4881
+ }
4882
+ var HEADER_BODY_SEP = [13, 10, 13, 10];
4883
+ var encoder2 = new TextEncoder();
4884
+ var decoder2 = new TextDecoder();
4885
+ function indexOfSequence(haystack, needle, from) {
4886
+ outer: for (let i = from; i + needle.length <= haystack.length; i++) {
4887
+ for (let j = 0; j < needle.length; j++) {
4888
+ if (haystack[i + j] !== needle[j]) continue outer;
4889
+ }
4890
+ return i;
4891
+ }
4892
+ return -1;
4893
+ }
4894
+ function unquote(value) {
4895
+ return value.replace(/\\(.)/g, "$1");
4896
+ }
4897
+ function parseMultipart(contentType, raw) {
4898
+ const boundary = extractBoundary(contentType);
4899
+ const delim = encoder2.encode(`--${boundary}`);
4900
+ const positions = [];
4901
+ scan: for (let i = 0; i + delim.length <= raw.length; i++) {
4902
+ if (raw[i] !== delim[0]) continue;
4903
+ for (let j = 1; j < delim.length; j++) {
4904
+ if (raw[i + j] !== delim[j]) continue scan;
4905
+ }
4906
+ positions.push(i);
4907
+ }
4908
+ if (positions.length === 0) {
4909
+ throw new MultipartParseError(
4910
+ `\u8BF7\u6C42\u4F53\u91CC\u627E\u4E0D\u5230 boundary "${boundary}" \u7684\u5206\u9694\u7B26\u2014\u2014\u53EF\u80FD\u662F\u8BF7\u6C42\u88AB\u622A\u65AD\u6216 Content-Type \u4E0E\u8BF7\u6C42\u4F53\u4E0D\u5339\u914D`
4911
+ );
4912
+ }
4913
+ const lastPos = positions[positions.length - 1];
4914
+ if (raw[lastPos + delim.length] !== 45 || raw[lastPos + delim.length + 1] !== 45) {
4915
+ throw new MultipartParseError("multipart \u6570\u636E\u88AB\u622A\u65AD\uFF1A\u7F3A\u5C11\u7EC8\u7ED3\u5206\u9694\u7B26 --boundary--");
4916
+ }
4917
+ const files = [];
4918
+ const fields = {};
4919
+ let fieldCount = 0;
4920
+ for (let k = 0; k + 1 < positions.length; k++) {
4921
+ const partStart = positions[k] + delim.length + 2;
4922
+ const partEnd = positions[k + 1] - 2;
4923
+ if (raw[partStart - 2] !== 13 || raw[partStart - 1] !== 10) {
4924
+ throw new MultipartParseError("multipart \u5206\u9694\u7B26\u540E\u7F3A\u5C11 CRLF\uFF0C\u8BF7\u6C42\u4F53\u683C\u5F0F\u975E\u6CD5");
4925
+ }
4926
+ if (partEnd < partStart) {
4927
+ throw new MultipartParseError("multipart part \u5185\u5BB9\u4E3A\u7A7A\uFF08header \u4E0E\u6B63\u6587\u90FD\u4E0D\u5B58\u5728\uFF09");
4928
+ }
4929
+ const part = raw.subarray(partStart, partEnd);
4930
+ const headerSep = indexOfSequence(part, HEADER_BODY_SEP, 0);
4931
+ if (headerSep < 0) {
4932
+ throw new MultipartParseError("multipart part \u7F3A\u5C11 header \u4E0E\u6B63\u6587\u4E4B\u95F4\u7684\u7A7A\u884C\u5206\u9694");
4933
+ }
4934
+ const headerLines = decoder2.decode(part.subarray(0, headerSep)).split("\r\n");
4935
+ const data = part.subarray(headerSep + HEADER_BODY_SEP.length);
4936
+ const disposition = headerLines.find(
4937
+ (line) => line.toLowerCase().startsWith("content-disposition:")
4938
+ );
4939
+ if (disposition === void 0) {
4940
+ throw new MultipartParseError("multipart part \u7F3A\u5C11 Content-Disposition \u5934");
4941
+ }
4942
+ const nameMatch = /name="((?:[^"\\]|\\.)*)"/.exec(disposition);
4943
+ if (nameMatch === null) {
4944
+ throw new MultipartParseError("multipart part \u7684 Content-Disposition \u7F3A\u5C11 name \u53C2\u6570");
4945
+ }
4946
+ const fieldName = unquote(nameMatch[1]);
4947
+ const filenameMatch = /filename="((?:[^"\\]|\\.)*)"/.exec(disposition);
4948
+ if (filenameMatch !== null) {
4949
+ const clientName = unquote(filenameMatch[1]);
4950
+ if (clientName === "") continue;
4951
+ const typeLine = headerLines.find((line) => line.toLowerCase().startsWith("content-type:"));
4952
+ const type = typeLine === void 0 ? "application/octet-stream" : typeLine.slice(typeLine.indexOf(":") + 1).trim();
4953
+ files.push({ name: clientName, type, size: data.length, data });
4954
+ } else {
4955
+ const value = decoder2.decode(data);
4956
+ const prev = fields[fieldName];
4957
+ if (prev === void 0) fields[fieldName] = value;
4958
+ else if (typeof prev === "string") fields[fieldName] = [prev, value];
4959
+ else fields[fieldName] = [...prev, value];
4960
+ fieldCount++;
4961
+ }
4962
+ }
4963
+ return { fields: fieldCount > 0 ? fields : void 0, files };
4964
+ }
4965
+
4845
4966
  // packages/cli/src/dev-shared.ts
4846
4967
  var BEARER_TOKEN_RE = /^Bearer\s+(.+)$/i;
4847
- function bearerUserResolverFromEnv() {
4848
- const raw = process.env.ADEP_AUTH_ISSUER;
4849
- if (raw === void 0 || raw.trim() === "") return void 0;
4850
- return createBearerUserResolver(raw.trim());
4968
+ function bearerUserResolverFromEnv(fileEnv = {}) {
4969
+ const raw = firstNonEmpty(process.env.ADEP_AUTH_ISSUER, fileEnv.ADEP_AUTH_ISSUER);
4970
+ return raw === void 0 ? void 0 : createBearerUserResolver(raw);
4971
+ }
4972
+ function firstNonEmpty(...values) {
4973
+ for (const value of values) {
4974
+ const trimmed = value?.trim();
4975
+ if (trimmed !== void 0 && trimmed !== "") return trimmed;
4976
+ }
4977
+ return void 0;
4851
4978
  }
4852
4979
  function createBearerUserResolver(issuer) {
4853
4980
  const userinfoUrl = `${issuer.replace(/\/+$/, "")}/oauth/userinfo`;
@@ -4914,25 +5041,41 @@ function mergeSharedIntoFunctions(files) {
4914
5041
  }
4915
5042
  return out;
4916
5043
  }
4917
- function bodyOf(req) {
4918
- return new Promise((resolveBody, rejectBody) => {
5044
+ function readRawBody(req) {
5045
+ return new Promise((resolveRaw, rejectRaw) => {
4919
5046
  const chunks = [];
4920
5047
  req.on("data", (chunk) => chunks.push(chunk));
4921
- req.on("end", () => {
4922
- const raw = Buffer.concat(chunks).toString("utf8");
4923
- if (raw.length === 0) {
4924
- resolveBody(void 0);
4925
- return;
4926
- }
4927
- try {
4928
- resolveBody(JSON.parse(raw));
4929
- } catch {
4930
- resolveBody(raw);
4931
- }
4932
- });
4933
- req.on("error", rejectBody);
5048
+ req.on("end", () => resolveRaw(Buffer.concat(chunks)));
5049
+ req.on("error", rejectRaw);
4934
5050
  });
4935
5051
  }
5052
+ async function bodyOf(req) {
5053
+ const raw = (await readRawBody(req)).toString("utf8");
5054
+ if (raw.length === 0) return void 0;
5055
+ try {
5056
+ return JSON.parse(raw);
5057
+ } catch {
5058
+ return raw;
5059
+ }
5060
+ }
5061
+ async function bodyWithFiles(req) {
5062
+ const contentType = String(req.headers["content-type"] ?? "");
5063
+ if (!contentType.toLowerCase().startsWith("multipart/form-data")) {
5064
+ return { body: await bodyOf(req) };
5065
+ }
5066
+ const bytes = await readRawBody(req);
5067
+ let parsed;
5068
+ try {
5069
+ parsed = parseMultipart(contentType, bytes);
5070
+ } catch (error) {
5071
+ const message = error instanceof MultipartParseError ? error.message : `multipart \u89E3\u6790\u5931\u8D25\uFF1A${error instanceof Error ? error.message : String(error)}`;
5072
+ throw new ExecutorError(400, "FN_MULTIPART_INVALID", message);
5073
+ }
5074
+ return {
5075
+ body: parsed.fields,
5076
+ ...parsed.files.length > 0 ? { files: [...parsed.files] } : {}
5077
+ };
5078
+ }
4936
5079
  function writeJson(res, status, payload) {
4937
5080
  res.writeHead(status, { "content-type": "application/json" });
4938
5081
  res.end(JSON.stringify(payload));
@@ -4947,13 +5090,14 @@ async function requestInput(url, req, readBody) {
4947
5090
  for (const [key, value] of Object.entries(req.headers)) {
4948
5091
  if (typeof value === "string") headers[key] = value;
4949
5092
  }
4950
- const body = req.method === "GET" || req.method === "HEAD" ? void 0 : await readBody(req);
5093
+ const parsed = req.method === "GET" || req.method === "HEAD" ? void 0 : await readBody(req);
4951
5094
  return {
4952
5095
  method: req.method ?? "GET",
4953
5096
  path: url.pathname,
4954
5097
  query,
4955
5098
  headers,
4956
- ...body === void 0 ? {} : { body }
5099
+ ...parsed?.body === void 0 ? {} : { body: parsed.body },
5100
+ ...parsed?.files === void 0 ? {} : { files: parsed.files }
4957
5101
  };
4958
5102
  }
4959
5103
 
@@ -5024,8 +5168,8 @@ async function startDevServer(options) {
5024
5168
  ...options.db === void 0 ? {} : { db: options.db },
5025
5169
  ...options.dbFile === void 0 ? {} : { dbFile: options.dbFile }
5026
5170
  });
5027
- const bearerUser = bearerUserResolverFromEnv();
5028
5171
  const simEnv = await loadSimEnv(cwd).catch(() => ({}));
5172
+ let bearerUser = bearerUserResolverFromEnv(simEnv);
5029
5173
  const fetchConfig = resolveLocalFetchConfig(simEnv);
5030
5174
  const executor = new WorkerFunctionExecutor({
5031
5175
  deps: { rootDir: cwd, builtin: LOCAL_BUILTIN_DEPS },
@@ -5139,6 +5283,7 @@ async function startDevServer(options) {
5139
5283
  ]);
5140
5284
  files = nextFiles;
5141
5285
  env = { ...config.environment, ...parseEnvFile(envText2) };
5286
+ bearerUser = bearerUserResolverFromEnv(await loadSimEnv(cwd).catch(() => ({})));
5142
5287
  };
5143
5288
  const envText = await readFile7(join10(cwd, ".env.local"), "utf8").catch(() => "");
5144
5289
  env = { ...config.environment, ...parseEnvFile(envText) };
@@ -5156,7 +5301,7 @@ async function startDevServer(options) {
5156
5301
  }
5157
5302
  const buildInput = async (fnName, entry, url, req) => {
5158
5303
  const hasEnv = Object.keys(env).length > 0;
5159
- const request = await requestInput(url, req, bodyOf);
5304
+ const request = await requestInput(url, req, bodyWithFiles);
5160
5305
  if (bearerUser !== void 0) request.user = await bearerUser(request.headers);
5161
5306
  return {
5162
5307
  project: { id: "local", slug: config.name },
@@ -5230,9 +5375,9 @@ async function startDevServer(options) {
5230
5375
  writeJson(res, 404, { error: { code: "FN_NOT_FOUND", message: `\u51FD\u6570 "${fnName}" \u4E0D\u5B58\u5728` } });
5231
5376
  return;
5232
5377
  }
5233
- const input = await buildInput(fnName, entry, url, req);
5234
5378
  const startedAt = performance.now();
5235
5379
  try {
5380
+ const input = await buildInput(fnName, entry, url, req);
5236
5381
  const result = await executor.execute(input);
5237
5382
  const durationMs = Math.round(performance.now() - startedAt);
5238
5383
  for (const line of result.logs) log(`[adep] ${line}`);
@@ -5305,7 +5450,9 @@ async function startDevServer(options) {
5305
5450
  log(`[adep] curl \u793A\u4F8B\uFF1Acurl ${baseUrl}${curlPath}`);
5306
5451
  printBoundaries(log);
5307
5452
  if (bearerUser !== void 0) {
5308
- log(`[adep] \u767B\u5F55\u5373\u670D\u52A1\uFF1AADEP_AUTH_ISSUER \u5DF2\u914D\u7F6E\uFF0CBearer token \u5C06\u89E3\u6790\u4E3A\u7528\u6237\u8EAB\u4EFD\uFF08userinfo \u7AEF\u70B9\uFF09`);
5453
+ log(
5454
+ `[adep] \u767B\u5F55\u5373\u670D\u52A1\uFF1AADEP_AUTH_ISSUER \u5DF2\u914D\u7F6E\uFF0CBearer token \u5C06\u89E3\u6790\u4E3A\u7528\u6237\u8EAB\u4EFD\uFF08userinfo \u7AEF\u70B9\uFF09`
5455
+ );
5309
5456
  }
5310
5457
  log(`[adep] \u6570\u636E\u5E93\uFF1A${dbLabel} \u2192 ${dbTargetText}`);
5311
5458
  startStateAlarmScheduler();
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "homepage": "https://adep.top",
9
9
  "bugs": "https://gitcode.com/yunqiang_wu/ai-yunke/issues",
10
- "version": "0.4.6",
10
+ "version": "0.4.11",
11
11
  "type": "module",
12
12
  "description": "`adep` 命令行工具包位:登录 / 初始化 / 本地调试 / 部署 / 数据库维护 / 云存储 / 静态托管 / 微前端组件(widget),实现见任务单 CLI-001 ~ CLI-003 与 FE-002;子路径 `@adep/cli/vite` 提供云函数 vite 插件(CLI-014)",
13
13
  "bin": {
@@ -30,11 +30,11 @@
30
30
  "esbuild": "0.25.12",
31
31
  "yaml": "2.9.1",
32
32
  "zod": "^4.6.6",
33
- "@adep/runtime": "0.3.5",
34
33
  "@adep/app-runtime": "0.1.1",
35
34
  "@adep/cf-compat": "0.1.4",
36
- "@adep/vite-plugin": "0.1.9",
37
- "@adep/crypto": "0.1.1"
35
+ "@adep/vite-plugin": "0.1.11",
36
+ "@adep/crypto": "0.1.1",
37
+ "@adep/runtime": "0.3.7"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@adep/types": "0.3.2"