@graphprotocol/grc-20 0.31.1 → 0.32.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/dist/examples/ranks/create-ordinal-rank.js +4 -4
  2. package/dist/examples/ranks/create-ordinal-rank.js.map +1 -1
  3. package/dist/examples/ranks/create-weighted-rank.js +4 -4
  4. package/dist/examples/ranks/create-weighted-rank.js.map +1 -1
  5. package/dist/proto.d.ts +4 -8
  6. package/dist/proto.d.ts.map +1 -1
  7. package/dist/proto.js +4 -8
  8. package/dist/proto.js.map +1 -1
  9. package/dist/scripts/setup-rank-types.d.ts +2 -2
  10. package/dist/scripts/setup-rank-types.d.ts.map +1 -1
  11. package/dist/scripts/setup-rank-types.js.map +1 -1
  12. package/dist/src/codec/convert.d.ts +18 -0
  13. package/dist/src/codec/convert.d.ts.map +1 -0
  14. package/dist/src/codec/convert.js +188 -0
  15. package/dist/src/codec/convert.js.map +1 -0
  16. package/dist/src/core/account.d.ts +2 -2
  17. package/dist/src/core/account.d.ts.map +1 -1
  18. package/dist/src/core/account.js +2 -0
  19. package/dist/src/core/account.js.map +1 -1
  20. package/dist/src/core/account.test.js +69 -22
  21. package/dist/src/core/account.test.js.map +1 -1
  22. package/dist/src/core/blocks/data.d.ts +3 -3
  23. package/dist/src/core/blocks/data.d.ts.map +1 -1
  24. package/dist/src/core/blocks/data.js +2 -1
  25. package/dist/src/core/blocks/data.js.map +1 -1
  26. package/dist/src/core/blocks/data.test.js +74 -36
  27. package/dist/src/core/blocks/data.test.js.map +1 -1
  28. package/dist/src/core/blocks/text.d.ts +3 -3
  29. package/dist/src/core/blocks/text.d.ts.map +1 -1
  30. package/dist/src/core/blocks/text.js +2 -1
  31. package/dist/src/core/blocks/text.js.map +1 -1
  32. package/dist/src/core/blocks/text.test.js +79 -15
  33. package/dist/src/core/blocks/text.test.js.map +1 -1
  34. package/dist/src/encoding.test.d.ts +2 -0
  35. package/dist/src/encoding.test.d.ts.map +1 -0
  36. package/dist/src/encoding.test.js +644 -0
  37. package/dist/src/encoding.test.js.map +1 -0
  38. package/dist/src/full-flow-test.test.js +125 -37
  39. package/dist/src/full-flow-test.test.js.map +1 -1
  40. package/dist/src/graph/constants.d.ts +2 -1
  41. package/dist/src/graph/constants.d.ts.map +1 -1
  42. package/dist/src/graph/constants.js +4 -0
  43. package/dist/src/graph/constants.js.map +1 -1
  44. package/dist/src/graph/create-entity.d.ts +0 -1
  45. package/dist/src/graph/create-entity.d.ts.map +1 -1
  46. package/dist/src/graph/create-entity.js +155 -111
  47. package/dist/src/graph/create-entity.js.map +1 -1
  48. package/dist/src/graph/create-entity.test.js +339 -206
  49. package/dist/src/graph/create-entity.test.js.map +1 -1
  50. package/dist/src/graph/create-image.d.ts.map +1 -1
  51. package/dist/src/graph/create-image.js +14 -13
  52. package/dist/src/graph/create-image.js.map +1 -1
  53. package/dist/src/graph/create-image.test.js +109 -50
  54. package/dist/src/graph/create-image.test.js.map +1 -1
  55. package/dist/src/graph/create-property.d.ts.map +1 -1
  56. package/dist/src/graph/create-property.js +10 -19
  57. package/dist/src/graph/create-property.js.map +1 -1
  58. package/dist/src/graph/create-property.test.js +129 -19
  59. package/dist/src/graph/create-property.test.js.map +1 -1
  60. package/dist/src/graph/create-relation.d.ts +1 -3
  61. package/dist/src/graph/create-relation.d.ts.map +1 -1
  62. package/dist/src/graph/create-relation.js +21 -37
  63. package/dist/src/graph/create-relation.js.map +1 -1
  64. package/dist/src/graph/create-relation.test.js +186 -200
  65. package/dist/src/graph/create-relation.test.js.map +1 -1
  66. package/dist/src/graph/create-space.d.ts +2 -2
  67. package/dist/src/graph/create-space.d.ts.map +1 -1
  68. package/dist/src/graph/create-space.js.map +1 -1
  69. package/dist/src/graph/create-type.d.ts.map +1 -1
  70. package/dist/src/graph/create-type.js +16 -21
  71. package/dist/src/graph/create-type.js.map +1 -1
  72. package/dist/src/graph/create-type.test.js +76 -67
  73. package/dist/src/graph/create-type.test.js.map +1 -1
  74. package/dist/src/graph/delete-relation.d.ts.map +1 -1
  75. package/dist/src/graph/delete-relation.js +3 -6
  76. package/dist/src/graph/delete-relation.js.map +1 -1
  77. package/dist/src/graph/delete-relation.test.js +6 -8
  78. package/dist/src/graph/delete-relation.test.js.map +1 -1
  79. package/dist/src/graph/index.d.ts +1 -4
  80. package/dist/src/graph/index.d.ts.map +1 -1
  81. package/dist/src/graph/index.js +1 -4
  82. package/dist/src/graph/index.js.map +1 -1
  83. package/dist/src/graph/update-entity.d.ts.map +1 -1
  84. package/dist/src/graph/update-entity.js +109 -57
  85. package/dist/src/graph/update-entity.js.map +1 -1
  86. package/dist/src/graph/update-entity.test.js +167 -40
  87. package/dist/src/graph/update-entity.test.js.map +1 -1
  88. package/dist/src/graph/update-relation.d.ts +1 -2
  89. package/dist/src/graph/update-relation.d.ts.map +1 -1
  90. package/dist/src/graph/update-relation.js +12 -16
  91. package/dist/src/graph/update-relation.js.map +1 -1
  92. package/dist/src/graph/update-relation.test.js +75 -109
  93. package/dist/src/graph/update-relation.test.js.map +1 -1
  94. package/dist/src/id-utils.d.ts +6 -0
  95. package/dist/src/id-utils.d.ts.map +1 -1
  96. package/dist/src/id-utils.js +13 -0
  97. package/dist/src/id-utils.js.map +1 -1
  98. package/dist/src/ipfs.d.ts +3 -3
  99. package/dist/src/ipfs.d.ts.map +1 -1
  100. package/dist/src/ipfs.js +27 -7
  101. package/dist/src/ipfs.js.map +1 -1
  102. package/dist/src/ipfs.test.js +130 -17
  103. package/dist/src/ipfs.test.js.map +1 -1
  104. package/dist/src/proto/index.d.ts +7 -1
  105. package/dist/src/proto/index.d.ts.map +1 -1
  106. package/dist/src/proto/index.js +6 -1
  107. package/dist/src/proto/index.js.map +1 -1
  108. package/dist/src/ranks/create-rank.d.ts.map +1 -1
  109. package/dist/src/ranks/create-rank.js +54 -47
  110. package/dist/src/ranks/create-rank.js.map +1 -1
  111. package/dist/src/ranks/create-rank.test.js +181 -94
  112. package/dist/src/ranks/create-rank.test.js.map +1 -1
  113. package/dist/src/types.d.ts +52 -89
  114. package/dist/src/types.d.ts.map +1 -1
  115. package/dist/src/types.js.map +1 -1
  116. package/package.json +2 -5
