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.
- package/README.md +145 -518
- package/dist/build-emitter.d.ts +47 -0
- package/dist/build-emitter.d.ts.map +1 -0
- package/dist/builder.d.ts +370 -0
- package/dist/builder.d.ts.map +1 -0
- package/dist/bundler.d.ts +3 -3
- package/dist/bundler.d.ts.map +1 -1
- package/dist/commands/compile.d.ts +13 -0
- package/dist/commands/compile.d.ts.map +1 -0
- package/dist/commands/index.d.ts +17 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/packages.d.ts +17 -0
- package/dist/commands/packages.d.ts.map +1 -0
- package/dist/commands/run.d.ts +40 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/types.d.ts +141 -0
- package/dist/commands/types.d.ts.map +1 -0
- package/dist/fs.d.ts +60 -42
- package/dist/fs.d.ts.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +304 -491
- package/dist/internal.d.ts +5 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +174 -95
- package/dist/runner.d.ts +314 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/sandbox-manager.d.ts +45 -33
- package/dist/sandbox-manager.d.ts.map +1 -1
- package/dist/sandbox.d.ts +144 -70
- package/dist/sandbox.d.ts.map +1 -1
- package/dist/shared-modules.d.ts +22 -3
- package/dist/shared-modules.d.ts.map +1 -1
- package/dist/shared-resources.d.ts +0 -3
- package/dist/shared-resources.d.ts.map +1 -1
- package/dist/typechecker.d.ts +1 -1
- package/package.json +3 -17
- package/src/build-emitter.ts +64 -0
- package/src/builder.ts +498 -0
- package/src/bundler.ts +86 -57
- package/src/commands/compile.ts +236 -0
- package/src/commands/index.ts +51 -0
- package/src/commands/packages.ts +154 -0
- package/src/commands/run.ts +245 -0
- package/src/commands/types.ts +172 -0
- package/src/fs.ts +90 -216
- package/src/index.ts +34 -12
- package/src/internal.ts +5 -2
- package/src/sandbox.ts +214 -220
- package/src/shared-modules.ts +74 -4
- package/src/shared-resources.ts +0 -3
- package/src/ts-libs.ts +1 -1
- package/src/typechecker.ts +1 -1
- package/dist/react.d.ts +0 -159
- package/dist/react.d.ts.map +0 -1
- package/dist/react.js +0 -149
- package/src/commands.ts +0 -733
- package/src/react.tsx +0 -331
- package/src/sandbox-manager.ts +0 -490
package/src/fs.ts
CHANGED
|
@@ -23,9 +23,12 @@ interface ReadFileOptions {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
|
-
* Options for writing files
|
|
26
|
+
* Options for writing files.
|
|
27
|
+
* Note: In this browser-based filesystem, content is stored as-is.
|
|
28
|
+
* The encoding option is accepted for API compatibility but not used.
|
|
27
29
|
*/
|
|
28
30
|
interface WriteFileOptions {
|
|
31
|
+
/** Accepted for API compatibility but not used - content is stored as-is */
|
|
29
32
|
encoding?: BufferEncoding;
|
|
30
33
|
}
|
|
31
34
|
|
|
@@ -45,85 +48,54 @@ const DEFAULT_SYMLINK_MODE = 0o777;
|
|
|
45
48
|
const DEFAULT_MAX_SIZE_BYTES = 50 * 1024 * 1024; // 50MB default limit
|
|
46
49
|
|
|
47
50
|
/**
|
|
48
|
-
* Options for creating
|
|
51
|
+
* Options for creating a Filesystem instance
|
|
49
52
|
*/
|
|
50
|
-
export interface
|
|
51
|
-
/** Database name in IndexedDB */
|
|
52
|
-
dbName?: string;
|
|
53
|
+
export interface FilesystemOptions {
|
|
53
54
|
/** Maximum total size in bytes (default: 50MB) */
|
|
54
55
|
maxSizeBytes?: number;
|
|
55
|
-
/** Initial files to populate
|
|
56
|
+
/** Initial files to populate */
|
|
56
57
|
initialFiles?: InitialFiles;
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
/**
|
|
60
|
-
* In-memory filesystem
|
|
61
|
-
*
|
|
61
|
+
* In-memory virtual filesystem for sandlot sandboxes.
|
|
62
|
+
*
|
|
63
|
+
* All operations are synchronous in-memory. Use `getFiles()` to export
|
|
64
|
+
* the current state for persistence, and `initialFiles` to restore.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* // Create filesystem
|
|
69
|
+
* const fs = Filesystem.create({ initialFiles: { '/src/index.ts': 'export const x = 1;' } });
|
|
70
|
+
*
|
|
71
|
+
* // Use filesystem
|
|
72
|
+
* await fs.writeFile('/src/app.ts', 'console.log("hello")');
|
|
73
|
+
*
|
|
74
|
+
* // Export for persistence
|
|
75
|
+
* const files = fs.getFiles();
|
|
76
|
+
* localStorage.setItem('my-project', JSON.stringify(files));
|
|
77
|
+
*
|
|
78
|
+
* // Later, restore
|
|
79
|
+
* const saved = JSON.parse(localStorage.getItem('my-project'));
|
|
80
|
+
* const fs2 = Filesystem.create({ initialFiles: saved });
|
|
81
|
+
* ```
|
|
62
82
|
*/
|
|
63
|
-
export class
|
|
83
|
+
export class Filesystem implements IFileSystem {
|
|
64
84
|
private entries: Map<string, FsEntry>;
|
|
65
|
-
private db: IDBDatabase | null = null;
|
|
66
|
-
private dbName: string;
|
|
67
85
|
private maxSizeBytes: number;
|
|
68
|
-
private dirty = false;
|
|
69
86
|
|
|
70
87
|
private constructor(
|
|
71
88
|
entries: Map<string, FsEntry>,
|
|
72
|
-
db: IDBDatabase | null,
|
|
73
|
-
dbName: string,
|
|
74
89
|
maxSizeBytes: number
|
|
75
90
|
) {
|
|
76
91
|
this.entries = entries;
|
|
77
|
-
this.db = db;
|
|
78
|
-
this.dbName = dbName;
|
|
79
92
|
this.maxSizeBytes = maxSizeBytes;
|
|
80
93
|
}
|
|
81
94
|
|
|
82
95
|
/**
|
|
83
|
-
* Create
|
|
96
|
+
* Create a new Filesystem instance
|
|
84
97
|
*/
|
|
85
|
-
static
|
|
86
|
-
const dbName = options.dbName ?? "sandlot-fs";
|
|
87
|
-
const maxSizeBytes = options.maxSizeBytes ?? DEFAULT_MAX_SIZE_BYTES;
|
|
88
|
-
|
|
89
|
-
const db = await IndexedDbFs.openDatabase(dbName);
|
|
90
|
-
const entries = await IndexedDbFs.loadEntries(db);
|
|
91
|
-
|
|
92
|
-
// If empty and initialFiles provided, populate
|
|
93
|
-
if (entries.size === 0) {
|
|
94
|
-
// Always ensure root exists
|
|
95
|
-
entries.set("/", {
|
|
96
|
-
type: "directory",
|
|
97
|
-
mode: DEFAULT_DIR_MODE,
|
|
98
|
-
mtime: new Date(),
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
if (options.initialFiles) {
|
|
102
|
-
for (const [path, value] of Object.entries(options.initialFiles)) {
|
|
103
|
-
const normalizedPath = IndexedDbFs.normalizePath(path);
|
|
104
|
-
const init = IndexedDbFs.parseFileInit(value);
|
|
105
|
-
|
|
106
|
-
// Ensure parent directories exist
|
|
107
|
-
IndexedDbFs.ensureParentDirs(entries, normalizedPath);
|
|
108
|
-
|
|
109
|
-
entries.set(normalizedPath, {
|
|
110
|
-
type: "file",
|
|
111
|
-
content: init.content,
|
|
112
|
-
mode: init.mode ?? DEFAULT_FILE_MODE,
|
|
113
|
-
mtime: init.mtime ?? new Date(),
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const fs = new IndexedDbFs(entries, db, dbName, maxSizeBytes);
|
|
120
|
-
return fs;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Create an in-memory only instance (no IndexedDB)
|
|
125
|
-
*/
|
|
126
|
-
static createInMemory(options: Omit<IndexedDbFsOptions, "dbName"> = {}): IndexedDbFs {
|
|
98
|
+
static create(options: FilesystemOptions = {}): Filesystem {
|
|
127
99
|
const maxSizeBytes = options.maxSizeBytes ?? DEFAULT_MAX_SIZE_BYTES;
|
|
128
100
|
const entries = new Map<string, FsEntry>();
|
|
129
101
|
|
|
@@ -136,11 +108,11 @@ export class IndexedDbFs implements IFileSystem {
|
|
|
136
108
|
|
|
137
109
|
if (options.initialFiles) {
|
|
138
110
|
for (const [path, value] of Object.entries(options.initialFiles)) {
|
|
139
|
-
const normalizedPath =
|
|
140
|
-
const init =
|
|
111
|
+
const normalizedPath = Filesystem.normalizePath(path);
|
|
112
|
+
const init = Filesystem.parseFileInit(value);
|
|
141
113
|
|
|
142
114
|
// Ensure parent directories exist
|
|
143
|
-
|
|
115
|
+
Filesystem.ensureParentDirs(entries, normalizedPath);
|
|
144
116
|
|
|
145
117
|
entries.set(normalizedPath, {
|
|
146
118
|
type: "file",
|
|
@@ -151,52 +123,50 @@ export class IndexedDbFs implements IFileSystem {
|
|
|
151
123
|
}
|
|
152
124
|
}
|
|
153
125
|
|
|
154
|
-
return new
|
|
126
|
+
return new Filesystem(entries, maxSizeBytes);
|
|
155
127
|
}
|
|
156
128
|
|
|
157
|
-
// ============
|
|
129
|
+
// ============ State Export ============
|
|
158
130
|
|
|
159
131
|
/**
|
|
160
|
-
*
|
|
161
|
-
*
|
|
132
|
+
* Get all files as a serializable object.
|
|
133
|
+
*
|
|
134
|
+
* Returns a Record<string, string> that can be JSON-serialized and
|
|
135
|
+
* used as `initialFiles` when creating a new filesystem.
|
|
136
|
+
*
|
|
137
|
+
* Note: Only includes files, not directories (directories are
|
|
138
|
+
* automatically created from file paths). Binary files are
|
|
139
|
+
* base64-encoded with a `data:` prefix.
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```ts
|
|
143
|
+
* const files = fs.getFiles();
|
|
144
|
+
* // { '/src/index.ts': 'export const x = 1;', '/package.json': '{"name":"app"}' }
|
|
145
|
+
*
|
|
146
|
+
* // Persist however you want
|
|
147
|
+
* localStorage.setItem('project', JSON.stringify(files));
|
|
148
|
+
*
|
|
149
|
+
* // Restore later
|
|
150
|
+
* const saved = JSON.parse(localStorage.getItem('project'));
|
|
151
|
+
* const fs2 = Filesystem.create({ initialFiles: saved });
|
|
152
|
+
* ```
|
|
162
153
|
*/
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const tx = this.db.transaction("entries", "readwrite");
|
|
169
|
-
const store = tx.objectStore("entries");
|
|
170
|
-
|
|
171
|
-
// Clear and rewrite all entries
|
|
172
|
-
await this.promisifyRequest(store.clear());
|
|
173
|
-
|
|
154
|
+
getFiles(): Record<string, string> {
|
|
155
|
+
const files: Record<string, string> = {};
|
|
156
|
+
|
|
174
157
|
for (const [path, entry] of this.entries) {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
* Reload entries from IndexedDB, discarding unsaved changes
|
|
185
|
-
*/
|
|
186
|
-
async reload(): Promise<void> {
|
|
187
|
-
if (!this.db) {
|
|
188
|
-
return;
|
|
158
|
+
if (entry.type === "file") {
|
|
159
|
+
if (typeof entry.content === "string") {
|
|
160
|
+
files[path] = entry.content;
|
|
161
|
+
} else {
|
|
162
|
+
// Binary content - base64 encode with data URI prefix
|
|
163
|
+
const base64 = this.encodeBase64(entry.content);
|
|
164
|
+
files[path] = `data:application/octet-stream;base64,${base64}`;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
189
167
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
this.dirty = false;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Check if there are unsaved changes
|
|
197
|
-
*/
|
|
198
|
-
isDirty(): boolean {
|
|
199
|
-
return this.dirty;
|
|
168
|
+
|
|
169
|
+
return files;
|
|
200
170
|
}
|
|
201
171
|
|
|
202
172
|
/**
|
|
@@ -217,16 +187,6 @@ export class IndexedDbFs implements IFileSystem {
|
|
|
217
187
|
return size;
|
|
218
188
|
}
|
|
219
189
|
|
|
220
|
-
/**
|
|
221
|
-
* Close the database connection
|
|
222
|
-
*/
|
|
223
|
-
close(): void {
|
|
224
|
-
if (this.db) {
|
|
225
|
-
this.db.close();
|
|
226
|
-
this.db = null;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
190
|
// ============ IFileSystem Implementation ============
|
|
231
191
|
|
|
232
192
|
async readFile(
|
|
@@ -276,7 +236,7 @@ export class IndexedDbFs implements IFileSystem {
|
|
|
276
236
|
async writeFile(
|
|
277
237
|
path: string,
|
|
278
238
|
content: FileContent,
|
|
279
|
-
|
|
239
|
+
_options?: WriteFileOptions | BufferEncoding
|
|
280
240
|
): Promise<void> {
|
|
281
241
|
const normalizedPath = this.normalizePath(path);
|
|
282
242
|
this.checkSizeLimit(content);
|
|
@@ -293,7 +253,6 @@ export class IndexedDbFs implements IFileSystem {
|
|
|
293
253
|
mode: existing?.mode ?? DEFAULT_FILE_MODE,
|
|
294
254
|
mtime: new Date(),
|
|
295
255
|
});
|
|
296
|
-
this.dirty = true;
|
|
297
256
|
}
|
|
298
257
|
|
|
299
258
|
async appendFile(
|
|
@@ -372,7 +331,6 @@ export class IndexedDbFs implements IFileSystem {
|
|
|
372
331
|
mode: DEFAULT_DIR_MODE,
|
|
373
332
|
mtime: new Date(),
|
|
374
333
|
});
|
|
375
|
-
this.dirty = true;
|
|
376
334
|
}
|
|
377
335
|
|
|
378
336
|
async readdir(path: string): Promise<string[]> {
|
|
@@ -461,7 +419,6 @@ export class IndexedDbFs implements IFileSystem {
|
|
|
461
419
|
}
|
|
462
420
|
|
|
463
421
|
this.entries.delete(normalizedPath);
|
|
464
|
-
this.dirty = true;
|
|
465
422
|
}
|
|
466
423
|
|
|
467
424
|
async cp(src: string, dest: string, options?: CpOptions): Promise<void> {
|
|
@@ -494,8 +451,6 @@ export class IndexedDbFs implements IFileSystem {
|
|
|
494
451
|
this.ensureParentDirs(destPath);
|
|
495
452
|
this.entries.set(destPath, this.cloneEntry(entry));
|
|
496
453
|
}
|
|
497
|
-
|
|
498
|
-
this.dirty = true;
|
|
499
454
|
}
|
|
500
455
|
|
|
501
456
|
async mv(src: string, dest: string): Promise<void> {
|
|
@@ -529,8 +484,6 @@ export class IndexedDbFs implements IFileSystem {
|
|
|
529
484
|
this.entries.delete(srcPath);
|
|
530
485
|
this.entries.set(destPath, entry);
|
|
531
486
|
}
|
|
532
|
-
|
|
533
|
-
this.dirty = true;
|
|
534
487
|
}
|
|
535
488
|
|
|
536
489
|
resolvePath(base: string, path: string): string {
|
|
@@ -568,7 +521,6 @@ export class IndexedDbFs implements IFileSystem {
|
|
|
568
521
|
|
|
569
522
|
entry.mode = mode;
|
|
570
523
|
entry.mtime = new Date();
|
|
571
|
-
this.dirty = true;
|
|
572
524
|
}
|
|
573
525
|
|
|
574
526
|
async symlink(target: string, linkPath: string): Promise<void> {
|
|
@@ -586,7 +538,6 @@ export class IndexedDbFs implements IFileSystem {
|
|
|
586
538
|
mode: DEFAULT_SYMLINK_MODE,
|
|
587
539
|
mtime: new Date(),
|
|
588
540
|
});
|
|
589
|
-
this.dirty = true;
|
|
590
541
|
}
|
|
591
542
|
|
|
592
543
|
async link(existingPath: string, newPath: string): Promise<void> {
|
|
@@ -613,7 +564,6 @@ export class IndexedDbFs implements IFileSystem {
|
|
|
613
564
|
mode: entry.mode,
|
|
614
565
|
mtime: new Date(),
|
|
615
566
|
});
|
|
616
|
-
this.dirty = true;
|
|
617
567
|
}
|
|
618
568
|
|
|
619
569
|
async readlink(path: string): Promise<string> {
|
|
@@ -677,13 +627,12 @@ export class IndexedDbFs implements IFileSystem {
|
|
|
677
627
|
|
|
678
628
|
// Update mtime (atime is ignored as per interface docs, kept for API compatibility)
|
|
679
629
|
entry.mtime = mtime;
|
|
680
|
-
this.dirty = true;
|
|
681
630
|
}
|
|
682
631
|
|
|
683
632
|
// ============ Private Helpers ============
|
|
684
633
|
|
|
685
634
|
private normalizePath(path: string): string {
|
|
686
|
-
return
|
|
635
|
+
return Filesystem.normalizePath(path);
|
|
687
636
|
}
|
|
688
637
|
|
|
689
638
|
private static normalizePath(path: string): string {
|
|
@@ -715,8 +664,7 @@ export class IndexedDbFs implements IFileSystem {
|
|
|
715
664
|
}
|
|
716
665
|
|
|
717
666
|
private ensureParentDirs(path: string): void {
|
|
718
|
-
|
|
719
|
-
this.dirty = true;
|
|
667
|
+
Filesystem.ensureParentDirs(this.entries, path);
|
|
720
668
|
}
|
|
721
669
|
|
|
722
670
|
private static ensureParentDirs(entries: Map<string, FsEntry>, path: string): void {
|
|
@@ -815,11 +763,7 @@ export class IndexedDbFs implements IFileSystem {
|
|
|
815
763
|
return new TextDecoder("utf-8").decode(buffer);
|
|
816
764
|
}
|
|
817
765
|
if (encoding === "base64") {
|
|
818
|
-
|
|
819
|
-
for (let i = 0; i < buffer.byteLength; i++) {
|
|
820
|
-
binary += String.fromCharCode(buffer[i]!);
|
|
821
|
-
}
|
|
822
|
-
return btoa(binary);
|
|
766
|
+
return this.encodeBase64(buffer);
|
|
823
767
|
}
|
|
824
768
|
if (encoding === "hex") {
|
|
825
769
|
return Array.from(buffer)
|
|
@@ -830,6 +774,14 @@ export class IndexedDbFs implements IFileSystem {
|
|
|
830
774
|
return new TextDecoder("utf-8").decode(buffer);
|
|
831
775
|
}
|
|
832
776
|
|
|
777
|
+
private encodeBase64(buffer: Uint8Array): string {
|
|
778
|
+
let binary = "";
|
|
779
|
+
for (let i = 0; i < buffer.byteLength; i++) {
|
|
780
|
+
binary += String.fromCharCode(buffer[i]!);
|
|
781
|
+
}
|
|
782
|
+
return btoa(binary);
|
|
783
|
+
}
|
|
784
|
+
|
|
833
785
|
private concatBuffers(a: Uint8Array, b: Uint8Array): Uint8Array {
|
|
834
786
|
const result = new Uint8Array(a.byteLength + b.byteLength);
|
|
835
787
|
result.set(a, 0);
|
|
@@ -843,93 +795,15 @@ export class IndexedDbFs implements IFileSystem {
|
|
|
843
795
|
}
|
|
844
796
|
return value;
|
|
845
797
|
}
|
|
846
|
-
|
|
847
|
-
// ============ IndexedDB Helpers ============
|
|
848
|
-
|
|
849
|
-
private static openDatabase(dbName: string): Promise<IDBDatabase> {
|
|
850
|
-
return new Promise((resolve, reject) => {
|
|
851
|
-
const request = indexedDB.open(dbName, 1);
|
|
852
|
-
|
|
853
|
-
request.onerror = () => reject(request.error);
|
|
854
|
-
request.onsuccess = () => resolve(request.result);
|
|
855
|
-
|
|
856
|
-
request.onupgradeneeded = (event) => {
|
|
857
|
-
const db = (event.target as IDBOpenDBRequest).result;
|
|
858
|
-
if (!db.objectStoreNames.contains("entries")) {
|
|
859
|
-
db.createObjectStore("entries", { keyPath: "path" });
|
|
860
|
-
}
|
|
861
|
-
};
|
|
862
|
-
});
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
private static async loadEntries(db: IDBDatabase): Promise<Map<string, FsEntry>> {
|
|
866
|
-
const tx = db.transaction("entries", "readonly");
|
|
867
|
-
const store = tx.objectStore("entries");
|
|
868
|
-
|
|
869
|
-
return new Promise((resolve, reject) => {
|
|
870
|
-
const request = store.getAll();
|
|
871
|
-
request.onerror = () => reject(request.error);
|
|
872
|
-
request.onsuccess = () => {
|
|
873
|
-
const entries = new Map<string, FsEntry>();
|
|
874
|
-
for (const record of request.result) {
|
|
875
|
-
entries.set(record.path, IndexedDbFs.deserializeEntry(record.entry));
|
|
876
|
-
}
|
|
877
|
-
resolve(entries);
|
|
878
|
-
};
|
|
879
|
-
});
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
private serializeEntry(entry: FsEntry): object {
|
|
883
|
-
if (entry.type === "file" && entry.content instanceof Uint8Array) {
|
|
884
|
-
return {
|
|
885
|
-
...entry,
|
|
886
|
-
content: Array.from(entry.content),
|
|
887
|
-
contentType: "uint8array",
|
|
888
|
-
mtime: entry.mtime.toISOString(),
|
|
889
|
-
};
|
|
890
|
-
}
|
|
891
|
-
return {
|
|
892
|
-
...entry,
|
|
893
|
-
mtime: entry.mtime.toISOString(),
|
|
894
|
-
};
|
|
895
|
-
}
|
|
896
|
-
|
|
897
|
-
private static deserializeEntry(data: any): FsEntry {
|
|
898
|
-
const mtime = new Date(data.mtime);
|
|
899
|
-
|
|
900
|
-
if (data.type === "file") {
|
|
901
|
-
let content = data.content;
|
|
902
|
-
if (data.contentType === "uint8array" && Array.isArray(content)) {
|
|
903
|
-
content = new Uint8Array(content);
|
|
904
|
-
}
|
|
905
|
-
return { type: "file", content, mode: data.mode, mtime };
|
|
906
|
-
}
|
|
907
|
-
if (data.type === "symlink") {
|
|
908
|
-
return { type: "symlink", target: data.target, mode: data.mode, mtime };
|
|
909
|
-
}
|
|
910
|
-
return { type: "directory", mode: data.mode, mtime };
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
private promisifyRequest<T>(request: IDBRequest<T>): Promise<T> {
|
|
914
|
-
return new Promise((resolve, reject) => {
|
|
915
|
-
request.onerror = () => reject(request.error);
|
|
916
|
-
request.onsuccess = () => resolve(request.result);
|
|
917
|
-
});
|
|
918
|
-
}
|
|
919
|
-
|
|
920
|
-
private promisifyTransaction(tx: IDBTransaction): Promise<void> {
|
|
921
|
-
return new Promise((resolve, reject) => {
|
|
922
|
-
tx.onerror = () => reject(tx.error);
|
|
923
|
-
tx.oncomplete = () => resolve();
|
|
924
|
-
});
|
|
925
|
-
}
|
|
926
798
|
}
|
|
927
799
|
|
|
928
800
|
/**
|
|
929
|
-
*
|
|
801
|
+
* Create an in-memory filesystem.
|
|
802
|
+
*
|
|
803
|
+
* @param initialFiles - Optional initial files to populate the filesystem
|
|
804
|
+
* @returns A new Filesystem instance
|
|
930
805
|
*/
|
|
931
|
-
export function
|
|
932
|
-
|
|
933
|
-
// Use IndexedDbFs.create() for async with persistence
|
|
934
|
-
return IndexedDbFs.createInMemory({ initialFiles });
|
|
806
|
+
export function createFilesystem(options?: FilesystemOptions): Filesystem {
|
|
807
|
+
return Filesystem.create(options);
|
|
935
808
|
}
|
|
809
|
+
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Browser polyfills - inject before anything else loads
|
|
3
|
+
// =============================================================================
|
|
4
|
+
|
|
5
|
+
// Some dependencies (like just-bash) reference Node.js globals.
|
|
6
|
+
// Provide shims so they work in the browser without user configuration.
|
|
7
|
+
if (typeof window !== "undefined" && typeof globalThis.process === "undefined") {
|
|
8
|
+
(globalThis as Record<string, unknown>).process = {
|
|
9
|
+
env: {},
|
|
10
|
+
platform: "browser",
|
|
11
|
+
version: "v20.0.0",
|
|
12
|
+
browser: true,
|
|
13
|
+
cwd: () => "/",
|
|
14
|
+
nextTick: (fn: () => void) => setTimeout(fn, 0),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
1
18
|
// =============================================================================
|
|
2
19
|
// CORE API - Most users only need these
|
|
3
20
|
// =============================================================================
|
|
@@ -8,19 +25,23 @@
|
|
|
8
25
|
|
|
9
26
|
export {
|
|
10
27
|
createSandbox,
|
|
11
|
-
createInMemorySandbox,
|
|
12
28
|
type Sandbox,
|
|
13
29
|
type SandboxOptions,
|
|
30
|
+
type SandboxState,
|
|
31
|
+
type SandboxBashOptions,
|
|
14
32
|
} from "./sandbox";
|
|
15
33
|
|
|
34
|
+
// -----------------------------------------------------------------------------
|
|
35
|
+
// Builder (recommended for agent workflows)
|
|
36
|
+
// -----------------------------------------------------------------------------
|
|
37
|
+
|
|
16
38
|
export {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
type
|
|
20
|
-
type
|
|
21
|
-
type
|
|
22
|
-
|
|
23
|
-
} from "./sandbox-manager";
|
|
39
|
+
createBuilder,
|
|
40
|
+
type BuildResult,
|
|
41
|
+
type CreateBuilderOptions,
|
|
42
|
+
type BuildCallOptions,
|
|
43
|
+
type BuilderFn,
|
|
44
|
+
} from "./builder";
|
|
24
45
|
|
|
25
46
|
// -----------------------------------------------------------------------------
|
|
26
47
|
// Module Loading (use after build to get exports)
|
|
@@ -51,6 +72,7 @@ export {
|
|
|
51
72
|
// -----------------------------------------------------------------------------
|
|
52
73
|
|
|
53
74
|
export type { BundleResult } from "./bundler";
|
|
75
|
+
export type { BuildOutput, ValidateFn } from "./commands/types";
|
|
54
76
|
export type { TypecheckResult, Diagnostic } from "./typechecker";
|
|
55
77
|
export type { PackageManifest, InstallResult } from "./packages";
|
|
56
78
|
|
|
@@ -114,9 +136,9 @@ export {
|
|
|
114
136
|
// -----------------------------------------------------------------------------
|
|
115
137
|
|
|
116
138
|
export {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
type
|
|
139
|
+
Filesystem,
|
|
140
|
+
createFilesystem,
|
|
141
|
+
type FilesystemOptions,
|
|
120
142
|
} from "./fs";
|
|
121
143
|
|
|
122
144
|
export type { IFileSystem, FsEntry } from "just-bash/browser";
|
|
@@ -146,4 +168,4 @@ export {
|
|
|
146
168
|
type RunContext,
|
|
147
169
|
type RunOptions,
|
|
148
170
|
type RunResult,
|
|
149
|
-
} from "./commands";
|
|
171
|
+
} from "./commands/index";
|
package/src/internal.ts
CHANGED
|
@@ -112,5 +112,8 @@ export { formatEsbuildMessages } from "./commands";
|
|
|
112
112
|
// BuildEmitter (for custom build event handling)
|
|
113
113
|
// =============================================================================
|
|
114
114
|
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
/**
|
|
116
|
+
* Build event emitter for sandbox environments.
|
|
117
|
+
* Use this for custom build event handling in advanced use cases.
|
|
118
|
+
*/
|
|
119
|
+
export { BuildEmitter } from "./build-emitter";
|