cojson 0.8.12 → 0.8.17

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 (164) hide show
  1. package/CHANGELOG.md +95 -83
  2. package/dist/native/PeerKnownStates.js +6 -1
  3. package/dist/native/PeerKnownStates.js.map +1 -1
  4. package/dist/native/PeerState.js +4 -3
  5. package/dist/native/PeerState.js.map +1 -1
  6. package/dist/native/PriorityBasedMessageQueue.js +1 -10
  7. package/dist/native/PriorityBasedMessageQueue.js.map +1 -1
  8. package/dist/native/SyncStateSubscriptionManager.js +70 -0
  9. package/dist/native/SyncStateSubscriptionManager.js.map +1 -0
  10. package/dist/native/base64url.js.map +1 -1
  11. package/dist/native/base64url.test.js +1 -1
  12. package/dist/native/base64url.test.js.map +1 -1
  13. package/dist/native/coValue.js.map +1 -1
  14. package/dist/native/coValueCore.js +141 -149
  15. package/dist/native/coValueCore.js.map +1 -1
  16. package/dist/native/coValueState.js.map +1 -1
  17. package/dist/native/coValues/account.js +6 -6
  18. package/dist/native/coValues/account.js.map +1 -1
  19. package/dist/native/coValues/coList.js +2 -3
  20. package/dist/native/coValues/coList.js.map +1 -1
  21. package/dist/native/coValues/coMap.js +1 -1
  22. package/dist/native/coValues/coMap.js.map +1 -1
  23. package/dist/native/coValues/coStream.js +3 -5
  24. package/dist/native/coValues/coStream.js.map +1 -1
  25. package/dist/native/coValues/group.js +11 -11
  26. package/dist/native/coValues/group.js.map +1 -1
  27. package/dist/native/coreToCoValue.js +2 -2
  28. package/dist/native/coreToCoValue.js.map +1 -1
  29. package/dist/native/crypto/PureJSCrypto.js +4 -4
  30. package/dist/native/crypto/PureJSCrypto.js.map +1 -1
  31. package/dist/native/crypto/crypto.js.map +1 -1
  32. package/dist/native/exports.js +12 -12
  33. package/dist/native/exports.js.map +1 -1
  34. package/dist/native/ids.js.map +1 -1
  35. package/dist/native/jsonStringify.js.map +1 -1
  36. package/dist/native/localNode.js +5 -7
  37. package/dist/native/localNode.js.map +1 -1
  38. package/dist/native/permissions.js +4 -7
  39. package/dist/native/permissions.js.map +1 -1
  40. package/dist/native/priority.js.map +1 -1
  41. package/dist/native/storage/FileSystem.js.map +1 -1
  42. package/dist/native/storage/chunksAndKnownStates.js +2 -4
  43. package/dist/native/storage/chunksAndKnownStates.js.map +1 -1
  44. package/dist/native/storage/index.js +6 -15
  45. package/dist/native/storage/index.js.map +1 -1
  46. package/dist/native/streamUtils.js.map +1 -1
  47. package/dist/native/sync.js +57 -7
  48. package/dist/native/sync.js.map +1 -1
  49. package/dist/native/typeUtils/accountOrAgentIDfromSessionID.js.map +1 -1
  50. package/dist/native/typeUtils/expectGroup.js.map +1 -1
  51. package/dist/native/typeUtils/isAccountID.js.map +1 -1
  52. package/dist/native/typeUtils/isCoValue.js +1 -1
  53. package/dist/native/typeUtils/isCoValue.js.map +1 -1
  54. package/dist/web/PeerKnownStates.js +6 -1
  55. package/dist/web/PeerKnownStates.js.map +1 -1
  56. package/dist/web/PeerState.js +4 -3
  57. package/dist/web/PeerState.js.map +1 -1
  58. package/dist/web/PriorityBasedMessageQueue.js +1 -10
  59. package/dist/web/PriorityBasedMessageQueue.js.map +1 -1
  60. package/dist/web/SyncStateSubscriptionManager.js +70 -0
  61. package/dist/web/SyncStateSubscriptionManager.js.map +1 -0
  62. package/dist/web/base64url.js.map +1 -1
  63. package/dist/web/base64url.test.js +1 -1
  64. package/dist/web/base64url.test.js.map +1 -1
  65. package/dist/web/coValue.js.map +1 -1
  66. package/dist/web/coValueCore.js +141 -149
  67. package/dist/web/coValueCore.js.map +1 -1
  68. package/dist/web/coValueState.js.map +1 -1
  69. package/dist/web/coValues/account.js +6 -6
  70. package/dist/web/coValues/account.js.map +1 -1
  71. package/dist/web/coValues/coList.js +2 -3
  72. package/dist/web/coValues/coList.js.map +1 -1
  73. package/dist/web/coValues/coMap.js +1 -1
  74. package/dist/web/coValues/coMap.js.map +1 -1
  75. package/dist/web/coValues/coStream.js +3 -5
  76. package/dist/web/coValues/coStream.js.map +1 -1
  77. package/dist/web/coValues/group.js +11 -11
  78. package/dist/web/coValues/group.js.map +1 -1
  79. package/dist/web/coreToCoValue.js +2 -2
  80. package/dist/web/coreToCoValue.js.map +1 -1
  81. package/dist/web/crypto/PureJSCrypto.js +4 -4
  82. package/dist/web/crypto/PureJSCrypto.js.map +1 -1
  83. package/dist/web/crypto/WasmCrypto.js +5 -5
  84. package/dist/web/crypto/WasmCrypto.js.map +1 -1
  85. package/dist/web/crypto/crypto.js.map +1 -1
  86. package/dist/web/exports.js +12 -12
  87. package/dist/web/exports.js.map +1 -1
  88. package/dist/web/ids.js.map +1 -1
  89. package/dist/web/jsonStringify.js.map +1 -1
  90. package/dist/web/localNode.js +5 -7
  91. package/dist/web/localNode.js.map +1 -1
  92. package/dist/web/permissions.js +4 -7
  93. package/dist/web/permissions.js.map +1 -1
  94. package/dist/web/priority.js.map +1 -1
  95. package/dist/web/storage/FileSystem.js.map +1 -1
  96. package/dist/web/storage/chunksAndKnownStates.js +2 -4
  97. package/dist/web/storage/chunksAndKnownStates.js.map +1 -1
  98. package/dist/web/storage/index.js +6 -15
  99. package/dist/web/storage/index.js.map +1 -1
  100. package/dist/web/streamUtils.js.map +1 -1
  101. package/dist/web/sync.js +57 -7
  102. package/dist/web/sync.js.map +1 -1
  103. package/dist/web/typeUtils/accountOrAgentIDfromSessionID.js.map +1 -1
  104. package/dist/web/typeUtils/expectGroup.js.map +1 -1
  105. package/dist/web/typeUtils/isAccountID.js.map +1 -1
  106. package/dist/web/typeUtils/isCoValue.js +1 -1
  107. package/dist/web/typeUtils/isCoValue.js.map +1 -1
  108. package/package.json +4 -14
  109. package/src/PeerKnownStates.ts +98 -90
  110. package/src/PeerState.ts +92 -73
  111. package/src/PriorityBasedMessageQueue.ts +42 -49
  112. package/src/SyncStateSubscriptionManager.ts +124 -0
  113. package/src/base64url.test.ts +24 -24
  114. package/src/base64url.ts +44 -45
  115. package/src/coValue.ts +45 -45
  116. package/src/coValueCore.ts +746 -785
  117. package/src/coValueState.ts +82 -72
  118. package/src/coValues/account.ts +143 -150
  119. package/src/coValues/coList.ts +520 -522
  120. package/src/coValues/coMap.ts +283 -285
  121. package/src/coValues/coStream.ts +320 -324
  122. package/src/coValues/group.ts +306 -305
  123. package/src/coreToCoValue.ts +28 -31
  124. package/src/crypto/PureJSCrypto.ts +188 -194
  125. package/src/crypto/WasmCrypto.ts +236 -254
  126. package/src/crypto/crypto.ts +302 -309
  127. package/src/exports.ts +116 -116
  128. package/src/ids.ts +9 -9
  129. package/src/jsonStringify.ts +46 -46
  130. package/src/jsonValue.ts +24 -10
  131. package/src/localNode.ts +635 -660
  132. package/src/media.ts +3 -3
  133. package/src/permissions.ts +272 -278
  134. package/src/priority.ts +21 -19
  135. package/src/storage/FileSystem.ts +91 -99
  136. package/src/storage/chunksAndKnownStates.ts +110 -115
  137. package/src/storage/index.ts +466 -497
  138. package/src/streamUtils.ts +60 -60
  139. package/src/sync.ts +656 -608
  140. package/src/tests/PeerKnownStates.test.ts +38 -34
  141. package/src/tests/PeerState.test.ts +101 -64
  142. package/src/tests/PriorityBasedMessageQueue.test.ts +91 -91
  143. package/src/tests/SyncStateSubscriptionManager.test.ts +232 -0
  144. package/src/tests/account.test.ts +59 -59
  145. package/src/tests/coList.test.ts +65 -65
  146. package/src/tests/coMap.test.ts +137 -137
  147. package/src/tests/coStream.test.ts +254 -257
  148. package/src/tests/coValueCore.test.ts +153 -156
  149. package/src/tests/crypto.test.ts +136 -144
  150. package/src/tests/cryptoImpl.test.ts +205 -197
  151. package/src/tests/group.test.ts +24 -24
  152. package/src/tests/permissions.test.ts +1306 -1371
  153. package/src/tests/priority.test.ts +65 -82
  154. package/src/tests/sync.test.ts +1573 -1263
  155. package/src/tests/testUtils.ts +85 -53
  156. package/src/typeUtils/accountOrAgentIDfromSessionID.ts +4 -4
  157. package/src/typeUtils/expectGroup.ts +9 -9
  158. package/src/typeUtils/isAccountID.ts +1 -1
  159. package/src/typeUtils/isCoValue.ts +9 -9
  160. package/tsconfig.json +4 -6
  161. package/tsconfig.native.json +9 -11
  162. package/tsconfig.web.json +4 -10
  163. package/.eslintrc.cjs +0 -25
  164. package/.prettierrc.js +0 -9
