@adep/web-container 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/completion.d.ts +1 -1
- package/dist/container.d.ts +17 -0
- package/dist/function-fetch-proxy.d.ts +54 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +2044 -882
- package/dist/{preview.d.ts → preview-server.d.ts} +6 -1
- package/dist/relay-fetch.d.ts +32 -0
- package/dist/shell.d.ts +45 -0
- package/dist/vite-dev.d.ts +94 -0
- package/package.json +22 -17
- package/dist/web-container.esm.js +0 -5628
- package/dist/web-container.iife.js +0 -5646
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* 浏览器原生开发环境的「虚拟静态 dev server + 内联预览 + HMR」(FN-012 Scenario 1 / 验收 5)。
|
|
3
|
+
*
|
|
4
|
+
* 原 `preview.ts`(IDE-004 删除)迁移而来:IDE 预览面板已统一为 RuntimeAdapter 提供的
|
|
5
|
+
* dev server URL(iframe 直加载),不再消费本模块;但浏览器终端(BrowserTerminal)的
|
|
6
|
+
* 内联预览(`container.preview()`,web-container 回退路径)与 `vite-dev.ts` 的经典资源
|
|
7
|
+
* 内联仍依赖它,故保留在 `preview-server.ts`(随 web-container 大版本废弃时一并移除)。
|
|
3
8
|
*
|
|
4
9
|
* 真实浏览器里没有 Node / Vite 运行时,预习用「虚拟静态 dev server」实现(全程浏览器内、
|
|
5
10
|
* 零依赖、无需本机运行时):
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP 中继客户端(curl/wget 的网络端口实现)。
|
|
3
|
+
*
|
|
4
|
+
* 浏览器虚拟系统直连任意主机受跨域(CORS)限制——与 npm 依赖走 `/npm-relay/*` 同一取向,
|
|
5
|
+
* `curl` / `wget` 的网络请求全部经平台 `/v1/http-relay/fetch` 中继:
|
|
6
|
+
* 服务端代理发起请求并做 SSRF 防护(拦截内网 / 回环 / 链路本地地址)、限速、超时与响应体上限。
|
|
7
|
+
*
|
|
8
|
+
* 中继协议:`POST <baseUrl>/fetch`,JSON 请求体 `{ url, method?, headers?, body? }`;
|
|
9
|
+
* 响应为 JSON 信封 `{ ok, status, statusText, headers, body }`(body 为 UTF-8 文本——
|
|
10
|
+
* VFS 本身只存字符串,二进制下载与 npm tarball 同属 lossy 形态)。
|
|
11
|
+
* 中继级错误(非法 URL / 主机被拒 / 限速 / 上游不可达)以 `{ error: { code, message } }` 返回,
|
|
12
|
+
* 此处归一为 reject,错误消息直接可进终端 stderr。
|
|
13
|
+
*/
|
|
14
|
+
import type { CloudFetch } from '@adep/types';
|
|
15
|
+
export interface RelayFetchOptions {
|
|
16
|
+
/** 平台 HTTP 中继基础路径(如 `/api/v1/http-relay`;相对绝对均可)。 */
|
|
17
|
+
baseUrl: string;
|
|
18
|
+
/** 底层网络实现(缺省 globalThis.fetch;测试注入假中继)。 */
|
|
19
|
+
fetchImpl?: CloudFetch;
|
|
20
|
+
}
|
|
21
|
+
/** 中继成功响应信封。 */
|
|
22
|
+
export interface RelayEnvelope {
|
|
23
|
+
ok: boolean;
|
|
24
|
+
status: number;
|
|
25
|
+
statusText: string;
|
|
26
|
+
headers: Record<string, string>;
|
|
27
|
+
body: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* 构造一个经平台 HTTP 中继发请求的受控 fetch(满足 `cloud.fetch` 契约,可注入 ShellCtx.net)。
|
|
31
|
+
*/
|
|
32
|
+
export declare function createRelayFetch(options: RelayFetchOptions): CloudFetch;
|
package/dist/shell.d.ts
CHANGED
|
@@ -6,10 +6,16 @@
|
|
|
6
6
|
* 输出以 `stdout` / `stderr` 分通道收集,供上层包装成 WebContainerProcess 双工流。
|
|
7
7
|
*
|
|
8
8
|
* 浏览器可跑(零 node 依赖),`runtime` 为可替换适配(QuickJS WASM / Node vm)。
|
|
9
|
+
*
|
|
10
|
+
* `curl` / `wget` 走 `net` 端口(受控 fetch,与 `runtime` / `test` 同一注入取向):
|
|
11
|
+
* 浏览器直连任意主机受跨域限制,生产实现由 `bootstrap` 装配成平台 HTTP 中继
|
|
12
|
+
* (`/v1/http-relay/fetch`,服务端带 SSRF 防护 / 限速 / 体上限);裸 Shell 未注入时如实报错。
|
|
9
13
|
*/
|
|
14
|
+
import type { CloudFetch } from '@adep/types';
|
|
10
15
|
import type { VirtualFileSystem } from './vfs';
|
|
11
16
|
import { type CompletionResult } from './completion';
|
|
12
17
|
import type { TestCommandPort } from './test-runner';
|
|
18
|
+
import type { ViteCommandPort } from './vite-dev';
|
|
13
19
|
/** JS 运行时适配接口:能加载并执行一段 JS 模块(QuickJS WASM / Web Worker 沙箱 / Node vm 等实现)。 */
|
|
14
20
|
export interface JsRuntime {
|
|
15
21
|
/** 执行脚本文件,返回标准输出文本;实现抛错时以 `stderr` 语义上报。 */
|
|
@@ -29,6 +35,16 @@ export interface ShellCtx {
|
|
|
29
35
|
runtime?: JsRuntime;
|
|
30
36
|
/** `test` 命令的运行器(FN-022):由 `bootstrap` 装配;裸 Shell 未注入时如实报「未装配」。 */
|
|
31
37
|
test?: TestCommandPort;
|
|
38
|
+
/**
|
|
39
|
+
* `curl` / `wget` 的网络端口(受控 fetch,契约同 `cloud.fetch`):由 `bootstrap` 装配成
|
|
40
|
+
* 平台 HTTP 中继(浏览器跨域无法直连任意主机);裸 Shell 未注入时 curl/wget 如实报错。
|
|
41
|
+
*/
|
|
42
|
+
net?: CloudFetch;
|
|
43
|
+
/**
|
|
44
|
+
* `vite` 命令端口(浏览器内 Vite 兼容 dev server):由 `bootstrap` 装配;
|
|
45
|
+
* 裸 Shell 未注入时 `vite` 如实报「未装配」(与 `test` 同款注入取向)。
|
|
46
|
+
*/
|
|
47
|
+
vite?: ViteCommandPort;
|
|
32
48
|
}
|
|
33
49
|
export declare class Shell {
|
|
34
50
|
private readonly ctx;
|
|
@@ -37,6 +53,35 @@ export declare class Shell {
|
|
|
37
53
|
execute(line: string): Promise<ShellResult>;
|
|
38
54
|
private runSegment;
|
|
39
55
|
private ls;
|
|
56
|
+
/**
|
|
57
|
+
* `curl [选项] <url>`(常用旗标最小子集):
|
|
58
|
+
* - 响应体默认写 stdout(可 `|` 管道 / `>` 重定向);`-o <file>` 写 VFS 文件、`-o -` 显式 stdout;
|
|
59
|
+
* - `-i/--include` 输出响应头 + 体;`-I/--head` 发 HEAD 且只输出响应头;
|
|
60
|
+
* - `-X/--request`、`-H/--header`(可多次)、`-d/--data`(可多次,`&` 拼接,隐含 POST 与表单头)、
|
|
61
|
+
* `-A/--user-agent`、`-u/--user`(转 Basic 认证)、`-f/--fail`(HTTP ≥400 退出码 22);
|
|
62
|
+
* - `-s/-S/-L/-k/-g/-N/--compressed` 等常见旗标接受但无效果(仿真环境本就静默/跟随重定向/不校验证书);
|
|
63
|
+
* - 裸主机名(`example.com/x`)按 curl 语义补 `http://`;网络故障退出码 7,用法错误 2。
|
|
64
|
+
*/
|
|
65
|
+
private runCurl;
|
|
66
|
+
/**
|
|
67
|
+
* `wget [选项] <url>`(常用旗标最小子集):
|
|
68
|
+
* - 默认按 URL 末级路径名落 VFS 文件(目录形态落 `index.html`),过程信息走 stderr;
|
|
69
|
+
* - `-O <file>` 指定文件名、`-O -` 输出到 stdout;`-q/--quiet` 静默;`-S/--server-response` 打印响应头;
|
|
70
|
+
* - HTTP ≥400 / 网络失败退出码 1 且不落文件(与 GNU wget 默认一致)。
|
|
71
|
+
*/
|
|
72
|
+
private runWget;
|
|
73
|
+
/**
|
|
74
|
+
* `vite [子命令|目录]`:
|
|
75
|
+
* - `vite` / `vite dev [dir]`:启动浏览器内 Vite 兼容 dev server(`dir` 为 root,缺省 `/`;
|
|
76
|
+
* `--port` 等旗标接受但无效果——端口是虚拟语义值);
|
|
77
|
+
* - `vite stop`:停止并释放;
|
|
78
|
+
* - `vite build`:首版明确不支持(dev 语义优先),如实报错。
|
|
79
|
+
* dev server 常驻在容器层(`serverready` 事件 + HMR),命令本身立即返回——与真实
|
|
80
|
+
* vite 的前台常驻进程形态不同,属仿真终端的取舍(见 vite-dev.ts 文件头)。
|
|
81
|
+
*/
|
|
82
|
+
private runVite;
|
|
83
|
+
/** 经 net 端口发请求;端口缺失 / 网络失败归一为 NetCommandError(curl/wget 各自映射退出码与文案)。 */
|
|
84
|
+
private netRequest;
|
|
40
85
|
/**
|
|
41
86
|
* 对当前输入行求 Tab 补全候选(FE-022):命令位补内建命令名,参数位补 VFS 路径。
|
|
42
87
|
* 无候选不抛错(Tab 不该让终端报错),由调用方决定「不响应」还是「列出可能项」。
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 浏览器内 Vite 兼容 dev server(`vite` 命令本体)。
|
|
3
|
+
*
|
|
4
|
+
* preview.ts 的「虚拟静态 dev server」只内联经典脚本(`<script src>`),明确不跑
|
|
5
|
+
* ESM / TS / npm 依赖的编译管线(其文件头留了「替换为真正的 Vite pipeline」的接口)。
|
|
6
|
+
* 本模块补上这一层——在浏览器内、零第三方运行时约束下实现 Vite dev server 的核心语义:
|
|
7
|
+
*
|
|
8
|
+
* - **入口**:root 下的 `index.html`(或选项指定),`<script type="module">` 是模块入口;
|
|
9
|
+
* - **模块图**:递归解析 ESM import / export…from / 动态 import(),每个模块转换后生成
|
|
10
|
+
* 一个 `blob:` URL,模块里的说明符被改写成目标的 blob URL——整条链是浏览器原生 ESM
|
|
11
|
+
* (真 live binding、真模块隔离),不是 CJS 打平;
|
|
12
|
+
* - **转换**:`.ts` 复用 stripTypes 擦类型;`.css` 变成「注入 `<style>` 的副作用模块」;
|
|
13
|
+
* `.json` 变成默认导出对象;`.vue` 经注入的 SFC 编译器(IDE 侧装 `vue/compiler-sfc`);
|
|
14
|
+
* - **依赖**:裸说明符经 node-resolve 命中 VFS `node_modules/`(终端 `npm install` 的产物),
|
|
15
|
+
* 与 CLI / 线上同一套解析规则;相对说明符支持 Vite 风格省略扩展名(.ts/.js/.vue/…);
|
|
16
|
+
* - **HMR**:订阅 VFS 变更(`vfs.onMutate`,IDE 保存 / shell 写入 / npm 解包皆触发)→
|
|
17
|
+
* 防抖全量重建模块图 → 入口文档变化则经 `BroadcastChannel` 广播新 blob URL,预览 iframe
|
|
18
|
+
* `location.replace` 自刷新(整页刷新式 HMR,组件级热替换留后续);构建 / 解析失败时生成
|
|
19
|
+
* 「红屏错误页」而不是静默白屏。
|
|
20
|
+
*
|
|
21
|
+
* 边界(响亮失败,不静默降级):
|
|
22
|
+
* - **循环依赖直接报错**(与 ide-widget-bundle 同口径):blob 链的改写发生在加载期,
|
|
23
|
+
* 环会让「先有 URL 才能写引用」无解,如实报告环路径链;
|
|
24
|
+
* - `.tsx` / `.jsx` 不支持(stripTypes 只擦类型标注,不转 JSX),明确报错;
|
|
25
|
+
* - Node 内建模块(`node:`)与 CJS-only 包不支持(解析器只认 ESM 入口),明确报错。
|
|
26
|
+
*/
|
|
27
|
+
import type { VirtualFileSystem } from './vfs';
|
|
28
|
+
/** SFC 编译器注入契约:`vue/compiler-sfc` 的适配(IDE 侧装配,本包零依赖不引 vue)。 */
|
|
29
|
+
export interface SfcCompiler {
|
|
30
|
+
/**
|
|
31
|
+
* 编译单个 `.vue` 文件。`script` 必须是纯 JS(可含 ESM import,供后续 blob 改写),
|
|
32
|
+
* `styles` 为已编译的 CSS 文本(逐条注入副作用模块)。
|
|
33
|
+
*/
|
|
34
|
+
(source: string, filename: string): {
|
|
35
|
+
script: string;
|
|
36
|
+
styles: string[];
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export interface ViteServerOptions {
|
|
40
|
+
/** dev server 根目录(VFS 绝对路径,缺省 '/')。 */
|
|
41
|
+
root?: string;
|
|
42
|
+
/** 入口文件名(相对 root,缺省 'index.html')。 */
|
|
43
|
+
entry?: string;
|
|
44
|
+
/** SFC 编译器(缺省时 `.vue` 模块报「未装配」)。 */
|
|
45
|
+
sfcCompiler?: SfcCompiler;
|
|
46
|
+
/** blob URL 工厂(Node 单测注入假实现)。 */
|
|
47
|
+
createObjectURL?: (blob: Blob) => string;
|
|
48
|
+
revokeObjectURL?: (url: string) => void;
|
|
49
|
+
}
|
|
50
|
+
/** dev server 句柄:url / root 对外只读,`touch` 驱动 HMR,`stop` 释放资源。 */
|
|
51
|
+
export interface ViteServer {
|
|
52
|
+
/** 当前入口文档的 blob URL(首次 `ready` 完成后有效)。 */
|
|
53
|
+
readonly url: string;
|
|
54
|
+
/** 虚拟端口(Vite 默认 5173,仅语义展示)。 */
|
|
55
|
+
readonly port: number;
|
|
56
|
+
/** root 的规范化绝对路径(幂等启动判定用)。 */
|
|
57
|
+
readonly root: string;
|
|
58
|
+
/** 首次构建完成(含错误文档——失败也是一次完成)。 */
|
|
59
|
+
readonly ready: Promise<void>;
|
|
60
|
+
/** 某路径发生变更:防抖全量重建,文档变化则广播 HMR。 */
|
|
61
|
+
touch(path: string): void;
|
|
62
|
+
/** 停止:撤销全部 blob URL、关闭 HMR 通道。 */
|
|
63
|
+
stop(): Promise<void>;
|
|
64
|
+
}
|
|
65
|
+
/** vite 构建期错误(红屏文档的 reason + message)。 */
|
|
66
|
+
export declare class ViteDevError extends Error {
|
|
67
|
+
readonly reason: string;
|
|
68
|
+
constructor(reason: string, message: string);
|
|
69
|
+
}
|
|
70
|
+
/** `vite` 命令端口(shell 的 `case 'vite'` 消费;`bootstrap` 装配实现)。 */
|
|
71
|
+
export interface ViteCommandPort {
|
|
72
|
+
/** `vite [dir]` / `vite dev [dir]`:启动(同根幂等复用,异根重启)。 */
|
|
73
|
+
start(args: readonly string[]): Promise<ViteCommandOutcome>;
|
|
74
|
+
/** `vite stop`:停止并释放。 */
|
|
75
|
+
stop(): Promise<ViteCommandOutcome>;
|
|
76
|
+
}
|
|
77
|
+
export interface ViteCommandOutcome {
|
|
78
|
+
code: number;
|
|
79
|
+
stdout: string;
|
|
80
|
+
}
|
|
81
|
+
/** 一次说明符命中:`start`/`end` 为含引号的原文区间(end 不含),改写按此切片替换。 */
|
|
82
|
+
export interface EsmSpecifierHit {
|
|
83
|
+
specifier: string;
|
|
84
|
+
start: number;
|
|
85
|
+
end: number;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* 扫描源码里的 ESM 模块说明符(静态 import / export…from / 动态 import())。
|
|
89
|
+
* 说明符是这些语句里唯一的字符串字面量(`from` 别名 / 对象键等场景的字符串前必有
|
|
90
|
+
* `=` `:` `,` `(` 等标点,天然不命中),因此「字符串 + 前一个 token」即可可靠判定。
|
|
91
|
+
* 模板串整体跳过(`${}` 里的动态 import 不在支持范围,见文件头边界注)。
|
|
92
|
+
*/
|
|
93
|
+
export declare function scanEsmSpecifiers(source: string): EsmSpecifierHit[];
|
|
94
|
+
export declare function createViteServer(vfs: VirtualFileSystem, options?: ViteServerOptions): ViteServer;
|
package/package.json
CHANGED
|
@@ -1,32 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adep/web-container",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"description": "adep 平台浏览器原生开发环境对外 SDK(FN-012):虚拟文件系统 + 进程/shell + JS 运行时适配接口 + npm-relay 客户端,对标 WebContainers API,Node 可测、浏览器可跑。",
|
|
8
|
-
"main": "./
|
|
9
|
-
"types": "./
|
|
8
|
+
"main": "./src/index.ts",
|
|
9
|
+
"types": "./src/index.ts",
|
|
10
10
|
"files": [
|
|
11
11
|
"dist"
|
|
12
12
|
],
|
|
13
|
-
"dependencies": {
|
|
14
|
-
"@adep/runtime": "0.1.1",
|
|
15
|
-
"@adep/types": "0.1.1"
|
|
16
|
-
},
|
|
17
13
|
"scripts": {
|
|
18
14
|
"test": "vitest run",
|
|
19
15
|
"build": "bun run ../../scripts/build-package.ts web-container",
|
|
20
16
|
"build:sdk": "pnpm exec esbuild src/index.ts --bundle --format=esm --platform=browser --outfile=dist/web-container.esm.js && pnpm exec esbuild src/index.ts --bundle --format=iife --global-name=AdepWebContainer --platform=browser --outfile=dist/web-container.iife.js"
|
|
21
17
|
},
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@adep/runtime": "0.2.0",
|
|
20
|
+
"@adep/types": "0.2.0"
|
|
21
|
+
},
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"main": "./dist/index.js",
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"default": "./dist/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./*": {
|
|
31
|
+
"types": "./dist/*.d.ts",
|
|
32
|
+
"default": "./dist/*.js"
|
|
33
|
+
}
|
|
30
34
|
}
|
|
31
|
-
}
|
|
32
|
-
|
|
35
|
+
},
|
|
36
|
+
"gitHead": "9c29cbb2a942afe4d4c7ae2987bcc229f6b99f9b"
|
|
37
|
+
}
|