@vuer-ai/vuer-rtc 0.5.4 → 0.7.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 (65) hide show
  1. package/CLAUDE.md +65 -0
  2. package/dist/client/coalesceTextOperations.d.ts.map +1 -1
  3. package/dist/client/coalesceTextOperations.js +14 -13
  4. package/dist/client/coalesceTextOperations.js.map +1 -1
  5. package/dist/client/coalescence/index.d.ts +3 -0
  6. package/dist/client/coalescence/index.d.ts.map +1 -1
  7. package/dist/client/coalescence/index.js +3 -0
  8. package/dist/client/coalescence/index.js.map +1 -1
  9. package/dist/client/coalescence/lwwOperations.d.ts +37 -0
  10. package/dist/client/coalescence/lwwOperations.d.ts.map +1 -0
  11. package/dist/client/coalescence/lwwOperations.js +69 -0
  12. package/dist/client/coalescence/lwwOperations.js.map +1 -0
  13. package/dist/client/coalescence/numberOperations.d.ts +32 -0
  14. package/dist/client/coalescence/numberOperations.d.ts.map +1 -0
  15. package/dist/client/coalescence/numberOperations.js +66 -0
  16. package/dist/client/coalescence/numberOperations.js.map +1 -0
  17. package/dist/client/coalescence/registry.d.ts.map +1 -1
  18. package/dist/client/coalescence/registry.js +20 -0
  19. package/dist/client/coalescence/registry.js.map +1 -1
  20. package/dist/client/coalescence/vector3Operations.d.ts +32 -0
  21. package/dist/client/coalescence/vector3Operations.d.ts.map +1 -0
  22. package/dist/client/coalescence/vector3Operations.js +71 -0
  23. package/dist/client/coalescence/vector3Operations.js.map +1 -0
  24. package/dist/client/createTextDocument.js +4 -4
  25. package/dist/client/createTextDocument.js.map +1 -1
  26. package/dist/client/textActions.js +21 -21
  27. package/dist/client/textActions.js.map +1 -1
  28. package/dist/client/textTypes.d.ts +3 -9
  29. package/dist/client/textTypes.d.ts.map +1 -1
  30. package/dist/crdt/BTree.d.ts +2 -2
  31. package/dist/crdt/BTree.d.ts.map +1 -1
  32. package/dist/crdt/BTree.js +12 -12
  33. package/dist/crdt/BTree.js.map +1 -1
  34. package/dist/crdt/RangeTree.d.ts +2 -2
  35. package/dist/crdt/RangeTree.d.ts.map +1 -1
  36. package/dist/crdt/RangeTree.js +10 -10
  37. package/dist/crdt/RangeTree.js.map +1 -1
  38. package/dist/crdt/Rope.d.ts +6 -0
  39. package/dist/crdt/Rope.d.ts.map +1 -1
  40. package/dist/crdt/Rope.js +38 -10
  41. package/dist/crdt/Rope.js.map +1 -1
  42. package/dist/operations/apply/text.d.ts.map +1 -1
  43. package/dist/operations/apply/text.js +5 -2
  44. package/dist/operations/apply/text.js.map +1 -1
  45. package/package.json +1 -1
  46. package/src/client/TEXT_DOCUMENT_API.md +11 -4
  47. package/src/client/coalesceTextOperations.ts +17 -16
  48. package/src/client/coalescence/index.ts +3 -0
  49. package/src/client/coalescence/lwwOperations.ts +104 -0
  50. package/src/client/coalescence/numberOperations.ts +80 -0
  51. package/src/client/coalescence/registry.ts +22 -0
  52. package/src/client/coalescence/vector3Operations.ts +85 -0
  53. package/src/client/createTextDocument.ts +4 -4
  54. package/src/client/textActions.ts +21 -21
  55. package/src/client/textTypes.ts +3 -5
  56. package/src/crdt/BTree.ts +14 -14
  57. package/src/crdt/RangeTree.ts +12 -12
  58. package/src/crdt/Rope.ts +46 -11
  59. package/src/operations/apply/text.ts +5 -2
  60. package/tests/client/coalesce-text-operations.test.ts +182 -244
  61. package/tests/client/delete-coalescence-bug.test.ts +5 -5
  62. package/tests/client/graph-coalescence-phase1.test.ts +357 -0
  63. package/tests/crdt/btree.test.ts +2 -2
  64. package/tests/crdt/rope.test.ts +41 -0
  65. package/docs/rope-optimization-plan.md +0 -329
package/CLAUDE.md CHANGED
@@ -29,6 +29,71 @@ Deploy
29
29
 
30
30
  This ensures high-quality implementations and catches issues early.
31
31
 
