@lix-js/sdk 0.10.0 → 0.12.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.
Files changed (42) hide show
  1. package/README.md +49 -78
  2. package/dist/binding-types.d.ts +9 -18
  3. package/dist/binding.browser.js +18 -5
  4. package/dist/binding.node.js +5 -11
  5. package/dist/bundled-plugins/plugin_csv.lixplugin +0 -0
  6. package/dist/bundled-plugins/plugin_markdown.lixplugin +0 -0
  7. package/dist/errors.d.ts +0 -2
  8. package/dist/errors.js +0 -13
  9. package/dist/index.d.ts +3 -3
  10. package/dist/index.js +1 -1
  11. package/dist/indexeddb-backend.d.ts +19 -0
  12. package/dist/indexeddb-backend.js +121 -0
  13. package/dist/lix.d.ts +3 -6
  14. package/dist/lix.js +28 -54
  15. package/dist/open-lix.d.ts +4 -13
  16. package/dist/open-lix.js +45 -152
  17. package/dist/remote/client.d.ts +2 -3
  18. package/dist/remote/client.js +50 -23
  19. package/dist/remote/{protocol.d.ts → server-protocol.d.ts} +40 -32
  20. package/dist/remote/{protocol.js → server-protocol.js} +36 -17
  21. package/dist/result.d.ts +2 -1
  22. package/dist/result.js +12 -0
  23. package/dist/storage-adapter.d.ts +30 -0
  24. package/dist/storage-adapter.js +12 -0
  25. package/dist/types.d.ts +25 -27
  26. package/dist/value.d.ts +2 -1
  27. package/dist/value.js +23 -10
  28. package/dist/wasm/lix_js_sdk.d.ts +5 -10
  29. package/dist/wasm/lix_js_sdk.js +33 -45
  30. package/dist/wasm/lix_js_sdk_bg.wasm +0 -0
  31. package/dist/wasm/lix_js_sdk_bg.wasm.d.ts +3 -6
  32. package/dist/worker/client.d.ts +1 -12
  33. package/dist/worker/client.js +0 -161
  34. package/dist/worker/host.js +0 -23
  35. package/dist/worker/protocol.d.ts +1 -15
  36. package/package.json +8 -12
  37. package/dist/client-state.d.ts +0 -53
  38. package/dist/client-state.js +0 -318
  39. package/dist/local-storage-adapter.d.ts +0 -26
  40. package/dist/local-storage-adapter.js +0 -117
  41. package/dist/snapshot-persistence.d.ts +0 -7
  42. package/dist/snapshot-persistence.js +0 -26
