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.
@@ -0,0 +1,277 @@
1
+ // node_worker.ts
2
+ import { createReadStream } from "node:fs";
3
+ import { createRequire } from "node:module";
4
+ import { dirname, isAbsolute, join, posix, relative, resolve, sep } from "node:path";
5
+ import { Readable } from "node:stream";
6
+ import { parentPort, workerData } from "node:worker_threads";
7
+ import { fileURLToPath } from "node:url";
8
+ import { createBrotliDecompress } from "node:zlib";
9
+
10
+ // wasm_bindings.ts
11
+ var resultStates = ["ok", "pending", "chunk", "done", "error", "busy"];
12
+ function safeInteger(value, name) {
13
+ const number = typeof value === "bigint" && value <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(value) : value;
14
+ if (typeof number !== "number" || !Number.isSafeInteger(number) || number < 0) throw new Error(`${name} must be a nonnegative safe integer`);
15
+ return number;
16
+ }
17
+ var HyperDBBindings = class {
18
+ module;
19
+ connect;
20
+ disconnect;
21
+ startQuery;
22
+ insertArrowIPCFromPath;
23
+ pollQuery;
24
+ cancelQuery;
25
+ releaseQuery;
26
+ resultState;
27
+ resultPayloadLength;
28
+ free;
29
+ nextTemporaryFile = 1;
30
+ constructor(module2) {
31
+ this.module = module2;
32
+ this.connect = module2.cwrap("hyperdb_wasm_connect", "pointer", []);
33
+ this.disconnect = module2.cwrap("hyperdb_wasm_disconnect", "pointer", ["number"]);
34
+ this.startQuery = module2.cwrap("hyperdb_wasm_query_start", "pointer", ["number", "string"]);
35
+ this.insertArrowIPCFromPath = module2.cwrap("hyperdb_wasm_arrow_insert_from_path", "pointer", ["number", "string", "string", "string", "number"]);
36
+ this.pollQuery = module2.cwrap("hyperdb_wasm_query_poll", "pointer", ["number"]);
37
+ this.cancelQuery = module2.cwrap("hyperdb_wasm_query_cancel", "pointer", ["number"]);
38
+ this.releaseQuery = module2.cwrap("hyperdb_wasm_query_release", "pointer", ["number"]);
39
+ this.resultState = module2.cwrap("hyperdb_wasm_result_state", "number", ["number"]);
40
+ this.resultPayloadLength = module2.cwrap("hyperdb_wasm_result_payload_len", "number", ["number"]);
41
+ this.free = module2.cwrap("hyperdb_wasm_free", null, ["pointer"]);
42
+ }
43
+ handle(request) {
44
+ if (request.type === "createTemporaryFile") {
45
+ const path = `/tmp/hyperdb/arrow-${this.nextTemporaryFile++}.arrows`;
46
+ this.module.FS.mkdirTree("/tmp/hyperdb");
47
+ this.module.FS.writeFile(path, request.bytes);
48
+ return { response: { id: request.id, type: "response", result: { state: "ok", payload: new TextEncoder().encode(path) } }, transfer: [] };
49
+ }
50
+ if (request.type === "removeFile") {
51
+ this.module.FS.unlink(request.path);
52
+ return { response: { id: request.id, type: "response", result: { state: "ok", payload: new Uint8Array() } }, transfer: [] };
53
+ }
54
+ const pointer = safeInteger(this.invoke(request), "result pointer");
55
+ const result = this.decodeResult(pointer);
56
+ const response = { id: request.id, type: "response", result };
57
+ return { response, transfer: result.state === "chunk" ? [result.payload.buffer] : [] };
58
+ }
59
+ invoke(request) {
60
+ switch (request.type) {
61
+ case "connect":
62
+ return this.connect();
63
+ case "disconnect":
64
+ return this.disconnect(request.connection);
65
+ case "startQuery":
66
+ return this.startQuery(request.connection, request.sql);
67
+ case "insertArrowIPCFromPath": {
68
+ const path = request.internal ? request.path : this.module.resolveHyperDBPath?.(request.path) ?? request.path;
69
+ return this.insertArrowIPCFromPath(request.connection, path, request.name, request.schema ?? "", Number(request.create));
70
+ }
71
+ case "pollQuery":
72
+ return this.pollQuery(request.query);
73
+ case "cancelQuery":
74
+ return this.cancelQuery(request.query);
75
+ case "releaseQuery":
76
+ return this.releaseQuery(request.query);
77
+ }
78
+ }
79
+ decodeResult(pointer) {
80
+ if (pointer === 0) return { state: "error", error: "out of memory" };
81
+ try {
82
+ const rawState = safeInteger(this.resultState(pointer), "result state");
83
+ const state = resultStates[rawState];
84
+ if (!state) return { state: "error", error: `invalid result state ${rawState}` };
85
+ const payloadLength = safeInteger(this.resultPayloadLength(pointer), "result payload length");
86
+ const payloadStart = safeInteger(pointer + 8, "result payload start");
87
+ const payloadEnd = safeInteger(payloadStart + payloadLength, "result payload end");
88
+ if (payloadEnd > this.module.HEAPU8.byteLength) throw new Error("result payload exceeds the wasm heap");
89
+ const payload = new Uint8Array(payloadLength);
90
+ payload.set(this.module.HEAPU8.subarray(payloadStart, payloadEnd));
91
+ switch (state) {
92
+ case "ok":
93
+ return { state, payload };
94
+ case "pending":
95
+ return { state };
96
+ case "chunk":
97
+ return { state, payload };
98
+ case "done":
99
+ return { state };
100
+ case "error":
101
+ return { state, error: new TextDecoder().decode(payload) };
102
+ case "busy":
103
+ return { state, error: new TextDecoder().decode(payload) };
104
+ }
105
+ } finally {
106
+ this.free(pointer);
107
+ }
108
+ }
109
+ };
110
+
111
+ // protocol.ts
112
+ function isRecord(value) {
113
+ return typeof value === "object" && value !== null;
114
+ }
115
+ function hasKeys(value, keys) {
116
+ const actual = Object.keys(value).sort();
117
+ const expected = [...keys].sort();
118
+ return actual.length === expected.length && actual.every((key, index) => key === expected[index]);
119
+ }
120
+ function isEngineRequest(value) {
121
+ if (!isRecord(value) || !Number.isSafeInteger(value.id) || typeof value.type !== "string") return false;
122
+ switch (value.type) {
123
+ case "connect":
124
+ return hasKeys(value, ["id", "type"]);
125
+ case "disconnect":
126
+ return hasKeys(value, ["id", "type", "connection"]) && Number.isSafeInteger(value.connection);
127
+ case "startQuery":
128
+ return hasKeys(value, ["id", "type", "connection", "sql"]) && Number.isSafeInteger(value.connection) && typeof value.sql === "string";
129
+ case "insertArrowIPCFromPath":
130
+ return hasKeys(value, ["id", "type", "connection", "path", "name", "schema", "create", "internal"]) && Number.isSafeInteger(value.connection) && typeof value.path === "string" && typeof value.name === "string" && (typeof value.schema === "string" || value.schema === null) && typeof value.create === "boolean" && typeof value.internal === "boolean";
131
+ case "createTemporaryFile":
132
+ return hasKeys(value, ["id", "type", "bytes"]) && value.bytes instanceof Uint8Array;
133
+ case "removeFile":
134
+ return hasKeys(value, ["id", "type", "path"]) && typeof value.path === "string";
135
+ case "pollQuery":
136
+ case "cancelQuery":
137
+ case "releaseQuery":
138
+ return hasKeys(value, ["id", "type", "query"]) && Number.isSafeInteger(value.query);
139
+ default:
140
+ return false;
141
+ }
142
+ }
143
+
144
+ // worker_setup.ts
145
+ function errorText(error) {
146
+ return error instanceof Error ? error.message : String(error);
147
+ }
148
+ function safePointer(value, name) {
149
+ const pointer = typeof value === "bigint" && value <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(value) : value;
150
+ if (typeof pointer !== "number" || !Number.isSafeInteger(pointer) || pointer < 0) throw new Error(`${name} must be a nonnegative safe integer`);
151
+ return pointer;
152
+ }
153
+ function allocate(module2, bytes) {
154
+ const pointer = safePointer(module2._malloc(bytes.byteLength || 1), "allocation pointer");
155
+ if (pointer === 0) throw new Error("wasm allocation failed");
156
+ if (pointer + bytes.byteLength > module2.HEAPU8.byteLength) throw new Error("allocation exceeds the wasm heap");
157
+ module2.HEAPU8.set(bytes, pointer);
158
+ return pointer;
159
+ }
160
+ function installHttpRuntime(module2, transport2) {
161
+ module2.hyperdbWasmFetchStart = (id, url, offset, length) => {
162
+ const headers = new Headers();
163
+ if (length > 0) headers.set("Range", `bytes=${offset}-${offset + length - 1}`);
164
+ void fetch(url, { headers }).then(async (response) => {
165
+ if (!response.ok && response.status !== 206) {
166
+ module2._hyperdb_wasm_fetch_complete(id, 0, -1);
167
+ return;
168
+ }
169
+ const bytes = new Uint8Array(await response.arrayBuffer());
170
+ module2._hyperdb_wasm_fetch_complete(id, allocate(module2, bytes), bytes.byteLength);
171
+ }).catch((error) => {
172
+ transport2.postMessage({ type: "log", text: `fetch failed: ${errorText(error)}` });
173
+ module2._hyperdb_wasm_fetch_complete(id, 0, -1);
174
+ });
175
+ };
176
+ module2.hyperdbWasmHttpStart = (id, method, url, headerLines, bodyPointer, bodyLength) => {
177
+ const headers = new Headers();
178
+ for (const line of headerLines.split("\n")) {
179
+ const separator = line.indexOf(":");
180
+ if (separator > 0) headers.set(line.slice(0, separator), line.slice(separator + 1));
181
+ }
182
+ const pointer = safePointer(bodyPointer, "HTTP body pointer");
183
+ const bodyEnd = safePointer(pointer + bodyLength, "HTTP body end");
184
+ if (bodyEnd > module2.HEAPU8.byteLength) throw new Error("HTTP body exceeds the wasm heap");
185
+ const body = bodyLength > 0 ? module2.HEAPU8.slice(pointer, bodyEnd) : void 0;
186
+ const init = { method, headers };
187
+ if (body) init.body = body;
188
+ void fetch(url, init).then(async (response) => {
189
+ const responseBody = new Uint8Array(await response.arrayBuffer());
190
+ let responseHeaders = "";
191
+ response.headers.forEach((value, name) => {
192
+ responseHeaders += `${name.toLowerCase()}:${value}
193
+ `;
194
+ });
195
+ const headersPointer = responseHeaders ? safePointer(module2.stringToNewUTF8(responseHeaders), "headers pointer") : 0;
196
+ const responseBodyPointer = responseBody.byteLength ? allocate(module2, responseBody) : 0;
197
+ module2._hyperdb_wasm_http_complete(id, response.status, headersPointer, responseBodyPointer, responseBody.byteLength);
198
+ }).catch((error) => {
199
+ const errorBytes = new TextEncoder().encode(errorText(error));
200
+ module2._hyperdb_wasm_http_complete(id, -1, 0, allocate(module2, errorBytes), errorBytes.byteLength);
201
+ });
202
+ };
203
+ }
204
+ function configureWorker(module2, transport2, configureFilesystem = () => void 0) {
205
+ const queuedRequests = [];
206
+ let bindings;
207
+ const handle = (request) => {
208
+ if (!bindings) {
209
+ queuedRequests.push(request);
210
+ return;
211
+ }
212
+ try {
213
+ const result = bindings.handle(request);
214
+ transport2.postMessage(result.response, result.transfer);
215
+ } catch (error) {
216
+ transport2.postMessage({ id: request.id, type: "response", result: { state: "error", error: errorText(error) } });
217
+ }
218
+ };
219
+ transport2.onMessage((message) => {
220
+ if (isEngineRequest(message)) handle(message);
221
+ });
222
+ module2.arguments = ["--no-demo"];
223
+ module2.print = (text) => transport2.postMessage({ type: "log", text });
224
+ module2.printErr = (text) => transport2.postMessage({ type: "log", text });
225
+ module2.onRuntimeInitialized = () => {
226
+ try {
227
+ configureFilesystem(module2);
228
+ installHttpRuntime(module2, transport2);
229
+ bindings = new HyperDBBindings(module2);
230
+ transport2.postMessage({ type: "ready" });
231
+ for (const request of queuedRequests.splice(0)) handle(request);
232
+ } catch (error) {
233
+ transport2.postMessage({ type: "fatal", error: `engine initialization failed: ${errorText(error)}` });
234
+ }
235
+ };
236
+ module2.onAbort = (reason) => transport2.postMessage({ type: "fatal", error: `engine aborted: ${String(reason)}` });
237
+ }
238
+
239
+ // node_worker.ts
240
+ if (!parentPort) throw new Error("Node engine worker requires a parent port");
241
+ var enginePort = parentPort;
242
+ var options = workerData;
243
+ var engineUrl = options?.engineUrl ?? fileURLToPath(new URL("./hyperdb-wasm.cjs", import.meta.url));
244
+ var hostPath = resolve(options?.hostPath ?? process.cwd());
245
+ var transport = {
246
+ postMessage: (message, transfer = []) => enginePort.postMessage(message, [...transfer]),
247
+ onMessage: (listener) => enginePort.on("message", listener)
248
+ };
249
+ process.argv.push("--no-demo");
250
+ var compressedWasm = join(dirname(engineUrl), "hyperdb-wasm.wasm.br");
251
+ var decompressedWasm = Readable.toWeb(createReadStream(compressedWasm).pipe(createBrotliDecompress()));
252
+ var compiledWasm = await WebAssembly.compileStreaming(new Response(decompressedWasm, {
253
+ headers: { "Content-Type": "application/wasm" }
254
+ }));
255
+ var moduleConfiguration = {
256
+ instantiateWasm: (imports, receiveInstance) => {
257
+ void WebAssembly.instantiate(compiledWasm, imports).then((instance) => receiveInstance(instance, compiledWasm));
258
+ return {};
259
+ }
260
+ };
261
+ var configuredGlobal = globalThis;
262
+ configuredGlobal.HYPERDB_WASM_MODULE = moduleConfiguration;
263
+ var module = createRequire(import.meta.url)(engineUrl);
264
+ delete configuredGlobal.HYPERDB_WASM_MODULE;
265
+ configureWorker(module, transport, (runtime) => {
266
+ if (!runtime.NODEFS) throw new Error("Node filesystem backend is unavailable");
267
+ runtime.FS.mkdirTree("/host");
268
+ runtime.FS.mount(runtime.NODEFS, { root: hostPath }, "/host");
269
+ runtime.resolveHyperDBPath = (path) => {
270
+ const absolute = resolve(isAbsolute(path) ? path : join(hostPath, path));
271
+ const suffix = relative(hostPath, absolute);
272
+ if (suffix === ".." || suffix.startsWith(`..${sep}`) || isAbsolute(suffix)) {
273
+ throw new Error(`Arrow IPC path is outside the mounted host directory: ${path}`);
274
+ }
275
+ return posix.join("/host", ...suffix.split(sep));
276
+ };
277
+ });
@@ -0,0 +1,84 @@
1
+ export type RequestId = number;
2
+ export type EngineRequest = {
3
+ id: RequestId;
4
+ type: 'connect';
5
+ } | {
6
+ id: RequestId;
7
+ type: 'disconnect';
8
+ connection: number;
9
+ } | {
10
+ id: RequestId;
11
+ type: 'startQuery';
12
+ connection: number;
13
+ sql: string;
14
+ } | {
15
+ id: RequestId;
16
+ type: 'insertArrowIPCFromPath';
17
+ connection: number;
18
+ path: string;
19
+ name: string;
20
+ schema: string | null;
21
+ create: boolean;
22
+ internal: boolean;
23
+ } | {
24
+ id: RequestId;
25
+ type: 'createTemporaryFile';
26
+ bytes: Uint8Array;
27
+ } | {
28
+ id: RequestId;
29
+ type: 'removeFile';
30
+ path: string;
31
+ } | {
32
+ id: RequestId;
33
+ type: 'pollQuery';
34
+ query: number;
35
+ } | {
36
+ id: RequestId;
37
+ type: 'cancelQuery';
38
+ query: number;
39
+ } | {
40
+ id: RequestId;
41
+ type: 'releaseQuery';
42
+ query: number;
43
+ };
44
+ export type WasmResult = {
45
+ state: 'ok';
46
+ payload: Uint8Array;
47
+ } | {
48
+ state: 'pending';
49
+ } | {
50
+ state: 'chunk';
51
+ payload: Uint8Array;
52
+ } | {
53
+ state: 'done';
54
+ } | {
55
+ state: 'error';
56
+ error: string;
57
+ } | {
58
+ state: 'busy';
59
+ error: string;
60
+ };
61
+ export type WasmResponse = {
62
+ id: RequestId;
63
+ type: 'response';
64
+ result: WasmResult;
65
+ };
66
+ export type WorkerEvent = {
67
+ type: 'ready';
68
+ } | {
69
+ type: 'fatal';
70
+ error: string;
71
+ } | {
72
+ type: 'log';
73
+ text: string;
74
+ } | WasmResponse;
75
+ export interface WorkerTransport {
76
+ postMessage(message: EngineRequest, transfer?: readonly ArrayBuffer[]): void;
77
+ onMessage(listener: (message: unknown) => void): () => void;
78
+ onError(listener: (error: Error) => void): () => void;
79
+ onClose(listener: (error: Error) => void): () => void;
80
+ terminate(): void | Promise<unknown>;
81
+ }
82
+ export declare function isWasmResult(value: unknown): value is WasmResult;
83
+ export declare function isEngineRequest(value: unknown): value is EngineRequest;
84
+ export declare function isWorkerEvent(message: unknown): message is WorkerEvent;
@@ -0,0 +1,3 @@
1
+ export * from './raw.js';
2
+ export { BrowserWorker, createBrowserClient } from './browser.js';
3
+ export type { BrowserWorkerLike } from './browser.js';
@@ -0,0 +1,279 @@
1
+ // protocol.ts
2
+ function isRecord(value) {
3
+ return typeof value === "object" && value !== null;
4
+ }
5
+ function hasKeys(value, keys) {
6
+ const actual = Object.keys(value).sort();
7
+ const expected = [...keys].sort();
8
+ return actual.length === expected.length && actual.every((key, index) => key === expected[index]);
9
+ }
10
+ function isWasmResult(value) {
11
+ if (!isRecord(value) || typeof value.state !== "string") return false;
12
+ switch (value.state) {
13
+ case "ok":
14
+ case "chunk":
15
+ return hasKeys(value, ["state", "payload"]) && value.payload instanceof Uint8Array;
16
+ case "pending":
17
+ case "done":
18
+ return hasKeys(value, ["state"]);
19
+ case "error":
20
+ case "busy":
21
+ return hasKeys(value, ["state", "error"]) && typeof value.error === "string";
22
+ default:
23
+ return false;
24
+ }
25
+ }
26
+ function isWorkerEvent(message) {
27
+ if (!isRecord(message) || typeof message.type !== "string") return false;
28
+ switch (message.type) {
29
+ case "ready":
30
+ return hasKeys(message, ["type"]);
31
+ case "fatal":
32
+ return hasKeys(message, ["type", "error"]) && typeof message.error === "string";
33
+ case "log":
34
+ return hasKeys(message, ["type", "text"]) && typeof message.text === "string";
35
+ case "response":
36
+ return hasKeys(message, ["id", "type", "result"]) && Number.isSafeInteger(message.id) && isWasmResult(message.result);
37
+ default:
38
+ return false;
39
+ }
40
+ }
41
+
42
+ // client.ts
43
+ var HyperDBEngineClient = class {
44
+ transport;
45
+ pending = /* @__PURE__ */ new Map();
46
+ readyPromise;
47
+ resolveReady;
48
+ rejectReady;
49
+ nextId = 1;
50
+ failed;
51
+ unsubscribe;
52
+ constructor(transport) {
53
+ this.transport = transport;
54
+ this.readyPromise = new Promise((resolve, reject) => {
55
+ this.resolveReady = resolve;
56
+ this.rejectReady = reject;
57
+ });
58
+ this.unsubscribe = [
59
+ transport.onMessage((message) => this.onMessage(message)),
60
+ transport.onError((error) => this.fail(error)),
61
+ transport.onClose((error) => this.fail(error))
62
+ ];
63
+ }
64
+ ready() {
65
+ return this.readyPromise;
66
+ }
67
+ connect() {
68
+ return this.request({ id: this.nextId++, type: "connect" });
69
+ }
70
+ disconnect(connection) {
71
+ return this.request({ id: this.nextId++, type: "disconnect", connection });
72
+ }
73
+ startQuery(connection, sql) {
74
+ return this.request({ id: this.nextId++, type: "startQuery", connection, sql });
75
+ }
76
+ insertArrowIPCFromPath(connection, path, name, schema, create, internal = false) {
77
+ return this.request({ id: this.nextId++, type: "insertArrowIPCFromPath", connection, path, name, schema, create, internal });
78
+ }
79
+ createTemporaryFile(bytes) {
80
+ const payload = bytes.slice();
81
+ return this.request({ id: this.nextId++, type: "createTemporaryFile", bytes: payload }, [payload.buffer]);
82
+ }
83
+ removeFile(path) {
84
+ return this.request({ id: this.nextId++, type: "removeFile", path });
85
+ }
86
+ pollQuery(query) {
87
+ return this.request({ id: this.nextId++, type: "pollQuery", query });
88
+ }
89
+ cancelQuery(query) {
90
+ return this.request({ id: this.nextId++, type: "cancelQuery", query });
91
+ }
92
+ releaseQuery(query) {
93
+ return this.request({ id: this.nextId++, type: "releaseQuery", query });
94
+ }
95
+ async terminate() {
96
+ this.fail(new Error("engine worker terminated"));
97
+ await this.transport.terminate();
98
+ }
99
+ request(request, transfer = []) {
100
+ if (this.failed) return Promise.reject(this.failed);
101
+ return new Promise((resolve, reject) => {
102
+ this.pending.set(request.id, { resolve, reject });
103
+ try {
104
+ this.transport.postMessage(request, transfer);
105
+ } catch (error) {
106
+ this.pending.delete(request.id);
107
+ reject(error instanceof Error ? error : new Error(String(error)));
108
+ }
109
+ });
110
+ }
111
+ onMessage(message) {
112
+ if (!isWorkerEvent(message)) return;
113
+ if (message.type === "ready") {
114
+ this.resolveReady();
115
+ return;
116
+ }
117
+ if (message.type === "fatal") {
118
+ this.fail(new Error(message.error || "engine aborted"));
119
+ return;
120
+ }
121
+ if (message.type !== "response") return;
122
+ const pending = this.pending.get(message.id);
123
+ if (!pending) return;
124
+ this.pending.delete(message.id);
125
+ pending.resolve(message.result);
126
+ }
127
+ fail(error) {
128
+ if (this.failed) return;
129
+ this.failed = error;
130
+ for (const unsubscribe of this.unsubscribe.splice(0)) unsubscribe();
131
+ this.rejectReady(error);
132
+ for (const pending of this.pending.values()) pending.reject(error);
133
+ this.pending.clear();
134
+ }
135
+ };
136
+
137
+ // wasm_bindings.ts
138
+ var resultStates = ["ok", "pending", "chunk", "done", "error", "busy"];
139
+ function safeInteger(value, name) {
140
+ const number = typeof value === "bigint" && value <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(value) : value;
141
+ if (typeof number !== "number" || !Number.isSafeInteger(number) || number < 0) throw new Error(`${name} must be a nonnegative safe integer`);
142
+ return number;
143
+ }
144
+ var HyperDBBindings = class {
145
+ module;
146
+ connect;
147
+ disconnect;
148
+ startQuery;
149
+ insertArrowIPCFromPath;
150
+ pollQuery;
151
+ cancelQuery;
152
+ releaseQuery;
153
+ resultState;
154
+ resultPayloadLength;
155
+ free;
156
+ nextTemporaryFile = 1;
157
+ constructor(module) {
158
+ this.module = module;
159
+ this.connect = module.cwrap("hyperdb_wasm_connect", "pointer", []);
160
+ this.disconnect = module.cwrap("hyperdb_wasm_disconnect", "pointer", ["number"]);
161
+ this.startQuery = module.cwrap("hyperdb_wasm_query_start", "pointer", ["number", "string"]);
162
+ this.insertArrowIPCFromPath = module.cwrap("hyperdb_wasm_arrow_insert_from_path", "pointer", ["number", "string", "string", "string", "number"]);
163
+ this.pollQuery = module.cwrap("hyperdb_wasm_query_poll", "pointer", ["number"]);
164
+ this.cancelQuery = module.cwrap("hyperdb_wasm_query_cancel", "pointer", ["number"]);
165
+ this.releaseQuery = module.cwrap("hyperdb_wasm_query_release", "pointer", ["number"]);
166
+ this.resultState = module.cwrap("hyperdb_wasm_result_state", "number", ["number"]);
167
+ this.resultPayloadLength = module.cwrap("hyperdb_wasm_result_payload_len", "number", ["number"]);
168
+ this.free = module.cwrap("hyperdb_wasm_free", null, ["pointer"]);
169
+ }
170
+ handle(request) {
171
+ if (request.type === "createTemporaryFile") {
172
+ const path = `/tmp/hyperdb/arrow-${this.nextTemporaryFile++}.arrows`;
173
+ this.module.FS.mkdirTree("/tmp/hyperdb");
174
+ this.module.FS.writeFile(path, request.bytes);
175
+ return { response: { id: request.id, type: "response", result: { state: "ok", payload: new TextEncoder().encode(path) } }, transfer: [] };
176
+ }
177
+ if (request.type === "removeFile") {
178
+ this.module.FS.unlink(request.path);
179
+ return { response: { id: request.id, type: "response", result: { state: "ok", payload: new Uint8Array() } }, transfer: [] };
180
+ }
181
+ const pointer = safeInteger(this.invoke(request), "result pointer");
182
+ const result = this.decodeResult(pointer);
183
+ const response = { id: request.id, type: "response", result };
184
+ return { response, transfer: result.state === "chunk" ? [result.payload.buffer] : [] };
185
+ }
186
+ invoke(request) {
187
+ switch (request.type) {
188
+ case "connect":
189
+ return this.connect();
190
+ case "disconnect":
191
+ return this.disconnect(request.connection);
192
+ case "startQuery":
193
+ return this.startQuery(request.connection, request.sql);
194
+ case "insertArrowIPCFromPath": {
195
+ const path = request.internal ? request.path : this.module.resolveHyperDBPath?.(request.path) ?? request.path;
196
+ return this.insertArrowIPCFromPath(request.connection, path, request.name, request.schema ?? "", Number(request.create));
197
+ }
198
+ case "pollQuery":
199
+ return this.pollQuery(request.query);
200
+ case "cancelQuery":
201
+ return this.cancelQuery(request.query);
202
+ case "releaseQuery":
203
+ return this.releaseQuery(request.query);
204
+ }
205
+ }
206
+ decodeResult(pointer) {
207
+ if (pointer === 0) return { state: "error", error: "out of memory" };
208
+ try {
209
+ const rawState = safeInteger(this.resultState(pointer), "result state");
210
+ const state = resultStates[rawState];
211
+ if (!state) return { state: "error", error: `invalid result state ${rawState}` };
212
+ const payloadLength = safeInteger(this.resultPayloadLength(pointer), "result payload length");
213
+ const payloadStart = safeInteger(pointer + 8, "result payload start");
214
+ const payloadEnd = safeInteger(payloadStart + payloadLength, "result payload end");
215
+ if (payloadEnd > this.module.HEAPU8.byteLength) throw new Error("result payload exceeds the wasm heap");
216
+ const payload = new Uint8Array(payloadLength);
217
+ payload.set(this.module.HEAPU8.subarray(payloadStart, payloadEnd));
218
+ switch (state) {
219
+ case "ok":
220
+ return { state, payload };
221
+ case "pending":
222
+ return { state };
223
+ case "chunk":
224
+ return { state, payload };
225
+ case "done":
226
+ return { state };
227
+ case "error":
228
+ return { state, error: new TextDecoder().decode(payload) };
229
+ case "busy":
230
+ return { state, error: new TextDecoder().decode(payload) };
231
+ }
232
+ } finally {
233
+ this.free(pointer);
234
+ }
235
+ }
236
+ };
237
+
238
+ // browser.ts
239
+ var BrowserWorker = class {
240
+ constructor(worker) {
241
+ this.worker = worker;
242
+ }
243
+ worker;
244
+ postMessage(message, transfer = []) {
245
+ this.worker.postMessage(message, [...transfer]);
246
+ }
247
+ onMessage(listener) {
248
+ const wrapped = (event) => listener(event.data);
249
+ this.worker.addEventListener("message", wrapped);
250
+ return () => this.worker.removeEventListener("message", wrapped);
251
+ }
252
+ onError(listener) {
253
+ const wrapped = (event) => listener(new Error(event.message || "engine worker error"));
254
+ this.worker.addEventListener("error", wrapped);
255
+ return () => this.worker.removeEventListener("error", wrapped);
256
+ }
257
+ onClose() {
258
+ return () => void 0;
259
+ }
260
+ terminate() {
261
+ this.worker.terminate();
262
+ }
263
+ };
264
+ function resolveBrowserWorkerUrl(workerUrl, engineUrl) {
265
+ const resolved = new URL(workerUrl);
266
+ resolved.searchParams.set("engineUrl", new URL(engineUrl).href);
267
+ return resolved;
268
+ }
269
+ function createBrowserClient(options = {}) {
270
+ const workerUrl = options.workerUrl ?? new URL("./browser_worker.js", import.meta.url);
271
+ const engineUrl = options.engineUrl ?? new URL("./hyperdb-wasm.js", import.meta.url);
272
+ return new HyperDBEngineClient(new BrowserWorker(new Worker(resolveBrowserWorkerUrl(workerUrl, engineUrl), { type: "classic" })));
273
+ }
274
+ export {
275
+ BrowserWorker,
276
+ HyperDBBindings,
277
+ HyperDBEngineClient,
278
+ createBrowserClient
279
+ };
package/dist/raw.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export { HyperDBEngineClient } from './client.js';
2
+ export { HyperDBBindings } from './wasm_bindings.js';
3
+ export type { EngineRequest, WasmResponse, WasmResult, WorkerEvent, WorkerTransport } from './protocol.js';
@@ -0,0 +1,3 @@
1
+ export * from './raw.js';
2
+ export { NodeWorker, createNodeClient } from './node.js';
3
+ export type { NodeClientOptions, NodeWorkerLike } from './node.js';