@lix-js/sdk 0.9.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -12
- package/dist/binding-types.d.ts +7 -4
- package/dist/binding.browser.js +1 -1
- package/dist/binding.node.js +7 -4
- package/dist/bundled-plugins/plugin_csv.lixplugin +0 -0
- package/dist/bundled-plugins/plugin_markdown.lixplugin +0 -0
- package/dist/bundled-plugins.js +4 -4
- package/dist/client-state.d.ts +16 -3
- package/dist/client-state.js +137 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/lix.d.ts +7 -4
- package/dist/lix.js +16 -2
- package/dist/open-lix.d.ts +1 -5
- package/dist/open-lix.js +12 -33
- package/dist/remote/client.d.ts +1 -0
- package/dist/remote/client.js +156 -7
- package/dist/remote/protocol.d.ts +19 -1
- package/dist/remote/protocol.js +20 -3
- package/dist/result.d.ts +2 -1
- package/dist/result.js +12 -0
- package/dist/types.d.ts +22 -4
- package/dist/wasm/lix_js_sdk.d.ts +8 -2
- package/dist/wasm/lix_js_sdk.js +28 -7
- package/dist/wasm/lix_js_sdk_bg.wasm +0 -0
- package/dist/wasm/lix_js_sdk_bg.wasm.d.ts +5 -2
- package/dist/worker/client.js +42 -1
- package/dist/worker/factory.browser.d.ts +2 -0
- package/dist/worker/factory.browser.js +2 -0
- package/dist/worker/factory.node.d.ts +2 -0
- package/dist/worker/factory.node.js +5 -0
- package/dist/worker/host.js +6 -0
- package/dist/worker/protocol.d.ts +6 -0
- package/package.json +5 -5
- package/dist/bundled-plugins/plugin_csv_v2.lixplugin +0 -0
- package/dist/bundled-plugins/plugin_markdown_incremental_v2.lixplugin +0 -0
package/dist/remote/client.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { decodeExecuteResult, decodeHandshake, decodeObserveEvent, encodeWireValue, errorFromResponseBody, protocolError, record, REMOTE_PROTOCOL_PATH, remoteError, } from "./protocol.js";
|
|
1
|
+
import { decodeExecuteBatchResult, decodeExecuteResult, decodeHandshake, decodeObserveEvent, encodeWireValue, errorFromResponseBody, protocolError, record, REMOTE_PROTOCOL_PATH, remoteError, } from "./protocol.js";
|
|
2
2
|
import { readSseEvents } from "./sse.js";
|
|
3
3
|
const OBSERVE_RETRY_BASE_MS = 100;
|
|
4
4
|
const OBSERVE_RETRY_MAX_MS = 5_000;
|
|
5
5
|
const REMOTE_SESSION_HEADER = "Lix-Session-Id";
|
|
6
|
+
const REMOTE_TRANSACTION_HEADER = "Lix-Transaction-Id";
|
|
6
7
|
const IDEMPOTENCY_KEY_HEADER = "Idempotency-Key";
|
|
7
8
|
const REQUEST_BLOB_DELTA_MIN_BYTES = 32 * 1024;
|
|
8
9
|
const REQUEST_BLOB_DELTA_MIN_WIRE_RATIO = 0.9;
|
|
@@ -31,10 +32,12 @@ class RemoteLixBinding {
|
|
|
31
32
|
#fetch;
|
|
32
33
|
#headers;
|
|
33
34
|
#initialActiveBranchId;
|
|
35
|
+
#initialActiveAccountId;
|
|
34
36
|
#observationHub;
|
|
35
37
|
#requestBlobBases = new Map();
|
|
36
38
|
#sessionId;
|
|
37
39
|
#activeBranchId;
|
|
40
|
+
#activeAccountId;
|
|
38
41
|
#requestBlobBaseBytes = 0;
|
|
39
42
|
#acceptingOperations = true;
|
|
40
43
|
#operationQueue = Promise.resolve();
|
|
@@ -63,17 +66,29 @@ class RemoteLixBinding {
|
|
|
63
66
|
throw new TypeError("initialActiveBranchId must be a non-empty string");
|
|
64
67
|
}
|
|
65
68
|
this.#initialActiveBranchId = clientOptions.initialActiveBranchId;
|
|
69
|
+
if (clientOptions.initialActiveAccountId !== undefined &&
|
|
70
|
+
clientOptions.initialActiveAccountId.length === 0) {
|
|
71
|
+
throw new TypeError("initialActiveAccountId must be a non-empty string");
|
|
72
|
+
}
|
|
73
|
+
this.#initialActiveAccountId = clientOptions.initialActiveAccountId;
|
|
66
74
|
this.#observationHub = new RemoteObservationHub({
|
|
67
75
|
openStream: (subscriptions, signal) => this.#requestObserveStream(subscriptions, signal),
|
|
76
|
+
refreshObservation: (subscription) => this.#refreshObservation(subscription),
|
|
68
77
|
});
|
|
69
78
|
}
|
|
70
79
|
async open() {
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
80
|
+
const query = new URLSearchParams();
|
|
81
|
+
if (this.#initialActiveBranchId !== undefined) {
|
|
82
|
+
query.set("activeBranchId", this.#initialActiveBranchId);
|
|
83
|
+
}
|
|
84
|
+
if (this.#initialActiveAccountId !== undefined) {
|
|
85
|
+
query.set("activeAccountId", this.#initialActiveAccountId);
|
|
86
|
+
}
|
|
87
|
+
const path = query.size === 0 ? "" : `?${query}`;
|
|
74
88
|
const handshake = decodeHandshake(await this.#requestJson(path, { method: "GET" }));
|
|
75
89
|
this.#sessionId = handshake.sessionId;
|
|
76
90
|
this.#activeBranchId = handshake.activeBranchId;
|
|
91
|
+
this.#activeAccountId = handshake.activeAccountId;
|
|
77
92
|
}
|
|
78
93
|
async execute(sql, params, options) {
|
|
79
94
|
this.#assertOpen();
|
|
@@ -105,10 +120,12 @@ class RemoteLixBinding {
|
|
|
105
120
|
const snapshot = statements.map((statement) => ({
|
|
106
121
|
sql: statement.sql,
|
|
107
122
|
params: snapshotParams(statement.params),
|
|
123
|
+
...(statement.label === undefined ? {} : { label: statement.label }),
|
|
108
124
|
}));
|
|
109
125
|
return this.#enqueue(async () => {
|
|
110
126
|
const preparedStatements = await Promise.all(snapshot.map(async (statement, statementIndex) => ({
|
|
111
127
|
sql: statement.sql,
|
|
128
|
+
label: statement.label,
|
|
112
129
|
prepared: await this.#prepareParams(statement.params, (paramIndex) => requestBlobSlot("batch", statement.sql, paramIndex, statementIndex)),
|
|
113
130
|
})));
|
|
114
131
|
const cacheBlobs = preparedStatements.some((statement) => statement.prepared.cacheBlobs);
|
|
@@ -119,6 +136,9 @@ class RemoteLixBinding {
|
|
|
119
136
|
body: JSON.stringify({
|
|
120
137
|
statements: preparedStatements.map((statement) => ({
|
|
121
138
|
sql: statement.sql,
|
|
139
|
+
...(statement.label === undefined
|
|
140
|
+
? {}
|
|
141
|
+
: { label: statement.label }),
|
|
122
142
|
params: full
|
|
123
143
|
? statement.prepared.fullParams()
|
|
124
144
|
: statement.prepared.params,
|
|
@@ -131,7 +151,7 @@ class RemoteLixBinding {
|
|
|
131
151
|
if (!Array.isArray(value)) {
|
|
132
152
|
throw protocolError("execute batch response must be an array");
|
|
133
153
|
}
|
|
134
|
-
const results = value.map(
|
|
154
|
+
const results = value.map(decodeExecuteBatchResult);
|
|
135
155
|
this.#commitRequestBlobBases(preparedStatements.flatMap((statement) => statement.prepared.cacheUpdates));
|
|
136
156
|
return results;
|
|
137
157
|
});
|
|
@@ -142,7 +162,62 @@ class RemoteLixBinding {
|
|
|
142
162
|
}
|
|
143
163
|
async beginTransaction() {
|
|
144
164
|
this.#assertOpen();
|
|
145
|
-
|
|
165
|
+
return this.#enqueue(async () => {
|
|
166
|
+
const begun = record(await this.#requestJson("transaction/begin", { method: "POST" }), "begin transaction response");
|
|
167
|
+
if (typeof begun.transactionId !== "string") {
|
|
168
|
+
throw protocolError("begin transaction response.transactionId must be a string");
|
|
169
|
+
}
|
|
170
|
+
const transactionId = begun.transactionId;
|
|
171
|
+
let active = true;
|
|
172
|
+
const assertActive = () => {
|
|
173
|
+
if (!active) {
|
|
174
|
+
throw remoteError("LIX_INVALID_TRANSACTION_STATE", "Lix transaction is closed");
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
return {
|
|
178
|
+
execute: async (sql, params, options) => {
|
|
179
|
+
assertActive();
|
|
180
|
+
const snapshot = snapshotParams(params);
|
|
181
|
+
const requestOptions = remoteExecuteOptions(options);
|
|
182
|
+
return this.#enqueue(async () => {
|
|
183
|
+
const value = await this.#requestJson("transaction/execute", {
|
|
184
|
+
method: "POST",
|
|
185
|
+
headers: { [REMOTE_TRANSACTION_HEADER]: transactionId },
|
|
186
|
+
body: JSON.stringify({
|
|
187
|
+
sql,
|
|
188
|
+
params: snapshot.map(encodeWireValue),
|
|
189
|
+
...(requestOptions === undefined
|
|
190
|
+
? {}
|
|
191
|
+
: { options: requestOptions }),
|
|
192
|
+
}),
|
|
193
|
+
});
|
|
194
|
+
return decodeExecuteResult(value);
|
|
195
|
+
});
|
|
196
|
+
},
|
|
197
|
+
commit: async () => {
|
|
198
|
+
assertActive();
|
|
199
|
+
return this.#enqueue(async () => {
|
|
200
|
+
assertActive();
|
|
201
|
+
await this.#requestJson("transaction/commit", {
|
|
202
|
+
method: "POST",
|
|
203
|
+
headers: { [REMOTE_TRANSACTION_HEADER]: transactionId },
|
|
204
|
+
}, "empty");
|
|
205
|
+
active = false;
|
|
206
|
+
});
|
|
207
|
+
},
|
|
208
|
+
rollback: async () => {
|
|
209
|
+
assertActive();
|
|
210
|
+
return this.#enqueue(async () => {
|
|
211
|
+
assertActive();
|
|
212
|
+
await this.#requestJson("transaction/rollback", {
|
|
213
|
+
method: "POST",
|
|
214
|
+
headers: { [REMOTE_TRANSACTION_HEADER]: transactionId },
|
|
215
|
+
}, "empty");
|
|
216
|
+
active = false;
|
|
217
|
+
});
|
|
218
|
+
},
|
|
219
|
+
};
|
|
220
|
+
});
|
|
146
221
|
}
|
|
147
222
|
async activeBranchId() {
|
|
148
223
|
this.#assertOpen();
|
|
@@ -157,6 +232,19 @@ class RemoteLixBinding {
|
|
|
157
232
|
return this.#activeBranchId;
|
|
158
233
|
});
|
|
159
234
|
}
|
|
235
|
+
async activeAccountId() {
|
|
236
|
+
this.#assertOpen();
|
|
237
|
+
return this.#enqueue(async () => {
|
|
238
|
+
if (this.#activeAccountId === undefined) {
|
|
239
|
+
const handshake = decodeHandshake(await this.#requestJson("", { method: "GET" }));
|
|
240
|
+
if (handshake.sessionId !== this.#sessionId) {
|
|
241
|
+
throw protocolError("remote handshake changed sessionId");
|
|
242
|
+
}
|
|
243
|
+
this.#activeAccountId = handshake.activeAccountId;
|
|
244
|
+
}
|
|
245
|
+
return this.#activeAccountId;
|
|
246
|
+
});
|
|
247
|
+
}
|
|
160
248
|
async createBranch(options) {
|
|
161
249
|
this.#assertOpen();
|
|
162
250
|
return this.#enqueue(async () => {
|
|
@@ -189,6 +277,38 @@ class RemoteLixBinding {
|
|
|
189
277
|
return { commitId: value.commitId };
|
|
190
278
|
});
|
|
191
279
|
}
|
|
280
|
+
async undo() {
|
|
281
|
+
this.#assertOpen();
|
|
282
|
+
return this.#enqueue(async () => {
|
|
283
|
+
const value = record(await this.#requestJson("undo", { method: "POST" }), "undo response");
|
|
284
|
+
if (typeof value.branchId !== "string" ||
|
|
285
|
+
typeof value.targetCommitId !== "string" ||
|
|
286
|
+
typeof value.inverseCommitId !== "string") {
|
|
287
|
+
throw protocolError("undo response is invalid");
|
|
288
|
+
}
|
|
289
|
+
return {
|
|
290
|
+
branchId: value.branchId,
|
|
291
|
+
targetCommitId: value.targetCommitId,
|
|
292
|
+
inverseCommitId: value.inverseCommitId,
|
|
293
|
+
};
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
async redo() {
|
|
297
|
+
this.#assertOpen();
|
|
298
|
+
return this.#enqueue(async () => {
|
|
299
|
+
const value = record(await this.#requestJson("redo", { method: "POST" }), "redo response");
|
|
300
|
+
if (typeof value.branchId !== "string" ||
|
|
301
|
+
typeof value.targetCommitId !== "string" ||
|
|
302
|
+
typeof value.replayCommitId !== "string") {
|
|
303
|
+
throw protocolError("redo response is invalid");
|
|
304
|
+
}
|
|
305
|
+
return {
|
|
306
|
+
branchId: value.branchId,
|
|
307
|
+
targetCommitId: value.targetCommitId,
|
|
308
|
+
replayCommitId: value.replayCommitId,
|
|
309
|
+
};
|
|
310
|
+
});
|
|
311
|
+
}
|
|
192
312
|
async switchBranch(options) {
|
|
193
313
|
this.#assertOpen();
|
|
194
314
|
return this.#enqueue(async () => {
|
|
@@ -328,6 +448,18 @@ class RemoteLixBinding {
|
|
|
328
448
|
throw remoteError("LIX_REMOTE_UNAVAILABLE", "The remote Lix observation stream is unavailable", { details: { cause: errorMessage(cause) } });
|
|
329
449
|
}
|
|
330
450
|
}
|
|
451
|
+
async #refreshObservation(subscription) {
|
|
452
|
+
return this.#enqueue(async () => {
|
|
453
|
+
const value = await this.#requestJson("execute", {
|
|
454
|
+
method: "POST",
|
|
455
|
+
body: JSON.stringify({
|
|
456
|
+
sql: subscription.sql,
|
|
457
|
+
params: subscription.params,
|
|
458
|
+
}),
|
|
459
|
+
});
|
|
460
|
+
return decodeExecuteResult(value);
|
|
461
|
+
});
|
|
462
|
+
}
|
|
331
463
|
async #prepareParams(params, slot) {
|
|
332
464
|
const prepared = await Promise.all(params.map(async (param, index) => {
|
|
333
465
|
if (param.kind !== "blob" ||
|
|
@@ -547,6 +679,7 @@ function copyArrayBuffer(bytes) {
|
|
|
547
679
|
}
|
|
548
680
|
class RemoteObservationHub {
|
|
549
681
|
#openStream;
|
|
682
|
+
#refreshObservation;
|
|
550
683
|
#observations = new Map();
|
|
551
684
|
#nextObservationId = 0;
|
|
552
685
|
#controller;
|
|
@@ -558,6 +691,7 @@ class RemoteObservationHub {
|
|
|
558
691
|
#closed = false;
|
|
559
692
|
constructor(options) {
|
|
560
693
|
this.#openStream = options.openStream;
|
|
694
|
+
this.#refreshObservation = options.refreshObservation;
|
|
561
695
|
}
|
|
562
696
|
observe(sql, params) {
|
|
563
697
|
const id = `observe-${++this.#nextObservationId}`;
|
|
@@ -629,6 +763,7 @@ class RemoteObservationHub {
|
|
|
629
763
|
if (!this.#isCurrent(generation, controller))
|
|
630
764
|
return;
|
|
631
765
|
streamOpened = true;
|
|
766
|
+
const initialSubscriptions = new Set(this.#observations.keys());
|
|
632
767
|
if (!response.ok) {
|
|
633
768
|
if (isRetryableObserveStatus(response.status)) {
|
|
634
769
|
void response.body?.cancel();
|
|
@@ -667,7 +802,21 @@ class RemoteObservationHub {
|
|
|
667
802
|
const transportDelta = payload.delta !== undefined;
|
|
668
803
|
const event = decodeObserveEvent(payload, transportBases.get(subscriptionId));
|
|
669
804
|
transportBases.set(subscriptionId, event);
|
|
670
|
-
|
|
805
|
+
if (initialSubscriptions.delete(subscriptionId)) {
|
|
806
|
+
// The first frame after opening (including a reconnect) is a
|
|
807
|
+
// synchronization point, not an authoritative snapshot. The
|
|
808
|
+
// remote runtime may have observed the stream before its
|
|
809
|
+
// external-storage watcher caught up. Reconcile through the
|
|
810
|
+
// normal execute endpoint before publishing it to consumers.
|
|
811
|
+
const rows = await this.#refreshObservation(observation.request());
|
|
812
|
+
observation.accept({
|
|
813
|
+
...event,
|
|
814
|
+
rows,
|
|
815
|
+
}, false);
|
|
816
|
+
}
|
|
817
|
+
else {
|
|
818
|
+
observation.accept(event, transportDelta);
|
|
819
|
+
}
|
|
671
820
|
this.#retryAttempt = 0;
|
|
672
821
|
}
|
|
673
822
|
catch (error) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { BindingExecuteResult, BindingObserveEvent } from "../binding-types.js";
|
|
2
2
|
import type { NativeLixValue } from "../value.js";
|
|
3
|
-
export declare const REMOTE_PROTOCOL_VERSION =
|
|
3
|
+
export declare const REMOTE_PROTOCOL_VERSION = 2;
|
|
4
4
|
export declare const REMOTE_PROTOCOL_PATH = "/lix/v1/";
|
|
5
5
|
export type WireValue = {
|
|
6
6
|
kind: "null";
|
|
@@ -36,10 +36,12 @@ export type WireRequestValue = WireValue | WireRequestBlobSplice;
|
|
|
36
36
|
export type RemoteHandshake = {
|
|
37
37
|
protocolVersion: number;
|
|
38
38
|
activeBranchId: string;
|
|
39
|
+
activeAccountId: string;
|
|
39
40
|
sessionId: string;
|
|
40
41
|
};
|
|
41
42
|
export type RemoteHandshakeRequest = {
|
|
42
43
|
activeBranchId?: string;
|
|
44
|
+
activeAccountId?: string;
|
|
43
45
|
};
|
|
44
46
|
export type RemoteExecuteRequest = {
|
|
45
47
|
sql: string;
|
|
@@ -53,6 +55,7 @@ export type RemoteExecuteBatchRequest = {
|
|
|
53
55
|
statements: Array<{
|
|
54
56
|
sql: string;
|
|
55
57
|
params: WireRequestValue[];
|
|
58
|
+
label?: string;
|
|
56
59
|
}>;
|
|
57
60
|
options?: {
|
|
58
61
|
originKey?: string;
|
|
@@ -69,6 +72,10 @@ export type RemoteExecuteResponse = {
|
|
|
69
72
|
hint?: string;
|
|
70
73
|
}>;
|
|
71
74
|
};
|
|
75
|
+
export type RemoteExecuteBatchResponse = RemoteExecuteResponse & {
|
|
76
|
+
statementIndex: number;
|
|
77
|
+
label?: string;
|
|
78
|
+
};
|
|
72
79
|
export type RemoteObserveRequest = {
|
|
73
80
|
sql: string;
|
|
74
81
|
params: WireValue[];
|
|
@@ -122,6 +129,16 @@ export type RemoteCreateBranchResponse = {
|
|
|
122
129
|
export type RemoteCreateCheckpointResponse = {
|
|
123
130
|
commitId: string;
|
|
124
131
|
};
|
|
132
|
+
export type RemoteUndoResponse = {
|
|
133
|
+
branchId: string;
|
|
134
|
+
targetCommitId: string;
|
|
135
|
+
inverseCommitId: string;
|
|
136
|
+
};
|
|
137
|
+
export type RemoteRedoResponse = {
|
|
138
|
+
branchId: string;
|
|
139
|
+
targetCommitId: string;
|
|
140
|
+
replayCommitId: string;
|
|
141
|
+
};
|
|
125
142
|
export type RemoteSwitchBranchRequest = {
|
|
126
143
|
branchId: string;
|
|
127
144
|
};
|
|
@@ -144,6 +161,7 @@ export type RemoteMultiplexObserveErrorEvent = RemoteObserveErrorEvent & {
|
|
|
144
161
|
};
|
|
145
162
|
export declare function encodeWireValue(value: NativeLixValue): WireValue;
|
|
146
163
|
export declare function decodeExecuteResult(value: unknown): BindingExecuteResult;
|
|
164
|
+
export declare function decodeExecuteBatchResult(value: unknown): BindingExecuteResult;
|
|
147
165
|
export declare function decodeHandshake(value: unknown): RemoteHandshake;
|
|
148
166
|
export declare function decodeObserveEvent(value: unknown, base?: BindingObserveEvent): BindingObserveEvent;
|
|
149
167
|
export declare function remoteError(code: string, message: string, options?: {
|
package/dist/remote/protocol.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const REMOTE_PROTOCOL_VERSION =
|
|
1
|
+
export const REMOTE_PROTOCOL_VERSION = 2;
|
|
2
2
|
export const REMOTE_PROTOCOL_PATH = "/lix/v1/";
|
|
3
3
|
export function encodeWireValue(value) {
|
|
4
4
|
switch (value.kind) {
|
|
@@ -57,6 +57,18 @@ export function decodeExecuteResult(value) {
|
|
|
57
57
|
});
|
|
58
58
|
return { columns, rows, rowsAffected: result.rowsAffected, notices };
|
|
59
59
|
}
|
|
60
|
+
export function decodeExecuteBatchResult(value) {
|
|
61
|
+
const result = record(value, "execute batch result");
|
|
62
|
+
const statementIndex = nonNegativeSafeInteger(result.statementIndex, "execute batch result statementIndex");
|
|
63
|
+
if (result.label !== undefined && typeof result.label !== "string") {
|
|
64
|
+
throw protocolError("execute batch result label must be a string when present");
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
...decodeExecuteResult(value),
|
|
68
|
+
statementIndex,
|
|
69
|
+
...(result.label === undefined ? {} : { label: result.label }),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
60
72
|
export function decodeHandshake(value) {
|
|
61
73
|
const handshake = record(value, "remote handshake");
|
|
62
74
|
if (handshake.protocolVersion !== REMOTE_PROTOCOL_VERSION) {
|
|
@@ -66,6 +78,10 @@ export function decodeHandshake(value) {
|
|
|
66
78
|
handshake.activeBranchId.length === 0) {
|
|
67
79
|
throw protocolError("remote handshake requires activeBranchId");
|
|
68
80
|
}
|
|
81
|
+
if (typeof handshake.activeAccountId !== "string" ||
|
|
82
|
+
handshake.activeAccountId.length === 0) {
|
|
83
|
+
throw protocolError("remote handshake requires activeAccountId");
|
|
84
|
+
}
|
|
69
85
|
if (typeof handshake.sessionId !== "string" ||
|
|
70
86
|
!/^[\x21-\x7e]{1,256}$/.test(handshake.sessionId)) {
|
|
71
87
|
throw protocolError("remote handshake requires a valid sessionId");
|
|
@@ -73,6 +89,7 @@ export function decodeHandshake(value) {
|
|
|
73
89
|
return {
|
|
74
90
|
protocolVersion: REMOTE_PROTOCOL_VERSION,
|
|
75
91
|
activeBranchId: handshake.activeBranchId,
|
|
92
|
+
activeAccountId: handshake.activeAccountId,
|
|
76
93
|
sessionId: handshake.sessionId,
|
|
77
94
|
};
|
|
78
95
|
}
|
|
@@ -127,7 +144,7 @@ function applyObserveBlobDelta(delta, sequence, base) {
|
|
|
127
144
|
}
|
|
128
145
|
const baseValue = base.rows.rows[0]?.[0];
|
|
129
146
|
if (base.rows.columns.length !== 1 ||
|
|
130
|
-
base.rows.columns[0] !== "
|
|
147
|
+
base.rows.columns[0] !== "content" ||
|
|
131
148
|
base.rows.rows.length !== 1 ||
|
|
132
149
|
base.rows.rows[0]?.length !== 1 ||
|
|
133
150
|
base.rows.rowsAffected !== 0 ||
|
|
@@ -154,7 +171,7 @@ function applyObserveBlobDelta(delta, sequence, base) {
|
|
|
154
171
|
blob.set(insert, prefixBytes);
|
|
155
172
|
blob.set(baseValue.blob.subarray(baseValue.blob.byteLength - suffixBytes), prefixBytes + insert.byteLength);
|
|
156
173
|
return {
|
|
157
|
-
columns: ["
|
|
174
|
+
columns: ["content"],
|
|
158
175
|
rows: [[{ kind: "blob", value: null, blob }]],
|
|
159
176
|
rowsAffected: 0,
|
|
160
177
|
notices: [],
|
package/dist/result.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type NativeLixValue, Value } from "./value.js";
|
|
2
|
-
import type { ExecuteResult, LixValue } from "./types.js";
|
|
2
|
+
import type { ExecuteBatchResult, ExecuteResult, LixValue } from "./types.js";
|
|
3
3
|
export declare class Row {
|
|
4
4
|
private readonly columns;
|
|
5
5
|
private readonly values;
|
|
@@ -14,5 +14,6 @@ type NativeExecuteResult = Omit<ExecuteResult, "rows"> & {
|
|
|
14
14
|
rows: NativeLixValue[][];
|
|
15
15
|
};
|
|
16
16
|
export declare function wrapExecuteResult(result: NativeExecuteResult): ExecuteResult;
|
|
17
|
+
export declare function wrapExecuteBatchResult(result: NativeExecuteResult): ExecuteBatchResult;
|
|
17
18
|
export declare function normalizeOptionals<T>(value: T): T;
|
|
18
19
|
export {};
|
package/dist/result.js
CHANGED
|
@@ -36,6 +36,18 @@ export function wrapExecuteResult(result) {
|
|
|
36
36
|
rows: result.rows.map((row) => Row.fromRaw(result.columns, row.map(fromNativeValue))),
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
|
+
export function wrapExecuteBatchResult(result) {
|
|
40
|
+
const statementIndex = result.statementIndex;
|
|
41
|
+
if (typeof statementIndex !== "number" ||
|
|
42
|
+
!Number.isSafeInteger(statementIndex) ||
|
|
43
|
+
statementIndex < 0) {
|
|
44
|
+
throw new Error("executeBatch result is missing a valid statementIndex");
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
...wrapExecuteResult(result),
|
|
48
|
+
statementIndex,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
39
51
|
export function normalizeOptionals(value) {
|
|
40
52
|
if (Array.isArray(value))
|
|
41
53
|
return value.map(normalizeOptionals);
|
package/dist/types.d.ts
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
export type SQLiteOptions = {
|
|
2
|
-
path: string;
|
|
3
|
-
};
|
|
4
1
|
export type LocalFilesystemOptions = {
|
|
5
2
|
path: string;
|
|
6
3
|
lixDir?: string;
|
|
@@ -36,7 +33,7 @@ export interface LixSnapshotStorage {
|
|
|
36
33
|
save(namespace: string, snapshot: Uint8Array): Promise<void>;
|
|
37
34
|
}
|
|
38
35
|
export type OpenLixOptions = {
|
|
39
|
-
storage?: import("./open-lix.js").
|
|
36
|
+
storage?: import("./open-lix.js").LocalFilesystem | LixSnapshotStorage;
|
|
40
37
|
server?: never;
|
|
41
38
|
telemetry?: LixTelemetryOptions;
|
|
42
39
|
} | {
|
|
@@ -86,6 +83,7 @@ export type ExecuteOptions = {
|
|
|
86
83
|
export type LixBatchStatement = {
|
|
87
84
|
sql: string;
|
|
88
85
|
params?: readonly SqlParam[];
|
|
86
|
+
label?: string;
|
|
89
87
|
};
|
|
90
88
|
export type LixBatchOptions = {
|
|
91
89
|
originKey?: string;
|
|
@@ -93,6 +91,8 @@ export type LixBatchOptions = {
|
|
|
93
91
|
idempotencyKey?: string;
|
|
94
92
|
};
|
|
95
93
|
export type ExecuteResult = {
|
|
94
|
+
statementIndex?: number;
|
|
95
|
+
label?: string;
|
|
96
96
|
columns: string[];
|
|
97
97
|
rows: RowLike[];
|
|
98
98
|
rowsAffected: number;
|
|
@@ -102,9 +102,17 @@ export type ExecuteResult = {
|
|
|
102
102
|
hint?: string;
|
|
103
103
|
}>;
|
|
104
104
|
};
|
|
105
|
+
export type ExecuteBatchResult = ExecuteResult & {
|
|
106
|
+
statementIndex: number;
|
|
107
|
+
};
|
|
105
108
|
export type ObserveEvent = {
|
|
106
109
|
sequence: number;
|
|
107
110
|
mutationSequence: number;
|
|
111
|
+
/**
|
|
112
|
+
* The current result of the observed query. Remote observations reconcile
|
|
113
|
+
* the first frame of every stream through execute before publishing it, so
|
|
114
|
+
* reconnects cannot expose a stale server snapshot to consumers.
|
|
115
|
+
*/
|
|
108
116
|
result: ExecuteResult;
|
|
109
117
|
};
|
|
110
118
|
export type RowLike = {
|
|
@@ -132,6 +140,16 @@ export type CreateBranchReceipt = {
|
|
|
132
140
|
export type CreateCheckpointReceipt = {
|
|
133
141
|
commitId: string;
|
|
134
142
|
};
|
|
143
|
+
export type UndoReceipt = {
|
|
144
|
+
branchId: string;
|
|
145
|
+
targetCommitId: string;
|
|
146
|
+
inverseCommitId: string;
|
|
147
|
+
};
|
|
148
|
+
export type RedoReceipt = {
|
|
149
|
+
branchId: string;
|
|
150
|
+
targetCommitId: string;
|
|
151
|
+
replayCommitId: string;
|
|
152
|
+
};
|
|
135
153
|
export type SwitchBranchOptions = {
|
|
136
154
|
branchId: string;
|
|
137
155
|
};
|
|
@@ -5,6 +5,7 @@ export class WasmLix {
|
|
|
5
5
|
private constructor();
|
|
6
6
|
free(): void;
|
|
7
7
|
[Symbol.dispose](): void;
|
|
8
|
+
activeAccountId(): Promise<string>;
|
|
8
9
|
activeBranchId(): Promise<string>;
|
|
9
10
|
beginTransaction(): Promise<WasmLixTransaction>;
|
|
10
11
|
clientStateDelete(key: string): Promise<void>;
|
|
@@ -20,7 +21,9 @@ export class WasmLix {
|
|
|
20
21
|
mergeBranch(options: any): Promise<any>;
|
|
21
22
|
mergeBranchPreview(options: any): Promise<any>;
|
|
22
23
|
observe(sql: string, params: any): Promise<WasmObserveEvents>;
|
|
24
|
+
redo(): Promise<any>;
|
|
23
25
|
switchBranch(options: any): Promise<any>;
|
|
26
|
+
undo(): Promise<any>;
|
|
24
27
|
}
|
|
25
28
|
|
|
26
29
|
export class WasmLixTransaction {
|
|
@@ -56,6 +59,7 @@ export interface InitOutput {
|
|
|
56
59
|
readonly openMemory: (a: number) => number;
|
|
57
60
|
readonly openMemoryFromSnapshot: (a: number, b: number, c: number) => number;
|
|
58
61
|
readonly parseSqlScript: (a: number, b: number, c: number, d: number) => void;
|
|
62
|
+
readonly wasmlix_activeAccountId: (a: number) => number;
|
|
59
63
|
readonly wasmlix_activeBranchId: (a: number) => number;
|
|
60
64
|
readonly wasmlix_beginTransaction: (a: number) => number;
|
|
61
65
|
readonly wasmlix_clientStateDelete: (a: number, b: number, c: number) => number;
|
|
@@ -71,14 +75,16 @@ export interface InitOutput {
|
|
|
71
75
|
readonly wasmlix_mergeBranch: (a: number, b: number) => number;
|
|
72
76
|
readonly wasmlix_mergeBranchPreview: (a: number, b: number) => number;
|
|
73
77
|
readonly wasmlix_observe: (a: number, b: number, c: number, d: number) => number;
|
|
78
|
+
readonly wasmlix_redo: (a: number) => number;
|
|
74
79
|
readonly wasmlix_switchBranch: (a: number, b: number) => number;
|
|
80
|
+
readonly wasmlix_undo: (a: number) => number;
|
|
75
81
|
readonly wasmlixtransaction_commit: (a: number) => number;
|
|
76
82
|
readonly wasmlixtransaction_execute: (a: number, b: number, c: number, d: number, e: number) => number;
|
|
77
83
|
readonly wasmlixtransaction_rollback: (a: number) => number;
|
|
78
84
|
readonly wasmobserveevents_close: (a: number) => void;
|
|
79
85
|
readonly wasmobserveevents_next: (a: number) => number;
|
|
80
|
-
readonly
|
|
81
|
-
readonly
|
|
86
|
+
readonly __wasm_bindgen_func_elem_122229: (a: number, b: number, c: number, d: number) => void;
|
|
87
|
+
readonly __wasm_bindgen_func_elem_122231: (a: number, b: number, c: number, d: number) => void;
|
|
82
88
|
readonly __wbindgen_export: (a: number, b: number) => number;
|
|
83
89
|
readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
|
|
84
90
|
readonly __wbindgen_export3: (a: number) => void;
|
package/dist/wasm/lix_js_sdk.js
CHANGED
|
@@ -17,6 +17,13 @@ export class WasmLix {
|
|
|
17
17
|
const ptr = this.__destroy_into_raw();
|
|
18
18
|
wasm.__wbg_wasmlix_free(ptr, 0);
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* @returns {Promise<string>}
|
|
22
|
+
*/
|
|
23
|
+
activeAccountId() {
|
|
24
|
+
const ret = wasm.wasmlix_activeAccountId(this.__wbg_ptr);
|
|
25
|
+
return takeObject(ret);
|
|
26
|
+
}
|
|
20
27
|
/**
|
|
21
28
|
* @returns {Promise<string>}
|
|
22
29
|
*/
|
|
@@ -146,6 +153,13 @@ export class WasmLix {
|
|
|
146
153
|
const ret = wasm.wasmlix_observe(this.__wbg_ptr, ptr0, len0, addHeapObject(params));
|
|
147
154
|
return takeObject(ret);
|
|
148
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* @returns {Promise<any>}
|
|
158
|
+
*/
|
|
159
|
+
redo() {
|
|
160
|
+
const ret = wasm.wasmlix_redo(this.__wbg_ptr);
|
|
161
|
+
return takeObject(ret);
|
|
162
|
+
}
|
|
149
163
|
/**
|
|
150
164
|
* @param {any} options
|
|
151
165
|
* @returns {Promise<any>}
|
|
@@ -154,6 +168,13 @@ export class WasmLix {
|
|
|
154
168
|
const ret = wasm.wasmlix_switchBranch(this.__wbg_ptr, addHeapObject(options));
|
|
155
169
|
return takeObject(ret);
|
|
156
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* @returns {Promise<any>}
|
|
173
|
+
*/
|
|
174
|
+
undo() {
|
|
175
|
+
const ret = wasm.wasmlix_undo(this.__wbg_ptr);
|
|
176
|
+
return takeObject(ret);
|
|
177
|
+
}
|
|
157
178
|
}
|
|
158
179
|
if (Symbol.dispose) WasmLix.prototype[Symbol.dispose] = WasmLix.prototype.free;
|
|
159
180
|
|
|
@@ -515,7 +536,7 @@ function __wbg_get_imports() {
|
|
|
515
536
|
const a = state0.a;
|
|
516
537
|
state0.a = 0;
|
|
517
538
|
try {
|
|
518
|
-
return
|
|
539
|
+
return __wasm_bindgen_func_elem_122231(a, state0.b, arg0, arg1);
|
|
519
540
|
} finally {
|
|
520
541
|
state0.a = a;
|
|
521
542
|
}
|
|
@@ -625,8 +646,8 @@ function __wbg_get_imports() {
|
|
|
625
646
|
return addHeapObject(ret);
|
|
626
647
|
},
|
|
627
648
|
__wbindgen_cast_0000000000000001: function(arg0, arg1) {
|
|
628
|
-
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx:
|
|
629
|
-
const ret = makeMutClosure(arg0, arg1,
|
|
649
|
+
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 30525, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
|
|
650
|
+
const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_122229);
|
|
630
651
|
return addHeapObject(ret);
|
|
631
652
|
},
|
|
632
653
|
__wbindgen_cast_0000000000000002: function(arg0) {
|
|
@@ -675,10 +696,10 @@ function __wbg_get_imports() {
|
|
|
675
696
|
};
|
|
676
697
|
}
|
|
677
698
|
|
|
678
|
-
function
|
|
699
|
+
function __wasm_bindgen_func_elem_122229(arg0, arg1, arg2) {
|
|
679
700
|
try {
|
|
680
701
|
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
681
|
-
wasm.
|
|
702
|
+
wasm.__wasm_bindgen_func_elem_122229(retptr, arg0, arg1, addHeapObject(arg2));
|
|
682
703
|
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
683
704
|
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
684
705
|
if (r1) {
|
|
@@ -689,8 +710,8 @@ function __wasm_bindgen_func_elem_111270(arg0, arg1, arg2) {
|
|
|
689
710
|
}
|
|
690
711
|
}
|
|
691
712
|
|
|
692
|
-
function
|
|
693
|
-
wasm.
|
|
713
|
+
function __wasm_bindgen_func_elem_122231(arg0, arg1, arg2, arg3) {
|
|
714
|
+
wasm.__wasm_bindgen_func_elem_122231(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3));
|
|
694
715
|
}
|
|
695
716
|
|
|
696
717
|
const WasmLixFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
Binary file
|
|
@@ -7,6 +7,7 @@ export const __wbg_wasmobserveevents_free: (a: number, b: number) => void;
|
|
|
7
7
|
export const openMemory: (a: number) => number;
|
|
8
8
|
export const openMemoryFromSnapshot: (a: number, b: number, c: number) => number;
|
|
9
9
|
export const parseSqlScript: (a: number, b: number, c: number, d: number) => void;
|
|
10
|
+
export const wasmlix_activeAccountId: (a: number) => number;
|
|
10
11
|
export const wasmlix_activeBranchId: (a: number) => number;
|
|
11
12
|
export const wasmlix_beginTransaction: (a: number) => number;
|
|
12
13
|
export const wasmlix_clientStateDelete: (a: number, b: number, c: number) => number;
|
|
@@ -22,14 +23,16 @@ export const wasmlix_exportSnapshot: (a: number) => number;
|
|
|
22
23
|
export const wasmlix_mergeBranch: (a: number, b: number) => number;
|
|
23
24
|
export const wasmlix_mergeBranchPreview: (a: number, b: number) => number;
|
|
24
25
|
export const wasmlix_observe: (a: number, b: number, c: number, d: number) => number;
|
|
26
|
+
export const wasmlix_redo: (a: number) => number;
|
|
25
27
|
export const wasmlix_switchBranch: (a: number, b: number) => number;
|
|
28
|
+
export const wasmlix_undo: (a: number) => number;
|
|
26
29
|
export const wasmlixtransaction_commit: (a: number) => number;
|
|
27
30
|
export const wasmlixtransaction_execute: (a: number, b: number, c: number, d: number, e: number) => number;
|
|
28
31
|
export const wasmlixtransaction_rollback: (a: number) => number;
|
|
29
32
|
export const wasmobserveevents_close: (a: number) => void;
|
|
30
33
|
export const wasmobserveevents_next: (a: number) => number;
|
|
31
|
-
export const
|
|
32
|
-
export const
|
|
34
|
+
export const __wasm_bindgen_func_elem_122229: (a: number, b: number, c: number, d: number) => void;
|
|
35
|
+
export const __wasm_bindgen_func_elem_122231: (a: number, b: number, c: number, d: number) => void;
|
|
33
36
|
export const __wbindgen_export: (a: number, b: number) => number;
|
|
34
37
|
export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
|
|
35
38
|
export const __wbindgen_export3: (a: number) => void;
|