cojson 0.8.0 → 0.8.5

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 (210) hide show
  1. package/.turbo/turbo-build.log +11 -3
  2. package/CHANGELOG.md +13 -0
  3. package/dist/native/PeerState.js.map +1 -0
  4. package/dist/native/PriorityBasedMessageQueue.js.map +1 -0
  5. package/dist/native/base64url.js.map +1 -0
  6. package/dist/native/base64url.test.js.map +1 -0
  7. package/dist/native/coValue.js.map +1 -0
  8. package/dist/native/coValueCore.js.map +1 -0
  9. package/dist/native/coValues/account.js.map +1 -0
  10. package/dist/native/coValues/coList.js.map +1 -0
  11. package/dist/native/coValues/coMap.js.map +1 -0
  12. package/dist/native/coValues/coStream.js.map +1 -0
  13. package/dist/native/coValues/group.js.map +1 -0
  14. package/dist/native/coreToCoValue.js.map +1 -0
  15. package/dist/{crypto → native/crypto}/PureJSCrypto.js +4 -0
  16. package/dist/native/crypto/PureJSCrypto.js.map +1 -0
  17. package/dist/{crypto → native/crypto}/crypto.js +1 -1
  18. package/dist/native/crypto/crypto.js.map +1 -0
  19. package/dist/native/ids.js.map +1 -0
  20. package/dist/{index.js → native/index.native.js} +3 -4
  21. package/dist/native/index.native.js.map +1 -0
  22. package/dist/native/jsonStringify.js.map +1 -0
  23. package/dist/{jsonValue.js.map → native/jsonValue.js.map} +1 -1
  24. package/dist/{localNode.js → native/localNode.js} +50 -33
  25. package/dist/native/localNode.js.map +1 -0
  26. package/dist/native/media.js.map +1 -0
  27. package/dist/native/permissions.js.map +1 -0
  28. package/dist/native/priority.js.map +1 -0
  29. package/dist/native/storage/FileSystem.js.map +1 -0
  30. package/dist/{storage → native/storage}/chunksAndKnownStates.js +1 -1
  31. package/dist/native/storage/chunksAndKnownStates.js.map +1 -0
  32. package/dist/native/storage/index.js.map +1 -0
  33. package/dist/native/streamUtils.js.map +1 -0
  34. package/dist/native/sync.js.map +1 -0
  35. package/dist/native/typeUtils/accountOrAgentIDfromSessionID.js.map +1 -0
  36. package/dist/native/typeUtils/expectGroup.js.map +1 -0
  37. package/dist/native/typeUtils/isAccountID.js.map +1 -0
  38. package/dist/native/typeUtils/isCoValue.js.map +1 -0
  39. package/dist/web/PeerState.js +66 -0
  40. package/dist/web/PeerState.js.map +1 -0
  41. package/dist/web/PriorityBasedMessageQueue.js +51 -0
  42. package/dist/web/PriorityBasedMessageQueue.js.map +1 -0
  43. package/dist/web/base64url.js +59 -0
  44. package/dist/web/base64url.js.map +1 -0
  45. package/dist/web/base64url.test.js +25 -0
  46. package/dist/web/base64url.test.js.map +1 -0
  47. package/dist/web/coValue.js +19 -0
  48. package/dist/web/coValue.js.map +1 -0
  49. package/dist/web/coValueCore.js +693 -0
  50. package/dist/web/coValueCore.js.map +1 -0
  51. package/dist/web/coValues/account.js +96 -0
  52. package/dist/web/coValues/account.js.map +1 -0
  53. package/dist/web/coValues/coList.js +393 -0
  54. package/dist/web/coValues/coList.js.map +1 -0
  55. package/dist/web/coValues/coMap.js +197 -0
  56. package/dist/web/coValues/coMap.js.map +1 -0
  57. package/dist/web/coValues/coStream.js +220 -0
  58. package/dist/web/coValues/coStream.js.map +1 -0
  59. package/dist/web/coValues/group.js +250 -0
  60. package/dist/web/coValues/group.js.map +1 -0
  61. package/dist/web/coreToCoValue.js +42 -0
  62. package/dist/web/coreToCoValue.js.map +1 -0
  63. package/dist/web/crypto/PureJSCrypto.js +93 -0
  64. package/dist/web/crypto/PureJSCrypto.js.map +1 -0
  65. package/dist/{crypto → web/crypto}/WasmCrypto.js +3 -0
  66. package/dist/web/crypto/WasmCrypto.js.map +1 -0
  67. package/dist/web/crypto/crypto.js +154 -0
  68. package/dist/web/crypto/crypto.js.map +1 -0
  69. package/dist/web/ids.js +17 -0
  70. package/dist/web/ids.js.map +1 -0
  71. package/dist/web/index.web.js +40 -0
  72. package/dist/web/index.web.js.map +1 -0
  73. package/dist/web/jsonStringify.js +57 -0
  74. package/dist/web/jsonStringify.js.map +1 -0
  75. package/dist/web/jsonValue.js +2 -0
  76. package/dist/web/jsonValue.js.map +1 -0
  77. package/dist/web/localNode.js +453 -0
  78. package/dist/web/localNode.js.map +1 -0
  79. package/dist/web/media.js +2 -0
  80. package/dist/web/media.js.map +1 -0
  81. package/dist/web/permissions.js +206 -0
  82. package/dist/web/permissions.js.map +1 -0
  83. package/dist/web/priority.js +31 -0
  84. package/dist/web/priority.js.map +1 -0
  85. package/dist/web/storage/FileSystem.js +58 -0
  86. package/dist/web/storage/FileSystem.js.map +1 -0
  87. package/dist/web/storage/chunksAndKnownStates.js +100 -0
  88. package/dist/web/storage/chunksAndKnownStates.js.map +1 -0
  89. package/dist/web/storage/index.js +348 -0
  90. package/dist/web/storage/index.js.map +1 -0
  91. package/dist/web/streamUtils.js +41 -0
  92. package/dist/web/streamUtils.js.map +1 -0
  93. package/dist/web/sync.js +504 -0
  94. package/dist/web/sync.js.map +1 -0
  95. package/dist/web/typeUtils/accountOrAgentIDfromSessionID.js +5 -0
  96. package/dist/web/typeUtils/accountOrAgentIDfromSessionID.js.map +1 -0
  97. package/dist/web/typeUtils/expectGroup.js +13 -0
  98. package/dist/web/typeUtils/expectGroup.js.map +1 -0
  99. package/dist/web/typeUtils/isAccountID.js +4 -0
  100. package/dist/web/typeUtils/isAccountID.js.map +1 -0
  101. package/dist/web/typeUtils/isCoValue.js +11 -0
  102. package/dist/web/typeUtils/isCoValue.js.map +1 -0
  103. package/package.json +25 -8
  104. package/src/coValue.ts +1 -1
  105. package/src/coValueCore.ts +4 -1
  106. package/src/coValues/account.ts +9 -3
  107. package/src/crypto/PureJSCrypto.ts +5 -0
  108. package/src/crypto/WasmCrypto.ts +4 -0
  109. package/src/crypto/crypto.ts +7 -2
  110. package/src/{index.ts → index.native.ts} +4 -5
  111. package/src/index.web.ts +152 -0
  112. package/src/jsonValue.ts +25 -0
  113. package/src/localNode.ts +74 -55
  114. package/src/storage/chunksAndKnownStates.ts +1 -1
  115. package/src/storage/index.ts +1 -1
  116. package/src/tests/coList.test.ts +1 -1
  117. package/src/tests/coMap.test.ts +1 -1
  118. package/src/tests/coStream.test.ts +2 -1
  119. package/src/tests/cryptoImpl.test.ts +24 -2
  120. package/src/tests/group.test.ts +6 -8
  121. package/src/tests/permissions.test.ts +66 -18
  122. package/src/tests/priority.test.ts +44 -15
  123. package/tsconfig.json +5 -4
  124. package/tsconfig.native.json +12 -0
  125. package/tsconfig.web.json +11 -0
  126. package/dist/PeerState.js.map +0 -1
  127. package/dist/PriorityBasedMessageQueue.js.map +0 -1
  128. package/dist/base64url.js.map +0 -1
  129. package/dist/base64url.test.js.map +0 -1
  130. package/dist/coValue.js.map +0 -1
  131. package/dist/coValueCore.js.map +0 -1
  132. package/dist/coValues/account.js.map +0 -1
  133. package/dist/coValues/coList.js.map +0 -1
  134. package/dist/coValues/coMap.js.map +0 -1
  135. package/dist/coValues/coStream.js.map +0 -1
  136. package/dist/coValues/group.js.map +0 -1
  137. package/dist/coreToCoValue.js.map +0 -1
  138. package/dist/crypto/PureJSCrypto.js.map +0 -1
  139. package/dist/crypto/WasmCrypto.js.map +0 -1
  140. package/dist/crypto/crypto.js.map +0 -1
  141. package/dist/ids.js.map +0 -1
  142. package/dist/index.js.map +0 -1
  143. package/dist/jsonStringify.js.map +0 -1
  144. package/dist/localNode.js.map +0 -1
  145. package/dist/media.js.map +0 -1
  146. package/dist/permissions.js.map +0 -1
  147. package/dist/priority.js.map +0 -1
  148. package/dist/storage/FileSystem.js.map +0 -1
  149. package/dist/storage/chunksAndKnownStates.js.map +0 -1
  150. package/dist/storage/index.js.map +0 -1
  151. package/dist/streamUtils.js.map +0 -1
  152. package/dist/sync.js.map +0 -1
  153. package/dist/tests/PeerState.test.js +0 -80
  154. package/dist/tests/PeerState.test.js.map +0 -1
  155. package/dist/tests/PriorityBasedMessageQueue.test.js +0 -97
  156. package/dist/tests/PriorityBasedMessageQueue.test.js.map +0 -1
  157. package/dist/tests/account.test.js +0 -58
  158. package/dist/tests/account.test.js.map +0 -1
  159. package/dist/tests/coList.test.js +0 -76
  160. package/dist/tests/coList.test.js.map +0 -1
  161. package/dist/tests/coMap.test.js +0 -136
  162. package/dist/tests/coMap.test.js.map +0 -1
  163. package/dist/tests/coStream.test.js +0 -205
  164. package/dist/tests/coStream.test.js.map +0 -1
  165. package/dist/tests/coValueCore.test.js +0 -124
  166. package/dist/tests/coValueCore.test.js.map +0 -1
  167. package/dist/tests/crypto.test.js +0 -118
  168. package/dist/tests/crypto.test.js.map +0 -1
  169. package/dist/tests/cryptoImpl.test.js +0 -113
  170. package/dist/tests/cryptoImpl.test.js.map +0 -1
  171. package/dist/tests/group.test.js +0 -34
  172. package/dist/tests/group.test.js.map +0 -1
  173. package/dist/tests/permissions.test.js +0 -1059
  174. package/dist/tests/permissions.test.js.map +0 -1
  175. package/dist/tests/priority.test.js +0 -61
  176. package/dist/tests/priority.test.js.map +0 -1
  177. package/dist/tests/sync.test.js +0 -1186
  178. package/dist/tests/sync.test.js.map +0 -1
  179. package/dist/tests/testUtils.js +0 -59
  180. package/dist/tests/testUtils.js.map +0 -1
  181. package/dist/typeUtils/accountOrAgentIDfromSessionID.js.map +0 -1
  182. package/dist/typeUtils/expectGroup.js.map +0 -1
  183. package/dist/typeUtils/isAccountID.js.map +0 -1
  184. package/dist/typeUtils/isCoValue.js.map +0 -1
  185. /package/dist/{PeerState.js → native/PeerState.js} +0 -0
  186. /package/dist/{PriorityBasedMessageQueue.js → native/PriorityBasedMessageQueue.js} +0 -0
  187. /package/dist/{base64url.js → native/base64url.js} +0 -0
  188. /package/dist/{base64url.test.js → native/base64url.test.js} +0 -0
  189. /package/dist/{coValue.js → native/coValue.js} +0 -0
  190. /package/dist/{coValueCore.js → native/coValueCore.js} +0 -0
  191. /package/dist/{coValues → native/coValues}/account.js +0 -0
  192. /package/dist/{coValues → native/coValues}/coList.js +0 -0
  193. /package/dist/{coValues → native/coValues}/coMap.js +0 -0
  194. /package/dist/{coValues → native/coValues}/coStream.js +0 -0
  195. /package/dist/{coValues → native/coValues}/group.js +0 -0
  196. /package/dist/{coreToCoValue.js → native/coreToCoValue.js} +0 -0
  197. /package/dist/{ids.js → native/ids.js} +0 -0
  198. /package/dist/{jsonStringify.js → native/jsonStringify.js} +0 -0
  199. /package/dist/{jsonValue.js → native/jsonValue.js} +0 -0
  200. /package/dist/{media.js → native/media.js} +0 -0
  201. /package/dist/{permissions.js → native/permissions.js} +0 -0
  202. /package/dist/{priority.js → native/priority.js} +0 -0
  203. /package/dist/{storage → native/storage}/FileSystem.js +0 -0
  204. /package/dist/{storage → native/storage}/index.js +0 -0
  205. /package/dist/{streamUtils.js → native/streamUtils.js} +0 -0
  206. /package/dist/{sync.js → native/sync.js} +0 -0
  207. /package/dist/{typeUtils → native/typeUtils}/accountOrAgentIDfromSessionID.js +0 -0
  208. /package/dist/{typeUtils → native/typeUtils}/expectGroup.js +0 -0
  209. /package/dist/{typeUtils → native/typeUtils}/isAccountID.js +0 -0
  210. /package/dist/{typeUtils → native/typeUtils}/isCoValue.js +0 -0
