cojson 0.1.7 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/account.d.ts +4 -2
  2. package/dist/account.js +4 -2
  3. package/dist/account.js.map +1 -1
  4. package/dist/coValue.d.ts +44 -81
  5. package/dist/coValue.js +4 -348
  6. package/dist/coValue.js.map +1 -1
  7. package/dist/coValueCore.d.ts +84 -0
  8. package/dist/coValueCore.js +351 -0
  9. package/dist/coValueCore.js.map +1 -0
  10. package/dist/coValues/coList.d.ts +113 -0
  11. package/dist/{contentTypes → coValues}/coList.js +59 -19
  12. package/dist/coValues/coList.js.map +1 -0
  13. package/dist/{contentTypes → coValues}/coMap.d.ts +25 -7
  14. package/dist/{contentTypes → coValues}/coMap.js +34 -15
  15. package/dist/coValues/coMap.js.map +1 -0
  16. package/dist/coValues/coStream.d.ts +14 -0
  17. package/dist/coValues/coStream.js +22 -0
  18. package/dist/coValues/coStream.js.map +1 -0
  19. package/dist/coValues/static.d.ts +14 -0
  20. package/dist/coValues/static.js +20 -0
  21. package/dist/coValues/static.js.map +1 -0
  22. package/dist/group.d.ts +54 -9
  23. package/dist/group.js +68 -28
  24. package/dist/group.js.map +1 -1
  25. package/dist/index.d.ts +17 -9
  26. package/dist/index.js +6 -4
  27. package/dist/index.js.map +1 -1
  28. package/dist/node.d.ts +59 -5
  29. package/dist/node.js +36 -15
  30. package/dist/node.js.map +1 -1
  31. package/dist/permissions.d.ts +2 -2
  32. package/dist/permissions.js +1 -1
  33. package/dist/permissions.js.map +1 -1
  34. package/dist/sync.d.ts +3 -3
  35. package/dist/sync.js +2 -2
  36. package/dist/sync.js.map +1 -1
  37. package/dist/testUtils.d.ts +2 -2
  38. package/dist/testUtils.js +1 -1
  39. package/dist/testUtils.js.map +1 -1
  40. package/package.json +2 -2
  41. package/src/account.test.ts +1 -1
  42. package/src/account.ts +6 -4
  43. package/src/coValue.test.ts +233 -130
  44. package/src/coValue.ts +50 -576
  45. package/src/coValueCore.test.ts +181 -0
  46. package/src/coValueCore.ts +588 -0
  47. package/src/{contentTypes → coValues}/coList.ts +89 -40
  48. package/src/{contentTypes → coValues}/coMap.ts +40 -20
  49. package/src/coValues/coStream.ts +33 -0
  50. package/src/coValues/static.ts +31 -0
  51. package/src/group.ts +87 -50
  52. package/src/index.ts +31 -27
  53. package/src/node.ts +47 -26
  54. package/src/permissions.test.ts +32 -32
  55. package/src/permissions.ts +5 -5
  56. package/src/sync.test.ts +77 -77
  57. package/src/sync.ts +5 -5
  58. package/src/testUtils.ts +1 -1
  59. package/tsconfig.json +1 -2
  60. package/dist/contentType.d.ts +0 -15
  61. package/dist/contentType.js +0 -7
  62. package/dist/contentType.js.map +0 -1
  63. package/dist/contentTypes/coList.d.ts +0 -77
  64. package/dist/contentTypes/coList.js.map +0 -1
  65. package/dist/contentTypes/coMap.js.map +0 -1
  66. package/dist/contentTypes/coStream.d.ts +0 -11
  67. package/dist/contentTypes/coStream.js +0 -16
  68. package/dist/contentTypes/coStream.js.map +0 -1
  69. package/dist/contentTypes/static.d.ts +0 -11
  70. package/dist/contentTypes/static.js +0 -14
  71. package/dist/contentTypes/static.js.map +0 -1
  72. package/src/contentType.test.ts +0 -284
  73. package/src/contentType.ts +0 -26
  74. package/src/contentTypes/coStream.ts +0 -24
  75. package/src/contentTypes/static.ts +0 -22
