@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.
Files changed (44) hide show
  1. package/README.md +0 -7
  2. package/dist/index.cjs +1 -1
  3. package/dist/index.cjs.map +4 -4
  4. package/dist/index.mjs +1 -1
  5. package/dist/index.mjs.map +4 -4
  6. package/dist/src/1-api.d.ts +172 -178
  7. package/dist/src/1-api.d.ts.map +1 -1
  8. package/dist/src/2-types.d.ts +39 -152
  9. package/dist/src/2-types.d.ts.map +1 -1
  10. package/dist/src/3-errors.d.ts +2 -8
  11. package/dist/src/3-errors.d.ts.map +1 -1
  12. package/dist/src/4-utilities.d.ts +8 -0
  13. package/dist/src/4-utilities.d.ts.map +1 -0
  14. package/dist/src/index.d.ts +1 -0
  15. package/dist/src/index.d.ts.map +1 -1
  16. package/dist/tests/crud.d.ts +1 -1
  17. package/dist/tests/crud.d.ts.map +1 -1
  18. package/dist/tests/discover.d.ts +1 -1
  19. package/dist/tests/discover.d.ts.map +1 -1
  20. package/dist/tests/index.d.ts +1 -2
  21. package/dist/tests/index.d.ts.map +1 -1
  22. package/dist/tests/media.d.ts +3 -0
  23. package/dist/tests/media.d.ts.map +1 -0
  24. package/dist/tests/utils.d.ts +3 -3
  25. package/dist/tests/utils.d.ts.map +1 -1
  26. package/dist/tests.mjs +207 -790
  27. package/dist/tests.mjs.map +4 -4
  28. package/package.json +6 -6
  29. package/src/1-api.ts +182 -186
  30. package/src/2-types.ts +42 -157
  31. package/src/3-errors.ts +6 -22
  32. package/src/4-utilities.ts +65 -0
  33. package/src/index.ts +1 -0
  34. package/tests/crud.ts +39 -332
  35. package/tests/discover.ts +51 -349
  36. package/tests/index.ts +1 -2
  37. package/tests/media.ts +158 -0
  38. package/tests/utils.ts +4 -4
  39. package/dist/tests/channel-stats.d.ts +0 -3
  40. package/dist/tests/channel-stats.d.ts.map +0 -1
  41. package/dist/tests/orphans.d.ts +0 -3
  42. package/dist/tests/orphans.d.ts.map +0 -1
  43. package/tests/channel-stats.ts +0 -129
  44. package/tests/orphans.ts +0 -128
package/tests/crud.ts CHANGED
@@ -2,7 +2,6 @@ import { it, expect, describe, beforeAll } from "vitest";
2
2
  import type {
3
3
  Graffiti,
4
4
  GraffitiSession,
5
- GraffitiPatch,
6
5
  JSONSchema,
7
6
  } from "@graffiti-garden/api";
