cojson 0.6.7 → 0.7.0-alpha.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.
Files changed (53) hide show
  1. package/.eslintrc.cjs +1 -0
  2. package/.turbo/turbo-build.log +2 -2
  3. package/CHANGELOG.md +3 -3
  4. package/dist/coValue.js.map +1 -1
  5. package/dist/coValueCore.js.map +1 -1
  6. package/dist/coValues/account.js +5 -5
  7. package/dist/coValues/account.js.map +1 -1
  8. package/dist/coValues/coList.js +39 -58
  9. package/dist/coValues/coList.js.map +1 -1
  10. package/dist/coValues/coMap.js +20 -61
  11. package/dist/coValues/coMap.js.map +1 -1
  12. package/dist/coValues/coStream.js +14 -64
  13. package/dist/coValues/coStream.js.map +1 -1
  14. package/dist/coValues/group.js +57 -59
  15. package/dist/coValues/group.js.map +1 -1
  16. package/dist/coreToCoValue.js +17 -12
  17. package/dist/coreToCoValue.js.map +1 -1
  18. package/dist/index.js +8 -8
  19. package/dist/index.js.map +1 -1
  20. package/dist/localNode.js +54 -38
  21. package/dist/localNode.js.map +1 -1
  22. package/dist/permissions.js +2 -2
  23. package/dist/permissions.js.map +1 -1
  24. package/dist/tests/testUtils.js +6 -11
  25. package/dist/tests/testUtils.js.map +1 -1
  26. package/dist/typeUtils/expectGroup.js +2 -2
  27. package/dist/typeUtils/expectGroup.js.map +1 -1
  28. package/dist/typeUtils/isCoValue.js +8 -8
  29. package/dist/typeUtils/isCoValue.js.map +1 -1
  30. package/package.json +3 -4
  31. package/src/coValue.ts +21 -21
  32. package/src/coValueCore.ts +8 -8
  33. package/src/coValues/account.ts +14 -26
  34. package/src/coValues/coList.ts +58 -97
  35. package/src/coValues/coMap.ts +27 -129
  36. package/src/coValues/coStream.ts +31 -137
  37. package/src/coValues/group.ts +52 -46
  38. package/src/coreToCoValue.ts +16 -12
  39. package/src/index.ts +27 -36
  40. package/src/jsonValue.ts +1 -1
  41. package/src/localNode.ts +88 -75
  42. package/src/media.ts +4 -4
  43. package/src/permissions.ts +2 -2
  44. package/src/tests/account.test.ts +12 -12
  45. package/src/tests/coValue.test.ts +149 -182
  46. package/src/tests/coValueCore.test.ts +8 -3
  47. package/src/tests/crypto.test.ts +7 -0
  48. package/src/tests/group.test.ts +13 -6
  49. package/src/tests/permissions.test.ts +648 -840
  50. package/src/tests/sync.test.ts +44 -68
  51. package/src/tests/testUtils.ts +6 -11
  52. package/src/typeUtils/expectGroup.ts +4 -4
  53. package/src/typeUtils/isCoValue.ts +11 -11
@@ -1,10 +1,10 @@
1
1
  import { JsonObject, JsonValue } from "../jsonValue.js";
2
- import { CoValue, CoID } from "../coValue.js";
2
+ import { RawCoValue, CoID } from "../coValue.js";
3
3
  import { isAccountID } from "../typeUtils/isAccountID.js";
4
4
  import { isCoValue } from "../typeUtils/isCoValue.js";
5
5
  import { CoValueCore } from "../coValueCore.js";
6
6
  import { accountOrAgentIDfromSessionID } from "../typeUtils/accountOrAgentIDfromSessionID.js";
7
- import { Group } from "./group.js";
7
+ import { RawGroup } from "./group.js";
8
8
  import { AgentID, SessionID, TransactionID } from "../ids.js";
9
9
  import { base64URLtoBytes, bytesToBase64url } from "../base64url.js";
10
10
  import { AccountID } from "./account.js";
@@ -41,10 +41,10 @@ export type CoStreamItem<Item extends JsonValue> = {
41
41
  madeAt: number;
42
42
  };
43
43
 
44
- export class CoStreamView<
44
+ export class RawCoStreamView<
45
45
  Item extends JsonValue = JsonValue,