@@ -0,0 +1,197 @@
1
+ import { isCoValue } from "../typeUtils/isCoValue.js";
2
+ import { accountOrAgentIDfromSessionID } from "../typeUtils/accountOrAgentIDfromSessionID.js";
3
+ export class RawCoMapView {
4
+ /** @internal */
5
+ constructor(core, options) {
6
+ /** @category 6. Meta */
7
+ this.type = "comap";
8
+ /** @internal */
9
+ this.atTimeFilter = undefined;
10
+ this.id = core.id;
11
+ this.core = core;
12
+ this.ops = {};
13
+ for (const { txID, changes, madeAt } of core.getValidSortedTransactions(options)) {
14
+ for (const [changeIdx, changeUntyped] of changes.entries()) {
15
+ const change = changeUntyped;
16
+ let entries = this.ops[change.key];
17
+ if (!entries) {
18
+ entries = [];
19
+ this.ops[change.key] = entries;
20
+ }
21
+ entries.push({
22
+ txID,
23
+ madeAt,
24
+ changeIdx,
25
+ ...change,
26
+ });
27
+ }
28
+ }
29
+ }
30
+ /** @category 6. Meta */
31
+ get headerMeta() {
32
+ return this.core.header.meta;
33
+ }
34
+ /** @category 6. Meta */
35
+ get group() {
36
+ return this.core.getGroup();
37
+ }
38
+ /** @category 4. Time travel */
39
+ atTime(time) {
40
+ const clone = Object.create(this);
41
+ clone.id = this.id;
42
+ clone.type = this.type;
43
+ clone.core = this.core;
44
+ clone.ops = this.ops;
45
+ clone.atTimeFilter = time;
46
+ return clone;
47
+ }
48
+ /** @internal */
49
+ timeFilteredOps(key) {
50
+ if (this.atTimeFilter) {
51
+ return this.ops[key]?.filter((op) => op.madeAt <= this.atTimeFilter);
52
+ }
53
+ else {
54
+ return this.ops[key];
55
+ }
56
+ }
57
+ /**
58
+ * Get all keys currently in the map.
59
+ *
60
+ * @category 1. Reading */
61
+ keys() {
62
+ return Object.keys(this.ops).filter((key) => {
63
+ const ops = this.ops[key];
64
+ if (!ops) {
65
+ return undefined;
66
+ }
67
+ const includeUntil = this.atTimeFilter;
68
+ const lastEntry = includeUntil
69
+ ? ops.findLast((entry) => entry.madeAt <= includeUntil)
70
+ : ops[ops.length - 1];
71
+ if (lastEntry?.op === "del") {
72
+ return false;
73
+ }
74
+ else {
75
+ return true;
76
+ }
77
+ });
78
+ }
79
+ /**
80
+ * Returns the current value for the given key.
81
+ *
82
+ * @category 1. Reading
83
+ **/
84
+ get(key) {
85
+ const ops = this.ops[key];
86
+ if (!ops) {
87
+ return undefined;
88
+ }
89
+ const includeUntil = this.atTimeFilter;
90
+ const lastEntry = includeUntil
91
+ ? ops.findLast((entry) => entry.madeAt <= includeUntil)
92
+ : ops[ops.length - 1];
93
+ if (lastEntry?.op === "del") {
94
+ return undefined;
95
+ }
96
+ else {
97
+ return lastEntry?.value;
98
+ }
99
+ }
100
+ /** @category 1. Reading */
101
+ asObject() {
102
+ const object = {};
103
+ for (const key of this.keys()) {
104
+ const value = this.get(key);
105
+ if (value !== undefined) {
106
+ object[key] = value;
107
+ }
108
+ }
109
+ return object;
110
+ }
111
+ /** @category 1. Reading */
112
+ toJSON() {
113
+ return this.asObject();
114
+ }
115
+ /** @category 5. Edit history */
116
+ nthEditAt(key, n) {
117
+ const ops = this.timeFilteredOps(key);
118
+ if (!ops || ops.length <= n) {
119
+ return undefined;
120
+ }
121
+ const entry = ops[n];
122
+ if (this.atTimeFilter && entry.madeAt > this.atTimeFilter) {
123
+ return undefined;
124
+ }
125
+ return {
126
+ by: accountOrAgentIDfromSessionID(entry.txID.sessionID),
127
+ tx: entry.txID,
128
+ at: new Date(entry.madeAt),
129
+ value: entry.op === "del" ? undefined : entry.value,
130
+ };
131
+ }
132
+ /** @category 5. Edit history */
133
+ lastEditAt(key) {
134
+ const ops = this.timeFilteredOps(key);
135
+ if (!ops || ops.length === 0) {
136
+ return undefined;
137
+ }
138
+ return this.nthEditAt(key, ops.length - 1);
139
+ }
140
+ /** @category 5. Edit history */
141
+ *editsAt(key) {
142
+ const ops = this.timeFilteredOps(key);
143
+ if (!ops) {
144
+ return;
145
+ }
146
+ for (let i = 0; i < ops.length; i++) {
147
+ yield this.nthEditAt(key, i);
148
+ }
149
+ }
150
+ /** @category 3. Subscription */
151
+ subscribe(listener) {
152
+ return this.core.subscribe((content) => {
153
+ listener(content);
154
+ });
155
+ }
156
+ }
157
+ /** A collaborative map with precise shape `Shape` and optional static metadata `Meta` */
158
+ export class RawCoMap extends RawCoMapView {
159
+ /** Set a new value for the given key.
160
+ *
161
+ * If `privacy` is `"private"` **(default)**, both `key` and `value` are encrypted in the transaction, only readable by other members of the group this `CoMap` belongs to. Not even sync servers can see the content in plaintext.
162
+ *
163
+ * If `privacy` is `"trusting"`, both `key` and `value` are stored in plaintext in the transaction, visible to everyone who gets a hold of it, including sync servers.
164
+ *
165
+ * @category 2. Editing
166
+ **/
167
+ set(key, value, privacy = "private") {
168
+ this.core.makeTransaction([
169
+ {
170
+ op: "set",
171
+ key,
172
+ value: isCoValue(value) ? value.id : value,
173
+ },
174
+ ], privacy);
175
+ const after = new RawCoMap(this.core);
176
+ this.ops = after.ops;
177
+ }
178
+ /** Delete the given key (setting it to undefined).
179
+ *
180
+ * If `privacy` is `"private"` **(default)**, `key` is encrypted in the transaction, only readable by other members of the group this `CoMap` belongs to. Not even sync servers can see the content in plaintext.
181
+ *
182
+ * If `privacy` is `"trusting"`, `key` is stored in plaintext in the transaction, visible to everyone who gets a hold of it, including sync servers.
183
+ *
184
+ * @category 2. Editing
185
+ **/
186
+ delete(key, privacy = "private") {
187
+ this.core.makeTransaction([
188
+ {
189
+ op: "del",
190
+ key,
191
+ },
192
+ ], privacy);
193
+ const after = new RawCoMap(this.core);
194
+ this.ops = after.ops;
195
+ }
196
+ }
197
+ //# sourceMappingURL=coMap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coMap.js","sourceRoot":"","sources":["../../../src/coValues/coMap.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,220 @@
1
+ import { isAccountID } from "../typeUtils/isAccountID.js";
2
+ import { isCoValue } from "../typeUtils/isCoValue.js";
3
+ import { accountOrAgentIDfromSessionID } from "../typeUtils/accountOrAgentIDfromSessionID.js";
4
+ import { base64URLtoBytes, bytesToBase64url } from "../base64url.js";
5
+ export class RawCoStreamView {
6
+ constructor(core) {
7
+ this.type = "costream";
8
+ this.id = core.id;
9
+ this.core = core;
10
+ this.items = {};
11
+ this.fillFromCoValue();
12
+ }
13
+ get headerMeta() {
14
+ return this.core.header.meta;
15
+ }
16
+ get group() {
17
+ return this.core.getGroup();
18
+ }
19
+ /** Not yet implemented */
20
+ atTime(_time) {
21
+ throw new Error("Not yet implemented");
22
+ }
23
+ /** @internal */
24
+ fillFromCoValue() {
25
+ this.items = {};
26
+ for (const { txID, madeAt, changes, } of this.core.getValidSortedTransactions()) {
27
+ for (const changeUntyped of changes) {
28
+ const change = changeUntyped;
29
+ let entries = this.items[txID.sessionID];
30
+ if (!entries) {
31
+ entries = [];
32
+ this.items[txID.sessionID] = entries;
33
+ }
34
+ entries.push({ value: change, madeAt, tx: txID });
35
+ }
36
+ }
37
+ }
38
+ getSingleStream() {
39
+ const streams = Object.values(this.items);
40
+ const firstStream = streams[0];
41
+ if (!firstStream) {
42
+ return undefined;
43
+ }
44
+ if (streams.length > 1) {
45
+ throw new Error("CoStream.getSingleStream() can only be called when there is exactly one stream");
46
+ }
47
+ return firstStream.map((item) => item.value);
48
+ }
49
+ sessions() {
50
+ return Object.keys(this.items);
51
+ }
52
+ accounts() {
53
+ return new Set(this.sessions()
54
+ .map(accountOrAgentIDfromSessionID)
55
+ .filter(isAccountID));
56
+ }
57
+ nthItemIn(sessionID, n) {
58
+ const items = this.items[sessionID];
59
+ if (!items)
60
+ return;
61
+ const item = items[n];
62
+ if (!item)
63
+ return;
64
+ return {
65
+ by: accountOrAgentIDfromSessionID(sessionID),
66
+ tx: item.tx,
67
+ at: new Date(item.madeAt),
68
+ value: item.value,
69
+ };
70
+ }
71
+ lastItemIn(sessionID) {
72
+ const items = this.items[sessionID];
73
+ if (!items)
74
+ return;
75
+ return this.nthItemIn(sessionID, items.length - 1);
76
+ }
77
+ *itemsIn(sessionID) {
78
+ const items = this.items[sessionID];
79
+ if (!items)
80
+ return;
81
+ for (const item of items) {
82
+ yield {
83
+ by: accountOrAgentIDfromSessionID(sessionID),
84
+ tx: item.tx,
85
+ at: new Date(item.madeAt),
86
+ value: item.value,
87
+ };
88
+ }
89
+ }
90
+ lastItemBy(account) {
91
+ let latestItem;
92
+ for (const sessionID of Object.keys(this.items)) {
93
+ if (sessionID.startsWith(account)) {
94
+ const item = this.lastItemIn(sessionID);
95
+ if (!item)
96
+ continue;
97
+ if (!latestItem || item.at > latestItem.at) {
98
+ latestItem = {
99
+ by: item.by,
100
+ tx: item.tx,
101
+ at: item.at,
102
+ value: item.value,
103
+ };
104
+ }
105
+ }
106
+ }
107
+ return latestItem;
108
+ }
109
+ *itemsBy(account) {
110
+ // TODO: this can be made more lazy without a huge collect and sort
111
+ const items = [
112
+ ...Object.keys(this.items).flatMap((sessionID) => sessionID.startsWith(account)
113
+ ? [...this.itemsIn(sessionID)].map((item) => ({
114
+ in: sessionID,
115
+ ...item,
116
+ }))
117
+ : []),
118
+ ];
119
+ items.sort((a, b) => a.at.getTime() - b.at.getTime());
120
+ for (const item of items) {
121
+ yield item;
122
+ }
123
+ }
124
+ toJSON() {
125
+ return Object.fromEntries(Object.entries(this.items).map(([sessionID, items]) => [
126
+ sessionID,
127
+ items.map((item) => item.value),
128
+ ]));
129
+ }
130
+ subscribe(listener) {
131
+ return this.core.subscribe((content) => {
132
+ listener(content);
133
+ });
134
+ }
135
+ }
136
+ export class RawCoStream extends RawCoStreamView {
137
+ push(item, privacy = "private") {
138
+ this.core.makeTransaction([isCoValue(item) ? item.id : item], privacy);
139
+ this.fillFromCoValue();
140
+ }
141
+ }
142
+ const binary_U_prefixLength = 8; // "binary_U".length;
143
+ export class RawBinaryCoStreamView extends RawCoStreamView {
144
+ isBinaryStreamEnded() {
145
+ const items = this.getSingleStream();
146
+ if (!items || items.length === 0) {
147
+ return false;
148
+ }
149
+ const lastItem = items[items.length - 1];
150
+ return lastItem?.type === "end";
151
+ }
152
+ getBinaryChunks(allowUnfinished) {
153
+ const items = this.getSingleStream();
154
+ // No active streams
155
+ if (!items)
156
+ return;
157
+ const start = items[0];
158
+ if (start?.type !== "start") {
159
+ console.error("Invalid binary stream start", start);
160
+ return;
161
+ }
162
+ const end = items[items.length - 1];
163
+ if (end?.type !== "end" && !allowUnfinished)
164
+ return;
165
+ const chunks = [];
166
+ let finished = false;
167
+ for (const item of items.slice(1)) {
168
+ if (item.type === "end") {
169
+ finished = true;
170
+ break;
171
+ }
172
+ if (item.type !== "chunk") {
173
+ console.error("Invalid binary stream chunk", item);
174
+ return undefined;
175
+ }
176
+ const chunk = base64URLtoBytes(item.chunk.slice(binary_U_prefixLength));
177
+ chunks.push(chunk);
178
+ }
179
+ return {
180
+ mimeType: start.mimeType,
181
+ fileName: start.fileName,
182
+ totalSizeBytes: start.totalSizeBytes,
183
+ chunks,
184
+ finished,
185
+ };
186
+ }
187
+ }
188
+ export class RawBinaryCoStream extends RawBinaryCoStreamView {
189
+ /** @internal */
190
+ push(item, privacy = "private", updateView = true) {
191
+ this.core.makeTransaction([item], privacy);
192
+ if (updateView) {
193
+ this.fillFromCoValue();
194
+ }
195
+ }
196
+ startBinaryStream(settings, privacy = "private") {
197
+ this.push({
198
+ type: "start",
199
+ ...settings,
200
+ }, privacy, false);
201
+ }
202
+ pushBinaryStreamChunk(chunk, privacy = "private") {
203
+ // const before = performance.now();
204
+ this.push({
205
+ type: "chunk",
206
+ chunk: `binary_U${bytesToBase64url(chunk)}`,
207
+ }, privacy, false);
208
+ // const after = performance.now();
209
+ // console.log(
210
+ // "pushBinaryStreamChunk bandwidth in MB/s",
211
+ // (1000 * chunk.length) / (after - before) / (1024 * 1024)
212
+ // );
213
+ }
214
+ endBinaryStream(privacy = "private") {
215
+ this.push({
216
+ type: "end",
217
+ }, privacy, true);
218
+ }
219
+ }
220
+ //# sourceMappingURL=coStream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coStream.js","sourceRoot":"","sources":["../../../src/coValues/coStream.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,250 @@
1
+ import { RawCoMap } from "./coMap.js";
2
+ import { isAgentID } from "../ids.js";
3
+ import { base58 } from "@scure/base";
4
+ export const EVERYONE = "everyone";
5
+ /** A `Group` is a scope for permissions of its members (`"reader" | "writer" | "admin"`), applying to objects owned by that group.
6
+ *
7
+ * A `Group` object exposes methods for permission management and allows you to create new CoValues owned by that group.
8
+ *
9
+ * (Internally, a `Group` is also just a `CoMap`, mapping member accounts to roles and containing some
10
+ * state management for making cryptographic keys available to current members)
11
+ *
12
+ * @example
13
+ * You typically get a group from a CoValue that you already have loaded:
14
+ *
15
+ * ```typescript
16
+ * const group = coMap.group;
17
+ * ```
18
+ *
19
+ * @example
20
+ * Or, you can create a new group with a `LocalNode`:
21
+ *
22
+ * ```typescript
23
+ * const localNode.createGroup();
24
+ * ```
25
+ * */
26
+ export class RawGroup extends RawCoMap {
27
+ /**
28
+ * Returns the current role of a given account.
29
+ *
30
+ * @category 1. Role reading
31
+ */
32
+ roleOf(accountID) {
33
+ return this.roleOfInternal(accountID);
34
+ }
35
+ /** @internal */
36
+ roleOfInternal(accountID) {
37
+ return this.get(accountID);
38
+ }
39
+ /**
40
+ * Returns the role of the current account in the group.
41
+ *
42
+ * @category 1. Role reading
43
+ */
44
+ myRole() {
45
+ return this.roleOfInternal(this.core.node.account.id);
46
+ }
47
+ /**
48
+ * Directly grants a new member a role in the group. The current account must be an
49
+ * admin to be able to do so. Throws otherwise.
50
+ *
51
+ * @category 2. Role changing
52
+ */
53
+ addMember(account, role) {
54
+ this.addMemberInternal(account, role);
55
+ }
56
+ /** @internal */
57
+ addMemberInternal(account, role) {
58
+ const currentReadKey = this.core.getCurrentReadKey();
59
+ if (!currentReadKey.secret) {
60
+ throw new Error("Can't add member without read key secret");
61
+ }
62
+ if (account === EVERYONE) {
63
+ if (!(role === "reader" || role === "writer")) {
64
+ throw new Error("Can't make everyone something other than reader or writer");
65
+ }
66
+ this.set(account, role, "trusting");
67
+ if (this.get(account) !== role) {
68
+ throw new Error("Failed to set role");
69
+ }
70
+ this.set(`${currentReadKey.id}_for_${EVERYONE}`, currentReadKey.secret, "trusting");
71
+ }
72
+ else {
73
+ const memberKey = typeof account === "string" ? account : account.id;
74
+ const agent = typeof account === "string"
75
+ ? account
76
+ : account
77
+ .currentAgentID()
78
+ ._unsafeUnwrap({ withStackTrace: true });
79
+ this.set(memberKey, role, "trusting");
80
+ if (this.get(memberKey) !== role) {
81
+ throw new Error("Failed to set role");
82
+ }
83
+ this.set(`${currentReadKey.id}_for_${memberKey}`, this.core.crypto.seal({
84
+ message: currentReadKey.secret,
85
+ from: this.core.node.account.currentSealerSecret(),
86
+ to: this.core.crypto.getAgentSealerID(agent),
87
+ nOnceMaterial: {
88
+ in: this.id,
89
+ tx: this.core.nextTransactionID(),
90
+ },
91
+ }), "trusting");
92
+ }
93
+ }
94
+ /** @internal */
95
+ rotateReadKey() {
96
+ const currentlyPermittedReaders = this.keys().filter((key) => {
97
+ if (key.startsWith("co_") || isAgentID(key)) {
98
+ const role = this.get(key);
99
+ return (role === "admin" || role === "writer" || role === "reader");
100
+ }
101
+ else {
102
+ return false;
103
+ }
104
+ });
105
+ const maybeCurrentReadKey = this.core.getCurrentReadKey();
106
+ if (!maybeCurrentReadKey.secret) {
107
+ throw new Error("Can't rotate read key secret we don't have access to");
108
+ }
109
+ const currentReadKey = {
110
+ id: maybeCurrentReadKey.id,
111
+ secret: maybeCurrentReadKey.secret,
112
+ };
113
+ const newReadKey = this.core.crypto.newRandomKeySecret();
114
+ for (const readerID of currentlyPermittedReaders) {
115
+ const reader = this.core.node.resolveAccountAgent(readerID, "Expected to know currently permitted reader")._unsafeUnwrap({ withStackTrace: true });
116
+ this.set(`${newReadKey.id}_for_${readerID}`, this.core.crypto.seal({
117
+ message: newReadKey.secret,
118
+ from: this.core.node.account.currentSealerSecret(),
119
+ to: this.core.crypto.getAgentSealerID(reader),
120
+ nOnceMaterial: {
121
+ in: this.id,
122
+ tx: this.core.nextTransactionID(),
123
+ },
124
+ }), "trusting");
125
+ }
126
+ this.set(`${currentReadKey.id}_for_${newReadKey.id}`, this.core.crypto.encryptKeySecret({
127
+ encrypting: newReadKey,
128
+ toEncrypt: currentReadKey,
129
+ }).encrypted, "trusting");
130
+ this.set("readKey", newReadKey.id, "trusting");
131
+ }
132
+ /**
133
+ * Strips the specified member of all roles (preventing future writes in
134
+ * the group and owned values) and rotates the read encryption key for that group
135
+ * (preventing reads of new content in the group and owned values)
136
+ *
137
+ * @category 2. Role changing
138
+ */
139
+ removeMember(account) {
140
+ this.removeMemberInternal(account);
141
+ }
142
+ /** @internal */
143
+ removeMemberInternal(account) {
144
+ const memberKey = typeof account === "string" ? account : account.id;
145
+ this.set(memberKey, "revoked", "trusting");
146
+ this.rotateReadKey();
147
+ }
148
+ /**
149
+ * Creates an invite for new members to indirectly join the group,
150
+ * allowing them to grant themselves the specified role with the InviteSecret
151
+ * (a string starting with "inviteSecret_") - use `LocalNode.acceptInvite()` for this purpose.
152
+ *
153
+ * @category 2. Role changing
154
+ */
155
+ createInvite(role) {
156
+ const secretSeed = this.core.crypto.newRandomSecretSeed();
157
+ const inviteSecret = this.core.crypto.agentSecretFromSecretSeed(secretSeed);
158
+ const inviteID = this.core.crypto.getAgentID(inviteSecret);
159
+ this.addMemberInternal(inviteID, `${role}Invite`);
160
+ return inviteSecretFromSecretSeed(secretSeed);
161
+ }
162
+ /**
163
+ * Creates a new `CoMap` within this group, with the specified specialized
164
+ * `CoMap` type `M` and optional static metadata.
165
+ *
166
+ * @category 3. Value creation
167
+ */
168
+ createMap(init, meta, initPrivacy = "private", uniqueness = this.core.crypto.createdNowUnique()) {
169
+ const map = this.core.node
170
+ .createCoValue({
171
+ type: "comap",
172
+ ruleset: {
173
+ type: "ownedByGroup",
174
+ group: this.id,
175
+ },
176
+ meta: meta || null,
177
+ ...uniqueness
178
+ })
179
+ .getCurrentContent();
180
+ if (init) {
181
+ for (const [key, value] of Object.entries(init)) {
182
+ map.set(key, value, initPrivacy);
183
+ }
184
+ }
185
+ return map;
186
+ }
187
+ /**
188
+ * Creates a new `CoList` within this group, with the specified specialized
189
+ * `CoList` type `L` and optional static metadata.
190
+ *
191
+ * @category 3. Value creation
192
+ */
193
+ createList(init, meta, initPrivacy = "private", uniqueness = this.core.crypto.createdNowUnique()) {
194
+ const list = this.core.node
195
+ .createCoValue({
196
+ type: "colist",
197
+ ruleset: {
198
+ type: "ownedByGroup",
199
+ group: this.id,
200
+ },
201
+ meta: meta || null,
202
+ ...uniqueness
203
+ })
204
+ .getCurrentContent();
205
+ if (init) {
206
+ for (const item of init) {
207
+ list.append(item, undefined, initPrivacy);
208
+ }
209
+ }
210
+ return list;
211
+ }
212
+ /** @category 3. Value creation */
213
+ createStream(meta, uniqueness = this.core.crypto.createdNowUnique()) {
214
+ return this.core.node
215
+ .createCoValue({
216
+ type: "costream",
217
+ ruleset: {
218
+ type: "ownedByGroup",
219
+ group: this.id,
220
+ },
221
+ meta: meta || null,
222
+ ...uniqueness
223
+ })
224
+ .getCurrentContent();
225
+ }
226
+ /** @category 3. Value creation */
227
+ createBinaryStream(meta = { type: "binary" }, uniqueness = this.core.crypto.createdNowUnique()) {
228
+ return this.core.node
229
+ .createCoValue({
230
+ type: "costream",
231
+ ruleset: {
232
+ type: "ownedByGroup",
233
+ group: this.id,
234
+ },
235
+ meta: meta,
236
+ ...uniqueness
237
+ })
238
+ .getCurrentContent();
239
+ }
240
+ }
241
+ function inviteSecretFromSecretSeed(secretSeed) {
242
+ return `inviteSecret_z${base58.encode(secretSeed)}`;
243
+ }
244
+ export function secretSeedFromInviteSecret(inviteSecret) {
245
+ if (!inviteSecret.startsWith("inviteSecret_z")) {
246
+ throw new Error("Invalid invite secret");
247
+ }
248
+ return base58.decode(inviteSecret.slice("inviteSecret_z".length));
249
+ }
250
+ //# sourceMappingURL=group.js.map