@seanhogg/builderforce-webcontainers-core 2026.10.5 → 2026.10.7

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 (114) hide show
  1. package/README.md +1 -1
  2. package/dist/archive.d.ts +11 -0
  3. package/dist/archive.d.ts.map +1 -0
  4. package/dist/archive.js +51 -0
  5. package/dist/archive.js.map +1 -0
  6. package/dist/build.d.ts +3 -3
  7. package/dist/build.d.ts.map +1 -1
  8. package/dist/build.js +1 -1
  9. package/dist/build.js.map +1 -1
  10. package/dist/check/typecheck.d.ts +2 -2
  11. package/dist/check/typecheck.d.ts.map +1 -1
  12. package/dist/check/typecheck.js +1 -1
  13. package/dist/check/typecheck.js.map +1 -1
  14. package/dist/devServer.d.ts +5 -0
  15. package/dist/devServer.d.ts.map +1 -1
  16. package/dist/devServer.js +11 -2
  17. package/dist/devServer.js.map +1 -1
  18. package/dist/html.d.ts +10 -3
  19. package/dist/html.d.ts.map +1 -1
  20. package/dist/html.js +29 -5
  21. package/dist/html.js.map +1 -1
  22. package/dist/index.d.ts +5 -2
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +2 -1
  25. package/dist/index.js.map +1 -1
  26. package/dist/installer/index.d.ts +2 -0
  27. package/dist/installer/index.d.ts.map +1 -1
  28. package/dist/installer/index.js +1 -0
  29. package/dist/installer/index.js.map +1 -1
  30. package/dist/installer/install.d.ts +3 -0
  31. package/dist/installer/install.d.ts.map +1 -1
  32. package/dist/installer/install.js +1 -1
  33. package/dist/installer/install.js.map +1 -1
  34. package/dist/installer/npmrc.d.ts +26 -0
  35. package/dist/installer/npmrc.d.ts.map +1 -0
  36. package/dist/installer/npmrc.js +55 -0
  37. package/dist/installer/npmrc.js.map +1 -0
  38. package/dist/installer/registry.d.ts +3 -0
  39. package/dist/installer/registry.d.ts.map +1 -1
  40. package/dist/installer/registry.js +10 -5
  41. package/dist/installer/registry.js.map +1 -1
  42. package/dist/node/childProcess.js +1 -1
  43. package/dist/node/childProcess.js.map +1 -1
  44. package/dist/node/misc.js +1 -1
  45. package/dist/node/misc.js.map +1 -1
  46. package/dist/shell/builtins.d.ts.map +1 -1
  47. package/dist/shell/builtins.js +2 -2
  48. package/dist/shell/builtins.js.map +1 -1
  49. package/dist/shell/devHandoff.d.ts +1 -1
  50. package/dist/shell/exec.js +4 -4
  51. package/dist/shell/exec.js.map +1 -1
  52. package/dist/shell/expand.js +1 -1
  53. package/dist/shell/expand.js.map +1 -1
  54. package/dist/shell/npm.d.ts.map +1 -1
  55. package/dist/shell/npm.js +5 -1
  56. package/dist/shell/npm.js.map +1 -1
  57. package/dist/shell/program.d.ts +1 -1
  58. package/dist/shell/program.js +3 -3
  59. package/dist/shell/program.js.map +1 -1
  60. package/dist/system/commands.d.ts +4 -4
  61. package/dist/system/commands.d.ts.map +1 -1
  62. package/dist/system/commands.js +3 -3
  63. package/dist/system/commands.js.map +1 -1
  64. package/dist/system/index.d.ts +6 -4
  65. package/dist/system/index.d.ts.map +1 -1
  66. package/dist/system/index.js +2 -1
  67. package/dist/system/index.js.map +1 -1
  68. package/dist/system/kernel.d.ts +9 -16
  69. package/dist/system/kernel.d.ts.map +1 -1
  70. package/dist/system/kernel.js +10 -23
  71. package/dist/system/kernel.js.map +1 -1
  72. package/dist/system/process.d.ts +18 -14
  73. package/dist/system/process.d.ts.map +1 -1
  74. package/dist/system/process.js +12 -10
  75. package/dist/system/process.js.map +1 -1
  76. package/dist/system/programs.js +1 -1
  77. package/dist/system/programs.js.map +1 -1
  78. package/dist/system/serverEvents.d.ts +27 -0
  79. package/dist/system/serverEvents.d.ts.map +1 -0
  80. package/dist/system/serverEvents.js +33 -0
  81. package/dist/system/serverEvents.js.map +1 -0
  82. package/dist/system/types.d.ts +4 -4
  83. package/dist/system/types.d.ts.map +1 -1
  84. package/dist/vfs.d.ts +27 -17
  85. package/dist/vfs.d.ts.map +1 -1
  86. package/dist/vfs.js +48 -11
  87. package/dist/vfs.js.map +1 -1
  88. package/package.json +1 -1
  89. package/src/archive.ts +59 -0
  90. package/src/build.ts +4 -4
  91. package/src/check/typecheck.ts +4 -4
  92. package/src/devServer.ts +12 -2
  93. package/src/html.ts +32 -5
  94. package/src/index.ts +5 -2
  95. package/src/installer/index.ts +2 -0
  96. package/src/installer/install.ts +4 -1
  97. package/src/installer/npmrc.ts +69 -0
  98. package/src/installer/registry.ts +12 -5
  99. package/src/node/childProcess.ts +1 -1
  100. package/src/node/misc.ts +1 -1
  101. package/src/shell/builtins.ts +2 -2
  102. package/src/shell/devHandoff.ts +1 -1
  103. package/src/shell/exec.ts +4 -4
  104. package/src/shell/expand.ts +1 -1
  105. package/src/shell/npm.ts +5 -1
  106. package/src/shell/program.ts +4 -4
  107. package/src/system/commands.ts +6 -6
  108. package/src/system/index.ts +6 -4
  109. package/src/system/kernel.ts +15 -32
  110. package/src/system/process.ts +28 -20
  111. package/src/system/programs.ts +1 -1
  112. package/src/system/serverEvents.ts +44 -0
  113. package/src/system/types.ts +4 -4
  114. package/src/vfs.ts +58 -15
