@adep/web-container 0.2.3 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -147,8 +147,17 @@ var AdepWebContainer = (() => {
147
147
  if (typeof exp !== "object" || Array.isArray(exp)) {
148
148
  throw new ResolveError(`${context} \u5F62\u6001\u4E0D\u652F\u6301\uFF08exports \u53EA\u80FD\u662F\u5B57\u7B26\u4E32\u6216\u5BF9\u8C61\uFF09`);
149
149
  }
150
- const dot = exp["."];
150
+ const table = exp;
151
+ const dot = table["."];
152
+ const order = condition === "import" ? IMPORT_CONDITION_ORDER : REQUIRE_CONDITION_ORDER;
153
+ const resolveRel = (rel) => withinPackage(pkgDirAbs, rel, context);
151
154
  if (dot === void 0) {
155
+ const keys = Object.keys(table);
156
+ if (keys.length > 0 && keys.every((key) => !key.startsWith("."))) {
157
+ const shorthand = pickConditionTarget(table, order, resolveRel, context);
158
+ if (shorthand !== null) return shorthand;
159
+ throw new ResolveError(`${context}\uFF1A\u5305\u6839\u6761\u4EF6\u5BF9\u8C61\u91CC\u6CA1\u6709 ${order.join("/")} \u5165\u53E3`);
160
+ }
152
161
  throw new ResolveError(
153
162
  `${context} \u53EA\u58F0\u660E\u4E86\u5B50\u8DEF\u5F84\u6620\u5C04\u3001\u6CA1\u6709 "." \u5165\u53E3\uFF0C\u5F53\u524D\u4EC5\u652F\u6301 "." \u4E0E\u5B57\u7B26\u4E32\u5F62\u6001`
154
163
  );
@@ -159,8 +168,6 @@ var AdepWebContainer = (() => {
159
168
  if (typeof dot !== "object" || Array.isArray(dot)) {
160
169
  throw new ResolveError(`${context}\uFF1Aexports["."] \u5F62\u6001\u4E0D\u652F\u6301\uFF08\u4EC5\u63A5\u53D7\u5B57\u7B26\u4E32\u6216\u6761\u4EF6\u5BF9\u8C61\uFF09`);
161
170
  }
162
- const order = condition === "import" ? IMPORT_CONDITION_ORDER : REQUIRE_CONDITION_ORDER;
163
- const resolveRel = (rel) => withinPackage(pkgDirAbs, rel, context);
164
171
  const hit = pickConditionTarget(dot, order, resolveRel, context);
165
172
  if (hit !== null) return hit;
166
173
  throw new ResolveError(`${context}\uFF1Aexports["."] \u6761\u4EF6\u5BF9\u8C61\u91CC\u6CA1\u6709 ${order.join("/")} \u5165\u53E3`);
@@ -359,6 +366,28 @@ var AdepWebContainer = (() => {
359
366
  }
360
367
  return "";
361
368
  }
369
+ /**
370
+ * `interface` / `type` 声明之前若有 `export` 关键字,返回该关键字的起始下标,否则原样返回。
371
+ *
372
+ * 为什么必须吞掉:`export interface X { … }` 里 `interface` 分支只擦它自己那一段,
373
+ * 留下的孤立 `export` 是**非法 JS**——浏览器解析模块时直接
374
+ * `SyntaxError: Unexpected token 'export'`(实测 countdown 项目 `lib/auth.ts` 的
375
+ * `export interface AppUser`:整条预览链路因此白屏)。`export type X = …` 由 `export`
376
+ * 分支整条擦除,不受影响。
377
+ *
378
+ * 判据分两步:token 回看确认前一个显著 token 就是 `export`(避免误吞 `re-export` 之类
379
+ * 同名标识符——那会在下面按字符再校验一次);位置则往前跳空白后左推 6 个字符,并要求
380
+ * 再前一个字符不是标识符字符(`xexport interface` 不吞)。
381
+ */
382
+ includeLeadingExport(start) {
383
+ if (this.tokenAt(2) !== "export") return start;
384
+ let end = start - 1;
385
+ while (end >= 0 && /\s/.test(this.src[end])) end--;
386
+ if (end < 5 || this.src.slice(end - 5, end + 1) !== "export") return start;
387
+ const before = this.src[end - 6];
388
+ if (before !== void 0 && IDENT_PART.test(before)) return start;
389
+ return end - 5;
390
+ }
362
391
  /** 擦除 `[from, to)`:填等长空格,换行照抄——擦完行号与原文件一致。 */
363
392
  erase(from, to) {
364
393
  for (let j = Math.max(from, 0); j < to; j++) this.chars[j] = this.src[j] === "\n" ? "\n" : " ";
@@ -498,19 +527,31 @@ var AdepWebContainer = (() => {
498
527
  }
499
528
  switch (word) {
500
529
  case "interface": {
501
- const after = this.skipWhitespaceFrom(this.skipNameAndParams(start + word.length));
530
+ const heritage = this.skipInterfaceExtends(this.skipNameAndParams(start + word.length));
531
+ const after = heritage === null ? null : this.skipWhitespaceFrom(heritage);
502
532
  if (after === null || this.src[after] !== "{") return;
503
533
  const end = this.scanBalanced(after, "{", "}");
504
- this.erase(start, end);
534
+ this.erase(this.includeLeadingExport(start), end);
505
535
  this.i = end;
506
536
  this.pushToken("erased");
507
537
  return;
508
538
  }
509
539
  case "type": {
540
+ if (this.frames[this.frames.length - 1]?.specifierList === true) {
541
+ const specifierEnd = this.scanTypeOnlySpecifier(this.i);
542
+ if (specifierEnd !== null) {
543
+ this.erase(start, specifierEnd);
544
+ this.i = specifierEnd;
545
+ } else {
546
+ this.erase(start, start + word.length);
547
+ }
548
+ this.pushToken("erased");
549
+ return;
550
+ }
510
551
  const after = this.skipWhitespaceFrom(this.skipNameAndParams(this.i));
511
552
  if (after === null || this.src[after] !== "=") return;
512
553
  const end = this.scanTypeExpression(after + 1, true);
513
- this.erase(start, end);
554
+ this.erase(this.includeLeadingExport(start), end);
514
555
  this.i = end;
515
556
  this.pushToken("erased");
516
557
  return;
@@ -537,16 +578,20 @@ var AdepWebContainer = (() => {
537
578
  this.pushToken("erased");
538
579
  return;
539
580
  }
540
- case "class":
541
- this.pendingClassBody = true;
581
+ case "class": {
582
+ const next = this.skipWhitespaceFrom(this.i);
583
+ if (next !== null && (this.src[next] === "{" || IDENT_START.test(this.src[next]))) {
584
+ this.pendingClassBody = true;
585
+ }
542
586
  return;
587
+ }
543
588
  case "as":
544
589
  case "satisfies": {
545
590
  if (this.frames[this.frames.length - 1]?.specifierList === true) return;
546
591
  if (this.tokenAt(2) === "*" || this.tokenAt(2) === "type") return;
547
592
  const nextChar = this.skipWhitespaceFrom(this.i);
548
593
  if (nextChar === null || "=,:]})".includes(this.src[nextChar])) return;
549
- const end = this.scanTypeExpression(this.i, false);
594
+ const end = this.scanTypeExpression(this.i, true);
550
595
  this.erase(start, end);
551
596
  this.i = end;
552
597
  return;
@@ -682,6 +727,62 @@ var AdepWebContainer = (() => {
682
727
  this.i = end;
683
728
  return true;
684
729
  }
730
+ /**
731
+ * `interface X extends A, B<T> {` 的继承子句:返回接口体 `{` 的下标。
732
+ *
733
+ * 不处理 `extends` 会让 `interface` 分支取不到 `{` 而**整条不擦**——`export interface
734
+ * DecodedEvent extends CountdownEvent { … }` 原样留在产物里,浏览器解析即
735
+ * `SyntaxError: Unexpected token 'export'`(实测 countdown 的 lib/date.ts;同项目两个
736
+ * `.vue` 产物是它的级联失败)。无 `extends` 时原样返回入参(等价旧行为);遇到字符串 /
737
+ * 配不平的泛型一律返回 null(判不准就不擦)。
738
+ */
739
+ skipInterfaceExtends(from) {
740
+ if (from === null) return null;
741
+ const j = this.skipWhitespaceFrom(from);
742
+ if (j === null || !this.src.startsWith("extends", j) || IDENT_PART.test(this.src[j + 7] ?? "")) {
743
+ return j;
744
+ }
745
+ let k = this.skipWhitespaceFrom(j + 7);
746
+ while (k !== null) {
747
+ const c = this.src[k];
748
+ if (c === "{" || c === ";") return k;
749
+ if (c === "<") {
750
+ const end = this.scanTypeParams(k);
751
+ if (end === null) return null;
752
+ k = end;
753
+ continue;
754
+ }
755
+ if (c === "'" || c === '"' || c === "`") return null;
756
+ k = this.skipWhitespaceFrom(k + 1);
757
+ }
758
+ return null;
759
+ }
760
+ /**
761
+ * 「仅类型说明符」`type X [as Y]` 的擦除终点(返回应擦到、不含的下标)。
762
+ *
763
+ * - `type` 之后不是标识符 → null(调用方退化为只擦关键字,不猜);
764
+ * - 连带**其后的**逗号一起擦(`{ type A, b }` → `{ b }`);末位说明符没有逗号,
765
+ * 留下的 `{ a, }` 是合法尾逗号,无需回首删前导逗号;
766
+ * - `as Y` 重命名一并擦除(只影响类型侧,运行时无绑定)。
767
+ */
768
+ scanTypeOnlySpecifier(from) {
769
+ let j = this.skipWhitespaceFrom(from);
770
+ if (j === null || !IDENT_START.test(this.src[j])) return null;
771
+ j++;
772
+ while (j < this.src.length && IDENT_PART.test(this.src[j])) j++;
773
+ const asAt = this.skipWhitespaceFrom(j);
774
+ if (asAt !== null && this.src.startsWith("as", asAt) && !IDENT_PART.test(this.src[asAt + 2] ?? "")) {
775
+ const nameAt = this.skipWhitespaceFrom(asAt + 2);
776
+ if (nameAt !== null && IDENT_START.test(this.src[nameAt])) {
777
+ let k = nameAt + 1;
778
+ while (k < this.src.length && IDENT_PART.test(this.src[k])) k++;
779
+ j = k;
780
+ }
781
+ }
782
+ const next = this.skipWhitespaceFrom(j);
783
+ if (next !== null && this.src[next] === ",") return next + 1;
784
+ return j;
785
+ }
685
786
  /**
686
787
  * `{` 是 import / export 的说明符列表吗——`{ a as b }` 覆盖 `import { … }`、
687
788
  * `export { … }` 与 `import def, { … }` 三种写法(后者说明符花括号的前驱 token 是 `,`)。
@@ -742,7 +843,7 @@ var AdepWebContainer = (() => {
742
843
  const generic = this.scanTypeParams(j);
743
844
  return generic === null ? j : generic;
744
845
  }
745
- /** `<T, U extends X>`:返回 `>` 之后的下标;跨到 `)` `]` `;` 换行前配不平则 null。 */
846
+ /** `<T, U extends X>`:返回 `>` 之后的下标;尖括号内任何非 `<`/`>` 字符(含 `]` `;` `\n` `)`)都是合法类型字符,配不平自然到文件尾返回 null。 */
746
847
  scanTypeParams(from) {
747
848
  if (this.src[from] !== "<") return null;
748
849
  let depth = 0;
@@ -753,8 +854,7 @@ var AdepWebContainer = (() => {
753
854
  else if (c === ">") {
754
855
  depth--;
755
856
  if (depth === 0) return j + 1;
756
- } else if (c === ")" || c === "]" || c === ";" || c === "\n") return null;
757
- else if (c === "'" || c === '"') j = this.scanQuoted(j) - 1;
857
+ } else if (c === "'" || c === '"') j = this.scanQuoted(j) - 1;
758
858
  else if (c === "`") j = this.scanTemplate(j) - 1;
759
859
  }
760
860
  return null;
@@ -886,13 +986,14 @@ var AdepWebContainer = (() => {
886
986
  /**
887
987
  * 行尾处类型是否仍在继续:`type Id = string\n | number` 要接得上,
888
988
  * 而 `const x: Foo\nconst y = 1` 必须停。判据是两侧的非空邻字——
889
- * 前一个是连接符(`| & < > = , . ? : (`)或后一个是连接符 / 闭合符(`| & , . ? : ) ] } >`)。
989
+ * 前一个是连接符(`| & < = , . ? : (`,不含 `>`——`Foo<T>` 后换行是语句边界,
990
+ * 含 `>` 会把下一行的 `try` 等吞进类型区间)或后一个是连接符 / 闭合符(`| & , . ? : ) ] } >`)。
890
991
  */
891
992
  typeContinuesAt(index) {
892
993
  for (let j = index - 1; j >= 0; j--) {
893
994
  const c = this.src[j];
894
995
  if (/\s/.test(c)) continue;
895
- if ("|&<>=,.?:(".includes(c)) return true;
996
+ if ("|&<=,.?:(".includes(c)) return true;
896
997
  break;
897
998
  }
898
999
  for (let j = index + 1; j < this.src.length; j++) {
@@ -906,6 +1007,206 @@ var AdepWebContainer = (() => {
906
1007
  }
907
1008
  });
908
1009
 
1010
+ // src/css-imports.ts
1011
+ function isLocalSpec(spec) {
1012
+ return spec.startsWith("./") || spec.startsWith("../") || spec.startsWith("/");
1013
+ }
1014
+ function skipString(css, start) {
1015
+ const quote = css[start];
1016
+ let i = start + 1;
1017
+ while (i < css.length) {
1018
+ if (css[i] === "\\") {
1019
+ i += 2;
1020
+ continue;
1021
+ }
1022
+ if (css[i] === quote) return i + 1;
1023
+ i++;
1024
+ }
1025
+ return css.length;
1026
+ }
1027
+ function matchParen(text, open) {
1028
+ let depth = 0;
1029
+ let i = open;
1030
+ while (i < text.length) {
1031
+ const ch = text[i];
1032
+ if (ch === '"' || ch === "'") {
1033
+ i = skipString(text, i);
1034
+ continue;
1035
+ }
1036
+ if (ch === "(") depth++;
1037
+ else if (ch === ")") {
1038
+ depth--;
1039
+ if (depth === 0) return i;
1040
+ }
1041
+ i++;
1042
+ }
1043
+ return text.length;
1044
+ }
1045
+ function parseSpecifier(css, from) {
1046
+ let i = from;
1047
+ while (i < css.length && /\s/.test(css[i])) i++;
1048
+ const urlHead = /^url\s*\(/i.exec(css.slice(i, i + 8));
1049
+ if (urlHead !== null) {
1050
+ const open = i + urlHead[0].length - 1;
1051
+ const close = matchParen(css, open);
1052
+ if (close >= css.length) return { spec: null, next: i };
1053
+ const inner = css.slice(open + 1, close).trim();
1054
+ const quoted = inner.startsWith('"') || inner.startsWith("'");
1055
+ return { spec: quoted ? inner.slice(1, -1).trim() : inner, next: close + 1 };
1056
+ }
1057
+ const quote = css[i];
1058
+ if (quote === '"' || quote === "'") {
1059
+ const end = skipString(css, i);
1060
+ if (css[end - 1] !== quote) return { spec: null, next: i };
1061
+ return { spec: css.slice(i + 1, end - 1), next: end };
1062
+ }
1063
+ return { spec: null, next: i };
1064
+ }
1065
+ function parseImport(css, start) {
1066
+ const parsed = parseSpecifier(css, start + IMPORT_KEYWORD.length);
1067
+ if (parsed.spec === null) return null;
1068
+ let j = parsed.next;
1069
+ let depth = 0;
1070
+ while (j < css.length) {
1071
+ const ch = css[j];
1072
+ if (ch === '"' || ch === "'") {
1073
+ j = skipString(css, j);
1074
+ continue;
1075
+ }
1076
+ if (ch === "(") depth++;
1077
+ else if (ch === ")") depth--;
1078
+ else if (ch === ";" && depth <= 0) break;
1079
+ else if (ch === "{" || ch === "}") return null;
1080
+ j++;
1081
+ }
1082
+ if (j >= css.length) return null;
1083
+ return {
1084
+ start,
1085
+ end: j + 1,
1086
+ spec: parsed.spec,
1087
+ conditions: css.slice(parsed.next, j).trim(),
1088
+ raw: css.slice(start, j + 1)
1089
+ };
1090
+ }
1091
+ function scanCssImports(css) {
1092
+ const hits = [];
1093
+ let i = 0;
1094
+ while (i < css.length) {
1095
+ const ch = css[i];
1096
+ if (ch === "/" && css[i + 1] === "*") {
1097
+ const close = css.indexOf("*/", i + 2);
1098
+ i = close === -1 ? css.length : close + 2;
1099
+ continue;
1100
+ }
1101
+ if (ch === '"' || ch === "'") {
1102
+ i = skipString(css, i);
1103
+ continue;
1104
+ }
1105
+ if (ch === "@" && /^@import(?![-\w])/i.test(css.slice(i, i + IMPORT_KEYWORD.length + 1))) {
1106
+ const hit = parseImport(css, i);
1107
+ if (hit !== null) {
1108
+ hits.push(hit);
1109
+ i = hit.end;
1110
+ continue;
1111
+ }
1112
+ }
1113
+ i++;
1114
+ }
1115
+ return hits;
1116
+ }
1117
+ function stripCharset(css) {
1118
+ return css.replace(/^\uFEFF/, "").replace(/^\s*@charset\s+(["'])[^"']*\1\s*;/i, "");
1119
+ }
1120
+ function splitImportConditions(conditions) {
1121
+ let rest = conditions.trim();
1122
+ let layer = null;
1123
+ const layerFn = /^layer\s*\(/i.exec(rest);
1124
+ if (layerFn !== null) {
1125
+ const open = layerFn[0].length - 1;
1126
+ const close = matchParen(rest, open);
1127
+ layer = rest.slice(open + 1, close).trim();
1128
+ rest = rest.slice(close + 1).trim();
1129
+ } else if (/^layer(?![-\w(])/i.test(rest)) {
1130
+ layer = "";
1131
+ rest = rest.slice("layer".length).trim();
1132
+ }
1133
+ let supports = "";
1134
+ const supportsFn = /^supports\s*\(/i.exec(rest);
1135
+ if (supportsFn !== null) {
1136
+ const open = supportsFn[0].length - 1;
1137
+ const close = matchParen(rest, open);
1138
+ supports = rest.slice(open + 1, close).trim();
1139
+ rest = rest.slice(close + 1).trim();
1140
+ }
1141
+ return { layer, supports, media: rest };
1142
+ }
1143
+ function applyImportConditions(css, conditions) {
1144
+ if (conditions === "") return css;
1145
+ const { layer, supports, media } = splitImportConditions(conditions);
1146
+ let out = css;
1147
+ if (supports !== "") out = `@supports ${supports} {
1148
+ ${out}
1149
+ }`;
1150
+ if (layer !== null) out = layer === "" ? `@layer {
1151
+ ${out}
1152
+ }` : `@layer ${layer} {
1153
+ ${out}
1154
+ }`;
1155
+ if (media !== "") out = `@media ${media} {
1156
+ ${out}
1157
+ }`;
1158
+ return out;
1159
+ }
1160
+ function expand(css, importerAbs, resolver, seen) {
1161
+ const hits = scanCssImports(css);
1162
+ if (hits.length === 0) return css;
1163
+ const parts = [];
1164
+ let cursor = 0;
1165
+ for (const hit of hits) {
1166
+ parts.push(css.slice(cursor, hit.start));
1167
+ parts.push(expandHit(hit, importerAbs, resolver, seen));
1168
+ cursor = hit.end;
1169
+ }
1170
+ parts.push(css.slice(cursor));
1171
+ return parts.join("");
1172
+ }
1173
+ function expandHit(hit, importerAbs, resolver, seen) {
1174
+ if (hit.spec === null) return hit.raw;
1175
+ const spec = hit.spec.trim();
1176
+ if (spec === "" || EXTERNAL_SPEC.test(spec)) return hit.raw;
1177
+ const abs = resolver.resolve(spec, importerAbs);
1178
+ if (abs === null) {
1179
+ if (isLocalSpec(spec))
1180
+ throw new CssImportError(
1181
+ `CSS @import \u627E\u4E0D\u5230\u6587\u4EF6 "${spec}"\uFF08\u5728 ${importerAbs} \u4E2D\uFF09\u2014\u2014\u76F8\u5BF9\u8DEF\u5F84\u6309\u8BE5\u6587\u4EF6\u7684\u6240\u5728\u76EE\u5F55\u89E3\u6790\uFF0C\u8BF7\u68C0\u67E5\u8DEF\u5F84\u662F\u5426\u6B63\u786E\u3002`
1182
+ );
1183
+ return hit.raw;
1184
+ }
1185
+ if (!abs.toLowerCase().endsWith(".css")) return hit.raw;
1186
+ if (seen.has(abs)) return "";
1187
+ seen.add(abs);
1188
+ const source = resolver.read(abs);
1189
+ if (source === null) return hit.raw;
1190
+ return applyImportConditions(expand(stripCharset(source), abs, resolver, seen), hit.conditions);
1191
+ }
1192
+ function inlineCssImports(css, importerAbs, resolver) {
1193
+ return expand(css, importerAbs, resolver, /* @__PURE__ */ new Set([importerAbs]));
1194
+ }
1195
+ var CssImportError, IMPORT_KEYWORD, EXTERNAL_SPEC;
1196
+ var init_css_imports = __esm({
1197
+ "src/css-imports.ts"() {
1198
+ "use strict";
1199
+ CssImportError = class extends Error {
1200
+ constructor(message) {
1201
+ super(message);
1202
+ this.name = "CssImportError";
1203
+ }
1204
+ };
1205
+ IMPORT_KEYWORD = "@import";
1206
+ EXTERNAL_SPEC = /^(?:[A-Za-z][A-Za-z0-9+.-]*:|\/\/)/i;
1207
+ }
1208
+ });
1209
+
909
1210
  // src/preview-server.ts
910
1211
  var preview_server_exports = {};
911
1212
  __export(preview_server_exports, {
@@ -919,6 +1220,20 @@ var AdepWebContainer = (() => {
919
1220
  if (!vfs.exists(abs) || vfs.isDirectory(abs)) return null;
920
1221
  return abs;
921
1222
  }
1223
+ function cssResolverOf(vfs) {
1224
+ return {
1225
+ read: (abs) => vfs.exists(abs) && !vfs.isDirectory(abs) ? vfs.readFile(abs) : null,
1226
+ resolve: (spec, importerAbs) => {
1227
+ if (spec.startsWith("./") || spec.startsWith("../") || spec.startsWith("/"))
1228
+ return resolveLocal(vfs, spec, dirname(importerAbs));
1229
+ try {
1230
+ return resolveImport(vfs, spec, importerAbs, "import");
1231
+ } catch {
1232
+ return null;
1233
+ }
1234
+ }
1235
+ };
1236
+ }
922
1237
  function inlineAssets(html, vfs, baseDir) {
923
1238
  let out = html.replace(
924
1239
  /<script\b([^>]*?)\bsrc\s*=\s*(["'])(.*?)\2([^>]*)><\/script>/gi,
@@ -935,7 +1250,13 @@ var AdepWebContainer = (() => {
935
1250
  (whole, _pre, _q, _post, _r, orig) => {
936
1251
  const abs = resolveLocal(vfs, orig, baseDir);
937
1252
  if (abs === null) return whole;
938
- return `<style>${vfs.readFile(abs)}</style>`;
1253
+ const css = vfs.readFile(abs);
1254
+ try {
1255
+ return `<style>${inlineCssImports(css, abs, cssResolverOf(vfs))}</style>`;
1256
+ } catch (error) {
1257
+ if (error instanceof CssImportError) return `<style>${css}</style>`;
1258
+ throw error;
1259
+ }
939
1260
  }
940
1261
  );
941
1262
  return out;
@@ -1008,6 +1329,8 @@ var AdepWebContainer = (() => {
1008
1329
  "src/preview-server.ts"() {
1009
1330
  "use strict";
1010
1331
  init_path();
1332
+ init_node_resolve();
1333
+ init_css_imports();
1011
1334
  EXTERNAL_SRC = /(?:^https?:)?\/\//i;
1012
1335
  }
1013
1336
  });
@@ -1307,12 +1630,76 @@ var AdepWebContainer = (() => {
1307
1630
  }
1308
1631
  });
1309
1632
 
1633
+ // src/console-relay.ts
1634
+ var CONSOLE_RELAY_SCRIPT;
1635
+ var init_console_relay = __esm({
1636
+ "src/console-relay.ts"() {
1637
+ "use strict";
1638
+ CONSOLE_RELAY_SCRIPT = [
1639
+ "(function () {",
1640
+ " if (window.__adepErrorRelayInstalled) return;",
1641
+ " window.__adepErrorRelayInstalled = true;",
1642
+ ' var LEVELS = { log: "log", info: "info", warn: "warn", error: "error", debug: "log" };',
1643
+ " function fmt(value) {",
1644
+ " try {",
1645
+ ' if (typeof value === "string") return value;',
1646
+ ' if (value === undefined) return "undefined";',
1647
+ " var seen = [];",
1648
+ " var json = JSON.stringify(value, function (key, val) {",
1649
+ ' if (val instanceof Error) return val.stack || (val.name + ": " + val.message);',
1650
+ ' if (typeof val === "function") return "[Function " + (val.name || "anonymous") + "]";',
1651
+ ' if (typeof val === "bigint") return String(val) + "n";',
1652
+ ' if (val && typeof val === "object") {',
1653
+ ' if (seen.indexOf(val) !== -1) return "[Circular]";',
1654
+ " seen.push(val);",
1655
+ " }",
1656
+ " return val;",
1657
+ " });",
1658
+ " return json === undefined ? String(value) : json;",
1659
+ " } catch {",
1660
+ " return String(value);",
1661
+ " }",
1662
+ " }",
1663
+ " function send(level, args) {",
1664
+ " try {",
1665
+ " if (window.parent === window) return;",
1666
+ ' var text = Array.prototype.map.call(args, fmt).join(" ");',
1667
+ ' window.parent.postMessage({ source: "adep-ide-preview", kind: "console", level: level, text: text }, "*");',
1668
+ " } catch {",
1669
+ " }",
1670
+ " }",
1671
+ " Object.keys(LEVELS).forEach(function (name) {",
1672
+ " var native = console[name];",
1673
+ " console[name] = function () {",
1674
+ " send(LEVELS[name], arguments);",
1675
+ " native.apply(console, arguments);",
1676
+ " };",
1677
+ " });",
1678
+ " window.addEventListener('error', function (event) {",
1679
+ ' var text = event.message || "Script error";',
1680
+ " if (event.filename) {",
1681
+ ' text += " (" + event.filename + ":" + event.lineno + ":" + event.colno + ")";',
1682
+ " }",
1683
+ ' send("error", [text]);',
1684
+ " });",
1685
+ " window.addEventListener('unhandledrejection', function (event) {",
1686
+ " var reason = event.reason;",
1687
+ ' var text = reason && reason.stack ? String(reason.stack) : "Unhandled rejection: " + fmt(reason);',
1688
+ ' send("error", [text]);',
1689
+ " });",
1690
+ "})();",
1691
+ ""
1692
+ ].join("\n");
1693
+ }
1694
+ });
1695
+
1310
1696
  // src/vite-dev.ts
1311
1697
  var vite_dev_exports = {};
1312
1698
  __export(vite_dev_exports, {
1313
1699
  ViteDevError: () => ViteDevError,
1314
1700
  createViteServer: () => createViteServer,
1315
- scanEsmSpecifiers: () => scanEsmSpecifiers
1701
+ scanEsmSpecifiers: () => scanEsmSpecifiers,
1702
+ scanRequireSpecifiers: () => scanRequireSpecifiers
1316
1703
  });
1317
1704
  function tokenize2(source) {
1318
1705
  const tokens = [];
@@ -1410,6 +1797,20 @@ var AdepWebContainer = (() => {
1410
1797
  }
1411
1798
  return hits;
1412
1799
  }
1800
+ function scanRequireSpecifiers(source) {
1801
+ const tokens = tokenize2(source);
1802
+ const hits = [];
1803
+ for (let i = 0; i + 3 < tokens.length; i++) {
1804
+ const call = tokens[i];
1805
+ if (call.kind !== "ident" || call.text !== "require") continue;
1806
+ if (tokens[i + 1]?.text !== "(") continue;
1807
+ const arg = tokens[i + 2];
1808
+ if (arg.kind !== "string") continue;
1809
+ if (tokens[i + 3]?.text !== ")") continue;
1810
+ hits.push({ specifier: arg.text.slice(1, -1), start: arg.start, end: arg.end });
1811
+ }
1812
+ return hits;
1813
+ }
1413
1814
  function cssModule(css) {
1414
1815
  return [
1415
1816
  `const css = ${JSON.stringify(css)};`,
@@ -1440,6 +1841,113 @@ var AdepWebContainer = (() => {
1440
1841
  }
1441
1842
  return `export default ${source.trim()};`;
1442
1843
  }
1844
+ function stripShebang(source) {
1845
+ if (!source.startsWith("#!")) return source;
1846
+ const nl = source.indexOf("\n");
1847
+ return nl === -1 ? "" : source.slice(nl + 1);
1848
+ }
1849
+ function hasEsmSyntax(source) {
1850
+ const tokens = tokenize2(source);
1851
+ for (let i = 0; i < tokens.length; i++) {
1852
+ const tok = tokens[i];
1853
+ if (tok.kind !== "ident") continue;
1854
+ if (tok.text === "export") return true;
1855
+ if (tok.text === "import" && tokens[i + 1]?.text !== "(") return true;
1856
+ }
1857
+ return false;
1858
+ }
1859
+ function isCommonJs(abs, source) {
1860
+ if (abs.endsWith(".cjs")) return true;
1861
+ if (!abs.endsWith(".js")) return false;
1862
+ if (hasEsmSyntax(source)) return false;
1863
+ return /\bmodule\s*\.\s*exports\b|\bexports\s*\.|\brequire\s*\(/.test(source);
1864
+ }
1865
+ function collectCjsExportNames(source) {
1866
+ const tokens = tokenize2(source);
1867
+ const names = /* @__PURE__ */ new Set();
1868
+ const isIdent = (index) => {
1869
+ const tok = tokens[index];
1870
+ return tok?.kind === "ident" && VALID_IDENT.test(tok.text) ? tok.text : null;
1871
+ };
1872
+ for (let i = 0; i < tokens.length; i++) {
1873
+ const tok = tokens[i];
1874
+ if (tok.kind !== "ident") continue;
1875
+ if (tok.text === "exports") {
1876
+ const name = isIdent(i + 2);
1877
+ if (tokens[i + 1]?.text === "." && name !== null && tokens[i + 3]?.text === "=")
1878
+ names.add(name);
1879
+ continue;
1880
+ }
1881
+ if (tok.text === "module") {
1882
+ const name = isIdent(i + 4);
1883
+ if (tokens[i + 1]?.text === "." && tokens[i + 2]?.text === "exports" && tokens[i + 3]?.text === "." && name !== null && tokens[i + 5]?.text === "=") {
1884
+ names.add(name);
1885
+ }
1886
+ if (tokens[i + 1]?.text === "." && tokens[i + 2]?.text === "exports" && tokens[i + 3]?.text === "=" && tokens[i + 4]?.text === "{") {
1887
+ let depth = 0;
1888
+ for (let j = i + 4; j < tokens.length; j++) {
1889
+ const t = tokens[j];
1890
+ if (t.kind === "string" || t.kind === "template") continue;
1891
+ if (t.text === "{") depth++;
1892
+ else if (t.text === "}") {
1893
+ depth--;
1894
+ if (depth === 0) break;
1895
+ } else if (depth === 1) {
1896
+ const prev = tokens[j - 1]?.text;
1897
+ const key = isIdent(j);
1898
+ const next = tokens[j + 1]?.text;
1899
+ if (key !== null && (prev === "{" || prev === ",") && (next === ":" || next === "," || next === "}")) {
1900
+ names.add(key);
1901
+ }
1902
+ }
1903
+ }
1904
+ continue;
1905
+ }
1906
+ continue;
1907
+ }
1908
+ if (tok.text === "Object") {
1909
+ if (tokens[i + 1]?.text === "." && tokens[i + 2]?.text === "defineProperty" && tokens[i + 3]?.text === "(" && tokens[i + 4]?.text === "exports" && tokens[i + 5]?.text === "," && tokens[i + 6]?.kind === "string") {
1910
+ names.add(tokens[i + 6].text.slice(1, -1));
1911
+ }
1912
+ }
1913
+ }
1914
+ names.delete("default");
1915
+ return [...names].filter((name) => VALID_IDENT.test(name) && !CJS_INTERNALS.has(name));
1916
+ }
1917
+ function wrapCommonJs(abs, source) {
1918
+ const specifiers = [...new Set(scanRequireSpecifiers(source).map((hit) => hit.specifier))];
1919
+ const prelude = specifiers.map(
1920
+ (spec, index) => `import * as ${CJS_PREFIX}Dep${index} from ${JSON.stringify(CJS_SPECIFIER_PREFIX + spec)};`
1921
+ );
1922
+ const entries = specifiers.map(
1923
+ (spec, index) => `${JSON.stringify(spec)}: ${CJS_PREFIX}Dep${index}`
1924
+ );
1925
+ const names = collectCjsExportNames(source);
1926
+ const detail = JSON.stringify(
1927
+ `${abs} \u91CC\u7684 require() \u8BF4\u660E\u7B26\u65E0\u6CD5\u89E3\u6790\uFF08Node \u5185\u5EFA\u6A21\u5757\u6D4F\u89C8\u5668\u4E0D\u63D0\u4F9B / \u4F9D\u8D56\u672A\u5B89\u88C5 / \u52A8\u6001\u62FC\u63A5\uFF09`
1928
+ );
1929
+ return [
1930
+ ...prelude,
1931
+ `const ${CJS_PREFIX}Map = { ${entries.join(", ")} };`,
1932
+ `const ${CJS_PREFIX}Require = (id) => {`,
1933
+ ` const ns = ${CJS_PREFIX}Map[id];`,
1934
+ ` if (ns === undefined || ns.${CJS_PREFIX}Unresolved === true)`,
1935
+ ` throw new Error('require(' + JSON.stringify(id) + ') \u65E0\u6CD5\u89E3\u6790\uFF1A' + ${detail});`,
1936
+ ` return ns[${JSON.stringify(CJS_EXPORTS_MARKER)}] !== undefined ? ns[${JSON.stringify(CJS_EXPORTS_MARKER)}] : ns;`,
1937
+ `};`,
1938
+ `const ${CJS_PREFIX}Module = { exports: {} };`,
1939
+ "(function (module, exports, require) {",
1940
+ source,
1941
+ `}).call(${CJS_PREFIX}Module.exports, ${CJS_PREFIX}Module, ${CJS_PREFIX}Module.exports, ${CJS_PREFIX}Require);`,
1942
+ `const ${CJS_EXPORTS_MARKER}Value = ${CJS_PREFIX}Module.exports;`,
1943
+ `export const ${CJS_EXPORTS_MARKER} = ${CJS_EXPORTS_MARKER}Value;`,
1944
+ `const ${CJS_PREFIX}Default = ${CJS_EXPORTS_MARKER}Value && ${CJS_EXPORTS_MARKER}Value.__esModule ? ${CJS_EXPORTS_MARKER}Value.default : ${CJS_EXPORTS_MARKER}Value;`,
1945
+ `export default ${CJS_PREFIX}Default;`,
1946
+ ...names.map(
1947
+ (name) => `export const ${name} = ${CJS_EXPORTS_MARKER}Value[${JSON.stringify(name)}];`
1948
+ )
1949
+ ].join("\n");
1950
+ }
1443
1951
  function resolveWithSuffixes(vfs, base) {
1444
1952
  if (vfs.exists(base) && !vfs.isDirectory(base)) return base;
1445
1953
  const asFile2 = VITE_RESOLVE_SUFFIXES.map((suffix) => `${base}${suffix}`);
@@ -1486,15 +1994,42 @@ var AdepWebContainer = (() => {
1486
1994
  [/\bprocess\s*\.\s*env\s*\.\s*NODE_ENV\b/g, JSON.stringify("development")],
1487
1995
  [/\b__VUE_OPTIONS_API__\b/g, "true"],
1488
1996
  [/\b__VUE_PROD_DEVTOOLS__\b/g, "false"],
1489
- [/\b__VUE_PROD_HYDRATION_MISMATCH_DETAILS__\b/g, "false"]
1997
+ [/\b__VUE_PROD_HYDRATION_MISMATCH_DETAILS__\b/g, "false"],
1998
+ [
1999
+ /\bimport\s*\.\s*meta\s*\.\s*env\b/g,
2000
+ '({ BASE_URL: "/", MODE: "development", DEV: true, PROD: false, SSR: false })'
2001
+ ]
1490
2002
  ];
1491
2003
  function applyDefines(code) {
1492
2004
  let out = code;
1493
2005
  for (const [pattern, value] of DEFINES) out = out.replace(pattern, value);
1494
2006
  return out;
1495
2007
  }
2008
+ const cssResolver = {
2009
+ read: (abs) => vfs.exists(abs) && !vfs.isDirectory(abs) ? vfs.readFile(abs) : null,
2010
+ resolve: (spec, importerAbs) => {
2011
+ if (spec.startsWith("./") || spec.startsWith("../") || spec.startsWith("/")) {
2012
+ const base = spec.startsWith("/") ? absoluteFromRoot(spec) : join(dirname(importerAbs), spec);
2013
+ const target = resolveWithSuffixes(vfs, base);
2014
+ return vfs.exists(target) && !vfs.isDirectory(target) ? target : null;
2015
+ }
2016
+ try {
2017
+ return resolveImport(vfs, spec, importerAbs, "import");
2018
+ } catch {
2019
+ return null;
2020
+ }
2021
+ }
2022
+ };
2023
+ function inlineCss(css, importerAbs) {
2024
+ try {
2025
+ return inlineCssImports(css, importerAbs, cssResolver);
2026
+ } catch (error) {
2027
+ if (error instanceof CssImportError) throw new ViteDevError("CSS_IMPORT", error.message);
2028
+ throw error;
2029
+ }
2030
+ }
1496
2031
  function transformModule2(abs, source) {
1497
- if (abs.endsWith(".css")) return cssModule(source);
2032
+ if (abs.endsWith(".css")) return cssModule(inlineCss(source, abs));
1498
2033
  if (abs.endsWith(".json")) return jsonModule(source, abs);
1499
2034
  if (abs.endsWith(".vue")) {
1500
2035
  if (sfcCompiler === void 0)
@@ -1504,7 +2039,9 @@ var AdepWebContainer = (() => {
1504
2039
  );
1505
2040
  const compiled = sfcCompiler(source, abs);
1506
2041
  return [
1507
- ...compiled.styles.map((css, index) => inlineStyleBlock(css, `${abs}#${index}`)),
2042
+ ...compiled.styles.map(
2043
+ (css, index) => inlineStyleBlock(inlineCss(css, abs), `${abs}#${index}`)
2044
+ ),
1508
2045
  applyDefines(stripTypes(compiled.script))
1509
2046
  ].join("\n");
1510
2047
  }
@@ -1513,37 +2050,65 @@ var AdepWebContainer = (() => {
1513
2050
  "JSX_UNSUPPORTED",
1514
2051
  `${abs} \u4F7F\u7528 JSX\uFF1A\u6D4F\u89C8\u5668\u5185 vite \u53EA\u64E6\u9664 TS \u7C7B\u578B\u6807\u6CE8\uFF0C\u4E0D\u8F6C\u8BD1 JSX\uFF08\u8BF7\u7528 h() \u6E32\u67D3\u51FD\u6570\u6216 .vue SFC\uFF09`
1515
2052
  );
1516
- if (abs.endsWith(".ts") || abs.endsWith(".mts")) return applyDefines(stripTypes(source));
1517
- return applyDefines(source);
2053
+ const bare = stripShebang(source);
2054
+ if (abs.endsWith(".ts") || abs.endsWith(".mts")) return applyDefines(stripTypes(bare));
2055
+ if (isCommonJs(abs, bare)) return applyDefines(wrapCommonJs(abs, bare));
2056
+ return applyDefines(bare);
1518
2057
  }
1519
2058
  function absoluteFromRoot(spec) {
1520
2059
  return join(root, spec.replace(/^\/+/, ""));
1521
2060
  }
1522
- async function resolveSpecifier(spec, importerAbs) {
1523
- if (EXTERNAL_SPECIFIER.test(spec) || DATA_OR_BLOB.test(spec)) return spec;
1524
- let target;
2061
+ function resolveToAbs(spec, importerAbs) {
1525
2062
  if (spec.startsWith("./") || spec.startsWith("../") || spec.startsWith("/")) {
1526
2063
  const base = spec.startsWith("/") ? absoluteFromRoot(spec) : join(dirname(importerAbs), spec);
1527
- target = resolveWithSuffixes(vfs, base);
2064
+ const target = resolveWithSuffixes(vfs, base);
1528
2065
  if (!vfs.exists(target) || vfs.isDirectory(target))
1529
2066
  throw new ViteDevError(
1530
2067
  "RESOLVE",
1531
2068
  `\u627E\u4E0D\u5230\u6A21\u5757 "${spec}"\uFF08\u81EA ${importerAbs}\uFF1B\u8BD5\u8FC7\u6269\u5C55\u540D ${VITE_RESOLVE_SUFFIXES.join("/")} \u4E0E\u76EE\u5F55 index\uFF09`
1532
2069
  );
1533
- } else {
1534
- try {
1535
- target = resolveImport(vfs, spec, importerAbs, "import");
1536
- } catch (error) {
1537
- if (error instanceof ResolveError)
1538
- throw new ViteDevError(
1539
- "RESOLVE",
1540
- `${error.message}
2070
+ return target;
2071
+ }
2072
+ try {
2073
+ return resolveImport(vfs, spec, importerAbs, "import");
2074
+ } catch (error) {
2075
+ if (error instanceof ResolveError)
2076
+ throw new ViteDevError(
2077
+ "RESOLVE",
2078
+ `${error.message}
1541
2079
  \uFF08\u5728 ${importerAbs} \u4E2D import "${spec}"\uFF09`
1542
- );
1543
- throw error;
2080
+ );
2081
+ throw error;
2082
+ }
2083
+ }
2084
+ const cjsStubSources = /* @__PURE__ */ new Map();
2085
+ function cjsStubUrl(spec) {
2086
+ let abs = cjsStubSources.get(spec);
2087
+ if (abs === void 0) {
2088
+ abs = `${INLINE_PREFIX}cjs_stub_${cjsStubSources.size}.mjs`;
2089
+ cjsStubSources.set(spec, abs);
2090
+ inlineSources.set(
2091
+ abs,
2092
+ [
2093
+ `export const ${CJS_PREFIX}Unresolved = true;`,
2094
+ `export const ${CJS_PREFIX}Specifier = ${JSON.stringify(spec)};`,
2095
+ "export default undefined;"
2096
+ ].join("\n")
2097
+ );
2098
+ }
2099
+ return loadModuleUrl(abs);
2100
+ }
2101
+ async function resolveSpecifier(spec, importerAbs) {
2102
+ if (spec.startsWith(CJS_SPECIFIER_PREFIX)) {
2103
+ const original = spec.slice(CJS_SPECIFIER_PREFIX.length);
2104
+ try {
2105
+ return await loadModuleUrl(resolveToAbs(original, importerAbs));
2106
+ } catch {
2107
+ return cjsStubUrl(original);
1544
2108
  }
1545
2109
  }
1546
- return loadModuleUrl(target);
2110
+ if (EXTERNAL_SPECIFIER.test(spec) || DATA_OR_BLOB.test(spec)) return spec;
2111
+ return loadModuleUrl(resolveToAbs(spec, importerAbs));
1547
2112
  }
1548
2113
  async function loadModuleUrl(abs) {
1549
2114
  const cached = moduleUrls.get(abs);
@@ -1635,14 +2200,15 @@ var AdepWebContainer = (() => {
1635
2200
  );
1636
2201
  const urls = await Promise.all(entryModuleUrls);
1637
2202
  html = html.replace(/__adep_vite_entry_(\d+)__/g, (_m, idx) => urls[Number(idx)] ?? "");
1638
- const interceptor = `<script>${FN_FETCH_INTERCEPTOR_SCRIPT}<\/script>`;
1639
- html = /<head[^>]*>/i.test(html) ? html.replace(/<head[^>]*>/i, (m) => `${m}${interceptor}`) : `${interceptor}${html}`;
2203
+ const preludeScripts = `<script>${CONSOLE_RELAY_SCRIPT}<\/script><script>${FN_FETCH_INTERCEPTOR_SCRIPT}<\/script>`;
2204
+ html = /<head[^>]*>/i.test(html) ? html.replace(/<head[^>]*>/i, (m) => `${m}${preludeScripts}`) : `${preludeScripts}${html}`;
1640
2205
  const hmr = hmrScript(channelName);
1641
2206
  return /<\/body>/i.test(html) ? html.replace(/<\/(body)>/i, `${hmr}</$1>`) : html + hmr;
1642
2207
  }
1643
2208
  async function rebuild() {
1644
2209
  moduleUrls = /* @__PURE__ */ new Map();
1645
2210
  inlineSources = /* @__PURE__ */ new Map();
2211
+ cjsStubSources.clear();
1646
2212
  inlineSeq = 0;
1647
2213
  let doc;
1648
2214
  try {
@@ -1652,6 +2218,7 @@ var AdepWebContainer = (() => {
1652
2218
  }
1653
2219
  const changed = lastDoc !== null && doc !== lastDoc;
1654
2220
  lastDoc = doc;
2221
+ if (!changed && currentUrl !== "") return;
1655
2222
  if (currentUrl !== "") revokeObjectURL(currentUrl);
1656
2223
  currentUrl = createObjectURL(new Blob([doc], { type: "text/html" }));
1657
2224
  if (changed) {
@@ -1690,7 +2257,7 @@ var AdepWebContainer = (() => {
1690
2257
  const unsubscribeMutate = vfs.onMutate(scheduleRebuild);
1691
2258
  return server;
1692
2259
  }
1693
- var ViteDevError, REGEX_PRECEDING_CHARS, REGEX_PRECEDING_KEYWORDS, isIdentStart, isIdentPart, VITE_RESOLVE_SUFFIXES, INLINE_PREFIX, EXTERNAL_SPECIFIER, DATA_OR_BLOB, MODULE_SCRIPT_SRC_RE, MODULE_SCRIPT_INLINE_RE;
2260
+ var ViteDevError, REGEX_PRECEDING_CHARS, REGEX_PRECEDING_KEYWORDS, isIdentStart, isIdentPart, CJS_PREFIX, CJS_EXPORTS_MARKER, CJS_SPECIFIER_PREFIX, VALID_IDENT, CJS_INTERNALS, VITE_RESOLVE_SUFFIXES, INLINE_PREFIX, EXTERNAL_SPECIFIER, DATA_OR_BLOB, MODULE_SCRIPT_SRC_RE, MODULE_SCRIPT_INLINE_RE;
1694
2261
  var init_vite_dev = __esm({
1695
2262
  "src/vite-dev.ts"() {
1696
2263
  "use strict";
@@ -1699,6 +2266,8 @@ var AdepWebContainer = (() => {
1699
2266
  init_strip_types();
1700
2267
  init_preview_server();
1701
2268
  init_function_fetch_proxy();
2269
+ init_console_relay();
2270
+ init_css_imports();
1702
2271
  ViteDevError = class extends Error {
1703
2272
  constructor(reason, message) {
1704
2273
  super(message);
@@ -1747,6 +2316,22 @@ var AdepWebContainer = (() => {
1747
2316
  ]);
1748
2317
  isIdentStart = (ch) => /[A-Za-z_$]/.test(ch);
1749
2318
  isIdentPart = (ch) => /[A-Za-z0-9_$]/.test(ch);
2319
+ CJS_PREFIX = "__adepCjs";
2320
+ CJS_EXPORTS_MARKER = `${CJS_PREFIX}Exports`;
2321
+ CJS_SPECIFIER_PREFIX = `${CJS_PREFIX}Spec:`;
2322
+ VALID_IDENT = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
2323
+ CJS_INTERNALS = /* @__PURE__ */ new Set([
2324
+ "module",
2325
+ "exports",
2326
+ "require",
2327
+ // 互操作标记而非用户导出:Babel 产物会 defineProperty(exports, "__esModule"),转发它没有意义。
2328
+ "__esModule",
2329
+ `${CJS_EXPORTS_MARKER}`,
2330
+ `${CJS_PREFIX}Default`,
2331
+ `${CJS_PREFIX}Map`,
2332
+ `${CJS_PREFIX}Module`,
2333
+ `${CJS_PREFIX}Require`
2334
+ ]);
1750
2335
  VITE_RESOLVE_SUFFIXES = [".ts", ".js", ".mjs", ".mts", ".vue", ".json", ".css"];
1751
2336
  INLINE_PREFIX = "/__vite_inline_";
1752
2337
  EXTERNAL_SPECIFIER = /^(?:https?:)?\/\//i;
@@ -1761,6 +2346,7 @@ var AdepWebContainer = (() => {
1761
2346
  __export(index_exports, {
1762
2347
  BUNDLE_MODULE_PATH_PREFIX: () => BUNDLE_MODULE_PATH_PREFIX,
1763
2348
  COMPLETABLE_COMMANDS: () => COMPLETABLE_COMMANDS,
2349
+ CONSOLE_RELAY_SCRIPT: () => CONSOLE_RELAY_SCRIPT,
1764
2350
  DEFAULT_MAX_INSTALL_DEPTH: () => DEFAULT_MAX_INSTALL_DEPTH,
1765
2351
  EXTRA_COMMANDS: () => EXTRA_COMMANDS,
1766
2352
  FN_FETCH_INTERCEPTOR_SCRIPT: () => FN_FETCH_INTERCEPTOR_SCRIPT,
@@ -2897,7 +3483,7 @@ var AdepWebContainer = (() => {
2897
3483
 
2898
3484
  // src/npm-client.ts
2899
3485
  init_node_resolve();
2900
- var DEFAULT_MAX_INSTALL_DEPTH = 5;
3486
+ var DEFAULT_MAX_INSTALL_DEPTH = 25;
2901
3487
  var defaultFetch = (url, init) => globalThis.fetch(url, init).then((res) => res);
2902
3488
  function parseSpec(spec) {
2903
3489
  if (spec.startsWith("@")) {
@@ -2922,29 +3508,50 @@ var AdepWebContainer = (() => {
2922
3508
  throw new Error(`${what} \u5931\u8D25\uFF1A\u65E0\u6CD5\u8BBF\u95EE npm \u4E2D\u7EE7\uFF08${url}\uFF0C${reason}\uFF09`, { cause: error });
2923
3509
  }
2924
3510
  }
3511
+ var RATE_LIMIT_MAX_RETRIES = 120;
3512
+ var DEFAULT_RETRY_AFTER_MS = 1e3;
3513
+ var MAX_RETRY_AFTER_MS = 6e4;
3514
+ var defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
3515
+ function retryAfterMs(res) {
3516
+ const raw = res.headers["retry-after"];
3517
+ const seconds = raw === void 0 ? Number.NaN : Number.parseFloat(raw);
3518
+ if (!Number.isFinite(seconds) || seconds <= 0) return DEFAULT_RETRY_AFTER_MS;
3519
+ return Math.min(seconds * 1e3, MAX_RETRY_AFTER_MS);
3520
+ }
2925
3521
  function createNpmClient(options) {
2926
3522
  const fetchImpl = options.fetchImpl ?? defaultFetch;
2927
3523
  const base = options.baseUrl.replace(/\/+$/, "");
2928
3524
  const storage = options.storage;
2929
3525
  const maxDepth = options.maxDepth ?? DEFAULT_MAX_INSTALL_DEPTH;
3526
+ const sleep = options.sleep ?? defaultSleep;
3527
+ async function relayRequest(url, what) {
3528
+ for (let attempt = 0; ; attempt += 1) {
3529
+ const res = await relayFetch(fetchImpl, url, what);
3530
+ if (res.status !== 429) return res;
3531
+ if (attempt >= RATE_LIMIT_MAX_RETRIES) {
3532
+ throw new Error(
3533
+ `${what} \u5931\u8D25\uFF1Anpm \u4E2D\u7EE7\u9650\u901F\uFF08HTTP 429\uFF09\uFF0C\u5DF2\u6309 Retry-After \u9000\u907F\u91CD\u8BD5 ${attempt} \u6B21\u4ECD\u88AB\u62D2\u2014\u2014\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002`
3534
+ );
3535
+ }
3536
+ await sleep(retryAfterMs(res));
3537
+ }
3538
+ }
2930
3539
  async function resolvePackage(name, spec) {
2931
3540
  const params = new URLSearchParams({ name });
2932
3541
  if (spec !== void 0) params.set("spec", spec);
2933
- const res = await relayFetch(
2934
- fetchImpl,
3542
+ const res = await relayRequest(
2935
3543
  `${base}/package?${params.toString()}`,
2936
3544
  `\u89E3\u6790\u5305 ${name}@${spec ?? "latest"}`
2937
3545
  );
2938
3546
  if (!res.ok) {
2939
3547
  throw new Error(
2940
- `\u89E3\u6790\u5305\u5931\u8D25 ${name}@${spec ?? "latest"}\uFF1AHTTP ${res.status}\uFF08\u4E0D\u5728\u767D\u540D\u5355\u6216\u5305\u4E0D\u5B58\u5728\u65F6\u7531\u4E2D\u7EE7\u62D2\u7EDD\uFF09`
3548
+ `\u89E3\u6790\u5305\u5931\u8D25 ${name}@${spec ?? "latest"}\uFF1AHTTP ${res.status}\uFF08\u4E2D\u7EE7\u62D2\u7EDD\uFF1A\u5305\u4E0D\u5B58\u5728 / registry \u4E0D\u53EF\u8FBE / registry \u975E\u767D\u540D\u5355\uFF09`
2941
3549
  );
2942
3550
  }
2943
3551
  return await res.json();
2944
3552
  }
2945
3553
  async function fetchAndUnpack(name, version) {
2946
- const res = await relayFetch(
2947
- fetchImpl,
3554
+ const res = await relayRequest(
2948
3555
  `${base}/tarball?${new URLSearchParams({ name, version }).toString()}`,
2949
3556
  `\u4E0B\u8F7D tarball ${name}@${version}`
2950
3557
  );
@@ -2968,17 +3575,12 @@ var AdepWebContainer = (() => {
2968
3575
  return null;
2969
3576
  }
2970
3577
  }
2971
- async function collect(name, spec, depth, path, staged, onStack, visited, packages, distTagsByName) {
3578
+ async function collect(name, spec, depth, path, staged, visited, packages, distTagsByName) {
2972
3579
  if (depth > maxDepth) {
2973
3580
  throw new Error(
2974
3581
  `\u4F9D\u8D56\u5C42\u7EA7\u8D85\u8FC7\u4E0A\u9650\uFF08${maxDepth}\uFF09\uFF1A${[...path, name].join(" \u2192 ")}\u3002\u8BF7\u6539\u7528\u66F4\u8F7B\u7684\u5305\u6216\u7ECF\u670D\u52A1\u7AEF\u53D1\u5E03\u94FE\u8DEF\u5B89\u88C5\uFF08FN-009 \u5B9E\u65F6\u88C5\u8F7D\uFF09\u3002`
2975
3582
  );
2976
3583
  }
2977
- if (onStack.has(name)) {
2978
- throw new Error(
2979
- `\u68C0\u6D4B\u5230\u5FAA\u73AF\u4F9D\u8D56\uFF1A${[...path, name].join(" \u2192 ")}\u3002\u6D4F\u89C8\u5668\u5B89\u88C5\u4E0D\u652F\u6301\u73AF\u72B6\u4F9D\u8D56\u6811\uFF0C\u8BF7\u79FB\u9664\u73AF\u4E0A\u5305\u7684\u76F8\u4E92\u58F0\u660E\u3002`
2980
- );
2981
- }
2982
3584
  const meta = await resolvePackage(name, spec);
2983
3585
  distTagsByName.set(meta.name, meta.distTags ?? []);
2984
3586
  const key = `${meta.name}@${meta.version}`;
@@ -3002,8 +3604,6 @@ var AdepWebContainer = (() => {
3002
3604
  }
3003
3605
  Object.assign(deps, pkgMeta.dependencies ?? {});
3004
3606
  }
3005
- const nextStack = new Set(onStack);
3006
- nextStack.add(meta.name);
3007
3607
  for (const [depName, depSpec] of Object.entries(deps)) {
3008
3608
  await collect(
3009
3609
  depName,
@@ -3011,7 +3611,6 @@ var AdepWebContainer = (() => {
3011
3611
  depth + 1,
3012
3612
  [...path, meta.name],
3013
3613
  staged,
3014
- nextStack,
3015
3614
  visited,
3016
3615
  packages,
3017
3616
  distTagsByName
@@ -3020,7 +3619,7 @@ var AdepWebContainer = (() => {
3020
3619
  }
3021
3620
  return {
3022
3621
  async registries() {
3023
- const res = await relayFetch(fetchImpl, `${base}/registry`, "\u83B7\u53D6 registry \u5217\u8868");
3622
+ const res = await relayRequest(`${base}/registry`, "\u83B7\u53D6 registry \u5217\u8868");
3024
3623
  if (!res.ok) throw new Error(`\u83B7\u53D6 registry \u5217\u8868\u5931\u8D25\uFF1AHTTP ${res.status}`);
3025
3624
  const body = await res.json();
3026
3625
  return body.registries;
@@ -3030,7 +3629,7 @@ var AdepWebContainer = (() => {
3030
3629
  const staged = /* @__PURE__ */ new Map();
3031
3630
  const packages = [];
3032
3631
  const distTagsByName = /* @__PURE__ */ new Map();
3033
- await collect(name, spec, 1, [], staged, /* @__PURE__ */ new Set(), /* @__PURE__ */ new Set(), packages, distTagsByName);
3632
+ await collect(name, spec, 1, [], staged, /* @__PURE__ */ new Set(), packages, distTagsByName);
3034
3633
  const root = packages[0] ?? { name, version: spec ?? "latest" };
3035
3634
  const downloaded = staged.size > 0;
3036
3635
  for (const [path, contents] of staged) storage.writeFile(path, contents);
@@ -5591,6 +6190,7 @@ self.onmessage = async (event) => {
5591
6190
  const t = raw.trim();
5592
6191
  if (/^'.*'$/.test(t)) return t.slice(1, -1);
5593
6192
  if (/^".*"$/.test(t)) return t.slice(1, -1);
6193
+ if (/^NULL$/i.test(t)) return null;
5594
6194
  return t;
5595
6195
  }
5596
6196
  function parseCreateTable(ddl) {
@@ -5611,50 +6211,109 @@ self.onmessage = async (event) => {
5611
6211
  }
5612
6212
  return { name, columns };
5613
6213
  }
5614
- function parseWhereClauses(whereRaw, cursor) {
5615
- const clauses = [];
5616
- for (const part of whereRaw.split(/\s+AND\s+/i)) {
5617
- const t = part.trim();
5618
- if (t.length === 0) continue;
5619
- if (/\bIS\s+NULL\b/i.test(t)) {
5620
- const col2 = ident(t.split(/\s+IS\s+NULL\b/i)[0] ?? "");
5621
- clauses.push({ column: col2, operator: "IS NULL", value: null, list: false });
5622
- continue;
5623
- }
5624
- if (/\bIS\s+NOT\s+NULL\b/i.test(t)) {
5625
- const col2 = ident(t.split(/\s+IS\s+NOT\s+NULL\b/i)[0] ?? "");
5626
- clauses.push({ column: col2, operator: "IS NOT NULL", value: null, list: false });
5627
- continue;
5628
- }
5629
- const opMatch = /^\s*((?:"[^"]+")|([A-Za-z_][A-Za-z0-9_]*))\s*(=|!=|>=|<=|>|<|like|in|not\s+in)\s*(.+)$/i.exec(
5630
- t
5631
- );
5632
- if (opMatch === null) continue;
5633
- const col = ident(opMatch[1] ?? "");
5634
- const op = (opMatch[3] ?? opMatch[2] ?? "").toLowerCase();
5635
- const rhs = (opMatch[4] ?? "").trim();
5636
- if (op === "in" || op === "not in") {
5637
- const inner = rhs.replace(/^\(|\)$/g, "");
5638
- const items = splitListItems(inner);
5639
- const list = items.map((item) => {
5640
- if (item.trim() === "?") return cursor.take();
5641
- return stripQuotes(item);
5642
- });
5643
- clauses.push({ column: col, operator: op, value: list, list: true });
6214
+ function splitTopLevel(raw, token) {
6215
+ const parts = [];
6216
+ let depth = 0;
6217
+ let inQuote = false;
6218
+ let buffer = "";
6219
+ const n = raw.length;
6220
+ const isTokenAt = (i) => {
6221
+ const word = raw.slice(i, i + token.length);
6222
+ if (word.toUpperCase() !== token) return false;
6223
+ const before = i === 0 ? "" : raw[i - 1] ?? "";
6224
+ const after = raw[i + token.length] ?? "";
6225
+ return !/[A-Za-z0-9_.]/.test(before) && !/[A-Za-z0-9_.]/.test(after);
6226
+ };
6227
+ for (let i = 0; i < n; i += 1) {
6228
+ const ch = raw[i] ?? "";
6229
+ if (ch === "'") {
6230
+ if (inQuote && raw[i + 1] === "'") {
6231
+ buffer += ch + (raw[i + 1] ?? "");
6232
+ i += 1;
6233
+ continue;
6234
+ }
6235
+ inQuote = !inQuote;
6236
+ buffer += ch;
5644
6237
  continue;
5645
6238
  }
5646
- let value;
5647
- if (rhs === "?") {
5648
- value = cursor.take();
6239
+ if (!inQuote && ch === "(") depth += 1;
6240
+ else if (!inQuote && ch === ")") depth -= 1;
6241
+ if (!inQuote && depth === 0 && isTokenAt(i)) {
6242
+ parts.push(buffer);
6243
+ buffer = "";
6244
+ i += token.length - 1;
5649
6245
  } else {
5650
- value = stripQuotes(rhs);
6246
+ buffer += ch;
5651
6247
  }
5652
- clauses.push({ column: col, operator: op, value, list: false });
5653
6248
  }
5654
- return clauses;
6249
+ parts.push(buffer);
6250
+ return parts;
5655
6251
  }
5656
- function matchWhere(clauses, row) {
5657
- return clauses.every((c) => matchValue(row[c.column], c));
6252
+ function unqualifyColumn(raw) {
6253
+ const t = raw.trim();
6254
+ const dot = t.lastIndexOf(".");
6255
+ if (dot > 0 && /^[A-Za-z_][A-Za-z0-9_]*\./.test(t)) return t.slice(dot + 1);
6256
+ return t;
6257
+ }
6258
+ function parseLeftJoins(tail) {
6259
+ const joins = [];
6260
+ const re = /LEFT\s+JOIN\s+((?:"[^"]+")|([A-Za-z_][A-Za-z0-9_]*))\s+([A-Za-z_][A-Za-z0-9_]*)\s+ON\s+([A-Za-z_][A-Za-z0-9_.]*)\s*=\s*([A-Za-z_][A-Za-z0-9_.]*)/gi;
6261
+ let m;
6262
+ while ((m = re.exec(tail)) !== null) {
6263
+ joins.push({
6264
+ table: ident(m[1] ?? ""),
6265
+ alias: m[3] ?? "",
6266
+ leftCol: unqualifyColumn(m[4] ?? ""),
6267
+ rightCol: unqualifyColumn(m[5] ?? "")
6268
+ });
6269
+ }
6270
+ return joins;
6271
+ }
6272
+ function parseWhereClauses(whereRaw, cursor) {
6273
+ const parseAndGroup = (andRaw) => {
6274
+ const clauses = [];
6275
+ for (const part of splitTopLevel(andRaw, "AND")) {
6276
+ const t = part.trim();
6277
+ if (t.length === 0) continue;
6278
+ if (/\bIS\s+NULL\b/i.test(t)) {
6279
+ clauses.push({ column: unqualifyColumn(ident(t.split(/\s+IS\s+NULL\b/i)[0] ?? "")), operator: "IS NULL", value: null, list: false });
6280
+ continue;
6281
+ }
6282
+ if (/\bIS\s+NOT\s+NULL\b/i.test(t)) {
6283
+ clauses.push({ column: unqualifyColumn(ident(t.split(/\s+IS\s+NOT\s+NULL\b/i)[0] ?? "")), operator: "IS NOT NULL", value: null, list: false });
6284
+ continue;
6285
+ }
6286
+ const opMatch = /^\s*((?:"[^"]+")|([A-Za-z_][A-Za-z0-9_.]*))\s*(=|!=|>=|<=|>|<|like|in|not\s+in)\s*(.+)$/i.exec(
6287
+ t
6288
+ );
6289
+ if (opMatch === null) continue;
6290
+ const col = unqualifyColumn(ident(opMatch[1] ?? ""));
6291
+ const op = (opMatch[3] ?? opMatch[2] ?? "").toLowerCase();
6292
+ const rhs = (opMatch[4] ?? "").trim();
6293
+ if (op === "in" || op === "not in") {
6294
+ const inner = rhs.replace(/^\(|\)$/g, "");
6295
+ const items = splitListItems(inner);
6296
+ const list = items.map((item) => {
6297
+ if (item.trim() === "?") return cursor.take();
6298
+ return stripQuotes(item);
6299
+ });
6300
+ clauses.push({ column: col, operator: op, value: list, list: true });
6301
+ continue;
6302
+ }
6303
+ let value;
6304
+ if (rhs === "?") {
6305
+ value = cursor.take();
6306
+ } else {
6307
+ value = stripQuotes(rhs);
6308
+ }
6309
+ clauses.push({ column: col, operator: op, value, list: false });
6310
+ }
6311
+ return clauses;
6312
+ };
6313
+ return splitTopLevel(whereRaw, "OR").map((group) => group.trim()).filter((group) => group.length > 0).map(parseAndGroup);
6314
+ }
6315
+ function matchWhere(groups, row) {
6316
+ return groups.some((clauses) => clauses.every((c) => matchValue(row[c.column], c)));
5658
6317
  }
5659
6318
  function splitListItems(inner) {
5660
6319
  const items = [];
@@ -5674,6 +6333,168 @@ self.onmessage = async (event) => {
5674
6333
  items.push(buffer);
5675
6334
  return items;
5676
6335
  }
6336
+ var ExcludedRef = class {
6337
+ constructor(column) {
6338
+ this.column = column;
6339
+ }
6340
+ };
6341
+ var ColumnRef = class {
6342
+ constructor(column) {
6343
+ this.column = column;
6344
+ }
6345
+ };
6346
+ var ExprRef = class {
6347
+ constructor(source) {
6348
+ this.source = source;
6349
+ }
6350
+ };
6351
+ function resolveSetValue(value, existing, row) {
6352
+ if (value instanceof ExcludedRef) return row[value.column];
6353
+ if (value instanceof ColumnRef) return existing[value.column];
6354
+ if (value instanceof ExprRef) return evalArithmetic(value.source, existing, row);
6355
+ return value;
6356
+ }
6357
+ function evalArithmetic(src, existing, row) {
6358
+ const num = (v) => {
6359
+ const n2 = Number(v);
6360
+ return Number.isFinite(n2) ? n2 : 0;
6361
+ };
6362
+ let i = 0;
6363
+ const n = src.length;
6364
+ const skip = () => {
6365
+ while (i < n && /\s/.test(src[i] ?? "")) i += 1;
6366
+ };
6367
+ const peek = () => {
6368
+ skip();
6369
+ return i < n ? src[i] ?? "" : null;
6370
+ };
6371
+ const parseIdent = () => {
6372
+ skip();
6373
+ const m = /^([A-Za-z_][A-Za-z0-9_]*)/.exec(src.slice(i));
6374
+ if (m === null) return null;
6375
+ i += (m[1] ?? "").length;
6376
+ skip();
6377
+ let col = ident(m[1] ?? "");
6378
+ let excluded = false;
6379
+ if (src[i] === ".") {
6380
+ const m2 = /^\.([A-Za-z_][A-Za-z0-9_]*)/.exec(src.slice(i));
6381
+ if (m2 !== null) {
6382
+ i += (m2[0] ?? "").length;
6383
+ if (col.toLowerCase() === "excluded") excluded = true;
6384
+ col = ident(m2[1] ?? "");
6385
+ }
6386
+ }
6387
+ return { col, excluded };
6388
+ };
6389
+ const parseFactor = () => {
6390
+ const ch = peek();
6391
+ if (ch === "(") {
6392
+ i += 1;
6393
+ const v = parseExpr();
6394
+ skip();
6395
+ if (src[i] === ")") i += 1;
6396
+ return v;
6397
+ }
6398
+ const numMatch = /^(\d+(?:\.\d+)?)/.exec(src.slice(i));
6399
+ if (numMatch !== null) {
6400
+ i += (numMatch[1] ?? "").length;
6401
+ return Number(numMatch[1]);
6402
+ }
6403
+ const id = parseIdent();
6404
+ if (id !== null) {
6405
+ const v = id.excluded ? row[id.col] : existing[id.col];
6406
+ return num(v);
6407
+ }
6408
+ return 0;
6409
+ };
6410
+ const parseTerm = () => {
6411
+ let v = parseFactor();
6412
+ for (; ; ) {
6413
+ const ch = peek();
6414
+ if (ch !== "*" && ch !== "/") return v;
6415
+ i += 1;
6416
+ const rhs = parseFactor();
6417
+ v = ch === "*" ? v * rhs : rhs === 0 ? v : v / rhs;
6418
+ }
6419
+ };
6420
+ const parseExpr = () => {
6421
+ let v = parseTerm();
6422
+ for (; ; ) {
6423
+ const ch = peek();
6424
+ if (ch !== "+" && ch !== "-") return v;
6425
+ i += 1;
6426
+ const rhs = parseTerm();
6427
+ v = ch === "+" ? v + rhs : v - rhs;
6428
+ }
6429
+ };
6430
+ return parseExpr();
6431
+ }
6432
+ function splitInsertTuples(body) {
6433
+ const tuples = [];
6434
+ let i = 0;
6435
+ const n = body.length;
6436
+ while (i < n) {
6437
+ while (i < n && (body[i] === " " || body[i] === " " || body[i] === "\n" || body[i] === "\r" || body[i] === ",")) {
6438
+ i += 1;
6439
+ }
6440
+ if (i >= n) break;
6441
+ if (body[i] !== "(") {
6442
+ return { tuples, conflict: body.slice(i).trim() };
6443
+ }
6444
+ let depth = 0;
6445
+ let j = i;
6446
+ for (; j < n; j += 1) {
6447
+ if (body[j] === "(") depth += 1;
6448
+ else if (body[j] === ")") {
6449
+ depth -= 1;
6450
+ if (depth === 0) break;
6451
+ }
6452
+ }
6453
+ if (j >= n) return { tuples, conflict: null };
6454
+ tuples.push(body.slice(i + 1, j));
6455
+ i = j + 1;
6456
+ }
6457
+ return { tuples, conflict: null };
6458
+ }
6459
+ function parseConflictClause(clause, cursor, fallbackCols) {
6460
+ const m = /^ON\s+CONFLICT(?:\s*\(([^)]*)\))?\s+DO\s+(UPDATE\s+SET\s+([\s\S]+)|NOTHING\s*)$/i.exec(
6461
+ clause.trim()
6462
+ );
6463
+ if (m === null) {
6464
+ throw new SimDbError("DB_UNSAFE_OP", `\u65E0\u6CD5\u89E3\u6790 ON CONFLICT \u5B50\u53E5\uFF1A${clause.trim().slice(0, 60)}\u2026`);
6465
+ }
6466
+ const colsRaw = m[1];
6467
+ const cols = colsRaw === void 0 ? fallbackCols : colsRaw.split(",").map(ident);
6468
+ if (cols.length === 0) throw new SimDbError("DB_UNSAFE_OP", "ON CONFLICT \u51B2\u7A81\u5217\u4E3A\u7A7A");
6469
+ const action = m[2] ?? "";
6470
+ if (/^NOTHING/i.test(action)) return { cols, sets: [] };
6471
+ const setRaw = m[3] ?? "";
6472
+ const sets = splitListItems(setRaw).map((part) => {
6473
+ const eq = /^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*([\s\S]+)$/i.exec(part.trim());
6474
+ if (eq === null) {
6475
+ throw new SimDbError("DB_UNSAFE_OP", `\u65E0\u6CD5\u89E3\u6790 SET \u8D4B\u503C\uFF1A${part.trim().slice(0, 60)}\u2026`);
6476
+ }
6477
+ const col = ident(eq[1] ?? "");
6478
+ const rhs = (eq[2] ?? "").trim();
6479
+ let value;
6480
+ if (rhs === "?") {
6481
+ value = cursor.take();
6482
+ } else {
6483
+ const ex = /^excluded\.([A-Za-z_][A-Za-z0-9_]*)$/i.exec(rhs);
6484
+ if (ex !== null) {
6485
+ value = new ExcludedRef(ident(ex[1] ?? ""));
6486
+ } else if (/^([A-Za-z_][A-Za-z0-9_]*)$/.test(rhs) && !/^NULL$/i.test(rhs)) {
6487
+ value = new ColumnRef(ident(rhs));
6488
+ } else if (/^'.*'$/.test(rhs) || /^".*"$/.test(rhs) || /^NULL$/i.test(rhs)) {
6489
+ value = stripQuotes(rhs);
6490
+ } else {
6491
+ value = new ExprRef(rhs);
6492
+ }
6493
+ }
6494
+ return { col, value };
6495
+ });
6496
+ return { cols, sets };
6497
+ }
5677
6498
  function matchValue(value, clause) {
5678
6499
  const op = clause.operator;
5679
6500
  if (op === "IS NULL") return value === null || value === void 0;
@@ -5827,16 +6648,36 @@ self.onmessage = async (event) => {
5827
6648
  const valueBody = match[4].trim();
5828
6649
  const cursor = new ParamCursor(params);
5829
6650
  const table = this.ensureTable(tableName);
6651
+ const { tuples, conflict } = splitInsertTuples(valueBody);
6652
+ if (tuples.length === 0) throw new SimDbError("DB_UNSAFE_OP", "INSERT \u7F3A\u5C11 VALUES \u5143\u7EC4");
6653
+ const conflictSpec = conflict === null ? null : parseConflictClause(
6654
+ conflict,
6655
+ cursor,
6656
+ table.columns.filter((c) => c.primaryKey).map((c) => c.name)
6657
+ );
5830
6658
  let inserted = 0;
5831
- for (const group of splitListItems(valueBody)) {
5832
- const inner = group.trim().replace(/^\(|\)$/g, "");
5833
- const values = splitListItems(inner).map(
6659
+ for (const tuple of tuples) {
6660
+ const values = splitListItems(tuple).map(
5834
6661
  (item) => item.trim() === "?" ? cursor.take() : stripQuotes(item)
5835
6662
  );
5836
6663
  const row = {};
5837
6664
  cols.forEach((col, i) => {
5838
6665
  row[col] = values[i] ?? null;
5839
6666
  });
6667
+ if (conflictSpec !== null) {
6668
+ const existing = table.rows.find(
6669
+ (r) => conflictSpec.cols.every((c) => r[c] === row[c])
6670
+ );
6671
+ if (existing !== void 0) {
6672
+ const oldRow = { ...existing };
6673
+ for (const set of conflictSpec.sets) {
6674
+ existing[set.col] = resolveSetValue(set.value, oldRow, row);
6675
+ }
6676
+ inserted += 1;
6677
+ void this.persist();
6678
+ continue;
6679
+ }
6680
+ }
5840
6681
  this.applyAutoincrement(table, row);
5841
6682
  table.rows.push(row);
5842
6683
  inserted += 1;
@@ -5905,6 +6746,20 @@ self.onmessage = async (event) => {
5905
6746
  return project(this.catalog(), selectRaw);
5906
6747
  }
5907
6748
  const table = this.ensureTable(tableName);
6749
+ let rows = table.rows;
6750
+ const joins = parseLeftJoins(tail);
6751
+ if (joins.length > 0) {
6752
+ rows = table.rows.map((row) => {
6753
+ const merged = { ...row };
6754
+ for (const j of joins) {
6755
+ const joined = this.tables[j.table]?.rows.find((jr) => jr[j.leftCol] === merged[j.rightCol]);
6756
+ if (joined !== void 0) {
6757
+ for (const [k, v] of Object.entries(joined)) merged[`${j.alias}.${k}`] = v;
6758
+ }
6759
+ }
6760
+ return merged;
6761
+ });
6762
+ }
5908
6763
  const whereMatch = /\bWHERE\b/i.exec(tail);
5909
6764
  const orderMatch = /\bORDER\s+BY\b/i.exec(tail);
5910
6765
  const limitMatch = /\bLIMIT\b/i.exec(tail);
@@ -5913,7 +6768,6 @@ self.onmessage = async (event) => {
5913
6768
  whereMatch.index + whereMatch[0].length,
5914
6769
  indexAfter(whereMatch.index, [orderMatch, limitMatch, offsetMatch], tail)
5915
6770
  );
5916
- let rows = table.rows;
5917
6771
  if (whereRaw.trim().length > 0) {
5918
6772
  const clauses = parseWhereClauses(whereRaw, cursor);
5919
6773
  rows = rows.filter((row) => matchWhere(clauses, row));
@@ -5923,9 +6777,9 @@ self.onmessage = async (event) => {
5923
6777
  orderMatch.index + orderMatch[0].length,
5924
6778
  indexAfter(orderMatch.index, [limitMatch, offsetMatch], tail)
5925
6779
  );
5926
- const oc = /^\s*((?:"[^"]+")|([A-Za-z_][A-Za-z0-9_]*))\s+(asc|desc)/i.exec(orderRaw);
6780
+ const oc = /^\s*((?:"[^"]+")|([A-Za-z_][A-Za-z0-9_.]*))\s+(asc|desc)/i.exec(orderRaw);
5927
6781
  if (oc !== null) {
5928
- const col = ident(oc[1]);
6782
+ const col = unqualifyColumn(ident(oc[1]));
5929
6783
  const dir = oc[3].toLowerCase();
5930
6784
  rows = [...rows].toSorted((a, b) => {
5931
6785
  const av = a[col];
@@ -5970,6 +6824,15 @@ self.onmessage = async (event) => {
5970
6824
  const end = candidates.length === 0 ? -1 : Math.min(...candidates);
5971
6825
  return end === -1 ? tail.length : end;
5972
6826
  }
6827
+ function parseSelectItem(raw) {
6828
+ const t = raw.trim();
6829
+ const as = /\s+AS\s+([A-Za-z_][A-Za-z0-9_]*)$/i.exec(t);
6830
+ let name = as === null ? t : t.slice(0, as.index).trim();
6831
+ if (unqualifyColumn(name) === "*") return { name: "", qualified: "", alias: "", star: true };
6832
+ const qualified = /^[A-Za-z_][A-Za-z0-9_]*\.[A-Za-z_][A-Za-z0-9_]*$/.test(name) ? ident(name) : "";
6833
+ const plain = unqualifyColumn(ident(name));
6834
+ return { name: plain, qualified, alias: as === null ? plain : ident(as[1] ?? ""), star: false };
6835
+ }
5973
6836
  function project(rows, selectRaw) {
5974
6837
  if (/^count\s*\(\s*\*/i.test(selectRaw) || /^count\s*\(\s*1\)/i.test(selectRaw)) {
5975
6838
  const alias = selectRaw.match(/\bAS\s+([A-Za-z_][A-Za-z0-9_]*)/i)?.[1] ?? "n";
@@ -5980,10 +6843,21 @@ self.onmessage = async (event) => {
5980
6843
  return [{ [constMatch[2]]: Number(constMatch[1]) }];
5981
6844
  }
5982
6845
  if (selectRaw.trim() === "*") return rows;
5983
- const cols = selectRaw.split(",").map((s) => ident(s.trim()));
6846
+ const items = selectRaw.split(",").map(parseSelectItem);
6847
+ const valueOf = (row, item) => item.qualified !== "" && row[item.qualified] !== void 0 ? row[item.qualified] : row[item.name];
6848
+ if (items.some((item) => item.star)) {
6849
+ return rows.map((row) => {
6850
+ const out = { ...row };
6851
+ for (const item of items) {
6852
+ if (item.star) continue;
6853
+ out[item.alias] = valueOf(row, item);
6854
+ }
6855
+ return out;
6856
+ });
6857
+ }
5984
6858
  return rows.map((row) => {
5985
6859
  const out = {};
5986
- for (const col of cols) out[col] = row[col];
6860
+ for (const item of items) out[item.alias] = valueOf(row, item);
5987
6861
  return out;
5988
6862
  });
5989
6863
  }
@@ -7182,5 +8056,6 @@ self.onmessage = async (event) => {
7182
8056
 
7183
8057
  // src/index.ts
7184
8058
  init_function_fetch_proxy();
8059
+ init_console_relay();
7185
8060
  return __toCommonJS(index_exports);
7186
8061
  })();