@ebowwa/sandbox 0.1.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 (108) hide show
  1. package/dist/compilers/index.d.ts +24 -0
  2. package/dist/compilers/index.d.ts.map +1 -0
  3. package/dist/compilers/index.js +42 -0
  4. package/dist/compilers/index.js.map +1 -0
  5. package/dist/compilers/javascript.d.ts +117 -0
  6. package/dist/compilers/javascript.d.ts.map +1 -0
  7. package/dist/compilers/javascript.js +462 -0
  8. package/dist/compilers/javascript.js.map +1 -0
  9. package/dist/compilers/python.d.ts +140 -0
  10. package/dist/compilers/python.d.ts.map +1 -0
  11. package/dist/compilers/python.js +650 -0
  12. package/dist/compilers/python.js.map +1 -0
  13. package/dist/compilers/typescript.d.ts +99 -0
  14. package/dist/compilers/typescript.d.ts.map +1 -0
  15. package/dist/compilers/typescript.js +323 -0
  16. package/dist/compilers/typescript.js.map +1 -0
  17. package/dist/core/cell.d.ts +160 -0
  18. package/dist/core/cell.d.ts.map +1 -0
  19. package/dist/core/cell.js +319 -0
  20. package/dist/core/cell.js.map +1 -0
  21. package/dist/core/compiler.d.ts +126 -0
  22. package/dist/core/compiler.d.ts.map +1 -0
  23. package/dist/core/compiler.js +123 -0
  24. package/dist/core/compiler.js.map +1 -0
  25. package/dist/core/index.d.ts +19 -0
  26. package/dist/core/index.d.ts.map +1 -0
  27. package/dist/core/index.js +14 -0
  28. package/dist/core/index.js.map +1 -0
  29. package/dist/core/limits.d.ts +173 -0
  30. package/dist/core/limits.d.ts.map +1 -0
  31. package/dist/core/limits.js +440 -0
  32. package/dist/core/limits.js.map +1 -0
  33. package/dist/core/permissions.d.ts +103 -0
  34. package/dist/core/permissions.d.ts.map +1 -0
  35. package/dist/core/permissions.js +341 -0
  36. package/dist/core/permissions.js.map +1 -0
  37. package/dist/core/runtime.d.ts +127 -0
  38. package/dist/core/runtime.d.ts.map +1 -0
  39. package/dist/core/runtime.js +325 -0
  40. package/dist/core/runtime.js.map +1 -0
  41. package/dist/core/types.d.ts +380 -0
  42. package/dist/core/types.d.ts.map +1 -0
  43. package/dist/core/types.js +67 -0
  44. package/dist/core/types.js.map +1 -0
  45. package/dist/index.d.ts +145 -0
  46. package/dist/index.d.ts.map +1 -0
  47. package/dist/index.js +279 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/multi/index.d.ts +9 -0
  50. package/dist/multi/index.d.ts.map +1 -0
  51. package/dist/multi/index.js +7 -0
  52. package/dist/multi/index.js.map +1 -0
  53. package/dist/multi/polyglot.d.ts +179 -0
  54. package/dist/multi/polyglot.d.ts.map +1 -0
  55. package/dist/multi/polyglot.js +319 -0
  56. package/dist/multi/polyglot.js.map +1 -0
  57. package/dist/runtimes/docker.d.ts +97 -0
  58. package/dist/runtimes/docker.d.ts.map +1 -0
  59. package/dist/runtimes/docker.js +368 -0
  60. package/dist/runtimes/docker.js.map +1 -0
  61. package/dist/runtimes/index.d.ts +11 -0
  62. package/dist/runtimes/index.d.ts.map +1 -0
  63. package/dist/runtimes/index.js +9 -0
  64. package/dist/runtimes/index.js.map +1 -0
  65. package/dist/runtimes/process.d.ts +47 -0
  66. package/dist/runtimes/process.d.ts.map +1 -0
  67. package/dist/runtimes/process.js +230 -0
  68. package/dist/runtimes/process.js.map +1 -0
  69. package/dist/session/index.d.ts +12 -0
  70. package/dist/session/index.d.ts.map +1 -0
  71. package/dist/session/index.js +9 -0
  72. package/dist/session/index.js.map +1 -0
  73. package/dist/session/kernel.d.ts +199 -0
  74. package/dist/session/kernel.d.ts.map +1 -0
  75. package/dist/session/kernel.js +400 -0
  76. package/dist/session/kernel.js.map +1 -0
  77. package/dist/session/notebook.d.ts +168 -0
  78. package/dist/session/notebook.d.ts.map +1 -0
  79. package/dist/session/notebook.js +499 -0
  80. package/dist/session/notebook.js.map +1 -0
  81. package/dist/session/repl.d.ts +159 -0
  82. package/dist/session/repl.d.ts.map +1 -0
  83. package/dist/session/repl.js +409 -0
  84. package/dist/session/repl.js.map +1 -0
  85. package/package.json +142 -0
  86. package/src/compilers/index.ts +80 -0
  87. package/src/compilers/javascript.ts +571 -0
  88. package/src/compilers/python.ts +785 -0
  89. package/src/compilers/typescript.ts +442 -0
  90. package/src/core/cell.ts +439 -0
  91. package/src/core/compiler.ts +250 -0
  92. package/src/core/index.ts +123 -0
  93. package/src/core/limits.ts +508 -0
  94. package/src/core/permissions.ts +409 -0
  95. package/src/core/runtime.ts +499 -0
  96. package/src/core/types.ts +528 -0
  97. package/src/global.d.ts +59 -0
  98. package/src/index.ts +515 -0
  99. package/src/multi/index.ts +22 -0
  100. package/src/multi/polyglot.ts +461 -0
  101. package/src/runtimes/docker.ts +501 -0
  102. package/src/runtimes/index.ts +21 -0
  103. package/src/runtimes/process.ts +316 -0
  104. package/src/session/index.ts +41 -0
  105. package/src/session/kernel.ts +553 -0
  106. package/src/session/notebook.ts +635 -0
  107. package/src/session/repl.ts +521 -0
  108. package/src/wasm2wasm.d.ts +35 -0
