@seanhogg/builderforce-webcontainers-core 2026.10.6 → 2026.10.8

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.
Files changed (184) hide show
  1. package/dist/archive.d.ts +13 -0
  2. package/dist/archive.d.ts.map +1 -0
  3. package/dist/archive.js +53 -0
  4. package/dist/archive.js.map +1 -0
  5. package/dist/devServer.d.ts +5 -0
  6. package/dist/devServer.d.ts.map +1 -1
  7. package/dist/devServer.js +11 -2
  8. package/dist/devServer.js.map +1 -1
  9. package/dist/html.d.ts +12 -3
  10. package/dist/html.d.ts.map +1 -1
  11. package/dist/html.js +31 -5
  12. package/dist/html.js.map +1 -1
  13. package/dist/index.d.ts +5 -1
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +3 -1
  16. package/dist/index.js.map +1 -1
  17. package/dist/installer/index.d.ts +2 -0
  18. package/dist/installer/index.d.ts.map +1 -1
  19. package/dist/installer/index.js +1 -0
  20. package/dist/installer/index.js.map +1 -1
  21. package/dist/installer/install.d.ts +3 -0
  22. package/dist/installer/install.d.ts.map +1 -1
  23. package/dist/installer/install.js +1 -1
  24. package/dist/installer/install.js.map +1 -1
  25. package/dist/installer/npmrc.d.ts +26 -0
  26. package/dist/installer/npmrc.d.ts.map +1 -0
  27. package/dist/installer/npmrc.js +55 -0
  28. package/dist/installer/npmrc.js.map +1 -0
  29. package/dist/installer/registry.d.ts +3 -0
  30. package/dist/installer/registry.d.ts.map +1 -1
  31. package/dist/installer/registry.js +10 -5
  32. package/dist/installer/registry.js.map +1 -1
  33. package/dist/node/http/client.d.ts +3 -1
  34. package/dist/node/http/client.d.ts.map +1 -1
  35. package/dist/node/http/client.js +74 -5
  36. package/dist/node/http/client.js.map +1 -1
  37. package/dist/node/http/index.d.ts.map +1 -1
  38. package/dist/node/http/index.js +2 -1
  39. package/dist/node/http/index.js.map +1 -1
  40. package/dist/node/http/messages.d.ts +87 -0
  41. package/dist/node/http/messages.d.ts.map +1 -0
  42. package/dist/node/http/messages.js +146 -0
  43. package/dist/node/http/messages.js.map +1 -0
  44. package/dist/node/http/server.d.ts +13 -98
  45. package/dist/node/http/server.d.ts.map +1 -1
  46. package/dist/node/http/server.js +34 -202
  47. package/dist/node/http/server.js.map +1 -1
  48. package/dist/node/http/serverResponse.d.ts +42 -0
  49. package/dist/node/http/serverResponse.d.ts.map +1 -0
  50. package/dist/node/http/serverResponse.js +89 -0
  51. package/dist/node/http/serverResponse.js.map +1 -0
  52. package/dist/node/http/upgradeSocket.d.ts +34 -0
  53. package/dist/node/http/upgradeSocket.d.ts.map +1 -0
  54. package/dist/node/http/upgradeSocket.js +73 -0
  55. package/dist/node/http/upgradeSocket.js.map +1 -0
  56. package/dist/node/runtime.js +2 -2
  57. package/dist/node/runtime.js.map +1 -1
  58. package/dist/previewBridge.d.ts +42 -0
  59. package/dist/previewBridge.d.ts.map +1 -0
  60. package/dist/previewBridge.js +192 -0
  61. package/dist/previewBridge.js.map +1 -0
  62. package/dist/shell/ast.d.ts +101 -0
  63. package/dist/shell/ast.d.ts.map +1 -0
  64. package/dist/shell/ast.js +7 -0
  65. package/dist/shell/ast.js.map +1 -0
  66. package/dist/shell/builtins.d.ts +14 -0
  67. package/dist/shell/builtins.d.ts.map +1 -1
  68. package/dist/shell/builtins.js +87 -7
  69. package/dist/shell/builtins.js.map +1 -1
  70. package/dist/shell/compound.d.ts +30 -0
  71. package/dist/shell/compound.d.ts.map +1 -0
  72. package/dist/shell/compound.js +73 -0
  73. package/dist/shell/compound.js.map +1 -0
  74. package/dist/shell/exec.d.ts +27 -6
  75. package/dist/shell/exec.d.ts.map +1 -1
  76. package/dist/shell/exec.js +127 -41
  77. package/dist/shell/exec.js.map +1 -1
  78. package/dist/shell/expand.d.ts +5 -1
  79. package/dist/shell/expand.d.ts.map +1 -1
  80. package/dist/shell/expand.js +7 -5
  81. package/dist/shell/expand.js.map +1 -1
  82. package/dist/shell/lineReader.d.ts +9 -0
  83. package/dist/shell/lineReader.d.ts.map +1 -0
  84. package/dist/shell/lineReader.js +42 -0
  85. package/dist/shell/lineReader.js.map +1 -0
  86. package/dist/shell/npm.d.ts.map +1 -1
  87. package/dist/shell/npm.js +5 -1
  88. package/dist/shell/npm.js.map +1 -1
  89. package/dist/shell/packageManagers.d.ts +20 -0
  90. package/dist/shell/packageManagers.d.ts.map +1 -0
  91. package/dist/shell/packageManagers.js +74 -0
  92. package/dist/shell/packageManagers.js.map +1 -0
  93. package/dist/shell/parse.d.ts +16 -66
  94. package/dist/shell/parse.d.ts.map +1 -1
  95. package/dist/shell/parse.js +244 -243
  96. package/dist/shell/parse.js.map +1 -1
  97. package/dist/shell/program.d.ts.map +1 -1
  98. package/dist/shell/program.js +2 -1
  99. package/dist/shell/program.js.map +1 -1
  100. package/dist/shell/testCommand.d.ts +9 -0
  101. package/dist/shell/testCommand.d.ts.map +1 -0
  102. package/dist/shell/testCommand.js +105 -0
  103. package/dist/shell/testCommand.js.map +1 -0
  104. package/dist/shell/tokenize.d.ts +25 -0
  105. package/dist/shell/tokenize.d.ts.map +1 -0
  106. package/dist/shell/tokenize.js +279 -0
  107. package/dist/shell/tokenize.js.map +1 -0
  108. package/dist/system/cookieJar.d.ts +59 -0
  109. package/dist/system/cookieJar.d.ts.map +1 -0
  110. package/dist/system/cookieJar.js +187 -0
  111. package/dist/system/cookieJar.js.map +1 -0
  112. package/dist/system/httpStream.d.ts +40 -0
  113. package/dist/system/httpStream.d.ts.map +1 -0
  114. package/dist/system/httpStream.js +156 -0
  115. package/dist/system/httpStream.js.map +1 -0
  116. package/dist/system/index.d.ts +9 -1
  117. package/dist/system/index.d.ts.map +1 -1
  118. package/dist/system/index.js +4 -0
  119. package/dist/system/index.js.map +1 -1
  120. package/dist/system/kernel.d.ts +10 -2
  121. package/dist/system/kernel.d.ts.map +1 -1
  122. package/dist/system/kernel.js +12 -3
  123. package/dist/system/kernel.js.map +1 -1
  124. package/dist/system/ports.d.ts +9 -4
  125. package/dist/system/ports.d.ts.map +1 -1
  126. package/dist/system/ports.js +21 -2
  127. package/dist/system/ports.js.map +1 -1
  128. package/dist/system/programs.d.ts +1 -1
  129. package/dist/system/programs.d.ts.map +1 -1
  130. package/dist/system/programs.js +2 -0
  131. package/dist/system/programs.js.map +1 -1
  132. package/dist/system/types.d.ts +36 -6
  133. package/dist/system/types.d.ts.map +1 -1
  134. package/dist/system/webSocketClient.d.ts +37 -0
  135. package/dist/system/webSocketClient.d.ts.map +1 -0
  136. package/dist/system/webSocketClient.js +152 -0
  137. package/dist/system/webSocketClient.js.map +1 -0
  138. package/dist/system/webSocketFrames.d.ts +39 -0
  139. package/dist/system/webSocketFrames.d.ts.map +1 -0
  140. package/dist/system/webSocketFrames.js +117 -0
  141. package/dist/system/webSocketFrames.js.map +1 -0
  142. package/dist/vfs.d.ts +16 -1
  143. package/dist/vfs.d.ts.map +1 -1
  144. package/dist/vfs.js +45 -3
  145. package/dist/vfs.js.map +1 -1
  146. package/package.json +1 -1
  147. package/src/archive.ts +63 -0
  148. package/src/devServer.ts +12 -2
  149. package/src/html.ts +34 -5
  150. package/src/index.ts +5 -1
  151. package/src/installer/index.ts +2 -0
  152. package/src/installer/install.ts +4 -1
  153. package/src/installer/npmrc.ts +69 -0
  154. package/src/installer/registry.ts +12 -5
  155. package/src/node/http/client.ts +69 -6
  156. package/src/node/http/index.ts +2 -1
  157. package/src/node/http/messages.ts +150 -0
  158. package/src/node/http/server.ts +37 -202
  159. package/src/node/http/serverResponse.ts +98 -0
  160. package/src/node/http/upgradeSocket.ts +79 -0
  161. package/src/node/runtime.ts +2 -2
  162. package/src/previewBridge.ts +194 -0
  163. package/src/shell/ast.ts +85 -0
  164. package/src/shell/builtins.ts +97 -7
  165. package/src/shell/compound.ts +89 -0
  166. package/src/shell/exec.ts +128 -40
  167. package/src/shell/expand.ts +8 -6
  168. package/src/shell/lineReader.ts +46 -0
  169. package/src/shell/npm.ts +5 -1
  170. package/src/shell/packageManagers.ts +75 -0
  171. package/src/shell/parse.ts +233 -236
  172. package/src/shell/program.ts +2 -1
  173. package/src/shell/testCommand.ts +105 -0
  174. package/src/shell/tokenize.ts +257 -0
  175. package/src/system/cookieJar.ts +187 -0
  176. package/src/system/httpStream.ts +168 -0
  177. package/src/system/index.ts +24 -1
  178. package/src/system/kernel.ts +16 -4
  179. package/src/system/ports.ts +23 -4
  180. package/src/system/programs.ts +3 -1
  181. package/src/system/types.ts +40 -6
  182. package/src/system/webSocketClient.ts +177 -0
  183. package/src/system/webSocketFrames.ts +118 -0
  184. package/src/vfs.ts +46 -3
