sandlot 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +138 -408
  2. package/dist/build-emitter.d.ts +31 -13
  3. package/dist/build-emitter.d.ts.map +1 -1
  4. package/dist/builder.d.ts +370 -0
  5. package/dist/builder.d.ts.map +1 -0
  6. package/dist/bundler.d.ts +6 -2
  7. package/dist/bundler.d.ts.map +1 -1
  8. package/dist/commands/compile.d.ts +13 -0
  9. package/dist/commands/compile.d.ts.map +1 -0
  10. package/dist/commands/index.d.ts +17 -0
  11. package/dist/commands/index.d.ts.map +1 -0
  12. package/dist/commands/packages.d.ts +17 -0
  13. package/dist/commands/packages.d.ts.map +1 -0
  14. package/dist/commands/run.d.ts +40 -0
  15. package/dist/commands/run.d.ts.map +1 -0
  16. package/dist/commands/types.d.ts +141 -0
  17. package/dist/commands/types.d.ts.map +1 -0
  18. package/dist/fs.d.ts +53 -49
  19. package/dist/fs.d.ts.map +1 -1
  20. package/dist/index.d.ts +5 -4
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +300 -511
  23. package/dist/internal.js +161 -171
  24. package/dist/runner.d.ts +314 -0
  25. package/dist/runner.d.ts.map +1 -0
  26. package/dist/sandbox-manager.d.ts +45 -21
  27. package/dist/sandbox-manager.d.ts.map +1 -1
  28. package/dist/sandbox.d.ts +144 -62
  29. package/dist/sandbox.d.ts.map +1 -1
  30. package/dist/shared-modules.d.ts +22 -3
  31. package/dist/shared-modules.d.ts.map +1 -1
  32. package/dist/shared-resources.d.ts +0 -3
  33. package/dist/shared-resources.d.ts.map +1 -1
  34. package/dist/ts-libs.d.ts +7 -20
  35. package/dist/ts-libs.d.ts.map +1 -1
  36. package/dist/typechecker.d.ts +1 -1
  37. package/package.json +5 -5
  38. package/src/build-emitter.ts +32 -29
  39. package/src/builder.ts +498 -0
  40. package/src/bundler.ts +76 -55
  41. package/src/commands/compile.ts +236 -0
  42. package/src/commands/index.ts +51 -0
  43. package/src/commands/packages.ts +154 -0
  44. package/src/commands/run.ts +245 -0
  45. package/src/commands/types.ts +172 -0
  46. package/src/fs.ts +82 -221
  47. package/src/index.ts +17 -12
  48. package/src/sandbox.ts +219 -149
  49. package/src/shared-modules.ts +74 -4
  50. package/src/shared-resources.ts +0 -3
  51. package/src/ts-libs.ts +19 -121
  52. package/src/typechecker.ts +1 -1
  53. package/dist/react.d.ts +0 -159
  54. package/dist/react.d.ts.map +0 -1
  55. package/dist/react.js +0 -149
  56. package/src/commands.ts +0 -733
  57. package/src/sandbox-manager.ts +0 -409
package/dist/index.js CHANGED
@@ -1,3 +1,11 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined")
5
+ return require.apply(this, arguments);
6
+ throw Error('Dynamic require of "' + x + '" is not supported');
7
+ });
8
+
1
9
  // src/sandbox.ts
2
10
  import { Bash } from "just-bash/browser";
3
11
 
@@ -7,47 +15,14 @@ var DEFAULT_DIR_MODE = 493;
7
15
  var DEFAULT_SYMLINK_MODE = 511;
8
16
  var DEFAULT_MAX_SIZE_BYTES = 50 * 1024 * 1024;
9
17
 