@@ -1,181 +1,284 @@
1
- import { Transaction } from "./coValue.js";
1
+ import { accountOrAgentIDfromSessionID } from "./coValueCore.js";
2
+ import { createdNowUnique } from "./crypto.js";
2
3
  import { LocalNode } from "./node.js";
3
- import { createdNowUnique, getAgentSignerSecret, newRandomAgentSecret, sign } from "./crypto.js";
4
4
  import { randomAnonymousAccountAndSessionID } from "./testUtils.js";
5
- import { CoMap, MapOpPayload } from "./contentTypes/coMap.js";
6
- import { AccountID } from "./index.js";
7
- import { Role } from "./permissions.js";
8
5
 
9
- test("Can create coValue with new agent credentials and add transaction to it", () => {
10
- const [account, sessionID] = randomAnonymousAccountAndSessionID();
11
- const node = new LocalNode(account, sessionID);
6
+ test("Empty CoMap works", () => {
7
+ const node = new LocalNode(...randomAnonymousAccountAndSessionID());
12
8
 
13
9
  const coValue = node.createCoValue({
14
- type: "costream",
10
+ type: "comap",
15
11
  ruleset: { type: "unsafeAllowAll" },
16
12
  meta: null,
17
13
  ...createdNowUnique(),
18
14
  });
19
15
 
20
- const transaction: Transaction = {
21
- privacy: "trusting",
22
- madeAt: Date.now(),
23
- changes: [
24
- {
25
- hello: "world",
26
- },
27
- ],
28
- };
29
-
30
- const { expectedNewHash } = coValue.expectedNewHashAfter(
31
- node.currentSessionID,
32
- [transaction]
33
- );
34
-
35
- expect(
36
- coValue.tryAddTransactions(
37
- node.currentSessionID,
38
- [transaction],
39
- expectedNewHash,
40
- sign(account.currentSignerSecret(), expectedNewHash)
41
- )
42
- ).toBe(true);
16
+ const content = coValue.getCurrentContent();
17
+
18
+ if (content.type !== "comap") {
19
+ throw new Error("Expected map");
20
+ }
21
+
22
+ expect(content.type).toEqual("comap");
23
+ expect([...content.keys()]).toEqual([]);
24
+ expect(content.toJSON()).toEqual({});
43
25
  });
44
26
 
45
- test("transactions with wrong signature are rejected", () => {
46
- const wrongAgent = newRandomAgentSecret();
47
- const [agentSecret, sessionID] = randomAnonymousAccountAndSessionID();
48
- const node = new LocalNode(agentSecret, sessionID);
27
+ test("Can insert and delete CoMap entries in edit()", () => {
28
+ const node = new LocalNode(...randomAnonymousAccountAndSessionID());
49
29
 
50
30
  const coValue = node.createCoValue({
51
- type: "costream",
31
+ type: "comap",
52
32
  ruleset: { type: "unsafeAllowAll" },
53
33
  meta: null,
54
34
  ...createdNowUnique(),
55
35
  });
56
36
 
57
- const transaction: Transaction = {
58
- privacy: "trusting",
59
- madeAt: Date.now(),
60
- changes: [
61
- {
62
- hello: "world",
63
- },
64
- ],
65
- };
66
-
67
- const { expectedNewHash } = coValue.expectedNewHashAfter(
68
- node.currentSessionID,
69
- [transaction]
70
- );
71
-
72
- expect(
73
- coValue.tryAddTransactions(
74
- node.currentSessionID,
75
- [transaction],
76
- expectedNewHash,
77
- sign(getAgentSignerSecret(wrongAgent), expectedNewHash)
78
- )
79
- ).toBe(false);
37
+ const content = coValue.getCurrentContent();
38
+
39
+ if (content.type !== "comap") {
40
+ throw new Error("Expected map");
41
+ }
42
+
43
+ expect(content.type).toEqual("comap");
44
+
45
+ content.edit((editable) => {
46
+ editable.set("hello", "world", "trusting");
47
+ expect(editable.get("hello")).toEqual("world");
48
+ editable.set("foo", "bar", "trusting");
49
+ expect(editable.get("foo")).toEqual("bar");
50
+ expect([...editable.keys()]).toEqual(["hello", "foo"]);
51
+ editable.delete("foo", "trusting");
52
+ expect(editable.get("foo")).toEqual(undefined);
53
+ });
80
54
  });
81
55
 
82
- test("transactions with correctly signed, but wrong hash are rejected", () => {
83
- const [account, sessionID] = randomAnonymousAccountAndSessionID();
84
- const node = new LocalNode(account, sessionID);
56
+ test("Can get CoMap entry values at different points in time", () => {
57
+ const node = new LocalNode(...randomAnonymousAccountAndSessionID());
85
58
 
86
59
  const coValue = node.createCoValue({
87
- type: "costream",
60
+ type: "comap",
88
61
  ruleset: { type: "unsafeAllowAll" },
89
62
  meta: null,
90
63
  ...createdNowUnique(),
91
64
  });
92
65
 
93
- const transaction: Transaction = {
94
- privacy: "trusting",
95
- madeAt: Date.now(),
96
- changes: [
66
+ const content = coValue.getCurrentContent();
67
+
68
+ if (content.type !== "comap") {
69
+ throw new Error("Expected map");
70
+ }
71
+
72
+ expect(content.type).toEqual("comap");
73
+
74
+ content.edit((editable) => {
75
+ const beforeA = Date.now();
76
+ while (Date.now() < beforeA + 10) {}
77
+ editable.set("hello", "A", "trusting");
78
+ const beforeB = Date.now();
79
+ while (Date.now() < beforeB + 10) {}
80
+ editable.set("hello", "B", "trusting");
81
+ const beforeC = Date.now();
82
+ while (Date.now() < beforeC + 10) {}
83
+ editable.set("hello", "C", "trusting");
84
+ expect(editable.get("hello")).toEqual("C");
85
+ expect(editable.getAtTime("hello", Date.now())).toEqual("C");
86
+ expect(editable.getAtTime("hello", beforeA)).toEqual(undefined);
87
+ expect(editable.getAtTime("hello", beforeB)).toEqual("A");
88
+ expect(editable.getAtTime("hello", beforeC)).toEqual("B");
89
+ });
90
+ });
91
+
92
+ test("Can get all historic values of key in CoMap", () => {
93
+ const node = new LocalNode(...randomAnonymousAccountAndSessionID());
94
+
95
+ const coValue = node.createCoValue({
96
+ type: "comap",
97
+ ruleset: { type: "unsafeAllowAll" },
98
+ meta: null,
99
+ ...createdNowUnique(),
100
+ });
101
+
102
+ const content = coValue.getCurrentContent();
103
+
104
+ if (content.type !== "comap") {
105
+ throw new Error("Expected map");
106
+ }
107
+
108
+ expect(content.type).toEqual("comap");
109
+
110
+ content.edit((editable) => {
111
+ editable.set("hello", "A", "trusting");
112
+ const txA = editable.getLastTxID("hello");
113
+ editable.set("hello", "B", "trusting");
114
+ const txB = editable.getLastTxID("hello");
115
+ editable.delete("hello", "trusting");
116
+ const txDel = editable.getLastTxID("hello");
117
+ editable.set("hello", "C", "trusting");
118
+ const txC = editable.getLastTxID("hello");
119
+ expect(editable.getHistory("hello")).toEqual([
97
120
  {
98
- hello: "world",
121
+ txID: txA,
122
+ value: "A",
123
+ at: txA && coValue.getTx(txA)?.madeAt,
124
+ },
125
+ {
126
+ txID: txB,
127
+ value: "B",
128
+ at: txB && coValue.getTx(txB)?.madeAt,
99
129
  },
100
- ],
101
- };
102
-
103
- const { expectedNewHash } = coValue.expectedNewHashAfter(
104
- node.currentSessionID,
105
- [
106
130
  {
107
- privacy: "trusting",
108
- madeAt: Date.now(),
109
- changes: [
110
- {
111
- hello: "wrong",
112
- },
113
- ],
131
+ txID: txDel,
132
+ value: undefined,
133
+ at: txDel && coValue.getTx(txDel)?.madeAt,
114
134
  },
115
- ]
116
- );
117
-
118
- expect(
119
- coValue.tryAddTransactions(
120
- node.currentSessionID,
121
- [transaction],
122
- expectedNewHash,
123
- sign(account.currentSignerSecret(), expectedNewHash)
124
- )
125
- ).toBe(false);
135
+ {
136
+ txID: txC,
137
+ value: "C",
138
+ at: txC && coValue.getTx(txC)?.madeAt,
139
+ },
140
+ ]);
141
+ });
126
142
  });
127
143
 
128
- test("New transactions in a group correctly update owned values, including subscriptions", async () => {
129
- const [account, sessionID] = randomAnonymousAccountAndSessionID();
130
- const node = new LocalNode(account, sessionID);
144
+ test("Can get last tx ID for a key in CoMap", () => {
145
+ const node = new LocalNode(...randomAnonymousAccountAndSessionID());
131
146
 
132
- const group = node.createGroup();
133
-
134
- const timeBeforeEdit = Date.now();
147
+ const coValue = node.createCoValue({
148
+ type: "comap",
149
+ ruleset: { type: "unsafeAllowAll" },
150
+ meta: null,
151
+ ...createdNowUnique(),
152
+ });
135
153
 
136
- await new Promise((resolve) => setTimeout(resolve, 10));
154
+ const content = coValue.getCurrentContent();
155
+
156
+ if (content.type !== "comap") {
157
+ throw new Error("Expected map");
158
+ }
159
+
160
+ expect(content.type).toEqual("comap");
161
+
162
+ content.edit((editable) => {
163
+ expect(editable.getLastTxID("hello")).toEqual(undefined);
164
+ editable.set("hello", "A", "trusting");
165
+ const sessionID = editable.getLastTxID("hello")?.sessionID;
166
+ expect(sessionID && accountOrAgentIDfromSessionID(sessionID)).toEqual(
167
+ node.account.id
168
+ );
169
+ expect(editable.getLastTxID("hello")?.txIndex).toEqual(0);
170
+ editable.set("hello", "B", "trusting");
171
+ expect(editable.getLastTxID("hello")?.txIndex).toEqual(1);
172
+ editable.set("hello", "C", "trusting");
173
+ expect(editable.getLastTxID("hello")?.txIndex).toEqual(2);
174
+ });
175
+ });
137
176
 
138
- let map = group.createMap();
177
+ test("Empty CoList works", () => {
178
+ const node = new LocalNode(...randomAnonymousAccountAndSessionID());
139
179
 
140
- let mapAfterEdit = map.edit((map) => {
141
- map.set("hello", "world");
180
+ const coValue = node.createCoValue({
181
+ type: "colist",
182
+ ruleset: { type: "unsafeAllowAll" },
183
+ meta: null,
184
+ ...createdNowUnique(),
142
185
  });
143
186
 
144
- const listener = jest.fn().mockImplementation();
187
+ const content = coValue.getCurrentContent();
145
188
 
146
- map.subscribe(listener);
189
+ if (content.type !== "colist") {
190
+ throw new Error("Expected list");
191
+ }
147
192
 
148
- expect(listener.mock.calls[0][0].get("hello")).toBe("world");
193
+ expect(content.type).toEqual("colist");
194
+ expect(content.toJSON()).toEqual([]);
195
+ });
149
196
 
150
- const resignationThatWeJustLearnedAbout = {
151
- privacy: "trusting",
152
- madeAt: timeBeforeEdit,
153
- changes: [
154
- {
155
- op: "set",
156
- key: account.id,
157
- value: "revoked"
158
- } satisfies MapOpPayload<typeof account.id, Role>
159
- ]
160
- } satisfies Transaction;
197
+ test("Can append, prepend and delete items to CoList", () => {
198
+ const node = new LocalNode(...randomAnonymousAccountAndSessionID());
161
199
 
162
- const { expectedNewHash } = group.groupMap.coValue.expectedNewHashAfter(sessionID, [
163
- resignationThatWeJustLearnedAbout,
164
- ]);
200
+ const coValue = node.createCoValue({
201
+ type: "colist",
202
+ ruleset: { type: "unsafeAllowAll" },
203
+ meta: null,
204
+ ...createdNowUnique(),
205
+ });
165
206
 
166
- const signature = sign(
167
- node.account.currentSignerSecret(),
168
- expectedNewHash
169
- );
207
+ const content = coValue.getCurrentContent();
208
+
209
+ if (content.type !== "colist") {
210
+ throw new Error("Expected list");
211
+ }
212
+
213
+ expect(content.type).toEqual("colist");
214
+
215
+ content.edit((editable) => {
216
+ editable.append(0, "hello", "trusting");
217
+ expect(editable.toJSON()).toEqual(["hello"]);
218
+ editable.append(0, "world", "trusting");
219
+ expect(editable.toJSON()).toEqual(["hello", "world"]);
220
+ editable.prepend(1, "beautiful", "trusting");
221
+ expect(editable.toJSON()).toEqual(["hello", "beautiful", "world"]);
222
+ editable.prepend(3, "hooray", "trusting");
223
+ expect(editable.toJSON()).toEqual([
224
+ "hello",
225
+ "beautiful",
226
+ "world",
227
+ "hooray",
228
+ ]);
229
+ editable.delete(2, "trusting");
230
+ expect(editable.toJSON()).toEqual(["hello", "beautiful", "hooray"]);
231
+ });
232
+ });
170
233
 
171
- expect(map.coValue.getValidSortedTransactions().length).toBe(1);
234
+ test("Push is equivalent to append after last item", () => {
235
+ const node = new LocalNode(...randomAnonymousAccountAndSessionID());
236
+
237
+ const coValue = node.createCoValue({
238
+ type: "colist",
239
+ ruleset: { type: "unsafeAllowAll" },
240
+ meta: null,
241
+ ...createdNowUnique(),
242
+ });
172
243
 
173
- const manuallyAdddedTxSuccess = group.groupMap.coValue.tryAddTransactions(node.currentSessionID, [resignationThatWeJustLearnedAbout], expectedNewHash, signature);
244
+ const content = coValue.getCurrentContent();
174
245
 
175
- expect(manuallyAdddedTxSuccess).toBe(true);
246
+ if (content.type !== "colist") {
247
+ throw new Error("Expected list");
248
+ }
176
249
 
177
- expect(listener.mock.calls.length).toBe(2);
178
- expect(listener.mock.calls[1][0].get("hello")).toBe(undefined);
250
+ expect(content.type).toEqual("colist");
179
251
 
180
- expect(map.coValue.getValidSortedTransactions().length).toBe(0);
252
+ content.edit((editable) => {
253
+ editable.append(0, "hello", "trusting");
254
+ expect(editable.toJSON()).toEqual(["hello"]);
255
+ editable.push("world", "trusting");
256
+ expect(editable.toJSON()).toEqual(["hello", "world"]);
257
+ editable.push("hooray", "trusting");
258
+ expect(editable.toJSON()).toEqual(["hello", "world", "hooray"]);
259
+ });
181
260
  });
261
+
262
+ test("Can push into empty list", () => {
263
+ const node = new LocalNode(...randomAnonymousAccountAndSessionID());
264
+
265
+ const coValue = node.createCoValue({
266
+ type: "colist",
267
+ ruleset: { type: "unsafeAllowAll" },
268
+ meta: null,
269
+ ...createdNowUnique(),
270
+ });
271
+
272
+ const content = coValue.getCurrentContent();
273
+
274
+ if (content.type !== "colist") {
275
+ throw new Error("Expected list");
276
+ }
277
+
278
+ expect(content.type).toEqual("colist");
279
+
280
+ content.edit((editable) => {
281
+ editable.push("hello", "trusting");
282
+ expect(editable.toJSON()).toEqual(["hello"]);
283
+ });
284
+ })