@graffiti-garden/api 0.6.4 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -7
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +3 -3
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +3 -3
- package/dist/src/1-api.d.ts +121 -177
- package/dist/src/1-api.d.ts.map +1 -1
- package/dist/src/2-types.d.ts +38 -151
- package/dist/src/2-types.d.ts.map +1 -1
- package/dist/src/3-errors.d.ts +2 -2
- package/dist/src/3-errors.d.ts.map +1 -1
- package/dist/tests/crud.d.ts +1 -1
- package/dist/tests/crud.d.ts.map +1 -1
- package/dist/tests/discover.d.ts +1 -1
- package/dist/tests/discover.d.ts.map +1 -1
- package/dist/tests/index.d.ts +0 -4
- package/dist/tests/index.d.ts.map +1 -1
- package/dist/tests/utils.d.ts +3 -3
- package/dist/tests/utils.d.ts.map +1 -1
- package/dist/tests.mjs +3 -1269
- package/dist/tests.mjs.map +4 -4
- package/package.json +4 -5
- package/src/1-api.ts +126 -185
- package/src/2-types.ts +39 -156
- package/src/3-errors.ts +6 -6
- package/tests/crud.ts +42 -320
- package/tests/discover.ts +51 -349
- package/tests/index.ts +2 -4
- package/tests/utils.ts +4 -4
- package/dist/tests/channel-stats.d.ts +0 -3
- package/dist/tests/channel-stats.d.ts.map +0 -1
- package/dist/tests/orphans.d.ts +0 -3
- package/dist/tests/orphans.d.ts.map +0 -1
- package/tests/channel-stats.ts +0 -129
- package/tests/orphans.ts +0 -128
package/tests/discover.ts
CHANGED
|
@@ -8,14 +8,14 @@ import type {
|
|
|
8
8
|
import {
|
|
9
9
|
randomString,
|
|
10
10
|
nextStreamValue,
|
|
11
|
-
|
|
11
|
+
randomPostObject,
|
|
12
12
|
continueStream,
|
|
13
13
|
} from "./utils";
|
|
14
14
|
|
|
15
15
|
export const graffitiDiscoverTests = (
|
|
16
16
|
useGraffiti: () => Pick<
|
|
17
17
|
Graffiti,
|
|
18
|
-
"discover" | "
|
|
18
|
+
"discover" | "post" | "delete" | "continueDiscover"
|
|
19
19
|
>,
|
|
20
20
|
useSession1: () => GraffitiSession | Promise<GraffitiSession>,
|
|
21
21
|
useSession2: () => GraffitiSession | Promise<GraffitiSession>,
|
|
@@ -38,33 +38,33 @@ export const graffitiDiscoverTests = (
|
|
|
38
38
|
});
|
|
39
39
|
|
|
40
40
|
it("discover single", async () => {
|
|
41
|
-
const object =
|
|
41
|
+
const object = randomPostObject();
|
|
42
42
|
|
|
43
|
-
const
|
|
43
|
+
const posted = await graffiti.post<{}>(object, session);
|
|
44
44
|
|
|
45
45
|
const queryChannels = [randomString(), object.channels[0]];
|
|
46
46
|
const iterator = graffiti.discover<{}>(queryChannels, {});
|
|
47
47
|
const value = await nextStreamValue<{}>(iterator);
|
|
48
|
+
expect(value.url).toEqual(posted.url);
|
|
48
49
|
expect(value.value).toEqual(object.value);
|
|
49
50
|
expect(value.channels).toEqual([object.channels[0]]);
|
|
50
51
|
expect(value.allowed).toBeUndefined();
|
|
51
52
|
expect(value.actor).toEqual(session.actor);
|
|
52
|
-
expect(value.lastModified).toEqual(putted.lastModified);
|
|
53
53
|
const result2 = await iterator.next();
|
|
54
54
|
expect(result2.done).toBe(true);
|
|
55
55
|
});
|
|
56
56
|
|
|
57
57
|
it("discover wrong channel", async () => {
|
|
58
|
-
const object =
|
|
59
|
-
await graffiti.
|
|
58
|
+
const object = randomPostObject();
|
|
59
|
+
await graffiti.post<{}>(object, session);
|
|
60
60
|
const iterator = graffiti.discover([randomString()], {});
|
|
61
61
|
await expect(iterator.next()).resolves.toHaveProperty("done", true);
|
|
62
62
|
});
|
|
63
63
|
|
|
64
64
|
it("discover not allowed", async () => {
|
|
65
|
-
const object =
|
|
65
|
+
const object = randomPostObject();
|
|
66
66
|
object.allowed = [randomString(), randomString()];
|
|
67
|
-
const
|
|
67
|
+
const posted = await graffiti.post<{}>(object, session1);
|
|
68
68
|
|
|
69
69
|
const iteratorSession1 = graffiti.discover<{}>(
|
|
70
70
|
object.channels,
|
|
@@ -72,11 +72,11 @@ export const graffitiDiscoverTests = (
|
|
|
72
72
|
session1,
|
|
73
73
|
);
|
|
74
74
|
const value = await nextStreamValue<{}>(iteratorSession1);
|
|
75
|
+
expect(value.url).toEqual(posted.url);
|
|
75
76
|
expect(value.value).toEqual(object.value);
|
|
76
77
|
expect(value.channels).toEqual(object.channels);
|
|
77
78
|
expect(value.allowed).toEqual(object.allowed);
|
|
78
79
|
expect(value.actor).toEqual(session1.actor);
|
|
79
|
-
expect(value.lastModified).toEqual(putted.lastModified);
|
|
80
80
|
|
|
81
81
|
const iteratorSession2 = graffiti.discover(object.channels, {}, session2);
|
|
82
82
|
expect(await iteratorSession2.next()).toHaveProperty("done", true);
|
|
@@ -86,9 +86,9 @@ export const graffitiDiscoverTests = (
|
|
|
86
86
|
});
|
|
87
87
|
|
|
88
88
|
it("discover allowed", async () => {
|
|
89
|
-
const object =
|
|
89
|
+
const object = randomPostObject();
|
|
90
90
|
object.allowed = [randomString(), session2.actor, randomString()];
|
|
91
|
-
const
|
|
91
|
+
const posted = await graffiti.post<{}>(object, session1);
|
|
92
92
|
|
|
93
93
|
const iteratorSession2 = graffiti.discover<{}>(
|
|
94
94
|
object.channels,
|
|
@@ -96,133 +96,38 @@ export const graffitiDiscoverTests = (
|
|
|
96
96
|
session2,
|
|
97
97
|
);
|
|
98
98
|
const value = await nextStreamValue<{}>(iteratorSession2);
|
|
99
|
+
expect(value.url).toEqual(posted.url);
|
|
99
100
|
expect(value.value).toEqual(object.value);
|
|
100
101
|
expect(value.allowed).toEqual([session2.actor]);
|
|
101
102
|
expect(value.channels).toEqual(object.channels);
|
|
102
103
|
expect(value.actor).toEqual(session1.actor);
|
|
103
|
-
expect(value.lastModified).toEqual(putted.lastModified);
|
|
104
104
|
});
|
|
105
105
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const putted1 = await graffiti.put<{}>(object1, session1);
|
|
106
|
+
it("discover for actor", async () => {
|
|
107
|
+
const object1 = randomPostObject();
|
|
108
|
+
const posted1 = await graffiti.post<{}>(object1, session1);
|
|
110
109
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
await new Promise((r) => setTimeout(r, 20));
|
|
115
|
-
const putted2 = await graffiti.put<{}>(object2, session2);
|
|
116
|
-
|
|
117
|
-
const iterator = graffiti.discover<{}>(object1.channels, {
|
|
118
|
-
properties: {
|
|
119
|
-
[prop]: {
|
|
120
|
-
enum: [putted1[prop]],
|
|
121
|
-
},
|
|
122
|
-
},
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
const value = await nextStreamValue<{}>(iterator);
|
|
126
|
-
expect(value.url).toEqual(putted1.url);
|
|
127
|
-
expect(value.url).not.toEqual(putted2.url);
|
|
128
|
-
expect(value.value).toEqual(object1.value);
|
|
129
|
-
await expect(iterator.next()).resolves.toHaveProperty("done", true);
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
it("discover with lastModified range", async () => {
|
|
134
|
-
const object = randomPutObject();
|
|
135
|
-
const putted1 = await graffiti.put<{}>(object, session);
|
|
136
|
-
// Make sure the lastModified is different
|
|
137
|
-
await new Promise((r) => setTimeout(r, 20));
|
|
138
|
-
const putted2 = await graffiti.put<{}>(object, session);
|
|
139
|
-
|
|
140
|
-
expect(putted1.url).not.toEqual(putted2.url);
|
|
141
|
-
expect(putted1.lastModified).toBeLessThan(putted2.lastModified);
|
|
142
|
-
|
|
143
|
-
const gtIterator = graffiti.discover([object.channels[0]], {
|
|
144
|
-
properties: {
|
|
145
|
-
lastModified: {
|
|
146
|
-
exclusiveMinimum: putted2.lastModified,
|
|
147
|
-
},
|
|
148
|
-
},
|
|
149
|
-
});
|
|
150
|
-
expect(await gtIterator.next()).toHaveProperty("done", true);
|
|
151
|
-
const gtIteratorEpsilon = graffiti.discover<{}>([object.channels[0]], {
|
|
152
|
-
properties: {
|
|
153
|
-
lastModified: {
|
|
154
|
-
exclusiveMinimum: putted2.lastModified - 0.1,
|
|
155
|
-
},
|
|
156
|
-
},
|
|
157
|
-
});
|
|
158
|
-
const value1 = await nextStreamValue<{}>(gtIteratorEpsilon);
|
|
159
|
-
expect(value1.url).toEqual(putted2.url);
|
|
160
|
-
expect(await gtIteratorEpsilon.next()).toHaveProperty("done", true);
|
|
161
|
-
const gteIterator = graffiti.discover<{}>(object.channels, {
|
|
162
|
-
properties: {
|
|
163
|
-
value: {},
|
|
164
|
-
lastModified: {
|
|
165
|
-
minimum: putted2.lastModified,
|
|
166
|
-
},
|
|
167
|
-
},
|
|
168
|
-
});
|
|
169
|
-
const value = await nextStreamValue<{}>(gteIterator);
|
|
170
|
-
expect(value.url).toEqual(putted2.url);
|
|
171
|
-
expect(await gteIterator.next()).toHaveProperty("done", true);
|
|
172
|
-
const gteIteratorEpsilon = graffiti.discover(object.channels, {
|
|
173
|
-
properties: {
|
|
174
|
-
lastModified: {
|
|
175
|
-
minimum: putted2.lastModified + 0.1,
|
|
176
|
-
},
|
|
177
|
-
},
|
|
178
|
-
});
|
|
179
|
-
expect(await gteIteratorEpsilon.next()).toHaveProperty("done", true);
|
|
180
|
-
|
|
181
|
-
const ltIterator = graffiti.discover(object.channels, {
|
|
182
|
-
properties: {
|
|
183
|
-
lastModified: {
|
|
184
|
-
exclusiveMaximum: putted1.lastModified,
|
|
185
|
-
},
|
|
186
|
-
},
|
|
187
|
-
});
|
|
188
|
-
expect(await ltIterator.next()).toHaveProperty("done", true);
|
|
189
|
-
|
|
190
|
-
const ltIteratorEpsilon = graffiti.discover<{}>(object.channels, {
|
|
191
|
-
properties: {
|
|
192
|
-
lastModified: {
|
|
193
|
-
exclusiveMaximum: putted1.lastModified + 0.1,
|
|
194
|
-
},
|
|
195
|
-
},
|
|
196
|
-
});
|
|
197
|
-
const value3 = await nextStreamValue<{}>(ltIteratorEpsilon);
|
|
198
|
-
expect(value3.url).toEqual(putted1.url);
|
|
199
|
-
expect(await ltIteratorEpsilon.next()).toHaveProperty("done", true);
|
|
110
|
+
const object2 = randomPostObject();
|
|
111
|
+
object2.channels = object1.channels;
|
|
112
|
+
const posted2 = await graffiti.post<{}>(object2, session2);
|
|
200
113
|
|
|
201
|
-
const
|
|
114
|
+
const iterator = graffiti.discover<{}>(object1.channels, {
|
|
202
115
|
properties: {
|
|
203
|
-
|
|
204
|
-
maximum: putted1.lastModified,
|
|
205
|
-
},
|
|
116
|
+
actor: { const: posted1.actor },
|
|
206
117
|
},
|
|
207
118
|
});
|
|
208
|
-
const value2 = await nextStreamValue<{}>(lteIterator);
|
|
209
|
-
expect(value2.url).toEqual(putted1.url);
|
|
210
|
-
expect(await lteIterator.next()).toHaveProperty("done", true);
|
|
211
119
|
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
},
|
|
218
|
-
});
|
|
219
|
-
expect(await lteIteratorEpsilon.next()).toHaveProperty("done", true);
|
|
120
|
+
const value = await nextStreamValue<{}>(iterator);
|
|
121
|
+
expect(value.url).toEqual(posted1.url);
|
|
122
|
+
expect(value.url).not.toEqual(posted2.url);
|
|
123
|
+
expect(value.value).toEqual(object1.value);
|
|
124
|
+
await expect(iterator.next()).resolves.toHaveProperty("done", true);
|
|
220
125
|
});
|
|
221
126
|
|
|
222
127
|
it("discover schema allowed, as and not as owner", async () => {
|
|
223
|
-
const object =
|
|
128
|
+
const object = randomPostObject();
|
|
224
129
|
object.allowed = [randomString(), session2.actor, randomString()];
|
|
225
|
-
await graffiti.
|
|
130
|
+
await graffiti.post<{}>(object, session1);
|
|
226
131
|
|
|
227
132
|
const iteratorSession1 = graffiti.discover<{}>(
|
|
228
133
|
object.channels,
|
|
@@ -233,9 +138,7 @@ export const graffitiDiscoverTests = (
|
|
|
233
138
|
// Make sure session2.actor is in the allow list
|
|
234
139
|
not: {
|
|
235
140
|
items: {
|
|
236
|
-
not: {
|
|
237
|
-
enum: [session2.actor],
|
|
238
|
-
},
|
|
141
|
+
not: { const: session2.actor },
|
|
239
142
|
},
|
|
240
143
|
},
|
|
241
144
|
},
|
|
@@ -272,9 +175,7 @@ export const graffitiDiscoverTests = (
|
|
|
272
175
|
allowed: {
|
|
273
176
|
not: {
|
|
274
177
|
items: {
|
|
275
|
-
not: {
|
|
276
|
-
enum: [object.channels[0]],
|
|
277
|
-
},
|
|
178
|
+
not: { const: object.allowed[0] },
|
|
278
179
|
},
|
|
279
180
|
},
|
|
280
181
|
},
|
|
@@ -294,9 +195,7 @@ export const graffitiDiscoverTests = (
|
|
|
294
195
|
maxItems: 1,
|
|
295
196
|
not: {
|
|
296
197
|
items: {
|
|
297
|
-
not: {
|
|
298
|
-
enum: [session2.actor],
|
|
299
|
-
},
|
|
198
|
+
not: { const: session2.actor },
|
|
300
199
|
},
|
|
301
200
|
},
|
|
302
201
|
},
|
|
@@ -314,9 +213,9 @@ export const graffitiDiscoverTests = (
|
|
|
314
213
|
});
|
|
315
214
|
|
|
316
215
|
it("discover schema channels, as and not as owner", async () => {
|
|
317
|
-
const object =
|
|
216
|
+
const object = randomPostObject();
|
|
318
217
|
object.channels = [randomString(), randomString(), randomString()];
|
|
319
|
-
await graffiti.
|
|
218
|
+
await graffiti.post<{}>(object, session1);
|
|
320
219
|
|
|
321
220
|
const iteratorSession1 = graffiti.discover<{}>(
|
|
322
221
|
[object.channels[0], object.channels[2]],
|
|
@@ -324,12 +223,10 @@ export const graffitiDiscoverTests = (
|
|
|
324
223
|
properties: {
|
|
325
224
|
channels: {
|
|
326
225
|
minItems: 3,
|
|
327
|
-
// Make sure
|
|
226
|
+
// Make sure channel 1 is in the allow list
|
|
328
227
|
not: {
|
|
329
228
|
items: {
|
|
330
|
-
not: {
|
|
331
|
-
enum: [object.channels[1]],
|
|
332
|
-
},
|
|
229
|
+
not: { const: object.channels[1] },
|
|
333
230
|
},
|
|
334
231
|
},
|
|
335
232
|
},
|
|
@@ -366,9 +263,7 @@ export const graffitiDiscoverTests = (
|
|
|
366
263
|
channels: {
|
|
367
264
|
not: {
|
|
368
265
|
items: {
|
|
369
|
-
not: {
|
|
370
|
-
enum: [object.channels[1]],
|
|
371
|
-
},
|
|
266
|
+
not: { const: object.channels[1] },
|
|
372
267
|
},
|
|
373
268
|
},
|
|
374
269
|
},
|
|
@@ -388,9 +283,7 @@ export const graffitiDiscoverTests = (
|
|
|
388
283
|
maxItems: 2,
|
|
389
284
|
not: {
|
|
390
285
|
items: {
|
|
391
|
-
not: {
|
|
392
|
-
enum: [object.channels[2]],
|
|
393
|
-
},
|
|
286
|
+
not: { const: object.channels[2] },
|
|
394
287
|
},
|
|
395
288
|
},
|
|
396
289
|
},
|
|
@@ -408,7 +301,7 @@ export const graffitiDiscoverTests = (
|
|
|
408
301
|
});
|
|
409
302
|
|
|
410
303
|
it("discover query for empty allowed", async () => {
|
|
411
|
-
const publicO =
|
|
304
|
+
const publicO = randomPostObject();
|
|
412
305
|
|
|
413
306
|
const publicSchema = {
|
|
414
307
|
not: {
|
|
@@ -416,7 +309,7 @@ export const graffitiDiscoverTests = (
|
|
|
416
309
|
},
|
|
417
310
|
} satisfies JSONSchema;
|
|
418
311
|
|
|
419
|
-
await graffiti.
|
|
312
|
+
await graffiti.post<{}>(publicO, session1);
|
|
420
313
|
const iterator = graffiti.discover<{}>(
|
|
421
314
|
publicO.channels,
|
|
422
315
|
publicSchema,
|
|
@@ -427,9 +320,9 @@ export const graffitiDiscoverTests = (
|
|
|
427
320
|
expect(value.allowed).toBeUndefined();
|
|
428
321
|
await expect(iterator.next()).resolves.toHaveProperty("done", true);
|
|
429
322
|
|
|
430
|
-
const restricted =
|
|
323
|
+
const restricted = randomPostObject();
|
|
431
324
|
restricted.allowed = [];
|
|
432
|
-
await graffiti.
|
|
325
|
+
await graffiti.post<{}>(restricted, session1);
|
|
433
326
|
const iterator2 = graffiti.discover(
|
|
434
327
|
restricted.channels,
|
|
435
328
|
publicSchema,
|
|
@@ -439,19 +332,19 @@ export const graffitiDiscoverTests = (
|
|
|
439
332
|
});
|
|
440
333
|
|
|
441
334
|
it("discover query for values", async () => {
|
|
442
|
-
const object1 =
|
|
335
|
+
const object1 = randomPostObject();
|
|
443
336
|
object1.value = { test: randomString() };
|
|
444
|
-
await graffiti.
|
|
337
|
+
await graffiti.post<{}>(object1, session);
|
|
445
338
|
|
|
446
|
-
const object2 =
|
|
339
|
+
const object2 = randomPostObject();
|
|
447
340
|
object2.channels = object1.channels;
|
|
448
341
|
object2.value = { test: randomString(), something: randomString() };
|
|
449
|
-
await graffiti.
|
|
342
|
+
await graffiti.post<{}>(object2, session);
|
|
450
343
|
|
|
451
|
-
const object3 =
|
|
344
|
+
const object3 = randomPostObject();
|
|
452
345
|
object3.channels = object1.channels;
|
|
453
346
|
object3.value = { other: randomString(), something: randomString() };
|
|
454
|
-
await graffiti.
|
|
347
|
+
await graffiti.post<{}>(object3, session);
|
|
455
348
|
|
|
456
349
|
const counts = new Map<string, number>();
|
|
457
350
|
for (const property of ["test", "something", "other"] as const) {
|
|
@@ -479,9 +372,9 @@ export const graffitiDiscoverTests = (
|
|
|
479
372
|
for (const continueType of ["cursor", "continue"] as const) {
|
|
480
373
|
describe(`continue discover with ${continueType}`, () => {
|
|
481
374
|
it("discover for deleted content", async () => {
|
|
482
|
-
const object =
|
|
375
|
+
const object = randomPostObject();
|
|
483
376
|
|
|
484
|
-
const
|
|
377
|
+
const posted = await graffiti.post<{}>(object, session);
|
|
485
378
|
|
|
486
379
|
const iterator1 = graffiti.discover<{}>(object.channels, {});
|
|
487
380
|
const value1 = await nextStreamValue<{}>(iterator1);
|
|
@@ -489,7 +382,7 @@ export const graffitiDiscoverTests = (
|
|
|
489
382
|
const returnValue = await iterator1.next();
|
|
490
383
|
assert(returnValue.done, "value2 is not done");
|
|
491
384
|
|
|
492
|
-
|
|
385
|
+
await graffiti.delete(posted, session);
|
|
493
386
|
|
|
494
387
|
const iterator = graffiti.discover(object.channels, {});
|
|
495
388
|
await expect(iterator.next()).resolves.toHaveProperty("done", true);
|
|
@@ -502,203 +395,12 @@ export const graffitiDiscoverTests = (
|
|
|
502
395
|
const value = await tombIterator.next();
|
|
503
396
|
assert(!value.done && !value.value.error, "value is done");
|
|
504
397
|
assert(value.value.tombstone, "value is not tombstone");
|
|
505
|
-
expect(value.value.object.url).toEqual(
|
|
398
|
+
expect(value.value.object.url).toEqual(posted.url);
|
|
506
399
|
await expect(tombIterator.next()).resolves.toHaveProperty(
|
|
507
400
|
"done",
|
|
508
401
|
true,
|
|
509
402
|
);
|
|
510
403
|
});
|
|
511
|
-
|
|
512
|
-
it("discover for replaced channels", async () => {
|
|
513
|
-
// Do this a bunch to check for concurrency issues
|
|
514
|
-
async function runTest() {
|
|
515
|
-
const object1 = randomPutObject();
|
|
516
|
-
const putted = await graffiti.put<{}>(object1, session);
|
|
517
|
-
|
|
518
|
-
const iterator3 = graffiti.discover<{}>(object1.channels, {});
|
|
519
|
-
const value3 = await nextStreamValue<{}>(iterator3);
|
|
520
|
-
expect(value3.value).toEqual(object1.value);
|
|
521
|
-
const returnValue = await iterator3.next();
|
|
522
|
-
assert(returnValue.done, "value2 is not done");
|
|
523
|
-
|
|
524
|
-
const object2 = randomPutObject();
|
|
525
|
-
const replaced = await graffiti.put<{}>(
|
|
526
|
-
{
|
|
527
|
-
...object2,
|
|
528
|
-
url: putted.url,
|
|
529
|
-
},
|
|
530
|
-
session,
|
|
531
|
-
);
|
|
532
|
-
|
|
533
|
-
const iterator1 = graffiti.discover<{}>(object1.channels, {});
|
|
534
|
-
const iterator2 = graffiti.discover<{}>(object2.channels, {});
|
|
535
|
-
const tombIterator = continueStream<{}>(
|
|
536
|
-
graffiti,
|
|
537
|
-
returnValue.value,
|
|
538
|
-
continueType,
|
|
539
|
-
);
|
|
540
|
-
|
|
541
|
-
if (putted.lastModified === replaced.lastModified) {
|
|
542
|
-
const value1 = await iterator1.next();
|
|
543
|
-
const value2 = await iterator2.next();
|
|
544
|
-
const value3 = await tombIterator.next();
|
|
545
|
-
|
|
546
|
-
// Only one should be done
|
|
547
|
-
expect(value1.done || value2.done).toBe(true);
|
|
548
|
-
expect(value1.done && value2.done).toBe(false);
|
|
549
|
-
|
|
550
|
-
assert(!value3.done && !value3.value.error, "value is done");
|
|
551
|
-
expect(value3.value.tombstone || value2.done).toBe(true);
|
|
552
|
-
expect(value3.value.tombstone && value2.done).toBe(false);
|
|
553
|
-
return;
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
// Otherwise 1 should be done and 2 should not
|
|
557
|
-
const value5 = await iterator1.next();
|
|
558
|
-
assert(value5.done, "value5 is not done");
|
|
559
|
-
|
|
560
|
-
const value4 = await tombIterator.next();
|
|
561
|
-
assert(!value4.done && !value4.value.error, "value is done");
|
|
562
|
-
|
|
563
|
-
assert(value4.value.tombstone, "value is not tombstone");
|
|
564
|
-
expect(value4.value.object.url).toEqual(putted.url);
|
|
565
|
-
expect(value4.value.object.lastModified).toEqual(
|
|
566
|
-
replaced.lastModified,
|
|
567
|
-
);
|
|
568
|
-
|
|
569
|
-
const value2 = await nextStreamValue<{}>(iterator2);
|
|
570
|
-
await expect(iterator2.next()).resolves.toHaveProperty(
|
|
571
|
-
"done",
|
|
572
|
-
true,
|
|
573
|
-
);
|
|
574
|
-
|
|
575
|
-
expect(value2.value).toEqual(object2.value);
|
|
576
|
-
expect(value2.channels).toEqual(object2.channels);
|
|
577
|
-
expect(value2.lastModified).toEqual(replaced.lastModified);
|
|
578
|
-
|
|
579
|
-
// Replace the channels back
|
|
580
|
-
const patched = await graffiti.patch(
|
|
581
|
-
{
|
|
582
|
-
channels: [
|
|
583
|
-
{ op: "replace", path: "", value: object1.channels },
|
|
584
|
-
],
|
|
585
|
-
},
|
|
586
|
-
replaced,
|
|
587
|
-
session,
|
|
588
|
-
);
|
|
589
|
-
|
|
590
|
-
const tombIterator2 = continueStream<{}>(
|
|
591
|
-
graffiti,
|
|
592
|
-
value5.value,
|
|
593
|
-
continueType,
|
|
594
|
-
);
|
|
595
|
-
|
|
596
|
-
let result:
|
|
597
|
-
| {
|
|
598
|
-
tombstone: true;
|
|
599
|
-
object: {
|
|
600
|
-
url: string;
|
|
601
|
-
lastModified: number;
|
|
602
|
-
};
|
|
603
|
-
}
|
|
604
|
-
| {
|
|
605
|
-
tombstone?: undefined;
|
|
606
|
-
object: GraffitiObjectBase;
|
|
607
|
-
}
|
|
608
|
-
| undefined;
|
|
609
|
-
for await (const value of tombIterator2) {
|
|
610
|
-
if (value.error) continue;
|
|
611
|
-
if (!result) {
|
|
612
|
-
result = value;
|
|
613
|
-
continue;
|
|
614
|
-
}
|
|
615
|
-
if (
|
|
616
|
-
value.object.lastModified > result.object.lastModified ||
|
|
617
|
-
(value.object.lastModified === result.object.lastModified &&
|
|
618
|
-
!value.tombstone &&
|
|
619
|
-
result.tombstone)
|
|
620
|
-
) {
|
|
621
|
-
result = value;
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
assert(result, "result is not defined");
|
|
626
|
-
assert(!result.tombstone, "result is tombstone");
|
|
627
|
-
expect(result.object.url).toEqual(replaced.url);
|
|
628
|
-
expect(result.object.lastModified).toEqual(patched.lastModified);
|
|
629
|
-
expect(result.object.channels).toEqual(object1.channels);
|
|
630
|
-
expect(result.object.value).toEqual(object2.value);
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
// Run the test 20 times in parallel to check for concurrency issues
|
|
634
|
-
await Promise.allSettled(Array.from({ length: 20 }, () => runTest()));
|
|
635
|
-
});
|
|
636
|
-
|
|
637
|
-
it("discover for patched allowed", async () => {
|
|
638
|
-
const object = randomPutObject();
|
|
639
|
-
const putted = await graffiti.put<{}>(object, session);
|
|
640
|
-
|
|
641
|
-
const iterator1 = graffiti.discover<{}>(object.channels, {});
|
|
642
|
-
const value1 = await nextStreamValue<{}>(iterator1);
|
|
643
|
-
expect(value1.value).toEqual(object.value);
|
|
644
|
-
const returnValue = await iterator1.next();
|
|
645
|
-
assert(returnValue.done, "value2 is not done");
|
|
646
|
-
|
|
647
|
-
await graffiti.patch(
|
|
648
|
-
{
|
|
649
|
-
allowed: [{ op: "add", path: "", value: [] }],
|
|
650
|
-
},
|
|
651
|
-
putted,
|
|
652
|
-
session,
|
|
653
|
-
);
|
|
654
|
-
const iterator2 = graffiti.discover(object.channels, {});
|
|
655
|
-
expect(await iterator2.next()).toHaveProperty("done", true);
|
|
656
|
-
|
|
657
|
-
const iterator = continueStream<{}>(
|
|
658
|
-
graffiti,
|
|
659
|
-
returnValue.value,
|
|
660
|
-
continueType,
|
|
661
|
-
);
|
|
662
|
-
const value = await iterator.next();
|
|
663
|
-
assert(!value.done && !value.value.error, "value is done");
|
|
664
|
-
assert(value.value.tombstone, "value is not tombstone");
|
|
665
|
-
expect(value.value.object.url).toEqual(putted.url);
|
|
666
|
-
await expect(iterator.next()).resolves.toHaveProperty("done", true);
|
|
667
|
-
});
|
|
668
|
-
|
|
669
|
-
it("put concurrently and discover one", async () => {
|
|
670
|
-
const object = randomPutObject();
|
|
671
|
-
|
|
672
|
-
// Put a first one to get a URI
|
|
673
|
-
const putted = await graffiti.put<{}>(object, session);
|
|
674
|
-
|
|
675
|
-
const putPromises = Array(99)
|
|
676
|
-
.fill(0)
|
|
677
|
-
.map(() =>
|
|
678
|
-
graffiti.put<{}>(
|
|
679
|
-
{
|
|
680
|
-
...object,
|
|
681
|
-
url: putted.url,
|
|
682
|
-
},
|
|
683
|
-
session,
|
|
684
|
-
),
|
|
685
|
-
);
|
|
686
|
-
await Promise.all(putPromises);
|
|
687
|
-
|
|
688
|
-
const iterator = graffiti.discover(object.channels, {});
|
|
689
|
-
let tombstoneCount = 0;
|
|
690
|
-
let valueCount = 0;
|
|
691
|
-
for await (const result of iterator) {
|
|
692
|
-
assert(!result.error, "result has error");
|
|
693
|
-
if (result.tombstone) {
|
|
694
|
-
tombstoneCount++;
|
|
695
|
-
} else {
|
|
696
|
-
valueCount++;
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
expect(tombstoneCount).toBe(0);
|
|
700
|
-
expect(valueCount).toBe(1);
|
|
701
|
-
});
|
|
702
404
|
});
|
|
703
405
|
}
|
|
704
406
|
});
|
package/tests/index.ts
CHANGED
package/tests/utils.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { assert } from "vitest";
|
|
2
2
|
import type {
|
|
3
|
-
|
|
3
|
+
GraffitiPostObject,
|
|
4
4
|
GraffitiObjectStream,
|
|
5
5
|
JSONSchema,
|
|
6
6
|
GraffitiObject,
|
|
@@ -27,7 +27,7 @@ export function randomValue() {
|
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
export function
|
|
30
|
+
export function randomPostObject(): GraffitiPostObject<{}> {
|
|
31
31
|
return {
|
|
32
32
|
value: randomValue(),
|
|
33
33
|
channels: [randomString(), randomString()],
|
|
@@ -44,13 +44,13 @@ export async function nextStreamValue<Schema extends JSONSchema>(
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
export function continueStream<Schema extends JSONSchema>(
|
|
47
|
-
graffiti: Pick<Graffiti, "
|
|
47
|
+
graffiti: Pick<Graffiti, "continueDiscover">,
|
|
48
48
|
streamReturn: GraffitiObjectStreamReturn<Schema>,
|
|
49
49
|
type: "cursor" | "continue",
|
|
50
50
|
session?: GraffitiSession | null,
|
|
51
51
|
): GraffitiObjectStreamContinue<Schema> {
|
|
52
52
|
if (type === "cursor") {
|
|
53
|
-
return graffiti.
|
|
53
|
+
return graffiti.continueDiscover(
|
|
54
54
|
streamReturn.cursor,
|
|
55
55
|
session,
|
|
56
56
|
) as unknown as GraffitiObjectStreamContinue<Schema>;
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import type { Graffiti, GraffitiSession } from "@graffiti-garden/api";
|
|
2
|
-
export declare const graffitiChannelStatsTests: (useGraffiti: () => Pick<Graffiti, "channelStats" | "put" | "delete" | "patch">, useSession1: () => GraffitiSession | Promise<GraffitiSession>, useSession2: () => GraffitiSession | Promise<GraffitiSession>) => void;
|
|
3
|
-
//# sourceMappingURL=channel-stats.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"channel-stats.d.ts","sourceRoot":"","sources":["../../tests/channel-stats.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGtE,eAAO,MAAM,yBAAyB,GACpC,aAAa,MAAM,IAAI,CACrB,QAAQ,EACR,cAAc,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAC5C,EACD,aAAa,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,EAC7D,aAAa,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,SAsH9D,CAAC"}
|
package/dist/tests/orphans.d.ts
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import type { Graffiti, GraffitiSession } from "@graffiti-garden/api";
|
|
2
|
-
export declare const graffitiOrphanTests: (useGraffiti: () => Pick<Graffiti, "recoverOrphans" | "put" | "delete" | "patch" | "continueObjectStream">, useSession1: () => GraffitiSession | Promise<GraffitiSession>, useSession2: () => GraffitiSession | Promise<GraffitiSession>) => void;
|
|
3
|
-
//# sourceMappingURL=orphans.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"orphans.d.ts","sourceRoot":"","sources":["../../tests/orphans.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAQtE,eAAO,MAAM,mBAAmB,GAC9B,aAAa,MAAM,IAAI,CACrB,QAAQ,EACR,gBAAgB,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,sBAAsB,CACvE,EACD,aAAa,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,EAC7D,aAAa,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,SAgH9D,CAAC"}
|