sandlot 0.1.1 → 0.1.3

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 (59) hide show
  1. package/README.md +145 -518
  2. package/dist/build-emitter.d.ts +47 -0
  3. package/dist/build-emitter.d.ts.map +1 -0
  4. package/dist/builder.d.ts +370 -0
  5. package/dist/builder.d.ts.map +1 -0
  6. package/dist/bundler.d.ts +3 -3
  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 +60 -42
  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 +304 -491
  23. package/dist/internal.d.ts +5 -0
  24. package/dist/internal.d.ts.map +1 -1
  25. package/dist/internal.js +174 -95
  26. package/dist/runner.d.ts +314 -0
  27. package/dist/runner.d.ts.map +1 -0
  28. package/dist/sandbox-manager.d.ts +45 -33
  29. package/dist/sandbox-manager.d.ts.map +1 -1
  30. package/dist/sandbox.d.ts +144 -70
  31. package/dist/sandbox.d.ts.map +1 -1
  32. package/dist/shared-modules.d.ts +22 -3
  33. package/dist/shared-modules.d.ts.map +1 -1
  34. package/dist/shared-resources.d.ts +0 -3
  35. package/dist/shared-resources.d.ts.map +1 -1
  36. package/dist/typechecker.d.ts +1 -1
  37. package/package.json +3 -17
  38. package/src/build-emitter.ts +64 -0
  39. package/src/builder.ts +498 -0
  40. package/src/bundler.ts +86 -57
  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 +90 -216
  47. package/src/index.ts +34 -12
  48. package/src/internal.ts +5 -2
  49. package/src/sandbox.ts +214 -220
  50. package/src/shared-modules.ts +74 -4
  51. package/src/shared-resources.ts +0 -3
  52. package/src/ts-libs.ts +1 -1
  53. package/src/typechecker.ts +1 -1
  54. package/dist/react.d.ts +0 -159
  55. package/dist/react.d.ts.map +0 -1
  56. package/dist/react.js +0 -149
  57. package/src/commands.ts +0 -733
  58. package/src/react.tsx +0 -331
  59. package/src/sandbox-manager.ts +0 -490
@@ -71,4 +71,9 @@ export { getSharedModuleRuntimeCode } from "./shared-modules";
71
71
  * Format esbuild messages for display.
72
72
  */
73
73
  export { formatEsbuildMessages } from "./commands";
74
+ /**
75
+ * Build event emitter for sandbox environments.
76
+ * Use this for custom build event handling in advanced use cases.
77
+ */
78
+ export { BuildEmitter } from "./build-emitter";
74
79
  //# sourceMappingURL=internal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH;;;GAGG;AACH,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAM5D;;GAEG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C;;GAEG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C;;GAEG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C;;GAEG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAMhD;;GAEG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C;;GAEG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE9C;;GAEG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C;;GAEG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC;;GAEG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC;;GAEG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAMrC;;GAEG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAExD;;GAEG;AACH,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAE3D;;GAEG;AACH,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAE3D;;GAEG;AACH,OAAO,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAM9D;;GAEG;AACH,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH;;;GAGG;AACH,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAM5D;;GAEG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C;;GAEG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C;;GAEG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C;;GAEG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAMhD;;GAEG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C;;GAEG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE9C;;GAEG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C;;GAEG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC;;GAEG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC;;GAEG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAMrC;;GAEG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAExD;;GAEG;AACH,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAE3D;;GAEG;AACH,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAE3D;;GAEG;AACH,OAAO,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAM9D;;GAEG;AACH,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAMnD;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/internal.js CHANGED
@@ -675,16 +675,18 @@ var GLOBAL_KEY = "__sandlot_shared_modules__";
675
675
 
