hyperdb-wasm 0.0.26268-dev.remotes-origin-wasm.gcf8d815a
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/api.d.ts +61 -0
- package/dist/browser.d.ts +25 -0
- package/dist/browser.js +12323 -0
- package/dist/browser_worker.d.ts +1 -0
- package/dist/browser_worker.js +271 -0
- package/dist/client.d.ts +26 -0
- package/dist/hyperdb-wasm.cjs +3 -0
- package/dist/hyperdb-wasm.js +3 -0
- package/dist/hyperdb-wasm.wasm.br +0 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.node.d.ts +7 -0
- package/dist/node.d.ts +26 -0
- package/dist/node.js +532 -0
- package/dist/node_worker.d.ts +1 -0
- package/dist/node_worker.js +277 -0
- package/dist/protocol.d.ts +84 -0
- package/dist/raw.browser.d.ts +3 -0
- package/dist/raw.browser.js +279 -0
- package/dist/raw.d.ts +3 -0
- package/dist/raw.node.d.ts +3 -0
- package/dist/raw.node.js +281 -0
- package/dist/wasm_bindings.d.ts +37 -0
- package/dist/worker_setup.d.ts +25 -0
- package/examples/browser.html +84 -0
- package/examples/node.mjs +68 -0
- package/examples/serve.mjs +35 -0
- package/package.json +41 -0
package/dist/node.js
ADDED
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __esm = (fn, res, err) => function __init() {
|
|
4
|
+
if (err) throw err[0];
|
|
5
|
+
try {
|
|
6
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
7
|
+
} catch (e) {
|
|
8
|
+
throw err = [e], e;
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
var __export = (target, all) => {
|
|
12
|
+
for (var name in all)
|
|
13
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// protocol.ts
|
|
17
|
+
function isRecord(value) {
|
|
18
|
+
return typeof value === "object" && value !== null;
|
|
19
|
+
}
|
|
20
|
+
function hasKeys(value, keys) {
|
|
21
|
+
const actual = Object.keys(value).sort();
|
|
22
|
+
const expected = [...keys].sort();
|
|
23
|
+
return actual.length === expected.length && actual.every((key, index) => key === expected[index]);
|
|
24
|
+
}
|
|
25
|
+
function isWasmResult(value) {
|
|
26
|
+
if (!isRecord(value) || typeof value.state !== "string") return false;
|
|
27
|
+
switch (value.state) {
|
|
28
|
+
case "ok":
|
|
29
|
+
case "chunk":
|
|
30
|
+
return hasKeys(value, ["state", "payload"]) && value.payload instanceof Uint8Array;
|
|
31
|
+
case "pending":
|
|
32
|
+
case "done":
|
|
33
|
+
return hasKeys(value, ["state"]);
|
|
34
|
+
case "error":
|
|
35
|
+
case "busy":
|
|
36
|
+
return hasKeys(value, ["state", "error"]) && typeof value.error === "string";
|
|
37
|
+
default:
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function isWorkerEvent(message) {
|
|
42
|
+
if (!isRecord(message) || typeof message.type !== "string") return false;
|
|
43
|
+
switch (message.type) {
|
|
44
|
+
case "ready":
|
|
45
|
+
return hasKeys(message, ["type"]);
|
|
46
|
+
case "fatal":
|
|
47
|
+
return hasKeys(message, ["type", "error"]) && typeof message.error === "string";
|
|
48
|
+
case "log":
|
|
49
|
+
return hasKeys(message, ["type", "text"]) && typeof message.text === "string";
|
|
50
|
+
case "response":
|
|
51
|
+
return hasKeys(message, ["id", "type", "result"]) && Number.isSafeInteger(message.id) && isWasmResult(message.result);
|
|
52
|
+
default:
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
var init_protocol = __esm({
|
|
57
|
+
"protocol.ts"() {
|
|
58
|
+
"use strict";
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// client.ts
|
|
63
|
+
var HyperDBEngineClient;
|
|
64
|
+
var init_client = __esm({
|
|
65
|
+
"client.ts"() {
|
|
66
|
+
"use strict";
|
|
67
|
+
init_protocol();
|
|
68
|
+
HyperDBEngineClient = class {
|
|
69
|
+
transport;
|
|
70
|
+
pending = /* @__PURE__ */ new Map();
|
|
71
|
+
readyPromise;
|
|
72
|
+
resolveReady;
|
|
73
|
+
rejectReady;
|
|
74
|
+
nextId = 1;
|
|
75
|
+
failed;
|
|
76
|
+
unsubscribe;
|
|
77
|
+
constructor(transport) {
|
|
78
|
+
this.transport = transport;
|
|
79
|
+
this.readyPromise = new Promise((resolve, reject) => {
|
|
80
|
+
this.resolveReady = resolve;
|
|
81
|
+
this.rejectReady = reject;
|
|
82
|
+
});
|
|
83
|
+
this.unsubscribe = [
|
|
84
|
+
transport.onMessage((message) => this.onMessage(message)),
|
|
85
|
+
transport.onError((error) => this.fail(error)),
|
|
86
|
+
transport.onClose((error) => this.fail(error))
|
|
87
|
+
];
|
|
88
|
+
}
|
|
89
|
+
ready() {
|
|
90
|
+
return this.readyPromise;
|
|
91
|
+
}
|
|
92
|
+
connect() {
|
|
93
|
+
return this.request({ id: this.nextId++, type: "connect" });
|
|
94
|
+
}
|
|
95
|
+
disconnect(connection) {
|
|
96
|
+
return this.request({ id: this.nextId++, type: "disconnect", connection });
|
|
97
|
+
}
|
|
98
|
+
startQuery(connection, sql) {
|
|
99
|
+
return this.request({ id: this.nextId++, type: "startQuery", connection, sql });
|
|
100
|
+
}
|
|
101
|
+
insertArrowIPCFromPath(connection, path, name, schema, create, internal = false) {
|
|
102
|
+
return this.request({ id: this.nextId++, type: "insertArrowIPCFromPath", connection, path, name, schema, create, internal });
|
|
103
|
+
}
|
|
104
|
+
createTemporaryFile(bytes) {
|
|
105
|
+
const payload = bytes.slice();
|
|
106
|
+
return this.request({ id: this.nextId++, type: "createTemporaryFile", bytes: payload }, [payload.buffer]);
|
|
107
|
+
}
|
|
108
|
+
removeFile(path) {
|
|
109
|
+
return this.request({ id: this.nextId++, type: "removeFile", path });
|
|
110
|
+
}
|
|
111
|
+
pollQuery(query) {
|
|
112
|
+
return this.request({ id: this.nextId++, type: "pollQuery", query });
|
|
113
|
+
}
|
|
114
|
+
cancelQuery(query) {
|
|
115
|
+
return this.request({ id: this.nextId++, type: "cancelQuery", query });
|
|
116
|
+
}
|
|
117
|
+
releaseQuery(query) {
|
|
118
|
+
return this.request({ id: this.nextId++, type: "releaseQuery", query });
|
|
119
|
+
}
|
|
120
|
+
async terminate() {
|
|
121
|
+
this.fail(new Error("engine worker terminated"));
|
|
122
|
+
await this.transport.terminate();
|
|
123
|
+
}
|
|
124
|
+
request(request, transfer = []) {
|
|
125
|
+
if (this.failed) return Promise.reject(this.failed);
|
|
126
|
+
return new Promise((resolve, reject) => {
|
|
127
|
+
this.pending.set(request.id, { resolve, reject });
|
|
128
|
+
try {
|
|
129
|
+
this.transport.postMessage(request, transfer);
|
|
130
|
+
} catch (error) {
|
|
131
|
+
this.pending.delete(request.id);
|
|
132
|
+
reject(error instanceof Error ? error : new Error(String(error)));
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
onMessage(message) {
|
|
137
|
+
if (!isWorkerEvent(message)) return;
|
|
138
|
+
if (message.type === "ready") {
|
|
139
|
+
this.resolveReady();
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
if (message.type === "fatal") {
|
|
143
|
+
this.fail(new Error(message.error || "engine aborted"));
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (message.type !== "response") return;
|
|
147
|
+
const pending = this.pending.get(message.id);
|
|
148
|
+
if (!pending) return;
|
|
149
|
+
this.pending.delete(message.id);
|
|
150
|
+
pending.resolve(message.result);
|
|
151
|
+
}
|
|
152
|
+
fail(error) {
|
|
153
|
+
if (this.failed) return;
|
|
154
|
+
this.failed = error;
|
|
155
|
+
for (const unsubscribe of this.unsubscribe.splice(0)) unsubscribe();
|
|
156
|
+
this.rejectReady(error);
|
|
157
|
+
for (const pending of this.pending.values()) pending.reject(error);
|
|
158
|
+
this.pending.clear();
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// browser.ts
|
|
165
|
+
var browser_exports = {};
|
|
166
|
+
__export(browser_exports, {
|
|
167
|
+
BrowserWorker: () => BrowserWorker,
|
|
168
|
+
createBrowserClient: () => createBrowserClient,
|
|
169
|
+
resolveBrowserWorkerUrl: () => resolveBrowserWorkerUrl
|
|
170
|
+
});
|
|
171
|
+
function resolveBrowserWorkerUrl(workerUrl, engineUrl) {
|
|
172
|
+
const resolved = new URL(workerUrl);
|
|
173
|
+
resolved.searchParams.set("engineUrl", new URL(engineUrl).href);
|
|
174
|
+
return resolved;
|
|
175
|
+
}
|
|
176
|
+
function createBrowserClient(options = {}) {
|
|
177
|
+
const workerUrl = options.workerUrl ?? new URL("./browser_worker.js", import.meta.url);
|
|
178
|
+
const engineUrl = options.engineUrl ?? new URL("./hyperdb-wasm.js", import.meta.url);
|
|
179
|
+
return new HyperDBEngineClient(new BrowserWorker(new Worker(resolveBrowserWorkerUrl(workerUrl, engineUrl), { type: "classic" })));
|
|
180
|
+
}
|
|
181
|
+
var BrowserWorker;
|
|
182
|
+
var init_browser = __esm({
|
|
183
|
+
"browser.ts"() {
|
|
184
|
+
"use strict";
|
|
185
|
+
init_client();
|
|
186
|
+
BrowserWorker = class {
|
|
187
|
+
constructor(worker) {
|
|
188
|
+
this.worker = worker;
|
|
189
|
+
}
|
|
190
|
+
worker;
|
|
191
|
+
postMessage(message, transfer = []) {
|
|
192
|
+
this.worker.postMessage(message, [...transfer]);
|
|
193
|
+
}
|
|
194
|
+
onMessage(listener) {
|
|
195
|
+
const wrapped = (event) => listener(event.data);
|
|
196
|
+
this.worker.addEventListener("message", wrapped);
|
|
197
|
+
return () => this.worker.removeEventListener("message", wrapped);
|
|
198
|
+
}
|
|
199
|
+
onError(listener) {
|
|
200
|
+
const wrapped = (event) => listener(new Error(event.message || "engine worker error"));
|
|
201
|
+
this.worker.addEventListener("error", wrapped);
|
|
202
|
+
return () => this.worker.removeEventListener("error", wrapped);
|
|
203
|
+
}
|
|
204
|
+
onClose() {
|
|
205
|
+
return () => void 0;
|
|
206
|
+
}
|
|
207
|
+
terminate() {
|
|
208
|
+
this.worker.terminate();
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// api.ts
|
|
215
|
+
import { DataType, RecordBatchReader, Schema, Table, tableToIPC, vectorFromArray } from "apache-arrow";
|
|
216
|
+
function normalizeArrowInsertOptions(options) {
|
|
217
|
+
if (!options.name) throw new Error("Arrow insert table name must not be empty");
|
|
218
|
+
return { name: options.name, schema: options.schema ?? null, create: options.create ?? true };
|
|
219
|
+
}
|
|
220
|
+
function materializeDictionaryColumns(table) {
|
|
221
|
+
const dictionaryColumns = table.schema.fields.map((field, index) => DataType.isDictionary(field.type) ? index : -1).filter((index) => index !== -1);
|
|
222
|
+
if (dictionaryColumns.length === 0) return table;
|
|
223
|
+
const fields = table.schema.fields.map((field) => DataType.isDictionary(field.type) ? field.clone({ type: field.type.dictionary }) : field);
|
|
224
|
+
const batches = table.batches.map((batch) => {
|
|
225
|
+
let result = batch;
|
|
226
|
+
for (const index of dictionaryColumns) {
|
|
227
|
+
const column = result.getChildAt(index);
|
|
228
|
+
const sourceField = table.schema.fields[index];
|
|
229
|
+
if (!column || !sourceField) throw new Error(`Arrow table is missing column ${index}`);
|
|
230
|
+
const type = sourceField.type;
|
|
231
|
+
const materialized = vectorFromArray([...column], type.dictionary);
|
|
232
|
+
result = result.setChildAt(index, materialized);
|
|
233
|
+
}
|
|
234
|
+
return result;
|
|
235
|
+
});
|
|
236
|
+
return new Table(new Schema(fields, table.schema.metadata, null, table.schema.metadataVersion), batches);
|
|
237
|
+
}
|
|
238
|
+
function readHandleFromResult(result, operation) {
|
|
239
|
+
if (result.state !== "ok") throw readErrorFromResult(result, operation);
|
|
240
|
+
if (result.payload.byteLength !== 4) throw new Error(`${operation} returned an invalid handle`);
|
|
241
|
+
return new DataView(result.payload.buffer, result.payload.byteOffset, result.payload.byteLength).getUint32(0, true);
|
|
242
|
+
}
|
|
243
|
+
function readErrorFromResult(result, operation) {
|
|
244
|
+
if (result.state === "error" || result.state === "busy") return new Error(result.error);
|
|
245
|
+
return new Error(`${operation} returned unexpected state ${result.state}`);
|
|
246
|
+
}
|
|
247
|
+
function expectOk(result, operation) {
|
|
248
|
+
if (result.state !== "ok") throw readErrorFromResult(result, operation);
|
|
249
|
+
}
|
|
250
|
+
function yieldToEventLoop() {
|
|
251
|
+
return new Promise((resolve) => setTimeout(resolve, 0));
|
|
252
|
+
}
|
|
253
|
+
var HyperDB = class _HyperDB {
|
|
254
|
+
constructor(client) {
|
|
255
|
+
this.client = client;
|
|
256
|
+
}
|
|
257
|
+
client;
|
|
258
|
+
terminated = false;
|
|
259
|
+
termination;
|
|
260
|
+
connections = /* @__PURE__ */ new Set();
|
|
261
|
+
static async create(options = {}) {
|
|
262
|
+
const { createBrowserClient: createBrowserClient2 } = await Promise.resolve().then(() => (init_browser(), browser_exports));
|
|
263
|
+
const database = new _HyperDB(createBrowserClient2(options));
|
|
264
|
+
await database.ready();
|
|
265
|
+
return database;
|
|
266
|
+
}
|
|
267
|
+
ready() {
|
|
268
|
+
this.ensureRunning();
|
|
269
|
+
return this.client.ready();
|
|
270
|
+
}
|
|
271
|
+
async connect() {
|
|
272
|
+
this.ensureRunning();
|
|
273
|
+
const connection = readHandleFromResult(await this.client.connect(), "connect");
|
|
274
|
+
const result = new HyperDBConnection(this.client, connection, () => this.connections.delete(result));
|
|
275
|
+
this.connections.add(result);
|
|
276
|
+
return result;
|
|
277
|
+
}
|
|
278
|
+
async terminate() {
|
|
279
|
+
if (this.terminated) return;
|
|
280
|
+
if (!this.termination) {
|
|
281
|
+
this.termination = (async () => {
|
|
282
|
+
try {
|
|
283
|
+
await Promise.all([...this.connections].map(async (connection) => connection.closeForTermination()));
|
|
284
|
+
} catch (error) {
|
|
285
|
+
this.termination = void 0;
|
|
286
|
+
throw error;
|
|
287
|
+
}
|
|
288
|
+
this.terminated = true;
|
|
289
|
+
await this.client.terminate();
|
|
290
|
+
})();
|
|
291
|
+
}
|
|
292
|
+
await this.termination;
|
|
293
|
+
}
|
|
294
|
+
ensureRunning() {
|
|
295
|
+
if (this.terminated) throw new Error("database is terminated");
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
var HyperDBConnection = class {
|
|
299
|
+
constructor(client, connection, onClose = () => void 0) {
|
|
300
|
+
this.client = client;
|
|
301
|
+
this.connection = connection;
|
|
302
|
+
this.onClose = onClose;
|
|
303
|
+
}
|
|
304
|
+
client;
|
|
305
|
+
connection;
|
|
306
|
+
onClose;
|
|
307
|
+
closed = false;
|
|
308
|
+
active = false;
|
|
309
|
+
closing;
|
|
310
|
+
async close() {
|
|
311
|
+
if (this.closed) return;
|
|
312
|
+
if (this.active) throw new Error("connection has an active query");
|
|
313
|
+
if (!this.closing) {
|
|
314
|
+
this.closing = (async () => {
|
|
315
|
+
try {
|
|
316
|
+
expectOk(await this.client.disconnect(this.connection), "disconnect");
|
|
317
|
+
} catch (error) {
|
|
318
|
+
this.closing = void 0;
|
|
319
|
+
throw error;
|
|
320
|
+
}
|
|
321
|
+
this.closed = true;
|
|
322
|
+
this.onClose();
|
|
323
|
+
})();
|
|
324
|
+
}
|
|
325
|
+
await this.closing;
|
|
326
|
+
}
|
|
327
|
+
sendIPC(sql) {
|
|
328
|
+
const connection = this;
|
|
329
|
+
return {
|
|
330
|
+
async *[Symbol.asyncIterator]() {
|
|
331
|
+
connection.ensureAvailable();
|
|
332
|
+
let query;
|
|
333
|
+
let terminal = false;
|
|
334
|
+
let prefetched;
|
|
335
|
+
try {
|
|
336
|
+
query = readHandleFromResult(await connection.client.startQuery(connection.connection, sql), "start query");
|
|
337
|
+
for (; ; ) {
|
|
338
|
+
let result = prefetched ? await prefetched : await connection.client.pollQuery(query);
|
|
339
|
+
prefetched = void 0;
|
|
340
|
+
while (result.state === "pending") {
|
|
341
|
+
await yieldToEventLoop();
|
|
342
|
+
result = await connection.client.pollQuery(query);
|
|
343
|
+
}
|
|
344
|
+
if (result.state === "chunk") {
|
|
345
|
+
prefetched = connection.client.pollQuery(query);
|
|
346
|
+
void prefetched.catch(() => void 0);
|
|
347
|
+
yield result.payload;
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
terminal = true;
|
|
351
|
+
if (result.state === "done") return;
|
|
352
|
+
throw readErrorFromResult(result, "poll query");
|
|
353
|
+
}
|
|
354
|
+
} finally {
|
|
355
|
+
try {
|
|
356
|
+
if (query !== void 0) {
|
|
357
|
+
let cleanupError;
|
|
358
|
+
if (prefetched) {
|
|
359
|
+
try {
|
|
360
|
+
await prefetched;
|
|
361
|
+
} catch (error) {
|
|
362
|
+
cleanupError = error;
|
|
363
|
+
}
|
|
364
|
+
prefetched = void 0;
|
|
365
|
+
}
|
|
366
|
+
if (!terminal) {
|
|
367
|
+
try {
|
|
368
|
+
expectOk(await connection.client.cancelQuery(query), "cancel query");
|
|
369
|
+
} catch (error) {
|
|
370
|
+
cleanupError ??= error;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
try {
|
|
374
|
+
await connection.release(query);
|
|
375
|
+
} catch (error) {
|
|
376
|
+
cleanupError ??= error;
|
|
377
|
+
}
|
|
378
|
+
if (cleanupError) throw cleanupError;
|
|
379
|
+
}
|
|
380
|
+
} finally {
|
|
381
|
+
connection.active = false;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
async queryIPC(sql) {
|
|
388
|
+
const chunks = [];
|
|
389
|
+
let length = 0;
|
|
390
|
+
for await (const chunk of this.sendIPC(sql)) {
|
|
391
|
+
chunks.push(chunk);
|
|
392
|
+
length += chunk.byteLength;
|
|
393
|
+
}
|
|
394
|
+
const result = new Uint8Array(length);
|
|
395
|
+
let offset = 0;
|
|
396
|
+
for (const chunk of chunks) {
|
|
397
|
+
result.set(chunk, offset);
|
|
398
|
+
offset += chunk.byteLength;
|
|
399
|
+
}
|
|
400
|
+
return result;
|
|
401
|
+
}
|
|
402
|
+
async send(sql) {
|
|
403
|
+
const reader = await RecordBatchReader.from(this.sendIPC(sql));
|
|
404
|
+
if (!reader.isAsync() || !reader.isStream()) throw new Error("query did not produce an Arrow async stream");
|
|
405
|
+
return reader;
|
|
406
|
+
}
|
|
407
|
+
async query(sql) {
|
|
408
|
+
const reader = await this.send(sql);
|
|
409
|
+
const batches = [];
|
|
410
|
+
for await (const batch of reader) batches.push(batch);
|
|
411
|
+
return new Table(reader.schema, batches);
|
|
412
|
+
}
|
|
413
|
+
async insertArrowTable(table, options) {
|
|
414
|
+
this.ensureAvailable();
|
|
415
|
+
let path;
|
|
416
|
+
try {
|
|
417
|
+
const result = await this.client.createTemporaryFile(tableToIPC(materializeDictionaryColumns(table), "stream"));
|
|
418
|
+
expectOk(result, "create temporary Arrow IPC file");
|
|
419
|
+
path = new TextDecoder().decode(result.payload);
|
|
420
|
+
await this.insertArrowIPCFromPathInternal(path, options, true, false);
|
|
421
|
+
} finally {
|
|
422
|
+
try {
|
|
423
|
+
if (path !== void 0) expectOk(await this.client.removeFile(path), "remove temporary Arrow IPC file");
|
|
424
|
+
} finally {
|
|
425
|
+
this.active = false;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
async insertArrowIPCFromPath(path, options) {
|
|
430
|
+
await this.insertArrowIPCFromPathInternal(path, options, false);
|
|
431
|
+
}
|
|
432
|
+
async insertArrowIPCFromPathInternal(path, options, internal, acquire = true) {
|
|
433
|
+
if (!path) throw new Error("Arrow IPC input path must not be empty");
|
|
434
|
+
const normalized = normalizeArrowInsertOptions(options);
|
|
435
|
+
if (acquire) this.ensureAvailable();
|
|
436
|
+
let query;
|
|
437
|
+
try {
|
|
438
|
+
query = readHandleFromResult(await this.client.insertArrowIPCFromPath(this.connection, path, normalized.name, normalized.schema, normalized.create, internal), "insert Arrow IPC from path");
|
|
439
|
+
for (; ; ) {
|
|
440
|
+
let result = await this.client.pollQuery(query);
|
|
441
|
+
while (result.state === "pending") {
|
|
442
|
+
await yieldToEventLoop();
|
|
443
|
+
result = await this.client.pollQuery(query);
|
|
444
|
+
}
|
|
445
|
+
if (result.state === "done") return;
|
|
446
|
+
if (result.state === "chunk") continue;
|
|
447
|
+
throw readErrorFromResult(result, "insert Arrow IPC from path");
|
|
448
|
+
}
|
|
449
|
+
} finally {
|
|
450
|
+
try {
|
|
451
|
+
if (query !== void 0) await this.release(query);
|
|
452
|
+
} finally {
|
|
453
|
+
if (acquire) this.active = false;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
ensureAvailable() {
|
|
458
|
+
if (this.closed) throw new Error("connection is closed");
|
|
459
|
+
if (this.closing) throw new Error("connection is closing");
|
|
460
|
+
if (this.active) {
|
|
461
|
+
throw new Error("connection has an active query");
|
|
462
|
+
}
|
|
463
|
+
this.active = true;
|
|
464
|
+
}
|
|
465
|
+
async release(query) {
|
|
466
|
+
let delay = 1;
|
|
467
|
+
for (; ; ) {
|
|
468
|
+
const result = await this.client.releaseQuery(query);
|
|
469
|
+
if (result.state === "ok") return;
|
|
470
|
+
if (result.state !== "pending") throw readErrorFromResult(result, "release query");
|
|
471
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
472
|
+
delay = Math.min(delay * 2, 32);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
async closeForTermination() {
|
|
476
|
+
if (this.active) throw new Error("cannot terminate while a connection has an active query");
|
|
477
|
+
await this.close();
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
// node.ts
|
|
482
|
+
init_client();
|
|
483
|
+
import { Worker as NativeWorker } from "node:worker_threads";
|
|
484
|
+
import { fileURLToPath } from "node:url";
|
|
485
|
+
var NodeWorker = class {
|
|
486
|
+
constructor(worker) {
|
|
487
|
+
this.worker = worker;
|
|
488
|
+
}
|
|
489
|
+
worker;
|
|
490
|
+
postMessage(message, transfer = []) {
|
|
491
|
+
this.worker.postMessage(message, transfer);
|
|
492
|
+
}
|
|
493
|
+
onMessage(listener) {
|
|
494
|
+
const wrapped = (message) => listener(message);
|
|
495
|
+
this.worker.on("message", wrapped);
|
|
496
|
+
return () => this.worker.off("message", wrapped);
|
|
497
|
+
}
|
|
498
|
+
onError(listener) {
|
|
499
|
+
const wrapped = (error) => listener(error instanceof Error ? error : new Error(String(error)));
|
|
500
|
+
this.worker.on("error", wrapped);
|
|
501
|
+
return () => this.worker.off("error", wrapped);
|
|
502
|
+
}
|
|
503
|
+
onClose(listener) {
|
|
504
|
+
const wrapped = (code) => listener(new Error(`engine worker exited with code ${String(code)}`));
|
|
505
|
+
this.worker.on("exit", wrapped);
|
|
506
|
+
return () => this.worker.off("exit", wrapped);
|
|
507
|
+
}
|
|
508
|
+
terminate() {
|
|
509
|
+
return this.worker.terminate();
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
function resolveNodeEnginePath(engineUrl) {
|
|
513
|
+
return fileURLToPath(engineUrl);
|
|
514
|
+
}
|
|
515
|
+
function createNodeClient(options = {}) {
|
|
516
|
+
const workerUrl = options.workerUrl ?? new URL("./node_worker.js", import.meta.url);
|
|
517
|
+
const engineUrl = options.engineUrl ?? resolveNodeEnginePath(new URL("./hyperdb-wasm.cjs", import.meta.url));
|
|
518
|
+
return new HyperDBEngineClient(new NodeWorker(new NativeWorker(workerUrl, { workerData: { engineUrl, hostPath: options.hostPath } })));
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// index.node.ts
|
|
522
|
+
var HyperDB2 = class _HyperDB extends HyperDB {
|
|
523
|
+
static async create(options = {}) {
|
|
524
|
+
const database = new _HyperDB(createNodeClient(options));
|
|
525
|
+
await database.ready();
|
|
526
|
+
return database;
|
|
527
|
+
}
|
|
528
|
+
};
|
|
529
|
+
export {
|
|
530
|
+
HyperDB2 as HyperDB,
|
|
531
|
+
HyperDBConnection
|
|
532
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|