10
- class IndexedDbFs {
18
+ class Filesystem {
11
19
  entries;
12
- db = null;
13
- dbName;
14
20
  maxSizeBytes;
15
- dirty = false;
16
- constructor(entries, db, dbName, maxSizeBytes) {
21
+ constructor(entries, maxSizeBytes) {
17
22
  this.entries = entries;
18
- this.db = db;
19
- this.dbName = dbName;
20
23
  this.maxSizeBytes = maxSizeBytes;
21
24
  }
22
- static async create(options = {}) {
23
- const dbName = options.dbName ?? "sandlot-fs";
24
- const maxSizeBytes = options.maxSizeBytes ?? DEFAULT_MAX_SIZE_BYTES;
25
- const db = await IndexedDbFs.openDatabase(dbName);
26
- const entries = await IndexedDbFs.loadEntries(db);
27
- if (entries.size === 0) {
28
- entries.set("/", {
29
- type: "directory",
30
- mode: DEFAULT_DIR_MODE,
31
- mtime: new Date
32
- });
33
- if (options.initialFiles) {
34
- for (const [path, value] of Object.entries(options.initialFiles)) {
35
- const normalizedPath = IndexedDbFs.normalizePath(path);
36
- const init = IndexedDbFs.parseFileInit(value);
37
- IndexedDbFs.ensureParentDirs(entries, normalizedPath);
38
- entries.set(normalizedPath, {
39
- type: "file",
40
- content: init.content,
41
- mode: init.mode ?? DEFAULT_FILE_MODE,
42
- mtime: init.mtime ?? new Date
43
- });
44
- }
45
- }
46
- }
47
- const fs = new IndexedDbFs(entries, db, dbName, maxSizeBytes);
48
- return fs;
49
- }
50
- static createInMemory(options = {}) {
25
+ static create(options = {}) {
51
26
  const maxSizeBytes = options.maxSizeBytes ?? DEFAULT_MAX_SIZE_BYTES;
52
27
  const entries = new Map;
53
28
  entries.set("/", {
@@ -57,9 +32,9 @@ class IndexedDbFs {
57
32
  });
58
33
  if (options.initialFiles) {
59
34
  for (const [path, value] of Object.entries(options.initialFiles)) {
60
- const normalizedPath = IndexedDbFs.normalizePath(path);
61
- const init = IndexedDbFs.parseFileInit(value);
62
- IndexedDbFs.ensureParentDirs(entries, normalizedPath);
35
+ const normalizedPath = Filesystem.normalizePath(path);
36
+ const init = Filesystem.parseFileInit(value);
37
+ Filesystem.ensureParentDirs(entries, normalizedPath);
63
38
  entries.set(normalizedPath, {
64
39
  type: "file",
65
40
  content: init.content,
@@ -68,31 +43,21 @@ class IndexedDbFs {
68
43
  });
69
44
  }
70
45
  }
71
- return new IndexedDbFs(entries, null, "", maxSizeBytes);
46
+ return new Filesystem(entries, maxSizeBytes);
72
47
  }
73
- async save() {
74
- if (!this.db || !this.dirty) {
75
- return false;
76
- }
77
- const tx = this.db.transaction("entries", "readwrite");
78
- const store = tx.objectStore("entries");
79
- await this.promisifyRequest(store.clear());
48
+ getFiles() {
49
+ const files = {};
80
50
  for (const [path, entry] of this.entries) {
81
- store.put({ path, entry: this.serializeEntry(entry) });
82
- }
83
- await this.promisifyTransaction(tx);
84
- this.dirty = false;
85
- return true;
86
- }
87
- async reload() {
88
- if (!this.db) {
89
- return;
51
+ if (entry.type === "file") {
52
+ if (typeof entry.content === "string") {
53
+ files[path] = entry.content;
54
+ } else {
55
+ const base64 = this.encodeBase64(entry.content);
56
+ files[path] = `data:application/octet-stream;base64,${base64}`;
57
+ }
58
+ }
90
59
  }
91
- this.entries = await IndexedDbFs.loadEntries(this.db);
92
- this.dirty = false;
93
- }
94
- isDirty() {
95
- return this.dirty;
60
+ return files;
96
61
  }
97
62
  getSize() {
98
63
  let size = 0;
@@ -108,12 +73,6 @@ class IndexedDbFs {
108
73
  }
109
74
  return size;
110
75
  }
111
- close() {
112
- if (this.db) {
113
- this.db.close();
114
- this.db = null;
115
- }
116
- }
117
76
  async readFile(path, options) {
118
77
  const normalizedPath = this.normalizePath(path);
119
78
  const entry = this.resolveSymlinks(normalizedPath);
@@ -159,7 +118,6 @@ class IndexedDbFs {
159
118
  mode: existing?.mode ?? DEFAULT_FILE_MODE,
160
119
  mtime: new Date
161
120
  });
162
- this.dirty = true;
163
121
  }
164
122
  async appendFile(path, content, options) {
165
123
  const normalizedPath = this.normalizePath(path);
@@ -211,7 +169,6 @@ class IndexedDbFs {
211
169
  mode: DEFAULT_DIR_MODE,
212
170
  mtime: new Date
213
171
  });
214
- this.dirty = true;
215
172
  }
216
173
  async readdir(path) {
217
174
  const normalizedPath = this.normalizePath(path);
@@ -287,7 +244,6 @@ class IndexedDbFs {
287
244
  }
288
245
  }
289
246
  this.entries.delete(normalizedPath);
290
- this.dirty = true;
291
247
  }
292
248
  async cp(src, dest, options) {
293
249
  const srcPath = this.normalizePath(src);
@@ -314,7 +270,6 @@ class IndexedDbFs {
314
270
  this.ensureParentDirs(destPath);
315
271
  this.entries.set(destPath, this.cloneEntry(entry));
316
272
  }
317
- this.dirty = true;
318
273
  }
319
274
  async mv(src, dest) {
320
275
  const srcPath = this.normalizePath(src);
@@ -341,7 +296,6 @@ class IndexedDbFs {
341
296
  this.entries.delete(srcPath);
342
297
  this.entries.set(destPath, entry);
343
298
  }
344
- this.dirty = true;
345
299
  }
346
300
  resolvePath(base, path) {
347
301
  if (path.startsWith("/")) {
@@ -371,7 +325,6 @@ class IndexedDbFs {
371
325
  }
372
326
  entry.mode = mode;
373
327
  entry.mtime = new Date;
374
- this.dirty = true;
375
328
  }
376
329
  async symlink(target, linkPath) {
377
330
  const normalizedLinkPath = this.normalizePath(linkPath);
@@ -385,7 +338,6 @@ class IndexedDbFs {
385
338
  mode: DEFAULT_SYMLINK_MODE,
386
339
  mtime: new Date
387
340
  });
388
- this.dirty = true;
389
341
  }
390
342
  async link(existingPath, newPath) {
391
343
  const srcPath = this.normalizePath(existingPath);
@@ -407,7 +359,6 @@ class IndexedDbFs {
407
359
  mode: entry.mode,
408
360
  mtime: new Date
409
361
  });
410
- this.dirty = true;
411
362
  }
412
363
  async readlink(path) {
413
364
  const normalizedPath = this.normalizePath(path);
@@ -453,10 +404,9 @@ class IndexedDbFs {
453
404
  throw new Error(`ENOENT: no such file or directory, utimes '${path}'`);
454
405
  }
455
406
  entry.mtime = mtime;
456
- this.dirty = true;
457
407
  }
458
408
  normalizePath(path) {
459
- return IndexedDbFs.normalizePath(path);
409
+ return Filesystem.normalizePath(path);
460
410
  }
461
411
  static normalizePath(path) {
462
412
  if (!path || path === ".")
@@ -484,8 +434,7 @@ class IndexedDbFs {
484
434
  return lastSlash === 0 ? "/" : path.slice(0, lastSlash);
485
435
  }
486
436
  ensureParentDirs(path) {
487
- IndexedDbFs.ensureParentDirs(this.entries, path);
488
- this.dirty = true;
437
+ Filesystem.ensureParentDirs(this.entries, path);
489
438
  }
490
439
  static ensureParentDirs(entries, path) {
491
440
  const parts = path.split("/").filter(Boolean);
@@ -562,17 +511,20 @@ class IndexedDbFs {
562
511
  return new TextDecoder("utf-8").decode(buffer);
563
512
  }
564
513
  if (encoding === "base64") {
565
- let binary = "";
566
- for (let i = 0;i < buffer.byteLength; i++) {
567
- binary += String.fromCharCode(buffer[i]);
568
- }
569
- return btoa(binary);
514
+ return this.encodeBase64(buffer);
570
515
  }
571
516
  if (encoding === "hex") {
572
517
  return Array.from(buffer).map((b) => b.toString(16).padStart(2, "0")).join("");
573
518
  }
574
519
  return new TextDecoder("utf-8").decode(buffer);
575
520
  }
521
+ encodeBase64(buffer) {
522
+ let binary = "";
523
+ for (let i = 0;i < buffer.byteLength; i++) {
524
+ binary += String.fromCharCode(buffer[i]);
525
+ }
526
+ return btoa(binary);
527
+ }
576
528
  concatBuffers(a, b) {
577
529
  const result = new Uint8Array(a.byteLength + b.byteLength);
578
530
  result.set(a, 0);
@@ -585,77 +537,9 @@ class IndexedDbFs {
585
537
  }
586
538
  return value;
587
539
  }
588
- static openDatabase(dbName) {
589
- return new Promise((resolve, reject) => {
590
- const request = indexedDB.open(dbName, 1);
591
- request.onerror = () => reject(request.error);
592
- request.onsuccess = () => resolve(request.result);
593
- request.onupgradeneeded = (event) => {
594
- const db = event.target.result;
595
- if (!db.objectStoreNames.contains("entries")) {
596
- db.createObjectStore("entries", { keyPath: "path" });
597
- }
598
- };
599
- });
600
- }
601
- static async loadEntries(db) {
602
- const tx = db.transaction("entries", "readonly");
603
- const store = tx.objectStore("entries");
604
- return new Promise((resolve, reject) => {
605
- const request = store.getAll();
606
- request.onerror = () => reject(request.error);
607
- request.onsuccess = () => {
608
- const entries = new Map;
609
- for (const record of request.result) {
610
- entries.set(record.path, IndexedDbFs.deserializeEntry(record.entry));
611
- }
612
- resolve(entries);
613
- };
614
- });
615
- }
616
- serializeEntry(entry) {
617
- if (entry.type === "file" && entry.content instanceof Uint8Array) {
618
- return {
619
- ...entry,
620
- content: Array.from(entry.content),
621
- contentType: "uint8array",
622
- mtime: entry.mtime.toISOString()
623
- };
624
- }
625
- return {
626
- ...entry,
627
- mtime: entry.mtime.toISOString()
628
- };
629
- }
630
- static deserializeEntry(data) {
631
- const mtime = new Date(data.mtime);
632
- if (data.type === "file") {
633
- let content = data.content;
634
- if (data.contentType === "uint8array" && Array.isArray(content)) {
635
- content = new Uint8Array(content);
636
- }
637
- return { type: "file", content, mode: data.mode, mtime };
638
- }
639
- if (data.type === "symlink") {
640
- return { type: "symlink", target: data.target, mode: data.mode, mtime };
641
- }
642
- return { type: "directory", mode: data.mode, mtime };
643
- }
644
- promisifyRequest(request) {
645
- return new Promise((resolve, reject) => {
646
- request.onerror = () => reject(request.error);
647
- request.onsuccess = () => resolve(request.result);
648
- });
649
- }
650
- promisifyTransaction(tx) {
651
- return new Promise((resolve, reject) => {
652
- tx.onerror = () => reject(tx.error);
653
- tx.oncomplete = () => resolve();
654
- });
655
- }
656
540
  }
657
- function createInMemoryFs(initialFiles) {
658
- return IndexedDbFs.createInMemory({ initialFiles });
541
+ function createFilesystem(options) {
542
+ return Filesystem.create(options);
659
543
  }
660
544
 
661
545
  // src/packages.ts
@@ -1122,16 +1006,18 @@ var GLOBAL_KEY = "__sandlot_shared_modules__";
1122
1006
 
1123
1007
  class SharedModuleRegistry {
1124
1008
  modules = new Map;
1009
+ exportNames = new Map;
1125
1010
  constructor() {
1126
1011
  globalThis[GLOBAL_KEY] = this;
1127
1012
  }
1128
1013
  register(moduleId, module) {
1129
1014
  this.modules.set(moduleId, module);
1015
+ this.exportNames.set(moduleId, introspectExports(module));
1130
1016
  return this;
1131
1017
  }
1132
1018
  registerAll(modules) {
1133
1019
  for (const [id, mod] of Object.entries(modules)) {
1134
- this.modules.set(id, mod);
1020
+ this.register(id, mod);
1135
1021
  }
1136
1022
  return this;
1137
1023
  }
@@ -1152,13 +1038,44 @@ class SharedModuleRegistry {
1152
1038
  list() {
1153
1039
  return [...this.modules.keys()];
1154
1040
  }
1041
+ getExportNames(moduleId) {
1042
+ return this.exportNames.get(moduleId) ?? [];
1043
+ }
1155
1044
  clear() {
1156
1045
  this.modules.clear();
1046
+ this.exportNames.clear();
1157
1047
  }
1158
1048
  get size() {
1159
1049
  return this.modules.size;
1160
1050
  }
1161
1051
  }
1052
+ function introspectExports(module) {
1053
+ if (module === null || module === undefined) {
1054
+ return [];
1055
+ }
1056
+ if (typeof module !== "object" && typeof module !== "function") {
1057
+ return [];
1058
+ }
1059
+ const exports = [];
1060
+ for (const key of Object.keys(module)) {
1061
+ if (isValidIdentifier(key)) {
1062
+ exports.push(key);
1063
+ }
1064
+ }
1065
+ return exports;
1066
+ }
1067
+ function isValidIdentifier(name) {
1068
+ if (name.length === 0)
1069
+ return false;
1070
+ if (!/^[a-zA-Z_$]/.test(name))
1071
+ return false;
1072
+ if (!/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name))
1073
+ return false;
1074
+ const reserved = ["default", "class", "function", "var", "let", "const", "import", "export"];
1075
+ if (reserved.includes(name))
1076
+ return false;
1077
+ return true;
1078
+ }
1162
1079
  var defaultRegistry = null;
1163
1080
  function getSharedModuleRegistry() {
1164
1081
  if (!defaultRegistry) {
@@ -1178,6 +1095,9 @@ function unregisterSharedModule(moduleId) {
1178
1095
  function clearSharedModules() {
1179
1096
  getSharedModuleRegistry().clear();
1180
1097
  }
1098
+ function getSharedModuleExports(moduleId) {
1099
+ return getSharedModuleRegistry().getExportNames(moduleId);
1100
+ }
1181
1101
  function getSharedModuleRuntimeCode(moduleId) {
1182
1102
  return `
1183
1103
  (function() {
@@ -1195,15 +1115,32 @@ function getSharedModuleRuntimeCode(moduleId) {
1195
1115
 
1196
1116
  // src/bundler.ts
1197
1117
  var esbuild = null;
1118
+ function isServerEnvironment() {
1119
+ if (typeof globalThis !== "undefined" && "Bun" in globalThis) {
1120
+ return true;
1121
+ }
1122
+ if (typeof globalThis !== "undefined" && "Deno" in globalThis) {
1123
+ return true;
1124
+ }
1125
+ if (typeof process !== "undefined" && process.versions?.node) {
1126
+ return true;
1127
+ }
1128
+ return false;
1129
+ }
1198
1130
  async function getEsbuild() {
1199
1131
  if (esbuild)
1200
1132
  return esbuild;
1201
- const cdnUrl = `https://esm.sh/esbuild-wasm@${ESBUILD_VERSION}`;
1202
- const mod = await import(cdnUrl);
1203
- esbuild = mod.default ?? mod;
1204
- if (typeof esbuild?.initialize !== "function") {
1205
- console.error("esbuild-wasm module structure:", mod);
1206
- throw new Error("Failed to load esbuild-wasm: initialize function not found");
1133
+ if (isServerEnvironment()) {
1134
+ const mod = await import("esbuild");
1135
+ esbuild = mod.default ?? mod;
1136
+ } else {
1137
+ const cdnUrl = `https://esm.sh/esbuild-wasm@${ESBUILD_VERSION}`;
1138
+ const mod = await import(cdnUrl);
1139
+ esbuild = mod.default ?? mod;
1140
+ if (typeof esbuild?.initialize !== "function") {
1141
+ console.error("esbuild-wasm module structure:", mod);
1142
+ throw new Error("Failed to load esbuild-wasm: initialize function not found");
1143
+ }
1207
1144
  }
1208
1145
  return esbuild;
1209
1146
  }
@@ -1231,12 +1168,14 @@ async function initBundler() {
1231
1168
  await initPromise;
1232
1169
  return;
1233
1170
  }
1234
- checkCrossOriginIsolation();
1235
1171
  initPromise = (async () => {
1236
1172
  const es = await getEsbuild();
1237
- await es.initialize({
1238
- wasmURL: getWasmUrl()
1239
- });
1173
+ if (!isServerEnvironment() && typeof es.initialize === "function") {
1174
+ checkCrossOriginIsolation();
1175
+ await es.initialize({
1176
+ wasmURL: getWasmUrl()
1177
+ });
1178
+ }
1240
1179
  })();
1241
1180
  await initPromise;
1242
1181
  initialized = true;
@@ -1375,55 +1314,12 @@ ${generateNamedExports(args.path)}
1375
1314
  };
1376
1315
  }
1377
1316
  function generateNamedExports(moduleId) {
1378
- const knownExports = {
1379
- react: [
1380
- "useState",
1381
- "useEffect",
1382
- "useContext",
1383
- "useReducer",
1384
- "useCallback",
1385
- "useMemo",
1386
- "useRef",
1387
- "useImperativeHandle",
1388
- "useLayoutEffect",
1389
- "useDebugValue",
1390
- "useDeferredValue",
1391
- "useTransition",
1392
- "useId",
1393
- "useSyncExternalStore",
1394
- "useInsertionEffect",
1395
- "useOptimistic",
1396
- "useActionState",
1397
- "createElement",
1398
- "cloneElement",
1399
- "createContext",
1400
- "forwardRef",
1401
- "lazy",
1402
- "memo",
1403
- "startTransition",
1404
- "Children",
1405
- "Component",
1406
- "PureComponent",
1407
- "Fragment",
1408
- "Profiler",
1409
- "StrictMode",
1410
- "Suspense",
1411
- "version",
1412
- "isValidElement"
1413
- ],
1414
- "react-dom": ["createPortal", "flushSync", "version"],
1415
- "react-dom/client": ["createRoot", "hydrateRoot"],
1416
- "react-dom/server": ["renderToString", "renderToStaticMarkup", "renderToPipeableStream"]
1417
- };
1418
- const exports = knownExports[moduleId];
1419
- if (!exports) {
1420
- return `
1421
- // Dynamic re-export for unknown module
1422
- export const __moduleProxy__ = __sandlot_mod__;
1423
- `;
1424
- }
1425
- return exports.map((name) => `export const ${name} = __sandlot_mod__.${name};`).join(`
1317
+ const exports = getSharedModuleExports(moduleId);
1318
+ if (exports.length > 0) {
1319
+ return exports.map((name) => `export const ${name} = __sandlot_mod__.${name};`).join(`
1426
1320
  `);
1321
+ }
1322
+ return `// No exports discovered for "${moduleId}" - use default import or call registerSharedModules() first`;
1427
1323
  }
1428
1324
  async function bundle(options) {
1429
1325
  await initBundler();
@@ -1466,7 +1362,8 @@ async function bundle(options) {
1466
1362
  globalName,
1467
1363
  target,
1468
1364
  external,
1469
- plugins: [plugin]
1365
+ plugins: [plugin],
1366
+ jsx: "automatic"
1470
1367
  });
1471
1368
  const code = result.outputFiles?.[0]?.text ?? "";
1472
1369
  return {
@@ -1489,7 +1386,21 @@ async function bundleAndImport(options) {
1489
1386
  }
1490
1387
  }
1491
1388
 
1492
- // src/commands.ts
1389
+ // src/commands/types.ts
1390
+ function formatEsbuildMessages(messages) {
1391
+ if (messages.length === 0)
1392
+ return "";
1393
+ return messages.map((msg) => {
1394
+ if (msg.location) {
1395
+ const { file, line, column } = msg.location;
1396
+ const loc = file ? `${file}${line ? `:${line}` : ""}${column ? `:${column}` : ""}` : "";
1397
+ return loc ? `${loc}: ${msg.text}` : msg.text;
1398
+ }
1399
+ return msg.text;
1400
+ }).join(`
1401
+ `);
1402
+ }
1403
+ // src/commands/compile.ts
1493
1404
  import { defineCommand } from "just-bash/browser";
1494
1405
 
1495
1406
  // src/typechecker.ts
@@ -1880,20 +1791,7 @@ async function hasExport(result, exportName) {
1880
1791
  return exportName in module;
1881
1792
  }
1882
1793
 
1883
- // src/commands.ts
1884
- function formatEsbuildMessages(messages) {
1885
- if (messages.length === 0)
1886
- return "";
1887
- return messages.map((msg) => {
1888
- if (msg.location) {
1889
- const { file, line, column } = msg.location;
1890
- const loc = file ? `${file}${line ? `:${line}` : ""}${column ? `:${column}` : ""}` : "";
1891
- return loc ? `${loc}: ${msg.text}` : msg.text;
1892
- }
1893
- return msg.text;
1894
- }).join(`
1895
- `);
1896
- }
1794
+ // src/commands/compile.ts
1897
1795
  function createTscCommand(deps) {
1898
1796
  const { fs, libFiles, tsconfigPath } = deps;
1899
1797
  return defineCommand("tsc", async (args, _ctx) => {
@@ -1958,7 +1856,7 @@ ${formatDiagnosticsForAgent(result.diagnostics.filter((d) => d.category === "war
1958
1856
  });
1959
1857
  }
1960
1858
  function createBuildCommand(deps) {
1961
- const { fs, libFiles, tsconfigPath, onBuild, sharedModules } = deps;
1859
+ const { fs, libFiles, tsconfigPath, onBuild, getValidation, sharedModules } = deps;
1962
1860
  return defineCommand("build", async (args, _ctx) => {
1963
1861
  let entryPoint = null;
1964
1862
  let skipTypecheck = false;
@@ -2030,8 +1928,39 @@ ${formatted}
2030
1928
  minify,
2031
1929
  sharedModules
2032
1930
  });
1931
+ let loadedModule;
1932
+ try {
1933
+ loadedModule = await loadModule(bundleResult);
1934
+ } catch (err) {
1935
+ const errorMessage = err instanceof Error ? err.message : String(err);
1936
+ return {
1937
+ stdout: "",
1938
+ stderr: `Build failed: Module failed to load.
1939
+
1940
+ ${errorMessage}
1941
+ `,
1942
+ exitCode: 1
1943
+ };
1944
+ }
1945
+ const validateFn = getValidation?.();
1946
+ let validatedModule = loadedModule;
1947
+ if (validateFn) {
1948
+ try {
1949
+ validatedModule = validateFn(loadedModule);
1950
+ } catch (err) {
1951
+ const errorMessage = err instanceof Error ? err.message : String(err);
1952
+ return {
1953
+ stdout: "",
1954
+ stderr: `Build failed: Validation error.
1955
+
1956
+ ${errorMessage}
1957
+ `,
1958
+ exitCode: 1
1959
+ };
1960
+ }
1961
+ }
2033
1962
  if (onBuild) {
2034
- await onBuild(bundleResult);
1963
+ await onBuild({ bundle: bundleResult, module: validatedModule });
2035
1964
  }
2036
1965
  let output = `Build successful!
2037
1966
  `;
@@ -2047,6 +1976,15 @@ ${formatted}
2047
1976
  }
2048
1977
  output += `Bundled: ${bundleResult.includedFiles.length} file(s)
2049
1978
  `;
1979
+ const exportNames = Object.keys(loadedModule).filter((k) => !k.startsWith("__"));
1980
+ if (exportNames.length > 0) {
1981
+ output += `Exports: ${exportNames.join(", ")}
1982
+ `;
1983
+ }
1984
+ if (validateFn) {
1985
+ output += `Validation: passed
1986
+ `;
1987
+ }
2050
1988
  if (bundleResult.warnings.length > 0) {
2051
1989
  output += `
2052
1990
  Build warnings:
@@ -2078,9 +2016,11 @@ ${formatDiagnosticsForAgent(warnings)}
2078
2016
  }
2079
2017
  });
2080
2018
  }
2019
+ // src/commands/packages.ts
2020
+ import { defineCommand as defineCommand2 } from "just-bash/browser";
2081
2021
  function createInstallCommand(deps) {
2082
2022
  const { fs, typesCache } = deps;
2083
- return defineCommand("install", async (args, _ctx) => {
2023
+ return defineCommand2("install", async (args, _ctx) => {
2084
2024
  if (args.length === 0) {
2085
2025
  return {
2086
2026
  stdout: "",
@@ -2134,7 +2074,7 @@ Examples:
2134
2074
  }
2135
2075
  function createUninstallCommand(deps) {
2136
2076
  const { fs } = deps;
2137
- return defineCommand("uninstall", async (args, _ctx) => {
2077
+ return defineCommand2("uninstall", async (args, _ctx) => {
2138
2078
  if (args.length === 0) {
2139
2079
  return {
2140
2080
  stdout: "",
@@ -2179,7 +2119,7 @@ function createUninstallCommand(deps) {
2179
2119
  }
2180
2120
  function createListCommand(deps) {
2181
2121
  const { fs } = deps;
2182
- return defineCommand("list", async (_args, _ctx) => {
2122
+ return defineCommand2("list", async (_args, _ctx) => {
2183
2123
  try {
2184
2124
  const packages = await listPackages(fs);
2185
2125
  if (packages.length === 0) {
@@ -2209,9 +2149,11 @@ function createListCommand(deps) {
2209
2149
  }
2210
2150
  });
2211
2151
  }
2152
+ // src/commands/run.ts
2153
+ import { defineCommand as defineCommand3 } from "just-bash/browser";
2212
2154
  function createRunCommand(deps) {
2213
2155
  const { fs, libFiles, tsconfigPath, runOptions = {}, sharedModules } = deps;
2214
- return defineCommand("run", async (args, _ctx) => {
2156
+ return defineCommand3("run", async (args, _ctx) => {
2215
2157
  let entryPoint = null;
2216
2158
  let skipTypecheck = runOptions.skipTypecheck ?? false;
2217
2159
  let timeout = runOptions.timeout ?? 30000;
@@ -2388,6 +2330,7 @@ ${err.stack}` : "";
2388
2330
  }
2389
2331
  });
2390
2332
  }
2333
+ // src/commands/index.ts
2391
2334
  function createDefaultCommands(deps) {
2392
2335
  return [
2393
2336
  createTscCommand(deps),
@@ -2402,9 +2345,6 @@ function createDefaultCommands(deps) {
2402
2345
  // src/ts-libs.ts
2403
2346
  var TS_VERSION = "5.9.3";
2404
2347
  var CDN_BASE = `https://cdn.jsdelivr.net/npm/typescript@${TS_VERSION}/lib`;
2405
- var DB_NAME = "ts-lib-cache";
2406
- var DB_VERSION = 1;
2407
- var STORE_NAME = "libs";
2408
2348
  function getDefaultBrowserLibs() {
2409
2349
  return ["es2020", "dom", "dom.iterable"];
2410
2350
  }
@@ -2469,94 +2409,36 @@ async function fetchAllLibs(libs) {
2469
2409
  }
2470
2410
  return result;
2471
2411
  }
2472
- async function openDatabase() {
2473
- return new Promise((resolve, reject) => {
2474
- const request = indexedDB.open(DB_NAME, DB_VERSION);
2475
- request.onerror = () => reject(request.error);
2476
- request.onsuccess = () => resolve(request.result);
2477
- request.onupgradeneeded = (event) => {
2478
- const db = event.target.result;
2479
- if (!db.objectStoreNames.contains(STORE_NAME)) {
2480
- db.createObjectStore(STORE_NAME);
2481
- }
2482
- };
2483
- });
2484
- }
2485
- function promisifyRequest(request) {
2486
- return new Promise((resolve, reject) => {
2487
- request.onsuccess = () => resolve(request.result);
2488
- request.onerror = () => reject(request.error);
2489
- });
2490
- }
2491
- function getCacheKey() {
2492
- return `libs-${TS_VERSION}`;
2493
- }
2412
+ var memoryCache = null;
2494
2413
 
2495
2414
  class LibCache {
2496
- db;
2497
- constructor(db) {
2498
- this.db = db;
2499
- }
2500
- static async create() {
2501
- const db = await openDatabase();
2502
- return new LibCache(db);
2503
- }
2504
2415
  async getOrFetch(libs) {
2505
- const cached = await this.get();
2506
- if (cached) {
2507
- const missing = libs.filter((lib) => !cached.has(lib));
2416
+ if (memoryCache) {
2417
+ const missing = libs.filter((lib) => !memoryCache.has(lib));
2508
2418
  if (missing.length === 0) {
2509
- return cached;
2419
+ return memoryCache;
2510
2420
  }
2511
2421
  console.log(`Cache missing libs: ${missing.join(", ")}, fetching all...`);
2512
2422
  }
2513
2423
  console.log(`Fetching TypeScript libs from CDN: ${libs.join(", ")}...`);
2514
2424
  const fetched = await fetchAllLibs(libs);
2515
2425
  console.log(`Fetched ${fetched.size} lib files`);
2516
- await this.set(fetched);
2426
+ memoryCache = fetched;
2517
2427
  return fetched;
2518
2428
  }
2519
- async get() {
2520
- const tx = this.db.transaction(STORE_NAME, "readonly");
2521
- const store = tx.objectStore(STORE_NAME);
2522
- const key = getCacheKey();
2523
- const cached = await promisifyRequest(store.get(key));
2524
- if (!cached) {
2525
- return null;
2526
- }
2527
- if (cached.version !== TS_VERSION) {
2528
- console.log(`Cache version mismatch: ${cached.version} vs ${TS_VERSION}`);
2529
- return null;
2530
- }
2531
- return new Map(Object.entries(cached.libs));
2532
- }
2533
- async set(libs) {
2534
- const tx = this.db.transaction(STORE_NAME, "readwrite");
2535
- const store = tx.objectStore(STORE_NAME);
2536
- const key = getCacheKey();
2537
- const cached = {
2538
- version: TS_VERSION,
2539
- timestamp: Date.now(),
2540
- libs: Object.fromEntries(libs)
2541
- };
2542
- await promisifyRequest(store.put(cached, key));
2429
+ get() {
2430
+ return memoryCache;
2543
2431
  }
2544
- async clear() {
2545
- const tx = this.db.transaction(STORE_NAME, "readwrite");
2546
- const store = tx.objectStore(STORE_NAME);
2547
- await promisifyRequest(store.clear());
2432
+ set(libs) {
2433
+ memoryCache = libs;
2548
2434
  }
2549
- close() {
2550
- this.db.close();
2435
+ clear() {
2436
+ memoryCache = null;
2551
2437
  }
2552
2438
  }
2553
2439
  async function fetchAndCacheLibs(libs = getDefaultBrowserLibs()) {
2554
- const cache = await LibCache.create();
2555
- try {
2556
- return await cache.getOrFetch(libs);
2557
- } finally {
2558
- cache.close();
2559
- }
2440
+ const cache = new LibCache;
2441
+ return cache.getOrFetch(libs);
2560
2442
  }
2561
2443
 
2562
2444
  // src/shared-resources.ts
@@ -2597,9 +2479,7 @@ function hasDefaultResources() {
2597
2479
  // src/build-emitter.ts
2598
2480
  class BuildEmitter {
2599
2481
  listeners = new Set;
2600
- lastResult = null;
2601
2482
  emit = async (result) => {
2602
- this.lastResult = result;
2603
2483
  const promises = [];
2604
2484
  for (const listener of this.listeners) {
2605
2485
  const ret = listener(result);
@@ -2615,245 +2495,156 @@ class BuildEmitter {
2615
2495
  this.listeners.delete(callback);
2616
2496
  };
2617
2497
  }
2618
- waitFor() {
2619
- if (this.lastResult) {
2620
- const result = this.lastResult;
2621
- this.lastResult = null;
2622
- return Promise.resolve(result);
2623
- }
2624
- return new Promise((resolve) => {
2625
- const unsub = this.on((result) => {
2626
- unsub();
2627
- this.lastResult = null;
2628
- resolve(result);
2629
- });
2630
- });
2631
- }
2632
2498
  }
2633
2499
 
2634
2500
  // src/sandbox.ts
2635
2501
  async function createSandbox(options = {}) {
2636
- const {
2637
- fsOptions = {},
2638
- tsconfigPath = "/tsconfig.json",
2639
- resources: providedResources,
2640
- onBuild: onBuildCallback,
2641
- customCommands = [],
2642
- sharedModules
2643
- } = options;
2644
- const fsPromise = IndexedDbFs.create(fsOptions);
2645
- const resourcesPromise = providedResources ? Promise.resolve(providedResources) : getDefaultResources();
2646
- const bundlerPromise = initBundler();
2647
- const [fs, resources] = await Promise.all([fsPromise, resourcesPromise, bundlerPromise]);
2648
- const libFiles = resources.libFiles;
2649
- const typesCache = resources.typesCache;
2650
- const buildEmitter = new BuildEmitter;
2651
- if (onBuildCallback) {
2652
- buildEmitter.on(onBuildCallback);
2653
- }
2654
- const commandDeps = {
2655
- fs,
2656
- libFiles,
2657
- tsconfigPath,
2658
- onBuild: buildEmitter.emit,
2659
- typesCache,
2660
- sharedModules
2661
- };
2662
- const defaultCommands = createDefaultCommands(commandDeps);
2663
- const bash = new Bash({
2664
- fs,
2665
- cwd: "/",
2666
- customCommands: [...defaultCommands, ...customCommands]
2667
- });
2668
- return {
2669
- fs,
2670
- bash,
2671
- isDirty: () => fs.isDirty(),
2672
- save: () => fs.save(),
2673
- close: () => fs.close(),
2674
- onBuild: (callback) => buildEmitter.on(callback)
2675
- };
2676
- }
2677
- async function createInMemorySandbox(options = {}) {
2678
2502
  const {
2679
2503
  initialFiles,
2504
+ maxFilesystemSize,
2680
2505
  tsconfigPath = "/tsconfig.json",
2681
2506
  resources: providedResources,
2682
2507
  onBuild: onBuildCallback,
2683
2508
  customCommands = [],
2684
- sharedModules
2509
+ sharedModules,
2510
+ bashOptions = {}
2685
2511
  } = options;
2512
+ const fs = Filesystem.create({
2513
+ initialFiles,
2514
+ maxSizeBytes: maxFilesystemSize
2515
+ });
2686
2516
  const resourcesPromise = providedResources ? Promise.resolve(providedResources) : getDefaultResources();
2687
2517
  const bundlerPromise = initBundler();
2688
- const fs = IndexedDbFs.createInMemory({ initialFiles });
2689
2518
  const [resources] = await Promise.all([resourcesPromise, bundlerPromise]);
2690
2519
  const libFiles = resources.libFiles;
2691
2520
  const typesCache = resources.typesCache;
2521
+ if (sharedModules && sharedModules.length > 0) {
2522
+ const basePackages = new Set;
2523
+ for (const moduleId of sharedModules) {
2524
+ const { packageName } = parseImportPath(moduleId);
2525
+ basePackages.add(packageName);
2526
+ }
2527
+ await Promise.all(Array.from(basePackages).map(async (packageName) => {
2528
+ try {
2529
+ await installPackage(fs, packageName, { cache: typesCache });
2530
+ } catch (err) {
2531
+ console.warn(`[sandlot] Failed to install types for shared module "${packageName}":`, err);
2532
+ }
2533
+ }));
2534
+ }
2692
2535
  const buildEmitter = new BuildEmitter;
2536
+ let lastBuild = null;
2537
+ buildEmitter.on((result) => {
2538
+ lastBuild = result;
2539
+ });
2693
2540
  if (onBuildCallback) {
2694
2541
  buildEmitter.on(onBuildCallback);
2695
2542
  }
2543
+ let validationFn = null;
2696
2544
  const commandDeps = {
2697
2545
  fs,
2698
2546
  libFiles,
2699
2547
  tsconfigPath,
2700
2548
  onBuild: buildEmitter.emit,
2549
+ getValidation: () => validationFn,
2701
2550
  typesCache,
2702
2551
  sharedModules
2703
2552
  };
2704
2553
  const defaultCommands = createDefaultCommands(commandDeps);
2705
2554
  const bash = new Bash({
2706
- fs,
2555
+ ...bashOptions,
2707
2556
  cwd: "/",
2557
+ fs,
2708
2558
  customCommands: [...defaultCommands, ...customCommands]
2709
2559
  });
2710
2560
  return {
2711
2561
  fs,
2712
2562
  bash,
2713
- isDirty: () => fs.isDirty(),
2714
- save: () => Promise.resolve(false),
2715
- close: () => {},
2716
- onBuild: (callback) => buildEmitter.on(callback)
2563
+ get lastBuild() {
2564
+ return lastBuild;
2565
+ },
2566
+ getState: () => ({ files: fs.getFiles() }),
2567
+ onBuild: (callback) => buildEmitter.on(callback),
2568
+ setValidation: (fn) => {
2569
+ validationFn = fn;
2570
+ },
2571
+ clearValidation: () => {
2572
+ validationFn = null;
2573
+ }
2717
2574
  };
2718
2575
  }
2719
- // src/sandbox-manager.ts
2720
- import { Bash as Bash2 } from "just-bash/browser";
2721
- class SandboxManager {
2722
- resources = null;
2723
- sandboxes = new Map;
2724
- initialized = false;
2725
- initPromise = null;
2726
- nextId = 1;
2727
- options;
2728
- constructor(options = {}) {
2729
- this.options = {
2730
- libs: options.libs ?? getDefaultBrowserLibs(),
2731
- ...options
2732
- };
2733
- }
2734
- async initialize() {
2735
- if (this.initialized)
2736
- return;
2737
- if (this.initPromise) {
2738
- await this.initPromise;
2739
- return;
2740
- }
2741
- this.initPromise = this.doInitialize();
2742
- await this.initPromise;
2743
- this.initialized = true;
2744
- }
2745
- async doInitialize() {
2746
- this.resources = await createSharedResources({
2747
- libs: this.options.libs,
2748
- skipLibs: this.options.skipLibs,
2749
- skipBundler: this.options.skipBundler
2750
- });
2751
- }
2752
- async createSandbox(options = {}) {
2753
- await this.initialize();
2754
- const {
2755
- id = `sandbox-${this.nextId++}`,
2756
- fsOptions = {},
2757
- initialFiles,
2758
- tsconfigPath = "/tsconfig.json",
2759
- onBuild,
2760
- customCommands = [],
2761
- inMemory = true,
2762
- sharedModules = this.options.sharedModules
2763
- } = options;
2764
- let fs;
2765
- if (inMemory) {
2766
- fs = IndexedDbFs.createInMemory({
2767
- initialFiles,
2768
- maxSizeBytes: fsOptions.maxSizeBytes
2769
- });
2770
- } else {
2771
- fs = await IndexedDbFs.create({
2772
- dbName: fsOptions.dbName ?? id,
2773
- initialFiles,
2774
- maxSizeBytes: fsOptions.maxSizeBytes
2775
- });
2576
+ // src/builder.ts
2577
+ function createBuilder(options) {
2578
+ return async (prompt, callOptions) => {
2579
+ const sandbox = options.sandbox ?? await createSandbox(options.sandboxOptions);
2580
+ if (callOptions?.validate) {
2581
+ sandbox.setValidation(callOptions.validate);
2776
2582
  }
2777
- const buildEmitter = new BuildEmitter;
2778
- if (onBuild) {
2779
- buildEmitter.on(onBuild);
2780
- }
2781
- const commandDeps = {
2782
- fs,
2783
- libFiles: this.resources.libFiles,
2784
- tsconfigPath,
2785
- onBuild: buildEmitter.emit,
2786
- typesCache: this.resources.typesCache,
2787
- sharedModules
2788
- };
2789
- const defaultCommands = createDefaultCommands(commandDeps);
2790
- const bash = new Bash2({
2791
- fs,
2792
- cwd: "/",
2793
- customCommands: [...defaultCommands, ...customCommands]
2583
+ const captured = { output: null };
2584
+ const unsubscribe = sandbox.onBuild((output) => {
2585
+ captured.output = output;
2794
2586
  });
2795
- const sandbox = {
2796
- id,
2797
- fs,
2798
- bash,
2799
- isDirty: () => fs.isDirty(),
2800
- save: () => fs.save(),
2801
- close: () => {
2802
- fs.close();
2803
- this.sandboxes.delete(id);
2804
- },
2805
- onBuild: (callback) => buildEmitter.on(callback)
2806
- };
2807
- this.sandboxes.set(id, sandbox);
2808
- return sandbox;
2809
- }
2810
- getSandbox(id) {
2811
- return this.sandboxes.get(id);
2812
- }
2813
- getAllSandboxes() {
2814
- return Array.from(this.sandboxes.values());
2815
- }
2816
- closeSandbox(id) {
2817
- const sandbox = this.sandboxes.get(id);
2818
- if (sandbox) {
2819
- sandbox.close();
2820
- return true;
2821
- }
2822
- return false;
2823
- }
2824
- destroyAll() {
2825
- for (const sandbox of this.sandboxes.values()) {
2826
- sandbox.fs.close();
2587
+ const { timeout, signal } = callOptions ?? {};
2588
+ let timeoutId;
2589
+ let abortController;
2590
+ if (timeout !== undefined || signal !== undefined) {
2591
+ abortController = new AbortController;
2592
+ if (timeout !== undefined) {
2593
+ timeoutId = setTimeout(() => {
2594
+ abortController.abort(new Error(`Build timed out after ${timeout}ms`));
2595
+ }, timeout);
2596
+ }
2597
+ if (signal !== undefined) {
2598
+ if (signal.aborted) {
2599
+ abortController.abort(signal.reason);
2600
+ } else {
2601
+ signal.addEventListener("abort", () => {
2602
+ abortController.abort(signal.reason);
2603
+ }, { once: true });
2604
+ }
2605
+ }
2827
2606
  }
2828
- this.sandboxes.clear();
2829
- }
2830
- async saveAll() {
2831
- const results = new Map;
2832
- for (const [id, sandbox] of this.sandboxes) {
2833
- const saved = await sandbox.save();
2834
- results.set(id, saved);
2607
+ let result;
2608
+ let error = null;
2609
+ try {
2610
+ const buildPromise = options.build(sandbox, prompt);
2611
+ if (abortController) {
2612
+ const abortPromise = new Promise((_, reject) => {
2613
+ abortController.signal.addEventListener("abort", () => {
2614
+ const err = abortController.signal.reason instanceof Error ? abortController.signal.reason : new Error("Build aborted");
2615
+ err.name = "AbortError";
2616
+ reject(err);
2617
+ }, { once: true });
2618
+ if (abortController.signal.aborted) {
2619
+ const err = abortController.signal.reason instanceof Error ? abortController.signal.reason : new Error("Build aborted");
2620
+ err.name = "AbortError";
2621
+ reject(err);
2622
+ }
2623
+ });
2624
+ result = await Promise.race([buildPromise, abortPromise]);
2625
+ } else {
2626
+ result = await buildPromise;
2627
+ }
2628
+ } catch (err) {
2629
+ error = err instanceof Error ? err : new Error(String(err));
2630
+ } finally {
2631
+ if (timeoutId !== undefined) {
2632
+ clearTimeout(timeoutId);
2633
+ }
2634
+ unsubscribe();
2635
+ if (callOptions?.validate) {
2636
+ sandbox.clearValidation();
2637
+ }
2835
2638
  }
2836
- return results;
2837
- }
2838
- getDirtySandboxes() {
2839
- return Array.from(this.sandboxes.entries()).filter(([_, sandbox]) => sandbox.isDirty()).map(([id]) => id);
2840
- }
2841
- getStats() {
2639
+ const buildOutput = captured.output;
2842
2640
  return {
2843
- initialized: this.initialized,
2844
- activeSandboxes: this.sandboxes.size,
2845
- libFilesCount: this.resources?.libFiles.size ?? 0,
2846
- sandboxIds: Array.from(this.sandboxes.keys())
2641
+ result,
2642
+ error,
2643
+ bundle: buildOutput?.bundle ?? null,
2644
+ module: buildOutput?.module ?? null,
2645
+ sandbox
2847
2646
  };
2848
- }
2849
- getResources() {
2850
- return this.resources;
2851
- }
2852
- }
2853
- async function createSandboxManager(options = {}) {
2854
- const manager = new SandboxManager(options);
2855
- await manager.initialize();
2856
- return manager;
2647
+ };
2857
2648
  }
2858
2649
 
2859
2650
  // src/index.ts
@@ -2890,22 +2681,20 @@ export {
2890
2681
  createUninstallCommand,
2891
2682
  createTscCommand,
2892
2683
  createSharedResources,
2893
- createSandboxManager,
2894
2684
  createSandbox,
2895
2685
  createRunCommand,
2896
2686
  createListCommand,
2897
2687
  createInstallCommand,
2898
- createInMemorySandbox,
2899
- createInMemoryFs,
2688
+ createFilesystem,
2900
2689
  createDefaultCommands,
2690
+ createBuilder,
2901
2691
  createBuildCommand,
2902
2692
  clearSharedModules,
2903
2693
  clearDefaultResources,
2904
2694
  bundleToUrl,
2905
2695
  bundleAndImport,
2906
2696
  bundle,
2907
- SandboxManager,
2908
2697
  ModuleLoadError,
2909
- IndexedDbFs,
2698
+ Filesystem,
2910
2699
  ExportNotFoundError
2911
2700
  };