@@ -0,0 +1,644 @@
1
+ import { decodeEdit, encodeEdit, formatId, parseId, } from '@geoprotocol/grc-20';
2
+ import { describe, expect, it } from 'vitest';
3
+ // Helper to convert string ID to GRC-20 Id
4
+ function toGrcId(id) {
5
+ const parsed = parseId(id);
6
+ if (!parsed)
7
+ throw new Error(`Invalid ID: ${id}`);
8
+ return parsed;
9
+ }
10
+ describe('GRC-20 v2 Encoding', () => {
11
+ describe('createEntity ops', () => {
12
+ it('encodes and decodes createEntity with text value', () => {
13
+ const entityId = toGrcId('3af3e22d21694a078681516710b7ecf1');
14
+ const propertyId = toGrcId('d4bc2f205e2d415e971eb0b9fbf6b6fc');
15
+ const languageId = toGrcId('a6104fe0d6954f9392fa0a1afc552bc5');
16
+ const editId = toGrcId('11111111111111111111111111111111');
17
+ const authorId = toGrcId('22222222222222222222222222222222');
18
+ const edit = {
19
+ id: editId,
20
+ name: 'test',
21
+ authors: [authorId],
22
+ createdAt: BigInt(1000000),
23
+ ops: [
24
+ {
25
+ type: 'createEntity',
26
+ id: entityId,
27
+ values: [
28
+ {
29
+ property: propertyId,
30
+ value: {
31
+ type: 'text',
32
+ value: 'test value',
33
+ language: languageId,
34
+ },
35
+ },
36
+ ],
37
+ },
38
+ ],
39
+ };
40
+ const binary = encodeEdit(edit);
41
+ const decoded = decodeEdit(binary);
42
+ expect(decoded.name).toBe('test');
43
+ expect(decoded.ops.length).toBe(1);
44
+ expect(decoded.ops[0]?.type).toBe('createEntity');
45
+ const op = decoded.ops[0];
46
+ expect(formatId(op.id)).toBe('3af3e22d21694a078681516710b7ecf1');
47
+ expect(op.values.length).toBe(1);
48
+ expect(op.values[0]?.value.type).toBe('text');
49
+ if (op.values[0]?.value.type === 'text') {
50
+ expect(op.values[0].value.value).toBe('test value');
51
+ }
52
+ });
53
+ it('encodes and decodes createEntity with float64 value', () => {
54
+ const entityId = toGrcId('3af3e22d21694a078681516710b7ecf1');
55
+ const propertyId = toGrcId('d4bc2f205e2d415e971eb0b9fbf6b6fc');
56
+ const unitId = toGrcId('a6104fe0d6954f9392fa0a1afc552bc5');
57
+ const editId = toGrcId('11111111111111111111111111111111');
58
+ const authorId = toGrcId('22222222222222222222222222222222');
59
+ const edit = {
60
+ id: editId,
61
+ name: 'test',
62
+ authors: [authorId],
63
+ createdAt: BigInt(1000000),
64
+ ops: [
65
+ {
66
+ type: 'createEntity',
67
+ id: entityId,
68
+ values: [
69
+ {
70
+ property: propertyId,
71
+ value: {
72
+ type: 'float64',
73
+ value: 42.5,
74
+ unit: unitId,
75
+ },
76
+ },
77
+ ],
78
+ },
79
+ ],
80
+ };
81
+ const binary = encodeEdit(edit);
82
+ const decoded = decodeEdit(binary);
83
+ expect(decoded.name).toBe('test');
84
+ expect(decoded.ops.length).toBe(1);
85
+ const op = decoded.ops[0];
86
+ expect(op.values[0]?.value.type).toBe('float64');
87
+ if (op.values[0]?.value.type === 'float64') {
88
+ expect(op.values[0].value.value).toBe(42.5);
89
+ }
90
+ });
91
+ it('encodes and decodes createEntity with bool value', () => {
92
+ const entityId = toGrcId('3af3e22d21694a078681516710b7ecf1');
93
+ const propertyId = toGrcId('d4bc2f205e2d415e971eb0b9fbf6b6fc');
94
+ const editId = toGrcId('11111111111111111111111111111111');
95
+ const authorId = toGrcId('22222222222222222222222222222222');
96
+ const edit = {
97
+ id: editId,
98
+ name: 'test',
99
+ authors: [authorId],
100
+ createdAt: BigInt(1000000),
101
+ ops: [
102
+ {
103
+ type: 'createEntity',
104
+ id: entityId,
105
+ values: [
106
+ {
107
+ property: propertyId,
108
+ value: {
109
+ type: 'bool',
110
+ value: true,
111
+ },
112
+ },
113
+ ],
114
+ },
115
+ ],
116
+ };
117
+ const binary = encodeEdit(edit);
118
+ const decoded = decodeEdit(binary);
119
+ const op = decoded.ops[0];
120
+ expect(op.values[0]?.value.type).toBe('bool');
121
+ if (op.values[0]?.value.type === 'bool') {
122
+ expect(op.values[0].value.value).toBe(true);
123
+ }
124
+ });
125
+ it('encodes and decodes createEntity with point value', () => {
126
+ const entityId = toGrcId('3af3e22d21694a078681516710b7ecf1');
127
+ const propertyId = toGrcId('d4bc2f205e2d415e971eb0b9fbf6b6fc');
128
+ const editId = toGrcId('11111111111111111111111111111111');
129
+ const authorId = toGrcId('22222222222222222222222222222222');
130
+ const edit = {
131
+ id: editId,
132
+ name: 'test',
133
+ authors: [authorId],
134
+ createdAt: BigInt(1000000),
135
+ ops: [
136
+ {
137
+ type: 'createEntity',
138
+ id: entityId,
139
+ values: [
140
+ {
141
+ property: propertyId,
142
+ value: {
143
+ type: 'point',
144
+ lon: -122.4194,
145
+ lat: 37.7749,
146
+ alt: 10.5,
147
+ },
148
+ },
149
+ ],
150
+ },
151
+ ],
152
+ };
153
+ const binary = encodeEdit(edit);
154
+ const decoded = decodeEdit(binary);
155
+ const op = decoded.ops[0];
156
+ expect(op.values[0]?.value.type).toBe('point');
157
+ if (op.values[0]?.value.type === 'point') {
158
+ expect(op.values[0].value.lon).toBeCloseTo(-122.4194, 4);
159
+ expect(op.values[0].value.lat).toBeCloseTo(37.7749, 4);
160
+ expect(op.values[0].value.alt).toBeCloseTo(10.5, 1);
161
+ }
162
+ });
163
+ it('encodes and decodes createEntity with date value', () => {
164
+ const entityId = toGrcId('3af3e22d21694a078681516710b7ecf1');
165
+ const propertyId = toGrcId('d4bc2f205e2d415e971eb0b9fbf6b6fc');
166
+ const editId = toGrcId('11111111111111111111111111111111');
167
+ const authorId = toGrcId('22222222222222222222222222222222');
168
+ const edit = {
169
+ id: editId,
170
+ name: 'test',
171
+ authors: [authorId],
172
+ createdAt: BigInt(1000000),
173
+ ops: [
174
+ {
175
+ type: 'createEntity',
176
+ id: entityId,
177
+ values: [
178
+ {
179
+ property: propertyId,
180
+ value: {
181
+ type: 'date',
182
+ value: '2024-01-15',
183
+ },
184
+ },
185
+ ],
186
+ },
187
+ ],
188
+ };
189
+ const binary = encodeEdit(edit);
190
+ const decoded = decodeEdit(binary);
191
+ const op = decoded.ops[0];
192
+ expect(op.values[0]?.value.type).toBe('date');
193
+ if (op.values[0]?.value.type === 'date') {
194
+ expect(op.values[0].value.value).toBe('2024-01-15');
195
+ }
196
+ });
197
+ it('encodes and decodes createEntity with time value', () => {
198
+ const entityId = toGrcId('3af3e22d21694a078681516710b7ecf1');
199
+ const propertyId = toGrcId('d4bc2f205e2d415e971eb0b9fbf6b6fc');
200
+ const editId = toGrcId('11111111111111111111111111111111');
201
+ const authorId = toGrcId('22222222222222222222222222222222');
202
+ const edit = {
203
+ id: editId,
204
+ name: 'test',
205
+ authors: [authorId],
206
+ createdAt: BigInt(1000000),
207
+ ops: [
208
+ {
209
+ type: 'createEntity',
210
+ id: entityId,
211
+ values: [
212
+ {
213
+ property: propertyId,
214
+ value: {
215
+ type: 'time',
216
+ value: '14:30:00Z',
217
+ },
218
+ },
219
+ ],
220
+ },
221
+ ],
222
+ };
223
+ const binary = encodeEdit(edit);
224
+ const decoded = decodeEdit(binary);
225
+ const op = decoded.ops[0];
226
+ expect(op.values[0]?.value.type).toBe('time');
227
+ if (op.values[0]?.value.type === 'time') {
228
+ expect(op.values[0].value.value).toBe('14:30:00Z');
229
+ }
230
+ });
231
+ it('encodes and decodes createEntity with datetime value', () => {
232
+ const entityId = toGrcId('3af3e22d21694a078681516710b7ecf1');
233
+ const propertyId = toGrcId('d4bc2f205e2d415e971eb0b9fbf6b6fc');
234
+ const editId = toGrcId('11111111111111111111111111111111');
235
+ const authorId = toGrcId('22222222222222222222222222222222');
236
+ const edit = {
237
+ id: editId,
238
+ name: 'test',
239
+ authors: [authorId],
240
+ createdAt: BigInt(1000000),
241
+ ops: [
242
+ {
243
+ type: 'createEntity',
244
+ id: entityId,
245
+ values: [
246
+ {
247
+ property: propertyId,
248
+ value: {
249
+ type: 'datetime',
250
+ value: '2024-01-15T14:30:00Z',
251
+ },
252
+ },
253
+ ],
254
+ },
255
+ ],
256
+ };
257
+ const binary = encodeEdit(edit);
258
+ const decoded = decodeEdit(binary);
259
+ const op = decoded.ops[0];
260
+ expect(op.values[0]?.value.type).toBe('datetime');
261
+ if (op.values[0]?.value.type === 'datetime') {
262
+ expect(op.values[0].value.value).toBe('2024-01-15T14:30:00Z');
263
+ }
264
+ });
265
+ it('encodes and decodes createEntity with schedule value', () => {
266
+ const entityId = toGrcId('3af3e22d21694a078681516710b7ecf1');
267
+ const propertyId = toGrcId('d4bc2f205e2d415e971eb0b9fbf6b6fc');
268
+ const editId = toGrcId('11111111111111111111111111111111');
269
+ const authorId = toGrcId('22222222222222222222222222222222');
270
+ const edit = {
271
+ id: editId,
272
+ name: 'test',
273
+ authors: [authorId],
274
+ createdAt: BigInt(1000000),
275
+ ops: [
276
+ {
277
+ type: 'createEntity',
278
+ id: entityId,
279
+ values: [
280
+ {
281
+ property: propertyId,
282
+ value: {
283
+ type: 'schedule',
284
+ value: 'FREQ=WEEKLY;BYDAY=MO,WE,FR',
285
+ },
286
+ },
287
+ ],
288
+ },
289
+ ],
290
+ };
291
+ const binary = encodeEdit(edit);
292
+ const decoded = decodeEdit(binary);
293
+ const op = decoded.ops[0];
294
+ expect(op.values[0]?.value.type).toBe('schedule');
295
+ if (op.values[0]?.value.type === 'schedule') {
296
+ expect(op.values[0].value.value).toBe('FREQ=WEEKLY;BYDAY=MO,WE,FR');
297
+ }
298
+ });
299
+ });
300
+ describe('relation ops', () => {
301
+ it('encodes and decodes createRelation', () => {
302
+ const relationId = toGrcId('765564cac7e54c61b1dcc28ab77ec6b7');
303
+ const relationTypeId = toGrcId('cf518eafef744aadbc87fe09c2631fcd');
304
+ const fromEntityId = toGrcId('3af3e22d21694a078681516710b7ecf1');
305
+ const toEntityId = toGrcId('d4bc2f205e2d415e971eb0b9fbf6b6fc');
306
+ const entityId = toGrcId('a6104fe0d6954f9392fa0a1afc552bc5');
307
+ const editId = toGrcId('11111111111111111111111111111111');
308
+ const authorId = toGrcId('22222222222222222222222222222222');
309
+ const edit = {
310
+ id: editId,
311
+ name: 'test',
312
+ authors: [authorId],
313
+ createdAt: BigInt(1000000),
314
+ ops: [
315
+ {
316
+ type: 'createRelation',
317
+ id: relationId,
318
+ relationType: relationTypeId,
319
+ from: fromEntityId,
320
+ to: toEntityId,
321
+ entity: entityId,
322
+ position: 'test-position',
323
+ },
324
+ ],
325
+ };
326
+ const binary = encodeEdit(edit);
327
+ const decoded = decodeEdit(binary);
328
+ expect(decoded.name).toBe('test');
329
+ expect(decoded.ops.length).toBe(1);
330
+ expect(decoded.ops[0]?.type).toBe('createRelation');
331
+ const op = decoded.ops[0];
332
+ expect(formatId(op.id)).toBe('765564cac7e54c61b1dcc28ab77ec6b7');
333
+ expect(formatId(op.relationType)).toBe('cf518eafef744aadbc87fe09c2631fcd');
334
+ expect(formatId(op.from)).toBe('3af3e22d21694a078681516710b7ecf1');
335
+ expect(formatId(op.to)).toBe('d4bc2f205e2d415e971eb0b9fbf6b6fc');
336
+ expect(op.position).toBe('test-position');
337
+ });
338
+ it('encodes and decodes createRelation with space pins', () => {
339
+ const relationId = toGrcId('765564cac7e54c61b1dcc28ab77ec6b7');
340
+ const relationTypeId = toGrcId('cf518eafef744aadbc87fe09c2631fcd');
341
+ const fromEntityId = toGrcId('3af3e22d21694a078681516710b7ecf1');
342
+ const toEntityId = toGrcId('d4bc2f205e2d415e971eb0b9fbf6b6fc');
343
+ const fromSpaceId = toGrcId('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
344
+ const toSpaceId = toGrcId('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb');
345
+ const editId = toGrcId('11111111111111111111111111111111');
346
+ const authorId = toGrcId('22222222222222222222222222222222');
347
+ const edit = {
348
+ id: editId,
349
+ name: 'test',
350
+ authors: [authorId],
351
+ createdAt: BigInt(1000000),
352
+ ops: [
353
+ {
354
+ type: 'createRelation',
355
+ id: relationId,
356
+ relationType: relationTypeId,
357
+ from: fromEntityId,
358
+ to: toEntityId,
359
+ fromSpace: fromSpaceId,
360
+ toSpace: toSpaceId,
361
+ },
362
+ ],
363
+ };
364
+ const binary = encodeEdit(edit);
365
+ const decoded = decodeEdit(binary);
366
+ const op = decoded.ops[0];
367
+ expect(op.fromSpace).toBeDefined();
368
+ expect(op.toSpace).toBeDefined();
369
+ if (op.fromSpace)
370
+ expect(formatId(op.fromSpace)).toBe('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
371
+ if (op.toSpace)
372
+ expect(formatId(op.toSpace)).toBe('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb');
373
+ });
374
+ it('encodes and decodes deleteRelation', () => {
375
+ const relationId = toGrcId('765564cac7e54c61b1dcc28ab77ec6b7');
376
+ const editId = toGrcId('11111111111111111111111111111111');
377
+ const authorId = toGrcId('22222222222222222222222222222222');
378
+ const edit = {
379
+ id: editId,
380
+ name: 'test',
381
+ authors: [authorId],
382
+ createdAt: BigInt(1000000),
383
+ ops: [
384
+ {
385
+ type: 'deleteRelation',
386
+ id: relationId,
387
+ },
388
+ ],
389
+ };
390
+ const binary = encodeEdit(edit);
391
+ const decoded = decodeEdit(binary);
392
+ expect(decoded.ops.length).toBe(1);
393
+ expect(decoded.ops[0]?.type).toBe('deleteRelation');
394
+ const op = decoded.ops[0];
395
+ expect(formatId(op.id)).toBe('765564cac7e54c61b1dcc28ab77ec6b7');
396
+ });
397
+ it('encodes and decodes updateRelation', () => {
398
+ const relationId = toGrcId('765564cac7e54c61b1dcc28ab77ec6b7');
399
+ const editId = toGrcId('11111111111111111111111111111111');
400
+ const authorId = toGrcId('22222222222222222222222222222222');
401
+ const edit = {
402
+ id: editId,
403
+ name: 'test',
404
+ authors: [authorId],
405
+ createdAt: BigInt(1000000),
406
+ ops: [
407
+ {
408
+ type: 'updateRelation',
409
+ id: relationId,
410
+ position: 'new-position',
411
+ unset: [],
412
+ },
413
+ ],
414
+ };
415
+ const binary = encodeEdit(edit);
416
+ const decoded = decodeEdit(binary);
417
+ expect(decoded.ops.length).toBe(1);
418
+ expect(decoded.ops[0]?.type).toBe('updateRelation');
419
+ const op = decoded.ops[0];
420
+ expect(formatId(op.id)).toBe('765564cac7e54c61b1dcc28ab77ec6b7');
421
+ expect(op.position).toBe('new-position');
422
+ });
423
+ it('encodes and decodes updateRelation with unset fields', () => {
424
+ const relationId = toGrcId('765564cac7e54c61b1dcc28ab77ec6b7');
425
+ const editId = toGrcId('11111111111111111111111111111111');
426
+ const authorId = toGrcId('22222222222222222222222222222222');
427
+ const edit = {
428
+ id: editId,
429
+ name: 'test',
430
+ authors: [authorId],
431
+ createdAt: BigInt(1000000),
432
+ ops: [
433
+ {
434
+ type: 'updateRelation',
435
+ id: relationId,
436
+ unset: ['fromSpace', 'toSpace', 'position'],
437
+ },
438
+ ],
439
+ };
440
+ const binary = encodeEdit(edit);
441
+ const decoded = decodeEdit(binary);
442
+ const op = decoded.ops[0];
443
+ expect(op.unset).toContain('fromSpace');
444
+ expect(op.unset).toContain('toSpace');
445
+ expect(op.unset).toContain('position');
446
+ });
447
+ });
448
+ describe('entity ops', () => {
449
+ it('encodes and decodes updateEntity with set and unset', () => {
450
+ const entityId = toGrcId('3af3e22d21694a078681516710b7ecf1');
451
+ const propertyId = toGrcId('d4bc2f205e2d415e971eb0b9fbf6b6fc');
452
+ const unsetPropertyId = toGrcId('a6104fe0d6954f9392fa0a1afc552bc5');
453
+ const editId = toGrcId('11111111111111111111111111111111');
454
+ const authorId = toGrcId('22222222222222222222222222222222');
455
+ const edit = {
456
+ id: editId,
457
+ name: 'test',
458
+ authors: [authorId],
459
+ createdAt: BigInt(1000000),
460
+ ops: [
461
+ {
462
+ type: 'updateEntity',
463
+ id: entityId,
464
+ set: [
465
+ {
466
+ property: propertyId,
467
+ value: {
468
+ type: 'text',
469
+ value: 'updated value',
470
+ },
471
+ },
472
+ ],
473
+ unset: [
474
+ {
475
+ property: unsetPropertyId,
476
+ language: { type: 'all' },
477
+ },
478
+ ],
479
+ },
480
+ ],
481
+ };
482
+ const binary = encodeEdit(edit);
483
+ const decoded = decodeEdit(binary);
484
+ expect(decoded.ops.length).toBe(1);
485
+ expect(decoded.ops[0]?.type).toBe('updateEntity');
486
+ const op = decoded.ops[0];
487
+ expect(formatId(op.id)).toBe('3af3e22d21694a078681516710b7ecf1');
488
+ expect(op.set.length).toBe(1);
489
+ expect(op.unset.length).toBe(1);
490
+ });
491
+ it('encodes and decodes deleteEntity', () => {
492
+ const entityId = toGrcId('3af3e22d21694a078681516710b7ecf1');
493
+ const editId = toGrcId('11111111111111111111111111111111');
494
+ const authorId = toGrcId('22222222222222222222222222222222');
495
+ const edit = {
496
+ id: editId,
497
+ name: 'test',
498
+ authors: [authorId],
499
+ createdAt: BigInt(1000000),
500
+ ops: [
501
+ {
502
+ type: 'deleteEntity',
503
+ id: entityId,
504
+ },
505
+ ],
506
+ };
507
+ const binary = encodeEdit(edit);
508
+ const decoded = decodeEdit(binary);
509
+ expect(decoded.ops.length).toBe(1);
510
+ expect(decoded.ops[0]?.type).toBe('deleteEntity');
511
+ const op = decoded.ops[0];
512
+ expect(formatId(op.id)).toBe('3af3e22d21694a078681516710b7ecf1');
513
+ });
514
+ it('encodes and decodes restoreEntity', () => {
515
+ const entityId = toGrcId('3af3e22d21694a078681516710b7ecf1');
516
+ const editId = toGrcId('11111111111111111111111111111111');
517
+ const authorId = toGrcId('22222222222222222222222222222222');
518
+ const edit = {
519
+ id: editId,
520
+ name: 'test',
521
+ authors: [authorId],
522
+ createdAt: BigInt(1000000),
523
+ ops: [
524
+ {
525
+ type: 'restoreEntity',
526
+ id: entityId,
527
+ },
528
+ ],
529
+ };
530
+ const binary = encodeEdit(edit);
531
+ const decoded = decodeEdit(binary);
532
+ expect(decoded.ops.length).toBe(1);
533
+ expect(decoded.ops[0]?.type).toBe('restoreEntity');
534
+ const op = decoded.ops[0];
535
+ expect(formatId(op.id)).toBe('3af3e22d21694a078681516710b7ecf1');
536
+ });
537
+ });
538
+ describe('multiple ops', () => {
539
+ it('encodes and decodes edit with multiple ops', () => {
540
+ const entityId1 = toGrcId('3af3e22d21694a078681516710b7ecf1');
541
+ const entityId2 = toGrcId('d4bc2f205e2d415e971eb0b9fbf6b6fc');
542
+ const propertyId = toGrcId('a6104fe0d6954f9392fa0a1afc552bc5');
543
+ const relationId = toGrcId('765564cac7e54c61b1dcc28ab77ec6b7');
544
+ const relationTypeId = toGrcId('cf518eafef744aadbc87fe09c2631fcd');
545
+ const editId = toGrcId('11111111111111111111111111111111');
546
+ const authorId = toGrcId('22222222222222222222222222222222');
547
+ const edit = {
548
+ id: editId,
549
+ name: 'multi-op test',
550
+ authors: [authorId],
551
+ createdAt: BigInt(1000000),
552
+ ops: [
553
+ {
554
+ type: 'createEntity',
555
+ id: entityId1,
556
+ values: [
557
+ {
558
+ property: propertyId,
559
+ value: { type: 'text', value: 'Entity 1' },
560
+ },
561
+ ],
562
+ },
563
+ {
564
+ type: 'createEntity',
565
+ id: entityId2,
566
+ values: [
567
+ {
568
+ property: propertyId,
569
+ value: { type: 'text', value: 'Entity 2' },
570
+ },
571
+ ],
572
+ },
573
+ {
574
+ type: 'createRelation',
575
+ id: relationId,
576
+ relationType: relationTypeId,
577
+ from: entityId1,
578
+ to: entityId2,
579
+ },
580
+ ],
581
+ };
582
+ const binary = encodeEdit(edit);
583
+ const decoded = decodeEdit(binary);
584
+ expect(decoded.name).toBe('multi-op test');
585
+ expect(decoded.ops.length).toBe(3);
586
+ expect(decoded.ops[0]?.type).toBe('createEntity');
587
+ expect(decoded.ops[1]?.type).toBe('createEntity');
588
+ expect(decoded.ops[2]?.type).toBe('createRelation');
589
+ });
590
+ });
591
+ describe('edit metadata', () => {
592
+ it('preserves edit id', () => {
593
+ const editId = toGrcId('abcdef12345678901234567890abcdef');
594
+ const authorId = toGrcId('22222222222222222222222222222222');
595
+ const edit = {
596
+ id: editId,
597
+ name: 'test',
598
+ authors: [authorId],
599
+ createdAt: BigInt(1000000),
600
+ ops: [],
601
+ };
602
+ const binary = encodeEdit(edit);
603
+ const decoded = decodeEdit(binary);
604
+ expect(formatId(decoded.id)).toBe('abcdef12345678901234567890abcdef');
605
+ });
606
+ it('preserves multiple authors', () => {
607
+ const editId = toGrcId('11111111111111111111111111111111');
608
+ const authorId1 = toGrcId('22222222222222222222222222222222');
609
+ const authorId2 = toGrcId('33333333333333333333333333333333');
610
+ const edit = {
611
+ id: editId,
612
+ name: 'test',
613
+ authors: [authorId1, authorId2],
614
+ createdAt: BigInt(1000000),
615
+ ops: [],
616
+ };
617
+ const binary = encodeEdit(edit);
618
+ const decoded = decodeEdit(binary);
619
+ expect(decoded.authors.length).toBe(2);
620
+ const author0 = decoded.authors[0];
621
+ const author1 = decoded.authors[1];
622
+ if (!author0 || !author1)
623
+ throw new Error('Expected authors to be defined');
624
+ expect(formatId(author0)).toBe('22222222222222222222222222222222');
625
+ expect(formatId(author1)).toBe('33333333333333333333333333333333');
626
+ });
627
+ it('preserves createdAt timestamp', () => {
628
+ const editId = toGrcId('11111111111111111111111111111111');
629
+ const authorId = toGrcId('22222222222222222222222222222222');
630
+ const timestamp = BigInt(1705334400000000); // 2024-01-15 in microseconds
631
+ const edit = {
632
+ id: editId,
633
+ name: 'test',
634
+ authors: [authorId],
635
+ createdAt: timestamp,
636
+ ops: [],
637
+ };
638
+ const binary = encodeEdit(edit);
639
+ const decoded = decodeEdit(binary);
640
+ expect(decoded.createdAt).toBe(timestamp);
641
+ });
642
+ });
643
+ });
644
+ //# sourceMappingURL=encoding.test.js.map