jazz-tools 0.7.0-alpha.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/.eslintrc.cjs +24 -0
- package/.turbo/turbo-build.log +24 -0
- package/CHANGELOG.md +42 -0
- package/LICENSE.txt +19 -0
- package/README.md +3 -0
- package/dist/coValueInterfaces.js +8 -0
- package/dist/coValueInterfaces.js.map +1 -0
- package/dist/coValues/account/account.js +11 -0
- package/dist/coValues/account/account.js.map +1 -0
- package/dist/coValues/account/accountOf.js +150 -0
- package/dist/coValues/account/accountOf.js.map +1 -0
- package/dist/coValues/account/migration.js +4 -0
- package/dist/coValues/account/migration.js.map +1 -0
- package/dist/coValues/coList/coList.js +2 -0
- package/dist/coValues/coList/coList.js.map +1 -0
- package/dist/coValues/coList/coListOf.js +235 -0
- package/dist/coValues/coList/coListOf.js.map +1 -0
- package/dist/coValues/coList/internalDocs.js +2 -0
- package/dist/coValues/coList/internalDocs.js.map +1 -0
- package/dist/coValues/coMap/coMap.js +2 -0
- package/dist/coValues/coMap/coMap.js.map +1 -0
- package/dist/coValues/coMap/coMapOf.js +262 -0
- package/dist/coValues/coMap/coMapOf.js.map +1 -0
- package/dist/coValues/coMap/internalDocs.js +2 -0
- package/dist/coValues/coMap/internalDocs.js.map +1 -0
- package/dist/coValues/coStream/coStream.js +2 -0
- package/dist/coValues/coStream/coStream.js.map +1 -0
- package/dist/coValues/coStream/coStreamOf.js +244 -0
- package/dist/coValues/coStream/coStreamOf.js.map +1 -0
- package/dist/coValues/construction.js +34 -0
- package/dist/coValues/construction.js.map +1 -0
- package/dist/coValues/extensions/imageDef.js +36 -0
- package/dist/coValues/extensions/imageDef.js.map +1 -0
- package/dist/coValues/group/group.js +2 -0
- package/dist/coValues/group/group.js.map +1 -0
- package/dist/coValues/group/groupOf.js +109 -0
- package/dist/coValues/group/groupOf.js.map +1 -0
- package/dist/coValues/resolution.js +66 -0
- package/dist/coValues/resolution.js.map +1 -0
- package/dist/errors.js +2 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/refs.js +95 -0
- package/dist/refs.js.map +1 -0
- package/dist/schemaHelpers.js +14 -0
- package/dist/schemaHelpers.js.map +1 -0
- package/dist/subscriptionScope.js +81 -0
- package/dist/subscriptionScope.js.map +1 -0
- package/dist/tests/coList.test.js +207 -0
- package/dist/tests/coList.test.js.map +1 -0
- package/dist/tests/coMap.test.js +238 -0
- package/dist/tests/coMap.test.js.map +1 -0
- package/dist/tests/coStream.test.js +263 -0
- package/dist/tests/coStream.test.js.map +1 -0
- package/dist/tests/types.test.js +33 -0
- package/dist/tests/types.test.js.map +1 -0
- package/package.json +23 -0
- package/src/coValueInterfaces.ts +105 -0
- package/src/coValues/account/account.ts +106 -0
- package/src/coValues/account/accountOf.ts +284 -0
- package/src/coValues/account/migration.ts +12 -0
- package/src/coValues/coList/coList.ts +57 -0
- package/src/coValues/coList/coListOf.ts +377 -0
- package/src/coValues/coList/internalDocs.ts +1 -0
- package/src/coValues/coMap/coMap.ts +110 -0
- package/src/coValues/coMap/coMapOf.ts +451 -0
- package/src/coValues/coMap/internalDocs.ts +1 -0
- package/src/coValues/coStream/coStream.ts +63 -0
- package/src/coValues/coStream/coStreamOf.ts +404 -0
- package/src/coValues/construction.ts +110 -0
- package/src/coValues/extensions/imageDef.ts +51 -0
- package/src/coValues/group/group.ts +27 -0
- package/src/coValues/group/groupOf.ts +183 -0
- package/src/coValues/resolution.ts +111 -0
- package/src/errors.ts +1 -0
- package/src/index.ts +68 -0
- package/src/refs.ts +128 -0
- package/src/schemaHelpers.ts +72 -0
- package/src/subscriptionScope.ts +118 -0
- package/src/tests/coList.test.ts +283 -0
- package/src/tests/coMap.test.ts +357 -0
- package/src/tests/coStream.test.ts +415 -0
- package/src/tests/types.test.ts +37 -0
- package/tsconfig.json +15 -0
@@ -0,0 +1,415 @@
|
|
1
|
+
import { expect, describe, test, beforeEach, Test } from "vitest";
|
2
|
+
|
3
|
+
import { webcrypto } from "node:crypto";
|
4
|
+
import { connectedPeers } from "cojson/src/streamUtils.js";
|
5
|
+
import { newRandomSessionID } from "cojson/src/coValueCore.js";
|
6
|
+
import { Effect, Queue } from "effect";
|
7
|
+
import { AnyAccount, BinaryCoStream, Co, ID, S, Account, jazzReady } from "..";
|
8
|
+
import { Simplify } from "effect/Types";
|
9
|
+
|
10
|
+
if (!("crypto" in globalThis)) {
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
12
|
+
(globalThis as any).crypto = webcrypto;
|
13
|
+
}
|
14
|
+
|
15
|
+
beforeEach(async () => {
|
16
|
+
await jazzReady;
|
17
|
+
});
|
18
|
+
|
19
|
+
describe("Simple CoStream operations", async () => {
|
20
|
+
const me = await Account.create({
|
21
|
+
name: "Hermes Puggington",
|
22
|
+
});
|
23
|
+
|
24
|
+
class TestStream extends Co.stream(S.string).as<TestStream>() {}
|
25
|
+
|
26
|
+
const stream = new TestStream(["milk"], { owner: me });
|
27
|
+
|
28
|
+
test("Construction", () => {
|
29
|
+
expect(stream.by[me.id]?.value).toEqual("milk");
|
30
|
+
expect(stream.in[me.sessionID]?.value).toEqual("milk");
|
31
|
+
});
|
32
|
+
|
33
|
+
describe("Mutation", () => {
|
34
|
+
test("pushing", () => {
|
35
|
+
stream.push("bread");
|
36
|
+
expect(stream.by[me.id]?.value).toEqual("bread");
|
37
|
+
expect(stream.in[me.sessionID]?.value).toEqual("bread");
|
38
|
+
|
39
|
+
stream.push("butter");
|
40
|
+
expect(stream.by[me.id]?.value).toEqual("butter");
|
41
|
+
expect(stream.in[me.sessionID]?.value).toEqual("butter");
|
42
|
+
});
|
43
|
+
});
|
44
|
+
});
|
45
|
+
|
46
|
+
describe("CoStream resolution", async () => {
|
47
|
+
class TwiceNestedStream extends Co.stream(
|
48
|
+
S.string
|
49
|
+
).as<TwiceNestedStream>() {
|
50
|
+
fancyValueOf(account: ID<AnyAccount>) {
|
51
|
+
return "Sir " + this.by[account]?.value;
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
class NestedStream extends Co.stream(
|
56
|
+
TwiceNestedStream
|
57
|
+
).as<NestedStream>() {}
|
58
|
+
|
59
|
+
class TestStream extends Co.stream(NestedStream).as<TestStream>() {}
|
60
|
+
|
61
|
+
const initNodeAndStream = async () => {
|
62
|
+
const me = await Account.create({
|
63
|
+
name: "Hermes Puggington",
|
64
|
+
});
|
65
|
+
|
66
|
+
const stream = new TestStream(
|
67
|
+
[
|
68
|
+
new NestedStream(
|
69
|
+
[new TwiceNestedStream(["milk"], { owner: me })],
|
70
|
+
{ owner: me }
|
71
|
+
),
|
72
|
+
],
|
73
|
+
{ owner: me }
|
74
|
+
);
|
75
|
+
|
76
|
+
return { me, stream };
|
77
|
+
};
|
78
|
+
|
79
|
+
test("Construction", async () => {
|
80
|
+
const { me, stream } = await initNodeAndStream();
|
81
|
+
expect(
|
82
|
+
stream.by[me.id]?.value?.by[me.id]?.value?.by[me.id]?.value
|
83
|
+
).toEqual("milk");
|
84
|
+
});
|
85
|
+
|
86
|
+
test("Loading and availability", async () => {
|
87
|
+
const { me, stream } = await initNodeAndStream();
|
88
|
+
const [initialAsPeer, secondPeer] = connectedPeers(
|
89
|
+
"initial",
|
90
|
+
"second",
|
91
|
+
{ peer1role: "server", peer2role: "client" }
|
92
|
+
);
|
93
|
+
me._raw.core.node.syncManager.addPeer(secondPeer);
|
94
|
+
const meOnSecondPeer = await Account.become({
|
95
|
+
accountID: me.id,
|
96
|
+
accountSecret: me._raw.agentSecret,
|
97
|
+
peersToLoadFrom: [initialAsPeer],
|
98
|
+
sessionID: newRandomSessionID(me.id as any),
|
99
|
+
});
|
100
|
+
|
101
|
+
const loadedStream = await TestStream.load(stream.id, {
|
102
|
+
as: meOnSecondPeer,
|
103
|
+
});
|
104
|
+
|
105
|
+
expect(loadedStream?.by[me.id]?.value).toEqual(undefined);
|
106
|
+
expect(loadedStream?.by[me.id]?.ref?.id).toEqual(
|
107
|
+
stream.by[me.id]?.value?.id
|
108
|
+
);
|
109
|
+
|
110
|
+
const loadedNestedStream = await NestedStream.load(
|
111
|
+
stream.by[me.id]!.value!.id,
|
112
|
+
{ as: meOnSecondPeer }
|
113
|
+
);
|
114
|
+
|
115
|
+
expect(loadedStream?.by[me.id]?.value).toEqual(loadedNestedStream);
|
116
|
+
expect(loadedStream?.by[me.id]?.value?.by[me.id]?.value).toEqual(
|
117
|
+
undefined
|
118
|
+
);
|
119
|
+
expect(loadedStream?.by[me.id]?.ref?.value).toEqual(loadedNestedStream);
|
120
|
+
expect(loadedStream?.by[me.id]?.value?.by[me.id]?.ref?.id).toEqual(
|
121
|
+
stream.by[me.id]?.value?.by[me.id]?.value?.id
|
122
|
+
);
|
123
|
+
|
124
|
+
const loadedTwiceNestedStream = await TwiceNestedStream.load(
|
125
|
+
stream.by[me.id]!.value!.by[me.id]!.value!.id,
|
126
|
+
{ as: meOnSecondPeer }
|
127
|
+
);
|
128
|
+
|
129
|
+
expect(loadedStream?.by[me.id]?.value?.by[me.id]?.value).toEqual(
|
130
|
+
loadedTwiceNestedStream
|
131
|
+
);
|
132
|
+
expect(
|
133
|
+
loadedStream?.by[me.id]?.value?.by[me.id]?.value?.fancyValueOf(me.id)
|
134
|
+
).toEqual("Sir milk");
|
135
|
+
expect(loadedStream?.by[me.id]?.ref?.value).toEqual(loadedNestedStream);
|
136
|
+
expect(loadedStream?.by[me.id]?.value?.by[me.id]?.ref?.value).toEqual(
|
137
|
+
loadedTwiceNestedStream
|
138
|
+
);
|
139
|
+
|
140
|
+
const otherNestedStream = new NestedStream(
|
141
|
+
[new TwiceNestedStream(["butter"], { owner: meOnSecondPeer })],
|
142
|
+
{ owner: meOnSecondPeer }
|
143
|
+
);
|
144
|
+
loadedStream?.push(otherNestedStream);
|
145
|
+
expect(loadedStream?.by[me.id]?.value).toEqual(otherNestedStream);
|
146
|
+
expect(loadedStream?.by[me.id]?.ref?.value).toEqual(otherNestedStream);
|
147
|
+
expect(loadedStream?.by[me.id]?.value?.by[me.id]?.value).toEqual(
|
148
|
+
otherNestedStream.by[me.id]?.value
|
149
|
+
);
|
150
|
+
expect(
|
151
|
+
loadedStream?.by[me.id]?.value?.by[me.id]?.value?.fancyValueOf(me.id)
|
152
|
+
).toEqual("Sir butter");
|
153
|
+
});
|
154
|
+
|
155
|
+
test("Subscription & auto-resolution", async () => {
|
156
|
+
const { me, stream } = await initNodeAndStream();
|
157
|
+
|
158
|
+
const [initialAsPeer, secondAsPeer] = connectedPeers(
|
159
|
+
"initial",
|
160
|
+
"second",
|
161
|
+
{ peer1role: "server", peer2role: "client" }
|
162
|
+
);
|
163
|
+
|
164
|
+
me._raw.core.node.syncManager.addPeer(secondAsPeer);
|
165
|
+
|
166
|
+
const meOnSecondPeer = await Account.become({
|
167
|
+
accountID: me.id,
|
168
|
+
accountSecret: me._raw.agentSecret,
|
169
|
+
peersToLoadFrom: [initialAsPeer],
|
170
|
+
sessionID: newRandomSessionID(me.id as any),
|
171
|
+
});
|
172
|
+
|
173
|
+
await Effect.runPromise(
|
174
|
+
Effect.gen(function* ($) {
|
175
|
+
const queue = yield* $(Queue.unbounded<TestStream>());
|
176
|
+
|
177
|
+
TestStream.subscribe(
|
178
|
+
stream.id,
|
179
|
+
{ as: meOnSecondPeer },
|
180
|
+
(subscribedStream) => {
|
181
|
+
console.log(
|
182
|
+
"subscribedStream.by[me.id]",
|
183
|
+
subscribedStream.by[me.id]
|
184
|
+
);
|
185
|
+
console.log(
|
186
|
+
"subscribedStream.by[me.id]?.value?.by[me.id]?.value",
|
187
|
+
subscribedStream.by[me.id]?.value?.by[me.id]?.value
|
188
|
+
);
|
189
|
+
console.log(
|
190
|
+
"subscribedStream.by[me.id]?.value?.by[me.id]?.value?.by[me.id]?.value",
|
191
|
+
subscribedStream.by[me.id]?.value?.by[me.id]?.value
|
192
|
+
?.by[me.id]?.value
|
193
|
+
);
|
194
|
+
Effect.runPromise(Queue.offer(queue, subscribedStream));
|
195
|
+
}
|
196
|
+
);
|
197
|
+
|
198
|
+
type T = Simplify<TestStream>;
|
199
|
+
const te: T = stream;
|
200
|
+
|
201
|
+
const update1 = yield* $(Queue.take(queue));
|
202
|
+
expect(update1.by[me.id]?.value).toEqual(undefined);
|
203
|
+
|
204
|
+
const update2 = yield* $(Queue.take(queue));
|
205
|
+
expect(update2.by[me.id]?.value).toBeDefined();
|
206
|
+
expect(
|
207
|
+
update2.by[me.id]?.value?.by[me.id]?.value
|
208
|
+
).toBeUndefined();
|
209
|
+
|
210
|
+
const update3 = yield* $(Queue.take(queue));
|
211
|
+
expect(update3.by[me.id]?.value?.by[me.id]?.value).toBeDefined();
|
212
|
+
expect(
|
213
|
+
update3.by[me.id]?.value?.by[me.id]?.value?.by[me.id]?.value
|
214
|
+
).toBe("milk");
|
215
|
+
|
216
|
+
update3.by[me.id]!.value!.by[me.id]!.value!.push("bread");
|
217
|
+
|
218
|
+
const update4 = yield* $(Queue.take(queue));
|
219
|
+
expect(
|
220
|
+
update4.by[me.id]?.value?.by[me.id]?.value?.by[me.id]?.value
|
221
|
+
).toBe("bread");
|
222
|
+
|
223
|
+
// When assigning a new nested stream, we get an update
|
224
|
+
const newTwiceNested = new TwiceNestedStream(["butter"], {
|
225
|
+
owner: meOnSecondPeer,
|
226
|
+
});
|
227
|
+
|
228
|
+
const newNested = new NestedStream([newTwiceNested], {
|
229
|
+
owner: meOnSecondPeer,
|
230
|
+
});
|
231
|
+
|
232
|
+
update4.push(newNested);
|
233
|
+
|
234
|
+
const update5 = yield* $(Queue.take(queue));
|
235
|
+
expect(
|
236
|
+
update5.by[me.id]?.value?.by[me.id]?.value?.by[me.id]?.value
|
237
|
+
).toBe("butter");
|
238
|
+
|
239
|
+
// we get updates when the new nested stream changes
|
240
|
+
newTwiceNested.push("jam");
|
241
|
+
const update6 = yield* $(Queue.take(queue));
|
242
|
+
expect(
|
243
|
+
update6.by[me.id]?.value?.by[me.id]?.value?.by[me.id]?.value
|
244
|
+
).toBe("jam");
|
245
|
+
})
|
246
|
+
);
|
247
|
+
});
|
248
|
+
});
|
249
|
+
|
250
|
+
describe("Simple BinaryCoStream operations", async () => {
|
251
|
+
const me = await Account.create({
|
252
|
+
name: "Hermes Puggington",
|
253
|
+
});
|
254
|
+
|
255
|
+
const stream = new Co.binaryStream(undefined, { owner: me });
|
256
|
+
|
257
|
+
test("Construction", () => {
|
258
|
+
expect(stream.getChunks()).toBeUndefined();
|
259
|
+
});
|
260
|
+
|
261
|
+
test("Mutation", () => {
|
262
|
+
stream.start({ mimeType: "text/plain" });
|
263
|
+
stream.push(new Uint8Array([1, 2, 3]));
|
264
|
+
stream.push(new Uint8Array([4, 5, 6]));
|
265
|
+
stream.end();
|
266
|
+
|
267
|
+
const chunks = stream.getChunks();
|
268
|
+
expect(chunks?.mimeType).toBe("text/plain");
|
269
|
+
expect(chunks?.chunks).toEqual([
|
270
|
+
new Uint8Array([1, 2, 3]),
|
271
|
+
new Uint8Array([4, 5, 6]),
|
272
|
+
]);
|
273
|
+
expect(chunks?.finished).toBe(true);
|
274
|
+
});
|
275
|
+
});
|
276
|
+
|
277
|
+
describe("BinaryCoStream loading & Subscription", async () => {
|
278
|
+
const initNodeAndStream = async () => {
|
279
|
+
const me = await Account.create({
|
280
|
+
name: "Hermes Puggington",
|
281
|
+
});
|
282
|
+
|
283
|
+
const stream = new Co.binaryStream(undefined, { owner: me });
|
284
|
+
|
285
|
+
stream.start({ mimeType: "text/plain" });
|
286
|
+
stream.push(new Uint8Array([1, 2, 3]));
|
287
|
+
stream.push(new Uint8Array([4, 5, 6]));
|
288
|
+
stream.end();
|
289
|
+
|
290
|
+
return { me, stream };
|
291
|
+
};
|
292
|
+
|
293
|
+
test("Construction", async () => {
|
294
|
+
const { me, stream } = await initNodeAndStream();
|
295
|
+
expect(stream.getChunks()).toEqual({
|
296
|
+
mimeType: "text/plain",
|
297
|
+
chunks: [new Uint8Array([1, 2, 3]), new Uint8Array([4, 5, 6])],
|
298
|
+
finished: true,
|
299
|
+
});
|
300
|
+
});
|
301
|
+
|
302
|
+
test("Loading and availability", async () => {
|
303
|
+
const { me, stream } = await initNodeAndStream();
|
304
|
+
const [initialAsPeer, secondAsPeer] = connectedPeers(
|
305
|
+
"initial",
|
306
|
+
"second",
|
307
|
+
{ peer1role: "server", peer2role: "client" }
|
308
|
+
);
|
309
|
+
me._raw.core.node.syncManager.addPeer(secondAsPeer);
|
310
|
+
const meOnSecondPeer = await Account.become({
|
311
|
+
accountID: me.id,
|
312
|
+
accountSecret: me._raw.agentSecret,
|
313
|
+
peersToLoadFrom: [initialAsPeer],
|
314
|
+
sessionID: newRandomSessionID(me.id as any),
|
315
|
+
});
|
316
|
+
|
317
|
+
const loadedStream = await Co.binaryStream.load(stream.id, {
|
318
|
+
as: meOnSecondPeer,
|
319
|
+
});
|
320
|
+
|
321
|
+
expect(loadedStream?.getChunks()).toEqual({
|
322
|
+
mimeType: "text/plain",
|
323
|
+
chunks: [new Uint8Array([1, 2, 3]), new Uint8Array([4, 5, 6])],
|
324
|
+
finished: true,
|
325
|
+
});
|
326
|
+
});
|
327
|
+
|
328
|
+
test("Subscription", async () => {
|
329
|
+
const { me } = await initNodeAndStream();
|
330
|
+
|
331
|
+
const stream = new Co.binaryStream(undefined, { owner: me });
|
332
|
+
|
333
|
+
const [initialAsPeer, secondAsPeer] = connectedPeers(
|
334
|
+
"initial",
|
335
|
+
"second",
|
336
|
+
{ peer1role: "server", peer2role: "client" }
|
337
|
+
);
|
338
|
+
|
339
|
+
me._raw.core.node.syncManager.addPeer(secondAsPeer);
|
340
|
+
|
341
|
+
const meOnSecondPeer = await Account.become({
|
342
|
+
accountID: me.id,
|
343
|
+
accountSecret: me._raw.agentSecret,
|
344
|
+
peersToLoadFrom: [initialAsPeer],
|
345
|
+
sessionID: newRandomSessionID(me.id as any),
|
346
|
+
});
|
347
|
+
|
348
|
+
await Effect.runPromise(
|
349
|
+
Effect.gen(function* ($) {
|
350
|
+
const queue = yield* $(Queue.unbounded<BinaryCoStream>());
|
351
|
+
|
352
|
+
Co.binaryStream.subscribe(
|
353
|
+
stream.id,
|
354
|
+
{ as: meOnSecondPeer },
|
355
|
+
(subscribedStream) => {
|
356
|
+
Effect.runPromise(Queue.offer(queue, subscribedStream));
|
357
|
+
}
|
358
|
+
);
|
359
|
+
|
360
|
+
const update1 = yield* $(Queue.take(queue));
|
361
|
+
expect(update1.getChunks()).toBeUndefined();
|
362
|
+
|
363
|
+
stream.start({ mimeType: "text/plain" });
|
364
|
+
|
365
|
+
const update2 = yield* $(Queue.take(queue));
|
366
|
+
expect(update2.getChunks({ allowUnfinished: true })).toEqual({
|
367
|
+
mimeType: "text/plain",
|
368
|
+
fileName: undefined,
|
369
|
+
chunks: [],
|
370
|
+
totalSizeBytes: undefined,
|
371
|
+
finished: false,
|
372
|
+
});
|
373
|
+
|
374
|
+
stream.push(new Uint8Array([1, 2, 3]));
|
375
|
+
|
376
|
+
const update3 = yield* $(Queue.take(queue));
|
377
|
+
expect(update3.getChunks({ allowUnfinished: true })).toEqual({
|
378
|
+
mimeType: "text/plain",
|
379
|
+
fileName: undefined,
|
380
|
+
chunks: [new Uint8Array([1, 2, 3])],
|
381
|
+
totalSizeBytes: undefined,
|
382
|
+
finished: false,
|
383
|
+
});
|
384
|
+
|
385
|
+
stream.push(new Uint8Array([4, 5, 6]));
|
386
|
+
|
387
|
+
const update4 = yield* $(Queue.take(queue));
|
388
|
+
expect(update4.getChunks({ allowUnfinished: true })).toEqual({
|
389
|
+
mimeType: "text/plain",
|
390
|
+
fileName: undefined,
|
391
|
+
chunks: [
|
392
|
+
new Uint8Array([1, 2, 3]),
|
393
|
+
new Uint8Array([4, 5, 6]),
|
394
|
+
],
|
395
|
+
totalSizeBytes: undefined,
|
396
|
+
finished: false,
|
397
|
+
});
|
398
|
+
|
399
|
+
stream.end();
|
400
|
+
|
401
|
+
const update5 = yield* $(Queue.take(queue));
|
402
|
+
expect(update5.getChunks()).toEqual({
|
403
|
+
mimeType: "text/plain",
|
404
|
+
fileName: undefined,
|
405
|
+
chunks: [
|
406
|
+
new Uint8Array([1, 2, 3]),
|
407
|
+
new Uint8Array([4, 5, 6]),
|
408
|
+
],
|
409
|
+
totalSizeBytes: undefined,
|
410
|
+
finished: true,
|
411
|
+
});
|
412
|
+
})
|
413
|
+
);
|
414
|
+
});
|
415
|
+
});
|
@@ -0,0 +1,37 @@
|
|
1
|
+
import { Account, Co, ImageDefinition, S, jazzReady } from "..";
|
2
|
+
import { describe, test, beforeEach, expectTypeOf } from "vitest";
|
3
|
+
import { ValueRef } from "../refs";
|
4
|
+
import { webcrypto } from "node:crypto";
|
5
|
+
|
6
|
+
if (!("crypto" in globalThis)) {
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
8
|
+
(globalThis as any).crypto = webcrypto;
|
9
|
+
}
|
10
|
+
|
11
|
+
beforeEach(async () => {
|
12
|
+
await jazzReady;
|
13
|
+
});
|
14
|
+
|
15
|
+
class TestMap extends Co.map({
|
16
|
+
name: S.string,
|
17
|
+
image: Co.media.imageDef,
|
18
|
+
maybeImage: S.optional(Co.media.imageDef),
|
19
|
+
}).as<TestMap>() {}
|
20
|
+
|
21
|
+
describe("CoMap type tests", () => {
|
22
|
+
test("Optional field refs work", async () => {
|
23
|
+
const me = await Account.create({
|
24
|
+
name: "Hermes Puggington",
|
25
|
+
});
|
26
|
+
|
27
|
+
const map = new TestMap({
|
28
|
+
name: "Hermes",
|
29
|
+
image: new ImageDefinition({
|
30
|
+
originalSize: [100, 100],
|
31
|
+
placeholderDataURL: "data:image/png;base64,",
|
32
|
+
}, { owner: me }),
|
33
|
+
}, {owner: me});
|
34
|
+
expectTypeOf(map._refs.image).toMatchTypeOf<ValueRef<ImageDefinition>>();
|
35
|
+
expectTypeOf(map._refs.maybeImage).toMatchTypeOf<ValueRef<ImageDefinition>>();
|
36
|
+
})
|
37
|
+
})
|
package/tsconfig.json
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
{
|
2
|
+
"compilerOptions": {
|
3
|
+
"lib": ["ESNext"],
|
4
|
+
"module": "esnext",
|
5
|
+
"target": "ES2020",
|
6
|
+
"moduleResolution": "bundler",
|
7
|
+
"moduleDetection": "force",
|
8
|
+
"strict": true,
|
9
|
+
"skipLibCheck": true,
|
10
|
+
"forceConsistentCasingInFileNames": true,
|
11
|
+
"noUncheckedIndexedAccess": true,
|
12
|
+
"esModuleInterop": true
|
13
|
+
},
|
14
|
+
"include": ["./src/**/*"],
|
15
|
+
}
|