@scelar/nodepod 1.0.4 → 1.0.5
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/dist/{child_process-lxSKECHq.cjs → child_process-B9qsOKHs.cjs} +7434 -7434
- package/dist/{child_process-lxSKECHq.cjs.map → child_process-B9qsOKHs.cjs.map} +1 -1
- package/dist/{child_process-53fMkug_.js → child_process-PY34i_6n.js} +8233 -8233
- package/dist/{child_process-53fMkug_.js.map → child_process-PY34i_6n.js.map} +1 -1
- package/dist/{index-C-TQIrdG.cjs → index-CyhVjVJU.cjs} +38383 -38005
- package/dist/index-CyhVjVJU.cjs.map +1 -0
- package/dist/{index-B8lyh_ti.js → index-D8Hn2kWU.js} +36455 -36065
- package/dist/index-D8Hn2kWU.js.map +1 -0
- package/dist/index.cjs +67 -65
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +88 -86
- package/dist/index.mjs +61 -59
- package/dist/memory-handler.d.ts +57 -0
- package/dist/memory-volume.d.ts +157 -147
- package/dist/packages/installer.d.ts +44 -41
- package/dist/persistence/idb-cache.d.ts +7 -0
- package/dist/script-engine.d.ts +84 -81
- package/dist/sdk/nodepod-process.d.ts +29 -28
- package/dist/sdk/nodepod.d.ts +59 -40
- package/dist/sdk/types.d.ts +64 -59
- package/package.json +97 -97
- package/src/index.ts +2 -0
- package/src/memory-handler.ts +168 -0
- package/src/memory-volume.ts +72 -8
- package/src/packages/installer.ts +49 -1
- package/src/packages/version-resolver.ts +421 -421
- package/src/persistence/idb-cache.ts +107 -0
- package/src/polyfills/events.ts +6 -2
- package/src/polyfills/stream.ts +1 -0
- package/src/polyfills/wasi.ts +1306 -1306
- package/src/polyfills/zlib.ts +881 -881
- package/src/script-engine.ts +3722 -3694
- package/src/sdk/nodepod-process.ts +94 -86
- package/src/sdk/nodepod.ts +52 -6
- package/src/sdk/types.ts +82 -77
- package/src/threading/process-manager.ts +11 -0
- package/src/threading/worker-protocol.ts +358 -358
- package/dist/index-B8lyh_ti.js.map +0 -1
- package/dist/index-C-TQIrdG.cjs.map +0 -1
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// IndexedDB-backed cache for node_modules snapshots.
|
|
2
|
+
// Keyed by a hash of the package.json contents so stale caches auto-invalidate.
|
|
3
|
+
|
|
4
|
+
import type { VolumeSnapshot } from '../engine-types';
|
|
5
|
+
|
|
6
|
+
const DB_NAME = 'nodepod-snapshots';
|
|
7
|
+
const STORE_NAME = 'snapshots';
|
|
8
|
+
const DB_VERSION = 1;
|
|
9
|
+
const MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
|
|
10
|
+
|
|
11
|
+
export interface IDBSnapshotCache {
|
|
12
|
+
get(packageJsonHash: string): Promise<VolumeSnapshot | null>;
|
|
13
|
+
set(packageJsonHash: string, snapshot: VolumeSnapshot): Promise<void>;
|
|
14
|
+
close(): void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function openDB(): Promise<IDBDatabase | null> {
|
|
18
|
+
if (typeof indexedDB === 'undefined') return Promise.resolve(null);
|
|
19
|
+
return new Promise((resolve) => {
|
|
20
|
+
try {
|
|
21
|
+
const req = indexedDB.open(DB_NAME, DB_VERSION);
|
|
22
|
+
req.onupgradeneeded = () => {
|
|
23
|
+
const db = req.result;
|
|
24
|
+
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
|
25
|
+
db.createObjectStore(STORE_NAME);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
req.onsuccess = () => resolve(req.result);
|
|
29
|
+
req.onerror = () => resolve(null);
|
|
30
|
+
} catch {
|
|
31
|
+
resolve(null);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function idbGet(db: IDBDatabase, key: string): Promise<any> {
|
|
37
|
+
return new Promise((resolve, reject) => {
|
|
38
|
+
const tx = db.transaction(STORE_NAME, 'readonly');
|
|
39
|
+
const store = tx.objectStore(STORE_NAME);
|
|
40
|
+
const req = store.get(key);
|
|
41
|
+
req.onsuccess = () => resolve(req.result ?? null);
|
|
42
|
+
req.onerror = () => reject(req.error);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function idbPut(db: IDBDatabase, key: string, value: any): Promise<void> {
|
|
47
|
+
return new Promise((resolve, reject) => {
|
|
48
|
+
const tx = db.transaction(STORE_NAME, 'readwrite');
|
|
49
|
+
const store = tx.objectStore(STORE_NAME);
|
|
50
|
+
store.put(value, key);
|
|
51
|
+
tx.oncomplete = () => resolve();
|
|
52
|
+
tx.onerror = () => reject(tx.error);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function idbCleanExpired(db: IDBDatabase): void {
|
|
57
|
+
try {
|
|
58
|
+
const tx = db.transaction(STORE_NAME, 'readwrite');
|
|
59
|
+
const store = tx.objectStore(STORE_NAME);
|
|
60
|
+
const req = store.openCursor();
|
|
61
|
+
const now = Date.now();
|
|
62
|
+
req.onsuccess = () => {
|
|
63
|
+
const cursor = req.result;
|
|
64
|
+
if (!cursor) return;
|
|
65
|
+
const entry = cursor.value;
|
|
66
|
+
if (entry?.createdAt && (now - entry.createdAt) > MAX_AGE_MS) {
|
|
67
|
+
cursor.delete();
|
|
68
|
+
}
|
|
69
|
+
cursor.continue();
|
|
70
|
+
};
|
|
71
|
+
} catch { /* best-effort cleanup */ }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export async function openSnapshotCache(): Promise<IDBSnapshotCache | null> {
|
|
75
|
+
const db = await openDB();
|
|
76
|
+
if (!db) return null;
|
|
77
|
+
|
|
78
|
+
// Background cleanup of expired entries
|
|
79
|
+
idbCleanExpired(db);
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
async get(packageJsonHash: string): Promise<VolumeSnapshot | null> {
|
|
83
|
+
try {
|
|
84
|
+
const entry = await idbGet(db, packageJsonHash);
|
|
85
|
+
if (!entry?.snapshot) return null;
|
|
86
|
+
// Check expiry
|
|
87
|
+
if (entry.createdAt && (Date.now() - entry.createdAt) > MAX_AGE_MS) return null;
|
|
88
|
+
return entry.snapshot as VolumeSnapshot;
|
|
89
|
+
} catch {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
async set(packageJsonHash: string, snapshot: VolumeSnapshot): Promise<void> {
|
|
95
|
+
try {
|
|
96
|
+
await idbPut(db, packageJsonHash, {
|
|
97
|
+
snapshot,
|
|
98
|
+
createdAt: Date.now(),
|
|
99
|
+
});
|
|
100
|
+
} catch { /* silently fail — cache is optional */ }
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
close(): void {
|
|
104
|
+
try { db.close(); } catch { /* ignore */ }
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
}
|
package/src/polyfills/events.ts
CHANGED
|
@@ -11,7 +11,7 @@ const DEFAULT_CEILING = 10;
|
|
|
11
11
|
// complete in browser, so we detect FSWatchers by _watched Map and bridge
|
|
12
12
|
// VFS file changes directly to the watcher.
|
|
13
13
|
const _vfsBridged = new WeakSet<object>();
|
|
14
|
-
|
|
14
|
+
const _vfsBridgeCleanups = new Set<() => void>();
|
|
15
15
|
|
|
16
16
|
function _bridgeVfsToWatcher(watcher: EventEmitter): void {
|
|
17
17
|
const vol = (globalThis as any).__nodepodVolume;
|
|
@@ -45,7 +45,11 @@ function _bridgeVfsToWatcher(watcher: EventEmitter): void {
|
|
|
45
45
|
}, DEBOUNCE_MS),
|
|
46
46
|
});
|
|
47
47
|
});
|
|
48
|
-
|
|
48
|
+
const selfCleanup = () => {
|
|
49
|
+
cleanup();
|
|
50
|
+
_vfsBridgeCleanups.delete(selfCleanup);
|
|
51
|
+
};
|
|
52
|
+
_vfsBridgeCleanups.add(selfCleanup);
|
|
49
53
|
}
|
|
50
54
|
|
|
51
55
|
// lazily init the listener map (handles Object.create() bypassing constructor)
|
package/src/polyfills/stream.ts
CHANGED
|
@@ -836,6 +836,7 @@ Writable.prototype.destroy = function destroy(fault?: Error): any {
|
|
|
836
836
|
this._destroy(fault ?? null, (err: Error | null | undefined) => {
|
|
837
837
|
if (err && !fault) this.errored = err;
|
|
838
838
|
this._parts.length = 0;
|
|
839
|
+
this._corkedWrites.length = 0;
|
|
839
840
|
this._writableByteLength = 0;
|
|
840
841
|
this._closed = true;
|
|
841
842
|
this.writable = false;
|