@graffiti-garden/api 0.6.4 → 1.0.1
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 +4 -4
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +4 -4
- package/dist/src/1-api.d.ts +172 -178
- package/dist/src/1-api.d.ts.map +1 -1
- package/dist/src/2-types.d.ts +39 -152
- package/dist/src/2-types.d.ts.map +1 -1
- package/dist/src/3-errors.d.ts +2 -8
- package/dist/src/3-errors.d.ts.map +1 -1
- package/dist/src/4-utilities.d.ts +8 -0
- package/dist/src/4-utilities.d.ts.map +1 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.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 +1 -2
- package/dist/tests/index.d.ts.map +1 -1
- package/dist/tests/media.d.ts +3 -0
- package/dist/tests/media.d.ts.map +1 -0
- package/dist/tests/utils.d.ts +3 -3
- package/dist/tests/utils.d.ts.map +1 -1
- package/dist/tests.mjs +207 -790
- package/dist/tests.mjs.map +4 -4
- package/package.json +6 -6
- package/src/1-api.ts +182 -186
- package/src/2-types.ts +42 -157
- package/src/3-errors.ts +6 -22
- package/src/4-utilities.ts +65 -0
- package/src/index.ts +1 -0
- package/tests/crud.ts +39 -332
- package/tests/discover.ts +51 -349
- package/tests/index.ts +1 -2
- package/tests/media.ts +158 -0
- 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/dist/tests.mjs
CHANGED
|
@@ -4,9 +4,7 @@ import {
|
|
|
4
4
|
GraffitiErrorNotFound,
|
|
5
5
|
GraffitiErrorSchemaMismatch,
|
|
6
6
|
GraffitiErrorInvalidSchema,
|
|
7
|
-
GraffitiErrorForbidden
|
|
8
|
-
GraffitiErrorPatchTestFailed,
|
|
9
|
-
GraffitiErrorPatchError
|
|
7
|
+
GraffitiErrorForbidden
|
|
10
8
|
} from "@graffiti-garden/api";
|
|
11
9
|
|
|
12
10
|
// tests/utils.ts
|
|
@@ -22,7 +20,7 @@ function randomValue() {
|
|
|
22
20
|
[randomString()]: randomString()
|
|
23
21
|
};
|
|
24
22
|
}
|
|
25
|
-
function
|
|
23
|
+
function randomPostObject() {
|
|
26
24
|
return {
|
|
27
25
|
value: randomValue(),
|
|
28
26
|
channels: [randomString(), randomString()]
|
|
@@ -36,7 +34,7 @@ async function nextStreamValue(iterator) {
|
|
|
36
34
|
}
|
|
37
35
|
function continueStream(graffiti, streamReturn, type, session) {
|
|
38
36
|
if (type === "cursor") {
|
|
39
|
-
return graffiti.
|
|
37
|
+
return graffiti.continueDiscover(
|
|
40
38
|
streamReturn.cursor,
|
|
41
39
|
session
|
|
42
40
|
);
|
|
@@ -63,15 +61,15 @@ var graffitiCRUDTests = (useGraffiti, useSession1, useSession2) => {
|
|
|
63
61
|
session = session1;
|
|
64
62
|
session2 = await useSession2();
|
|
65
63
|
});
|
|
66
|
-
it("
|
|
64
|
+
it("post, get, delete", async () => {
|
|
67
65
|
const value = {
|
|
68
66
|
something: "hello, world~ c:"
|
|
69
67
|
};
|
|
70
68
|
const channels = [randomString(), randomString()];
|
|
71
|
-
const previous = await graffiti.
|
|
72
|
-
expect(previous.value).toEqual(
|
|
73
|
-
expect(previous.channels).toEqual(
|
|
74
|
-
expect(previous.allowed).toEqual(
|
|
69
|
+
const previous = await graffiti.post({ value, channels }, session);
|
|
70
|
+
expect(previous.value).toEqual(value);
|
|
71
|
+
expect(previous.channels).toEqual(channels);
|
|
72
|
+
expect(previous.allowed).toEqual(void 0);
|
|
75
73
|
expect(previous.actor).toEqual(session.actor);
|
|
76
74
|
const gotten = await graffiti.get(previous, {});
|
|
77
75
|
expect(gotten.value).toEqual(value);
|
|
@@ -79,100 +77,24 @@ var graffitiCRUDTests = (useGraffiti, useSession1, useSession2) => {
|
|
|
79
77
|
expect(gotten.allowed).toBeUndefined();
|
|
80
78
|
expect(gotten.url).toEqual(previous.url);
|
|
81
79
|
expect(gotten.actor).toEqual(previous.actor);
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
something: "goodbye, world~ :c"
|
|
85
|
-
};
|
|
86
|
-
const beforeReplaced = await graffiti.put(
|
|
87
|
-
{
|
|
88
|
-
url: previous.url,
|
|
89
|
-
value: newValue,
|
|
90
|
-
channels: []
|
|
91
|
-
},
|
|
92
|
-
session
|
|
93
|
-
);
|
|
94
|
-
expect(beforeReplaced.value).toEqual(value);
|
|
95
|
-
expect(beforeReplaced.url).toEqual(previous.url);
|
|
96
|
-
expect(beforeReplaced.actor).toEqual(previous.actor);
|
|
97
|
-
expect(beforeReplaced.lastModified).toBeGreaterThanOrEqual(
|
|
98
|
-
gotten.lastModified
|
|
99
|
-
);
|
|
100
|
-
const afterReplaced = await graffiti.get(previous, {});
|
|
101
|
-
expect(afterReplaced.value).toEqual(newValue);
|
|
102
|
-
expect(afterReplaced.lastModified).toEqual(beforeReplaced.lastModified);
|
|
103
|
-
const beforeDeleted = await graffiti.delete(afterReplaced, session);
|
|
104
|
-
expect(beforeDeleted.value).toEqual(newValue);
|
|
105
|
-
expect(beforeDeleted.lastModified).toBeGreaterThanOrEqual(
|
|
106
|
-
beforeReplaced.lastModified
|
|
107
|
-
);
|
|
108
|
-
await expect(graffiti.get(afterReplaced, {})).rejects.toBeInstanceOf(
|
|
80
|
+
await graffiti.delete(gotten, session);
|
|
81
|
+
await expect(graffiti.get(gotten, {})).rejects.toBeInstanceOf(
|
|
109
82
|
GraffitiErrorNotFound
|
|
110
83
|
);
|
|
111
|
-
await expect(graffiti.delete(
|
|
84
|
+
await expect(graffiti.delete(gotten, session)).rejects.toThrow(
|
|
112
85
|
GraffitiErrorNotFound
|
|
113
86
|
);
|
|
114
|
-
await expect(
|
|
115
|
-
graffiti.put(
|
|
116
|
-
{ url: beforeDeleted.url, value: {}, channels: [] },
|
|
117
|
-
session
|
|
118
|
-
)
|
|
119
|
-
).rejects.toThrow(GraffitiErrorNotFound);
|
|
120
87
|
});
|
|
121
|
-
it("
|
|
122
|
-
await
|
|
123
|
-
graffiti.put(
|
|
124
|
-
{ value: {}, channels: [], actor: session2.actor },
|
|
125
|
-
session1
|
|
126
|
-
)
|
|
127
|
-
).rejects.toThrow(GraffitiErrorForbidden);
|
|
128
|
-
const putted = await graffiti.put(
|
|
88
|
+
it("post then delete with wrong actor", async () => {
|
|
89
|
+
const posted = await graffiti.post(
|
|
129
90
|
{ value: {}, channels: [] },
|
|
130
91
|
session2
|
|
131
92
|
);
|
|
132
|
-
await expect(
|
|
133
|
-
graffiti.put(
|
|
134
|
-
{
|
|
135
|
-
url: putted.url,
|
|
136
|
-
value: {},
|
|
137
|
-
channels: []
|
|
138
|
-
},
|
|
139
|
-
session1
|
|
140
|
-
)
|
|
141
|
-
).rejects.toThrow(GraffitiErrorForbidden);
|
|
142
|
-
await expect(graffiti.delete(putted, session1)).rejects.toThrow(
|
|
143
|
-
GraffitiErrorForbidden
|
|
144
|
-
);
|
|
145
|
-
await expect(graffiti.patch({}, putted, session1)).rejects.toThrow(
|
|
93
|
+
await expect(graffiti.delete(posted, session1)).rejects.toThrow(
|
|
146
94
|
GraffitiErrorForbidden
|
|
147
95
|
);
|
|
148
96
|
});
|
|
149
|
-
it("
|
|
150
|
-
const putted = await graffiti.put(
|
|
151
|
-
{
|
|
152
|
-
value: {},
|
|
153
|
-
channels: [],
|
|
154
|
-
allowed: []
|
|
155
|
-
},
|
|
156
|
-
session1
|
|
157
|
-
);
|
|
158
|
-
await expect(
|
|
159
|
-
graffiti.put(
|
|
160
|
-
{
|
|
161
|
-
url: putted.url,
|
|
162
|
-
value: {},
|
|
163
|
-
channels: []
|
|
164
|
-
},
|
|
165
|
-
session2
|
|
166
|
-
)
|
|
167
|
-
).rejects.toThrow(GraffitiErrorNotFound);
|
|
168
|
-
await expect(graffiti.patch({}, putted, session2)).rejects.toThrow(
|
|
169
|
-
GraffitiErrorNotFound
|
|
170
|
-
);
|
|
171
|
-
await expect(graffiti.delete(putted, session2)).rejects.toThrow(
|
|
172
|
-
GraffitiErrorNotFound
|
|
173
|
-
);
|
|
174
|
-
});
|
|
175
|
-
it("put and get with schema", async () => {
|
|
97
|
+
it("post and get with schema", async () => {
|
|
176
98
|
const schema = {
|
|
177
99
|
properties: {
|
|
178
100
|
value: {
|
|
@@ -207,26 +129,26 @@ var graffitiCRUDTests = (useGraffiti, useSession1, useSession2) => {
|
|
|
207
129
|
deepProp: "hello"
|
|
208
130
|
}
|
|
209
131
|
};
|
|
210
|
-
const
|
|
132
|
+
const posted = await graffiti.post(
|
|
211
133
|
{
|
|
212
134
|
value: goodValue,
|
|
213
135
|
channels: []
|
|
214
136
|
},
|
|
215
137
|
session
|
|
216
138
|
);
|
|
217
|
-
const gotten = await graffiti.get(
|
|
139
|
+
const gotten = await graffiti.get(posted, schema);
|
|
218
140
|
expect(gotten.value.something).toEqual(goodValue.something);
|
|
219
141
|
expect(gotten.value.another).toEqual(goodValue.another);
|
|
220
142
|
expect(gotten.value.another[0]).toEqual(1);
|
|
221
143
|
expect(gotten.value.deeper.deepProp).toEqual(goodValue.deeper.deepProp);
|
|
222
144
|
});
|
|
223
|
-
it("
|
|
224
|
-
const
|
|
145
|
+
it("post and get with invalid schema", async () => {
|
|
146
|
+
const posted = await graffiti.post(
|
|
225
147
|
{ value: {}, channels: [] },
|
|
226
148
|
session
|
|
227
149
|
);
|
|
228
150
|
await expect(
|
|
229
|
-
graffiti.get(
|
|
151
|
+
graffiti.get(posted, {
|
|
230
152
|
properties: {
|
|
231
153
|
value: {
|
|
232
154
|
//@ts-ignore
|
|
@@ -236,8 +158,8 @@ var graffitiCRUDTests = (useGraffiti, useSession1, useSession2) => {
|
|
|
236
158
|
})
|
|
237
159
|
).rejects.toThrow(GraffitiErrorInvalidSchema);
|
|
238
160
|
});
|
|
239
|
-
it("
|
|
240
|
-
const
|
|
161
|
+
it("post and get with wrong schema", async () => {
|
|
162
|
+
const posted = await graffiti.post(
|
|
241
163
|
{
|
|
242
164
|
value: {
|
|
243
165
|
hello: "world"
|
|
@@ -247,7 +169,7 @@ var graffitiCRUDTests = (useGraffiti, useSession1, useSession2) => {
|
|
|
247
169
|
session
|
|
248
170
|
);
|
|
249
171
|
await expect(
|
|
250
|
-
graffiti.get(
|
|
172
|
+
graffiti.get(posted, {
|
|
251
173
|
properties: {
|
|
252
174
|
value: {
|
|
253
175
|
properties: {
|
|
@@ -260,34 +182,36 @@ var graffitiCRUDTests = (useGraffiti, useSession1, useSession2) => {
|
|
|
260
182
|
})
|
|
261
183
|
).rejects.toThrow(GraffitiErrorSchemaMismatch);
|
|
262
184
|
});
|
|
263
|
-
it("
|
|
185
|
+
it("post and get with empty access control", async () => {
|
|
264
186
|
const value = {
|
|
265
187
|
um: "hi"
|
|
266
188
|
};
|
|
267
189
|
const allowed = [randomString()];
|
|
268
190
|
const channels = [randomString()];
|
|
269
|
-
const
|
|
191
|
+
const posted = await graffiti.post(
|
|
270
192
|
{ value, allowed, channels },
|
|
271
193
|
session1
|
|
272
194
|
);
|
|
273
|
-
const gotten = await graffiti.get(
|
|
195
|
+
const gotten = await graffiti.get(posted, {}, session1);
|
|
196
|
+
expect(gotten.url).toEqual(posted.url);
|
|
197
|
+
expect(gotten.actor).toEqual(session1.actor);
|
|
274
198
|
expect(gotten.value).toEqual(value);
|
|
275
199
|
expect(gotten.allowed).toEqual(allowed);
|
|
276
200
|
expect(gotten.channels).toEqual(channels);
|
|
277
|
-
await expect(graffiti.get(
|
|
201
|
+
await expect(graffiti.get(posted, {})).rejects.toBeInstanceOf(
|
|
278
202
|
GraffitiErrorNotFound
|
|
279
203
|
);
|
|
280
|
-
await expect(graffiti.get(
|
|
204
|
+
await expect(graffiti.get(posted, {}, session2)).rejects.toBeInstanceOf(
|
|
281
205
|
GraffitiErrorNotFound
|
|
282
206
|
);
|
|
283
207
|
});
|
|
284
|
-
it("
|
|
208
|
+
it("post and get with specific access control", async () => {
|
|
285
209
|
const value = {
|
|
286
210
|
um: "hi"
|
|
287
211
|
};
|
|
288
212
|
const allowed = [randomString(), session2.actor, randomString()];
|
|
289
213
|
const channels = [randomString()];
|
|
290
|
-
const
|
|
214
|
+
const posted = await graffiti.post(
|
|
291
215
|
{
|
|
292
216
|
value,
|
|
293
217
|
allowed,
|
|
@@ -295,204 +219,22 @@ var graffitiCRUDTests = (useGraffiti, useSession1, useSession2) => {
|
|
|
295
219
|
},
|
|
296
220
|
session1
|
|
297
221
|
);
|
|
298
|
-
const gotten = await graffiti.get(
|
|
222
|
+
const gotten = await graffiti.get(posted, {}, session1);
|
|
223
|
+
expect(gotten.url).toEqual(posted.url);
|
|
224
|
+
expect(gotten.actor).toEqual(session1.actor);
|
|
299
225
|
expect(gotten.value).toEqual(value);
|
|
300
226
|
expect(gotten.allowed).toEqual(allowed);
|
|
301
227
|
expect(gotten.channels).toEqual(channels);
|
|
302
|
-
await expect(graffiti.get(
|
|
228
|
+
await expect(graffiti.get(posted, {})).rejects.toBeInstanceOf(
|
|
303
229
|
GraffitiErrorNotFound
|
|
304
230
|
);
|
|
305
|
-
const gotten2 = await graffiti.get(
|
|
231
|
+
const gotten2 = await graffiti.get(posted, {}, session2);
|
|
232
|
+
expect(gotten.url).toEqual(posted.url);
|
|
233
|
+
expect(gotten.actor).toEqual(session1.actor);
|
|
306
234
|
expect(gotten2.value).toEqual(value);
|
|
307
235
|
expect(gotten2.allowed).toEqual([session2.actor]);
|
|
308
236
|
expect(gotten2.channels).toEqual([]);
|
|
309
237
|
});
|
|
310
|
-
it("patch value", async () => {
|
|
311
|
-
const value = {
|
|
312
|
-
something: "hello, world~ c:"
|
|
313
|
-
};
|
|
314
|
-
const putted = await graffiti.put({ value, channels: [] }, session);
|
|
315
|
-
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
316
|
-
const patch = {
|
|
317
|
-
value: [
|
|
318
|
-
{ op: "replace", path: "/something", value: "goodbye, world~ :c" }
|
|
319
|
-
]
|
|
320
|
-
};
|
|
321
|
-
const beforePatched = await graffiti.patch(patch, putted, session);
|
|
322
|
-
expect(beforePatched.value).toEqual(value);
|
|
323
|
-
expect(beforePatched.lastModified).toBeGreaterThan(putted.lastModified);
|
|
324
|
-
const gotten = await graffiti.get(putted, {});
|
|
325
|
-
expect(gotten.value).toEqual({
|
|
326
|
-
something: "goodbye, world~ :c"
|
|
327
|
-
});
|
|
328
|
-
expect(beforePatched.lastModified).toBe(gotten.lastModified);
|
|
329
|
-
await graffiti.delete(putted, session);
|
|
330
|
-
});
|
|
331
|
-
it("patch deleted object", async () => {
|
|
332
|
-
const putted = await graffiti.put(randomPutObject(), session);
|
|
333
|
-
const deleted = await graffiti.delete(putted, session);
|
|
334
|
-
await expect(
|
|
335
|
-
graffiti.patch({}, putted, session)
|
|
336
|
-
).rejects.toBeInstanceOf(GraffitiErrorNotFound);
|
|
337
|
-
});
|
|
338
|
-
it("deep patch", async () => {
|
|
339
|
-
const value = {
|
|
340
|
-
something: {
|
|
341
|
-
another: {
|
|
342
|
-
somethingElse: "hello"
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
};
|
|
346
|
-
const putted = await graffiti.put(
|
|
347
|
-
{ value, channels: [] },
|
|
348
|
-
session
|
|
349
|
-
);
|
|
350
|
-
const beforePatch = await graffiti.patch(
|
|
351
|
-
{
|
|
352
|
-
value: [
|
|
353
|
-
{
|
|
354
|
-
op: "replace",
|
|
355
|
-
path: "/something/another/somethingElse",
|
|
356
|
-
value: "goodbye"
|
|
357
|
-
}
|
|
358
|
-
]
|
|
359
|
-
},
|
|
360
|
-
putted,
|
|
361
|
-
session
|
|
362
|
-
);
|
|
363
|
-
const gotten = await graffiti.get(putted, {});
|
|
364
|
-
expect(beforePatch.value).toEqual(value);
|
|
365
|
-
expect(gotten.value).toEqual({
|
|
366
|
-
something: {
|
|
367
|
-
another: {
|
|
368
|
-
somethingElse: "goodbye"
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
});
|
|
372
|
-
});
|
|
373
|
-
it("patch channels", async () => {
|
|
374
|
-
const channelsBefore = [randomString()];
|
|
375
|
-
const channelsAfter = [randomString()];
|
|
376
|
-
const putted = await graffiti.put(
|
|
377
|
-
{ value: {}, channels: channelsBefore },
|
|
378
|
-
session
|
|
379
|
-
);
|
|
380
|
-
const patch = {
|
|
381
|
-
channels: [{ op: "replace", path: "/0", value: channelsAfter[0] }]
|
|
382
|
-
};
|
|
383
|
-
const patched = await graffiti.patch(patch, putted, session);
|
|
384
|
-
expect(patched.channels).toEqual(channelsBefore);
|
|
385
|
-
const gotten = await graffiti.get(putted, {}, session);
|
|
386
|
-
expect(gotten.channels).toEqual(channelsAfter);
|
|
387
|
-
await graffiti.delete(putted, session);
|
|
388
|
-
});
|
|
389
|
-
it("patch 'increment' with test", async () => {
|
|
390
|
-
const putted = await graffiti.put(
|
|
391
|
-
{
|
|
392
|
-
value: {
|
|
393
|
-
counter: 1
|
|
394
|
-
},
|
|
395
|
-
channels: []
|
|
396
|
-
},
|
|
397
|
-
session
|
|
398
|
-
);
|
|
399
|
-
const previous = await graffiti.patch(
|
|
400
|
-
{
|
|
401
|
-
value: [
|
|
402
|
-
{ op: "test", path: "/counter", value: 1 },
|
|
403
|
-
{ op: "replace", path: "/counter", value: 2 }
|
|
404
|
-
]
|
|
405
|
-
},
|
|
406
|
-
putted,
|
|
407
|
-
session
|
|
408
|
-
);
|
|
409
|
-
expect(previous.value).toEqual({ counter: 1 });
|
|
410
|
-
const result = await graffiti.get(previous, {
|
|
411
|
-
properties: {
|
|
412
|
-
value: {
|
|
413
|
-
properties: {
|
|
414
|
-
counter: {
|
|
415
|
-
type: "integer"
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
});
|
|
421
|
-
expect(result.value.counter).toEqual(2);
|
|
422
|
-
await expect(
|
|
423
|
-
graffiti.patch(
|
|
424
|
-
{
|
|
425
|
-
value: [
|
|
426
|
-
{ op: "test", path: "/counter", value: 1 },
|
|
427
|
-
{ op: "replace", path: "/counter", value: 3 }
|
|
428
|
-
]
|
|
429
|
-
},
|
|
430
|
-
putted,
|
|
431
|
-
session
|
|
432
|
-
)
|
|
433
|
-
).rejects.toThrow(GraffitiErrorPatchTestFailed);
|
|
434
|
-
});
|
|
435
|
-
it("invalid patch", async () => {
|
|
436
|
-
const object = randomPutObject();
|
|
437
|
-
const putted = await graffiti.put(object, session);
|
|
438
|
-
await expect(
|
|
439
|
-
graffiti.patch(
|
|
440
|
-
{
|
|
441
|
-
value: [
|
|
442
|
-
{ op: "add", path: "/root", value: [] },
|
|
443
|
-
{ op: "add", path: "/root/2", value: 2 }
|
|
444
|
-
// out of bounds
|
|
445
|
-
]
|
|
446
|
-
},
|
|
447
|
-
putted,
|
|
448
|
-
session
|
|
449
|
-
)
|
|
450
|
-
).rejects.toThrow(GraffitiErrorPatchError);
|
|
451
|
-
});
|
|
452
|
-
it("patch channels to be wrong", async () => {
|
|
453
|
-
const object = randomPutObject();
|
|
454
|
-
object.allowed = [randomString()];
|
|
455
|
-
const putted = await graffiti.put(object, session);
|
|
456
|
-
const patches = [
|
|
457
|
-
{
|
|
458
|
-
channels: [{ op: "replace", path: "", value: null }]
|
|
459
|
-
},
|
|
460
|
-
{
|
|
461
|
-
channels: [{ op: "replace", path: "", value: {} }]
|
|
462
|
-
},
|
|
463
|
-
{
|
|
464
|
-
channels: [{ op: "replace", path: "", value: ["hello", ["hi"]] }]
|
|
465
|
-
},
|
|
466
|
-
{
|
|
467
|
-
channels: [{ op: "add", path: "/0", value: 1 }]
|
|
468
|
-
},
|
|
469
|
-
{
|
|
470
|
-
value: [{ op: "replace", path: "", value: "not an object" }]
|
|
471
|
-
},
|
|
472
|
-
{
|
|
473
|
-
value: [{ op: "replace", path: "", value: null }]
|
|
474
|
-
},
|
|
475
|
-
{
|
|
476
|
-
value: [{ op: "replace", path: "", value: [] }]
|
|
477
|
-
},
|
|
478
|
-
{
|
|
479
|
-
allowed: [{ op: "replace", path: "", value: {} }]
|
|
480
|
-
},
|
|
481
|
-
{
|
|
482
|
-
allowed: [{ op: "replace", path: "", value: ["hello", ["hi"]] }]
|
|
483
|
-
}
|
|
484
|
-
];
|
|
485
|
-
for (const patch of patches) {
|
|
486
|
-
await expect(graffiti.patch(patch, putted, session)).rejects.toThrow(
|
|
487
|
-
GraffitiErrorPatchError
|
|
488
|
-
);
|
|
489
|
-
}
|
|
490
|
-
const gotten = await graffiti.get(putted, {}, session);
|
|
491
|
-
expect(gotten.value).toEqual(object.value);
|
|
492
|
-
expect(gotten.channels).toEqual(object.channels);
|
|
493
|
-
expect(gotten.allowed).toEqual(object.allowed);
|
|
494
|
-
expect(gotten.lastModified).toEqual(putted.lastModified);
|
|
495
|
-
});
|
|
496
238
|
}
|
|
497
239
|
);
|
|
498
240
|
};
|
|
@@ -516,168 +258,82 @@ var graffitiDiscoverTests = (useGraffiti, useSession1, useSession2) => {
|
|
|
516
258
|
expect2(await iterator.next()).toHaveProperty("done", true);
|
|
517
259
|
});
|
|
518
260
|
it2("discover single", async () => {
|
|
519
|
-
const object =
|
|
520
|
-
const
|
|
261
|
+
const object = randomPostObject();
|
|
262
|
+
const posted = await graffiti.post(object, session);
|
|
521
263
|
const queryChannels = [randomString(), object.channels[0]];
|
|
522
264
|
const iterator = graffiti.discover(queryChannels, {});
|
|
523
265
|
const value = await nextStreamValue(iterator);
|
|
266
|
+
expect2(value.url).toEqual(posted.url);
|
|
524
267
|
expect2(value.value).toEqual(object.value);
|
|
525
268
|
expect2(value.channels).toEqual([object.channels[0]]);
|
|
526
269
|
expect2(value.allowed).toBeUndefined();
|
|
527
270
|
expect2(value.actor).toEqual(session.actor);
|
|
528
|
-
expect2(value.lastModified).toEqual(putted.lastModified);
|
|
529
271
|
const result2 = await iterator.next();
|
|
530
272
|
expect2(result2.done).toBe(true);
|
|
531
273
|
});
|
|
532
274
|
it2("discover wrong channel", async () => {
|
|
533
|
-
const object =
|
|
534
|
-
await graffiti.
|
|
275
|
+
const object = randomPostObject();
|
|
276
|
+
await graffiti.post(object, session);
|
|
535
277
|
const iterator = graffiti.discover([randomString()], {});
|
|
536
278
|
await expect2(iterator.next()).resolves.toHaveProperty("done", true);
|
|
537
279
|
});
|
|
538
280
|
it2("discover not allowed", async () => {
|
|
539
|
-
const object =
|
|
281
|
+
const object = randomPostObject();
|
|
540
282
|
object.allowed = [randomString(), randomString()];
|
|
541
|
-
const
|
|
283
|
+
const posted = await graffiti.post(object, session1);
|
|
542
284
|
const iteratorSession1 = graffiti.discover(
|
|
543
285
|
object.channels,
|
|
544
286
|
{},
|
|
545
287
|
session1
|
|
546
288
|
);
|
|
547
289
|
const value = await nextStreamValue(iteratorSession1);
|
|
290
|
+
expect2(value.url).toEqual(posted.url);
|
|
548
291
|
expect2(value.value).toEqual(object.value);
|
|
549
292
|
expect2(value.channels).toEqual(object.channels);
|
|
550
293
|
expect2(value.allowed).toEqual(object.allowed);
|
|
551
294
|
expect2(value.actor).toEqual(session1.actor);
|
|
552
|
-
expect2(value.lastModified).toEqual(putted.lastModified);
|
|
553
295
|
const iteratorSession2 = graffiti.discover(object.channels, {}, session2);
|
|
554
296
|
expect2(await iteratorSession2.next()).toHaveProperty("done", true);
|
|
555
297
|
const iteratorNoSession = graffiti.discover(object.channels, {});
|
|
556
298
|
expect2(await iteratorNoSession.next()).toHaveProperty("done", true);
|
|
557
299
|
});
|
|
558
300
|
it2("discover allowed", async () => {
|
|
559
|
-
const object =
|
|
301
|
+
const object = randomPostObject();
|
|
560
302
|
object.allowed = [randomString(), session2.actor, randomString()];
|
|
561
|
-
const
|
|
303
|
+
const posted = await graffiti.post(object, session1);
|
|
562
304
|
const iteratorSession2 = graffiti.discover(
|
|
563
305
|
object.channels,
|
|
564
306
|
{},
|
|
565
307
|
session2
|
|
566
308
|
);
|
|
567
309
|
const value = await nextStreamValue(iteratorSession2);
|
|
310
|
+
expect2(value.url).toEqual(posted.url);
|
|
568
311
|
expect2(value.value).toEqual(object.value);
|
|
569
312
|
expect2(value.allowed).toEqual([session2.actor]);
|
|
570
313
|
expect2(value.channels).toEqual(object.channels);
|
|
571
314
|
expect2(value.actor).toEqual(session1.actor);
|
|
572
|
-
expect2(value.lastModified).toEqual(putted.lastModified);
|
|
573
315
|
});
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
const putted2 = await graffiti.put(object2, session2);
|
|
582
|
-
const iterator = graffiti.discover(object1.channels, {
|
|
583
|
-
properties: {
|
|
584
|
-
[prop]: {
|
|
585
|
-
enum: [putted1[prop]]
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
});
|
|
589
|
-
const value = await nextStreamValue(iterator);
|
|
590
|
-
expect2(value.url).toEqual(putted1.url);
|
|
591
|
-
expect2(value.url).not.toEqual(putted2.url);
|
|
592
|
-
expect2(value.value).toEqual(object1.value);
|
|
593
|
-
await expect2(iterator.next()).resolves.toHaveProperty("done", true);
|
|
594
|
-
});
|
|
595
|
-
}
|
|
596
|
-
it2("discover with lastModified range", async () => {
|
|
597
|
-
const object = randomPutObject();
|
|
598
|
-
const putted1 = await graffiti.put(object, session);
|
|
599
|
-
await new Promise((r) => setTimeout(r, 20));
|
|
600
|
-
const putted2 = await graffiti.put(object, session);
|
|
601
|
-
expect2(putted1.url).not.toEqual(putted2.url);
|
|
602
|
-
expect2(putted1.lastModified).toBeLessThan(putted2.lastModified);
|
|
603
|
-
const gtIterator = graffiti.discover([object.channels[0]], {
|
|
604
|
-
properties: {
|
|
605
|
-
lastModified: {
|
|
606
|
-
exclusiveMinimum: putted2.lastModified
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
});
|
|
610
|
-
expect2(await gtIterator.next()).toHaveProperty("done", true);
|
|
611
|
-
const gtIteratorEpsilon = graffiti.discover([object.channels[0]], {
|
|
612
|
-
properties: {
|
|
613
|
-
lastModified: {
|
|
614
|
-
exclusiveMinimum: putted2.lastModified - 0.1
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
});
|
|
618
|
-
const value1 = await nextStreamValue(gtIteratorEpsilon);
|
|
619
|
-
expect2(value1.url).toEqual(putted2.url);
|
|
620
|
-
expect2(await gtIteratorEpsilon.next()).toHaveProperty("done", true);
|
|
621
|
-
const gteIterator = graffiti.discover(object.channels, {
|
|
622
|
-
properties: {
|
|
623
|
-
value: {},
|
|
624
|
-
lastModified: {
|
|
625
|
-
minimum: putted2.lastModified
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
});
|
|
629
|
-
const value = await nextStreamValue(gteIterator);
|
|
630
|
-
expect2(value.url).toEqual(putted2.url);
|
|
631
|
-
expect2(await gteIterator.next()).toHaveProperty("done", true);
|
|
632
|
-
const gteIteratorEpsilon = graffiti.discover(object.channels, {
|
|
633
|
-
properties: {
|
|
634
|
-
lastModified: {
|
|
635
|
-
minimum: putted2.lastModified + 0.1
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
});
|
|
639
|
-
expect2(await gteIteratorEpsilon.next()).toHaveProperty("done", true);
|
|
640
|
-
const ltIterator = graffiti.discover(object.channels, {
|
|
641
|
-
properties: {
|
|
642
|
-
lastModified: {
|
|
643
|
-
exclusiveMaximum: putted1.lastModified
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
});
|
|
647
|
-
expect2(await ltIterator.next()).toHaveProperty("done", true);
|
|
648
|
-
const ltIteratorEpsilon = graffiti.discover(object.channels, {
|
|
649
|
-
properties: {
|
|
650
|
-
lastModified: {
|
|
651
|
-
exclusiveMaximum: putted1.lastModified + 0.1
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
});
|
|
655
|
-
const value3 = await nextStreamValue(ltIteratorEpsilon);
|
|
656
|
-
expect2(value3.url).toEqual(putted1.url);
|
|
657
|
-
expect2(await ltIteratorEpsilon.next()).toHaveProperty("done", true);
|
|
658
|
-
const lteIterator = graffiti.discover(object.channels, {
|
|
659
|
-
properties: {
|
|
660
|
-
lastModified: {
|
|
661
|
-
maximum: putted1.lastModified
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
});
|
|
665
|
-
const value2 = await nextStreamValue(lteIterator);
|
|
666
|
-
expect2(value2.url).toEqual(putted1.url);
|
|
667
|
-
expect2(await lteIterator.next()).toHaveProperty("done", true);
|
|
668
|
-
const lteIteratorEpsilon = graffiti.discover(object.channels, {
|
|
316
|
+
it2("discover for actor", async () => {
|
|
317
|
+
const object1 = randomPostObject();
|
|
318
|
+
const posted1 = await graffiti.post(object1, session1);
|
|
319
|
+
const object2 = randomPostObject();
|
|
320
|
+
object2.channels = object1.channels;
|
|
321
|
+
const posted2 = await graffiti.post(object2, session2);
|
|
322
|
+
const iterator = graffiti.discover(object1.channels, {
|
|
669
323
|
properties: {
|
|
670
|
-
|
|
671
|
-
maximum: putted1.lastModified - 0.1
|
|
672
|
-
}
|
|
324
|
+
actor: { const: posted1.actor }
|
|
673
325
|
}
|
|
674
326
|
});
|
|
675
|
-
|
|
327
|
+
const value = await nextStreamValue(iterator);
|
|
328
|
+
expect2(value.url).toEqual(posted1.url);
|
|
329
|
+
expect2(value.url).not.toEqual(posted2.url);
|
|
330
|
+
expect2(value.value).toEqual(object1.value);
|
|
331
|
+
await expect2(iterator.next()).resolves.toHaveProperty("done", true);
|
|
676
332
|
});
|
|
677
333
|
it2("discover schema allowed, as and not as owner", async () => {
|
|
678
|
-
const object =
|
|
334
|
+
const object = randomPostObject();
|
|
679
335
|
object.allowed = [randomString(), session2.actor, randomString()];
|
|
680
|
-
await graffiti.
|
|
336
|
+
await graffiti.post(object, session1);
|
|
681
337
|
const iteratorSession1 = graffiti.discover(
|
|
682
338
|
object.channels,
|
|
683
339
|
{
|
|
@@ -687,9 +343,7 @@ var graffitiDiscoverTests = (useGraffiti, useSession1, useSession2) => {
|
|
|
687
343
|
// Make sure session2.actor is in the allow list
|
|
688
344
|
not: {
|
|
689
345
|
items: {
|
|
690
|
-
not: {
|
|
691
|
-
enum: [session2.actor]
|
|
692
|
-
}
|
|
346
|
+
not: { const: session2.actor }
|
|
693
347
|
}
|
|
694
348
|
}
|
|
695
349
|
}
|
|
@@ -725,9 +379,7 @@ var graffitiDiscoverTests = (useGraffiti, useSession1, useSession2) => {
|
|
|
725
379
|
allowed: {
|
|
726
380
|
not: {
|
|
727
381
|
items: {
|
|
728
|
-
not: {
|
|
729
|
-
enum: [object.channels[0]]
|
|
730
|
-
}
|
|
382
|
+
not: { const: object.allowed[0] }
|
|
731
383
|
}
|
|
732
384
|
}
|
|
733
385
|
}
|
|
@@ -747,9 +399,7 @@ var graffitiDiscoverTests = (useGraffiti, useSession1, useSession2) => {
|
|
|
747
399
|
maxItems: 1,
|
|
748
400
|
not: {
|
|
749
401
|
items: {
|
|
750
|
-
not: {
|
|
751
|
-
enum: [session2.actor]
|
|
752
|
-
}
|
|
402
|
+
not: { const: session2.actor }
|
|
753
403
|
}
|
|
754
404
|
}
|
|
755
405
|
}
|
|
@@ -766,21 +416,19 @@ var graffitiDiscoverTests = (useGraffiti, useSession1, useSession2) => {
|
|
|
766
416
|
).resolves.toHaveProperty("done", true);
|
|
767
417
|
});
|
|
768
418
|
it2("discover schema channels, as and not as owner", async () => {
|
|
769
|
-
const object =
|
|
419
|
+
const object = randomPostObject();
|
|
770
420
|
object.channels = [randomString(), randomString(), randomString()];
|
|
771
|
-
await graffiti.
|
|
421
|
+
await graffiti.post(object, session1);
|
|
772
422
|
const iteratorSession1 = graffiti.discover(
|
|
773
423
|
[object.channels[0], object.channels[2]],
|
|
774
424
|
{
|
|
775
425
|
properties: {
|
|
776
426
|
channels: {
|
|
777
427
|
minItems: 3,
|
|
778
|
-
// Make sure
|
|
428
|
+
// Make sure channel 1 is in the allow list
|
|
779
429
|
not: {
|
|
780
430
|
items: {
|
|
781
|
-
not: {
|
|
782
|
-
enum: [object.channels[1]]
|
|
783
|
-
}
|
|
431
|
+
not: { const: object.channels[1] }
|
|
784
432
|
}
|
|
785
433
|
}
|
|
786
434
|
}
|
|
@@ -816,9 +464,7 @@ var graffitiDiscoverTests = (useGraffiti, useSession1, useSession2) => {
|
|
|
816
464
|
channels: {
|
|
817
465
|
not: {
|
|
818
466
|
items: {
|
|
819
|
-
not: {
|
|
820
|
-
enum: [object.channels[1]]
|
|
821
|
-
}
|
|
467
|
+
not: { const: object.channels[1] }
|
|
822
468
|
}
|
|
823
469
|
}
|
|
824
470
|
}
|
|
@@ -838,9 +484,7 @@ var graffitiDiscoverTests = (useGraffiti, useSession1, useSession2) => {
|
|
|
838
484
|
maxItems: 2,
|
|
839
485
|
not: {
|
|
840
486
|
items: {
|
|
841
|
-
not: {
|
|
842
|
-
enum: [object.channels[2]]
|
|
843
|
-
}
|
|
487
|
+
not: { const: object.channels[2] }
|
|
844
488
|
}
|
|
845
489
|
}
|
|
846
490
|
}
|
|
@@ -857,13 +501,13 @@ var graffitiDiscoverTests = (useGraffiti, useSession1, useSession2) => {
|
|
|
857
501
|
).resolves.toHaveProperty("done", true);
|
|
858
502
|
});
|
|
859
503
|
it2("discover query for empty allowed", async () => {
|
|
860
|
-
const publicO =
|
|
504
|
+
const publicO = randomPostObject();
|
|
861
505
|
const publicSchema = {
|
|
862
506
|
not: {
|
|
863
507
|
required: ["allowed"]
|
|
864
508
|
}
|
|
865
509
|
};
|
|
866
|
-
await graffiti.
|
|
510
|
+
await graffiti.post(publicO, session1);
|
|
867
511
|
const iterator = graffiti.discover(
|
|
868
512
|
publicO.channels,
|
|
869
513
|
publicSchema,
|
|
@@ -873,9 +517,9 @@ var graffitiDiscoverTests = (useGraffiti, useSession1, useSession2) => {
|
|
|
873
517
|
expect2(value.value).toEqual(publicO.value);
|
|
874
518
|
expect2(value.allowed).toBeUndefined();
|
|
875
519
|
await expect2(iterator.next()).resolves.toHaveProperty("done", true);
|
|
876
|
-
const restricted =
|
|
520
|
+
const restricted = randomPostObject();
|
|
877
521
|
restricted.allowed = [];
|
|
878
|
-
await graffiti.
|
|
522
|
+
await graffiti.post(restricted, session1);
|
|
879
523
|
const iterator2 = graffiti.discover(
|
|
880
524
|
restricted.channels,
|
|
881
525
|
publicSchema,
|
|
@@ -884,17 +528,17 @@ var graffitiDiscoverTests = (useGraffiti, useSession1, useSession2) => {
|
|
|
884
528
|
await expect2(iterator2.next()).resolves.toHaveProperty("done", true);
|
|
885
529
|
});
|
|
886
530
|
it2("discover query for values", async () => {
|
|
887
|
-
const object1 =
|
|
531
|
+
const object1 = randomPostObject();
|
|
888
532
|
object1.value = { test: randomString() };
|
|
889
|
-
await graffiti.
|
|
890
|
-
const object2 =
|
|
533
|
+
await graffiti.post(object1, session);
|
|
534
|
+
const object2 = randomPostObject();
|
|
891
535
|
object2.channels = object1.channels;
|
|
892
536
|
object2.value = { test: randomString(), something: randomString() };
|
|
893
|
-
await graffiti.
|
|
894
|
-
const object3 =
|
|
537
|
+
await graffiti.post(object2, session);
|
|
538
|
+
const object3 = randomPostObject();
|
|
895
539
|
object3.channels = object1.channels;
|
|
896
540
|
object3.value = { other: randomString(), something: randomString() };
|
|
897
|
-
await graffiti.
|
|
541
|
+
await graffiti.post(object3, session);
|
|
898
542
|
const counts = /* @__PURE__ */ new Map();
|
|
899
543
|
for (const property of ["test", "something", "other"]) {
|
|
900
544
|
let count = 0;
|
|
@@ -919,14 +563,14 @@ var graffitiDiscoverTests = (useGraffiti, useSession1, useSession2) => {
|
|
|
919
563
|
for (const continueType of ["cursor", "continue"]) {
|
|
920
564
|
describe2(`continue discover with ${continueType}`, () => {
|
|
921
565
|
it2("discover for deleted content", async () => {
|
|
922
|
-
const object =
|
|
923
|
-
const
|
|
566
|
+
const object = randomPostObject();
|
|
567
|
+
const posted = await graffiti.post(object, session);
|
|
924
568
|
const iterator1 = graffiti.discover(object.channels, {});
|
|
925
569
|
const value1 = await nextStreamValue(iterator1);
|
|
926
570
|
expect2(value1.value).toEqual(object.value);
|
|
927
571
|
const returnValue = await iterator1.next();
|
|
928
572
|
assert2(returnValue.done, "value2 is not done");
|
|
929
|
-
|
|
573
|
+
await graffiti.delete(posted, session);
|
|
930
574
|
const iterator = graffiti.discover(object.channels, {});
|
|
931
575
|
await expect2(iterator.next()).resolves.toHaveProperty("done", true);
|
|
932
576
|
const tombIterator = continueStream(
|
|
@@ -937,372 +581,145 @@ var graffitiDiscoverTests = (useGraffiti, useSession1, useSession2) => {
|
|
|
937
581
|
const value = await tombIterator.next();
|
|
938
582
|
assert2(!value.done && !value.value.error, "value is done");
|
|
939
583
|
assert2(value.value.tombstone, "value is not tombstone");
|
|
940
|
-
expect2(value.value.object.url).toEqual(
|
|
584
|
+
expect2(value.value.object.url).toEqual(posted.url);
|
|
941
585
|
await expect2(tombIterator.next()).resolves.toHaveProperty(
|
|
942
586
|
"done",
|
|
943
587
|
true
|
|
944
588
|
);
|
|
945
589
|
});
|
|
946
|
-
it2("discover for replaced channels", async () => {
|
|
947
|
-
async function runTest() {
|
|
948
|
-
const object1 = randomPutObject();
|
|
949
|
-
const putted = await graffiti.put(object1, session);
|
|
950
|
-
const iterator3 = graffiti.discover(object1.channels, {});
|
|
951
|
-
const value3 = await nextStreamValue(iterator3);
|
|
952
|
-
expect2(value3.value).toEqual(object1.value);
|
|
953
|
-
const returnValue = await iterator3.next();
|
|
954
|
-
assert2(returnValue.done, "value2 is not done");
|
|
955
|
-
const object2 = randomPutObject();
|
|
956
|
-
const replaced = await graffiti.put(
|
|
957
|
-
{
|
|
958
|
-
...object2,
|
|
959
|
-
url: putted.url
|
|
960
|
-
},
|
|
961
|
-
session
|
|
962
|
-
);
|
|
963
|
-
const iterator1 = graffiti.discover(object1.channels, {});
|
|
964
|
-
const iterator2 = graffiti.discover(object2.channels, {});
|
|
965
|
-
const tombIterator = continueStream(
|
|
966
|
-
graffiti,
|
|
967
|
-
returnValue.value,
|
|
968
|
-
continueType
|
|
969
|
-
);
|
|
970
|
-
if (putted.lastModified === replaced.lastModified) {
|
|
971
|
-
const value1 = await iterator1.next();
|
|
972
|
-
const value22 = await iterator2.next();
|
|
973
|
-
const value32 = await tombIterator.next();
|
|
974
|
-
expect2(value1.done || value22.done).toBe(true);
|
|
975
|
-
expect2(value1.done && value22.done).toBe(false);
|
|
976
|
-
assert2(!value32.done && !value32.value.error, "value is done");
|
|
977
|
-
expect2(value32.value.tombstone || value22.done).toBe(true);
|
|
978
|
-
expect2(value32.value.tombstone && value22.done).toBe(false);
|
|
979
|
-
return;
|
|
980
|
-
}
|
|
981
|
-
const value5 = await iterator1.next();
|
|
982
|
-
assert2(value5.done, "value5 is not done");
|
|
983
|
-
const value4 = await tombIterator.next();
|
|
984
|
-
assert2(!value4.done && !value4.value.error, "value is done");
|
|
985
|
-
assert2(value4.value.tombstone, "value is not tombstone");
|
|
986
|
-
expect2(value4.value.object.url).toEqual(putted.url);
|
|
987
|
-
expect2(value4.value.object.lastModified).toEqual(
|
|
988
|
-
replaced.lastModified
|
|
989
|
-
);
|
|
990
|
-
const value2 = await nextStreamValue(iterator2);
|
|
991
|
-
await expect2(iterator2.next()).resolves.toHaveProperty(
|
|
992
|
-
"done",
|
|
993
|
-
true
|
|
994
|
-
);
|
|
995
|
-
expect2(value2.value).toEqual(object2.value);
|
|
996
|
-
expect2(value2.channels).toEqual(object2.channels);
|
|
997
|
-
expect2(value2.lastModified).toEqual(replaced.lastModified);
|
|
998
|
-
const patched = await graffiti.patch(
|
|
999
|
-
{
|
|
1000
|
-
channels: [
|
|
1001
|
-
{ op: "replace", path: "", value: object1.channels }
|
|
1002
|
-
]
|
|
1003
|
-
},
|
|
1004
|
-
replaced,
|
|
1005
|
-
session
|
|
1006
|
-
);
|
|
1007
|
-
const tombIterator2 = continueStream(
|
|
1008
|
-
graffiti,
|
|
1009
|
-
value5.value,
|
|
1010
|
-
continueType
|
|
1011
|
-
);
|
|
1012
|
-
let result;
|
|
1013
|
-
for await (const value of tombIterator2) {
|
|
1014
|
-
if (value.error) continue;
|
|
1015
|
-
if (!result) {
|
|
1016
|
-
result = value;
|
|
1017
|
-
continue;
|
|
1018
|
-
}
|
|
1019
|
-
if (value.object.lastModified > result.object.lastModified || value.object.lastModified === result.object.lastModified && !value.tombstone && result.tombstone) {
|
|
1020
|
-
result = value;
|
|
1021
|
-
}
|
|
1022
|
-
}
|
|
1023
|
-
assert2(result, "result is not defined");
|
|
1024
|
-
assert2(!result.tombstone, "result is tombstone");
|
|
1025
|
-
expect2(result.object.url).toEqual(replaced.url);
|
|
1026
|
-
expect2(result.object.lastModified).toEqual(patched.lastModified);
|
|
1027
|
-
expect2(result.object.channels).toEqual(object1.channels);
|
|
1028
|
-
expect2(result.object.value).toEqual(object2.value);
|
|
1029
|
-
}
|
|
1030
|
-
await Promise.allSettled(Array.from({ length: 20 }, () => runTest()));
|
|
1031
|
-
});
|
|
1032
|
-
it2("discover for patched allowed", async () => {
|
|
1033
|
-
const object = randomPutObject();
|
|
1034
|
-
const putted = await graffiti.put(object, session);
|
|
1035
|
-
const iterator1 = graffiti.discover(object.channels, {});
|
|
1036
|
-
const value1 = await nextStreamValue(iterator1);
|
|
1037
|
-
expect2(value1.value).toEqual(object.value);
|
|
1038
|
-
const returnValue = await iterator1.next();
|
|
1039
|
-
assert2(returnValue.done, "value2 is not done");
|
|
1040
|
-
await graffiti.patch(
|
|
1041
|
-
{
|
|
1042
|
-
allowed: [{ op: "add", path: "", value: [] }]
|
|
1043
|
-
},
|
|
1044
|
-
putted,
|
|
1045
|
-
session
|
|
1046
|
-
);
|
|
1047
|
-
const iterator2 = graffiti.discover(object.channels, {});
|
|
1048
|
-
expect2(await iterator2.next()).toHaveProperty("done", true);
|
|
1049
|
-
const iterator = continueStream(
|
|
1050
|
-
graffiti,
|
|
1051
|
-
returnValue.value,
|
|
1052
|
-
continueType
|
|
1053
|
-
);
|
|
1054
|
-
const value = await iterator.next();
|
|
1055
|
-
assert2(!value.done && !value.value.error, "value is done");
|
|
1056
|
-
assert2(value.value.tombstone, "value is not tombstone");
|
|
1057
|
-
expect2(value.value.object.url).toEqual(putted.url);
|
|
1058
|
-
await expect2(iterator.next()).resolves.toHaveProperty("done", true);
|
|
1059
|
-
});
|
|
1060
|
-
it2("put concurrently and discover one", async () => {
|
|
1061
|
-
const object = randomPutObject();
|
|
1062
|
-
const putted = await graffiti.put(object, session);
|
|
1063
|
-
const putPromises = Array(99).fill(0).map(
|
|
1064
|
-
() => graffiti.put(
|
|
1065
|
-
{
|
|
1066
|
-
...object,
|
|
1067
|
-
url: putted.url
|
|
1068
|
-
},
|
|
1069
|
-
session
|
|
1070
|
-
)
|
|
1071
|
-
);
|
|
1072
|
-
await Promise.all(putPromises);
|
|
1073
|
-
const iterator = graffiti.discover(object.channels, {});
|
|
1074
|
-
let tombstoneCount = 0;
|
|
1075
|
-
let valueCount = 0;
|
|
1076
|
-
for await (const result of iterator) {
|
|
1077
|
-
assert2(!result.error, "result has error");
|
|
1078
|
-
if (result.tombstone) {
|
|
1079
|
-
tombstoneCount++;
|
|
1080
|
-
} else {
|
|
1081
|
-
valueCount++;
|
|
1082
|
-
}
|
|
1083
|
-
}
|
|
1084
|
-
expect2(tombstoneCount).toBe(0);
|
|
1085
|
-
expect2(valueCount).toBe(1);
|
|
1086
|
-
});
|
|
1087
590
|
});
|
|
1088
591
|
}
|
|
1089
592
|
});
|
|
1090
593
|
};
|
|
1091
594
|
|
|
1092
|
-
// tests/
|
|
1093
|
-
import {
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
expect3(Object.keys(object.value)[0]).toBeTypeOf("string");
|
|
1137
|
-
const iterator1 = graffiti.recoverOrphans(
|
|
1138
|
-
{
|
|
1139
|
-
properties: {
|
|
1140
|
-
value: {
|
|
1141
|
-
properties: {
|
|
1142
|
-
[Object.keys(object.value)[0]]: {
|
|
1143
|
-
type: "string"
|
|
1144
|
-
}
|
|
1145
|
-
},
|
|
1146
|
-
required: [Object.keys(object.value)[0]]
|
|
1147
|
-
}
|
|
1148
|
-
}
|
|
1149
|
-
},
|
|
1150
|
-
session
|
|
1151
|
-
);
|
|
1152
|
-
const value1 = await nextStreamValue(iterator1);
|
|
1153
|
-
expect3(value1.value).toEqual(object.value);
|
|
1154
|
-
const returnValue = await iterator1.next();
|
|
1155
|
-
assert3(returnValue.done, "value2 is not done");
|
|
1156
|
-
const putNotOrphan = await graffiti.put(
|
|
1157
|
-
{
|
|
1158
|
-
...putOrphan,
|
|
1159
|
-
...object,
|
|
1160
|
-
channels: [randomString()]
|
|
1161
|
-
},
|
|
1162
|
-
session
|
|
1163
|
-
);
|
|
1164
|
-
expect3(putNotOrphan.url).toBe(putOrphan.url);
|
|
1165
|
-
expect3(putNotOrphan.lastModified).toBeGreaterThan(
|
|
1166
|
-
putOrphan.lastModified
|
|
1167
|
-
);
|
|
1168
|
-
const orphanIterator = graffiti.recoverOrphans({}, session);
|
|
1169
|
-
let numResults = 0;
|
|
1170
|
-
for await (const orphan of orphanIterator) {
|
|
1171
|
-
if (orphan.error) continue;
|
|
1172
|
-
if (orphan.object.url === putOrphan.url) {
|
|
1173
|
-
numResults++;
|
|
1174
|
-
}
|
|
1175
|
-
}
|
|
1176
|
-
expect3(numResults).toBe(0);
|
|
1177
|
-
const iterator2 = continueStream(
|
|
1178
|
-
graffiti,
|
|
1179
|
-
returnValue.value,
|
|
1180
|
-
continueType,
|
|
1181
|
-
session
|
|
1182
|
-
);
|
|
1183
|
-
const value2 = await iterator2.next();
|
|
1184
|
-
assert3(
|
|
1185
|
-
!value2.done && !value2.value.error,
|
|
1186
|
-
"value2 is done or has error"
|
|
1187
|
-
);
|
|
1188
|
-
assert3(value2.value.tombstone, "value2 is not tombstone");
|
|
1189
|
-
expect3(value2.value.object.url).toBe(putOrphan.url);
|
|
1190
|
-
await expect3(iterator2.next()).resolves.toHaveProperty("done", true);
|
|
595
|
+
// tests/media.ts
|
|
596
|
+
import {
|
|
597
|
+
GraffitiErrorNotAcceptable,
|
|
598
|
+
GraffitiErrorNotFound as GraffitiErrorNotFound2,
|
|
599
|
+
GraffitiErrorTooLarge
|
|
600
|
+
} from "@graffiti-garden/api";
|
|
601
|
+
import { it as it3, expect as expect3, describe as describe3, beforeAll as beforeAll3 } from "vitest";
|
|
602
|
+
var graffitiMediaTests = (useGraffiti, useSession1, useSession2) => {
|
|
603
|
+
describe3.concurrent(
|
|
604
|
+
"media",
|
|
605
|
+
{
|
|
606
|
+
timeout: 2e4
|
|
607
|
+
},
|
|
608
|
+
() => {
|
|
609
|
+
let graffiti;
|
|
610
|
+
let session;
|
|
611
|
+
let session1;
|
|
612
|
+
let session2;
|
|
613
|
+
beforeAll3(async () => {
|
|
614
|
+
graffiti = useGraffiti();
|
|
615
|
+
session1 = await useSession1();
|
|
616
|
+
session = session1;
|
|
617
|
+
session2 = await useSession2();
|
|
618
|
+
});
|
|
619
|
+
it3("post, get, delete media", async () => {
|
|
620
|
+
const text = randomString();
|
|
621
|
+
const data = new Blob([text], { type: "text/plain" });
|
|
622
|
+
const mediaUrl = await graffiti.postMedia({ data }, session);
|
|
623
|
+
const media = await graffiti.getMedia(mediaUrl, {});
|
|
624
|
+
expect3(await media.data.text()).toEqual(text);
|
|
625
|
+
expect3(media.data.type).toEqual("text/plain");
|
|
626
|
+
expect3(media.allowed).toBeUndefined();
|
|
627
|
+
expect3(media.actor).toBe(session.actor);
|
|
628
|
+
await graffiti.deleteMedia(mediaUrl, session);
|
|
629
|
+
await expect3(graffiti.getMedia(mediaUrl, {})).rejects.toThrow(
|
|
630
|
+
GraffitiErrorNotFound2
|
|
631
|
+
);
|
|
632
|
+
});
|
|
633
|
+
it3("acceptable type", async () => {
|
|
634
|
+
const text = randomString();
|
|
635
|
+
const data = new Blob([text], { type: "text/plain" });
|
|
636
|
+
const mediaUrl = await graffiti.postMedia({ data }, session);
|
|
637
|
+
const media = await graffiti.getMedia(mediaUrl, {
|
|
638
|
+
accept: "text/*"
|
|
1191
639
|
});
|
|
640
|
+
expect3(await media.data.text()).toEqual(text);
|
|
641
|
+
expect3(media.data.type).toEqual("text/plain");
|
|
642
|
+
expect3(media.allowed).toBeUndefined();
|
|
643
|
+
expect3(media.actor).toBe(session.actor);
|
|
1192
644
|
});
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
};
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
}
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
let newChannels = /* @__PURE__ */ new Map();
|
|
1238
|
-
for await (const channel of channelIterator2) {
|
|
1239
|
-
if (channel.error) continue;
|
|
1240
|
-
newChannels.set(channel.value.channel, channel.value.count);
|
|
1241
|
-
}
|
|
1242
|
-
newChannels = new Map(
|
|
1243
|
-
Array.from(newChannels).filter(
|
|
1244
|
-
([channel, count]) => !existingChannels.has(channel)
|
|
1245
|
-
)
|
|
1246
|
-
);
|
|
1247
|
-
expect4(newChannels.size).toBe(3);
|
|
1248
|
-
expect4(newChannels.get(channels[0])).toBe(6);
|
|
1249
|
-
expect4(newChannels.get(channels[1])).toBe(5);
|
|
1250
|
-
expect4(newChannels.get(channels[2])).toBe(4);
|
|
1251
|
-
});
|
|
1252
|
-
it4("list channels with deleted channel", async () => {
|
|
1253
|
-
const channels = [randomString(), randomString(), randomString()];
|
|
1254
|
-
const before = await graffiti.put(
|
|
1255
|
-
{
|
|
1256
|
-
value: { index: 2 },
|
|
1257
|
-
channels: channels.slice(1)
|
|
1258
|
-
},
|
|
1259
|
-
session
|
|
1260
|
-
);
|
|
1261
|
-
const first = await graffiti.put(
|
|
1262
|
-
{ value: { index: 0 }, channels },
|
|
1263
|
-
session
|
|
1264
|
-
);
|
|
1265
|
-
await graffiti.delete(first, session);
|
|
1266
|
-
const second = await graffiti.put(
|
|
1267
|
-
{
|
|
1268
|
-
value: { index: 1 },
|
|
1269
|
-
channels: channels.slice(2)
|
|
1270
|
-
},
|
|
1271
|
-
session
|
|
1272
|
-
);
|
|
1273
|
-
const channelIterator = graffiti.channelStats(session);
|
|
1274
|
-
let got1 = 0;
|
|
1275
|
-
let got2 = 0;
|
|
1276
|
-
for await (const result of channelIterator) {
|
|
1277
|
-
if (result.error) continue;
|
|
1278
|
-
const { channel, count, lastModified } = result.value;
|
|
1279
|
-
assert4(
|
|
1280
|
-
channel !== channels[0],
|
|
1281
|
-
"There should not be an object in channel[0]"
|
|
645
|
+
it3("unacceptable type", async () => {
|
|
646
|
+
const text = randomString();
|
|
647
|
+
const data = new Blob([text], { type: "text/plain" });
|
|
648
|
+
const mediaUrl = await graffiti.postMedia({ data }, session);
|
|
649
|
+
await expect3(
|
|
650
|
+
graffiti.getMedia(mediaUrl, {
|
|
651
|
+
accept: "image/*"
|
|
652
|
+
})
|
|
653
|
+
).rejects.toThrow(GraffitiErrorNotAcceptable);
|
|
654
|
+
});
|
|
655
|
+
it3("acceptable size", async () => {
|
|
656
|
+
const text = randomString();
|
|
657
|
+
const data = new Blob([text], { type: "text/plain" });
|
|
658
|
+
const mediaUrl = await graffiti.postMedia({ data }, session);
|
|
659
|
+
const media = await graffiti.getMedia(mediaUrl, {
|
|
660
|
+
maxBytes: data.size
|
|
661
|
+
});
|
|
662
|
+
expect3(await media.data.text()).toEqual(text);
|
|
663
|
+
expect3(media.data.type).toEqual("text/plain");
|
|
664
|
+
expect3(media.allowed).toBeUndefined();
|
|
665
|
+
expect3(media.actor).toBe(session.actor);
|
|
666
|
+
});
|
|
667
|
+
it3("unacceptable size", async () => {
|
|
668
|
+
const text = randomString();
|
|
669
|
+
const data = new Blob([text], { type: "text/plain" });
|
|
670
|
+
const mediaUrl = await graffiti.postMedia({ data }, session);
|
|
671
|
+
await expect3(
|
|
672
|
+
graffiti.getMedia(mediaUrl, {
|
|
673
|
+
maxBytes: data.size - 1
|
|
674
|
+
})
|
|
675
|
+
).rejects.toThrow(GraffitiErrorTooLarge);
|
|
676
|
+
});
|
|
677
|
+
it3("empty allowed", async () => {
|
|
678
|
+
const text = randomString();
|
|
679
|
+
const data = new Blob([text], { type: "text/plain" });
|
|
680
|
+
const allowed = [];
|
|
681
|
+
const mediaUrl = await graffiti.postMedia({ data, allowed }, session1);
|
|
682
|
+
const media = await graffiti.getMedia(mediaUrl, {}, session1);
|
|
683
|
+
expect3(await media.data.text()).toEqual(text);
|
|
684
|
+
expect3(media.data.type).toEqual("text/plain");
|
|
685
|
+
expect3(media.allowed).toEqual([]);
|
|
686
|
+
expect3(media.actor).toBe(session1.actor);
|
|
687
|
+
await expect3(graffiti.getMedia(mediaUrl, {}, session2)).rejects.toThrow(
|
|
688
|
+
GraffitiErrorNotFound2
|
|
1282
689
|
);
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
}
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
690
|
+
await expect3(graffiti.getMedia(mediaUrl, {})).rejects.toThrow(
|
|
691
|
+
GraffitiErrorNotFound2
|
|
692
|
+
);
|
|
693
|
+
});
|
|
694
|
+
it3("allowed", async () => {
|
|
695
|
+
const text = randomString();
|
|
696
|
+
const data = new Blob([text], { type: "text/plain" });
|
|
697
|
+
const allowed = [randomString(), session2.actor, randomString()];
|
|
698
|
+
const mediaUrl = await graffiti.postMedia({ data, allowed }, session1);
|
|
699
|
+
const media = await graffiti.getMedia(mediaUrl, {}, session1);
|
|
700
|
+
expect3(await media.data.text()).toEqual(text);
|
|
701
|
+
expect3(media.data.type).toEqual("text/plain");
|
|
702
|
+
expect3(media.allowed).toEqual(allowed);
|
|
703
|
+
expect3(media.actor).toBe(session1.actor);
|
|
704
|
+
const media2 = await graffiti.getMedia(mediaUrl, {}, session2);
|
|
705
|
+
expect3(await media2.data.text()).toEqual(text);
|
|
706
|
+
expect3(media2.data.type).toEqual("text/plain");
|
|
707
|
+
expect3(media2.allowed).toEqual([session2.actor]);
|
|
708
|
+
expect3(media2.actor).toBe(session1.actor);
|
|
709
|
+
await expect3(graffiti.getMedia(mediaUrl, {})).rejects.toThrow(
|
|
710
|
+
GraffitiErrorNotFound2
|
|
711
|
+
);
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
);
|
|
1297
715
|
};
|
|
1298
716
|
export {
|
|
1299
717
|
continueStream,
|
|
1300
718
|
graffitiCRUDTests,
|
|
1301
|
-
graffitiChannelStatsTests,
|
|
1302
719
|
graffitiDiscoverTests,
|
|
1303
|
-
|
|
720
|
+
graffitiMediaTests,
|
|
1304
721
|
nextStreamValue,
|
|
1305
|
-
|
|
722
|
+
randomPostObject,
|
|
1306
723
|
randomString,
|
|
1307
724
|
randomValue
|
|
1308
725
|
};
|