@graffiti-garden/api 1.0.2 → 1.0.3

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.
@@ -391,4 +391,39 @@ export type GraffitiSessionInitializedEvent = CustomEvent<{
391
391
  error?: Error;
392
392
  href?: string;
393
393
  } | null | undefined>;
394
+ export type GraffitiMedia = {
395
+ /**
396
+ * The binary data of the media to be uploaded,
397
+ * along with its [media type](https://www.iana.org/assignments/media-types/media-types.xhtml),
398
+ * formatted as a [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob).
399
+ */
400
+ data: Blob;
401
+ /**
402
+ * The {@link GraffitiObjectBase.actor | `actor`} that
403
+ * {@link Graffiti.postMedia | `post`ed} the media.
404
+ */
405
+ actor: string;
406
+ /**
407
+ * An optional list, identical in function to an object's
408
+ * {@link GraffitiObjectBase.allowed | `allowed`} property,
409
+ * that specifies the {@link GraffitiObjectBase.actor | `actor`}s
410
+ * who are allowed to access the media. If the list is `undefined`
411
+ * or `null`, anyone with the URL can access the media. If the list
412
+ * is empty, only the {@link GraffitiObjectBase.actor | `actor`}
413
+ * who {@link Graffiti.postMedia | `post`ed} the media can access it.
414
+ */
415
+ allowed?: string[] | null;
416
+ };
417
+ export type GraffitiPostMedia = Pick<GraffitiMedia, "data" | "allowed">;
418
+ export type GraffitiMediaRequirements = {
419
+ /**
420
+ * A list of acceptable media types for the retrieved media,
421
+ * formatted as like an [HTTP Accept header](https://httpwg.org/specs/rfc9110.html#field.accept)
422
+ */
423
+ accept?: string;
424
+ /**
425
+ * The maximum acceptable size, in bytes, of the media.
426
+ */
427
+ maxBytes?: number;
428
+ };
394
429
  //# sourceMappingURL=2-types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"2-types.d.ts","sourceRoot":"","sources":["../../src/2-types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"2-types.d.ts","sourceRoot":"","sources":["../../src/2-types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"crud.d.ts","sourceRoot":"","sources":["../../tests/crud.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,QAAQ,EACR,eAAe,EAEhB,MAAM,sBAAsB,CAAC;AAS9B,eAAO,MAAM,iBAAiB,GAC5B,aAAa,MAAM,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC,EAC5D,aAAa,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,EAC7D,aAAa,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,SAqO9D,CAAC"}
1
+ {"version":3,"file":"crud.d.ts","sourceRoot":"","sources":["../../tests/crud.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,QAAQ,EACR,eAAe,EAEhB,MAAM,sBAAsB,CAAC;AAS9B,eAAO,MAAM,iBAAiB,GAC5B,aAAa,MAAM,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC,EAC5D,aAAa,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,EAC7D,aAAa,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,SA2O9D,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../../tests/discover.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,QAAQ,EAER,eAAe,EAEhB,MAAM,sBAAsB,CAAC;AAQ9B,eAAO,MAAM,qBAAqB,GAChC,aAAa,MAAM,IAAI,CACrB,QAAQ,EACR,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,kBAAkB,CACpD,EACD,aAAa,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,EAC7D,aAAa,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,SAkY9D,CAAC"}
1
+ {"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../../tests/discover.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,QAAQ,EACR,eAAe,EAEhB,MAAM,sBAAsB,CAAC;AAa9B,eAAO,MAAM,qBAAqB,GAChC,aAAa,MAAM,IAAI,CACrB,QAAQ,EACR,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,kBAAkB,CACpD,EACD,aAAa,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,EAC7D,aAAa,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,SAkb9D,CAAC"}
package/dist/tests.mjs CHANGED
@@ -61,6 +61,11 @@ var graffitiCRUDTests = (useGraffiti, useSession1, useSession2) => {
61
61
  session = session1;
62
62
  session2 = await useSession2();
63
63
  });
