cojson 0.8.12 → 0.8.16

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 (158) hide show
  1. package/CHANGELOG.md +89 -83
  2. package/dist/native/PeerKnownStates.js +1 -1
  3. package/dist/native/PeerKnownStates.js.map +1 -1
  4. package/dist/native/PeerState.js +1 -1
  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/base64url.js.map +1 -1
  9. package/dist/native/base64url.test.js +1 -1
  10. package/dist/native/base64url.test.js.map +1 -1
  11. package/dist/native/coValue.js.map +1 -1
  12. package/dist/native/coValueCore.js +141 -149
  13. package/dist/native/coValueCore.js.map +1 -1
  14. package/dist/native/coValueState.js.map +1 -1
  15. package/dist/native/coValues/account.js +6 -6
  16. package/dist/native/coValues/account.js.map +1 -1
  17. package/dist/native/coValues/coList.js +2 -3
  18. package/dist/native/coValues/coList.js.map +1 -1
  19. package/dist/native/coValues/coMap.js +1 -1
  20. package/dist/native/coValues/coMap.js.map +1 -1
  21. package/dist/native/coValues/coStream.js +3 -5
  22. package/dist/native/coValues/coStream.js.map +1 -1
  23. package/dist/native/coValues/group.js +11 -11
  24. package/dist/native/coValues/group.js.map +1 -1
  25. package/dist/native/coreToCoValue.js +2 -2
  26. package/dist/native/coreToCoValue.js.map +1 -1
  27. package/dist/native/crypto/PureJSCrypto.js +4 -4
  28. package/dist/native/crypto/PureJSCrypto.js.map +1 -1
  29. package/dist/native/crypto/crypto.js.map +1 -1
  30. package/dist/native/exports.js +12 -12
  31. package/dist/native/exports.js.map +1 -1
  32. package/dist/native/ids.js.map +1 -1
  33. package/dist/native/jsonStringify.js.map +1 -1
  34. package/dist/native/localNode.js +5 -7
  35. package/dist/native/localNode.js.map +1 -1
  36. package/dist/native/permissions.js +4 -7
  37. package/dist/native/permissions.js.map +1 -1
  38. package/dist/native/priority.js.map +1 -1
  39. package/dist/native/storage/FileSystem.js.map +1 -1
  40. package/dist/native/storage/chunksAndKnownStates.js +2 -4
  41. package/dist/native/storage/chunksAndKnownStates.js.map +1 -1
  42. package/dist/native/storage/index.js +6 -15
  43. package/dist/native/storage/index.js.map +1 -1
  44. package/dist/native/streamUtils.js.map +1 -1
  45. package/dist/native/sync.js +2 -4
  46. package/dist/native/sync.js.map +1 -1
  47. package/dist/native/typeUtils/accountOrAgentIDfromSessionID.js.map +1 -1
  48. package/dist/native/typeUtils/expectGroup.js.map +1 -1
  49. package/dist/native/typeUtils/isAccountID.js.map +1 -1
  50. package/dist/native/typeUtils/isCoValue.js +1 -1
  51. package/dist/native/typeUtils/isCoValue.js.map +1 -1
  52. package/dist/web/PeerKnownStates.js +1 -1
  53. package/dist/web/PeerKnownStates.js.map +1 -1
  54. package/dist/web/PeerState.js +1 -1
  55. package/dist/web/PeerState.js.map +1 -1
  56. package/dist/web/PriorityBasedMessageQueue.js +1 -10
  57. package/dist/web/PriorityBasedMessageQueue.js.map +1 -1
  58. package/dist/web/base64url.js.map +1 -1
  59. package/dist/web/base64url.test.js +1 -1
  60. package/dist/web/base64url.test.js.map +1 -1
  61. package/dist/web/coValue.js.map +1 -1
  62. package/dist/web/coValueCore.js +141 -149
  63. package/dist/web/coValueCore.js.map +1 -1
  64. package/dist/web/coValueState.js.map +1 -1
  65. package/dist/web/coValues/account.js +6 -6
  66. package/dist/web/coValues/account.js.map +1 -1
  67. package/dist/web/coValues/coList.js +2 -3
  68. package/dist/web/coValues/coList.js.map +1 -1
  69. package/dist/web/coValues/coMap.js +1 -1
  70. package/dist/web/coValues/coMap.js.map +1 -1
  71. package/dist/web/coValues/coStream.js +3 -5
  72. package/dist/web/coValues/coStream.js.map +1 -1
  73. package/dist/web/coValues/group.js +11 -11
  74. package/dist/web/coValues/group.js.map +1 -1
  75. package/dist/web/coreToCoValue.js +2 -2
  76. package/dist/web/coreToCoValue.js.map +1 -1
  77. package/dist/web/crypto/PureJSCrypto.js +4 -4
  78. package/dist/web/crypto/PureJSCrypto.js.map +1 -1
  79. package/dist/web/crypto/WasmCrypto.js +5 -5
  80. package/dist/web/crypto/WasmCrypto.js.map +1 -1
  81. package/dist/web/crypto/crypto.js.map +1 -1
  82. package/dist/web/exports.js +12 -12
  83. package/dist/web/exports.js.map +1 -1
  84. package/dist/web/ids.js.map +1 -1
  85. package/dist/web/jsonStringify.js.map +1 -1
  86. package/dist/web/localNode.js +5 -7
  87. package/dist/web/localNode.js.map +1 -1
  88. package/dist/web/permissions.js +4 -7
  89. package/dist/web/permissions.js.map +1 -1
  90. package/dist/web/priority.js.map +1 -1
  91. package/dist/web/storage/FileSystem.js.map +1 -1
  92. package/dist/web/storage/chunksAndKnownStates.js +2 -4
  93. package/dist/web/storage/chunksAndKnownStates.js.map +1 -1
  94. package/dist/web/storage/index.js +6 -15
  95. package/dist/web/storage/index.js.map +1 -1
  96. package/dist/web/streamUtils.js.map +1 -1
  97. package/dist/web/sync.js +2 -4
  98. package/dist/web/sync.js.map +1 -1
  99. package/dist/web/typeUtils/accountOrAgentIDfromSessionID.js.map +1 -1
  100. package/dist/web/typeUtils/expectGroup.js.map +1 -1
  101. package/dist/web/typeUtils/isAccountID.js.map +1 -1
  102. package/dist/web/typeUtils/isCoValue.js +1 -1
  103. package/dist/web/typeUtils/isCoValue.js.map +1 -1
  104. package/package.json +4 -14
  105. package/src/PeerKnownStates.ts +91 -89
  106. package/src/PeerState.ts +72 -73
  107. package/src/PriorityBasedMessageQueue.ts +42 -49
  108. package/src/base64url.test.ts +24 -24
  109. package/src/base64url.ts +44 -45
  110. package/src/coValue.ts +45 -45
  111. package/src/coValueCore.ts +746 -785
  112. package/src/coValueState.ts +82 -72
  113. package/src/coValues/account.ts +143 -150
  114. package/src/coValues/coList.ts +520 -522
  115. package/src/coValues/coMap.ts +283 -285
  116. package/src/coValues/coStream.ts +320 -324
  117. package/src/coValues/group.ts +306 -305
  118. package/src/coreToCoValue.ts +28 -31
  119. package/src/crypto/PureJSCrypto.ts +188 -194
  120. package/src/crypto/WasmCrypto.ts +236 -254
  121. package/src/crypto/crypto.ts +302 -309
  122. package/src/exports.ts +116 -116
  123. package/src/ids.ts +9 -9
  124. package/src/jsonStringify.ts +46 -46
  125. package/src/jsonValue.ts +24 -10
  126. package/src/localNode.ts +635 -660
  127. package/src/media.ts +3 -3
  128. package/src/permissions.ts +272 -278
  129. package/src/priority.ts +21 -19
  130. package/src/storage/FileSystem.ts +91 -99
  131. package/src/storage/chunksAndKnownStates.ts +110 -115
  132. package/src/storage/index.ts +466 -497
  133. package/src/streamUtils.ts +60 -60
  134. package/src/sync.ts +593 -615
  135. package/src/tests/PeerKnownStates.test.ts +38 -34
  136. package/src/tests/PeerState.test.ts +101 -64
  137. package/src/tests/PriorityBasedMessageQueue.test.ts +91 -91
  138. package/src/tests/account.test.ts +59 -59
  139. package/src/tests/coList.test.ts +65 -65
  140. package/src/tests/coMap.test.ts +137 -137
  141. package/src/tests/coStream.test.ts +254 -257
  142. package/src/tests/coValueCore.test.ts +153 -156
  143. package/src/tests/crypto.test.ts +136 -144
  144. package/src/tests/cryptoImpl.test.ts +205 -197
  145. package/src/tests/group.test.ts +24 -24
  146. package/src/tests/permissions.test.ts +1306 -1371
  147. package/src/tests/priority.test.ts +65 -82
  148. package/src/tests/sync.test.ts +1300 -1291
  149. package/src/tests/testUtils.ts +52 -53
  150. package/src/typeUtils/accountOrAgentIDfromSessionID.ts +4 -4
  151. package/src/typeUtils/expectGroup.ts +9 -9
  152. package/src/typeUtils/isAccountID.ts +1 -1
  153. package/src/typeUtils/isCoValue.ts +9 -9
  154. package/tsconfig.json +4 -6
  155. package/tsconfig.native.json +9 -11
  156. package/tsconfig.web.json +4 -10
  157. package/.eslintrc.cjs +0 -25
  158. package/.prettierrc.js +0 -9
