@adep/web-container 0.1.1 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -92,9 +92,796 @@ var AdepWebContainer = (() => {
92
92
  }
93
93
  });
94
94
 
95
- // src/preview.ts
96
- var preview_exports = {};
97
- __export(preview_exports, {
95
+ // src/node-resolve.ts
96
+ function parsePackageMeta(content, context) {
97
+ let parsed;
98
+ try {
99
+ parsed = JSON.parse(content);
100
+ } catch {
101
+ throw new ResolveError(`${context} \u4E0D\u662F\u5408\u6CD5 JSON`);
102
+ }
103
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
104
+ throw new ResolveError(`${context} \u9876\u5C42\u5FC5\u987B\u662F\u5BF9\u8C61`);
105
+ }
106
+ return parsed;
107
+ }
108
+ function withinPackage(pkgDirAbs, rel, context) {
109
+ if (typeof rel !== "string" || rel === "") {
110
+ throw new ResolveError(`${context}\uFF1A\u5165\u53E3\u8DEF\u5F84\u5FC5\u987B\u662F\u5B57\u7B26\u4E32`);
111
+ }
112
+ if (!rel.startsWith("./") && !rel.startsWith("../") && rel.startsWith("/")) {
113
+ throw new ResolveError(`${context}\uFF1A\u5165\u53E3\u8DEF\u5F84 "${rel}" \u5FC5\u987B\u662F\u5305\u5185\u76F8\u5BF9\u8DEF\u5F84\uFF08\u4EE5 ./ \u5F00\u5934\uFF09`);
114
+ }
115
+ const abs = join(pkgDirAbs, rel.startsWith(".") ? rel : `./${rel}`);
116
+ if (!abs.startsWith(`${pkgDirAbs}/`)) {
117
+ throw new ResolveError(`${context}\uFF1A\u5165\u53E3\u8DEF\u5F84 "${rel}" \u8D8A\u51FA\u5305\u76EE\u5F55\uFF0C\u5DF2\u62D2\u7EDD`);
118
+ }
119
+ return abs;
120
+ }
121
+ function resolvePackageEntry(meta, pkgDirAbs, condition) {
122
+ const context = `\u5305 ${meta.name ?? meta.version ?? pkgDirAbs} \u7684 exports/main \u58F0\u660E`;
123
+ const exp = meta.exports;
124
+ if (exp !== void 0 && exp !== null) {
125
+ if (typeof exp === "string") return withinPackage(pkgDirAbs, exp, context);
126
+ if (typeof exp !== "object" || Array.isArray(exp)) {
127
+ throw new ResolveError(`${context} \u5F62\u6001\u4E0D\u652F\u6301\uFF08exports \u53EA\u80FD\u662F\u5B57\u7B26\u4E32\u6216\u5BF9\u8C61\uFF09`);
128
+ }
129
+ const dot = exp["."];
130
+ if (dot === void 0) {
131
+ throw new ResolveError(
132
+ `${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`
133
+ );
134
+ }
135
+ if (typeof dot === "string") return withinPackage(pkgDirAbs, dot, context);
136
+ if (dot === null)
137
+ throw new ResolveError(`${context}\uFF1Aexports["."] \u4E3A null\uFF08\u8BE5\u6761\u4EF6\u88AB\u663E\u5F0F\u6392\u9664\uFF09\uFF0C\u65E0\u6CD5\u89E3\u6790\u5165\u53E3`);
138
+ if (typeof dot !== "object" || Array.isArray(dot)) {
139
+ throw new ResolveError(`${context}\uFF1Aexports["."] \u5F62\u6001\u4E0D\u652F\u6301\uFF08\u4EC5\u63A5\u53D7\u5B57\u7B26\u4E32\u6216\u6761\u4EF6\u5BF9\u8C61\uFF09`);
140
+ }
141
+ const conditions = dot;
142
+ const order = condition === "import" ? ["import", "node", "default"] : ["require", "node", "default"];
143
+ for (const key of order) {
144
+ const value = conditions[key];
145
+ if (typeof value === "string") return withinPackage(pkgDirAbs, value, context);
146
+ if (value !== void 0 && (typeof value !== "object" || value === null)) {
147
+ throw new ResolveError(
148
+ `${context}\uFF1Aexports["."]["${key}"] \u5F62\u6001\u4E0D\u652F\u6301\uFF08\u4EC5\u63A5\u53D7\u5B57\u7B26\u4E32\u6216 null\uFF09`
149
+ );
150
+ }
151
+ }
152
+ throw new ResolveError(
153
+ `${context}\uFF1Aexports["."] \u6761\u4EF6\u5BF9\u8C61\u91CC\u6CA1\u6709 ${condition}/node/default \u5B57\u7B26\u4E32\u5165\u53E3\uFF08\u5B50\u8DEF\u5F84/\u5D4C\u5957\u6761\u4EF6\u4E0D\u652F\u6301\uFF09`
154
+ );
155
+ }
156
+ if (meta.main !== void 0) {
157
+ if (typeof meta.main !== "string") {
158
+ throw new ResolveError(`${context}\uFF1Amain \u5FC5\u987B\u662F\u5B57\u7B26\u4E32`);
159
+ }
160
+ return withinPackage(pkgDirAbs, meta.main, context);
161
+ }
162
+ return join(pkgDirAbs, "index.js");
163
+ }
164
+ function splitPackageSpecifier(spec) {
165
+ if (spec.startsWith("@")) {
166
+ const first = spec.indexOf("/");
167
+ if (first === -1) return { name: spec, subpath: "" };
168
+ const second = spec.indexOf("/", first + 1);
169
+ if (second === -1) return { name: spec, subpath: "" };
170
+ return { name: spec.slice(0, second), subpath: spec.slice(second + 1) };
171
+ }
172
+ const slash = spec.indexOf("/");
173
+ if (slash === -1) return { name: spec, subpath: "" };
174
+ return { name: spec.slice(0, slash), subpath: spec.slice(slash + 1) };
175
+ }
176
+ function asFile(fs, baseAbs) {
177
+ if (fs.exists(baseAbs) && !fsIsDirectory(fs, baseAbs)) return baseAbs;
178
+ for (const ext of RESOLVE_EXTENSIONS) {
179
+ const candidate = `${baseAbs}${ext}`;
180
+ if (fs.exists(candidate) && !fsIsDirectory(fs, candidate)) return candidate;
181
+ }
182
+ return null;
183
+ }
184
+ function asDirectory(fs, dirAbs) {
185
+ if (!fs.exists(dirAbs) || !fsIsDirectory(fs, dirAbs)) return null;
186
+ const manifest = `${dirAbs}/package.json`;
187
+ if (fs.exists(manifest)) {
188
+ const meta = parsePackageMeta(fs.readFile(manifest), manifest);
189
+ const entry = resolvePackageEntry(meta, dirAbs, "require");
190
+ const hit = asFile(fs, entry);
191
+ if (hit !== null) return hit;
192
+ }
193
+ return asFile(fs, join(dirAbs, "index"));
194
+ }
195
+ function fsIsDirectory(fs, path) {
196
+ const probe = fs;
197
+ return probe.isDirectory?.(path) ?? false;
198
+ }
199
+ function resolveImport(fs, specifier, fromFileAbs, condition = "require") {
200
+ if (specifier === "") throw new ResolveError("\u7A7A\u8BF4\u660E\u7B26\uFF1A\u65E0\u6CD5\u89E3\u6790\u6A21\u5757");
201
+ if (specifier.startsWith("./") || specifier.startsWith("../")) {
202
+ const base = join(dirname(fromFileAbs), specifier);
203
+ const hit = asFile(fs, base) ?? asDirectory(fs, base);
204
+ if (hit === null) {
205
+ throw new ResolveError(
206
+ `\u627E\u4E0D\u5230\u76F8\u5BF9\u6A21\u5757 "${specifier}"\uFF08\u81EA ${dirname(fromFileAbs)}\uFF0C\u8BD5\u8FC7\u6269\u5C55\u540D ${RESOLVE_EXTENSIONS.join("/")} \u4E0E\u76EE\u5F55\u7D22\u5F15\uFF09`
207
+ );
208
+ }
209
+ return hit;
210
+ }
211
+ if (specifier.startsWith("/")) {
212
+ const hit = asFile(fs, specifier) ?? asDirectory(fs, specifier);
213
+ if (hit === null) throw new ResolveError(`\u627E\u4E0D\u5230\u7EDD\u5BF9\u8DEF\u5F84\u6A21\u5757 "${specifier}"`);
214
+ return hit;
215
+ }
216
+ const { name, subpath } = splitPackageSpecifier(specifier);
217
+ if (name.startsWith("node:")) {
218
+ throw new ResolveError(`\u6D4F\u89C8\u5668\u6C99\u7BB1\u4E0D\u63D0\u4F9B Node \u5185\u5EFA\u6A21\u5757 "${specifier}"`);
219
+ }
220
+ let dir = dirname(fromFileAbs);
221
+ for (; ; ) {
222
+ const pkgDir = join(dir, "node_modules", name);
223
+ if (fs.exists(pkgDir) && fsIsDirectory(fs, pkgDir)) {
224
+ if (subpath === "") {
225
+ const manifest = `${pkgDir}/package.json`;
226
+ if (fs.exists(manifest)) {
227
+ const meta = parsePackageMeta(fs.readFile(manifest), manifest);
228
+ const entry = resolvePackageEntry(meta, pkgDir, condition);
229
+ const hit = asFile(fs, entry) ?? asDirectory(fs, entry);
230
+ if (hit !== null) return hit;
231
+ } else {
232
+ const hit = asFile(fs, join(pkgDir, "index")) ?? asDirectory(fs, pkgDir);
233
+ if (hit !== null) return hit;
234
+ }
235
+ } else {
236
+ const base = join(pkgDir, subpath);
237
+ const hit = asFile(fs, base) ?? asDirectory(fs, base);
238
+ if (hit !== null) return hit;
239
+ }
240
+ throw new ResolveError(
241
+ `\u5728 ${pkgDir} \u627E\u5230\u4E86\u5305 "${name}"\uFF0C\u4F46\u89E3\u6790\u8BF4\u660E\u7B26 "${specifier}" \u5931\u8D25\uFF08\u5B50\u8DEF\u5F84\u4E0D\u5B58\u5728\uFF0C\u6216 exports/main \u6307\u5411\u7684\u5165\u53E3\u6587\u4EF6\u7F3A\u5931\uFF09`
242
+ );
243
+ }
244
+ const parent = dirname(dir);
245
+ if (parent === dir) break;
246
+ dir = parent;
247
+ }
248
+ throw new ResolveError(
249
+ `\u627E\u4E0D\u5230\u5305 "${specifier}"\uFF1A${dirname(fromFileAbs)} \u53CA\u5176\u5404\u7EA7\u7236\u76EE\u5F55\u4E0B\u90FD\u6CA1\u6709 node_modules/${name}\uFF08\u5148\u5728\u7EC8\u7AEF npm install ${name}\uFF09`
250
+ );
251
+ }
252
+ var RESOLVE_EXTENSIONS, ResolveError;
253
+ var init_node_resolve = __esm({
254
+ "src/node-resolve.ts"() {
255
+ "use strict";
256
+ init_path();
257
+ RESOLVE_EXTENSIONS = [".js", ".mjs", ".cjs", ".json"];
258
+ ResolveError = class extends Error {
259
+ constructor(message) {
260
+ super(message);
261
+ this.name = "ResolveError";
262
+ }
263
+ };
264
+ }
265
+ });
266
+
267
+ // src/strip-types.ts
268
+ function isAnnotationLeader(token) {
269
+ return ANNOTATION_LEADERS.has(token) || TS_MODIFIERS.has(token);
270
+ }
271
+ function stripTypes(source) {
272
+ return new Eraser(source).run();
273
+ }
274
+ var UnsupportedTsSyntaxError, IDENT_START, IDENT_PART, DECL_KEYWORDS, TS_MODIFIERS, ANNOTATION_LEADERS, Eraser;
275
+ var init_strip_types = __esm({
276
+ "src/strip-types.ts"() {
277
+ "use strict";
278
+ UnsupportedTsSyntaxError = class extends Error {
279
+ constructor(construct, line) {
280
+ super(`\u4E0D\u53D7\u652F\u6301\u7684 TypeScript \u8BED\u6CD5\uFF1A${construct}\uFF08\u7B2C ${line} \u884C\uFF09\u2014\u2014\u6D4F\u89C8\u5668\u6D4B\u8BD5\u6C99\u7BB1\u53EA\u64E6\u9664\u7C7B\u578B\u6807\u6CE8`);
281
+ this.construct = construct;
282
+ this.line = line;
283
+ this.name = "UnsupportedTsSyntaxError";
284
+ }
285
+ };
286
+ IDENT_START = /[A-Za-z_$]/;
287
+ IDENT_PART = /[A-Za-z0-9_$]/;
288
+ DECL_KEYWORDS = /* @__PURE__ */ new Set(["const", "let", "var"]);
289
+ TS_MODIFIERS = /* @__PURE__ */ new Set([
290
+ "private",
291
+ "protected",
292
+ "public",
293
+ "readonly",
294
+ "abstract",
295
+ "override",
296
+ "declare"
297
+ ]);
298
+ ANNOTATION_LEADERS = /* @__PURE__ */ new Set(["(", ",", "{", ";", "erased", "modifier"]);
299
+ Eraser = class {
300
+ constructor(src) {
301
+ this.src = src;
302
+ this.chars = [...src];
303
+ }
304
+ chars;
305
+ tokens = [];
306
+ frames = [];
307
+ /** 刚消费 `class` 头:下一个 `{` 是类体起始。 */
308
+ pendingClassBody = false;
309
+ /** 刚消费 `=>`:其后的 `(` 是箭头函数参数列表(声明位)。 */
310
+ afterArrow = false;
311
+ /** 刚消费 `function` 关键字:其后的标识符是函数名,再后是参数列表。 */
312
+ afterFunctionKeyword = false;
313
+ /** 最近一次 `)` 闭合的是不是参数列表(返回值标注判据)。 */
314
+ justClosedDeclareParen = false;
315
+ i = 0;
316
+ run() {
317
+ while (this.i < this.src.length) {
318
+ if (/\s/.test(this.ch())) {
319
+ this.i++;
320
+ continue;
321
+ }
322
+ if (this.copyTrivia()) continue;
323
+ if (this.copyLiteral()) continue;
324
+ if (this.copyRegexIfNeeded()) continue;
325
+ if (this.readNumber()) continue;
326
+ const word = this.readWord();
327
+ if (word !== null) this.handleWord(word);
328
+ else this.handlePunctuation();
329
+ }
330
+ return this.chars.join("");
331
+ }
332
+ /* ———————————————————— 游标原语 ———————————————————— */
333
+ ch(offset = 0) {
334
+ return this.src[this.i + offset] ?? "";
335
+ }
336
+ /** 回看第 `back` 个显著 token(1 = 最近一个)。 */
337
+ tokenAt(back) {
338
+ return this.tokens[this.tokens.length - back] ?? "";
339
+ }
340
+ /** 擦除结果里 `from` 往前的最后一个非空白字符(看的是已擦除文本,不是原文)。 */
341
+ prevSignificantChar(from) {
342
+ for (let j = from; j >= 0; j--) {
343
+ const c = this.chars[j];
344
+ if (c !== " " && c !== " " && c !== "\n" && c !== "\r") return c;
345
+ }
346
+ return "";
347
+ }
348
+ /** 擦除 `[from, to)`:填等长空格,换行照抄——擦完行号与原文件一致。 */
349
+ erase(from, to) {
350
+ for (let j = Math.max(from, 0); j < to; j++) this.chars[j] = this.src[j] === "\n" ? "\n" : " ";
351
+ }
352
+ pushToken(token) {
353
+ this.afterArrow = token === "=>";
354
+ this.afterFunctionKeyword = token === "function";
355
+ this.tokens.push(token);
356
+ }
357
+ /** 数字面量整段消费(否则 `1.5` 会被拆成 `1` `.` `5`,`.` 参与判据时误判)。 */
358
+ readNumber() {
359
+ if (!/[0-9]/.test(this.ch())) return false;
360
+ let end = this.i;
361
+ while (end < this.src.length && /[0-9a-fA-FxXoObB._]/.test(this.src[end])) end++;
362
+ this.i = end;
363
+ this.pushToken("number");
364
+ return true;
365
+ }
366
+ readWord() {
367
+ if (!IDENT_START.test(this.ch())) return null;
368
+ let end = this.i;
369
+ while (end < this.src.length && IDENT_PART.test(this.src[end])) end++;
370
+ const word = this.src.slice(this.i, end);
371
+ this.i = end;
372
+ this.pushToken(word);
373
+ return word;
374
+ }
375
+ /* —————————————— 字面量与注释:整段跳过(内容永不参与判定) —————————————— */
376
+ copyTrivia() {
377
+ const head = this.ch();
378
+ const next = this.ch(1);
379
+ if (head === "/" && next === "/") {
380
+ while (this.i < this.src.length && this.ch() !== "\n") this.i++;
381
+ return true;
382
+ }
383
+ if (head === "/" && next === "*") {
384
+ const end = this.src.indexOf("*/", this.i + 2);
385
+ this.i = end === -1 ? this.src.length : end + 2;
386
+ return true;
387
+ }
388
+ return false;
389
+ }
390
+ copyLiteral() {
391
+ const head = this.ch();
392
+ if (head !== "'" && head !== '"' && head !== "`") return false;
393
+ this.i = head === "`" ? this.scanTemplate(this.i) : this.scanQuoted(this.i);
394
+ this.pushToken(head === "`" ? "template" : "string");
395
+ return true;
396
+ }
397
+ /** 引号串结束下标(未闭合则到行尾,把真实的语法错误留给求值期)。 */
398
+ scanQuoted(start) {
399
+ const quote = this.src[start];
400
+ let j = start + 1;
401
+ while (j < this.src.length) {
402
+ const c = this.src[j];
403
+ if (c === "\\") j += 2;
404
+ else if (c === quote) return j + 1;
405
+ else if (c === "\n") return j;
406
+ else j++;
407
+ }
408
+ return this.src.length;
409
+ }
410
+ /** 模板串结束下标(`${}` 内按大括号配平,内层字符串 / 模板一并识别)。 */
411
+ scanTemplate(start) {
412
+ let j = start + 1;
413
+ while (j < this.src.length) {
414
+ const c = this.src[j];
415
+ if (c === "\\") j += 2;
416
+ else if (c === "`") return j + 1;
417
+ else if (c === "$" && this.src[j + 1] === "{") j = this.scanInterpolation(j + 2);
418
+ else j++;
419
+ }
420
+ return this.src.length;
421
+ }
422
+ scanInterpolation(start) {
423
+ let depth = 1;
424
+ let j = start;
425
+ while (j < this.src.length) {
426
+ const c = this.src[j];
427
+ if (c === "\\") j += 2;
428
+ else if (c === "'" || c === '"') j = this.scanQuoted(j);
429
+ else if (c === "`") j = this.scanTemplate(j);
430
+ else if (c === "{") {
431
+ depth++;
432
+ j++;
433
+ } else if (c === "}") {
434
+ depth--;
435
+ j++;
436
+ if (depth === 0) return j;
437
+ } else j++;
438
+ }
439
+ return this.src.length;
440
+ }
441
+ /**
442
+ * 正则字面量:`/` 只在「运算符位」才是正则起始(前一个显著字符不是值结尾)。
443
+ * 判不准时按除号处理——除号后面不会有需要擦除的类型标注,最坏只是漏擦。
444
+ * 有了这条,`const url = /https:\/\//` 里的 `:` 与 `//` 才不会被人当语法(恒等用例之一)。
445
+ */
446
+ copyRegexIfNeeded() {
447
+ if (this.ch() !== "/") return false;
448
+ const prev = this.prevSignificantChar(this.i - 1);
449
+ const valueEnding = prev !== "" && (IDENT_PART.test(prev) || prev === ")" || prev === "]" || prev === "}" || prev === '"' || prev === "'" || prev === "`");
450
+ if (valueEnding) return false;
451
+ const end = this.scanRegex(this.i);
452
+ if (end === null) return false;
453
+ this.i = end;
454
+ this.pushToken("regex");
455
+ return true;
456
+ }
457
+ scanRegex(start) {
458
+ let j = start + 1;
459
+ let inClass = false;
460
+ while (j < this.src.length) {
461
+ const c = this.src[j];
462
+ if (c === "\\") {
463
+ j += 2;
464
+ continue;
465
+ }
466
+ if (c === "\n") return null;
467
+ if (c === "[") inClass = true;
468
+ else if (c === "]") inClass = false;
469
+ else if (c === "/" && !inClass) {
470
+ j++;
471
+ while (j < this.src.length && /[a-z]/i.test(this.src[j])) j++;
472
+ return j;
473
+ }
474
+ j++;
475
+ }
476
+ return null;
477
+ }
478
+ /* ———————————————— 关键字与声明结构 ———————————————— */
479
+ handleWord(word) {
480
+ const start = this.i - word.length;
481
+ if (this.tokenAt(2) === ".") {
482
+ this.consumeGenericsAfterName();
483
+ return;
484
+ }
485
+ switch (word) {
486
+ case "interface": {
487
+ const after = this.skipWhitespaceFrom(this.skipNameAndParams(start + word.length));
488
+ if (after === null || this.src[after] !== "{") return;
489
+ const end = this.scanBalanced(after, "{", "}");
490
+ this.erase(start, end);
491
+ this.i = end;
492
+ this.pushToken("erased");
493
+ return;
494
+ }
495
+ case "type": {
496
+ const after = this.skipWhitespaceFrom(this.skipNameAndParams(this.i));
497
+ if (after === null || this.src[after] !== "=") return;
498
+ const end = this.scanTypeExpression(after + 1, true);
499
+ this.erase(start, end);
500
+ this.i = end;
501
+ this.pushToken("erased");
502
+ return;
503
+ }
504
+ case "import":
505
+ case "export": {
506
+ if (!/^\s+type\b/.test(this.src.slice(this.i))) return;
507
+ const after = this.skipNameAndParams(this.i);
508
+ if (after === null) return;
509
+ const end = this.scanStatementEnd(after);
510
+ this.erase(start, end);
511
+ this.i = end;
512
+ this.pushToken("erased");
513
+ return;
514
+ }
515
+ case "enum":
516
+ case "namespace":
517
+ throw new UnsupportedTsSyntaxError(word, this.lineAt(start));
518
+ case "implements": {
519
+ let j = this.i;
520
+ while (j < this.src.length && this.src[j] !== "{" && this.src[j] !== ";") j++;
521
+ this.erase(start, j);
522
+ this.i = j;
523
+ this.pushToken("erased");
524
+ return;
525
+ }
526
+ case "class":
527
+ this.pendingClassBody = true;
528
+ return;
529
+ case "as":
530
+ case "satisfies": {
531
+ if (this.tokenAt(2) === "*" || this.tokenAt(2) === "type") return;
532
+ const nextChar = this.skipWhitespaceFrom(this.i);
533
+ if (nextChar === null || "=,:]})".includes(this.src[nextChar])) return;
534
+ const end = this.scanTypeExpression(this.i, false);
535
+ this.erase(start, end);
536
+ this.i = end;
537
+ return;
538
+ }
539
+ default: {
540
+ if (TS_MODIFIERS.has(word) && this.inClassBody()) {
541
+ const next = this.peekWord();
542
+ if (next === "" || /[{(=]/.test(next[0])) return;
543
+ this.erase(start, this.i);
544
+ this.pushToken("modifier");
545
+ return;
546
+ }
547
+ this.consumeGenericsAfterName();
548
+ }
549
+ }
550
+ }
551
+ peekWord() {
552
+ let j = this.i;
553
+ while (j < this.src.length && /\s/.test(this.src[j])) j++;
554
+ let end = j;
555
+ while (end < this.src.length && IDENT_PART.test(this.src[end])) end++;
556
+ return this.src.slice(j, end);
557
+ }
558
+ lineAt(index) {
559
+ let line = 1;
560
+ for (let j = 0; j < index; j++) if (this.src[j] === "\n") line++;
561
+ return line;
562
+ }
563
+ /** `:` 之前紧邻的是不是 `)`(返回值标注位;用于决定是否允许顶层 `=>` 续读)。 */
564
+ lastSignificantCharIsCloseParen(at) {
565
+ return this.prevSignificantChar(at - 1) === ")";
566
+ }
567
+ inClassBody() {
568
+ return this.frames[this.frames.length - 1]?.classBody === true;
569
+ }
570
+ /** 当前帧是不是声明位(参数列表 / 类体)——只有这里才允许把 `:` 判成标注。 */
571
+ inDeclarePosition() {
572
+ const frame = this.frames[this.frames.length - 1];
573
+ return frame !== void 0 && (frame.declare || frame.classBody);
574
+ }
575
+ /* ———————————————— 标点与括号帧 ———————————————— */
576
+ handlePunctuation() {
577
+ const c = this.ch();
578
+ const start = this.i;
579
+ if (c === "(" || c === "{" || c === "[") {
580
+ const frame = {
581
+ kind: c === "(" ? "paren" : c === "{" ? "brace" : "bracket",
582
+ declare: false,
583
+ classBody: false
584
+ };
585
+ if (c === "{" && this.pendingClassBody) {
586
+ frame.classBody = true;
587
+ this.pendingClassBody = false;
588
+ }
589
+ if (c === "(" && this.isDeclareParen(start)) frame.declare = true;
590
+ this.frames.push(frame);
591
+ this.i++;
592
+ this.pushToken(c);
593
+ return;
594
+ }
595
+ if (c === ")" || c === "}" || c === "]") {
596
+ const closed = this.frames.pop();
597
+ if (closed?.kind === "paren") this.justClosedDeclareParen = closed.declare;
598
+ this.i++;
599
+ this.pushToken(c);
600
+ return;
601
+ }
602
+ if (c === ":") {
603
+ if (this.ch(1) === ":") {
604
+ this.i++;
605
+ this.pushToken(":");
606
+ return;
607
+ }
608
+ const returnType = this.isAnnotationColon(start) && this.lastSignificantCharIsCloseParen(start);
609
+ if (returnType || this.isAnnotationColon(start)) {
610
+ const end = this.scanTypeExpression(start + 1, false, returnType);
611
+ this.erase(start, end);
612
+ this.i = end;
613
+ this.pushToken("erased");
614
+ return;
615
+ }
616
+ this.i++;
617
+ this.pushToken(":");
618
+ return;
619
+ }
620
+ if (c === "?" && this.ch(1) !== "?" && this.ch(1) !== ".") {
621
+ let j = start + 1;
622
+ while (j < this.src.length && (this.src[j] === " " || this.src[j] === " ")) j++;
623
+ if (this.src[j] === ":" && this.inDeclarePosition() && IDENT_PART.test(this.prevSignificantChar(start - 1))) {
624
+ const end = this.scanTypeExpression(j + 1, false);
625
+ this.erase(start, end);
626
+ this.i = end;
627
+ this.pushToken("erased");
628
+ return;
629
+ }
630
+ this.i++;
631
+ this.pushToken("?");
632
+ return;
633
+ }
634
+ if (c === "!" && this.ch(1) !== "=" && this.isPostfixBang(start)) {
635
+ this.erase(start, start + 1);
636
+ this.i++;
637
+ return;
638
+ }
639
+ if (c === "=" && this.ch(1) === ">") {
640
+ this.i += 2;
641
+ this.pushToken("=>");
642
+ return;
643
+ }
644
+ if (c === "<" && this.consumeLeadingGenerics(start)) return;
645
+ this.i++;
646
+ this.pushToken(c);
647
+ }
648
+ /** 空白跳跃(供声明结构找下一个非空白字符;不改游标,纯函数)。 */
649
+ skipWhitespaceFrom(index) {
650
+ if (index === null) return null;
651
+ let j = index;
652
+ while (j < this.src.length && /\s/.test(this.src[j])) j++;
653
+ return j;
654
+ }
655
+ /**
656
+ * 运算符位上的泛型参数列表(`const f = <T, >(x: T) => x`、`arr.map<T2>(...)` 之外的箭头形态):
657
+ * 前一个显著字符不是值结尾(否则是 `a < b` 比较),且 `>` 之后紧跟 `(` 才擦。
658
+ */
659
+ consumeLeadingGenerics(at) {
660
+ if (!"([{,=;:>!&|?".includes(this.prevSignificantChar(at - 1))) return false;
661
+ const end = this.scanTypeParams(at);
662
+ if (end === null) return false;
663
+ const after = this.skipWhitespaceFrom(end);
664
+ if (after === null || this.src[after] !== "(") return false;
665
+ this.erase(at, end);
666
+ this.i = end;
667
+ return true;
668
+ }
669
+ /**
670
+ * `(` 是否为参数列表(声明位):`function f(`、类体里的方法 `m(`、箭头 `=> (`,
671
+ * 以及出现在 `(` `,` `=` `>` `:` `[` `{` `}` `;` 之后(如 `map((v: T) => v)` 的内层括号)。
672
+ * 调用位 `foo(` 与控制流 `if (` `for (` 都不算。
673
+ * 误判成声明位也不足以擦掉什么:`:` 还要过 `isAnnotationColon` 的「名字前驱必须是
674
+ * `(` `,` `{` `;` 修饰符」这一关,而三元表达式的中间段前面必然是 `?`。
675
+ */
676
+ isDeclareParen(at) {
677
+ if (this.afterFunctionKeyword) return true;
678
+ if (this.tokenAt(2) === "function" && IDENT_START.test(this.tokenAt(1))) return true;
679
+ if (this.afterArrow) return true;
680
+ if (this.inClassBody() && IDENT_PART.test(this.prevSignificantChar(at - 1))) return true;
681
+ const prev = this.prevSignificantChar(at - 1);
682
+ return prev === "" || "(,=>:[{};".includes(prev);
683
+ }
684
+ /** `:` 是类型标注吗:看名字前驱 token 与所在帧(对象键、三元、`case` 一律排除)。 */
685
+ isAnnotationColon(at) {
686
+ const prev = this.prevSignificantChar(at - 1);
687
+ if (prev === ")") return this.justClosedDeclareParen;
688
+ if (prev === "}" || prev === "]") {
689
+ const frame = this.frames[this.frames.length - 1];
690
+ return frame?.kind === "paren" && frame.declare;
691
+ }
692
+ if (!IDENT_PART.test(prev)) return false;
693
+ if (this.tokenAt(1) === "number" || this.tokenAt(1) === "string") return false;
694
+ if (this.inDeclarePosition() && isAnnotationLeader(this.tokenAt(2))) return true;
695
+ return DECL_KEYWORDS.has(this.tokenAt(2));
696
+ }
697
+ /** 非空断言 `x!`:前一个显著字符是值结尾,且后一个非空白字符不是操作数起始。 */
698
+ isPostfixBang(at) {
699
+ const prev = this.prevSignificantChar(at - 1);
700
+ if (!(IDENT_PART.test(prev) || prev === ")" || prev === "]")) return false;
701
+ let j = at + 1;
702
+ while (j < this.src.length && (this.src[j] === " " || this.src[j] === " ")) j++;
703
+ const next = this.src[j] ?? "";
704
+ if (next === "") return true;
705
+ return !(IDENT_START.test(next) || /[0-9]/.test(next) || "(![~".includes(next));
706
+ }
707
+ /* ———————————————— 区间扫描(全部字符串 / 注释安全) ———————————————— */
708
+ /** 跳过「名字 + 泛型参数」;没有合法名字时返回 null(`{ type: 1 }` 因此落空)。 */
709
+ skipNameAndParams(from) {
710
+ let j = from;
711
+ while (j < this.src.length && /\s/.test(this.src[j])) j++;
712
+ const nameStart = j;
713
+ while (j < this.src.length && IDENT_PART.test(this.src[j])) j++;
714
+ if (j === nameStart) return null;
715
+ const generic = this.scanTypeParams(j);
716
+ return generic === null ? j : generic;
717
+ }
718
+ /** `<T, U extends X>`:返回 `>` 之后的下标;跨到 `)` `]` `;` 换行前配不平则 null。 */
719
+ scanTypeParams(from) {
720
+ if (this.src[from] !== "<") return null;
721
+ let depth = 0;
722
+ let j = from;
723
+ for (; j < this.src.length; j++) {
724
+ const c = this.src[j];
725
+ if (c === "<") depth++;
726
+ else if (c === ">") {
727
+ depth--;
728
+ if (depth === 0) return j + 1;
729
+ } else if (c === ")" || c === "]" || c === ";" || c === "\n") return null;
730
+ else if (c === "'" || c === '"') j = this.scanQuoted(j) - 1;
731
+ else if (c === "`") j = this.scanTemplate(j) - 1;
732
+ }
733
+ return null;
734
+ }
735
+ /**
736
+ * 消费「刚读出的标识符之后」的泛型实参 / 类型参数(`function f<T>(`、方法 `m<T>(`、`f<T>(x)`)。
737
+ * 只有 `>` 之后紧跟 `(` / `{` / `implements` 才算——`if (a < b) {` 里 `>` 之后是 `)`,故安全。
738
+ */
739
+ consumeGenericsAfterName() {
740
+ if (this.ch() !== "<") return;
741
+ const end = this.scanTypeParams(this.i);
742
+ if (end === null) return;
743
+ let j = end;
744
+ while (j < this.src.length && (this.src[j] === " " || this.src[j] === " ")) j++;
745
+ const after = this.src.slice(j);
746
+ if (!/^[({]/.test(after) && !/^implements\b/.test(after)) return;
747
+ this.erase(this.i, end);
748
+ this.i = end;
749
+ }
750
+ /** 括号配平:返回闭括号之后的下标(未配平则到文件尾)。 */
751
+ scanBalanced(from, open, close) {
752
+ let depth = 0;
753
+ let j = from;
754
+ while (j < this.src.length) {
755
+ const c = this.src[j];
756
+ if (c === "'" || c === '"') j = this.scanQuoted(j);
757
+ else if (c === "`") j = this.scanTemplate(j);
758
+ else if (c === "/" && (this.src[j + 1] === "/" || this.src[j + 1] === "*"))
759
+ j = this.skipComment(j);
760
+ else if (c === open) {
761
+ depth++;
762
+ j++;
763
+ } else if (c === close) {
764
+ depth--;
765
+ j++;
766
+ if (depth === 0) return j;
767
+ } else j++;
768
+ }
769
+ return this.src.length;
770
+ }
771
+ skipComment(from) {
772
+ if (this.src[from + 1] === "/") {
773
+ const end2 = this.src.indexOf("\n", from);
774
+ return end2 === -1 ? this.src.length : end2;
775
+ }
776
+ const end = this.src.indexOf("*/", from + 2);
777
+ return end === -1 ? this.src.length : end + 2;
778
+ }
779
+ /** 语句结束(`;` 或括号已配平时的行尾),用于 `import type …`。 */
780
+ scanStatementEnd(from) {
781
+ let depth = 0;
782
+ let j = from;
783
+ while (j < this.src.length) {
784
+ const c = this.src[j];
785
+ if (c === "'" || c === '"') j = this.scanQuoted(j);
786
+ else if (c === "`") j = this.scanTemplate(j);
787
+ else if (c === "{" || c === "(" || c === "[") {
788
+ depth++;
789
+ j++;
790
+ } else if (c === "}" || c === ")" || c === "]") {
791
+ depth--;
792
+ j++;
793
+ } else if (c === ";" || c === "\n" && depth <= 0) break;
794
+ else j++;
795
+ }
796
+ return j;
797
+ }
798
+ /**
799
+ * 类型表达式结束下标:消费标识符 / 字符串字面量类型 / 泛型实参 / 元组 / 对象类型 /
800
+ * 函数类型(含 `=>` 返回值)/ 联合与交叉;在深度 0 的 `= , ; ) ]` 与「已结束的行」处停下。
801
+ *
802
+ * 两处歧义的处理:
803
+ * - `function f(): { a: number } { … }`——还没消费过类型原子时遇到的 `{` 属于类型,
804
+ * 之后再遇 `{` 才是函数体;`type X = A` 的初始值花括号整体算类型(`leadingBraceIsType`)。
805
+ * - `const x: Foo = { … }`——在 `=` 处停,不会把右侧对象字面量吞掉。
806
+ */
807
+ scanTypeExpression(from, leadingBraceIsType, topLevelArrowEnds = false) {
808
+ let depth = 0;
809
+ let j = from;
810
+ let sawAtom = false;
811
+ while (j < this.src.length) {
812
+ const c = this.src[j];
813
+ if (c === "'" || c === '"') {
814
+ j = this.scanQuoted(j);
815
+ sawAtom = true;
816
+ } else if (c === "`") {
817
+ j = this.scanTemplate(j);
818
+ sawAtom = true;
819
+ } else if (c === "/" && (this.src[j + 1] === "/" || this.src[j + 1] === "*")) {
820
+ j = this.skipComment(j);
821
+ } else if (c === "(" || c === "[") {
822
+ depth++;
823
+ sawAtom = true;
824
+ j++;
825
+ } else if (c === ")" || c === "]") {
826
+ if (depth === 0) break;
827
+ depth--;
828
+ j++;
829
+ } else if (c === "{") {
830
+ if (depth === 0 && sawAtom && !leadingBraceIsType) break;
831
+ j = this.scanBalanced(j, "{", "}");
832
+ sawAtom = true;
833
+ } else if (c === "}") {
834
+ if (depth === 0) break;
835
+ depth--;
836
+ j++;
837
+ } else if (depth === 0 && (c === "," || c === ";")) break;
838
+ else if (depth === 0 && c === "=") {
839
+ if (this.src[j + 1] === ">" && !topLevelArrowEnds) {
840
+ j += 2;
841
+ continue;
842
+ }
843
+ break;
844
+ } else if (depth === 0 && c === "\n") {
845
+ if (!this.typeContinuesAt(j)) break;
846
+ j++;
847
+ } else if (c === "<") {
848
+ const generic = this.scanTypeParams(j);
849
+ if (generic === null) break;
850
+ j = generic;
851
+ sawAtom = true;
852
+ } else {
853
+ if (IDENT_PART.test(c)) sawAtom = true;
854
+ j++;
855
+ }
856
+ }
857
+ return j;
858
+ }
859
+ /**
860
+ * 行尾处类型是否仍在继续:`type Id = string\n | number` 要接得上,
861
+ * 而 `const x: Foo\nconst y = 1` 必须停。判据是两侧的非空邻字——
862
+ * 前一个是连接符(`| & < > = , . ? : (`)或后一个是连接符 / 闭合符(`| & , . ? : ) ] } >`)。
863
+ */
864
+ typeContinuesAt(index) {
865
+ for (let j = index - 1; j >= 0; j--) {
866
+ const c = this.src[j];
867
+ if (/\s/.test(c)) continue;
868
+ if ("|&<>=,.?:(".includes(c)) return true;
869
+ break;
870
+ }
871
+ for (let j = index + 1; j < this.src.length; j++) {
872
+ const c = this.src[j];
873
+ if (/\s/.test(c)) continue;
874
+ return "|&,.?:)]}>".includes(c);
875
+ }
876
+ return false;
877
+ }
878
+ };
879
+ }
880
+ });
881
+
882
+ // src/preview-server.ts
883
+ var preview_server_exports = {};
884
+ __export(preview_server_exports, {
98
885
  buildPreviewDocument: () => buildPreviewDocument,
99
886
  createPreviewServer: () => createPreviewServer,
100
887
  inlineAssets: () => inlineAssets
@@ -190,20 +977,664 @@ var AdepWebContainer = (() => {
190
977
  };
191
978
  }
192
979
  var EXTERNAL_SRC;
193
- var init_preview = __esm({
194
- "src/preview.ts"() {
980
+ var init_preview_server = __esm({
981
+ "src/preview-server.ts"() {
195
982
  "use strict";
196
983
  init_path();
197
984
  EXTERNAL_SRC = /(?:^https?:)?\/\//i;
198
985
  }
199
986
  });
200
987
 
988
+ // src/function-fetch-proxy.ts
989
+ function parseBodyByContentType(rawBody, headers) {
990
+ if (rawBody === null) return void 0;
991
+ const contentType = headers["content-type"] ?? headers["Content-Type"] ?? headers["CONTENT-TYPE"] ?? "";
992
+ if (!/json/i.test(contentType)) return rawBody;
993
+ try {
994
+ return JSON.parse(rawBody);
995
+ } catch {
996
+ return rawBody;
997
+ }
998
+ }
999
+ function createFunctionFetchHandler(options) {
1000
+ return async (event) => {
1001
+ const data = event.data;
1002
+ if (!data || data.__adepFnRequest !== true) return;
1003
+ const source = event.source;
1004
+ const post = source?.postMessage;
1005
+ if (typeof post !== "function") return;
1006
+ const reply = (payload) => {
1007
+ try {
1008
+ post.call(source, { __adepFnResponse: true, ...payload }, "*");
1009
+ } catch {
1010
+ }
1011
+ };
1012
+ try {
1013
+ const id = data.id;
1014
+ const method = String(data.method ?? "GET").toUpperCase();
1015
+ const url = String(data.url ?? "");
1016
+ const headers = typeof data.headers === "object" && data.headers !== null ? data.headers : {};
1017
+ const rawBody = typeof data.body === "string" ? data.body : data.body === null || data.body === void 0 ? null : String(data.body);
1018
+ const qIndex = url.indexOf("?");
1019
+ const pathPart = qIndex === -1 ? url : url.slice(0, qIndex);
1020
+ const queryPart = qIndex === -1 ? "" : url.slice(qIndex + 1);
1021
+ const match = pathPart.match(/^\/api\/([^/]+)(\/.*)?$/);
1022
+ if (match === null) {
1023
+ reply({
1024
+ id,
1025
+ status: 404,
1026
+ headers: { "content-type": "application/json" },
1027
+ body: JSON.stringify({
1028
+ error: { code: "FN_NOT_FOUND", message: `\u65E0\u6CD5\u89E3\u6790\u7684\u4E91\u51FD\u6570\u8DEF\u5F84: ${url}` }
1029
+ })
1030
+ });
1031
+ return;
1032
+ }
1033
+ const fnName = decodeURIComponent(match[1] ?? "");
1034
+ const subPath = match[2] ?? "/";
1035
+ const query = {};
1036
+ if (queryPart !== "") {
1037
+ try {
1038
+ new URLSearchParams(queryPart).forEach((value, key) => {
1039
+ query[key] = value;
1040
+ });
1041
+ } catch {
1042
+ }
1043
+ }
1044
+ const files = await options.getFunctionFiles(fnName);
1045
+ if (files === null || Object.keys(files).length === 0) {
1046
+ reply({
1047
+ id,
1048
+ status: 404,
1049
+ headers: { "content-type": "application/json" },
1050
+ body: JSON.stringify({
1051
+ error: {
1052
+ code: "FN_NOT_FOUND",
1053
+ message: `\u4E91\u51FD\u6570 "${fnName}" \u4E0D\u5B58\u5728\u6216\u5C1A\u672A\u52A0\u8F7D\u8349\u7A3F`
1054
+ }
1055
+ })
1056
+ });
1057
+ return;
1058
+ }
1059
+ const entry = files["index.ts"] !== void 0 ? "index.ts" : Object.keys(files)[0] ?? "";
1060
+ if (entry === "") {
1061
+ reply({
1062
+ id,
1063
+ status: 500,
1064
+ headers: { "content-type": "application/json" },
1065
+ body: JSON.stringify({
1066
+ error: { code: "FN_NO_ENTRY", message: `\u4E91\u51FD\u6570 "${fnName}" \u6CA1\u6709\u53EF\u6267\u884C\u6587\u4EF6` }
1067
+ })
1068
+ });
1069
+ return;
1070
+ }
1071
+ const body = parseBodyByContentType(rawBody, headers);
1072
+ const result = await options.runner.run({
1073
+ files,
1074
+ entry,
1075
+ request: {
1076
+ method,
1077
+ path: subPath,
1078
+ query,
1079
+ headers,
1080
+ ...body === void 0 ? {} : { body }
1081
+ },
1082
+ bundle: options.bundle
1083
+ });
1084
+ let status = result.status;
1085
+ let outBody;
1086
+ let outContentType = "application/json";
1087
+ if (result.error !== void 0) {
1088
+ if (status === 200) status = 500;
1089
+ outBody = JSON.stringify({ error: result.error });
1090
+ } else if (typeof result.body === "string") {
1091
+ outBody = result.body;
1092
+ outContentType = "text/plain; charset=utf-8";
1093
+ } else {
1094
+ outBody = JSON.stringify(result.body ?? null);
1095
+ }
1096
+ reply({ id, status, headers: { "content-type": outContentType }, body: outBody });
1097
+ } catch (error) {
1098
+ reply({
1099
+ id: data?.id,
1100
+ status: 500,
1101
+ headers: { "content-type": "application/json" },
1102
+ body: JSON.stringify({
1103
+ error: {
1104
+ code: "FN_PROXY_ERROR",
1105
+ message: error instanceof Error ? error.message : String(error)
1106
+ }
1107
+ })
1108
+ });
1109
+ }
1110
+ };
1111
+ }
1112
+ var FN_FETCH_INTERCEPTOR_SCRIPT;
1113
+ var init_function_fetch_proxy = __esm({
1114
+ "src/function-fetch-proxy.ts"() {
1115
+ "use strict";
1116
+ FN_FETCH_INTERCEPTOR_SCRIPT = (function() {
1117
+ var src = [
1118
+ "(function () {",
1119
+ " if (window.__adepFnProxyInstalled) return;",
1120
+ " window.__adepFnProxyInstalled = true;",
1121
+ " var ORIGINAL_FETCH = window.fetch.bind(window);",
1122
+ " var pending = {};",
1123
+ " var nextId = 1;",
1124
+ " var TIMEOUT_MS = 15000;",
1125
+ "",
1126
+ ' window.addEventListener("message", function (event) {',
1127
+ " var data = event.data;",
1128
+ " if (!data || data.__adepFnResponse !== true) return;",
1129
+ " var entry = pending[data.id];",
1130
+ " if (!entry) return;",
1131
+ " delete pending[data.id];",
1132
+ " clearTimeout(entry.timer);",
1133
+ " var headers;",
1134
+ " try { headers = new Headers(data.headers || {}); }",
1135
+ ' catch (e) { headers = new Headers({ "content-type": "text/plain" }); }',
1136
+ " var body = data.body == null ? null : data.body;",
1137
+ " try {",
1138
+ ' entry.resolve(new Response(body, { status: data.status || 200, statusText: "", headers: headers }));',
1139
+ " } catch (e2) {",
1140
+ ' entry.resolve(new Response(String(body), { status: data.status || 200, headers: { "content-type": "text/plain" } }));',
1141
+ " }",
1142
+ " });",
1143
+ "",
1144
+ " function readBody(input, init) {",
1145
+ ' if (typeof Request !== "undefined" && input instanceof Request) {',
1146
+ " return input.text().catch(function () { return null; });",
1147
+ " }",
1148
+ " var body = init && init.body !== undefined ? init.body : input;",
1149
+ " if (body == null) return Promise.resolve(null);",
1150
+ ' if (typeof body === "string") return Promise.resolve(body);',
1151
+ ' if (typeof ArrayBuffer !== "undefined" && body instanceof ArrayBuffer) {',
1152
+ " return Promise.resolve(new TextDecoder().decode(body));",
1153
+ " }",
1154
+ ' if (typeof Blob !== "undefined" && body instanceof Blob) return body.text();',
1155
+ ' if (typeof URLSearchParams !== "undefined" && body instanceof URLSearchParams) {',
1156
+ " return Promise.resolve(body.toString());",
1157
+ " }",
1158
+ " try { return Promise.resolve(String(body)); } catch (e) { return Promise.resolve(null); }",
1159
+ " }",
1160
+ "",
1161
+ " function collectHeaders(input, init) {",
1162
+ " var out = {};",
1163
+ " try { input.headers.forEach(function (v, k) { out[k] = v; }); } catch (e) {}",
1164
+ " if (init && init.headers) {",
1165
+ " try { new Headers(init.headers).forEach(function (v, k) { out[k] = v; }); } catch (e2) {}",
1166
+ " }",
1167
+ " return out;",
1168
+ " }",
1169
+ "",
1170
+ " window.fetch = function (input, init) {",
1171
+ " var urlStr;",
1172
+ " var method;",
1173
+ " var headers = {};",
1174
+ ' var isRequest = typeof Request !== "undefined" && input instanceof Request;',
1175
+ " if (isRequest) {",
1176
+ " urlStr = String(input.url);",
1177
+ ' method = (init && init.method) || input.method || "GET";',
1178
+ " headers = collectHeaders(input, init);",
1179
+ ' } else if (typeof input === "string" || (typeof URL !== "undefined" && input instanceof URL)) {',
1180
+ " urlStr = String(input);",
1181
+ ' method = (init && init.method) || "GET";',
1182
+ " try { new Headers(init && init.headers || {}).forEach(function (v, k) { headers[k] = v; }); } catch (e) {}",
1183
+ " } else {",
1184
+ " return ORIGINAL_FETCH(input, init);",
1185
+ " }",
1186
+ " var u;",
1187
+ " try { u = new URL(urlStr, document.baseURI); }",
1188
+ " catch (e) { return ORIGINAL_FETCH(input, init); }",
1189
+ ' if (u.pathname.indexOf("/api/") !== 0 && u.pathname !== "/api") {',
1190
+ " return ORIGINAL_FETCH(input, init);",
1191
+ " }",
1192
+ " if (window.parent === window) return ORIGINAL_FETCH(input, init);",
1193
+ ' method = (method || "GET").toUpperCase();',
1194
+ " var target = u.pathname + u.search;",
1195
+ " return readBody(input, init).then(function (textBody) {",
1196
+ " return new Promise(function (resolve) {",
1197
+ " var id = nextId++;",
1198
+ " var timer = setTimeout(function () {",
1199
+ " delete pending[id];",
1200
+ ` resolve(new Response('{"error":{"code":"FN_PROXY_TIMEOUT","message":"\\u4e91\\u51fd\\u6570\\u6267\\u884c\\u8d85\\u65f6"}}', { status: 504, headers: { "content-type": "application/json" } }));`,
1201
+ " }, TIMEOUT_MS);",
1202
+ " pending[id] = { resolve: resolve, timer: timer };",
1203
+ ' window.parent.postMessage({ __adepFnRequest: true, id: id, method: method, url: target, headers: headers, body: textBody }, "*");',
1204
+ " });",
1205
+ " });",
1206
+ " };",
1207
+ "})();"
1208
+ ].join("\n");
1209
+ return src;
1210
+ })();
1211
+ }
1212
+ });
1213
+
1214
+ // src/vite-dev.ts
1215
+ var vite_dev_exports = {};
1216
+ __export(vite_dev_exports, {
1217
+ ViteDevError: () => ViteDevError,
1218
+ createViteServer: () => createViteServer,
1219
+ scanEsmSpecifiers: () => scanEsmSpecifiers
1220
+ });
1221
+ function tokenize2(source) {
1222
+ const tokens = [];
1223
+ let i = 0;
1224
+ const n = source.length;
1225
+ while (i < n) {
1226
+ const ch = source[i];
1227
+ if (ch === " " || ch === " " || ch === "\n" || ch === "\r") {
1228
+ i++;
1229
+ continue;
1230
+ }
1231
+ if (ch === "/" && source[i + 1] === "/") {
1232
+ i = source.indexOf("\n", i);
1233
+ if (i === -1) break;
1234
+ continue;
1235
+ }
1236
+ if (ch === "/" && source[i + 1] === "*") {
1237
+ const close = source.indexOf("*/", i + 2);
1238
+ if (close === -1) break;
1239
+ i = close + 2;
1240
+ continue;
1241
+ }
1242
+ if (ch === "'" || ch === '"') {
1243
+ let j = i + 1;
1244
+ while (j < n && source[j] !== ch) {
1245
+ if (source[j] === "\\") j++;
1246
+ j++;
1247
+ }
1248
+ tokens.push({ kind: "string", text: source.slice(i, j + 1), start: i, end: j + 1 });
1249
+ i = j + 1;
1250
+ continue;
1251
+ }
1252
+ if (ch === "`") {
1253
+ let j = i + 1;
1254
+ while (j < n && source[j] !== "`") {
1255
+ if (source[j] === "\\") j++;
1256
+ j++;
1257
+ }
1258
+ tokens.push({ kind: "template", text: source.slice(i, j + 1), start: i, end: j + 1 });
1259
+ i = j + 1;
1260
+ continue;
1261
+ }
1262
+ if (ch === "/") {
1263
+ const prev = tokens[tokens.length - 1];
1264
+ const isRegex = prev === void 0 || prev.kind === "punct" && REGEX_PRECEDING_CHARS.has(prev.text) || prev.kind === "ident" && REGEX_PRECEDING_KEYWORDS.has(prev.text);
1265
+ if (isRegex) {
1266
+ let j = i + 1;
1267
+ let inClass = false;
1268
+ while (j < n) {
1269
+ const c = source[j];
1270
+ if (c === "\\") j++;
1271
+ else if (c === "[") inClass = true;
1272
+ else if (c === "]") inClass = false;
1273
+ else if (c === "/" && !inClass) break;
1274
+ else if (c === "\n") break;
1275
+ j++;
1276
+ }
1277
+ tokens.push({ kind: "punct", text: "/", start: i, end: i + 1 });
1278
+ i = j + 1;
1279
+ continue;
1280
+ }
1281
+ }
1282
+ if (isIdentStart(ch)) {
1283
+ let j = i + 1;
1284
+ while (j < n && isIdentPart(source[j])) j++;
1285
+ tokens.push({ kind: "ident", text: source.slice(i, j), start: i, end: j });
1286
+ i = j;
1287
+ continue;
1288
+ }
1289
+ tokens.push({ kind: "punct", text: ch, start: i, end: i + 1 });
1290
+ i++;
1291
+ }
1292
+ return tokens;
1293
+ }
1294
+ function scanEsmSpecifiers(source) {
1295
+ const tokens = tokenize2(source);
1296
+ const hits = [];
1297
+ for (let i = 1; i < tokens.length; i++) {
1298
+ const tok = tokens[i];
1299
+ if (tok.kind !== "string") continue;
1300
+ const prev = tokens[i - 1];
1301
+ const prev2 = tokens[i - 2];
1302
+ if (prev.kind !== "ident" && prev.kind !== "punct") continue;
1303
+ if (prev.kind === "ident" && prev.text === "import") {
1304
+ hits.push({ specifier: tok.text.slice(1, -1), start: tok.start, end: tok.end });
1305
+ continue;
1306
+ }
1307
+ if (prev.kind === "ident" && prev.text === "from" && !(prev2?.kind === "punct" && ["=", ":", ",", "(", "["].includes(prev2.text))) {
1308
+ hits.push({ specifier: tok.text.slice(1, -1), start: tok.start, end: tok.end });
1309
+ continue;
1310
+ }
1311
+ if (prev.kind === "punct" && prev.text === "(" && prev2?.kind === "ident" && prev2.text === "import") {
1312
+ hits.push({ specifier: tok.text.slice(1, -1), start: tok.start, end: tok.end });
1313
+ }
1314
+ }
1315
+ return hits;
1316
+ }
1317
+ function cssModule(css) {
1318
+ return [
1319
+ `const css = ${JSON.stringify(css)};`,
1320
+ 'const el = document.createElement("style");',
1321
+ 'el.setAttribute("data-adep-vite", "");',
1322
+ "el.textContent = css;",
1323
+ "document.head.appendChild(el);",
1324
+ "export default css;"
1325
+ ].join("\n");
1326
+ }
1327
+ function jsonModule(source, abs) {
1328
+ try {
1329
+ JSON.parse(source);
1330
+ } catch {
1331
+ throw new ViteDevError("JSON_PARSE", `${abs} \u4E0D\u662F\u5408\u6CD5 JSON`);
1332
+ }
1333
+ return `export default ${source.trim()};`;
1334
+ }
1335
+ function resolveWithSuffixes(vfs, base) {
1336
+ if (vfs.exists(base) && !vfs.isDirectory(base)) return base;
1337
+ const asFile2 = VITE_RESOLVE_SUFFIXES.map((suffix) => `${base}${suffix}`);
1338
+ const asIndex = VITE_RESOLVE_SUFFIXES.map((suffix) => join(base, `index${suffix}`));
1339
+ return asFile2.find((p) => vfs.exists(p) && !vfs.isDirectory(p)) ?? asIndex.find((p) => vfs.exists(p) && !vfs.isDirectory(p)) ?? base;
1340
+ }
1341
+ function hmrScript(name) {
1342
+ return `<script>(function(){if(typeof BroadcastChannel==='undefined')return;var bc=new BroadcastChannel(${JSON.stringify(
1343
+ name
1344
+ )});bc.onmessage=function(e){var d=e.data;if(d&&d.type==='update'&&d.url&&d.url!==location.href){location.replace(d.url);}};})();<\/script>`;
1345
+ }
1346
+ function createViteServer(vfs, options = {}) {
1347
+ const root = normalize(options.root ?? "/");
1348
+ const entry = options.entry ?? "index.html";
1349
+ const sfcCompiler = options.sfcCompiler;
1350
+ const createObjectURL = options.createObjectURL ?? ((blob) => URL.createObjectURL(blob));
1351
+ const revokeObjectURL = options.revokeObjectURL ?? ((url) => URL.revokeObjectURL(url));
1352
+ const channelName = `adep:vite:${Math.random().toString(36).slice(2)}`;
1353
+ const port = 5173;
1354
+ let moduleUrls = /* @__PURE__ */ new Map();
1355
+ const inFlight = /* @__PURE__ */ new Set();
1356
+ const stableUrls = /* @__PURE__ */ new Map();
1357
+ let inlineSources = /* @__PURE__ */ new Map();
1358
+ let currentUrl = "";
1359
+ let lastDoc = null;
1360
+ let bc = null;
1361
+ let touchTimer = null;
1362
+ let inlineSeq = 0;
1363
+ const scheduleRebuild = () => {
1364
+ if (touchTimer !== null) clearTimeout(touchTimer);
1365
+ touchTimer = setTimeout(() => {
1366
+ touchTimer = null;
1367
+ void rebuild();
1368
+ }, 100);
1369
+ };
1370
+ const broadcast = (url) => {
1371
+ try {
1372
+ bc ??= new BroadcastChannel(channelName);
1373
+ bc.postMessage({ type: "update", url });
1374
+ } catch {
1375
+ }
1376
+ };
1377
+ function transformModule2(abs, source) {
1378
+ if (abs.endsWith(".css")) return cssModule(source);
1379
+ if (abs.endsWith(".json")) return jsonModule(source, abs);
1380
+ if (abs.endsWith(".vue")) {
1381
+ if (sfcCompiler === void 0)
1382
+ throw new ViteDevError(
1383
+ "SFC_NO_COMPILER",
1384
+ `${abs} \u662F Vue SFC\uFF0C\u4F46\u5F53\u524D\u73AF\u5883\u672A\u88C5\u914D SFC \u7F16\u8BD1\u5668\uFF08IDE \u4FA7\u9700\u6CE8\u5165 vue/compiler-sfc\uFF09`
1385
+ );
1386
+ const compiled = sfcCompiler(source, abs);
1387
+ return [...compiled.styles.map((css) => cssModule(css)), compiled.script].join("\n");
1388
+ }
1389
+ if (abs.endsWith(".tsx") || abs.endsWith(".jsx"))
1390
+ throw new ViteDevError(
1391
+ "JSX_UNSUPPORTED",
1392
+ `${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`
1393
+ );
1394
+ if (abs.endsWith(".ts") || abs.endsWith(".mts")) return stripTypes(source);
1395
+ return source;
1396
+ }
1397
+ async function resolveSpecifier(spec, importerAbs) {
1398
+ if (EXTERNAL_SPECIFIER.test(spec) || DATA_OR_BLOB.test(spec)) return spec;
1399
+ let target;
1400
+ if (spec.startsWith("./") || spec.startsWith("../") || spec.startsWith("/")) {
1401
+ const base = spec.startsWith("/") ? spec : join(dirname(importerAbs), spec);
1402
+ target = resolveWithSuffixes(vfs, base);
1403
+ if (!vfs.exists(target) || vfs.isDirectory(target))
1404
+ throw new ViteDevError(
1405
+ "RESOLVE",
1406
+ `\u627E\u4E0D\u5230\u6A21\u5757 "${spec}"\uFF08\u81EA ${importerAbs}\uFF1B\u8BD5\u8FC7\u6269\u5C55\u540D ${VITE_RESOLVE_SUFFIXES.join("/")} \u4E0E\u76EE\u5F55 index\uFF09`
1407
+ );
1408
+ } else {
1409
+ try {
1410
+ target = resolveImport(vfs, spec, importerAbs, "import");
1411
+ } catch (error) {
1412
+ if (error instanceof ResolveError)
1413
+ throw new ViteDevError(
1414
+ "RESOLVE",
1415
+ `${error.message}
1416
+ \uFF08\u5728 ${importerAbs} \u4E2D import "${spec}"\uFF09`
1417
+ );
1418
+ throw error;
1419
+ }
1420
+ }
1421
+ return loadModuleUrl(target);
1422
+ }
1423
+ async function loadModuleUrl(abs) {
1424
+ const cached = moduleUrls.get(abs);
1425
+ if (cached !== void 0) return cached;
1426
+ if (inFlight.has(abs))
1427
+ throw new ViteDevError(
1428
+ "CYCLE",
1429
+ `\u5FAA\u73AF\u4F9D\u8D56\uFF1A${[...inFlight, abs].join(" \u2192 ")}\uFF08blob \u6A21\u5757\u94FE\u7684\u6539\u5199\u53D1\u751F\u5728\u52A0\u8F7D\u671F\uFF0C\u73AF\u65E0\u6CD5\u6210\u94FE\uFF1B\u8BF7\u62C6\u6389\u73AF\u6216\u6539\u7528\u52A8\u6001 import()\uFF09`
1430
+ );
1431
+ inFlight.add(abs);
1432
+ const pending = (async () => {
1433
+ const source = inlineSources.get(abs) ?? vfs.readFile(abs);
1434
+ const code = transformModule2(abs, source);
1435
+ const hits = scanEsmSpecifiers(code);
1436
+ const targets = await Promise.all(hits.map((hit) => resolveSpecifier(hit.specifier, abs)));
1437
+ let out = code;
1438
+ for (let i = hits.length - 1; i >= 0; i--) {
1439
+ const hit = hits[i];
1440
+ out = out.slice(0, hit.start) + JSON.stringify(targets[i]) + out.slice(hit.end);
1441
+ }
1442
+ const key = `${abs}\0${out}`;
1443
+ let url = stableUrls.get(key);
1444
+ if (url === void 0) {
1445
+ url = createObjectURL(new Blob([out], { type: "text/javascript" }));
1446
+ stableUrls.set(key, url);
1447
+ }
1448
+ return url;
1449
+ })();
1450
+ moduleUrls.set(abs, pending);
1451
+ try {
1452
+ return await pending;
1453
+ } catch (error) {
1454
+ moduleUrls.delete(abs);
1455
+ throw error;
1456
+ } finally {
1457
+ inFlight.delete(abs);
1458
+ }
1459
+ }
1460
+ const revokeStableUrls = () => {
1461
+ for (const url of stableUrls.values()) revokeObjectURL(url);
1462
+ stableUrls.clear();
1463
+ };
1464
+ function directoryListing2() {
1465
+ const rows = vfs.listDirectory(root).map((e) => `<li>${e.type === "file" ? "\u{1F4C4}" : "\u{1F4C1}"} <code>${e.path}</code></li>`).join("");
1466
+ return `<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><title>vite \xB7 ${root}</title></head>
1467
+ <body style="font-family:system-ui;padding:24px"><h3>vite dev server \xB7 <code>${root}</code></h3>
1468
+ <p>\u672A\u627E\u5230\u5165\u53E3 <code>${entry}</code>\u3002\u5F53\u524D\u76EE\u5F55\u5185\u5BB9\uFF1A</p><ul>${rows}</ul>
1469
+ <p style="color:#64748b">\u5728 root \u4E0B\u521B\u5EFA ${entry}\uFF0C\u7528 &lt;script type="module" src="./main.ts"&gt; \u5F15\u5165\u6A21\u5757\u5165\u53E3\u3002</p></body></html>`;
1470
+ }
1471
+ function errorDocument(error) {
1472
+ const reason = error instanceof ViteDevError ? error.reason : "BUILD_FAILED";
1473
+ const message = error instanceof Error ? error.message : String(error);
1474
+ return `<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><title>vite error</title></head>
1475
+ <body style="font-family:ui-monospace,monospace;background:#1a1c24;color:#e2e8f0;padding:24px">
1476
+ <h2 style="color:#f43f5e;margin-top:0">[vite] ${reason}</h2>
1477
+ <pre style="white-space:pre-wrap;word-break:break-all;line-height:1.7">${message.replace(/&/g, "&amp;").replace(/</g, "&lt;")}</pre>
1478
+ <p style="color:#94a3b8">\u4FEE\u590D\u4EE3\u7801\u540E\u9884\u89C8\u81EA\u52A8\u91CD\u5EFA\uFF1B\u4E5F\u53EF\u5728\u7EC8\u7AEF\u6267\u884C vite stop / vite &lt;dir&gt; \u91CD\u542F\u3002</p>
1479
+ </body></html>`;
1480
+ }
1481
+ async function buildDocument() {
1482
+ const entryAbs = join(root, entry);
1483
+ if (!vfs.exists(entryAbs) || vfs.isDirectory(entryAbs)) return directoryListing2();
1484
+ let html = vfs.readFile(entryAbs);
1485
+ html = inlineAssets(html, vfs, dirname(entryAbs));
1486
+ const entryModuleUrls = [];
1487
+ html = html.replace(
1488
+ MODULE_SCRIPT_SRC_RE,
1489
+ (_whole, pre, _q1, mid, _q2, src, post) => {
1490
+ const base = src.startsWith("/") ? normalize(src) : join(dirname(entryAbs), src);
1491
+ const abs = resolveWithSuffixes(vfs, base);
1492
+ if (!vfs.exists(abs) || vfs.isDirectory(abs))
1493
+ throw new ViteDevError(
1494
+ "RESOLVE",
1495
+ `\u5165\u53E3 module script \u627E\u4E0D\u5230 "${src}"\uFF08root: ${root}\uFF1B\u8BD5\u8FC7\u6269\u5C55\u540D ${VITE_RESOLVE_SUFFIXES.join("/")} \u4E0E\u76EE\u5F55 index\uFF09`
1496
+ );
1497
+ entryModuleUrls.push(loadModuleUrl(abs));
1498
+ return `<script${pre}${mid}src="__adep_vite_entry_${entryModuleUrls.length - 1}__"${post}><\/script>`;
1499
+ }
1500
+ );
1501
+ html = html.replace(
1502
+ MODULE_SCRIPT_INLINE_RE,
1503
+ (whole, pre, _q, post, body) => {
1504
+ if (/\bsrc\s*=/.test(pre + post)) return whole;
1505
+ const abs = `${INLINE_PREFIX}${inlineSeq++}.mjs`;
1506
+ inlineSources.set(abs, body);
1507
+ entryModuleUrls.push(loadModuleUrl(abs));
1508
+ return `<script${pre}${post}src="__adep_vite_entry_${entryModuleUrls.length - 1}__"><\/script>`;
1509
+ }
1510
+ );
1511
+ const urls = await Promise.all(entryModuleUrls);
1512
+ html = html.replace(/__adep_vite_entry_(\d+)__/g, (_m, idx) => urls[Number(idx)] ?? "");
1513
+ const interceptor = `<script>${FN_FETCH_INTERCEPTOR_SCRIPT}<\/script>`;
1514
+ html = /<head[^>]*>/i.test(html) ? html.replace(/<head[^>]*>/i, (m) => `${m}${interceptor}`) : `${interceptor}${html}`;
1515
+ const hmr = hmrScript(channelName);
1516
+ return /<\/body>/i.test(html) ? html.replace(/<\/(body)>/i, `${hmr}</$1>`) : html + hmr;
1517
+ }
1518
+ async function rebuild() {
1519
+ moduleUrls = /* @__PURE__ */ new Map();
1520
+ inlineSources = /* @__PURE__ */ new Map();
1521
+ inlineSeq = 0;
1522
+ let doc;
1523
+ try {
1524
+ doc = await buildDocument();
1525
+ } catch (error) {
1526
+ doc = errorDocument(error);
1527
+ }
1528
+ const changed = lastDoc !== null && doc !== lastDoc;
1529
+ lastDoc = doc;
1530
+ if (currentUrl !== "") revokeObjectURL(currentUrl);
1531
+ currentUrl = createObjectURL(new Blob([doc], { type: "text/html" }));
1532
+ if (changed) broadcast(currentUrl);
1533
+ }
1534
+ const server = {
1535
+ get url() {
1536
+ return currentUrl;
1537
+ },
1538
+ get port() {
1539
+ return port;
1540
+ },
1541
+ get root() {
1542
+ return root;
1543
+ },
1544
+ ready: rebuild(),
1545
+ touch() {
1546
+ scheduleRebuild();
1547
+ },
1548
+ async stop() {
1549
+ if (touchTimer !== null) {
1550
+ clearTimeout(touchTimer);
1551
+ touchTimer = null;
1552
+ }
1553
+ unsubscribeMutate();
1554
+ moduleUrls = /* @__PURE__ */ new Map();
1555
+ revokeStableUrls();
1556
+ if (currentUrl !== "") revokeObjectURL(currentUrl);
1557
+ currentUrl = "";
1558
+ bc?.close();
1559
+ bc = null;
1560
+ }
1561
+ };
1562
+ const unsubscribeMutate = vfs.onMutate(scheduleRebuild);
1563
+ return server;
1564
+ }
1565
+ 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;
1566
+ var init_vite_dev = __esm({
1567
+ "src/vite-dev.ts"() {
1568
+ "use strict";
1569
+ init_path();
1570
+ init_node_resolve();
1571
+ init_strip_types();
1572
+ init_preview_server();
1573
+ init_function_fetch_proxy();
1574
+ ViteDevError = class extends Error {
1575
+ constructor(reason, message) {
1576
+ super(message);
1577
+ this.reason = reason;
1578
+ this.name = "ViteDevError";
1579
+ }
1580
+ };
1581
+ REGEX_PRECEDING_CHARS = /* @__PURE__ */ new Set([
1582
+ "=",
1583
+ "(",
1584
+ ",",
1585
+ "[",
1586
+ "!",
1587
+ "&",
1588
+ "|",
1589
+ "?",
1590
+ ":",
1591
+ ";",
1592
+ "{",
1593
+ "}",
1594
+ "^",
1595
+ "~",
1596
+ "<",
1597
+ ">",
1598
+ "+",
1599
+ "-",
1600
+ "*",
1601
+ "/",
1602
+ "%"
1603
+ ]);
1604
+ REGEX_PRECEDING_KEYWORDS = /* @__PURE__ */ new Set([
1605
+ "return",
1606
+ "typeof",
1607
+ "instanceof",
1608
+ "in",
1609
+ "of",
1610
+ "new",
1611
+ "delete",
1612
+ "void",
1613
+ "throw",
1614
+ "case",
1615
+ "do",
1616
+ "else",
1617
+ "yield",
1618
+ "await"
1619
+ ]);
1620
+ isIdentStart = (ch) => /[A-Za-z_$]/.test(ch);
1621
+ isIdentPart = (ch) => /[A-Za-z0-9_$]/.test(ch);
1622
+ VITE_RESOLVE_SUFFIXES = [".ts", ".js", ".mjs", ".mts", ".vue", ".json", ".css"];
1623
+ INLINE_PREFIX = "/__vite_inline_";
1624
+ EXTERNAL_SPECIFIER = /^(?:https?:)?\/\//i;
1625
+ DATA_OR_BLOB = /^(?:data|blob):/i;
1626
+ MODULE_SCRIPT_SRC_RE = /<script\b([^>]*?)\btype\s*=\s*(["'])module\2([^>]*?)\bsrc\s*=\s*(["'])(.*?)\4([^>]*)><\/script>/gi;
1627
+ MODULE_SCRIPT_INLINE_RE = /<script\b([^>]*?)\btype\s*=\s*(["'])module\2([^>]*)>([\s\S]*?)<\/script>/gi;
1628
+ }
1629
+ });
1630
+
201
1631
  // src/index.ts
202
1632
  var index_exports = {};
203
1633
  __export(index_exports, {
204
1634
  COMPLETABLE_COMMANDS: () => COMPLETABLE_COMMANDS,
205
1635
  DEFAULT_MAX_INSTALL_DEPTH: () => DEFAULT_MAX_INSTALL_DEPTH,
206
1636
  EXTRA_COMMANDS: () => EXTRA_COMMANDS,
1637
+ FN_FETCH_INTERCEPTOR_SCRIPT: () => FN_FETCH_INTERCEPTOR_SCRIPT,
207
1638
  RESOLVE_EXTENSIONS: () => RESOLVE_EXTENSIONS,
208
1639
  ResolveError: () => ResolveError,
209
1640
  SHELL_COMMANDS: () => SHELL_COMMANDS,
@@ -212,6 +1643,7 @@ var AdepWebContainer = (() => {
212
1643
  TestAssertionError: () => TestAssertionError,
213
1644
  UnsupportedTsSyntaxError: () => UnsupportedTsSyntaxError,
214
1645
  VirtualFileSystem: () => VirtualFileSystem,
1646
+ ViteDevError: () => ViteDevError,
215
1647
  applyCompletion: () => applyCompletion,
216
1648
  bootstrap: () => bootstrap,
217
1649
  buildCloudFromBundle: () => buildCloudFromBundle,
@@ -227,6 +1659,7 @@ var AdepWebContainer = (() => {
227
1659
  createBrowserStorageDriver: () => createBrowserStorageDriver,
228
1660
  createCommandHistory: () => createCommandHistory,
229
1661
  createFsPersistence: () => createFsPersistence,
1662
+ createFunctionFetchHandler: () => createFunctionFetchHandler,
230
1663
  createIdbSimKv: () => createIdbSimKv,
231
1664
  createIndexedDbFsBackend: () => createIndexedDbFsBackend,
232
1665
  createLocalPort: () => createLocalPort,
@@ -235,10 +1668,12 @@ var AdepWebContainer = (() => {
235
1668
  createMemorySimKv: () => createMemorySimKv,
236
1669
  createNpmClient: () => createNpmClient,
237
1670
  createOfflineFunctionRunner: () => createOfflineFunctionRunner,
1671
+ createRelayFetch: () => createRelayFetch,
238
1672
  createRequire: () => createRequire,
239
1673
  createSandboxModuleGlobals: () => createSandboxModuleGlobals,
240
1674
  createTestRunner: () => createTestRunner,
241
1675
  createTestScope: () => createTestScope,
1676
+ createViteServer: () => createViteServer,
242
1677
  createWorkerRuntime: () => createWorkerRuntime,
243
1678
  deepEqual: () => deepEqual,
244
1679
  displayPath: () => displayPath,
@@ -267,6 +1702,7 @@ var AdepWebContainer = (() => {
267
1702
  resolvePackageEntry: () => resolvePackageEntry,
268
1703
  restoreVfs: () => restoreVfs,
269
1704
  runCollectedTests: () => runCollectedTests,
1705
+ scanEsmSpecifiers: () => scanEsmSpecifiers,
270
1706
  simDbKey: () => simDbKey,
271
1707
  simStorageKey: () => simStorageKey,
272
1708
  snapshotVfs: () => snapshotVfs,
@@ -489,6 +1925,9 @@ var AdepWebContainer = (() => {
489
1925
  }
490
1926
  };
491
1927
 
1928
+ // src/container.ts
1929
+ init_path();
1930
+
492
1931
  // src/shell.ts
493
1932
  init_path();
494
1933
 
@@ -508,9 +1947,12 @@ var AdepWebContainer = (() => {
508
1947
  "cd",
509
1948
  "head",
510
1949
  "tail",
1950
+ "curl",
1951
+ "wget",
511
1952
  "test",
512
1953
  "node",
513
1954
  "js",
1955
+ "vite",
514
1956
  "help"
515
1957
  ];
516
1958
  var EXTRA_COMMANDS = ["npm"];
@@ -815,6 +2257,33 @@ var AdepWebContainer = (() => {
815
2257
  }
816
2258
  break;
817
2259
  }
2260
+ case "curl": {
2261
+ const outcome = await this.runCurl(argv.slice(1));
2262
+ stdout = outcome.stdout;
2263
+ stderr = outcome.stderr;
2264
+ exitCode = outcome.code;
2265
+ break;
2266
+ }
2267
+ case "wget": {
2268
+ const outcome = await this.runWget(argv.slice(1));
2269
+ stdout = outcome.stdout;
2270
+ stderr = outcome.stderr;
2271
+ exitCode = outcome.code;
2272
+ break;
2273
+ }
2274
+ case "vite": {
2275
+ if (this.ctx.vite === void 0)
2276
+ return {
2277
+ code: 1,
2278
+ stdout: "",
2279
+ stderr: "vite: \u672A\u88C5\u914D\u524D\u7AEF\u5F00\u53D1\u670D\u52A1\u5668\uFF08bootstrap \u4F1A\u6CE8\u5165\uFF1B\u88F8 Shell \u9700\u81EA\u884C\u7ED9 ctx.vite\uFF09\n"
2280
+ };
2281
+ const outcome = await this.runVite(argv.slice(1));
2282
+ stdout = outcome.stdout;
2283
+ stderr = outcome.stderr;
2284
+ exitCode = outcome.code;
2285
+ break;
2286
+ }
818
2287
  default:
819
2288
  stderr = `${command}: command not found
820
2289
  `;
@@ -837,6 +2306,168 @@ var AdepWebContainer = (() => {
837
2306
  }
838
2307
  return out;
839
2308
  }
2309
+ /**
2310
+ * `curl [选项] <url>`(常用旗标最小子集):
2311
+ * - 响应体默认写 stdout(可 `|` 管道 / `>` 重定向);`-o <file>` 写 VFS 文件、`-o -` 显式 stdout;
2312
+ * - `-i/--include` 输出响应头 + 体;`-I/--head` 发 HEAD 且只输出响应头;
2313
+ * - `-X/--request`、`-H/--header`(可多次)、`-d/--data`(可多次,`&` 拼接,隐含 POST 与表单头)、
2314
+ * `-A/--user-agent`、`-u/--user`(转 Basic 认证)、`-f/--fail`(HTTP ≥400 退出码 22);
2315
+ * - `-s/-S/-L/-k/-g/-N/--compressed` 等常见旗标接受但无效果(仿真环境本就静默/跟随重定向/不校验证书);
2316
+ * - 裸主机名(`example.com/x`)按 curl 语义补 `http://`;网络故障退出码 7,用法错误 2。
2317
+ */
2318
+ async runCurl(args) {
2319
+ const flags = parseCurlArgs(args);
2320
+ if (flags.url === null) {
2321
+ return { code: 2, stdout: "", stderr: "curl: \u672A\u63D0\u4F9B URL\uFF08\u7528\u6CD5\uFF1Acurl [\u9009\u9879] <url>\uFF09\n" };
2322
+ }
2323
+ const url = normalizeUrl(flags.url);
2324
+ if (url === null)
2325
+ return { code: 3, stdout: "", stderr: `curl: (3) URL \u683C\u5F0F\u9519\u8BEF\uFF1A${flags.url}
2326
+ ` };
2327
+ const method = flags.head ? "HEAD" : flags.method ?? (flags.data.length > 0 ? "POST" : "GET");
2328
+ const headers = { ...flags.headers };
2329
+ const body = flags.data.length > 0 ? flags.data.join("&") : void 0;
2330
+ if (body !== void 0 && !("content-type" in headers)) {
2331
+ headers["content-type"] = "application/x-www-form-urlencoded";
2332
+ }
2333
+ let res;
2334
+ try {
2335
+ res = await this.netRequest(url, {
2336
+ method,
2337
+ headers,
2338
+ ...body === void 0 ? {} : { body }
2339
+ });
2340
+ } catch (error) {
2341
+ if (error instanceof NetCommandError && error.kind === "no-net")
2342
+ return { code: 1, stdout: "", stderr: `curl: ${error.message}
2343
+ ` };
2344
+ return {
2345
+ code: 7,
2346
+ stdout: "",
2347
+ stderr: `curl: (7) \u65E0\u6CD5\u8FDE\u63A5\u4E3B\u673A\uFF1A${error instanceof Error ? error.message : String(error)}
2348
+ `
2349
+ };
2350
+ }
2351
+ const head = flags.head || flags.include ? formatResponseHead(res) : "";
2352
+ let stdout;
2353
+ if (flags.output !== null && flags.output !== "-") {
2354
+ this.ctx.vfs.writeFile(this.resolve(flags.output), res.body);
2355
+ stdout = head;
2356
+ } else {
2357
+ stdout = head + (flags.head ? "" : res.body);
2358
+ }
2359
+ if (flags.fail && !res.ok) {
2360
+ return { code: 22, stdout, stderr: `curl: (22) HTTP \u8BF7\u6C42\u8FD4\u56DE\u9519\u8BEF\u7801 ${res.status}
2361
+ ` };
2362
+ }
2363
+ return { code: 0, stdout, stderr: "" };
2364
+ }
2365
+ /**
2366
+ * `wget [选项] <url>`(常用旗标最小子集):
2367
+ * - 默认按 URL 末级路径名落 VFS 文件(目录形态落 `index.html`),过程信息走 stderr;
2368
+ * - `-O <file>` 指定文件名、`-O -` 输出到 stdout;`-q/--quiet` 静默;`-S/--server-response` 打印响应头;
2369
+ * - HTTP ≥400 / 网络失败退出码 1 且不落文件(与 GNU wget 默认一致)。
2370
+ */
2371
+ async runWget(args) {
2372
+ const flags = parseWgetArgs(args);
2373
+ if (flags.url === null) {
2374
+ return { code: 1, stdout: "", stderr: "wget: \u672A\u63D0\u4F9B URL\uFF08\u7528\u6CD5\uFF1Awget [\u9009\u9879] <url>\uFF09\n" };
2375
+ }
2376
+ const url = normalizeUrl(flags.url);
2377
+ if (url === null) return { code: 1, stdout: "", stderr: `wget: URL \u683C\u5F0F\u9519\u8BEF\uFF1A${flags.url}
2378
+ ` };
2379
+ let parsed;
2380
+ try {
2381
+ parsed = new URL(url);
2382
+ } catch {
2383
+ return { code: 1, stdout: "", stderr: `wget: URL \u683C\u5F0F\u9519\u8BEF\uFF1A${url}
2384
+ ` };
2385
+ }
2386
+ let res;
2387
+ try {
2388
+ res = await this.netRequest(url, { method: "GET" });
2389
+ } catch (error) {
2390
+ if (error instanceof NetCommandError && error.kind === "no-net")
2391
+ return { code: 1, stdout: "", stderr: `wget: ${error.message}
2392
+ ` };
2393
+ const reason = error instanceof Error ? error.message : String(error);
2394
+ return { code: 1, stdout: "", stderr: `wget: \u65E0\u6CD5\u4E0B\u8F7D ${url}\uFF1A${reason}
2395
+ ` };
2396
+ }
2397
+ const toStdout = flags.output === "-";
2398
+ const fileName = flags.output !== null && flags.output !== "-" ? flags.output : wgetFileName(parsed);
2399
+ let stderr = "";
2400
+ if (!flags.quiet) {
2401
+ const type = res.headers["content-type"] ?? "application/octet-stream";
2402
+ const length = res.headers["content-length"] ?? String(new TextEncoder().encode(res.body).byteLength);
2403
+ stderr += `\u6B63\u5728\u8FDE\u63A5 ${parsed.hostname}...
2404
+ `;
2405
+ stderr += `HTTP \u8BF7\u6C42\u5DF2\u53D1\u9001\uFF0C\u6B63\u5728\u7B49\u5F85\u54CD\u5E94... ${res.status}${res.statusText ? ` ${res.statusText}` : ""}
2406
+ `;
2407
+ if (flags.serverResponse) stderr += formatResponseHead(res);
2408
+ stderr += `\u957F\u5EA6\uFF1A${length} [${type}]
2409
+ `;
2410
+ if (!toStdout) stderr += `\u6B63\u5728\u4FDD\u5B58\u5230: \u201C${fileName}\u201D
2411
+ `;
2412
+ }
2413
+ if (!res.ok) {
2414
+ return { code: 1, stdout: "", stderr: `${stderr}wget: \u9519\u8BEF\uFF1A\u670D\u52A1\u5668\u8FD4\u56DE HTTP ${res.status}
2415
+ ` };
2416
+ }
2417
+ if (toStdout) return { code: 0, stdout: res.body, stderr };
2418
+ this.ctx.vfs.writeFile(this.resolve(fileName), res.body);
2419
+ if (!flags.quiet) stderr += `${fileName} \u5DF2\u4FDD\u5B58 [${res.body.length} \u5B57\u8282]
2420
+ `;
2421
+ return { code: 0, stdout: "", stderr };
2422
+ }
2423
+ /**
2424
+ * `vite [子命令|目录]`:
2425
+ * - `vite` / `vite dev [dir]`:启动浏览器内 Vite 兼容 dev server(`dir` 为 root,缺省 `/`;
2426
+ * `--port` 等旗标接受但无效果——端口是虚拟语义值);
2427
+ * - `vite stop`:停止并释放;
2428
+ * - `vite build`:首版明确不支持(dev 语义优先),如实报错。
2429
+ * dev server 常驻在容器层(`serverready` 事件 + HMR),命令本身立即返回——与真实
2430
+ * vite 的前台常驻进程形态不同,属仿真终端的取舍(见 vite-dev.ts 文件头)。
2431
+ */
2432
+ async runVite(args) {
2433
+ const positional = args.filter((a) => !a.startsWith("-"));
2434
+ const sub = positional[0] ?? "";
2435
+ if (sub === "stop") {
2436
+ const outcome2 = await this.ctx.vite.stop();
2437
+ return outcome2.code === 0 ? { ...outcome2, stderr: "" } : { code: outcome2.code, stdout: "", stderr: outcome2.stdout };
2438
+ }
2439
+ if (sub === "build")
2440
+ return {
2441
+ code: 1,
2442
+ stdout: "",
2443
+ stderr: "vite build: \u6682\u4E0D\u652F\u6301\uFF08\u6D4F\u89C8\u5668\u5185 vite \u9996\u7248\u53EA\u63D0\u4F9B dev server\uFF1B\u53D1\u5E03\u8D70\u524D\u7AEF\u53D1\u5E03\u7BA1\u7EBF\uFF09\n"
2444
+ };
2445
+ const rootArgs = sub === "" || sub === "dev" || sub === "serve" ? positional.slice(1) : [sub];
2446
+ const outcome = await this.ctx.vite.start(rootArgs);
2447
+ return outcome.code === 0 ? { ...outcome, stderr: "" } : { code: outcome.code, stdout: "", stderr: outcome.stdout };
2448
+ }
2449
+ /** 经 net 端口发请求;端口缺失 / 网络失败归一为 NetCommandError(curl/wget 各自映射退出码与文案)。 */
2450
+ async netRequest(url, init) {
2451
+ if (this.ctx.net === void 0) {
2452
+ throw new NetCommandError(
2453
+ "no-net",
2454
+ "\u672A\u6CE8\u5165\u7F51\u7EDC\u7AEF\u53E3\uFF08\u6D4F\u89C8\u5668\u7AEF\u7ECF\u5E73\u53F0 HTTP \u4E2D\u7EE7\u8BBF\u95EE\uFF1Bbootstrap \u9700\u63D0\u4F9B httpRelayBaseUrl\uFF09"
2455
+ );
2456
+ }
2457
+ try {
2458
+ const res = await this.ctx.net(url, init);
2459
+ return {
2460
+ ok: res.ok,
2461
+ status: res.status,
2462
+ statusText: res.statusText,
2463
+ headers: res.headers,
2464
+ body: await res.text()
2465
+ };
2466
+ } catch (error) {
2467
+ if (error instanceof NetCommandError) throw error;
2468
+ throw new NetCommandError("network", error instanceof Error ? error.message : String(error));
2469
+ }
2470
+ }
840
2471
  /**
841
2472
  * 对当前输入行求 Tab 补全候选(FE-022):命令位补内建命令名,参数位补 VFS 路径。
842
2473
  * 无候选不抛错(Tab 不该让终端报错),由调用方决定「不响应」还是「列出可能项」。
@@ -850,6 +2481,200 @@ var AdepWebContainer = (() => {
850
2481
  return join(this.ctx.getCwd(), target);
851
2482
  }
852
2483
  };
2484
+ var NetCommandError = class extends Error {
2485
+ constructor(kind, message) {
2486
+ super(message);
2487
+ this.kind = kind;
2488
+ this.name = "NetCommandError";
2489
+ }
2490
+ };
2491
+ var CURL_BOOLEAN_NOOP = /* @__PURE__ */ new Set([
2492
+ "-s",
2493
+ "--silent",
2494
+ "-S",
2495
+ "--show-error",
2496
+ "-L",
2497
+ "--location",
2498
+ "-k",
2499
+ "--insecure",
2500
+ "-g",
2501
+ "--globoff",
2502
+ "-N",
2503
+ "--no-buffer",
2504
+ "--compressed",
2505
+ "-#",
2506
+ "--progress-bar",
2507
+ "-v",
2508
+ "--verbose",
2509
+ "-G",
2510
+ "--get"
2511
+ ]);
2512
+ var WGET_BOOLEAN_NOOP = /* @__PURE__ */ new Set([
2513
+ "--no-check-certificate",
2514
+ "-nc",
2515
+ "--no-clobber",
2516
+ "-c",
2517
+ "--continue",
2518
+ "-nv",
2519
+ "--no-verbose",
2520
+ "--content-on-error"
2521
+ ]);
2522
+ function matchValueFlag(arg, name, longNames, consume) {
2523
+ if (arg === name || longNames.includes(arg)) return { matched: true, value: consume() };
2524
+ for (const long of longNames) {
2525
+ if (arg.startsWith(`${long}=`)) return { matched: true, value: arg.slice(long.length + 1) };
2526
+ }
2527
+ return { matched: false, value: null };
2528
+ }
2529
+ function expandShortArgs(args, valueFlags) {
2530
+ const out = [];
2531
+ for (const arg of args) {
2532
+ const cluster = /^-([A-Za-z]+)$/.exec(arg);
2533
+ if (cluster === null) {
2534
+ out.push(arg);
2535
+ continue;
2536
+ }
2537
+ const chars = cluster[1];
2538
+ for (let j = 0; j < chars.length; j++) {
2539
+ const c = chars[j];
2540
+ out.push(`-${c}`);
2541
+ if (valueFlags.has(c)) {
2542
+ const rest = chars.slice(j + 1);
2543
+ if (rest !== "") out.push(rest);
2544
+ break;
2545
+ }
2546
+ }
2547
+ }
2548
+ return out;
2549
+ }
2550
+ function parseCurlArgs(rawArgs) {
2551
+ const args = expandShortArgs(rawArgs, /* @__PURE__ */ new Set(["X", "H", "d", "o", "A", "u", "m"]));
2552
+ const flags = {
2553
+ url: null,
2554
+ method: null,
2555
+ headers: {},
2556
+ data: [],
2557
+ include: false,
2558
+ head: false,
2559
+ output: null,
2560
+ fail: false
2561
+ };
2562
+ for (let i = 0; i < args.length; i++) {
2563
+ const arg = args[i];
2564
+ const consume = () => {
2565
+ const v = args[i + 1];
2566
+ if (v !== void 0) i++;
2567
+ return v ?? "";
2568
+ };
2569
+ let m = matchValueFlag(arg, "-X", ["--request"], consume);
2570
+ if (m.matched) {
2571
+ flags.method = (m.value ?? "").toUpperCase();
2572
+ continue;
2573
+ }
2574
+ m = matchValueFlag(arg, "-H", ["--header"], consume);
2575
+ if (m.matched) {
2576
+ const raw = m.value ?? "";
2577
+ const colon = raw.indexOf(":");
2578
+ if (colon > 0)
2579
+ flags.headers[raw.slice(0, colon).trim().toLowerCase()] = raw.slice(colon + 1).trim();
2580
+ continue;
2581
+ }
2582
+ m = matchValueFlag(arg, "-A", ["--user-agent"], consume);
2583
+ if (m.matched) {
2584
+ flags.headers["user-agent"] = m.value ?? "";
2585
+ continue;
2586
+ }
2587
+ m = matchValueFlag(arg, "-u", ["--user"], consume);
2588
+ if (m.matched) {
2589
+ flags.headers["authorization"] = `Basic ${btoa(m.value ?? "")}`;
2590
+ continue;
2591
+ }
2592
+ m = matchValueFlag(
2593
+ arg,
2594
+ "-d",
2595
+ ["--data", "--data-raw", "--data-binary", "--data-urlencode"],
2596
+ consume
2597
+ );
2598
+ if (m.matched) {
2599
+ flags.data.push(m.value ?? "");
2600
+ continue;
2601
+ }
2602
+ m = matchValueFlag(arg, "-o", ["--output"], consume);
2603
+ if (m.matched) {
2604
+ flags.output = m.value;
2605
+ continue;
2606
+ }
2607
+ m = matchValueFlag(arg, "-m", ["--max-time", "--connect-timeout"], consume);
2608
+ if (m.matched) continue;
2609
+ if (arg === "-i" || arg === "--include") {
2610
+ flags.include = true;
2611
+ continue;
2612
+ }
2613
+ if (arg === "-I" || arg === "--head") {
2614
+ flags.head = true;
2615
+ continue;
2616
+ }
2617
+ if (arg === "-f" || arg === "--fail") {
2618
+ flags.fail = true;
2619
+ continue;
2620
+ }
2621
+ if (CURL_BOOLEAN_NOOP.has(arg) || arg.startsWith("-")) continue;
2622
+ if (flags.url === null) flags.url = arg;
2623
+ }
2624
+ return flags;
2625
+ }
2626
+ function parseWgetArgs(rawArgs) {
2627
+ const args = expandShortArgs(rawArgs, /* @__PURE__ */ new Set(["O"]));
2628
+ const flags = { url: null, output: null, quiet: false, serverResponse: false };
2629
+ for (let i = 0; i < args.length; i++) {
2630
+ const arg = args[i];
2631
+ const consume = () => {
2632
+ const v = args[i + 1];
2633
+ if (v !== void 0) i++;
2634
+ return v ?? "";
2635
+ };
2636
+ const m = matchValueFlag(arg, "-O", ["--output-document"], consume);
2637
+ if (m.matched) {
2638
+ flags.output = m.value;
2639
+ continue;
2640
+ }
2641
+ if (arg === "-q" || arg === "--quiet") {
2642
+ flags.quiet = true;
2643
+ continue;
2644
+ }
2645
+ if (arg === "-S" || arg === "--server-response") {
2646
+ flags.serverResponse = true;
2647
+ continue;
2648
+ }
2649
+ if (WGET_BOOLEAN_NOOP.has(arg) || arg.startsWith("-")) continue;
2650
+ if (flags.url === null) flags.url = arg;
2651
+ }
2652
+ return flags;
2653
+ }
2654
+ function normalizeUrl(raw) {
2655
+ if (raw.startsWith("/")) return null;
2656
+ if (/^[a-z][a-z0-9+.-]*:\/\//i.test(raw)) return raw;
2657
+ return `http://${raw}`;
2658
+ }
2659
+ function formatResponseHead(res) {
2660
+ const reason = res.statusText !== "" ? ` ${res.statusText}` : "";
2661
+ let head = `HTTP/1.1 ${res.status}${reason}\r
2662
+ `;
2663
+ for (const [key, value] of Object.entries(res.headers)) head += `${key}: ${value}\r
2664
+ `;
2665
+ return `${head}\r
2666
+ `;
2667
+ }
2668
+ function wgetFileName(url) {
2669
+ const segments = url.pathname.split("/").filter((s) => s !== "");
2670
+ const last = segments.length === 0 ? void 0 : segments[segments.length - 1];
2671
+ if (last === void 0) return "index.html";
2672
+ try {
2673
+ return decodeURIComponent(last);
2674
+ } catch {
2675
+ return last;
2676
+ }
2677
+ }
853
2678
 
854
2679
  // src/tar.ts
855
2680
  var BLOCK = 512;
@@ -874,237 +2699,72 @@ var AdepWebContainer = (() => {
874
2699
  }
875
2700
  function assertSafePath(path) {
876
2701
  if (path === "" || path.startsWith("/") || path.startsWith("\\"))
877
- throw new Error(`tar \u6761\u76EE\u8DEF\u5F84\u975E\u6CD5\uFF08\u7EDD\u5BF9\u8DEF\u5F84\u6216\u4E3A\u7A7A\uFF09\uFF1A"${path}"`);
878
- for (const segment of path.split("/")) {
879
- if (segment === "..") throw new Error(`tar \u6761\u76EE\u8DEF\u5F84\u542B ".." \u7A7F\u8D8A\uFF0C\u5DF2\u62D2\u7EDD\uFF1A"${path}"`);
880
- }
881
- }
882
- async function gunzip(bytes) {
883
- if (bytes.length < 2 || bytes[0] !== GZIP_MAGIC_0 || bytes[1] !== GZIP_MAGIC_1) {
884
- throw new Error("tarball \u4E0D\u662F gzip \u6570\u636E\uFF08\u7F3A\u5C11 1f 8b \u9B54\u6570\uFF09\uFF0C\u65E0\u6CD5\u89E3\u5305");
885
- }
886
- const stream = new Blob([bytes]).stream().pipeThrough(new DecompressionStream("gzip"));
887
- const buffer = await new Response(stream).arrayBuffer();
888
- return new Uint8Array(buffer);
889
- }
890
- function unpackTar(bytes) {
891
- const entries = [];
892
- let offset = 0;
893
- let longName = null;
894
- while (offset + BLOCK <= bytes.length) {
895
- const header = bytes.subarray(offset, offset + BLOCK);
896
- if (header.every((byte) => byte === 0)) break;
897
- const typeflag = String.fromCharCode(header[156]);
898
- const size = parseOctalSize(header, 124, 12);
899
- let name = readString(bytes, offset, 100);
900
- const prefix = readString(bytes, offset + 345, 155);
901
- if (prefix !== "") name = `${prefix}/${name}`;
902
- const dataStart = offset + BLOCK;
903
- const data = bytes.subarray(dataStart, dataStart + size);
904
- offset = dataStart + Math.ceil(size / BLOCK) * BLOCK;
905
- if (typeflag === "L") {
906
- longName = new TextDecoder("utf-8").decode(data).replace(/\0+$/g, "").trim();
907
- continue;
908
- }
909
- if (typeflag === "x" || typeflag === "g") continue;
910
- if (typeflag === "5") continue;
911
- if (typeflag !== "0" && typeflag !== "\0") {
912
- throw new Error(`tar \u6761\u76EE\u7C7B\u578B "${typeflag}" \u4E0D\u652F\u6301\uFF08\u53EA\u63A5\u53D7\u666E\u901A\u6587\u4EF6\u4E0E\u76EE\u5F55\uFF09\uFF1A"${name}"`);
913
- }
914
- if (longName !== null) {
915
- name = longName;
916
- longName = null;
917
- }
918
- assertSafePath(name);
919
- entries.push({ path: name, contents: new Uint8Array(data) });
920
- }
921
- return entries;
922
- }
923
- async function unpackNpmTarball(bytes) {
924
- const tar = unpackTar(await gunzip(bytes));
925
- if (tar.length === 0) throw new Error("tarball \u89E3\u5305\u540E\u4E3A\u7A7A\uFF0C\u6CA1\u6709\u4EFB\u4F55\u6587\u4EF6\u6761\u76EE");
926
- const out = [];
927
- for (const entry of tar) {
928
- if (!entry.path.startsWith("package/")) {
929
- throw new Error(
930
- `tarball \u9876\u5C42\u76EE\u5F55\u5F02\u5E38\uFF08npm registry \u5F52\u6863\u5E94\u5168\u90E8\u4F4D\u4E8E "package/" \u4E0B\uFF09\uFF1A"${entry.path}"`
931
- );
932
- }
933
- out.push({ path: entry.path.slice("package/".length), contents: entry.contents });
934
- }
935
- if (!out.some((entry) => entry.path === "package.json")) {
936
- throw new Error("tarball \u7F3A\u5C11 package.json\uFF0C\u62D2\u7EDD\u89E3\u5305");
937
- }
938
- return out;
939
- }
940
-
941
- // src/node-resolve.ts
942
- init_path();
943
- var RESOLVE_EXTENSIONS = [".js", ".mjs", ".cjs", ".json"];
944
- var ResolveError = class extends Error {
945
- constructor(message) {
946
- super(message);
947
- this.name = "ResolveError";
948
- }
949
- };
950
- function parsePackageMeta(content, context) {
951
- let parsed;
952
- try {
953
- parsed = JSON.parse(content);
954
- } catch {
955
- throw new ResolveError(`${context} \u4E0D\u662F\u5408\u6CD5 JSON`);
956
- }
957
- if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
958
- throw new ResolveError(`${context} \u9876\u5C42\u5FC5\u987B\u662F\u5BF9\u8C61`);
959
- }
960
- return parsed;
961
- }
962
- function withinPackage(pkgDirAbs, rel, context) {
963
- if (typeof rel !== "string" || rel === "") {
964
- throw new ResolveError(`${context}\uFF1A\u5165\u53E3\u8DEF\u5F84\u5FC5\u987B\u662F\u5B57\u7B26\u4E32`);
965
- }
966
- if (!rel.startsWith("./") && !rel.startsWith("../") && rel.startsWith("/")) {
967
- throw new ResolveError(`${context}\uFF1A\u5165\u53E3\u8DEF\u5F84 "${rel}" \u5FC5\u987B\u662F\u5305\u5185\u76F8\u5BF9\u8DEF\u5F84\uFF08\u4EE5 ./ \u5F00\u5934\uFF09`);
968
- }
969
- const abs = join(pkgDirAbs, rel.startsWith(".") ? rel : `./${rel}`);
970
- if (!abs.startsWith(`${pkgDirAbs}/`)) {
971
- throw new ResolveError(`${context}\uFF1A\u5165\u53E3\u8DEF\u5F84 "${rel}" \u8D8A\u51FA\u5305\u76EE\u5F55\uFF0C\u5DF2\u62D2\u7EDD`);
972
- }
973
- return abs;
974
- }
975
- function resolvePackageEntry(meta, pkgDirAbs, condition) {
976
- const context = `\u5305 ${meta.name ?? meta.version ?? pkgDirAbs} \u7684 exports/main \u58F0\u660E`;
977
- const exp = meta.exports;
978
- if (exp !== void 0 && exp !== null) {
979
- if (typeof exp === "string") return withinPackage(pkgDirAbs, exp, context);
980
- if (typeof exp !== "object" || Array.isArray(exp)) {
981
- throw new ResolveError(`${context} \u5F62\u6001\u4E0D\u652F\u6301\uFF08exports \u53EA\u80FD\u662F\u5B57\u7B26\u4E32\u6216\u5BF9\u8C61\uFF09`);
982
- }
983
- const dot = exp["."];
984
- if (dot === void 0) {
985
- throw new ResolveError(
986
- `${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`
987
- );
988
- }
989
- if (typeof dot === "string") return withinPackage(pkgDirAbs, dot, context);
990
- if (dot === null)
991
- throw new ResolveError(`${context}\uFF1Aexports["."] \u4E3A null\uFF08\u8BE5\u6761\u4EF6\u88AB\u663E\u5F0F\u6392\u9664\uFF09\uFF0C\u65E0\u6CD5\u89E3\u6790\u5165\u53E3`);
992
- if (typeof dot !== "object" || Array.isArray(dot)) {
993
- throw new ResolveError(`${context}\uFF1Aexports["."] \u5F62\u6001\u4E0D\u652F\u6301\uFF08\u4EC5\u63A5\u53D7\u5B57\u7B26\u4E32\u6216\u6761\u4EF6\u5BF9\u8C61\uFF09`);
994
- }
995
- const conditions = dot;
996
- const order = condition === "import" ? ["import", "node", "default"] : ["require", "node", "default"];
997
- for (const key of order) {
998
- const value = conditions[key];
999
- if (typeof value === "string") return withinPackage(pkgDirAbs, value, context);
1000
- if (value !== void 0 && (typeof value !== "object" || value === null)) {
1001
- throw new ResolveError(
1002
- `${context}\uFF1Aexports["."]["${key}"] \u5F62\u6001\u4E0D\u652F\u6301\uFF08\u4EC5\u63A5\u53D7\u5B57\u7B26\u4E32\u6216 null\uFF09`
1003
- );
1004
- }
1005
- }
1006
- throw new ResolveError(
1007
- `${context}\uFF1Aexports["."] \u6761\u4EF6\u5BF9\u8C61\u91CC\u6CA1\u6709 ${condition}/node/default \u5B57\u7B26\u4E32\u5165\u53E3\uFF08\u5B50\u8DEF\u5F84/\u5D4C\u5957\u6761\u4EF6\u4E0D\u652F\u6301\uFF09`
1008
- );
1009
- }
1010
- if (meta.main !== void 0) {
1011
- if (typeof meta.main !== "string") {
1012
- throw new ResolveError(`${context}\uFF1Amain \u5FC5\u987B\u662F\u5B57\u7B26\u4E32`);
1013
- }
1014
- return withinPackage(pkgDirAbs, meta.main, context);
1015
- }
1016
- return join(pkgDirAbs, "index.js");
1017
- }
1018
- function splitPackageSpecifier(spec) {
1019
- if (spec.startsWith("@")) {
1020
- const first = spec.indexOf("/");
1021
- if (first === -1) return { name: spec, subpath: "" };
1022
- const second = spec.indexOf("/", first + 1);
1023
- if (second === -1) return { name: spec, subpath: "" };
1024
- return { name: spec.slice(0, second), subpath: spec.slice(second + 1) };
1025
- }
1026
- const slash = spec.indexOf("/");
1027
- if (slash === -1) return { name: spec, subpath: "" };
1028
- return { name: spec.slice(0, slash), subpath: spec.slice(slash + 1) };
1029
- }
1030
- function asFile(fs, baseAbs) {
1031
- if (fs.exists(baseAbs) && !fsIsDirectory(fs, baseAbs)) return baseAbs;
1032
- for (const ext of RESOLVE_EXTENSIONS) {
1033
- const candidate = `${baseAbs}${ext}`;
1034
- if (fs.exists(candidate) && !fsIsDirectory(fs, candidate)) return candidate;
2702
+ throw new Error(`tar \u6761\u76EE\u8DEF\u5F84\u975E\u6CD5\uFF08\u7EDD\u5BF9\u8DEF\u5F84\u6216\u4E3A\u7A7A\uFF09\uFF1A"${path}"`);
2703
+ for (const segment of path.split("/")) {
2704
+ if (segment === "..") throw new Error(`tar \u6761\u76EE\u8DEF\u5F84\u542B ".." \u7A7F\u8D8A\uFF0C\u5DF2\u62D2\u7EDD\uFF1A"${path}"`);
1035
2705
  }
1036
- return null;
1037
2706
  }
1038
- function asDirectory(fs, dirAbs) {
1039
- if (!fs.exists(dirAbs) || !fsIsDirectory(fs, dirAbs)) return null;
1040
- const manifest = `${dirAbs}/package.json`;
1041
- if (fs.exists(manifest)) {
1042
- const meta = parsePackageMeta(fs.readFile(manifest), manifest);
1043
- const entry = resolvePackageEntry(meta, dirAbs, "require");
1044
- const hit = asFile(fs, entry);
1045
- if (hit !== null) return hit;
2707
+ async function gunzip(bytes) {
2708
+ if (bytes.length < 2 || bytes[0] !== GZIP_MAGIC_0 || bytes[1] !== GZIP_MAGIC_1) {
2709
+ throw new Error("tarball \u4E0D\u662F gzip \u6570\u636E\uFF08\u7F3A\u5C11 1f 8b \u9B54\u6570\uFF09\uFF0C\u65E0\u6CD5\u89E3\u5305");
1046
2710
  }
1047
- return asFile(fs, join(dirAbs, "index"));
1048
- }
1049
- function fsIsDirectory(fs, path) {
1050
- const probe = fs;
1051
- return probe.isDirectory?.(path) ?? false;
2711
+ const stream = new Blob([bytes]).stream().pipeThrough(new DecompressionStream("gzip"));
2712
+ const buffer = await new Response(stream).arrayBuffer();
2713
+ return new Uint8Array(buffer);
1052
2714
  }
1053
- function resolveImport(fs, specifier, fromFileAbs, condition = "require") {
1054
- if (specifier === "") throw new ResolveError("\u7A7A\u8BF4\u660E\u7B26\uFF1A\u65E0\u6CD5\u89E3\u6790\u6A21\u5757");
1055
- if (specifier.startsWith("./") || specifier.startsWith("../")) {
1056
- const base = join(dirname(fromFileAbs), specifier);
1057
- const hit = asFile(fs, base) ?? asDirectory(fs, base);
1058
- if (hit === null) {
1059
- throw new ResolveError(
1060
- `\u627E\u4E0D\u5230\u76F8\u5BF9\u6A21\u5757 "${specifier}"\uFF08\u81EA ${dirname(fromFileAbs)}\uFF0C\u8BD5\u8FC7\u6269\u5C55\u540D ${RESOLVE_EXTENSIONS.join("/")} \u4E0E\u76EE\u5F55\u7D22\u5F15\uFF09`
1061
- );
2715
+ function unpackTar(bytes) {
2716
+ const entries = [];
2717
+ let offset = 0;
2718
+ let longName = null;
2719
+ while (offset + BLOCK <= bytes.length) {
2720
+ const header = bytes.subarray(offset, offset + BLOCK);
2721
+ if (header.every((byte) => byte === 0)) break;
2722
+ const typeflag = String.fromCharCode(header[156]);
2723
+ const size = parseOctalSize(header, 124, 12);
2724
+ let name = readString(bytes, offset, 100);
2725
+ const prefix = readString(bytes, offset + 345, 155);
2726
+ if (prefix !== "") name = `${prefix}/${name}`;
2727
+ const dataStart = offset + BLOCK;
2728
+ const data = bytes.subarray(dataStart, dataStart + size);
2729
+ offset = dataStart + Math.ceil(size / BLOCK) * BLOCK;
2730
+ if (typeflag === "L") {
2731
+ longName = new TextDecoder("utf-8").decode(data).replace(/\0+$/g, "").trim();
2732
+ continue;
1062
2733
  }
1063
- return hit;
1064
- }
1065
- if (specifier.startsWith("/")) {
1066
- const hit = asFile(fs, specifier) ?? asDirectory(fs, specifier);
1067
- if (hit === null) throw new ResolveError(`\u627E\u4E0D\u5230\u7EDD\u5BF9\u8DEF\u5F84\u6A21\u5757 "${specifier}"`);
1068
- return hit;
1069
- }
1070
- const { name, subpath } = splitPackageSpecifier(specifier);
1071
- if (name.startsWith("node:")) {
1072
- throw new ResolveError(`\u6D4F\u89C8\u5668\u6C99\u7BB1\u4E0D\u63D0\u4F9B Node \u5185\u5EFA\u6A21\u5757 "${specifier}"`);
2734
+ if (typeflag === "x" || typeflag === "g") continue;
2735
+ if (typeflag === "5") continue;
2736
+ if (typeflag !== "0" && typeflag !== "\0") {
2737
+ throw new Error(`tar \u6761\u76EE\u7C7B\u578B "${typeflag}" \u4E0D\u652F\u6301\uFF08\u53EA\u63A5\u53D7\u666E\u901A\u6587\u4EF6\u4E0E\u76EE\u5F55\uFF09\uFF1A"${name}"`);
2738
+ }
2739
+ if (longName !== null) {
2740
+ name = longName;
2741
+ longName = null;
2742
+ }
2743
+ assertSafePath(name);
2744
+ entries.push({ path: name, contents: new Uint8Array(data) });
1073
2745
  }
1074
- let dir = dirname(fromFileAbs);
1075
- for (; ; ) {
1076
- const pkgDir = join(dir, "node_modules", name);
1077
- if (fs.exists(pkgDir) && fsIsDirectory(fs, pkgDir)) {
1078
- if (subpath === "") {
1079
- const manifest = `${pkgDir}/package.json`;
1080
- if (fs.exists(manifest)) {
1081
- const meta = parsePackageMeta(fs.readFile(manifest), manifest);
1082
- const entry = resolvePackageEntry(meta, pkgDir, condition);
1083
- const hit = asFile(fs, entry) ?? asDirectory(fs, entry);
1084
- if (hit !== null) return hit;
1085
- } else {
1086
- const hit = asFile(fs, join(pkgDir, "index")) ?? asDirectory(fs, pkgDir);
1087
- if (hit !== null) return hit;
1088
- }
1089
- } else {
1090
- const base = join(pkgDir, subpath);
1091
- const hit = asFile(fs, base) ?? asDirectory(fs, base);
1092
- if (hit !== null) return hit;
1093
- }
1094
- throw new ResolveError(
1095
- `\u5728 ${pkgDir} \u627E\u5230\u4E86\u5305 "${name}"\uFF0C\u4F46\u89E3\u6790\u8BF4\u660E\u7B26 "${specifier}" \u5931\u8D25\uFF08\u5B50\u8DEF\u5F84\u4E0D\u5B58\u5728\uFF0C\u6216 exports/main \u6307\u5411\u7684\u5165\u53E3\u6587\u4EF6\u7F3A\u5931\uFF09`
2746
+ return entries;
2747
+ }
2748
+ async function unpackNpmTarball(bytes) {
2749
+ const tar = unpackTar(await gunzip(bytes));
2750
+ if (tar.length === 0) throw new Error("tarball \u89E3\u5305\u540E\u4E3A\u7A7A\uFF0C\u6CA1\u6709\u4EFB\u4F55\u6587\u4EF6\u6761\u76EE");
2751
+ const out = [];
2752
+ for (const entry of tar) {
2753
+ if (!entry.path.startsWith("package/")) {
2754
+ throw new Error(
2755
+ `tarball \u9876\u5C42\u76EE\u5F55\u5F02\u5E38\uFF08npm registry \u5F52\u6863\u5E94\u5168\u90E8\u4F4D\u4E8E "package/" \u4E0B\uFF09\uFF1A"${entry.path}"`
1096
2756
  );
1097
2757
  }
1098
- const parent = dirname(dir);
1099
- if (parent === dir) break;
1100
- dir = parent;
2758
+ out.push({ path: entry.path.slice("package/".length), contents: entry.contents });
1101
2759
  }
1102
- throw new ResolveError(
1103
- `\u627E\u4E0D\u5230\u5305 "${specifier}"\uFF1A${dirname(fromFileAbs)} \u53CA\u5176\u5404\u7EA7\u7236\u76EE\u5F55\u4E0B\u90FD\u6CA1\u6709 node_modules/${name}\uFF08\u5148\u5728\u7EC8\u7AEF npm install ${name}\uFF09`
1104
- );
2760
+ if (!out.some((entry) => entry.path === "package.json")) {
2761
+ throw new Error("tarball \u7F3A\u5C11 package.json\uFF0C\u62D2\u7EDD\u89E3\u5305");
2762
+ }
2763
+ return out;
1105
2764
  }
1106
2765
 
1107
2766
  // src/npm-client.ts
2767
+ init_node_resolve();
1108
2768
  var DEFAULT_MAX_INSTALL_DEPTH = 5;
1109
2769
  var defaultFetch = (url, init) => globalThis.fetch(url, init).then((res) => res);
1110
2770
  function parseSpec(spec) {
@@ -1255,7 +2915,58 @@ var AdepWebContainer = (() => {
1255
2915
  };
1256
2916
  }
1257
2917
 
2918
+ // src/relay-fetch.ts
2919
+ var defaultFetch2 = (url, init) => globalThis.fetch(url, init).then((res) => res);
2920
+ function createRelayFetch(options) {
2921
+ const fetchImpl = options.fetchImpl ?? defaultFetch2;
2922
+ const base = options.baseUrl.replace(/\/+$/, "");
2923
+ return async (url, init) => {
2924
+ let res;
2925
+ try {
2926
+ res = await fetchImpl(`${base}/fetch`, {
2927
+ method: "POST",
2928
+ headers: { "content-type": "application/json" },
2929
+ body: JSON.stringify({
2930
+ url,
2931
+ method: init?.method ?? "GET",
2932
+ ...init?.headers === void 0 ? {} : { headers: init.headers },
2933
+ ...init?.body === void 0 ? {} : { body: init.body }
2934
+ })
2935
+ });
2936
+ } catch (error) {
2937
+ const reason = error instanceof Error ? error.message : String(error);
2938
+ throw new Error(`HTTP \u4E2D\u7EE7\u4E0D\u53EF\u8FBE\uFF08${base}/fetch\uFF0C${reason}\uFF09`, { cause: error });
2939
+ }
2940
+ if (!res.ok) {
2941
+ let message = `HTTP \u4E2D\u7EE7\u8FD4\u56DE ${res.status}`;
2942
+ try {
2943
+ const data = await res.json();
2944
+ if (data.error?.message) message = data.error.message;
2945
+ } catch {
2946
+ }
2947
+ throw new Error(message);
2948
+ }
2949
+ const env = await res.json();
2950
+ return {
2951
+ ok: env.ok,
2952
+ status: env.status,
2953
+ statusText: env.statusText,
2954
+ headers: env.headers ?? {},
2955
+ text: async () => env.body,
2956
+ json: async () => JSON.parse(env.body),
2957
+ arrayBuffer: async () => {
2958
+ const bytes = new TextEncoder().encode(env.body);
2959
+ return bytes.buffer.slice(
2960
+ bytes.byteOffset,
2961
+ bytes.byteOffset + bytes.byteLength
2962
+ );
2963
+ }
2964
+ };
2965
+ };
2966
+ }
2967
+
1258
2968
  // src/module-loader.ts
2969
+ init_node_resolve();
1259
2970
  function interopDefault(value) {
1260
2971
  if (value !== null && typeof value === "object" && "__esModule" in value) {
1261
2972
  return value.default;
@@ -1461,614 +3172,8 @@ self.onmessage = async (event) => {
1461
3172
  };
1462
3173
  }
1463
3174
 
1464
- // src/strip-types.ts
1465
- var UnsupportedTsSyntaxError = class extends Error {
1466
- constructor(construct, line) {
1467
- super(`\u4E0D\u53D7\u652F\u6301\u7684 TypeScript \u8BED\u6CD5\uFF1A${construct}\uFF08\u7B2C ${line} \u884C\uFF09\u2014\u2014\u6D4F\u89C8\u5668\u6D4B\u8BD5\u6C99\u7BB1\u53EA\u64E6\u9664\u7C7B\u578B\u6807\u6CE8`);
1468
- this.construct = construct;
1469
- this.line = line;
1470
- this.name = "UnsupportedTsSyntaxError";
1471
- }
1472
- };
1473
- var IDENT_START = /[A-Za-z_$]/;
1474
- var IDENT_PART = /[A-Za-z0-9_$]/;
1475
- var DECL_KEYWORDS = /* @__PURE__ */ new Set(["const", "let", "var"]);
1476
- var TS_MODIFIERS = /* @__PURE__ */ new Set([
1477
- "private",
1478
- "protected",
1479
- "public",
1480
- "readonly",
1481
- "abstract",
1482
- "override",
1483
- "declare"
1484
- ]);
1485
- var ANNOTATION_LEADERS = /* @__PURE__ */ new Set(["(", ",", "{", ";", "erased", "modifier"]);
1486
- function isAnnotationLeader(token) {
1487
- return ANNOTATION_LEADERS.has(token) || TS_MODIFIERS.has(token);
1488
- }
1489
- var Eraser = class {
1490
- constructor(src) {
1491
- this.src = src;
1492
- this.chars = [...src];
1493
- }
1494
- chars;
1495
- tokens = [];
1496
- frames = [];
1497
- /** 刚消费 `class` 头:下一个 `{` 是类体起始。 */
1498
- pendingClassBody = false;
1499
- /** 刚消费 `=>`:其后的 `(` 是箭头函数参数列表(声明位)。 */
1500
- afterArrow = false;
1501
- /** 刚消费 `function` 关键字:其后的标识符是函数名,再后是参数列表。 */
1502
- afterFunctionKeyword = false;
1503
- /** 最近一次 `)` 闭合的是不是参数列表(返回值标注判据)。 */
1504
- justClosedDeclareParen = false;
1505
- i = 0;
1506
- run() {
1507
- while (this.i < this.src.length) {
1508
- if (/\s/.test(this.ch())) {
1509
- this.i++;
1510
- continue;
1511
- }
1512
- if (this.copyTrivia()) continue;
1513
- if (this.copyLiteral()) continue;
1514
- if (this.copyRegexIfNeeded()) continue;
1515
- if (this.readNumber()) continue;
1516
- const word = this.readWord();
1517
- if (word !== null) this.handleWord(word);
1518
- else this.handlePunctuation();
1519
- }
1520
- return this.chars.join("");
1521
- }
1522
- /* ———————————————————— 游标原语 ———————————————————— */
1523
- ch(offset = 0) {
1524
- return this.src[this.i + offset] ?? "";
1525
- }
1526
- /** 回看第 `back` 个显著 token(1 = 最近一个)。 */
1527
- tokenAt(back) {
1528
- return this.tokens[this.tokens.length - back] ?? "";
1529
- }
1530
- /** 擦除结果里 `from` 往前的最后一个非空白字符(看的是已擦除文本,不是原文)。 */
1531
- prevSignificantChar(from) {
1532
- for (let j = from; j >= 0; j--) {
1533
- const c = this.chars[j];
1534
- if (c !== " " && c !== " " && c !== "\n" && c !== "\r") return c;
1535
- }
1536
- return "";
1537
- }
1538
- /** 擦除 `[from, to)`:填等长空格,换行照抄——擦完行号与原文件一致。 */
1539
- erase(from, to) {
1540
- for (let j = Math.max(from, 0); j < to; j++) this.chars[j] = this.src[j] === "\n" ? "\n" : " ";
1541
- }
1542
- pushToken(token) {
1543
- this.afterArrow = token === "=>";
1544
- this.afterFunctionKeyword = token === "function";
1545
- this.tokens.push(token);
1546
- }
1547
- /** 数字面量整段消费(否则 `1.5` 会被拆成 `1` `.` `5`,`.` 参与判据时误判)。 */
1548
- readNumber() {
1549
- if (!/[0-9]/.test(this.ch())) return false;
1550
- let end = this.i;
1551
- while (end < this.src.length && /[0-9a-fA-FxXoObB._]/.test(this.src[end])) end++;
1552
- this.i = end;
1553
- this.pushToken("number");
1554
- return true;
1555
- }
1556
- readWord() {
1557
- if (!IDENT_START.test(this.ch())) return null;
1558
- let end = this.i;
1559
- while (end < this.src.length && IDENT_PART.test(this.src[end])) end++;
1560
- const word = this.src.slice(this.i, end);
1561
- this.i = end;
1562
- this.pushToken(word);
1563
- return word;
1564
- }
1565
- /* —————————————— 字面量与注释:整段跳过(内容永不参与判定) —————————————— */
1566
- copyTrivia() {
1567
- const head = this.ch();
1568
- const next = this.ch(1);
1569
- if (head === "/" && next === "/") {
1570
- while (this.i < this.src.length && this.ch() !== "\n") this.i++;
1571
- return true;
1572
- }
1573
- if (head === "/" && next === "*") {
1574
- const end = this.src.indexOf("*/", this.i + 2);
1575
- this.i = end === -1 ? this.src.length : end + 2;
1576
- return true;
1577
- }
1578
- return false;
1579
- }
1580
- copyLiteral() {
1581
- const head = this.ch();
1582
- if (head !== "'" && head !== '"' && head !== "`") return false;
1583
- this.i = head === "`" ? this.scanTemplate(this.i) : this.scanQuoted(this.i);
1584
- this.pushToken(head === "`" ? "template" : "string");
1585
- return true;
1586
- }
1587
- /** 引号串结束下标(未闭合则到行尾,把真实的语法错误留给求值期)。 */
1588
- scanQuoted(start) {
1589
- const quote = this.src[start];
1590
- let j = start + 1;
1591
- while (j < this.src.length) {
1592
- const c = this.src[j];
1593
- if (c === "\\") j += 2;
1594
- else if (c === quote) return j + 1;
1595
- else if (c === "\n") return j;
1596
- else j++;
1597
- }
1598
- return this.src.length;
1599
- }
1600
- /** 模板串结束下标(`${}` 内按大括号配平,内层字符串 / 模板一并识别)。 */
1601
- scanTemplate(start) {
1602
- let j = start + 1;
1603
- while (j < this.src.length) {
1604
- const c = this.src[j];
1605
- if (c === "\\") j += 2;
1606
- else if (c === "`") return j + 1;
1607
- else if (c === "$" && this.src[j + 1] === "{") j = this.scanInterpolation(j + 2);
1608
- else j++;
1609
- }
1610
- return this.src.length;
1611
- }
1612
- scanInterpolation(start) {
1613
- let depth = 1;
1614
- let j = start;
1615
- while (j < this.src.length) {
1616
- const c = this.src[j];
1617
- if (c === "\\") j += 2;
1618
- else if (c === "'" || c === '"') j = this.scanQuoted(j);
1619
- else if (c === "`") j = this.scanTemplate(j);
1620
- else if (c === "{") {
1621
- depth++;
1622
- j++;
1623
- } else if (c === "}") {
1624
- depth--;
1625
- j++;
1626
- if (depth === 0) return j;
1627
- } else j++;
1628
- }
1629
- return this.src.length;
1630
- }
1631
- /**
1632
- * 正则字面量:`/` 只在「运算符位」才是正则起始(前一个显著字符不是值结尾)。
1633
- * 判不准时按除号处理——除号后面不会有需要擦除的类型标注,最坏只是漏擦。
1634
- * 有了这条,`const url = /https:\/\//` 里的 `:` 与 `//` 才不会被人当语法(恒等用例之一)。
1635
- */
1636
- copyRegexIfNeeded() {
1637
- if (this.ch() !== "/") return false;
1638
- const prev = this.prevSignificantChar(this.i - 1);
1639
- const valueEnding = prev !== "" && (IDENT_PART.test(prev) || prev === ")" || prev === "]" || prev === "}" || prev === '"' || prev === "'" || prev === "`");
1640
- if (valueEnding) return false;
1641
- const end = this.scanRegex(this.i);
1642
- if (end === null) return false;
1643
- this.i = end;
1644
- this.pushToken("regex");
1645
- return true;
1646
- }
1647
- scanRegex(start) {
1648
- let j = start + 1;
1649
- let inClass = false;
1650
- while (j < this.src.length) {
1651
- const c = this.src[j];
1652
- if (c === "\\") {
1653
- j += 2;
1654
- continue;
1655
- }
1656
- if (c === "\n") return null;
1657
- if (c === "[") inClass = true;
1658
- else if (c === "]") inClass = false;
1659
- else if (c === "/" && !inClass) {
1660
- j++;
1661
- while (j < this.src.length && /[a-z]/i.test(this.src[j])) j++;
1662
- return j;
1663
- }
1664
- j++;
1665
- }
1666
- return null;
1667
- }
1668
- /* ———————————————— 关键字与声明结构 ———————————————— */
1669
- handleWord(word) {
1670
- const start = this.i - word.length;
1671
- if (this.tokenAt(2) === ".") {
1672
- this.consumeGenericsAfterName();
1673
- return;
1674
- }
1675
- switch (word) {
1676
- case "interface": {
1677
- const after = this.skipWhitespaceFrom(this.skipNameAndParams(start + word.length));
1678
- if (after === null || this.src[after] !== "{") return;
1679
- const end = this.scanBalanced(after, "{", "}");
1680
- this.erase(start, end);
1681
- this.i = end;
1682
- this.pushToken("erased");
1683
- return;
1684
- }
1685
- case "type": {
1686
- const after = this.skipWhitespaceFrom(this.skipNameAndParams(this.i));
1687
- if (after === null || this.src[after] !== "=") return;
1688
- const end = this.scanTypeExpression(after + 1, true);
1689
- this.erase(start, end);
1690
- this.i = end;
1691
- this.pushToken("erased");
1692
- return;
1693
- }
1694
- case "import":
1695
- case "export": {
1696
- if (!/^\s+type\b/.test(this.src.slice(this.i))) return;
1697
- const after = this.skipNameAndParams(this.i);
1698
- if (after === null) return;
1699
- const end = this.scanStatementEnd(after);
1700
- this.erase(start, end);
1701
- this.i = end;
1702
- this.pushToken("erased");
1703
- return;
1704
- }
1705
- case "enum":
1706
- case "namespace":
1707
- throw new UnsupportedTsSyntaxError(word, this.lineAt(start));
1708
- case "implements": {
1709
- let j = this.i;
1710
- while (j < this.src.length && this.src[j] !== "{" && this.src[j] !== ";") j++;
1711
- this.erase(start, j);
1712
- this.i = j;
1713
- this.pushToken("erased");
1714
- return;
1715
- }
1716
- case "class":
1717
- this.pendingClassBody = true;
1718
- return;
1719
- case "as":
1720
- case "satisfies": {
1721
- if (this.tokenAt(2) === "*" || this.tokenAt(2) === "type") return;
1722
- const nextChar = this.skipWhitespaceFrom(this.i);
1723
- if (nextChar === null || "=,:]})".includes(this.src[nextChar])) return;
1724
- const end = this.scanTypeExpression(this.i, false);
1725
- this.erase(start, end);
1726
- this.i = end;
1727
- return;
1728
- }
1729
- default: {
1730
- if (TS_MODIFIERS.has(word) && this.inClassBody()) {
1731
- const next = this.peekWord();
1732
- if (next === "" || /[{(=]/.test(next[0])) return;
1733
- this.erase(start, this.i);
1734
- this.pushToken("modifier");
1735
- return;
1736
- }
1737
- this.consumeGenericsAfterName();
1738
- }
1739
- }
1740
- }
1741
- peekWord() {
1742
- let j = this.i;
1743
- while (j < this.src.length && /\s/.test(this.src[j])) j++;
1744
- let end = j;
1745
- while (end < this.src.length && IDENT_PART.test(this.src[end])) end++;
1746
- return this.src.slice(j, end);
1747
- }
1748
- lineAt(index) {
1749
- let line = 1;
1750
- for (let j = 0; j < index; j++) if (this.src[j] === "\n") line++;
1751
- return line;
1752
- }
1753
- /** `:` 之前紧邻的是不是 `)`(返回值标注位;用于决定是否允许顶层 `=>` 续读)。 */
1754
- lastSignificantCharIsCloseParen(at) {
1755
- return this.prevSignificantChar(at - 1) === ")";
1756
- }
1757
- inClassBody() {
1758
- return this.frames[this.frames.length - 1]?.classBody === true;
1759
- }
1760
- /** 当前帧是不是声明位(参数列表 / 类体)——只有这里才允许把 `:` 判成标注。 */
1761
- inDeclarePosition() {
1762
- const frame = this.frames[this.frames.length - 1];
1763
- return frame !== void 0 && (frame.declare || frame.classBody);
1764
- }
1765
- /* ———————————————— 标点与括号帧 ———————————————— */
1766
- handlePunctuation() {
1767
- const c = this.ch();
1768
- const start = this.i;
1769
- if (c === "(" || c === "{" || c === "[") {
1770
- const frame = {
1771
- kind: c === "(" ? "paren" : c === "{" ? "brace" : "bracket",
1772
- declare: false,
1773
- classBody: false
1774
- };
1775
- if (c === "{" && this.pendingClassBody) {
1776
- frame.classBody = true;
1777
- this.pendingClassBody = false;
1778
- }
1779
- if (c === "(" && this.isDeclareParen(start)) frame.declare = true;
1780
- this.frames.push(frame);
1781
- this.i++;
1782
- this.pushToken(c);
1783
- return;
1784
- }
1785
- if (c === ")" || c === "}" || c === "]") {
1786
- const closed = this.frames.pop();
1787
- if (closed?.kind === "paren") this.justClosedDeclareParen = closed.declare;
1788
- this.i++;
1789
- this.pushToken(c);
1790
- return;
1791
- }
1792
- if (c === ":") {
1793
- if (this.ch(1) === ":") {
1794
- this.i++;
1795
- this.pushToken(":");
1796
- return;
1797
- }
1798
- const returnType = this.isAnnotationColon(start) && this.lastSignificantCharIsCloseParen(start);
1799
- if (returnType || this.isAnnotationColon(start)) {
1800
- const end = this.scanTypeExpression(start + 1, false, returnType);
1801
- this.erase(start, end);
1802
- this.i = end;
1803
- this.pushToken("erased");
1804
- return;
1805
- }
1806
- this.i++;
1807
- this.pushToken(":");
1808
- return;
1809
- }
1810
- if (c === "?" && this.ch(1) !== "?" && this.ch(1) !== ".") {
1811
- let j = start + 1;
1812
- while (j < this.src.length && (this.src[j] === " " || this.src[j] === " ")) j++;
1813
- if (this.src[j] === ":" && this.inDeclarePosition() && IDENT_PART.test(this.prevSignificantChar(start - 1))) {
1814
- const end = this.scanTypeExpression(j + 1, false);
1815
- this.erase(start, end);
1816
- this.i = end;
1817
- this.pushToken("erased");
1818
- return;
1819
- }
1820
- this.i++;
1821
- this.pushToken("?");
1822
- return;
1823
- }
1824
- if (c === "!" && this.ch(1) !== "=" && this.isPostfixBang(start)) {
1825
- this.erase(start, start + 1);
1826
- this.i++;
1827
- return;
1828
- }
1829
- if (c === "=" && this.ch(1) === ">") {
1830
- this.i += 2;
1831
- this.pushToken("=>");
1832
- return;
1833
- }
1834
- if (c === "<" && this.consumeLeadingGenerics(start)) return;
1835
- this.i++;
1836
- this.pushToken(c);
1837
- }
1838
- /** 空白跳跃(供声明结构找下一个非空白字符;不改游标,纯函数)。 */
1839
- skipWhitespaceFrom(index) {
1840
- if (index === null) return null;
1841
- let j = index;
1842
- while (j < this.src.length && /\s/.test(this.src[j])) j++;
1843
- return j;
1844
- }
1845
- /**
1846
- * 运算符位上的泛型参数列表(`const f = <T, >(x: T) => x`、`arr.map<T2>(...)` 之外的箭头形态):
1847
- * 前一个显著字符不是值结尾(否则是 `a < b` 比较),且 `>` 之后紧跟 `(` 才擦。
1848
- */
1849
- consumeLeadingGenerics(at) {
1850
- if (!"([{,=;:>!&|?".includes(this.prevSignificantChar(at - 1))) return false;
1851
- const end = this.scanTypeParams(at);
1852
- if (end === null) return false;
1853
- const after = this.skipWhitespaceFrom(end);
1854
- if (after === null || this.src[after] !== "(") return false;
1855
- this.erase(at, end);
1856
- this.i = end;
1857
- return true;
1858
- }
1859
- /**
1860
- * `(` 是否为参数列表(声明位):`function f(`、类体里的方法 `m(`、箭头 `=> (`,
1861
- * 以及出现在 `(` `,` `=` `>` `:` `[` `{` `}` `;` 之后(如 `map((v: T) => v)` 的内层括号)。
1862
- * 调用位 `foo(` 与控制流 `if (` `for (` 都不算。
1863
- * 误判成声明位也不足以擦掉什么:`:` 还要过 `isAnnotationColon` 的「名字前驱必须是
1864
- * `(` `,` `{` `;` 修饰符」这一关,而三元表达式的中间段前面必然是 `?`。
1865
- */
1866
- isDeclareParen(at) {
1867
- if (this.afterFunctionKeyword) return true;
1868
- if (this.tokenAt(2) === "function" && IDENT_START.test(this.tokenAt(1))) return true;
1869
- if (this.afterArrow) return true;
1870
- if (this.inClassBody() && IDENT_PART.test(this.prevSignificantChar(at - 1))) return true;
1871
- const prev = this.prevSignificantChar(at - 1);
1872
- return prev === "" || "(,=>:[{};".includes(prev);
1873
- }
1874
- /** `:` 是类型标注吗:看名字前驱 token 与所在帧(对象键、三元、`case` 一律排除)。 */
1875
- isAnnotationColon(at) {
1876
- const prev = this.prevSignificantChar(at - 1);
1877
- if (prev === ")") return this.justClosedDeclareParen;
1878
- if (prev === "}" || prev === "]") {
1879
- const frame = this.frames[this.frames.length - 1];
1880
- return frame?.kind === "paren" && frame.declare;
1881
- }
1882
- if (!IDENT_PART.test(prev)) return false;
1883
- if (this.tokenAt(1) === "number" || this.tokenAt(1) === "string") return false;
1884
- if (this.inDeclarePosition() && isAnnotationLeader(this.tokenAt(2))) return true;
1885
- return DECL_KEYWORDS.has(this.tokenAt(2));
1886
- }
1887
- /** 非空断言 `x!`:前一个显著字符是值结尾,且后一个非空白字符不是操作数起始。 */
1888
- isPostfixBang(at) {
1889
- const prev = this.prevSignificantChar(at - 1);
1890
- if (!(IDENT_PART.test(prev) || prev === ")" || prev === "]")) return false;
1891
- let j = at + 1;
1892
- while (j < this.src.length && (this.src[j] === " " || this.src[j] === " ")) j++;
1893
- const next = this.src[j] ?? "";
1894
- if (next === "") return true;
1895
- return !(IDENT_START.test(next) || /[0-9]/.test(next) || "(![~".includes(next));
1896
- }
1897
- /* ———————————————— 区间扫描(全部字符串 / 注释安全) ———————————————— */
1898
- /** 跳过「名字 + 泛型参数」;没有合法名字时返回 null(`{ type: 1 }` 因此落空)。 */
1899
- skipNameAndParams(from) {
1900
- let j = from;
1901
- while (j < this.src.length && /\s/.test(this.src[j])) j++;
1902
- const nameStart = j;
1903
- while (j < this.src.length && IDENT_PART.test(this.src[j])) j++;
1904
- if (j === nameStart) return null;
1905
- const generic = this.scanTypeParams(j);
1906
- return generic === null ? j : generic;
1907
- }
1908
- /** `<T, U extends X>`:返回 `>` 之后的下标;跨到 `)` `]` `;` 换行前配不平则 null。 */
1909
- scanTypeParams(from) {
1910
- if (this.src[from] !== "<") return null;
1911
- let depth = 0;
1912
- let j = from;
1913
- for (; j < this.src.length; j++) {
1914
- const c = this.src[j];
1915
- if (c === "<") depth++;
1916
- else if (c === ">") {
1917
- depth--;
1918
- if (depth === 0) return j + 1;
1919
- } else if (c === ")" || c === "]" || c === ";" || c === "\n") return null;
1920
- else if (c === "'" || c === '"') j = this.scanQuoted(j) - 1;
1921
- else if (c === "`") j = this.scanTemplate(j) - 1;
1922
- }
1923
- return null;
1924
- }
1925
- /**
1926
- * 消费「刚读出的标识符之后」的泛型实参 / 类型参数(`function f<T>(`、方法 `m<T>(`、`f<T>(x)`)。
1927
- * 只有 `>` 之后紧跟 `(` / `{` / `implements` 才算——`if (a < b) {` 里 `>` 之后是 `)`,故安全。
1928
- */
1929
- consumeGenericsAfterName() {
1930
- if (this.ch() !== "<") return;
1931
- const end = this.scanTypeParams(this.i);
1932
- if (end === null) return;
1933
- let j = end;
1934
- while (j < this.src.length && (this.src[j] === " " || this.src[j] === " ")) j++;
1935
- const after = this.src.slice(j);
1936
- if (!/^[({]/.test(after) && !/^implements\b/.test(after)) return;
1937
- this.erase(this.i, end);
1938
- this.i = end;
1939
- }
1940
- /** 括号配平:返回闭括号之后的下标(未配平则到文件尾)。 */
1941
- scanBalanced(from, open, close) {
1942
- let depth = 0;
1943
- let j = from;
1944
- while (j < this.src.length) {
1945
- const c = this.src[j];
1946
- if (c === "'" || c === '"') j = this.scanQuoted(j);
1947
- else if (c === "`") j = this.scanTemplate(j);
1948
- else if (c === "/" && (this.src[j + 1] === "/" || this.src[j + 1] === "*"))
1949
- j = this.skipComment(j);
1950
- else if (c === open) {
1951
- depth++;
1952
- j++;
1953
- } else if (c === close) {
1954
- depth--;
1955
- j++;
1956
- if (depth === 0) return j;
1957
- } else j++;
1958
- }
1959
- return this.src.length;
1960
- }
1961
- skipComment(from) {
1962
- if (this.src[from + 1] === "/") {
1963
- const end2 = this.src.indexOf("\n", from);
1964
- return end2 === -1 ? this.src.length : end2;
1965
- }
1966
- const end = this.src.indexOf("*/", from + 2);
1967
- return end === -1 ? this.src.length : end + 2;
1968
- }
1969
- /** 语句结束(`;` 或括号已配平时的行尾),用于 `import type …`。 */
1970
- scanStatementEnd(from) {
1971
- let depth = 0;
1972
- let j = from;
1973
- while (j < this.src.length) {
1974
- const c = this.src[j];
1975
- if (c === "'" || c === '"') j = this.scanQuoted(j);
1976
- else if (c === "`") j = this.scanTemplate(j);
1977
- else if (c === "{" || c === "(" || c === "[") {
1978
- depth++;
1979
- j++;
1980
- } else if (c === "}" || c === ")" || c === "]") {
1981
- depth--;
1982
- j++;
1983
- } else if (c === ";" || c === "\n" && depth <= 0) break;
1984
- else j++;
1985
- }
1986
- return j;
1987
- }
1988
- /**
1989
- * 类型表达式结束下标:消费标识符 / 字符串字面量类型 / 泛型实参 / 元组 / 对象类型 /
1990
- * 函数类型(含 `=>` 返回值)/ 联合与交叉;在深度 0 的 `= , ; ) ]` 与「已结束的行」处停下。
1991
- *
1992
- * 两处歧义的处理:
1993
- * - `function f(): { a: number } { … }`——还没消费过类型原子时遇到的 `{` 属于类型,
1994
- * 之后再遇 `{` 才是函数体;`type X = A` 的初始值花括号整体算类型(`leadingBraceIsType`)。
1995
- * - `const x: Foo = { … }`——在 `=` 处停,不会把右侧对象字面量吞掉。
1996
- */
1997
- scanTypeExpression(from, leadingBraceIsType, topLevelArrowEnds = false) {
1998
- let depth = 0;
1999
- let j = from;
2000
- let sawAtom = false;
2001
- while (j < this.src.length) {
2002
- const c = this.src[j];
2003
- if (c === "'" || c === '"') {
2004
- j = this.scanQuoted(j);
2005
- sawAtom = true;
2006
- } else if (c === "`") {
2007
- j = this.scanTemplate(j);
2008
- sawAtom = true;
2009
- } else if (c === "/" && (this.src[j + 1] === "/" || this.src[j + 1] === "*")) {
2010
- j = this.skipComment(j);
2011
- } else if (c === "(" || c === "[") {
2012
- depth++;
2013
- sawAtom = true;
2014
- j++;
2015
- } else if (c === ")" || c === "]") {
2016
- if (depth === 0) break;
2017
- depth--;
2018
- j++;
2019
- } else if (c === "{") {
2020
- if (depth === 0 && sawAtom && !leadingBraceIsType) break;
2021
- j = this.scanBalanced(j, "{", "}");
2022
- sawAtom = true;
2023
- } else if (c === "}") {
2024
- if (depth === 0) break;
2025
- depth--;
2026
- j++;
2027
- } else if (depth === 0 && (c === "," || c === ";")) break;
2028
- else if (depth === 0 && c === "=") {
2029
- if (this.src[j + 1] === ">" && !topLevelArrowEnds) {
2030
- j += 2;
2031
- continue;
2032
- }
2033
- break;
2034
- } else if (depth === 0 && c === "\n") {
2035
- if (!this.typeContinuesAt(j)) break;
2036
- j++;
2037
- } else if (c === "<") {
2038
- const generic = this.scanTypeParams(j);
2039
- if (generic === null) break;
2040
- j = generic;
2041
- sawAtom = true;
2042
- } else {
2043
- if (IDENT_PART.test(c)) sawAtom = true;
2044
- j++;
2045
- }
2046
- }
2047
- return j;
2048
- }
2049
- /**
2050
- * 行尾处类型是否仍在继续:`type Id = string\n | number` 要接得上,
2051
- * 而 `const x: Foo\nconst y = 1` 必须停。判据是两侧的非空邻字——
2052
- * 前一个是连接符(`| & < > = , . ? : (`)或后一个是连接符 / 闭合符(`| & , . ? : ) ] } >`)。
2053
- */
2054
- typeContinuesAt(index) {
2055
- for (let j = index - 1; j >= 0; j--) {
2056
- const c = this.src[j];
2057
- if (/\s/.test(c)) continue;
2058
- if ("|&<>=,.?:(".includes(c)) return true;
2059
- break;
2060
- }
2061
- for (let j = index + 1; j < this.src.length; j++) {
2062
- const c = this.src[j];
2063
- if (/\s/.test(c)) continue;
2064
- return "|&,.?:)]}>".includes(c);
2065
- }
2066
- return false;
2067
- }
2068
- };
2069
- function stripTypes(source) {
2070
- return new Eraser(source).run();
2071
- }
3175
+ // src/test-runner.ts
3176
+ init_strip_types();
2072
3177
 
2073
3178
  // src/test-framework.ts
2074
3179
  var TestAssertionError = class extends Error {
@@ -2503,6 +3608,17 @@ self.onmessage = async (event) => {
2503
3608
  }
2504
3609
 
2505
3610
  // src/container.ts
3611
+ function viteBanner(server, fresh) {
3612
+ return [
3613
+ fresh ? ` VITE \u6D4F\u89C8\u5668\u5185 dev server \u5DF2\u5C31\u7EEA\uFF08root: ${server.root}\uFF09
3614
+ ` : ` vite dev server \u5DF2\u5728\u8FD0\u884C\uFF08root: ${server.root}\uFF09
3615
+ `,
3616
+ "\n",
3617
+ " \u279C Local: http://localhost:5173/\n",
3618
+ " \u279C \u9884\u89C8\uFF1A\u7EC8\u7AEF / IDE \u7684\u9884\u89C8\u9762\u677F\u5DF2\u5C31\u7EEA\uFF0C\u7F16\u8F91\u4FDD\u5B58\u540E\u81EA\u52A8\u5237\u65B0\uFF08HMR\uFF09\n",
3619
+ " \u279C \u505C\u6B62\uFF1Avite stop\uFF08\u6362\u76EE\u5F55\uFF1Avite <dir>\uFF09\n"
3620
+ ].join("");
3621
+ }
2506
3622
  function bootstrap(options) {
2507
3623
  const vfs = options.vfs ?? new VirtualFileSystem();
2508
3624
  if (options.initialTree !== void 0) vfs.mount(options.initialTree);
@@ -2521,12 +3637,46 @@ self.onmessage = async (event) => {
2521
3637
  return { code: outcome.code, stdout: outcome.stdout, stderr: outcome.stderr };
2522
3638
  }
2523
3639
  };
3640
+ const net = options.net ?? createRelayFetch({
3641
+ baseUrl: options.httpRelayBaseUrl ?? "/api/v1/http-relay",
3642
+ ...options.fetchImpl === void 0 ? {} : { fetchImpl: options.fetchImpl }
3643
+ });
3644
+ let viteServer = null;
3645
+ const vite = {
3646
+ async start(args) {
3647
+ const target = args[0] ?? "/";
3648
+ const root = target.startsWith("/") ? normalize(target) : join(cwd, target);
3649
+ if (viteServer !== null && viteServer.root === root)
3650
+ return { code: 0, stdout: viteBanner(viteServer, false) };
3651
+ await viteServer?.stop();
3652
+ viteServer = null;
3653
+ const { createViteServer: createViteServer2 } = await Promise.resolve().then(() => (init_vite_dev(), vite_dev_exports));
3654
+ const server = createViteServer2(vfs, {
3655
+ root,
3656
+ ...options.viteCompiler === void 0 ? {} : { sfcCompiler: options.viteCompiler }
3657
+ });
3658
+ await server.ready;
3659
+ viteServer = server;
3660
+ emit("serverready", { port: server.port, url: server.url, kind: "vite", root: server.root });
3661
+ return { code: 0, stdout: viteBanner(server, true) };
3662
+ },
3663
+ async stop() {
3664
+ if (viteServer === null) return { code: 0, stdout: "vite: dev server \u672A\u5728\u8FD0\u884C\n" };
3665
+ const root = viteServer.root;
3666
+ await viteServer.stop();
3667
+ viteServer = null;
3668
+ return { code: 0, stdout: ` vite dev server \u5DF2\u505C\u6B62\uFF08root: ${root}\uFF09
3669
+ ` };
3670
+ }
3671
+ };
2524
3672
  const shell = new Shell({
2525
3673
  vfs,
2526
3674
  getCwd: () => cwd,
2527
3675
  setCwd,
2528
3676
  ...runtime === void 0 ? {} : { runtime },
2529
- test
3677
+ test,
3678
+ net,
3679
+ vite
2530
3680
  });
2531
3681
  const npmClient = createNpmClient({
2532
3682
  baseUrl: options.npmRelayBaseUrl,
@@ -2646,9 +3796,9 @@ self.onmessage = async (event) => {
2646
3796
  },
2647
3797
  async preview(previewOptions) {
2648
3798
  if (preview === null) {
2649
- const { createPreviewServer: createPreviewServer2 } = await Promise.resolve().then(() => (init_preview(), preview_exports));
3799
+ const { createPreviewServer: createPreviewServer2 } = await Promise.resolve().then(() => (init_preview_server(), preview_server_exports));
2650
3800
  preview = createPreviewServer2(vfs, previewOptions);
2651
- emit("serverready", { port: preview.port, url: preview.url });
3801
+ emit("serverready", { port: preview.port, url: preview.url, kind: "preview" });
2652
3802
  }
2653
3803
  return { url: preview.url, port: preview.port };
2654
3804
  },
@@ -2657,11 +3807,15 @@ self.onmessage = async (event) => {
2657
3807
  defaultRuntime?.close?.();
2658
3808
  await preview?.stop();
2659
3809
  preview = null;
3810
+ await viteServer?.stop();
3811
+ viteServer = null;
2660
3812
  }
2661
3813
  };
2662
3814
  }
2663
3815
 
2664
3816
  // src/index.ts
3817
+ init_node_resolve();
3818
+ init_vite_dev();
2665
3819
  init_path();
2666
3820
 
2667
3821
  // src/persistence.ts
@@ -2877,6 +4031,9 @@ self.onmessage = async (event) => {
2877
4031
  };
2878
4032
  }
2879
4033
 
4034
+ // src/index.ts
4035
+ init_strip_types();
4036
+
2880
4037
  // src/offline/net.ts
2881
4038
  var HEALTH_CHECK_INTERVAL_MS = 3e4;
2882
4039
  var HEALTH_CHECK_TIMEOUT_MS = 5e3;
@@ -3140,7 +4297,6 @@ self.onmessage = async (event) => {
3140
4297
 
3141
4298
  // src/offline/workspace.ts
3142
4299
  var DB_NAME = "adep-offline-workspace";
3143
- var DB_VERSION = 1;
3144
4300
  function requestError(request) {
3145
4301
  return request.error ?? new Error("IndexedDB operation failed");
3146
4302
  }
@@ -3155,7 +4311,7 @@ self.onmessage = async (event) => {
3155
4311
  reject(new Error("IndexedDB not available"));
3156
4312
  return;
3157
4313
  }
3158
- const request = indexedDB.open(DB_NAME, DB_VERSION);
4314
+ const request = indexedDB.open(DB_NAME);
3159
4315
  request.onupgradeneeded = () => {
3160
4316
  };
3161
4317
  request.onsuccess = () => {
@@ -3182,10 +4338,12 @@ self.onmessage = async (event) => {
3182
4338
  };
3183
4339
  request.onsuccess = () => {
3184
4340
  this.db = request.result;
4341
+ this.initPromise = Promise.resolve(request.result);
3185
4342
  const tx2 = this.db.transaction(storeName, "readwrite");
3186
4343
  resolve(tx2.objectStore(storeName));
3187
4344
  };
3188
4345
  request.onerror = () => reject(requestError(request));
4346
+ request.onblocked = () => reject(new Error("IndexedDB \u5347\u7EA7\u88AB\u5176\u4ED6\u6807\u7B7E\u9875\u963B\u585E\uFF08adep-offline-workspace\uFF09"));
3189
4347
  });
3190
4348
  }
3191
4349
  const tx = db.transaction(storeName, "readwrite");
@@ -5467,6 +6625,7 @@ self.onmessage = async (event) => {
5467
6625
  }
5468
6626
 
5469
6627
  // src/sim/runner.ts
6628
+ init_strip_types();
5470
6629
  function safeStringify2(value) {
5471
6630
  if (typeof value === "string") return value;
5472
6631
  try {
@@ -5642,5 +6801,8 @@ self.onmessage = async (event) => {
5642
6801
  dispose: async () => void 0
5643
6802
  };
5644
6803
  }
6804
+
6805
+ // src/index.ts
6806
+ init_function_fetch_proxy();
5645
6807
  return __toCommonJS(index_exports);
5646
6808
  })();