64
+ it("get nonexistant object", async () => {
65
+ await expect(graffiti.get(randomString(), {})).rejects.toThrow(
66
+ GraffitiErrorNotFound
67
+ );
68
+ });
64
69
  it("post, get, delete", async () => {
65
70
  const value = {
66
71
  something: "hello, world~ c:"
@@ -241,6 +246,11 @@ var graffitiCRUDTests = (useGraffiti, useSession1, useSession2) => {
241
246
 
242
247
  // tests/discover.ts
243
248
  import { it as it2, expect as expect2, describe as describe2, assert as assert2, beforeAll as beforeAll2 } from "vitest";
249
+ import {
250
+ GraffitiErrorForbidden as GraffitiErrorForbidden2,
251
+ GraffitiErrorInvalidSchema as GraffitiErrorInvalidSchema2,
252
+ GraffitiErrorNotFound as GraffitiErrorNotFound2
253
+ } from "@graffiti-garden/api";
244
254
  var graffitiDiscoverTests = (useGraffiti, useSession1, useSession2) => {
245
255
  describe2.concurrent("discover", { timeout: 2e4 }, () => {
246
256
  let graffiti;
@@ -313,6 +323,17 @@ var graffitiDiscoverTests = (useGraffiti, useSession1, useSession2) => {
313
323
  expect2(value.channels).toEqual(object.channels);
314
324
  expect2(value.actor).toEqual(session1.actor);
315
325
  });
326
+ it2("discover bad schema", async () => {
327
+ const iterator = graffiti.discover([], {
328
+ properties: {
329
+ value: {
330
+ //@ts-ignore
331
+ type: "asdf"
332
+ }
333
+ }
334
+ });
335
+ await expect2(iterator.next()).rejects.toThrow(GraffitiErrorInvalidSchema2);
336
+ });
316
337
  it2("discover for actor", async () => {
317
338
  const object1 = randomPostObject();
318
339
  const posted1 = await graffiti.post(object1, session1);
@@ -582,20 +603,50 @@ var graffitiDiscoverTests = (useGraffiti, useSession1, useSession2) => {
582
603
  assert2(!value.done && !value.value.error, "value is done");
583
604
  assert2(value.value.tombstone, "value is not tombstone");
584
605
  expect2(value.value.object.url).toEqual(posted.url);
585
- await expect2(tombIterator.next()).resolves.toHaveProperty(
606
+ const returnValue2 = await tombIterator.next();
607
+ assert2(returnValue2.done, "value2 is not done");
608
+ const posted2 = await graffiti.post(object, session);
609
+ const doubleContinueIterator = continueStream(
610
+ graffiti,
611
+ returnValue2.value,
612
+ continueType
613
+ );
614
+ const value2 = await doubleContinueIterator.next();
615
+ assert2(!value2.done && !value2.value.error, "value2 is done");
616
+ assert2(!value2.value.tombstone, "value2 is tombstone");
617
+ expect2(value2.value.object.url).toEqual(posted2.url);
618
+ await expect2(doubleContinueIterator.next()).resolves.toHaveProperty(
586
619
  "done",
587
620
  true
588
621
  );
589
622
  });
623
+ it2("continue with wrong actor", async () => {
624
+ const iterator = graffiti.discover([], {}, session1);
625
+ const result = await iterator.next();
626
+ assert2(result.done, "iterator is not done");
627
+ const continuation = continueStream(
628
+ graffiti,
629
+ result.value,
630
+ continueType,
631
+ session2
632
+ );
633
+ await expect2(continuation.next()).rejects.toThrow(
634
+ GraffitiErrorForbidden2
635
+ );
636
+ });
590
637
  });
591
638
  }
639
+ it2("lookup non-existant cursor", async () => {
640
+ const iterator = graffiti.continueDiscover(randomString());
641
+ await expect2(iterator.next()).rejects.toThrow(GraffitiErrorNotFound2);
642
+ });
592
643
  });
593
644
  };
594
645
 
595
646
  // tests/media.ts
596
647
  import {
597
648
  GraffitiErrorNotAcceptable,
598
- GraffitiErrorNotFound as GraffitiErrorNotFound2,
649
+ GraffitiErrorNotFound as GraffitiErrorNotFound3,
599
650
  GraffitiErrorTooLarge
600
651
  } from "@graffiti-garden/api";
601
652
  import { it as it3, expect as expect3, describe as describe3, beforeAll as beforeAll3 } from "vitest";
@@ -627,7 +678,7 @@ var graffitiMediaTests = (useGraffiti, useSession1, useSession2) => {
627
678
  expect3(media.actor).toBe(session.actor);
628
679
  await graffiti.deleteMedia(mediaUrl, session);
629
680
  await expect3(graffiti.getMedia(mediaUrl, {})).rejects.toThrow(
630
- GraffitiErrorNotFound2
681
+ GraffitiErrorNotFound3
631
682
  );
632
683
  });
633
684
  it3("acceptable type", async () => {
@@ -685,10 +736,10 @@ var graffitiMediaTests = (useGraffiti, useSession1, useSession2) => {
685
736
  expect3(media.allowed).toEqual([]);
686
737
  expect3(media.actor).toBe(session1.actor);
687
738
  await expect3(graffiti.getMedia(mediaUrl, {}, session2)).rejects.toThrow(
688
- GraffitiErrorNotFound2
739
+ GraffitiErrorNotFound3
689
740
  );
690
741
  await expect3(graffiti.getMedia(mediaUrl, {})).rejects.toThrow(
691
- GraffitiErrorNotFound2
742
+ GraffitiErrorNotFound3
692
743
  );
693
744
  });
694
745
  it3("allowed", async () => {
@@ -707,7 +758,7 @@ var graffitiMediaTests = (useGraffiti, useSession1, useSession2) => {
707
758
  expect3(media2.allowed).toEqual([session2.actor]);
708
759
  expect3(media2.actor).toBe(session1.actor);
709
760
  await expect3(graffiti.getMedia(mediaUrl, {})).rejects.toThrow(
710
- GraffitiErrorNotFound2
761
+ GraffitiErrorNotFound3
711
762
  );
712
763
  });
713
764
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../tests/crud.ts", "../tests/utils.ts", "../tests/discover.ts", "../tests/media.ts"],
4
- "sourcesContent": ["import { it, expect, describe, beforeAll } from \"vitest\";\nimport type {\n Graffiti,\n GraffitiSession,\n JSONSchema,\n} from \"@graffiti-garden/api\";\nimport {\n GraffitiErrorNotFound,\n GraffitiErrorSchemaMismatch,\n GraffitiErrorInvalidSchema,\n GraffitiErrorForbidden,\n} from \"@graffiti-garden/api\";\nimport { randomPostObject, randomString } from \"./utils\";\n\nexport const graffitiCRUDTests = (\n useGraffiti: () => Pick<Graffiti, \"post\" | \"get\" | \"delete\">,\n useSession1: () => GraffitiSession | Promise<GraffitiSession>,\n useSession2: () => GraffitiSession | Promise<GraffitiSession>,\n) => {\n describe.concurrent(\n \"CRUD\",\n {\n timeout: 20000,\n },\n () => {\n let graffiti: ReturnType<typeof useGraffiti>;\n let session: GraffitiSession;\n let session1: GraffitiSession;\n let session2: GraffitiSession;\n beforeAll(async () => {\n graffiti = useGraffiti();\n session1 = await useSession1();\n session = session1;\n session2 = await useSession2();\n });\n\n it(\"post, get, delete\", async () => {\n const value = {\n something: \"hello, world~ c:\",\n };\n const channels = [randomString(), randomString()];\n\n // Post the object\n const previous = await graffiti.post<{}>({ value, channels }, session);\n expect(previous.value).toEqual(value);\n expect(previous.channels).toEqual(channels);\n expect(previous.allowed).toEqual(undefined);\n expect(previous.actor).toEqual(session.actor);\n\n // Get it back\n const gotten = await graffiti.get(previous, {});\n expect(gotten.value).toEqual(value);\n expect(gotten.channels).toEqual([]);\n expect(gotten.allowed).toBeUndefined();\n expect(gotten.url).toEqual(previous.url);\n expect(gotten.actor).toEqual(previous.actor);\n\n // Delete it\n await graffiti.delete(gotten, session);\n\n // Get is not found\n await expect(graffiti.get(gotten, {})).rejects.toBeInstanceOf(\n GraffitiErrorNotFound,\n );\n\n // Delete it again\n await expect(graffiti.delete(gotten, session)).rejects.toThrow(\n GraffitiErrorNotFound,\n );\n });\n\n it(\"post then delete with wrong actor\", async () => {\n const posted = await graffiti.post<{}>(\n { value: {}, channels: [] },\n session2,\n );\n\n await expect(graffiti.delete(posted, session1)).rejects.toThrow(\n GraffitiErrorForbidden,\n );\n });\n\n it(\"post and get with schema\", async () => {\n const schema = {\n properties: {\n value: {\n properties: {\n something: {\n type: \"string\",\n },\n another: {\n type: \"array\",\n items: {\n type: \"number\",\n },\n },\n deeper: {\n type: \"object\",\n properties: {\n deepProp: {\n type: \"string\",\n },\n },\n required: [\"deepProp\"],\n },\n },\n required: [\"another\", \"deeper\"],\n },\n },\n } as const satisfies JSONSchema;\n\n const goodValue = {\n something: \"hello\",\n another: [1, 2, 3],\n deeper: {\n deepProp: \"hello\",\n },\n };\n\n const posted = await graffiti.post<typeof schema>(\n {\n value: goodValue,\n channels: [],\n },\n session,\n );\n const gotten = await graffiti.get(posted, schema);\n\n expect(gotten.value.something).toEqual(goodValue.something);\n expect(gotten.value.another).toEqual(goodValue.another);\n expect(gotten.value.another[0]).toEqual(1);\n expect(gotten.value.deeper.deepProp).toEqual(goodValue.deeper.deepProp);\n });\n\n it(\"post and get with invalid schema\", async () => {\n const posted = await graffiti.post<{}>(\n { value: {}, channels: [] },\n session,\n );\n await expect(\n graffiti.get(posted, {\n properties: {\n value: {\n //@ts-ignore\n type: \"asdf\",\n },\n },\n }),\n ).rejects.toThrow(GraffitiErrorInvalidSchema);\n });\n\n it(\"post and get with wrong schema\", async () => {\n const posted = await graffiti.post<{}>(\n {\n value: {\n hello: \"world\",\n },\n channels: [],\n },\n session,\n );\n\n await expect(\n graffiti.get(posted, {\n properties: {\n value: {\n properties: {\n hello: {\n type: \"number\",\n },\n },\n },\n },\n }),\n ).rejects.toThrow(GraffitiErrorSchemaMismatch);\n });\n\n it(\"post and get with empty access control\", async () => {\n const value = {\n um: \"hi\",\n };\n const allowed = [randomString()];\n const channels = [randomString()];\n const posted = await graffiti.post<{}>(\n { value, allowed, channels },\n session1,\n );\n\n // Get it with authenticated session\n const gotten = await graffiti.get(posted, {}, session1);\n expect(gotten.url).toEqual(posted.url);\n expect(gotten.actor).toEqual(session1.actor);\n expect(gotten.value).toEqual(value);\n expect(gotten.allowed).toEqual(allowed);\n expect(gotten.channels).toEqual(channels);\n\n // But not without session\n await expect(graffiti.get(posted, {})).rejects.toBeInstanceOf(\n GraffitiErrorNotFound,\n );\n\n // Or the wrong session\n await expect(graffiti.get(posted, {}, session2)).rejects.toBeInstanceOf(\n GraffitiErrorNotFound,\n );\n });\n\n it(\"post and get with specific access control\", async () => {\n const value = {\n um: \"hi\",\n };\n const allowed = [randomString(), session2.actor, randomString()];\n const channels = [randomString()];\n const posted = await graffiti.post<{}>(\n {\n value,\n allowed,\n channels,\n },\n session1,\n );\n\n // Get it with authenticated session\n const gotten = await graffiti.get(posted, {}, session1);\n expect(gotten.url).toEqual(posted.url);\n expect(gotten.actor).toEqual(session1.actor);\n expect(gotten.value).toEqual(value);\n expect(gotten.allowed).toEqual(allowed);\n expect(gotten.channels).toEqual(channels);\n\n // But not without session\n await expect(graffiti.get(posted, {})).rejects.toBeInstanceOf(\n GraffitiErrorNotFound,\n );\n\n const gotten2 = await graffiti.get(posted, {}, session2);\n expect(gotten.url).toEqual(posted.url);\n expect(gotten.actor).toEqual(session1.actor);\n expect(gotten2.value).toEqual(value);\n // They should only see that is is private to them\n expect(gotten2.allowed).toEqual([session2.actor]);\n // And not see any channels\n expect(gotten2.channels).toEqual([]);\n });\n },\n );\n};\n", "import { assert } from \"vitest\";\nimport type {\n GraffitiPostObject,\n GraffitiObjectStream,\n JSONSchema,\n GraffitiObject,\n GraffitiObjectStreamReturn,\n GraffitiObjectStreamContinue,\n Graffiti,\n GraffitiSession,\n} from \"@graffiti-garden/api\";\n\nexport function randomString(): string {\n const array = new Uint8Array(16);\n crypto.getRandomValues(array);\n const str = Array.from(array)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n\n // check for unicode support\n return str + \"\uD83D\uDC69\uD83C\uDFFD\u200D\u2764\uFE0F\u200D\uD83D\uDC8B\u200D\uD83D\uDC69\uD83C\uDFFB\uD83E\uDEF1\uD83C\uDFFC\u200D\uD83E\uDEF2\uD83C\uDFFF\";\n}\n\nexport function randomValue() {\n return {\n [randomString()]: randomString(),\n };\n}\n\nexport function randomPostObject(): GraffitiPostObject<{}> {\n return {\n value: randomValue(),\n channels: [randomString(), randomString()],\n };\n}\n\nexport async function nextStreamValue<Schema extends JSONSchema>(\n iterator: GraffitiObjectStream<Schema>,\n): Promise<GraffitiObject<Schema>> {\n const result = await iterator.next();\n assert(!result.done && !result.value.error, \"result has no value\");\n assert(!result.value.tombstone, \"result has been deleted!\");\n return result.value.object;\n}\n\nexport function continueStream<Schema extends JSONSchema>(\n graffiti: Pick<Graffiti, \"continueDiscover\">,\n streamReturn: GraffitiObjectStreamReturn<Schema>,\n type: \"cursor\" | \"continue\",\n session?: GraffitiSession | null,\n): GraffitiObjectStreamContinue<Schema> {\n if (type === \"cursor\") {\n return graffiti.continueDiscover(\n streamReturn.cursor,\n session,\n ) as unknown as GraffitiObjectStreamContinue<Schema>;\n } else {\n return streamReturn.continue();\n }\n}\n", "import { it, expect, describe, assert, beforeAll } from \"vitest\";\nimport type {\n Graffiti,\n GraffitiObjectBase,\n GraffitiSession,\n JSONSchema,\n} from \"@graffiti-garden/api\";\nimport {\n randomString,\n nextStreamValue,\n randomPostObject,\n continueStream,\n} from \"./utils\";\n\nexport const graffitiDiscoverTests = (\n useGraffiti: () => Pick<\n Graffiti,\n \"discover\" | \"post\" | \"delete\" | \"continueDiscover\"\n >,\n useSession1: () => GraffitiSession | Promise<GraffitiSession>,\n useSession2: () => GraffitiSession | Promise<GraffitiSession>,\n) => {\n describe.concurrent(\"discover\", { timeout: 20000 }, () => {\n let graffiti: ReturnType<typeof useGraffiti>;\n let session: GraffitiSession;\n let session1: GraffitiSession;\n let session2: GraffitiSession;\n beforeAll(async () => {\n graffiti = useGraffiti();\n session1 = await useSession1();\n session = session1;\n session2 = await useSession2();\n });\n\n it(\"discover nothing\", async () => {\n const iterator = graffiti.discover([], {});\n expect(await iterator.next()).toHaveProperty(\"done\", true);\n });\n\n it(\"discover single\", async () => {\n const object = randomPostObject();\n\n const posted = await graffiti.post<{}>(object, session);\n\n const queryChannels = [randomString(), object.channels[0]];\n const iterator = graffiti.discover<{}>(queryChannels, {});\n const value = await nextStreamValue<{}>(iterator);\n expect(value.url).toEqual(posted.url);\n expect(value.value).toEqual(object.value);\n expect(value.channels).toEqual([object.channels[0]]);\n expect(value.allowed).toBeUndefined();\n expect(value.actor).toEqual(session.actor);\n const result2 = await iterator.next();\n expect(result2.done).toBe(true);\n });\n\n it(\"discover wrong channel\", async () => {\n const object = randomPostObject();\n await graffiti.post<{}>(object, session);\n const iterator = graffiti.discover([randomString()], {});\n await expect(iterator.next()).resolves.toHaveProperty(\"done\", true);\n });\n\n it(\"discover not allowed\", async () => {\n const object = randomPostObject();\n object.allowed = [randomString(), randomString()];\n const posted = await graffiti.post<{}>(object, session1);\n\n const iteratorSession1 = graffiti.discover<{}>(\n object.channels,\n {},\n session1,\n );\n const value = await nextStreamValue<{}>(iteratorSession1);\n expect(value.url).toEqual(posted.url);\n expect(value.value).toEqual(object.value);\n expect(value.channels).toEqual(object.channels);\n expect(value.allowed).toEqual(object.allowed);\n expect(value.actor).toEqual(session1.actor);\n\n const iteratorSession2 = graffiti.discover(object.channels, {}, session2);\n expect(await iteratorSession2.next()).toHaveProperty(\"done\", true);\n\n const iteratorNoSession = graffiti.discover(object.channels, {});\n expect(await iteratorNoSession.next()).toHaveProperty(\"done\", true);\n });\n\n it(\"discover allowed\", async () => {\n const object = randomPostObject();\n object.allowed = [randomString(), session2.actor, randomString()];\n const posted = await graffiti.post<{}>(object, session1);\n\n const iteratorSession2 = graffiti.discover<{}>(\n object.channels,\n {},\n session2,\n );\n const value = await nextStreamValue<{}>(iteratorSession2);\n expect(value.url).toEqual(posted.url);\n expect(value.value).toEqual(object.value);\n expect(value.allowed).toEqual([session2.actor]);\n expect(value.channels).toEqual(object.channels);\n expect(value.actor).toEqual(session1.actor);\n });\n\n it(\"discover for actor\", async () => {\n const object1 = randomPostObject();\n const posted1 = await graffiti.post<{}>(object1, session1);\n\n const object2 = randomPostObject();\n object2.channels = object1.channels;\n const posted2 = await graffiti.post<{}>(object2, session2);\n\n const iterator = graffiti.discover<{}>(object1.channels, {\n properties: {\n actor: { const: posted1.actor },\n },\n });\n\n const value = await nextStreamValue<{}>(iterator);\n expect(value.url).toEqual(posted1.url);\n expect(value.url).not.toEqual(posted2.url);\n expect(value.value).toEqual(object1.value);\n await expect(iterator.next()).resolves.toHaveProperty(\"done\", true);\n });\n\n it(\"discover schema allowed, as and not as owner\", async () => {\n const object = randomPostObject();\n object.allowed = [randomString(), session2.actor, randomString()];\n await graffiti.post<{}>(object, session1);\n\n const iteratorSession1 = graffiti.discover<{}>(\n object.channels,\n {\n properties: {\n allowed: {\n minItems: 3,\n // Make sure session2.actor is in the allow list\n not: {\n items: {\n not: { const: session2.actor },\n },\n },\n },\n },\n },\n session1,\n );\n const value = await nextStreamValue<{}>(iteratorSession1);\n expect(value.value).toEqual(object.value);\n await expect(iteratorSession1.next()).resolves.toHaveProperty(\n \"done\",\n true,\n );\n\n const iteratorSession2BigAllow = graffiti.discover(\n object.channels,\n {\n properties: {\n allowed: {\n minItems: 3,\n },\n },\n },\n session2,\n );\n await expect(iteratorSession2BigAllow.next()).resolves.toHaveProperty(\n \"done\",\n true,\n );\n const iteratorSession2PeekOther = graffiti.discover(\n object.channels,\n {\n properties: {\n allowed: {\n not: {\n items: {\n not: { const: object.allowed[0] },\n },\n },\n },\n },\n },\n session2,\n );\n await expect(iteratorSession2PeekOther.next()).resolves.toHaveProperty(\n \"done\",\n true,\n );\n const iteratorSession2SmallAllowPeekSelf = graffiti.discover<{}>(\n object.channels,\n {\n properties: {\n allowed: {\n maxItems: 1,\n not: {\n items: {\n not: { const: session2.actor },\n },\n },\n },\n },\n },\n session2,\n );\n const value2 = await nextStreamValue<{}>(\n iteratorSession2SmallAllowPeekSelf,\n );\n expect(value2.value).toEqual(object.value);\n await expect(\n iteratorSession2SmallAllowPeekSelf.next(),\n ).resolves.toHaveProperty(\"done\", true);\n });\n\n it(\"discover schema channels, as and not as owner\", async () => {\n const object = randomPostObject();\n object.channels = [randomString(), randomString(), randomString()];\n await graffiti.post<{}>(object, session1);\n\n const iteratorSession1 = graffiti.discover<{}>(\n [object.channels[0], object.channels[2]],\n {\n properties: {\n channels: {\n minItems: 3,\n // Make sure channel 1 is in the allow list\n not: {\n items: {\n not: { const: object.channels[1] },\n },\n },\n },\n },\n },\n session1,\n );\n const value = await nextStreamValue<{}>(iteratorSession1);\n expect(value.value).toEqual(object.value);\n await expect(iteratorSession1.next()).resolves.toHaveProperty(\n \"done\",\n true,\n );\n\n const iteratorSession2BigAllow = graffiti.discover(\n [object.channels[0], object.channels[2]],\n {\n properties: {\n channels: {\n minItems: 3,\n },\n },\n },\n session2,\n );\n await expect(iteratorSession2BigAllow.next()).resolves.toHaveProperty(\n \"done\",\n true,\n );\n const iteratorSession2PeekOther = graffiti.discover(\n [object.channels[0], object.channels[2]],\n {\n properties: {\n channels: {\n not: {\n items: {\n not: { const: object.channels[1] },\n },\n },\n },\n },\n },\n session2,\n );\n await expect(iteratorSession2PeekOther.next()).resolves.toHaveProperty(\n \"done\",\n true,\n );\n const iteratorSession2SmallAllowPeekSelf = graffiti.discover<{}>(\n [object.channels[0], object.channels[2]],\n {\n properties: {\n allowed: {\n maxItems: 2,\n not: {\n items: {\n not: { const: object.channels[2] },\n },\n },\n },\n },\n },\n session2,\n );\n const value2 = await nextStreamValue<{}>(\n iteratorSession2SmallAllowPeekSelf,\n );\n expect(value2.value).toEqual(object.value);\n await expect(\n iteratorSession2SmallAllowPeekSelf.next(),\n ).resolves.toHaveProperty(\"done\", true);\n });\n\n it(\"discover query for empty allowed\", async () => {\n const publicO = randomPostObject();\n\n const publicSchema = {\n not: {\n required: [\"allowed\"],\n },\n } satisfies JSONSchema;\n\n await graffiti.post<{}>(publicO, session1);\n const iterator = graffiti.discover<{}>(\n publicO.channels,\n publicSchema,\n session1,\n );\n const value = await nextStreamValue<{}>(iterator);\n expect(value.value).toEqual(publicO.value);\n expect(value.allowed).toBeUndefined();\n await expect(iterator.next()).resolves.toHaveProperty(\"done\", true);\n\n const restricted = randomPostObject();\n restricted.allowed = [];\n await graffiti.post<{}>(restricted, session1);\n const iterator2 = graffiti.discover(\n restricted.channels,\n publicSchema,\n session1,\n );\n await expect(iterator2.next()).resolves.toHaveProperty(\"done\", true);\n });\n\n it(\"discover query for values\", async () => {\n const object1 = randomPostObject();\n object1.value = { test: randomString() };\n await graffiti.post<{}>(object1, session);\n\n const object2 = randomPostObject();\n object2.channels = object1.channels;\n object2.value = { test: randomString(), something: randomString() };\n await graffiti.post<{}>(object2, session);\n\n const object3 = randomPostObject();\n object3.channels = object1.channels;\n object3.value = { other: randomString(), something: randomString() };\n await graffiti.post<{}>(object3, session);\n\n const counts = new Map<string, number>();\n for (const property of [\"test\", \"something\", \"other\"] as const) {\n let count = 0;\n for await (const result of graffiti.discover(object1.channels, {\n properties: {\n value: {\n required: [property],\n },\n },\n })) {\n assert(!result.error, \"result has error\");\n if (property in result.object.value) {\n count++;\n }\n }\n counts.set(property, count);\n }\n\n expect(counts.get(\"test\")).toBe(2);\n expect(counts.get(\"something\")).toBe(2);\n expect(counts.get(\"other\")).toBe(1);\n });\n\n for (const continueType of [\"cursor\", \"continue\"] as const) {\n describe(`continue discover with ${continueType}`, () => {\n it(\"discover for deleted content\", async () => {\n const object = randomPostObject();\n\n const posted = await graffiti.post<{}>(object, session);\n\n const iterator1 = graffiti.discover<{}>(object.channels, {});\n const value1 = await nextStreamValue<{}>(iterator1);\n expect(value1.value).toEqual(object.value);\n const returnValue = await iterator1.next();\n assert(returnValue.done, \"value2 is not done\");\n\n await graffiti.delete(posted, session);\n\n const iterator = graffiti.discover(object.channels, {});\n await expect(iterator.next()).resolves.toHaveProperty(\"done\", true);\n\n const tombIterator = continueStream<{}>(\n graffiti,\n returnValue.value,\n continueType,\n );\n const value = await tombIterator.next();\n assert(!value.done && !value.value.error, \"value is done\");\n assert(value.value.tombstone, \"value is not tombstone\");\n expect(value.value.object.url).toEqual(posted.url);\n await expect(tombIterator.next()).resolves.toHaveProperty(\n \"done\",\n true,\n );\n });\n });\n }\n });\n};\n", "import {\n GraffitiErrorNotAcceptable,\n GraffitiErrorNotFound,\n GraffitiErrorTooLarge,\n type Graffiti,\n type GraffitiSession,\n} from \"@graffiti-garden/api\";\nimport { it, expect, describe, beforeAll } from \"vitest\";\nimport { randomString } from \"./utils\";\n\nexport const graffitiMediaTests = (\n useGraffiti: () => Pick<Graffiti, \"postMedia\" | \"getMedia\" | \"deleteMedia\">,\n useSession1: () => GraffitiSession | Promise<GraffitiSession>,\n useSession2: () => GraffitiSession | Promise<GraffitiSession>,\n) => {\n describe.concurrent(\n \"media\",\n {\n timeout: 20000,\n },\n () => {\n let graffiti: ReturnType<typeof useGraffiti>;\n let session: GraffitiSession;\n let session1: GraffitiSession;\n let session2: GraffitiSession;\n beforeAll(async () => {\n graffiti = useGraffiti();\n session1 = await useSession1();\n session = session1;\n session2 = await useSession2();\n });\n\n it(\"post, get, delete media\", async () => {\n // Post media\n const text = randomString();\n const data = new Blob([text], { type: \"text/plain\" });\n const mediaUrl = await graffiti.postMedia({ data }, session);\n\n // Get the media back\n const media = await graffiti.getMedia(mediaUrl, {});\n expect(await media.data.text()).toEqual(text);\n expect(media.data.type).toEqual(\"text/plain\");\n expect(media.allowed).toBeUndefined();\n expect(media.actor).toBe(session.actor);\n\n // Delete the media\n await graffiti.deleteMedia(mediaUrl, session);\n\n // Try to get the media again\n await expect(graffiti.getMedia(mediaUrl, {})).rejects.toThrow(\n GraffitiErrorNotFound,\n );\n });\n\n it(\"acceptable type\", async () => {\n const text = randomString();\n const data = new Blob([text], { type: \"text/plain\" });\n const mediaUrl = await graffiti.postMedia({ data }, session);\n\n const media = await graffiti.getMedia(mediaUrl, {\n accept: \"text/*\",\n });\n expect(await media.data.text()).toEqual(text);\n expect(media.data.type).toEqual(\"text/plain\");\n expect(media.allowed).toBeUndefined();\n expect(media.actor).toBe(session.actor);\n });\n\n it(\"unacceptable type\", async () => {\n const text = randomString();\n const data = new Blob([text], { type: \"text/plain\" });\n const mediaUrl = await graffiti.postMedia({ data }, session);\n\n await expect(\n graffiti.getMedia(mediaUrl, {\n accept: \"image/*\",\n }),\n ).rejects.toThrow(GraffitiErrorNotAcceptable);\n });\n\n it(\"acceptable size\", async () => {\n const text = randomString();\n const data = new Blob([text], { type: \"text/plain\" });\n const mediaUrl = await graffiti.postMedia({ data }, session);\n\n const media = await graffiti.getMedia(mediaUrl, {\n maxBytes: data.size,\n });\n expect(await media.data.text()).toEqual(text);\n expect(media.data.type).toEqual(\"text/plain\");\n expect(media.allowed).toBeUndefined();\n expect(media.actor).toBe(session.actor);\n });\n\n it(\"unacceptable size\", async () => {\n const text = randomString();\n const data = new Blob([text], { type: \"text/plain\" });\n const mediaUrl = await graffiti.postMedia({ data }, session);\n\n await expect(\n graffiti.getMedia(mediaUrl, {\n maxBytes: data.size - 1,\n }),\n ).rejects.toThrow(GraffitiErrorTooLarge);\n });\n\n it(\"empty allowed\", async () => {\n const text = randomString();\n const data = new Blob([text], { type: \"text/plain\" });\n const allowed: string[] = [];\n const mediaUrl = await graffiti.postMedia({ data, allowed }, session1);\n\n // Get it with the authorized user\n const media = await graffiti.getMedia(mediaUrl, {}, session1);\n expect(await media.data.text()).toEqual(text);\n expect(media.data.type).toEqual(\"text/plain\");\n expect(media.allowed).toEqual([]);\n expect(media.actor).toBe(session1.actor);\n\n // Get it with the unauthorized user\n await expect(graffiti.getMedia(mediaUrl, {}, session2)).rejects.toThrow(\n GraffitiErrorNotFound,\n );\n\n // Get it without authorization\n await expect(graffiti.getMedia(mediaUrl, {})).rejects.toThrow(\n GraffitiErrorNotFound,\n );\n });\n\n it(\"allowed\", async () => {\n const text = randomString();\n const data = new Blob([text], { type: \"text/plain\" });\n const allowed = [randomString(), session2.actor, randomString()];\n const mediaUrl = await graffiti.postMedia({ data, allowed }, session1);\n\n // Get it with the authorized user\n const media = await graffiti.getMedia(mediaUrl, {}, session1);\n expect(await media.data.text()).toEqual(text);\n expect(media.data.type).toEqual(\"text/plain\");\n expect(media.allowed).toEqual(allowed);\n expect(media.actor).toBe(session1.actor);\n\n // Get it with the allowed user\n const media2 = await graffiti.getMedia(mediaUrl, {}, session2);\n expect(await media2.data.text()).toEqual(text);\n expect(media2.data.type).toEqual(\"text/plain\");\n expect(media2.allowed).toEqual([session2.actor]);\n expect(media2.actor).toBe(session1.actor);\n\n // Get it without authorization\n await expect(graffiti.getMedia(mediaUrl, {})).rejects.toThrow(\n GraffitiErrorNotFound,\n );\n });\n },\n );\n};\n"],
5
- "mappings": "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",
6
- "names": ["it", "expect", "describe", "assert", "beforeAll", "describe", "beforeAll", "it", "expect", "assert", "GraffitiErrorNotFound", "it", "expect", "describe", "beforeAll", "describe", "beforeAll", "it", "expect", "GraffitiErrorNotFound"]
4
+ "sourcesContent": ["import { it, expect, describe, beforeAll } from \"vitest\";\nimport type {\n Graffiti,\n GraffitiSession,\n JSONSchema,\n} from \"@graffiti-garden/api\";\nimport {\n GraffitiErrorNotFound,\n GraffitiErrorSchemaMismatch,\n GraffitiErrorInvalidSchema,\n GraffitiErrorForbidden,\n} from \"@graffiti-garden/api\";\nimport { randomPostObject, randomString } from \"./utils\";\n\nexport const graffitiCRUDTests = (\n useGraffiti: () => Pick<Graffiti, \"post\" | \"get\" | \"delete\">,\n useSession1: () => GraffitiSession | Promise<GraffitiSession>,\n useSession2: () => GraffitiSession | Promise<GraffitiSession>,\n) => {\n describe.concurrent(\n \"CRUD\",\n {\n timeout: 20000,\n },\n () => {\n let graffiti: ReturnType<typeof useGraffiti>;\n let session: GraffitiSession;\n let session1: GraffitiSession;\n let session2: GraffitiSession;\n beforeAll(async () => {\n graffiti = useGraffiti();\n session1 = await useSession1();\n session = session1;\n session2 = await useSession2();\n });\n\n it(\"get nonexistant object\", async () => {\n await expect(graffiti.get(randomString(), {})).rejects.toThrow(\n GraffitiErrorNotFound,\n );\n });\n\n it(\"post, get, delete\", async () => {\n const value = {\n something: \"hello, world~ c:\",\n };\n const channels = [randomString(), randomString()];\n\n // Post the object\n const previous = await graffiti.post<{}>({ value, channels }, session);\n expect(previous.value).toEqual(value);\n expect(previous.channels).toEqual(channels);\n expect(previous.allowed).toEqual(undefined);\n expect(previous.actor).toEqual(session.actor);\n\n // Get it back\n const gotten = await graffiti.get(previous, {});\n expect(gotten.value).toEqual(value);\n expect(gotten.channels).toEqual([]);\n expect(gotten.allowed).toBeUndefined();\n expect(gotten.url).toEqual(previous.url);\n expect(gotten.actor).toEqual(previous.actor);\n\n // Delete it\n await graffiti.delete(gotten, session);\n\n // Get is not found\n await expect(graffiti.get(gotten, {})).rejects.toBeInstanceOf(\n GraffitiErrorNotFound,\n );\n\n // Delete it again\n await expect(graffiti.delete(gotten, session)).rejects.toThrow(\n GraffitiErrorNotFound,\n );\n });\n\n it(\"post then delete with wrong actor\", async () => {\n const posted = await graffiti.post<{}>(\n { value: {}, channels: [] },\n session2,\n );\n\n await expect(graffiti.delete(posted, session1)).rejects.toThrow(\n GraffitiErrorForbidden,\n );\n });\n\n it(\"post and get with schema\", async () => {\n const schema = {\n properties: {\n value: {\n properties: {\n something: {\n type: \"string\",\n },\n another: {\n type: \"array\",\n items: {\n type: \"number\",\n },\n },\n deeper: {\n type: \"object\",\n properties: {\n deepProp: {\n type: \"string\",\n },\n },\n required: [\"deepProp\"],\n },\n },\n required: [\"another\", \"deeper\"],\n },\n },\n } as const satisfies JSONSchema;\n\n const goodValue = {\n something: \"hello\",\n another: [1, 2, 3],\n deeper: {\n deepProp: \"hello\",\n },\n };\n\n const posted = await graffiti.post<typeof schema>(\n {\n value: goodValue,\n channels: [],\n },\n session,\n );\n const gotten = await graffiti.get(posted, schema);\n\n expect(gotten.value.something).toEqual(goodValue.something);\n expect(gotten.value.another).toEqual(goodValue.another);\n expect(gotten.value.another[0]).toEqual(1);\n expect(gotten.value.deeper.deepProp).toEqual(goodValue.deeper.deepProp);\n });\n\n it(\"post and get with invalid schema\", async () => {\n const posted = await graffiti.post<{}>(\n { value: {}, channels: [] },\n session,\n );\n await expect(\n graffiti.get(posted, {\n properties: {\n value: {\n //@ts-ignore\n type: \"asdf\",\n },\n },\n }),\n ).rejects.toThrow(GraffitiErrorInvalidSchema);\n });\n\n it(\"post and get with wrong schema\", async () => {\n const posted = await graffiti.post<{}>(\n {\n value: {\n hello: \"world\",\n },\n channels: [],\n },\n session,\n );\n\n await expect(\n graffiti.get(posted, {\n properties: {\n value: {\n properties: {\n hello: {\n type: \"number\",\n },\n },\n },\n },\n }),\n ).rejects.toThrow(GraffitiErrorSchemaMismatch);\n });\n\n it(\"post and get with empty access control\", async () => {\n const value = {\n um: \"hi\",\n };\n const allowed = [randomString()];\n const channels = [randomString()];\n const posted = await graffiti.post<{}>(\n { value, allowed, channels },\n session1,\n );\n\n // Get it with authenticated session\n const gotten = await graffiti.get(posted, {}, session1);\n expect(gotten.url).toEqual(posted.url);\n expect(gotten.actor).toEqual(session1.actor);\n expect(gotten.value).toEqual(value);\n expect(gotten.allowed).toEqual(allowed);\n expect(gotten.channels).toEqual(channels);\n\n // But not without session\n await expect(graffiti.get(posted, {})).rejects.toBeInstanceOf(\n GraffitiErrorNotFound,\n );\n\n // Or the wrong session\n await expect(graffiti.get(posted, {}, session2)).rejects.toBeInstanceOf(\n GraffitiErrorNotFound,\n );\n });\n\n it(\"post and get with specific access control\", async () => {\n const value = {\n um: \"hi\",\n };\n const allowed = [randomString(), session2.actor, randomString()];\n const channels = [randomString()];\n const posted = await graffiti.post<{}>(\n {\n value,\n allowed,\n channels,\n },\n session1,\n );\n\n // Get it with authenticated session\n const gotten = await graffiti.get(posted, {}, session1);\n expect(gotten.url).toEqual(posted.url);\n expect(gotten.actor).toEqual(session1.actor);\n expect(gotten.value).toEqual(value);\n expect(gotten.allowed).toEqual(allowed);\n expect(gotten.channels).toEqual(channels);\n\n // But not without session\n await expect(graffiti.get(posted, {})).rejects.toBeInstanceOf(\n GraffitiErrorNotFound,\n );\n\n const gotten2 = await graffiti.get(posted, {}, session2);\n expect(gotten.url).toEqual(posted.url);\n expect(gotten.actor).toEqual(session1.actor);\n expect(gotten2.value).toEqual(value);\n // They should only see that is is private to them\n expect(gotten2.allowed).toEqual([session2.actor]);\n // And not see any channels\n expect(gotten2.channels).toEqual([]);\n });\n },\n );\n};\n", "import { assert } from \"vitest\";\nimport type {\n GraffitiPostObject,\n GraffitiObjectStream,\n JSONSchema,\n GraffitiObject,\n GraffitiObjectStreamReturn,\n GraffitiObjectStreamContinue,\n Graffiti,\n GraffitiSession,\n} from \"@graffiti-garden/api\";\n\nexport function randomString(): string {\n const array = new Uint8Array(16);\n crypto.getRandomValues(array);\n const str = Array.from(array)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n\n // check for unicode support\n return str + \"\uD83D\uDC69\uD83C\uDFFD\u200D\u2764\uFE0F\u200D\uD83D\uDC8B\u200D\uD83D\uDC69\uD83C\uDFFB\uD83E\uDEF1\uD83C\uDFFC\u200D\uD83E\uDEF2\uD83C\uDFFF\";\n}\n\nexport function randomValue() {\n return {\n [randomString()]: randomString(),\n };\n}\n\nexport function randomPostObject(): GraffitiPostObject<{}> {\n return {\n value: randomValue(),\n channels: [randomString(), randomString()],\n };\n}\n\nexport async function nextStreamValue<Schema extends JSONSchema>(\n iterator: GraffitiObjectStream<Schema>,\n): Promise<GraffitiObject<Schema>> {\n const result = await iterator.next();\n assert(!result.done && !result.value.error, \"result has no value\");\n assert(!result.value.tombstone, \"result has been deleted!\");\n return result.value.object;\n}\n\nexport function continueStream<Schema extends JSONSchema>(\n graffiti: Pick<Graffiti, \"continueDiscover\">,\n streamReturn: GraffitiObjectStreamReturn<Schema>,\n type: \"cursor\" | \"continue\",\n session?: GraffitiSession | null,\n): GraffitiObjectStreamContinue<Schema> {\n if (type === \"cursor\") {\n return graffiti.continueDiscover(\n streamReturn.cursor,\n session,\n ) as unknown as GraffitiObjectStreamContinue<Schema>;\n } else {\n return streamReturn.continue();\n }\n}\n", "import { it, expect, describe, assert, beforeAll } from \"vitest\";\nimport type {\n Graffiti,\n GraffitiSession,\n JSONSchema,\n} from \"@graffiti-garden/api\";\nimport {\n GraffitiErrorForbidden,\n GraffitiErrorInvalidSchema,\n GraffitiErrorNotFound,\n} from \"@graffiti-garden/api\";\nimport {\n randomString,\n nextStreamValue,\n randomPostObject,\n continueStream,\n} from \"./utils\";\n\nexport const graffitiDiscoverTests = (\n useGraffiti: () => Pick<\n Graffiti,\n \"discover\" | \"post\" | \"delete\" | \"continueDiscover\"\n >,\n useSession1: () => GraffitiSession | Promise<GraffitiSession>,\n useSession2: () => GraffitiSession | Promise<GraffitiSession>,\n) => {\n describe.concurrent(\"discover\", { timeout: 20000 }, () => {\n let graffiti: ReturnType<typeof useGraffiti>;\n let session: GraffitiSession;\n let session1: GraffitiSession;\n let session2: GraffitiSession;\n beforeAll(async () => {\n graffiti = useGraffiti();\n session1 = await useSession1();\n session = session1;\n session2 = await useSession2();\n });\n\n it(\"discover nothing\", async () => {\n const iterator = graffiti.discover([], {});\n expect(await iterator.next()).toHaveProperty(\"done\", true);\n });\n\n it(\"discover single\", async () => {\n const object = randomPostObject();\n\n const posted = await graffiti.post<{}>(object, session);\n\n const queryChannels = [randomString(), object.channels[0]];\n const iterator = graffiti.discover<{}>(queryChannels, {});\n const value = await nextStreamValue<{}>(iterator);\n expect(value.url).toEqual(posted.url);\n expect(value.value).toEqual(object.value);\n expect(value.channels).toEqual([object.channels[0]]);\n expect(value.allowed).toBeUndefined();\n expect(value.actor).toEqual(session.actor);\n const result2 = await iterator.next();\n expect(result2.done).toBe(true);\n });\n\n it(\"discover wrong channel\", async () => {\n const object = randomPostObject();\n await graffiti.post<{}>(object, session);\n const iterator = graffiti.discover([randomString()], {});\n await expect(iterator.next()).resolves.toHaveProperty(\"done\", true);\n });\n\n it(\"discover not allowed\", async () => {\n const object = randomPostObject();\n object.allowed = [randomString(), randomString()];\n const posted = await graffiti.post<{}>(object, session1);\n\n const iteratorSession1 = graffiti.discover<{}>(\n object.channels,\n {},\n session1,\n );\n const value = await nextStreamValue<{}>(iteratorSession1);\n expect(value.url).toEqual(posted.url);\n expect(value.value).toEqual(object.value);\n expect(value.channels).toEqual(object.channels);\n expect(value.allowed).toEqual(object.allowed);\n expect(value.actor).toEqual(session1.actor);\n\n const iteratorSession2 = graffiti.discover(object.channels, {}, session2);\n expect(await iteratorSession2.next()).toHaveProperty(\"done\", true);\n\n const iteratorNoSession = graffiti.discover(object.channels, {});\n expect(await iteratorNoSession.next()).toHaveProperty(\"done\", true);\n });\n\n it(\"discover allowed\", async () => {\n const object = randomPostObject();\n object.allowed = [randomString(), session2.actor, randomString()];\n const posted = await graffiti.post<{}>(object, session1);\n\n const iteratorSession2 = graffiti.discover<{}>(\n object.channels,\n {},\n session2,\n );\n const value = await nextStreamValue<{}>(iteratorSession2);\n expect(value.url).toEqual(posted.url);\n expect(value.value).toEqual(object.value);\n expect(value.allowed).toEqual([session2.actor]);\n expect(value.channels).toEqual(object.channels);\n expect(value.actor).toEqual(session1.actor);\n });\n\n it(\"discover bad schema\", async () => {\n const iterator = graffiti.discover([], {\n properties: {\n value: {\n //@ts-ignore\n type: \"asdf\",\n },\n },\n });\n\n await expect(iterator.next()).rejects.toThrow(GraffitiErrorInvalidSchema);\n });\n\n it(\"discover for actor\", async () => {\n const object1 = randomPostObject();\n const posted1 = await graffiti.post<{}>(object1, session1);\n\n const object2 = randomPostObject();\n object2.channels = object1.channels;\n const posted2 = await graffiti.post<{}>(object2, session2);\n\n const iterator = graffiti.discover<{}>(object1.channels, {\n properties: {\n actor: { const: posted1.actor },\n },\n });\n\n const value = await nextStreamValue<{}>(iterator);\n expect(value.url).toEqual(posted1.url);\n expect(value.url).not.toEqual(posted2.url);\n expect(value.value).toEqual(object1.value);\n await expect(iterator.next()).resolves.toHaveProperty(\"done\", true);\n });\n\n it(\"discover schema allowed, as and not as owner\", async () => {\n const object = randomPostObject();\n object.allowed = [randomString(), session2.actor, randomString()];\n await graffiti.post<{}>(object, session1);\n\n const iteratorSession1 = graffiti.discover<{}>(\n object.channels,\n {\n properties: {\n allowed: {\n minItems: 3,\n // Make sure session2.actor is in the allow list\n not: {\n items: {\n not: { const: session2.actor },\n },\n },\n },\n },\n },\n session1,\n );\n const value = await nextStreamValue<{}>(iteratorSession1);\n expect(value.value).toEqual(object.value);\n await expect(iteratorSession1.next()).resolves.toHaveProperty(\n \"done\",\n true,\n );\n\n const iteratorSession2BigAllow = graffiti.discover(\n object.channels,\n {\n properties: {\n allowed: {\n minItems: 3,\n },\n },\n },\n session2,\n );\n await expect(iteratorSession2BigAllow.next()).resolves.toHaveProperty(\n \"done\",\n true,\n );\n const iteratorSession2PeekOther = graffiti.discover(\n object.channels,\n {\n properties: {\n allowed: {\n not: {\n items: {\n not: { const: object.allowed[0] },\n },\n },\n },\n },\n },\n session2,\n );\n await expect(iteratorSession2PeekOther.next()).resolves.toHaveProperty(\n \"done\",\n true,\n );\n const iteratorSession2SmallAllowPeekSelf = graffiti.discover<{}>(\n object.channels,\n {\n properties: {\n allowed: {\n maxItems: 1,\n not: {\n items: {\n not: { const: session2.actor },\n },\n },\n },\n },\n },\n session2,\n );\n const value2 = await nextStreamValue<{}>(\n iteratorSession2SmallAllowPeekSelf,\n );\n expect(value2.value).toEqual(object.value);\n await expect(\n iteratorSession2SmallAllowPeekSelf.next(),\n ).resolves.toHaveProperty(\"done\", true);\n });\n\n it(\"discover schema channels, as and not as owner\", async () => {\n const object = randomPostObject();\n object.channels = [randomString(), randomString(), randomString()];\n await graffiti.post<{}>(object, session1);\n\n const iteratorSession1 = graffiti.discover<{}>(\n [object.channels[0], object.channels[2]],\n {\n properties: {\n channels: {\n minItems: 3,\n // Make sure channel 1 is in the allow list\n not: {\n items: {\n not: { const: object.channels[1] },\n },\n },\n },\n },\n },\n session1,\n );\n const value = await nextStreamValue<{}>(iteratorSession1);\n expect(value.value).toEqual(object.value);\n await expect(iteratorSession1.next()).resolves.toHaveProperty(\n \"done\",\n true,\n );\n\n const iteratorSession2BigAllow = graffiti.discover(\n [object.channels[0], object.channels[2]],\n {\n properties: {\n channels: {\n minItems: 3,\n },\n },\n },\n session2,\n );\n await expect(iteratorSession2BigAllow.next()).resolves.toHaveProperty(\n \"done\",\n true,\n );\n const iteratorSession2PeekOther = graffiti.discover(\n [object.channels[0], object.channels[2]],\n {\n properties: {\n channels: {\n not: {\n items: {\n not: { const: object.channels[1] },\n },\n },\n },\n },\n },\n session2,\n );\n await expect(iteratorSession2PeekOther.next()).resolves.toHaveProperty(\n \"done\",\n true,\n );\n const iteratorSession2SmallAllowPeekSelf = graffiti.discover<{}>(\n [object.channels[0], object.channels[2]],\n {\n properties: {\n allowed: {\n maxItems: 2,\n not: {\n items: {\n not: { const: object.channels[2] },\n },\n },\n },\n },\n },\n session2,\n );\n const value2 = await nextStreamValue<{}>(\n iteratorSession2SmallAllowPeekSelf,\n );\n expect(value2.value).toEqual(object.value);\n await expect(\n iteratorSession2SmallAllowPeekSelf.next(),\n ).resolves.toHaveProperty(\"done\", true);\n });\n\n it(\"discover query for empty allowed\", async () => {\n const publicO = randomPostObject();\n\n const publicSchema = {\n not: {\n required: [\"allowed\"],\n },\n } satisfies JSONSchema;\n\n await graffiti.post<{}>(publicO, session1);\n const iterator = graffiti.discover<{}>(\n publicO.channels,\n publicSchema,\n session1,\n );\n const value = await nextStreamValue<{}>(iterator);\n expect(value.value).toEqual(publicO.value);\n expect(value.allowed).toBeUndefined();\n await expect(iterator.next()).resolves.toHaveProperty(\"done\", true);\n\n const restricted = randomPostObject();\n restricted.allowed = [];\n await graffiti.post<{}>(restricted, session1);\n const iterator2 = graffiti.discover(\n restricted.channels,\n publicSchema,\n session1,\n );\n await expect(iterator2.next()).resolves.toHaveProperty(\"done\", true);\n });\n\n it(\"discover query for values\", async () => {\n const object1 = randomPostObject();\n object1.value = { test: randomString() };\n await graffiti.post<{}>(object1, session);\n\n const object2 = randomPostObject();\n object2.channels = object1.channels;\n object2.value = { test: randomString(), something: randomString() };\n await graffiti.post<{}>(object2, session);\n\n const object3 = randomPostObject();\n object3.channels = object1.channels;\n object3.value = { other: randomString(), something: randomString() };\n await graffiti.post<{}>(object3, session);\n\n const counts = new Map<string, number>();\n for (const property of [\"test\", \"something\", \"other\"] as const) {\n let count = 0;\n for await (const result of graffiti.discover(object1.channels, {\n properties: {\n value: {\n required: [property],\n },\n },\n })) {\n assert(!result.error, \"result has error\");\n if (property in result.object.value) {\n count++;\n }\n }\n counts.set(property, count);\n }\n\n expect(counts.get(\"test\")).toBe(2);\n expect(counts.get(\"something\")).toBe(2);\n expect(counts.get(\"other\")).toBe(1);\n });\n\n for (const continueType of [\"cursor\", \"continue\"] as const) {\n describe(`continue discover with ${continueType}`, () => {\n it(\"discover for deleted content\", async () => {\n const object = randomPostObject();\n\n const posted = await graffiti.post<{}>(object, session);\n\n const iterator1 = graffiti.discover<{}>(object.channels, {});\n const value1 = await nextStreamValue<{}>(iterator1);\n expect(value1.value).toEqual(object.value);\n const returnValue = await iterator1.next();\n assert(returnValue.done, \"value2 is not done\");\n\n await graffiti.delete(posted, session);\n\n const iterator = graffiti.discover(object.channels, {});\n await expect(iterator.next()).resolves.toHaveProperty(\"done\", true);\n\n const tombIterator = continueStream<{}>(\n graffiti,\n returnValue.value,\n continueType,\n );\n const value = await tombIterator.next();\n assert(!value.done && !value.value.error, \"value is done\");\n assert(value.value.tombstone, \"value is not tombstone\");\n expect(value.value.object.url).toEqual(posted.url);\n const returnValue2 = await tombIterator.next();\n assert(returnValue2.done, \"value2 is not done\");\n\n // Post another object\n const posted2 = await graffiti.post<{}>(object, session);\n const doubleContinueIterator = continueStream<{}>(\n graffiti,\n returnValue2.value,\n continueType,\n );\n const value2 = await doubleContinueIterator.next();\n assert(!value2.done && !value2.value.error, \"value2 is done\");\n assert(!value2.value.tombstone, \"value2 is tombstone\");\n expect(value2.value.object.url).toEqual(posted2.url);\n await expect(doubleContinueIterator.next()).resolves.toHaveProperty(\n \"done\",\n true,\n );\n });\n\n it(\"continue with wrong actor\", async () => {\n const iterator = graffiti.discover<{}>([], {}, session1);\n const result = await iterator.next();\n assert(result.done, \"iterator is not done\");\n\n const continuation = continueStream<{}>(\n graffiti,\n result.value,\n continueType,\n session2,\n );\n await expect(continuation.next()).rejects.toThrow(\n GraffitiErrorForbidden,\n );\n });\n });\n }\n\n it(\"lookup non-existant cursor\", async () => {\n const iterator = graffiti.continueDiscover(randomString());\n await expect(iterator.next()).rejects.toThrow(GraffitiErrorNotFound);\n });\n });\n};\n", "import {\n GraffitiErrorNotAcceptable,\n GraffitiErrorNotFound,\n GraffitiErrorTooLarge,\n type Graffiti,\n type GraffitiSession,\n} from \"@graffiti-garden/api\";\nimport { it, expect, describe, beforeAll } from \"vitest\";\nimport { randomString } from \"./utils\";\n\nexport const graffitiMediaTests = (\n useGraffiti: () => Pick<Graffiti, \"postMedia\" | \"getMedia\" | \"deleteMedia\">,\n useSession1: () => GraffitiSession | Promise<GraffitiSession>,\n useSession2: () => GraffitiSession | Promise<GraffitiSession>,\n) => {\n describe.concurrent(\n \"media\",\n {\n timeout: 20000,\n },\n () => {\n let graffiti: ReturnType<typeof useGraffiti>;\n let session: GraffitiSession;\n let session1: GraffitiSession;\n let session2: GraffitiSession;\n beforeAll(async () => {\n graffiti = useGraffiti();\n session1 = await useSession1();\n session = session1;\n session2 = await useSession2();\n });\n\n it(\"post, get, delete media\", async () => {\n // Post media\n const text = randomString();\n const data = new Blob([text], { type: \"text/plain\" });\n const mediaUrl = await graffiti.postMedia({ data }, session);\n\n // Get the media back\n const media = await graffiti.getMedia(mediaUrl, {});\n expect(await media.data.text()).toEqual(text);\n expect(media.data.type).toEqual(\"text/plain\");\n expect(media.allowed).toBeUndefined();\n expect(media.actor).toBe(session.actor);\n\n // Delete the media\n await graffiti.deleteMedia(mediaUrl, session);\n\n // Try to get the media again\n await expect(graffiti.getMedia(mediaUrl, {})).rejects.toThrow(\n GraffitiErrorNotFound,\n );\n });\n\n it(\"acceptable type\", async () => {\n const text = randomString();\n const data = new Blob([text], { type: \"text/plain\" });\n const mediaUrl = await graffiti.postMedia({ data }, session);\n\n const media = await graffiti.getMedia(mediaUrl, {\n accept: \"text/*\",\n });\n expect(await media.data.text()).toEqual(text);\n expect(media.data.type).toEqual(\"text/plain\");\n expect(media.allowed).toBeUndefined();\n expect(media.actor).toBe(session.actor);\n });\n\n it(\"unacceptable type\", async () => {\n const text = randomString();\n const data = new Blob([text], { type: \"text/plain\" });\n const mediaUrl = await graffiti.postMedia({ data }, session);\n\n await expect(\n graffiti.getMedia(mediaUrl, {\n accept: \"image/*\",\n }),\n ).rejects.toThrow(GraffitiErrorNotAcceptable);\n });\n\n it(\"acceptable size\", async () => {\n const text = randomString();\n const data = new Blob([text], { type: \"text/plain\" });\n const mediaUrl = await graffiti.postMedia({ data }, session);\n\n const media = await graffiti.getMedia(mediaUrl, {\n maxBytes: data.size,\n });\n expect(await media.data.text()).toEqual(text);\n expect(media.data.type).toEqual(\"text/plain\");\n expect(media.allowed).toBeUndefined();\n expect(media.actor).toBe(session.actor);\n });\n\n it(\"unacceptable size\", async () => {\n const text = randomString();\n const data = new Blob([text], { type: \"text/plain\" });\n const mediaUrl = await graffiti.postMedia({ data }, session);\n\n await expect(\n graffiti.getMedia(mediaUrl, {\n maxBytes: data.size - 1,\n }),\n ).rejects.toThrow(GraffitiErrorTooLarge);\n });\n\n it(\"empty allowed\", async () => {\n const text = randomString();\n const data = new Blob([text], { type: \"text/plain\" });\n const allowed: string[] = [];\n const mediaUrl = await graffiti.postMedia({ data, allowed }, session1);\n\n // Get it with the authorized user\n const media = await graffiti.getMedia(mediaUrl, {}, session1);\n expect(await media.data.text()).toEqual(text);\n expect(media.data.type).toEqual(\"text/plain\");\n expect(media.allowed).toEqual([]);\n expect(media.actor).toBe(session1.actor);\n\n // Get it with the unauthorized user\n await expect(graffiti.getMedia(mediaUrl, {}, session2)).rejects.toThrow(\n GraffitiErrorNotFound,\n );\n\n // Get it without authorization\n await expect(graffiti.getMedia(mediaUrl, {})).rejects.toThrow(\n GraffitiErrorNotFound,\n );\n });\n\n it(\"allowed\", async () => {\n const text = randomString();\n const data = new Blob([text], { type: \"text/plain\" });\n const allowed = [randomString(), session2.actor, randomString()];\n const mediaUrl = await graffiti.postMedia({ data, allowed }, session1);\n\n // Get it with the authorized user\n const media = await graffiti.getMedia(mediaUrl, {}, session1);\n expect(await media.data.text()).toEqual(text);\n expect(media.data.type).toEqual(\"text/plain\");\n expect(media.allowed).toEqual(allowed);\n expect(media.actor).toBe(session1.actor);\n\n // Get it with the allowed user\n const media2 = await graffiti.getMedia(mediaUrl, {}, session2);\n expect(await media2.data.text()).toEqual(text);\n expect(media2.data.type).toEqual(\"text/plain\");\n expect(media2.allowed).toEqual([session2.actor]);\n expect(media2.actor).toBe(session1.actor);\n\n // Get it without authorization\n await expect(graffiti.getMedia(mediaUrl, {})).rejects.toThrow(\n GraffitiErrorNotFound,\n );\n });\n },\n );\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["it", "expect", "describe", "assert", "beforeAll", "GraffitiErrorForbidden", "GraffitiErrorInvalidSchema", "GraffitiErrorNotFound", "describe", "beforeAll", "it", "expect", "GraffitiErrorInvalidSchema", "assert", "GraffitiErrorForbidden", "GraffitiErrorNotFound", "GraffitiErrorNotFound", "it", "expect", "describe", "beforeAll", "describe", "beforeAll", "it", "expect", "GraffitiErrorNotFound"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graffiti-garden/api",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "The heart of Graffiti",
5
5
  "types": "./dist/src/index.d.ts",
6
6
  "module": "./dist/index.mjs",
package/src/1-api.ts CHANGED
@@ -6,6 +6,9 @@ import type {
6
6
  GraffitiPostObject,
7
7
  GraffitiObjectStream,
8
8
  GraffitiObjectStreamContinue,
9
+ GraffitiMedia,
10
+ GraffitiPostMedia,
11
+ GraffitiMediaRequirements,
9
12
  } from "./2-types";
10
13
  import type { JSONSchema } from "json-schema-to-ts";
11
14
 
@@ -150,6 +153,8 @@ export abstract class Graffiti {
150
153
  *
151
154
  * @throws {@link GraffitiErrorSchemaMismatch} if the retrieved object does not match the provided schema.
152
155
  *
156
+ * @throws {@link GraffitiErrorInvalidSchema} If an invalid schema is provided.
157
+ *
153
158
  * @group 1 - Single-Object Methods
154
159
  */
155
160
  abstract get<Schema extends JSONSchema>(
@@ -223,6 +228,9 @@ export abstract class Graffiti {
223
228
  * Since different implementations may fetch data from multiple sources there is
224
229
  * no guarentee on the order that objects are returned in.
225
230
  *
231
+ * @throws {@link GraffitiErrorInvalidSchema} if an invalid schema is provided.
232
+ * Discovery is lazy and will not throw until the iterator is consumed.
233
+ *
226
234
  * @returns Returns a stream of objects that match the given {@link GraffitiObjectBase.channels | `channels`}
227
235
  * and [JSON Schema](https://json-schema.org).
228
236
  *
@@ -263,7 +271,11 @@ export abstract class Graffiti {
263
271
  * instead, which is returned along with the `cursor` at the
264
272
  * end of the original stream.
265
273
  *
266
- * @throws {@link GraffitiErrorForbidden} if the {@link GraffitiObjectBase.actor | `actor`}
274
+ * @throws {@link GraffitiErrorNotFound} upon iteration
275
+ * if the cursor is invalid or expired.
276
+ *
277
+ * @throws {@link GraffitiErrorForbidden} upon iteration
278
+ * if the {@link GraffitiObjectBase.actor | `actor`}
267
279
  * provided in the `session` is not the same as the `actor`
268
280
  * that initiated the original stream.
269
281
  *
@@ -286,24 +298,12 @@ export abstract class Graffiti {
286
298
  * @group 3 - Media Methods
287
299
  */
288
300
  abstract postMedia(
289
- media: {
290
- /**
291
- * The binary data of the media to be uploaded,
292
- * along with its [media type](https://www.iana.org/assignments/media-types/media-types.xhtml),
293
- * formatted as a [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob).
294
- */
295
- data: Blob;
296
- /**
297
- * An optional list, identical in function to an object's
298
- * {@link GraffitiObjectBase.allowed | `allowed`} property,
299
- * that specifies the {@link GraffitiObjectBase.actor | `actor`}s
300
- * who are allowed to access the media. If the list is `undefined`
301
- * or `null`, anyone with the URL can access the media. If the list
302
- * is empty, only the {@link GraffitiObjectBase.actor | `actor`}
303
- * who {@link postMedia | `post`ed} the media can access it.
304
- */
305
- allowed?: string[] | null;
306
- },
301
+ /**
302
+ * The media data to upload, and optionally
303
+ * an {@link GraffitiObjectBase.allowed | `allowed`}
304
+ * list of actors that can view it.
305
+ */
306
+ media: GraffitiPostMedia,
307
307
  /**
308
308
  * An implementation-specific object with information to authenticate the
309
309
  * {@link GraffitiObjectBase.actor | `actor`}.
@@ -326,7 +326,7 @@ export abstract class Graffiti {
326
326
  /**
327
327
  * A globally unique identifier and locator for the media.
328
328
  */
329
- mediaUrl: string,
329
+ url: string,
330
330
  /**
331
331
  * An implementation-specific object with information to authenticate the
332
332
  * {@link GraffitiObjectBase.actor | `actor`}.
@@ -357,27 +357,13 @@ export abstract class Graffiti {
357
357
  /**
358
358
  * A set of requirements the retrieved media must meet.
359
359
  */
360
- requirements: {
361
- /**
362
- * A list of acceptable media types for the retrieved media,
363
- * formatted as like an [HTTP Accept header](https://httpwg.org/specs/rfc9110.html#field.accept)
364
- */
365
- accept?: string;
366
- /**
367
- * The maximum acceptable size, in bytes, of the media.
368
- */
369
- maxBytes?: number;
370
- },
360
+ requirements: GraffitiMediaRequirements,
371
361
  /**
372
362
  * An implementation-specific object with information to authenticate the
373
363
  * {@link GraffitiObjectBase.actor | `actor`}.
374
364
  */
375
365
  session?: GraffitiSession | null,
376
- ): Promise<{
377
- data: Blob;
378
- actor: string;
379
- allowed?: string[] | null;
380
- }>;
366
+ ): Promise<GraffitiMedia>;
381
367
 
382
368
  /**
383
369
  * Begins the login process. Depending on the implementation, this may
package/src/2-types.ts CHANGED
@@ -396,3 +396,41 @@ export type GraffitiSessionInitializedEvent = CustomEvent<
396
396
  | null
397
397
  | undefined
398
398
  >;
399
+
400
+ export type GraffitiMedia = {
401
+ /**
402
+ * The binary data of the media to be uploaded,
403
+ * along with its [media type](https://www.iana.org/assignments/media-types/media-types.xhtml),
404
+ * formatted as a [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob).
405
+ */
406
+ data: Blob;
407
+ /**
408
+ * The {@link GraffitiObjectBase.actor | `actor`} that
409
+ * {@link Graffiti.postMedia | `post`ed} the media.
410
+ */
411
+ actor: string;
412
+ /**
413
+ * An optional list, identical in function to an object's
414
+ * {@link GraffitiObjectBase.allowed | `allowed`} property,
415
+ * that specifies the {@link GraffitiObjectBase.actor | `actor`}s
416
+ * who are allowed to access the media. If the list is `undefined`
417
+ * or `null`, anyone with the URL can access the media. If the list
418
+ * is empty, only the {@link GraffitiObjectBase.actor | `actor`}
419
+ * who {@link Graffiti.postMedia | `post`ed} the media can access it.
420
+ */
421
+ allowed?: string[] | null;
422
+ };
423
+
424
+ export type GraffitiPostMedia = Pick<GraffitiMedia, "data" | "allowed">;
425
+
426
+ export type GraffitiMediaRequirements = {
427
+ /**
428
+ * A list of acceptable media types for the retrieved media,
429
+ * formatted as like an [HTTP Accept header](https://httpwg.org/specs/rfc9110.html#field.accept)
430
+ */
431
+ accept?: string;
432
+ /**
433
+ * The maximum acceptable size, in bytes, of the media.
434
+ */
435
+ maxBytes?: number;
436
+ };
package/tests/crud.ts CHANGED
@@ -34,6 +34,12 @@ export const graffitiCRUDTests = (
34
34
  session2 = await useSession2();
35
35
  });
36
36
 
37
+ it("get nonexistant object", async () => {
38
+ await expect(graffiti.get(randomString(), {})).rejects.toThrow(
39
+ GraffitiErrorNotFound,
40
+ );
41
+ });
42
+
37
43
  it("post, get, delete", async () => {
38
44
  const value = {
39
45
  something: "hello, world~ c:",