46
46
  Meta extends JsonObject | null = JsonObject | null
47
- > implements CoValue
47
+ > implements RawCoValue
48
48
  {
49
49
  id: CoID<this>;
50
50
  type = "costream" as const;
@@ -65,7 +65,7 @@ export class CoStreamView<
65
65
  return this.core.header.meta as Meta;
66
66
  }
67
67
 
68
- get group(): Group {
68
+ get group(): RawGroup {
69
69
  return this.core.getGroup();
70
70
  }
71
71
 
@@ -95,9 +95,7 @@ export class CoStreamView<
95
95
  }
96
96
  }
97
97
 
98
- getSingleStream():
99
- | (Item)[]
100
- | undefined {
98
+ getSingleStream(): Item[] | undefined {
101
99
  if (Object.keys(this.items).length === 0) {
102
100
  return undefined;
103
101
  } else if (Object.keys(this.items).length !== 1) {
@@ -114,7 +112,11 @@ export class CoStreamView<
114
112
  }
115
113
 
116
114
  accounts(): Set<AccountID> {
117
- return new Set(this.sessions().map(accountOrAgentIDfromSessionID).filter(isAccountID));
115
+ return new Set(
116
+ this.sessions()
117
+ .map(accountOrAgentIDfromSessionID)
118
+ .filter(isAccountID)
119
+ );
118
120
  }
119
121
 
120
122
  nthItemIn(
@@ -224,7 +226,7 @@ export class CoStreamView<
224
226
  }
225
227
 
226
228
  toJSON(): {
227
- [key: SessionID]: (Item )[];
229
+ [key: SessionID]: Item[];
228
230
  } {
229
231
  return Object.fromEntries(
230
232
  Object.entries(this.items).map(([sessionID, items]) => [
@@ -241,44 +243,14 @@ export class CoStreamView<
241
243
  }
242
244
  }
243
245
 
244
- export class CoStream<
246
+ export class RawCoStream<
245
247
  Item extends JsonValue = JsonValue,
246
248
  Meta extends JsonObject | null = JsonObject | null
247
249
  >
248
- extends CoStreamView<Item, Meta>
249
- implements CoValue
250
+ extends RawCoStreamView<Item, Meta>
251
+ implements RawCoValue
250
252
  {
251
- push(
252
- item: Item,
253
- privacy: "private" | "trusting" = "private"
254
- ): this {
255
- this.core.makeTransaction([isCoValue(item) ? item.id : item], privacy);
256
- return new CoStream(this.core) as this;
257
- }
258
-
259
- mutate(mutator: (mutable: MutableCoStream<Item, Meta>) => void): this {
260
- const mutable = new MutableCoStream<Item, Meta>(this.core);
261
- mutator(mutable);
262
- return new CoStream(this.core) as this;
263
- }
264
-
265
- /** @deprecated Use `mutate` instead. */
266
- edit(mutator: (mutable: MutableCoStream<Item, Meta>) => void): this {
267
- return this.mutate(mutator);
268
- }
269
- }
270
-
271
- export class MutableCoStream<
272
- Item extends JsonValue,
273
- Meta extends JsonObject | null = JsonObject | null
274
- >
275
- extends CoStreamView<Item, Meta>
276
- implements CoValue
277
- {
278
- push(
279
- item: Item,
280
- privacy: "private" | "trusting" = "private"
281
- ) {
253
+ push(item: Item, privacy: "private" | "trusting" = "private"): void {
282
254
  this.core.makeTransaction([isCoValue(item) ? item.id : item], privacy);
283
255
  this.fillFromCoValue();
284
256
  }
@@ -286,14 +258,14 @@ export class MutableCoStream<
286
258
 
287
259
  const binary_U_prefixLength = 8; // "binary_U".length;
288
260
 
289
- export class BinaryCoStreamView<
261
+ export class RawBinaryCoStreamView<
290
262
  Meta extends BinaryCoStreamMeta = { type: "binary" }
291
263
  >
292
- extends CoStreamView<BinaryStreamItem, Meta>
293
- implements CoValue
264
+ extends RawCoStreamView<BinaryStreamItem, Meta>
265
+ implements RawCoValue
294
266
  {
295
267
  getBinaryChunks(
296
- allowUnfinished?: boolean,
268
+ allowUnfinished?: boolean
297
269
  ):
298
270
  | (BinaryStreamInfo & { chunks: Uint8Array[]; finished: boolean })
299
271
  | undefined {
@@ -358,35 +330,21 @@ export class BinaryCoStreamView<
358
330
  }
359
331
  }
360
332
 
361
- export class BinaryCoStream<
333
+ export class RawBinaryCoStream<
362
334
  Meta extends BinaryCoStreamMeta = { type: "binary" }
363
335
  >
364
- extends BinaryCoStreamView<Meta>
365
- implements CoValue
336
+ extends RawBinaryCoStreamView<Meta>
337
+ implements RawCoValue
366
338
  {
367
339
  /** @internal */
368
- push(
369
- item: BinaryStreamItem,
370
- privacy?: "private" | "trusting",
371
- ): this
372
- push(
373
- item: BinaryStreamItem,
374
- privacy: "private" | "trusting",
375
- returnNewStream: true
376
- ): this
377
- push(
378
- item: BinaryStreamItem,
379
- privacy: "private" | "trusting",
380
- returnNewStream: false
381
- ): void
382
340
  push(
383
341
  item: BinaryStreamItem,
384
342
  privacy: "private" | "trusting" = "private",
385
- returnNewStream: boolean = true
386
- ): this | void {
343
+ updateView: boolean = true
344
+ ): void {
387
345
  this.core.makeTransaction([item], privacy);
388
- if (returnNewStream) {
389
- return new BinaryCoStream(this.core) as this;
346
+ if (updateView) {
347
+ this.fillFromCoValue();
390
348
  }
391
349
  }
392
350
 
@@ -394,7 +352,7 @@ export class BinaryCoStream<
394
352
  settings: BinaryStreamInfo,
395
353
  privacy: "private" | "trusting" = "private"
396
354
  ): void {
397
- return this.push(
355
+ this.push(
398
356
  {
399
357
  type: "start",
400
358
  ...settings,
@@ -409,7 +367,7 @@ export class BinaryCoStream<
409
367
  privacy: "private" | "trusting" = "private"
410
368
  ): void {
411
369
  // const before = performance.now();
412
- return this.push(
370
+ this.push(
413
371
  {
414
372
  type: "chunk",
415
373
  chunk: `binary_U${bytesToBase64url(chunk)}`,
@@ -424,77 +382,13 @@ export class BinaryCoStream<
424
382
  // );
425
383
  }
426
384
 
427
- endBinaryStream(privacy: "private" | "trusting" = "private"): this {
428
- return this.push(
429
- {
430
- type: "end",
431
- } satisfies BinaryStreamEnd,
432
- privacy,
433
- true
434
- );
435
- }
436
-
437
- mutate(mutator: (mutable: MutableBinaryCoStream<Meta>) => void): this {
438
- const mutable = new MutableBinaryCoStream<Meta>(this.core);
439
- mutator(mutable);
440
- return new BinaryCoStream(this.core) as this;
441
- }
442
-
443
- /** @deprecated Use `mutate` instead. */
444
- edit(mutator: (mutable: MutableBinaryCoStream<Meta>) => void): this {
445
- return this.mutate(mutator);
446
- }
447
- }
448
-
449
- export class MutableBinaryCoStream<
450
- Meta extends BinaryCoStreamMeta = { type: "binary" }
451
- >
452
- extends BinaryCoStreamView<Meta>
453
- implements CoValue
454
- {
455
- /** @internal */
456
- push(item: BinaryStreamItem, privacy: "private" | "trusting" = "private") {
457
- MutableCoStream.prototype.push.call(this, item, privacy);
458
- }
459
-
460
- startBinaryStream(
461
- settings: BinaryStreamInfo,
462
- privacy: "private" | "trusting" = "private"
463
- ) {
464
- this.push(
465
- {
466
- type: "start",
467
- ...settings,
468
- } satisfies BinaryStreamStart,
469
- privacy
470
- );
471
- }
472
-
473
- pushBinaryStreamChunk(
474
- chunk: Uint8Array,
475
- privacy: "private" | "trusting" = "private"
476
- ) {
477
- // const before = performance.now();
478
- this.push(
479
- {
480
- type: "chunk",
481
- chunk: `binary_U${bytesToBase64url(chunk)}`,
482
- } satisfies BinaryStreamChunk,
483
- privacy
484
- );
485
- // const after = performance.now();
486
- // console.log(
487
- // "pushBinaryStreamChunk bandwidth in MB/s",
488
- // (1000 * chunk.length) / (after - before) / (1024 * 1024)
489
- // );
490
- }
491
-
492
385
  endBinaryStream(privacy: "private" | "trusting" = "private") {
493
386
  this.push(
494
387
  {
495
388
  type: "end",
496
389
  } satisfies BinaryStreamEnd,
497
- privacy
390
+ privacy,
391
+ true
498
392
  );
499
393
  }
500
394
  }
@@ -1,8 +1,8 @@
1
1
  import { CoID } from "../coValue.js";
2
- import { CoMap } from "./coMap.js";
3
- import { CoList } from "./coList.js";
2
+ import { RawCoMap } from "./coMap.js";
3
+ import { RawCoList } from "./coList.js";
4
4
  import { JsonObject } from "../jsonValue.js";
5
- import { BinaryCoStream, CoStream } from "./coStream.js";
5
+ import { RawBinaryCoStream, RawCoStream } from "./coStream.js";
6
6
  import {
7
7
  Encrypted,
8
8
  KeyID,
@@ -18,16 +18,20 @@ import {
18
18
  getAgentID,
19
19
  } from "../crypto.js";
20
20
  import { AgentID, isAgentID } from "../ids.js";
21
- import { Account, AccountID, ControlledAccountOrAgent, Profile } from "./account.js";
21
+ import {
22
+ RawAccount,
23
+ AccountID,
24
+ ControlledAccountOrAgent,
25
+ } from "./account.js";
22
26
  import { Role } from "../permissions.js";
23
27
  import { base58 } from "@scure/base";
24
28
 
25
29
  export const EVERYONE = "everyone" as const;
26
30
  export type Everyone = "everyone";
27
31
 
28
- export type GroupShape<P extends Profile, R extends CoMap> = {
29
- profile?: CoID<P> | null;
30
- root?: CoID<R> | null;
32
+ export type GroupShape = {
33
+ profile: CoID<RawCoMap> | null;
34
+ root: CoID<RawCoMap> | null;
31
35
  [key: AccountID | AgentID]: Role;
32
36
  [EVERYONE]?: Role;
33
37
  readKey?: KeyID;
@@ -60,11 +64,9 @@ export type GroupShape<P extends Profile, R extends CoMap> = {
60
64
  * const localNode.createGroup();
61
65
  * ```
62
66
  * */
63
- export class Group<
64
- P extends Profile = Profile,
65
- R extends CoMap = CoMap,
67
+ export class RawGroup<
66
68
  Meta extends JsonObject | null = JsonObject | null
67
- > extends CoMap<GroupShape<P, R>, Meta> {
69
+ > extends RawCoMap<GroupShape, Meta> {
68
70
  /**
69
71
  * Returns the current role of a given account.
70
72
  *
@@ -94,16 +96,18 @@ export class Group<
94
96
  *
95
97
  * @category 2. Role changing
96
98
  */
97
- addMember(account: Account | ControlledAccountOrAgent | Everyone, role: Role): this {
98
- return this.addMemberInternal(account, role);
99
+ addMember(
100
+ account: RawAccount | ControlledAccountOrAgent | Everyone,
101
+ role: Role
102
+ ) {
103
+ this.addMemberInternal(account, role);
99
104
  }
100
105
 
101
106
  /** @internal */
102
107
  addMemberInternal(
103
- account: Account | ControlledAccountOrAgent | AgentID | Everyone,
108
+ account: RawAccount | ControlledAccountOrAgent | AgentID | Everyone,
104
109
  role: Role
105
- ): this {
106
- return this.mutate((mutable) => {
110
+ ) {
107
111
  const currentReadKey = this.core.getCurrentReadKey();
108
112
 
109
113
  if (!currentReadKey.secret) {
@@ -116,27 +120,31 @@ export class Group<
116
120
  "Can't make everyone something other than reader or writer"
117
121
  );
118
122
  }
119
- mutable.set(account, role, "trusting");
123
+ this.set(account, role, "trusting");
120
124
 
121
- if (mutable.get(account) !== role) {
125
+ if (this.get(account) !== role) {
122
126
  throw new Error("Failed to set role");
123
127
  }
124
128
 
125
- mutable.set(
129
+ this.set(
126
130
  `${currentReadKey.id}_for_${EVERYONE}`,
127
131
  currentReadKey.secret,
128
132
  "trusting"
129
133
  );
130
134
  } else {
131
- const memberKey = typeof account === "string" ? account : account.id;
132
- const agent = typeof account === "string" ? account : account.currentAgentID();
133
- mutable.set(memberKey, role, "trusting");
134
-
135
- if (mutable.get(memberKey) !== role) {
135
+ const memberKey =
136
+ typeof account === "string" ? account : account.id;
137
+ const agent =
138
+ typeof account === "string"
139
+ ? account
140
+ : account.currentAgentID();
141
+ this.set(memberKey, role, "trusting");
142
+
143
+ if (this.get(memberKey) !== role) {
136
144
  throw new Error("Failed to set role");
137
145
  }
138
146
 
139
- mutable.set(
147
+ this.set(
140
148
  `${currentReadKey.id}_for_${memberKey}`,
141
149
  seal({
142
150
  message: currentReadKey.secret,
@@ -150,11 +158,10 @@ export class Group<
150
158
  "trusting"
151
159
  );
152
160
  }
153
- });
154
161
  }
155
162
 
156
163
  /** @internal */
157
- rotateReadKey(): this {
164
+ rotateReadKey() {
158
165
  const currentlyPermittedReaders = this.keys().filter((key) => {
159
166
  if (key.startsWith("co_") || isAgentID(key)) {
160
167
  const role = this.get(key);
@@ -181,14 +188,13 @@ export class Group<
181
188
 
182
189
  const newReadKey = newRandomKeySecret();
183
190
 
184
- return this.mutate((mutable) => {
185
191
  for (const readerID of currentlyPermittedReaders) {
186
192
  const reader = this.core.node.resolveAccountAgent(
187
193
  readerID,
188
194
  "Expected to know currently permitted reader"
189
195
  );
190
196
 
191
- mutable.set(
197
+ this.set(
192
198
  `${newReadKey.id}_for_${readerID}`,
193
199
  seal({
194
200
  message: newReadKey.secret,
@@ -203,7 +209,7 @@ export class Group<
203
209
  );
204
210
  }
205
211
 
206
- mutable.set(
212
+ this.set(
207
213
  `${currentReadKey.id}_for_${newReadKey.id}`,
208
214
  encryptKeySecret({
209
215
  encrypting: newReadKey,
@@ -212,8 +218,7 @@ export class Group<
212
218
  "trusting"
213
219
  );
214
220
 
215
- mutable.set("readKey", newReadKey.id, "trusting");
216
- });
221
+ this.set("readKey", newReadKey.id, "trusting");
217
222
  }
218
223
 
219
224
  /**
@@ -223,16 +228,17 @@ export class Group<
223
228
  *
224
229
  * @category 2. Role changing
225
230
  */
226
- removeMember(account: Account | ControlledAccountOrAgent | Everyone): this {
227
- return this.removeMemberInternal(account);
231
+ removeMember(account: RawAccount | ControlledAccountOrAgent | Everyone) {
232
+ this.removeMemberInternal(account);
228
233
  }
229
234
 
230
235
  /** @internal */
231
- removeMemberInternal(account: Account | ControlledAccountOrAgent | AgentID | Everyone): this {
236
+ removeMemberInternal(
237
+ account: RawAccount | ControlledAccountOrAgent | AgentID | Everyone
238
+ ) {
232
239
  const memberKey = typeof account === "string" ? account : account.id;
233
- const afterRevoke = this.set(memberKey, "revoked", "trusting");
234
-
235
- return afterRevoke.rotateReadKey();
240
+ this.set(memberKey, "revoked", "trusting");
241
+ this.rotateReadKey();
236
242
  }
237
243
 
238
244
  /**
@@ -259,12 +265,12 @@ export class Group<
259
265
  *
260
266
  * @category 3. Value creation
261
267
  */
262
- createMap<M extends CoMap>(
268
+ createMap<M extends RawCoMap>(
263
269
  init?: M["_shape"],
264
270
  meta?: M["headerMeta"],
265
271
  initPrivacy: "trusting" | "private" = "private"
266
272
  ): M {
267
- let map = this.core.node
273
+ const map = this.core.node
268
274
  .createCoValue({
269
275
  type: "comap",
270
276
  ruleset: {
@@ -278,7 +284,7 @@ export class Group<
278
284
 
279
285
  if (init) {
280
286
  for (const [key, value] of Object.entries(init)) {
281
- map = map.set(key, value, initPrivacy);
287
+ map.set(key, value, initPrivacy);
282
288
  }
283
289
  }
284
290
 
@@ -291,12 +297,12 @@ export class Group<
291
297
  *
292
298
  * @category 3. Value creation
293
299
  */
294
- createList<L extends CoList>(
300
+ createList<L extends RawCoList>(
295
301
  init?: L["_item"][],
296
302
  meta?: L["headerMeta"],
297
303
  initPrivacy: "trusting" | "private" = "private"
298
304
  ): L {
299
- let list = this.core.node
305
+ const list = this.core.node
300
306
  .createCoValue({
301
307
  type: "colist",
302
308
  ruleset: {
@@ -310,7 +316,7 @@ export class Group<
310
316
 
311
317
  if (init) {
312
318
  for (const item of init) {
313
- list = list.append(item, undefined, initPrivacy);
319
+ list.append(item, undefined, initPrivacy);
314
320
  }
315
321
  }
316
322
 
@@ -318,7 +324,7 @@ export class Group<
318
324
  }
319
325
 
320
326
  /** @category 3. Value creation */
321
- createStream<C extends CoStream>(meta?: C["headerMeta"]): C {
327
+ createStream<C extends RawCoStream>(meta?: C["headerMeta"]): C {
322
328
  return this.core.node
323
329
  .createCoValue({
324
330
  type: "costream",
@@ -333,7 +339,7 @@ export class Group<
333
339
  }
334
340
 
335
341
  /** @category 3. Value creation */
336
- createBinaryStream<C extends BinaryCoStream>(
342
+ createBinaryStream<C extends RawBinaryCoStream>(
337
343
  meta: C["headerMeta"] = { type: "binary" }
338
344
  ): C {
339
345
  return this.core.node
@@ -1,10 +1,10 @@
1
1
  import type { CoValueCore } from "./coValueCore.js";
2
- import { Account } from "./coValues/account.js";
3
- import { Group } from "./coValues/group.js";
4
- import { CoMap } from "./coValues/coMap.js";
5
- import { CoList } from "./coValues/coList.js";
6
- import { CoStream } from "./coValues/coStream.js";
7
- import { BinaryCoStream } from "./coValues/coStream.js";
2
+ import { RawAccount, RawControlledAccount } from "./coValues/account.js";
3
+ import { RawGroup } from "./coValues/group.js";
4
+ import { RawCoMap } from "./coValues/coMap.js";
5
+ import { RawCoList } from "./coValues/coList.js";
6
+ import { RawCoStream } from "./coValues/coStream.js";
7
+ import { RawBinaryCoStream } from "./coValues/coStream.js";
8
8
 
9
9
  export function coreToCoValue(
10
10
  core: CoValueCore,
@@ -16,20 +16,24 @@ export function coreToCoValue(
16
16
  core.header.meta?.type === "account" &&
17
17
  !options?.ignorePrivateTransactions
18
18
  ) {
19
- return new Account(core);
19
+ if (core.id === core.node.account.id) {
20
+ return new RawControlledAccount(core, core.node.account.agentSecret);
21
+ } else {
22
+ return new RawAccount(core);
23
+ }
20
24
  } else {
21
- return new Group(core, options);
25
+ return new RawGroup(core, options);
22
26
  }
23
27
  } else {
24
- return new CoMap(core);
28
+ return new RawCoMap(core);
25
29
  }
26
30
  } else if (core.header.type === "colist") {
27
- return new CoList(core);
31
+ return new RawCoList(core);
28
32
  } else if (core.header.type === "costream") {
29
33
  if (core.header.meta && core.header.meta.type === "binary") {
30
- return new BinaryCoStream(core);
34
+ return new RawBinaryCoStream(core);
31
35
  } else {
32
- return new CoStream(core);
36
+ return new RawCoStream(core);
33
37
  }
34
38
  } else {
35
39
  throw new Error(`Unknown coValue type ${core.header.type}`);