@graffiti-garden/api 0.6.0 → 0.6.2
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/dist/index.cjs +1 -1
- package/dist/index.cjs.map +3 -3
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +3 -3
- package/dist/src/1-api.d.ts +32 -21
- package/dist/src/1-api.d.ts.map +1 -1
- package/dist/src/2-types.d.ts +135 -23
- package/dist/src/2-types.d.ts.map +1 -1
- package/dist/src/3-errors.d.ts +2 -2
- 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/orphans.d.ts +1 -1
- package/dist/tests/orphans.d.ts.map +1 -1
- package/dist/tests/utils.d.ts +3 -2
- package/dist/tests/utils.d.ts.map +1 -1
- package/dist/tests.mjs +269 -180
- package/dist/tests.mjs.map +2 -2
- package/package.json +1 -1
- package/src/1-api.ts +35 -22
- package/src/2-types.ts +156 -29
- package/src/3-errors.ts +5 -5
- package/tests/crud.ts +8 -0
- package/tests/discover.ts +265 -172
- package/tests/orphans.ts +74 -59
- package/tests/utils.ts +30 -3
package/dist/tests.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../tests/crud.ts", "../tests/utils.ts", "../tests/discover.ts", "../tests/orphans.ts", "../tests/channel-stats.ts"],
|
|
4
|
-
"sourcesContent": ["import { it, expect, describe, beforeAll } from \"vitest\";\nimport type {\n Graffiti,\n GraffitiSession,\n GraffitiPatch,\n JSONSchema,\n} from \"@graffiti-garden/api\";\nimport {\n GraffitiErrorNotFound,\n GraffitiErrorSchemaMismatch,\n GraffitiErrorInvalidSchema,\n GraffitiErrorForbidden,\n GraffitiErrorPatchTestFailed,\n GraffitiErrorPatchError,\n} from \"@graffiti-garden/api\";\nimport { randomPutObject, randomString } from \"./utils\";\n\nexport const graffitiCRUDTests = (\n useGraffiti: () => Pick<Graffiti, \"put\" | \"get\" | \"delete\" | \"patch\">,\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(\"put, get, delete\", async () => {\n const value = {\n something: \"hello, world~ c:\",\n };\n const channels = [randomString(), randomString()];\n\n // Put the object\n const previous = await graffiti.put<{}>({ value, channels }, session);\n expect(previous.value).toEqual({});\n expect(previous.channels).toEqual([]);\n expect(previous.allowed).toEqual([]);\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 expect(gotten.lastModified).toEqual(previous.lastModified);\n\n // Replace it\n const newValue = {\n something: \"goodbye, world~ :c\",\n };\n const beforeReplaced = await graffiti.put<{}>(\n {\n url: previous.url,\n value: newValue,\n channels: [],\n },\n session,\n );\n expect(beforeReplaced.value).toEqual(value);\n expect(beforeReplaced.url).toEqual(previous.url);\n expect(beforeReplaced.actor).toEqual(previous.actor);\n expect(beforeReplaced.lastModified).toBeGreaterThanOrEqual(\n gotten.lastModified,\n );\n\n // Get it again\n const afterReplaced = await graffiti.get(previous, {});\n expect(afterReplaced.value).toEqual(newValue);\n expect(afterReplaced.lastModified).toEqual(beforeReplaced.lastModified);\n\n // Delete it\n const beforeDeleted = await graffiti.delete(afterReplaced, session);\n expect(beforeDeleted.value).toEqual(newValue);\n expect(beforeDeleted.lastModified).toBeGreaterThanOrEqual(\n beforeReplaced.lastModified,\n );\n\n // Get is not found\n await expect(graffiti.get(afterReplaced, {})).rejects.toBeInstanceOf(\n GraffitiErrorNotFound,\n );\n\n // Delete it again\n await expect(graffiti.delete(beforeDeleted, session)).rejects.toThrow(\n GraffitiErrorNotFound,\n );\n });\n\n it(\"put, delete, patch with wrong actor\", async () => {\n await expect(\n graffiti.put<{}>(\n { value: {}, channels: [], actor: session2.actor },\n session1,\n ),\n ).rejects.toThrow(GraffitiErrorForbidden);\n\n const putted = await graffiti.put<{}>(\n { value: {}, channels: [] },\n session2,\n );\n\n await expect(\n graffiti.put<{}>(\n {\n url: putted.url,\n value: {},\n channels: [],\n },\n session1,\n ),\n ).rejects.toThrow(GraffitiErrorForbidden);\n\n await expect(graffiti.delete(putted, session1)).rejects.toThrow(\n GraffitiErrorForbidden,\n );\n\n await expect(graffiti.patch({}, putted, session1)).rejects.toThrow(\n GraffitiErrorForbidden,\n );\n });\n\n it(\"put, patch, delete object that is not allowed\", async () => {\n const putted = await graffiti.put<{}>(\n {\n value: {},\n channels: [],\n allowed: [],\n },\n session1,\n );\n\n await expect(\n graffiti.put(\n {\n url: putted.url,\n value: {},\n channels: [],\n },\n session2,\n ),\n ).rejects.toThrow(GraffitiErrorNotFound);\n\n await expect(graffiti.patch({}, putted, session2)).rejects.toThrow(\n GraffitiErrorNotFound,\n );\n\n await expect(graffiti.delete(putted, session2)).rejects.toThrow(\n GraffitiErrorNotFound,\n );\n });\n\n it(\"put 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 putted = await graffiti.put<typeof schema>(\n {\n value: goodValue,\n channels: [],\n },\n session,\n );\n const gotten = await graffiti.get(putted, 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(\"put and get with invalid schema\", async () => {\n const putted = await graffiti.put<{}>(\n { value: {}, channels: [] },\n session,\n );\n await expect(\n graffiti.get(putted, {\n properties: {\n value: {\n //@ts-ignore\n type: \"asdf\",\n },\n },\n }),\n ).rejects.toThrow(GraffitiErrorInvalidSchema);\n });\n\n it(\"put and get with wrong schema\", async () => {\n const putted = await graffiti.put<{}>(\n {\n value: {\n hello: \"world\",\n },\n channels: [],\n },\n session,\n );\n\n await expect(\n graffiti.get(putted, {\n properties: {\n value: {\n properties: {\n hello: {\n type: \"number\",\n },\n },\n },\n },\n }),\n ).rejects.toThrow(GraffitiErrorSchemaMismatch);\n });\n\n it(\"put and get with empty access control\", async () => {\n const value = {\n um: \"hi\",\n };\n const allowed = [randomString()];\n const channels = [randomString()];\n const putted = await graffiti.put<{}>(\n { value, allowed, channels },\n session1,\n );\n\n // Get it with authenticated session\n const gotten = await graffiti.get(putted, {}, session1);\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(putted, {})).rejects.toBeInstanceOf(\n GraffitiErrorNotFound,\n );\n\n // Or the wrong session\n await expect(graffiti.get(putted, {}, session2)).rejects.toBeInstanceOf(\n GraffitiErrorNotFound,\n );\n });\n\n it(\"put 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 putted = await graffiti.put<{}>(\n {\n value,\n allowed,\n channels,\n },\n session1,\n );\n\n // Get it with authenticated session\n const gotten = await graffiti.get(putted, {}, session1);\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(putted, {})).rejects.toBeInstanceOf(\n GraffitiErrorNotFound,\n );\n\n const gotten2 = await graffiti.get(putted, {}, session2);\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 it(\"patch value\", async () => {\n const value = {\n something: \"hello, world~ c:\",\n };\n const putted = await graffiti.put<{}>({ value, channels: [] }, session);\n\n // Wait just a bit to make sure the lastModified is different\n await new Promise((resolve) => setTimeout(resolve, 10));\n\n const patch: GraffitiPatch = {\n value: [\n { op: \"replace\", path: \"/something\", value: \"goodbye, world~ :c\" },\n ],\n };\n const beforePatched = await graffiti.patch(patch, putted, session);\n expect(beforePatched.value).toEqual(value);\n expect(beforePatched.lastModified).toBeGreaterThan(putted.lastModified);\n\n const gotten = await graffiti.get(putted, {});\n expect(gotten.value).toEqual({\n something: \"goodbye, world~ :c\",\n });\n expect(beforePatched.lastModified).toBe(gotten.lastModified);\n\n await graffiti.delete(putted, session);\n });\n\n it(\"patch deleted object\", async () => {\n const putted = await graffiti.put<{}>(randomPutObject(), session);\n const deleted = await graffiti.delete(putted, session);\n await expect(\n graffiti.patch({}, putted, session),\n ).rejects.toBeInstanceOf(GraffitiErrorNotFound);\n });\n\n it(\"deep patch\", async () => {\n const value = {\n something: {\n another: {\n somethingElse: \"hello\",\n },\n },\n };\n const putted = await graffiti.put<{}>(\n { value: value, channels: [] },\n session,\n );\n\n const beforePatch = await graffiti.patch(\n {\n value: [\n {\n op: \"replace\",\n path: \"/something/another/somethingElse\",\n value: \"goodbye\",\n },\n ],\n },\n putted,\n session,\n );\n const gotten = await graffiti.get(putted, {});\n\n expect(beforePatch.value).toEqual(value);\n expect(gotten.value).toEqual({\n something: {\n another: {\n somethingElse: \"goodbye\",\n },\n },\n });\n });\n\n it(\"patch channels\", async () => {\n const channelsBefore = [randomString()];\n const channelsAfter = [randomString()];\n\n const putted = await graffiti.put<{}>(\n { value: {}, channels: channelsBefore },\n session,\n );\n\n const patch: GraffitiPatch = {\n channels: [{ op: \"replace\", path: \"/0\", value: channelsAfter[0] }],\n };\n const patched = await graffiti.patch(patch, putted, session);\n expect(patched.channels).toEqual(channelsBefore);\n const gotten = await graffiti.get(putted, {}, session);\n expect(gotten.channels).toEqual(channelsAfter);\n await graffiti.delete(putted, session);\n });\n\n it(\"patch 'increment' with test\", async () => {\n const putted = await graffiti.put<{}>(\n {\n value: {\n counter: 1,\n },\n channels: [],\n },\n session,\n );\n\n const previous = await graffiti.patch(\n {\n value: [\n { op: \"test\", path: \"/counter\", value: 1 },\n { op: \"replace\", path: \"/counter\", value: 2 },\n ],\n },\n putted,\n session,\n );\n expect(previous.value).toEqual({ counter: 1 });\n const result = await graffiti.get(previous, {\n properties: {\n value: {\n properties: {\n counter: {\n type: \"integer\",\n },\n },\n },\n },\n });\n expect(result.value.counter).toEqual(2);\n\n await expect(\n graffiti.patch(\n {\n value: [\n { op: \"test\", path: \"/counter\", value: 1 },\n { op: \"replace\", path: \"/counter\", value: 3 },\n ],\n },\n putted,\n session,\n ),\n ).rejects.toThrow(GraffitiErrorPatchTestFailed);\n });\n\n it(\"invalid patch\", async () => {\n const object = randomPutObject();\n const putted = await graffiti.put<{}>(object, session);\n\n await expect(\n graffiti.patch(\n {\n value: [\n { op: \"add\", path: \"/root\", value: [] },\n { op: \"add\", path: \"/root/2\", value: 2 }, // out of bounds\n ],\n },\n putted,\n session,\n ),\n ).rejects.toThrow(GraffitiErrorPatchError);\n });\n\n it(\"patch channels to be wrong\", async () => {\n const object = randomPutObject();\n object.allowed = [randomString()];\n const putted = await graffiti.put<{}>(object, session);\n\n const patches: GraffitiPatch[] = [\n {\n channels: [{ op: \"replace\", path: \"\", value: null }],\n },\n {\n channels: [{ op: \"replace\", path: \"\", value: {} }],\n },\n {\n channels: [{ op: \"replace\", path: \"\", value: [\"hello\", [\"hi\"]] }],\n },\n {\n channels: [{ op: \"add\", path: \"/0\", value: 1 }],\n },\n {\n value: [{ op: \"replace\", path: \"\", value: \"not an object\" }],\n },\n {\n value: [{ op: \"replace\", path: \"\", value: null }],\n },\n {\n value: [{ op: \"replace\", path: \"\", value: [] }],\n },\n {\n allowed: [{ op: \"replace\", path: \"\", value: {} }],\n },\n {\n allowed: [{ op: \"replace\", path: \"\", value: [\"hello\", [\"hi\"]] }],\n },\n ];\n\n for (const patch of patches) {\n await expect(graffiti.patch(patch, putted, session)).rejects.toThrow(\n GraffitiErrorPatchError,\n );\n }\n\n const gotten = await graffiti.get(putted, {}, session);\n expect(gotten.value).toEqual(object.value);\n expect(gotten.channels).toEqual(object.channels);\n expect(gotten.allowed).toEqual(object.allowed);\n expect(gotten.lastModified).toEqual(putted.lastModified);\n });\n },\n );\n};\n", "import { assert } from \"vitest\";\nimport type { GraffitiPutObject, GraffitiStream } 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 randomPutObject(): GraffitiPutObject<{}> {\n return {\n value: randomValue(),\n channels: [randomString(), randomString()],\n };\n}\n\nexport async function nextStreamValue<S>(iterator: GraffitiStream<S>) {\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.value;\n}\n", "import { it, expect, describe, assert, beforeAll } from \"vitest\";\nimport type {\n Graffiti,\n GraffitiSession,\n JSONSchema,\n} from \"@graffiti-garden/api\";\nimport { randomString, nextStreamValue, randomPutObject } from \"./utils\";\n\nexport const graffitiDiscoverTests = (\n useGraffiti: () => Pick<Graffiti, \"discover\" | \"put\" | \"delete\" | \"patch\">,\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 = randomPutObject();\n\n const putted = await graffiti.put<{}>(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.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 expect(value.lastModified).toEqual(putted.lastModified);\n const result2 = await iterator.next();\n expect(result2.done).toBe(true);\n });\n\n it(\"discover wrong channel\", async () => {\n const object = randomPutObject();\n await graffiti.put<{}>(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 = randomPutObject();\n object.allowed = [randomString(), randomString()];\n const putted = await graffiti.put<{}>(object, session1);\n\n const iteratorSession1 = graffiti.discover(object.channels, {}, session1);\n const value = await nextStreamValue(iteratorSession1);\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 expect(value.lastModified).toEqual(putted.lastModified);\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 = randomPutObject();\n object.allowed = [randomString(), session2.actor, randomString()];\n const putted = await graffiti.put<{}>(object, session1);\n\n const iteratorSession2 = graffiti.discover(object.channels, {}, session2);\n const value = await nextStreamValue(iteratorSession2);\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 expect(value.lastModified).toEqual(putted.lastModified);\n });\n\n for (const prop of [\"actor\", \"lastModified\"] as const) {\n it(`discover for ${prop}`, async () => {\n const object1 = randomPutObject();\n const putted1 = await graffiti.put<{}>(object1, session1);\n\n const object2 = randomPutObject();\n object2.channels = object1.channels;\n // Make sure the lastModified is different for the query\n await new Promise((r) => setTimeout(r, 20));\n const putted2 = await graffiti.put<{}>(object2, session2);\n\n const iterator = graffiti.discover(object1.channels, {\n properties: {\n [prop]: {\n enum: [putted1[prop]],\n },\n },\n });\n\n const value = await nextStreamValue(iterator);\n expect(value.url).toEqual(putted1.url);\n expect(value.url).not.toEqual(putted2.url);\n expect(value.value).toEqual(object1.value);\n await expect(iterator.next()).resolves.toHaveProperty(\"done\", true);\n });\n }\n\n it(\"discover with lastModified range\", async () => {\n const object = randomPutObject();\n const putted1 = await graffiti.put<{}>(object, session);\n // Make sure the lastModified is different\n await new Promise((r) => setTimeout(r, 20));\n const putted2 = await graffiti.put<{}>(object, session);\n\n expect(putted1.url).not.toEqual(putted2.url);\n expect(putted1.lastModified).toBeLessThan(putted2.lastModified);\n\n const gtIterator = graffiti.discover([object.channels[0]], {\n properties: {\n lastModified: {\n exclusiveMinimum: putted2.lastModified,\n },\n },\n });\n expect(await gtIterator.next()).toHaveProperty(\"done\", true);\n const gtIteratorEpsilon = graffiti.discover([object.channels[0]], {\n properties: {\n lastModified: {\n exclusiveMinimum: putted2.lastModified - 0.1,\n },\n },\n });\n const value1 = await nextStreamValue(gtIteratorEpsilon);\n expect(value1.url).toEqual(putted2.url);\n expect(await gtIteratorEpsilon.next()).toHaveProperty(\"done\", true);\n const gteIterator = graffiti.discover(object.channels, {\n properties: {\n value: {},\n lastModified: {\n minimum: putted2.lastModified,\n },\n },\n });\n const value = await nextStreamValue(gteIterator);\n expect(value.url).toEqual(putted2.url);\n expect(await gteIterator.next()).toHaveProperty(\"done\", true);\n const gteIteratorEpsilon = graffiti.discover(object.channels, {\n properties: {\n lastModified: {\n minimum: putted2.lastModified + 0.1,\n },\n },\n });\n expect(await gteIteratorEpsilon.next()).toHaveProperty(\"done\", true);\n\n const ltIterator = graffiti.discover(object.channels, {\n properties: {\n lastModified: {\n exclusiveMaximum: putted1.lastModified,\n },\n },\n });\n expect(await ltIterator.next()).toHaveProperty(\"done\", true);\n\n const ltIteratorEpsilon = graffiti.discover(object.channels, {\n properties: {\n lastModified: {\n exclusiveMaximum: putted1.lastModified + 0.1,\n },\n },\n });\n const value3 = await nextStreamValue(ltIteratorEpsilon);\n expect(value3.url).toEqual(putted1.url);\n expect(await ltIteratorEpsilon.next()).toHaveProperty(\"done\", true);\n\n const lteIterator = graffiti.discover(object.channels, {\n properties: {\n lastModified: {\n maximum: putted1.lastModified,\n },\n },\n });\n const value2 = await nextStreamValue(lteIterator);\n expect(value2.url).toEqual(putted1.url);\n expect(await lteIterator.next()).toHaveProperty(\"done\", true);\n\n const lteIteratorEpsilon = graffiti.discover(object.channels, {\n properties: {\n lastModified: {\n maximum: putted1.lastModified - 0.1,\n },\n },\n });\n expect(await lteIteratorEpsilon.next()).toHaveProperty(\"done\", true);\n });\n\n it(\"discover schema allowed, as and not as owner\", async () => {\n const object = randomPutObject();\n object.allowed = [randomString(), session2.actor, randomString()];\n await graffiti.put<{}>(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: {\n enum: [session2.actor],\n },\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: {\n enum: [object.channels[0]],\n },\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: {\n enum: [session2.actor],\n },\n },\n },\n },\n },\n },\n session2,\n );\n const value2 = await nextStreamValue(iteratorSession2SmallAllowPeekSelf);\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 = randomPutObject();\n object.channels = [randomString(), randomString(), randomString()];\n await graffiti.put<{}>(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 session2.actor is in the allow list\n not: {\n items: {\n not: {\n enum: [object.channels[1]],\n },\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: {\n enum: [object.channels[1]],\n },\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: {\n enum: [object.channels[2]],\n },\n },\n },\n },\n },\n },\n session2,\n );\n const value2 = await nextStreamValue(iteratorSession2SmallAllowPeekSelf);\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 = randomPutObject();\n\n const publicSchema = {\n not: {\n required: [\"allowed\"],\n },\n } satisfies JSONSchema;\n\n await graffiti.put<{}>(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 = randomPutObject();\n restricted.allowed = [];\n await graffiti.put<{}>(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 = randomPutObject();\n object1.value = { test: randomString() };\n await graffiti.put<{}>(object1, session);\n\n const object2 = randomPutObject();\n object2.channels = object1.channels;\n object2.value = { test: randomString(), something: randomString() };\n await graffiti.put<{}>(object2, session);\n\n const object3 = randomPutObject();\n object3.channels = object1.channels;\n object3.value = { other: randomString(), something: randomString() };\n await graffiti.put<{}>(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.value.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 it(\"discover for deleted content\", async () => {\n const object = randomPutObject();\n\n const putted = await graffiti.put<{}>(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 const deleted = await graffiti.delete(putted, session);\n\n const iterator = graffiti.discover(object.channels, {});\n await expect(iterator.next()).resolves.toHaveProperty(\"done\", true);\n\n const tombIterator = returnValue.value.continue();\n const value = await tombIterator.next();\n assert(!value.done && !value.value.error, \"value is done\");\n expect(value.value.tombstone).toBe(true);\n expect(value.value.value.value).toEqual(object.value);\n expect(value.value.value.channels).toEqual(object.channels);\n expect(value.value.value.actor).toEqual(session.actor);\n expect(value.value.value.lastModified).toEqual(deleted.lastModified);\n await expect(tombIterator.next()).resolves.toHaveProperty(\"done\", true);\n });\n\n it(\"discover for replaced channels\", async () => {\n // Do this a bunch to check for concurrency issues\n for (let i = 0; i < 20; i++) {\n const object1 = randomPutObject();\n const putted = await graffiti.put<{}>(object1, session);\n\n const iterator3 = graffiti.discover(object1.channels, {});\n const value3 = await nextStreamValue(iterator3);\n expect(value3.value).toEqual(object1.value);\n const returnValue = await iterator3.next();\n assert(returnValue.done, \"value2 is not done\");\n\n const object2 = randomPutObject();\n const replaced = await graffiti.put<{}>(\n {\n ...object2,\n url: putted.url,\n },\n session,\n );\n\n const iterator1 = graffiti.discover(object1.channels, {});\n const iterator2 = graffiti.discover(object2.channels, {});\n const tombIterator = returnValue.value.continue();\n\n if (putted.lastModified === replaced.lastModified) {\n const value1 = await iterator1.next();\n const value2 = await iterator2.next();\n const value3 = await tombIterator.next();\n\n // Only one should be done\n expect(value1.done || value2.done).toBe(true);\n expect(value1.done && value2.done).toBe(false);\n\n assert(!value3.done && !value3.value.error, \"value is done\");\n expect(value3.value.tombstone || value2.done).toBe(true);\n expect(value3.value.tombstone && value2.done).toBe(false);\n continue;\n }\n\n // Otherwise 1 should be done and 2 should not\n await expect(iterator1.next()).resolves.toHaveProperty(\"done\", true);\n\n const value4 = await tombIterator.next();\n assert(!value4.done && !value4.value.error, \"value is done\");\n\n expect(value4.value.tombstone).toBe(true);\n expect(value4.value.value.value).toEqual(object1.value);\n expect(value4.value.value.channels).toEqual(object1.channels);\n expect(value4.value.value.lastModified).toEqual(replaced.lastModified);\n\n const value2 = await nextStreamValue(iterator2);\n await expect(iterator2.next()).resolves.toHaveProperty(\"done\", true);\n\n expect(value2.value).toEqual(object2.value);\n expect(value2.channels).toEqual(object2.channels);\n expect(value2.lastModified).toEqual(replaced.lastModified);\n }\n });\n\n it(\"discover for patched allowed\", async () => {\n const object = randomPutObject();\n const putted = await graffiti.put<{}>(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.patch(\n {\n allowed: [{ op: \"add\", path: \"\", value: [] }],\n },\n putted,\n session,\n );\n const iterator2 = graffiti.discover(object.channels, {});\n expect(await iterator2.next()).toHaveProperty(\"done\", true);\n\n const iterator = returnValue.value.continue();\n const value = await iterator.next();\n assert(!value.done && !value.value.error, \"value is done\");\n expect(value.value.tombstone).toBe(true);\n expect(value.value.value.value).toEqual(object.value);\n expect(value.value.value.channels).toEqual(object.channels);\n expect(value.value.value.allowed).toBeUndefined();\n await expect(iterator.next()).resolves.toHaveProperty(\"done\", true);\n });\n\n it(\"put concurrently and discover one\", async () => {\n const object = randomPutObject();\n\n // Put a first one to get a URI\n const putted = await graffiti.put<{}>(object, session);\n\n const putPromises = Array(99)\n .fill(0)\n .map(() =>\n graffiti.put<{}>(\n {\n ...object,\n url: putted.url,\n },\n session,\n ),\n );\n await Promise.all(putPromises);\n\n const iterator = graffiti.discover(object.channels, {});\n let tombstoneCount = 0;\n let valueCount = 0;\n for await (const result of iterator) {\n assert(!result.error, \"result has error\");\n if (result.tombstone) {\n tombstoneCount++;\n } else {\n valueCount++;\n }\n }\n expect(tombstoneCount).toBe(0);\n expect(valueCount).toBe(1);\n });\n });\n};\n", "import { it, expect, describe, assert, beforeAll } from \"vitest\";\nimport type { Graffiti, GraffitiSession } from \"@graffiti-garden/api\";\nimport { randomPutObject, randomString, nextStreamValue } from \"./utils\";\n\nexport const graffitiOrphanTests = (\n useGraffiti: () => Pick<\n Graffiti,\n \"recoverOrphans\" | \"put\" | \"delete\" | \"patch\"\n >,\n useSession1: () => GraffitiSession | Promise<GraffitiSession>,\n useSession2: () => GraffitiSession | Promise<GraffitiSession>,\n) => {\n describe(\"recoverOrphans\", { 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(\"list orphans\", async () => {\n const existingOrphans: string[] = [];\n const orphanIterator1 = graffiti.recoverOrphans({}, session);\n for await (const orphan of orphanIterator1) {\n if (orphan.error) continue;\n existingOrphans.push(orphan.value.url);\n }\n\n const object = randomPutObject();\n object.channels = [];\n const putted = await graffiti.put<{}>(object, session);\n const orphanIterator2 = graffiti.recoverOrphans({}, session);\n let numResults = 0;\n for await (const orphan of orphanIterator2) {\n if (orphan.error) continue;\n assert(!orphan.tombstone, \"orphan is tombstone\");\n if (orphan.value.url === putted.url) {\n numResults++;\n expect(orphan.value.lastModified).toBe(putted.lastModified);\n }\n }\n expect(numResults).toBe(1);\n });\n\n it(\"replaced orphan, no longer\", async () => {\n const object = randomPutObject();\n object.channels = [];\n const putOrphan = await graffiti.put<{}>(object, session);\n\n // Wait for the put to be processed\n await new Promise((resolve) => setTimeout(resolve, 10));\n\n expect(Object.keys(object.value).length).toBeGreaterThanOrEqual(1);\n expect(Object.keys(object.value)[0]).toBeTypeOf(\"string\");\n const iterator1 = graffiti.recoverOrphans(\n {\n properties: {\n value: {\n properties: {\n [Object.keys(object.value)[0]]: {\n type: \"string\",\n },\n },\n required: [Object.keys(object.value)[0]],\n },\n },\n },\n session,\n );\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 const putNotOrphan = await graffiti.put<{}>(\n {\n ...putOrphan,\n ...object,\n channels: [randomString()],\n },\n session,\n );\n expect(putNotOrphan.url).toBe(putOrphan.url);\n expect(putNotOrphan.lastModified).toBeGreaterThan(putOrphan.lastModified);\n\n // The tombstone will not appear to a fresh iterator\n const orphanIterator = graffiti.recoverOrphans({}, session);\n let numResults = 0;\n for await (const orphan of orphanIterator) {\n if (orphan.error) continue;\n if (orphan.value.url === putOrphan.url) {\n numResults++;\n }\n }\n expect(numResults).toBe(0);\n\n const iterator2 = returnValue.value.continue();\n const value2 = await iterator2.next();\n assert(\n !value2.done && !value2.value.error,\n \"value2 is done or has error\",\n );\n expect(value2.value.tombstone).toBe(true);\n expect(value2.value.value.lastModified).toBe(putNotOrphan.lastModified);\n expect(value2.value.value.channels).toEqual([]);\n await expect(iterator2.next()).resolves.toHaveProperty(\"done\", true);\n });\n });\n};\n", "import { it, expect, describe, assert, beforeAll } from \"vitest\";\nimport type { Graffiti, GraffitiSession } from \"@graffiti-garden/api\";\nimport { randomString } from \"./utils\";\n\nexport const graffitiChannelStatsTests = (\n useGraffiti: () => Pick<\n Graffiti,\n \"channelStats\" | \"put\" | \"delete\" | \"patch\"\n >,\n useSession1: () => GraffitiSession | Promise<GraffitiSession>,\n useSession2: () => GraffitiSession | Promise<GraffitiSession>,\n) => {\n describe(\"channel stats\", { 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(\"list channels\", async () => {\n const existingChannels: Map<string, number> = new Map();\n const channelIterator1 = graffiti.channelStats(session);\n for await (const channel of channelIterator1) {\n if (channel.error) continue;\n existingChannels.set(channel.value.channel, channel.value.count);\n }\n\n const channels = [randomString(), randomString(), randomString()];\n\n // Add one value to channels[0],\n // two values to both channels[0] and channels[1],\n // three values to all channels\n // one value to channels[2]\n for (let i = 0; i < 3; i++) {\n for (let j = 0; j < i + 1; j++) {\n await graffiti.put<{}>(\n {\n value: {\n index: j,\n },\n channels: channels.slice(0, i + 1),\n },\n session,\n );\n }\n }\n await graffiti.put<{}>(\n { value: { index: 3 }, channels: [channels[2]] },\n session,\n );\n\n const channelIterator2 = graffiti.channelStats(session);\n let newChannels: Map<string, number> = new Map();\n for await (const channel of channelIterator2) {\n if (channel.error) continue;\n newChannels.set(channel.value.channel, channel.value.count);\n }\n // Filter out existing channels\n newChannels = new Map(\n Array.from(newChannels).filter(\n ([channel, count]) => !existingChannels.has(channel),\n ),\n );\n expect(newChannels.size).toBe(3);\n expect(newChannels.get(channels[0])).toBe(6);\n expect(newChannels.get(channels[1])).toBe(5);\n expect(newChannels.get(channels[2])).toBe(4);\n });\n\n it(\"list channels with deleted channel\", async () => {\n const channels = [randomString(), randomString(), randomString()];\n\n // Add an item with two channels\n const before = await graffiti.put<{}>(\n {\n value: { index: 2 },\n channels: channels.slice(1),\n },\n session,\n );\n\n // Add an item with all channels\n const first = await graffiti.put<{}>(\n { value: { index: 0 }, channels },\n session,\n );\n // But then delete it\n await graffiti.delete(first, session);\n\n // Create a new object with only one channel\n const second = await graffiti.put<{}>(\n {\n value: { index: 1 },\n channels: channels.slice(2),\n },\n session,\n );\n\n const channelIterator = graffiti.channelStats(session);\n\n let got1 = 0;\n let got2 = 0;\n for await (const result of channelIterator) {\n if (result.error) continue;\n const { channel, count, lastModified } = result.value;\n assert(\n channel !== channels[0],\n \"There should not be an object in channel[0]\",\n );\n if (channel === channels[1]) {\n expect(count).toBe(1);\n expect(lastModified).toBe(before.lastModified);\n got1++;\n } else if (channel === channels[2]) {\n expect(count).toBe(2);\n expect(lastModified).toBe(second.lastModified);\n got2++;\n }\n }\n expect(got1).toBe(1);\n expect(got2).toBe(1);\n });\n });\n};\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { it, expect, describe, beforeAll } from \"vitest\";\nimport type {\n Graffiti,\n GraffitiSession,\n GraffitiPatch,\n JSONSchema,\n} from \"@graffiti-garden/api\";\nimport {\n GraffitiErrorNotFound,\n GraffitiErrorSchemaMismatch,\n GraffitiErrorInvalidSchema,\n GraffitiErrorForbidden,\n GraffitiErrorPatchTestFailed,\n GraffitiErrorPatchError,\n} from \"@graffiti-garden/api\";\nimport { randomPutObject, randomString } from \"./utils\";\n\nexport const graffitiCRUDTests = (\n useGraffiti: () => Pick<Graffiti, \"put\" | \"get\" | \"delete\" | \"patch\">,\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(\"put, get, delete\", async () => {\n const value = {\n something: \"hello, world~ c:\",\n };\n const channels = [randomString(), randomString()];\n\n // Put the object\n const previous = await graffiti.put<{}>({ value, channels }, session);\n expect(previous.value).toEqual({});\n expect(previous.channels).toEqual([]);\n expect(previous.allowed).toEqual([]);\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 expect(gotten.lastModified).toEqual(previous.lastModified);\n\n // Replace it\n const newValue = {\n something: \"goodbye, world~ :c\",\n };\n const beforeReplaced = await graffiti.put<{}>(\n {\n url: previous.url,\n value: newValue,\n channels: [],\n },\n session,\n );\n expect(beforeReplaced.value).toEqual(value);\n expect(beforeReplaced.url).toEqual(previous.url);\n expect(beforeReplaced.actor).toEqual(previous.actor);\n expect(beforeReplaced.lastModified).toBeGreaterThanOrEqual(\n gotten.lastModified,\n );\n\n // Get it again\n const afterReplaced = await graffiti.get(previous, {});\n expect(afterReplaced.value).toEqual(newValue);\n expect(afterReplaced.lastModified).toEqual(beforeReplaced.lastModified);\n\n // Delete it\n const beforeDeleted = await graffiti.delete(afterReplaced, session);\n expect(beforeDeleted.value).toEqual(newValue);\n expect(beforeDeleted.lastModified).toBeGreaterThanOrEqual(\n beforeReplaced.lastModified,\n );\n\n // Get is not found\n await expect(graffiti.get(afterReplaced, {})).rejects.toBeInstanceOf(\n GraffitiErrorNotFound,\n );\n\n // Delete it again\n await expect(graffiti.delete(beforeDeleted, session)).rejects.toThrow(\n GraffitiErrorNotFound,\n );\n\n // Try to re-put it\n await expect(\n graffiti.put(\n { url: beforeDeleted.url, value: {}, channels: [] },\n session,\n ),\n ).rejects.toThrow(GraffitiErrorNotFound);\n });\n\n it(\"put, delete, patch with wrong actor\", async () => {\n await expect(\n graffiti.put<{}>(\n { value: {}, channels: [], actor: session2.actor },\n session1,\n ),\n ).rejects.toThrow(GraffitiErrorForbidden);\n\n const putted = await graffiti.put<{}>(\n { value: {}, channels: [] },\n session2,\n );\n\n await expect(\n graffiti.put<{}>(\n {\n url: putted.url,\n value: {},\n channels: [],\n },\n session1,\n ),\n ).rejects.toThrow(GraffitiErrorForbidden);\n\n await expect(graffiti.delete(putted, session1)).rejects.toThrow(\n GraffitiErrorForbidden,\n );\n\n await expect(graffiti.patch({}, putted, session1)).rejects.toThrow(\n GraffitiErrorForbidden,\n );\n });\n\n it(\"put, patch, delete object that is not allowed\", async () => {\n const putted = await graffiti.put<{}>(\n {\n value: {},\n channels: [],\n allowed: [],\n },\n session1,\n );\n\n await expect(\n graffiti.put(\n {\n url: putted.url,\n value: {},\n channels: [],\n },\n session2,\n ),\n ).rejects.toThrow(GraffitiErrorNotFound);\n\n await expect(graffiti.patch({}, putted, session2)).rejects.toThrow(\n GraffitiErrorNotFound,\n );\n\n await expect(graffiti.delete(putted, session2)).rejects.toThrow(\n GraffitiErrorNotFound,\n );\n });\n\n it(\"put 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 putted = await graffiti.put<typeof schema>(\n {\n value: goodValue,\n channels: [],\n },\n session,\n );\n const gotten = await graffiti.get(putted, 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(\"put and get with invalid schema\", async () => {\n const putted = await graffiti.put<{}>(\n { value: {}, channels: [] },\n session,\n );\n await expect(\n graffiti.get(putted, {\n properties: {\n value: {\n //@ts-ignore\n type: \"asdf\",\n },\n },\n }),\n ).rejects.toThrow(GraffitiErrorInvalidSchema);\n });\n\n it(\"put and get with wrong schema\", async () => {\n const putted = await graffiti.put<{}>(\n {\n value: {\n hello: \"world\",\n },\n channels: [],\n },\n session,\n );\n\n await expect(\n graffiti.get(putted, {\n properties: {\n value: {\n properties: {\n hello: {\n type: \"number\",\n },\n },\n },\n },\n }),\n ).rejects.toThrow(GraffitiErrorSchemaMismatch);\n });\n\n it(\"put and get with empty access control\", async () => {\n const value = {\n um: \"hi\",\n };\n const allowed = [randomString()];\n const channels = [randomString()];\n const putted = await graffiti.put<{}>(\n { value, allowed, channels },\n session1,\n );\n\n // Get it with authenticated session\n const gotten = await graffiti.get(putted, {}, session1);\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(putted, {})).rejects.toBeInstanceOf(\n GraffitiErrorNotFound,\n );\n\n // Or the wrong session\n await expect(graffiti.get(putted, {}, session2)).rejects.toBeInstanceOf(\n GraffitiErrorNotFound,\n );\n });\n\n it(\"put 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 putted = await graffiti.put<{}>(\n {\n value,\n allowed,\n channels,\n },\n session1,\n );\n\n // Get it with authenticated session\n const gotten = await graffiti.get(putted, {}, session1);\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(putted, {})).rejects.toBeInstanceOf(\n GraffitiErrorNotFound,\n );\n\n const gotten2 = await graffiti.get(putted, {}, session2);\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 it(\"patch value\", async () => {\n const value = {\n something: \"hello, world~ c:\",\n };\n const putted = await graffiti.put<{}>({ value, channels: [] }, session);\n\n // Wait just a bit to make sure the lastModified is different\n await new Promise((resolve) => setTimeout(resolve, 10));\n\n const patch: GraffitiPatch = {\n value: [\n { op: \"replace\", path: \"/something\", value: \"goodbye, world~ :c\" },\n ],\n };\n const beforePatched = await graffiti.patch(patch, putted, session);\n expect(beforePatched.value).toEqual(value);\n expect(beforePatched.lastModified).toBeGreaterThan(putted.lastModified);\n\n const gotten = await graffiti.get(putted, {});\n expect(gotten.value).toEqual({\n something: \"goodbye, world~ :c\",\n });\n expect(beforePatched.lastModified).toBe(gotten.lastModified);\n\n await graffiti.delete(putted, session);\n });\n\n it(\"patch deleted object\", async () => {\n const putted = await graffiti.put<{}>(randomPutObject(), session);\n const deleted = await graffiti.delete(putted, session);\n await expect(\n graffiti.patch({}, putted, session),\n ).rejects.toBeInstanceOf(GraffitiErrorNotFound);\n });\n\n it(\"deep patch\", async () => {\n const value = {\n something: {\n another: {\n somethingElse: \"hello\",\n },\n },\n };\n const putted = await graffiti.put<{}>(\n { value: value, channels: [] },\n session,\n );\n\n const beforePatch = await graffiti.patch(\n {\n value: [\n {\n op: \"replace\",\n path: \"/something/another/somethingElse\",\n value: \"goodbye\",\n },\n ],\n },\n putted,\n session,\n );\n const gotten = await graffiti.get(putted, {});\n\n expect(beforePatch.value).toEqual(value);\n expect(gotten.value).toEqual({\n something: {\n another: {\n somethingElse: \"goodbye\",\n },\n },\n });\n });\n\n it(\"patch channels\", async () => {\n const channelsBefore = [randomString()];\n const channelsAfter = [randomString()];\n\n const putted = await graffiti.put<{}>(\n { value: {}, channels: channelsBefore },\n session,\n );\n\n const patch: GraffitiPatch = {\n channels: [{ op: \"replace\", path: \"/0\", value: channelsAfter[0] }],\n };\n const patched = await graffiti.patch(patch, putted, session);\n expect(patched.channels).toEqual(channelsBefore);\n const gotten = await graffiti.get(putted, {}, session);\n expect(gotten.channels).toEqual(channelsAfter);\n await graffiti.delete(putted, session);\n });\n\n it(\"patch 'increment' with test\", async () => {\n const putted = await graffiti.put<{}>(\n {\n value: {\n counter: 1,\n },\n channels: [],\n },\n session,\n );\n\n const previous = await graffiti.patch(\n {\n value: [\n { op: \"test\", path: \"/counter\", value: 1 },\n { op: \"replace\", path: \"/counter\", value: 2 },\n ],\n },\n putted,\n session,\n );\n expect(previous.value).toEqual({ counter: 1 });\n const result = await graffiti.get(previous, {\n properties: {\n value: {\n properties: {\n counter: {\n type: \"integer\",\n },\n },\n },\n },\n });\n expect(result.value.counter).toEqual(2);\n\n await expect(\n graffiti.patch(\n {\n value: [\n { op: \"test\", path: \"/counter\", value: 1 },\n { op: \"replace\", path: \"/counter\", value: 3 },\n ],\n },\n putted,\n session,\n ),\n ).rejects.toThrow(GraffitiErrorPatchTestFailed);\n });\n\n it(\"invalid patch\", async () => {\n const object = randomPutObject();\n const putted = await graffiti.put<{}>(object, session);\n\n await expect(\n graffiti.patch(\n {\n value: [\n { op: \"add\", path: \"/root\", value: [] },\n { op: \"add\", path: \"/root/2\", value: 2 }, // out of bounds\n ],\n },\n putted,\n session,\n ),\n ).rejects.toThrow(GraffitiErrorPatchError);\n });\n\n it(\"patch channels to be wrong\", async () => {\n const object = randomPutObject();\n object.allowed = [randomString()];\n const putted = await graffiti.put<{}>(object, session);\n\n const patches: GraffitiPatch[] = [\n {\n channels: [{ op: \"replace\", path: \"\", value: null }],\n },\n {\n channels: [{ op: \"replace\", path: \"\", value: {} }],\n },\n {\n channels: [{ op: \"replace\", path: \"\", value: [\"hello\", [\"hi\"]] }],\n },\n {\n channels: [{ op: \"add\", path: \"/0\", value: 1 }],\n },\n {\n value: [{ op: \"replace\", path: \"\", value: \"not an object\" }],\n },\n {\n value: [{ op: \"replace\", path: \"\", value: null }],\n },\n {\n value: [{ op: \"replace\", path: \"\", value: [] }],\n },\n {\n allowed: [{ op: \"replace\", path: \"\", value: {} }],\n },\n {\n allowed: [{ op: \"replace\", path: \"\", value: [\"hello\", [\"hi\"]] }],\n },\n ];\n\n for (const patch of patches) {\n await expect(graffiti.patch(patch, putted, session)).rejects.toThrow(\n GraffitiErrorPatchError,\n );\n }\n\n const gotten = await graffiti.get(putted, {}, session);\n expect(gotten.value).toEqual(object.value);\n expect(gotten.channels).toEqual(object.channels);\n expect(gotten.allowed).toEqual(object.allowed);\n expect(gotten.lastModified).toEqual(putted.lastModified);\n });\n },\n );\n};\n", "import { assert } from \"vitest\";\nimport type {\n GraffitiPutObject,\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 randomPutObject(): GraffitiPutObject<{}> {\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, \"continueObjectStream\">,\n streamReturn: GraffitiObjectStreamReturn<Schema>,\n type: \"cursor\" | \"continue\",\n session?: GraffitiSession | null,\n): GraffitiObjectStreamContinue<Schema> {\n if (type === \"cursor\") {\n return graffiti.continueObjectStream(\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 randomPutObject,\n continueStream,\n} from \"./utils\";\n\nexport const graffitiDiscoverTests = (\n useGraffiti: () => Pick<\n Graffiti,\n \"discover\" | \"put\" | \"delete\" | \"patch\" | \"continueObjectStream\"\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 = randomPutObject();\n\n const putted = await graffiti.put<{}>(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.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 expect(value.lastModified).toEqual(putted.lastModified);\n const result2 = await iterator.next();\n expect(result2.done).toBe(true);\n });\n\n it(\"discover wrong channel\", async () => {\n const object = randomPutObject();\n await graffiti.put<{}>(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 = randomPutObject();\n object.allowed = [randomString(), randomString()];\n const putted = await graffiti.put<{}>(object, session1);\n\n const iteratorSession1 = graffiti.discover<{}>(\n object.channels,\n {},\n session1,\n );\n const value = await nextStreamValue<{}>(iteratorSession1);\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 expect(value.lastModified).toEqual(putted.lastModified);\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 = randomPutObject();\n object.allowed = [randomString(), session2.actor, randomString()];\n const putted = await graffiti.put<{}>(object, session1);\n\n const iteratorSession2 = graffiti.discover<{}>(\n object.channels,\n {},\n session2,\n );\n const value = await nextStreamValue<{}>(iteratorSession2);\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 expect(value.lastModified).toEqual(putted.lastModified);\n });\n\n for (const prop of [\"actor\", \"lastModified\"] as const) {\n it(`discover for ${prop}`, async () => {\n const object1 = randomPutObject();\n const putted1 = await graffiti.put<{}>(object1, session1);\n\n const object2 = randomPutObject();\n object2.channels = object1.channels;\n // Make sure the lastModified is different for the query\n await new Promise((r) => setTimeout(r, 20));\n const putted2 = await graffiti.put<{}>(object2, session2);\n\n const iterator = graffiti.discover<{}>(object1.channels, {\n properties: {\n [prop]: {\n enum: [putted1[prop]],\n },\n },\n });\n\n const value = await nextStreamValue<{}>(iterator);\n expect(value.url).toEqual(putted1.url);\n expect(value.url).not.toEqual(putted2.url);\n expect(value.value).toEqual(object1.value);\n await expect(iterator.next()).resolves.toHaveProperty(\"done\", true);\n });\n }\n\n it(\"discover with lastModified range\", async () => {\n const object = randomPutObject();\n const putted1 = await graffiti.put<{}>(object, session);\n // Make sure the lastModified is different\n await new Promise((r) => setTimeout(r, 20));\n const putted2 = await graffiti.put<{}>(object, session);\n\n expect(putted1.url).not.toEqual(putted2.url);\n expect(putted1.lastModified).toBeLessThan(putted2.lastModified);\n\n const gtIterator = graffiti.discover([object.channels[0]], {\n properties: {\n lastModified: {\n exclusiveMinimum: putted2.lastModified,\n },\n },\n });\n expect(await gtIterator.next()).toHaveProperty(\"done\", true);\n const gtIteratorEpsilon = graffiti.discover<{}>([object.channels[0]], {\n properties: {\n lastModified: {\n exclusiveMinimum: putted2.lastModified - 0.1,\n },\n },\n });\n const value1 = await nextStreamValue<{}>(gtIteratorEpsilon);\n expect(value1.url).toEqual(putted2.url);\n expect(await gtIteratorEpsilon.next()).toHaveProperty(\"done\", true);\n const gteIterator = graffiti.discover<{}>(object.channels, {\n properties: {\n value: {},\n lastModified: {\n minimum: putted2.lastModified,\n },\n },\n });\n const value = await nextStreamValue<{}>(gteIterator);\n expect(value.url).toEqual(putted2.url);\n expect(await gteIterator.next()).toHaveProperty(\"done\", true);\n const gteIteratorEpsilon = graffiti.discover(object.channels, {\n properties: {\n lastModified: {\n minimum: putted2.lastModified + 0.1,\n },\n },\n });\n expect(await gteIteratorEpsilon.next()).toHaveProperty(\"done\", true);\n\n const ltIterator = graffiti.discover(object.channels, {\n properties: {\n lastModified: {\n exclusiveMaximum: putted1.lastModified,\n },\n },\n });\n expect(await ltIterator.next()).toHaveProperty(\"done\", true);\n\n const ltIteratorEpsilon = graffiti.discover<{}>(object.channels, {\n properties: {\n lastModified: {\n exclusiveMaximum: putted1.lastModified + 0.1,\n },\n },\n });\n const value3 = await nextStreamValue<{}>(ltIteratorEpsilon);\n expect(value3.url).toEqual(putted1.url);\n expect(await ltIteratorEpsilon.next()).toHaveProperty(\"done\", true);\n\n const lteIterator = graffiti.discover<{}>(object.channels, {\n properties: {\n lastModified: {\n maximum: putted1.lastModified,\n },\n },\n });\n const value2 = await nextStreamValue<{}>(lteIterator);\n expect(value2.url).toEqual(putted1.url);\n expect(await lteIterator.next()).toHaveProperty(\"done\", true);\n\n const lteIteratorEpsilon = graffiti.discover(object.channels, {\n properties: {\n lastModified: {\n maximum: putted1.lastModified - 0.1,\n },\n },\n });\n expect(await lteIteratorEpsilon.next()).toHaveProperty(\"done\", true);\n });\n\n it(\"discover schema allowed, as and not as owner\", async () => {\n const object = randomPutObject();\n object.allowed = [randomString(), session2.actor, randomString()];\n await graffiti.put<{}>(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: {\n enum: [session2.actor],\n },\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: {\n enum: [object.channels[0]],\n },\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: {\n enum: [session2.actor],\n },\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 = randomPutObject();\n object.channels = [randomString(), randomString(), randomString()];\n await graffiti.put<{}>(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 session2.actor is in the allow list\n not: {\n items: {\n not: {\n enum: [object.channels[1]],\n },\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: {\n enum: [object.channels[1]],\n },\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: {\n enum: [object.channels[2]],\n },\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 = randomPutObject();\n\n const publicSchema = {\n not: {\n required: [\"allowed\"],\n },\n } satisfies JSONSchema;\n\n await graffiti.put<{}>(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 = randomPutObject();\n restricted.allowed = [];\n await graffiti.put<{}>(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 = randomPutObject();\n object1.value = { test: randomString() };\n await graffiti.put<{}>(object1, session);\n\n const object2 = randomPutObject();\n object2.channels = object1.channels;\n object2.value = { test: randomString(), something: randomString() };\n await graffiti.put<{}>(object2, session);\n\n const object3 = randomPutObject();\n object3.channels = object1.channels;\n object3.value = { other: randomString(), something: randomString() };\n await graffiti.put<{}>(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 = randomPutObject();\n\n const putted = await graffiti.put<{}>(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 const deleted = await graffiti.delete(putted, 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(putted.url);\n await expect(tombIterator.next()).resolves.toHaveProperty(\n \"done\",\n true,\n );\n });\n\n it(\"discover for replaced channels\", async () => {\n // Do this a bunch to check for concurrency issues\n for (let i = 0; i < 20; i++) {\n const object1 = randomPutObject();\n const putted = await graffiti.put<{}>(object1, session);\n\n const iterator3 = graffiti.discover<{}>(object1.channels, {});\n const value3 = await nextStreamValue<{}>(iterator3);\n expect(value3.value).toEqual(object1.value);\n const returnValue = await iterator3.next();\n assert(returnValue.done, \"value2 is not done\");\n\n const object2 = randomPutObject();\n const replaced = await graffiti.put<{}>(\n {\n ...object2,\n url: putted.url,\n },\n session,\n );\n\n const iterator1 = graffiti.discover<{}>(object1.channels, {});\n const iterator2 = graffiti.discover<{}>(object2.channels, {});\n const tombIterator = continueStream<{}>(\n graffiti,\n returnValue.value,\n continueType,\n );\n\n if (putted.lastModified === replaced.lastModified) {\n const value1 = await iterator1.next();\n const value2 = await iterator2.next();\n const value3 = await tombIterator.next();\n\n // Only one should be done\n expect(value1.done || value2.done).toBe(true);\n expect(value1.done && value2.done).toBe(false);\n\n assert(!value3.done && !value3.value.error, \"value is done\");\n expect(value3.value.tombstone || value2.done).toBe(true);\n expect(value3.value.tombstone && value2.done).toBe(false);\n continue;\n }\n\n // Otherwise 1 should be done and 2 should not\n const value5 = await iterator1.next();\n assert(value5.done, \"value5 is not done\");\n\n const value4 = await tombIterator.next();\n assert(!value4.done && !value4.value.error, \"value is done\");\n\n assert(value4.value.tombstone, \"value is not tombstone\");\n expect(value4.value.object.url).toEqual(putted.url);\n expect(value4.value.object.lastModified).toEqual(\n replaced.lastModified,\n );\n\n const value2 = await nextStreamValue<{}>(iterator2);\n await expect(iterator2.next()).resolves.toHaveProperty(\n \"done\",\n true,\n );\n\n expect(value2.value).toEqual(object2.value);\n expect(value2.channels).toEqual(object2.channels);\n expect(value2.lastModified).toEqual(replaced.lastModified);\n\n // Replace the channels back\n const patched = await graffiti.patch(\n {\n channels: [\n { op: \"replace\", path: \"\", value: object1.channels },\n ],\n },\n replaced,\n session,\n );\n\n const tombIterator2 = continueStream<{}>(\n graffiti,\n value5.value,\n continueType,\n );\n\n let result:\n | {\n tombstone: true;\n object: {\n url: string;\n lastModified: number;\n };\n }\n | {\n tombstone?: undefined;\n object: GraffitiObjectBase;\n }\n | undefined;\n for await (const value of tombIterator2) {\n if (value.error) continue;\n if (!result) {\n result = value;\n continue;\n }\n if (\n value.object.lastModified > result.object.lastModified ||\n (value.object.lastModified === result.object.lastModified &&\n !value.tombstone &&\n result.tombstone)\n ) {\n result = value;\n }\n }\n\n assert(result, \"result is not defined\");\n assert(!result.tombstone, \"result is tombstone\");\n expect(result.object.url).toEqual(replaced.url);\n expect(result.object.lastModified).toEqual(patched.lastModified);\n expect(result.object.channels).toEqual(object1.channels);\n expect(result.object.value).toEqual(object2.value);\n }\n });\n\n it(\"discover for patched allowed\", async () => {\n const object = randomPutObject();\n const putted = await graffiti.put<{}>(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.patch(\n {\n allowed: [{ op: \"add\", path: \"\", value: [] }],\n },\n putted,\n session,\n );\n const iterator2 = graffiti.discover(object.channels, {});\n expect(await iterator2.next()).toHaveProperty(\"done\", true);\n\n const iterator = continueStream<{}>(\n graffiti,\n returnValue.value,\n continueType,\n );\n const value = await iterator.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(putted.url);\n await expect(iterator.next()).resolves.toHaveProperty(\"done\", true);\n });\n\n it(\"put concurrently and discover one\", async () => {\n const object = randomPutObject();\n\n // Put a first one to get a URI\n const putted = await graffiti.put<{}>(object, session);\n\n const putPromises = Array(99)\n .fill(0)\n .map(() =>\n graffiti.put<{}>(\n {\n ...object,\n url: putted.url,\n },\n session,\n ),\n );\n await Promise.all(putPromises);\n\n const iterator = graffiti.discover(object.channels, {});\n let tombstoneCount = 0;\n let valueCount = 0;\n for await (const result of iterator) {\n assert(!result.error, \"result has error\");\n if (result.tombstone) {\n tombstoneCount++;\n } else {\n valueCount++;\n }\n }\n expect(tombstoneCount).toBe(0);\n expect(valueCount).toBe(1);\n });\n });\n }\n });\n};\n", "import { it, expect, describe, assert, beforeAll } from \"vitest\";\nimport type { Graffiti, GraffitiSession } from \"@graffiti-garden/api\";\nimport {\n randomPutObject,\n randomString,\n nextStreamValue,\n continueStream,\n} from \"./utils\";\n\nexport const graffitiOrphanTests = (\n useGraffiti: () => Pick<\n Graffiti,\n \"recoverOrphans\" | \"put\" | \"delete\" | \"patch\" | \"continueObjectStream\"\n >,\n useSession1: () => GraffitiSession | Promise<GraffitiSession>,\n useSession2: () => GraffitiSession | Promise<GraffitiSession>,\n) => {\n describe(\"recoverOrphans\", { 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(\"list orphans\", async () => {\n const existingOrphans: string[] = [];\n const orphanIterator1 = graffiti.recoverOrphans({}, session);\n for await (const orphan of orphanIterator1) {\n if (orphan.error) continue;\n existingOrphans.push(orphan.object.url);\n }\n\n const object = randomPutObject();\n object.channels = [];\n const putted = await graffiti.put<{}>(object, session);\n const orphanIterator2 = graffiti.recoverOrphans({}, session);\n let numResults = 0;\n for await (const orphan of orphanIterator2) {\n if (orphan.error) continue;\n assert(!orphan.tombstone, \"orphan is tombstone\");\n if (orphan.object.url === putted.url) {\n numResults++;\n expect(orphan.object.lastModified).toBe(putted.lastModified);\n }\n }\n expect(numResults).toBe(1);\n });\n\n for (const continueType of [\"continue\", \"cursor\"] as const) {\n describe(`continue orphans with ${continueType}`, () => {\n it(\"replaced orphan, no longer\", async () => {\n const object = randomPutObject();\n object.channels = [];\n const putOrphan = await graffiti.put<{}>(object, session);\n\n // Wait for the put to be processed\n await new Promise((resolve) => setTimeout(resolve, 10));\n\n expect(Object.keys(object.value).length).toBeGreaterThanOrEqual(1);\n expect(Object.keys(object.value)[0]).toBeTypeOf(\"string\");\n const iterator1 = graffiti.recoverOrphans<{}>(\n {\n properties: {\n value: {\n properties: {\n [Object.keys(object.value)[0]]: {\n type: \"string\",\n },\n },\n required: [Object.keys(object.value)[0]],\n },\n },\n },\n session,\n );\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 const putNotOrphan = await graffiti.put<{}>(\n {\n ...putOrphan,\n ...object,\n channels: [randomString()],\n },\n session,\n );\n expect(putNotOrphan.url).toBe(putOrphan.url);\n expect(putNotOrphan.lastModified).toBeGreaterThan(\n putOrphan.lastModified,\n );\n\n // The tombstone will not appear to a fresh iterator\n const orphanIterator = graffiti.recoverOrphans({}, session);\n let numResults = 0;\n for await (const orphan of orphanIterator) {\n if (orphan.error) continue;\n if (orphan.object.url === putOrphan.url) {\n numResults++;\n }\n }\n expect(numResults).toBe(0);\n\n const iterator2 = continueStream<{}>(\n graffiti,\n returnValue.value,\n continueType,\n session,\n );\n const value2 = await iterator2.next();\n assert(\n !value2.done && !value2.value.error,\n \"value2 is done or has error\",\n );\n assert(value2.value.tombstone, \"value2 is not tombstone\");\n expect(value2.value.object.url).toBe(putOrphan.url);\n await expect(iterator2.next()).resolves.toHaveProperty(\"done\", true);\n });\n });\n }\n });\n};\n", "import { it, expect, describe, assert, beforeAll } from \"vitest\";\nimport type { Graffiti, GraffitiSession } from \"@graffiti-garden/api\";\nimport { randomString } from \"./utils\";\n\nexport const graffitiChannelStatsTests = (\n useGraffiti: () => Pick<\n Graffiti,\n \"channelStats\" | \"put\" | \"delete\" | \"patch\"\n >,\n useSession1: () => GraffitiSession | Promise<GraffitiSession>,\n useSession2: () => GraffitiSession | Promise<GraffitiSession>,\n) => {\n describe(\"channel stats\", { 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(\"list channels\", async () => {\n const existingChannels: Map<string, number> = new Map();\n const channelIterator1 = graffiti.channelStats(session);\n for await (const channel of channelIterator1) {\n if (channel.error) continue;\n existingChannels.set(channel.value.channel, channel.value.count);\n }\n\n const channels = [randomString(), randomString(), randomString()];\n\n // Add one value to channels[0],\n // two values to both channels[0] and channels[1],\n // three values to all channels\n // one value to channels[2]\n for (let i = 0; i < 3; i++) {\n for (let j = 0; j < i + 1; j++) {\n await graffiti.put<{}>(\n {\n value: {\n index: j,\n },\n channels: channels.slice(0, i + 1),\n },\n session,\n );\n }\n }\n await graffiti.put<{}>(\n { value: { index: 3 }, channels: [channels[2]] },\n session,\n );\n\n const channelIterator2 = graffiti.channelStats(session);\n let newChannels: Map<string, number> = new Map();\n for await (const channel of channelIterator2) {\n if (channel.error) continue;\n newChannels.set(channel.value.channel, channel.value.count);\n }\n // Filter out existing channels\n newChannels = new Map(\n Array.from(newChannels).filter(\n ([channel, count]) => !existingChannels.has(channel),\n ),\n );\n expect(newChannels.size).toBe(3);\n expect(newChannels.get(channels[0])).toBe(6);\n expect(newChannels.get(channels[1])).toBe(5);\n expect(newChannels.get(channels[2])).toBe(4);\n });\n\n it(\"list channels with deleted channel\", async () => {\n const channels = [randomString(), randomString(), randomString()];\n\n // Add an item with two channels\n const before = await graffiti.put<{}>(\n {\n value: { index: 2 },\n channels: channels.slice(1),\n },\n session,\n );\n\n // Add an item with all channels\n const first = await graffiti.put<{}>(\n { value: { index: 0 }, channels },\n session,\n );\n // But then delete it\n await graffiti.delete(first, session);\n\n // Create a new object with only one channel\n const second = await graffiti.put<{}>(\n {\n value: { index: 1 },\n channels: channels.slice(2),\n },\n session,\n );\n\n const channelIterator = graffiti.channelStats(session);\n\n let got1 = 0;\n let got2 = 0;\n for await (const result of channelIterator) {\n if (result.error) continue;\n const { channel, count, lastModified } = result.value;\n assert(\n channel !== channels[0],\n \"There should not be an object in channel[0]\",\n );\n if (channel === channels[1]) {\n expect(count).toBe(1);\n expect(lastModified).toBe(before.lastModified);\n got1++;\n } else if (channel === channels[2]) {\n expect(count).toBe(2);\n expect(lastModified).toBe(second.lastModified);\n got2++;\n }\n }\n expect(got1).toBe(1);\n expect(got2).toBe(1);\n });\n });\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["it", "expect", "describe", "assert", "beforeAll", "describe", "beforeAll", "it", "expect", "assert", "value2", "value3", "it", "expect", "describe", "assert", "beforeAll", "describe", "beforeAll", "it", "assert", "expect", "it", "expect", "describe", "assert", "beforeAll", "describe", "beforeAll", "it", "expect", "assert"]
|
|
7
7
|
}
|
package/package.json
CHANGED
package/src/1-api.ts
CHANGED
|
@@ -5,8 +5,10 @@ import type {
|
|
|
5
5
|
GraffitiPatch,
|
|
6
6
|
GraffitiSession,
|
|
7
7
|
GraffitiPutObject,
|
|
8
|
-
|
|
8
|
+
GraffitiObjectStream,
|
|
9
9
|
ChannelStats,
|
|
10
|
+
GraffitiChannelStatsStream,
|
|
11
|
+
GraffitiObjectStreamContinue,
|
|
10
12
|
} from "./2-types";
|
|
11
13
|
import type { JSONSchema } from "json-schema-to-ts";
|
|
12
14
|
|
|
@@ -302,7 +304,13 @@ export abstract class Graffiti {
|
|
|
302
304
|
* The deleting {@link GraffitiObjectBase.actor | `actor`} must be the same as the
|
|
303
305
|
* `actor` that created the object.
|
|
304
306
|
*
|
|
305
|
-
* @
|
|
307
|
+
* It is not possible to re-{@link put} an object that has been deleted
|
|
308
|
+
* to ensure a user's [right to be forgotten](https://en.wikipedia.org/wiki/Right_to_be_forgotten).
|
|
309
|
+
* In cases where deleting and restoring an object is useful, an object's
|
|
310
|
+
* {@link GraffitiObjectBase.allowed | `allowed`} property can be set to
|
|
311
|
+
* an empty list to hide it from all users except the creator.
|
|
312
|
+
*
|
|
313
|
+
* @returns The object that was deleted with its
|
|
306
314
|
* {@link GraffitiObjectBase.lastModified | `lastModified`}
|
|
307
315
|
* property updated to the time of deletion.
|
|
308
316
|
*
|
|
@@ -333,21 +341,22 @@ export abstract class Graffiti {
|
|
|
333
341
|
*
|
|
334
342
|
* Objects are returned asynchronously as they are discovered but the stream
|
|
335
343
|
* will end once all leads have been exhausted.
|
|
336
|
-
* The {@link
|
|
337
|
-
*
|
|
338
|
-
*
|
|
344
|
+
* The {@link GraffitiObjectStream} ends by returning a
|
|
345
|
+
* {@link GraffitiObjectStreamReturn.continue | `continue`} method and a
|
|
346
|
+
* {@link GraffitiObjectStreamReturn.cursor | `cursor`} string,
|
|
347
|
+
* each of which can be be used to poll for new objects.
|
|
348
|
+
* The `continue` method preserves the type safety of the stream and the `cursor`
|
|
339
349
|
* string can be serialized to continue the stream after an application is closed
|
|
340
350
|
* and reopened.
|
|
341
|
-
* See the {@link continueStream} method for more information on continuing a stream.
|
|
342
351
|
*
|
|
343
352
|
* `discover` will not return objects that the {@link GraffitiObjectBase.actor | `actor`}
|
|
344
353
|
* is not {@link GraffitiObjectBase.allowed | `allowed`} to access.
|
|
345
|
-
* If the actor is not the creator of a discovered object,
|
|
354
|
+
* If the `actor` is not the creator of a discovered object,
|
|
346
355
|
* the allowed list will be masked to only contain the querying actor if the
|
|
347
356
|
* allowed list is not `undefined` (public). Additionally, if the actor is not the
|
|
348
357
|
* creator of a discovered object, any {@link GraffitiObjectBase.channels | `channels`}
|
|
349
358
|
* not specified by the `discover` method will not be revealed. This masking happens
|
|
350
|
-
* before the supplied schema
|
|
359
|
+
* before the object is validated against the supplied `schema`.
|
|
351
360
|
*
|
|
352
361
|
* Since different implementations may fetch data from multiple sources there is
|
|
353
362
|
* no guarentee on the order that objects are returned in.
|
|
@@ -376,7 +385,7 @@ export abstract class Graffiti {
|
|
|
376
385
|
* property will be returned.
|
|
377
386
|
*/
|
|
378
387
|
session?: GraffitiSession | null,
|
|
379
|
-
):
|
|
388
|
+
): GraffitiObjectStream<Schema>;
|
|
380
389
|
|
|
381
390
|
/**
|
|
382
391
|
* Discovers objects **not** contained in any
|
|
@@ -391,7 +400,8 @@ export abstract class Graffiti {
|
|
|
391
400
|
*
|
|
392
401
|
* Like {@link discover}, objects are returned asynchronously as they are discovered,
|
|
393
402
|
* the stream will end once all leads have been exhausted, and the stream
|
|
394
|
-
* can be continued using the
|
|
403
|
+
* can be continued using the {@link GraffitiObjectStreamReturn.continue | `continue`}
|
|
404
|
+
* method or {@link GraffitiObjectStreamReturn.cursor | `cursor`} string.
|
|
395
405
|
*
|
|
396
406
|
* @returns A stream of objects created by the querying {@link GraffitiObjectBase.actor | `actor`}
|
|
397
407
|
* that do not belong to any {@link GraffitiObjectBase.channels | `channels`}
|
|
@@ -409,7 +419,7 @@ export abstract class Graffiti {
|
|
|
409
419
|
* {@link GraffitiObjectBase.actor | `actor`}.
|
|
410
420
|
*/
|
|
411
421
|
session: GraffitiSession,
|
|
412
|
-
):
|
|
422
|
+
): GraffitiObjectStream<Schema>;
|
|
413
423
|
|
|
414
424
|
/**
|
|
415
425
|
* Returns statistics about all the {@link GraffitiObjectBase.channels | `channels`}
|
|
@@ -418,10 +428,9 @@ export abstract class Graffiti {
|
|
|
418
428
|
* necessary for certain applications where a user wants a
|
|
419
429
|
* global view of all their Graffiti data or to debug
|
|
420
430
|
* channel usage.
|
|
421
|
-
|
|
431
|
+
*
|
|
422
432
|
* Like {@link discover}, objects are returned asynchronously as they are discovered,
|
|
423
|
-
|
|
424
|
-
* can be continued using the `continue` method or `cursor` string.
|
|
433
|
+
* the stream will end once all leads have been exhausted.
|
|
425
434
|
*
|
|
426
435
|
* @group Query Methods
|
|
427
436
|
*
|
|
@@ -434,13 +443,15 @@ export abstract class Graffiti {
|
|
|
434
443
|
* {@link GraffitiObjectBase.actor | `actor`}.
|
|
435
444
|
*/
|
|
436
445
|
session: GraffitiSession,
|
|
437
|
-
):
|
|
446
|
+
): GraffitiChannelStatsStream;
|
|
438
447
|
|
|
439
448
|
/**
|
|
440
|
-
* Continues a {@link
|
|
449
|
+
* Continues a {@link GraffitiObjectStream} from a given
|
|
450
|
+
* {@link GraffitiObjectStreamReturn.cursor | `cursor`} string.
|
|
441
451
|
* The continuation will return new objects that have been created
|
|
442
|
-
* that match the original stream, and also
|
|
443
|
-
*
|
|
452
|
+
* that match the original stream, and also returns the
|
|
453
|
+
* {@link GraffitiObjectBase.url | `url`}s of objects that
|
|
454
|
+
* have been deleted, as marked by a `tombstone`.
|
|
444
455
|
*
|
|
445
456
|
* The continuation may also include duplicates of objects that
|
|
446
457
|
* were already returned by the original stream. This is dependent
|
|
@@ -449,8 +460,10 @@ export abstract class Graffiti {
|
|
|
449
460
|
* The `cursor` allows the client to
|
|
450
461
|
* serialize the state of the stream and continue it later.
|
|
451
462
|
* However this method loses any typing information that was
|
|
452
|
-
* present in the original stream.
|
|
453
|
-
*
|
|
463
|
+
* present in the original stream. For better type safety
|
|
464
|
+
* and when serializing is not necessary, use the
|
|
465
|
+
* {@link GraffitiObjectStreamReturn.continue | `continue`} method
|
|
466
|
+
* instead, which is returned along with the `cursor` at the
|
|
454
467
|
* end of the original stream.
|
|
455
468
|
*
|
|
456
469
|
* @throws {@link GraffitiErrorForbidden} if the {@link GraffitiObjectBase.actor | `actor`}
|
|
@@ -459,10 +472,10 @@ export abstract class Graffiti {
|
|
|
459
472
|
*
|
|
460
473
|
* @group Query Methods
|
|
461
474
|
*/
|
|
462
|
-
abstract
|
|
475
|
+
abstract continueObjectStream(
|
|
463
476
|
cursor: string,
|
|
464
477
|
session?: GraffitiSession | null,
|
|
465
|
-
):
|
|
478
|
+
): GraffitiObjectStreamContinue<{}>;
|
|
466
479
|
|
|
467
480
|
/**
|
|
468
481
|
* Begins the login process. Depending on the implementation, this may
|