@@ -1,327 +1,325 @@
1
- import { JsonObject, JsonValue } from "../jsonValue.js";
2
- import { AgentID, TransactionID } from "../ids.js";
3
1
  import { CoID, RawCoValue } from "../coValue.js";
4
- import { isCoValue } from "../typeUtils/isCoValue.js";
5
2
  import { CoValueCore } from "../coValueCore.js";
3
+ import { AgentID, TransactionID } from "../ids.js";
4
+ import { JsonObject, JsonValue } from "../jsonValue.js";
6
5
  import { accountOrAgentIDfromSessionID } from "../typeUtils/accountOrAgentIDfromSessionID.js";
6
+ import { isCoValue } from "../typeUtils/isCoValue.js";
7
7
  import { RawAccountID } from "./account.js";
8
8
  import type { RawGroup } from "./group.js";
9
9
 
10
10
  type MapOp<K extends string, V extends JsonValue | undefined> = {
11
- txID: TransactionID;
12
- madeAt: number;
13
- changeIdx: number;
11
+ txID: TransactionID;
12
+ madeAt: number;
13
+ changeIdx: number;
14
14
  } & MapOpPayload<K, V>;
15
15
  // TODO: add after TransactionID[] for conflicts/ordering
16
16
 
17
17
  export type MapOpPayload<K extends string, V extends JsonValue | undefined> =