package/src/vfs.ts CHANGED
@@ -2,13 +2,22 @@ import { normalizePath, join, dirname } from './paths.js';
2
2
 
3
3
  export type FileContent = string | Uint8Array;
4
4
 
5
- /** The nested tree shape `@webcontainer/api`'s `mount()` takes — accepted as-is. */
6
- export interface FileSystemTree {
7
- [name: string]: { file: { contents: FileContent } } | { directory: FileSystemTree };
5
+ /** A flat `{ 'src/main.tsx': '...' }` map: path → contents. */
6
+ export type FlatFiles = Record<string, FileContent>;
7
+
8
+ /**
9
+ * Files to write: a name maps to contents (a file) or to another tree (a
10
+ * directory). Names may hold slashes, so a {@link FlatFiles} map is a tree too,
11
+ * and the two styles mix freely: `{ src: { 'main.tsx': '…' }, 'public/a.svg': '…' }`.
12
+ */
13
+ export interface FileTree {
14
+ [name: string]: FileContent | FileTree;
8
15
  }
9
16
 
10
- /** A flat `{ 'src/main.tsx': '...' }` map, the other shape callers commonly hold. */
11
- export type FlatFiles = Record<string, FileContent>;
17
+ export interface DirectoryEntry {
18
+ name: string;
19
+ kind: 'file' | 'directory';
20
+ }
12
21
 
13
22
  export interface FsChange {
14
23
  /** `mkdir` is an explicitly created (possibly empty) directory. */
@@ -94,6 +103,39 @@ export class VirtualFileSystem {
94
103
  return [...(this.children.get(normalizePath(path)) ?? [])].sort();
95
104
  }
96
105
 
106
+ /** Direct children with their kind, sorted by name — `readdir` for callers that render a tree. */
107
+ entries(path: string): DirectoryEntry[] {
108
+ const dir = normalizePath(path);
109
+ return this.readdir(dir).map((name) => ({ name, kind: this.children.has(join(dir, name)) ? 'directory' : 'file' }));
110
+ }
111
+
112
+ /**
113
+ * Move a file or a directory (with everything under it). Throws when `from` is
114
+ * missing or `to` already exists. Watchers see the old paths removed and the
115
+ * new ones written, which is what every consumer (dev server, process sync) needs.
116
+ */
117
+ rename(from: string, to: string): void {
118
+ const source = normalizePath(from);
119
+ const target = normalizePath(to);
120
+ if (source === target) return;
121
+ if (!this.exists(source)) throw new Error(`ENOENT: no such file or directory, rename '${source}' -> '${target}'`);
122
+ if (this.exists(target)) throw new Error(`EEXIST: file already exists, rename '${source}' -> '${target}'`);
123
+ if (target.startsWith(source + '/')) throw new Error(`EINVAL: cannot move '${source}' into itself`);
124
+ if (this.files.has(source)) {
125
+ const contents = this.files.get(source)!;
126
+ this.removeFile(source);
127
+ this.writeFile(target, contents);
128
+ return;
129
+ }
130
+ const prefix = source + '/';
131
+ const moved = [...this.files].filter(([path]) => path.startsWith(prefix));
132
+ const dirs = [...this.explicit].filter((dir) => dir === source || dir.startsWith(prefix));
133
+ this.rm(source);
134
+ this.mkdir(target);
135
+ for (const dir of dirs) this.mkdir(target + dir.slice(source.length));
136
+ for (const [path, contents] of moved) this.writeFile(target + path.slice(source.length), contents);
137
+ }
138
+
97
139
  /** Every file path, sorted. */
98
140
  list(): string[] {
99
141
  return [...this.files.keys()].sort();
@@ -129,18 +171,14 @@ export class VirtualFileSystem {
129
171
  return this.mtimes.get(normalizePath(path));
130
172
  }
131
173
 
132
- /**
133
- * Write many files at once. Takes either the nested WebContainer tree or a flat
134
- * path→contents map — or a mix, since each entry is judged on its own.
135
- */
136
- mount(files: FileSystemTree | FlatFiles, at = '/'): void {
174
+ /** Write many files at once, under `at` (default `/`). A nested object is a directory, created even when empty. */
175
+ writeTree(files: FileTree, at = '/'): void {
137
176
  for (const [name, entry] of Object.entries(files)) {
138
177
  const path = join(at, name);
139
178
  if (typeof entry === 'string' || entry instanceof Uint8Array) this.writeFile(path, entry);
140
- else if ('file' in entry) this.writeFile(path, entry.file.contents);
141
179
  else {
142
180
  this.mkdir(path);
143
- this.mount(entry.directory, path);
181
+ this.writeTree(entry, path);
144
182
  }
145
183
  }
146
184
  }
@@ -152,9 +190,14 @@ export class VirtualFileSystem {
152
190
  return out;
153
191
  }
154
192
 
155
- watch(listener: (change: FsChange) => void): () => void {
156
- this.listeners.add(listener);
157
- return () => this.listeners.delete(listener);
193
+ /** Every change, or with `under` only changes at or below that path. */
194
+ watch(listener: (change: FsChange) => void, options: { under?: string } = {}): () => void {
195
+ const root = options.under === undefined ? undefined : normalizePath(options.under);
196
+ const filtered = root === undefined || root === '/'
197
+ ? listener
198
+ : (change: FsChange) => (change.path === root || change.path.startsWith(root + '/')) && listener(change);
199
+ this.listeners.add(filtered);
200
+ return () => this.listeners.delete(filtered);
158
201
  }
159
202
 
160
203
  private removeFile(key: string): void {