@@ -1,33 +1,33 @@
1
+ import { expect, test } from "vitest";
1
2
  import { base64URLtoBytes, bytesToBase64url } from "./base64url.js";
2
- import { test, expect } from "vitest";
3
3
 
4
4
  const txt = new TextEncoder();
5
5
 
6
6
  test("Test our Base64 URL encoding and decoding", () => {
7
- // tests from the RFC
7
+ // tests from the RFC
8
8
 
9
- expect(base64URLtoBytes("")).toEqual(new Uint8Array([]));
10
- expect(bytesToBase64url(new Uint8Array([]))).toEqual("");
9
+ expect(base64URLtoBytes("")).toEqual(new Uint8Array([]));
10
+ expect(bytesToBase64url(new Uint8Array([]))).toEqual("");
11
11
 
12
- expect(bytesToBase64url(txt.encode("f"))).toEqual("Zg==");
13
- expect(bytesToBase64url(txt.encode("fo"))).toEqual("Zm8=");
14
- expect(bytesToBase64url(txt.encode("foo"))).toEqual("Zm9v");
15
- expect(bytesToBase64url(txt.encode("foob"))).toEqual("Zm9vYg==");
16
- expect(bytesToBase64url(txt.encode("fooba"))).toEqual("Zm9vYmE=");
17
- expect(bytesToBase64url(txt.encode("foobar"))).toEqual("Zm9vYmFy");
18
- // reverse
19
- expect(base64URLtoBytes("Zg==")).toEqual(txt.encode("f"));
20
- expect(base64URLtoBytes("Zm8=")).toEqual(txt.encode("fo"));
21
- expect(base64URLtoBytes("Zm9v")).toEqual(txt.encode("foo"));
22
- expect(base64URLtoBytes("Zm9vYg==")).toEqual(txt.encode("foob"));
23
- expect(base64URLtoBytes("Zm9vYmE=")).toEqual(txt.encode("fooba"));
24
- expect(base64URLtoBytes("Zm9vYmFy")).toEqual(txt.encode("foobar"));
12
+ expect(bytesToBase64url(txt.encode("f"))).toEqual("Zg==");
13
+ expect(bytesToBase64url(txt.encode("fo"))).toEqual("Zm8=");
14
+ expect(bytesToBase64url(txt.encode("foo"))).toEqual("Zm9v");
15
+ expect(bytesToBase64url(txt.encode("foob"))).toEqual("Zm9vYg==");
16
+ expect(bytesToBase64url(txt.encode("fooba"))).toEqual("Zm9vYmE=");
17
+ expect(bytesToBase64url(txt.encode("foobar"))).toEqual("Zm9vYmFy");
18
+ // reverse
19
+ expect(base64URLtoBytes("Zg==")).toEqual(txt.encode("f"));
20
+ expect(base64URLtoBytes("Zm8=")).toEqual(txt.encode("fo"));
21
+ expect(base64URLtoBytes("Zm9v")).toEqual(txt.encode("foo"));
22
+ expect(base64URLtoBytes("Zm9vYg==")).toEqual(txt.encode("foob"));
23
+ expect(base64URLtoBytes("Zm9vYmE=")).toEqual(txt.encode("fooba"));
24
+ expect(base64URLtoBytes("Zm9vYmFy")).toEqual(txt.encode("foobar"));
25
25
 
26
- expect(
27
- base64URLtoBytes("V2hhdCBkb2VzIDIgKyAyLjEgZXF1YWw_PyB-IDQ="),
28
- ).toEqual(txt.encode("What does 2 + 2.1 equal?? ~ 4"));
29
- // reverse
30
- expect(
31
- bytesToBase64url(txt.encode("What does 2 + 2.1 equal?? ~ 4")),
32
- ).toEqual("V2hhdCBkb2VzIDIgKyAyLjEgZXF1YWw_PyB-IDQ=");
26
+ expect(base64URLtoBytes("V2hhdCBkb2VzIDIgKyAyLjEgZXF1YWw_PyB-IDQ=")).toEqual(
27
+ txt.encode("What does 2 + 2.1 equal?? ~ 4"),
28
+ );
29
+ // reverse
30
+ expect(bytesToBase64url(txt.encode("What does 2 + 2.1 equal?? ~ 4"))).toEqual(
31
+ "V2hhdCBkb2VzIDIgKyAyLjEgZXF1YWw_PyB-IDQ=",
32
+ );
33
33
  });