676
676
  class SharedModuleRegistry {
677
677
  modules = new Map;
678
+ exportNames = new Map;
678
679
  constructor() {
679
680
  globalThis[GLOBAL_KEY] = this;
680
681
  }
681
682
  register(moduleId, module) {
682
683
  this.modules.set(moduleId, module);
684
+ this.exportNames.set(moduleId, introspectExports(module));
683
685
  return this;
684
686
  }
685
687
  registerAll(modules) {
686
688
  for (const [id, mod] of Object.entries(modules)) {
687
- this.modules.set(id, mod);
689
+ this.register(id, mod);
688
690
  }
689
691
  return this;
690
692
  }
@@ -705,13 +707,44 @@ class SharedModuleRegistry {
705
707
  list() {
706
708
  return [...this.modules.keys()];
707
709
  }
710
+ getExportNames(moduleId) {
711
+ return this.exportNames.get(moduleId) ?? [];
712
+ }
708
713
  clear() {
709
714
  this.modules.clear();
715
+ this.exportNames.clear();
710
716
  }
711
717
  get size() {
712
718
  return this.modules.size;
713
719
  }
714
720
  }
721
+ function introspectExports(module) {
722
+ if (module === null || module === undefined) {
723
+ return [];
724
+ }
725
+ if (typeof module !== "object" && typeof module !== "function") {
726
+ return [];
727
+ }
728
+ const exports = [];
729
+ for (const key of Object.keys(module)) {
730
+ if (isValidIdentifier(key)) {
731
+ exports.push(key);
732
+ }
733
+ }
734
+ return exports;
735
+ }
736
+ function isValidIdentifier(name) {
737
+ if (name.length === 0)
738
+ return false;
739
+ if (!/^[a-zA-Z_$]/.test(name))
740
+ return false;
741
+ if (!/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name))
742
+ return false;
743
+ const reserved = ["default", "class", "function", "var", "let", "const", "import", "export"];
744
+ if (reserved.includes(name))
745
+ return false;
746
+ return true;
747
+ }
715
748
  var defaultRegistry = null;
