sandlot 0.1.4 → 0.2.1

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 (115) hide show
  1. package/dist/browser/bundler.d.ts +68 -0
  2. package/dist/browser/bundler.d.ts.map +1 -0
  3. package/dist/browser/executor.d.ts +46 -0
  4. package/dist/browser/executor.d.ts.map +1 -0
  5. package/dist/browser/index.d.ts +9 -0
  6. package/dist/browser/index.d.ts.map +1 -0
  7. package/dist/browser/index.js +2690 -0
  8. package/dist/browser/preset.d.ts +63 -0
  9. package/dist/browser/preset.d.ts.map +1 -0
  10. package/dist/commands/index.d.ts +20 -11
  11. package/dist/commands/index.d.ts.map +1 -1
  12. package/dist/commands/types.d.ts +37 -130
  13. package/dist/commands/types.d.ts.map +1 -1
  14. package/dist/core/bundler-utils.d.ts +142 -0
  15. package/dist/core/bundler-utils.d.ts.map +1 -0
  16. package/dist/core/esm-types-resolver.d.ts +125 -0
  17. package/dist/core/esm-types-resolver.d.ts.map +1 -0
  18. package/dist/core/executor.d.ts +35 -0
  19. package/dist/core/executor.d.ts.map +1 -0
  20. package/dist/{fs.d.ts → core/fs.d.ts} +27 -29
  21. package/dist/core/fs.d.ts.map +1 -0
  22. package/dist/core/sandbox.d.ts +30 -0
  23. package/dist/core/sandbox.d.ts.map +1 -0
  24. package/dist/core/sandlot.d.ts +30 -0
  25. package/dist/core/sandlot.d.ts.map +1 -0
  26. package/dist/core/shared-module-registry.d.ts +46 -0
  27. package/dist/core/shared-module-registry.d.ts.map +1 -0
  28. package/dist/core/typechecker.d.ts +60 -0
  29. package/dist/core/typechecker.d.ts.map +1 -0
  30. package/dist/index.d.ts +11 -16
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +1398 -2010
  33. package/dist/node/bundler.d.ts +48 -0
  34. package/dist/node/bundler.d.ts.map +1 -0
  35. package/dist/node/executor.d.ts +48 -0
  36. package/dist/node/executor.d.ts.map +1 -0
  37. package/dist/node/index.d.ts +9 -0
  38. package/dist/node/index.d.ts.map +1 -0
  39. package/dist/node/index.js +2644 -0
  40. package/dist/node/preset.d.ts +62 -0
  41. package/dist/node/preset.d.ts.map +1 -0
  42. package/dist/types.d.ts +528 -0
  43. package/dist/types.d.ts.map +1 -0
  44. package/package.json +16 -6
  45. package/src/browser/bundler.ts +294 -0
  46. package/src/browser/executor.ts +71 -0
  47. package/src/browser/index.ts +57 -0
  48. package/src/browser/preset.ts +179 -0
  49. package/src/commands/index.ts +498 -37
  50. package/src/commands/types.ts +117 -145
  51. package/src/core/bundler-utils.ts +630 -0
  52. package/src/core/esm-types-resolver.ts +432 -0
  53. package/src/core/executor.ts +161 -0
  54. package/src/{fs.ts → core/fs.ts} +59 -37
  55. package/src/core/sandbox.ts +624 -0
  56. package/src/core/sandlot.ts +77 -0
  57. package/src/core/shared-module-registry.ts +138 -0
  58. package/src/core/typechecker.ts +609 -0
  59. package/src/index.ts +106 -139
  60. package/src/node/bundler.ts +194 -0
  61. package/src/node/executor.ts +87 -0
  62. package/src/node/index.ts +39 -0
  63. package/src/node/preset.ts +178 -0
  64. package/src/types.ts +672 -0
  65. package/README.md +0 -243
  66. package/dist/build-emitter.d.ts +0 -47
  67. package/dist/build-emitter.d.ts.map +0 -1
  68. package/dist/builder.d.ts +0 -370
  69. package/dist/builder.d.ts.map +0 -1
  70. package/dist/bundler.d.ts +0 -152
  71. package/dist/bundler.d.ts.map +0 -1
  72. package/dist/commands/compile.d.ts +0 -13
  73. package/dist/commands/compile.d.ts.map +0 -1
  74. package/dist/commands/packages.d.ts +0 -17
  75. package/dist/commands/packages.d.ts.map +0 -1
  76. package/dist/commands/run.d.ts +0 -40
  77. package/dist/commands/run.d.ts.map +0 -1
  78. package/dist/commands.d.ts +0 -179
  79. package/dist/commands.d.ts.map +0 -1
  80. package/dist/fs.d.ts.map +0 -1
  81. package/dist/internal.d.ts +0 -79
  82. package/dist/internal.d.ts.map +0 -1
  83. package/dist/internal.js +0 -1942
  84. package/dist/loader.d.ts +0 -164
  85. package/dist/loader.d.ts.map +0 -1
  86. package/dist/packages.d.ts +0 -199
  87. package/dist/packages.d.ts.map +0 -1
  88. package/dist/runner.d.ts +0 -314
  89. package/dist/runner.d.ts.map +0 -1
  90. package/dist/sandbox-manager.d.ts +0 -261
  91. package/dist/sandbox-manager.d.ts.map +0 -1
  92. package/dist/sandbox.d.ts +0 -267
  93. package/dist/sandbox.d.ts.map +0 -1
  94. package/dist/shared-modules.d.ts +0 -148
  95. package/dist/shared-modules.d.ts.map +0 -1
  96. package/dist/shared-resources.d.ts +0 -102
  97. package/dist/shared-resources.d.ts.map +0 -1
  98. package/dist/ts-libs.d.ts +0 -85
  99. package/dist/ts-libs.d.ts.map +0 -1
  100. package/dist/typechecker.d.ts +0 -127
  101. package/dist/typechecker.d.ts.map +0 -1
  102. package/src/build-emitter.ts +0 -64
  103. package/src/builder.ts +0 -498
  104. package/src/bundler.ts +0 -575
  105. package/src/commands/compile.ts +0 -236
  106. package/src/commands/packages.ts +0 -154
  107. package/src/commands/run.ts +0 -245
  108. package/src/internal.ts +0 -119
  109. package/src/loader.ts +0 -229
  110. package/src/packages.ts +0 -936
  111. package/src/sandbox.ts +0 -398
  112. package/src/shared-modules.ts +0 -280
  113. package/src/shared-resources.ts +0 -166
  114. package/src/ts-libs.ts +0 -218
  115. package/src/typechecker.ts +0 -635