8
7
  import {
@@ -10,13 +9,11 @@ import {
10
9
  GraffitiErrorSchemaMismatch,
11
10
  GraffitiErrorInvalidSchema,
12
11
  GraffitiErrorForbidden,
13
- GraffitiErrorPatchTestFailed,
14
- GraffitiErrorPatchError,
15
12
  } from "@graffiti-garden/api";
16
- import { randomPutObject, randomString } from "./utils";
13
+ import { randomPostObject, randomString } from "./utils";
17
14
 
18
15
  export const graffitiCRUDTests = (
19
- useGraffiti: () => Pick<Graffiti, "put" | "get" | "delete" | "patch">,
16
+ useGraffiti: () => Pick<Graffiti, "post" | "get" | "delete">,
20
17
  useSession1: () => GraffitiSession | Promise<GraffitiSession>,
21
18
  useSession2: () => GraffitiSession | Promise<GraffitiSession>,
22
19
  ) => {
@@ -37,17 +34,17 @@ export const graffitiCRUDTests = (
37
34
  session2 = await useSession2();
38
35
  });
39
36
 
40
- it("put, get, delete", async () => {
37
+ it("post, get, delete", async () => {
41
38
  const value = {
42
39
  something: "hello, world~ c:",
43
40
  };
44
41
  const channels = [randomString(), randomString()];
45
42
 
46
- // Put the object
47
- const previous = await graffiti.put<{}>({ value, channels }, session);
48
- expect(previous.value).toEqual({});
49
- expect(previous.channels).toEqual([]);
50
- expect(previous.allowed).toEqual([]);
43
+ // Post the object
44
+ const previous = await graffiti.post<{}>({ value, channels }, session);
45
+ expect(previous.value).toEqual(value);
46
+ expect(previous.channels).toEqual(channels);
47
+ expect(previous.allowed).toEqual(undefined);
51
48
  expect(previous.actor).toEqual(session.actor);
52
49
 
53
50
  // Get it back
@@ -57,122 +54,33 @@ export const graffitiCRUDTests = (
57
54
  expect(gotten.allowed).toBeUndefined();
58
55
  expect(gotten.url).toEqual(previous.url);
59
56
  expect(gotten.actor).toEqual(previous.actor);
60
- expect(gotten.lastModified).toEqual(previous.lastModified);
61
-
62
- // Replace it
63
- const newValue = {
64
- something: "goodbye, world~ :c",
65
- };
66
- const beforeReplaced = await graffiti.put<{}>(
67
- {
68
- url: previous.url,
69
- value: newValue,
70
- channels: [],
71
- },
72
- session,
73
- );
74
- expect(beforeReplaced.value).toEqual(value);
75
- expect(beforeReplaced.url).toEqual(previous.url);
76
- expect(beforeReplaced.actor).toEqual(previous.actor);
77
- expect(beforeReplaced.lastModified).toBeGreaterThanOrEqual(
78
- gotten.lastModified,
79
- );
80
-
81
- // Get it again
82
- const afterReplaced = await graffiti.get(previous, {});
83
- expect(afterReplaced.value).toEqual(newValue);
84
- expect(afterReplaced.lastModified).toEqual(beforeReplaced.lastModified);
85
57
 
86
58
  // Delete it
87
- const beforeDeleted = await graffiti.delete(afterReplaced, session);
88
- expect(beforeDeleted.value).toEqual(newValue);
89
- expect(beforeDeleted.lastModified).toBeGreaterThanOrEqual(
90
- beforeReplaced.lastModified,
91
- );
59
+ await graffiti.delete(gotten, session);
92
60
 
93
61
  // Get is not found
94
- await expect(graffiti.get(afterReplaced, {})).rejects.toBeInstanceOf(
62
+ await expect(graffiti.get(gotten, {})).rejects.toBeInstanceOf(
95
63
  GraffitiErrorNotFound,
96
64
  );
97
65
 
98
66
  // Delete it again
99
- await expect(graffiti.delete(beforeDeleted, session)).rejects.toThrow(
67
+ await expect(graffiti.delete(gotten, session)).rejects.toThrow(
100
68
  GraffitiErrorNotFound,
101
69
  );
102
-
103
- // Try to re-put it
104
- await expect(
105
- graffiti.put(
106
- { url: beforeDeleted.url, value: {}, channels: [] },
107
- session,
108
- ),
109
- ).rejects.toThrow(GraffitiErrorNotFound);
110
70
  });
111
71
 
112
- it("put, delete, patch with wrong actor", async () => {
113
- await expect(
114
- graffiti.put<{}>(
115
- { value: {}, channels: [], actor: session2.actor },
116
- session1,
117
- ),
118
- ).rejects.toThrow(GraffitiErrorForbidden);
119
-
120
- const putted = await graffiti.put<{}>(
72
+ it("post then delete with wrong actor", async () => {
73
+ const posted = await graffiti.post<{}>(
121
74
  { value: {}, channels: [] },
122
75
  session2,
123
76
  );
124
77
 
125
- await expect(
126
- graffiti.put<{}>(
127
- {
128
- url: putted.url,
129
- value: {},
130
- channels: [],
131
- },
132
- session1,
133
- ),
134
- ).rejects.toThrow(GraffitiErrorForbidden);
135
-
136
- await expect(graffiti.delete(putted, session1)).rejects.toThrow(
137
- GraffitiErrorForbidden,
138
- );
139
-
140
- await expect(graffiti.patch({}, putted, session1)).rejects.toThrow(
78
+ await expect(graffiti.delete(posted, session1)).rejects.toThrow(
141
79
  GraffitiErrorForbidden,
142
80
  );
143
81
  });
144
82
 
145
- it("put, patch, delete object that is not allowed", async () => {
146
- const putted = await graffiti.put<{}>(
147
- {
148
- value: {},
149
- channels: [],
150
- allowed: [],
151
- },
152
- session1,
153
- );
154
-
155
- await expect(
156
- graffiti.put(
157
- {
158
- url: putted.url,
159
- value: {},
160
- channels: [],
161
- },
162
- session2,
163
- ),
164
- ).rejects.toThrow(GraffitiErrorNotFound);
165
-
166
- await expect(graffiti.patch({}, putted, session2)).rejects.toThrow(
167
- GraffitiErrorNotFound,
168
- );
169
-
170
- await expect(graffiti.delete(putted, session2)).rejects.toThrow(
171
- GraffitiErrorNotFound,
172
- );
173
- });
174
-
175
- it("put and get with schema", async () => {
83
+ it("post and get with schema", async () => {
176
84
  const schema = {
177
85
  properties: {
178
86
  value: {
@@ -209,14 +117,14 @@ export const graffitiCRUDTests = (
209
117
  },
210
118
  };
211
119
 
212
- const putted = await graffiti.put<typeof schema>(
120
+ const posted = await graffiti.post<typeof schema>(
213
121
  {
214
122
  value: goodValue,
215
123
  channels: [],
216
124
  },
217
125
  session,
218
126
  );
219
- const gotten = await graffiti.get(putted, schema);
127
+ const gotten = await graffiti.get(posted, schema);
220
128
 
221
129
  expect(gotten.value.something).toEqual(goodValue.something);
222
130
  expect(gotten.value.another).toEqual(goodValue.another);
@@ -224,13 +132,13 @@ export const graffitiCRUDTests = (
224
132
  expect(gotten.value.deeper.deepProp).toEqual(goodValue.deeper.deepProp);
225
133
  });
226
134
 
227
- it("put and get with invalid schema", async () => {
228
- const putted = await graffiti.put<{}>(
135
+ it("post and get with invalid schema", async () => {
136
+ const posted = await graffiti.post<{}>(
229
137
  { value: {}, channels: [] },
230
138
  session,
231
139
  );
232
140
  await expect(
233
- graffiti.get(putted, {
141
+ graffiti.get(posted, {
234
142
  properties: {
235
143
  value: {
236
144
  //@ts-ignore
@@ -241,8 +149,8 @@ export const graffitiCRUDTests = (
241
149
  ).rejects.toThrow(GraffitiErrorInvalidSchema);
242
150
  });
243
151
 
244
- it("put and get with wrong schema", async () => {
245
- const putted = await graffiti.put<{}>(
152
+ it("post and get with wrong schema", async () => {
153
+ const posted = await graffiti.post<{}>(
246
154
  {
247
155
  value: {
248
156
  hello: "world",
@@ -253,7 +161,7 @@ export const graffitiCRUDTests = (
253
161
  );
254
162
 
255
163
  await expect(
256
- graffiti.get(putted, {
164
+ graffiti.get(posted, {
257
165
  properties: {
258
166
  value: {
259
167
  properties: {
@@ -267,41 +175,43 @@ export const graffitiCRUDTests = (
267
175
  ).rejects.toThrow(GraffitiErrorSchemaMismatch);
268
176
  });
269
177
 
270
- it("put and get with empty access control", async () => {
178
+ it("post and get with empty access control", async () => {
271
179
  const value = {
272
180
  um: "hi",
273
181
  };
274
182
  const allowed = [randomString()];
275
183
  const channels = [randomString()];
276
- const putted = await graffiti.put<{}>(
184
+ const posted = await graffiti.post<{}>(
277
185
  { value, allowed, channels },
278
186
  session1,
279
187
  );
280
188
 
281
189
  // Get it with authenticated session
282
- const gotten = await graffiti.get(putted, {}, session1);
190
+ const gotten = await graffiti.get(posted, {}, session1);
191
+ expect(gotten.url).toEqual(posted.url);
192
+ expect(gotten.actor).toEqual(session1.actor);
283
193
  expect(gotten.value).toEqual(value);
284
194
  expect(gotten.allowed).toEqual(allowed);
285
195
  expect(gotten.channels).toEqual(channels);
286
196
 
287
197
  // But not without session
288
- await expect(graffiti.get(putted, {})).rejects.toBeInstanceOf(
198
+ await expect(graffiti.get(posted, {})).rejects.toBeInstanceOf(
289
199
  GraffitiErrorNotFound,
290
200
  );
291
201
 
292
202
  // Or the wrong session
293
- await expect(graffiti.get(putted, {}, session2)).rejects.toBeInstanceOf(
203
+ await expect(graffiti.get(posted, {}, session2)).rejects.toBeInstanceOf(
294
204
  GraffitiErrorNotFound,
295
205
  );
296
206
  });
297
207
 
298
- it("put and get with specific access control", async () => {
208
+ it("post and get with specific access control", async () => {
299
209
  const value = {
300
210
  um: "hi",
301
211
  };
302
212
  const allowed = [randomString(), session2.actor, randomString()];
303
213
  const channels = [randomString()];
304
- const putted = await graffiti.put<{}>(
214
+ const posted = await graffiti.post<{}>(
305
215
  {
306
216
  value,
307
217
  allowed,
@@ -311,230 +221,27 @@ export const graffitiCRUDTests = (
311
221
  );
312
222
 
313
223
  // Get it with authenticated session
314
- const gotten = await graffiti.get(putted, {}, session1);
224
+ const gotten = await graffiti.get(posted, {}, session1);
225
+ expect(gotten.url).toEqual(posted.url);
226
+ expect(gotten.actor).toEqual(session1.actor);
315
227
  expect(gotten.value).toEqual(value);
316
228
  expect(gotten.allowed).toEqual(allowed);
317
229
  expect(gotten.channels).toEqual(channels);
318
230
 
319
231
  // But not without session
320
- await expect(graffiti.get(putted, {})).rejects.toBeInstanceOf(
232
+ await expect(graffiti.get(posted, {})).rejects.toBeInstanceOf(
321
233
  GraffitiErrorNotFound,
322
234
  );
323
235
 
324
- const gotten2 = await graffiti.get(putted, {}, session2);
236
+ const gotten2 = await graffiti.get(posted, {}, session2);
237
+ expect(gotten.url).toEqual(posted.url);
238
+ expect(gotten.actor).toEqual(session1.actor);
325
239
  expect(gotten2.value).toEqual(value);
326
240
  // They should only see that is is private to them
327
241
  expect(gotten2.allowed).toEqual([session2.actor]);
328
242
  // And not see any channels
329
243
  expect(gotten2.channels).toEqual([]);
330
244
  });
331
-
332
- it("patch value", async () => {
333
- const value = {
334
- something: "hello, world~ c:",
335
- };
336
- const putted = await graffiti.put<{}>({ value, channels: [] }, session);
337
-
338
- // Wait just a bit to make sure the lastModified is different
339
- await new Promise((resolve) => setTimeout(resolve, 10));
340
-
341
- const patch: GraffitiPatch = {
342
- value: [
343
- { op: "replace", path: "/something", value: "goodbye, world~ :c" },
344
- ],
345
- };
346
- const beforePatched = await graffiti.patch(patch, putted, session);
347
- expect(beforePatched.value).toEqual(value);
348
- expect(beforePatched.lastModified).toBeGreaterThan(putted.lastModified);
349
-
350
- const gotten = await graffiti.get(putted, {});
351
- expect(gotten.value).toEqual({
352
- something: "goodbye, world~ :c",
353
- });
354
- expect(beforePatched.lastModified).toBe(gotten.lastModified);
355
-
356
- await graffiti.delete(putted, session);
357
- });
358
-
359
- it("patch deleted object", async () => {
360
- const putted = await graffiti.put<{}>(randomPutObject(), session);
361
- const deleted = await graffiti.delete(putted, session);
362
- await expect(
363
- graffiti.patch({}, putted, session),
364
- ).rejects.toBeInstanceOf(GraffitiErrorNotFound);
365
- });
366
-
367
- it("deep patch", async () => {
368
- const value = {
369
- something: {
370
- another: {
371
- somethingElse: "hello",
372
- },
373
- },
374
- };
375
- const putted = await graffiti.put<{}>(
376
- { value: value, channels: [] },
377
- session,
378
- );
379
-
380
- const beforePatch = await graffiti.patch(
381
- {
382
- value: [
383
- {
384
- op: "replace",
385
- path: "/something/another/somethingElse",
386
- value: "goodbye",
387
- },
388
- ],
389
- },
390
- putted,
391
- session,
392
- );
393
- const gotten = await graffiti.get(putted, {});
394
-
395
- expect(beforePatch.value).toEqual(value);
396
- expect(gotten.value).toEqual({
397
- something: {
398
- another: {
399
- somethingElse: "goodbye",
400
- },
401
- },
402
- });
403
- });
404
-
405
- it("patch channels", async () => {
406
- const channelsBefore = [randomString()];
407
- const channelsAfter = [randomString()];
408
-
409
- const putted = await graffiti.put<{}>(
410
- { value: {}, channels: channelsBefore },
411
- session,
412
- );
413
-
414
- const patch: GraffitiPatch = {
415
- channels: [{ op: "replace", path: "/0", value: channelsAfter[0] }],
416
- };
417
- const patched = await graffiti.patch(patch, putted, session);
418
- expect(patched.channels).toEqual(channelsBefore);
419
- const gotten = await graffiti.get(putted, {}, session);
420
- expect(gotten.channels).toEqual(channelsAfter);
421
- await graffiti.delete(putted, session);
422
- });
423
-
424
- it("patch 'increment' with test", async () => {
425
- const putted = await graffiti.put<{}>(
426
- {
427
- value: {
428
- counter: 1,
429
- },
430
- channels: [],
431
- },
432
- session,
433
- );
434
-
435
- const previous = await graffiti.patch(
436
- {
437
- value: [
438
- { op: "test", path: "/counter", value: 1 },
439
- { op: "replace", path: "/counter", value: 2 },
440
- ],
441
- },
442
- putted,
443
- session,
444
- );
445
- expect(previous.value).toEqual({ counter: 1 });
446
- const result = await graffiti.get(previous, {
447
- properties: {
448
- value: {
449
- properties: {
450
- counter: {
451
- type: "integer",
452
- },
453
- },
454
- },
455
- },
456
- });
457
- expect(result.value.counter).toEqual(2);
458
-
459
- await expect(
460
- graffiti.patch(
461
- {
462
- value: [
463
- { op: "test", path: "/counter", value: 1 },
464
- { op: "replace", path: "/counter", value: 3 },
465
- ],
466
- },
467
- putted,
468
- session,
469
- ),
470
- ).rejects.toThrow(GraffitiErrorPatchTestFailed);
471
- });
472
-
473
- it("invalid patch", async () => {
474
- const object = randomPutObject();
475
- const putted = await graffiti.put<{}>(object, session);
476
-
477
- await expect(
478
- graffiti.patch(
479
- {
480
- value: [
481
- { op: "add", path: "/root", value: [] },
482
- { op: "add", path: "/root/2", value: 2 }, // out of bounds
483
- ],
484
- },
485
- putted,
486
- session,
487
- ),
488
- ).rejects.toThrow(GraffitiErrorPatchError);
489
- });
490
-
491
- it("patch channels to be wrong", async () => {
492
- const object = randomPutObject();
493
- object.allowed = [randomString()];
494
- const putted = await graffiti.put<{}>(object, session);
495
-
496
- const patches: GraffitiPatch[] = [
497
- {
498
- channels: [{ op: "replace", path: "", value: null }],
499
- },
500
- {
501
- channels: [{ op: "replace", path: "", value: {} }],
502
- },
503
- {
504
- channels: [{ op: "replace", path: "", value: ["hello", ["hi"]] }],
505
- },
506
- {
507
- channels: [{ op: "add", path: "/0", value: 1 }],
508
- },
509
- {
510
- value: [{ op: "replace", path: "", value: "not an object" }],
511
- },
512
- {
513
- value: [{ op: "replace", path: "", value: null }],
514
- },
515
- {
516
- value: [{ op: "replace", path: "", value: [] }],
517
- },
518
- {
519
- allowed: [{ op: "replace", path: "", value: {} }],
520
- },
521
- {
522
- allowed: [{ op: "replace", path: "", value: ["hello", ["hi"]] }],
523
- },
524
- ];
525
-
526
- for (const patch of patches) {
527
- await expect(graffiti.patch(patch, putted, session)).rejects.toThrow(
528
- GraffitiErrorPatchError,
529
- );
530
- }
531
-
532
- const gotten = await graffiti.get(putted, {}, session);
533
- expect(gotten.value).toEqual(object.value);
534
- expect(gotten.channels).toEqual(object.channels);
535
- expect(gotten.allowed).toEqual(object.allowed);
536
- expect(gotten.lastModified).toEqual(putted.lastModified);
537
- });
538
245
  },
539
246
  );
540
247
  };