@storacha/md-merge 0.4.0 → 0.5.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.
@@ -41,6 +41,14 @@ export declare class RGA<T, E extends RGAEvent = RGAEvent> {
41
41
  toNodes(): RGANode<T, E>[];
42
42
  /** Get all ordered nodes including tombstones. */
43
43
  toAllNodes(): RGANode<T, E>[];
44
+ /** Rebuild ordered nodes via BFS over causal tree (including tombstones). */
45
+ private allWeighted;
46
+ /** Get all weighted-order nodes including tombstones. */
47
+ toAllWeightedNodes(): RGANode<T, E>[];
48
+ /** Get weighted-order non-tombstoned nodes. */
49
+ toWeightedNodes(): RGANode<T, E>[];
50
+ /** Rebuild the weighted-order array, excluding tombstones. */
51
+ toWeightedArray(): T[];
44
52
  /** Merge another RGA into this one. Union of all nodes; tombstones win. */
45
53
  merge(other: RGA<T, E>): void;
46
54
  /** Create an RGA from an array of items. Each item is inserted sequentially. */
package/dist/crdt/rga.js CHANGED
@@ -80,6 +80,49 @@ export class RGA {
80
80
  toAllNodes() {
81
81
  return this.allOrdered();
82
82
  }
83
+ /** Rebuild ordered nodes via BFS over causal tree (including tombstones). */
84
+ allWeighted() {
85
+ const ROOT_KEY = '__ROOT__';
86
+ const children = new Map();
87
+ for (const node of this.nodes.values()) {
88
+ const key = node.afterId ? serializeId(node.afterId) : ROOT_KEY;
89
+ let list = children.get(key);
90
+ if (!list) {
91
+ list = [];
92
+ children.set(key, list);
93
+ }
94
+ list.push(node);
95
+ }
96
+ for (const list of children.values()) {
97
+ list.sort((a, b) => this.compareIds(a.id, b.id));
98
+ }
99
+ const result = [];
100
+ let currentLevel = children.get(ROOT_KEY) ?? [];
101
+ while (currentLevel.length > 0) {
102
+ result.push(...currentLevel);
103
+ const nextLevel = [];
104
+ for (const node of currentLevel) {
105
+ const kids = children.get(serializeId(node.id));
106
+ if (kids)
107
+ nextLevel.push(...kids);
108
+ }
109
+ nextLevel.sort((a, b) => this.compareIds(a.id, b.id));
110
+ currentLevel = nextLevel;
111
+ }
112
+ return result;
113
+ }
114
+ /** Get all weighted-order nodes including tombstones. */
115
+ toAllWeightedNodes() {
116
+ return this.allWeighted();
117
+ }
118
+ /** Get weighted-order non-tombstoned nodes. */
119
+ toWeightedNodes() {
120
+ return this.allWeighted().filter(n => !n.tombstone);
121
+ }
122
+ /** Rebuild the weighted-order array, excluding tombstones. */
123
+ toWeightedArray() {
124
+ return this.toWeightedNodes().map(n => n.value);
125
+ }
83
126
  /** Merge another RGA into this one. Union of all nodes; tombstones win. */
84
127
  merge(other) {
85
128
  for (const [key, node] of other.nodes) {
package/dist/index.d.ts CHANGED
@@ -9,9 +9,9 @@ import type { RGAEvent, EventComparator } from "./crdt/rga.js";
9
9
  export { parse, stringify, stringifyNode, fingerprint } from "./parse.js";
10
10
  export { diff, applyChangeSet } from "./diff.js";
11
11
  export { toRGATree, toMdast, applyMdastToRGATree, generateRGAChangeSet, applyRGAChangeSet, } from "./rga-tree.js";
12
- export { encodeTree, decodeTree, encodeChangeSet, decodeChangeSet } from "./codec.js";
12
+ export { encodeTree, decodeTree, encodeChangeSet, decodeChangeSet, encodeRGA, decodeRGA, } from "./codec.js";
13
13
  export type { ChangeSet, Change, RGAChangeSet, RGAChange, RGATreeRoot, RGATreeNode, RGAParentNode, RGALeafNode, } from "./types.js";
14
- export { RGA, type RGAEvent, type RGANodeId, type EventComparator } from "./types.js";
14
+ export { RGA, type RGAEvent, type RGANodeId, type EventComparator, } from "./types.js";
15
15
  /**
16
16
  * Compute an RGA-addressed changeset between an existing RGA tree and new markdown.
17
17
  */
package/dist/index.js CHANGED
@@ -10,8 +10,8 @@ import { toRGATree, toMdast, generateRGAChangeSet, applyRGAChangeSet, } from "./
10
10
  export { parse, stringify, stringifyNode, fingerprint } from "./parse.js";
11
11
  export { diff, applyChangeSet } from "./diff.js";
12
12
  export { toRGATree, toMdast, applyMdastToRGATree, generateRGAChangeSet, applyRGAChangeSet, } from "./rga-tree.js";
13
- export { encodeTree, decodeTree, encodeChangeSet, decodeChangeSet } from "./codec.js";
14
- export { RGA } from "./types.js";
13
+ export { encodeTree, decodeTree, encodeChangeSet, decodeChangeSet, encodeRGA, decodeRGA, } from "./codec.js";
14
+ export { RGA, } from "./types.js";
15
15
  /**
16
16
  * Compute an RGA-addressed changeset between an existing RGA tree and new markdown.
17
17
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storacha/md-merge",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/crdt/rga.ts CHANGED
@@ -108,6 +108,53 @@ export class RGA<T, E extends RGAEvent = RGAEvent> {
108
108
  return this.allOrdered()
109
109
  }
110
110
 
111
+ /** Rebuild ordered nodes via BFS over causal tree (including tombstones). */
112
+ private allWeighted(): RGANode<T, E>[] {
113
+ const ROOT_KEY = '__ROOT__'
114
+ const children = new Map<string, RGANode<T, E>[]>()
115
+ for (const node of this.nodes.values()) {
116
+ const key = node.afterId ? serializeId(node.afterId) : ROOT_KEY
117
+ let list = children.get(key)
118
+ if (!list) {
119
+ list = []
120
+ children.set(key, list)
121
+ }
122
+ list.push(node)
123
+ }
124
+ for (const list of children.values()) {
125
+ list.sort((a, b) => this.compareIds(a.id, b.id))
126
+ }
127
+ const result: RGANode<T, E>[] = []
128
+ let currentLevel = children.get(ROOT_KEY) ?? []
129
+ while (currentLevel.length > 0) {
130
+ result.push(...currentLevel)
131
+ const nextLevel: RGANode<T, E>[] = []
132
+ for (const node of currentLevel) {
133
+ const kids = children.get(serializeId(node.id))
134
+ if (kids) nextLevel.push(...kids)
135
+ }
136
+ nextLevel.sort((a, b) => this.compareIds(a.id, b.id))
137
+ currentLevel = nextLevel
138
+ }
139
+ return result
140
+ }
141
+
142
+ /** Get all weighted-order nodes including tombstones. */
143
+ toAllWeightedNodes(): RGANode<T, E>[] {
144
+ return this.allWeighted()
145
+ }
146
+
147
+ /** Get weighted-order non-tombstoned nodes. */
148
+ toWeightedNodes(): RGANode<T, E>[] {
149
+ return this.allWeighted().filter(n => !n.tombstone)
150
+ }
151
+
152
+ /** Rebuild the weighted-order array, excluding tombstones. */
153
+ toWeightedArray(): T[] {
154
+ return this.toWeightedNodes().map(n => n.value)
155
+ }
156
+
157
+
111
158
  /** Merge another RGA into this one. Union of all nodes; tombstones win. */
112
159
  merge(other: RGA<T, E>): void {
113
160
  for (const [key, node] of other.nodes) {
package/src/index.ts CHANGED
@@ -25,7 +25,14 @@ export {
25
25
  generateRGAChangeSet,
26
26
  applyRGAChangeSet,
27
27
  } from "./rga-tree.js";
28
- export { encodeTree, decodeTree, encodeChangeSet, decodeChangeSet } from "./codec.js";
28
+ export {
29
+ encodeTree,
30
+ decodeTree,
31
+ encodeChangeSet,
32
+ decodeChangeSet,
33
+ encodeRGA,
34
+ decodeRGA,
35
+ } from "./codec.js";
29
36
  export type {
30
37
  ChangeSet,
31
38
  Change,
@@ -36,7 +43,12 @@ export type {
36
43
  RGAParentNode,
37
44
  RGALeafNode,
38
45
  } from "./types.js";
39
- export { RGA, type RGAEvent, type RGANodeId, type EventComparator } from "./types.js";
46
+ export {
47
+ RGA,
48
+ type RGAEvent,
49
+ type RGANodeId,
50
+ type EventComparator,
51
+ } from "./types.js";
40
52
 
41
53
  /**
42
54
  * Compute an RGA-addressed changeset between an existing RGA tree and new markdown.