@@ -0,0 +1,442 @@
1
+ /**
2
+ * TypeScript Compiler for @ebowwa/sandbox
3
+ *
4
+ * Compiles TypeScript to WASM via JavaScript.
5
+ * Uses esbuild for fast TypeScript transpilation, then delegates to JavaScript compiler.
6
+ */
7
+
8
+ import {
9
+ BaseCompiler,
10
+ type CompileResult,
11
+ type CompilerOptions,
12
+ type LanguageCapabilities,
13
+ } from "../core/compiler.js";
14
+ import type { Permissions, Limits } from "../core/types.js";
15
+ import { JavaScriptCompiler, type JavaScriptCompilerOptions } from "./javascript.js";
16
+
17
+ /** TypeScript compiler options */
18
+ export interface TypeScriptCompilerOptions extends CompilerOptions {
19
+ /** TypeScript target */
20
+ target?: "es2015" | "es2016" | "es2017" | "es2018" | "es2019" | "es2020" | "es2021" | "es2022" | "esnext";
21
+ /** Module format */
22
+ module?: "esm" | "cjs" | "iife";
23
+ /** Enable strict type checking */
24
+ strict?: boolean;
25
+ /** Emit declaration files */
26
+ declaration?: boolean;
27
+ /** Source map generation */
28
+ sourceMap?: boolean;
29
+ /** JSX transform */
30
+ jsx?: "transform" | "preserve" | "automatic";
31
+ /** JSX factory */
32
+ jsxFactory?: string;
33
+ /** JSX fragment factory */
34
+ jsxFragment?: string;
35
+ /** Use AssemblyScript for compilation */
36
+ useAssemblyScript?: boolean;
37
+ /** Transpiler to use */
38
+ transpiler?: "esbuild" | "swc" | "tsc";
39
+ }
40
+
41
+ /** Transpilation result */
42
+ interface TranspileResult {
43
+ code: string;
44
+ map?: string;
45
+ declarations?: string;
46
+ }
47
+
48
+ // Dynamic import type for esbuild (optional dependency)
49
+ type EsbuildModule = {
50
+ transform: (input: string, options?: Record<string, unknown>) => Promise<{ code: string; map?: string }>;
51
+ };
52
+
53
+ // Dynamic import type for SWC (optional dependency)
54
+ type SwcModule = {
55
+ transform: (code: string, options?: Record<string, unknown>) => Promise<{ code: string; map?: string }>;
56
+ };
57
+
58
+ /**
59
+ * TypeScript Compiler
60
+ *
61
+ * Transpiles TypeScript to JavaScript, then compiles to WASM.
62
+ * Supports both standard TypeScript and AssemblyScript syntax.
63
+ */
64
+ export class TypeScriptCompiler extends BaseCompiler {
65
+ readonly language = "typescript" as const;
66
+
67
+ private jsCompiler: JavaScriptCompiler;
68
+ private esbuildAvailable: boolean | null = null;
69
+ private swcAvailable: boolean | null = null;
70
+
71
+ constructor() {
72
+ super();
73
+ this.jsCompiler = new JavaScriptCompiler();
74
+ }
75
+
76
+ /**
77
+ * Check if TypeScript compiler is available
78
+ */
79
+ async isAvailable(): Promise<boolean> {
80
+ // TypeScript compiler is always available (we have built-in support)
81
+ // But transpilers may vary
82
+ return true;
83
+ }
84
+
85
+ /**
86
+ * Validate TypeScript syntax
87
+ */
88
+ async validate(source: string): Promise<{ valid: boolean; error?: string }> {
89
+ try {
90
+ const transpiler = await this.getTranspiler("esbuild");
91
+
92
+ if (transpiler?.type === "esbuild") {
93
+ await transpiler.module.transform(source, {
94
+ loader: "ts",
95
+ target: "es2020",
96
+ tsconfigRaw: {
97
+ compilerOptions: {
98
+ strict: true,
99
+ noEmit: true,
100
+ },
101
+ },
102
+ });
103
+ return { valid: true };
104
+ }
105
+
106
+ // Fallback: basic regex check for common syntax errors
107
+ const syntaxErrors = this.checkBasicSyntax(source);
108
+ if (syntaxErrors) {
109
+ return { valid: false, error: syntaxErrors };
110
+ }
111
+
112
+ return { valid: true };
113
+ } catch (error) {
114
+ return {
115
+ valid: false,
116
+ error: error instanceof Error ? error.message : String(error),
117
+ };
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Compile TypeScript to WASM
123
+ *
124
+ * 1. Transpile TypeScript to JavaScript
125
+ * 2. Use JavaScript compiler for WASM compilation
126
+ */
127
+ async compile(
128
+ source: string,
129
+ permissions: Permissions,
130
+ limits: Limits,
131
+ options?: TypeScriptCompilerOptions
132
+ ): Promise<CompileResult> {
133
+ const opts: TypeScriptCompilerOptions = {
134
+ target: "es2020",
135
+ module: "esm",
136
+ strict: true,
137
+ declaration: false,
138
+ sourceMap: options?.sourceMap ?? false,
139
+ jsx: "transform",
140
+ jsxFactory: "React.createElement",
141
+ jsxFragment: "React.Fragment",
142
+ useAssemblyScript: false,
143
+ transpiler: "esbuild",
144
+ ...options,
145
+ };
146
+
147
+ // Check if source uses AssemblyScript types
148
+ const isAssemblyScript = this.detectAssemblyScript(source);
149
+ const effectiveUseAssemblyScript = opts.useAssemblyScript || isAssemblyScript;
150
+
151
+ // Transpile TypeScript to JavaScript
152
+ const transpiled = await this.transpile(source, {
153
+ ...opts,
154
+ useAssemblyScript: effectiveUseAssemblyScript,
155
+ });
156
+
157
+ // Delegate to JavaScript compiler
158
+ const jsOptions: JavaScriptCompilerOptions = {
159
+ target: opts.target,
160
+ module: opts.module,
161
+ strict: opts.strict,
162
+ useAssemblyScript: effectiveUseAssemblyScript,
163
+ optimize: opts.optimize,
164
+ debug: opts.debug,
165
+ sourceMap: opts.sourceMap,
166
+ };
167
+
168
+ const result = await this.jsCompiler.compile(
169
+ transpiled.code,
170
+ permissions,
171
+ limits,
172
+ jsOptions
173
+ );
174
+
175
+ // Include source map if generated
176
+ if (transpiled.map) {
177
+ result.sourceMap = transpiled.map;
178
+ }
179
+
180
+ return result;
181
+ }
182
+
183
+ /**
184
+ * Get language capabilities
185
+ */
186
+ getCapabilities(): LanguageCapabilities {
187
+ return {
188
+ repl: true,
189
+ stateful: true,
190
+ compiled: false, // TS transpiles to JS, which is interpreted
191
+ gc: true, // JavaScript has garbage collection
192
+ imports: true,
193
+ async: true,
194
+ };
195
+ }
196
+
197
+ /**
198
+ * Transpile TypeScript to JavaScript
199
+ */
200
+ private async transpile(
201
+ source: string,
202
+ options: TypeScriptCompilerOptions
203
+ ): Promise<TranspileResult> {
204
+ // If using AssemblyScript, don't transpile types
205
+ if (options.useAssemblyScript) {
206
+ return {
207
+ code: source,
208
+ map: undefined,
209
+ };
210
+ }
211
+
212
+ const transpiler = await this.getTranspiler(options.transpiler || "esbuild");
213
+
214
+ if (transpiler?.type === "esbuild") {
215
+ return this.transpileWithEsbuild(source, options, transpiler.module);
216
+ }
217
+
218
+ if (transpiler?.type === "swc") {
219
+ return this.transpileWithSwc(source, options, transpiler.module);
220
+ }
221
+
222
+ // Fallback: strip types using regex (not recommended for production)
223
+ return this.transpileWithRegex(source);
224
+ }
225
+
226
+ /**
227
+ * Transpile using esbuild
228
+ */
229
+ private async transpileWithEsbuild(
230
+ source: string,
231
+ options: TypeScriptCompilerOptions,
232
+ esbuild: EsbuildModule
233
+ ): Promise<TranspileResult> {
234
+ const result = await esbuild.transform(source, {
235
+ loader: "ts",
236
+ target: options.target || "es2020",
237
+ format: options.module === "cjs" ? "cjs" : "esm",
238
+ minify: options.optimize,
239
+ sourcemap: options.sourceMap ? "external" : false,
240
+ jsx: options.jsx === "automatic" ? "automatic" : "transform",
241
+ jsxFactory: options.jsxFactory,
242
+ jsxFragment: options.jsxFragment,
243
+ tsconfigRaw: {
244
+ compilerOptions: {
245
+ strict: options.strict,
246
+ target: options.target,
247
+ module: options.module?.toUpperCase(),
248
+ esModuleInterop: true,
249
+ allowSyntheticDefaultImports: true,
250
+ resolveJsonModule: true,
251
+ declaration: options.declaration,
252
+ },
253
+ },
254
+ });
255
+
256
+ return {
257
+ code: result.code,
258
+ map: result.map,
259
+ };
260
+ }
261
+
262
+ /**
263
+ * Transpile using SWC
264
+ */
265
+ private async transpileWithSwc(
266
+ source: string,
267
+ options: TypeScriptCompilerOptions,
268
+ swc: SwcModule
269
+ ): Promise<TranspileResult> {
270
+ const result = await swc.transform(source, {
271
+ jsc: {
272
+ parser: {
273
+ syntax: "typescript",
274
+ tsx: options.jsx !== "preserve",
275
+ },
276
+ transform: {
277
+ react: {
278
+ runtime: options.jsx === "automatic" ? "automatic" : "classic",
279
+ pragma: options.jsxFactory,
280
+ pragmaFrag: options.jsxFragment,
281
+ },
282
+ },
283
+ target: options.target?.replace("es", "es") || "es2020",
284
+ },
285
+ module: {
286
+ type: options.module === "cjs" ? "commonjs" : "es6",
287
+ },
288
+ minify: options.optimize,
289
+ sourceMaps: options.sourceMap,
290
+ });
291
+
292
+ return {
293
+ code: result.code,
294
+ map: result.map,
295
+ };
296
+ }
297
+
298
+ /**
299
+ * Fallback transpilation using regex (basic type stripping)
300
+ *
301
+ * Note: This is not a complete TypeScript implementation.
302
+ * Use esbuild or swc for production code.
303
+ */
304
+ private transpileWithRegex(source: string): TranspileResult {
305
+ let code = source;
306
+
307
+ // Strip type annotations
308
+ // This is a simplified implementation
309
+ const patterns = [
310
+ // Remove type annotations: : Type
311
+ /:\s*[A-Z][a-zA-Z0-9_]*(?:<[^>]+>)?(?:\[\])?(?:\s*\|\s*[A-Z][a-zA-Z0-9_]*(?:<[^>]+>)?(?:\[\])?)*/g,
312
+ // Remove interface declarations
313
+ /interface\s+[A-Z][a-zA-Z0-9_]*\s*(?:<[^>]+>)?\s*\{[^}]*\}/g,
314
+ // Remove type declarations
315
+ /type\s+[A-Z][a-zA-Z0-9_]*\s*(?:<[^>]+>)?\s*=\s*[^;]+;/g,
316
+ // Remove enum declarations (convert to const objects)
317
+ /enum\s+([A-Z][a-zA-Z0-9_]*)\s*\{([^}]*)\}/g,
318
+ // Remove generic type parameters
319
+ /<[^>]+>/g,
320
+ // Remove 'as' type assertions
321
+ /\s+as\s+[A-Z][a-zA-Z0-9_]*(?:<[^>]+>)?/g,
322
+ // Remove 'satisfies' type assertions
323
+ /\s+satisfies\s+[A-Z][a-zA-Z0-9_]*(?:<[^>]+>)?/g,
324
+ // Remove 'declare' statements
325
+ /declare\s+(?:const|let|var|function|class|interface|type|enum)\s+[^;]+;/g,
326
+ // Remove 'public', 'private', 'protected', 'readonly' modifiers
327
+ /\b(?:public|private|protected|readonly)\s+/g,
328
+ // Remove 'abstract' modifier
329
+ /\babstract\s+/g,
330
+ // Remove parameter properties in constructors
331
+ /constructor\s*\(([^)]*)\)/g,
332
+ ];
333
+
334
+ for (const pattern of patterns) {
335
+ code = code.replace(pattern, "");
336
+ }
337
+
338
+ return {
339
+ code,
340
+ map: undefined,
341
+ };
342
+ }
343
+
344
+ /**
345
+ * Get the best available transpiler
346
+ */
347
+ private async getTranspiler(
348
+ preferred: "esbuild" | "swc" | "tsc"
349
+ ): Promise<
350
+ | {
351
+ type: "esbuild";
352
+ module: EsbuildModule;
353
+ }
354
+ | {
355
+ type: "swc";
356
+ module: SwcModule;
357
+ }
358
+ | null
359
+ > {
360
+ if (preferred === "esbuild" || preferred === "tsc") {
361
+ if (this.esbuildAvailable === null) {
362
+ try {
363
+ await import("esbuild");
364
+ this.esbuildAvailable = true;
365
+ } catch {
366
+ this.esbuildAvailable = false;
367
+ }
368
+ }
369
+
370
+ if (this.esbuildAvailable) {
371
+ const esbuild = await import("esbuild") as EsbuildModule;
372
+ return { type: "esbuild", module: esbuild };
373
+ }
374
+ }
375
+
376
+ if (preferred === "swc") {
377
+ if (this.swcAvailable === null) {
378
+ try {
379
+ await import("@swc/core");
380
+ this.swcAvailable = true;
381
+ } catch {
382
+ this.swcAvailable = false;
383
+ }
384
+ }
385
+
386
+ if (this.swcAvailable) {
387
+ const swc = await import("@swc/core") as SwcModule;
388
+ return { type: "swc", module: swc };
389
+ }
390
+ }
391
+
392
+ // Fallback to esbuild if swc was preferred but not available
393
+ if (preferred === "swc" && this.esbuildAvailable !== false) {
394
+ return this.getTranspiler("esbuild");
395
+ }
396
+
397
+ return null;
398
+ }
399
+
400
+ /**
401
+ * Detect if source uses AssemblyScript-specific types
402
+ */
403
+ private detectAssemblyScript(source: string): boolean {
404
+ // AssemblyScript uses specific types: i8, i16, i32, i64, f32, f64, usize, etc.
405
+ const assemblyScriptTypes = /\b(i8|i16|i32|i64|f32|f64|usize|isize|bool)\b/;
406
+ return assemblyScriptTypes.test(source);
407
+ }
408
+
409
+ /**
410
+ * Basic syntax check for TypeScript
411
+ */
412
+ private checkBasicSyntax(source: string): string | null {
413
+ // Check for common syntax errors
414
+ const errors: string[] = [];
415
+
416
+ // Check for unmatched braces
417
+ const openBraces = (source.match(/\{/g) || []).length;
418
+ const closeBraces = (source.match(/\}/g) || []).length;
419
+ if (openBraces !== closeBraces) {
420
+ errors.push(`Unmatched braces: ${openBraces} open, ${closeBraces} close`);
421
+ }
422
+
423
+ // Check for unmatched parentheses
424
+ const openParens = (source.match(/\(/g) || []).length;
425
+ const closeParens = (source.match(/\)/g) || []).length;
426
+ if (openParens !== closeParens) {
427
+ errors.push(`Unmatched parentheses: ${openParens} open, ${closeParens} close`);
428
+ }
429
+
430
+ // Check for unmatched brackets
431
+ const openBrackets = (source.match(/\[/g) || []).length;
432
+ const closeBrackets = (source.match(/\]/g) || []).length;
433
+ if (openBrackets !== closeBrackets) {
434
+ errors.push(`Unmatched brackets: ${openBrackets} open, ${closeBrackets} close`);
435
+ }
436
+
437
+ return errors.length > 0 ? errors.join("; ") : null;
438
+ }
439
+ }
440
+
441
+ // Default instance
442
+ export const typescriptCompiler = new TypeScriptCompiler();