spacetimedb 2.4.1 → 2.5.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/LICENSE.txt +2 -2
- package/README.md +91 -0
- package/dist/browser/solid/index.mjs +1863 -0
- package/dist/browser/solid/index.mjs.map +1 -0
- package/dist/solid/SpacetimeDBProvider.d.ts +7 -0
- package/dist/solid/SpacetimeDBProvider.d.ts.map +1 -0
- package/dist/solid/connection_state.d.ts +6 -0
- package/dist/solid/connection_state.d.ts.map +1 -0
- package/dist/solid/index.cjs +1869 -0
- package/dist/solid/index.cjs.map +1 -0
- package/dist/solid/index.d.ts +6 -0
- package/dist/solid/index.d.ts.map +1 -0
- package/dist/solid/index.mjs +1863 -0
- package/dist/solid/index.mjs.map +1 -0
- package/dist/solid/useProcedure.d.ts +4 -0
- package/dist/solid/useProcedure.d.ts.map +1 -0
- package/dist/solid/useReducer.d.ts +4 -0
- package/dist/solid/useReducer.d.ts.map +1 -0
- package/dist/solid/useSpacetimeDB.d.ts +4 -0
- package/dist/solid/useSpacetimeDB.d.ts.map +1 -0
- package/dist/solid/useTable.d.ts +32 -0
- package/dist/solid/useTable.d.ts.map +1 -0
- package/package.json +13 -3
- package/src/solid/SpacetimeDBProvider.ts +97 -0
- package/src/solid/connection_state.ts +6 -0
- package/src/solid/index.ts +5 -0
- package/src/solid/useProcedure.ts +57 -0
- package/src/solid/useReducer.ts +50 -0
- package/src/solid/useSpacetimeDB.ts +18 -0
- package/src/solid/useTable.ts +203 -0
|
@@ -0,0 +1,1863 @@
|
|
|
1
|
+
import { fromByteArray } from 'base64-js';
|
|
2
|
+
import { createContext, useContext, createMemo, createComputed, onCleanup, createSignal, createEffect } from 'solid-js';
|
|
3
|
+
import { createStore, reconcile } from 'solid-js/store';
|
|
4
|
+
|
|
5
|
+
// src/lib/time_duration.ts
|
|
6
|
+
var TimeDuration = class _TimeDuration {
|
|
7
|
+
__time_duration_micros__;
|
|
8
|
+
static MICROS_PER_MILLIS = 1000n;
|
|
9
|
+
/**
|
|
10
|
+
* Get the algebraic type representation of the {@link TimeDuration} type.
|
|
11
|
+
* @returns The algebraic type representation of the type.
|
|
12
|
+
*/
|
|
13
|
+
static getAlgebraicType() {
|
|
14
|
+
return AlgebraicType.Product({
|
|
15
|
+
elements: [
|
|
16
|
+
{
|
|
17
|
+
name: "__time_duration_micros__",
|
|
18
|
+
algebraicType: AlgebraicType.I64
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
static isTimeDuration(algebraicType) {
|
|
24
|
+
if (algebraicType.tag !== "Product") {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
const elements = algebraicType.value.elements;
|
|
28
|
+
if (elements.length !== 1) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
const microsElement = elements[0];
|
|
32
|
+
return microsElement.name === "__time_duration_micros__" && microsElement.algebraicType.tag === "I64";
|
|
33
|
+
}
|
|
34
|
+
get micros() {
|
|
35
|
+
return this.__time_duration_micros__;
|
|
36
|
+
}
|
|
37
|
+
get millis() {
|
|
38
|
+
return Number(this.micros / _TimeDuration.MICROS_PER_MILLIS);
|
|
39
|
+
}
|
|
40
|
+
constructor(micros) {
|
|
41
|
+
this.__time_duration_micros__ = micros;
|
|
42
|
+
}
|
|
43
|
+
static fromMillis(millis) {
|
|
44
|
+
return new _TimeDuration(BigInt(millis) * _TimeDuration.MICROS_PER_MILLIS);
|
|
45
|
+
}
|
|
46
|
+
/** This outputs the same string format that we use in the host and in Rust modules */
|
|
47
|
+
toString() {
|
|
48
|
+
const micros = this.micros;
|
|
49
|
+
const sign = micros < 0 ? "-" : "+";
|
|
50
|
+
const pos = micros < 0 ? -micros : micros;
|
|
51
|
+
const secs = pos / 1000000n;
|
|
52
|
+
const micros_remaining = pos % 1000000n;
|
|
53
|
+
return `${sign}${secs}.${String(micros_remaining).padStart(6, "0")}`;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// src/lib/timestamp.ts
|
|
58
|
+
var Timestamp = class _Timestamp {
|
|
59
|
+
__timestamp_micros_since_unix_epoch__;
|
|
60
|
+
static MICROS_PER_MILLIS = 1000n;
|
|
61
|
+
get microsSinceUnixEpoch() {
|
|
62
|
+
return this.__timestamp_micros_since_unix_epoch__;
|
|
63
|
+
}
|
|
64
|
+
constructor(micros) {
|
|
65
|
+
this.__timestamp_micros_since_unix_epoch__ = micros;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get the algebraic type representation of the {@link Timestamp} type.
|
|
69
|
+
* @returns The algebraic type representation of the type.
|
|
70
|
+
*/
|
|
71
|
+
static getAlgebraicType() {
|
|
72
|
+
return AlgebraicType.Product({
|
|
73
|
+
elements: [
|
|
74
|
+
{
|
|
75
|
+
name: "__timestamp_micros_since_unix_epoch__",
|
|
76
|
+
algebraicType: AlgebraicType.I64
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
static isTimestamp(algebraicType) {
|
|
82
|
+
if (algebraicType.tag !== "Product") {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
const elements = algebraicType.value.elements;
|
|
86
|
+
if (elements.length !== 1) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
const microsElement = elements[0];
|
|
90
|
+
return microsElement.name === "__timestamp_micros_since_unix_epoch__" && microsElement.algebraicType.tag === "I64";
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The Unix epoch, the midnight at the beginning of January 1, 1970, UTC.
|
|
94
|
+
*/
|
|
95
|
+
static UNIX_EPOCH = new _Timestamp(0n);
|
|
96
|
+
/**
|
|
97
|
+
* Get a `Timestamp` representing the execution environment's belief of the current moment in time.
|
|
98
|
+
*/
|
|
99
|
+
static now() {
|
|
100
|
+
return _Timestamp.fromDate(/* @__PURE__ */ new Date());
|
|
101
|
+
}
|
|
102
|
+
/** Convert to milliseconds since Unix epoch. */
|
|
103
|
+
toMillis() {
|
|
104
|
+
return this.microsSinceUnixEpoch / 1000n;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Get a `Timestamp` representing the same point in time as `date`.
|
|
108
|
+
*/
|
|
109
|
+
static fromDate(date) {
|
|
110
|
+
const millis = date.getTime();
|
|
111
|
+
const micros = BigInt(millis) * _Timestamp.MICROS_PER_MILLIS;
|
|
112
|
+
return new _Timestamp(micros);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Get a `Date` representing approximately the same point in time as `this`.
|
|
116
|
+
*
|
|
117
|
+
* This method truncates to millisecond precision,
|
|
118
|
+
* and throws `RangeError` if the `Timestamp` is outside the range representable as a `Date`.
|
|
119
|
+
*/
|
|
120
|
+
toDate() {
|
|
121
|
+
const micros = this.__timestamp_micros_since_unix_epoch__;
|
|
122
|
+
const millis = micros / _Timestamp.MICROS_PER_MILLIS;
|
|
123
|
+
if (millis > BigInt(Number.MAX_SAFE_INTEGER) || millis < BigInt(Number.MIN_SAFE_INTEGER)) {
|
|
124
|
+
throw new RangeError(
|
|
125
|
+
"Timestamp is outside of the representable range of JS's Date"
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
return new Date(Number(millis));
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Get an ISO 8601 / RFC 3339 formatted string representation of this timestamp with microsecond precision.
|
|
132
|
+
*
|
|
133
|
+
* This method preserves the full microsecond precision of the timestamp,
|
|
134
|
+
* and throws `RangeError` if the `Timestamp` is outside the range representable in ISO format.
|
|
135
|
+
*
|
|
136
|
+
* @returns ISO 8601 formatted string with microsecond precision (e.g., '2025-02-17T10:30:45.123456Z')
|
|
137
|
+
*/
|
|
138
|
+
toISOString() {
|
|
139
|
+
const micros = this.__timestamp_micros_since_unix_epoch__;
|
|
140
|
+
const millis = micros / _Timestamp.MICROS_PER_MILLIS;
|
|
141
|
+
if (millis > BigInt(Number.MAX_SAFE_INTEGER) || millis < BigInt(Number.MIN_SAFE_INTEGER)) {
|
|
142
|
+
throw new RangeError(
|
|
143
|
+
"Timestamp is outside of the representable range for ISO string formatting"
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
const date = new Date(Number(millis));
|
|
147
|
+
const isoBase = date.toISOString();
|
|
148
|
+
const microsRemainder = Math.abs(Number(micros % 1000000n));
|
|
149
|
+
const fractionalPart = String(microsRemainder).padStart(6, "0");
|
|
150
|
+
return isoBase.replace(/\.\d{3}Z$/, `.${fractionalPart}Z`);
|
|
151
|
+
}
|
|
152
|
+
since(other) {
|
|
153
|
+
return new TimeDuration(
|
|
154
|
+
this.__timestamp_micros_since_unix_epoch__ - other.__timestamp_micros_since_unix_epoch__
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
// src/lib/uuid.ts
|
|
160
|
+
var Uuid = class _Uuid {
|
|
161
|
+
__uuid__;
|
|
162
|
+
/**
|
|
163
|
+
* The nil UUID (all zeros).
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```ts
|
|
167
|
+
* const uuid = Uuid.NIL;
|
|
168
|
+
* console.assert(
|
|
169
|
+
* uuid.toString() === "00000000-0000-0000-0000-000000000000"
|
|
170
|
+
* );
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
static NIL = new _Uuid(0n);
|
|
174
|
+
static MAX_UUID_BIGINT = 0xffffffffffffffffffffffffffffffffn;
|
|
175
|
+
/**
|
|
176
|
+
* The max UUID (all ones).
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```ts
|
|
180
|
+
* const uuid = Uuid.MAX;
|
|
181
|
+
* console.assert(
|
|
182
|
+
* uuid.toString() === "ffffffff-ffff-ffff-ffff-ffffffffffff"
|
|
183
|
+
* );
|
|
184
|
+
* ```
|
|
185
|
+
*/
|
|
186
|
+
static MAX = new _Uuid(_Uuid.MAX_UUID_BIGINT);
|
|
187
|
+
/**
|
|
188
|
+
* Create a UUID from a raw 128-bit value.
|
|
189
|
+
*
|
|
190
|
+
* @param u - Unsigned 128-bit integer
|
|
191
|
+
* @throws {Error} If the value is outside the valid UUID range
|
|
192
|
+
*/
|
|
193
|
+
constructor(u) {
|
|
194
|
+
if (u < 0n || u > _Uuid.MAX_UUID_BIGINT) {
|
|
195
|
+
throw new Error("Invalid UUID: must be between 0 and `MAX_UUID_BIGINT`");
|
|
196
|
+
}
|
|
197
|
+
this.__uuid__ = u;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Create a UUID `v4` from explicit random bytes.
|
|
201
|
+
*
|
|
202
|
+
* This method assumes the bytes are already sufficiently random.
|
|
203
|
+
* It only sets the appropriate bits for the UUID version and variant.
|
|
204
|
+
*
|
|
205
|
+
* @param bytes - Exactly 16 random bytes
|
|
206
|
+
* @returns A UUID `v4`
|
|
207
|
+
* @throws {Error} If `bytes.length !== 16`
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ```ts
|
|
211
|
+
* const randomBytes = new Uint8Array(16);
|
|
212
|
+
* const uuid = Uuid.fromRandomBytesV4(randomBytes);
|
|
213
|
+
*
|
|
214
|
+
* console.assert(
|
|
215
|
+
* uuid.toString() === "00000000-0000-4000-8000-000000000000"
|
|
216
|
+
* );
|
|
217
|
+
* ```
|
|
218
|
+
*/
|
|
219
|
+
static fromRandomBytesV4(bytes) {
|
|
220
|
+
if (bytes.length !== 16) throw new Error("UUID v4 requires 16 bytes");
|
|
221
|
+
const arr = new Uint8Array(bytes);
|
|
222
|
+
arr[6] = arr[6] & 15 | 64;
|
|
223
|
+
arr[8] = arr[8] & 63 | 128;
|
|
224
|
+
return new _Uuid(_Uuid.bytesToBigInt(arr));
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Generate a UUID `v7` using a monotonic counter from `0` to `2^31 - 1`,
|
|
228
|
+
* a timestamp, and 4 random bytes.
|
|
229
|
+
*
|
|
230
|
+
* The counter wraps around on overflow.
|
|
231
|
+
*
|
|
232
|
+
* The UUID `v7` is structured as follows:
|
|
233
|
+
*
|
|
234
|
+
* ```ascii
|
|
235
|
+
* ┌───────────────────────────────────────────────┬───────────────────┐
|
|
236
|
+
* | B0 | B1 | B2 | B3 | B4 | B5 | B6 |
|
|
237
|
+
* ├───────────────────────────────────────────────┼───────────────────┤
|
|
238
|
+
* | unix_ts_ms | version 7 |
|
|
239
|
+
* └───────────────────────────────────────────────┴───────────────────┘
|
|
240
|
+
* ┌──────────────┬─────────┬──────────────────┬───────────────────────┐
|
|
241
|
+
* | B7 | B8 | B9 | B10 | B11 | B12 | B13 | B14 | B15 |
|
|
242
|
+
* ├──────────────┼─────────┼──────────────────┼───────────────────────┤
|
|
243
|
+
* | counter_high | variant | counter_low | random |
|
|
244
|
+
* └──────────────┴─────────┴──────────────────┴───────────────────────┘
|
|
245
|
+
* ```
|
|
246
|
+
*
|
|
247
|
+
* @param counter - Mutable monotonic counter (31-bit)
|
|
248
|
+
* @param now - Timestamp since the Unix epoch
|
|
249
|
+
* @param randomBytes - Exactly 4 random bytes
|
|
250
|
+
* @returns A UUID `v7`
|
|
251
|
+
*
|
|
252
|
+
* @throws {Error} If the `counter` is negative
|
|
253
|
+
* @throws {Error} If the `timestamp` is before the Unix epoch
|
|
254
|
+
* @throws {Error} If `randomBytes.length !== 4`
|
|
255
|
+
*
|
|
256
|
+
* @example
|
|
257
|
+
* ```ts
|
|
258
|
+
* const now = Timestamp.fromMillis(1_686_000_000_000n);
|
|
259
|
+
* const counter = { value: 1 };
|
|
260
|
+
* const randomBytes = new Uint8Array(4);
|
|
261
|
+
*
|
|
262
|
+
* const uuid = Uuid.fromCounterV7(counter, now, randomBytes);
|
|
263
|
+
*
|
|
264
|
+
* console.assert(
|
|
265
|
+
* uuid.toString() === "0000647e-5180-7000-8000-000200000000"
|
|
266
|
+
* );
|
|
267
|
+
* ```
|
|
268
|
+
*/
|
|
269
|
+
static fromCounterV7(counter, now, randomBytes) {
|
|
270
|
+
if (randomBytes.length !== 4) {
|
|
271
|
+
throw new Error("`fromCounterV7` requires `randomBytes.length == 4`");
|
|
272
|
+
}
|
|
273
|
+
if (counter.value < 0) {
|
|
274
|
+
throw new Error("`fromCounterV7` uuid `counter` must be non-negative");
|
|
275
|
+
}
|
|
276
|
+
if (now.__timestamp_micros_since_unix_epoch__ < 0) {
|
|
277
|
+
throw new Error("`fromCounterV7` `timestamp` before unix epoch");
|
|
278
|
+
}
|
|
279
|
+
const counterVal = counter.value;
|
|
280
|
+
counter.value = counterVal + 1 & 2147483647;
|
|
281
|
+
const tsMs = now.toMillis() & 0xffffffffffffn;
|
|
282
|
+
const bytes = new Uint8Array(16);
|
|
283
|
+
bytes[0] = Number(tsMs >> 40n & 0xffn);
|
|
284
|
+
bytes[1] = Number(tsMs >> 32n & 0xffn);
|
|
285
|
+
bytes[2] = Number(tsMs >> 24n & 0xffn);
|
|
286
|
+
bytes[3] = Number(tsMs >> 16n & 0xffn);
|
|
287
|
+
bytes[4] = Number(tsMs >> 8n & 0xffn);
|
|
288
|
+
bytes[5] = Number(tsMs & 0xffn);
|
|
289
|
+
bytes[7] = counterVal >>> 23 & 255;
|
|
290
|
+
bytes[9] = counterVal >>> 15 & 255;
|
|
291
|
+
bytes[10] = counterVal >>> 7 & 255;
|
|
292
|
+
bytes[11] = (counterVal & 127) << 1 & 255;
|
|
293
|
+
bytes[12] |= randomBytes[0] & 127;
|
|
294
|
+
bytes[13] = randomBytes[1];
|
|
295
|
+
bytes[14] = randomBytes[2];
|
|
296
|
+
bytes[15] = randomBytes[3];
|
|
297
|
+
bytes[6] = bytes[6] & 15 | 112;
|
|
298
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
299
|
+
return new _Uuid(_Uuid.bytesToBigInt(bytes));
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Parse a UUID from a string representation.
|
|
303
|
+
*
|
|
304
|
+
* @param s - UUID string
|
|
305
|
+
* @returns Parsed UUID
|
|
306
|
+
* @throws {Error} If the string is not a valid UUID
|
|
307
|
+
*
|
|
308
|
+
* @example
|
|
309
|
+
* ```ts
|
|
310
|
+
* const s = "01888d6e-5c00-7000-8000-000000000000";
|
|
311
|
+
* const uuid = Uuid.parse(s);
|
|
312
|
+
*
|
|
313
|
+
* console.assert(uuid.toString() === s);
|
|
314
|
+
* ```
|
|
315
|
+
*/
|
|
316
|
+
static parse(s) {
|
|
317
|
+
const hex = s.replace(/-/g, "");
|
|
318
|
+
if (hex.length !== 32) throw new Error("Invalid hex UUID");
|
|
319
|
+
let v = 0n;
|
|
320
|
+
for (let i = 0; i < 32; i += 2) {
|
|
321
|
+
v = v << 8n | BigInt(parseInt(hex.slice(i, i + 2), 16));
|
|
322
|
+
}
|
|
323
|
+
return new _Uuid(v);
|
|
324
|
+
}
|
|
325
|
+
/** Convert to string (hyphenated form). */
|
|
326
|
+
toString() {
|
|
327
|
+
const bytes = _Uuid.bigIntToBytes(this.__uuid__);
|
|
328
|
+
const hex = [...bytes].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
329
|
+
return hex.slice(0, 8) + "-" + hex.slice(8, 12) + "-" + hex.slice(12, 16) + "-" + hex.slice(16, 20) + "-" + hex.slice(20);
|
|
330
|
+
}
|
|
331
|
+
/** Convert to bigint (u128). */
|
|
332
|
+
asBigInt() {
|
|
333
|
+
return this.__uuid__;
|
|
334
|
+
}
|
|
335
|
+
/** Return a `Uint8Array` of 16 bytes. */
|
|
336
|
+
toBytes() {
|
|
337
|
+
return _Uuid.bigIntToBytes(this.__uuid__);
|
|
338
|
+
}
|
|
339
|
+
static bytesToBigInt(bytes) {
|
|
340
|
+
let result = 0n;
|
|
341
|
+
for (const b of bytes) result = result << 8n | BigInt(b);
|
|
342
|
+
return result;
|
|
343
|
+
}
|
|
344
|
+
static bigIntToBytes(value) {
|
|
345
|
+
const bytes = new Uint8Array(16);
|
|
346
|
+
for (let i = 15; i >= 0; i--) {
|
|
347
|
+
bytes[i] = Number(value & 0xffn);
|
|
348
|
+
value >>= 8n;
|
|
349
|
+
}
|
|
350
|
+
return bytes;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Returns the version of this UUID.
|
|
354
|
+
*
|
|
355
|
+
* This represents the algorithm used to generate the value.
|
|
356
|
+
*
|
|
357
|
+
* @returns A `UuidVersion`
|
|
358
|
+
* @throws {Error} If the version field is not recognized
|
|
359
|
+
*/
|
|
360
|
+
getVersion() {
|
|
361
|
+
const version = this.toBytes()[6] >> 4 & 15;
|
|
362
|
+
switch (version) {
|
|
363
|
+
case 4:
|
|
364
|
+
return "V4";
|
|
365
|
+
case 7:
|
|
366
|
+
return "V7";
|
|
367
|
+
default:
|
|
368
|
+
if (this == _Uuid.NIL) {
|
|
369
|
+
return "Nil";
|
|
370
|
+
}
|
|
371
|
+
if (this == _Uuid.MAX) {
|
|
372
|
+
return "Max";
|
|
373
|
+
}
|
|
374
|
+
throw new Error(`Unsupported UUID version: ${version}`);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Extract the monotonic counter from a UUIDv7.
|
|
379
|
+
*
|
|
380
|
+
* Intended for testing and diagnostics.
|
|
381
|
+
* Behavior is undefined if called on a non-V7 UUID.
|
|
382
|
+
*
|
|
383
|
+
* @returns 31-bit counter value
|
|
384
|
+
*/
|
|
385
|
+
getCounter() {
|
|
386
|
+
const bytes = this.toBytes();
|
|
387
|
+
const high = bytes[7];
|
|
388
|
+
const mid1 = bytes[9];
|
|
389
|
+
const mid2 = bytes[10];
|
|
390
|
+
const low = bytes[11] >>> 1;
|
|
391
|
+
return high << 23 | mid1 << 15 | mid2 << 7 | low | 0;
|
|
392
|
+
}
|
|
393
|
+
compareTo(other) {
|
|
394
|
+
if (this.__uuid__ < other.__uuid__) return -1;
|
|
395
|
+
if (this.__uuid__ > other.__uuid__) return 1;
|
|
396
|
+
return 0;
|
|
397
|
+
}
|
|
398
|
+
static getAlgebraicType() {
|
|
399
|
+
return AlgebraicType.Product({
|
|
400
|
+
elements: [
|
|
401
|
+
{
|
|
402
|
+
name: "__uuid__",
|
|
403
|
+
algebraicType: AlgebraicType.U128
|
|
404
|
+
}
|
|
405
|
+
]
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
// src/lib/binary_reader.ts
|
|
411
|
+
var BinaryReader = class {
|
|
412
|
+
/**
|
|
413
|
+
* The DataView used to read values from the binary data.
|
|
414
|
+
*
|
|
415
|
+
* Note: The DataView's `byteOffset` is relative to the beginning of the
|
|
416
|
+
* underlying ArrayBuffer, not the start of the provided Uint8Array input.
|
|
417
|
+
* This `BinaryReader`'s `#offset` field is used to track the current read position
|
|
418
|
+
* relative to the start of the provided Uint8Array input.
|
|
419
|
+
*/
|
|
420
|
+
view;
|
|
421
|
+
/**
|
|
422
|
+
* Represents the offset (in bytes) relative to the start of the DataView
|
|
423
|
+
* and provided Uint8Array input.
|
|
424
|
+
*
|
|
425
|
+
* Note: This is *not* the absolute byte offset within the underlying ArrayBuffer.
|
|
426
|
+
*/
|
|
427
|
+
offset = 0;
|
|
428
|
+
constructor(input) {
|
|
429
|
+
this.view = input instanceof DataView ? input : new DataView(input.buffer, input.byteOffset, input.byteLength);
|
|
430
|
+
this.offset = 0;
|
|
431
|
+
}
|
|
432
|
+
reset(input) {
|
|
433
|
+
this.view = input instanceof DataView ? input : new DataView(input.buffer, input.byteOffset, input.byteLength);
|
|
434
|
+
this.offset = 0;
|
|
435
|
+
}
|
|
436
|
+
get remaining() {
|
|
437
|
+
return this.view.byteLength - this.offset;
|
|
438
|
+
}
|
|
439
|
+
/** Ensure we have at least `n` bytes left to read */
|
|
440
|
+
#ensure(n) {
|
|
441
|
+
if (this.offset + n > this.view.byteLength) {
|
|
442
|
+
throw new RangeError(
|
|
443
|
+
`Tried to read ${n} byte(s) at relative offset ${this.offset}, but only ${this.remaining} byte(s) remain`
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
readUInt8Array() {
|
|
448
|
+
const length = this.readU32();
|
|
449
|
+
this.#ensure(length);
|
|
450
|
+
return this.readBytes(length);
|
|
451
|
+
}
|
|
452
|
+
readBool() {
|
|
453
|
+
const value = this.view.getUint8(this.offset);
|
|
454
|
+
this.offset += 1;
|
|
455
|
+
return value !== 0;
|
|
456
|
+
}
|
|
457
|
+
readByte() {
|
|
458
|
+
const value = this.view.getUint8(this.offset);
|
|
459
|
+
this.offset += 1;
|
|
460
|
+
return value;
|
|
461
|
+
}
|
|
462
|
+
readBytes(length) {
|
|
463
|
+
const array = new Uint8Array(
|
|
464
|
+
this.view.buffer,
|
|
465
|
+
this.view.byteOffset + this.offset,
|
|
466
|
+
length
|
|
467
|
+
);
|
|
468
|
+
this.offset += length;
|
|
469
|
+
return array;
|
|
470
|
+
}
|
|
471
|
+
readI8() {
|
|
472
|
+
const value = this.view.getInt8(this.offset);
|
|
473
|
+
this.offset += 1;
|
|
474
|
+
return value;
|
|
475
|
+
}
|
|
476
|
+
readU8() {
|
|
477
|
+
return this.readByte();
|
|
478
|
+
}
|
|
479
|
+
readI16() {
|
|
480
|
+
const value = this.view.getInt16(this.offset, true);
|
|
481
|
+
this.offset += 2;
|
|
482
|
+
return value;
|
|
483
|
+
}
|
|
484
|
+
readU16() {
|
|
485
|
+
const value = this.view.getUint16(this.offset, true);
|
|
486
|
+
this.offset += 2;
|
|
487
|
+
return value;
|
|
488
|
+
}
|
|
489
|
+
readI32() {
|
|
490
|
+
const value = this.view.getInt32(this.offset, true);
|
|
491
|
+
this.offset += 4;
|
|
492
|
+
return value;
|
|
493
|
+
}
|
|
494
|
+
readU32() {
|
|
495
|
+
const value = this.view.getUint32(this.offset, true);
|
|
496
|
+
this.offset += 4;
|
|
497
|
+
return value;
|
|
498
|
+
}
|
|
499
|
+
readI64() {
|
|
500
|
+
const value = this.view.getBigInt64(this.offset, true);
|
|
501
|
+
this.offset += 8;
|
|
502
|
+
return value;
|
|
503
|
+
}
|
|
504
|
+
readU64() {
|
|
505
|
+
const value = this.view.getBigUint64(this.offset, true);
|
|
506
|
+
this.offset += 8;
|
|
507
|
+
return value;
|
|
508
|
+
}
|
|
509
|
+
readU128() {
|
|
510
|
+
const lowerPart = this.view.getBigUint64(this.offset, true);
|
|
511
|
+
const upperPart = this.view.getBigUint64(this.offset + 8, true);
|
|
512
|
+
this.offset += 16;
|
|
513
|
+
return (upperPart << BigInt(64)) + lowerPart;
|
|
514
|
+
}
|
|
515
|
+
readI128() {
|
|
516
|
+
const lowerPart = this.view.getBigUint64(this.offset, true);
|
|
517
|
+
const upperPart = this.view.getBigInt64(this.offset + 8, true);
|
|
518
|
+
this.offset += 16;
|
|
519
|
+
return (upperPart << BigInt(64)) + lowerPart;
|
|
520
|
+
}
|
|
521
|
+
readU256() {
|
|
522
|
+
const p0 = this.view.getBigUint64(this.offset, true);
|
|
523
|
+
const p1 = this.view.getBigUint64(this.offset + 8, true);
|
|
524
|
+
const p2 = this.view.getBigUint64(this.offset + 16, true);
|
|
525
|
+
const p3 = this.view.getBigUint64(this.offset + 24, true);
|
|
526
|
+
this.offset += 32;
|
|
527
|
+
return (p3 << BigInt(3 * 64)) + (p2 << BigInt(2 * 64)) + (p1 << BigInt(1 * 64)) + p0;
|
|
528
|
+
}
|
|
529
|
+
readI256() {
|
|
530
|
+
const p0 = this.view.getBigUint64(this.offset, true);
|
|
531
|
+
const p1 = this.view.getBigUint64(this.offset + 8, true);
|
|
532
|
+
const p2 = this.view.getBigUint64(this.offset + 16, true);
|
|
533
|
+
const p3 = this.view.getBigInt64(this.offset + 24, true);
|
|
534
|
+
this.offset += 32;
|
|
535
|
+
return (p3 << BigInt(3 * 64)) + (p2 << BigInt(2 * 64)) + (p1 << BigInt(1 * 64)) + p0;
|
|
536
|
+
}
|
|
537
|
+
readF32() {
|
|
538
|
+
const value = this.view.getFloat32(this.offset, true);
|
|
539
|
+
this.offset += 4;
|
|
540
|
+
return value;
|
|
541
|
+
}
|
|
542
|
+
readF64() {
|
|
543
|
+
const value = this.view.getFloat64(this.offset, true);
|
|
544
|
+
this.offset += 8;
|
|
545
|
+
return value;
|
|
546
|
+
}
|
|
547
|
+
readString() {
|
|
548
|
+
const uint8Array = this.readUInt8Array();
|
|
549
|
+
return new TextDecoder("utf-8").decode(uint8Array);
|
|
550
|
+
}
|
|
551
|
+
};
|
|
552
|
+
var ArrayBufferPrototypeTransfer = ArrayBuffer.prototype.transfer ?? function(newByteLength) {
|
|
553
|
+
if (newByteLength === void 0) {
|
|
554
|
+
return this.slice();
|
|
555
|
+
} else if (newByteLength <= this.byteLength) {
|
|
556
|
+
return this.slice(0, newByteLength);
|
|
557
|
+
} else {
|
|
558
|
+
const copy = new Uint8Array(newByteLength);
|
|
559
|
+
copy.set(new Uint8Array(this));
|
|
560
|
+
return copy.buffer;
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
var ResizableBuffer = class {
|
|
564
|
+
buffer;
|
|
565
|
+
view;
|
|
566
|
+
constructor(init) {
|
|
567
|
+
this.buffer = typeof init === "number" ? new ArrayBuffer(init) : init;
|
|
568
|
+
this.view = new DataView(this.buffer);
|
|
569
|
+
}
|
|
570
|
+
get capacity() {
|
|
571
|
+
return this.buffer.byteLength;
|
|
572
|
+
}
|
|
573
|
+
grow(newSize) {
|
|
574
|
+
if (newSize <= this.buffer.byteLength) return;
|
|
575
|
+
this.buffer = ArrayBufferPrototypeTransfer.call(this.buffer, newSize);
|
|
576
|
+
this.view = new DataView(this.buffer);
|
|
577
|
+
}
|
|
578
|
+
};
|
|
579
|
+
var BinaryWriter = class {
|
|
580
|
+
buffer;
|
|
581
|
+
offset = 0;
|
|
582
|
+
constructor(init) {
|
|
583
|
+
this.buffer = typeof init === "number" ? new ResizableBuffer(init) : init;
|
|
584
|
+
}
|
|
585
|
+
clear() {
|
|
586
|
+
this.offset = 0;
|
|
587
|
+
}
|
|
588
|
+
reset(buffer) {
|
|
589
|
+
this.buffer = buffer;
|
|
590
|
+
this.offset = 0;
|
|
591
|
+
}
|
|
592
|
+
expandBuffer(additionalCapacity) {
|
|
593
|
+
const minCapacity = this.offset + additionalCapacity + 1;
|
|
594
|
+
if (minCapacity <= this.buffer.capacity) return;
|
|
595
|
+
let newCapacity = this.buffer.capacity * 2;
|
|
596
|
+
if (newCapacity < minCapacity) newCapacity = minCapacity;
|
|
597
|
+
this.buffer.grow(newCapacity);
|
|
598
|
+
}
|
|
599
|
+
toBase64() {
|
|
600
|
+
return fromByteArray(this.getBuffer());
|
|
601
|
+
}
|
|
602
|
+
getBuffer() {
|
|
603
|
+
return new Uint8Array(this.buffer.buffer, 0, this.offset);
|
|
604
|
+
}
|
|
605
|
+
get view() {
|
|
606
|
+
return this.buffer.view;
|
|
607
|
+
}
|
|
608
|
+
writeUInt8Array(value) {
|
|
609
|
+
const length = value.length;
|
|
610
|
+
this.expandBuffer(4 + length);
|
|
611
|
+
this.writeU32(length);
|
|
612
|
+
new Uint8Array(this.buffer.buffer, this.offset).set(value);
|
|
613
|
+
this.offset += length;
|
|
614
|
+
}
|
|
615
|
+
writeBool(value) {
|
|
616
|
+
this.expandBuffer(1);
|
|
617
|
+
this.view.setUint8(this.offset, value ? 1 : 0);
|
|
618
|
+
this.offset += 1;
|
|
619
|
+
}
|
|
620
|
+
writeByte(value) {
|
|
621
|
+
this.expandBuffer(1);
|
|
622
|
+
this.view.setUint8(this.offset, value);
|
|
623
|
+
this.offset += 1;
|
|
624
|
+
}
|
|
625
|
+
writeBytes(value) {
|
|
626
|
+
this.expandBuffer(value.length);
|
|
627
|
+
new Uint8Array(this.buffer.buffer, this.offset, value.length).set(value);
|
|
628
|
+
this.offset += value.length;
|
|
629
|
+
}
|
|
630
|
+
writeI8(value) {
|
|
631
|
+
this.expandBuffer(1);
|
|
632
|
+
this.view.setInt8(this.offset, value);
|
|
633
|
+
this.offset += 1;
|
|
634
|
+
}
|
|
635
|
+
writeU8(value) {
|
|
636
|
+
this.expandBuffer(1);
|
|
637
|
+
this.view.setUint8(this.offset, value);
|
|
638
|
+
this.offset += 1;
|
|
639
|
+
}
|
|
640
|
+
writeI16(value) {
|
|
641
|
+
this.expandBuffer(2);
|
|
642
|
+
this.view.setInt16(this.offset, value, true);
|
|
643
|
+
this.offset += 2;
|
|
644
|
+
}
|
|
645
|
+
writeU16(value) {
|
|
646
|
+
this.expandBuffer(2);
|
|
647
|
+
this.view.setUint16(this.offset, value, true);
|
|
648
|
+
this.offset += 2;
|
|
649
|
+
}
|
|
650
|
+
writeI32(value) {
|
|
651
|
+
this.expandBuffer(4);
|
|
652
|
+
this.view.setInt32(this.offset, value, true);
|
|
653
|
+
this.offset += 4;
|
|
654
|
+
}
|
|
655
|
+
writeU32(value) {
|
|
656
|
+
this.expandBuffer(4);
|
|
657
|
+
this.view.setUint32(this.offset, value, true);
|
|
658
|
+
this.offset += 4;
|
|
659
|
+
}
|
|
660
|
+
writeI64(value) {
|
|
661
|
+
this.expandBuffer(8);
|
|
662
|
+
this.view.setBigInt64(this.offset, value, true);
|
|
663
|
+
this.offset += 8;
|
|
664
|
+
}
|
|
665
|
+
writeU64(value) {
|
|
666
|
+
this.expandBuffer(8);
|
|
667
|
+
this.view.setBigUint64(this.offset, value, true);
|
|
668
|
+
this.offset += 8;
|
|
669
|
+
}
|
|
670
|
+
writeU128(value) {
|
|
671
|
+
this.expandBuffer(16);
|
|
672
|
+
const lowerPart = value & BigInt("0xFFFFFFFFFFFFFFFF");
|
|
673
|
+
const upperPart = value >> BigInt(64);
|
|
674
|
+
this.view.setBigUint64(this.offset, lowerPart, true);
|
|
675
|
+
this.view.setBigUint64(this.offset + 8, upperPart, true);
|
|
676
|
+
this.offset += 16;
|
|
677
|
+
}
|
|
678
|
+
writeI128(value) {
|
|
679
|
+
this.expandBuffer(16);
|
|
680
|
+
const lowerPart = value & BigInt("0xFFFFFFFFFFFFFFFF");
|
|
681
|
+
const upperPart = value >> BigInt(64);
|
|
682
|
+
this.view.setBigInt64(this.offset, lowerPart, true);
|
|
683
|
+
this.view.setBigInt64(this.offset + 8, upperPart, true);
|
|
684
|
+
this.offset += 16;
|
|
685
|
+
}
|
|
686
|
+
writeU256(value) {
|
|
687
|
+
this.expandBuffer(32);
|
|
688
|
+
const low_64_mask = BigInt("0xFFFFFFFFFFFFFFFF");
|
|
689
|
+
const p0 = value & low_64_mask;
|
|
690
|
+
const p1 = value >> BigInt(64 * 1) & low_64_mask;
|
|
691
|
+
const p2 = value >> BigInt(64 * 2) & low_64_mask;
|
|
692
|
+
const p3 = value >> BigInt(64 * 3);
|
|
693
|
+
this.view.setBigUint64(this.offset + 8 * 0, p0, true);
|
|
694
|
+
this.view.setBigUint64(this.offset + 8 * 1, p1, true);
|
|
695
|
+
this.view.setBigUint64(this.offset + 8 * 2, p2, true);
|
|
696
|
+
this.view.setBigUint64(this.offset + 8 * 3, p3, true);
|
|
697
|
+
this.offset += 32;
|
|
698
|
+
}
|
|
699
|
+
writeI256(value) {
|
|
700
|
+
this.expandBuffer(32);
|
|
701
|
+
const low_64_mask = BigInt("0xFFFFFFFFFFFFFFFF");
|
|
702
|
+
const p0 = value & low_64_mask;
|
|
703
|
+
const p1 = value >> BigInt(64 * 1) & low_64_mask;
|
|
704
|
+
const p2 = value >> BigInt(64 * 2) & low_64_mask;
|
|
705
|
+
const p3 = value >> BigInt(64 * 3);
|
|
706
|
+
this.view.setBigUint64(this.offset + 8 * 0, p0, true);
|
|
707
|
+
this.view.setBigUint64(this.offset + 8 * 1, p1, true);
|
|
708
|
+
this.view.setBigUint64(this.offset + 8 * 2, p2, true);
|
|
709
|
+
this.view.setBigInt64(this.offset + 8 * 3, p3, true);
|
|
710
|
+
this.offset += 32;
|
|
711
|
+
}
|
|
712
|
+
writeF32(value) {
|
|
713
|
+
this.expandBuffer(4);
|
|
714
|
+
this.view.setFloat32(this.offset, value, true);
|
|
715
|
+
this.offset += 4;
|
|
716
|
+
}
|
|
717
|
+
writeF64(value) {
|
|
718
|
+
this.expandBuffer(8);
|
|
719
|
+
this.view.setFloat64(this.offset, value, true);
|
|
720
|
+
this.offset += 8;
|
|
721
|
+
}
|
|
722
|
+
writeString(value) {
|
|
723
|
+
const encoder = new TextEncoder();
|
|
724
|
+
const encodedString = encoder.encode(value);
|
|
725
|
+
this.writeUInt8Array(encodedString);
|
|
726
|
+
}
|
|
727
|
+
};
|
|
728
|
+
|
|
729
|
+
// src/lib/util.ts
|
|
730
|
+
function uint8ArrayToHexString(array) {
|
|
731
|
+
return Array.prototype.map.call(array.reverse(), (x) => ("00" + x.toString(16)).slice(-2)).join("");
|
|
732
|
+
}
|
|
733
|
+
function uint8ArrayToU128(array) {
|
|
734
|
+
if (array.length != 16) {
|
|
735
|
+
throw new Error(`Uint8Array is not 16 bytes long: ${array}`);
|
|
736
|
+
}
|
|
737
|
+
return new BinaryReader(array).readU128();
|
|
738
|
+
}
|
|
739
|
+
function uint8ArrayToU256(array) {
|
|
740
|
+
if (array.length != 32) {
|
|
741
|
+
throw new Error(`Uint8Array is not 32 bytes long: [${array}]`);
|
|
742
|
+
}
|
|
743
|
+
return new BinaryReader(array).readU256();
|
|
744
|
+
}
|
|
745
|
+
function hexStringToUint8Array(str) {
|
|
746
|
+
if (str.startsWith("0x")) {
|
|
747
|
+
str = str.slice(2);
|
|
748
|
+
}
|
|
749
|
+
const matches = str.match(/.{1,2}/g) || [];
|
|
750
|
+
const data = Uint8Array.from(
|
|
751
|
+
matches.map((byte) => parseInt(byte, 16))
|
|
752
|
+
);
|
|
753
|
+
return data.reverse();
|
|
754
|
+
}
|
|
755
|
+
function hexStringToU128(str) {
|
|
756
|
+
return uint8ArrayToU128(hexStringToUint8Array(str));
|
|
757
|
+
}
|
|
758
|
+
function hexStringToU256(str) {
|
|
759
|
+
return uint8ArrayToU256(hexStringToUint8Array(str));
|
|
760
|
+
}
|
|
761
|
+
function u128ToUint8Array(data) {
|
|
762
|
+
const writer = new BinaryWriter(16);
|
|
763
|
+
writer.writeU128(data);
|
|
764
|
+
return writer.getBuffer();
|
|
765
|
+
}
|
|
766
|
+
function u128ToHexString(data) {
|
|
767
|
+
return uint8ArrayToHexString(u128ToUint8Array(data));
|
|
768
|
+
}
|
|
769
|
+
function u256ToUint8Array(data) {
|
|
770
|
+
const writer = new BinaryWriter(32);
|
|
771
|
+
writer.writeU256(data);
|
|
772
|
+
return writer.getBuffer();
|
|
773
|
+
}
|
|
774
|
+
function u256ToHexString(data) {
|
|
775
|
+
return uint8ArrayToHexString(u256ToUint8Array(data));
|
|
776
|
+
}
|
|
777
|
+
var hasOwn = Object.hasOwn;
|
|
778
|
+
|
|
779
|
+
// src/lib/identity.ts
|
|
780
|
+
var Identity = class _Identity {
|
|
781
|
+
__identity__;
|
|
782
|
+
/**
|
|
783
|
+
* Creates a new `Identity`.
|
|
784
|
+
*
|
|
785
|
+
* `data` can be a hexadecimal string or a `bigint`.
|
|
786
|
+
*/
|
|
787
|
+
constructor(data) {
|
|
788
|
+
this.__identity__ = typeof data === "string" ? hexStringToU256(data) : data;
|
|
789
|
+
}
|
|
790
|
+
/**
|
|
791
|
+
* Get the algebraic type representation of the {@link Identity} type.
|
|
792
|
+
* @returns The algebraic type representation of the type.
|
|
793
|
+
*/
|
|
794
|
+
static getAlgebraicType() {
|
|
795
|
+
return AlgebraicType.Product({
|
|
796
|
+
elements: [{ name: "__identity__", algebraicType: AlgebraicType.U256 }]
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
/**
|
|
800
|
+
* Check if two identities are equal.
|
|
801
|
+
*/
|
|
802
|
+
isEqual(other) {
|
|
803
|
+
return this.toHexString() === other.toHexString();
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* Check if two identities are equal.
|
|
807
|
+
*/
|
|
808
|
+
equals(other) {
|
|
809
|
+
return this.isEqual(other);
|
|
810
|
+
}
|
|
811
|
+
/**
|
|
812
|
+
* Print the identity as a hexadecimal string.
|
|
813
|
+
*/
|
|
814
|
+
toHexString() {
|
|
815
|
+
return u256ToHexString(this.__identity__);
|
|
816
|
+
}
|
|
817
|
+
/**
|
|
818
|
+
* Convert the address to a Uint8Array.
|
|
819
|
+
*/
|
|
820
|
+
toUint8Array() {
|
|
821
|
+
return u256ToUint8Array(this.__identity__);
|
|
822
|
+
}
|
|
823
|
+
/**
|
|
824
|
+
* Parse an Identity from a hexadecimal string.
|
|
825
|
+
*/
|
|
826
|
+
static fromString(str) {
|
|
827
|
+
return new _Identity(str);
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* Zero identity (0x0000000000000000000000000000000000000000000000000000000000000000)
|
|
831
|
+
*/
|
|
832
|
+
static zero() {
|
|
833
|
+
return new _Identity(0n);
|
|
834
|
+
}
|
|
835
|
+
toString() {
|
|
836
|
+
return this.toHexString();
|
|
837
|
+
}
|
|
838
|
+
};
|
|
839
|
+
|
|
840
|
+
// src/lib/algebraic_type.ts
|
|
841
|
+
var SERIALIZERS = /* @__PURE__ */ new Map();
|
|
842
|
+
var DESERIALIZERS = /* @__PURE__ */ new Map();
|
|
843
|
+
var AlgebraicType = {
|
|
844
|
+
Ref: (value) => ({ tag: "Ref", value }),
|
|
845
|
+
Sum: (value) => ({
|
|
846
|
+
tag: "Sum",
|
|
847
|
+
value
|
|
848
|
+
}),
|
|
849
|
+
Product: (value) => ({
|
|
850
|
+
tag: "Product",
|
|
851
|
+
value
|
|
852
|
+
}),
|
|
853
|
+
Array: (value) => ({
|
|
854
|
+
tag: "Array",
|
|
855
|
+
value
|
|
856
|
+
}),
|
|
857
|
+
String: { tag: "String" },
|
|
858
|
+
Bool: { tag: "Bool" },
|
|
859
|
+
I8: { tag: "I8" },
|
|
860
|
+
U8: { tag: "U8" },
|
|
861
|
+
I16: { tag: "I16" },
|
|
862
|
+
U16: { tag: "U16" },
|
|
863
|
+
I32: { tag: "I32" },
|
|
864
|
+
U32: { tag: "U32" },
|
|
865
|
+
I64: { tag: "I64" },
|
|
866
|
+
U64: { tag: "U64" },
|
|
867
|
+
I128: { tag: "I128" },
|
|
868
|
+
U128: { tag: "U128" },
|
|
869
|
+
I256: { tag: "I256" },
|
|
870
|
+
U256: { tag: "U256" },
|
|
871
|
+
F32: { tag: "F32" },
|
|
872
|
+
F64: { tag: "F64" },
|
|
873
|
+
makeSerializer(ty, typespace) {
|
|
874
|
+
if (ty.tag === "Ref") {
|
|
875
|
+
if (!typespace)
|
|
876
|
+
throw new Error("cannot serialize refs without a typespace");
|
|
877
|
+
while (ty.tag === "Ref") ty = typespace.types[ty.value];
|
|
878
|
+
}
|
|
879
|
+
switch (ty.tag) {
|
|
880
|
+
case "Product":
|
|
881
|
+
return ProductType.makeSerializer(ty.value, typespace);
|
|
882
|
+
case "Sum":
|
|
883
|
+
return SumType.makeSerializer(ty.value, typespace);
|
|
884
|
+
case "Array":
|
|
885
|
+
if (ty.value.tag === "U8") {
|
|
886
|
+
return serializeUint8Array;
|
|
887
|
+
} else {
|
|
888
|
+
const serialize = AlgebraicType.makeSerializer(ty.value, typespace);
|
|
889
|
+
return (writer, value) => {
|
|
890
|
+
writer.writeU32(value.length);
|
|
891
|
+
for (const elem of value) {
|
|
892
|
+
serialize(writer, elem);
|
|
893
|
+
}
|
|
894
|
+
};
|
|
895
|
+
}
|
|
896
|
+
default:
|
|
897
|
+
return primitiveSerializers[ty.tag];
|
|
898
|
+
}
|
|
899
|
+
},
|
|
900
|
+
/** @deprecated Use `makeSerializer` instead. */
|
|
901
|
+
serializeValue(writer, ty, value, typespace) {
|
|
902
|
+
AlgebraicType.makeSerializer(ty, typespace)(writer, value);
|
|
903
|
+
},
|
|
904
|
+
makeDeserializer(ty, typespace) {
|
|
905
|
+
if (ty.tag === "Ref") {
|
|
906
|
+
if (!typespace)
|
|
907
|
+
throw new Error("cannot deserialize refs without a typespace");
|
|
908
|
+
while (ty.tag === "Ref") ty = typespace.types[ty.value];
|
|
909
|
+
}
|
|
910
|
+
switch (ty.tag) {
|
|
911
|
+
case "Product":
|
|
912
|
+
return ProductType.makeDeserializer(ty.value, typespace);
|
|
913
|
+
case "Sum":
|
|
914
|
+
return SumType.makeDeserializer(ty.value, typespace);
|
|
915
|
+
case "Array":
|
|
916
|
+
if (ty.value.tag === "U8") {
|
|
917
|
+
return deserializeUint8Array;
|
|
918
|
+
} else {
|
|
919
|
+
const deserialize = AlgebraicType.makeDeserializer(
|
|
920
|
+
ty.value,
|
|
921
|
+
typespace
|
|
922
|
+
);
|
|
923
|
+
return (reader) => {
|
|
924
|
+
const length = reader.readU32();
|
|
925
|
+
const result = Array(length);
|
|
926
|
+
for (let i = 0; i < length; i++) {
|
|
927
|
+
result[i] = deserialize(reader);
|
|
928
|
+
}
|
|
929
|
+
return result;
|
|
930
|
+
};
|
|
931
|
+
}
|
|
932
|
+
default:
|
|
933
|
+
return primitiveDeserializers[ty.tag];
|
|
934
|
+
}
|
|
935
|
+
},
|
|
936
|
+
/** @deprecated Use `makeDeserializer` instead. */
|
|
937
|
+
deserializeValue(reader, ty, typespace) {
|
|
938
|
+
return AlgebraicType.makeDeserializer(ty, typespace)(reader);
|
|
939
|
+
},
|
|
940
|
+
/**
|
|
941
|
+
* Convert a value of the algebraic type into something that can be used as a key in a map.
|
|
942
|
+
* There are no guarantees about being able to order it.
|
|
943
|
+
* This is only guaranteed to be comparable to other values of the same type.
|
|
944
|
+
* @param value A value of the algebraic type
|
|
945
|
+
* @returns Something that can be used as a key in a map.
|
|
946
|
+
*/
|
|
947
|
+
intoMapKey: function(ty, value) {
|
|
948
|
+
switch (ty.tag) {
|
|
949
|
+
case "U8":
|
|
950
|
+
case "U16":
|
|
951
|
+
case "U32":
|
|
952
|
+
case "U64":
|
|
953
|
+
case "U128":
|
|
954
|
+
case "U256":
|
|
955
|
+
case "I8":
|
|
956
|
+
case "I16":
|
|
957
|
+
case "I32":
|
|
958
|
+
case "I64":
|
|
959
|
+
case "I128":
|
|
960
|
+
case "I256":
|
|
961
|
+
case "F32":
|
|
962
|
+
case "F64":
|
|
963
|
+
case "String":
|
|
964
|
+
case "Bool":
|
|
965
|
+
return value;
|
|
966
|
+
case "Product":
|
|
967
|
+
return ProductType.intoMapKey(ty.value, value);
|
|
968
|
+
default: {
|
|
969
|
+
const writer = new BinaryWriter(10);
|
|
970
|
+
AlgebraicType.serializeValue(writer, ty, value);
|
|
971
|
+
return writer.toBase64();
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
};
|
|
976
|
+
function bindCall(f) {
|
|
977
|
+
return Function.prototype.call.bind(f);
|
|
978
|
+
}
|
|
979
|
+
var primitiveSerializers = {
|
|
980
|
+
Bool: bindCall(BinaryWriter.prototype.writeBool),
|
|
981
|
+
I8: bindCall(BinaryWriter.prototype.writeI8),
|
|
982
|
+
U8: bindCall(BinaryWriter.prototype.writeU8),
|
|
983
|
+
I16: bindCall(BinaryWriter.prototype.writeI16),
|
|
984
|
+
U16: bindCall(BinaryWriter.prototype.writeU16),
|
|
985
|
+
I32: bindCall(BinaryWriter.prototype.writeI32),
|
|
986
|
+
U32: bindCall(BinaryWriter.prototype.writeU32),
|
|
987
|
+
I64: bindCall(BinaryWriter.prototype.writeI64),
|
|
988
|
+
U64: bindCall(BinaryWriter.prototype.writeU64),
|
|
989
|
+
I128: bindCall(BinaryWriter.prototype.writeI128),
|
|
990
|
+
U128: bindCall(BinaryWriter.prototype.writeU128),
|
|
991
|
+
I256: bindCall(BinaryWriter.prototype.writeI256),
|
|
992
|
+
U256: bindCall(BinaryWriter.prototype.writeU256),
|
|
993
|
+
F32: bindCall(BinaryWriter.prototype.writeF32),
|
|
994
|
+
F64: bindCall(BinaryWriter.prototype.writeF64),
|
|
995
|
+
String: bindCall(BinaryWriter.prototype.writeString)
|
|
996
|
+
};
|
|
997
|
+
Object.freeze(primitiveSerializers);
|
|
998
|
+
var serializeUint8Array = bindCall(BinaryWriter.prototype.writeUInt8Array);
|
|
999
|
+
var primitiveDeserializers = {
|
|
1000
|
+
Bool: bindCall(BinaryReader.prototype.readBool),
|
|
1001
|
+
I8: bindCall(BinaryReader.prototype.readI8),
|
|
1002
|
+
U8: bindCall(BinaryReader.prototype.readU8),
|
|
1003
|
+
I16: bindCall(BinaryReader.prototype.readI16),
|
|
1004
|
+
U16: bindCall(BinaryReader.prototype.readU16),
|
|
1005
|
+
I32: bindCall(BinaryReader.prototype.readI32),
|
|
1006
|
+
U32: bindCall(BinaryReader.prototype.readU32),
|
|
1007
|
+
I64: bindCall(BinaryReader.prototype.readI64),
|
|
1008
|
+
U64: bindCall(BinaryReader.prototype.readU64),
|
|
1009
|
+
I128: bindCall(BinaryReader.prototype.readI128),
|
|
1010
|
+
U128: bindCall(BinaryReader.prototype.readU128),
|
|
1011
|
+
I256: bindCall(BinaryReader.prototype.readI256),
|
|
1012
|
+
U256: bindCall(BinaryReader.prototype.readU256),
|
|
1013
|
+
F32: bindCall(BinaryReader.prototype.readF32),
|
|
1014
|
+
F64: bindCall(BinaryReader.prototype.readF64),
|
|
1015
|
+
String: bindCall(BinaryReader.prototype.readString)
|
|
1016
|
+
};
|
|
1017
|
+
Object.freeze(primitiveDeserializers);
|
|
1018
|
+
var deserializeUint8Array = bindCall(BinaryReader.prototype.readUInt8Array);
|
|
1019
|
+
var primitiveSizes = {
|
|
1020
|
+
Bool: 1,
|
|
1021
|
+
I8: 1,
|
|
1022
|
+
U8: 1,
|
|
1023
|
+
I16: 2,
|
|
1024
|
+
U16: 2,
|
|
1025
|
+
I32: 4,
|
|
1026
|
+
U32: 4,
|
|
1027
|
+
I64: 8,
|
|
1028
|
+
U64: 8,
|
|
1029
|
+
I128: 16,
|
|
1030
|
+
U128: 16,
|
|
1031
|
+
I256: 32,
|
|
1032
|
+
U256: 32,
|
|
1033
|
+
F32: 4,
|
|
1034
|
+
F64: 8
|
|
1035
|
+
};
|
|
1036
|
+
var fixedSizePrimitives = new Set(Object.keys(primitiveSizes));
|
|
1037
|
+
var isFixedSizeProduct = (ty) => ty.elements.every(
|
|
1038
|
+
({ algebraicType }) => fixedSizePrimitives.has(algebraicType.tag)
|
|
1039
|
+
);
|
|
1040
|
+
var productSize = (ty) => ty.elements.reduce(
|
|
1041
|
+
(acc, { algebraicType }) => acc + primitiveSizes[algebraicType.tag],
|
|
1042
|
+
0
|
|
1043
|
+
);
|
|
1044
|
+
var primitiveJSName = {
|
|
1045
|
+
Bool: "Uint8",
|
|
1046
|
+
I8: "Int8",
|
|
1047
|
+
U8: "Uint8",
|
|
1048
|
+
I16: "Int16",
|
|
1049
|
+
U16: "Uint16",
|
|
1050
|
+
I32: "Int32",
|
|
1051
|
+
U32: "Uint32",
|
|
1052
|
+
I64: "BigInt64",
|
|
1053
|
+
U64: "BigUint64",
|
|
1054
|
+
F32: "Float32",
|
|
1055
|
+
F64: "Float64"
|
|
1056
|
+
};
|
|
1057
|
+
var specialProductDeserializers = {
|
|
1058
|
+
__time_duration_micros__: (reader) => new TimeDuration(reader.readI64()),
|
|
1059
|
+
__timestamp_micros_since_unix_epoch__: (reader) => new Timestamp(reader.readI64()),
|
|
1060
|
+
__identity__: (reader) => new Identity(reader.readU256()),
|
|
1061
|
+
__connection_id__: (reader) => new ConnectionId(reader.readU128()),
|
|
1062
|
+
__uuid__: (reader) => new Uuid(reader.readU128())
|
|
1063
|
+
};
|
|
1064
|
+
Object.freeze(specialProductDeserializers);
|
|
1065
|
+
var unitDeserializer = () => ({});
|
|
1066
|
+
var getElementInitializer = (element) => {
|
|
1067
|
+
let init;
|
|
1068
|
+
switch (element.algebraicType.tag) {
|
|
1069
|
+
case "String":
|
|
1070
|
+
init = "''";
|
|
1071
|
+
break;
|
|
1072
|
+
case "Bool":
|
|
1073
|
+
init = "false";
|
|
1074
|
+
break;
|
|
1075
|
+
case "I8":
|
|
1076
|
+
case "U8":
|
|
1077
|
+
case "I16":
|
|
1078
|
+
case "U16":
|
|
1079
|
+
case "I32":
|
|
1080
|
+
case "U32":
|
|
1081
|
+
init = "0";
|
|
1082
|
+
break;
|
|
1083
|
+
case "I64":
|
|
1084
|
+
case "U64":
|
|
1085
|
+
case "I128":
|
|
1086
|
+
case "U128":
|
|
1087
|
+
case "I256":
|
|
1088
|
+
case "U256":
|
|
1089
|
+
init = "0n";
|
|
1090
|
+
break;
|
|
1091
|
+
case "F32":
|
|
1092
|
+
case "F64":
|
|
1093
|
+
init = "0.0";
|
|
1094
|
+
break;
|
|
1095
|
+
default:
|
|
1096
|
+
init = "undefined";
|
|
1097
|
+
}
|
|
1098
|
+
return `${element.name}: ${init}`;
|
|
1099
|
+
};
|
|
1100
|
+
var ProductType = {
|
|
1101
|
+
makeSerializer(ty, typespace) {
|
|
1102
|
+
let serializer = SERIALIZERS.get(ty);
|
|
1103
|
+
if (serializer != null) return serializer;
|
|
1104
|
+
if (isFixedSizeProduct(ty)) {
|
|
1105
|
+
const size = productSize(ty);
|
|
1106
|
+
const body2 = `"use strict";
|
|
1107
|
+
writer.expandBuffer(${size});
|
|
1108
|
+
const view = writer.view;
|
|
1109
|
+
${ty.elements.map(
|
|
1110
|
+
({ name, algebraicType: { tag } }) => tag in primitiveJSName ? `view.set${primitiveJSName[tag]}(writer.offset, value.${name}, ${primitiveSizes[tag] > 1 ? "true" : ""});
|
|
1111
|
+
writer.offset += ${primitiveSizes[tag]};` : `writer.write${tag}(value.${name});`
|
|
1112
|
+
).join("\n")}`;
|
|
1113
|
+
serializer = Function("writer", "value", body2);
|
|
1114
|
+
SERIALIZERS.set(ty, serializer);
|
|
1115
|
+
return serializer;
|
|
1116
|
+
}
|
|
1117
|
+
const serializers = {};
|
|
1118
|
+
const body = '"use strict";\n' + ty.elements.map(
|
|
1119
|
+
(element) => `this.${element.name}(writer, value.${element.name});`
|
|
1120
|
+
).join("\n");
|
|
1121
|
+
serializer = Function("writer", "value", body).bind(
|
|
1122
|
+
serializers
|
|
1123
|
+
);
|
|
1124
|
+
SERIALIZERS.set(ty, serializer);
|
|
1125
|
+
for (const { name, algebraicType } of ty.elements) {
|
|
1126
|
+
serializers[name] = AlgebraicType.makeSerializer(
|
|
1127
|
+
algebraicType,
|
|
1128
|
+
typespace
|
|
1129
|
+
);
|
|
1130
|
+
}
|
|
1131
|
+
Object.freeze(serializers);
|
|
1132
|
+
return serializer;
|
|
1133
|
+
},
|
|
1134
|
+
/** @deprecated Use `makeSerializer` instead. */
|
|
1135
|
+
serializeValue(writer, ty, value, typespace) {
|
|
1136
|
+
ProductType.makeSerializer(ty, typespace)(writer, value);
|
|
1137
|
+
},
|
|
1138
|
+
makeDeserializer(ty, typespace) {
|
|
1139
|
+
switch (ty.elements.length) {
|
|
1140
|
+
case 0:
|
|
1141
|
+
return unitDeserializer;
|
|
1142
|
+
case 1: {
|
|
1143
|
+
const fieldName = ty.elements[0].name;
|
|
1144
|
+
if (hasOwn(specialProductDeserializers, fieldName))
|
|
1145
|
+
return specialProductDeserializers[fieldName];
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
let deserializer = DESERIALIZERS.get(ty);
|
|
1149
|
+
if (deserializer != null) return deserializer;
|
|
1150
|
+
if (isFixedSizeProduct(ty)) {
|
|
1151
|
+
const body = `"use strict";
|
|
1152
|
+
const result = { ${ty.elements.map(getElementInitializer).join(", ")} };
|
|
1153
|
+
const view = reader.view;
|
|
1154
|
+
${ty.elements.map(
|
|
1155
|
+
({ name, algebraicType: { tag } }) => tag in primitiveJSName ? tag === "Bool" ? `result.${name} = view.getUint8(reader.offset) !== 0;
|
|
1156
|
+
reader.offset += 1;` : `result.${name} = view.get${primitiveJSName[tag]}(reader.offset, ${primitiveSizes[tag] > 1 ? "true" : ""});
|
|
1157
|
+
reader.offset += ${primitiveSizes[tag]};` : `result.${name} = reader.read${tag}();`
|
|
1158
|
+
).join("\n")}
|
|
1159
|
+
return result;`;
|
|
1160
|
+
deserializer = Function("reader", body);
|
|
1161
|
+
DESERIALIZERS.set(ty, deserializer);
|
|
1162
|
+
return deserializer;
|
|
1163
|
+
}
|
|
1164
|
+
const deserializers = {};
|
|
1165
|
+
deserializer = Function(
|
|
1166
|
+
"reader",
|
|
1167
|
+
`"use strict";
|
|
1168
|
+
const result = { ${ty.elements.map(getElementInitializer).join(", ")} };
|
|
1169
|
+
${ty.elements.map(({ name }) => `result.${name} = this.${name}(reader);`).join("\n")}
|
|
1170
|
+
return result;`
|
|
1171
|
+
).bind(deserializers);
|
|
1172
|
+
DESERIALIZERS.set(ty, deserializer);
|
|
1173
|
+
for (const { name, algebraicType } of ty.elements) {
|
|
1174
|
+
deserializers[name] = AlgebraicType.makeDeserializer(
|
|
1175
|
+
algebraicType,
|
|
1176
|
+
typespace
|
|
1177
|
+
);
|
|
1178
|
+
}
|
|
1179
|
+
Object.freeze(deserializers);
|
|
1180
|
+
return deserializer;
|
|
1181
|
+
},
|
|
1182
|
+
/** @deprecated Use `makeDeserializer` instead. */
|
|
1183
|
+
deserializeValue(reader, ty, typespace) {
|
|
1184
|
+
return ProductType.makeDeserializer(ty, typespace)(reader);
|
|
1185
|
+
},
|
|
1186
|
+
intoMapKey(ty, value) {
|
|
1187
|
+
if (ty.elements.length === 1) {
|
|
1188
|
+
const fieldName = ty.elements[0].name;
|
|
1189
|
+
if (hasOwn(specialProductDeserializers, fieldName)) {
|
|
1190
|
+
return value[fieldName];
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
const writer = new BinaryWriter(10);
|
|
1194
|
+
AlgebraicType.serializeValue(writer, AlgebraicType.Product(ty), value);
|
|
1195
|
+
return writer.toBase64();
|
|
1196
|
+
}
|
|
1197
|
+
};
|
|
1198
|
+
var SumType = {
|
|
1199
|
+
makeSerializer(ty, typespace) {
|
|
1200
|
+
if (ty.variants.length == 2 && ty.variants[0].name === "some" && ty.variants[1].name === "none") {
|
|
1201
|
+
const serialize = AlgebraicType.makeSerializer(
|
|
1202
|
+
ty.variants[0].algebraicType,
|
|
1203
|
+
typespace
|
|
1204
|
+
);
|
|
1205
|
+
return (writer, value) => {
|
|
1206
|
+
if (value !== null && value !== void 0) {
|
|
1207
|
+
writer.writeByte(0);
|
|
1208
|
+
serialize(writer, value);
|
|
1209
|
+
} else {
|
|
1210
|
+
writer.writeByte(1);
|
|
1211
|
+
}
|
|
1212
|
+
};
|
|
1213
|
+
} else if (ty.variants.length == 2 && ty.variants[0].name === "ok" && ty.variants[1].name === "err") {
|
|
1214
|
+
const serializeOk = AlgebraicType.makeSerializer(
|
|
1215
|
+
ty.variants[0].algebraicType,
|
|
1216
|
+
typespace
|
|
1217
|
+
);
|
|
1218
|
+
const serializeErr = AlgebraicType.makeSerializer(
|
|
1219
|
+
ty.variants[0].algebraicType,
|
|
1220
|
+
typespace
|
|
1221
|
+
);
|
|
1222
|
+
return (writer, value) => {
|
|
1223
|
+
if ("ok" in value) {
|
|
1224
|
+
writer.writeU8(0);
|
|
1225
|
+
serializeOk(writer, value.ok);
|
|
1226
|
+
} else if ("err" in value) {
|
|
1227
|
+
writer.writeU8(1);
|
|
1228
|
+
serializeErr(writer, value.err);
|
|
1229
|
+
} else {
|
|
1230
|
+
throw new TypeError(
|
|
1231
|
+
"could not serialize result: object had neither a `ok` nor an `err` field"
|
|
1232
|
+
);
|
|
1233
|
+
}
|
|
1234
|
+
};
|
|
1235
|
+
} else {
|
|
1236
|
+
let serializer = SERIALIZERS.get(ty);
|
|
1237
|
+
if (serializer != null) return serializer;
|
|
1238
|
+
const serializers = {};
|
|
1239
|
+
const body = `switch (value.tag) {
|
|
1240
|
+
${ty.variants.map(
|
|
1241
|
+
({ name }, i) => ` case ${JSON.stringify(name)}:
|
|
1242
|
+
writer.writeByte(${i});
|
|
1243
|
+
return this.${name}(writer, value.value);`
|
|
1244
|
+
).join("\n")}
|
|
1245
|
+
default:
|
|
1246
|
+
throw new TypeError(
|
|
1247
|
+
\`Could not serialize sum type; unknown tag \${value.tag}\`
|
|
1248
|
+
)
|
|
1249
|
+
}
|
|
1250
|
+
`;
|
|
1251
|
+
serializer = Function("writer", "value", body).bind(
|
|
1252
|
+
serializers
|
|
1253
|
+
);
|
|
1254
|
+
SERIALIZERS.set(ty, serializer);
|
|
1255
|
+
for (const { name, algebraicType } of ty.variants) {
|
|
1256
|
+
serializers[name] = AlgebraicType.makeSerializer(
|
|
1257
|
+
algebraicType,
|
|
1258
|
+
typespace
|
|
1259
|
+
);
|
|
1260
|
+
}
|
|
1261
|
+
Object.freeze(serializers);
|
|
1262
|
+
return serializer;
|
|
1263
|
+
}
|
|
1264
|
+
},
|
|
1265
|
+
/** @deprecated Use `makeSerializer` instead. */
|
|
1266
|
+
serializeValue(writer, ty, value, typespace) {
|
|
1267
|
+
SumType.makeSerializer(ty, typespace)(writer, value);
|
|
1268
|
+
},
|
|
1269
|
+
makeDeserializer(ty, typespace) {
|
|
1270
|
+
if (ty.variants.length == 2 && ty.variants[0].name === "some" && ty.variants[1].name === "none") {
|
|
1271
|
+
const deserialize = AlgebraicType.makeDeserializer(
|
|
1272
|
+
ty.variants[0].algebraicType,
|
|
1273
|
+
typespace
|
|
1274
|
+
);
|
|
1275
|
+
return (reader) => {
|
|
1276
|
+
const tag = reader.readU8();
|
|
1277
|
+
if (tag === 0) {
|
|
1278
|
+
return deserialize(reader);
|
|
1279
|
+
} else if (tag === 1) {
|
|
1280
|
+
return void 0;
|
|
1281
|
+
} else {
|
|
1282
|
+
throw `Can't deserialize an option type, couldn't find ${tag} tag`;
|
|
1283
|
+
}
|
|
1284
|
+
};
|
|
1285
|
+
} else if (ty.variants.length == 2 && ty.variants[0].name === "ok" && ty.variants[1].name === "err") {
|
|
1286
|
+
const deserializeOk = AlgebraicType.makeDeserializer(
|
|
1287
|
+
ty.variants[0].algebraicType,
|
|
1288
|
+
typespace
|
|
1289
|
+
);
|
|
1290
|
+
const deserializeErr = AlgebraicType.makeDeserializer(
|
|
1291
|
+
ty.variants[1].algebraicType,
|
|
1292
|
+
typespace
|
|
1293
|
+
);
|
|
1294
|
+
return (reader) => {
|
|
1295
|
+
const tag = reader.readByte();
|
|
1296
|
+
if (tag === 0) {
|
|
1297
|
+
return { ok: deserializeOk(reader) };
|
|
1298
|
+
} else if (tag === 1) {
|
|
1299
|
+
return { err: deserializeErr(reader) };
|
|
1300
|
+
} else {
|
|
1301
|
+
throw `Can't deserialize a result type, couldn't find ${tag} tag`;
|
|
1302
|
+
}
|
|
1303
|
+
};
|
|
1304
|
+
} else {
|
|
1305
|
+
let deserializer = DESERIALIZERS.get(ty);
|
|
1306
|
+
if (deserializer != null) return deserializer;
|
|
1307
|
+
const deserializers = {};
|
|
1308
|
+
deserializer = Function(
|
|
1309
|
+
"reader",
|
|
1310
|
+
`switch (reader.readU8()) {
|
|
1311
|
+
${ty.variants.map(
|
|
1312
|
+
({ name }, i) => `case ${i}: return { tag: ${JSON.stringify(name)}, value: this.${name}(reader) };`
|
|
1313
|
+
).join("\n")} }`
|
|
1314
|
+
).bind(deserializers);
|
|
1315
|
+
DESERIALIZERS.set(ty, deserializer);
|
|
1316
|
+
for (const { name, algebraicType } of ty.variants) {
|
|
1317
|
+
deserializers[name] = AlgebraicType.makeDeserializer(
|
|
1318
|
+
algebraicType,
|
|
1319
|
+
typespace
|
|
1320
|
+
);
|
|
1321
|
+
}
|
|
1322
|
+
Object.freeze(deserializers);
|
|
1323
|
+
return deserializer;
|
|
1324
|
+
}
|
|
1325
|
+
},
|
|
1326
|
+
/** @deprecated Use `makeDeserializer` instead. */
|
|
1327
|
+
deserializeValue(reader, ty, typespace) {
|
|
1328
|
+
return SumType.makeDeserializer(ty, typespace)(reader);
|
|
1329
|
+
}
|
|
1330
|
+
};
|
|
1331
|
+
|
|
1332
|
+
// src/lib/connection_id.ts
|
|
1333
|
+
var ConnectionId = class _ConnectionId {
|
|
1334
|
+
__connection_id__;
|
|
1335
|
+
/**
|
|
1336
|
+
* Creates a new `ConnectionId`.
|
|
1337
|
+
*/
|
|
1338
|
+
constructor(data) {
|
|
1339
|
+
this.__connection_id__ = data;
|
|
1340
|
+
}
|
|
1341
|
+
/**
|
|
1342
|
+
* Get the algebraic type representation of the {@link ConnectionId} type.
|
|
1343
|
+
* @returns The algebraic type representation of the type.
|
|
1344
|
+
*/
|
|
1345
|
+
static getAlgebraicType() {
|
|
1346
|
+
return AlgebraicType.Product({
|
|
1347
|
+
elements: [
|
|
1348
|
+
{ name: "__connection_id__", algebraicType: AlgebraicType.U128 }
|
|
1349
|
+
]
|
|
1350
|
+
});
|
|
1351
|
+
}
|
|
1352
|
+
isZero() {
|
|
1353
|
+
return this.__connection_id__ === BigInt(0);
|
|
1354
|
+
}
|
|
1355
|
+
static nullIfZero(addr) {
|
|
1356
|
+
if (addr.isZero()) {
|
|
1357
|
+
return null;
|
|
1358
|
+
} else {
|
|
1359
|
+
return addr;
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
static random() {
|
|
1363
|
+
function randomU8() {
|
|
1364
|
+
return Math.floor(Math.random() * 255);
|
|
1365
|
+
}
|
|
1366
|
+
let result = BigInt(0);
|
|
1367
|
+
for (let i = 0; i < 16; i++) {
|
|
1368
|
+
result = result << BigInt(8) | BigInt(randomU8());
|
|
1369
|
+
}
|
|
1370
|
+
return new _ConnectionId(result);
|
|
1371
|
+
}
|
|
1372
|
+
/**
|
|
1373
|
+
* Compare two connection IDs for equality.
|
|
1374
|
+
*/
|
|
1375
|
+
isEqual(other) {
|
|
1376
|
+
return this.__connection_id__ == other.__connection_id__;
|
|
1377
|
+
}
|
|
1378
|
+
/**
|
|
1379
|
+
* Check if two connection IDs are equal.
|
|
1380
|
+
*/
|
|
1381
|
+
equals(other) {
|
|
1382
|
+
return this.isEqual(other);
|
|
1383
|
+
}
|
|
1384
|
+
/**
|
|
1385
|
+
* Print the connection ID as a hexadecimal string.
|
|
1386
|
+
*/
|
|
1387
|
+
toHexString() {
|
|
1388
|
+
return u128ToHexString(this.__connection_id__);
|
|
1389
|
+
}
|
|
1390
|
+
/**
|
|
1391
|
+
* Convert the connection ID to a Uint8Array.
|
|
1392
|
+
*/
|
|
1393
|
+
toUint8Array() {
|
|
1394
|
+
return u128ToUint8Array(this.__connection_id__);
|
|
1395
|
+
}
|
|
1396
|
+
/**
|
|
1397
|
+
* Parse a connection ID from a hexadecimal string.
|
|
1398
|
+
*/
|
|
1399
|
+
static fromString(str) {
|
|
1400
|
+
return new _ConnectionId(hexStringToU128(str));
|
|
1401
|
+
}
|
|
1402
|
+
static fromStringOrNull(str) {
|
|
1403
|
+
const addr = _ConnectionId.fromString(str);
|
|
1404
|
+
if (addr.isZero()) {
|
|
1405
|
+
return null;
|
|
1406
|
+
} else {
|
|
1407
|
+
return addr;
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
};
|
|
1411
|
+
function toSql(q) {
|
|
1412
|
+
return q.toSql();
|
|
1413
|
+
}
|
|
1414
|
+
function isLiteralExpr(expr) {
|
|
1415
|
+
return expr.type === "literal";
|
|
1416
|
+
}
|
|
1417
|
+
function evaluateBooleanExpr(expr, row) {
|
|
1418
|
+
return evaluateData(expr.data, row);
|
|
1419
|
+
}
|
|
1420
|
+
function evaluateData(data, row) {
|
|
1421
|
+
switch (data.type) {
|
|
1422
|
+
case "eq":
|
|
1423
|
+
return resolveValue(data.left, row) === resolveValue(data.right, row);
|
|
1424
|
+
case "ne":
|
|
1425
|
+
return resolveValue(data.left, row) !== resolveValue(data.right, row);
|
|
1426
|
+
case "gt":
|
|
1427
|
+
return resolveValue(data.left, row) > resolveValue(data.right, row);
|
|
1428
|
+
case "gte":
|
|
1429
|
+
return resolveValue(data.left, row) >= resolveValue(data.right, row);
|
|
1430
|
+
case "lt":
|
|
1431
|
+
return resolveValue(data.left, row) < resolveValue(data.right, row);
|
|
1432
|
+
case "lte":
|
|
1433
|
+
return resolveValue(data.left, row) <= resolveValue(data.right, row);
|
|
1434
|
+
case "and":
|
|
1435
|
+
return data.clauses.every((c) => evaluateData(c, row));
|
|
1436
|
+
case "or":
|
|
1437
|
+
return data.clauses.some((c) => evaluateData(c, row));
|
|
1438
|
+
case "not":
|
|
1439
|
+
return !evaluateData(data.clause, row);
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
function resolveValue(expr, row) {
|
|
1443
|
+
if (isLiteralExpr(expr)) {
|
|
1444
|
+
return toComparableValue(expr.value);
|
|
1445
|
+
}
|
|
1446
|
+
return toComparableValue(row[expr.column]);
|
|
1447
|
+
}
|
|
1448
|
+
function isHexSerializableLike(value) {
|
|
1449
|
+
return !!value && typeof value === "object" && typeof value.toHexString === "function";
|
|
1450
|
+
}
|
|
1451
|
+
function isTimestampLike(value) {
|
|
1452
|
+
if (!value || typeof value !== "object") return false;
|
|
1453
|
+
if (value instanceof Timestamp) return true;
|
|
1454
|
+
const micros = value["__timestamp_micros_since_unix_epoch__"];
|
|
1455
|
+
return typeof micros === "bigint";
|
|
1456
|
+
}
|
|
1457
|
+
function toComparableValue(value) {
|
|
1458
|
+
if (isHexSerializableLike(value)) {
|
|
1459
|
+
return value.toHexString();
|
|
1460
|
+
}
|
|
1461
|
+
if (isTimestampLike(value)) {
|
|
1462
|
+
return value.__timestamp_micros_since_unix_epoch__;
|
|
1463
|
+
}
|
|
1464
|
+
return value;
|
|
1465
|
+
}
|
|
1466
|
+
function getQueryAccessorName(query) {
|
|
1467
|
+
if (query.table) return query.table.accessorName;
|
|
1468
|
+
if (query.accessorName) return query.accessorName;
|
|
1469
|
+
if (query.sourceQuery) return query.sourceQuery.table.accessorName;
|
|
1470
|
+
throw new Error("Cannot extract accessor name from query");
|
|
1471
|
+
}
|
|
1472
|
+
function getQueryWhereClause(query) {
|
|
1473
|
+
if (query.whereClause) return query.whereClause;
|
|
1474
|
+
return void 0;
|
|
1475
|
+
}
|
|
1476
|
+
var SpacetimeDBContext = createContext(
|
|
1477
|
+
void 0
|
|
1478
|
+
);
|
|
1479
|
+
function useSpacetimeDB() {
|
|
1480
|
+
const context = useContext(SpacetimeDBContext);
|
|
1481
|
+
if (!context) {
|
|
1482
|
+
throw new Error(
|
|
1483
|
+
"useSpacetimeDB must be used within a SpacetimeDBProvider component. Did you forget to add a `SpacetimeDBProvider` to your component tree?"
|
|
1484
|
+
);
|
|
1485
|
+
}
|
|
1486
|
+
return context;
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
// src/sdk/connection_manager.ts
|
|
1490
|
+
function defaultState() {
|
|
1491
|
+
return {
|
|
1492
|
+
isActive: false,
|
|
1493
|
+
identity: void 0,
|
|
1494
|
+
token: void 0,
|
|
1495
|
+
connectionId: ConnectionId.random(),
|
|
1496
|
+
connectionError: void 0
|
|
1497
|
+
};
|
|
1498
|
+
}
|
|
1499
|
+
var ConnectionManagerImpl = class _ConnectionManagerImpl {
|
|
1500
|
+
#connections = /* @__PURE__ */ new Map();
|
|
1501
|
+
/** Generates a unique key for a connection based on URI and module name. */
|
|
1502
|
+
static getKey(uri, moduleName) {
|
|
1503
|
+
return `${uri}::${moduleName}`;
|
|
1504
|
+
}
|
|
1505
|
+
/** Instance method wrapper for getKey. */
|
|
1506
|
+
getKey(uri, moduleName) {
|
|
1507
|
+
return _ConnectionManagerImpl.getKey(uri, moduleName);
|
|
1508
|
+
}
|
|
1509
|
+
#ensureEntry(key) {
|
|
1510
|
+
const existing = this.#connections.get(key);
|
|
1511
|
+
if (existing) {
|
|
1512
|
+
return existing;
|
|
1513
|
+
}
|
|
1514
|
+
const managed = {
|
|
1515
|
+
connection: void 0,
|
|
1516
|
+
refCount: 0,
|
|
1517
|
+
state: defaultState(),
|
|
1518
|
+
listeners: /* @__PURE__ */ new Set(),
|
|
1519
|
+
pendingRelease: null
|
|
1520
|
+
};
|
|
1521
|
+
this.#connections.set(key, managed);
|
|
1522
|
+
return managed;
|
|
1523
|
+
}
|
|
1524
|
+
#notify(managed) {
|
|
1525
|
+
for (const listener of managed.listeners) {
|
|
1526
|
+
listener();
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
/**
|
|
1530
|
+
* Retains a connection, incrementing its reference count.
|
|
1531
|
+
* Creates the connection on first call; returns existing connection on subsequent calls.
|
|
1532
|
+
* Cancels any pending release if the connection was about to be cleaned up.
|
|
1533
|
+
*
|
|
1534
|
+
* @param key - Unique identifier for the connection (use getKey to generate)
|
|
1535
|
+
* @param builder - Connection builder to create the connection if needed
|
|
1536
|
+
* @returns The managed connection instance
|
|
1537
|
+
*/
|
|
1538
|
+
retain(key, builder) {
|
|
1539
|
+
const managed = this.#ensureEntry(key);
|
|
1540
|
+
if (managed.pendingRelease) {
|
|
1541
|
+
clearTimeout(managed.pendingRelease);
|
|
1542
|
+
managed.pendingRelease = null;
|
|
1543
|
+
}
|
|
1544
|
+
managed.refCount += 1;
|
|
1545
|
+
if (managed.connection) {
|
|
1546
|
+
return managed.connection;
|
|
1547
|
+
}
|
|
1548
|
+
const connection = builder.build();
|
|
1549
|
+
managed.connection = connection;
|
|
1550
|
+
const updateState = (updates) => {
|
|
1551
|
+
managed.state = { ...managed.state, ...updates };
|
|
1552
|
+
this.#notify(managed);
|
|
1553
|
+
};
|
|
1554
|
+
updateState({
|
|
1555
|
+
isActive: connection.isActive,
|
|
1556
|
+
identity: connection.identity,
|
|
1557
|
+
token: connection.token,
|
|
1558
|
+
connectionId: connection.connectionId,
|
|
1559
|
+
connectionError: void 0
|
|
1560
|
+
});
|
|
1561
|
+
managed.onConnect = (conn) => {
|
|
1562
|
+
updateState({
|
|
1563
|
+
isActive: conn.isActive,
|
|
1564
|
+
identity: conn.identity,
|
|
1565
|
+
token: conn.token,
|
|
1566
|
+
connectionId: conn.connectionId,
|
|
1567
|
+
connectionError: void 0
|
|
1568
|
+
});
|
|
1569
|
+
};
|
|
1570
|
+
managed.onDisconnect = (ctx, error) => {
|
|
1571
|
+
updateState({
|
|
1572
|
+
isActive: ctx.isActive,
|
|
1573
|
+
connectionError: error ?? void 0
|
|
1574
|
+
});
|
|
1575
|
+
};
|
|
1576
|
+
managed.onConnectError = (ctx, error) => {
|
|
1577
|
+
updateState({
|
|
1578
|
+
isActive: ctx.isActive,
|
|
1579
|
+
connectionError: error
|
|
1580
|
+
});
|
|
1581
|
+
};
|
|
1582
|
+
builder.onConnect(managed.onConnect);
|
|
1583
|
+
builder.onDisconnect(managed.onDisconnect);
|
|
1584
|
+
builder.onConnectError(managed.onConnectError);
|
|
1585
|
+
return connection;
|
|
1586
|
+
}
|
|
1587
|
+
release(key) {
|
|
1588
|
+
const managed = this.#connections.get(key);
|
|
1589
|
+
if (!managed) {
|
|
1590
|
+
return;
|
|
1591
|
+
}
|
|
1592
|
+
managed.refCount -= 1;
|
|
1593
|
+
if (managed.refCount > 0 || managed.pendingRelease) {
|
|
1594
|
+
return;
|
|
1595
|
+
}
|
|
1596
|
+
managed.pendingRelease = setTimeout(() => {
|
|
1597
|
+
managed.pendingRelease = null;
|
|
1598
|
+
if (managed.refCount > 0) {
|
|
1599
|
+
return;
|
|
1600
|
+
}
|
|
1601
|
+
if (managed.connection) {
|
|
1602
|
+
if (managed.onConnect) {
|
|
1603
|
+
managed.connection.removeOnConnect(managed.onConnect);
|
|
1604
|
+
}
|
|
1605
|
+
if (managed.onDisconnect) {
|
|
1606
|
+
managed.connection.removeOnDisconnect(managed.onDisconnect);
|
|
1607
|
+
}
|
|
1608
|
+
if (managed.onConnectError) {
|
|
1609
|
+
managed.connection.removeOnConnectError(
|
|
1610
|
+
managed.onConnectError
|
|
1611
|
+
);
|
|
1612
|
+
}
|
|
1613
|
+
managed.connection.disconnect();
|
|
1614
|
+
}
|
|
1615
|
+
this.#connections.delete(key);
|
|
1616
|
+
}, 0);
|
|
1617
|
+
}
|
|
1618
|
+
subscribe(key, listener) {
|
|
1619
|
+
const managed = this.#ensureEntry(key);
|
|
1620
|
+
managed.listeners.add(listener);
|
|
1621
|
+
return () => {
|
|
1622
|
+
managed.listeners.delete(listener);
|
|
1623
|
+
if (managed.refCount <= 0 && managed.listeners.size === 0 && !managed.connection) {
|
|
1624
|
+
this.#connections.delete(key);
|
|
1625
|
+
}
|
|
1626
|
+
};
|
|
1627
|
+
}
|
|
1628
|
+
getSnapshot(key) {
|
|
1629
|
+
return this.#connections.get(key)?.state;
|
|
1630
|
+
}
|
|
1631
|
+
getConnection(key) {
|
|
1632
|
+
return this.#connections.get(key)?.connection ?? null;
|
|
1633
|
+
}
|
|
1634
|
+
};
|
|
1635
|
+
var ConnectionManager = new ConnectionManagerImpl();
|
|
1636
|
+
|
|
1637
|
+
// src/solid/SpacetimeDBProvider.ts
|
|
1638
|
+
function SpacetimeDBProvider(props) {
|
|
1639
|
+
const uri = () => props.connectionBuilder.getUri();
|
|
1640
|
+
const moduleName = () => props.connectionBuilder.getModuleName();
|
|
1641
|
+
const key = createMemo(() => ConnectionManager.getKey(uri(), moduleName()));
|
|
1642
|
+
const fallbackState = {
|
|
1643
|
+
isActive: false,
|
|
1644
|
+
identity: void 0,
|
|
1645
|
+
token: void 0,
|
|
1646
|
+
connectionId: ConnectionId.random(),
|
|
1647
|
+
connectionError: void 0
|
|
1648
|
+
};
|
|
1649
|
+
const [state, setState] = createStore(fallbackState);
|
|
1650
|
+
createComputed(() => {
|
|
1651
|
+
const currentKey = key();
|
|
1652
|
+
const unsubscribe = ConnectionManager.subscribe(currentKey, () => {
|
|
1653
|
+
const snapshot2 = ConnectionManager.getSnapshot(currentKey) ?? fallbackState;
|
|
1654
|
+
setState(snapshot2);
|
|
1655
|
+
});
|
|
1656
|
+
const snapshot = ConnectionManager.getSnapshot(currentKey) ?? fallbackState;
|
|
1657
|
+
setState(snapshot);
|
|
1658
|
+
onCleanup(() => {
|
|
1659
|
+
unsubscribe();
|
|
1660
|
+
});
|
|
1661
|
+
});
|
|
1662
|
+
const getConnection = () => ConnectionManager.getConnection(key());
|
|
1663
|
+
const contextValue = {
|
|
1664
|
+
get isActive() {
|
|
1665
|
+
return state.isActive;
|
|
1666
|
+
},
|
|
1667
|
+
get identity() {
|
|
1668
|
+
return state.identity;
|
|
1669
|
+
},
|
|
1670
|
+
get token() {
|
|
1671
|
+
return state.token;
|
|
1672
|
+
},
|
|
1673
|
+
get connectionId() {
|
|
1674
|
+
return state.connectionId;
|
|
1675
|
+
},
|
|
1676
|
+
get connectionError() {
|
|
1677
|
+
return state.connectionError;
|
|
1678
|
+
},
|
|
1679
|
+
getConnection
|
|
1680
|
+
};
|
|
1681
|
+
createComputed(() => {
|
|
1682
|
+
const currentKey = key();
|
|
1683
|
+
ConnectionManager.retain(currentKey, props.connectionBuilder);
|
|
1684
|
+
onCleanup(() => {
|
|
1685
|
+
ConnectionManager.release(currentKey);
|
|
1686
|
+
});
|
|
1687
|
+
});
|
|
1688
|
+
return SpacetimeDBContext.Provider({
|
|
1689
|
+
value: contextValue,
|
|
1690
|
+
get children() {
|
|
1691
|
+
return props.children;
|
|
1692
|
+
}
|
|
1693
|
+
});
|
|
1694
|
+
}
|
|
1695
|
+
function classifyMembership(whereExpr, oldRow, newRow) {
|
|
1696
|
+
if (!whereExpr) return "stayIn";
|
|
1697
|
+
const oldIn = evaluateBooleanExpr(whereExpr, oldRow);
|
|
1698
|
+
const newIn = evaluateBooleanExpr(whereExpr, newRow);
|
|
1699
|
+
if (oldIn && !newIn) return "leave";
|
|
1700
|
+
if (!oldIn && newIn) return "enter";
|
|
1701
|
+
if (oldIn && newIn) return "stayIn";
|
|
1702
|
+
return "stayOut";
|
|
1703
|
+
}
|
|
1704
|
+
function useTable(query, callbacks) {
|
|
1705
|
+
const enabled = callbacks?.enabled ?? (() => true);
|
|
1706
|
+
const q = createMemo(query);
|
|
1707
|
+
const accessorName = createMemo(() => getQueryAccessorName(q()));
|
|
1708
|
+
const whereExpr = createMemo(() => getQueryWhereClause(q()));
|
|
1709
|
+
const querySql = createMemo(() => toSql(q()));
|
|
1710
|
+
let connectionState;
|
|
1711
|
+
try {
|
|
1712
|
+
connectionState = useSpacetimeDB();
|
|
1713
|
+
} catch {
|
|
1714
|
+
throw new Error(
|
|
1715
|
+
"Could not find SpacetimeDB client! Did you forget to add a `SpacetimeDBProvider`? `useTable` must be used in the SolidJS component tree under a `SpacetimeDBProvider` component."
|
|
1716
|
+
);
|
|
1717
|
+
}
|
|
1718
|
+
const [rows, setRows] = createStore([]);
|
|
1719
|
+
let latestTransactionEventId = null;
|
|
1720
|
+
const computeSnapshot = () => {
|
|
1721
|
+
if (!enabled()) {
|
|
1722
|
+
return [];
|
|
1723
|
+
}
|
|
1724
|
+
const connection = connectionState.getConnection();
|
|
1725
|
+
if (!connection) {
|
|
1726
|
+
return [];
|
|
1727
|
+
}
|
|
1728
|
+
const table = connection.db[accessorName()];
|
|
1729
|
+
const result = whereExpr() ? Array.from(table.iter()).filter(
|
|
1730
|
+
(row) => evaluateBooleanExpr(whereExpr(), row)
|
|
1731
|
+
) : Array.from(table.iter());
|
|
1732
|
+
return result;
|
|
1733
|
+
};
|
|
1734
|
+
const [isReady, setIsReady] = createSignal(false);
|
|
1735
|
+
createComputed(() => {
|
|
1736
|
+
if (!enabled()) {
|
|
1737
|
+
setIsReady(false);
|
|
1738
|
+
return;
|
|
1739
|
+
}
|
|
1740
|
+
const connection = connectionState.getConnection();
|
|
1741
|
+
if (!connectionState.isActive || !connection) {
|
|
1742
|
+
setIsReady(false);
|
|
1743
|
+
return;
|
|
1744
|
+
}
|
|
1745
|
+
const cancel = connection.subscriptionBuilder().onApplied(() => {
|
|
1746
|
+
setIsReady(true);
|
|
1747
|
+
}).subscribe(querySql());
|
|
1748
|
+
onCleanup(() => {
|
|
1749
|
+
cancel.unsubscribe();
|
|
1750
|
+
});
|
|
1751
|
+
const table = connection.db[accessorName()];
|
|
1752
|
+
const onInsert = (ctx, row) => {
|
|
1753
|
+
if (whereExpr() && !evaluateBooleanExpr(whereExpr(), row)) {
|
|
1754
|
+
return;
|
|
1755
|
+
}
|
|
1756
|
+
callbacks?.onInsert?.(row);
|
|
1757
|
+
if (ctx.event.id !== latestTransactionEventId) {
|
|
1758
|
+
latestTransactionEventId = ctx.event.id;
|
|
1759
|
+
setRows(reconcile(computeSnapshot()));
|
|
1760
|
+
}
|
|
1761
|
+
};
|
|
1762
|
+
const onDelete = (ctx, row) => {
|
|
1763
|
+
if (whereExpr() && !evaluateBooleanExpr(whereExpr(), row)) {
|
|
1764
|
+
return;
|
|
1765
|
+
}
|
|
1766
|
+
callbacks?.onDelete?.(row);
|
|
1767
|
+
if (ctx.event.id !== latestTransactionEventId) {
|
|
1768
|
+
latestTransactionEventId = ctx.event.id;
|
|
1769
|
+
setRows(reconcile(computeSnapshot()));
|
|
1770
|
+
}
|
|
1771
|
+
};
|
|
1772
|
+
const onUpdate = (ctx, oldRow, newRow) => {
|
|
1773
|
+
const change = classifyMembership(whereExpr(), oldRow, newRow);
|
|
1774
|
+
switch (change) {
|
|
1775
|
+
case "leave":
|
|
1776
|
+
callbacks?.onDelete?.(oldRow);
|
|
1777
|
+
break;
|
|
1778
|
+
case "enter":
|
|
1779
|
+
callbacks?.onInsert?.(newRow);
|
|
1780
|
+
break;
|
|
1781
|
+
case "stayIn":
|
|
1782
|
+
callbacks?.onUpdate?.(oldRow, newRow);
|
|
1783
|
+
break;
|
|
1784
|
+
case "stayOut":
|
|
1785
|
+
return;
|
|
1786
|
+
}
|
|
1787
|
+
if (ctx.event.id !== latestTransactionEventId) {
|
|
1788
|
+
latestTransactionEventId = ctx.event.id;
|
|
1789
|
+
setRows(reconcile(computeSnapshot()));
|
|
1790
|
+
}
|
|
1791
|
+
};
|
|
1792
|
+
table.onInsert(onInsert);
|
|
1793
|
+
table.onDelete(onDelete);
|
|
1794
|
+
table.onUpdate?.(onUpdate);
|
|
1795
|
+
setRows(reconcile(computeSnapshot()));
|
|
1796
|
+
onCleanup(() => {
|
|
1797
|
+
table.removeOnInsert(onInsert);
|
|
1798
|
+
table.removeOnDelete(onDelete);
|
|
1799
|
+
table.removeOnUpdate?.(onUpdate);
|
|
1800
|
+
});
|
|
1801
|
+
});
|
|
1802
|
+
return [rows, isReady];
|
|
1803
|
+
}
|
|
1804
|
+
function useReducer(reducerDef) {
|
|
1805
|
+
const { getConnection, isActive } = useSpacetimeDB();
|
|
1806
|
+
const reducerName = reducerDef.accessorName;
|
|
1807
|
+
const queue = [];
|
|
1808
|
+
createEffect(() => {
|
|
1809
|
+
if (!isActive) return;
|
|
1810
|
+
const conn = getConnection();
|
|
1811
|
+
if (!conn) return;
|
|
1812
|
+
const fn = conn.reducers[reducerName];
|
|
1813
|
+
if (queue.length) {
|
|
1814
|
+
const pending = queue.splice(0);
|
|
1815
|
+
for (const item of pending) {
|
|
1816
|
+
fn(...item.params).then(item.resolve, item.reject);
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
});
|
|
1820
|
+
return (...params) => {
|
|
1821
|
+
const conn = getConnection();
|
|
1822
|
+
if (!conn) {
|
|
1823
|
+
return new Promise((resolve, reject) => {
|
|
1824
|
+
queue.push({ params, resolve, reject });
|
|
1825
|
+
});
|
|
1826
|
+
}
|
|
1827
|
+
const fn = conn.reducers[reducerName];
|
|
1828
|
+
return fn(...params);
|
|
1829
|
+
};
|
|
1830
|
+
}
|
|
1831
|
+
function useProcedure(procedureDef) {
|
|
1832
|
+
const { getConnection, isActive } = useSpacetimeDB();
|
|
1833
|
+
const procedureName = procedureDef.accessorName;
|
|
1834
|
+
const queue = [];
|
|
1835
|
+
createEffect(() => {
|
|
1836
|
+
if (!isActive) return;
|
|
1837
|
+
const conn = getConnection();
|
|
1838
|
+
if (!conn) return;
|
|
1839
|
+
const fn = conn.procedures[procedureName];
|
|
1840
|
+
if (queue.length) {
|
|
1841
|
+
const pending = queue.splice(0);
|
|
1842
|
+
for (const item of pending) {
|
|
1843
|
+
fn(...item.params).then(item.resolve, item.reject);
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
});
|
|
1847
|
+
return (...params) => {
|
|
1848
|
+
const conn = getConnection();
|
|
1849
|
+
if (!conn) {
|
|
1850
|
+
return new Promise(
|
|
1851
|
+
(resolve, reject) => {
|
|
1852
|
+
queue.push({ params, resolve, reject });
|
|
1853
|
+
}
|
|
1854
|
+
);
|
|
1855
|
+
}
|
|
1856
|
+
const fn = conn.procedures[procedureName];
|
|
1857
|
+
return fn(...params);
|
|
1858
|
+
};
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
export { SpacetimeDBProvider, useProcedure, useReducer, useSpacetimeDB, useTable };
|
|
1862
|
+
//# sourceMappingURL=index.mjs.map
|
|
1863
|
+
//# sourceMappingURL=index.mjs.map
|