@adep/web-container 0.2.2 → 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.
package/dist/index.js CHANGED
@@ -134,8 +134,17 @@ function resolvePackageEntry(meta, pkgDirAbs, condition) {
134
134
  if (typeof exp !== "object" || Array.isArray(exp)) {
135
135
  throw new ResolveError(`${context} \u5F62\u6001\u4E0D\u652F\u6301\uFF08exports \u53EA\u80FD\u662F\u5B57\u7B26\u4E32\u6216\u5BF9\u8C61\uFF09`);
136
136
  }
137
- const dot = exp["."];
137
+ const table = exp;
138
+ const dot = table["."];
139
+ const order = condition === "import" ? IMPORT_CONDITION_ORDER : REQUIRE_CONDITION_ORDER;
140
+ const resolveRel = (rel) => withinPackage(pkgDirAbs, rel, context);
138
141
  if (dot === void 0) {
142
+ const keys = Object.keys(table);
143
+ if (keys.length > 0 && keys.every((key) => !key.startsWith("."))) {
144
+ const shorthand = pickConditionTarget(table, order, resolveRel, context);
145
+ if (shorthand !== null) return shorthand;
146
+ throw new ResolveError(`${context}\uFF1A\u5305\u6839\u6761\u4EF6\u5BF9\u8C61\u91CC\u6CA1\u6709 ${order.join("/")} \u5165\u53E3`);
147
+ }
139
148
  throw new ResolveError(
140
149
  `${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`
141
150
  );
@@ -146,8 +155,6 @@ function resolvePackageEntry(meta, pkgDirAbs, condition) {
146
155
  if (typeof dot !== "object" || Array.isArray(dot)) {
147
156
  throw new ResolveError(`${context}\uFF1Aexports["."] \u5F62\u6001\u4E0D\u652F\u6301\uFF08\u4EC5\u63A5\u53D7\u5B57\u7B26\u4E32\u6216\u6761\u4EF6\u5BF9\u8C61\uFF09`);
148
157
  }
149
- const order = condition === "import" ? IMPORT_CONDITION_ORDER : REQUIRE_CONDITION_ORDER;
150
- const resolveRel = (rel) => withinPackage(pkgDirAbs, rel, context);
151
158
  const hit = pickConditionTarget(dot, order, resolveRel, context);
152
159
  if (hit !== null) return hit;
153
160
  throw new ResolveError(`${context}\uFF1Aexports["."] \u6761\u4EF6\u5BF9\u8C61\u91CC\u6CA1\u6709 ${order.join("/")} \u5165\u53E3`);
@@ -346,6 +353,28 @@ var init_strip_types = __esm({
346
353
  }
347
354
  return "";
348
355
  }
356
+ /**
357
+ * `interface` / `type` 声明之前若有 `export` 关键字,返回该关键字的起始下标,否则原样返回。
358
+ *
359
+ * 为什么必须吞掉:`export interface X { … }` 里 `interface` 分支只擦它自己那一段,
360
+ * 留下的孤立 `export` 是**非法 JS**——浏览器解析模块时直接
361
+ * `SyntaxError: Unexpected token 'export'`(实测 countdown 项目 `lib/auth.ts` 的
362
+ * `export interface AppUser`:整条预览链路因此白屏)。`export type X = …` 由 `export`
363
+ * 分支整条擦除,不受影响。
364
+ *
365
+ * 判据分两步:token 回看确认前一个显著 token 就是 `export`(避免误吞 `re-export` 之类
366
+ * 同名标识符——那会在下面按字符再校验一次);位置则往前跳空白后左推 6 个字符,并要求
367
+ * 再前一个字符不是标识符字符(`xexport interface` 不吞)。
368
+ */
369
+ includeLeadingExport(start) {
370
+ if (this.tokenAt(2) !== "export") return start;
371
+ let end = start - 1;
372
+ while (end >= 0 && /\s/.test(this.src[end])) end--;
373
+ if (end < 5 || this.src.slice(end - 5, end + 1) !== "export") return start;
374
+ const before = this.src[end - 6];
375
+ if (before !== void 0 && IDENT_PART.test(before)) return start;
376
+ return end - 5;
377
+ }
349
378
  /** 擦除 `[from, to)`:填等长空格,换行照抄——擦完行号与原文件一致。 */
350
379
  erase(from, to) {
351
380
  for (let j = Math.max(from, 0); j < to; j++) this.chars[j] = this.src[j] === "\n" ? "\n" : " ";
@@ -485,19 +514,31 @@ var init_strip_types = __esm({
485
514
  }
486
515
  switch (word) {
487
516
  case "interface": {
488
- const after = this.skipWhitespaceFrom(this.skipNameAndParams(start + word.length));
517
+ const heritage = this.skipInterfaceExtends(this.skipNameAndParams(start + word.length));
518
+ const after = heritage === null ? null : this.skipWhitespaceFrom(heritage);
489
519
  if (after === null || this.src[after] !== "{") return;
490
520
  const end = this.scanBalanced(after, "{", "}");
491
- this.erase(start, end);
521
+ this.erase(this.includeLeadingExport(start), end);
492
522
  this.i = end;
493
523
  this.pushToken("erased");
494
524
  return;
495
525
  }
496
526
  case "type": {
527
+ if (this.frames[this.frames.length - 1]?.specifierList === true) {
528
+ const specifierEnd = this.scanTypeOnlySpecifier(this.i);
529
+ if (specifierEnd !== null) {
530
+ this.erase(start, specifierEnd);
531
+ this.i = specifierEnd;
532
+ } else {
533
+ this.erase(start, start + word.length);
534
+ }
535
+ this.pushToken("erased");
536
+ return;
537
+ }
497
538
  const after = this.skipWhitespaceFrom(this.skipNameAndParams(this.i));
498
539
  if (after === null || this.src[after] !== "=") return;
499
540
  const end = this.scanTypeExpression(after + 1, true);
500
- this.erase(start, end);
541
+ this.erase(this.includeLeadingExport(start), end);
501
542
  this.i = end;
502
543
  this.pushToken("erased");
503
544
  return;
@@ -524,16 +565,20 @@ var init_strip_types = __esm({
524
565
  this.pushToken("erased");
525
566
  return;
526
567
  }
527
- case "class":
528
- this.pendingClassBody = true;
568
+ case "class": {
569
+ const next = this.skipWhitespaceFrom(this.i);
570
+ if (next !== null && (this.src[next] === "{" || IDENT_START.test(this.src[next]))) {
571
+ this.pendingClassBody = true;
572
+ }
529
573
  return;
574
+ }
530
575
  case "as":
531
576
  case "satisfies": {
532
577
  if (this.frames[this.frames.length - 1]?.specifierList === true) return;
533
578
  if (this.tokenAt(2) === "*" || this.tokenAt(2) === "type") return;
534
579
  const nextChar = this.skipWhitespaceFrom(this.i);
535
580
  if (nextChar === null || "=,:]})".includes(this.src[nextChar])) return;
536
- const end = this.scanTypeExpression(this.i, false);
581
+ const end = this.scanTypeExpression(this.i, true);
537
582
  this.erase(start, end);
538
583
  this.i = end;
539
584
  return;
@@ -669,6 +714,62 @@ var init_strip_types = __esm({
669
714
  this.i = end;
670
715
  return true;
671
716
  }
717
+ /**
718
+ * `interface X extends A, B<T> {` 的继承子句:返回接口体 `{` 的下标。
719
+ *
720
+ * 不处理 `extends` 会让 `interface` 分支取不到 `{` 而**整条不擦**——`export interface
721
+ * DecodedEvent extends CountdownEvent { … }` 原样留在产物里,浏览器解析即
722
+ * `SyntaxError: Unexpected token 'export'`(实测 countdown 的 lib/date.ts;同项目两个
723
+ * `.vue` 产物是它的级联失败)。无 `extends` 时原样返回入参(等价旧行为);遇到字符串 /
724
+ * 配不平的泛型一律返回 null(判不准就不擦)。
725
+ */
726
+ skipInterfaceExtends(from) {
727
+ if (from === null) return null;
728
+ const j = this.skipWhitespaceFrom(from);
729
+ if (j === null || !this.src.startsWith("extends", j) || IDENT_PART.test(this.src[j + 7] ?? "")) {
730
+ return j;
731
+ }
732
+ let k = this.skipWhitespaceFrom(j + 7);
733
+ while (k !== null) {
734
+ const c = this.src[k];
735
+ if (c === "{" || c === ";") return k;
736
+ if (c === "<") {
737
+ const end = this.scanTypeParams(k);
738
+ if (end === null) return null;
739
+ k = end;
740
+ continue;
741
+ }
742
+ if (c === "'" || c === '"' || c === "`") return null;
743
+ k = this.skipWhitespaceFrom(k + 1);
744
+ }
745
+ return null;
746
+ }
747
+ /**
748
+ * 「仅类型说明符」`type X [as Y]` 的擦除终点(返回应擦到、不含的下标)。
749
+ *
750
+ * - `type` 之后不是标识符 → null(调用方退化为只擦关键字,不猜);
751
+ * - 连带**其后的**逗号一起擦(`{ type A, b }` → `{ b }`);末位说明符没有逗号,
752
+ * 留下的 `{ a, }` 是合法尾逗号,无需回首删前导逗号;
753
+ * - `as Y` 重命名一并擦除(只影响类型侧,运行时无绑定)。
754
+ */
755
+ scanTypeOnlySpecifier(from) {
756
+ let j = this.skipWhitespaceFrom(from);
757
+ if (j === null || !IDENT_START.test(this.src[j])) return null;
758
+ j++;
759
+ while (j < this.src.length && IDENT_PART.test(this.src[j])) j++;
760
+ const asAt = this.skipWhitespaceFrom(j);
761
+ if (asAt !== null && this.src.startsWith("as", asAt) && !IDENT_PART.test(this.src[asAt + 2] ?? "")) {
762
+ const nameAt = this.skipWhitespaceFrom(asAt + 2);
763
+ if (nameAt !== null && IDENT_START.test(this.src[nameAt])) {
764
+ let k = nameAt + 1;
765
+ while (k < this.src.length && IDENT_PART.test(this.src[k])) k++;
766
+ j = k;
767
+ }
768
+ }
769
+ const next = this.skipWhitespaceFrom(j);
770
+ if (next !== null && this.src[next] === ",") return next + 1;
771
+ return j;
772
+ }
672
773
  /**
673
774
  * `{` 是 import / export 的说明符列表吗——`{ a as b }` 覆盖 `import { … }`、
674
775
  * `export { … }` 与 `import def, { … }` 三种写法(后者说明符花括号的前驱 token 是 `,`)。
@@ -679,8 +780,8 @@ var init_strip_types = __esm({
679
780
  return back1 === "," && this.tokenAt(3) === "import";
680
781
  }
681
782
  /**
682
- * `(` 是否为参数列表(声明位):`function f(`、类体里的方法 `m(`、箭头 `=> (`,
683
- * 以及出现在 `(` `,` `=` `>` `:` `[` `{` `}` `;` 之后(如 `map((v: T) => v)` 的内层括号)。
783
+ * `(` 是否为参数列表(声明位):`function f(`、`async` 箭头 `async (`、类体里的方法 `m(`、
784
+ * 箭头 `=> (`,以及出现在 `(` `,` `=` `>` `:` `[` `{` `}` `;` 之后(如 `map((v: T) => v)` 的内层括号)。
684
785
  * 调用位 `foo(` 与控制流 `if (` `for (` 都不算。
685
786
  * 误判成声明位也不足以擦掉什么:`:` 还要过 `isAnnotationColon` 的「名字前驱必须是
686
787
  * `(` `,` `{` `;` 修饰符」这一关,而三元表达式的中间段前面必然是 `?`。
@@ -689,6 +790,7 @@ var init_strip_types = __esm({
689
790
  if (this.afterFunctionKeyword) return true;
690
791
  if (this.tokenAt(2) === "function" && IDENT_START.test(this.tokenAt(1))) return true;
691
792
  if (this.afterArrow) return true;
793
+ if (this.tokenAt(1) === "async") return true;
692
794
  if (this.tokenAt(1) === "return") return true;
693
795
  if (this.inClassBody() && IDENT_PART.test(this.prevSignificantChar(at - 1))) return true;
694
796
  const prev = this.prevSignificantChar(at - 1);
@@ -728,7 +830,7 @@ var init_strip_types = __esm({
728
830
  const generic = this.scanTypeParams(j);
729
831
  return generic === null ? j : generic;
730
832
  }
731
- /** `<T, U extends X>`:返回 `>` 之后的下标;跨到 `)` `]` `;` 换行前配不平则 null。 */
833
+ /** `<T, U extends X>`:返回 `>` 之后的下标;尖括号内任何非 `<`/`>` 字符(含 `]` `;` `\n` `)`)都是合法类型字符,配不平自然到文件尾返回 null。 */
732
834
  scanTypeParams(from) {
733
835
  if (this.src[from] !== "<") return null;
734
836
  let depth = 0;
@@ -739,8 +841,7 @@ var init_strip_types = __esm({
739
841
  else if (c === ">") {
740
842
  depth--;
741
843
  if (depth === 0) return j + 1;
742
- } else if (c === ")" || c === "]" || c === ";" || c === "\n") return null;
743
- else if (c === "'" || c === '"') j = this.scanQuoted(j) - 1;
844
+ } else if (c === "'" || c === '"') j = this.scanQuoted(j) - 1;
744
845
  else if (c === "`") j = this.scanTemplate(j) - 1;
745
846
  }
746
847
  return null;
@@ -872,13 +973,14 @@ var init_strip_types = __esm({
872
973
  /**
873
974
  * 行尾处类型是否仍在继续:`type Id = string\n | number` 要接得上,
874
975
  * 而 `const x: Foo\nconst y = 1` 必须停。判据是两侧的非空邻字——
875
- * 前一个是连接符(`| & < > = , . ? : (`)或后一个是连接符 / 闭合符(`| & , . ? : ) ] } >`)。
976
+ * 前一个是连接符(`| & < = , . ? : (`,不含 `>`——`Foo<T>` 后换行是语句边界,
977
+ * 含 `>` 会把下一行的 `try` 等吞进类型区间)或后一个是连接符 / 闭合符(`| & , . ? : ) ] } >`)。
876
978
  */
877
979
  typeContinuesAt(index) {
878
980
  for (let j = index - 1; j >= 0; j--) {
879
981
  const c = this.src[j];
880
982
  if (/\s/.test(c)) continue;
881
- if ("|&<>=,.?:(".includes(c)) return true;
983
+ if ("|&<=,.?:(".includes(c)) return true;
882
984
  break;
883
985
  }
884
986
  for (let j = index + 1; j < this.src.length; j++) {
@@ -892,6 +994,206 @@ var init_strip_types = __esm({
892
994
  }
893
995
  });
894
996
 
997
+ // packages/web-container/src/css-imports.ts
998
+ function isLocalSpec(spec) {
999
+ return spec.startsWith("./") || spec.startsWith("../") || spec.startsWith("/");
1000
+ }
1001
+ function skipString(css, start) {
1002
+ const quote = css[start];
1003
+ let i = start + 1;
1004
+ while (i < css.length) {
1005
+ if (css[i] === "\\") {
1006
+ i += 2;
1007
+ continue;
1008
+ }
1009
+ if (css[i] === quote) return i + 1;
1010
+ i++;
1011
+ }
1012
+ return css.length;
1013
+ }
1014
+ function matchParen(text, open) {
1015
+ let depth = 0;
1016
+ let i = open;
1017
+ while (i < text.length) {
1018
+ const ch = text[i];
1019
+ if (ch === '"' || ch === "'") {
1020
+ i = skipString(text, i);
1021
+ continue;
1022
+ }
1023
+ if (ch === "(") depth++;
1024
+ else if (ch === ")") {
1025
+ depth--;
1026
+ if (depth === 0) return i;
1027
+ }
1028
+ i++;
1029
+ }
1030
+ return text.length;
1031
+ }
1032
+ function parseSpecifier(css, from) {
1033
+ let i = from;
1034
+ while (i < css.length && /\s/.test(css[i])) i++;
1035
+ const urlHead = /^url\s*\(/i.exec(css.slice(i, i + 8));
1036
+ if (urlHead !== null) {
1037
+ const open = i + urlHead[0].length - 1;
1038
+ const close = matchParen(css, open);
1039
+ if (close >= css.length) return { spec: null, next: i };
1040
+ const inner = css.slice(open + 1, close).trim();
1041
+ const quoted = inner.startsWith('"') || inner.startsWith("'");
1042
+ return { spec: quoted ? inner.slice(1, -1).trim() : inner, next: close + 1 };
1043
+ }
1044
+ const quote = css[i];
1045
+ if (quote === '"' || quote === "'") {
1046
+ const end = skipString(css, i);
1047
+ if (css[end - 1] !== quote) return { spec: null, next: i };
1048
+ return { spec: css.slice(i + 1, end - 1), next: end };
1049
+ }
1050
+ return { spec: null, next: i };
1051
+ }
1052
+ function parseImport(css, start) {
1053
+ const parsed = parseSpecifier(css, start + IMPORT_KEYWORD.length);
1054
+ if (parsed.spec === null) return null;
1055
+ let j = parsed.next;
1056
+ let depth = 0;
1057
+ while (j < css.length) {
1058
+ const ch = css[j];
1059
+ if (ch === '"' || ch === "'") {
1060
+ j = skipString(css, j);
1061
+ continue;
1062
+ }
1063
+ if (ch === "(") depth++;
1064
+ else if (ch === ")") depth--;
1065
+ else if (ch === ";" && depth <= 0) break;
1066
+ else if (ch === "{" || ch === "}") return null;
1067
+ j++;
1068
+ }
1069
+ if (j >= css.length) return null;
1070
+ return {
1071
+ start,
1072
+ end: j + 1,
1073
+ spec: parsed.spec,
1074
+ conditions: css.slice(parsed.next, j).trim(),
1075
+ raw: css.slice(start, j + 1)
1076
+ };
1077
+ }
1078
+ function scanCssImports(css) {
1079
+ const hits = [];
1080
+ let i = 0;
1081
+ while (i < css.length) {
1082
+ const ch = css[i];
1083
+ if (ch === "/" && css[i + 1] === "*") {
1084
+ const close = css.indexOf("*/", i + 2);
1085
+ i = close === -1 ? css.length : close + 2;
1086
+ continue;
1087
+ }
1088
+ if (ch === '"' || ch === "'") {
1089
+ i = skipString(css, i);
1090
+ continue;
1091
+ }
1092
+ if (ch === "@" && /^@import(?![-\w])/i.test(css.slice(i, i + IMPORT_KEYWORD.length + 1))) {
1093
+ const hit = parseImport(css, i);
1094
+ if (hit !== null) {
1095
+ hits.push(hit);
1096
+ i = hit.end;
1097
+ continue;
1098
+ }
1099
+ }
1100
+ i++;
1101
+ }
1102
+ return hits;
1103
+ }
1104
+ function stripCharset(css) {
1105
+ return css.replace(/^\uFEFF/, "").replace(/^\s*@charset\s+(["'])[^"']*\1\s*;/i, "");
1106
+ }
1107
+ function splitImportConditions(conditions) {
1108
+ let rest = conditions.trim();
1109
+ let layer = null;
1110
+ const layerFn = /^layer\s*\(/i.exec(rest);
1111
+ if (layerFn !== null) {
1112
+ const open = layerFn[0].length - 1;
1113
+ const close = matchParen(rest, open);
1114
+ layer = rest.slice(open + 1, close).trim();
1115
+ rest = rest.slice(close + 1).trim();
1116
+ } else if (/^layer(?![-\w(])/i.test(rest)) {
1117
+ layer = "";
1118
+ rest = rest.slice("layer".length).trim();
1119
+ }
1120
+ let supports = "";
1121
+ const supportsFn = /^supports\s*\(/i.exec(rest);
1122
+ if (supportsFn !== null) {
1123
+ const open = supportsFn[0].length - 1;
1124
+ const close = matchParen(rest, open);
1125
+ supports = rest.slice(open + 1, close).trim();
1126
+ rest = rest.slice(close + 1).trim();
1127
+ }
1128
+ return { layer, supports, media: rest };
1129
+ }
1130
+ function applyImportConditions(css, conditions) {
1131
+ if (conditions === "") return css;
1132
+ const { layer, supports, media } = splitImportConditions(conditions);
1133
+ let out = css;
1134
+ if (supports !== "") out = `@supports ${supports} {
1135
+ ${out}
1136
+ }`;
1137
+ if (layer !== null) out = layer === "" ? `@layer {
1138
+ ${out}
1139
+ }` : `@layer ${layer} {
1140
+ ${out}
1141
+ }`;
1142
+ if (media !== "") out = `@media ${media} {
1143
+ ${out}
1144
+ }`;
1145
+ return out;
1146
+ }
1147
+ function expand(css, importerAbs, resolver, seen) {
1148
+ const hits = scanCssImports(css);
1149
+ if (hits.length === 0) return css;
1150
+ const parts = [];
1151
+ let cursor = 0;
1152
+ for (const hit of hits) {
1153
+ parts.push(css.slice(cursor, hit.start));
1154
+ parts.push(expandHit(hit, importerAbs, resolver, seen));
1155
+ cursor = hit.end;
1156
+ }
1157
+ parts.push(css.slice(cursor));
1158
+ return parts.join("");
1159
+ }
1160
+ function expandHit(hit, importerAbs, resolver, seen) {
1161
+ if (hit.spec === null) return hit.raw;
1162
+ const spec = hit.spec.trim();
1163
+ if (spec === "" || EXTERNAL_SPEC.test(spec)) return hit.raw;
1164
+ const abs = resolver.resolve(spec, importerAbs);
1165
+ if (abs === null) {
1166
+ if (isLocalSpec(spec))
1167
+ throw new CssImportError(
1168
+ `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`
1169
+ );
1170
+ return hit.raw;
1171
+ }
1172
+ if (!abs.toLowerCase().endsWith(".css")) return hit.raw;
1173
+ if (seen.has(abs)) return "";
1174
+ seen.add(abs);
1175
+ const source = resolver.read(abs);
1176
+ if (source === null) return hit.raw;
1177
+ return applyImportConditions(expand(stripCharset(source), abs, resolver, seen), hit.conditions);
1178
+ }
1179
+ function inlineCssImports(css, importerAbs, resolver) {
1180
+ return expand(css, importerAbs, resolver, /* @__PURE__ */ new Set([importerAbs]));
1181
+ }
1182
+ var CssImportError, IMPORT_KEYWORD, EXTERNAL_SPEC;
1183
+ var init_css_imports = __esm({
1184
+ "packages/web-container/src/css-imports.ts"() {
1185
+ "use strict";
1186
+ CssImportError = class extends Error {
1187
+ constructor(message) {
1188
+ super(message);
1189
+ this.name = "CssImportError";
1190
+ }
1191
+ };
1192
+ IMPORT_KEYWORD = "@import";
1193
+ EXTERNAL_SPEC = /^(?:[A-Za-z][A-Za-z0-9+.-]*:|\/\/)/i;
1194
+ }
1195
+ });
1196
+
895
1197
  // packages/web-container/src/preview-server.ts
896
1198
  var preview_server_exports = {};
897
1199
  __export(preview_server_exports, {
@@ -905,6 +1207,20 @@ function resolveLocal(vfs, src, baseDir) {
905
1207
  if (!vfs.exists(abs) || vfs.isDirectory(abs)) return null;
906
1208
  return abs;
907
1209
  }
1210
+ function cssResolverOf(vfs) {
1211
+ return {
1212
+ read: (abs) => vfs.exists(abs) && !vfs.isDirectory(abs) ? vfs.readFile(abs) : null,
1213
+ resolve: (spec, importerAbs) => {
1214
+ if (spec.startsWith("./") || spec.startsWith("../") || spec.startsWith("/"))
1215
+ return resolveLocal(vfs, spec, dirname(importerAbs));
1216
+ try {
1217
+ return resolveImport(vfs, spec, importerAbs, "import");
1218
+ } catch {
1219
+ return null;
1220
+ }
1221
+ }
1222
+ };
1223
+ }
908
1224
  function inlineAssets(html, vfs, baseDir) {
909
1225
  let out = html.replace(
910
1226
  /<script\b([^>]*?)\bsrc\s*=\s*(["'])(.*?)\2([^>]*)><\/script>/gi,
@@ -921,7 +1237,13 @@ function inlineAssets(html, vfs, baseDir) {
921
1237
  (whole, _pre, _q, _post, _r, orig) => {
922
1238
  const abs = resolveLocal(vfs, orig, baseDir);
923
1239
  if (abs === null) return whole;
924
- return `<style>${vfs.readFile(abs)}</style>`;
1240
+ const css = vfs.readFile(abs);
1241
+ try {
1242
+ return `<style>${inlineCssImports(css, abs, cssResolverOf(vfs))}</style>`;
1243
+ } catch (error) {
1244
+ if (error instanceof CssImportError) return `<style>${css}</style>`;
1245
+ throw error;
1246
+ }
925
1247
  }
926
1248
  );
927
1249
  return out;
@@ -994,6 +1316,8 @@ var init_preview_server = __esm({
994
1316
  "packages/web-container/src/preview-server.ts"() {
995
1317
  "use strict";
996
1318
  init_path();
1319
+ init_node_resolve();
1320
+ init_css_imports();
997
1321
  EXTERNAL_SRC = /(?:^https?:)?\/\//i;
998
1322
  }
999
1323
  });
@@ -1205,7 +1529,8 @@ var init_function_fetch_proxy = __esm({
1205
1529
  ' if (u.pathname.indexOf("/api/") !== 0 && u.pathname !== "/api") {',
1206
1530
  " return ORIGINAL_FETCH(input, init);",
1207
1531
  " }",
1208
- " if (window.parent === window) return ORIGINAL_FETCH(input, init);",
1532
+ " var bridgeWindow = window.parent !== window ? window.parent : window.opener;",
1533
+ " if (!bridgeWindow) return ORIGINAL_FETCH(input, init);",
1209
1534
  ' method = (method || "GET").toUpperCase();',
1210
1535
  " var target = u.pathname + u.search;",
1211
1536
  " return readBody(input, init).then(function (textBody) {",
@@ -1216,10 +1541,75 @@ var init_function_fetch_proxy = __esm({
1216
1541
  ` resolve(new Response('{"error":{"code":"FN_PROXY_TIMEOUT","message":"\\u4e91\\u51fd\\u6570\\u6267\\u884c\\u8d85\\u65f6"}}', { status: 504, headers: { "content-type": "application/json" } }));`,
1217
1542
  " }, TIMEOUT_MS);",
1218
1543
  " pending[id] = { resolve: resolve, timer: timer };",
1219
- ' window.parent.postMessage({ __adepFnRequest: true, id: id, method: method, url: target, headers: headers, body: textBody }, "*");',
1544
+ ' bridgeWindow.postMessage({ __adepFnRequest: true, id: id, method: method, url: target, headers: headers, body: textBody }, "*");',
1220
1545
  " });",
1221
1546
  " });",
1222
1547
  " };",
1548
+ "",
1549
+ " /* \u2014\u2014 blob URL SPA \u8DEF\u7531\u652F\u6301 \u2014\u2014",
1550
+ " blob: \u662F\u4E0D\u53EF\u5206\u5C42 scheme\uFF0Chistory.pushState('/about') \u5185\u90E8\u89E3\u6790\u76F8\u5BF9\u8DEF\u5F84\u4F1A\u629B",
1551
+ " TypeError \u2192 SPA history \u6A21\u5F0F\u8DEF\u7531\u5D29\u6E83\u3002patch pushState/replaceState\uFF0C\u5BF9\u76F8\u5BF9",
1552
+ " \u8DEF\u5F84\u76F4\u63A5\u541E\u6389\uFF08\u4E0D\u5BFC\u822A\u3001\u4E0D\u629B\u9519\uFF09\uFF0C\u8DEF\u7531\u5E93\u5185\u90E8\u72B6\u6001\u81EA\u884C\u66F4\u65B0\uFF1Blocation.pathname",
1553
+ " \u8986\u76D6\u4E3A\u5F53\u524D\u8DEF\u7531\u8DEF\u5F84\uFF0C\u4F9B\u8DEF\u7531\u5E93\u521D\u59CB\u5316\u65F6\u8BFB\u53D6\u3002sessionStorage \u6301\u4E45\u5316\uFF0C\u5237\u65B0\u540E\u6062\u590D\u3002 */",
1554
+ ' if (window.location.protocol === "blob:") {',
1555
+ ' var SPA_KEY = "__adep_spa_path";',
1556
+ ' var spaPath = "/";',
1557
+ " try {",
1558
+ " var _saved = window.sessionStorage.getItem(SPA_KEY);",
1559
+ " if (_saved) spaPath = _saved;",
1560
+ " } catch (e) {}",
1561
+ " try {",
1562
+ ' Object.defineProperty(window.location, "pathname", {',
1563
+ " get: function () { return spaPath; },",
1564
+ " configurable: true",
1565
+ " });",
1566
+ " } catch (e) {}",
1567
+ " var _origPush = window.history.pushState.bind(window.history);",
1568
+ " var _origReplace = window.history.replaceState.bind(window.history);",
1569
+ " function _isRelative(url) {",
1570
+ ' if (!url || typeof url !== "string") return false;',
1571
+ ' if (url.charAt(0) === "#") return false;',
1572
+ " if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(url)) return false;",
1573
+ " return true;",
1574
+ " }",
1575
+ " function _resolvePath(url) {",
1576
+ ' var qi = url.indexOf("?");',
1577
+ ' var hi = url.indexOf("#");',
1578
+ " var end = url.length;",
1579
+ " if (qi !== -1) end = qi;",
1580
+ " if (hi !== -1 && hi < end) end = hi;",
1581
+ " var p = url.slice(0, end);",
1582
+ ' if (p.charAt(0) !== "/") {',
1583
+ ' var base = spaPath.slice(0, spaPath.lastIndexOf("/") + 1);',
1584
+ " p = base + p;",
1585
+ " }",
1586
+ ' var parts = p.split("/");',
1587
+ " var out = [];",
1588
+ " for (var i = 0; i < parts.length; i++) {",
1589
+ " var seg = parts[i];",
1590
+ ' if (seg === "" || seg === ".") continue;',
1591
+ ' if (seg === "..") { out.pop(); continue; }',
1592
+ " out.push(seg);",
1593
+ " }",
1594
+ ' return "/" + out.join("/");',
1595
+ " }",
1596
+ " window.history.pushState = function (state, title, url) {",
1597
+ " if (_isRelative(url)) {",
1598
+ " spaPath = _resolvePath(url);",
1599
+ " try { window.sessionStorage.setItem(SPA_KEY, spaPath); } catch (e) {}",
1600
+ " return;",
1601
+ " }",
1602
+ " return _origPush(state, title, url);",
1603
+ " };",
1604
+ " window.history.replaceState = function (state, title, url) {",
1605
+ " if (_isRelative(url)) {",
1606
+ " spaPath = _resolvePath(url);",
1607
+ " try { window.sessionStorage.setItem(SPA_KEY, spaPath); } catch (e) {}",
1608
+ " return;",
1609
+ " }",
1610
+ " return _origReplace(state, title, url);",
1611
+ " };",
1612
+ " }",
1223
1613
  "})();"
1224
1614
  ].join("\n");
1225
1615
  return src;
@@ -1227,12 +1617,76 @@ var init_function_fetch_proxy = __esm({
1227
1617
  }
1228
1618
  });
1229
1619
 
1620
+ // packages/web-container/src/console-relay.ts
1621
+ var CONSOLE_RELAY_SCRIPT;
1622
+ var init_console_relay = __esm({
1623
+ "packages/web-container/src/console-relay.ts"() {
1624
+ "use strict";
1625
+ CONSOLE_RELAY_SCRIPT = [
1626
+ "(function () {",
1627
+ " if (window.__adepErrorRelayInstalled) return;",
1628
+ " window.__adepErrorRelayInstalled = true;",
1629
+ ' var LEVELS = { log: "log", info: "info", warn: "warn", error: "error", debug: "log" };',
1630
+ " function fmt(value) {",
1631
+ " try {",
1632
+ ' if (typeof value === "string") return value;',
1633
+ ' if (value === undefined) return "undefined";',
1634
+ " var seen = [];",
1635
+ " var json = JSON.stringify(value, function (key, val) {",
1636
+ ' if (val instanceof Error) return val.stack || (val.name + ": " + val.message);',
1637
+ ' if (typeof val === "function") return "[Function " + (val.name || "anonymous") + "]";',
1638
+ ' if (typeof val === "bigint") return String(val) + "n";',
1639
+ ' if (val && typeof val === "object") {',
1640
+ ' if (seen.indexOf(val) !== -1) return "[Circular]";',
1641
+ " seen.push(val);",
1642
+ " }",
1643
+ " return val;",
1644
+ " });",
1645
+ " return json === undefined ? String(value) : json;",
1646
+ " } catch {",
1647
+ " return String(value);",
1648
+ " }",
1649
+ " }",
1650
+ " function send(level, args) {",
1651
+ " try {",
1652
+ " if (window.parent === window) return;",
1653
+ ' var text = Array.prototype.map.call(args, fmt).join(" ");',
1654
+ ' window.parent.postMessage({ source: "adep-ide-preview", kind: "console", level: level, text: text }, "*");',
1655
+ " } catch {",
1656
+ " }",
1657
+ " }",
1658
+ " Object.keys(LEVELS).forEach(function (name) {",
1659
+ " var native = console[name];",
1660
+ " console[name] = function () {",
1661
+ " send(LEVELS[name], arguments);",
1662
+ " native.apply(console, arguments);",
1663
+ " };",
1664
+ " });",
1665
+ " window.addEventListener('error', function (event) {",
1666
+ ' var text = event.message || "Script error";',
1667
+ " if (event.filename) {",
1668
+ ' text += " (" + event.filename + ":" + event.lineno + ":" + event.colno + ")";',
1669
+ " }",
1670
+ ' send("error", [text]);',
1671
+ " });",
1672
+ " window.addEventListener('unhandledrejection', function (event) {",
1673
+ " var reason = event.reason;",
1674
+ ' var text = reason && reason.stack ? String(reason.stack) : "Unhandled rejection: " + fmt(reason);',
1675
+ ' send("error", [text]);',
1676
+ " });",
1677
+ "})();",
1678
+ ""
1679
+ ].join("\n");
1680
+ }
1681
+ });
1682
+
1230
1683
  // packages/web-container/src/vite-dev.ts
1231
1684
  var vite_dev_exports = {};
1232
1685
  __export(vite_dev_exports, {
1233
1686
  ViteDevError: () => ViteDevError,
1234
1687
  createViteServer: () => createViteServer,
1235
- scanEsmSpecifiers: () => scanEsmSpecifiers
1688
+ scanEsmSpecifiers: () => scanEsmSpecifiers,
1689
+ scanRequireSpecifiers: () => scanRequireSpecifiers
1236
1690
  });
1237
1691
  function tokenize2(source) {
1238
1692
  const tokens = [];
@@ -1330,6 +1784,20 @@ function scanEsmSpecifiers(source) {
1330
1784
  }
1331
1785
  return hits;
1332
1786
  }
1787
+ function scanRequireSpecifiers(source) {
1788
+ const tokens = tokenize2(source);
1789
+ const hits = [];
1790
+ for (let i = 0; i + 3 < tokens.length; i++) {
1791
+ const call = tokens[i];
1792
+ if (call.kind !== "ident" || call.text !== "require") continue;
1793
+ if (tokens[i + 1]?.text !== "(") continue;
1794
+ const arg = tokens[i + 2];
1795
+ if (arg.kind !== "string") continue;
1796
+ if (tokens[i + 3]?.text !== ")") continue;
1797
+ hits.push({ specifier: arg.text.slice(1, -1), start: arg.start, end: arg.end });
1798
+ }
1799
+ return hits;
1800
+ }
1333
1801
  function cssModule(css) {
1334
1802
  return [
1335
1803
  `const css = ${JSON.stringify(css)};`,
@@ -1360,6 +1828,113 @@ function jsonModule(source, abs) {
1360
1828
  }
1361
1829
  return `export default ${source.trim()};`;
1362
1830
  }
1831
+ function stripShebang(source) {
1832
+ if (!source.startsWith("#!")) return source;
1833
+ const nl = source.indexOf("\n");
1834
+ return nl === -1 ? "" : source.slice(nl + 1);
1835
+ }
1836
+ function hasEsmSyntax(source) {
1837
+ const tokens = tokenize2(source);
1838
+ for (let i = 0; i < tokens.length; i++) {
1839
+ const tok = tokens[i];
1840
+ if (tok.kind !== "ident") continue;
1841
+ if (tok.text === "export") return true;
1842
+ if (tok.text === "import" && tokens[i + 1]?.text !== "(") return true;
1843
+ }
1844
+ return false;
1845
+ }
1846
+ function isCommonJs(abs, source) {
1847
+ if (abs.endsWith(".cjs")) return true;
1848
+ if (!abs.endsWith(".js")) return false;
1849
+ if (hasEsmSyntax(source)) return false;
1850
+ return /\bmodule\s*\.\s*exports\b|\bexports\s*\.|\brequire\s*\(/.test(source);
1851
+ }
1852
+ function collectCjsExportNames(source) {
1853
+ const tokens = tokenize2(source);
1854
+ const names = /* @__PURE__ */ new Set();
1855
+ const isIdent = (index) => {
1856
+ const tok = tokens[index];
1857
+ return tok?.kind === "ident" && VALID_IDENT.test(tok.text) ? tok.text : null;
1858
+ };
1859
+ for (let i = 0; i < tokens.length; i++) {
1860
+ const tok = tokens[i];
1861
+ if (tok.kind !== "ident") continue;
1862
+ if (tok.text === "exports") {
1863
+ const name = isIdent(i + 2);
1864
+ if (tokens[i + 1]?.text === "." && name !== null && tokens[i + 3]?.text === "=")
1865
+ names.add(name);
1866
+ continue;
1867
+ }
1868
+ if (tok.text === "module") {
1869
+ const name = isIdent(i + 4);
1870
+ if (tokens[i + 1]?.text === "." && tokens[i + 2]?.text === "exports" && tokens[i + 3]?.text === "." && name !== null && tokens[i + 5]?.text === "=") {
1871
+ names.add(name);
1872
+ }
1873
+ if (tokens[i + 1]?.text === "." && tokens[i + 2]?.text === "exports" && tokens[i + 3]?.text === "=" && tokens[i + 4]?.text === "{") {
1874
+ let depth = 0;
1875
+ for (let j = i + 4; j < tokens.length; j++) {
1876
+ const t = tokens[j];
1877
+ if (t.kind === "string" || t.kind === "template") continue;
1878
+ if (t.text === "{") depth++;
1879
+ else if (t.text === "}") {
1880
+ depth--;
1881
+ if (depth === 0) break;
1882
+ } else if (depth === 1) {
1883
+ const prev = tokens[j - 1]?.text;
1884
+ const key = isIdent(j);
1885
+ const next = tokens[j + 1]?.text;
1886
+ if (key !== null && (prev === "{" || prev === ",") && (next === ":" || next === "," || next === "}")) {
1887
+ names.add(key);
1888
+ }
1889
+ }
1890
+ }
1891
+ continue;
1892
+ }
1893
+ continue;
1894
+ }
1895
+ if (tok.text === "Object") {
1896
+ 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") {
1897
+ names.add(tokens[i + 6].text.slice(1, -1));
1898
+ }
1899
+ }
1900
+ }
1901
+ names.delete("default");
1902
+ return [...names].filter((name) => VALID_IDENT.test(name) && !CJS_INTERNALS.has(name));
1903
+ }
1904
+ function wrapCommonJs(abs, source) {
1905
+ const specifiers = [...new Set(scanRequireSpecifiers(source).map((hit) => hit.specifier))];
1906
+ const prelude = specifiers.map(
1907
+ (spec, index) => `import * as ${CJS_PREFIX}Dep${index} from ${JSON.stringify(CJS_SPECIFIER_PREFIX + spec)};`
1908
+ );
1909
+ const entries = specifiers.map(
1910
+ (spec, index) => `${JSON.stringify(spec)}: ${CJS_PREFIX}Dep${index}`
1911
+ );
1912
+ const names = collectCjsExportNames(source);
1913
+ const detail = JSON.stringify(
1914
+ `${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`
1915
+ );
1916
+ return [
1917
+ ...prelude,
1918
+ `const ${CJS_PREFIX}Map = { ${entries.join(", ")} };`,
1919
+ `const ${CJS_PREFIX}Require = (id) => {`,
1920
+ ` const ns = ${CJS_PREFIX}Map[id];`,
1921
+ ` if (ns === undefined || ns.${CJS_PREFIX}Unresolved === true)`,
1922
+ ` throw new Error('require(' + JSON.stringify(id) + ') \u65E0\u6CD5\u89E3\u6790\uFF1A' + ${detail});`,
1923
+ ` return ns[${JSON.stringify(CJS_EXPORTS_MARKER)}] !== undefined ? ns[${JSON.stringify(CJS_EXPORTS_MARKER)}] : ns;`,
1924
+ `};`,
1925
+ `const ${CJS_PREFIX}Module = { exports: {} };`,
1926
+ "(function (module, exports, require) {",
1927
+ source,
1928
+ `}).call(${CJS_PREFIX}Module.exports, ${CJS_PREFIX}Module, ${CJS_PREFIX}Module.exports, ${CJS_PREFIX}Require);`,
1929
+ `const ${CJS_EXPORTS_MARKER}Value = ${CJS_PREFIX}Module.exports;`,
1930
+ `export const ${CJS_EXPORTS_MARKER} = ${CJS_EXPORTS_MARKER}Value;`,
1931
+ `const ${CJS_PREFIX}Default = ${CJS_EXPORTS_MARKER}Value && ${CJS_EXPORTS_MARKER}Value.__esModule ? ${CJS_EXPORTS_MARKER}Value.default : ${CJS_EXPORTS_MARKER}Value;`,
1932
+ `export default ${CJS_PREFIX}Default;`,
1933
+ ...names.map(
1934
+ (name) => `export const ${name} = ${CJS_EXPORTS_MARKER}Value[${JSON.stringify(name)}];`
1935
+ )
1936
+ ].join("\n");
1937
+ }
1363
1938
  function resolveWithSuffixes(vfs, base) {
1364
1939
  if (vfs.exists(base) && !vfs.isDirectory(base)) return base;
1365
1940
  const asFile2 = VITE_RESOLVE_SUFFIXES.map((suffix) => `${base}${suffix}`);
@@ -1406,15 +1981,42 @@ function createViteServer(vfs, options = {}) {
1406
1981
  [/\bprocess\s*\.\s*env\s*\.\s*NODE_ENV\b/g, JSON.stringify("development")],
1407
1982
  [/\b__VUE_OPTIONS_API__\b/g, "true"],
1408
1983
  [/\b__VUE_PROD_DEVTOOLS__\b/g, "false"],
1409
- [/\b__VUE_PROD_HYDRATION_MISMATCH_DETAILS__\b/g, "false"]
1984
+ [/\b__VUE_PROD_HYDRATION_MISMATCH_DETAILS__\b/g, "false"],
1985
+ [
1986
+ /\bimport\s*\.\s*meta\s*\.\s*env\b/g,
1987
+ '({ BASE_URL: "/", MODE: "development", DEV: true, PROD: false, SSR: false })'
1988
+ ]
1410
1989
  ];
1411
1990
  function applyDefines(code) {
1412
1991
  let out = code;
1413
1992
  for (const [pattern, value] of DEFINES) out = out.replace(pattern, value);
1414
1993
  return out;
1415
1994
  }
1995
+ const cssResolver = {
1996
+ read: (abs) => vfs.exists(abs) && !vfs.isDirectory(abs) ? vfs.readFile(abs) : null,
1997
+ resolve: (spec, importerAbs) => {
1998
+ if (spec.startsWith("./") || spec.startsWith("../") || spec.startsWith("/")) {
1999
+ const base = spec.startsWith("/") ? absoluteFromRoot(spec) : join(dirname(importerAbs), spec);
2000
+ const target = resolveWithSuffixes(vfs, base);
2001
+ return vfs.exists(target) && !vfs.isDirectory(target) ? target : null;
2002
+ }
2003
+ try {
2004
+ return resolveImport(vfs, spec, importerAbs, "import");
2005
+ } catch {
2006
+ return null;
2007
+ }
2008
+ }
2009
+ };
2010
+ function inlineCss(css, importerAbs) {
2011
+ try {
2012
+ return inlineCssImports(css, importerAbs, cssResolver);
2013
+ } catch (error) {
2014
+ if (error instanceof CssImportError) throw new ViteDevError("CSS_IMPORT", error.message);
2015
+ throw error;
2016
+ }
2017
+ }
1416
2018
  function transformModule2(abs, source) {
1417
- if (abs.endsWith(".css")) return cssModule(source);
2019
+ if (abs.endsWith(".css")) return cssModule(inlineCss(source, abs));
1418
2020
  if (abs.endsWith(".json")) return jsonModule(source, abs);
1419
2021
  if (abs.endsWith(".vue")) {
1420
2022
  if (sfcCompiler === void 0)
@@ -1424,7 +2026,9 @@ function createViteServer(vfs, options = {}) {
1424
2026
  );
1425
2027
  const compiled = sfcCompiler(source, abs);
1426
2028
  return [
1427
- ...compiled.styles.map((css, index) => inlineStyleBlock(css, `${abs}#${index}`)),
2029
+ ...compiled.styles.map(
2030
+ (css, index) => inlineStyleBlock(inlineCss(css, abs), `${abs}#${index}`)
2031
+ ),
1428
2032
  applyDefines(stripTypes(compiled.script))
1429
2033
  ].join("\n");
1430
2034
  }
@@ -1433,37 +2037,65 @@ function createViteServer(vfs, options = {}) {
1433
2037
  "JSX_UNSUPPORTED",
1434
2038
  `${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`
1435
2039
  );
1436
- if (abs.endsWith(".ts") || abs.endsWith(".mts")) return applyDefines(stripTypes(source));
1437
- return applyDefines(source);
2040
+ const bare = stripShebang(source);
2041
+ if (abs.endsWith(".ts") || abs.endsWith(".mts")) return applyDefines(stripTypes(bare));
2042
+ if (isCommonJs(abs, bare)) return applyDefines(wrapCommonJs(abs, bare));
2043
+ return applyDefines(bare);
1438
2044
  }
1439
2045
  function absoluteFromRoot(spec) {
1440
2046
  return join(root, spec.replace(/^\/+/, ""));
1441
2047
  }
1442
- async function resolveSpecifier(spec, importerAbs) {
1443
- if (EXTERNAL_SPECIFIER.test(spec) || DATA_OR_BLOB.test(spec)) return spec;
1444
- let target;
2048
+ function resolveToAbs(spec, importerAbs) {
1445
2049
  if (spec.startsWith("./") || spec.startsWith("../") || spec.startsWith("/")) {
1446
2050
  const base = spec.startsWith("/") ? absoluteFromRoot(spec) : join(dirname(importerAbs), spec);
1447
- target = resolveWithSuffixes(vfs, base);
2051
+ const target = resolveWithSuffixes(vfs, base);
1448
2052
  if (!vfs.exists(target) || vfs.isDirectory(target))
1449
2053
  throw new ViteDevError(
1450
2054
  "RESOLVE",
1451
2055
  `\u627E\u4E0D\u5230\u6A21\u5757 "${spec}"\uFF08\u81EA ${importerAbs}\uFF1B\u8BD5\u8FC7\u6269\u5C55\u540D ${VITE_RESOLVE_SUFFIXES.join("/")} \u4E0E\u76EE\u5F55 index\uFF09`
1452
2056
  );
1453
- } else {
1454
- try {
1455
- target = resolveImport(vfs, spec, importerAbs, "import");
1456
- } catch (error) {
1457
- if (error instanceof ResolveError)
1458
- throw new ViteDevError(
1459
- "RESOLVE",
1460
- `${error.message}
2057
+ return target;
2058
+ }
2059
+ try {
2060
+ return resolveImport(vfs, spec, importerAbs, "import");
2061
+ } catch (error) {
2062
+ if (error instanceof ResolveError)
2063
+ throw new ViteDevError(
2064
+ "RESOLVE",
2065
+ `${error.message}
1461
2066
  \uFF08\u5728 ${importerAbs} \u4E2D import "${spec}"\uFF09`
1462
- );
1463
- throw error;
2067
+ );
2068
+ throw error;
2069
+ }
2070
+ }
2071
+ const cjsStubSources = /* @__PURE__ */ new Map();
2072
+ function cjsStubUrl(spec) {
2073
+ let abs = cjsStubSources.get(spec);
2074
+ if (abs === void 0) {
2075
+ abs = `${INLINE_PREFIX}cjs_stub_${cjsStubSources.size}.mjs`;
2076
+ cjsStubSources.set(spec, abs);
2077
+ inlineSources.set(
2078
+ abs,
2079
+ [
2080
+ `export const ${CJS_PREFIX}Unresolved = true;`,
2081
+ `export const ${CJS_PREFIX}Specifier = ${JSON.stringify(spec)};`,
2082
+ "export default undefined;"
2083
+ ].join("\n")
2084
+ );
2085
+ }
2086
+ return loadModuleUrl(abs);
2087
+ }
2088
+ async function resolveSpecifier(spec, importerAbs) {
2089
+ if (spec.startsWith(CJS_SPECIFIER_PREFIX)) {
2090
+ const original = spec.slice(CJS_SPECIFIER_PREFIX.length);
2091
+ try {
2092
+ return await loadModuleUrl(resolveToAbs(original, importerAbs));
2093
+ } catch {
2094
+ return cjsStubUrl(original);
1464
2095
  }
1465
2096
  }
1466
- return loadModuleUrl(target);
2097
+ if (EXTERNAL_SPECIFIER.test(spec) || DATA_OR_BLOB.test(spec)) return spec;
2098
+ return loadModuleUrl(resolveToAbs(spec, importerAbs));
1467
2099
  }
1468
2100
  async function loadModuleUrl(abs) {
1469
2101
  const cached = moduleUrls.get(abs);
@@ -1555,14 +2187,15 @@ function createViteServer(vfs, options = {}) {
1555
2187
  );
1556
2188
  const urls = await Promise.all(entryModuleUrls);
1557
2189
  html = html.replace(/__adep_vite_entry_(\d+)__/g, (_m, idx) => urls[Number(idx)] ?? "");
1558
- const interceptor = `<script>${FN_FETCH_INTERCEPTOR_SCRIPT}</script>`;
1559
- html = /<head[^>]*>/i.test(html) ? html.replace(/<head[^>]*>/i, (m) => `${m}${interceptor}`) : `${interceptor}${html}`;
2190
+ const preludeScripts = `<script>${CONSOLE_RELAY_SCRIPT}</script><script>${FN_FETCH_INTERCEPTOR_SCRIPT}</script>`;
2191
+ html = /<head[^>]*>/i.test(html) ? html.replace(/<head[^>]*>/i, (m) => `${m}${preludeScripts}`) : `${preludeScripts}${html}`;
1560
2192
  const hmr = hmrScript(channelName);
1561
2193
  return /<\/body>/i.test(html) ? html.replace(/<\/(body)>/i, `${hmr}</$1>`) : html + hmr;
1562
2194
  }
1563
2195
  async function rebuild() {
1564
2196
  moduleUrls = /* @__PURE__ */ new Map();
1565
2197
  inlineSources = /* @__PURE__ */ new Map();
2198
+ cjsStubSources.clear();
1566
2199
  inlineSeq = 0;
1567
2200
  let doc;
1568
2201
  try {
@@ -1572,9 +2205,13 @@ function createViteServer(vfs, options = {}) {
1572
2205
  }
1573
2206
  const changed = lastDoc !== null && doc !== lastDoc;
1574
2207
  lastDoc = doc;
2208
+ if (!changed && currentUrl !== "") return;
1575
2209
  if (currentUrl !== "") revokeObjectURL(currentUrl);
1576
2210
  currentUrl = createObjectURL(new Blob([doc], { type: "text/html" }));
1577
- if (changed) broadcast(currentUrl);
2211
+ if (changed) {
2212
+ broadcast(currentUrl);
2213
+ options.onDocumentChange?.(currentUrl);
2214
+ }
1578
2215
  }
1579
2216
  const server = {
1580
2217
  get url() {
@@ -1607,7 +2244,7 @@ function createViteServer(vfs, options = {}) {
1607
2244
  const unsubscribeMutate = vfs.onMutate(scheduleRebuild);
1608
2245
  return server;
1609
2246
  }
1610
- 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;
2247
+ 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;
1611
2248
  var init_vite_dev = __esm({
1612
2249
  "packages/web-container/src/vite-dev.ts"() {
1613
2250
  "use strict";
@@ -1616,6 +2253,8 @@ var init_vite_dev = __esm({
1616
2253
  init_strip_types();
1617
2254
  init_preview_server();
1618
2255
  init_function_fetch_proxy();
2256
+ init_console_relay();
2257
+ init_css_imports();
1619
2258
  ViteDevError = class extends Error {
1620
2259
  constructor(reason, message) {
1621
2260
  super(message);
@@ -1664,6 +2303,22 @@ var init_vite_dev = __esm({
1664
2303
  ]);
1665
2304
  isIdentStart = (ch) => /[A-Za-z_$]/.test(ch);
1666
2305
  isIdentPart = (ch) => /[A-Za-z0-9_$]/.test(ch);
2306
+ CJS_PREFIX = "__adepCjs";
2307
+ CJS_EXPORTS_MARKER = `${CJS_PREFIX}Exports`;
2308
+ CJS_SPECIFIER_PREFIX = `${CJS_PREFIX}Spec:`;
2309
+ VALID_IDENT = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
2310
+ CJS_INTERNALS = /* @__PURE__ */ new Set([
2311
+ "module",
2312
+ "exports",
2313
+ "require",
2314
+ // 互操作标记而非用户导出:Babel 产物会 defineProperty(exports, "__esModule"),转发它没有意义。
2315
+ "__esModule",
2316
+ `${CJS_EXPORTS_MARKER}`,
2317
+ `${CJS_PREFIX}Default`,
2318
+ `${CJS_PREFIX}Map`,
2319
+ `${CJS_PREFIX}Module`,
2320
+ `${CJS_PREFIX}Require`
2321
+ ]);
1667
2322
  VITE_RESOLVE_SUFFIXES = [".ts", ".js", ".mjs", ".mts", ".vue", ".json", ".css"];
1668
2323
  INLINE_PREFIX = "/__vite_inline_";
1669
2324
  EXTERNAL_SPECIFIER = /^(?:https?:)?\/\//i;
@@ -2723,7 +3378,7 @@ async function unpackNpmTarball(bytes) {
2723
3378
 
2724
3379
  // packages/web-container/src/npm-client.ts
2725
3380
  init_node_resolve();
2726
- var DEFAULT_MAX_INSTALL_DEPTH = 5;
3381
+ var DEFAULT_MAX_INSTALL_DEPTH = 25;
2727
3382
  var defaultFetch = (url, init) => globalThis.fetch(url, init).then((res) => res);
2728
3383
  function parseSpec(spec) {
2729
3384
  if (spec.startsWith("@")) {
@@ -2748,29 +3403,50 @@ async function relayFetch(fetchImpl, url, what) {
2748
3403
  throw new Error(`${what} \u5931\u8D25\uFF1A\u65E0\u6CD5\u8BBF\u95EE npm \u4E2D\u7EE7\uFF08${url}\uFF0C${reason}\uFF09`, { cause: error });
2749
3404
  }
2750
3405
  }
3406
+ var RATE_LIMIT_MAX_RETRIES = 120;
3407
+ var DEFAULT_RETRY_AFTER_MS = 1e3;
3408
+ var MAX_RETRY_AFTER_MS = 6e4;
3409
+ var defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
3410
+ function retryAfterMs(res) {
3411
+ const raw = res.headers["retry-after"];
3412
+ const seconds = raw === void 0 ? Number.NaN : Number.parseFloat(raw);
3413
+ if (!Number.isFinite(seconds) || seconds <= 0) return DEFAULT_RETRY_AFTER_MS;
3414
+ return Math.min(seconds * 1e3, MAX_RETRY_AFTER_MS);
3415
+ }
2751
3416
  function createNpmClient(options) {
2752
3417
  const fetchImpl = options.fetchImpl ?? defaultFetch;
2753
3418
  const base = options.baseUrl.replace(/\/+$/, "");
2754
3419
  const storage = options.storage;
2755
3420
  const maxDepth = options.maxDepth ?? DEFAULT_MAX_INSTALL_DEPTH;
3421
+ const sleep = options.sleep ?? defaultSleep;
3422
+ async function relayRequest(url, what) {
3423
+ for (let attempt = 0; ; attempt += 1) {
3424
+ const res = await relayFetch(fetchImpl, url, what);
3425
+ if (res.status !== 429) return res;
3426
+ if (attempt >= RATE_LIMIT_MAX_RETRIES) {
3427
+ throw new Error(
3428
+ `${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`
3429
+ );
3430
+ }
3431
+ await sleep(retryAfterMs(res));
3432
+ }
3433
+ }
2756
3434
  async function resolvePackage(name, spec) {
2757
3435
  const params = new URLSearchParams({ name });
2758
3436
  if (spec !== void 0) params.set("spec", spec);
2759
- const res = await relayFetch(
2760
- fetchImpl,
3437
+ const res = await relayRequest(
2761
3438
  `${base}/package?${params.toString()}`,
2762
3439
  `\u89E3\u6790\u5305 ${name}@${spec ?? "latest"}`
2763
3440
  );
2764
3441
  if (!res.ok) {
2765
3442
  throw new Error(
2766
- `\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`
3443
+ `\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`
2767
3444
  );
2768
3445
  }
2769
3446
  return await res.json();
2770
3447
  }
2771
3448
  async function fetchAndUnpack(name, version) {
2772
- const res = await relayFetch(
2773
- fetchImpl,
3449
+ const res = await relayRequest(
2774
3450
  `${base}/tarball?${new URLSearchParams({ name, version }).toString()}`,
2775
3451
  `\u4E0B\u8F7D tarball ${name}@${version}`
2776
3452
  );
@@ -2794,17 +3470,12 @@ function createNpmClient(options) {
2794
3470
  return null;
2795
3471
  }
2796
3472
  }
2797
- async function collect(name, spec, depth, path, staged, onStack, visited, packages, distTagsByName) {
3473
+ async function collect(name, spec, depth, path, staged, visited, packages, distTagsByName) {
2798
3474
  if (depth > maxDepth) {
2799
3475
  throw new Error(
2800
3476
  `\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`
2801
3477
  );
2802
3478
  }
2803
- if (onStack.has(name)) {
2804
- throw new Error(
2805
- `\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`
2806
- );
2807
- }
2808
3479
  const meta = await resolvePackage(name, spec);
2809
3480
  distTagsByName.set(meta.name, meta.distTags ?? []);
2810
3481
  const key = `${meta.name}@${meta.version}`;
@@ -2828,8 +3499,6 @@ function createNpmClient(options) {
2828
3499
  }
2829
3500
  Object.assign(deps, pkgMeta.dependencies ?? {});
2830
3501
  }
2831
- const nextStack = new Set(onStack);
2832
- nextStack.add(meta.name);
2833
3502
  for (const [depName, depSpec] of Object.entries(deps)) {
2834
3503
  await collect(
2835
3504
  depName,
@@ -2837,7 +3506,6 @@ function createNpmClient(options) {
2837
3506
  depth + 1,
2838
3507
  [...path, meta.name],
2839
3508
  staged,
2840
- nextStack,
2841
3509
  visited,
2842
3510
  packages,
2843
3511
  distTagsByName
@@ -2846,7 +3514,7 @@ function createNpmClient(options) {
2846
3514
  }
2847
3515
  return {
2848
3516
  async registries() {
2849
- const res = await relayFetch(fetchImpl, `${base}/registry`, "\u83B7\u53D6 registry \u5217\u8868");
3517
+ const res = await relayRequest(`${base}/registry`, "\u83B7\u53D6 registry \u5217\u8868");
2850
3518
  if (!res.ok) throw new Error(`\u83B7\u53D6 registry \u5217\u8868\u5931\u8D25\uFF1AHTTP ${res.status}`);
2851
3519
  const body = await res.json();
2852
3520
  return body.registries;
@@ -2856,7 +3524,7 @@ function createNpmClient(options) {
2856
3524
  const staged = /* @__PURE__ */ new Map();
2857
3525
  const packages = [];
2858
3526
  const distTagsByName = /* @__PURE__ */ new Map();
2859
- await collect(name, spec, 1, [], staged, /* @__PURE__ */ new Set(), /* @__PURE__ */ new Set(), packages, distTagsByName);
3527
+ await collect(name, spec, 1, [], staged, /* @__PURE__ */ new Set(), packages, distTagsByName);
2860
3528
  const root = packages[0] ?? { name, version: spec ?? "latest" };
2861
3529
  const downloaded = staged.size > 0;
2862
3530
  for (const [path, contents] of staged) storage.writeFile(path, contents);
@@ -3611,7 +4279,11 @@ function bootstrap(options) {
3611
4279
  const { createViteServer: createViteServer2 } = await Promise.resolve().then(() => (init_vite_dev(), vite_dev_exports));
3612
4280
  const server = createViteServer2(vfs, {
3613
4281
  root,
3614
- ...options.viteCompiler === void 0 ? {} : { sfcCompiler: options.viteCompiler }
4282
+ ...options.viteCompiler === void 0 ? {} : { sfcCompiler: options.viteCompiler },
4283
+ // PV-006:内容重建 → 以 `serverready`(update: true)事件上报新文档 URL,宿主导出预览产物。
4284
+ onDocumentChange: (url) => {
4285
+ emit("serverready", { port: server.port, url, kind: "vite", root: server.root, update: true });
4286
+ }
3615
4287
  });
3616
4288
  await server.ready;
3617
4289
  viteServer = server;
@@ -3776,6 +4448,92 @@ init_node_resolve();
3776
4448
  init_vite_dev();
3777
4449
  init_path();
3778
4450
 
4451
+ // packages/web-container/src/bundle-export.ts
4452
+ var BUNDLE_MODULE_PATH_PREFIX = "/_adep/m/";
4453
+ var BLOB_REF_RE = /blob:[^\s"'`<>()\\]+/g;
4454
+ function fnv1a(code) {
4455
+ let hash = 2166136261;
4456
+ for (let i = 0; i < code.length; i++) {
4457
+ hash ^= code.charCodeAt(i);
4458
+ hash = Math.imul(hash, 16777619) >>> 0;
4459
+ }
4460
+ return `${hash.toString(16).padStart(8, "0")}${code.length.toString(16)}`;
4461
+ }
4462
+ async function defaultModuleName(code) {
4463
+ const subtle = globalThis.crypto?.subtle;
4464
+ if (subtle === void 0) return fnv1a(code);
4465
+ const digest = await subtle.digest("SHA-256", new TextEncoder().encode(code));
4466
+ let hex = "";
4467
+ for (const byte of new Uint8Array(digest).slice(0, 8)) {
4468
+ hex += byte.toString(16).padStart(2, "0");
4469
+ }
4470
+ return hex;
4471
+ }
4472
+ function findBlobRefs(text) {
4473
+ const found = text.match(BLOB_REF_RE);
4474
+ return found === null ? [] : [...new Set(found)];
4475
+ }
4476
+ function rewriteRefs(text, urls) {
4477
+ let out = text;
4478
+ for (const [blobUrl, path] of urls) {
4479
+ if (out.includes(blobUrl)) out = out.split(blobUrl).join(path);
4480
+ }
4481
+ return out;
4482
+ }
4483
+ function injectScript(html, script) {
4484
+ return /<\/body>/i.test(html) ? html.replace(/<\/body>/i, `${script}</body>`) : html + script;
4485
+ }
4486
+ async function exportBundle(options) {
4487
+ const readText = options.readText ?? ((url) => fetch(url).then((response) => response.text()));
4488
+ const nameOf = options.moduleName ?? defaultModuleName;
4489
+ const prefix = options.modulePathPrefix ?? BUNDLE_MODULE_PATH_PREFIX;
4490
+ const uploaded = new Set(options.known === void 0 ? [] : [...options.known.values()]);
4491
+ const urls = /* @__PURE__ */ new Map();
4492
+ const sources = [];
4493
+ const readOrThrow = async (url) => {
4494
+ try {
4495
+ return await readText(url);
4496
+ } catch (error) {
4497
+ throw new Error(
4498
+ `\u9884\u89C8\u4EA7\u7269\u5BFC\u51FA\u5931\u8D25\uFF1A\u8BFB\u4E0D\u5230\u6A21\u5757 ${url}\uFF08${error instanceof Error ? error.message : String(error)}\uFF09`,
4499
+ { cause: error }
4500
+ );
4501
+ }
4502
+ };
4503
+ const html = await readOrThrow(options.documentUrl);
4504
+ const loadLayer = async (layer) => {
4505
+ const batch = [...new Set(layer)].filter((url) => !urls.has(url));
4506
+ if (batch.length === 0) return;
4507
+ const loaded = await Promise.all(
4508
+ batch.map(async (url) => {
4509
+ const code = await readOrThrow(url);
4510
+ return { url, code, path: `${prefix}${await nameOf(code)}.js` };
4511
+ })
4512
+ );
4513
+ const next = [];
4514
+ for (const item of loaded) {
4515
+ urls.set(item.url, item.path);
4516
+ sources.push({ url: item.url, code: item.code });
4517
+ next.push(...findBlobRefs(item.code));
4518
+ }
4519
+ await loadLayer(next);
4520
+ };
4521
+ await loadLayer(findBlobRefs(html));
4522
+ const modules = {};
4523
+ for (const { url, code } of sources) {
4524
+ const path = urls.get(url);
4525
+ if (uploaded.has(path)) continue;
4526
+ modules[path] = rewriteRefs(code, urls);
4527
+ }
4528
+ const rewrittenHtml = rewriteRefs(html, urls);
4529
+ return {
4530
+ html: options.appendScript === void 0 ? rewrittenHtml : injectScript(rewrittenHtml, options.appendScript),
4531
+ modules,
4532
+ paths: [...new Set(urls.values())].toSorted(),
4533
+ urls
4534
+ };
4535
+ }
4536
+
3779
4537
  // packages/web-container/src/persistence.ts
3780
4538
  function cloneEntries(entries) {
3781
4539
  return entries.map(
@@ -5327,6 +6085,7 @@ function stripQuotes(raw) {
5327
6085
  const t = raw.trim();
5328
6086
  if (/^'.*'$/.test(t)) return t.slice(1, -1);
5329
6087
  if (/^".*"$/.test(t)) return t.slice(1, -1);
6088
+ if (/^NULL$/i.test(t)) return null;
5330
6089
  return t;
5331
6090
  }
5332
6091
  function parseCreateTable(ddl) {
@@ -5347,50 +6106,109 @@ function parseCreateTable(ddl) {
5347
6106
  }
5348
6107
  return { name, columns };
5349
6108
  }
5350
- function parseWhereClauses(whereRaw, cursor) {
5351
- const clauses = [];
5352
- for (const part of whereRaw.split(/\s+AND\s+/i)) {
5353
- const t = part.trim();
5354
- if (t.length === 0) continue;
5355
- if (/\bIS\s+NULL\b/i.test(t)) {
5356
- const col2 = ident(t.split(/\s+IS\s+NULL\b/i)[0] ?? "");
5357
- clauses.push({ column: col2, operator: "IS NULL", value: null, list: false });
5358
- continue;
5359
- }
5360
- if (/\bIS\s+NOT\s+NULL\b/i.test(t)) {
5361
- const col2 = ident(t.split(/\s+IS\s+NOT\s+NULL\b/i)[0] ?? "");
5362
- clauses.push({ column: col2, operator: "IS NOT NULL", value: null, list: false });
5363
- continue;
5364
- }
5365
- const opMatch = /^\s*((?:"[^"]+")|([A-Za-z_][A-Za-z0-9_]*))\s*(=|!=|>=|<=|>|<|like|in|not\s+in)\s*(.+)$/i.exec(
5366
- t
5367
- );
5368
- if (opMatch === null) continue;
5369
- const col = ident(opMatch[1] ?? "");
5370
- const op = (opMatch[3] ?? opMatch[2] ?? "").toLowerCase();
5371
- const rhs = (opMatch[4] ?? "").trim();
5372
- if (op === "in" || op === "not in") {
5373
- const inner = rhs.replace(/^\(|\)$/g, "");
5374
- const items = splitListItems(inner);
5375
- const list = items.map((item) => {
5376
- if (item.trim() === "?") return cursor.take();
5377
- return stripQuotes(item);
5378
- });
5379
- clauses.push({ column: col, operator: op, value: list, list: true });
6109
+ function splitTopLevel(raw, token) {
6110
+ const parts = [];
6111
+ let depth = 0;
6112
+ let inQuote = false;
6113
+ let buffer = "";
6114
+ const n = raw.length;
6115
+ const isTokenAt = (i) => {
6116
+ const word = raw.slice(i, i + token.length);
6117
+ if (word.toUpperCase() !== token) return false;
6118
+ const before = i === 0 ? "" : raw[i - 1] ?? "";
6119
+ const after = raw[i + token.length] ?? "";
6120
+ return !/[A-Za-z0-9_.]/.test(before) && !/[A-Za-z0-9_.]/.test(after);
6121
+ };
6122
+ for (let i = 0; i < n; i += 1) {
6123
+ const ch = raw[i] ?? "";
6124
+ if (ch === "'") {
6125
+ if (inQuote && raw[i + 1] === "'") {
6126
+ buffer += ch + (raw[i + 1] ?? "");
6127
+ i += 1;
6128
+ continue;
6129
+ }
6130
+ inQuote = !inQuote;
6131
+ buffer += ch;
5380
6132
  continue;
5381
6133
  }
5382
- let value;
5383
- if (rhs === "?") {
5384
- value = cursor.take();
6134
+ if (!inQuote && ch === "(") depth += 1;
6135
+ else if (!inQuote && ch === ")") depth -= 1;
6136
+ if (!inQuote && depth === 0 && isTokenAt(i)) {
6137
+ parts.push(buffer);
6138
+ buffer = "";
6139
+ i += token.length - 1;
5385
6140
  } else {
5386
- value = stripQuotes(rhs);
6141
+ buffer += ch;
5387
6142
  }
5388
- clauses.push({ column: col, operator: op, value, list: false });
5389
6143
  }
5390
- return clauses;
6144
+ parts.push(buffer);
6145
+ return parts;
5391
6146
  }
5392
- function matchWhere(clauses, row) {
5393
- return clauses.every((c) => matchValue(row[c.column], c));
6147
+ function unqualifyColumn(raw) {
6148
+ const t = raw.trim();
6149
+ const dot = t.lastIndexOf(".");
6150
+ if (dot > 0 && /^[A-Za-z_][A-Za-z0-9_]*\./.test(t)) return t.slice(dot + 1);
6151
+ return t;
6152
+ }
6153
+ function parseLeftJoins(tail) {
6154
+ const joins = [];
6155
+ 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;
6156
+ let m;
6157
+ while ((m = re.exec(tail)) !== null) {
6158
+ joins.push({
6159
+ table: ident(m[1] ?? ""),
6160
+ alias: m[3] ?? "",
6161
+ leftCol: unqualifyColumn(m[4] ?? ""),
6162
+ rightCol: unqualifyColumn(m[5] ?? "")
6163
+ });
6164
+ }
6165
+ return joins;
6166
+ }
6167
+ function parseWhereClauses(whereRaw, cursor) {
6168
+ const parseAndGroup = (andRaw) => {
6169
+ const clauses = [];
6170
+ for (const part of splitTopLevel(andRaw, "AND")) {
6171
+ const t = part.trim();
6172
+ if (t.length === 0) continue;
6173
+ if (/\bIS\s+NULL\b/i.test(t)) {
6174
+ clauses.push({ column: unqualifyColumn(ident(t.split(/\s+IS\s+NULL\b/i)[0] ?? "")), operator: "IS NULL", value: null, list: false });
6175
+ continue;
6176
+ }
6177
+ if (/\bIS\s+NOT\s+NULL\b/i.test(t)) {
6178
+ clauses.push({ column: unqualifyColumn(ident(t.split(/\s+IS\s+NOT\s+NULL\b/i)[0] ?? "")), operator: "IS NOT NULL", value: null, list: false });
6179
+ continue;
6180
+ }
6181
+ const opMatch = /^\s*((?:"[^"]+")|([A-Za-z_][A-Za-z0-9_.]*))\s*(=|!=|>=|<=|>|<|like|in|not\s+in)\s*(.+)$/i.exec(
6182
+ t
6183
+ );
6184
+ if (opMatch === null) continue;
6185
+ const col = unqualifyColumn(ident(opMatch[1] ?? ""));
6186
+ const op = (opMatch[3] ?? opMatch[2] ?? "").toLowerCase();
6187
+ const rhs = (opMatch[4] ?? "").trim();
6188
+ if (op === "in" || op === "not in") {
6189
+ const inner = rhs.replace(/^\(|\)$/g, "");
6190
+ const items = splitListItems(inner);
6191
+ const list = items.map((item) => {
6192
+ if (item.trim() === "?") return cursor.take();
6193
+ return stripQuotes(item);
6194
+ });
6195
+ clauses.push({ column: col, operator: op, value: list, list: true });
6196
+ continue;
6197
+ }
6198
+ let value;
6199
+ if (rhs === "?") {
6200
+ value = cursor.take();
6201
+ } else {
6202
+ value = stripQuotes(rhs);
6203
+ }
6204
+ clauses.push({ column: col, operator: op, value, list: false });
6205
+ }
6206
+ return clauses;
6207
+ };
6208
+ return splitTopLevel(whereRaw, "OR").map((group) => group.trim()).filter((group) => group.length > 0).map(parseAndGroup);
6209
+ }
6210
+ function matchWhere(groups, row) {
6211
+ return groups.some((clauses) => clauses.every((c) => matchValue(row[c.column], c)));
5394
6212
  }
5395
6213
  function splitListItems(inner) {
5396
6214
  const items = [];
@@ -5410,6 +6228,168 @@ function splitListItems(inner) {
5410
6228
  items.push(buffer);
5411
6229
  return items;
5412
6230
  }
6231
+ var ExcludedRef = class {
6232
+ constructor(column) {
6233
+ this.column = column;
6234
+ }
6235
+ };
6236
+ var ColumnRef = class {
6237
+ constructor(column) {
6238
+ this.column = column;
6239
+ }
6240
+ };
6241
+ var ExprRef = class {
6242
+ constructor(source) {
6243
+ this.source = source;
6244
+ }
6245
+ };
6246
+ function resolveSetValue(value, existing, row) {
6247
+ if (value instanceof ExcludedRef) return row[value.column];
6248
+ if (value instanceof ColumnRef) return existing[value.column];
6249
+ if (value instanceof ExprRef) return evalArithmetic(value.source, existing, row);
6250
+ return value;
6251
+ }
6252
+ function evalArithmetic(src, existing, row) {
6253
+ const num = (v) => {
6254
+ const n2 = Number(v);
6255
+ return Number.isFinite(n2) ? n2 : 0;
6256
+ };
6257
+ let i = 0;
6258
+ const n = src.length;
6259
+ const skip = () => {
6260
+ while (i < n && /\s/.test(src[i] ?? "")) i += 1;
6261
+ };
6262
+ const peek = () => {
6263
+ skip();
6264
+ return i < n ? src[i] ?? "" : null;
6265
+ };
6266
+ const parseIdent = () => {
6267
+ skip();
6268
+ const m = /^([A-Za-z_][A-Za-z0-9_]*)/.exec(src.slice(i));
6269
+ if (m === null) return null;
6270
+ i += (m[1] ?? "").length;
6271
+ skip();
6272
+ let col = ident(m[1] ?? "");
6273
+ let excluded = false;
6274
+ if (src[i] === ".") {
6275
+ const m2 = /^\.([A-Za-z_][A-Za-z0-9_]*)/.exec(src.slice(i));
6276
+ if (m2 !== null) {
6277
+ i += (m2[0] ?? "").length;
6278
+ if (col.toLowerCase() === "excluded") excluded = true;
6279
+ col = ident(m2[1] ?? "");
6280
+ }
6281
+ }
6282
+ return { col, excluded };
6283
+ };
6284
+ const parseFactor = () => {
6285
+ const ch = peek();
6286
+ if (ch === "(") {
6287
+ i += 1;
6288
+ const v = parseExpr();
6289
+ skip();
6290
+ if (src[i] === ")") i += 1;
6291
+ return v;
6292
+ }
6293
+ const numMatch = /^(\d+(?:\.\d+)?)/.exec(src.slice(i));
6294
+ if (numMatch !== null) {
6295
+ i += (numMatch[1] ?? "").length;
6296
+ return Number(numMatch[1]);
6297
+ }
6298
+ const id = parseIdent();
6299
+ if (id !== null) {
6300
+ const v = id.excluded ? row[id.col] : existing[id.col];
6301
+ return num(v);
6302
+ }
6303
+ return 0;
6304
+ };
6305
+ const parseTerm = () => {
6306
+ let v = parseFactor();
6307
+ for (; ; ) {
6308
+ const ch = peek();
6309
+ if (ch !== "*" && ch !== "/") return v;
6310
+ i += 1;
6311
+ const rhs = parseFactor();
6312
+ v = ch === "*" ? v * rhs : rhs === 0 ? v : v / rhs;
6313
+ }
6314
+ };
6315
+ const parseExpr = () => {
6316
+ let v = parseTerm();
6317
+ for (; ; ) {
6318
+ const ch = peek();
6319
+ if (ch !== "+" && ch !== "-") return v;
6320
+ i += 1;
6321
+ const rhs = parseTerm();
6322
+ v = ch === "+" ? v + rhs : v - rhs;
6323
+ }
6324
+ };
6325
+ return parseExpr();
6326
+ }
6327
+ function splitInsertTuples(body) {
6328
+ const tuples = [];
6329
+ let i = 0;
6330
+ const n = body.length;
6331
+ while (i < n) {
6332
+ while (i < n && (body[i] === " " || body[i] === " " || body[i] === "\n" || body[i] === "\r" || body[i] === ",")) {
6333
+ i += 1;
6334
+ }
6335
+ if (i >= n) break;
6336
+ if (body[i] !== "(") {
6337
+ return { tuples, conflict: body.slice(i).trim() };
6338
+ }
6339
+ let depth = 0;
6340
+ let j = i;
6341
+ for (; j < n; j += 1) {
6342
+ if (body[j] === "(") depth += 1;
6343
+ else if (body[j] === ")") {
6344
+ depth -= 1;
6345
+ if (depth === 0) break;
6346
+ }
6347
+ }
6348
+ if (j >= n) return { tuples, conflict: null };
6349
+ tuples.push(body.slice(i + 1, j));
6350
+ i = j + 1;
6351
+ }
6352
+ return { tuples, conflict: null };
6353
+ }
6354
+ function parseConflictClause(clause, cursor, fallbackCols) {
6355
+ const m = /^ON\s+CONFLICT(?:\s*\(([^)]*)\))?\s+DO\s+(UPDATE\s+SET\s+([\s\S]+)|NOTHING\s*)$/i.exec(
6356
+ clause.trim()
6357
+ );
6358
+ if (m === null) {
6359
+ throw new SimDbError("DB_UNSAFE_OP", `\u65E0\u6CD5\u89E3\u6790 ON CONFLICT \u5B50\u53E5\uFF1A${clause.trim().slice(0, 60)}\u2026`);
6360
+ }
6361
+ const colsRaw = m[1];
6362
+ const cols = colsRaw === void 0 ? fallbackCols : colsRaw.split(",").map(ident);
6363
+ if (cols.length === 0) throw new SimDbError("DB_UNSAFE_OP", "ON CONFLICT \u51B2\u7A81\u5217\u4E3A\u7A7A");
6364
+ const action = m[2] ?? "";
6365
+ if (/^NOTHING/i.test(action)) return { cols, sets: [] };
6366
+ const setRaw = m[3] ?? "";
6367
+ const sets = splitListItems(setRaw).map((part) => {
6368
+ const eq = /^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*([\s\S]+)$/i.exec(part.trim());
6369
+ if (eq === null) {
6370
+ throw new SimDbError("DB_UNSAFE_OP", `\u65E0\u6CD5\u89E3\u6790 SET \u8D4B\u503C\uFF1A${part.trim().slice(0, 60)}\u2026`);
6371
+ }
6372
+ const col = ident(eq[1] ?? "");
6373
+ const rhs = (eq[2] ?? "").trim();
6374
+ let value;
6375
+ if (rhs === "?") {
6376
+ value = cursor.take();
6377
+ } else {
6378
+ const ex = /^excluded\.([A-Za-z_][A-Za-z0-9_]*)$/i.exec(rhs);
6379
+ if (ex !== null) {
6380
+ value = new ExcludedRef(ident(ex[1] ?? ""));
6381
+ } else if (/^([A-Za-z_][A-Za-z0-9_]*)$/.test(rhs) && !/^NULL$/i.test(rhs)) {
6382
+ value = new ColumnRef(ident(rhs));
6383
+ } else if (/^'.*'$/.test(rhs) || /^".*"$/.test(rhs) || /^NULL$/i.test(rhs)) {
6384
+ value = stripQuotes(rhs);
6385
+ } else {
6386
+ value = new ExprRef(rhs);
6387
+ }
6388
+ }
6389
+ return { col, value };
6390
+ });
6391
+ return { cols, sets };
6392
+ }
5413
6393
  function matchValue(value, clause) {
5414
6394
  const op = clause.operator;
5415
6395
  if (op === "IS NULL") return value === null || value === void 0;
@@ -5537,6 +6517,17 @@ var SimSqlEngine = class {
5537
6517
  }
5538
6518
  return { changes: 0 };
5539
6519
  }
6520
+ if (/^CREATE\s+(?:UNIQUE\s+)?INDEX\s+(?:IF\s+NOT\s+EXISTS\s+)?/i.test(stmt)) {
6521
+ const idx = /^CREATE\s+(?:UNIQUE\s+)?INDEX\s+(?:IF\s+NOT\s+EXISTS\s+)?((?:"[^"]+")|([A-Za-z_][A-Za-z0-9_]*))\s+ON\s+((?:"[^"]+")|([A-Za-z_][A-Za-z0-9_]*))/i.exec(
6522
+ stmt
6523
+ );
6524
+ if (idx === null) throw new SimDbError("DB_UNSAFE_OP", `\u65E0\u6CD5\u89E3\u6790 CREATE INDEX \u8BED\u53E5`);
6525
+ const tableName = ident(idx[3]);
6526
+ if (this.tables[tableName] === void 0) {
6527
+ throw new SimDbError("DB_UNSAFE_OP", `CREATE INDEX \u76EE\u6807\u8868\u4E0D\u5B58\u5728\uFF1A${tableName}`);
6528
+ }
6529
+ return { changes: 0 };
6530
+ }
5540
6531
  if (/^INSERT\s+INTO/i.test(stmt)) return this.execInsert(stmt, params);
5541
6532
  if (/^UPDATE\s+/i.test(stmt)) return this.execUpdate(stmt, params);
5542
6533
  if (/^DELETE\s+FROM/i.test(stmt)) return this.execDelete(stmt, params);
@@ -5552,16 +6543,36 @@ var SimSqlEngine = class {
5552
6543
  const valueBody = match[4].trim();
5553
6544
  const cursor = new ParamCursor(params);
5554
6545
  const table = this.ensureTable(tableName);
6546
+ const { tuples, conflict } = splitInsertTuples(valueBody);
6547
+ if (tuples.length === 0) throw new SimDbError("DB_UNSAFE_OP", "INSERT \u7F3A\u5C11 VALUES \u5143\u7EC4");
6548
+ const conflictSpec = conflict === null ? null : parseConflictClause(
6549
+ conflict,
6550
+ cursor,
6551
+ table.columns.filter((c) => c.primaryKey).map((c) => c.name)
6552
+ );
5555
6553
  let inserted = 0;
5556
- for (const group of splitListItems(valueBody)) {
5557
- const inner = group.trim().replace(/^\(|\)$/g, "");
5558
- const values = splitListItems(inner).map(
6554
+ for (const tuple of tuples) {
6555
+ const values = splitListItems(tuple).map(
5559
6556
  (item) => item.trim() === "?" ? cursor.take() : stripQuotes(item)
5560
6557
  );
5561
6558
  const row = {};
5562
6559
  cols.forEach((col, i) => {
5563
6560
  row[col] = values[i] ?? null;
5564
6561
  });
6562
+ if (conflictSpec !== null) {
6563
+ const existing = table.rows.find(
6564
+ (r) => conflictSpec.cols.every((c) => r[c] === row[c])
6565
+ );
6566
+ if (existing !== void 0) {
6567
+ const oldRow = { ...existing };
6568
+ for (const set of conflictSpec.sets) {
6569
+ existing[set.col] = resolveSetValue(set.value, oldRow, row);
6570
+ }
6571
+ inserted += 1;
6572
+ void this.persist();
6573
+ continue;
6574
+ }
6575
+ }
5565
6576
  this.applyAutoincrement(table, row);
5566
6577
  table.rows.push(row);
5567
6578
  inserted += 1;
@@ -5630,6 +6641,20 @@ var SimSqlEngine = class {
5630
6641
  return project(this.catalog(), selectRaw);
5631
6642
  }
5632
6643
  const table = this.ensureTable(tableName);
6644
+ let rows = table.rows;
6645
+ const joins = parseLeftJoins(tail);
6646
+ if (joins.length > 0) {
6647
+ rows = table.rows.map((row) => {
6648
+ const merged = { ...row };
6649
+ for (const j of joins) {
6650
+ const joined = this.tables[j.table]?.rows.find((jr) => jr[j.leftCol] === merged[j.rightCol]);
6651
+ if (joined !== void 0) {
6652
+ for (const [k, v] of Object.entries(joined)) merged[`${j.alias}.${k}`] = v;
6653
+ }
6654
+ }
6655
+ return merged;
6656
+ });
6657
+ }
5633
6658
  const whereMatch = /\bWHERE\b/i.exec(tail);
5634
6659
  const orderMatch = /\bORDER\s+BY\b/i.exec(tail);
5635
6660
  const limitMatch = /\bLIMIT\b/i.exec(tail);
@@ -5638,7 +6663,6 @@ var SimSqlEngine = class {
5638
6663
  whereMatch.index + whereMatch[0].length,
5639
6664
  indexAfter(whereMatch.index, [orderMatch, limitMatch, offsetMatch], tail)
5640
6665
  );
5641
- let rows = table.rows;
5642
6666
  if (whereRaw.trim().length > 0) {
5643
6667
  const clauses = parseWhereClauses(whereRaw, cursor);
5644
6668
  rows = rows.filter((row) => matchWhere(clauses, row));
@@ -5648,9 +6672,9 @@ var SimSqlEngine = class {
5648
6672
  orderMatch.index + orderMatch[0].length,
5649
6673
  indexAfter(orderMatch.index, [limitMatch, offsetMatch], tail)
5650
6674
  );
5651
- const oc = /^\s*((?:"[^"]+")|([A-Za-z_][A-Za-z0-9_]*))\s+(asc|desc)/i.exec(orderRaw);
6675
+ const oc = /^\s*((?:"[^"]+")|([A-Za-z_][A-Za-z0-9_.]*))\s+(asc|desc)/i.exec(orderRaw);
5652
6676
  if (oc !== null) {
5653
- const col = ident(oc[1]);
6677
+ const col = unqualifyColumn(ident(oc[1]));
5654
6678
  const dir = oc[3].toLowerCase();
5655
6679
  rows = [...rows].toSorted((a, b) => {
5656
6680
  const av = a[col];
@@ -5695,6 +6719,15 @@ function indexAfter(start, matches, tail) {
5695
6719
  const end = candidates.length === 0 ? -1 : Math.min(...candidates);
5696
6720
  return end === -1 ? tail.length : end;
5697
6721
  }
6722
+ function parseSelectItem(raw) {
6723
+ const t = raw.trim();
6724
+ const as = /\s+AS\s+([A-Za-z_][A-Za-z0-9_]*)$/i.exec(t);
6725
+ let name = as === null ? t : t.slice(0, as.index).trim();
6726
+ if (unqualifyColumn(name) === "*") return { name: "", qualified: "", alias: "", star: true };
6727
+ const qualified = /^[A-Za-z_][A-Za-z0-9_]*\.[A-Za-z_][A-Za-z0-9_]*$/.test(name) ? ident(name) : "";
6728
+ const plain = unqualifyColumn(ident(name));
6729
+ return { name: plain, qualified, alias: as === null ? plain : ident(as[1] ?? ""), star: false };
6730
+ }
5698
6731
  function project(rows, selectRaw) {
5699
6732
  if (/^count\s*\(\s*\*/i.test(selectRaw) || /^count\s*\(\s*1\)/i.test(selectRaw)) {
5700
6733
  const alias = selectRaw.match(/\bAS\s+([A-Za-z_][A-Za-z0-9_]*)/i)?.[1] ?? "n";
@@ -5705,10 +6738,21 @@ function project(rows, selectRaw) {
5705
6738
  return [{ [constMatch[2]]: Number(constMatch[1]) }];
5706
6739
  }
5707
6740
  if (selectRaw.trim() === "*") return rows;
5708
- const cols = selectRaw.split(",").map((s) => ident(s.trim()));
6741
+ const items = selectRaw.split(",").map(parseSelectItem);
6742
+ const valueOf = (row, item) => item.qualified !== "" && row[item.qualified] !== void 0 ? row[item.qualified] : row[item.name];
6743
+ if (items.some((item) => item.star)) {
6744
+ return rows.map((row) => {
6745
+ const out = { ...row };
6746
+ for (const item of items) {
6747
+ if (item.star) continue;
6748
+ out[item.alias] = valueOf(row, item);
6749
+ }
6750
+ return out;
6751
+ });
6752
+ }
5709
6753
  return rows.map((row) => {
5710
6754
  const out = {};
5711
- for (const col of cols) out[col] = row[col];
6755
+ for (const item of items) out[item.alias] = valueOf(row, item);
5712
6756
  return out;
5713
6757
  });
5714
6758
  }
@@ -5781,6 +6825,19 @@ function assertSafeStoragePath(path) {
5781
6825
  }
5782
6826
  return path;
5783
6827
  }
6828
+ function assertStoragePrefix(prefix) {
6829
+ if (prefix !== void 0 && prefix !== "") {
6830
+ const segments = prefix.split("/");
6831
+ if (prefix.startsWith("/") || /[\\]/.test(prefix) || segments.some((segment) => segment === "..")) {
6832
+ throw new StorageError(
6833
+ 400,
6834
+ STORAGE_CODES.invalidPath,
6835
+ `\u975E\u6CD5\u524D\u7F00 "${prefix}"\uFF08\u7981\u6B62 / \u5F00\u5934\u3001\u53CD\u659C\u6760\u6216 .. \u7A7F\u8D8A\uFF09`
6836
+ );
6837
+ }
6838
+ }
6839
+ return prefix ?? "";
6840
+ }
5784
6841
 
5785
6842
  // packages/runtime/src/storage/hmac-sha256.ts
5786
6843
  var K = new Uint32Array([
@@ -6100,16 +7157,7 @@ function createBrowserStorageDriver(options) {
6100
7157
  await saveBucket(bucket);
6101
7158
  },
6102
7159
  async list(_projectId, prefix) {
6103
- if (prefix !== void 0 && prefix !== "") {
6104
- const segments = prefix.split("/");
6105
- if (prefix.startsWith("/") || /[\\]/.test(prefix) || segments.some((segment) => segment === "..")) {
6106
- throw new StorageError(
6107
- 400,
6108
- STORAGE_CODES.invalidPath,
6109
- `\u975E\u6CD5\u524D\u7F00 "${prefix}"\uFF08\u7981\u6B62 / \u5F00\u5934\u3001\u53CD\u659C\u6760\u6216 .. \u7A7F\u8D8A\uFF09`
6110
- );
6111
- }
6112
- }
7160
+ assertStoragePrefix(prefix);
6113
7161
  const bucket = await loadBucket();
6114
7162
  return Object.values(bucket).filter((object) => prefix === void 0 || object.path.startsWith(prefix)).map(toMeta).toSorted((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
6115
7163
  },
@@ -6496,6 +7544,19 @@ function createCloudContainer() {
6496
7544
  };
6497
7545
  }
6498
7546
 
7547
+ // packages/runtime/src/functions/runtime/rpc-wire.ts
7548
+ function wireRpcResponses(port, pending) {
7549
+ port.on?.((message) => {
7550
+ const reply = message;
7551
+ if (reply?.type !== "rpc-response" || typeof reply.id !== "number") return;
7552
+ const entry = pending.get(reply.id);
7553
+ if (entry === void 0) return;
7554
+ pending.delete(reply.id);
7555
+ if (reply.ok === true) entry.resolve(reply.result);
7556
+ else entry.reject(new Error(reply.error ?? "RPC \u80FD\u529B\u8C03\u7528\u5931\u8D25"));
7557
+ });
7558
+ }
7559
+
6499
7560
  // packages/web-container/src/sim/ctx.ts
6500
7561
  function createLocalPort(handler) {
6501
7562
  const listeners = [];
@@ -6525,17 +7586,6 @@ function createLocalPort(handler) {
6525
7586
  }
6526
7587
  };
6527
7588
  }
6528
- function wireRpcResponses(port, pending) {
6529
- port.on((message) => {
6530
- const reply = message;
6531
- if (reply?.type !== "rpc-response" || typeof reply.id !== "number") return;
6532
- const entry = pending.get(reply.id);
6533
- if (entry === void 0) return;
6534
- pending.delete(reply.id);
6535
- if (reply.ok === true) entry.resolve(reply.result);
6536
- else entry.reject(new Error(reply.error ?? "RPC \u80FD\u529B\u8C03\u7528\u5931\u8D25"));
6537
- });
6538
- }
6539
7589
  function createFlatRpcClient(handler) {
6540
7590
  return new Proxy(
6541
7591
  {},
@@ -6749,6 +7799,27 @@ function createOfflineFunctionRunner(options = {}) {
6749
7799
  return { run };
6750
7800
  }
6751
7801
 
7802
+ // packages/runtime/src/sim/merge.ts
7803
+ function mergeBundles(bundles) {
7804
+ const capabilities = [];
7805
+ const byName = /* @__PURE__ */ new Map();
7806
+ for (const bundle of bundles) {
7807
+ for (const cap of bundle.capabilities) {
7808
+ const existing = byName.get(cap.name);
7809
+ if (existing !== void 0) capabilities.splice(capabilities.indexOf(existing), 1);
7810
+ byName.set(cap.name, cap);
7811
+ capabilities.push(cap);
7812
+ }
7813
+ }
7814
+ const rpcHandlers = {};
7815
+ for (const bundle of bundles) {
7816
+ for (const [name, handler] of Object.entries(bundle.rpcHandlers)) {
7817
+ rpcHandlers[name] = handler;
7818
+ }
7819
+ }
7820
+ return { capabilities, rpcHandlers };
7821
+ }
7822
+
6752
7823
  // packages/runtime/src/database/sdk/kv.ts
6753
7824
  var KV_TABLE = "_adep_kv";
6754
7825
  var KV_RPC = {
@@ -6850,25 +7921,6 @@ function createKvCapability(driver) {
6850
7921
  }
6851
7922
 
6852
7923
  // packages/web-container/src/sim/runtime.ts
6853
- function mergeBundles(bundles) {
6854
- const capabilities = [];
6855
- const byName = /* @__PURE__ */ new Map();
6856
- for (const bundle of bundles) {
6857
- for (const cap of bundle.capabilities) {
6858
- const existing = byName.get(cap.name);
6859
- if (existing !== void 0) capabilities.splice(capabilities.indexOf(existing), 1);
6860
- byName.set(cap.name, cap);
6861
- capabilities.push(cap);
6862
- }
6863
- }
6864
- const rpcHandlers = {};
6865
- for (const bundle of bundles) {
6866
- for (const [name, handler] of Object.entries(bundle.rpcHandlers)) {
6867
- rpcHandlers[name] = handler;
6868
- }
6869
- }
6870
- return { capabilities, rpcHandlers };
6871
- }
6872
7924
  async function createBrowserSimRuntime(options) {
6873
7925
  const kv = options.kv ?? pickDefaultSimKv();
6874
7926
  const db = createBrowserSimDb({ projectId: options.projectId, kv });
@@ -6899,8 +7951,11 @@ async function createBrowserSimRuntime(options) {
6899
7951
 
6900
7952
  // packages/web-container/src/index.ts
6901
7953
  init_function_fetch_proxy();
7954
+ init_console_relay();
6902
7955
  export {
7956
+ BUNDLE_MODULE_PATH_PREFIX,
6903
7957
  COMPLETABLE_COMMANDS,
7958
+ CONSOLE_RELAY_SCRIPT,
6904
7959
  DEFAULT_MAX_INSTALL_DEPTH,
6905
7960
  EXTRA_COMMANDS,
6906
7961
  FN_FETCH_INTERCEPTOR_SCRIPT,
@@ -6945,12 +8000,15 @@ export {
6945
8000
  createViteServer,
6946
8001
  createWorkerRuntime,
6947
8002
  deepEqual,
8003
+ defaultModuleName,
6948
8004
  displayPath,
6949
8005
  entriesToTree,
6950
8006
  evaluateModuleSource,
6951
8007
  evaluateSource,
6952
8008
  exampleTestSource,
6953
8009
  expect as expectAssertion,
8010
+ exportBundle,
8011
+ findBlobRefs,
6954
8012
  formatTestReport,
6955
8013
  formatValue,
6956
8014
  fullName,