package/src/base64url.ts CHANGED
@@ -2,67 +2,66 @@ const encoder = new TextEncoder();
2
2
  const decoder = new TextDecoder();
3
3
 
4
4
  export function base64URLtoBytes(base64: string) {
5
- base64 = base64.replace(/=/g, "");
6
- const n = base64.length;
7
- const rem = n % 4;
8
- const k = rem && rem - 1; // how many bytes the last base64 chunk encodes
9
- const m = (n >> 2) * 3 + k; // total encoded bytes
5
+ base64 = base64.replace(/=/g, "");
6
+ const n = base64.length;
7
+ const rem = n % 4;
8
+ const k = rem && rem - 1; // how many bytes the last base64 chunk encodes
9
+ const m = (n >> 2) * 3 + k; // total encoded bytes
10
10
 
11
- const encoded = new Uint8Array(n + 3);
12
- encoder.encodeInto(base64 + "===", encoded);
11
+ const encoded = new Uint8Array(n + 3);
12
+ encoder.encodeInto(base64 + "===", encoded);
13
13
 
14
- for (let i = 0, j = 0; i < n; i += 4, j += 3) {
15
- const x =
16
- (lookup[encoded[i]!]! << 18) +
17
- (lookup[encoded[i + 1]!]! << 12) +
18
- (lookup[encoded[i + 2]!]! << 6) +
19
- lookup[encoded[i + 3]!]!;
20
- encoded[j] = x >> 16;
21
- encoded[j + 1] = (x >> 8) & 0xff;
22
- encoded[j + 2] = x & 0xff;
23
- }
24
- return new Uint8Array(encoded.buffer, 0, m);
14
+ for (let i = 0, j = 0; i < n; i += 4, j += 3) {
15
+ const x =
16
+ (lookup[encoded[i]!]! << 18) +
17
+ (lookup[encoded[i + 1]!]! << 12) +
18
+ (lookup[encoded[i + 2]!]! << 6) +
19
+ lookup[encoded[i + 3]!]!;
20
+ encoded[j] = x >> 16;
21
+ encoded[j + 1] = (x >> 8) & 0xff;
22
+ encoded[j + 2] = x & 0xff;
23
+ }
24
+ return new Uint8Array(encoded.buffer, 0, m);
25
25
  }
