@lix-js/sdk 0.8.4 → 0.9.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 +82 -16
- package/dist/binding-types.d.ts +18 -2
- package/dist/binding.browser.d.ts +2 -2
- package/dist/binding.browser.js +3 -3
- package/dist/binding.node.d.ts +2 -2
- package/dist/binding.node.js +10 -4
- package/dist/bundled-plugins/plugin_csv_v2.lixplugin +0 -0
- package/dist/bundled-plugins/plugin_markdown_incremental_v2.lixplugin +0 -0
- package/dist/bundled-plugins.js +4 -4
- package/dist/client-state.d.ts +40 -0
- package/dist/client-state.js +178 -0
- package/dist/index.d.ts +2 -1
- package/dist/lix.d.ts +44 -0
- package/dist/lix.js +369 -0
- package/dist/local-storage-adapter.d.ts +26 -0
- package/dist/local-storage-adapter.js +117 -0
- package/dist/open-lix.d.ts +3 -34
- package/dist/open-lix.js +103 -170
- package/dist/remote/client.d.ts +8 -0
- package/dist/remote/client.js +1036 -0
- package/dist/remote/protocol.d.ts +166 -0
- package/dist/remote/protocol.js +362 -0
- package/dist/remote/sse.d.ts +12 -0
- package/dist/remote/sse.js +87 -0
- package/dist/snapshot-persistence.d.ts +7 -0
- package/dist/snapshot-persistence.js +26 -0
- package/dist/types.d.ts +58 -1
- package/dist/wasm/lix_js_sdk.d.ts +16 -4
- package/dist/wasm/lix_js_sdk.js +75 -17
- package/dist/wasm/lix_js_sdk_bg.wasm +0 -0
- package/dist/wasm/lix_js_sdk_bg.wasm.d.ts +8 -2
- package/dist/worker/client.d.ts +23 -4
- package/dist/worker/client.js +287 -10
- package/dist/worker/host.js +30 -2
- package/dist/worker/protocol.d.ts +26 -2
- package/dist/workerd.js +1 -3
- package/package.json +19 -16
- package/dist/bundled-plugins/plugin_csv.lixplugin +0 -0
- package/dist/bundled-plugins/plugin_md_v2.lixplugin +0 -0
- package/dist/jco/js-component-bindgen-component.core.wasm +0 -0
- package/dist/jco/js-component-bindgen-component.core2.wasm +0 -0
- package/dist/jco/js-component-bindgen-component.js +0 -13662
- package/dist/jco-transpile.browser.d.ts +0 -14
- package/dist/jco-transpile.browser.js +0 -22
- package/dist/plugin-runtime.d.ts +0 -45
- package/dist/plugin-runtime.js +0 -124
package/dist/open-lix.js
CHANGED
|
@@ -1,16 +1,7 @@
|
|
|
1
|
-
import { localFilesystemAlreadyOpen, localFilesystemNotOpen,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
const transactionFinalizer = new FinalizationRegistry(({ client, transactionId }) => {
|
|
6
|
-
client.notify({ kind: "transaction.abandon", transactionId });
|
|
7
|
-
});
|
|
8
|
-
const observeFinalizer = new FinalizationRegistry(({ client, observeId }) => {
|
|
9
|
-
void observeId.then((id) => {
|
|
10
|
-
if (id !== undefined)
|
|
11
|
-
client.notify({ kind: "observe.close", observeId: id });
|
|
12
|
-
});
|
|
13
|
-
});
|
|
1
|
+
import { localFilesystemAlreadyOpen, localFilesystemNotOpen, } from "./errors.js";
|
|
2
|
+
import { ACTIVE_BRANCH_CLIENT_STATE_KEY, openClientState, } from "./client-state.js";
|
|
3
|
+
import { Lix } from "./lix.js";
|
|
4
|
+
export { Lix, LixTransaction, ObserveEvents } from "./lix.js";
|
|
14
5
|
export class SQLite {
|
|
15
6
|
path;
|
|
16
7
|
constructor(options) {
|
|
@@ -53,16 +44,13 @@ export class LocalFilesystem {
|
|
|
53
44
|
throw new TypeError("importPaths() paths must contain non-empty strings");
|
|
54
45
|
}
|
|
55
46
|
if (path.endsWith("/")) {
|
|
56
|
-
throw new TypeError("importPaths() paths must
|
|
47
|
+
throw new TypeError("importPaths() paths must not end with a trailing slash");
|
|
57
48
|
}
|
|
58
49
|
}
|
|
59
|
-
await this.client("importPaths").
|
|
60
|
-
kind: "importFilesystemPaths",
|
|
61
|
-
paths: [...paths],
|
|
62
|
-
});
|
|
50
|
+
await this.client("importPaths").importFilesystemPaths([...paths]);
|
|
63
51
|
}
|
|
64
52
|
async syncDiskToLix() {
|
|
65
|
-
return this.client("syncDiskToLix").
|
|
53
|
+
return this.client("syncDiskToLix").syncDiskToLix();
|
|
66
54
|
}
|
|
67
55
|
client(operation) {
|
|
68
56
|
const client = openLocalFilesystems.get(this);
|
|
@@ -79,11 +67,67 @@ export async function openLix(options = {}) {
|
|
|
79
67
|
if ("backend" in options) {
|
|
80
68
|
throw new TypeError("openLix() option 'backend' was removed; use 'storage' instead");
|
|
81
69
|
}
|
|
70
|
+
if (options.telemetry !== undefined &&
|
|
71
|
+
(typeof options.telemetry !== "object" ||
|
|
72
|
+
typeof options.telemetry.onSpan !== "function")) {
|
|
73
|
+
throw new TypeError("openLix() telemetry requires an onSpan callback");
|
|
74
|
+
}
|
|
75
|
+
if (options.server !== undefined) {
|
|
76
|
+
const { openRemoteLixBinding } = await import("./remote/client.js");
|
|
77
|
+
if (options.storage === undefined) {
|
|
78
|
+
return new Lix(await openRemoteLixBinding(options.server));
|
|
79
|
+
}
|
|
80
|
+
assertSnapshotStorage(options.storage);
|
|
81
|
+
const { openPersistentLixWorkerBinding } = await import("./worker/client.js");
|
|
82
|
+
const clientBinding = await openPersistentLixWorkerBinding({
|
|
83
|
+
storage: options.storage,
|
|
84
|
+
namespace: remoteClientStateNamespace(options.server.url),
|
|
85
|
+
});
|
|
86
|
+
let clientState;
|
|
87
|
+
try {
|
|
88
|
+
clientState = await openClientState({
|
|
89
|
+
binding: clientBinding,
|
|
90
|
+
closeBinding: true,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
await clientBinding.close().catch(() => undefined);
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
const restoredBranchId = clientState.get(ACTIVE_BRANCH_CLIENT_STATE_KEY);
|
|
98
|
+
let remoteBinding;
|
|
99
|
+
try {
|
|
100
|
+
try {
|
|
101
|
+
remoteBinding = await openRemoteLixBinding(options.server, {
|
|
102
|
+
initialActiveBranchId: restoredBranchId,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
if (!restoredBranchId || !isBranchNotFoundError(error))
|
|
107
|
+
throw error;
|
|
108
|
+
remoteBinding = await openRemoteLixBinding(options.server);
|
|
109
|
+
}
|
|
110
|
+
const activeBranchId = await remoteBinding.activeBranchId();
|
|
111
|
+
if (activeBranchId !== restoredBranchId) {
|
|
112
|
+
await clientState.set(ACTIVE_BRANCH_CLIENT_STATE_KEY, activeBranchId);
|
|
113
|
+
}
|
|
114
|
+
return new Lix(remoteBinding, clientState);
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
await remoteBinding?.close().catch(() => undefined);
|
|
118
|
+
await clientState.close().catch(() => undefined);
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const { openLixWorkerBinding } = await import("./worker/client.js");
|
|
82
123
|
if (options.storage === undefined) {
|
|
83
|
-
return new Lix(await
|
|
124
|
+
return new Lix(await openLixWorkerBinding({ kind: "memory" }, undefined, options.telemetry));
|
|
84
125
|
}
|
|
85
126
|
if (options.storage instanceof SQLite) {
|
|
86
|
-
return new Lix(await
|
|
127
|
+
return new Lix(await openLixWorkerBinding({
|
|
128
|
+
kind: "sqlite",
|
|
129
|
+
path: options.storage.path,
|
|
130
|
+
}, undefined, options.telemetry));
|
|
87
131
|
}
|
|
88
132
|
if (options.storage instanceof LocalFilesystem) {
|
|
89
133
|
const storage = options.storage;
|
|
@@ -92,175 +136,64 @@ export async function openLix(options = {}) {
|
|
|
92
136
|
}
|
|
93
137
|
openLocalFilesystems.set(storage, null);
|
|
94
138
|
try {
|
|
95
|
-
const
|
|
139
|
+
const binding = await openLixWorkerBinding({
|
|
96
140
|
kind: "localFilesystem",
|
|
97
141
|
path: storage.path,
|
|
98
142
|
lixDir: storage.lixDir,
|
|
99
143
|
syncAllFiles: storage.syncAllFiles,
|
|
100
|
-
}, () => openLocalFilesystems.delete(storage));
|
|
101
|
-
openLocalFilesystems.set(storage,
|
|
102
|
-
return new Lix(
|
|
144
|
+
}, () => openLocalFilesystems.delete(storage), options.telemetry);
|
|
145
|
+
openLocalFilesystems.set(storage, binding);
|
|
146
|
+
return new Lix(binding);
|
|
103
147
|
}
|
|
104
148
|
catch (error) {
|
|
105
149
|
openLocalFilesystems.delete(storage);
|
|
106
150
|
throw error;
|
|
107
151
|
}
|
|
108
152
|
}
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
this.client = client;
|
|
116
|
-
}
|
|
117
|
-
async execute(sql, params = [], options) {
|
|
118
|
-
assertExecuteArgs("lix", sql, params, options);
|
|
119
|
-
return wrapExecuteResult(await this.client.request({
|
|
120
|
-
kind: "execute",
|
|
121
|
-
sql,
|
|
122
|
-
params: params.map((param, index) => toNativeValue(normalizeParam(param, index))),
|
|
123
|
-
options,
|
|
124
|
-
}));
|
|
125
|
-
}
|
|
126
|
-
observe(sql, params = []) {
|
|
127
|
-
assertSqlArgs("observe", "lix", sql, params);
|
|
128
|
-
return new ObserveEvents(this.client, this.client.request({
|
|
129
|
-
kind: "observe",
|
|
130
|
-
sql,
|
|
131
|
-
params: params.map((param, index) => toNativeValue(normalizeParam(param, index))),
|
|
132
|
-
}));
|
|
133
|
-
}
|
|
134
|
-
async beginTransaction() {
|
|
135
|
-
const transactionId = await this.client.request({
|
|
136
|
-
kind: "beginTransaction",
|
|
153
|
+
if (isSnapshotStorage(options.storage)) {
|
|
154
|
+
const { openPersistentLixWorkerBinding } = await import("./worker/client.js");
|
|
155
|
+
const binding = await openPersistentLixWorkerBinding({
|
|
156
|
+
storage: options.storage,
|
|
157
|
+
namespace: "local",
|
|
158
|
+
telemetry: options.telemetry,
|
|
137
159
|
});
|
|
138
|
-
return new LixTransaction(this.client, transactionId);
|
|
139
|
-
}
|
|
140
|
-
async activeBranchId() {
|
|
141
|
-
return this.client.request({ kind: "activeBranchId" });
|
|
142
|
-
}
|
|
143
|
-
async createBranch(options) {
|
|
144
|
-
return this.client.request({ kind: "createBranch", options });
|
|
145
|
-
}
|
|
146
|
-
async switchBranch(options) {
|
|
147
|
-
return this.client.request({ kind: "switchBranch", options });
|
|
148
|
-
}
|
|
149
|
-
async mergeBranchPreview(options) {
|
|
150
|
-
return normalizeOptionals(await this.client.request({ kind: "mergeBranchPreview", options }));
|
|
151
|
-
}
|
|
152
|
-
async mergeBranch(options) {
|
|
153
|
-
const receipt = normalizeOptionals(await this.client.request({ kind: "mergeBranch", options }));
|
|
154
|
-
receipt.createdMergeCommitId ??= null;
|
|
155
|
-
return receipt;
|
|
156
|
-
}
|
|
157
|
-
async close() {
|
|
158
|
-
this.closePromise ??= (async () => {
|
|
159
|
-
await this.client.request({ kind: "close" });
|
|
160
|
-
await this.client.terminate();
|
|
161
|
-
})();
|
|
162
160
|
try {
|
|
163
|
-
await
|
|
161
|
+
const clientState = await openClientState({ binding });
|
|
162
|
+
return new Lix(binding, clientState);
|
|
164
163
|
}
|
|
165
164
|
catch (error) {
|
|
166
|
-
|
|
165
|
+
await binding.close().catch(() => undefined);
|
|
167
166
|
throw error;
|
|
168
167
|
}
|
|
169
168
|
}
|
|
169
|
+
throw new TypeError("openLix() requires storage to be SQLite, LocalFilesystem, or a Lix snapshot storage adapter");
|
|
170
170
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
constructor(client, observeId) {
|
|
177
|
-
this.client = client;
|
|
178
|
-
const setup = this.setup;
|
|
179
|
-
this.observeId = observeId.catch((error) => {
|
|
180
|
-
setup.error = error;
|
|
181
|
-
return undefined;
|
|
182
|
-
});
|
|
183
|
-
observeFinalizer.register(this, { client, observeId: this.observeId }, this);
|
|
184
|
-
}
|
|
185
|
-
async next() {
|
|
186
|
-
if (this.closed)
|
|
187
|
-
return undefined;
|
|
188
|
-
const observeId = await this.observeId;
|
|
189
|
-
if (observeId === undefined) {
|
|
190
|
-
throw this.setup.error;
|
|
191
|
-
}
|
|
192
|
-
const event = await this.client.request({
|
|
193
|
-
kind: "observe.next",
|
|
194
|
-
observeId,
|
|
195
|
-
});
|
|
196
|
-
if (event == null) {
|
|
197
|
-
return undefined;
|
|
198
|
-
}
|
|
199
|
-
return {
|
|
200
|
-
sequence: event.sequence,
|
|
201
|
-
mutationSequence: event.mutationSequence,
|
|
202
|
-
result: wrapExecuteResult(event.rows),
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
close() {
|
|
206
|
-
if (this.closed)
|
|
207
|
-
return;
|
|
208
|
-
this.closed = true;
|
|
209
|
-
observeFinalizer.unregister(this);
|
|
210
|
-
void this.observeId.then((observeId) => {
|
|
211
|
-
if (observeId !== undefined) {
|
|
212
|
-
this.client.notify({ kind: "observe.close", observeId });
|
|
213
|
-
}
|
|
214
|
-
});
|
|
215
|
-
}
|
|
171
|
+
function isSnapshotStorage(value) {
|
|
172
|
+
return (typeof value === "object" &&
|
|
173
|
+
value !== null &&
|
|
174
|
+
typeof value.load === "function" &&
|
|
175
|
+
typeof value.save === "function");
|
|
216
176
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
constructor(client, transactionId) {
|
|
221
|
-
this.client = client;
|
|
222
|
-
this.transactionId = transactionId;
|
|
223
|
-
transactionFinalizer.register(this, { client, transactionId }, this);
|
|
224
|
-
}
|
|
225
|
-
async execute(sql, params = [], options) {
|
|
226
|
-
assertExecuteArgs("lixTransaction", sql, params, options);
|
|
227
|
-
return wrapExecuteResult(await this.client.request({
|
|
228
|
-
kind: "transaction.execute",
|
|
229
|
-
transactionId: this.transactionId,
|
|
230
|
-
sql,
|
|
231
|
-
params: params.map((param, index) => toNativeValue(normalizeParam(param, index))),
|
|
232
|
-
options,
|
|
233
|
-
}));
|
|
234
|
-
}
|
|
235
|
-
async commit() {
|
|
236
|
-
return this.finish("transaction.commit");
|
|
237
|
-
}
|
|
238
|
-
async rollback() {
|
|
239
|
-
return this.finish("transaction.rollback");
|
|
240
|
-
}
|
|
241
|
-
async finish(kind) {
|
|
242
|
-
transactionFinalizer.unregister(this);
|
|
243
|
-
return this.client.request({ kind, transactionId: this.transactionId });
|
|
177
|
+
function assertSnapshotStorage(value) {
|
|
178
|
+
if (!isSnapshotStorage(value)) {
|
|
179
|
+
throw new TypeError("openLix() remote storage must implement load() and save()");
|
|
244
180
|
}
|
|
245
181
|
}
|
|
246
|
-
function
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
throw
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
}
|
|
182
|
+
function remoteClientStateNamespace(value) {
|
|
183
|
+
let url;
|
|
184
|
+
try {
|
|
185
|
+
url = new URL(value);
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
throw new TypeError("openLix() remote server url must be an absolute URL");
|
|
189
|
+
}
|
|
190
|
+
url.pathname = url.pathname.replace(/\/$/, "");
|
|
191
|
+
url.search = "";
|
|
192
|
+
url.hash = "";
|
|
193
|
+
return `remote:${url.href}`;
|
|
258
194
|
}
|
|
259
|
-
function
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
if (!Array.isArray(params)) {
|
|
264
|
-
throw invalidArgument(operation, "params", "array", typeof params, receiver);
|
|
265
|
-
}
|
|
195
|
+
function isBranchNotFoundError(error) {
|
|
196
|
+
return (error instanceof Error &&
|
|
197
|
+
"code" in error &&
|
|
198
|
+
error.code === "LIX_BRANCH_NOT_FOUND");
|
|
266
199
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { LixBinding } from "../binding-types.js";
|
|
2
|
+
import type { RemoteLixServerOptions } from "../types.js";
|
|
3
|
+
import { type RemoteHandshakeRequest } from "./protocol.js";
|
|
4
|
+
type RemoteLixClientOptions = {
|
|
5
|
+
initialActiveBranchId?: RemoteHandshakeRequest["activeBranchId"];
|
|
6
|
+
};
|
|
7
|
+
export declare function openRemoteLixBinding(options: RemoteLixServerOptions, clientOptions?: RemoteLixClientOptions): Promise<LixBinding>;
|
|
8
|
+
export {};
|