package/dist/internal.js DELETED
@@ -1,1942 +0,0 @@
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
-
9
- // src/loader.ts
10
- class ModuleLoadError extends Error {
11
- constructor(message, cause) {
12
- super(message, { cause });
13
- this.name = "ModuleLoadError";
14
- }
15
- }
16
-
17
- class ExportNotFoundError extends Error {
18
- exportName;
19
- availableExports;
20
- constructor(exportName, availableExports) {
21
- super(`Export "${exportName}" not found. Available exports: ${availableExports.length > 0 ? availableExports.join(", ") : "(none)"}`);
22
- this.exportName = exportName;
23
- this.availableExports = availableExports;
24
- this.name = "ExportNotFoundError";
25
- }
26
- }
27
- function createModuleUrl(result) {
28
- const blob = new Blob([result.code], { type: "application/javascript" });
29
- return URL.createObjectURL(blob);
30
- }
31
- function revokeModuleUrl(url) {
32
- URL.revokeObjectURL(url);
33
- }
34
- async function loadModule(result) {
35
- const url = createModuleUrl(result);
36
- try {
37
- const module = await import(url);
38
- return module;
39
- } catch (err) {
40
- throw new ModuleLoadError(`Failed to load module: ${err instanceof Error ? err.message : String(err)}`, err);
41
- } finally {
42
- revokeModuleUrl(url);
43
- }
44
- }
45
- async function loadExport(result, exportName = "default") {
46
- const module = await loadModule(result);
47
- if (!(exportName in module)) {
48
- const availableExports = Object.keys(module).filter((key) => !key.startsWith("__"));
49
- throw new ExportNotFoundError(exportName, availableExports);
50
- }
51
- return module[exportName];
52
- }
53
- async function loadDefault(result) {
54
- return loadExport(result, "default");
55
- }
56
- async function getExportNames(result) {
57
- const module = await loadModule(result);
58
- return Object.keys(module).filter((key) => !key.startsWith("__"));
59
- }
60
- async function hasExport(result, exportName) {
61
- const module = await loadModule(result);
62
- return exportName in module;
63
- }
64
- // src/packages.ts
65
- var ESM_CDN_BASE = "https://esm.sh";
66
- var KNOWN_SUBPATHS = {
67
- react: ["jsx-runtime", "jsx-dev-runtime"],
68
- "react-dom": ["client", "server"]
69
- };
70
-
71
- class InMemoryTypesCache {
72
- cache = new Map;
73
- key(name, version) {
74
- return `${name}@${version}`;
75
- }
76
- get(name, version) {
77
- return this.cache.get(this.key(name, version)) ?? null;
78
- }
79
- set(name, version, types) {
80
- this.cache.set(this.key(name, version), types);
81
- }
82
- has(name, version) {
83
- return this.cache.has(this.key(name, version));
84
- }
85
- delete(name, version) {
86
- return this.cache.delete(this.key(name, version));
87
- }
88
- clear() {
89
- this.cache.clear();
90
- }
91
- get size() {
92
- return this.cache.size;
93
- }
94
- }
95
- var PACKAGE_JSON_PATH = "/package.json";
96
- function parsePackageSpec(spec) {
97
- if (spec.startsWith("@")) {
98
- const slashIndex = spec.indexOf("/");
99
- if (slashIndex === -1) {
100
- return { name: spec };
101
- }
102
- const afterSlash = spec.slice(slashIndex + 1);
103
- const atIndex2 = afterSlash.indexOf("@");
104
- if (atIndex2 === -1) {
105
- return { name: spec };
106
- }
107
- return {
108
- name: spec.slice(0, slashIndex + 1 + atIndex2),
109
- version: afterSlash.slice(atIndex2 + 1)
110
- };
111
- }
112
- const atIndex = spec.indexOf("@");
113
- if (atIndex === -1) {
114
- return { name: spec };
115
- }
116
- return {
117
- name: spec.slice(0, atIndex),
118
- version: spec.slice(atIndex + 1)
119
- };
120
- }
121
- function isTypesPackage(name) {
122
- return name.startsWith("@types/");
123
- }
124
- function extractVersionFromUrl(url, packageName) {
125
- const exactRegex = new RegExp(`${escapeRegExp(packageName)}@([^/]+)`);
126
- const exactMatch = url.match(exactRegex);
127
- if (exactMatch?.[1]) {
128
- return exactMatch[1];
129
- }
130
- if (packageName.startsWith("@")) {
131
- const scopedParts = packageName.split("/");
132
- if (scopedParts.length === 2 && scopedParts[1]) {
133
- const partialRegex = new RegExp(`${escapeRegExp(scopedParts[1])}@([^/]+)`);
134
- const partialMatch = url.match(partialRegex);
135
- if (partialMatch?.[1]) {
136
- return partialMatch[1];
137
- }
138
- }
139
- }
140
- const genericMatch = url.match(/@(\d+\.\d+\.\d+[^/]*)/);
141
- if (genericMatch?.[1]) {
142
- return genericMatch[1];
143
- }
144
- return null;
145
- }
146
- async function fetchVersionFromNpm(name) {
147
- const registryUrl = `https://registry.npmjs.org/${name}/latest`;
148
- const response = await fetch(registryUrl);
149
- if (!response.ok) {
150
- throw new Error(`Failed to fetch version from npm: ${response.status}`);
151
- }
152
- const data = await response.json();
153
- return data.version;
154
- }
155
- function extractVersionFromHeaders(headers, packageName) {
156
- const esmId = headers.get("x-esm-id");
157
- if (esmId) {
158
- const version = extractVersionFromUrl(esmId, packageName);
159
- if (version)
160
- return version;
161
- }
162
- const typesHeader = headers.get("X-TypeScript-Types");
163
- if (typesHeader) {
164
- const versionMatch = typesHeader.match(/@(\d+\.\d+\.\d+[^/]*)/);
165
- if (versionMatch?.[1]) {
166
- return versionMatch[1];
167
- }
168
- }
169
- return null;
170
- }
171
- async function fetchPackageInfo(name, version, subpath) {
172
- let url = version ? `${ESM_CDN_BASE}/${name}@${version}` : `${ESM_CDN_BASE}/${name}`;
173
- if (subpath) {
174
- url += `/${subpath}`;
175
- }
176
- const response = await fetch(url, { method: "HEAD" });
177
- if (!response.ok) {
178
- throw new Error(`Package not found: ${name}${version ? `@${version}` : ""}${subpath ? `/${subpath}` : ""}`);
179
- }
180
- const resolvedUrl = response.url;
181
- let resolvedVersion = extractVersionFromUrl(resolvedUrl, name);
182
- if (!resolvedVersion) {
183
- resolvedVersion = extractVersionFromHeaders(response.headers, name);
184
- }
185
- if (!resolvedVersion && version && version !== "latest") {
186
- resolvedVersion = version;
187
- }
188
- if (!resolvedVersion) {
189
- try {
190
- resolvedVersion = await fetchVersionFromNpm(name);
191
- } catch (err) {
192
- console.warn(`Could not resolve version for ${name}:`, err);
193
- resolvedVersion = "latest";
194
- }
195
- }
196
- const typesUrl = response.headers.get("X-TypeScript-Types") ?? undefined;
197
- return {
198
- version: resolvedVersion,
199
- typesUrl: typesUrl ? new URL(typesUrl, resolvedUrl).href : undefined
200
- };
201
- }
202
- function escapeRegExp(string) {
203
- return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
204
- }
205
- async function fetchTypeDefinitions(typesUrl, packageName) {
206
- const types = new Map;
207
- try {
208
- const response = await fetch(typesUrl);
209
- if (!response.ok) {
210
- throw new Error(`Failed to fetch types: ${response.status}`);
211
- }
212
- const content = await response.text();
213
- const typePath = `/node_modules/${packageName}/index.d.ts`;
214
- types.set(typePath, content);
215
- const refs = parseTypeReferences(content);
216
- await fetchReferencedTypes(refs, typesUrl, packageName, types);
217
- } catch (err) {
218
- console.warn(`Failed to fetch types for ${packageName}:`, err);
219
- throw err;
220
- }
221
- return types;
222
- }
223
- function parseTypeReferences(content) {
224
- const paths = [];
225
- const types = [];
226
- const pathRegex = /\/\/\/\s*<reference\s+path="([^"]+)"\s*\/>/g;
227
- let match;
228
- while ((match = pathRegex.exec(content)) !== null) {
229
- if (match[1])
230
- paths.push(match[1]);
231
- }
232
- const typesRegex = /\/\/\/\s*<reference\s+types="([^"]+)"\s*\/>/g;
233
- while ((match = typesRegex.exec(content)) !== null) {
234
- if (match[1])
235
- types.push(match[1]);
236
- }
237
- return { paths, types };
238
- }
239
- async function fetchReferencedTypes(refs, baseUrl, packageName, collected, visited = new Set) {
240
- for (const pathRef of refs.paths) {
241
- const refUrl = new URL(pathRef, baseUrl).href;
242
- if (visited.has(refUrl))
243
- continue;
244
- visited.add(refUrl);
245
- try {
246
- const response = await fetch(refUrl);
247
- if (!response.ok)
248
- continue;
249
- const content = await response.text();
250
- const fileName = pathRef.split("/").pop() ?? "types.d.ts";
251
- const typePath = `/node_modules/${packageName}/${fileName}`;
252
- collected.set(typePath, content);
253
- const nestedRefs = parseTypeReferences(content);
254
- await fetchReferencedTypes(nestedRefs, refUrl, packageName, collected, visited);
255
- } catch {}
256
- }
257
- }
258
- async function fetchSubpathTypes(packageName, subpath, version) {
259
- const types = new Map;
260
- try {
261
- const info = await fetchPackageInfo(packageName, version, subpath);
262
- if (!info.typesUrl) {
263
- return types;
264
- }
265
- const response = await fetch(info.typesUrl);
266
- if (!response.ok) {
267
- return types;
268
- }
269
- const content = await response.text();
270
- const typePath = `/node_modules/${packageName}/${subpath}.d.ts`;
271
- types.set(typePath, content);
272
- const indexTypePath = `/node_modules/${packageName}/${subpath}/index.d.ts`;
273
- types.set(indexTypePath, content);
274
- const refs = parseTypeReferences(content);
275
- await fetchReferencedTypes(refs, info.typesUrl, packageName, types);
276
- } catch (err) {
277
- console.warn(`Failed to fetch types for ${packageName}/${subpath}:`, err);
278
- }
279
- return types;
280
- }
281
- async function fetchTypesPackageContent(name, version) {
282
- const url = version ? `${ESM_CDN_BASE}/${name}@${version}` : `${ESM_CDN_BASE}/${name}`;
283
- const headResponse = await fetch(url, { method: "HEAD" });
284
- if (!headResponse.ok) {
285
- throw new Error(`Package not found: ${name}${version ? `@${version}` : ""}`);
286
- }
287
- const resolvedVersion = extractVersionFromUrl(headResponse.url, name) ?? version ?? "latest";
288
- const indexUrl = `${ESM_CDN_BASE}/${name}@${resolvedVersion}/index.d.ts`;
289
- const response = await fetch(indexUrl);
290
- if (!response.ok) {
291
- throw new Error(`Failed to fetch types from ${name}: ${response.status}`);
292
- }
293
- const content = await response.text();
294
- const types = new Map;
295
- const typePath = `/node_modules/${name}/index.d.ts`;
296
- types.set(typePath, content);
297
- const refs = parseTypeReferences(content);
298
- for (const pathRef of refs.paths) {
299
- try {
300
- const refUrl = new URL(pathRef, indexUrl).href;
301
- const refResponse = await fetch(refUrl);
302
- if (refResponse.ok) {
303
- const refContent = await refResponse.text();
304
- const fileName = pathRef.startsWith("./") ? pathRef.slice(2) : pathRef;
305
- const refTypePath = `/node_modules/${name}/${fileName}`;
306
- types.set(refTypePath, refContent);
307
- }
308
- } catch {}
309
- }
310
- return { version: resolvedVersion, types };
311
- }
312
- async function getPackageManifest(fs) {
313
- try {
314
- if (await fs.exists(PACKAGE_JSON_PATH)) {
315
- const content = await fs.readFile(PACKAGE_JSON_PATH);
316
- const parsed = JSON.parse(content);
317
- return {
318
- dependencies: parsed.dependencies ?? {}
319
- };
320
- }
321
- } catch {}
322
- return { dependencies: {} };
323
- }
324
- async function savePackageManifest(fs, manifest) {
325
- let existing = {};
326
- try {
327
- if (await fs.exists(PACKAGE_JSON_PATH)) {
328
- const content = await fs.readFile(PACKAGE_JSON_PATH);
329
- existing = JSON.parse(content);
330
- }
331
- } catch {}
332
- const updated = {
333
- ...existing,
334
- dependencies: manifest.dependencies
335
- };
336
- await fs.writeFile(PACKAGE_JSON_PATH, JSON.stringify(updated, null, 2));
337
- }
338
- async function installPackage(fs, packageSpec, options) {
339
- const { name, version } = parsePackageSpec(packageSpec);
340
- const { cache } = options ?? {};
341
- if (isTypesPackage(name)) {
342
- return installTypesPackage(fs, name, version, cache);
343
- }
344
- const info = await fetchPackageInfo(name, version);
345
- const packageDir = `/node_modules/${name}`;
346
- await ensureDir(fs, packageDir);
347
- const packageJsonPath = `${packageDir}/package.json`;
348
- const packageJson = {
349
- name,
350
- version: info.version,
351
- types: "./index.d.ts",
352
- main: "./index.js"
353
- };
354
- await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
355
- let typeFiles = null;
356
- let fromCache = false;
357
- if (cache) {
358
- typeFiles = cache.get(name, info.version);
359
- if (typeFiles) {
360
- fromCache = true;
361
- }
362
- }
363
- let typesError;
364
- if (!typeFiles) {
365
- typeFiles = new Map;
366
- if (info.typesUrl) {
367
- try {
368
- const mainTypes = await fetchTypeDefinitions(info.typesUrl, name);
369
- for (const [path, content] of mainTypes) {
370
- typeFiles.set(path, content);
371
- }
372
- } catch (err) {
373
- typesError = err instanceof Error ? err.message : String(err);
374
- }
375
- } else {
376
- typesError = "No TypeScript types available from esm.sh";
377
- }
378
- const knownSubpaths = KNOWN_SUBPATHS[name];
379
- if (knownSubpaths && knownSubpaths.length > 0) {
380
- const subpathResults = await Promise.allSettled(knownSubpaths.map((subpath) => fetchSubpathTypes(name, subpath, info.version)));
381
- for (const result of subpathResults) {
382
- if (result.status === "fulfilled") {
383
- for (const [path, content] of result.value) {
384
- typeFiles.set(path, content);
385
- }
386
- }
387
- }
388
- }
389
- if (cache && typeFiles.size > 0) {
390
- cache.set(name, info.version, typeFiles);
391
- }
392
- }
393
- for (const [path, content] of typeFiles) {
394
- const dir = path.substring(0, path.lastIndexOf("/"));
395
- await ensureDir(fs, dir);
396
- await fs.writeFile(path, content);
397
- }
398
- const manifest = await getPackageManifest(fs);
399
- manifest.dependencies[name] = info.version;
400
- await savePackageManifest(fs, manifest);
401
- return {
402
- name,
403
- version: info.version,
404
- typesInstalled: typeFiles.size > 0,
405
- typeFilesCount: typeFiles.size,
406
- typesError,
407
- fromCache
408
- };
409
- }
410
- async function installTypesPackage(fs, name, version, cache) {
411
- const url = version ? `${ESM_CDN_BASE}/${name}@${version}` : `${ESM_CDN_BASE}/${name}`;
412
- const headResponse = await fetch(url, { method: "HEAD" });
413
- if (!headResponse.ok) {
414
- throw new Error(`Package not found: ${name}${version ? `@${version}` : ""}`);
415
- }
416
- const resolvedVersion = extractVersionFromUrl(headResponse.url, name) ?? version ?? "latest";
417
- let types = null;
418
- let fromCache = false;
419
- if (cache) {
420
- types = cache.get(name, resolvedVersion);
421
- if (types) {
422
- fromCache = true;
423
- }
424
- }
425
- if (!types) {
426
- const result = await fetchTypesPackageContent(name, version);
427
- types = result.types;
428
- if (cache && types.size > 0) {
429
- cache.set(name, resolvedVersion, types);
430
- }
431
- }
432
- const packageDir = `/node_modules/${name}`;
433
- await ensureDir(fs, packageDir);
434
- const packageJsonPath = `${packageDir}/package.json`;
435
- const packageJson = {
436
- name,
437
- version: resolvedVersion,
438
- types: "./index.d.ts"
439
- };
440
- await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
441
- for (const [path, content] of types) {
442
- const dir = path.substring(0, path.lastIndexOf("/"));
443
- await ensureDir(fs, dir);
444
- await fs.writeFile(path, content);
445
- }
446
- const manifest = await getPackageManifest(fs);
447
- manifest.dependencies[name] = resolvedVersion;
448
- await savePackageManifest(fs, manifest);
449
- return {
450
- name,
451
- version: resolvedVersion,
452
- typesInstalled: types.size > 0,
453
- typeFilesCount: types.size,
454
- fromCache
455
- };
456
- }
457
- async function ensureDir(fs, path) {
458
- if (path === "/" || path === "")
459
- return;
460
- if (await fs.exists(path)) {
461
- const stat = await fs.stat(path);
462
- if (stat.isDirectory)
463
- return;
464
- }
465
- const parent = path.substring(0, path.lastIndexOf("/")) || "/";
466
- await ensureDir(fs, parent);
467
- await fs.mkdir(path);
468
- }
469
- async function uninstallPackage(fs, packageName) {
470
- const manifest = await getPackageManifest(fs);
471
- if (!(packageName in manifest.dependencies)) {
472
- return false;
473
- }
474
- delete manifest.dependencies[packageName];
475
- await savePackageManifest(fs, manifest);
476
- const typesPath = `/node_modules/${packageName}`;
477
- if (await fs.exists(typesPath)) {
478
- await removePath(fs, typesPath);
479
- }
480
- return true;
481
- }
482
- async function removePath(fs, path) {
483
- if (!await fs.exists(path))
484
- return;
485
- await fs.rm(path, { recursive: true, force: true });
486
- }
487
- function resolveToEsmUrl(importPath, installedPackages) {
488
- const { packageName, subpath } = parseImportPath(importPath);
489
- const version = installedPackages[packageName];
490
- if (!version) {
491
- return null;
492
- }
493
- const baseUrl = `${ESM_CDN_BASE}/${packageName}@${version}`;
494
- return subpath ? `${baseUrl}/${subpath}` : baseUrl;
495
- }
496
- function parseImportPath(importPath) {
497
- if (importPath.startsWith("@")) {
498
- const parts = importPath.split("/");
499
- if (parts.length >= 2) {
500
- const packageName = `${parts[0]}/${parts[1]}`;
501
- const subpath = parts.slice(2).join("/") || undefined;
502
- return { packageName, subpath };
503
- }
504
- return { packageName: importPath };
505
- }
506
- const slashIndex = importPath.indexOf("/");
507
- if (slashIndex === -1) {
508
- return { packageName: importPath };
509
- }
510
- return {
511
- packageName: importPath.slice(0, slashIndex),
512
- subpath: importPath.slice(slashIndex + 1)
513
- };
514
- }
515
- async function listPackages(fs) {
516
- const manifest = await getPackageManifest(fs);
517
- return Object.entries(manifest.dependencies).map(([name, version]) => ({
518
- name,
519
- version
520
- }));
521
- }
522
- // src/ts-libs.ts
523
- var TS_VERSION = "5.9.3";
524
- var CDN_BASE = `https://cdn.jsdelivr.net/npm/typescript@${TS_VERSION}/lib`;
525
- function getDefaultBrowserLibs() {
526
- return ["es2020", "dom", "dom.iterable"];
527
- }
528
- function parseLibReferences(content) {
529
- const refs = [];
530
- const regex = /\/\/\/\s*<reference\s+lib="([^"]+)"\s*\/>/g;
531
- let match;
532
- while ((match = regex.exec(content)) !== null) {
533
- if (match[1]) {
534
- refs.push(match[1]);
535
- }
536
- }
537
- return refs;
538
- }
539
- function libNameToFileName(name) {
540
- return `lib.${name}.d.ts`;
541
- }
542
- function extractLibName(filePath) {
543
- const match = filePath.match(/lib\.([^/]+)\.d\.ts$/);
544
- return match?.[1] ?? null;
545
- }
546
- async function fetchLibFile(name) {
547
- const fileName = libNameToFileName(name);
548
- const url = `${CDN_BASE}/${fileName}`;
549
- const response = await fetch(url);
550
- if (!response.ok) {
551
- throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);
552
- }
553
- return response.text();
554
- }
555
- async function fetchAllLibs(libs) {
556
- const result = new Map;
557
- const pending = new Set(libs);
558
- const fetched = new Set;
559
- while (pending.size > 0) {
560
- const batch = Array.from(pending);
561
- pending.clear();
562
- const results = await Promise.all(batch.map(async (name) => {
563
- if (fetched.has(name)) {
564
- return { name, content: null };
565
- }
566
- fetched.add(name);
567
- try {
568
- const content = await fetchLibFile(name);
569
- return { name, content };
570
- } catch (err) {
571
- console.warn(`Failed to fetch lib.${name}.d.ts:`, err);
572
- return { name, content: null };
573
- }
574
- }));
575
- for (const { name, content } of results) {
576
- if (content === null)
577
- continue;
578
- result.set(name, content);
579
- const refs = parseLibReferences(content);
580
- for (const ref of refs) {
581
- if (!fetched.has(ref) && !pending.has(ref)) {
582
- pending.add(ref);
583
- }
584
- }
585
- }
586
- }
587
- return result;
588
- }
589
- var memoryCache = null;
590
-
591
- class LibCache {
592
- async getOrFetch(libs) {
593
- if (memoryCache) {
594
- const missing = libs.filter((lib) => !memoryCache.has(lib));
595
- if (missing.length === 0) {
596
- return memoryCache;
597
- }
598
- console.log(`Cache missing libs: ${missing.join(", ")}, fetching all...`);
599
- }
600
- console.log(`Fetching TypeScript libs from CDN: ${libs.join(", ")}...`);
601
- const fetched = await fetchAllLibs(libs);
602
- console.log(`Fetched ${fetched.size} lib files`);
603
- memoryCache = fetched;
604
- return fetched;
605
- }
606
- get() {
607
- return memoryCache;
608
- }
609
- set(libs) {
610
- memoryCache = libs;
611
- }
612
- clear() {
613
- memoryCache = null;
614
- }
615
- }
616
- async function fetchAndCacheLibs(libs = getDefaultBrowserLibs()) {
617
- const cache = new LibCache;
618
- return cache.getOrFetch(libs);
619
- }
620
- // src/shared-modules.ts
621
- var GLOBAL_KEY = "__sandlot_shared_modules__";
622
-
623
- class SharedModuleRegistry {
624
- modules = new Map;
625
- exportNames = new Map;
626
- constructor() {
627
- globalThis[GLOBAL_KEY] = this;
628
- }
629
- register(moduleId, module) {
630
- this.modules.set(moduleId, module);
631
- this.exportNames.set(moduleId, introspectExports(module));
632
- return this;
633
- }
634
- registerAll(modules) {
635
- for (const [id, mod] of Object.entries(modules)) {
636
- this.register(id, mod);
637
- }
638
- return this;
639
- }
640
- unregister(moduleId) {
641
- return this.modules.delete(moduleId);
642
- }
643
- get(moduleId) {
644
- const mod = this.modules.get(moduleId);
645
- if (mod === undefined && !this.modules.has(moduleId)) {
646
- const available = this.list();
647
- throw new Error(`Shared module "${moduleId}" not registered. ` + `Available: ${available.length > 0 ? available.join(", ") : "(none)"}. ` + `Call registerSharedModules({ '${moduleId}': ... }) in your host application.`);
648
- }
649
- return mod;
650
- }
651
- has(moduleId) {
652
- return this.modules.has(moduleId);
653
- }
654
- list() {
655
- return [...this.modules.keys()];
656
- }
657
- getExportNames(moduleId) {
658
- return this.exportNames.get(moduleId) ?? [];
659
- }
660
- clear() {
661
- this.modules.clear();
662
- this.exportNames.clear();
663
- }
664
- get size() {
665
- return this.modules.size;
666
- }
667
- }
668
- function introspectExports(module) {
669
- if (module === null || module === undefined) {
670
- return [];
671
- }
672
- if (typeof module !== "object" && typeof module !== "function") {
673
- return [];
674
- }
675
- const exports = [];
676
- for (const key of Object.keys(module)) {
677
- if (isValidIdentifier(key)) {
678
- exports.push(key);
679
- }
680
- }
681
- return exports;
682
- }
683
- function isValidIdentifier(name) {
684
- if (name.length === 0)
685
- return false;
686
- if (!/^[a-zA-Z_$]/.test(name))
687
- return false;
688
- if (!/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name))
689
- return false;
690
- const reserved = ["default", "class", "function", "var", "let", "const", "import", "export"];
691
- if (reserved.includes(name))
692
- return false;
693
- return true;
694
- }
695
- var defaultRegistry = null;
696
- function getSharedModuleRegistry() {
697
- if (!defaultRegistry) {
698
- defaultRegistry = new SharedModuleRegistry;
699
- }
700
- return defaultRegistry;
701
- }
702
- function hasSharedModuleRegistry() {
703
- return GLOBAL_KEY in globalThis;
704
- }
705
- function registerSharedModules(modules) {
706
- getSharedModuleRegistry().registerAll(modules);
707
- }
708
- function unregisterSharedModule(moduleId) {
709
- return getSharedModuleRegistry().unregister(moduleId);
710
- }
711
- function clearSharedModules() {
712
- getSharedModuleRegistry().clear();
713
- }
714
- function getSharedModuleExports(moduleId) {
715
- return getSharedModuleRegistry().getExportNames(moduleId);
716
- }
717
- function getSharedModuleRuntimeCode(moduleId) {
718
- return `
719
- (function() {
720
- var registry = globalThis["${GLOBAL_KEY}"];
721
- if (!registry) {
722
- throw new Error(
723
- 'Sandlot SharedModuleRegistry not found. ' +
724
- 'Call registerSharedModules() in your host application before loading dynamic modules.'
725
- );
726
- }
727
- return registry.get(${JSON.stringify(moduleId)});
728
- })()
729
- `.trim();
730
- }
731
- // src/commands/types.ts
732
- function formatEsbuildMessages(messages) {
733
- if (messages.length === 0)
734
- return "";
735
- return messages.map((msg) => {
736
- if (msg.location) {
737
- const { file, line, column } = msg.location;
738
- const loc = file ? `${file}${line ? `:${line}` : ""}${column ? `:${column}` : ""}` : "";
739
- return loc ? `${loc}: ${msg.text}` : msg.text;
740
- }
741
- return msg.text;
742
- }).join(`
743
- `);
744
- }
745
- // src/commands/compile.ts
746
- import { defineCommand } from "just-bash/browser";
747
-
748
- // src/typechecker.ts
749
- import ts from "typescript";
750
- function categoryToString(category) {
751
- switch (category) {
752
- case ts.DiagnosticCategory.Error:
753
- return "error";
754
- case ts.DiagnosticCategory.Warning:
755
- return "warning";
756
- case ts.DiagnosticCategory.Suggestion:
757
- return "suggestion";
758
- case ts.DiagnosticCategory.Message:
759
- return "message";
760
- default:
761
- return "error";
762
- }
763
- }
764
- function convertDiagnostic(diag) {
765
- let file = null;
766
- let line = null;
767
- let column = null;
768
- if (diag.file && diag.start !== undefined) {
769
- file = diag.file.fileName;
770
- const pos = diag.file.getLineAndCharacterOfPosition(diag.start);
771
- line = pos.line + 1;
772
- column = pos.character + 1;
773
- }
774
- return {
775
- file,
776
- line,
777
- column,
778
- code: diag.code,
779
- category: categoryToString(diag.category),
780
- message: ts.flattenDiagnosticMessageText(diag.messageText, `
781
- `)
782
- };
783
- }
784
- function normalizePath(path) {
785
- if (!path.startsWith("/")) {
786
- return "/" + path;
787
- }
788
- return path;
789
- }
790
- async function preloadFiles(fs) {
791
- const cache = new Map;
792
- const allPaths = fs.getAllPaths();
793
- for (const path of allPaths) {
794
- if (path.endsWith(".ts") || path.endsWith(".tsx") || path.endsWith(".js") || path.endsWith(".jsx") || path.endsWith(".json") || path.endsWith(".d.ts")) {
795
- try {
796
- const stat = await fs.stat(path);
797
- if (stat.isFile) {
798
- const content = await fs.readFile(path);
799
- cache.set(path, content);
800
- }
801
- } catch {}
802
- }
803
- }
804
- return cache;
805
- }
806
- function parseTsConfig(configText, _configPath) {
807
- try {
808
- const config = JSON.parse(configText);
809
- const compilerOptions = config.compilerOptions || {};
810
- const options = {
811
- ...getDefaultCompilerOptions()
812
- };
813
- if (compilerOptions.target) {
814
- const targetMap = {
815
- es5: ts.ScriptTarget.ES5,
816
- es6: ts.ScriptTarget.ES2015,
817
- es2015: ts.ScriptTarget.ES2015,
818
- es2016: ts.ScriptTarget.ES2016,
819
- es2017: ts.ScriptTarget.ES2017,
820
- es2018: ts.ScriptTarget.ES2018,
821
- es2019: ts.ScriptTarget.ES2019,
822
- es2020: ts.ScriptTarget.ES2020,
823
- es2021: ts.ScriptTarget.ES2021,
824
- es2022: ts.ScriptTarget.ES2022,
825
- esnext: ts.ScriptTarget.ESNext
826
- };
827
- options.target = targetMap[compilerOptions.target.toLowerCase()] ?? ts.ScriptTarget.ES2020;
828
- }
829
- if (compilerOptions.module) {
830
- const moduleMap = {
831
- commonjs: ts.ModuleKind.CommonJS,
832
- amd: ts.ModuleKind.AMD,
833
- umd: ts.ModuleKind.UMD,
834
- system: ts.ModuleKind.System,
835
- es6: ts.ModuleKind.ES2015,
836
- es2015: ts.ModuleKind.ES2015,
837
- es2020: ts.ModuleKind.ES2020,
838
- es2022: ts.ModuleKind.ES2022,
839
- esnext: ts.ModuleKind.ESNext,
840
- node16: ts.ModuleKind.Node16,
841
- nodenext: ts.ModuleKind.NodeNext
842
- };
843
- options.module = moduleMap[compilerOptions.module.toLowerCase()] ?? ts.ModuleKind.ESNext;
844
- }
845
- if (compilerOptions.moduleResolution) {
846
- const resolutionMap = {
847
- classic: ts.ModuleResolutionKind.Classic,
848
- node: ts.ModuleResolutionKind.NodeJs,
849
- node10: ts.ModuleResolutionKind.NodeJs,
850
- node16: ts.ModuleResolutionKind.Node16,
851
- nodenext: ts.ModuleResolutionKind.NodeNext,
852
- bundler: ts.ModuleResolutionKind.Bundler
853
- };
854
- options.moduleResolution = resolutionMap[compilerOptions.moduleResolution.toLowerCase()] ?? ts.ModuleResolutionKind.Bundler;
855
- }
856
- if (compilerOptions.jsx) {
857
- const jsxMap = {
858
- preserve: ts.JsxEmit.Preserve,
859
- react: ts.JsxEmit.React,
860
- "react-jsx": ts.JsxEmit.ReactJSX,
861
- "react-jsxdev": ts.JsxEmit.ReactJSXDev,
862
- "react-native": ts.JsxEmit.ReactNative
863
- };
864
- options.jsx = jsxMap[compilerOptions.jsx.toLowerCase()] ?? ts.JsxEmit.ReactJSX;
865
- }
866
- if (compilerOptions.strict !== undefined)
867
- options.strict = compilerOptions.strict;
868
- if (compilerOptions.esModuleInterop !== undefined)
869
- options.esModuleInterop = compilerOptions.esModuleInterop;
870
- if (compilerOptions.skipLibCheck !== undefined)
871
- options.skipLibCheck = compilerOptions.skipLibCheck;
872
- if (compilerOptions.allowJs !== undefined)
873
- options.allowJs = compilerOptions.allowJs;
874
- if (compilerOptions.resolveJsonModule !== undefined)
875
- options.resolveJsonModule = compilerOptions.resolveJsonModule;
876
- if (compilerOptions.noImplicitAny !== undefined)
877
- options.noImplicitAny = compilerOptions.noImplicitAny;
878
- if (compilerOptions.strictNullChecks !== undefined)
879
- options.strictNullChecks = compilerOptions.strictNullChecks;
880
- if (Array.isArray(compilerOptions.lib)) {
881
- options.lib = compilerOptions.lib.map((lib) => lib.toLowerCase().startsWith("lib.") ? lib : `lib.${lib.toLowerCase()}.d.ts`);
882
- }
883
- options.noEmit = true;
884
- return options;
885
- } catch (err) {
886
- console.warn("Error parsing tsconfig.json:", err);
887
- return getDefaultCompilerOptions();
888
- }
889
- }
890
- function getDefaultCompilerOptions() {
891
- return {
892
- target: ts.ScriptTarget.ES2020,
893
- module: ts.ModuleKind.ESNext,
894
- moduleResolution: ts.ModuleResolutionKind.Bundler,
895
- esModuleInterop: true,
896
- strict: true,
897
- skipLibCheck: true,
898
- noEmit: true,
899
- jsx: ts.JsxEmit.ReactJSX,
900
- allowJs: true,
901
- resolveJsonModule: true,
902
- noLib: false,
903
- lib: [
904
- "lib.es2020.d.ts",
905
- "lib.dom.d.ts",
906
- "lib.dom.iterable.d.ts"
907
- ]
908
- };
909
- }
910
- var LIB_PATH_PREFIX = "/node_modules/typescript/lib/";
911
- function createVfsCompilerHost(fileCache, libFiles, _options) {
912
- function getLibContent(fileName) {
913
- const libMatch = fileName.match(/lib\.([^/]+)\.d\.ts$/);
914
- if (libMatch && libMatch[1]) {
915
- return libFiles.get(libMatch[1]);
916
- }
917
- return;
918
- }
919
- return {
920
- getSourceFile(fileName, languageVersion, onError) {
921
- const normalizedPath = normalizePath(fileName);
922
- const content = fileCache.get(normalizedPath);
923
- if (content !== undefined) {
924
- return ts.createSourceFile(normalizedPath, content, languageVersion, true);
925
- }
926
- const altContent = fileCache.get(fileName);
927
- if (altContent !== undefined) {
928
- return ts.createSourceFile(fileName, altContent, languageVersion, true);
929
- }
930
- const libContent = getLibContent(fileName);
931
- if (libContent !== undefined) {
932
- return ts.createSourceFile(fileName, libContent, languageVersion, true);
933
- }
934
- if (onError) {
935
- onError(`File not found: ${fileName}`);
936
- }
937
- return;
938
- },
939
- getDefaultLibFileName(options) {
940
- return LIB_PATH_PREFIX + ts.getDefaultLibFileName(options);
941
- },
942
- writeFile() {},
943
- getCurrentDirectory() {
944
- return "/";
945
- },
946
- getCanonicalFileName(fileName) {
947
- return fileName;
948
- },
949
- useCaseSensitiveFileNames() {
950
- return true;
951
- },
952
- getNewLine() {
953
- return `
954
- `;
955
- },
956
- fileExists(fileName) {
957
- const normalizedPath = normalizePath(fileName);
958
- if (fileCache.has(normalizedPath) || fileCache.has(fileName)) {
959
- return true;
960
- }
961
- return getLibContent(fileName) !== undefined;
962
- },
963
- readFile(fileName) {
964
- const normalizedPath = normalizePath(fileName);
965
- const content = fileCache.get(normalizedPath) ?? fileCache.get(fileName);
966
- if (content !== undefined) {
967
- return content;
968
- }
969
- return getLibContent(fileName);
970
- },
971
- directoryExists(directoryName) {
972
- const normalizedDir = normalizePath(directoryName);
973
- for (const path of fileCache.keys()) {
974
- if (path.startsWith(normalizedDir + "/")) {
975
- return true;
976
- }
977
- }
978
- if (normalizedDir === "/node_modules/typescript/lib" || normalizedDir === "/node_modules/typescript") {
979
- return libFiles.size > 0;
980
- }
981
- if (normalizedDir === "/node_modules") {
982
- return libFiles.size > 0 || Array.from(fileCache.keys()).some((p) => p.startsWith("/node_modules/"));
983
- }
984
- if (normalizedDir === "/node_modules/@types") {
985
- return Array.from(fileCache.keys()).some((p) => p.startsWith("/node_modules/@types/"));
986
- }
987
- return false;
988
- },
989
- getDirectories(path) {
990
- const normalizedPath = normalizePath(path);
991
- const prefix = normalizedPath === "/" ? "/" : normalizedPath + "/";
992
- const dirs = new Set;
993
- for (const filePath of fileCache.keys()) {
994
- if (filePath.startsWith(prefix)) {
995
- const relative = filePath.slice(prefix.length);
996
- const firstSlash = relative.indexOf("/");
997
- if (firstSlash > 0) {
998
- dirs.add(relative.slice(0, firstSlash));
999
- }
1000
- }
1001
- }
1002
- if (normalizedPath === "/") {
1003
- const hasNodeModules = libFiles.size > 0 || Array.from(fileCache.keys()).some((p) => p.startsWith("/node_modules/"));
1004
- if (hasNodeModules) {
1005
- dirs.add("node_modules");
1006
- }
1007
- }
1008
- return Array.from(dirs);
1009
- },
1010
- realpath(path) {
1011
- return path;
1012
- },
1013
- getEnvironmentVariable() {
1014
- return;
1015
- }
1016
- };
1017
- }
1018
- async function typecheck(options) {
1019
- const {
1020
- fs,
1021
- entryPoint,
1022
- tsconfigPath = "/tsconfig.json",
1023
- libFiles = new Map
1024
- } = options;
1025
- const normalizedEntry = normalizePath(entryPoint);
1026
- if (!await fs.exists(normalizedEntry)) {
1027
- throw new Error(`Entry point not found: ${normalizedEntry}`);
1028
- }
1029
- const fileCache = await preloadFiles(fs);
1030
- let compilerOptions = getDefaultCompilerOptions();
1031
- const tsconfigContent = fileCache.get(normalizePath(tsconfigPath));
1032
- if (tsconfigContent) {
1033
- compilerOptions = {
1034
- ...parseTsConfig(tsconfigContent, tsconfigPath),
1035
- noEmit: true
1036
- };
1037
- }
1038
- const host = createVfsCompilerHost(fileCache, libFiles, compilerOptions);
1039
- const program = ts.createProgram([normalizedEntry], compilerOptions, host);
1040
- const allDiagnostics = [
1041
- ...program.getSyntacticDiagnostics(),
1042
- ...program.getSemanticDiagnostics(),
1043
- ...program.getDeclarationDiagnostics()
1044
- ];
1045
- const diagnostics = allDiagnostics.map(convertDiagnostic);
1046
- const checkedFiles = program.getSourceFiles().map((sf) => sf.fileName).filter((f) => !f.includes("node_modules/typescript/lib"));
1047
- const hasErrors = diagnostics.some((d) => d.category === "error");
1048
- return {
1049
- diagnostics,
1050
- hasErrors,
1051
- checkedFiles
1052
- };
1053
- }
1054
- function formatDiagnostics(diagnostics) {
1055
- return diagnostics.map((d) => {
1056
- const location = d.file ? `${d.file}${d.line ? `:${d.line}` : ""}${d.column ? `:${d.column}` : ""}` : "(global)";
1057
- return `${location} - ${d.category} TS${d.code}: ${d.message}`;
1058
- }).join(`
1059
- `);
1060
- }
1061
- function formatDiagnosticsForAgent(diagnostics) {
1062
- if (diagnostics.length === 0) {
1063
- return "No type errors found.";
1064
- }
1065
- const errorCount = diagnostics.filter((d) => d.category === "error").length;
1066
- const warningCount = diagnostics.filter((d) => d.category === "warning").length;
1067
- const summary = errorCount > 0 || warningCount > 0 ? `Found ${errorCount} error(s) and ${warningCount} warning(s):
1068
-
1069
- ` : "";
1070
- const formatted = diagnostics.map((d) => {
1071
- const location = d.file ? `${d.file}${d.line ? ` at line ${d.line}` : ""}` : "Global";
1072
- const prefix = d.category === "error" ? "Error" : d.category === "warning" ? "Warning" : "Info";
1073
- return `${prefix} in ${location}: ${d.message} (TS${d.code})`;
1074
- }).join(`
1075
-
1076
- `);
1077
- return summary + formatted;
1078
- }
1079
-
1080
- // src/bundler.ts
1081
- var esbuild = null;
1082
- function isServerEnvironment() {
1083
- if (typeof globalThis !== "undefined" && "Bun" in globalThis) {
1084
- return true;
1085
- }
1086
- if (typeof globalThis !== "undefined" && "Deno" in globalThis) {
1087
- return true;
1088
- }
1089
- if (typeof process !== "undefined" && process.versions?.node) {
1090
- return true;
1091
- }
1092
- return false;
1093
- }
1094
- async function getEsbuild() {
1095
- if (esbuild)
1096
- return esbuild;
1097
- if (isServerEnvironment()) {
1098
- const mod = await import("esbuild");
1099
- esbuild = mod.default ?? mod;
1100
- } else {
1101
- const cdnUrl = `https://esm.sh/esbuild-wasm@${ESBUILD_VERSION}`;
1102
- const mod = await import(cdnUrl);
1103
- esbuild = mod.default ?? mod;
1104
- if (typeof esbuild?.initialize !== "function") {
1105
- console.error("esbuild-wasm module structure:", mod);
1106
- throw new Error("Failed to load esbuild-wasm: initialize function not found");
1107
- }
1108
- }
1109
- return esbuild;
1110
- }
1111
- var ESBUILD_VERSION = "0.27.2";
1112
- var initialized = false;
1113
- var initPromise = null;
1114
- function getWasmUrl() {
1115
- return `https://unpkg.com/esbuild-wasm@${ESBUILD_VERSION}/esbuild.wasm`;
1116
- }
1117
- function checkCrossOriginIsolation() {
1118
- if (typeof window === "undefined")
1119
- return;
1120
- if (!window.crossOriginIsolated) {
1121
- console.warn(`[sandlot] Cross-origin isolation is not enabled. esbuild-wasm may have reduced performance or fail on some browsers.
1122
- To enable, add these headers to your dev server:
1123
- Cross-Origin-Embedder-Policy: require-corp
1124
- Cross-Origin-Opener-Policy: same-origin
1125
- In Vite, add a plugin to configureServer. See sandlot README for details.`);
1126
- }
1127
- }
1128
- async function initBundler() {
1129
- if (initialized)
1130
- return;
1131
- if (initPromise) {
1132
- await initPromise;
1133
- return;
1134
- }
1135
- initPromise = (async () => {
1136
- const es = await getEsbuild();
1137
- if (!isServerEnvironment() && typeof es.initialize === "function") {
1138
- checkCrossOriginIsolation();
1139
- await es.initialize({
1140
- wasmURL: getWasmUrl()
1141
- });
1142
- }
1143
- })();
1144
- await initPromise;
1145
- initialized = true;
1146
- }
1147
- function isBareImport(path) {
1148
- return !path.startsWith(".") && !path.startsWith("/");
1149
- }
1150
- function getLoader(path) {
1151
- const ext = path.split(".").pop()?.toLowerCase();
1152
- switch (ext) {
1153
- case "ts":
1154
- return "ts";
1155
- case "tsx":
1156
- return "tsx";
1157
- case "jsx":
1158
- return "jsx";
1159
- case "js":
1160
- case "mjs":
1161
- return "js";
1162
- case "json":
1163
- return "json";
1164
- case "css":
1165
- return "css";
1166
- case "txt":
1167
- return "text";
1168
- default:
1169
- return "js";
1170
- }
1171
- }
1172
- function matchesSharedModule(importPath, sharedModuleIds) {
1173
- if (sharedModuleIds.has(importPath)) {
1174
- return importPath;
1175
- }
1176
- for (const moduleId of sharedModuleIds) {
1177
- if (importPath === moduleId || importPath.startsWith(moduleId + "/")) {
1178
- return importPath;
1179
- }
1180
- }
1181
- return null;
1182
- }
1183
- function createVfsPlugin(options) {
1184
- const {
1185
- fs,
1186
- entryPoint,
1187
- npmImports,
1188
- installedPackages,
1189
- includedFiles,
1190
- sharedModuleIds
1191
- } = options;
1192
- return {
1193
- name: "virtual-fs",
1194
- setup(build) {
1195
- build.onResolve({ filter: /.*/ }, async (args) => {
1196
- if (args.kind === "entry-point") {
1197
- return { path: entryPoint, namespace: "vfs" };
1198
- }
1199
- if (isBareImport(args.path)) {
1200
- const sharedMatch = matchesSharedModule(args.path, sharedModuleIds);
1201
- if (sharedMatch) {
1202
- return {
1203
- path: sharedMatch,
1204
- namespace: "sandlot-shared"
1205
- };
1206
- }
1207
- switch (npmImports) {
1208
- case "cdn": {
1209
- const esmUrl = resolveToEsmUrl(args.path, installedPackages);
1210
- if (esmUrl) {
1211
- return { path: esmUrl, external: true };
1212
- }
1213
- return { path: args.path, external: true };
1214
- }
1215
- case "external":
1216
- return { path: args.path, external: true };
1217
- case "bundle": {
1218
- const resolved2 = fs.resolvePath(args.resolveDir, `node_modules/${args.path}`);
1219
- const exists = await fs.exists(resolved2);
1220
- if (exists) {
1221
- return { path: resolved2, namespace: "vfs" };
1222
- }
1223
- return { path: args.path, external: true };
1224
- }
1225
- }
1226
- }
1227
- const resolved = fs.resolvePath(args.resolveDir, args.path);
1228
- const extensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".json"];
1229
- const hasExtension = extensions.some((ext) => resolved.endsWith(ext));
1230
- if (hasExtension) {
1231
- const exists = await fs.exists(resolved);
1232
- if (exists) {
1233
- return { path: resolved, namespace: "vfs" };
1234
- }
1235
- return { errors: [{ text: `File not found: ${resolved}` }] };
1236
- }
1237
- for (const ext of extensions) {
1238
- const withExt = resolved + ext;
1239
- if (await fs.exists(withExt)) {
1240
- return { path: withExt, namespace: "vfs" };
1241
- }
1242
- }
1243
- for (const ext of extensions) {
1244
- const indexPath = `${resolved}/index${ext}`;
1245
- if (await fs.exists(indexPath)) {
1246
- return { path: indexPath, namespace: "vfs" };
1247
- }
1248
- }
1249
- return { errors: [{ text: `Cannot resolve: ${args.path} from ${args.resolveDir}` }] };
1250
- });
1251
- build.onLoad({ filter: /.*/, namespace: "sandlot-shared" }, (args) => {
1252
- const contents = `
1253
- const __sandlot_mod__ = ${getSharedModuleRuntimeCode(args.path)};
1254
- export default __sandlot_mod__.default ?? __sandlot_mod__;
1255
- ${generateNamedExports(args.path)}
1256
- `;
1257
- return {
1258
- contents: contents.trim(),
1259
- loader: "js"
1260
- };
1261
- });
1262
- build.onLoad({ filter: /.*/, namespace: "vfs" }, async (args) => {
1263
- try {
1264
- const contents = await fs.readFile(args.path);
1265
- includedFiles.add(args.path);
1266
- return {
1267
- contents,
1268
- loader: getLoader(args.path),
1269
- resolveDir: args.path.substring(0, args.path.lastIndexOf("/"))
1270
- };
1271
- } catch (err) {
1272
- return {
1273
- errors: [{ text: `Failed to read ${args.path}: ${err}` }]
1274
- };
1275
- }
1276
- });
1277
- }
1278
- };
1279
- }
1280
- function generateNamedExports(moduleId) {
1281
- const exports = getSharedModuleExports(moduleId);
1282
- if (exports.length > 0) {
1283
- return exports.map((name) => `export const ${name} = __sandlot_mod__.${name};`).join(`
1284
- `);
1285
- }
1286
- return `// No exports discovered for "${moduleId}" - use default import or call registerSharedModules() first`;
1287
- }
1288
- async function bundle(options) {
1289
- await initBundler();
1290
- const {
1291
- fs,
1292
- entryPoint,
1293
- external = [],
1294
- npmImports = "cdn",
1295
- sharedModules = [],
1296
- format = "esm",
1297
- minify = false,
1298
- sourcemap = false,
1299
- globalName,
1300
- target = ["es2020"]
1301
- } = options;
1302
- const normalizedEntry = entryPoint.startsWith("/") ? entryPoint : `/${entryPoint}`;
1303
- if (!await fs.exists(normalizedEntry)) {
1304
- throw new Error(`Entry point not found: ${normalizedEntry}`);
1305
- }
1306
- const manifest = await getPackageManifest(fs);
1307
- const installedPackages = manifest.dependencies;
1308
- const sharedModuleIds = new Set(sharedModules);
1309
- const includedFiles = new Set;
1310
- const plugin = createVfsPlugin({
1311
- fs,
1312
- entryPoint: normalizedEntry,
1313
- npmImports,
1314
- installedPackages,
1315
- includedFiles,
1316
- sharedModuleIds
1317
- });
1318
- const es = await getEsbuild();
1319
- const result = await es.build({
1320
- entryPoints: [normalizedEntry],
1321
- bundle: true,
1322
- write: false,
1323
- format,
1324
- minify,
1325
- sourcemap: sourcemap ? "inline" : false,
1326
- globalName,
1327
- target,
1328
- external,
1329
- plugins: [plugin],
1330
- jsx: "automatic"
1331
- });
1332
- const code = result.outputFiles?.[0]?.text ?? "";
1333
- return {
1334
- code,
1335
- warnings: result.warnings,
1336
- includedFiles: Array.from(includedFiles)
1337
- };
1338
- }
1339
- async function bundleToUrl(options) {
1340
- const result = await bundle(options);
1341
- const blob = new Blob([result.code], { type: "application/javascript" });
1342
- return URL.createObjectURL(blob);
1343
- }
1344
- async function bundleAndImport(options) {
1345
- const url = await bundleToUrl(options);
1346
- try {
1347
- return await import(url);
1348
- } finally {
1349
- URL.revokeObjectURL(url);
1350
- }
1351
- }
1352
-
1353
- // src/commands/compile.ts
1354
- function createTscCommand(deps) {
1355
- const { fs, libFiles, tsconfigPath } = deps;
1356
- return defineCommand("tsc", async (args, _ctx) => {
1357
- const entryPoint = args[0];
1358
- if (!entryPoint) {
1359
- return {
1360
- stdout: "",
1361
- stderr: `Usage: tsc <entry-point>
1362
-
1363
- Example: tsc /src/index.ts
1364
- `,
1365
- exitCode: 1
1366
- };
1367
- }
1368
- try {
1369
- if (!await fs.exists(entryPoint)) {
1370
- return {
1371
- stdout: "",
1372
- stderr: `Error: Entry point not found: ${entryPoint}
1373
- `,
1374
- exitCode: 1
1375
- };
1376
- }
1377
- const result = await typecheck({
1378
- fs,
1379
- entryPoint,
1380
- tsconfigPath,
1381
- libFiles
1382
- });
1383
- if (result.hasErrors) {
1384
- const formatted = formatDiagnosticsForAgent(result.diagnostics);
1385
- return {
1386
- stdout: "",
1387
- stderr: formatted + `
1388
- `,
1389
- exitCode: 1
1390
- };
1391
- }
1392
- const checkedCount = result.checkedFiles.length;
1393
- const warningCount = result.diagnostics.filter((d) => d.category === "warning").length;
1394
- let output = `Type check passed. Checked ${checkedCount} file(s).
1395
- `;
1396
- if (warningCount > 0) {
1397
- output += `
1398
- Warnings:
1399
- ${formatDiagnosticsForAgent(result.diagnostics.filter((d) => d.category === "warning"))}
1400
- `;
1401
- }
1402
- return {
1403
- stdout: output,
1404
- stderr: "",
1405
- exitCode: 0
1406
- };
1407
- } catch (err) {
1408
- return {
1409
- stdout: "",
1410
- stderr: `Type check failed: ${err instanceof Error ? err.message : String(err)}
1411
- `,
1412
- exitCode: 1
1413
- };
1414
- }
1415
- });
1416
- }
1417
- function createBuildCommand(deps) {
1418
- const { fs, libFiles, tsconfigPath, onBuild, getValidation, sharedModules } = deps;
1419
- return defineCommand("build", async (args, _ctx) => {
1420
- let entryPoint = null;
1421
- let skipTypecheck = false;
1422
- let minify = false;
1423
- let format = "esm";
1424
- for (let i = 0;i < args.length; i++) {
1425
- const arg = args[i];
1426
- if (arg === "--skip-typecheck" || arg === "-s") {
1427
- skipTypecheck = true;
1428
- } else if (arg === "--minify" || arg === "-m") {
1429
- minify = true;
1430
- } else if ((arg === "--format" || arg === "-f") && args[i + 1]) {
1431
- const f = args[++i].toLowerCase();
1432
- if (f === "esm" || f === "iife" || f === "cjs") {
1433
- format = f;
1434
- }
1435
- } else if (!arg.startsWith("-")) {
1436
- entryPoint = arg;
1437
- }
1438
- }
1439
- if (!entryPoint) {
1440
- return {
1441
- stdout: "",
1442
- stderr: `Usage: build <entry-point> [options]
1443
-
1444
- Options:
1445
- --skip-typecheck, -s Skip type checking
1446
- --minify, -m Minify output
1447
- --format, -f <fmt> Output format (esm|iife|cjs)
1448
-
1449
- Example: build /src/index.ts
1450
- `,
1451
- exitCode: 1
1452
- };
1453
- }
1454
- try {
1455
- if (!await fs.exists(entryPoint)) {
1456
- return {
1457
- stdout: "",
1458
- stderr: `Error: Entry point not found: ${entryPoint}
1459
- `,
1460
- exitCode: 1
1461
- };
1462
- }
1463
- let typecheckResult = null;
1464
- if (!skipTypecheck) {
1465
- typecheckResult = await typecheck({
1466
- fs,
1467
- entryPoint,
1468
- tsconfigPath,
1469
- libFiles
1470
- });
1471
- if (typecheckResult.hasErrors) {
1472
- const formatted = formatDiagnosticsForAgent(typecheckResult.diagnostics);
1473
- return {
1474
- stdout: "",
1475
- stderr: `Build failed: Type errors found.
1476
-
1477
- ${formatted}
1478
- `,
1479
- exitCode: 1
1480
- };
1481
- }
1482
- }
1483
- const bundleResult = await bundle({
1484
- fs,
1485
- entryPoint,
1486
- format,
1487
- minify,
1488
- sharedModules
1489
- });
1490
- let loadedModule;
1491
- try {
1492
- loadedModule = await loadModule(bundleResult);
1493
- } catch (err) {
1494
- const errorMessage = err instanceof Error ? err.message : String(err);
1495
- return {
1496
- stdout: "",
1497
- stderr: `Build failed: Module failed to load.
1498
-
1499
- ${errorMessage}
1500
- `,
1501
- exitCode: 1
1502
- };
1503
- }
1504
- const validateFn = getValidation?.();
1505
- let validatedModule = loadedModule;
1506
- if (validateFn) {
1507
- try {
1508
- validatedModule = validateFn(loadedModule);
1509
- } catch (err) {
1510
- const errorMessage = err instanceof Error ? err.message : String(err);
1511
- return {
1512
- stdout: "",
1513
- stderr: `Build failed: Validation error.
1514
-
1515
- ${errorMessage}
1516
- `,
1517
- exitCode: 1
1518
- };
1519
- }
1520
- }
1521
- if (onBuild) {
1522
- await onBuild({ bundle: bundleResult, module: validatedModule });
1523
- }
1524
- let output = `Build successful!
1525
- `;
1526
- output += `Entry: ${entryPoint}
1527
- `;
1528
- output += `Format: ${format}
1529
- `;
1530
- output += `Size: ${(bundleResult.code.length / 1024).toFixed(2)} KB
1531
- `;
1532
- if (typecheckResult) {
1533
- output += `Type checked: ${typecheckResult.checkedFiles.length} file(s)
1534
- `;
1535
- }
1536
- output += `Bundled: ${bundleResult.includedFiles.length} file(s)
1537
- `;
1538
- const exportNames = Object.keys(loadedModule).filter((k) => !k.startsWith("__"));
1539
- if (exportNames.length > 0) {
1540
- output += `Exports: ${exportNames.join(", ")}
1541
- `;
1542
- }
1543
- if (validateFn) {
1544
- output += `Validation: passed
1545
- `;
1546
- }
1547
- if (bundleResult.warnings.length > 0) {
1548
- output += `
1549
- Build warnings:
1550
- ${formatEsbuildMessages(bundleResult.warnings)}
1551
- `;
1552
- }
1553
- if (typecheckResult) {
1554
- const warnings = typecheckResult.diagnostics.filter((d) => d.category === "warning");
1555
- if (warnings.length > 0) {
1556
- output += `
1557
- Type warnings:
1558
- ${formatDiagnosticsForAgent(warnings)}
1559
- `;
1560
- }
1561
- }
1562
- return {
1563
- stdout: output,
1564
- stderr: "",
1565
- exitCode: 0
1566
- };
1567
- } catch (err) {
1568
- const errorMessage = err instanceof Error ? err.message : String(err);
1569
- return {
1570
- stdout: "",
1571
- stderr: `Build failed: ${errorMessage}
1572
- `,
1573
- exitCode: 1
1574
- };
1575
- }
1576
- });
1577
- }
1578
- // src/commands/packages.ts
1579
- import { defineCommand as defineCommand2 } from "just-bash/browser";
1580
- function createInstallCommand(deps) {
1581
- const { fs, typesCache } = deps;
1582
- return defineCommand2("install", async (args, _ctx) => {
1583
- if (args.length === 0) {
1584
- return {
1585
- stdout: "",
1586
- stderr: `Usage: install <package>[@version] [...packages]
1587
-
1588
- Examples:
1589
- install react
1590
- install lodash@4.17.21
1591
- install @tanstack/react-query@5
1592
- `,
1593
- exitCode: 1
1594
- };
1595
- }
1596
- const results = [];
1597
- let hasError = false;
1598
- for (const packageSpec of args) {
1599
- try {
1600
- const result = await installPackage(fs, packageSpec, { cache: typesCache });
1601
- let status = `+ ${result.name}@${result.version}`;
1602
- if (result.typesInstalled) {
1603
- status += ` (${result.typeFilesCount} type file${result.typeFilesCount !== 1 ? "s" : ""})`;
1604
- if (result.fromCache) {
1605
- status += " [cached]";
1606
- }
1607
- } else if (result.typesError) {
1608
- status += ` (no types: ${result.typesError})`;
1609
- }
1610
- results.push(status);
1611
- } catch (err) {
1612
- hasError = true;
1613
- const message = err instanceof Error ? err.message : String(err);
1614
- results.push(`x ${packageSpec}: ${message}`);
1615
- }
1616
- }
1617
- const output = results.join(`
1618
- `) + `
1619
- `;
1620
- if (hasError) {
1621
- return {
1622
- stdout: "",
1623
- stderr: output,
1624
- exitCode: 1
1625
- };
1626
- }
1627
- return {
1628
- stdout: output,
1629
- stderr: "",
1630
- exitCode: 0
1631
- };
1632
- });
1633
- }
1634
- function createUninstallCommand(deps) {
1635
- const { fs } = deps;
1636
- return defineCommand2("uninstall", async (args, _ctx) => {
1637
- if (args.length === 0) {
1638
- return {
1639
- stdout: "",
1640
- stderr: `Usage: uninstall <package> [...packages]
1641
- `,
1642
- exitCode: 1
1643
- };
1644
- }
1645
- const results = [];
1646
- let hasError = false;
1647
- for (const packageName of args) {
1648
- try {
1649
- const removed = await uninstallPackage(fs, packageName);
1650
- if (removed) {
1651
- results.push(`- ${packageName}`);
1652
- } else {
1653
- results.push(`x ${packageName}: not installed`);
1654
- hasError = true;
1655
- }
1656
- } catch (err) {
1657
- hasError = true;
1658
- const message = err instanceof Error ? err.message : String(err);
1659
- results.push(`x ${packageName}: ${message}`);
1660
- }
1661
- }
1662
- const output = results.join(`
1663
- `) + `
1664
- `;
1665
- if (hasError) {
1666
- return {
1667
- stdout: "",
1668
- stderr: output,
1669
- exitCode: 1
1670
- };
1671
- }
1672
- return {
1673
- stdout: output,
1674
- stderr: "",
1675
- exitCode: 0
1676
- };
1677
- });
1678
- }
1679
- function createListCommand(deps) {
1680
- const { fs } = deps;
1681
- return defineCommand2("list", async (_args, _ctx) => {
1682
- try {
1683
- const packages = await listPackages(fs);
1684
- if (packages.length === 0) {
1685
- return {
1686
- stdout: `No packages installed.
1687
- `,
1688
- stderr: "",
1689
- exitCode: 0
1690
- };
1691
- }
1692
- const output = packages.map((pkg) => `${pkg.name}@${pkg.version}`).join(`
1693
- `) + `
1694
- `;
1695
- return {
1696
- stdout: output,
1697
- stderr: "",
1698
- exitCode: 0
1699
- };
1700
- } catch (err) {
1701
- const message = err instanceof Error ? err.message : String(err);
1702
- return {
1703
- stdout: "",
1704
- stderr: `Failed to list packages: ${message}
1705
- `,
1706
- exitCode: 1
1707
- };
1708
- }
1709
- });
1710
- }
1711
- // src/commands/run.ts
1712
- import { defineCommand as defineCommand3 } from "just-bash/browser";
1713
- function createRunCommand(deps) {
1714
- const { fs, libFiles, tsconfigPath, runOptions = {}, sharedModules } = deps;
1715
- return defineCommand3("run", async (args, _ctx) => {
1716
- let entryPoint = null;
1717
- let skipTypecheck = runOptions.skipTypecheck ?? false;
1718
- let timeout = runOptions.timeout ?? 30000;
1719
- const scriptArgs = [];
1720
- let collectingArgs = false;
1721
- for (let i = 0;i < args.length; i++) {
1722
- const arg = args[i];
1723
- if (collectingArgs) {
1724
- scriptArgs.push(arg);
1725
- continue;
1726
- }
1727
- if (arg === "--") {
1728
- collectingArgs = true;
1729
- } else if (arg === "--skip-typecheck" || arg === "-s") {
1730
- skipTypecheck = true;
1731
- } else if ((arg === "--timeout" || arg === "-t") && args[i + 1]) {
1732
- timeout = parseInt(args[++i], 10);
1733
- if (isNaN(timeout))
1734
- timeout = 30000;
1735
- } else if (!arg.startsWith("-")) {
1736
- entryPoint = arg;
1737
- }
1738
- }
1739
- if (!entryPoint) {
1740
- return {
1741
- stdout: "",
1742
- stderr: `Usage: run <entry-point> [options] [-- args...]
1743
-
1744
- Options:
1745
- --skip-typecheck, -s Skip type checking
1746
- --timeout, -t <ms> Execution timeout (default: 30000)
1747
-
1748
- Example: run /src/index.ts
1749
- `,
1750
- exitCode: 1
1751
- };
1752
- }
1753
- const logs = [];
1754
- const originalConsole = {
1755
- log: console.log,
1756
- warn: console.warn,
1757
- error: console.error,
1758
- info: console.info,
1759
- debug: console.debug
1760
- };
1761
- const formatArgs = (...a) => a.map((v) => typeof v === "object" ? JSON.stringify(v) : String(v)).join(" ");
1762
- const captureLog = (...a) => {
1763
- logs.push(formatArgs(...a));
1764
- originalConsole.log.apply(console, a);
1765
- };
1766
- const captureWarn = (...a) => {
1767
- logs.push(`[warn] ${formatArgs(...a)}`);
1768
- originalConsole.warn.apply(console, a);
1769
- };
1770
- const captureError = (...a) => {
1771
- logs.push(`[error] ${formatArgs(...a)}`);
1772
- originalConsole.error.apply(console, a);
1773
- };
1774
- const captureInfo = (...a) => {
1775
- logs.push(`[info] ${formatArgs(...a)}`);
1776
- originalConsole.info.apply(console, a);
1777
- };
1778
- const captureDebug = (...a) => {
1779
- logs.push(`[debug] ${formatArgs(...a)}`);
1780
- originalConsole.debug.apply(console, a);
1781
- };
1782
- const restoreConsole = () => {
1783
- console.log = originalConsole.log;
1784
- console.warn = originalConsole.warn;
1785
- console.error = originalConsole.error;
1786
- console.info = originalConsole.info;
1787
- console.debug = originalConsole.debug;
1788
- };
1789
- try {
1790
- if (!await fs.exists(entryPoint)) {
1791
- return {
1792
- stdout: "",
1793
- stderr: `Error: Entry point not found: ${entryPoint}
1794
- `,
1795
- exitCode: 1
1796
- };
1797
- }
1798
- if (!skipTypecheck) {
1799
- const typecheckResult = await typecheck({
1800
- fs,
1801
- entryPoint,
1802
- tsconfigPath,
1803
- libFiles
1804
- });
1805
- if (typecheckResult.hasErrors) {
1806
- const formatted = formatDiagnosticsForAgent(typecheckResult.diagnostics);
1807
- return {
1808
- stdout: "",
1809
- stderr: `Type errors:
1810
- ${formatted}
1811
- `,
1812
- exitCode: 1
1813
- };
1814
- }
1815
- }
1816
- const bundleResult = await bundle({
1817
- fs,
1818
- entryPoint,
1819
- format: "esm",
1820
- sharedModules
1821
- });
1822
- console.log = captureLog;
1823
- console.warn = captureWarn;
1824
- console.error = captureError;
1825
- console.info = captureInfo;
1826
- console.debug = captureDebug;
1827
- const context = {
1828
- fs,
1829
- env: { ...runOptions.env },
1830
- args: scriptArgs,
1831
- log: captureLog,
1832
- error: captureError
1833
- };
1834
- const startTime = performance.now();
1835
- let returnValue;
1836
- const executeCode = async () => {
1837
- const module = await loadModule(bundleResult);
1838
- if (typeof module.main === "function") {
1839
- returnValue = await module.main(context);
1840
- }
1841
- };
1842
- if (timeout > 0) {
1843
- const timeoutPromise = new Promise((_, reject) => {
1844
- setTimeout(() => reject(new Error(`Execution timed out after ${timeout}ms`)), timeout);
1845
- });
1846
- await Promise.race([executeCode(), timeoutPromise]);
1847
- } else {
1848
- await executeCode();
1849
- }
1850
- const executionTimeMs = performance.now() - startTime;
1851
- restoreConsole();
1852
- let output = "";
1853
- if (logs.length > 0) {
1854
- output = logs.join(`
1855
- `) + `
1856
- `;
1857
- }
1858
- if (returnValue !== undefined) {
1859
- const returnStr = typeof returnValue === "object" ? JSON.stringify(returnValue, null, 2) : String(returnValue);
1860
- output += `[return] ${returnStr}
1861
- `;
1862
- }
1863
- output += `
1864
- Execution completed in ${executionTimeMs.toFixed(2)}ms
1865
- `;
1866
- return {
1867
- stdout: output,
1868
- stderr: "",
1869
- exitCode: 0
1870
- };
1871
- } catch (err) {
1872
- restoreConsole();
1873
- const errorMessage = err instanceof Error ? err.message : String(err);
1874
- const errorStack = err instanceof Error && err.stack ? `
1875
- ${err.stack}` : "";
1876
- let output = "";
1877
- if (logs.length > 0) {
1878
- output = logs.join(`
1879
- `) + `
1880
-
1881
- `;
1882
- }
1883
- return {
1884
- stdout: output,
1885
- stderr: `Runtime error: ${errorMessage}${errorStack}
1886
- `,
1887
- exitCode: 1
1888
- };
1889
- }
1890
- });
1891
- }
1892
- // src/commands/index.ts
1893
- function createDefaultCommands(deps) {
1894
- return [
1895
- createTscCommand(deps),
1896
- createBuildCommand(deps),
1897
- createRunCommand(deps),
1898
- createInstallCommand(deps),
1899
- createUninstallCommand(deps),
1900
- createListCommand(deps)
1901
- ];
1902
- }
1903
- // src/build-emitter.ts
1904
- class BuildEmitter {
1905
- listeners = new Set;
1906
- emit = async (result) => {
1907
- const promises = [];
1908
- for (const listener of this.listeners) {
1909
- const ret = listener(result);
1910
- if (ret instanceof Promise) {
1911
- promises.push(ret);
1912
- }
1913
- }
1914
- await Promise.all(promises);
1915
- };
1916
- on(callback) {
1917
- this.listeners.add(callback);
1918
- return () => {
1919
- this.listeners.delete(callback);
1920
- };
1921
- }
1922
- }
1923
- export {
1924
- revokeModuleUrl,
1925
- resolveToEsmUrl,
1926
- parsePackageSpec,
1927
- parseLibReferences,
1928
- parseImportPath,
1929
- libNameToFileName,
1930
- hasSharedModuleRegistry,
1931
- getSharedModuleRuntimeCode,
1932
- getSharedModuleRegistry,
1933
- formatEsbuildMessages,
1934
- fetchLibFile,
1935
- fetchAllLibs,
1936
- extractLibName,
1937
- createModuleUrl,
1938
- SharedModuleRegistry,
1939
- LibCache,
1940
- InMemoryTypesCache,
1941
- BuildEmitter
1942
- };