@@ -1,9 +1,11 @@
1
+ import { bufferResponse, createChannelPair } from './httpStream.js';
1
2
  const EPHEMERAL_START = 49152;
2
3
  export class PortRegistry {
3
4
  handlers = new Map();
5
+ upgrades = new Map();
4
6
  listeners = new Set();
5
7
  nextEphemeral = EPHEMERAL_START;
6
- listen(port, handler) {
8
+ listen(port, handler, upgrade) {
7
9
  let actual = port;
8
10
  if (!actual) {
9
11
  while (this.handlers.has(this.nextEphemeral))
@@ -14,6 +16,8 @@ export class PortRegistry {
14
16
  throw Object.assign(new Error(`listen EADDRINUSE: address already in use :::${actual}`), { code: 'EADDRINUSE', errno: -98, syscall: 'listen', address: '::', port: actual });
15
17
  }
16
18
  this.handlers.set(actual, handler);
19
+ if (upgrade)
20
+ this.upgrades.set(actual, upgrade);
17
21
  this.emit({ type: 'open', port: actual });
18
22
  let open = true;
19
23
  return {
@@ -23,6 +27,7 @@ export class PortRegistry {
23
27
  return;
24
28
  open = false;
25
29
  this.handlers.delete(actual);
30
+ this.upgrades.delete(actual);
26
31
  this.emit({ type: 'close', port: actual });
27
32
  },
28
33
  };
@@ -33,11 +38,25 @@ export class PortRegistry {
33
38
  ports() {
34
39
  return [...this.handlers.keys()].sort((a, b) => a - b);
35
40
  }
36
- /** Dispatch to the server on `port`; undefined when nothing listens there. */
41
+ /** Dispatch to the server on `port`; resolves with the head as soon as it is written, the body streaming. Undefined when nothing listens there. */
37
42
  async request(port, request) {
38
43
  const handler = this.handlers.get(port);
39
44
  return handler ? handler(request) : undefined;
40
45
  }
46
+ /** {@link request}, waiting for the whole body. */
47
+ async requestBuffered(port, request) {
48
+ const response = await this.request(port, request);
49
+ return response && bufferResponse(response);
50
+ }
51
+ /** Open an upgraded connection to the server on `port`; returns the client end, or undefined when nothing there takes upgrades. */
52
+ upgrade(port, request) {
53
+ const upgrade = this.upgrades.get(port);
54
+ if (!upgrade)
55
+ return undefined;
56
+ const [client, server] = createChannelPair();
57
+ upgrade(request, server);
58
+ return client;
59
+ }
41
60
  watch(listener) {
42
61
  this.listeners.add(listener);
43
62
  return () => this.listeners.delete(listener);
@@ -1 +1 @@
1
- {"version":3,"file":"ports.js","sourceRoot":"","sources":["../../src/system/ports.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ports.js","sourceRoot":"","sources":["../../src/system/ports.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
  * The command table: every program a process can be. Hosts start from
3
3
  * `defaultPrograms()` and may add or replace entries (a custom `git`, say).
4
4
  *
5
- * `npm`/`npx` live in the shell (they run scripts through it), so spawning them
5
+ * `npm`/`npx`/`pnpm`/`yarn` live in the shell (they run scripts through it), so spawning them
6
6
  * directly runs them through a one-shot shell; coreutils run standalone.
7
7
  */
8
8
  import type { Program } from './types.js';
@@ -1 +1 @@
1
- {"version":3,"file":"programs.d.ts","sourceRoot":"","sources":["../../src/system/programs.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAY1C,wBAAgB,eAAe,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAWzD"}
1
+ {"version":3,"file":"programs.d.ts","sourceRoot":"","sources":["../../src/system/programs.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAY1C,wBAAgB,eAAe,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAazD"}
@@ -14,6 +14,8 @@ export function defaultPrograms() {
14
14
  bash: shellProgram,
15
15
  npm: viaShell('npm'),
16
16
  npx: viaShell('npx'),
17
+ pnpm: viaShell('pnpm'),
18
+ yarn: viaShell('yarn'),
17
19
  };
18
20
  for (const [name, command] of Object.entries(COREUTILS))
19
21
  programs[name] = asProgram(command, name);
@@ -1 +1 @@
1
- {"version":3,"file":"programs.js","sourceRoot":"","sources":["../../src/system/programs.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,MAAM,KAAK,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;AAExG,SAAS,QAAQ,CAAC,OAAe;IAC/B,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,EAAE,GAAG,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;AACtG,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,QAAQ,GAA4B;QACxC,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,YAAY;QAClB,EAAE,EAAE,YAAY;QAChB,IAAI,EAAE,YAAY;QAClB,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAC;QACpB,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAC;KACrB,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC;QAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACnG,OAAO,QAAQ,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"programs.js","sourceRoot":"","sources":["../../src/system/programs.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,MAAM,KAAK,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;AAExG,SAAS,QAAQ,CAAC,OAAe;IAC/B,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,EAAE,GAAG,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;AACtG,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,QAAQ,GAA4B;QACxC,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,YAAY;QAClB,EAAE,EAAE,YAAY;QAChB,IAAI,EAAE,YAAY;QAClB,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAC;QACpB,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAC;QACpB,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC;QACtB,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC;KACvB,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC;QAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACnG,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -48,25 +48,55 @@ export interface HttpRequestData {
48
48
  headers: Record<string, string>;
49
49
  body: Uint8Array | null;
50
50
  }
51
- export interface HttpResponseData {
51
+ export interface HttpResponseHead {
52
52
  status: number;
53
53
  statusText?: string;
54
54
  headers: Record<string, string | string[]>;
55
+ }
56
+ /** A whole response, body buffered (`Kernel.request`, tests). */
57
+ export interface HttpResponseData extends HttpResponseHead {
55
58
  body: Uint8Array;
56
59
  }
57
- export type HttpHandler = (request: HttpRequestData) => Promise<HttpResponseData>;
60
+ /**
61
+ * A response as the server produces it: the head as soon as it is written, then
62
+ * the body chunk by chunk (Server-Sent Events, chunked progress). Cancelling the
63
+ * body hangs up, which the server sees as the client closing the connection.
64
+ */
65
+ export interface HttpStreamResponse extends HttpResponseHead {
66
+ body: ReadableStream<Uint8Array>;
67
+ }
68
+ export type HttpHandler = (request: HttpRequestData) => Promise<HttpStreamResponse>;
69
+ /**
70
+ * One end of a raw byte pipe — an upgraded connection. The server end carries
71
+ * whatever the server writes (a WebSocket server writes its `101` reply and then
72
+ * frames), so packages like `ws` run their own framing over it unchanged.
73
+ */
74
+ export interface ByteChannel {
75
+ send(data: Uint8Array): void;
76
+ /** Hang up; the other end hears `onClose`. */
77
+ close(): void;
78
+ onData(listener: (data: Uint8Array) => void): () => void;
79
+ /** The other end hung up. */
80
+ onClose(listener: () => void): () => void;
81
+ readonly closed: boolean;
82
+ }
83
+ /** Take over a connection a client asked to upgrade (`Upgrade: websocket`); `socket` is the server end. */
84
+ export type UpgradeHandler = (request: HttpRequestData, socket: ByteChannel) => void;
58
85
  export interface System {
59
86
  fs: VirtualFileSystem;
60
87
  /** Outbound network (registry, `http.request`, `fetch`). */
61
88
  fetch(input: string, init?: RequestInit): Promise<Response>;
62
89
  spawn(command: string, args: string[], options?: ProcessOptions): ChildHandle;
63
- /** Register a virtual server; throws `EADDRINUSE`. Port 0 picks a free one. Returns the port and an unlisten. */
64
- listen(port: number, handler: HttpHandler): {
90
+ /**
91
+ * Register a virtual server; throws `EADDRINUSE`. Port 0 picks a free one.
92
+ * `upgrade` takes over connections that ask to upgrade (WebSockets). Returns the port and an unlisten.
93
+ */
94
+ listen(port: number, handler: HttpHandler, upgrade?: UpgradeHandler): {
65
95
  port: number;
66
96
  close(): void;
67
97
  };
68
- /** Send a request to a virtual server in this runtime (`http.get('http://localhost:3000')`); undefined when nothing listens. */
69
- loopback(port: number, request: HttpRequestData): Promise<HttpResponseData | undefined>;
98
+ /** Send a request to a virtual server in this runtime (`http.get('http://localhost:3000')`); undefined when nothing listens. The body streams. */
99
+ loopback(port: number, request: HttpRequestData): Promise<HttpStreamResponse | undefined>;
70
100
  /** Where a browser reaches a server on `port` (the preview URL), if known. */
71
101
  serverUrl(port: number): string | undefined;
72
102
  /** Tell the host a server is reachable without opening a port; used by the dev-server handoff. */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/system/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/system/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * The client end of a WebSocket to a virtual server, over an upgraded
3
+ * {@link ByteChannel}: sends the opening handshake as an HTTP request, checks
4
+ * the server's `101` reply (whatever wrote it — `ws`, socket.io's engine, a
5
+ * hand-written `upgrade` handler), then speaks RFC 6455 frames. The host page
6
+ * uses it to carry a preview's `new WebSocket('ws://localhost:3000')`.
7
+ */
8
+ import type { ByteChannel, HttpRequestData } from './types.js';
9
+ export interface WebSocketCloseInfo {
10
+ code: number;
11
+ reason: string;
12
+ wasClean: boolean;
13
+ }
14
+ export interface WebSocketConnection {
15
+ /** 0 connecting, 1 open, 2 closing, 3 closed — `WebSocket.readyState`'s values. */
16
+ readonly readyState: number;
17
+ onOpen(listener: (info: {
18
+ protocol: string;
19
+ }) => void): () => void;
20
+ onMessage(listener: (data: string | Uint8Array) => void): () => void;
21
+ /** Fires once; `wasClean` false and code 1006 when the connection dropped or the handshake failed. */
22
+ onClose(listener: (info: WebSocketCloseInfo) => void): () => void;
23
+ send(data: string | Uint8Array): void;
24
+ close(code?: number, reason?: string): void;
25
+ }
26
+ export interface WebSocketConnectOptions {
27
+ /** Path and query on the server (`/socket?room=1`). */
28
+ path: string;
29
+ protocols?: string[];
30
+ /** Extra request headers (`origin`, `cookie`). */
31
+ headers?: Record<string, string>;
32
+ /** Give up on a close handshake the server never answers. Default 5000ms. */
33
+ closeTimeoutMs?: number;
34
+ }
35
+ /** Open a WebSocket through `upgrade` (`kernel.upgrade` / `processHost.upgrade` bound to a port). */
36
+ export declare function connectWebSocket(upgrade: (request: HttpRequestData) => ByteChannel | undefined, options: WebSocketConnectOptions): WebSocketConnection;
37
+ //# sourceMappingURL=webSocketClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webSocketClient.d.ts","sourceRoot":"","sources":["../../src/system/webSocketClient.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAG/D,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,mFAAmF;IACnF,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACnE,SAAS,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACrE,sGAAsG;IACtG,OAAO,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAClE,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC;IACtC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7C;AAED,MAAM,WAAW,uBAAuB;IACtC,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,6EAA6E;IAC7E,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAsBD,qGAAqG;AACrG,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,WAAW,GAAG,SAAS,EAAE,OAAO,EAAE,uBAAuB,GAAG,mBAAmB,CAuGtJ"}
@@ -0,0 +1,152 @@
1
+ import { FrameDecoder, Opcode, decodeClosePayload, encodeClosePayload, encodeFrame, webSocketAccept, webSocketKey } from './webSocketFrames.js';
2
+ const HEAD_END = [13, 10, 13, 10];
3
+ function indexOfHeadEnd(bytes) {
4
+ outer: for (let i = 0; i + 3 < bytes.length; i++) {
5
+ for (let j = 0; j < 4; j++)
6
+ if (bytes[i + j] !== HEAD_END[j])
7
+ continue outer;
8
+ return i;
9
+ }
10
+ return -1;
11
+ }
12
+ function parseHead(text) {
13
+ const [statusLine = '', ...lines] = text.split('\r\n');
14
+ const headers = {};
15
+ for (const line of lines) {
16
+ const colon = line.indexOf(':');
17
+ if (colon > 0)
18
+ headers[line.slice(0, colon).trim().toLowerCase()] = line.slice(colon + 1).trim();
19
+ }
20
+ return { status: Number(/^HTTP\/\d(?:\.\d)?\s+(\d{3})/.exec(statusLine)?.[1] ?? 0), headers };
21
+ }
22
+ /** Open a WebSocket through `upgrade` (`kernel.upgrade` / `processHost.upgrade` bound to a port). */
23
+ export function connectWebSocket(upgrade, options) {
24
+ const opens = new Set();
25
+ const messages = new Set();
26
+ const closes = new Set();
27
+ const key = webSocketKey();
28
+ const decoder = new FrameDecoder();
29
+ let state = 0;
30
+ let head = new Uint8Array(0);
31
+ let fragments = [];
32
+ let fragmentOpcode = 0;
33
+ let closeSent = false;
34
+ let closeTimer;
35
+ const headers = {
36
+ ...options.headers,
37
+ connection: 'Upgrade',
38
+ upgrade: 'websocket',
39
+ 'sec-websocket-version': '13',
40
+ 'sec-websocket-key': key,
41
+ };
42
+ if (options.protocols?.length)
43
+ headers['sec-websocket-protocol'] = options.protocols.join(', ');
44
+ const channel = upgrade({ method: 'GET', url: options.path, headers, body: null });
45
+ const finish = (info) => {
46
+ if (state === 3)
47
+ return;
48
+ state = 3;
49
+ clearTimeout(closeTimer);
50
+ channel?.close();
51
+ for (const listener of closes)
52
+ listener(info);
53
+ };
54
+ const fail = () => finish({ code: 1006, reason: '', wasClean: false });
55
+ const sendFrame = (opcode, payload) => channel?.send(encodeFrame(opcode, payload, { mask: true }));
56
+ const onFrame = (opcode, fin, payload) => {
57
+ if (opcode === Opcode.ping)
58
+ return sendFrame(Opcode.pong, payload);
59
+ if (opcode === Opcode.pong)
60
+ return;
61
+ if (opcode === Opcode.close) {
62
+ const { code, reason } = decodeClosePayload(payload);
63
+ if (!closeSent) {
64
+ closeSent = true;
65
+ sendFrame(Opcode.close, code === 1005 ? new Uint8Array() : encodeClosePayload(code));
66
+ }
67
+ return finish({ code, reason, wasClean: true });
68
+ }
69
+ if (opcode !== Opcode.continuation) {
70
+ fragmentOpcode = opcode;
71
+ fragments = [];
72
+ }
73
+ fragments.push(payload);
74
+ if (!fin)
75
+ return;
76
+ const whole = fragments.length === 1 ? fragments[0] : joinChunks(fragments);
77
+ fragments = [];
78
+ const data = fragmentOpcode === Opcode.text ? new TextDecoder().decode(whole) : whole;
79
+ for (const listener of messages)
80
+ listener(data);
81
+ };
82
+ const onBytes = (bytes) => {
83
+ if (state === 3)
84
+ return;
85
+ let rest = bytes;
86
+ if (state === 0) {
87
+ head = joinChunks([head, bytes]);
88
+ const end = indexOfHeadEnd(head);
89
+ if (end < 0)
90
+ return;
91
+ const reply = parseHead(new TextDecoder().decode(head.subarray(0, end)));
92
+ rest = head.subarray(end + 4);
93
+ if (reply.status !== 101 || reply.headers['sec-websocket-accept'] !== webSocketAccept(key))
94
+ return fail();
95
+ state = 1;
96
+ const protocol = reply.headers['sec-websocket-protocol'] ?? '';
97
+ for (const listener of opens)
98
+ listener({ protocol });
99
+ }
100
+ for (const frame of decoder.push(rest)) {
101
+ onFrame(frame.opcode, frame.fin, frame.payload);
102
+ if (state === 3)
103
+ return;
104
+ }
105
+ };
106
+ if (!channel)
107
+ queueMicrotask(fail);
108
+ else {
109
+ channel.onData(onBytes);
110
+ channel.onClose(fail);
111
+ }
112
+ return {
113
+ get readyState() {
114
+ return state;
115
+ },
116
+ onOpen: (listener) => subscribe(opens, listener),
117
+ onMessage: (listener) => subscribe(messages, listener),
118
+ onClose: (listener) => subscribe(closes, listener),
119
+ send(data) {
120
+ if (state !== 1)
121
+ return;
122
+ if (typeof data === 'string')
123
+ sendFrame(Opcode.text, new TextEncoder().encode(data));
124
+ else
125
+ sendFrame(Opcode.binary, data);
126
+ },
127
+ close(code, reason) {
128
+ if (state === 0)
129
+ return fail();
130
+ if (state !== 1)
131
+ return;
132
+ state = 2;
133
+ closeSent = true;
134
+ sendFrame(Opcode.close, encodeClosePayload(code ?? 1000, reason));
135
+ closeTimer = setTimeout(fail, options.closeTimeoutMs ?? 5000);
136
+ },
137
+ };
138
+ }
139
+ function subscribe(set, listener) {
140
+ set.add(listener);
141
+ return () => set.delete(listener);
142
+ }
143
+ function joinChunks(chunks) {
144
+ const out = new Uint8Array(chunks.reduce((n, c) => n + c.byteLength, 0));
145
+ let offset = 0;
146
+ for (const chunk of chunks) {
147
+ out.set(chunk, offset);
148
+ offset += chunk.byteLength;
149
+ }
150
+ return out;
151
+ }
152
+ //# sourceMappingURL=webSocketClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webSocketClient.js","sourceRoot":"","sources":["../../src/system/webSocketClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ export declare const WEBSOCKET_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
2
+ export declare const Opcode: {
3
+ readonly continuation: 0;
4
+ readonly text: 1;
5
+ readonly binary: 2;
6
+ readonly close: 8;
7
+ readonly ping: 9;
8
+ readonly pong: 10;
9
+ };
10
+ export interface WebSocketFrame {
11
+ fin: boolean;
12
+ opcode: number;
13
+ /** Unmasked. */
14
+ payload: Uint8Array;
15
+ }
16
+ export declare function bytesToBase64(bytes: Uint8Array): string;
17
+ /** `Sec-WebSocket-Accept` for a client's `Sec-WebSocket-Key`. */
18
+ export declare function webSocketAccept(key: string): string;
19
+ /** A fresh `Sec-WebSocket-Key` (16 random bytes, base64). */
20
+ export declare function webSocketKey(): string;
21
+ /** One frame. Clients must mask (`mask: true` picks a random key); servers must not. */
22
+ export declare function encodeFrame(opcode: number, payload: Uint8Array, options?: {
23
+ mask?: boolean | Uint8Array;
24
+ fin?: boolean;
25
+ }): Uint8Array;
26
+ /** A close frame's payload: the status code and a UTF-8 reason. */
27
+ export declare function encodeClosePayload(code?: number, reason?: string): Uint8Array;
28
+ /** Status 1005 ("no status received") when the payload is empty. */
29
+ export declare function decodeClosePayload(payload: Uint8Array): {
30
+ code: number;
31
+ reason: string;
32
+ };
33
+ /** Splits a byte stream into frames, whatever the chunking. */
34
+ export declare class FrameDecoder {
35
+ private buffer;
36
+ push(bytes: Uint8Array): WebSocketFrame[];
37
+ private next;
38
+ }
39
+ //# sourceMappingURL=webSocketFrames.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webSocketFrames.d.ts","sourceRoot":"","sources":["../../src/system/webSocketFrames.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,cAAc,yCAAyC,CAAC;AAErE,eAAO,MAAM,MAAM;;;;;;;CAA2F,CAAC;AAE/G,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB;IAChB,OAAO,EAAE,UAAU,CAAC;CACrB;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAIvD;AAED,iEAAiE;AACjE,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,6DAA6D;AAC7D,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wFAAwF;AACxF,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,UAAU,CAmBzI;AAED,mEAAmE;AACnE,wBAAgB,kBAAkB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,SAAK,GAAG,UAAU,CAOzE;AAED,oEAAoE;AACpE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAGxF;AAED,+DAA+D;AAC/D,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAqB;IAEnC,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,cAAc,EAAE;IAezC,OAAO,CAAC,IAAI;CAyBb"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * The WebSocket wire format (RFC 6455): the opening handshake's accept key and
3
+ * frame encoding/decoding. Runtime-agnostic, so the same codec drives the
4
+ * client end in the host page (bridging a preview's `WebSocket`) and tests that
5
+ * speak to a server's `upgrade` handler byte for byte.
6
+ */
7
+ import { hashAlgorithm } from '../node/hashes.js';
8
+ export const WEBSOCKET_GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
9
+ export const Opcode = { continuation: 0x0, text: 0x1, binary: 0x2, close: 0x8, ping: 0x9, pong: 0xa };
10
+ export function bytesToBase64(bytes) {
11
+ let binary = '';
12
+ for (let i = 0; i < bytes.length; i++)
13
+ binary += String.fromCharCode(bytes[i]);
14
+ return btoa(binary);
15
+ }
16
+ /** `Sec-WebSocket-Accept` for a client's `Sec-WebSocket-Key`. */
17
+ export function webSocketAccept(key) {
18
+ return bytesToBase64(hashAlgorithm('sha1').digest(new TextEncoder().encode(key + WEBSOCKET_GUID)));
19
+ }
20
+ /** A fresh `Sec-WebSocket-Key` (16 random bytes, base64). */
21
+ export function webSocketKey() {
22
+ return bytesToBase64(globalThis.crypto.getRandomValues(new Uint8Array(16)));
23
+ }
24
+ /** One frame. Clients must mask (`mask: true` picks a random key); servers must not. */
25
+ export function encodeFrame(opcode, payload, options = {}) {
26
+ const length = payload.byteLength;
27
+ const maskKey = options.mask === true ? globalThis.crypto.getRandomValues(new Uint8Array(4)) : options.mask || undefined;
28
+ const extended = length < 126 ? 0 : length <= 0xffff ? 2 : 8;
29
+ const headerLength = 2 + extended + (maskKey ? 4 : 0);
30
+ const frame = new Uint8Array(headerLength + length);
31
+ const view = new DataView(frame.buffer);
32
+ frame[0] = (options.fin === false ? 0 : 0x80) | (opcode & 0x0f);
33
+ frame[1] = (maskKey ? 0x80 : 0) | (extended === 0 ? length : extended === 2 ? 126 : 127);
34
+ if (extended === 2)
35
+ view.setUint16(2, length);
36
+ else if (extended === 8) {
37
+ view.setUint32(2, Math.floor(length / 2 ** 32));
38
+ view.setUint32(6, length >>> 0);
39
+ }
40
+ if (maskKey) {
41
+ frame.set(maskKey, 2 + extended);
42
+ for (let i = 0; i < length; i++)
43
+ frame[headerLength + i] = payload[i] ^ maskKey[i & 3];
44
+ }
45
+ else
46
+ frame.set(payload, headerLength);
47
+ return frame;
48
+ }
49
+ /** A close frame's payload: the status code and a UTF-8 reason. */
50
+ export function encodeClosePayload(code, reason = '') {
51
+ if (code === undefined)
52
+ return new Uint8Array();
53
+ const text = new TextEncoder().encode(reason);
54
+ const out = new Uint8Array(2 + text.byteLength);
55
+ new DataView(out.buffer).setUint16(0, code);
56
+ out.set(text, 2);
57
+ return out;
58
+ }
59
+ /** Status 1005 ("no status received") when the payload is empty. */
60
+ export function decodeClosePayload(payload) {
61
+ if (payload.byteLength < 2)
62
+ return { code: 1005, reason: '' };
63
+ return { code: new DataView(payload.buffer, payload.byteOffset, payload.byteLength).getUint16(0), reason: new TextDecoder().decode(payload.subarray(2)) };
64
+ }
65
+ /** Splits a byte stream into frames, whatever the chunking. */
66
+ export class FrameDecoder {
67
+ buffer = new Uint8Array(0);
68
+ push(bytes) {
69
+ if (bytes.byteLength) {
70
+ const joined = new Uint8Array(this.buffer.byteLength + bytes.byteLength);
71
+ joined.set(this.buffer);
72
+ joined.set(bytes, this.buffer.byteLength);
73
+ this.buffer = joined;
74
+ }
75
+ const frames = [];
76
+ for (;;) {
77
+ const frame = this.next();
78
+ if (!frame)
79
+ return frames;
80
+ frames.push(frame);
81
+ }
82
+ }
83
+ next() {
84
+ const b = this.buffer;
85
+ if (b.byteLength < 2)
86
+ return undefined;
87
+ const masked = (b[1] & 0x80) !== 0;
88
+ let length = b[1] & 0x7f;
89
+ let offset = 2;
90
+ const view = new DataView(b.buffer, b.byteOffset, b.byteLength);
91
+ if (length === 126) {
92
+ if (b.byteLength < 4)
93
+ return undefined;
94
+ length = view.getUint16(2);
95
+ offset = 4;
96
+ }
97
+ else if (length === 127) {
98
+ if (b.byteLength < 10)
99
+ return undefined;
100
+ length = view.getUint32(2) * 2 ** 32 + view.getUint32(6);
101
+ offset = 10;
102
+ }
103
+ const maskKey = masked ? b.subarray(offset, offset + 4) : undefined;
104
+ if (masked)
105
+ offset += 4;
106
+ if (b.byteLength < offset + length)
107
+ return undefined;
108
+ const payload = b.slice(offset, offset + length);
109
+ if (maskKey)
110
+ for (let i = 0; i < payload.length; i++)
111
+ payload[i] = payload[i] ^ maskKey[i & 3];
112
+ const frame = { fin: (b[0] & 0x80) !== 0, opcode: b[0] & 0x0f, payload };
113
+ this.buffer = b.slice(offset + length);
114
+ return frame;
115
+ }
116
+ }
117
+ //# sourceMappingURL=webSocketFrames.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webSocketFrames.js","sourceRoot":"","sources":["../../src/system/webSocketFrames.ts"],"names":[],"mappings":"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"}
package/dist/vfs.d.ts CHANGED
@@ -9,6 +9,10 @@ export type FlatFiles = Record<string, FileContent>;
9
9
  export interface FileTree {
10
10
  [name: string]: FileContent | FileTree;
11
11
  }
12
+ export interface DirectoryEntry {
13
+ name: string;
14
+ kind: 'file' | 'directory';
15
+ }
12
16
  export interface FsChange {
13
17
  /** `mkdir` is an explicitly created (possibly empty) directory. */
14
18
  type: 'write' | 'remove' | 'mkdir';
@@ -49,6 +53,14 @@ export declare class VirtualFileSystem {
49
53
  mkdir(path: string): void;
50
54
  /** Direct children of a directory (files and sub-directories), sorted. */
51
55
  readdir(path: string): string[];
56
+ /** Direct children with their kind, sorted by name — `readdir` for callers that render a tree. */
57
+ entries(path: string): DirectoryEntry[];
58
+ /**
59
+ * Move a file or a directory (with everything under it). Throws when `from` is
60
+ * missing or `to` already exists. Watchers see the old paths removed and the
61
+ * new ones written, which is what every consumer (dev server, process sync) needs.
62
+ */
63
+ rename(from: string, to: string): void;
52
64
  /** Every file path, sorted. */
53
65
  list(): string[];
54
66
  /** Directories created explicitly with `mkdir` — what `list()` cannot reproduce. */
@@ -63,7 +75,10 @@ export declare class VirtualFileSystem {
63
75
  writeTree(files: FileTree, at?: string): void;
64
76
  /** Flat snapshot keyed without the leading slash (`src/main.tsx`). */
65
77
  toFlat(): FlatFiles;
66
- watch(listener: (change: FsChange) => void): () => void;
78
+ /** Every change, or with `under` only changes at or below that path. */
79
+ watch(listener: (change: FsChange) => void, options?: {
80
+ under?: string;
81
+ }): () => void;
67
82
  private removeFile;
68
83
  /** Register `key` under its parent, creating implicit ancestors as needed. */
69
84
  private link;
package/dist/vfs.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"vfs.d.ts","sourceRoot":"","sources":["../src/vfs.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,UAAU,CAAC;AAE9C,+DAA+D;AAC/D,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAEpD;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;CACxC;AAED,MAAM,WAAW,QAAQ;IACvB,mEAAmE;IACnE,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,6FAA6F;IAC7F,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAID;;;;;;;;;;;;GAYG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkC;IACxD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6B;IACtD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;IACpD,kEAAkE;IAClE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoD;IAC7E,sEAAsE;IACtE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyC;IACnE,OAAO,CAAC,KAAK,CAAK;IAElB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,GAAG,IAAI;IAWpD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAI/C,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAM1C,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI7B,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIlC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI7B,4EAA4E;IAC5E,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAWzB,0EAA0E;IAC1E,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE;IAI/B,+BAA+B;IAC/B,IAAI,IAAI,MAAM,EAAE;IAIhB,oFAAoF;IACpF,mBAAmB,IAAI,MAAM,EAAE;IAI/B,6DAA6D;IAC7D,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IActB,4EAA4E;IAC5E,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIzC,2EAA2E;IAC3E,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIvC,mHAAmH;IACnH,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,SAAM,GAAG,IAAI;IAW1C,sEAAsE;IACtE,MAAM,IAAI,SAAS;IAMnB,KAAK,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,QAAQ,KAAK,IAAI,GAAG,MAAM,IAAI;IAKvD,OAAO,CAAC,UAAU;IAQlB,8EAA8E;IAC9E,OAAO,CAAC,IAAI;IAMZ,OAAO,CAAC,SAAS;IAOjB,2EAA2E;IAC3E,OAAO,CAAC,MAAM;IAQd,OAAO,CAAC,SAAS;IAKjB,OAAO,CAAC,IAAI;CAGb"}
1
+ {"version":3,"file":"vfs.d.ts","sourceRoot":"","sources":["../src/vfs.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,UAAU,CAAC;AAE9C,+DAA+D;AAC/D,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAEpD;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;CACxC;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;CAC5B;AAED,MAAM,WAAW,QAAQ;IACvB,mEAAmE;IACnE,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,6FAA6F;IAC7F,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAID;;;;;;;;;;;;GAYG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkC;IACxD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6B;IACtD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;IACpD,kEAAkE;IAClE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoD;IAC7E,sEAAsE;IACtE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyC;IACnE,OAAO,CAAC,KAAK,CAAK;IAElB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,GAAG,IAAI;IAWpD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAI/C,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAM1C,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI7B,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIlC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI7B,4EAA4E;IAC5E,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAWzB,0EAA0E;IAC1E,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE;IAI/B,kGAAkG;IAClG,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE;IAKvC;;;;OAIG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI;IAsBtC,+BAA+B;IAC/B,IAAI,IAAI,MAAM,EAAE;IAIhB,oFAAoF;IACpF,mBAAmB,IAAI,MAAM,EAAE;IAI/B,6DAA6D;IAC7D,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IActB,4EAA4E;IAC5E,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIzC,2EAA2E;IAC3E,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIvC,mHAAmH;IACnH,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,SAAM,GAAG,IAAI;IAW1C,sEAAsE;IACtE,MAAM,IAAI,SAAS;IAMnB,wEAAwE;IACxE,KAAK,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,QAAQ,KAAK,IAAI,EAAE,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,MAAM,IAAI;IASzF,OAAO,CAAC,UAAU;IAQlB,8EAA8E;IAC9E,OAAO,CAAC,IAAI;IAMZ,OAAO,CAAC,SAAS;IAOjB,2EAA2E;IAC3E,OAAO,CAAC,MAAM;IAQd,OAAO,CAAC,SAAS;IAKjB,OAAO,CAAC,IAAI;CAGb"}