26
26
 
27
27
  export function bytesToBase64url(bytes: Uint8Array) {
28
- // const before = performance.now();
29
- const m = bytes.length;
30
- const k = m % 3;
31
- const n = Math.floor(m / 3) * 4 + (k && k + 1);
32
- const N = Math.ceil(m / 3) * 4;
33
- const encoded = new Uint8Array(N);
28
+ // const before = performance.now();
29
+ const m = bytes.length;
30
+ const k = m % 3;
31
+ const n = Math.floor(m / 3) * 4 + (k && k + 1);
32
+ const N = Math.ceil(m / 3) * 4;
33
+ const encoded = new Uint8Array(N);
34
34
 
35
- for (let i = 0, j = 0; j < m; i += 4, j += 3) {
36
- const y =
37
- (bytes[j]! << 16) + (bytes[j + 1]! << 8) + (bytes[j + 2]! | 0);
38
- encoded[i] = encodeLookup[y >> 18]!;
39
- encoded[i + 1] = encodeLookup[(y >> 12) & 0x3f]!;
40
- encoded[i + 2] = encodeLookup[(y >> 6) & 0x3f]!;
41
- encoded[i + 3] = encodeLookup[y & 0x3f]!;
42
- }
35
+ for (let i = 0, j = 0; j < m; i += 4, j += 3) {
36
+ const y = (bytes[j]! << 16) + (bytes[j + 1]! << 8) + (bytes[j + 2]! | 0);
37
+ encoded[i] = encodeLookup[y >> 18]!;
38
+ encoded[i + 1] = encodeLookup[(y >> 12) & 0x3f]!;
39
+ encoded[i + 2] = encodeLookup[(y >> 6) & 0x3f]!;
40
+ encoded[i + 3] = encodeLookup[y & 0x3f]!;
41
+ }
43
42
 
44
- let base64 = decoder.decode(new Uint8Array(encoded.buffer, 0, n));
45
- if (k === 1) base64 += "==";
46
- if (k === 2) base64 += "=";
47
- // const after = performance.now();
48
- // console.log(
49
- // "bytesToBase64url bandwidth in MB/s for length",
50
- // (1000 * bytes.length / (after - before)) / (1024 * 1024),
51
- // bytes.length
52
- // );
53
- return base64;
43
+ let base64 = decoder.decode(new Uint8Array(encoded.buffer, 0, n));
44
+ if (k === 1) base64 += "==";
45
+ if (k === 2) base64 += "=";
46
+ // const after = performance.now();
47
+ // console.log(
48
+ // "bytesToBase64url bandwidth in MB/s for length",
49
+ // (1000 * bytes.length / (after - before)) / (1024 * 1024),
50
+ // bytes.length
51
+ // );
52
+ return base64;
54
53
  }