18
- | {
19
- op: "set";
20
- key: K;
21
- value: V;
22
- }
23
- | {
24
- op: "del";
25
- key: K;
26
- };
18
+ | {
19
+ op: "set";
20
+ key: K;
21
+ value: V;
22
+ }
23
+ | {
24
+ op: "del";
25
+ key: K;
26
+ };
27
27
 
28
28
  export class RawCoMapView<
29
- Shape extends { [key: string]: JsonValue | undefined } = {
30
- [key: string]: JsonValue | undefined;
31
- },
32
- Meta extends JsonObject | null = JsonObject | null,
29
+ Shape extends { [key: string]: JsonValue | undefined } = {
30
+ [key: string]: JsonValue | undefined;
31
+ },
32
+ Meta extends JsonObject | null = JsonObject | null,
33
33
  > implements RawCoValue
34
34
  {
35
- /** @category 6. Meta */
36
- id: CoID<this>;
37
- /** @category 6. Meta */
38
- type = "comap" as const;
39
- /** @category 6. Meta */
40
- core: CoValueCore;
41
- /** @internal */
42
- ops: {
43
- [Key in keyof Shape & string]?: MapOp<Key, Shape[Key]>[];
44
- };
45
- /** @internal */
46
- atTimeFilter?: number = undefined;
47
- /** @category 6. Meta */
48
- readonly _shape!: Shape;
49
-
50
- /** @internal */
51
- constructor(
52
- core: CoValueCore,
53
- options?: { ignorePrivateTransactions: true },
54
- ) {
55
- this.id = core.id as CoID<this>;
56
- this.core = core;
57
- this.ops = {};
58
-
59
- for (const { txID, changes, madeAt } of core.getValidSortedTransactions(
60
- options,
61
- )) {
62
- for (const [changeIdx, changeUntyped] of changes.entries()) {
63
- const change = changeUntyped as MapOpPayload<
64
- keyof Shape & string,
65
- Shape[keyof Shape & string]
66
- >;
67
- let entries = this.ops[change.key];
68
- if (!entries) {
69
- entries = [];
70
- this.ops[change.key] = entries;
71
- }
72
- entries.push({
73
- txID,
74
- madeAt,
75
- changeIdx,
76
- ...(change as MapOpPayload<
77
- keyof Shape & string,
78
- Shape[keyof Shape & string]
79
- >),
80
- });
81
- }
35
+ /** @category 6. Meta */
36
+ id: CoID<this>;
37
+ /** @category 6. Meta */
38
+ type = "comap" as const;
39
+ /** @category 6. Meta */
40
+ core: CoValueCore;
41
+ /** @internal */
42
+ ops: {
43
+ [Key in keyof Shape & string]?: MapOp<Key, Shape[Key]>[];
44
+ };
45
+ /** @internal */
46
+ atTimeFilter?: number = undefined;
47
+ /** @category 6. Meta */
48
+ readonly _shape!: Shape;
49
+
50
+ /** @internal */
51
+ constructor(
52
+ core: CoValueCore,
53
+ options?: { ignorePrivateTransactions: true },
54
+ ) {
55
+ this.id = core.id as CoID<this>;
56
+ this.core = core;
57
+ this.ops = {};
58
+
59
+ for (const { txID, changes, madeAt } of core.getValidSortedTransactions(
60
+ options,
61
+ )) {
62
+ for (const [changeIdx, changeUntyped] of changes.entries()) {
63
+ const change = changeUntyped as MapOpPayload<
64
+ keyof Shape & string,
65
+ Shape[keyof Shape & string]
66
+ >;
67
+ let entries = this.ops[change.key];
68
+ if (!entries) {
69
+ entries = [];
70
+ this.ops[change.key] = entries;
82
71
  }
72
+ entries.push({
73
+ txID,
74
+ madeAt,
75
+ changeIdx,
76
+ ...(change as MapOpPayload<
77
+ keyof Shape & string,
78
+ Shape[keyof Shape & string]
79
+ >),
80
+ });
81
+ }
83
82
  }
84
-
85
- /** @category 6. Meta */
86
- get headerMeta(): Meta {
87
- return this.core.header.meta as Meta;
88
- }
89
-
90
- /** @category 6. Meta */
91
- get group(): RawGroup {
92
- return this.core.getGroup();
83
+ }
84
+
85
+ /** @category 6. Meta */
86
+ get headerMeta(): Meta {
87
+ return this.core.header.meta as Meta;
88
+ }
89
+
90
+ /** @category 6. Meta */
91
+ get group(): RawGroup {
92
+ return this.core.getGroup();
93
+ }
94
+
95
+ /** @category 4. Time travel */
96
+ atTime(time: number): this {
97
+ const clone = Object.create(this) as this;
98
+ clone.id = this.id;
99
+ clone.type = this.type;
100
+ clone.core = this.core;
101
+ clone.ops = this.ops;
102
+ clone.atTimeFilter = time;
103
+ return clone;
104
+ }
105
+
106
+ /** @internal */
107
+ timeFilteredOps<K extends keyof Shape & string>(
108
+ key: K,
109
+ ): MapOp<K, Shape[K]>[] | undefined {
110
+ if (this.atTimeFilter) {
111
+ return this.ops[key]?.filter((op) => op.madeAt <= this.atTimeFilter!);
112
+ } else {
113
+ return this.ops[key];
93
114
  }
115
+ }
116
+
117
+ /**
118
+ * Get all keys currently in the map.
119
+ *
120
+ * @category 1. Reading */
121
+ keys<K extends keyof Shape & string = keyof Shape & string>(): K[] {
122
+ return (Object.keys(this.ops) as K[]).filter((key) => {
123
+ const ops = this.ops[key];
124
+ if (!ops) {
125
+ return undefined;
126
+ }
94
127
 
95
- /** @category 4. Time travel */
96
- atTime(time: number): this {
97
- const clone = Object.create(this) as this;
98
- clone.id = this.id;
99
- clone.type = this.type;
100
- clone.core = this.core;
101
- clone.ops = this.ops;
102
- clone.atTimeFilter = time;
103
- return clone;
104
- }
128
+ const includeUntil = this.atTimeFilter;
129
+ const lastEntry = includeUntil
130
+ ? ops.findLast((entry) => entry.madeAt <= includeUntil)
131
+ : ops[ops.length - 1]!;
105
132
 
106
- /** @internal */
107
- timeFilteredOps<K extends keyof Shape & string>(
108
- key: K,
109
- ): MapOp<K, Shape[K]>[] | undefined {
110
- if (this.atTimeFilter) {
111
- return this.ops[key]?.filter(
112
- (op) => op.madeAt <= this.atTimeFilter!,
113
- );
114
- } else {
115
- return this.ops[key];
116
- }
133
+ if (lastEntry?.op === "del") {
134
+ return false;
135
+ } else {
136
+ return true;
137
+ }
138
+ });
139
+ }
140
+
141
+ /**
142
+ * Returns the current value for the given key.
143
+ *
144
+ * @category 1. Reading
145
+ **/
146
+ get<K extends keyof Shape & string>(key: K): Shape[K] | undefined {
147
+ const ops = this.ops[key];
148
+ if (!ops) {
149
+ return undefined;
117
150
  }
118
151
 
119
- /**
120
- * Get all keys currently in the map.
121
- *
122
- * @category 1. Reading */
123
- keys<K extends keyof Shape & string = keyof Shape & string>(): K[] {
124
- return (Object.keys(this.ops) as K[]).filter((key) => {
125
- const ops = this.ops[key];
126
- if (!ops) {
127
- return undefined;
128
- }
129
-
130
- const includeUntil = this.atTimeFilter;
131
- const lastEntry = includeUntil
132
- ? ops.findLast((entry) => entry.madeAt <= includeUntil)
133
- : ops[ops.length - 1]!;
134
-
135
- if (lastEntry?.op === "del") {
136
- return false;
137
- } else {
138
- return true;
139
- }
140
- });
141
- }
152
+ const includeUntil = this.atTimeFilter;
153
+ const lastEntry = includeUntil
154
+ ? ops.findLast((entry) => entry.madeAt <= includeUntil)
155
+ : ops[ops.length - 1]!;
142
156
 
143
- /**
144
- * Returns the current value for the given key.
145
- *
146
- * @category 1. Reading
147
- **/
148
- get<K extends keyof Shape & string>(key: K): Shape[K] | undefined {
149
- const ops = this.ops[key];
150
- if (!ops) {
151
- return undefined;
152
- }
153
-
154
- const includeUntil = this.atTimeFilter;
155
- const lastEntry = includeUntil
156
- ? ops.findLast((entry) => entry.madeAt <= includeUntil)
157
- : ops[ops.length - 1]!;
158
-
159
- if (lastEntry?.op === "del") {
160
- return undefined;
161
- } else {
162
- return lastEntry?.value;
163
- }
157
+ if (lastEntry?.op === "del") {
158
+ return undefined;
159
+ } else {
160
+ return lastEntry?.value;
164
161
  }
165
-
166
- /** @category 1. Reading */
167
- asObject(): {
168
- [K in keyof Shape & string]: Shape[K];
169
- } {
170
- const object: Partial<{
171
- [K in keyof Shape & string]: Shape[K];
172
- }> = {};
173
-
174
- for (const key of this.keys()) {
175
- const value = this.get(key);
176
- if (value !== undefined) {
177
- object[key] = value;
178
- }
179
- }
180
-
181
- return object as {
182
- [K in keyof Shape & string]: Shape[K];
183
- };
162
+ }
163
+
164
+ /** @category 1. Reading */
165
+ asObject(): {
166
+ [K in keyof Shape & string]: Shape[K];
167
+ } {
168
+ const object: Partial<{
169
+ [K in keyof Shape & string]: Shape[K];
170
+ }> = {};
171
+
172
+ for (const key of this.keys()) {
173
+ const value = this.get(key);
174
+ if (value !== undefined) {
175
+ object[key] = value;
176
+ }
184
177
  }
185
178
 
186
- /** @category 1. Reading */
187
- toJSON(): {
188
- [K in keyof Shape & string]: Shape[K];
189
- } {
190
- return this.asObject();
179
+ return object as {
180
+ [K in keyof Shape & string]: Shape[K];
181
+ };
182
+ }
183
+
184
+ /** @category 1. Reading */
185
+ toJSON(): {
186
+ [K in keyof Shape & string]: Shape[K];
187
+ } {
188
+ return this.asObject();
189
+ }
190
+
191
+ /** @category 5. Edit history */
192
+ nthEditAt<K extends keyof Shape & string>(
193
+ key: K,
194
+ n: number,
195
+ ):
196
+ | {
197
+ by: RawAccountID | AgentID;
198
+ tx: TransactionID;
199
+ at: Date;
200
+ value?: Shape[K];
201
+ }
202
+ | undefined {
203
+ const ops = this.timeFilteredOps(key);
204
+ if (!ops || ops.length <= n) {
205
+ return undefined;
191
206
  }
192
207
 
193
- /** @category 5. Edit history */
194
- nthEditAt<K extends keyof Shape & string>(
195
- key: K,
196
- n: number,
197
- ):
198
- | {
199
- by: RawAccountID | AgentID;
200
- tx: TransactionID;
201
- at: Date;
202
- value?: Shape[K];
203
- }
204
- | undefined {
205
- const ops = this.timeFilteredOps(key);
206
- if (!ops || ops.length <= n) {
207
- return undefined;
208
- }
208
+ const entry = ops[n]!;
209
209
 
210
- const entry = ops[n]!;
211
-
212
- if (this.atTimeFilter && entry.madeAt > this.atTimeFilter) {
213
- return undefined;
214
- }
215
-
216
- return {
217
- by: accountOrAgentIDfromSessionID(entry.txID.sessionID),
218
- tx: entry.txID,
219
- at: new Date(entry.madeAt),
220
- value: entry.op === "del" ? undefined : entry.value,
221
- };
210
+ if (this.atTimeFilter && entry.madeAt > this.atTimeFilter) {
211
+ return undefined;
222
212
  }
223
213
 
224
- /** @category 5. Edit history */
225
- lastEditAt<K extends keyof Shape & string>(
226
- key: K,
227
- ):
228
- | {
229
- by: RawAccountID | AgentID;
230
- tx: TransactionID;
231
- at: Date;
232
- value?: Shape[K];
233
- }
234
- | undefined {
235
- const ops = this.timeFilteredOps(key);
236
- if (!ops || ops.length === 0) {
237
- return undefined;
238
- }
239
- return this.nthEditAt(key, ops.length - 1);
240
- }
241
-
242
- /** @category 5. Edit history */
243
- *editsAt<K extends keyof Shape & string>(key: K) {
244
- const ops = this.timeFilteredOps(key);
245
- if (!ops) {
246
- return;
247
- }
214
+ return {
215
+ by: accountOrAgentIDfromSessionID(entry.txID.sessionID),
216
+ tx: entry.txID,
217
+ at: new Date(entry.madeAt),
218
+ value: entry.op === "del" ? undefined : entry.value,
219
+ };
220
+ }
248
221
 
249
- for (let i = 0; i < ops.length; i++) {
250
- yield this.nthEditAt(key, i)!;
251
- }
222
+ /** @category 5. Edit history */
223
+ lastEditAt<K extends keyof Shape & string>(
224
+ key: K,
225
+ ):
226
+ | {
227
+ by: RawAccountID | AgentID;
228
+ tx: TransactionID;
229
+ at: Date;
230
+ value?: Shape[K];
231
+ }
232
+ | undefined {
233
+ const ops = this.timeFilteredOps(key);
234
+ if (!ops || ops.length === 0) {
235
+ return undefined;
236
+ }
237
+ return this.nthEditAt(key, ops.length - 1);
238
+ }
239
+
240
+ /** @category 5. Edit history */
241
+ *editsAt<K extends keyof Shape & string>(key: K) {
242
+ const ops = this.timeFilteredOps(key);
243
+ if (!ops) {
244
+ return;
252
245
  }
253
246
 
254
- /** @category 3. Subscription */
255
- subscribe(listener: (coMap: this) => void): () => void {
256
- return this.core.subscribe((content) => {
257
- listener(content as this);
258
- });
247
+ for (let i = 0; i < ops.length; i++) {
248
+ yield this.nthEditAt(key, i)!;
259
249
  }
250
+ }
251
+
252
+ /** @category 3. Subscription */
253
+ subscribe(listener: (coMap: this) => void): () => void {
254
+ return this.core.subscribe((content) => {
255
+ listener(content as this);
256
+ });
257
+ }
260
258
  }
261
259
 
262
260
  /** A collaborative map with precise shape `Shape` and optional static metadata `Meta` */
263
261
  export class RawCoMap<
264
- Shape extends { [key: string]: JsonValue | undefined } = {
265
- [key: string]: JsonValue | undefined;
266
- },
267
- Meta extends JsonObject | null = JsonObject | null,
268
- >
269
- extends RawCoMapView<Shape, Meta>
270
- implements RawCoValue
262
+ Shape extends { [key: string]: JsonValue | undefined } = {
263
+ [key: string]: JsonValue | undefined;
264
+ },
265
+ Meta extends JsonObject | null = JsonObject | null,
266
+ >
267
+ extends RawCoMapView<Shape, Meta>
268
+ implements RawCoValue
271
269
  {
272
- /** Set a new value for the given key.
273
- *
274
- * 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.
275
- *
276
- * 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.
277
- *
278
- * @category 2. Editing
279
- **/
280
- set<K extends keyof Shape & string>(
281
- key: K,
282
- value: Shape[K],
283
- privacy: "private" | "trusting" = "private",
284
- ): void {
285
- this.core.makeTransaction(
286
- [
287
- {
288
- op: "set",
289
- key,
290
- value: isCoValue(value) ? value.id : value,
291
- },
292
- ],
293
- privacy,
294
- );
295
-
296
- const after = new RawCoMap(this.core) as this;
297
-
298
- this.ops = after.ops;
299
- }
270
+ /** Set a new value for the given key.
271
+ *
272
+ * 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.
273
+ *
274
+ * 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.
275
+ *
276
+ * @category 2. Editing
277
+ **/
278
+ set<K extends keyof Shape & string>(
279
+ key: K,
280
+ value: Shape[K],
281
+ privacy: "private" | "trusting" = "private",
282
+ ): void {
283
+ this.core.makeTransaction(
284
+ [
285
+ {
286
+ op: "set",
287
+ key,
288
+ value: isCoValue(value) ? value.id : value,
289
+ },
290
+ ],
291
+ privacy,
292
+ );
293
+
294
+ const after = new RawCoMap(this.core) as this;
295
+
296
+ this.ops = after.ops;
297
+ }
298
+
299
+ /** Delete the given key (setting it to undefined).
300
+ *
301
+ * 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.
302
+ *
303
+ * If `privacy` is `"trusting"`, `key` is stored in plaintext in the transaction, visible to everyone who gets a hold of it, including sync servers.
304
+ *
305
+ * @category 2. Editing
306
+ **/
307
+ delete(
308
+ key: keyof Shape & string,
309
+ privacy: "private" | "trusting" = "private",
310
+ ) {
311
+ this.core.makeTransaction(
312
+ [
313
+ {
314
+ op: "del",
315
+ key,
316
+ },
317
+ ],
318
+ privacy,
319
+ );
300
320
 
301
- /** Delete the given key (setting it to undefined).
302
- *
303
- * 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.
304
- *
305
- * If `privacy` is `"trusting"`, `key` is stored in plaintext in the transaction, visible to everyone who gets a hold of it, including sync servers.
306
- *
307
- * @category 2. Editing
308
- **/
309
- delete(
310
- key: keyof Shape & string,
311
- privacy: "private" | "trusting" = "private",
312
- ) {
313
- this.core.makeTransaction(
314
- [
315
- {
316
- op: "del",
317
- key,
318
- },
319
- ],
320
- privacy,
321
- );
322
-
323
- const after = new RawCoMap(this.core) as this;
324
-
325
- this.ops = after.ops;
326
- }
321
+ const after = new RawCoMap(this.core) as this;
322
+
323
+ this.ops = after.ops;
324
+ }
327
325
  }