32
+ ### Deployment Process
33
+
34
+ **Publishing a new version requires careful coordination between npm publish and documentation site updates.**
35
+
36
+ #### Complete Deployment Workflow
37
+
38
+ ```bash
39
+ # 1. Update package version
40
+ # Edit packages/vuer-rtc/package.json → bump version (e.g., 0.6.0)
41
+
42
+ # 2. Build and test locally
43
+ pnpm build && pnpm test
44
+
45
+ # 3. Commit package changes
46
+ git add -A && git commit -m "Release v0.6.0: <summary>" && git push
47
+
48
+ # 4. Publish to npm
49
+ pass otp npmjs && pnpm publish --otp $(pass otp npmjs)
50
+
51
+ # 5. Update documentation site
52
+ cd vuer-rtc-docs
53
+ # Edit package.json → update @vuer-ai/vuer-rtc to ^0.6.0
54
+ pnpm install # Updates pnpm-lock.yaml
55
+
56
+ # 6. Commit and deploy
57
+ git add -A && git commit -m "Update docs to v0.6.0"
58
+ cd ..
59
+ pnpm deploy # ← IMPORTANT: Uses workspace deploy script, pushes to main:netlify-production
60
+
61
+ # 7. WAIT for Netlify build (2-3 minutes)
62
+ # Do NOT check the site immediately - Netlify needs time to build and deploy
63
+
64
+ # 8. Verify deployment
65
+ curl https://rtc.vuer.ai | grep "v0.6.0"
66
+ # Or visit https://rtc.vuer.ai and check the version badge in the hero section
67
+ ```
68
+
69
+ #### Important Notes
70
+
71
+ **Why lockfile update is sufficient:**
72
+ - The docs site uses a Vite alias that points to the LOCAL package.json:
73
+ ```typescript
74
+ // vuer-rtc-docs/vite.config.ts
75
+ alias: {
76
+ '#vuer-rtc-pkg': path.resolve(__dirname, '../packages/vuer-rtc/package.json')
77
+ }
78
+ ```
79
+ - The VuerRTCBadge component imports version from this alias:
80
+ ```typescript
81
+ import packageJson from '#vuer-rtc-pkg';
82
+ const PACKAGE_VERSION = packageJson.version;
83
+ ```
84
+ - This means the site reads the version from the workspace, NOT from npm
85
+ - The lockfile change triggers Netlify rebuild, which picks up the updated local package.json
86
+
87
+ **Why to use `pnpm deploy`:**
88
+ - The workspace has a deploy script: `"deploy": "git push origin main:netlify-production"`
89
+ - This pushes to the correct branch that triggers Netlify deployment
90
+ - Using manual `git push` may push to the wrong branch
91
+
92
+ **Why to wait:**
93
+ - Netlify build takes 2-3 minutes after push
94
+ - Checking the site immediately will show stale version
95
+ - Wait for the build to complete before verifying
96
+
32
97
  ## Text Architecture (3-Component Design)
33
98
 
34
99
  The text handling system uses a 3-component architecture with clear separation of concerns:
@@ -1 +1 @@
1
- {"version":3,"file":"coalesceTextOperations.d.ts","sourceRoot":"","sources":["../../src/client/coalesceTextOperations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAIhD,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAsBD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,aAAa,EAAE,EACpB,OAAO,GAAE,eAAoB,GAC5B,aAAa,EAAE,CA6HjB;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAI/D"}
1
+ {"version":3,"file":"coalesceTextOperations.d.ts","sourceRoot":"","sources":["../../src/client/coalesceTextOperations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAY,MAAM,iBAAiB,CAAC;AAI1D,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAsBD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,aAAa,EAAE,EACpB,OAAO,GAAE,eAAoB,GAC5B,aAAa,EAAE,CA8HjB;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAI/D"}
@@ -49,21 +49,21 @@ export function coalesceTextOperations(ops, options = {}) {
49
49
  let pendingInsert = null;
50
50
  let pendingDelete = null;
51
51
  for (const op of ops) {
52
- if (op.type === 'insert') {
52
+ if (op.otype === 'insert') {
53
53
  // Flush any pending delete before starting new insert
54
54
  if (pendingDelete !== null) {
55
55
  // Sort and optimize deletions array before flushing
56
- pendingDelete.op.deletions = sortAndOptimizeDeletions(pendingDelete.op.deletions);
56
+ pendingDelete.deletions = sortAndOptimizeDeletions(pendingDelete.deletions);
57
57
  result.push(pendingDelete);
58
58
  pendingDelete = null;
59
59
  }
60
60
  if (pendingInsert === null) {
61
61
  // Start new pending insert
62
- pendingInsert = { type: 'insert', op: { ...op.op } };
62
+ pendingInsert = { ...op };
63
63
  }
64
64
  else {
65
- const prevOp = pendingInsert.op;
66
- const currOp = op.op;
65
+ const prevOp = pendingInsert;
66
+ const currOp = op;
67
67
  // Parse IDs to extract agent and local sequence numbers
68
68
  const prevId = parseItemId(prevOp.id);
69
69
  const currId = parseItemId(currOp.id);
@@ -85,6 +85,7 @@ export function coalesceTextOperations(ops, options = {}) {
85
85
  if (sameAgent && sequentialIds && withinThreshold && formsChain) {
86
86
  // Merge operations
87
87
  const mergedOp = {
88
+ otype: 'insert',
88
89
  id: prevOp.id, // Keep first ID (anchor point)
89
90
  content: prevOp.content + currOp.content, // Concatenate content
90
91
  parentId: prevOp.parentId, // Keep first parentId
@@ -93,7 +94,7 @@ export function coalesceTextOperations(ops, options = {}) {
93
94
  // Track the last character ID for chain validation in next merge
94
95
  _lastCharId: currOp.id,
95
96
  };
96
- pendingInsert = { type: 'insert', op: mergedOp };
97
+ pendingInsert = mergedOp;
97
98
  }
98
99
  else {
99
100
  // Debug: Log why merge failed
@@ -107,11 +108,11 @@ export function coalesceTextOperations(ops, options = {}) {
107
108
  console.log('[coalesce] Not a YATA chain:', { currParent: currOp.parentId, prevId: prevOp.id, prevParent: prevOp.parentId, currOp: currOp.id });
108
109
  // Can't merge - flush pending and start new
109
110
  result.push(pendingInsert);
110
- pendingInsert = { type: 'insert', op: { ...currOp } };
111
+ pendingInsert = { ...currOp };
111
112
  }
112
113
  }
113
114
  }
114
- else if (op.type === 'delete') {
115
+ else if (op.otype === 'delete') {
115
116
  // Flush any pending insert before handling delete
116
117
  if (pendingInsert !== null) {
117
118
  result.push(pendingInsert);
@@ -119,7 +120,7 @@ export function coalesceTextOperations(ops, options = {}) {
119
120
  }
120
121
  if (pendingDelete === null) {
121
122
  // Start new pending delete
122
- pendingDelete = { type: 'delete', op: { ...op.op, deletions: [...op.op.deletions] } };
123
+ pendingDelete = { ...op, deletions: [...op.deletions] };
123
124
  }
124
125
  else {
125
126
  // Try to merge consecutive delete operations
@@ -128,12 +129,12 @@ export function coalesceTextOperations(ops, options = {}) {
128
129
  const canMerge = true; // For deletes, we just merge the deletions arrays
129
130
  if (canMerge) {
130
131
  // Merge by combining deletions
131
- pendingDelete.op.deletions.push(...op.op.deletions);
132
+ pendingDelete.deletions.push(...op.deletions);
132
133
  }
133
134
  else {
134
135
  // Can't merge - flush pending and start new
135
136
  result.push(pendingDelete);
136
- pendingDelete = { type: 'delete', op: { ...op.op, deletions: [...op.op.deletions] } };
137
+ pendingDelete = { ...op, deletions: [...op.deletions] };
137
138
  }
138
139
  }
139
140
  }
@@ -145,7 +146,7 @@ export function coalesceTextOperations(ops, options = {}) {
145
146
  }
146
147
  if (pendingDelete !== null) {
147
148
  // Sort and optimize deletions array before flushing
148
- pendingDelete.op.deletions = sortAndOptimizeDeletions(pendingDelete.op.deletions);
149
+ pendingDelete.deletions = sortAndOptimizeDeletions(pendingDelete.deletions);
149
150
  result.push(pendingDelete);
150
151
  pendingDelete = null;
151
152
  }
@@ -158,7 +159,7 @@ export function coalesceTextOperations(ops, options = {}) {
158
159
  }
159
160
  if (pendingDelete !== null) {
160
161
  // Sort and optimize deletions array before flushing
161
- pendingDelete.op.deletions = sortAndOptimizeDeletions(pendingDelete.op.deletions);
162
+ pendingDelete.deletions = sortAndOptimizeDeletions(pendingDelete.deletions);
162
163
  result.push(pendingDelete);
163
164
  }
164
165
  return result;
@@ -1 +1 @@
1
- {"version":3,"file":"coalesceTextOperations.js","sourceRoot":"","sources":["../../src/client/coalesceTextOperations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,WAAW,IAAI,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAOnF;;;GAGG;AACH,SAAS,wBAAwB,CAAC,SAAgD;IAChF,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAE7C,+DAA+D;IAC/D,MAAM,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAC1C,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC1B,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC1B,IAAI,GAAG,CAAC,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,CAAC;YAC5B,OAAO,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC5C,CAAC;QACD,OAAO,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;IAC3B,CAAC,CAAC,CAAC;IAEH,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC;AACnC,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,sBAAsB,CACpC,GAAoB,EACpB,UAA2B,EAAE;IAE7B,MAAM,EAAE,WAAW,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAEvC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IAEjC,MAAM,MAAM,GAAoB,EAAE,CAAC;IACnC,IAAI,aAAa,GAA4C,IAAI,CAAC;IAClE,IAAI,aAAa,GAAuC,IAAI,CAAC;IAE7D,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,IAAI,EAAE,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACzB,sDAAsD;YACtD,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;gBAC3B,oDAAoD;gBACpD,aAAa,CAAC,EAAE,CAAC,SAAS,GAAG,wBAAwB,CAAC,aAAa,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC;gBAClF,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;gBAC3B,aAAa,GAAG,IAAI,CAAC;YACvB,CAAC;YACD,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;gBAC3B,2BAA2B;gBAC3B,aAAa,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC;YACvD,CAAC;iBAAM,CAAC;gBACN,MAAM,MAAM,GAAG,aAAa,CAAC,EAAE,CAAC;gBAChC,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC;gBAErB,wDAAwD;gBACxD,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACtC,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBAEtC,yBAAyB;gBACzB,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,CAAC;gBAEhD,kEAAkE;gBAClE,kEAAkE;gBAClE,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,KAAK,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;gBAExE,sEAAsE;gBACtE,MAAM,UAAU,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;gBAClD,MAAM,eAAe,GAAG,UAAU,IAAI,WAAW,CAAC;gBAElD,yDAAyD;gBACzD,4EAA4E;gBAC5E,qEAAqE;gBACrE,mEAAmE;gBACnE,MAAM,UAAU,GAAI,MAAc,CAAC,WAAW,IAAI,MAAM,CAAC,EAAE,CAAC;gBAC5D,MAAM,UAAU,GACd,MAAM,CAAC,QAAQ,KAAK,UAAU;oBAC9B,CAAC,MAAM,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC;gBAEpE,IAAI,SAAS,IAAI,aAAa,IAAI,eAAe,IAAI,UAAU,EAAE,CAAC;oBAChE,mBAAmB;oBACnB,MAAM,QAAQ,GAAa;wBACzB,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,+BAA+B;wBAC9C,OAAO,EAAE,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,EAAE,sBAAsB;wBAChE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,sBAAsB;wBACjD,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,qCAAqC;wBAC5E,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,+CAA+C;wBAC9D,iEAAiE;wBACjE,WAAW,EAAE,MAAM,CAAC,EAAE;qBAChB,CAAC;oBACT,aAAa,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC;gBACnD,CAAC;qBAAM,CAAC;oBACN,8BAA8B;oBAC9B,IAAI,CAAC,SAAS;wBAAE,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;oBAC9F,IAAI,CAAC,aAAa;wBAAE,OAAO,CAAC,GAAG,CAAC,gCAAgC,EAAE,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;oBACzH,IAAI,CAAC,eAAe;wBAAE,OAAO,CAAC,GAAG,CAAC,qCAAqC,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;oBAChH,IAAI,CAAC,UAAU;wBAAE,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;oBAEjK,4CAA4C;oBAC5C,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;oBAC3B,aAAa,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,GAAG,MAAM,EAAE,EAAE,CAAC;gBACxD,CAAC;YACH,CAAC;QACH,CAAC;aAAM,IAAI,EAAE,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAChC,kDAAkD;YAClD,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;gBAC3B,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;gBAC3B,aAAa,GAAG,IAAI,CAAC;YACvB,CAAC;YAED,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;gBAC3B,2BAA2B;gBAC3B,aAAa,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;YACxF,CAAC;iBAAM,CAAC;gBACN,6CAA6C;gBAC7C,6DAA6D;gBAC7D,yCAAyC;gBACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,kDAAkD;gBAEzE,IAAI,QAAQ,EAAE,CAAC;oBACb,+BAA+B;oBAC/B,aAAa,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC;gBACtD,CAAC;qBAAM,CAAC;oBACN,4CAA4C;oBAC5C,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;oBAC3B,aAAa,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;gBACxF,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,4CAA4C;YAC5C,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;gBAC3B,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;gBAC3B,aAAa,GAAG,IAAI,CAAC;YACvB,CAAC;YACD,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;gBAC3B,oDAAoD;gBACpD,aAAa,CAAC,EAAE,CAAC,SAAS,GAAG,wBAAwB,CAAC,aAAa,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC;gBAClF,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;gBAC3B,aAAa,GAAG,IAAI,CAAC;YACvB,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,yCAAyC;IACzC,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;QAC3B,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC7B,CAAC;IACD,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;QAC3B,oDAAoD;QACpD,aAAa,CAAC,EAAE,CAAC,SAAS,GAAG,wBAAwB,CAAC,aAAa,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC;QAClF,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC7B,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAC,CAAW,EAAE,CAAW;IACrD,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG;QAAE,OAAO,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,gBAAgB;IAC3D,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE;QAAE,OAAO,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,kBAAkB;IACzD,OAAO,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB;AACpD,CAAC"}
1
+ {"version":3,"file":"coalesceTextOperations.js","sourceRoot":"","sources":["../../src/client/coalesceTextOperations.ts"],"names":[],"mappings":"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"}
@@ -6,4 +6,7 @@
6
6
  export { coalesceOperations, registerCoalescer, getCoalescer, hasCoalescer, type CoalesceOptions, type CoalesceHandler, type TypeGuard, } from './registry.js';
7
7
  export { coalesceTextInserts, isTextInsertOp, type TextInsertOp } from './textInserts.js';
8
8
  export { coalesceTextDeletes, isTextDeleteOp, type TextDeleteOp } from './textDeletes.js';
9
+ export { coalesceNumberAdds, isNumberAddOp, type NumberAddOp } from './numberOperations.js';
10
+ export { coalesceVector3Adds, isVector3AddOp, type Vector3AddOp } from './vector3Operations.js';
11
+ export { coalesceLWWSets, isLWWSetOp, type LWWSetOp } from './lwwOperations.js';
9
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/coalescence/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,SAAS,GACf,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC1F,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/coalescence/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,SAAS,GACf,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC1F,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC1F,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,KAAK,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAC5F,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAChG,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC"}
@@ -6,4 +6,7 @@
6
6
  export { coalesceOperations, registerCoalescer, getCoalescer, hasCoalescer, } from './registry.js';
7
7
  export { coalesceTextInserts, isTextInsertOp } from './textInserts.js';
8
8
  export { coalesceTextDeletes, isTextDeleteOp } from './textDeletes.js';
9
+ export { coalesceNumberAdds, isNumberAddOp } from './numberOperations.js';
10
+ export { coalesceVector3Adds, isVector3AddOp } from './vector3Operations.js';
11
+ export { coalesceLWWSets, isLWWSetOp } from './lwwOperations.js';
9
12
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/coalescence/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,YAAY,GAIb,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAqB,MAAM,kBAAkB,CAAC;AAC1F,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAqB,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/coalescence/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,YAAY,GAIb,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAqB,MAAM,kBAAkB,CAAC;AAC1F,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAqB,MAAM,kBAAkB,CAAC;AAC1F,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAoB,MAAM,uBAAuB,CAAC;AAC5F,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAqB,MAAM,wBAAwB,CAAC;AAChG,OAAO,EAAE,eAAe,EAAE,UAAU,EAAiB,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Last-Write-Wins (LWW) Operations Coalescence
3
+ *
4
+ * Generic coalescer for all *.set operations.
5
+ * Set operations follow Last-Write-Wins semantics - only the last value matters.
6
+ *
7
+ * Supported operations:
8
+ * - number.set, string.set, boolean.set
9
+ * - vector3.set, euler.set, quaternion.set, color.set
10
+ * - array.set, object.set
11
+ */
12
+ import type { Operation, NumberSetOp, StringSetOp, BooleanSetOp, Vector3SetOp, EulerSetOp, QuaternionSetOp, ColorSetOp, ArraySetOp, ObjectSetOp } from '../../operations/OperationTypes.js';
13
+ import type { CoalesceOptions } from './registry.js';
14
+ export type LWWSetOp = NumberSetOp | StringSetOp | BooleanSetOp | Vector3SetOp | EulerSetOp | QuaternionSetOp | ColorSetOp | ArraySetOp | ObjectSetOp;
15
+ /**
16
+ * Check if an operation is a *.set operation
17
+ */
18
+ export declare function isLWWSetOp(op: Operation): op is LWWSetOp;
19
+ /**
20
+ * Coalesce consecutive *.set operations using Last-Write-Wins semantics.
21
+ *
22
+ * Since set operations follow LWW, only the last value in a sequence matters.
23
+ * We can safely discard all but the last operation for the same target.
24
+ *
25
+ * Example:
26
+ * Input: [set(key:"cube", path:"color", value:"red"), set(key:"cube", path:"color", value:"blue")]
27
+ * Output: [set(key:"cube", path:"color", value:"blue")]
28
+ *
29
+ * @param ops - Array of *.set operations
30
+ * @param options - Coalescence options
31
+ * NOTE: Time threshold is ignored for Last-Write-Wins operations.
32
+ * LWW semantics mean only the final value matters, regardless of timing,
33
+ * so we keep only the last operation on each target.
34
+ * @returns New array with coalesced operations
35
+ */
36
+ export declare function coalesceLWWSets(ops: LWWSetOp[], options?: CoalesceOptions): LWWSetOp[];
37
+ //# sourceMappingURL=lwwOperations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lwwOperations.d.ts","sourceRoot":"","sources":["../../../src/client/coalescence/lwwOperations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,WAAW,EACX,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,eAAe,EACf,UAAU,EACV,UAAU,EACV,WAAW,EACZ,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGrD,MAAM,MAAM,QAAQ,GAChB,WAAW,GACX,WAAW,GACX,YAAY,GACZ,YAAY,GACZ,UAAU,GACV,eAAe,GACf,UAAU,GACV,UAAU,GACV,WAAW,CAAC;AAEhB;;GAEG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,SAAS,GAAG,EAAE,IAAI,QAAQ,CAMxD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,QAAQ,EAAE,EACf,OAAO,GAAE,eAAoB,GAC5B,QAAQ,EAAE,CAkCZ"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Last-Write-Wins (LWW) Operations Coalescence
3
+ *
4
+ * Generic coalescer for all *.set operations.
5
+ * Set operations follow Last-Write-Wins semantics - only the last value matters.
6
+ *
7
+ * Supported operations:
8
+ * - number.set, string.set, boolean.set
9
+ * - vector3.set, euler.set, quaternion.set, color.set
10
+ * - array.set, object.set
11
+ */
12
+ /**
13
+ * Check if an operation is a *.set operation
14
+ */
15
+ export function isLWWSetOp(op) {
16
+ return (typeof op.otype === 'string' &&
17
+ op.otype.endsWith('.set') &&
18
+ op.value !== undefined);
19
+ }
20
+ /**
21
+ * Coalesce consecutive *.set operations using Last-Write-Wins semantics.
22
+ *
23
+ * Since set operations follow LWW, only the last value in a sequence matters.
24
+ * We can safely discard all but the last operation for the same target.
25
+ *
26
+ * Example:
27
+ * Input: [set(key:"cube", path:"color", value:"red"), set(key:"cube", path:"color", value:"blue")]
28
+ * Output: [set(key:"cube", path:"color", value:"blue")]
29
+ *
30
+ * @param ops - Array of *.set operations
31
+ * @param options - Coalescence options
32
+ * NOTE: Time threshold is ignored for Last-Write-Wins operations.
33
+ * LWW semantics mean only the final value matters, regardless of timing,
34
+ * so we keep only the last operation on each target.
35
+ * @returns New array with coalesced operations
36
+ */
37
+ export function coalesceLWWSets(ops, options = {}) {
38
+ if (ops.length === 0)
39
+ return ops;
40
+ const result = [];
41
+ let pending = null;
42
+ for (const op of ops) {
43
+ if (pending === null) {
44
+ // Start new pending set
45
+ pending = { ...op };
46
+ }
47
+ else {
48
+ // Check if operations target the same property AND same operation type
49
+ const sameTarget = pending.key === op.key &&
50
+ pending.path === op.path &&
51
+ pending.otype === op.otype;
52
+ if (sameTarget) {
53
+ // LWW: Replace with newer value
54
+ pending = { ...op };
55
+ }
56
+ else {
57
+ // Different target or type - flush pending and start new
58
+ result.push(pending);
59
+ pending = { ...op };
60
+ }
61
+ }
62
+ }
63
+ // Flush any remaining pending set
64
+ if (pending !== null) {
65
+ result.push(pending);
66
+ }
67
+ return result;
68
+ }
69
+ //# sourceMappingURL=lwwOperations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lwwOperations.js","sourceRoot":"","sources":["../../../src/client/coalescence/lwwOperations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA4BH;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,EAAa;IACtC,OAAO,CACL,OAAO,EAAE,CAAC,KAAK,KAAK,QAAQ;QAC5B,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;QACxB,EAAU,CAAC,KAAK,KAAK,SAAS,CAChC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,eAAe,CAC7B,GAAe,EACf,UAA2B,EAAE;IAE7B,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IAEjC,MAAM,MAAM,GAAe,EAAE,CAAC;IAC9B,IAAI,OAAO,GAAoB,IAAI,CAAC;IAEpC,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,wBAAwB;YACxB,OAAO,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,uEAAuE;YACvE,MAAM,UAAU,GACd,OAAO,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG;gBACtB,OAAO,CAAC,IAAI,KAAK,EAAE,CAAC,IAAI;gBACxB,OAAO,CAAC,KAAK,KAAK,EAAE,CAAC,KAAK,CAAC;YAE7B,IAAI,UAAU,EAAE,CAAC;gBACf,gCAAgC;gBAChC,OAAO,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC;YACtB,CAAC;iBAAM,CAAC;gBACN,yDAAyD;gBACzD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACrB,OAAO,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC;YACtB,CAAC;QACH,CAAC;IACH,CAAC;IAED,kCAAkC;IAClC,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Number Operations Coalescence
3
+ *
4
+ * Merges consecutive number.add operations on the same target.
5
+ * Addition is commutative, so we can safely merge multiple adds into one.
6
+ */
7
+ import type { Operation, NumberAddOp } from '../../operations/OperationTypes.js';
8
+ import type { CoalesceOptions } from './registry.js';
9
+ export type { NumberAddOp };
10
+ /**
11
+ * Check if an operation is a number.add operation
12
+ */
13
+ export declare function isNumberAddOp(op: Operation): op is NumberAddOp;
14
+ /**
15
+ * Coalesce consecutive number.add operations.
16
+ *
17
+ * Since addition is commutative (a + b = b + a), we can safely merge
18
+ * all consecutive adds into a single operation by summing the values.
19
+ *
20
+ * Example:
21
+ * Input: [add(key:"score", path:"value", value:10), add(key:"score", path:"value", value:5)]
22
+ * Output: [add(key:"score", path:"value", value:15)]
23
+ *
24
+ * @param ops - Array of number.add operations
25
+ * @param options - Coalescence options
26
+ * NOTE: Time threshold is ignored for commutative operations like addition.
27
+ * Mathematically, a+b = b+a regardless of when they occurred, so we merge
28
+ * all consecutive operations on the same target without time restrictions.
29
+ * @returns New array with coalesced operations
30
+ */
31
+ export declare function coalesceNumberAdds(ops: NumberAddOp[], options?: CoalesceOptions): NumberAddOp[];
32
+ //# sourceMappingURL=numberOperations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"numberOperations.d.ts","sourceRoot":"","sources":["../../../src/client/coalescence/numberOperations.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGrD,YAAY,EAAE,WAAW,EAAE,CAAC;AAE5B;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,SAAS,GAAG,EAAE,IAAI,WAAW,CAK9D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,WAAW,EAAE,EAClB,OAAO,GAAE,eAAoB,GAC5B,WAAW,EAAE,CAoCf"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Number Operations Coalescence
3
+ *
4
+ * Merges consecutive number.add operations on the same target.
5
+ * Addition is commutative, so we can safely merge multiple adds into one.
6
+ */
7
+ /**
8
+ * Check if an operation is a number.add operation
9
+ */
10
+ export function isNumberAddOp(op) {
11
+ return (op.otype === 'number.add' &&
12
+ typeof op.value === 'number');
13
+ }
14
+ /**
15
+ * Coalesce consecutive number.add operations.
16
+ *
17
+ * Since addition is commutative (a + b = b + a), we can safely merge
18
+ * all consecutive adds into a single operation by summing the values.
19
+ *
20
+ * Example:
21
+ * Input: [add(key:"score", path:"value", value:10), add(key:"score", path:"value", value:5)]
22
+ * Output: [add(key:"score", path:"value", value:15)]
23
+ *
24
+ * @param ops - Array of number.add operations
25
+ * @param options - Coalescence options
26
+ * NOTE: Time threshold is ignored for commutative operations like addition.
27
+ * Mathematically, a+b = b+a regardless of when they occurred, so we merge
28
+ * all consecutive operations on the same target without time restrictions.
29
+ * @returns New array with coalesced operations
30
+ */
31
+ export function coalesceNumberAdds(ops, options = {}) {
32
+ if (ops.length === 0)
33
+ return ops;
34
+ const result = [];
35
+ let pending = null;
36
+ for (const op of ops) {
37
+ if (pending === null) {
38
+ // Start new pending add
39
+ pending = { ...op };
40
+ }
41
+ else {
42
+ // Check if operations target the same property
43
+ const sameTarget = pending.key === op.key && pending.path === op.path;
44
+ if (sameTarget) {
45
+ // Merge operations by summing values
46
+ pending = {
47
+ otype: 'number.add',
48
+ key: pending.key,
49
+ path: pending.path,
50
+ value: pending.value + op.value,
51
+ };
52
+ }
53
+ else {
54
+ // Different target - flush pending and start new
55
+ result.push(pending);
56
+ pending = { ...op };
57
+ }
58
+ }
59
+ }
60
+ // Flush any remaining pending add
61
+ if (pending !== null) {
62
+ result.push(pending);
63
+ }
64
+ return result;
65
+ }
66
+ //# sourceMappingURL=numberOperations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"numberOperations.js","sourceRoot":"","sources":["../../../src/client/coalescence/numberOperations.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,EAAa;IACzC,OAAO,CACL,EAAE,CAAC,KAAK,KAAK,YAAY;QACzB,OAAQ,EAAU,CAAC,KAAK,KAAK,QAAQ,CACtC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,kBAAkB,CAChC,GAAkB,EAClB,UAA2B,EAAE;IAE7B,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IAEjC,MAAM,MAAM,GAAkB,EAAE,CAAC;IACjC,IAAI,OAAO,GAAuB,IAAI,CAAC;IAEvC,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,wBAAwB;YACxB,OAAO,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,+CAA+C;YAC/C,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI,OAAO,CAAC,IAAI,KAAK,EAAE,CAAC,IAAI,CAAC;YAEtE,IAAI,UAAU,EAAE,CAAC;gBACf,qCAAqC;gBACrC,OAAO,GAAG;oBACR,KAAK,EAAE,YAAY;oBACnB,GAAG,EAAE,OAAO,CAAC,GAAG;oBAChB,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,KAAK,EAAE,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC,KAAK;iBAChC,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,iDAAiD;gBACjD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACrB,OAAO,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC;YACtB,CAAC;QACH,CAAC;IACH,CAAC;IAED,kCAAkC;IAClC,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/client/coalescence/registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAC;AAIpE,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,IAAI,CAC7D,GAAG,EAAE,CAAC,EAAE,EACR,OAAO,EAAE,eAAe,KACrB,CAAC,EAAE,CAAC;AAET;;GAEG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,IAAI,CAAC,EAAE,EAAE,SAAS,KAAK,EAAE,IAAI,CAAC,CAAC;AAEpF;;GAEG;AACH,UAAU,aAAa,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS;IACrD,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IACpB,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;CAC7B;AAOD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,SAAS,EACnD,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,EACnB,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,GAC1B,IAAI,CAKN;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAErE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,SAAS,EAAE,EAChB,OAAO,GAAE,eAAoB,GAC5B,SAAS,EAAE,CAoDb"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/client/coalescence/registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAC;AAOpE,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,IAAI,CAC7D,GAAG,EAAE,CAAC,EAAE,EACR,OAAO,EAAE,eAAe,KACrB,CAAC,EAAE,CAAC;AAET;;GAEG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,IAAI,CAAC,EAAE,EAAE,SAAS,KAAK,EAAE,IAAI,CAAC,CAAC;AAEpF;;GAEG;AACH,UAAU,aAAa,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS;IACrD,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IACpB,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;CAC7B;AAOD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,SAAS,EACnD,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,EACnB,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,GAC1B,IAAI,CAKN;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAErE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,SAAS,EAAE,EAChB,OAAO,GAAE,eAAoB,GAC5B,SAAS,EAAE,CAoDb"}
@@ -6,6 +6,9 @@
6
6
  */
7
7
  import { coalesceTextInserts, isTextInsertOp } from './textInserts.js';
8
8
  import { coalesceTextDeletes, isTextDeleteOp } from './textDeletes.js';
9
+ import { coalesceNumberAdds, isNumberAddOp } from './numberOperations.js';
10
+ import { coalesceVector3Adds, isVector3AddOp } from './vector3Operations.js';
11
+ import { coalesceLWWSets, isLWWSetOp } from './lwwOperations.js';
9
12
  /**
10
13
  * Global coalescence registry
11
14
  */
@@ -92,4 +95,21 @@ export function coalesceOperations(ops, options = {}) {
92
95
  // Register built-in coalescers
93
96
  registerCoalescer('text.insert', isTextInsertOp, coalesceTextInserts);
94
97
  registerCoalescer('text.delete', isTextDeleteOp, coalesceTextDeletes);
98
+ registerCoalescer('number.add', isNumberAddOp, coalesceNumberAdds);
99
+ registerCoalescer('vector3.add', isVector3AddOp, coalesceVector3Adds);
100
+ // Register LWW coalescer for all *.set operations
101
+ const LWW_SET_OPERATIONS = [
102
+ 'number.set',
103
+ 'string.set',
104
+ 'boolean.set',
105
+ 'vector3.set',
106
+ 'euler.set',
107
+ 'quaternion.set',
108
+ 'color.set',
109
+ 'array.set',
110
+ 'object.set',
111
+ ];
112
+ for (const otype of LWW_SET_OPERATIONS) {
113
+ registerCoalescer(otype, isLWWSetOp, coalesceLWWSets);
114
+ }
95
115
  //# sourceMappingURL=registry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/client/coalescence/registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/client/coalescence/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Vector3 Operations Coalescence
3
+ *
4
+ * Merges consecutive vector3.add operations on the same target.
5
+ * Component-wise addition is commutative, so we can safely merge multiple adds.
6
+ */
7
+ import type { Operation, Vector3AddOp } from '../../operations/OperationTypes.js';
8
+ import type { CoalesceOptions } from './registry.js';
9
+ export type { Vector3AddOp };
10
+ /**
11
+ * Check if an operation is a vector3.add operation
12
+ */
13
+ export declare function isVector3AddOp(op: Operation): op is Vector3AddOp;
14
+ /**
15
+ * Coalesce consecutive vector3.add operations.
16
+ *
17
+ * Since component-wise addition is commutative, we can safely merge
18
+ * all consecutive adds into a single operation by summing the vectors.
19
+ *
20
+ * Example:
21
+ * Input: [add(key:"player", path:"position", value:[1,0,0]), add(key:"player", path:"position", value:[0,2,0])]
22
+ * Output: [add(key:"player", path:"position", value:[1,2,0])]
23
+ *
24
+ * @param ops - Array of vector3.add operations
25
+ * @param options - Coalescence options
26
+ * NOTE: Time threshold is ignored for commutative operations like vector addition.
27
+ * Component-wise addition is commutative regardless of timing, so we merge
28
+ * all consecutive operations on the same target without time restrictions.
29
+ * @returns New array with coalesced operations
30
+ */
31
+ export declare function coalesceVector3Adds(ops: Vector3AddOp[], options?: CoalesceOptions): Vector3AddOp[];
32
+ //# sourceMappingURL=vector3Operations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vector3Operations.d.ts","sourceRoot":"","sources":["../../../src/client/coalescence/vector3Operations.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGrD,YAAY,EAAE,YAAY,EAAE,CAAC;AAE7B;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,SAAS,GAAG,EAAE,IAAI,YAAY,CAMhE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,YAAY,EAAE,EACnB,OAAO,GAAE,eAAoB,GAC5B,YAAY,EAAE,CAwChB"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Vector3 Operations Coalescence
3
+ *
4
+ * Merges consecutive vector3.add operations on the same target.
5
+ * Component-wise addition is commutative, so we can safely merge multiple adds.
6
+ */
7
+ /**
8
+ * Check if an operation is a vector3.add operation
9
+ */
10
+ export function isVector3AddOp(op) {
11
+ return (op.otype === 'vector3.add' &&
12
+ Array.isArray(op.value) &&
13
+ op.value.length === 3);
14
+ }
15
+ /**
16
+ * Coalesce consecutive vector3.add operations.
17
+ *
18
+ * Since component-wise addition is commutative, we can safely merge
19
+ * all consecutive adds into a single operation by summing the vectors.
20
+ *
21
+ * Example:
22
+ * Input: [add(key:"player", path:"position", value:[1,0,0]), add(key:"player", path:"position", value:[0,2,0])]
23
+ * Output: [add(key:"player", path:"position", value:[1,2,0])]
24
+ *
25
+ * @param ops - Array of vector3.add operations
26
+ * @param options - Coalescence options
27
+ * NOTE: Time threshold is ignored for commutative operations like vector addition.
28
+ * Component-wise addition is commutative regardless of timing, so we merge
29
+ * all consecutive operations on the same target without time restrictions.
30
+ * @returns New array with coalesced operations
31
+ */
32
+ export function coalesceVector3Adds(ops, options = {}) {
33
+ if (ops.length === 0)
34
+ return ops;
35
+ const result = [];
36
+ let pending = null;
37
+ for (const op of ops) {
38
+ if (pending === null) {
39
+ // Start new pending add (copy value array to avoid mutations)
40
+ pending = { ...op, value: [...op.value] };
41
+ }
42
+ else {
43
+ // Check if operations target the same property
44
+ const sameTarget = pending.key === op.key && pending.path === op.path;
45
+ if (sameTarget) {
46
+ // Merge operations by summing vectors component-wise
47
+ pending = {
48
+ otype: 'vector3.add',
49
+ key: pending.key,
50
+ path: pending.path,
51
+ value: [
52
+ pending.value[0] + op.value[0],
53
+ pending.value[1] + op.value[1],
54
+ pending.value[2] + op.value[2],
55
+ ],
56
+ };
57
+ }
58
+ else {
59
+ // Different target - flush pending and start new
60
+ result.push(pending);
61
+ pending = { ...op, value: [...op.value] };
62
+ }
63
+ }
64
+ }
65
+ // Flush any remaining pending add
66
+ if (pending !== null) {
67
+ result.push(pending);
68
+ }
69
+ return result;
70
+ }
71
+ //# sourceMappingURL=vector3Operations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vector3Operations.js","sourceRoot":"","sources":["../../../src/client/coalescence/vector3Operations.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,EAAa;IAC1C,OAAO,CACL,EAAE,CAAC,KAAK,KAAK,aAAa;QAC1B,KAAK,CAAC,OAAO,CAAE,EAAU,CAAC,KAAK,CAAC;QAC/B,EAAU,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAC/B,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,mBAAmB,CACjC,GAAmB,EACnB,UAA2B,EAAE;IAE7B,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IAEjC,MAAM,MAAM,GAAmB,EAAE,CAAC;IAClC,IAAI,OAAO,GAAwB,IAAI,CAAC;IAExC,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,8DAA8D;YAC9D,OAAO,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAA6B,EAAE,CAAC;QACxE,CAAC;aAAM,CAAC;YACN,+CAA+C;YAC/C,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI,OAAO,CAAC,IAAI,KAAK,EAAE,CAAC,IAAI,CAAC;YAEtE,IAAI,UAAU,EAAE,CAAC;gBACf,qDAAqD;gBACrD,OAAO,GAAG;oBACR,KAAK,EAAE,aAAa;oBACpB,GAAG,EAAE,OAAO,CAAC,GAAG;oBAChB,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,KAAK,EAAE;wBACL,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;wBAC9B,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;wBAC9B,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;qBAC/B;iBACF,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,iDAAiD;gBACjD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACrB,OAAO,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAA6B,EAAE,CAAC;YACxE,CAAC;QACH,CAAC;IACH,CAAC;IAED,kCAAkC;IAClC,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}