hyperdb-wasm 0.0.26284-dev.wasm.gf1f9d795 → 0.0.26298-dev.wasm.gd63c7938
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 +23 -6
- package/dist/browser.js +124 -45
- package/dist/browser_worker.js +104 -26
- package/dist/client.d.ts +10 -2
- package/dist/hyperdb-wasm.cjs +1 -1
- package/dist/hyperdb-wasm.js +1 -1
- package/dist/hyperdb-wasm.wasm.br +0 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.node.d.ts +1 -1
- package/dist/node.d.ts +1 -0
- package/dist/node.js +125 -46
- package/dist/node_worker.js +101 -27
- package/dist/protocol.d.ts +41 -5
- package/dist/raw.browser.js +84 -21
- package/dist/raw.node.js +85 -22
- package/dist/wasm_bindings.d.ts +16 -2
- package/dist/worker_setup.d.ts +4 -1
- package/examples/browser-attached-databases.html +71 -0
- package/examples/browser.html +7 -7
- package/examples/node-attached-databases.mjs +36 -0
- package/examples/node.mjs +22 -10
- package/package.json +1 -1
package/dist/api.d.ts
CHANGED
|
@@ -7,12 +7,20 @@ export interface HyperDBClient {
|
|
|
7
7
|
ready(): Promise<void>;
|
|
8
8
|
connect(): Promise<WasmResult>;
|
|
9
9
|
disconnect(connection: number): Promise<WasmResult>;
|
|
10
|
+
createDatabase(databaseName: string, persistent: boolean): Promise<WasmResult>;
|
|
11
|
+
openDatabase(databaseName: string): Promise<WasmResult>;
|
|
12
|
+
checkpointDatabase(databaseName: string): Promise<WasmResult>;
|
|
13
|
+
dropDatabase(databaseName: string): Promise<WasmResult>;
|
|
14
|
+
attachDatabase(connection: number, databaseName: string, alias: string): Promise<WasmResult>;
|
|
15
|
+
detachDatabase(connection: number, alias: string): Promise<WasmResult>;
|
|
10
16
|
startQuery(connection: number, sql: string): Promise<WasmResult>;
|
|
11
|
-
|
|
12
|
-
|
|
17
|
+
insertArrowIPCFromPath(connection: number, path: string, name: string, schema: string | null, create: boolean, internal?: boolean): Promise<WasmResult>;
|
|
18
|
+
createTemporaryFile(bytes: Uint8Array): Promise<WasmResult>;
|
|
19
|
+
removeFile(path: string): Promise<WasmResult>;
|
|
13
20
|
pollQuery(query: number): Promise<WasmResult>;
|
|
14
21
|
cancelQuery(query: number): Promise<WasmResult>;
|
|
15
22
|
releaseQuery(query: number): Promise<WasmResult>;
|
|
23
|
+
shutdown(): Promise<WasmResult>;
|
|
16
24
|
terminate(): Promise<void>;
|
|
17
25
|
}
|
|
18
26
|
export interface ArrowInsertOptions {
|
|
@@ -20,17 +28,26 @@ export interface ArrowInsertOptions {
|
|
|
20
28
|
readonly schema?: string;
|
|
21
29
|
readonly create?: boolean;
|
|
22
30
|
}
|
|
31
|
+
export interface DatabaseCreateOptions {
|
|
32
|
+
readonly storage?: 'memory' | 'persistent';
|
|
33
|
+
}
|
|
23
34
|
export declare class HyperDB {
|
|
24
35
|
private readonly client;
|
|
25
36
|
private terminated;
|
|
26
37
|
private termination;
|
|
38
|
+
private activeDatabaseOperations;
|
|
27
39
|
private readonly connections;
|
|
28
40
|
constructor(client: HyperDBClient);
|
|
29
41
|
static create(options?: BrowserClientOptions): Promise<HyperDB>;
|
|
30
42
|
ready(): Promise<void>;
|
|
31
43
|
connect(): Promise<HyperDBConnection>;
|
|
44
|
+
createDatabase(databaseName: string, options?: DatabaseCreateOptions): Promise<void>;
|
|
45
|
+
openDatabase(databaseName: string): Promise<void>;
|
|
46
|
+
checkpointDatabase(databaseName: string): Promise<void>;
|
|
47
|
+
dropDatabase(databaseName: string): Promise<void>;
|
|
32
48
|
terminate(): Promise<void>;
|
|
33
49
|
private ensureRunning;
|
|
50
|
+
private runDatabaseOperation;
|
|
34
51
|
}
|
|
35
52
|
export declare class HyperDBConnection {
|
|
36
53
|
private readonly client;
|
|
@@ -38,11 +55,11 @@ export declare class HyperDBConnection {
|
|
|
38
55
|
private readonly onClose;
|
|
39
56
|
private closed;
|
|
40
57
|
private active;
|
|
41
|
-
private arrowInsertOptions;
|
|
42
|
-
private appendingArrow;
|
|
43
58
|
private closing;
|
|
44
59
|
constructor(client: HyperDBClient, connection: number, onClose?: () => void);
|
|
45
60
|
close(): Promise<void>;
|
|
61
|
+
attachDatabase(databaseName: string, alias?: string): Promise<void>;
|
|
62
|
+
detachDatabase(alias: string): Promise<void>;
|
|
46
63
|
sendIPC(sql: string): AsyncIterable<Uint8Array>;
|
|
47
64
|
queryIPC(sql: string): Promise<Uint8Array>;
|
|
48
65
|
send<T extends TypeMap = {
|
|
@@ -52,8 +69,8 @@ export declare class HyperDBConnection {
|
|
|
52
69
|
[key: string]: DataType;
|
|
53
70
|
}>(sql: string): Promise<Table<T>>;
|
|
54
71
|
insertArrowTable(table: Table, options: ArrowInsertOptions): Promise<void>;
|
|
55
|
-
|
|
56
|
-
|
|
72
|
+
insertArrowIPCFromPath(path: string, options: ArrowInsertOptions): Promise<void>;
|
|
73
|
+
private insertArrowIPCFromPathInternal;
|
|
57
74
|
private ensureAvailable;
|
|
58
75
|
private release;
|
|
59
76
|
closeForTermination(): Promise<void>;
|
package/dist/browser.js
CHANGED
|
@@ -95,15 +95,39 @@ var init_client = __esm({
|
|
|
95
95
|
disconnect(connection) {
|
|
96
96
|
return this.request({ id: this.nextId++, type: "disconnect", connection });
|
|
97
97
|
}
|
|
98
|
+
createDatabase(databaseName, persistent) {
|
|
99
|
+
return this.request({ id: this.nextId++, type: "createDatabase", databaseName, persistent });
|
|
100
|
+
}
|
|
101
|
+
openDatabase(databaseName) {
|
|
102
|
+
return this.request({ id: this.nextId++, type: "openDatabase", databaseName });
|
|
103
|
+
}
|
|
104
|
+
checkpointDatabase(databaseName) {
|
|
105
|
+
return this.request({ id: this.nextId++, type: "checkpointDatabase", databaseName });
|
|
106
|
+
}
|
|
107
|
+
dropDatabase(databaseName) {
|
|
108
|
+
return this.request({ id: this.nextId++, type: "dropDatabase", databaseName });
|
|
109
|
+
}
|
|
110
|
+
attachDatabase(connection, databaseName, alias) {
|
|
111
|
+
return this.request({ id: this.nextId++, type: "attachDatabase", connection, databaseName, alias });
|
|
112
|
+
}
|
|
113
|
+
detachDatabase(connection, alias) {
|
|
114
|
+
return this.request({ id: this.nextId++, type: "detachDatabase", connection, alias });
|
|
115
|
+
}
|
|
116
|
+
shutdown() {
|
|
117
|
+
return this.request({ id: this.nextId++, type: "shutdown" });
|
|
118
|
+
}
|
|
98
119
|
startQuery(connection, sql) {
|
|
99
120
|
return this.request({ id: this.nextId++, type: "startQuery", connection, sql });
|
|
100
121
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
return this.request({ id: this.nextId++, type: "appendArrowIPC", connection, chunk: payload }, [payload.buffer]);
|
|
122
|
+
insertArrowIPCFromPath(connection, path, name, schema, create, internal = false) {
|
|
123
|
+
return this.request({ id: this.nextId++, type: "insertArrowIPCFromPath", connection, path, name, schema, create, internal });
|
|
104
124
|
}
|
|
105
|
-
|
|
106
|
-
|
|
125
|
+
createTemporaryFile(bytes) {
|
|
126
|
+
const payload = bytes.slice();
|
|
127
|
+
return this.request({ id: this.nextId++, type: "createTemporaryFile", bytes: payload }, [payload.buffer]);
|
|
128
|
+
}
|
|
129
|
+
removeFile(path) {
|
|
130
|
+
return this.request({ id: this.nextId++, type: "removeFile", path });
|
|
107
131
|
}
|
|
108
132
|
pollQuery(query) {
|
|
109
133
|
return this.request({ id: this.nextId++, type: "pollQuery", query });
|
|
@@ -12054,8 +12078,13 @@ function normalizeArrowInsertOptions(options) {
|
|
|
12054
12078
|
if (!options.name) throw new Error("Arrow insert table name must not be empty");
|
|
12055
12079
|
return { name: options.name, schema: options.schema ?? null, create: options.create ?? true };
|
|
12056
12080
|
}
|
|
12057
|
-
function
|
|
12058
|
-
|
|
12081
|
+
function validateDatabaseName(databaseName) {
|
|
12082
|
+
if (!databaseName) throw new Error("Database name must not be empty");
|
|
12083
|
+
if (databaseName.includes("\0")) throw new Error("Database name must not contain NUL");
|
|
12084
|
+
}
|
|
12085
|
+
function validateDatabaseAlias(alias) {
|
|
12086
|
+
if (!alias) throw new Error("Database alias must not be empty");
|
|
12087
|
+
if (alias.includes("\0")) throw new Error("Database alias must not contain NUL");
|
|
12059
12088
|
}
|
|
12060
12089
|
function materializeDictionaryColumns(table) {
|
|
12061
12090
|
const dictionaryColumns = table.schema.fields.map((field, index) => DataType.isDictionary(field.type) ? index : -1).filter((index) => index !== -1);
|
|
@@ -12097,6 +12126,7 @@ var HyperDB = class _HyperDB {
|
|
|
12097
12126
|
client;
|
|
12098
12127
|
terminated = false;
|
|
12099
12128
|
termination;
|
|
12129
|
+
activeDatabaseOperations = 0;
|
|
12100
12130
|
connections = /* @__PURE__ */ new Set();
|
|
12101
12131
|
static async create(options = {}) {
|
|
12102
12132
|
const { createBrowserClient: createBrowserClient2 } = await Promise.resolve().then(() => (init_browser(), browser_exports));
|
|
@@ -12115,8 +12145,36 @@ var HyperDB = class _HyperDB {
|
|
|
12115
12145
|
this.connections.add(result);
|
|
12116
12146
|
return result;
|
|
12117
12147
|
}
|
|
12148
|
+
async createDatabase(databaseName, options = {}) {
|
|
12149
|
+
validateDatabaseName(databaseName);
|
|
12150
|
+
if (options.storage !== void 0 && options.storage !== "memory" && options.storage !== "persistent") {
|
|
12151
|
+
throw new Error(`Unsupported database storage: ${String(options.storage)}`);
|
|
12152
|
+
}
|
|
12153
|
+
await this.runDatabaseOperation(async () => {
|
|
12154
|
+
expectOk(await this.client.createDatabase(databaseName, options.storage === "persistent"), "create database");
|
|
12155
|
+
});
|
|
12156
|
+
}
|
|
12157
|
+
async openDatabase(databaseName) {
|
|
12158
|
+
validateDatabaseName(databaseName);
|
|
12159
|
+
await this.runDatabaseOperation(async () => {
|
|
12160
|
+
expectOk(await this.client.openDatabase(databaseName), "open database");
|
|
12161
|
+
});
|
|
12162
|
+
}
|
|
12163
|
+
async checkpointDatabase(databaseName) {
|
|
12164
|
+
validateDatabaseName(databaseName);
|
|
12165
|
+
await this.runDatabaseOperation(async () => {
|
|
12166
|
+
expectOk(await this.client.checkpointDatabase(databaseName), "checkpoint database");
|
|
12167
|
+
});
|
|
12168
|
+
}
|
|
12169
|
+
async dropDatabase(databaseName) {
|
|
12170
|
+
validateDatabaseName(databaseName);
|
|
12171
|
+
await this.runDatabaseOperation(async () => {
|
|
12172
|
+
expectOk(await this.client.dropDatabase(databaseName), "drop database");
|
|
12173
|
+
});
|
|
12174
|
+
}
|
|
12118
12175
|
async terminate() {
|
|
12119
12176
|
if (this.terminated) return;
|
|
12177
|
+
if (this.activeDatabaseOperations !== 0) throw new Error("database has an active operation");
|
|
12120
12178
|
if (!this.termination) {
|
|
12121
12179
|
this.termination = (async () => {
|
|
12122
12180
|
try {
|
|
@@ -12125,6 +12183,12 @@ var HyperDB = class _HyperDB {
|
|
|
12125
12183
|
this.termination = void 0;
|
|
12126
12184
|
throw error;
|
|
12127
12185
|
}
|
|
12186
|
+
try {
|
|
12187
|
+
expectOk(await this.client.shutdown(), "shutdown");
|
|
12188
|
+
} catch (error) {
|
|
12189
|
+
this.termination = void 0;
|
|
12190
|
+
throw error;
|
|
12191
|
+
}
|
|
12128
12192
|
this.terminated = true;
|
|
12129
12193
|
await this.client.terminate();
|
|
12130
12194
|
})();
|
|
@@ -12133,6 +12197,16 @@ var HyperDB = class _HyperDB {
|
|
|
12133
12197
|
}
|
|
12134
12198
|
ensureRunning() {
|
|
12135
12199
|
if (this.terminated) throw new Error("database is terminated");
|
|
12200
|
+
if (this.termination) throw new Error("database is terminating");
|
|
12201
|
+
}
|
|
12202
|
+
async runDatabaseOperation(operation) {
|
|
12203
|
+
this.ensureRunning();
|
|
12204
|
+
++this.activeDatabaseOperations;
|
|
12205
|
+
try {
|
|
12206
|
+
await operation();
|
|
12207
|
+
} finally {
|
|
12208
|
+
--this.activeDatabaseOperations;
|
|
12209
|
+
}
|
|
12136
12210
|
}
|
|
12137
12211
|
};
|
|
12138
12212
|
var HyperDBConnection = class {
|
|
@@ -12146,13 +12220,10 @@ var HyperDBConnection = class {
|
|
|
12146
12220
|
onClose;
|
|
12147
12221
|
closed = false;
|
|
12148
12222
|
active = false;
|
|
12149
|
-
arrowInsertOptions;
|
|
12150
|
-
appendingArrow = false;
|
|
12151
12223
|
closing;
|
|
12152
12224
|
async close() {
|
|
12153
12225
|
if (this.closed) return;
|
|
12154
|
-
if (this.active) throw new Error("connection has an active
|
|
12155
|
-
if (this.arrowInsertOptions) throw new Error("connection has an unfinished Arrow IPC stream");
|
|
12226
|
+
if (this.active) throw new Error("connection has an active operation");
|
|
12156
12227
|
if (!this.closing) {
|
|
12157
12228
|
this.closing = (async () => {
|
|
12158
12229
|
try {
|
|
@@ -12167,6 +12238,25 @@ var HyperDBConnection = class {
|
|
|
12167
12238
|
}
|
|
12168
12239
|
await this.closing;
|
|
12169
12240
|
}
|
|
12241
|
+
async attachDatabase(databaseName, alias = databaseName) {
|
|
12242
|
+
validateDatabaseName(databaseName);
|
|
12243
|
+
validateDatabaseAlias(alias);
|
|
12244
|
+
this.ensureAvailable();
|
|
12245
|
+
try {
|
|
12246
|
+
expectOk(await this.client.attachDatabase(this.connection, databaseName, alias), "attach database");
|
|
12247
|
+
} finally {
|
|
12248
|
+
this.active = false;
|
|
12249
|
+
}
|
|
12250
|
+
}
|
|
12251
|
+
async detachDatabase(alias) {
|
|
12252
|
+
validateDatabaseAlias(alias);
|
|
12253
|
+
this.ensureAvailable();
|
|
12254
|
+
try {
|
|
12255
|
+
expectOk(await this.client.detachDatabase(this.connection, alias), "detach database");
|
|
12256
|
+
} finally {
|
|
12257
|
+
this.active = false;
|
|
12258
|
+
}
|
|
12259
|
+
}
|
|
12170
12260
|
sendIPC(sql) {
|
|
12171
12261
|
const connection = this;
|
|
12172
12262
|
return {
|
|
@@ -12254,41 +12344,31 @@ var HyperDBConnection = class {
|
|
|
12254
12344
|
return new Table(reader.schema, batches);
|
|
12255
12345
|
}
|
|
12256
12346
|
async insertArrowTable(table, options) {
|
|
12257
|
-
|
|
12258
|
-
|
|
12259
|
-
}
|
|
12260
|
-
async insertArrowFromIPCStream(chunk, options) {
|
|
12261
|
-
if (this.closed) throw new Error("connection is closed");
|
|
12262
|
-
if (this.closing) throw new Error("connection is closing");
|
|
12263
|
-
if (this.active) throw new Error("connection has an active query");
|
|
12264
|
-
if (this.appendingArrow) throw new Error("connection is appending Arrow IPC");
|
|
12265
|
-
const normalized = normalizeArrowInsertOptions(options);
|
|
12266
|
-
if (this.arrowInsertOptions && !equalArrowInsertOptions(this.arrowInsertOptions, normalized)) {
|
|
12267
|
-
throw new Error("Arrow insert options must match the pending stream");
|
|
12268
|
-
}
|
|
12269
|
-
this.appendingArrow = true;
|
|
12347
|
+
this.ensureAvailable();
|
|
12348
|
+
let path;
|
|
12270
12349
|
try {
|
|
12271
|
-
|
|
12272
|
-
|
|
12350
|
+
const result = await this.client.createTemporaryFile(tableToIPC(materializeDictionaryColumns(table), "stream"));
|
|
12351
|
+
expectOk(result, "create temporary Arrow IPC file");
|
|
12352
|
+
path = new TextDecoder().decode(result.payload);
|
|
12353
|
+
await this.insertArrowIPCFromPathInternal(path, options, true, false);
|
|
12273
12354
|
} finally {
|
|
12274
|
-
|
|
12355
|
+
try {
|
|
12356
|
+
if (path !== void 0) expectOk(await this.client.removeFile(path), "remove temporary Arrow IPC file");
|
|
12357
|
+
} finally {
|
|
12358
|
+
this.active = false;
|
|
12359
|
+
}
|
|
12275
12360
|
}
|
|
12276
12361
|
}
|
|
12277
|
-
async
|
|
12278
|
-
|
|
12279
|
-
|
|
12280
|
-
|
|
12281
|
-
if (
|
|
12282
|
-
const normalized =
|
|
12283
|
-
if (
|
|
12284
|
-
if (this.arrowInsertOptions && !equalArrowInsertOptions(this.arrowInsertOptions, normalized)) {
|
|
12285
|
-
throw new Error("Arrow insert options must match the pending stream");
|
|
12286
|
-
}
|
|
12287
|
-
this.active = true;
|
|
12362
|
+
async insertArrowIPCFromPath(path, options) {
|
|
12363
|
+
await this.insertArrowIPCFromPathInternal(path, options, false);
|
|
12364
|
+
}
|
|
12365
|
+
async insertArrowIPCFromPathInternal(path, options, internal, acquire = true) {
|
|
12366
|
+
if (!path) throw new Error("Arrow IPC input path must not be empty");
|
|
12367
|
+
const normalized = normalizeArrowInsertOptions(options);
|
|
12368
|
+
if (acquire) this.ensureAvailable();
|
|
12288
12369
|
let query;
|
|
12289
12370
|
try {
|
|
12290
|
-
query = readHandleFromResult(await this.client.
|
|
12291
|
-
this.arrowInsertOptions = void 0;
|
|
12371
|
+
query = readHandleFromResult(await this.client.insertArrowIPCFromPath(this.connection, path, normalized.name, normalized.schema, normalized.create, internal), "insert Arrow IPC from path");
|
|
12292
12372
|
for (; ; ) {
|
|
12293
12373
|
let result = await this.client.pollQuery(query);
|
|
12294
12374
|
while (result.state === "pending") {
|
|
@@ -12297,13 +12377,13 @@ var HyperDBConnection = class {
|
|
|
12297
12377
|
}
|
|
12298
12378
|
if (result.state === "done") return;
|
|
12299
12379
|
if (result.state === "chunk") continue;
|
|
12300
|
-
throw readErrorFromResult(result, "
|
|
12380
|
+
throw readErrorFromResult(result, "insert Arrow IPC from path");
|
|
12301
12381
|
}
|
|
12302
12382
|
} finally {
|
|
12303
12383
|
try {
|
|
12304
12384
|
if (query !== void 0) await this.release(query);
|
|
12305
12385
|
} finally {
|
|
12306
|
-
this.active = false;
|
|
12386
|
+
if (acquire) this.active = false;
|
|
12307
12387
|
}
|
|
12308
12388
|
}
|
|
12309
12389
|
}
|
|
@@ -12311,7 +12391,7 @@ var HyperDBConnection = class {
|
|
|
12311
12391
|
if (this.closed) throw new Error("connection is closed");
|
|
12312
12392
|
if (this.closing) throw new Error("connection is closing");
|
|
12313
12393
|
if (this.active) {
|
|
12314
|
-
throw new Error("connection has an active
|
|
12394
|
+
throw new Error("connection has an active operation");
|
|
12315
12395
|
}
|
|
12316
12396
|
this.active = true;
|
|
12317
12397
|
}
|
|
@@ -12326,8 +12406,7 @@ var HyperDBConnection = class {
|
|
|
12326
12406
|
}
|
|
12327
12407
|
}
|
|
12328
12408
|
async closeForTermination() {
|
|
12329
|
-
if (this.active) throw new Error("cannot terminate while a connection has an active
|
|
12330
|
-
if (this.arrowInsertOptions) throw new Error("cannot terminate while a connection has an unfinished Arrow IPC stream");
|
|
12409
|
+
if (this.active) throw new Error("cannot terminate while a connection has an active operation");
|
|
12331
12410
|
await this.close();
|
|
12332
12411
|
}
|
|
12333
12412
|
};
|
package/dist/browser_worker.js
CHANGED
|
@@ -7,26 +7,43 @@
|
|
|
7
7
|
if (typeof number !== "number" || !Number.isSafeInteger(number) || number < 0) throw new Error(`${name} must be a nonnegative safe integer`);
|
|
8
8
|
return number;
|
|
9
9
|
}
|
|
10
|
+
function validateCString(value, name) {
|
|
11
|
+
if (!value) throw new Error(`${name} must not be empty`);
|
|
12
|
+
if (value.includes("\0")) throw new Error(`${name} must not contain NUL`);
|
|
13
|
+
}
|
|
10
14
|
var HyperDBBindings = class {
|
|
11
15
|
module;
|
|
12
16
|
connect;
|
|
13
17
|
disconnect;
|
|
18
|
+
createDatabase;
|
|
19
|
+
openDatabase;
|
|
20
|
+
checkpointDatabase;
|
|
21
|
+
dropDatabase;
|
|
22
|
+
shutdown;
|
|
23
|
+
attachDatabase;
|
|
24
|
+
detachDatabase;
|
|
14
25
|
startQuery;
|
|
15
|
-
|
|
16
|
-
finishArrowIPC;
|
|
26
|
+
insertArrowIPCFromPath;
|
|
17
27
|
pollQuery;
|
|
18
28
|
cancelQuery;
|
|
19
29
|
releaseQuery;
|
|
20
30
|
resultState;
|
|
21
31
|
resultPayloadLength;
|
|
22
32
|
free;
|
|
33
|
+
nextTemporaryFile = 1;
|
|
23
34
|
constructor(module) {
|
|
24
35
|
this.module = module;
|
|
25
36
|
this.connect = module.cwrap("hyperdb_wasm_connect", "pointer", []);
|
|
26
37
|
this.disconnect = module.cwrap("hyperdb_wasm_disconnect", "pointer", ["number"]);
|
|
38
|
+
this.createDatabase = module.cwrap("hyperdb_wasm_create_database", "pointer", ["string", "number"]);
|
|
39
|
+
this.openDatabase = module.cwrap("hyperdb_wasm_open_database", "pointer", ["string"]);
|
|
40
|
+
this.checkpointDatabase = module.cwrap("hyperdb_wasm_checkpoint_database", "pointer", ["string"]);
|
|
41
|
+
this.dropDatabase = module.cwrap("hyperdb_wasm_drop_database", "pointer", ["string"]);
|
|
42
|
+
this.shutdown = module.cwrap("hyperdb_wasm_shutdown", "pointer", []);
|
|
43
|
+
this.attachDatabase = module.cwrap("hyperdb_wasm_attach_database", "pointer", ["number", "string", "string"]);
|
|
44
|
+
this.detachDatabase = module.cwrap("hyperdb_wasm_detach_database", "pointer", ["number", "string"]);
|
|
27
45
|
this.startQuery = module.cwrap("hyperdb_wasm_query_start", "pointer", ["number", "string"]);
|
|
28
|
-
this.
|
|
29
|
-
this.finishArrowIPC = module.cwrap("hyperdb_wasm_arrow_insert_finish", "pointer", ["number", "string", "string", "number"]);
|
|
46
|
+
this.insertArrowIPCFromPath = module.cwrap("hyperdb_wasm_arrow_insert_from_path", "pointer", ["number", "string", "string", "string", "number"]);
|
|
30
47
|
this.pollQuery = module.cwrap("hyperdb_wasm_query_poll", "pointer", ["number"]);
|
|
31
48
|
this.cancelQuery = module.cwrap("hyperdb_wasm_query_cancel", "pointer", ["number"]);
|
|
32
49
|
this.releaseQuery = module.cwrap("hyperdb_wasm_query_release", "pointer", ["number"]);
|
|
@@ -35,6 +52,16 @@
|
|
|
35
52
|
this.free = module.cwrap("hyperdb_wasm_free", null, ["pointer"]);
|
|
36
53
|
}
|
|
37
54
|
handle(request) {
|
|
55
|
+
if (request.type === "createTemporaryFile") {
|
|
56
|
+
const path = `/tmp/hyperdb/arrow-${this.nextTemporaryFile++}.arrows`;
|
|
57
|
+
this.module.FS.mkdirTree("/tmp/hyperdb");
|
|
58
|
+
this.module.FS.writeFile(path, request.bytes);
|
|
59
|
+
return { response: { id: request.id, type: "response", result: { state: "ok", payload: new TextEncoder().encode(path) } }, transfer: [] };
|
|
60
|
+
}
|
|
61
|
+
if (request.type === "removeFile") {
|
|
62
|
+
this.module.FS.unlink(request.path);
|
|
63
|
+
return { response: { id: request.id, type: "response", result: { state: "ok", payload: new Uint8Array() } }, transfer: [] };
|
|
64
|
+
}
|
|
38
65
|
const pointer = safeInteger(this.invoke(request), "result pointer");
|
|
39
66
|
const result = this.decodeResult(pointer);
|
|
40
67
|
const response = { id: request.id, type: "response", result };
|
|
@@ -46,21 +73,33 @@
|
|
|
46
73
|
return this.connect();
|
|
47
74
|
case "disconnect":
|
|
48
75
|
return this.disconnect(request.connection);
|
|
76
|
+
case "createDatabase":
|
|
77
|
+
validateCString(request.databaseName, "database name");
|
|
78
|
+
return this.createDatabase(request.databaseName, Number(request.persistent));
|
|
79
|
+
case "openDatabase":
|
|
80
|
+
validateCString(request.databaseName, "database name");
|
|
81
|
+
return this.openDatabase(request.databaseName);
|
|
82
|
+
case "checkpointDatabase":
|
|
83
|
+
validateCString(request.databaseName, "database name");
|
|
84
|
+
return this.checkpointDatabase(request.databaseName);
|
|
85
|
+
case "dropDatabase":
|
|
86
|
+
validateCString(request.databaseName, "database name");
|
|
87
|
+
return this.dropDatabase(request.databaseName);
|
|
88
|
+
case "attachDatabase":
|
|
89
|
+
validateCString(request.databaseName, "database name");
|
|
90
|
+
validateCString(request.alias, "database alias");
|
|
91
|
+
return this.attachDatabase(request.connection, request.databaseName, request.alias);
|
|
92
|
+
case "detachDatabase":
|
|
93
|
+
validateCString(request.alias, "database alias");
|
|
94
|
+
return this.detachDatabase(request.connection, request.alias);
|
|
95
|
+
case "shutdown":
|
|
96
|
+
return this.shutdown();
|
|
49
97
|
case "startQuery":
|
|
50
98
|
return this.startQuery(request.connection, request.sql);
|
|
51
|
-
case "
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
try {
|
|
55
|
-
if (pointer + request.chunk.byteLength > this.module.HEAPU8.byteLength) throw new Error("allocation exceeds the wasm heap");
|
|
56
|
-
this.module.HEAPU8.set(request.chunk, pointer);
|
|
57
|
-
return this.appendArrowIPC(request.connection, pointer, request.chunk.byteLength);
|
|
58
|
-
} finally {
|
|
59
|
-
this.free(pointer);
|
|
60
|
-
}
|
|
99
|
+
case "insertArrowIPCFromPath": {
|
|
100
|
+
const path = request.internal ? request.path : this.module.resolveHyperDBPath?.(request.path) ?? request.path;
|
|
101
|
+
return this.insertArrowIPCFromPath(request.connection, path, request.name, request.schema ?? "", Number(request.create));
|
|
61
102
|
}
|
|
62
|
-
case "finishArrowIPC":
|
|
63
|
-
return this.finishArrowIPC(request.connection, request.name, request.schema ?? "", Number(request.create));
|
|
64
103
|
case "pollQuery":
|
|
65
104
|
return this.pollQuery(request.query);
|
|
66
105
|
case "cancelQuery":
|
|
@@ -117,12 +156,26 @@
|
|
|
117
156
|
return hasKeys(value, ["id", "type"]);
|
|
118
157
|
case "disconnect":
|
|
119
158
|
return hasKeys(value, ["id", "type", "connection"]) && Number.isSafeInteger(value.connection);
|
|
159
|
+
case "createDatabase":
|
|
160
|
+
return hasKeys(value, ["id", "type", "databaseName", "persistent"]) && typeof value.databaseName === "string" && typeof value.persistent === "boolean";
|
|
161
|
+
case "openDatabase":
|
|
162
|
+
case "checkpointDatabase":
|
|
163
|
+
case "dropDatabase":
|
|
164
|
+
return hasKeys(value, ["id", "type", "databaseName"]) && typeof value.databaseName === "string";
|
|
165
|
+
case "shutdown":
|
|
166
|
+
return hasKeys(value, ["id", "type"]);
|
|
167
|
+
case "attachDatabase":
|
|
168
|
+
return hasKeys(value, ["id", "type", "connection", "databaseName", "alias"]) && Number.isSafeInteger(value.connection) && typeof value.databaseName === "string" && typeof value.alias === "string";
|
|
169
|
+
case "detachDatabase":
|
|
170
|
+
return hasKeys(value, ["id", "type", "connection", "alias"]) && Number.isSafeInteger(value.connection) && typeof value.alias === "string";
|
|
120
171
|
case "startQuery":
|
|
121
172
|
return hasKeys(value, ["id", "type", "connection", "sql"]) && Number.isSafeInteger(value.connection) && typeof value.sql === "string";
|
|
122
|
-
case "
|
|
123
|
-
return hasKeys(value, ["id", "type", "connection", "
|
|
124
|
-
case "
|
|
125
|
-
return hasKeys(value, ["id", "type", "
|
|
173
|
+
case "insertArrowIPCFromPath":
|
|
174
|
+
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";
|
|
175
|
+
case "createTemporaryFile":
|
|
176
|
+
return hasKeys(value, ["id", "type", "bytes"]) && value.bytes instanceof Uint8Array;
|
|
177
|
+
case "removeFile":
|
|
178
|
+
return hasKeys(value, ["id", "type", "path"]) && typeof value.path === "string";
|
|
126
179
|
case "pollQuery":
|
|
127
180
|
case "cancelQuery":
|
|
128
181
|
case "releaseQuery":
|
|
@@ -192,7 +245,7 @@
|
|
|
192
245
|
});
|
|
193
246
|
};
|
|
194
247
|
}
|
|
195
|
-
function configureWorker(module, transport) {
|
|
248
|
+
function configureWorker(module, transport, configureFilesystem = () => void 0) {
|
|
196
249
|
const queuedRequests = [];
|
|
197
250
|
let bindings;
|
|
198
251
|
const handle = (request) => {
|
|
@@ -214,10 +267,15 @@
|
|
|
214
267
|
module.print = (text) => transport.postMessage({ type: "log", text });
|
|
215
268
|
module.printErr = (text) => transport.postMessage({ type: "log", text });
|
|
216
269
|
module.onRuntimeInitialized = () => {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
270
|
+
try {
|
|
271
|
+
configureFilesystem(module);
|
|
272
|
+
installHttpRuntime(module, transport);
|
|
273
|
+
bindings = new HyperDBBindings(module);
|
|
274
|
+
transport.postMessage({ type: "ready" });
|
|
275
|
+
for (const request of queuedRequests.splice(0)) handle(request);
|
|
276
|
+
} catch (error) {
|
|
277
|
+
transport.postMessage({ type: "fatal", error: `engine initialization failed: ${errorText(error)}` });
|
|
278
|
+
}
|
|
221
279
|
};
|
|
222
280
|
module.onAbort = (reason) => transport.postMessage({ type: "fatal", error: `engine aborted: ${String(reason)}` });
|
|
223
281
|
}
|
|
@@ -241,7 +299,27 @@
|
|
|
241
299
|
postMessage: (message, transfer = []) => self.postMessage(message, [...transfer]),
|
|
242
300
|
onMessage: (listener) => self.addEventListener("message", (event) => listener(event.data))
|
|
243
301
|
};
|
|
244
|
-
configureWorker(module, transport)
|
|
302
|
+
configureWorker(module, transport, (runtime) => {
|
|
303
|
+
if (!runtime.OPFS) throw new Error("OPFS backend is unavailable");
|
|
304
|
+
runtime.FS.mkdirTree("/opfs");
|
|
305
|
+
runtime.FS.mount(runtime.OPFS, {}, "/opfs");
|
|
306
|
+
runtime.FS.mkdirTree("/hyperdb-persistent");
|
|
307
|
+
runtime.FS.mount(runtime.OPFS, {}, "/hyperdb-persistent");
|
|
308
|
+
runtime.FS.mkdirTree("/hyperdb-persistent/hyperdb");
|
|
309
|
+
runtime.resolveHyperDBPath = (path) => {
|
|
310
|
+
const parts = [];
|
|
311
|
+
for (const part of path.replace(/^\/+/, "").split("/")) {
|
|
312
|
+
if (!part || part === ".") continue;
|
|
313
|
+
if (part === "..") {
|
|
314
|
+
if (parts.length === 0) throw new Error(`Arrow IPC path is outside the OPFS root: ${path}`);
|
|
315
|
+
parts.pop();
|
|
316
|
+
} else {
|
|
317
|
+
parts.push(part);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return `/opfs/${parts.join("/")}`;
|
|
321
|
+
};
|
|
322
|
+
});
|
|
245
323
|
self.importScripts(resolvedEngineUrl.href);
|
|
246
324
|
}
|
|
247
325
|
})();
|
package/dist/client.d.ts
CHANGED
|
@@ -12,9 +12,17 @@ export declare class HyperDBEngineClient {
|
|
|
12
12
|
ready(): Promise<void>;
|
|
13
13
|
connect(): Promise<WasmResult>;
|
|
14
14
|
disconnect(connection: number): Promise<WasmResult>;
|
|
15
|
+
createDatabase(databaseName: string, persistent: boolean): Promise<WasmResult>;
|
|
16
|
+
openDatabase(databaseName: string): Promise<WasmResult>;
|
|
17
|
+
checkpointDatabase(databaseName: string): Promise<WasmResult>;
|
|
18
|
+
dropDatabase(databaseName: string): Promise<WasmResult>;
|
|
19
|
+
attachDatabase(connection: number, databaseName: string, alias: string): Promise<WasmResult>;
|
|
20
|
+
detachDatabase(connection: number, alias: string): Promise<WasmResult>;
|
|
21
|
+
shutdown(): Promise<WasmResult>;
|
|
15
22
|
startQuery(connection: number, sql: string): Promise<WasmResult>;
|
|
16
|
-
|
|
17
|
-
|
|
23
|
+
insertArrowIPCFromPath(connection: number, path: string, name: string, schema: string | null, create: boolean, internal?: boolean): Promise<WasmResult>;
|
|
24
|
+
createTemporaryFile(bytes: Uint8Array): Promise<WasmResult>;
|
|
25
|
+
removeFile(path: string): Promise<WasmResult>;
|
|
18
26
|
pollQuery(query: number): Promise<WasmResult>;
|
|
19
27
|
cancelQuery(query: number): Promise<WasmResult>;
|
|
20
28
|
releaseQuery(query: number): Promise<WasmResult>;
|