55
54
 
56
55
  const alphabet =
57
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
56
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
58
57
 
59
58
  const lookup = new Uint8Array(128);
60
59
  for (const [i, a] of Array.from(alphabet).entries()) {
61
- lookup[a.charCodeAt(0)] = i;
60
+ lookup[a.charCodeAt(0)] = i;
62
61
  }
63
62
  lookup["=".charCodeAt(0)] = 0;
64
63
 
65
64
  const encodeLookup = new Uint8Array(64);
66
65
  for (const [i, a] of Array.from(alphabet).entries()) {
67
- encodeLookup[i] = a.charCodeAt(0);
66
+ encodeLookup[i] = a.charCodeAt(0);
68
67
  }
package/src/coValue.ts CHANGED
@@ -1,68 +1,68 @@
1
- import { JsonObject, JsonValue } from "./jsonValue.js";
2
- import { RawCoID } from "./ids.js";
1
+ import { CoValueCore } from "./coValueCore.js";
2
+ import { RawProfile as Profile, RawAccount } from "./coValues/account.js";
3
+ import { RawCoList } from "./coValues/coList.js";
3
4
  import { RawCoMap } from "./coValues/coMap.js";
4
5
  import { RawBinaryCoStream, RawCoStream } from "./coValues/coStream.js";
