@moltendb-web/core 0.1.0-alpha.21 → 0.1.0-beta.1
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/README.md +1 -3
- package/dist/index.d.ts +50 -51
- package/dist/index.js +173 -135
- package/dist/moltendb-worker.d.ts +1 -0
- package/dist/moltendb-worker.js +9 -12
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -243,7 +243,7 @@ This monorepo contains the following packages:
|
|
|
243
243
|
|
|
244
244
|
## Roadmap
|
|
245
245
|
|
|
246
|
-
- [ ]
|
|
246
|
+
- [ ] ~~**Multi-Tab Sync:** Leader election for multiple tabs to share a single OPFS instance.~~ ✅
|
|
247
247
|
- [ ] **Delta Sync:** Automatic two-way sync with the MoltenDB Rust server.
|
|
248
248
|
- [ ] **Analytics functionality:** Run analytics queries straight in the browser.
|
|
249
249
|
|
|
@@ -256,6 +256,4 @@ MoltenDB is licensed under the **Business Source License 1.1**.
|
|
|
256
256
|
|
|
257
257
|
For commercial licensing or questions: [maximilian.both27@outlook.com](mailto:maximilian.both27@outlook.com)
|
|
258
258
|
|
|
259
|
-
---
|
|
260
259
|
|
|
261
|
-
Created with 🌋 by Maximilian Both. Coming to the world on the Equinox.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,56 +1,55 @@
|
|
|
1
1
|
export interface MoltenDBOptions {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
/** URL or path to moltendb-worker.js. */
|
|
3
|
+
workerUrl?: string | URL;
|
|
4
|
+
/** Enable WebSocket sync with a MoltenDB server. Default: false. */
|
|
5
|
+
syncEnabled?: boolean;
|
|
6
|
+
/** WebSocket server URL. Default: 'wss://localhost:1538/ws'. */
|
|
7
|
+
serverUrl?: string;
|
|
8
|
+
/** Sync batch flush interval in ms. Default: 5000. */
|
|
9
|
+
syncIntervalMs?: number;
|
|
10
|
+
/** JWT token for WebSocket authentication. */
|
|
11
|
+
authToken?: string;
|
|
12
12
|
}
|
|
13
|
-
|
|
14
13
|
export type SyncCallback = (update: {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
event: 'change' | 'delete' | 'drop';
|
|
15
|
+
collection: string;
|
|
16
|
+
key: string;
|
|
17
|
+
new_v: number | null;
|
|
19
18
|
}) => void;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
19
|
+
export declare class MoltenDB {
|
|
20
|
+
readonly dbName: string;
|
|
21
|
+
readonly workerUrl: string | URL;
|
|
22
|
+
worker: Worker | null;
|
|
23
|
+
private messageId;
|
|
24
|
+
private pendingRequests;
|
|
25
|
+
isLeader: boolean;
|
|
26
|
+
private bc;
|
|
27
|
+
private syncEnabled;
|
|
28
|
+
private serverUrl;
|
|
29
|
+
private syncIntervalMs;
|
|
30
|
+
private authToken?;
|
|
31
|
+
private ws;
|
|
32
|
+
private syncCallbacks;
|
|
33
|
+
private syncQueue;
|
|
34
|
+
private syncTimer;
|
|
35
|
+
/** ⚡ Hook to listen to native real-time DB mutations (works on all tabs) */
|
|
36
|
+
onEvent?: (event: any) => void;
|
|
37
|
+
constructor(dbName?: string, options?: MoltenDBOptions);
|
|
38
|
+
init(): Promise<void>;
|
|
39
|
+
private startAsLeader;
|
|
40
|
+
private startAsFollower;
|
|
41
|
+
sendMessage(action: string, payload?: Record<string, unknown>): Promise<any>;
|
|
42
|
+
set(collection: string, key: string, value: Record<string, unknown>, options?: {
|
|
43
|
+
skipSync?: boolean;
|
|
44
|
+
}): Promise<void>;
|
|
45
|
+
get(collection: string, key: string): Promise<unknown>;
|
|
46
|
+
getAll(collection: string): Promise<unknown>;
|
|
47
|
+
delete(collection: string, key: string, options?: {
|
|
48
|
+
skipSync?: boolean;
|
|
49
|
+
}): Promise<void>;
|
|
50
|
+
compact(): Promise<unknown>;
|
|
51
|
+
private startSync;
|
|
52
|
+
onSyncEvent(callback: SyncCallback): void;
|
|
53
|
+
disconnect(): void;
|
|
54
|
+
terminate(): void;
|
|
56
55
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,176 +1,214 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MoltenDB main-thread client.
|
|
3
|
-
*
|
|
4
|
-
* Usage:
|
|
5
|
-
* import { MoltenDB } from 'moltendb-wasm';
|
|
6
|
-
*
|
|
7
|
-
* const db = new MoltenDB('my-db', {
|
|
8
|
-
* // Required: URL or path to the moltendb-worker.js file.
|
|
9
|
-
* // With a bundler: new URL('moltendb-wasm/worker', import.meta.url)
|
|
10
|
-
* // Plain script: '/node_modules/moltendb-wasm/dist/moltendb-worker.js'
|
|
11
|
-
* workerUrl: new URL('moltendb-wasm/worker', import.meta.url),
|
|
12
|
-
* });
|
|
13
|
-
* await db.init();
|
|
14
|
-
*/
|
|
15
1
|
export class MoltenDB {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
2
|
+
dbName;
|
|
3
|
+
workerUrl;
|
|
4
|
+
worker = null;
|
|
5
|
+
messageId = 0;
|
|
6
|
+
pendingRequests = new Map();
|
|
7
|
+
// Multi-tab Sync State
|
|
8
|
+
isLeader = false;
|
|
9
|
+
bc;
|
|
10
|
+
// Server Sync State
|
|
11
|
+
syncEnabled;
|
|
12
|
+
serverUrl;
|
|
13
|
+
syncIntervalMs;
|
|
14
|
+
authToken;
|
|
15
|
+
ws = null;
|
|
16
|
+
syncCallbacks = [];
|
|
17
|
+
syncQueue = [];
|
|
18
|
+
syncTimer = null;
|
|
19
|
+
/** ⚡ Hook to listen to native real-time DB mutations (works on all tabs) */
|
|
20
|
+
onEvent;
|
|
26
21
|
constructor(dbName = 'moltendb', options = {}) {
|
|
27
|
-
this.dbName
|
|
28
|
-
|
|
29
|
-
this.
|
|
30
|
-
this.
|
|
31
|
-
this.
|
|
32
|
-
|
|
33
|
-
this.syncEnabled = options.syncEnabled ?? false;
|
|
34
|
-
this.serverUrl = options.serverUrl ?? 'wss://localhost:3000/ws';
|
|
22
|
+
this.dbName = dbName;
|
|
23
|
+
// Zero-config default worker resolution
|
|
24
|
+
this.workerUrl = options.workerUrl ?? new URL('./moltendb-worker.js', import.meta.url).href;
|
|
25
|
+
this.syncEnabled = options.syncEnabled ?? false;
|
|
26
|
+
this.serverUrl = options.serverUrl ?? 'wss://localhost:3000/ws';
|
|
35
27
|
this.syncIntervalMs = options.syncIntervalMs ?? 5000;
|
|
36
|
-
this.authToken
|
|
37
|
-
|
|
38
|
-
this.ws = null;
|
|
39
|
-
this.syncCallbacks = new Set();
|
|
40
|
-
this.syncQueue = [];
|
|
41
|
-
this.syncTimer = null;
|
|
28
|
+
this.authToken = options.authToken;
|
|
42
29
|
}
|
|
43
|
-
|
|
44
|
-
/** Initialise the Web Worker and open the OPFS database. */
|
|
45
30
|
async init() {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
this.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
31
|
+
this.bc = new BroadcastChannel(`moltendb_channel_${this.dbName}`);
|
|
32
|
+
return new Promise((resolveInit) => {
|
|
33
|
+
// 1. Try to grab the lock immediately (Leader Election)
|
|
34
|
+
navigator.locks.request(`moltendb_lock_${this.dbName}`, { ifAvailable: true }, async (lock) => {
|
|
35
|
+
if (lock) {
|
|
36
|
+
// We got the lock! We are the active DB host.
|
|
37
|
+
await this.startAsLeader();
|
|
38
|
+
resolveInit();
|
|
39
|
+
// Return a promise that never resolves to hold the lock until the tab closes
|
|
40
|
+
return new Promise(() => { });
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
// Lock is taken. We are a proxy follower.
|
|
44
|
+
this.startAsFollower();
|
|
45
|
+
resolveInit();
|
|
46
|
+
// 2. Queue up in the background. If the Leader tab closes, this lock resolves!
|
|
47
|
+
navigator.locks.request(`moltendb_lock_${this.dbName}`, async (fallbackLock) => {
|
|
48
|
+
console.log(`[MoltenDB] Previous leader disconnected. Promoting this tab to Leader.`);
|
|
49
|
+
await this.startAsLeader();
|
|
50
|
+
return new Promise(() => { }); // Hold lock
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
});
|
|
67
54
|
});
|
|
68
55
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
56
|
+
async startAsLeader() {
|
|
57
|
+
this.isLeader = true;
|
|
58
|
+
if (this.worker)
|
|
59
|
+
this.worker.terminate(); // Clean slate if promoted
|
|
60
|
+
this.worker = new Worker(this.workerUrl, { type: 'module', name: `moltendb-${this.dbName}-leader` });
|
|
61
|
+
// Handle messages strictly from our local Worker
|
|
62
|
+
this.worker.onmessage = (e) => {
|
|
63
|
+
const data = e.data;
|
|
64
|
+
if (data.type === 'event') {
|
|
65
|
+
// Trigger local UI hook
|
|
66
|
+
if (this.onEvent)
|
|
67
|
+
this.onEvent(data);
|
|
68
|
+
// Broadcast the native event to all Follower tabs
|
|
69
|
+
this.bc.postMessage(data);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
// Resolve pending local promises
|
|
73
|
+
const req = this.pendingRequests.get(data.id);
|
|
74
|
+
if (req) {
|
|
75
|
+
if (data.error)
|
|
76
|
+
req.reject(new Error(data.error));
|
|
77
|
+
else
|
|
78
|
+
req.resolve(data.result);
|
|
79
|
+
this.pendingRequests.delete(data.id);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
// Initialize the WASM Engine
|
|
83
|
+
await new Promise((resolve, reject) => {
|
|
77
84
|
const id = this.messageId++;
|
|
78
85
|
this.pendingRequests.set(id, { resolve, reject });
|
|
79
|
-
this.worker.postMessage({ id, action,
|
|
86
|
+
this.worker.postMessage({ id, action: 'init', dbName: this.dbName, workerUrl: this.workerUrl });
|
|
80
87
|
});
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
this.ws.onopen = () => {
|
|
90
|
-
if (this.authToken) {
|
|
91
|
-
this.ws.send(JSON.stringify({ action: 'AUTH', token: this.authToken }));
|
|
88
|
+
// Listen to the BroadcastChannel for queries coming from Follower tabs
|
|
89
|
+
this.bc.onmessage = async (e) => {
|
|
90
|
+
const msg = e.data;
|
|
91
|
+
if (msg.type === 'query' && msg.action) {
|
|
92
|
+
try {
|
|
93
|
+
const result = await this.sendMessage(msg.action, msg.payload);
|
|
94
|
+
this.bc.postMessage({ type: 'response', id: msg.id, result });
|
|
92
95
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
this.ws.onclose = () => {
|
|
104
|
-
if (this.syncTimer) clearInterval(this.syncTimer);
|
|
105
|
-
setTimeout(() => this.connectSync(), 3000);
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
this.ws.onerror = (err) => reject(err);
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
handleServerUpdate(update) {
|
|
113
|
-
if (update.event === 'change' && update.collection && update.key) {
|
|
114
|
-
// Re-fetch the updated document from the server and apply locally.
|
|
115
|
-
// (The WS push only carries the key + new _v, not the full document.)
|
|
96
|
+
catch (err) {
|
|
97
|
+
this.bc.postMessage({ type: 'response', id: msg.id, error: err.message });
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
// If backend sync is enabled, only the Leader manages the WebSocket
|
|
102
|
+
if (this.syncEnabled) {
|
|
103
|
+
this.startSync();
|
|
116
104
|
}
|
|
117
|
-
this.syncCallbacks.forEach(cb => cb(update));
|
|
118
105
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
this.
|
|
123
|
-
|
|
106
|
+
startAsFollower() {
|
|
107
|
+
this.isLeader = false;
|
|
108
|
+
// We don't need a worker, we rely on the Leader.
|
|
109
|
+
if (this.worker) {
|
|
110
|
+
this.worker.terminate();
|
|
111
|
+
this.worker = null;
|
|
112
|
+
}
|
|
113
|
+
// Listen to the BroadcastChannel for answers from the Leader
|
|
114
|
+
this.bc.onmessage = (e) => {
|
|
115
|
+
const data = e.data;
|
|
116
|
+
if (data.type === 'event') {
|
|
117
|
+
// Trigger local UI hook as if it happened in this tab
|
|
118
|
+
if (this.onEvent)
|
|
119
|
+
this.onEvent(data);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
if (data.type === 'response') {
|
|
123
|
+
// Resolve our proxied promises
|
|
124
|
+
const req = this.pendingRequests.get(data.id);
|
|
125
|
+
if (req) {
|
|
126
|
+
if (data.error)
|
|
127
|
+
req.reject(new Error(data.error));
|
|
128
|
+
else
|
|
129
|
+
req.resolve(data.result);
|
|
130
|
+
this.pendingRequests.delete(data.id);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
};
|
|
124
134
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
135
|
+
async sendMessage(action, payload) {
|
|
136
|
+
const id = this.messageId++;
|
|
137
|
+
return new Promise((resolve, reject) => {
|
|
138
|
+
this.pendingRequests.set(id, { resolve, reject });
|
|
139
|
+
if (this.isLeader && this.worker) {
|
|
140
|
+
// Direct execution on the local Worker
|
|
141
|
+
this.worker.postMessage({ id, action, ...payload });
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
// Proxy the request to the Leader tab
|
|
145
|
+
this.bc.postMessage({ type: 'query', id, action, payload });
|
|
146
|
+
}
|
|
147
|
+
});
|
|
130
148
|
}
|
|
131
|
-
|
|
132
149
|
// ── Convenience CRUD helpers ──────────────────────────────────────────────
|
|
133
|
-
|
|
134
|
-
/** Insert / upsert one document. */
|
|
135
150
|
async set(collection, key, value, options = {}) {
|
|
136
151
|
await this.sendMessage('set', { collection, data: { [key]: value } });
|
|
137
|
-
if (this.syncEnabled && !options.skipSync) {
|
|
152
|
+
if (this.syncEnabled && !options.skipSync && this.isLeader) {
|
|
138
153
|
this.syncQueue.push({ action: 'set', collection, data: { [key]: value } });
|
|
139
154
|
}
|
|
140
155
|
}
|
|
141
|
-
|
|
142
|
-
/** Fetch a single document by key. */
|
|
143
156
|
get(collection, key) {
|
|
144
157
|
return this.sendMessage('get', { collection, keys: key });
|
|
145
158
|
}
|
|
146
|
-
|
|
147
|
-
/** Fetch all documents in a collection. */
|
|
148
159
|
getAll(collection) {
|
|
149
160
|
return this.sendMessage('get', { collection });
|
|
150
161
|
}
|
|
151
|
-
|
|
152
|
-
/** Delete a document by key. */
|
|
153
162
|
async delete(collection, key, options = {}) {
|
|
154
163
|
await this.sendMessage('delete', { collection, keys: key });
|
|
155
|
-
if (this.syncEnabled && !options.skipSync) {
|
|
164
|
+
if (this.syncEnabled && !options.skipSync && this.isLeader) {
|
|
156
165
|
this.syncQueue.push({ action: 'delete', collection, keys: key });
|
|
157
166
|
}
|
|
158
167
|
}
|
|
159
|
-
|
|
160
|
-
/** Compact the OPFS log file. */
|
|
161
168
|
compact() {
|
|
162
169
|
return this.sendMessage('compact');
|
|
163
170
|
}
|
|
164
|
-
|
|
165
|
-
|
|
171
|
+
// ── Server Sync Implementation (Leader Only) ──────────────────────────────
|
|
172
|
+
startSync() {
|
|
173
|
+
this.ws = new WebSocket(this.serverUrl);
|
|
174
|
+
this.ws.onopen = () => {
|
|
175
|
+
if (this.authToken) {
|
|
176
|
+
this.ws?.send(JSON.stringify({ type: 'auth', token: this.authToken }));
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
this.ws.onmessage = (e) => {
|
|
180
|
+
try {
|
|
181
|
+
const msg = JSON.parse(e.data);
|
|
182
|
+
if (msg.event) {
|
|
183
|
+
for (const cb of this.syncCallbacks)
|
|
184
|
+
cb(msg);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
catch (err) { }
|
|
188
|
+
};
|
|
189
|
+
this.syncTimer = setInterval(async () => {
|
|
190
|
+
if (!this.ws || this.ws.readyState !== WebSocket.OPEN)
|
|
191
|
+
return;
|
|
192
|
+
if (this.syncQueue.length === 0)
|
|
193
|
+
return;
|
|
194
|
+
const batch = this.syncQueue.splice(0, this.syncQueue.length);
|
|
195
|
+
this.ws.send(JSON.stringify({ type: 'batch', operations: batch }));
|
|
196
|
+
}, this.syncIntervalMs);
|
|
197
|
+
}
|
|
198
|
+
onSyncEvent(callback) {
|
|
199
|
+
this.syncCallbacks.push(callback);
|
|
200
|
+
}
|
|
166
201
|
disconnect() {
|
|
167
|
-
if (this.syncTimer)
|
|
168
|
-
|
|
202
|
+
if (this.syncTimer)
|
|
203
|
+
clearInterval(this.syncTimer);
|
|
204
|
+
if (this.ws)
|
|
205
|
+
this.ws.close();
|
|
206
|
+
if (this.bc)
|
|
207
|
+
this.bc.close();
|
|
169
208
|
}
|
|
170
|
-
|
|
171
|
-
/** Terminate the Web Worker (and disconnect sync). */
|
|
172
209
|
terminate() {
|
|
173
210
|
this.disconnect();
|
|
174
|
-
if (this.worker)
|
|
211
|
+
if (this.worker)
|
|
212
|
+
this.worker.terminate();
|
|
175
213
|
}
|
|
176
214
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/moltendb-worker.js
CHANGED
|
@@ -1,39 +1,36 @@
|
|
|
1
1
|
import init, { WorkerDb } from './moltendb.js';
|
|
2
|
-
|
|
3
2
|
let db;
|
|
4
|
-
|
|
5
3
|
self.onmessage = async (e) => {
|
|
6
4
|
const { id, action, ...payload } = e.data;
|
|
7
|
-
|
|
8
5
|
// --- Initialization Phase ---
|
|
9
6
|
if (action === 'init') {
|
|
10
7
|
try {
|
|
11
|
-
await init(
|
|
8
|
+
await init();
|
|
12
9
|
db = await new WorkerDb(payload.dbName);
|
|
13
|
-
|
|
14
10
|
// THE NATIVE FEED: Listen to Rust and broadcast to the main thread
|
|
15
11
|
db.subscribe((eventStr) => {
|
|
16
12
|
try {
|
|
17
13
|
const eventData = JSON.parse(eventStr);
|
|
18
14
|
// Use type: 'event' so the transport knows it's an unsolicited broadcast
|
|
19
15
|
self.postMessage({ type: 'event', ...eventData });
|
|
20
|
-
}
|
|
21
|
-
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
console.error('[MoltenDB Worker] Failed to parse event', err);
|
|
22
19
|
}
|
|
23
20
|
});
|
|
24
|
-
|
|
25
21
|
self.postMessage({ id, result: { status: 'ok' } });
|
|
26
|
-
}
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
27
24
|
self.postMessage({ id, error: String(error) });
|
|
28
25
|
}
|
|
29
26
|
return;
|
|
30
27
|
}
|
|
31
|
-
|
|
32
28
|
// --- Standard Request/Response Phase ---
|
|
33
29
|
try {
|
|
34
30
|
const result = db.handle_message({ action, ...payload });
|
|
35
31
|
self.postMessage({ id, result });
|
|
36
|
-
}
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
37
34
|
self.postMessage({ id, error: String(error) });
|
|
38
35
|
}
|
|
39
|
-
};
|
|
36
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moltendb-web/core",
|
|
3
|
-
"version": "0.1.0-
|
|
3
|
+
"version": "0.1.0-beta.1",
|
|
4
4
|
"description": "MoltenDB WASM runtime — the database engine, Web Worker, and main-thread client in one package.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Maximilian Both <maximilian.both27@outlook.com>",
|
|
@@ -25,6 +25,11 @@
|
|
|
25
25
|
},
|
|
26
26
|
"main": "./dist/index.js",
|
|
27
27
|
"types": "./dist/index.d.ts",
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsc",
|
|
30
|
+
"dev": "tsc --watch",
|
|
31
|
+
"typecheck": "tsc --noEmit"
|
|
32
|
+
},
|
|
28
33
|
"devDependencies": {
|
|
29
34
|
"typescript": "^6.0.1-rc"
|
|
30
35
|
},
|
|
@@ -38,4 +43,4 @@
|
|
|
38
43
|
"indexeddb",
|
|
39
44
|
"embedded"
|
|
40
45
|
]
|
|
41
|
-
}
|
|
46
|
+
}
|