@graffiti-garden/api 0.2.10 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +2 -2
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +2 -2
- package/dist/src/1-api.d.ts +1 -164
- package/dist/src/1-api.d.ts.map +1 -1
- package/dist/tests/index.d.ts +1 -1
- package/dist/tests/index.d.ts.map +1 -1
- package/dist/tests.mjs +139 -414
- package/dist/tests.mjs.map +4 -4
- package/package.json +3 -3
- package/src/1-api.ts +1 -171
- package/tests/index.ts +1 -1
- package/dist/tests/synchronize.d.ts +0 -3
- package/dist/tests/synchronize.d.ts.map +0 -1
- package/tests/synchronize.ts +0 -354
package/tests/index.ts
CHANGED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import type { GraffitiFactory, GraffitiSession } from "@graffiti-garden/api";
|
|
2
|
-
export declare const graffitiSynchronizeTests: (useGraffiti: GraffitiFactory, useSession1: () => GraffitiSession | Promise<GraffitiSession>, useSession2: () => GraffitiSession | Promise<GraffitiSession>) => void;
|
|
3
|
-
//# sourceMappingURL=synchronize.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"synchronize.d.ts","sourceRoot":"","sources":["../../tests/synchronize.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAG7E,eAAO,MAAM,wBAAwB,gBACtB,eAAe,eACf,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,eAChD,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,SA0V9D,CAAC"}
|
package/tests/synchronize.ts
DELETED
|
@@ -1,354 +0,0 @@
|
|
|
1
|
-
import { it, expect, describe, assert, beforeAll } from "vitest";
|
|
2
|
-
import type { GraffitiFactory, GraffitiSession } from "@graffiti-garden/api";
|
|
3
|
-
import { randomPutObject, randomString } from "./utils";
|
|
4
|
-
|
|
5
|
-
export const graffitiSynchronizeTests = (
|
|
6
|
-
useGraffiti: GraffitiFactory,
|
|
7
|
-
useSession1: () => GraffitiSession | Promise<GraffitiSession>,
|
|
8
|
-
useSession2: () => GraffitiSession | Promise<GraffitiSession>,
|
|
9
|
-
) => {
|
|
10
|
-
describe.concurrent("synchronizeDiscover", () => {
|
|
11
|
-
let graffiti: ReturnType<typeof useGraffiti>;
|
|
12
|
-
let session: GraffitiSession;
|
|
13
|
-
let session1: GraffitiSession;
|
|
14
|
-
let session2: GraffitiSession;
|
|
15
|
-
beforeAll(async () => {
|
|
16
|
-
graffiti = useGraffiti();
|
|
17
|
-
session1 = await useSession1();
|
|
18
|
-
session = session1;
|
|
19
|
-
session2 = await useSession2();
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it("get", async () => {
|
|
23
|
-
const graffiti1 = useGraffiti();
|
|
24
|
-
|
|
25
|
-
const object = randomPutObject();
|
|
26
|
-
const channels = object.channels.slice(1);
|
|
27
|
-
const putted = await graffiti1.put(object, session);
|
|
28
|
-
|
|
29
|
-
const graffiti2 = useGraffiti();
|
|
30
|
-
const next = graffiti2.synchronizeDiscover(channels, {}).next();
|
|
31
|
-
const gotten = await graffiti2.get(putted, {}, session);
|
|
32
|
-
|
|
33
|
-
const result = (await next).value;
|
|
34
|
-
if (!result || result.error) {
|
|
35
|
-
throw new Error("Error in synchronize");
|
|
36
|
-
}
|
|
37
|
-
expect(result.value.value).toEqual(object.value);
|
|
38
|
-
expect(result.value.channels).toEqual(channels);
|
|
39
|
-
expect(result.value.tombstone).toBe(false);
|
|
40
|
-
expect(result.value.lastModified).toEqual(gotten.lastModified);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it("put", async () => {
|
|
44
|
-
const beforeChannel = randomString();
|
|
45
|
-
const afterChannel = randomString();
|
|
46
|
-
const sharedChannel = randomString();
|
|
47
|
-
|
|
48
|
-
const oldValue = { hello: "world" };
|
|
49
|
-
const oldChannels = [beforeChannel, sharedChannel];
|
|
50
|
-
const putted = await graffiti.put(
|
|
51
|
-
{
|
|
52
|
-
value: oldValue,
|
|
53
|
-
channels: oldChannels,
|
|
54
|
-
},
|
|
55
|
-
session,
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
// Start listening for changes...
|
|
59
|
-
const before = graffiti.synchronizeDiscover([beforeChannel], {}).next();
|
|
60
|
-
const after = graffiti.synchronizeDiscover([afterChannel], {}).next();
|
|
61
|
-
const shared = graffiti.synchronizeDiscover([sharedChannel], {}).next();
|
|
62
|
-
|
|
63
|
-
// Replace the object
|
|
64
|
-
const newValue = { goodbye: "world" };
|
|
65
|
-
const newChannels = [afterChannel, sharedChannel];
|
|
66
|
-
await graffiti.put(
|
|
67
|
-
{
|
|
68
|
-
...putted,
|
|
69
|
-
value: newValue,
|
|
70
|
-
channels: newChannels,
|
|
71
|
-
},
|
|
72
|
-
session,
|
|
73
|
-
);
|
|
74
|
-
|
|
75
|
-
const beforeResult = (await before).value;
|
|
76
|
-
const afterResult = (await after).value;
|
|
77
|
-
const sharedResult = (await shared).value;
|
|
78
|
-
if (
|
|
79
|
-
!beforeResult ||
|
|
80
|
-
beforeResult.error ||
|
|
81
|
-
!afterResult ||
|
|
82
|
-
afterResult.error ||
|
|
83
|
-
!sharedResult ||
|
|
84
|
-
sharedResult.error
|
|
85
|
-
) {
|
|
86
|
-
throw new Error("Error in synchronize");
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
expect(beforeResult.value.value).toEqual(oldValue);
|
|
90
|
-
expect(beforeResult.value.channels).toEqual([beforeChannel]);
|
|
91
|
-
expect(beforeResult.value.tombstone).toBe(true);
|
|
92
|
-
expect(afterResult.value.value).toEqual(newValue);
|
|
93
|
-
expect(afterResult.value.channels).toEqual([afterChannel]);
|
|
94
|
-
expect(afterResult.value.tombstone).toBe(false);
|
|
95
|
-
expect(sharedResult.value.value).toEqual(newValue);
|
|
96
|
-
expect(sharedResult.value.channels).toEqual([sharedChannel]);
|
|
97
|
-
expect(sharedResult.value.tombstone).toBe(false);
|
|
98
|
-
expect(beforeResult.value.lastModified).toEqual(
|
|
99
|
-
afterResult.value.lastModified,
|
|
100
|
-
);
|
|
101
|
-
expect(sharedResult.value.lastModified).toEqual(
|
|
102
|
-
afterResult.value.lastModified,
|
|
103
|
-
);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it("patch", async () => {
|
|
107
|
-
const beforeChannel = randomString();
|
|
108
|
-
const afterChannel = randomString();
|
|
109
|
-
const sharedChannel = randomString();
|
|
110
|
-
|
|
111
|
-
const oldValue = { hello: "world" };
|
|
112
|
-
const oldChannels = [beforeChannel, sharedChannel];
|
|
113
|
-
const putted = await graffiti.put(
|
|
114
|
-
{
|
|
115
|
-
value: oldValue,
|
|
116
|
-
channels: oldChannels,
|
|
117
|
-
},
|
|
118
|
-
session,
|
|
119
|
-
);
|
|
120
|
-
|
|
121
|
-
// Start listening for changes...
|
|
122
|
-
const before = graffiti.synchronizeDiscover([beforeChannel], {}).next();
|
|
123
|
-
const after = graffiti.synchronizeDiscover([afterChannel], {}).next();
|
|
124
|
-
const shared = graffiti.synchronizeDiscover([sharedChannel], {}).next();
|
|
125
|
-
|
|
126
|
-
await graffiti.patch(
|
|
127
|
-
{
|
|
128
|
-
value: [
|
|
129
|
-
{
|
|
130
|
-
op: "add",
|
|
131
|
-
path: "/something",
|
|
132
|
-
value: "new value",
|
|
133
|
-
},
|
|
134
|
-
],
|
|
135
|
-
channels: [
|
|
136
|
-
{
|
|
137
|
-
op: "add",
|
|
138
|
-
path: "/-",
|
|
139
|
-
value: afterChannel,
|
|
140
|
-
},
|
|
141
|
-
{
|
|
142
|
-
op: "remove",
|
|
143
|
-
path: `/${oldChannels.indexOf(beforeChannel)}`,
|
|
144
|
-
},
|
|
145
|
-
],
|
|
146
|
-
},
|
|
147
|
-
putted,
|
|
148
|
-
session,
|
|
149
|
-
);
|
|
150
|
-
|
|
151
|
-
const beforeResult = (await before).value;
|
|
152
|
-
const afterResult = (await after).value;
|
|
153
|
-
const sharedResult = (await shared).value;
|
|
154
|
-
if (
|
|
155
|
-
!beforeResult ||
|
|
156
|
-
beforeResult.error ||
|
|
157
|
-
!afterResult ||
|
|
158
|
-
afterResult.error ||
|
|
159
|
-
!sharedResult ||
|
|
160
|
-
sharedResult.error
|
|
161
|
-
) {
|
|
162
|
-
throw new Error("Error in synchronize");
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const newValue = { ...oldValue, something: "new value" };
|
|
166
|
-
const newChannels = [sharedChannel, afterChannel];
|
|
167
|
-
expect(beforeResult.value.value).toEqual(oldValue);
|
|
168
|
-
expect(beforeResult.value.channels).toEqual([beforeChannel]);
|
|
169
|
-
expect(beforeResult.value.tombstone).toBe(true);
|
|
170
|
-
expect(afterResult.value.value).toEqual(newValue);
|
|
171
|
-
expect(afterResult.value.channels).toEqual([afterChannel]);
|
|
172
|
-
expect(afterResult.value.tombstone).toBe(false);
|
|
173
|
-
expect(sharedResult.value.value).toEqual(newValue);
|
|
174
|
-
expect(sharedResult.value.channels).toEqual([sharedChannel]);
|
|
175
|
-
expect(sharedResult.value.tombstone).toBe(false);
|
|
176
|
-
expect(beforeResult.value.lastModified).toEqual(
|
|
177
|
-
afterResult.value.lastModified,
|
|
178
|
-
);
|
|
179
|
-
expect(sharedResult.value.lastModified).toEqual(
|
|
180
|
-
afterResult.value.lastModified,
|
|
181
|
-
);
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
it("delete", async () => {
|
|
185
|
-
const channels = [randomString(), randomString(), randomString()];
|
|
186
|
-
|
|
187
|
-
const oldValue = { hello: "world" };
|
|
188
|
-
const oldChannels = [randomString(), ...channels.slice(1)];
|
|
189
|
-
const putted = await graffiti.put(
|
|
190
|
-
{
|
|
191
|
-
value: oldValue,
|
|
192
|
-
channels: oldChannels,
|
|
193
|
-
},
|
|
194
|
-
session,
|
|
195
|
-
);
|
|
196
|
-
|
|
197
|
-
const next = graffiti.synchronizeDiscover(channels, {}).next();
|
|
198
|
-
|
|
199
|
-
graffiti.delete(putted, session);
|
|
200
|
-
|
|
201
|
-
const result = (await next).value;
|
|
202
|
-
if (!result || result.error) {
|
|
203
|
-
throw new Error("Error in synchronize");
|
|
204
|
-
}
|
|
205
|
-
expect(result.value.tombstone).toBe(true);
|
|
206
|
-
expect(result.value.value).toEqual(oldValue);
|
|
207
|
-
expect(result.value.channels).toEqual(
|
|
208
|
-
channels.filter((c) => oldChannels.includes(c)),
|
|
209
|
-
);
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
it("not allowed", async () => {
|
|
213
|
-
const allChannels = [randomString(), randomString(), randomString()];
|
|
214
|
-
const channels = allChannels.slice(1);
|
|
215
|
-
|
|
216
|
-
const creatorNext = graffiti
|
|
217
|
-
.synchronizeDiscover(channels, {}, session1)
|
|
218
|
-
.next();
|
|
219
|
-
const allowedNext = graffiti
|
|
220
|
-
.synchronizeDiscover(channels, {}, session2)
|
|
221
|
-
.next();
|
|
222
|
-
const noSession = graffiti.synchronizeDiscover(channels, {}).next();
|
|
223
|
-
|
|
224
|
-
const value = {
|
|
225
|
-
hello: "world",
|
|
226
|
-
};
|
|
227
|
-
const allowed = [randomString(), session2.actor];
|
|
228
|
-
await graffiti.put({ value, channels: allChannels, allowed }, session1);
|
|
229
|
-
|
|
230
|
-
// Expect no session to time out!
|
|
231
|
-
await expect(
|
|
232
|
-
Promise.race([
|
|
233
|
-
noSession,
|
|
234
|
-
new Promise((resolve, rejects) =>
|
|
235
|
-
setTimeout(rejects, 100, "Timeout"),
|
|
236
|
-
),
|
|
237
|
-
]),
|
|
238
|
-
).rejects.toThrow("Timeout");
|
|
239
|
-
|
|
240
|
-
const creatorResult = (await creatorNext).value;
|
|
241
|
-
const allowedResult = (await allowedNext).value;
|
|
242
|
-
|
|
243
|
-
if (
|
|
244
|
-
!creatorResult ||
|
|
245
|
-
creatorResult.error ||
|
|
246
|
-
!allowedResult ||
|
|
247
|
-
allowedResult.error
|
|
248
|
-
) {
|
|
249
|
-
throw new Error("Error in synchronize");
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
expect(creatorResult.value.value).toEqual(value);
|
|
253
|
-
expect(creatorResult.value.allowed).toEqual(allowed);
|
|
254
|
-
expect(creatorResult.value.channels).toEqual(allChannels);
|
|
255
|
-
expect(allowedResult.value.value).toEqual(value);
|
|
256
|
-
expect(allowedResult.value.allowed).toEqual([session2.actor]);
|
|
257
|
-
expect(allowedResult.value.channels).toEqual(channels);
|
|
258
|
-
});
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
describe.concurrent("synchronizeGet", () => {
|
|
262
|
-
let graffiti: ReturnType<typeof useGraffiti>;
|
|
263
|
-
let session: GraffitiSession;
|
|
264
|
-
let session1: GraffitiSession;
|
|
265
|
-
let session2: GraffitiSession;
|
|
266
|
-
beforeAll(async () => {
|
|
267
|
-
graffiti = useGraffiti();
|
|
268
|
-
session1 = await useSession1();
|
|
269
|
-
session = session1;
|
|
270
|
-
session2 = await useSession2();
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
it("replace, delete", async () => {
|
|
274
|
-
const object = randomPutObject();
|
|
275
|
-
const putted = await graffiti.put(object, session);
|
|
276
|
-
|
|
277
|
-
const iterator = graffiti.synchronizeGet(putted, {});
|
|
278
|
-
const next = iterator.next();
|
|
279
|
-
|
|
280
|
-
// Change the object
|
|
281
|
-
const newValue = { goodbye: "world" };
|
|
282
|
-
const putted2 = await graffiti.put(
|
|
283
|
-
{
|
|
284
|
-
...putted,
|
|
285
|
-
value: newValue,
|
|
286
|
-
},
|
|
287
|
-
session,
|
|
288
|
-
);
|
|
289
|
-
|
|
290
|
-
const result = (await next).value;
|
|
291
|
-
assert(result && !result.error);
|
|
292
|
-
|
|
293
|
-
expect(result.value.value).toEqual(newValue);
|
|
294
|
-
expect(result.value.actor).toEqual(session.actor);
|
|
295
|
-
expect(result.value.channels).toEqual([]);
|
|
296
|
-
expect(result.value.tombstone).toBe(false);
|
|
297
|
-
expect(result.value.lastModified).toEqual(putted2.lastModified);
|
|
298
|
-
expect(result.value.allowed).toBeUndefined();
|
|
299
|
-
|
|
300
|
-
// Delete the object
|
|
301
|
-
const deleted = await graffiti.delete(putted2, session);
|
|
302
|
-
const result2 = (await iterator.next()).value;
|
|
303
|
-
assert(result2 && !result2.error);
|
|
304
|
-
expect(result2.value.tombstone).toBe(true);
|
|
305
|
-
expect(result2.value.lastModified).toEqual(deleted.lastModified);
|
|
306
|
-
|
|
307
|
-
// Put something else
|
|
308
|
-
await graffiti.put(randomPutObject(), session);
|
|
309
|
-
await expect(
|
|
310
|
-
Promise.race([
|
|
311
|
-
iterator.next(),
|
|
312
|
-
new Promise((resolve, reject) => setTimeout(reject, 100, "Timeout")),
|
|
313
|
-
]),
|
|
314
|
-
).rejects.toThrow("Timeout");
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
it("not allowed", async () => {
|
|
318
|
-
const object = randomPutObject();
|
|
319
|
-
const putted = await graffiti.put(object, session1);
|
|
320
|
-
|
|
321
|
-
const iterator1 = graffiti.synchronizeGet(putted, {}, session1);
|
|
322
|
-
const iterator2 = graffiti.synchronizeGet(putted, {}, session2);
|
|
323
|
-
|
|
324
|
-
const next1 = iterator1.next();
|
|
325
|
-
const next2 = iterator2.next();
|
|
326
|
-
|
|
327
|
-
const newValue = { goodbye: "world" };
|
|
328
|
-
const putted2 = await graffiti.put(
|
|
329
|
-
{
|
|
330
|
-
...putted,
|
|
331
|
-
...object,
|
|
332
|
-
allowed: [],
|
|
333
|
-
value: newValue,
|
|
334
|
-
},
|
|
335
|
-
session1,
|
|
336
|
-
);
|
|
337
|
-
const result1 = (await next1).value;
|
|
338
|
-
const result2 = (await next2).value;
|
|
339
|
-
assert(result1 && !result1.error);
|
|
340
|
-
assert(result2 && !result2.error);
|
|
341
|
-
|
|
342
|
-
expect(result1.value.value).toEqual(newValue);
|
|
343
|
-
expect(result2.value.value).toEqual(object.value);
|
|
344
|
-
expect(result1.value.actor).toEqual(session1.actor);
|
|
345
|
-
expect(result2.value.actor).toEqual(session1.actor);
|
|
346
|
-
expect(result1.value.channels).toEqual(object.channels);
|
|
347
|
-
expect(result2.value.channels).toEqual([]);
|
|
348
|
-
expect(result1.value.tombstone).toBe(false);
|
|
349
|
-
expect(result2.value.tombstone).toBe(true);
|
|
350
|
-
expect(result1.value.lastModified).toEqual(putted2.lastModified);
|
|
351
|
-
expect(result2.value.lastModified).toEqual(putted2.lastModified);
|
|
352
|
-
});
|
|
353
|
-
});
|
|
354
|
-
};
|