@solcreek/adapter-creek 0.1.0
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/LICENSE +190 -0
- package/README.md +184 -0
- package/dist/build.d.ts +57 -0
- package/dist/build.js +1382 -0
- package/dist/bundler.d.ts +20 -0
- package/dist/bundler.js +991 -0
- package/dist/cache-handler.d.ts +32 -0
- package/dist/cache-handler.js +100 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +247 -0
- package/dist/manifest.d.ts +40 -0
- package/dist/manifest.js +27 -0
- package/dist/worker-entry.d.ts +133 -0
- package/dist/worker-entry.js +7734 -0
- package/package.json +64 -0
- package/src/shims/als-polyfill.js +7 -0
- package/src/shims/critters.js +7 -0
- package/src/shims/empty.js +2 -0
- package/src/shims/env.js +3 -0
- package/src/shims/fast-set-immediate.js +285 -0
- package/src/shims/fs.js +225 -0
- package/src/shims/http.js +240 -0
- package/src/shims/image-optimizer.js +18 -0
- package/src/shims/load-manifest.js +123 -0
- package/src/shims/opentelemetry.js +229 -0
- package/src/shims/sharp.js +12 -0
- package/src/shims/sqlite3-binding.js +517 -0
- package/src/shims/track-module-loading.js +68 -0
- package/src/shims/vm.js +49 -0
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
// Creek adapter — sqlite3 native-binding replacement.
|
|
2
|
+
//
|
|
3
|
+
// The upstream `sqlite3` package loads a .node binary via require('bindings').
|
|
4
|
+
// workerd has no .node loader, and Next.js's build-time static analysis
|
|
5
|
+
// (which evaluates user modules to collect page config) also can't load it
|
|
6
|
+
// when `pnpm install --ignore-scripts` skipped sqlite3's post-install build.
|
|
7
|
+
//
|
|
8
|
+
// Our patcher (`scripts/patch-node-modules-sqlite3.mjs`) replaces
|
|
9
|
+
// `node_modules/sqlite3/lib/sqlite3-binding.js` with this file. The outer
|
|
10
|
+
// `sqlite3/lib/sqlite3.js` wrapper stays intact — it decorates the classes
|
|
11
|
+
// we export here with promise helpers and parameter normalization, so we
|
|
12
|
+
// only need to match the binding surface, not the full user-facing API.
|
|
13
|
+
//
|
|
14
|
+
// Backend: sql.js (WASM SQLite). Works at build-time (Node) and runtime
|
|
15
|
+
// (workerd) without a native binary.
|
|
16
|
+
|
|
17
|
+
'use strict';
|
|
18
|
+
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// Constants — copied from SQLite's sqlite3.h.
|
|
21
|
+
// * OPEN_* — open flags (passed as `mode` to `new Database`)
|
|
22
|
+
// * Plain names like READONLY / ERROR are SQLite result codes.
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
// Open flags
|
|
26
|
+
exports.OPEN_READONLY = 0x00000001;
|
|
27
|
+
exports.OPEN_READWRITE = 0x00000002;
|
|
28
|
+
exports.OPEN_CREATE = 0x00000004;
|
|
29
|
+
exports.OPEN_DELETEONCLOSE = 0x00000008;
|
|
30
|
+
exports.OPEN_EXCLUSIVE = 0x00000010;
|
|
31
|
+
exports.OPEN_AUTOPROXY = 0x00000020;
|
|
32
|
+
exports.OPEN_URI = 0x00000040;
|
|
33
|
+
exports.OPEN_MEMORY = 0x00000080;
|
|
34
|
+
exports.OPEN_MAIN_DB = 0x00000100;
|
|
35
|
+
exports.OPEN_TEMP_DB = 0x00000200;
|
|
36
|
+
exports.OPEN_TRANSIENT_DB = 0x00000400;
|
|
37
|
+
exports.OPEN_MAIN_JOURNAL = 0x00000800;
|
|
38
|
+
exports.OPEN_TEMP_JOURNAL = 0x00001000;
|
|
39
|
+
exports.OPEN_SUBJOURNAL = 0x00002000;
|
|
40
|
+
exports.OPEN_SUPER_JOURNAL = 0x00004000;
|
|
41
|
+
exports.OPEN_NOMUTEX = 0x00008000;
|
|
42
|
+
exports.OPEN_FULLMUTEX = 0x00010000;
|
|
43
|
+
exports.OPEN_SHAREDCACHE = 0x00020000;
|
|
44
|
+
exports.OPEN_PRIVATECACHE = 0x00040000;
|
|
45
|
+
exports.OPEN_WAL = 0x00080000;
|
|
46
|
+
exports.OPEN_NOFOLLOW = 0x01000000;
|
|
47
|
+
|
|
48
|
+
// Result codes
|
|
49
|
+
exports.OK = 0;
|
|
50
|
+
exports.ERROR = 1;
|
|
51
|
+
exports.INTERNAL = 2;
|
|
52
|
+
exports.PERM = 3;
|
|
53
|
+
exports.ABORT = 4;
|
|
54
|
+
exports.BUSY = 5;
|
|
55
|
+
exports.LOCKED = 6;
|
|
56
|
+
exports.NOMEM = 7;
|
|
57
|
+
exports.READONLY = 8;
|
|
58
|
+
exports.INTERRUPT = 9;
|
|
59
|
+
exports.IOERR = 10;
|
|
60
|
+
exports.CORRUPT = 11;
|
|
61
|
+
exports.NOTFOUND = 12;
|
|
62
|
+
exports.FULL = 13;
|
|
63
|
+
exports.CANTOPEN = 14;
|
|
64
|
+
exports.PROTOCOL = 15;
|
|
65
|
+
exports.EMPTY = 16;
|
|
66
|
+
exports.SCHEMA = 17;
|
|
67
|
+
exports.TOOBIG = 18;
|
|
68
|
+
exports.CONSTRAINT = 19;
|
|
69
|
+
exports.MISMATCH = 20;
|
|
70
|
+
exports.MISUSE = 21;
|
|
71
|
+
exports.NOLFS = 22;
|
|
72
|
+
exports.AUTH = 23;
|
|
73
|
+
exports.FORMAT = 24;
|
|
74
|
+
exports.RANGE = 25;
|
|
75
|
+
exports.NOTADB = 26;
|
|
76
|
+
exports.NOTICE = 27;
|
|
77
|
+
exports.WARNING = 28;
|
|
78
|
+
exports.ROW = 100;
|
|
79
|
+
exports.DONE = 101;
|
|
80
|
+
|
|
81
|
+
exports.VERSION = '3.46.1-creek-shim';
|
|
82
|
+
exports.SOURCE_ID = '0000000000000000000000000000000000000000';
|
|
83
|
+
exports.VERSION_NUMBER = 3046001;
|
|
84
|
+
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
// sql.js bootstrap — resolved lazily + once per process.
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
|
|
89
|
+
// sql.js's Emscripten bootstrap detects its environment by reading
|
|
90
|
+
// `globalThis.document?.currentScript?.src` and `self.location.href`.
|
|
91
|
+
// In workerd `self.location` is undefined — accessing `.href` throws.
|
|
92
|
+
// Stub a minimal location so the detection code falls through.
|
|
93
|
+
function ensureSqlJsGlobals() {
|
|
94
|
+
if (typeof globalThis.self === 'undefined') globalThis.self = globalThis;
|
|
95
|
+
if (typeof globalThis.self.location === 'undefined') {
|
|
96
|
+
try { globalThis.self.location = { href: '' }; }
|
|
97
|
+
catch { globalThis.location = globalThis.location || { href: '' }; }
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
let _SQL;
|
|
102
|
+
let _SQL_LOADING;
|
|
103
|
+
function loadSqlJs() {
|
|
104
|
+
if (_SQL) return Promise.resolve(_SQL);
|
|
105
|
+
if (_SQL_LOADING) return _SQL_LOADING;
|
|
106
|
+
_SQL_LOADING = (async () => {
|
|
107
|
+
ensureSqlJsGlobals();
|
|
108
|
+
// Use the asm.js build, not the default WASM one. workerd disallows
|
|
109
|
+
// runtime `WebAssembly.instantiate(bytes)` ("Wasm code generation
|
|
110
|
+
// disallowed by embedder"); only statically-imported CompiledWasm
|
|
111
|
+
// modules load. The asm.js variant is pure JavaScript (~1.3MB) and
|
|
112
|
+
// sidesteps that restriction entirely. Node/build-time works the
|
|
113
|
+
// same with either.
|
|
114
|
+
const initSqlJs = require('sql.js/dist/sql-asm.js');
|
|
115
|
+
_SQL = await initSqlJs();
|
|
116
|
+
return _SQL;
|
|
117
|
+
})();
|
|
118
|
+
return _SQL_LOADING;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
// Database class — async-ready facade over sql.js.
|
|
123
|
+
// sqlite3's real Database opens asynchronously via libuv and fires the
|
|
124
|
+
// constructor callback when ready. We keep the same shape: the constructor
|
|
125
|
+
// returns synchronously, and `_ready` resolves when the underlying sql.js
|
|
126
|
+
// instance exists.
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
|
|
129
|
+
const EventEmitter = require('events').EventEmitter;
|
|
130
|
+
|
|
131
|
+
function extractCallback(args) {
|
|
132
|
+
if (args.length && typeof args[args.length - 1] === 'function') {
|
|
133
|
+
return args.pop();
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
class Database extends EventEmitter {
|
|
139
|
+
constructor(filename, mode, cb) {
|
|
140
|
+
super();
|
|
141
|
+
if (typeof mode === 'function') { cb = mode; mode = undefined; }
|
|
142
|
+
this.filename = filename;
|
|
143
|
+
this.mode = mode;
|
|
144
|
+
this.open = false;
|
|
145
|
+
this._db = null;
|
|
146
|
+
this._ready = this._init()
|
|
147
|
+
.then(() => {
|
|
148
|
+
this.open = true;
|
|
149
|
+
this.emit('open');
|
|
150
|
+
if (cb) cb.call(this, null);
|
|
151
|
+
})
|
|
152
|
+
.catch((err) => {
|
|
153
|
+
this.emit('error', err);
|
|
154
|
+
if (cb) cb.call(this, err);
|
|
155
|
+
else throw err; // match sqlite3 behaviour when no cb
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async _init() {
|
|
160
|
+
const SQL = await loadSqlJs();
|
|
161
|
+
if (!this.filename || this.filename === ':memory:') {
|
|
162
|
+
this._db = new SQL.Database();
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
// Read the file via node:fs — this runs at build-time (getStaticProps
|
|
166
|
+
// evaluation) or in sandboxed runtimes that still expose `node:fs`
|
|
167
|
+
// (nodejs_compat on workerd). If fs is unavailable (pure workerd
|
|
168
|
+
// runtime path), users should migrate to env.DB (D1) — the future
|
|
169
|
+
// Phase C step extends this shim to route through D1 bindings.
|
|
170
|
+
const fs = require('node:fs');
|
|
171
|
+
const bytes = fs.readFileSync(this.filename);
|
|
172
|
+
this._db = new SQL.Database(new Uint8Array(bytes));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
_rowsFromStmt(stmt) {
|
|
176
|
+
const rows = [];
|
|
177
|
+
while (stmt.step()) rows.push(stmt.getAsObject());
|
|
178
|
+
return rows;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
_firstRowFromStmt(stmt) {
|
|
182
|
+
return stmt.step() ? stmt.getAsObject() : undefined;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
all(sql, ...rest) {
|
|
186
|
+
const cb = extractCallback(rest);
|
|
187
|
+
const params = rest.length === 1 && Array.isArray(rest[0]) ? rest[0] : rest;
|
|
188
|
+
this._ready
|
|
189
|
+
.then(() => {
|
|
190
|
+
const stmt = this._db.prepare(sql);
|
|
191
|
+
try {
|
|
192
|
+
if (params.length) stmt.bind(params);
|
|
193
|
+
const rows = this._rowsFromStmt(stmt);
|
|
194
|
+
if (cb) cb.call(this, null, rows);
|
|
195
|
+
} finally {
|
|
196
|
+
stmt.free();
|
|
197
|
+
}
|
|
198
|
+
})
|
|
199
|
+
.catch((err) => {
|
|
200
|
+
if (cb) cb.call(this, err);
|
|
201
|
+
else this.emit('error', err);
|
|
202
|
+
});
|
|
203
|
+
return this;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
get(sql, ...rest) {
|
|
207
|
+
const cb = extractCallback(rest);
|
|
208
|
+
const params = rest.length === 1 && Array.isArray(rest[0]) ? rest[0] : rest;
|
|
209
|
+
this._ready
|
|
210
|
+
.then(() => {
|
|
211
|
+
const stmt = this._db.prepare(sql);
|
|
212
|
+
try {
|
|
213
|
+
if (params.length) stmt.bind(params);
|
|
214
|
+
const row = this._firstRowFromStmt(stmt);
|
|
215
|
+
if (cb) cb.call(this, null, row);
|
|
216
|
+
} finally {
|
|
217
|
+
stmt.free();
|
|
218
|
+
}
|
|
219
|
+
})
|
|
220
|
+
.catch((err) => {
|
|
221
|
+
if (cb) cb.call(this, err);
|
|
222
|
+
else this.emit('error', err);
|
|
223
|
+
});
|
|
224
|
+
return this;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
run(sql, ...rest) {
|
|
228
|
+
const cb = extractCallback(rest);
|
|
229
|
+
const params = rest.length === 1 && Array.isArray(rest[0]) ? rest[0] : rest;
|
|
230
|
+
const self = this;
|
|
231
|
+
this._ready
|
|
232
|
+
.then(() => {
|
|
233
|
+
const stmt = self._db.prepare(sql);
|
|
234
|
+
try {
|
|
235
|
+
if (params.length) stmt.bind(params);
|
|
236
|
+
stmt.step();
|
|
237
|
+
// Real sqlite3 sets lastID / changes on the callback's `this`.
|
|
238
|
+
const ctx = { lastID: 0, changes: self._db.getRowsModified?.() ?? 0 };
|
|
239
|
+
if (cb) cb.call(ctx, null);
|
|
240
|
+
} finally {
|
|
241
|
+
stmt.free();
|
|
242
|
+
}
|
|
243
|
+
})
|
|
244
|
+
.catch((err) => {
|
|
245
|
+
if (cb) cb.call(self, err);
|
|
246
|
+
else self.emit('error', err);
|
|
247
|
+
});
|
|
248
|
+
return this;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
each(sql, ...rest) {
|
|
252
|
+
// sqlite3's `each(sql, [params], rowCb, completeCb)` — both callbacks optional
|
|
253
|
+
const callbacks = [];
|
|
254
|
+
while (rest.length && typeof rest[rest.length - 1] === 'function') {
|
|
255
|
+
callbacks.unshift(rest.pop());
|
|
256
|
+
}
|
|
257
|
+
const [rowCb, completeCb] = callbacks;
|
|
258
|
+
const params = rest.length === 1 && Array.isArray(rest[0]) ? rest[0] : rest;
|
|
259
|
+
this._ready
|
|
260
|
+
.then(() => {
|
|
261
|
+
const stmt = this._db.prepare(sql);
|
|
262
|
+
try {
|
|
263
|
+
if (params.length) stmt.bind(params);
|
|
264
|
+
let n = 0;
|
|
265
|
+
while (stmt.step()) {
|
|
266
|
+
n += 1;
|
|
267
|
+
if (rowCb) rowCb.call(this, null, stmt.getAsObject());
|
|
268
|
+
}
|
|
269
|
+
if (completeCb) completeCb.call(this, null, n);
|
|
270
|
+
} finally {
|
|
271
|
+
stmt.free();
|
|
272
|
+
}
|
|
273
|
+
})
|
|
274
|
+
.catch((err) => {
|
|
275
|
+
if (rowCb) rowCb.call(this, err);
|
|
276
|
+
if (completeCb) completeCb.call(this, err, 0);
|
|
277
|
+
});
|
|
278
|
+
return this;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
exec(sql, cb) {
|
|
282
|
+
this._ready
|
|
283
|
+
.then(() => {
|
|
284
|
+
this._db.exec(sql);
|
|
285
|
+
if (cb) cb.call(this, null);
|
|
286
|
+
})
|
|
287
|
+
.catch((err) => {
|
|
288
|
+
if (cb) cb.call(this, err);
|
|
289
|
+
else this.emit('error', err);
|
|
290
|
+
});
|
|
291
|
+
return this;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
prepare(sql, ...rest) {
|
|
295
|
+
const cb = extractCallback(rest);
|
|
296
|
+
const params = rest.length === 1 && Array.isArray(rest[0]) ? rest[0] : rest;
|
|
297
|
+
return new Statement(this, sql, params, cb);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
serialize(cb) {
|
|
301
|
+
// Our backend is already sync-serialized (sql.js is single-threaded).
|
|
302
|
+
// Real sqlite3 uses this to batch queued operations; the wrapper lib
|
|
303
|
+
// just calls cb immediately then relies on FIFO ordering, so we
|
|
304
|
+
// match that.
|
|
305
|
+
if (typeof cb === 'function') cb.call(this);
|
|
306
|
+
return this;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
parallelize(cb) {
|
|
310
|
+
if (typeof cb === 'function') cb.call(this);
|
|
311
|
+
return this;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
configure(_option, _value) {
|
|
315
|
+
// Accept-and-ignore: `busyTimeout`, `limit`, etc. Meaningless for sql.js.
|
|
316
|
+
return this;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
loadExtension(_path, cb) {
|
|
320
|
+
const err = new Error('sqlite3 extension loading unsupported by creek shim');
|
|
321
|
+
if (cb) cb.call(this, err);
|
|
322
|
+
else this.emit('error', err);
|
|
323
|
+
return this;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
close(cb) {
|
|
327
|
+
this._ready
|
|
328
|
+
.then(() => {
|
|
329
|
+
try {
|
|
330
|
+
if (this._db) this._db.close();
|
|
331
|
+
this.open = false;
|
|
332
|
+
this.emit('close');
|
|
333
|
+
if (cb) cb.call(this, null);
|
|
334
|
+
} catch (err) {
|
|
335
|
+
if (cb) cb.call(this, err);
|
|
336
|
+
else this.emit('error', err);
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
return this;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
interrupt() { /* no-op */ }
|
|
343
|
+
wait() { /* no-op */ }
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Real sqlite3 exposes verbose/cached on the module exports. Some code
|
|
347
|
+
// does `sqlite3.verbose()` — in the original package this returns the
|
|
348
|
+
// same module with extra stack-trace debugging. We stub it to a no-op
|
|
349
|
+
// that returns ourselves so chaining works.
|
|
350
|
+
// Handled by the outer sqlite3.js wrapper, but a defensive no-op here
|
|
351
|
+
// helps when code imports the binding directly.
|
|
352
|
+
Database.verbose = function verbose() { return module.exports; };
|
|
353
|
+
|
|
354
|
+
// ---------------------------------------------------------------------------
|
|
355
|
+
// Statement — represents a prepared statement. sqlite3's Statement class
|
|
356
|
+
// is an EventEmitter and exposes run/all/get/each/reset/finalize.
|
|
357
|
+
// ---------------------------------------------------------------------------
|
|
358
|
+
|
|
359
|
+
class Statement extends EventEmitter {
|
|
360
|
+
constructor(database, sql, boundParams, cb) {
|
|
361
|
+
super();
|
|
362
|
+
this._db = database;
|
|
363
|
+
this._sql = sql;
|
|
364
|
+
this._boundParams = boundParams || [];
|
|
365
|
+
this._stmt = null;
|
|
366
|
+
this._ready = database._ready
|
|
367
|
+
.then(() => {
|
|
368
|
+
this._stmt = database._db.prepare(sql);
|
|
369
|
+
if (this._boundParams.length) this._stmt.bind(this._boundParams);
|
|
370
|
+
if (cb) cb.call(this, null);
|
|
371
|
+
})
|
|
372
|
+
.catch((err) => {
|
|
373
|
+
if (cb) cb.call(this, err);
|
|
374
|
+
else this.emit('error', err);
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
bind(...rest) {
|
|
379
|
+
const cb = extractCallback(rest);
|
|
380
|
+
const params = rest.length === 1 && Array.isArray(rest[0]) ? rest[0] : rest;
|
|
381
|
+
this._ready
|
|
382
|
+
.then(() => {
|
|
383
|
+
this._stmt.bind(params);
|
|
384
|
+
if (cb) cb.call(this, null);
|
|
385
|
+
})
|
|
386
|
+
.catch((err) => {
|
|
387
|
+
if (cb) cb.call(this, err);
|
|
388
|
+
else this.emit('error', err);
|
|
389
|
+
});
|
|
390
|
+
return this;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
reset(cb) {
|
|
394
|
+
this._ready
|
|
395
|
+
.then(() => {
|
|
396
|
+
this._stmt.reset();
|
|
397
|
+
if (cb) cb.call(this, null);
|
|
398
|
+
})
|
|
399
|
+
.catch((err) => {
|
|
400
|
+
if (cb) cb.call(this, err);
|
|
401
|
+
else this.emit('error', err);
|
|
402
|
+
});
|
|
403
|
+
return this;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
finalize(cb) {
|
|
407
|
+
this._ready
|
|
408
|
+
.then(() => {
|
|
409
|
+
try {
|
|
410
|
+
if (this._stmt) this._stmt.free();
|
|
411
|
+
if (cb) cb.call(this, null);
|
|
412
|
+
} catch (err) {
|
|
413
|
+
if (cb) cb.call(this, err);
|
|
414
|
+
else this.emit('error', err);
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
return this;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
all(...rest) {
|
|
421
|
+
const cb = extractCallback(rest);
|
|
422
|
+
const params = rest.length === 1 && Array.isArray(rest[0]) ? rest[0] : rest;
|
|
423
|
+
this._ready
|
|
424
|
+
.then(() => {
|
|
425
|
+
if (params.length) this._stmt.bind(params);
|
|
426
|
+
const rows = [];
|
|
427
|
+
while (this._stmt.step()) rows.push(this._stmt.getAsObject());
|
|
428
|
+
this._stmt.reset();
|
|
429
|
+
if (cb) cb.call(this, null, rows);
|
|
430
|
+
})
|
|
431
|
+
.catch((err) => {
|
|
432
|
+
if (cb) cb.call(this, err);
|
|
433
|
+
else this.emit('error', err);
|
|
434
|
+
});
|
|
435
|
+
return this;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
get(...rest) {
|
|
439
|
+
const cb = extractCallback(rest);
|
|
440
|
+
const params = rest.length === 1 && Array.isArray(rest[0]) ? rest[0] : rest;
|
|
441
|
+
this._ready
|
|
442
|
+
.then(() => {
|
|
443
|
+
if (params.length) this._stmt.bind(params);
|
|
444
|
+
const row = this._stmt.step() ? this._stmt.getAsObject() : undefined;
|
|
445
|
+
this._stmt.reset();
|
|
446
|
+
if (cb) cb.call(this, null, row);
|
|
447
|
+
})
|
|
448
|
+
.catch((err) => {
|
|
449
|
+
if (cb) cb.call(this, err);
|
|
450
|
+
else this.emit('error', err);
|
|
451
|
+
});
|
|
452
|
+
return this;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
run(...rest) {
|
|
456
|
+
const cb = extractCallback(rest);
|
|
457
|
+
const params = rest.length === 1 && Array.isArray(rest[0]) ? rest[0] : rest;
|
|
458
|
+
const self = this;
|
|
459
|
+
this._ready
|
|
460
|
+
.then(() => {
|
|
461
|
+
if (params.length) self._stmt.bind(params);
|
|
462
|
+
self._stmt.step();
|
|
463
|
+
self._stmt.reset();
|
|
464
|
+
const ctx = { lastID: 0, changes: self._db._db.getRowsModified?.() ?? 0 };
|
|
465
|
+
if (cb) cb.call(ctx, null);
|
|
466
|
+
})
|
|
467
|
+
.catch((err) => {
|
|
468
|
+
if (cb) cb.call(self, err);
|
|
469
|
+
else self.emit('error', err);
|
|
470
|
+
});
|
|
471
|
+
return this;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
each(...rest) {
|
|
475
|
+
const callbacks = [];
|
|
476
|
+
while (rest.length && typeof rest[rest.length - 1] === 'function') {
|
|
477
|
+
callbacks.unshift(rest.pop());
|
|
478
|
+
}
|
|
479
|
+
const [rowCb, completeCb] = callbacks;
|
|
480
|
+
const params = rest.length === 1 && Array.isArray(rest[0]) ? rest[0] : rest;
|
|
481
|
+
this._ready
|
|
482
|
+
.then(() => {
|
|
483
|
+
if (params.length) this._stmt.bind(params);
|
|
484
|
+
let n = 0;
|
|
485
|
+
while (this._stmt.step()) {
|
|
486
|
+
n += 1;
|
|
487
|
+
if (rowCb) rowCb.call(this, null, this._stmt.getAsObject());
|
|
488
|
+
}
|
|
489
|
+
this._stmt.reset();
|
|
490
|
+
if (completeCb) completeCb.call(this, null, n);
|
|
491
|
+
})
|
|
492
|
+
.catch((err) => {
|
|
493
|
+
if (rowCb) rowCb.call(this, err);
|
|
494
|
+
if (completeCb) completeCb.call(this, err, 0);
|
|
495
|
+
});
|
|
496
|
+
return this;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// ---------------------------------------------------------------------------
|
|
501
|
+
// Backup — sqlite3 supports online backups; sql.js doesn't. Stub a class
|
|
502
|
+
// that throws when used. Most test/build paths never touch this.
|
|
503
|
+
// ---------------------------------------------------------------------------
|
|
504
|
+
|
|
505
|
+
class Backup extends EventEmitter {
|
|
506
|
+
constructor() {
|
|
507
|
+
super();
|
|
508
|
+
throw new Error('sqlite3 Backup API unsupported by creek shim');
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
exports.Database = Database;
|
|
513
|
+
exports.Statement = Statement;
|
|
514
|
+
exports.Backup = Backup;
|
|
515
|
+
|
|
516
|
+
// Some callers read `sqlite3.cached` — the outer sqlite3.js wrapper
|
|
517
|
+
// installs `cached.Database`, so we don't need to provide it here.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// Shim for `next/dist/server/app-render/module-loading/track-module-loading.instance`.
|
|
2
|
+
//
|
|
3
|
+
// Next's original keeps `_moduleLoadingSignal` as a **module-level singleton**:
|
|
4
|
+
//
|
|
5
|
+
// let _moduleLoadingSignal
|
|
6
|
+
// function getModuleLoadingSignal() {
|
|
7
|
+
// if (!_moduleLoadingSignal) _moduleLoadingSignal = new CacheSignal()
|
|
8
|
+
// return _moduleLoadingSignal
|
|
9
|
+
// }
|
|
10
|
+
//
|
|
11
|
+
// On Node that's fine — there's no IoContext. On workerd it's a cross-request
|
|
12
|
+
// leak: CacheSignal.noMorePendingCaches schedules a `setImmediate` inside
|
|
13
|
+
// `scheduleImmediateAndTimeoutWithCleanup` and stores the returned cleanup
|
|
14
|
+
// closure (which captures the Immediate) on `this.pendingTimeoutCleanup`. The
|
|
15
|
+
// Immediate object is bound to the creating request's IoContext. A later
|
|
16
|
+
// request calls `beginRead()` → `this.pendingTimeoutCleanup()` →
|
|
17
|
+
// `clearImmediate(immediate)`, at which point workerd throws:
|
|
18
|
+
//
|
|
19
|
+
// "Cannot perform I/O on behalf of a different request."
|
|
20
|
+
//
|
|
21
|
+
// Repro on workerd: hit `/opengraph-image` (a route that uses dynamic imports
|
|
22
|
+
// during render) twice — the second request 500s with the stack ending in
|
|
23
|
+
// `CacheSignal.pendingTimeoutCleanup → patchedClearImmediate`.
|
|
24
|
+
//
|
|
25
|
+
// Fix: scope the signal per-request via AsyncLocalStorage so the closed-over
|
|
26
|
+
// Immediate never crosses requests. The adapter's fetch handler calls
|
|
27
|
+
// `__withModuleLoadingContext(fn)` before invoking user handlers; every call
|
|
28
|
+
// inside that scope shares one signal.
|
|
29
|
+
//
|
|
30
|
+
// Outside a scope (shouldn't happen at runtime on workerd) we fall back to a
|
|
31
|
+
// module-level instance. That preserves the original behavior for build-time
|
|
32
|
+
// callers or any surface we haven't wrapped.
|
|
33
|
+
|
|
34
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
35
|
+
import { CacheSignal } from "next/dist/server/app-render/cache-signal.js";
|
|
36
|
+
|
|
37
|
+
const als = new AsyncLocalStorage();
|
|
38
|
+
let fallbackSignal = null;
|
|
39
|
+
|
|
40
|
+
function getModuleLoadingSignal() {
|
|
41
|
+
const scoped = als.getStore();
|
|
42
|
+
if (scoped) return scoped;
|
|
43
|
+
if (!fallbackSignal) fallbackSignal = new CacheSignal();
|
|
44
|
+
return fallbackSignal;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function trackPendingChunkLoad(promise) {
|
|
48
|
+
getModuleLoadingSignal().trackRead(promise);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function trackPendingImport(exportsOrPromise) {
|
|
52
|
+
if (exportsOrPromise && typeof exportsOrPromise.then === "function") {
|
|
53
|
+
const promise = Promise.resolve(exportsOrPromise);
|
|
54
|
+
getModuleLoadingSignal().trackRead(promise);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function trackPendingModules(cacheSignal) {
|
|
59
|
+
const moduleLoadingSignal = getModuleLoadingSignal();
|
|
60
|
+
const unsubscribe = moduleLoadingSignal.subscribeToReads(cacheSignal);
|
|
61
|
+
cacheSignal.cacheReady().then(unsubscribe);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Adapter hook: run `fn` with a fresh module-loading signal scoped to the
|
|
65
|
+
// current async context. Called from worker-entry at the start of each fetch.
|
|
66
|
+
globalThis.__CREEK_WITH_MODULE_LOADING_CONTEXT = function (fn) {
|
|
67
|
+
return als.run(new CacheSignal(), fn);
|
|
68
|
+
};
|
package/src/shims/vm.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// vm shim for CF Workers.
|
|
2
|
+
// CF Workers disallows new Function() from strings (CSP).
|
|
3
|
+
// Instead of executing code, we extract data from embedded manifests.
|
|
4
|
+
|
|
5
|
+
export function runInNewContext(code, context = {}) {
|
|
6
|
+
// Next.js uses this to evaluate _buildManifest.js which sets
|
|
7
|
+
// self.__BUILD_MANIFEST = {...}. Extract the JSON from the code.
|
|
8
|
+
try {
|
|
9
|
+
// Try to extract JSON object from JS code patterns:
|
|
10
|
+
// self.__BUILD_MANIFEST = {...}
|
|
11
|
+
// self.__BUILD_MANIFEST_CB && self.__BUILD_MANIFEST_CB()
|
|
12
|
+
const jsonMatch = code.match(/=\s*(\{[\s\S]*\})\s*[;\n]/);
|
|
13
|
+
if (jsonMatch) {
|
|
14
|
+
const data = JSON.parse(jsonMatch[1]);
|
|
15
|
+
// Assign to context as self.* or globalThis.*
|
|
16
|
+
for (const [key, val] of Object.entries(data)) {
|
|
17
|
+
context[key] = val;
|
|
18
|
+
}
|
|
19
|
+
return context;
|
|
20
|
+
}
|
|
21
|
+
} catch {}
|
|
22
|
+
|
|
23
|
+
// Fallback: try to extract from embedded manifests
|
|
24
|
+
if (typeof globalThis.__MANIFESTS !== "undefined") {
|
|
25
|
+
for (const [, val] of Object.entries(globalThis.__MANIFESTS)) {
|
|
26
|
+
if (val === code) {
|
|
27
|
+
try { return JSON.parse(val); } catch {}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return context;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function runInThisContext(code) {
|
|
36
|
+
return runInNewContext(code, {});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function createContext(sandbox = {}) {
|
|
40
|
+
return sandbox;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export class Script {
|
|
44
|
+
constructor(code) { this._code = code; }
|
|
45
|
+
runInNewContext(context = {}) { return runInNewContext(this._code, context); }
|
|
46
|
+
runInThisContext() { return runInThisContext(this._code); }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export default { runInNewContext, runInThisContext, createContext, Script };
|