@loro-extended/change 5.4.0 → 5.4.2

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.
package/dist/index.js CHANGED
@@ -99,6 +99,11 @@ function deriveValueShapePlaceholder(shape) {
99
99
  }
100
100
  }
101
101
 
102
+ // src/diff-overlay.ts
103
+ function createDiffOverlay(doc, batch) {
104
+ return new Map(doc.diff(batch.to, batch.from, false));
105
+ }
106
+
102
107
  // src/functional-helpers.ts
103
108
  import {
104
109
  LoroDoc as LoroDoc2
@@ -547,6 +552,10 @@ var BaseRefInternals = class {
547
552
  getDoc() {
548
553
  return this.params.getDoc();
549
554
  }
555
+ /** Get the diff overlay map (if provided) */
556
+ getOverlay() {
557
+ return this.params.overlay;
558
+ }
550
559
  /**
551
560
  * Get the TypedRefParams needed to recreate this ref.
552
561
  * Used by change() to create draft refs with modified params.
@@ -561,7 +570,8 @@ var BaseRefInternals = class {
561
570
  getContainer: this.params.getContainer,
562
571
  autoCommit: this.params.autoCommit,
563
572
  batchedMutation: this.params.batchedMutation,
564
- getDoc: this.params.getDoc
573
+ getDoc: this.params.getDoc,
574
+ overlay: this.params.overlay
565
575
  };
566
576
  }
567
577
  /** Get the loro namespace (cached) */
@@ -630,6 +640,14 @@ var CounterRefInternals = class extends BaseRefInternals {
630
640
  getValue() {
631
641
  const container = this.getContainer();
632
642
  const containerValue = container.value;
643
+ const overlay = this.getOverlay();
644
+ if (overlay) {
645
+ const diff = overlay.get(container.id);
646
+ if (diff && diff.type === "counter") {
647
+ const counterDiff = diff;
648
+ return containerValue + counterDiff.increment;
649
+ }
650
+ }
633
651
  if (containerValue !== 0 || this.materialized) {
634
652
  return containerValue;
635
653
  }
@@ -850,6 +868,33 @@ function convertInputToRef(value, shape) {
850
868
  // src/typed-refs/list-ref-base.ts
851
869
  var ListRefBaseInternals = class extends BaseRefInternals {
852
870
  itemCache = /* @__PURE__ */ new Map();
871
+ overlayListCache;
872
+ getOverlayList() {
873
+ const overlay = this.getOverlay();
874
+ if (!overlay) {
875
+ return void 0;
876
+ }
877
+ const shape = this.getShape();
878
+ if (!isValueShape(shape.shape)) {
879
+ return void 0;
880
+ }
881
+ if (!this.overlayListCache) {
882
+ const container = this.getContainer();
883
+ const diff = overlay.get(container.id);
884
+ if (!diff || diff.type !== "list") {
885
+ return void 0;
886
+ }
887
+ const afterValues = [];
888
+ for (let i = 0; i < container.length; i++) {
889
+ afterValues.push(container.get(i));
890
+ }
891
+ this.overlayListCache = applyListDelta(
892
+ afterValues,
893
+ diff.diff
894
+ );
895
+ }
896
+ return this.overlayListCache;
897
+ }
853
898
  /** Get typed ref params for creating child refs at an index */
854
899
  getChildTypedRefParams(index, shape) {
855
900
  return {
@@ -866,17 +911,22 @@ var ListRefBaseInternals = class extends BaseRefInternals {
866
911
  },
867
912
  autoCommit: this.getAutoCommit(),
868
913
  batchedMutation: this.getBatchedMutation(),
869
- getDoc: () => this.getDoc()
914
+ getDoc: () => this.getDoc(),
915
+ overlay: this.getOverlay()
870
916
  };
871
917
  }
872
918
  /** Get item for predicate functions (returns plain value) */
873
919
  getPredicateItem(index) {
874
920
  const shape = this.getShape();
875
921
  const container = this.getContainer();
922
+ const overlayList = this.getOverlayList();
876
923
  const cachedItem = this.itemCache.get(index);
877
924
  if (cachedItem && isValueShape(shape.shape)) {
878
925
  return cachedItem;
879
926
  }
927
+ if (overlayList && isValueShape(shape.shape)) {
928
+ return overlayList[index];
929
+ }
880
930
  const containerItem = container.get(index);
881
931
  if (containerItem === void 0) {
882
932
  return void 0;
@@ -900,7 +950,8 @@ var ListRefBaseInternals = class extends BaseRefInternals {
900
950
  getMutableItem(index) {
901
951
  const shape = this.getShape();
902
952
  const container = this.getContainer();
903
- const containerItem = container.get(index);
953
+ const overlayList = this.getOverlayList();
954
+ const containerItem = overlayList ? overlayList[index] : container.get(index);
904
955
  if (containerItem === void 0) {
905
956
  return void 0;
906
957
  }
@@ -920,6 +971,11 @@ var ListRefBaseInternals = class extends BaseRefInternals {
920
971
  this.itemCache.set(index, cachedItem2);
921
972
  return cachedItem2;
922
973
  }
974
+ if (!this.getBatchedMutation()) {
975
+ return createContainerTypedRef(
976
+ this.getChildTypedRefParams(index, shape.shape)
977
+ );
978
+ }
923
979
  let cachedItem = this.itemCache.get(index);
924
980
  if (!cachedItem) {
925
981
  cachedItem = createContainerTypedRef(
@@ -1133,6 +1189,10 @@ var ListRefBase = class extends TypedRef {
1133
1189
  return this[INTERNAL_SYMBOL].getMutableItem(index);
1134
1190
  }
1135
1191
  toArray() {
1192
+ const overlayList = this[INTERNAL_SYMBOL].getOverlayList();
1193
+ if (overlayList) {
1194
+ return [...overlayList];
1195
+ }
1136
1196
  const result = [];
1137
1197
  for (let i = 0; i < this.length; i++) {
1138
1198
  result.push(this[INTERNAL_SYMBOL].getPredicateItem(i));
@@ -1141,8 +1201,9 @@ var ListRefBase = class extends TypedRef {
1141
1201
  }
1142
1202
  toJSON() {
1143
1203
  const shape = this[INTERNAL_SYMBOL].getShape();
1204
+ const overlayList = this[INTERNAL_SYMBOL].getOverlayList();
1144
1205
  const container = this[INTERNAL_SYMBOL].getContainer();
1145
- const nativeJson = container.toJSON();
1206
+ const nativeJson = overlayList ?? container.toJSON();
1146
1207
  if (isContainerShape(shape.shape) || isValueShape(shape.shape) && shape.shape.valueType === "struct") {
1147
1208
  const itemPlaceholder = deriveShapePlaceholder(shape.shape);
1148
1209
  return nativeJson.map(
@@ -1169,10 +1230,32 @@ var ListRefBase = class extends TypedRef {
1169
1230
  };
1170
1231
  }
1171
1232
  get length() {
1233
+ const overlayList = this[INTERNAL_SYMBOL].getOverlayList();
1234
+ if (overlayList) {
1235
+ return overlayList.length;
1236
+ }
1172
1237
  const container = this[INTERNAL_SYMBOL].getContainer();
1173
1238
  return container.length;
1174
1239
  }
1175
1240
  };
1241
+ function applyListDelta(input, delta) {
1242
+ const result = [];
1243
+ let index = 0;
1244
+ for (const op of delta) {
1245
+ if (op.retain !== void 0) {
1246
+ result.push(...input.slice(index, index + op.retain));
1247
+ index += op.retain;
1248
+ } else if (op.delete !== void 0) {
1249
+ index += op.delete;
1250
+ } else if (op.insert !== void 0) {
1251
+ result.push(...op.insert);
1252
+ }
1253
+ }
1254
+ if (index < input.length) {
1255
+ result.push(...input.slice(index));
1256
+ }
1257
+ return result;
1258
+ }
1176
1259
 
1177
1260
  // src/typed-refs/list-ref-internals.ts
1178
1261
  var ListRefInternals = class extends ListRefBaseInternals {
@@ -1359,6 +1442,17 @@ var RecordRefInternals = class extends BaseRefInternals {
1359
1442
  const shape = recordShape.shape;
1360
1443
  const container = this.getContainer();
1361
1444
  if (isValueShape(shape)) {
1445
+ const overlay = this.getOverlay();
1446
+ if (overlay) {
1447
+ const containerId = container.id;
1448
+ const diff = overlay.get(containerId);
1449
+ if (diff && diff.type === "map") {
1450
+ const mapDiff = diff;
1451
+ if (key in mapDiff.updated) {
1452
+ return mapDiff.updated[key];
1453
+ }
1454
+ }
1455
+ }
1362
1456
  if (!this.getBatchedMutation()) {
1363
1457
  const containerValue = container.get(key);
1364
1458
  if (containerValue !== void 0) {
@@ -1668,6 +1762,17 @@ var StructRefInternals = class extends BaseRefInternals {
1668
1762
  const actualShape = shape || structShape.shapes[key];
1669
1763
  const container = this.getContainer();
1670
1764
  if (isValueShape(actualShape)) {
1765
+ const overlay = this.getOverlay();
1766
+ if (overlay) {
1767
+ const containerId = container.id;
1768
+ const diff = overlay.get(containerId);
1769
+ if (diff && diff.type === "map") {
1770
+ const mapDiff = diff;
1771
+ if (key in mapDiff.updated) {
1772
+ return mapDiff.updated[key];
1773
+ }
1774
+ }
1775
+ }
1671
1776
  if (!this.getBatchedMutation()) {
1672
1777
  const containerValue = container.get(key);
1673
1778
  if (containerValue !== void 0) {
@@ -1948,6 +2053,14 @@ var TextRefInternals = class extends BaseRefInternals {
1948
2053
  /** Get the text as a string */
1949
2054
  getStringValue() {
1950
2055
  const container = this.getContainer();
2056
+ const overlay = this.getOverlay();
2057
+ if (overlay) {
2058
+ const diff = overlay.get(container.id);
2059
+ if (diff && diff.type === "text") {
2060
+ const containerValue2 = container.toString();
2061
+ return applyTextDelta(containerValue2, diff.diff);
2062
+ }
2063
+ }
1951
2064
  const containerValue = container.toString();
1952
2065
  if (containerValue !== "" || this.materialized) {
1953
2066
  return containerValue;
@@ -1960,11 +2073,28 @@ var TextRefInternals = class extends BaseRefInternals {
1960
2073
  }
1961
2074
  /** Get the text as a delta */
1962
2075
  toDelta() {
1963
- return this.getContainer().toDelta();
2076
+ const container = this.getContainer();
2077
+ const overlay = this.getOverlay();
2078
+ if (overlay) {
2079
+ const diff = overlay.get(container.id);
2080
+ if (diff && diff.type === "text") {
2081
+ const base = container.toDelta();
2082
+ return applyDeltaToDelta(base, diff.diff);
2083
+ }
2084
+ }
2085
+ return container.toDelta();
1964
2086
  }
1965
2087
  /** Get the length of the text */
1966
2088
  getLength() {
1967
- return this.getContainer().length;
2089
+ const container = this.getContainer();
2090
+ const overlay = this.getOverlay();
2091
+ if (overlay) {
2092
+ const diff = overlay.get(container.id);
2093
+ if (diff && diff.type === "text") {
2094
+ return applyTextDelta(container.toString(), diff.diff).length;
2095
+ }
2096
+ }
2097
+ return container.length;
1968
2098
  }
1969
2099
  /** No plain values in text */
1970
2100
  absorbPlainValues() {
@@ -1985,6 +2115,29 @@ var TextRefInternals = class extends BaseRefInternals {
1985
2115
  };
1986
2116
  }
1987
2117
  };
2118
+ function applyTextDelta(text, delta) {
2119
+ let result = "";
2120
+ let index = 0;
2121
+ for (const op of delta) {
2122
+ if (op.retain !== void 0) {
2123
+ result += text.slice(index, index + op.retain);
2124
+ index += op.retain;
2125
+ } else if (op.delete !== void 0) {
2126
+ index += op.delete;
2127
+ } else if (op.insert !== void 0) {
2128
+ result += op.insert;
2129
+ }
2130
+ }
2131
+ if (index < text.length) {
2132
+ result += text.slice(index);
2133
+ }
2134
+ return result;
2135
+ }
2136
+ function applyDeltaToDelta(base, diff) {
2137
+ const baseText = base.map((op) => op.insert !== void 0 ? op.insert : "").join("");
2138
+ const nextText = applyTextDelta(baseText, diff);
2139
+ return nextText ? [{ insert: nextText }] : [];
2140
+ }
1988
2141
 
1989
2142
  // src/typed-refs/text-ref.ts
1990
2143
  var TextRef = class extends TypedRef {
@@ -2686,7 +2839,8 @@ var DocRefInternals = class extends BaseRefInternals {
2686
2839
  getContainer: () => getter(key),
2687
2840
  autoCommit: this.getAutoCommit(),
2688
2841
  batchedMutation: this.getBatchedMutation(),
2689
- getDoc: () => this.doc
2842
+ getDoc: () => this.doc,
2843
+ overlay: this.getOverlay()
2690
2844
  };
2691
2845
  }
2692
2846
  /** Get or create a typed ref for a key */
@@ -2967,13 +3121,15 @@ var TypedDocInternal = class {
2967
3121
  shape;
2968
3122
  placeholder;
2969
3123
  doc;
3124
+ overlay;
2970
3125
  valueRef = null;
2971
3126
  // Reference to the proxy for returning from change()
2972
3127
  proxy = null;
2973
- constructor(shape, doc = new LoroDoc()) {
3128
+ constructor(shape, doc = new LoroDoc(), overlay) {
2974
3129
  this.shape = shape;
2975
3130
  this.placeholder = derivePlaceholder(shape);
2976
3131
  this.doc = doc;
3132
+ this.overlay = overlay;
2977
3133
  validatePlaceholder(this.placeholder, this.shape);
2978
3134
  }
2979
3135
  get value() {
@@ -2982,7 +3138,8 @@ var TypedDocInternal = class {
2982
3138
  shape: this.shape,
2983
3139
  placeholder: this.placeholder,
2984
3140
  doc: this.doc,
2985
- autoCommit: true
3141
+ autoCommit: true,
3142
+ overlay: this.overlay
2986
3143
  });
2987
3144
  }
2988
3145
  return this.valueRef;
@@ -3001,8 +3158,9 @@ var TypedDocInternal = class {
3001
3158
  placeholder: this.placeholder,
3002
3159
  doc: this.doc,
3003
3160
  autoCommit: false,
3004
- batchedMutation: true
3161
+ batchedMutation: true,
3005
3162
  // Enable value shape caching for find-and-mutate patterns
3163
+ overlay: this.overlay
3006
3164
  });
3007
3165
  fn(draft);
3008
3166
  draft[INTERNAL_SYMBOL].absorbPlainValues();
@@ -3029,8 +3187,12 @@ var TypedDocInternal = class {
3029
3187
  return this.doc.toJSON();
3030
3188
  }
3031
3189
  };
3032
- function createTypedDoc(shape, existingDoc) {
3033
- const internal = new TypedDocInternal(shape, existingDoc || new LoroDoc());
3190
+ function createTypedDoc(shape, options = {}) {
3191
+ const internal = new TypedDocInternal(
3192
+ shape,
3193
+ options.doc || new LoroDoc(),
3194
+ options.overlay
3195
+ );
3034
3196
  const loroNamespace = {
3035
3197
  get doc() {
3036
3198
  return internal.loroDoc;
@@ -3057,7 +3219,7 @@ function createTypedDoc(shape, existingDoc) {
3057
3219
  };
3058
3220
  const forkAtFunction = (frontiers) => {
3059
3221
  const forkedLoroDoc = internal.loroDoc.forkAt(frontiers);
3060
- return createTypedDoc(internal.docShape, forkedLoroDoc);
3222
+ return createTypedDoc(internal.docShape, { doc: forkedLoroDoc });
3061
3223
  };
3062
3224
  const proxy = new Proxy(internal.value, {
3063
3225
  get(target, prop, receiver) {
@@ -3161,13 +3323,13 @@ function fork(doc, options) {
3161
3323
  if (options?.preservePeerId) {
3162
3324
  forkedLoroDoc.setPeerId(loroDoc.peerId);
3163
3325
  }
3164
- return createTypedDoc(shape, forkedLoroDoc);
3326
+ return createTypedDoc(shape, { doc: forkedLoroDoc });
3165
3327
  }
3166
3328
  function forkAt(doc, frontiers) {
3167
3329
  const loroDoc = loro(doc).doc;
3168
3330
  const forkedLoroDoc = loroDoc.forkAt(frontiers);
3169
3331
  const shape = loro(doc).docShape;
3170
- return createTypedDoc(shape, forkedLoroDoc);
3332
+ return createTypedDoc(shape, { doc: forkedLoroDoc });
3171
3333
  }
3172
3334
  function shallowForkAt(doc, frontiers, options) {
3173
3335
  const loroDoc = loro(doc).doc;
@@ -3180,7 +3342,19 @@ function shallowForkAt(doc, frontiers, options) {
3180
3342
  if (options?.preservePeerId) {
3181
3343
  shallowLoroDoc.setPeerId(loroDoc.peerId);
3182
3344
  }
3183
- return createTypedDoc(shape, shallowLoroDoc);
3345
+ return createTypedDoc(shape, { doc: shallowLoroDoc });
3346
+ }
3347
+ function getTransition(doc, event) {
3348
+ if (event.by === "checkout") {
3349
+ throw new Error("getTransition does not support checkout events");
3350
+ }
3351
+ const loroDoc = getLoroDoc(doc);
3352
+ const shape = loro(doc).docShape;
3353
+ const overlay = createDiffOverlay(loroDoc, event);
3354
+ return {
3355
+ before: createTypedDoc(shape, { doc: loroDoc, overlay }),
3356
+ after: createTypedDoc(shape, { doc: loroDoc })
3357
+ };
3184
3358
  }
3185
3359
 
3186
3360
  // src/path-builder.ts
@@ -3913,6 +4087,7 @@ export {
3913
4087
  Shape,
3914
4088
  change,
3915
4089
  compileToJsonPath,
4090
+ createDiffOverlay,
3916
4091
  createPathBuilder,
3917
4092
  createPlaceholderProxy,
3918
4093
  createTypedDoc,
@@ -3924,6 +4099,7 @@ export {
3924
4099
  forkAt,
3925
4100
  getLoroContainer,
3926
4101
  getLoroDoc,
4102
+ getTransition,
3927
4103
  hasWildcard,
3928
4104
  loro,
3929
4105
  mergeValue,