@@ -1,7 +1,7 @@
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 = 2;
4
- export declare const REMOTE_PROTOCOL_PATH = "/lix/v1/";
3
+ export declare const SERVER_PROTOCOL_VERSION = 2;
4
+ export declare const SERVER_PROTOCOL_PATH = "/lix/v1/";
5
5
  export type WireValue = {
6
6
  kind: "null";
7
7
  value: null;
@@ -18,8 +18,11 @@ export type WireValue = {
18
18
  kind: "text";
19
19
  value: string;
20
20
  } | {
21
- kind: "json";
21
+ kind: "jsonb";
22
22
  value: unknown;
23
+ } | {
24
+ kind: "timestamptz";
25
+ value: string;
23
26
  } | {
24
27
  kind: "blob";
25
28
  base64: string;
@@ -33,17 +36,16 @@ export type WireRequestBlobSplice = {
33
36
  insertBase64: string;
34
37
  };
35
38
  export type WireRequestValue = WireValue | WireRequestBlobSplice;
36
- export type RemoteHandshake = {
39
+ export type ServerProtocolHandshake = {
37
40
  protocolVersion: number;
38
41
  activeBranchId: string;
39
42
  activeAccountId: string;
40
43
  sessionId: string;
41
44
  };
42
- export type RemoteHandshakeRequest = {
45
+ export type ServerProtocolHandshakeRequest = {
43
46
  activeBranchId?: string;
44
- activeAccountId?: string;
45
47
  };
46
- export type RemoteExecuteRequest = {
48
+ export type ServerProtocolExecuteRequest = {
47
49
  sql: string;
48
50
  params: WireRequestValue[];
49
51
  options?: {
@@ -51,17 +53,18 @@ export type RemoteExecuteRequest = {
51
53
  };
52
54
  cacheBlobs?: true;
53
55
  };
54
- export type RemoteExecuteBatchRequest = {
56
+ export type ServerProtocolExecuteBatchRequest = {
55
57
  statements: Array<{
56
58
  sql: string;
57
59
  params: WireRequestValue[];
60
+ label?: string;
58
61
  }>;
59
62
  options?: {
60
63
  originKey?: string;
61
64
  };
62
65
  cacheBlobs?: true;
63
66
  };
64
- export type RemoteExecuteResponse = {
67
+ export type ServerProtocolExecuteResponse = {
65
68
  columns: string[];
66
69
  rows: WireValue[][];
67
70
  rowsAffected: number;
@@ -71,76 +74,80 @@ export type RemoteExecuteResponse = {
71
74
  hint?: string;
72
75
  }>;
73
76
  };
74
- export type RemoteObserveRequest = {
77
+ export type ServerProtocolExecuteBatchResponse = ServerProtocolExecuteResponse & {
78
+ statementIndex: number;
79
+ label?: string;
80
+ };
81
+ export type ServerProtocolObserveRequest = {
75
82
  sql: string;
76
83
  params: WireValue[];
77
84
  };
78
- export type RemoteObserveSubscription = RemoteObserveRequest & {
85
+ export type ServerProtocolObserveSubscription = ServerProtocolObserveRequest & {
79
86
  id: string;
80
87
  };
81
- export type RemoteMultiplexObserveRequest = {
82
- subscriptions: RemoteObserveSubscription[];
88
+ export type ServerProtocolMultiplexObserveRequest = {
89
+ subscriptions: ServerProtocolObserveSubscription[];
83
90
  };
84
- type RemoteObserveEventBase = {
91
+ type ServerProtocolObserveEventBase = {
85
92
  sequence: number;
86
93
  mutationSequence: number;
87
94
  };
88
- export type RemoteObserveBlobDelta = {
95
+ export type ServerProtocolObserveBlobDelta = {
89
96
  kind: "single-blob-splice";
90
97
  baseSequence: number;
91
98
  prefixBytes: number;
92
99
  suffixBytes: number;
93
100
  insertBase64: string;
94
101
  };
95
- type RemoteObserveRowSplice = {
102
+ type ServerProtocolObserveRowSplice = {
96
103
  kind: "row-splice";
97
104
  baseSequence: number;
98
105
  prefixRows: number;
99
106
  deleteRows: number;
100
107
  insertRows: WireValue[][];
101
108
  };
102
- type RemoteObserveDelta = RemoteObserveBlobDelta | RemoteObserveRowSplice;
103
- export type RemoteObserveEvent = RemoteObserveEventBase & ({
104
- result: RemoteExecuteResponse;
109
+ type ServerProtocolObserveDelta = ServerProtocolObserveBlobDelta | ServerProtocolObserveRowSplice;
110
+ export type ServerProtocolObserveEvent = ServerProtocolObserveEventBase & ({
111
+ result: ServerProtocolExecuteResponse;
105
112
  delta?: never;
106
113
  } | {
107
114
  result?: never;
108
- delta: RemoteObserveDelta;
115
+ delta: ServerProtocolObserveDelta;
109
116
  });
110
- export type RemoteMultiplexObserveEvent = RemoteObserveEvent & {
117
+ export type ServerProtocolMultiplexObserveEvent = ServerProtocolObserveEvent & {
111
118
  subscriptionId: string;
112
119
  };
113
- export type RemoteCreateBranchRequest = {
120
+ export type ServerProtocolCreateBranchRequest = {
114
121
  id?: string;
115
122
  name: string;
116
123
  fromCommitId?: string;
117
124
  };
118
- export type RemoteCreateBranchResponse = {
125
+ export type ServerProtocolCreateBranchResponse = {
119
126
  id: string;
120
127
  name: string;
121
128
  hidden: boolean;
122
129
  commitId: string;
123
130
  };
124
- export type RemoteCreateCheckpointResponse = {
131
+ export type ServerProtocolCreateCheckpointResponse = {
125
132
  commitId: string;
126
133
  };
127
- export type RemoteUndoResponse = {
134
+ export type ServerProtocolUndoResponse = {
128
135
  branchId: string;
129
136
  targetCommitId: string;
130
137
  inverseCommitId: string;
131
138
  };
132
- export type RemoteRedoResponse = {
139
+ export type ServerProtocolRedoResponse = {
133
140
  branchId: string;
134
141
  targetCommitId: string;
135
142
  replayCommitId: string;
136
143
  };
137
- export type RemoteSwitchBranchRequest = {
144
+ export type ServerProtocolSwitchBranchRequest = {
138
145
  branchId: string;
139
146
  };
140
- export type RemoteSwitchBranchResponse = {
147
+ export type ServerProtocolSwitchBranchResponse = {
141
148
  branchId: string;
142
149
  };
143
- export type RemoteErrorBody = {
150
+ export type ServerProtocolErrorBody = {
144
151
  error: {
145
152
  code?: string;
146
153
  message?: string;
@@ -148,15 +155,16 @@ export type RemoteErrorBody = {
148
155
  details?: unknown;
149
156
  };
150
157
  };
151
- export type RemoteObserveErrorEvent = RemoteErrorBody & {
158
+ export type ServerProtocolObserveErrorEvent = ServerProtocolErrorBody & {
152
159
  retryable?: boolean;
153
160
  };
154
- export type RemoteMultiplexObserveErrorEvent = RemoteObserveErrorEvent & {
161
+ export type ServerProtocolMultiplexObserveErrorEvent = ServerProtocolObserveErrorEvent & {
155
162
  subscriptionId?: string;
156
163
  };
157
164
  export declare function encodeWireValue(value: NativeLixValue): WireValue;
158
165
  export declare function decodeExecuteResult(value: unknown): BindingExecuteResult;
159
- export declare function decodeHandshake(value: unknown): RemoteHandshake;
166
+ export declare function decodeExecuteBatchResult(value: unknown): BindingExecuteResult;
167
+ export declare function decodeHandshake(value: unknown): ServerProtocolHandshake;
160
168
  export declare function decodeObserveEvent(value: unknown, base?: BindingObserveEvent): BindingObserveEvent;
161
169
  export declare function remoteError(code: string, message: string, options?: {
162
170
  hint?: string;
@@ -1,5 +1,5 @@
1
- export const REMOTE_PROTOCOL_VERSION = 2;
2
- export const REMOTE_PROTOCOL_PATH = "/lix/v1/";
1
+ export const SERVER_PROTOCOL_VERSION = 2;
2
+ export const SERVER_PROTOCOL_PATH = "/lix/v1/";
3
3
  export function encodeWireValue(value) {
4
4
  switch (value.kind) {
5
5
  case "null":
@@ -12,8 +12,10 @@ export function encodeWireValue(value) {
12
12
  return { kind: "float", value: value.value };
13
13
  case "text":
14
14
  return { kind: "text", value: value.value };
15
- case "json":
16
- return { kind: "json", value: value.value };
15
+ case "jsonb":
16
+ return { kind: "jsonb", value: value.value };
17
+ case "timestamptz":
18
+ return { kind: "timestamptz", value: value.value };
17
19
  case "blob":
18
20
  return { kind: "blob", base64: bytesToBase64(value.blob) };
19
21
  }
@@ -57,25 +59,37 @@ export function decodeExecuteResult(value) {
57
59
  });
58
60
  return { columns, rows, rowsAffected: result.rowsAffected, notices };
59
61
  }
62
+ export function decodeExecuteBatchResult(value) {
63
+ const result = record(value, "execute batch result");
64
+ const statementIndex = nonNegativeSafeInteger(result.statementIndex, "execute batch result statementIndex");
65
+ if (result.label !== undefined && typeof result.label !== "string") {
66
+ throw protocolError("execute batch result label must be a string when present");
67
+ }
68
+ return {
69
+ ...decodeExecuteResult(value),
70
+ statementIndex,
71
+ ...(result.label === undefined ? {} : { label: result.label }),
72
+ };
73
+ }
60
74
  export function decodeHandshake(value) {
61
- const handshake = record(value, "remote handshake");
62
- if (handshake.protocolVersion !== REMOTE_PROTOCOL_VERSION) {
63
- throw protocolError(`unsupported remote protocol version: ${String(handshake.protocolVersion)}`);
75
+ const handshake = record(value, "Lix Server Protocol handshake");
76
+ if (handshake.protocolVersion !== SERVER_PROTOCOL_VERSION) {
77
+ throw protocolError(`unsupported Lix Server Protocol version: ${String(handshake.protocolVersion)}`);
64
78
  }
65
79
  if (typeof handshake.activeBranchId !== "string" ||
66
80
  handshake.activeBranchId.length === 0) {
67
- throw protocolError("remote handshake requires activeBranchId");
81
+ throw protocolError("Lix Server Protocol handshake requires activeBranchId");
68
82
  }
69
83
  if (typeof handshake.activeAccountId !== "string" ||
70
84
  handshake.activeAccountId.length === 0) {
71
- throw protocolError("remote handshake requires activeAccountId");
85
+ throw protocolError("Lix Server Protocol handshake requires activeAccountId");
72
86
  }
73
87
  if (typeof handshake.sessionId !== "string" ||
74
88
  !/^[\x21-\x7e]{1,256}$/.test(handshake.sessionId)) {
75
- throw protocolError("remote handshake requires a valid sessionId");
89
+ throw protocolError("Lix Server Protocol handshake requires a valid sessionId");
76
90
  }
77
91
  return {
78
- protocolVersion: REMOTE_PROTOCOL_VERSION,
92
+ protocolVersion: SERVER_PROTOCOL_VERSION,
79
93
  activeBranchId: handshake.activeBranchId,
80
94
  activeAccountId: handshake.activeAccountId,
81
95
  sessionId: handshake.sessionId,
@@ -228,11 +242,11 @@ export function remoteError(code, message, options = {}) {
228
242
  return error;
229
243
  }
230
244
  export function protocolError(message) {
231
- return remoteError("LIX_REMOTE_PROTOCOL_ERROR", message);
245
+ return remoteError("LIX_SERVER_PROTOCOL_ERROR", message);
232
246
  }
233
247
  export function errorFromResponseBody(value, status) {
234
- const body = record(value, "remote error response");
235
- const rawError = record(body.error, "remote error response error");
248
+ const body = record(value, "Lix Server Protocol error response");
249
+ const rawError = record(body.error, "Lix Server Protocol error response error");
236
250
  return remoteError(typeof rawError.code === "string"
237
251
  ? rawError.code
238
252
  : "LIX_REMOTE_REQUEST_FAILED", typeof rawError.message === "string"
@@ -281,9 +295,14 @@ function decodeWireValue(value) {
281
295
  throw protocolError("text wire value is invalid");
282
296
  }
283
297
  return { kind: "text", value: wire.value };
284
- case "json":
285
- assertJsonValue(wire.value, "json wire value");
286
- return { kind: "json", value: wire.value };
298
+ case "jsonb":
299
+ assertJsonValue(wire.value, "jsonb wire value");
300
+ return { kind: "jsonb", value: wire.value };
301
+ case "timestamptz":
302
+ if (typeof wire.value !== "string") {
303
+ throw protocolError("timestamptz wire value is invalid");
304
+ }
305
+ return { kind: "timestamptz", value: wire.value };
287
306
  case "blob":
288
307
  if (typeof wire.base64 !== "string") {
289
308
  throw protocolError("blob wire value is invalid");
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);
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Operations exposed to a storage adapter while its Lix is open.
3
+ *
4
+ * This is intentionally narrower than the engine binding. Storage packages
5
+ * receive only the controls required to manage their own persistence layer.
6
+ */
7
+ export type LixStorageConnection = {
8
+ importFilesystemPaths(paths: string[]): Promise<void>;
9
+ syncDiskToLix(): Promise<void>;
10
+ };
11
+ /** Engine configuration currently supported by external JavaScript storage packages. */
12
+ export type LixStorageAdapterConfig = {
13
+ kind: "filesystem";
14
+ path: string;
15
+ syncAllFiles: boolean;
16
+ };
17
+ /**
18
+ * Protocol implemented by JavaScript storage packages accepted by `openLix()`.
19
+ *
20
+ * Applications normally use a concrete package such as
21
+ * `@lix-js/storage-filesystem` rather than implementing this directly.
22
+ */
23
+ export type LixStorage = {
24
+ readonly lixStorage: {
25
+ readonly version: 1;
26
+ readonly config: LixStorageAdapterConfig;
27
+ connect(connection: LixStorageConnection | undefined): void;
28
+ };
29
+ };
30
+ export declare function isLixStorage(value: unknown): value is LixStorage;
@@ -0,0 +1,12 @@
1
+ export function isLixStorage(value) {
2
+ if (!value || typeof value !== "object" || !("lixStorage" in value)) {
3
+ return false;
4
+ }
5
+ const adapter = value.lixStorage;
6
+ return Boolean(adapter &&
7
+ typeof adapter === "object" &&
8
+ adapter.version === 1 &&
9
+ typeof adapter.connect === "function" &&
10
+ adapter.config?.kind ===
11
+ "filesystem");
12
+ }
package/dist/types.d.ts CHANGED
@@ -1,10 +1,9 @@
1
- export type SQLiteOptions = {
2
- path: string;
3
- };
4
- export type LocalFilesystemOptions = {
5
- path: string;
6
- lixDir?: string;
7
- syncAllFiles: boolean;
1
+ export type IndexedDbStorageOptions = {
2
+ /**
3
+ * Identifies one persistent Lix database within the current origin.
4
+ * A database name can be opened by only one Lix handle at a time.
5
+ */
6
+ name: string;
8
7
  };
9
8
  export type RemoteLixFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
10
9
  export type RemoteLixServerOptions = {
@@ -24,27 +23,12 @@ export type LixTelemetrySpan = {
24
23
  export type LixTelemetryOptions = {
25
24
  onSpan(span: LixTelemetrySpan): void;
26
25
  };
27
- /**
28
- * Persists opaque Lix snapshots under SDK-provided namespaces.
29
- *
30
- * Implementations must treat snapshots as bytes owned by Lix. The namespace
31
- * selects one logical Lix and allows a single adapter to persist more than one
32
- * instance without collisions.
33
- */
34
- export interface LixSnapshotStorage {
35
- load(namespace: string): Promise<Uint8Array | undefined>;
36
- save(namespace: string, snapshot: Uint8Array): Promise<void>;
37
- }
38
26
  export type OpenLixOptions = {
39
- storage?: import("./open-lix.js").SQLite | import("./open-lix.js").LocalFilesystem | LixSnapshotStorage;
27
+ storage?: import("./storage-adapter.js").LixStorage | import("./open-lix.js").IndexedDbStorage;
40
28
  server?: never;
41
29
  telemetry?: LixTelemetryOptions;
42
30
  } | {
43
- /**
44
- * Optional client-local storage. In remote mode workspace SQL remains on
45
- * the server; only `lix.clientState` is stored here.
46
- */
47
- storage?: LixSnapshotStorage;
31
+ storage?: never;
48
32
  server: RemoteLixServerOptions;
49
33
  telemetry?: never;
50
34
  };
@@ -64,8 +48,11 @@ export type LixValue = {
64
48
  kind: "text";
65
49
  value: string;
66
50
  } | {
67
- kind: "json";
51
+ kind: "jsonb";
68
52
  value: JsonValue;
53
+ } | {
54
+ kind: "timestamptz";
55
+ value: string;
69
56
  } | {
70
57
  kind: "blob";
71
58
  value: Uint8Array;
@@ -86,6 +73,7 @@ export type ExecuteOptions = {
86
73
  export type LixBatchStatement = {
87
74
  sql: string;
88
75
  params?: readonly SqlParam[];
76
+ label?: string;
89
77
  };
90
78
  export type LixBatchOptions = {
91
79
  originKey?: string;
@@ -93,6 +81,8 @@ export type LixBatchOptions = {
93
81
  idempotencyKey?: string;
94
82
  };
95
83
  export type ExecuteResult = {
84
+ statementIndex?: number;
85
+ label?: string;
96
86
  columns: string[];
97
87
  rows: RowLike[];
98
88
  rowsAffected: number;
@@ -102,9 +92,17 @@ export type ExecuteResult = {
102
92
  hint?: string;
103
93
  }>;
104
94
  };
95
+ export type ExecuteBatchResult = ExecuteResult & {
96
+ statementIndex: number;
97
+ };
105
98
  export type ObserveEvent = {
106
99
  sequence: number;
107
100
  mutationSequence: number;
101
+ /**
102
+ * The current result of the observed query. Remote observations reconcile
103
+ * the first frame of every stream through execute before publishing it, so
104
+ * reconnects cannot expose a stale server snapshot to consumers.
105
+ */
108
106
  result: ExecuteResult;
109
107
  };
110
108
  export type RowLike = {
@@ -180,9 +178,9 @@ export type MergeChangeStats = {
180
178
  removed: number;
181
179
  };
182
180
  export type MergeConflict = {
183
- kind: "sameEntityChanged";
181
+ kind: "sameRowChanged";
184
182
  schemaKey: string;
185
- entityPk: unknown;
183
+ rowPk: unknown;
186
184
  fileId: string | null;
187
185
  target: MergeConflictSide;
188
186
  source: MergeConflictSide;
package/dist/value.d.ts CHANGED
@@ -8,7 +8,8 @@ export declare class Value {
8
8
  static integer(value: number): Value;
9
9
  static real(value: number): Value;
10
10
  static text(value: string): Value;
11
- static json(value: JsonValue): Value;
11
+ static jsonb(value: JsonValue): Value;
12
+ static timestamptz(value: string): Value;
12
13
  static blob(value: Uint8Array): Value;
13
14
  static from(value: SqlParam): Value;
14
15
  static _fromNative(value: LixValue): Value;
package/dist/value.js CHANGED
@@ -2,9 +2,9 @@ import { invalidParam } from "./errors.js";
2
2
  export class Value {
3
3
  kind;
4
4
  #raw;
5
- constructor(raw) {
5
+ constructor(raw, clone = true) {
6
6
  validateExplicitValue(raw);
7
- this.#raw = cloneValue(raw);
7
+ this.#raw = clone ? cloneValue(raw) : raw;
8
8
  this.kind = this.#raw.kind;
9
9
  }
10
10
  static null() {
@@ -22,8 +22,11 @@ export class Value {
22
22
  static text(value) {
23
23
  return new Value({ kind: "text", value });
24
24
  }
25
- static json(value) {
26
- return new Value({ kind: "json", value });
25
+ static jsonb(value) {
26
+ return new Value({ kind: "jsonb", value });
27
+ }
28
+ static timestamptz(value) {
29
+ return new Value({ kind: "timestamptz", value });
27
30
  }
28
31
  static blob(value) {
29
32
  return new Value({ kind: "blob", value });
@@ -32,7 +35,11 @@ export class Value {
32
35
  return new Value(normalizeParam(value));
33
36
  }
34
37
  static _fromNative(value) {
35
- return new Value(value);
38
+ // Native execute results are newly materialized for this result set. Keep
39
+ // the native value as-is and defer the defensive copy until toJS(). This
40
+ // avoids cloning every structured result once during row wrapping and
41
+ // again when callers read it.
42
+ return new Value(value, false);
36
43
  }
37
44
  _toNative() {
38
45
  return toNativeValue(this.#raw);
@@ -101,7 +108,7 @@ export function normalizeParam(value, index = 0, seen = new WeakSet()) {
101
108
  throw invalidParam(index, "typed array SQL parameters must be Uint8Array", value.constructor.name);
102
109
  }
103
110
  assertJsonSerializable(value, seen, index);
104
- return { kind: "json", value };
111
+ return { kind: "jsonb", value };
105
112
  }
106
113
  throw invalidParam(index, `${typeof value} is not a valid SQL parameter`, typeof value);
107
114
  }
@@ -113,7 +120,8 @@ function unwrapValue(value) {
113
120
  case "integer":
114
121
  case "real":
115
122
  case "text":
116
- case "json":
123
+ case "timestamptz":
124
+ case "jsonb":
117
125
  return cloneJsonValue(value.value);
118
126
  case "blob":
119
127
  return new Uint8Array(value.value);
@@ -193,9 +201,14 @@ function validateExplicitValue(value) {
193
201
  throw invalidParam(0, "string SQL parameters must be well-formed UTF-16", "string");
194
202
  }
195
203
  return;
196
- case "json":
204
+ case "jsonb":
197
205
  assertJsonSerializable(value.value, new WeakSet(), 0);
198
206
  return;
207
+ case "timestamptz":
208
+ if (typeof value.value === "string" && !Number.isNaN(Date.parse(value.value))) {
209
+ return;
210
+ }
211
+ break;
199
212
  case "blob":
200
213
  if (value.value instanceof Uint8Array)
201
214
  return;
@@ -209,8 +222,8 @@ function cloneValue(value) {
209
222
  if (value.kind === "blob") {
210
223
  return { kind: "blob", value: new Uint8Array(value.value) };
211
224
  }
212
- if (value.kind === "json") {
213
- return { kind: "json", value: cloneJsonValue(value.value) };
225
+ if (value.kind === "jsonb") {
226
+ return { kind: "jsonb", value: cloneJsonValue(value.value) };
214
227
  }
215
228
  return value;
216
229
  }
@@ -8,10 +8,6 @@ export class WasmLix {
8
8
  activeAccountId(): Promise<string>;
9
9
  activeBranchId(): Promise<string>;
10
10
  beginTransaction(): Promise<WasmLixTransaction>;
11
- clientStateDelete(key: string): Promise<void>;
12
- clientStateEntries(): Promise<any>;
13
- clientStateGet(key: string): Promise<any>;
14
- clientStateSet(key: string, value: any): Promise<void>;
15
11
  close(): Promise<void>;
16
12
  createBranch(options: any): Promise<any>;
17
13
  createCheckpoint(): Promise<any>;
@@ -43,6 +39,8 @@ export class WasmObserveEvents {
43
39
  next(): Promise<any>;
44
40
  }
45
41
 
42
+ export function openIndexedDb(backend: any, telemetry_dispatch?: Function | null): Promise<WasmLix>;
43
+
46
44
  export function openMemory(telemetry_dispatch?: Function | null): Promise<WasmLix>;
47
45
 
48
46
  export function openMemoryFromSnapshot(telemetry_dispatch?: Function | null, snapshot?: Uint8Array | null): Promise<WasmLix>;
@@ -56,16 +54,13 @@ export interface InitOutput {
56
54
  readonly __wbg_wasmlix_free: (a: number, b: number) => void;
57
55
  readonly __wbg_wasmlixtransaction_free: (a: number, b: number) => void;
58
56
  readonly __wbg_wasmobserveevents_free: (a: number, b: number) => void;
57
+ readonly openIndexedDb: (a: number, b: number) => number;
59
58
  readonly openMemory: (a: number) => number;
60
59
  readonly openMemoryFromSnapshot: (a: number, b: number, c: number) => number;
61
60
  readonly parseSqlScript: (a: number, b: number, c: number, d: number) => void;
62
61
  readonly wasmlix_activeAccountId: (a: number) => number;
63
62
  readonly wasmlix_activeBranchId: (a: number) => number;
64
63
  readonly wasmlix_beginTransaction: (a: number) => number;
65
- readonly wasmlix_clientStateDelete: (a: number, b: number, c: number) => number;
66
- readonly wasmlix_clientStateEntries: (a: number) => number;
67
- readonly wasmlix_clientStateGet: (a: number, b: number, c: number) => number;
68
- readonly wasmlix_clientStateSet: (a: number, b: number, c: number, d: number) => number;
69
64
  readonly wasmlix_close: (a: number) => number;
70
65
  readonly wasmlix_createBranch: (a: number, b: number) => number;
71
66
  readonly wasmlix_createCheckpoint: (a: number) => number;
@@ -83,8 +78,8 @@ export interface InitOutput {
83
78
  readonly wasmlixtransaction_rollback: (a: number) => number;
84
79
  readonly wasmobserveevents_close: (a: number) => void;
85
80
  readonly wasmobserveevents_next: (a: number) => number;
86
- readonly __wasm_bindgen_func_elem_120695: (a: number, b: number, c: number, d: number) => void;
87
- readonly __wasm_bindgen_func_elem_120697: (a: number, b: number, c: number, d: number) => void;
81
+ readonly __wasm_bindgen_func_elem_119239: (a: number, b: number, c: number, d: number) => void;
82
+ readonly __wasm_bindgen_func_elem_119241: (a: number, b: number, c: number, d: number) => void;
88
83
  readonly __wbindgen_export: (a: number, b: number) => number;
89
84
  readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
90
85
  readonly __wbindgen_export3: (a: number) => void;