716
749
  function getSharedModuleRegistry() {
717
750
  if (!defaultRegistry) {
@@ -731,6 +764,9 @@ function unregisterSharedModule(moduleId) {
731
764
  function clearSharedModules() {
732
765
  getSharedModuleRegistry().clear();
733
766
  }
767
+ function getSharedModuleExports(moduleId) {
768
+ return getSharedModuleRegistry().getExportNames(moduleId);
769
+ }
734
770
  function getSharedModuleRuntimeCode(moduleId) {
735
771
  return `
736
772
  (function() {
@@ -745,7 +781,21 @@ function getSharedModuleRuntimeCode(moduleId) {
745
781
  })()
746
782
  `.trim();
747
783
  }
748
- // src/commands.ts
784
+ // src/commands/types.ts
785
+ function formatEsbuildMessages(messages) {
786
+ if (messages.length === 0)
787
+ return "";
788
+ return messages.map((msg) => {
789
+ if (msg.location) {
790
+ const { file, line, column } = msg.location;
791
+ const loc = file ? `${file}${line ? `:${line}` : ""}${column ? `:${column}` : ""}` : "";
792
+ return loc ? `${loc}: ${msg.text}` : msg.text;
793
+ }
794
+ return msg.text;
795
+ }).join(`
796
+ `);
797
+ }
798
+ // src/commands/compile.ts
749
799
  import { defineCommand } from "just-bash/browser";
750
800
 
751
801
  // src/typechecker.ts
@@ -1081,12 +1131,35 @@ function formatDiagnosticsForAgent(diagnostics) {
1081
1131
  }
1082
1132
 
1083
1133
  // src/bundler.ts
1084
- import * as esbuild from "esbuild-wasm";
1134
+ var esbuild = null;
1135
+ async function getEsbuild() {
1136
+ if (esbuild)
1137
+ return esbuild;
1138
+ const cdnUrl = `https://esm.sh/esbuild-wasm@${ESBUILD_VERSION}`;
1139
+ const mod = await import(cdnUrl);
1140
+ esbuild = mod.default ?? mod;
1141
+ if (typeof esbuild?.initialize !== "function") {
1142
+ console.error("esbuild-wasm module structure:", mod);
1143
+ throw new Error("Failed to load esbuild-wasm: initialize function not found");
1144
+ }
1145
+ return esbuild;
1146
+ }
1147
+ var ESBUILD_VERSION = "0.27.2";
1085
1148
  var initialized = false;
1086
1149
  var initPromise = null;
1087
1150
  function getWasmUrl() {
1088
- const version = "0.27.2";
1089
- return `https://unpkg.com/esbuild-wasm@${version}/esbuild.wasm`;
1151
+ return `https://unpkg.com/esbuild-wasm@${ESBUILD_VERSION}/esbuild.wasm`;
1152
+ }
1153
+ function checkCrossOriginIsolation() {
1154
+ if (typeof window === "undefined")
1155
+ return;
1156
+ if (!window.crossOriginIsolated) {
1157
+ console.warn(`[sandlot] Cross-origin isolation is not enabled. esbuild-wasm may have reduced performance or fail on some browsers.
1158
+ To enable, add these headers to your dev server:
1159
+ Cross-Origin-Embedder-Policy: require-corp
1160
+ Cross-Origin-Opener-Policy: same-origin
1161
+ In Vite, add a plugin to configureServer. See sandlot README for details.`);
1162
+ }
1090
1163
  }
1091
1164
  async function initBundler() {
1092
1165
  if (initialized)
@@ -1095,9 +1168,13 @@ async function initBundler() {
1095
1168
  await initPromise;
1096
1169
  return;
1097
1170
  }
1098
- initPromise = esbuild.initialize({
1099
- wasmURL: getWasmUrl()
1100
- });
1171
+ checkCrossOriginIsolation();
1172
+ initPromise = (async () => {
1173
+ const es = await getEsbuild();
1174
+ await es.initialize({
1175
+ wasmURL: getWasmUrl()
1176
+ });
1177
+ })();
1101
1178
  await initPromise;
1102
1179
  initialized = true;
1103
1180
  }
@@ -1148,8 +1225,8 @@ function createVfsPlugin(options) {
1148
1225
  } = options;
1149
1226
  return {
1150
1227
  name: "virtual-fs",
1151
- setup(build2) {
1152
- build2.onResolve({ filter: /.*/ }, async (args) => {
1228
+ setup(build) {
1229
+ build.onResolve({ filter: /.*/ }, async (args) => {
1153
1230
  if (args.kind === "entry-point") {
1154
1231
  return { path: entryPoint, namespace: "vfs" };
1155
1232
  }
@@ -1205,28 +1282,18 @@ function createVfsPlugin(options) {
1205
1282
  }
1206
1283
  return { errors: [{ text: `Cannot resolve: ${args.path} from ${args.resolveDir}` }] };
1207
1284
  });
1208
- build2.onLoad({ filter: /.*/, namespace: "sandlot-shared" }, (args) => {
1209
- const contents = `export default ${getSharedModuleRuntimeCode(args.path)};
1210
- export * from ${JSON.stringify(args.path)};
1211
- // Re-export all named exports by importing from registry
1212
- const __mod__ = ${getSharedModuleRuntimeCode(args.path)};
1213
- for (const __k__ in __mod__) {
1214
- if (__k__ !== 'default') Object.defineProperty(exports, __k__, {
1215
- enumerable: true,
1216
- get: function() { return __mod__[__k__]; }
1217
- });
1218
- }`;
1219
- const esmContents = `
1285
+ build.onLoad({ filter: /.*/, namespace: "sandlot-shared" }, (args) => {
1286
+ const contents = `
1220
1287
  const __sandlot_mod__ = ${getSharedModuleRuntimeCode(args.path)};
1221
1288
  export default __sandlot_mod__.default ?? __sandlot_mod__;
1222
1289
  ${generateNamedExports(args.path)}
1223
1290
  `;
1224
1291
  return {
1225
- contents: esmContents.trim(),
1292
+ contents: contents.trim(),
1226
1293
  loader: "js"
1227
1294
  };
1228
1295
  });
1229
- build2.onLoad({ filter: /.*/, namespace: "vfs" }, async (args) => {
1296
+ build.onLoad({ filter: /.*/, namespace: "vfs" }, async (args) => {
1230
1297
  try {
1231
1298
  const contents = await fs.readFile(args.path);
1232
1299
  includedFiles.add(args.path);
@@ -1245,55 +1312,12 @@ ${generateNamedExports(args.path)}
1245
1312
  };
1246
1313
  }
1247
1314
  function generateNamedExports(moduleId) {
1248
- const knownExports = {
1249
- react: [
1250
- "useState",
1251
- "useEffect",
1252
- "useContext",
1253
- "useReducer",
1254
- "useCallback",
1255
- "useMemo",
1256
- "useRef",
1257
- "useImperativeHandle",
1258
- "useLayoutEffect",
1259
- "useDebugValue",
1260
- "useDeferredValue",
1261
- "useTransition",
1262
- "useId",
1263
- "useSyncExternalStore",
1264
- "useInsertionEffect",
1265
- "useOptimistic",
1266
- "useActionState",
1267
- "createElement",
1268
- "cloneElement",
1269
- "createContext",
1270
- "forwardRef",
1271
- "lazy",
1272
- "memo",
1273
- "startTransition",
1274
- "Children",
1275
- "Component",
1276
- "PureComponent",
1277
- "Fragment",
1278
- "Profiler",
1279
- "StrictMode",
1280
- "Suspense",
1281
- "version",
1282
- "isValidElement"
1283
- ],
1284
- "react-dom": ["createPortal", "flushSync", "version"],
1285
- "react-dom/client": ["createRoot", "hydrateRoot"],
1286
- "react-dom/server": ["renderToString", "renderToStaticMarkup", "renderToPipeableStream"]
1287
- };
1288
- const exports = knownExports[moduleId];
1289
- if (!exports) {
1290
- return `
1291
- // Dynamic re-export for unknown module
1292
- export const __moduleProxy__ = __sandlot_mod__;
1293
- `;
1294
- }
1295
- return exports.map((name) => `export const ${name} = __sandlot_mod__.${name};`).join(`
1315
+ const exports = getSharedModuleExports(moduleId);
1316
+ if (exports.length > 0) {
1317
+ return exports.map((name) => `export const ${name} = __sandlot_mod__.${name};`).join(`
1296
1318
  `);
1319
+ }
1320
+ return `// No exports discovered for "${moduleId}" - use default import or call registerSharedModules() first`;
1297
1321
  }
1298
1322
  async function bundle(options) {
1299
1323
  await initBundler();
@@ -1325,7 +1349,8 @@ async function bundle(options) {
1325
1349
  includedFiles,
1326
1350
  sharedModuleIds
1327
1351
  });
1328
- const result = await esbuild.build({
1352
+ const es = await getEsbuild();
1353
+ const result = await es.build({
1329
1354
  entryPoints: [normalizedEntry],
1330
1355
  bundle: true,
1331
1356
  write: false,
@@ -1335,7 +1360,8 @@ async function bundle(options) {
1335
1360
  globalName,
1336
1361
  target,
1337
1362
  external,
1338
- plugins: [plugin]
1363
+ plugins: [plugin],
1364
+ jsx: "automatic"
1339
1365
  });
1340
1366
  const code = result.outputFiles?.[0]?.text ?? "";
1341
1367
  return {
@@ -1358,20 +1384,7 @@ async function bundleAndImport(options) {
1358
1384
  }
1359
1385
  }
1360
1386
 
1361
- // src/commands.ts
1362
- function formatEsbuildMessages(messages) {
1363
- if (messages.length === 0)
1364
- return "";
1365
- return messages.map((msg) => {
1366
- if (msg.location) {
1367
- const { file, line, column } = msg.location;
1368
- const loc = file ? `${file}${line ? `:${line}` : ""}${column ? `:${column}` : ""}` : "";
1369
- return loc ? `${loc}: ${msg.text}` : msg.text;
1370
- }
1371
- return msg.text;
1372
- }).join(`
1373
- `);
1374
- }
1387
+ // src/commands/compile.ts
1375
1388
  function createTscCommand(deps) {
1376
1389
  const { fs, libFiles, tsconfigPath } = deps;
1377
1390
  return defineCommand("tsc", async (args, _ctx) => {
@@ -1436,7 +1449,7 @@ ${formatDiagnosticsForAgent(result.diagnostics.filter((d) => d.category === "war
1436
1449
  });
1437
1450
  }
1438
1451
  function createBuildCommand(deps) {
1439
- const { fs, libFiles, tsconfigPath, onBuild, sharedModules } = deps;
1452
+ const { fs, libFiles, tsconfigPath, onBuild, getValidation, sharedModules } = deps;
1440
1453
  return defineCommand("build", async (args, _ctx) => {
1441
1454
  let entryPoint = null;
1442
1455
  let skipTypecheck = false;
@@ -1508,8 +1521,39 @@ ${formatted}
1508
1521
  minify,
1509
1522
  sharedModules
1510
1523
  });
1524
+ let loadedModule;
1525
+ try {
1526
+ loadedModule = await loadModule(bundleResult);
1527
+ } catch (err) {
1528
+ const errorMessage = err instanceof Error ? err.message : String(err);
1529
+ return {
1530
+ stdout: "",
1531
+ stderr: `Build failed: Module failed to load.
1532
+
1533
+ ${errorMessage}
1534
+ `,
1535
+ exitCode: 1
1536
+ };
1537
+ }
1538
+ const validateFn = getValidation?.();
1539
+ let validatedModule = loadedModule;
1540
+ if (validateFn) {
1541
+ try {
1542
+ validatedModule = validateFn(loadedModule);
1543
+ } catch (err) {
1544
+ const errorMessage = err instanceof Error ? err.message : String(err);
1545
+ return {
1546
+ stdout: "",
1547
+ stderr: `Build failed: Validation error.
1548
+
1549
+ ${errorMessage}
1550
+ `,
1551
+ exitCode: 1
1552
+ };
1553
+ }
1554
+ }
1511
1555
  if (onBuild) {
1512
- await onBuild(bundleResult);
1556
+ await onBuild({ bundle: bundleResult, module: validatedModule });
1513
1557
  }
1514
1558
  let output = `Build successful!
1515
1559
  `;
@@ -1525,6 +1569,15 @@ ${formatted}
1525
1569
  }
1526
1570
  output += `Bundled: ${bundleResult.includedFiles.length} file(s)
1527
1571
  `;
1572
+ const exportNames = Object.keys(loadedModule).filter((k) => !k.startsWith("__"));
1573
+ if (exportNames.length > 0) {
1574
+ output += `Exports: ${exportNames.join(", ")}
1575
+ `;
1576
+ }
1577
+ if (validateFn) {
1578
+ output += `Validation: passed
1579
+ `;
1580
+ }
1528
1581
  if (bundleResult.warnings.length > 0) {
1529
1582
  output += `
1530
1583
  Build warnings:
@@ -1556,9 +1609,11 @@ ${formatDiagnosticsForAgent(warnings)}
1556
1609
  }
1557
1610
  });
1558
1611
  }
1612
+ // src/commands/packages.ts
1613
+ import { defineCommand as defineCommand2 } from "just-bash/browser";
1559
1614
  function createInstallCommand(deps) {
1560
1615
  const { fs, typesCache } = deps;
1561
- return defineCommand("install", async (args, _ctx) => {
1616
+ return defineCommand2("install", async (args, _ctx) => {
1562
1617
  if (args.length === 0) {
1563
1618
  return {
1564
1619
  stdout: "",
@@ -1612,7 +1667,7 @@ Examples:
1612
1667
  }
1613
1668
  function createUninstallCommand(deps) {
1614
1669
  const { fs } = deps;
1615
- return defineCommand("uninstall", async (args, _ctx) => {
1670
+ return defineCommand2("uninstall", async (args, _ctx) => {
1616
1671
  if (args.length === 0) {
1617
1672
  return {
1618
1673
  stdout: "",
@@ -1657,7 +1712,7 @@ function createUninstallCommand(deps) {
1657
1712
  }
1658
1713
  function createListCommand(deps) {
1659
1714
  const { fs } = deps;
1660
- return defineCommand("list", async (_args, _ctx) => {
1715
+ return defineCommand2("list", async (_args, _ctx) => {
1661
1716
  try {
1662
1717
  const packages = await listPackages(fs);
1663
1718
  if (packages.length === 0) {
@@ -1687,9 +1742,11 @@ function createListCommand(deps) {
1687
1742
  }
1688
1743
  });
1689
1744
  }
1745
+ // src/commands/run.ts
1746
+ import { defineCommand as defineCommand3 } from "just-bash/browser";
1690
1747
  function createRunCommand(deps) {
1691
1748
  const { fs, libFiles, tsconfigPath, runOptions = {}, sharedModules } = deps;
1692
- return defineCommand("run", async (args, _ctx) => {
1749
+ return defineCommand3("run", async (args, _ctx) => {
1693
1750
  let entryPoint = null;
1694
1751
  let skipTypecheck = runOptions.skipTypecheck ?? false;
1695
1752
  let timeout = runOptions.timeout ?? 30000;
@@ -1866,6 +1923,7 @@ ${err.stack}` : "";
1866
1923
  }
1867
1924
  });
1868
1925
  }
1926
+ // src/commands/index.ts
1869
1927
  function createDefaultCommands(deps) {
1870
1928
  return [
1871
1929
  createTscCommand(deps),
@@ -1876,6 +1934,26 @@ function createDefaultCommands(deps) {
1876
1934
  createListCommand(deps)
1877
1935
  ];
1878
1936
  }
1937
+ // src/build-emitter.ts
1938
+ class BuildEmitter {
1939
+ listeners = new Set;
1940
+ emit = async (result) => {
1941
+ const promises = [];
1942
+ for (const listener of this.listeners) {
1943
+ const ret = listener(result);
1944
+ if (ret instanceof Promise) {
1945
+ promises.push(ret);
1946
+ }
1947
+ }
1948
+ await Promise.all(promises);
1949
+ };
1950
+ on(callback) {
1951
+ this.listeners.add(callback);
1952
+ return () => {
1953
+ this.listeners.delete(callback);
1954
+ };
1955
+ }
1956
+ }
1879
1957
  export {
1880
1958
  revokeModuleUrl,
1881
1959
  resolveToEsmUrl,
@@ -1893,5 +1971,6 @@ export {
1893
1971
  createModuleUrl,
1894
1972
  SharedModuleRegistry,
1895
1973
  LibCache,
1896
- InMemoryTypesCache
1974
+ InMemoryTypesCache,
1975
+ BuildEmitter
1897
1976
  };