5
- import { RawCoList } from "./coValues/coList.js";
6
- import { CoValueCore } from "./coValueCore.js";
7
6
  import { RawGroup } from "./coValues/group.js";
8
- import { RawAccount, RawProfile as Profile } from "./coValues/account.js";
7
+ import { RawCoID } from "./ids.js";
8
+ import { JsonObject, JsonValue } from "./jsonValue.js";
9
9
 
10
10
  export type CoID<T extends RawCoValue> = RawCoID & {
11
- readonly __type: T;
11
+ readonly __type: T;
12
12
  };
13
13
 
14
14
  export interface RawCoValue {
15
- /** The `CoValue`'s (precisely typed) `CoID` */
16
- id: CoID<this>;
17
- core: CoValueCore;
18
- /** Specifies which kind of `CoValue` this is */
19
- type: string;
20
- /** The `CoValue`'s (precisely typed) static metadata */
21
- headerMeta: JsonObject | null;
22
- /** The `Group` this `CoValue` belongs to (determining permissions) */
23
- group: RawGroup;
24
- /** Returns an immutable JSON presentation of this `CoValue` */
25
- toJSON(): JsonValue;
26
- atTime(time: number): this;
27
- /** Lets you subscribe to future updates to this CoValue (whether made locally or by other users).
28
- *
29
- * Takes a listener function that will be called with the current state for each update.
30
- *
31
- * Returns an unsubscribe function.
32
- *
33
- * Used internally by `useTelepathicData()` for reactive updates on changes to a `CoValue`. */
34
- subscribe(listener: (coValue: this) => void): () => void;
15
+ /** The `CoValue`'s (precisely typed) `CoID` */
16
+ id: CoID<this>;
17
+ core: CoValueCore;
18
+ /** Specifies which kind of `CoValue` this is */
19
+ type: string;
20
+ /** The `CoValue`'s (precisely typed) static metadata */
21
+ headerMeta: JsonObject | null;
22
+ /** The `Group` this `CoValue` belongs to (determining permissions) */
23
+ group: RawGroup;
24
+ /** Returns an immutable JSON presentation of this `CoValue` */
25
+ toJSON(): JsonValue;
26
+ atTime(time: number): this;
27
+ /** Lets you subscribe to future updates to this CoValue (whether made locally or by other users).
28
+ *
29
+ * Takes a listener function that will be called with the current state for each update.
30
+ *
31
+ * Returns an unsubscribe function.
32
+ *
33
+ * Used internally by `useTelepathicData()` for reactive updates on changes to a `CoValue`. */
34
+ subscribe(listener: (coValue: this) => void): () => void;
35
35
  }
36
36
 
37
37
  export type AnyRawCoValue =
38
- | RawCoMap
39
- | RawGroup
40
- | RawAccount
41
- | Profile
42
- | RawCoList
43
- | RawCoStream
44
- | RawBinaryCoStream;
38
+ | RawCoMap
39
+ | RawGroup
40
+ | RawAccount
41
+ | Profile
42
+ | RawCoList
43
+ | RawCoStream
44
+ | RawBinaryCoStream;
45
45
 
46
46
  export function expectMap(content: RawCoValue): RawCoMap {
47
- if (content.type !== "comap") {
48
- throw new Error("Expected map");
49
- }
47
+ if (content.type !== "comap") {
48
+ throw new Error("Expected map");
49
+ }
50
50
 
51
- return content as RawCoMap;
51
+ return content as RawCoMap;
52
52
  }
53
53
 
54
54
  export function expectList(content: RawCoValue): RawCoList {
55
- if (content.type !== "colist") {
56
- throw new Error("Expected list");
57
- }
55
+ if (content.type !== "colist") {
56
+ throw new Error("Expected list");
57
+ }
58
58
 
59
- return content as RawCoList;
59
+ return content as RawCoList;
60
60
  }
61
61
 
62
62
  export function expectStream(content: RawCoValue): RawCoStream {
63
- if (content.type !== "costream") {
64
- throw new Error("Expected stream");
65
- }
63
+ if (content.type !== "costream") {
64
+ throw new Error("Expected stream");
65
+ }
66
66
 
67
- return content as RawCoStream;
67
+ return content as RawCoStream;
68
68
  }