@symbo.ls/sdk 2.32.1 → 2.32.4

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.
@@ -26,8 +26,7 @@ var import_RootStateManager = require("../state/RootStateManager.js");
26
26
  var import_rootEventBus = require("../state/rootEventBus.js");
27
27
  var import_validation = require("../utils/validation.js");
28
28
  var import_utils = require("@domql/utils");
29
- var import_jsonDiff = require("../utils/jsonDiff.js");
30
- var import_ordering = require("../utils/ordering.js");
29
+ var import_changePreprocessor = require("../utils/changePreprocessor.js");
31
30
  class CollabService extends import_BaseService.BaseService {
32
31
  constructor(config) {
33
32
  super(config);
@@ -164,8 +163,8 @@ class CollabService extends import_BaseService.BaseService {
164
163
  console.log(
165
164
  `[CollabService] Flushing ${this._pendingOps.length} offline operation batch(es)`
166
165
  );
167
- this._pendingOps.forEach(({ changes, orders }) => {
168
- this.socket.emit("ops", { changes, orders, ts: Date.now() });
166
+ this._pendingOps.forEach(({ changes, granularChanges, orders }) => {
167
+ this.socket.emit("ops", { changes, granularChanges, orders, ts: Date.now() });
169
168
  });
170
169
  this._pendingOps.length = 0;
171
170
  }
@@ -207,94 +206,24 @@ class CollabService extends import_BaseService.BaseService {
207
206
  }
208
207
  /* ---------- data helpers ---------- */
209
208
  updateData(tuples, options = {}) {
210
- var _a, _b;
209
+ var _a, _b, _c;
211
210
  this._ensureStateManager();
212
211
  const { isUndo = false, isRedo = false } = options;
213
212
  if (!isUndo && !isRedo && !this._isUndoRedo) {
214
213
  this._trackForUndo(tuples, options);
215
214
  }
216
- const processedTuples = (() => {
217
- var _a2;
218
- try {
219
- const root = (_a2 = this._stateManager) == null ? void 0 : _a2.root;
220
- const isPlainObject = (o) => o && typeof o === "object" && !Array.isArray(o);
221
- const getByPath = (state2, path) => {
222
- if (!state2 || typeof state2.getByPath !== "function") {
223
- return null;
224
- }
225
- try {
226
- return state2.getByPath(path);
227
- } catch {
228
- return null;
229
- }
230
- };
231
- const expandTuple = (t) => {
232
- const [action, path, value] = t || [];
233
- const isSchemaPath = Array.isArray(path) && path[0] === "schema";
234
- if (action === "delete" || isSchemaPath) {
235
- return [t];
236
- }
237
- const canConsiderExpansion = action === "update" && Array.isArray(path) && (path.length === 1 || path.length === 2) && isPlainObject(value);
238
- if (!canConsiderExpansion) {
239
- return [t];
240
- }
241
- const prev = getByPath(root, path) || {};
242
- const next = value || {};
243
- if (!isPlainObject(prev) || !isPlainObject(next)) {
244
- return [t];
245
- }
246
- const ops = (0, import_jsonDiff.diffJson)(prev, next, []);
247
- if (!ops.length) {
248
- return [];
249
- }
250
- const arr = [];
251
- for (let j = 0; j < ops.length; j++) {
252
- const op = ops[j];
253
- const fullPath = [...path, ...op.path];
254
- const last = fullPath[fullPath.length - 1];
255
- if (op.action === "set") {
256
- arr.push(["update", fullPath, op.value]);
257
- } else if (op.action === "del") {
258
- if (last !== "__order") {
259
- arr.push(["delete", fullPath]);
260
- }
261
- }
262
- }
263
- return arr;
264
- };
265
- const minimizeTuples = (inputTuples) => {
266
- const out = [];
267
- for (let i = 0; i < inputTuples.length; i++) {
268
- const expanded = expandTuple(inputTuples[i]);
269
- for (let k = 0; k < expanded.length; k++) {
270
- const tuple = expanded[k];
271
- const isDelete = Array.isArray(tuple) && tuple[0] === "delete";
272
- const isOrderKey = isDelete && Array.isArray(tuple[1]) && tuple[1][tuple[1].length - 1] === "__order";
273
- if (!isOrderKey) {
274
- out.push(tuple);
275
- }
276
- }
277
- }
278
- console.log(`Minimized tuples`, out);
279
- return out;
280
- };
281
- console.log(`Processing tuples`, tuples);
282
- return minimizeTuples(tuples);
283
- } catch (err) {
284
- console.warn(
285
- "[CollabService] Minimal diff expansion failed \u2013 using original tuples",
286
- err
287
- );
288
- return tuples;
289
- }
290
- })();
215
+ const root = (_a = this._stateManager) == null ? void 0 : _a.root;
216
+ const { granularChanges: processedTuples, orders } = (0, import_changePreprocessor.preprocessChanges)(
217
+ root,
218
+ tuples,
219
+ options
220
+ );
291
221
  if (options.append && options.append.length) {
292
222
  processedTuples.push(...options.append);
293
223
  }
294
224
  this._stateManager.applyChanges(tuples, { ...options });
295
- const state = (_a = this._stateManager) == null ? void 0 : _a.root;
225
+ const state = (_b = this._stateManager) == null ? void 0 : _b.root;
296
226
  const el = state == null ? void 0 : state.__element;
297
- const orders = (0, import_ordering.computeOrdersForTuples)(state, processedTuples);
298
227
  const stringifiedGranularTuples = (el == null ? void 0 : el.call) ? el.call(
299
228
  "deepStringifyFunctions",
300
229
  processedTuples,
@@ -307,16 +236,18 @@ class CollabService extends import_BaseService.BaseService {
307
236
  "deepStringifyFunctions",
308
237
  tuples,
309
238
  Array.isArray(tuples) ? [] : {}
310
- ) : (0, import_utils.deepStringifyFunctions)(
311
- tuples,
312
- Array.isArray(tuples) ? [] : {}
313
- );
239
+ ) : (0, import_utils.deepStringifyFunctions)(tuples, Array.isArray(tuples) ? [] : {});
314
240
  if (!this.isConnected()) {
315
241
  console.warn("[CollabService] Not connected, queuing real-time update");
316
- this._pendingOps.push({ changes: stringifiedTuples, granularChanges: stringifiedGranularTuples, orders, options });
242
+ this._pendingOps.push({
243
+ changes: stringifiedTuples,
244
+ granularChanges: stringifiedGranularTuples,
245
+ orders,
246
+ options
247
+ });
317
248
  return;
318
249
  }
319
- if ((_b = this.socket) == null ? void 0 : _b.connected) {
250
+ if ((_c = this.socket) == null ? void 0 : _c.connected) {
320
251
  console.log("[CollabService] Sending operations to the backend", {
321
252
  changes: stringifiedTuples,
322
253
  granularChanges: stringifiedGranularTuples,
@@ -22,6 +22,8 @@ __export(ProjectService_exports, {
22
22
  module.exports = __toCommonJS(ProjectService_exports);
23
23
  var import_BaseService = require("./BaseService.js");
24
24
  var import_ordering = require("../utils/ordering.js");
25
+ var import_changePreprocessor = require("../utils/changePreprocessor.js");
26
+ var import_utils = require("@domql/utils");
25
27
  class ProjectService extends import_BaseService.BaseService {
26
28
  // ==================== PROJECT METHODS ====================
27
29
  async createProject(projectData) {
@@ -554,12 +556,15 @@ class ProjectService extends import_BaseService.BaseService {
554
556
  }
555
557
  const { message, branch = "main", type = "patch" } = options;
556
558
  const state = this._context && this._context.state;
557
- const derivedOrders = options.orders || (state ? (0, import_ordering.computeOrdersForTuples)(state, changes) : []);
559
+ const { granularChanges, orders: preprocessorOrders } = (0, import_changePreprocessor.preprocessChanges)(state, changes, options);
560
+ const derivedOrders = options.orders || (preprocessorOrders && preprocessorOrders.length ? preprocessorOrders : state ? (0, import_ordering.computeOrdersForTuples)(state, granularChanges) : []);
561
+ const stringify = (val) => (0, import_utils.deepStringifyFunctions)(val, Array.isArray(val) ? [] : {});
558
562
  try {
559
563
  const response = await this._request(`/projects/${projectId}/changes`, {
560
564
  method: "POST",
561
565
  body: JSON.stringify({
562
- changes,
566
+ changes: stringify(changes),
567
+ granularChanges: stringify(granularChanges),
563
568
  message,
564
569
  branch,
565
570
  type,
@@ -0,0 +1,134 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var changePreprocessor_exports = {};
19
+ __export(changePreprocessor_exports, {
20
+ preprocessChanges: () => preprocessChanges
21
+ });
22
+ module.exports = __toCommonJS(changePreprocessor_exports);
23
+ var import_jsonDiff = require("./jsonDiff.js");
24
+ var import_ordering = require("./ordering.js");
25
+ function isPlainObject(val) {
26
+ return val && typeof val === "object" && !Array.isArray(val);
27
+ }
28
+ function getByPathSafe(root, path) {
29
+ if (!root || typeof root.getByPath !== "function") {
30
+ return null;
31
+ }
32
+ try {
33
+ return root.getByPath(path);
34
+ } catch {
35
+ return null;
36
+ }
37
+ }
38
+ function preprocessChanges(root, tuples = [], options = {}) {
39
+ const expandTuple = (t) => {
40
+ const [action, path, value] = t || [];
41
+ const isSchemaPath = Array.isArray(path) && path[0] === "schema";
42
+ if (action === "delete") {
43
+ return [t];
44
+ }
45
+ const canConsiderExpansion = action === "update" && Array.isArray(path) && (path.length === 1 || path.length === 2 || isSchemaPath && path.length === 3) && isPlainObject(value);
46
+ if (!canConsiderExpansion) {
47
+ return [t];
48
+ }
49
+ const prev = getByPathSafe(root, path) || {};
50
+ const next = value || {};
51
+ if (!isPlainObject(prev) || !isPlainObject(next)) {
52
+ return [t];
53
+ }
54
+ const ops = (0, import_jsonDiff.diffJson)(prev, next, []);
55
+ if (!ops.length) {
56
+ return [t];
57
+ }
58
+ const out = [];
59
+ for (let i = 0; i < ops.length; i++) {
60
+ const op = ops[i];
61
+ const fullPath = [...path, ...op.path];
62
+ const last = fullPath[fullPath.length - 1];
63
+ if (op.action === "set") {
64
+ out.push(["update", fullPath, op.value]);
65
+ } else if (op.action === "del") {
66
+ if (last !== "__order") {
67
+ out.push(["delete", fullPath]);
68
+ }
69
+ }
70
+ }
71
+ return out;
72
+ };
73
+ const minimizeTuples = (input) => {
74
+ const out = [];
75
+ const seen2 = /* @__PURE__ */ new Set();
76
+ for (let i = 0; i < input.length; i++) {
77
+ const expanded = expandTuple(input[i]);
78
+ for (let k = 0; k < expanded.length; k++) {
79
+ const tuple = expanded[k];
80
+ const isDelete = Array.isArray(tuple) && tuple[0] === "delete";
81
+ const isOrderKey = isDelete && Array.isArray(tuple[1]) && tuple[1][tuple[1].length - 1] === "__order";
82
+ if (!isOrderKey) {
83
+ const key = JSON.stringify(tuple);
84
+ if (!seen2.has(key)) {
85
+ seen2.add(key);
86
+ out.push(tuple);
87
+ }
88
+ }
89
+ }
90
+ }
91
+ return out;
92
+ };
93
+ const granularChanges = (() => {
94
+ try {
95
+ const res = minimizeTuples(tuples);
96
+ if (options.append && options.append.length) {
97
+ res.push(...options.append);
98
+ }
99
+ return res;
100
+ } catch {
101
+ return Array.isArray(tuples) ? tuples.slice() : [];
102
+ }
103
+ })();
104
+ const baseOrders = (0, import_ordering.computeOrdersForTuples)(root, granularChanges);
105
+ const preferOrdersMap = /* @__PURE__ */ new Map();
106
+ for (let i = 0; i < tuples.length; i++) {
107
+ const t = tuples[i];
108
+ if (!Array.isArray(t) || t.length < 3) {
109
+ continue;
110
+ }
111
+ const [action, path, value] = t;
112
+ if (action !== "update" || !Array.isArray(path) || path.length !== 1 && path.length !== 2 || !isPlainObject(value)) {
113
+ continue;
114
+ }
115
+ const keys = Object.keys(value).filter((k) => k !== "__order");
116
+ const key = JSON.stringify(path);
117
+ preferOrdersMap.set(key, { path, keys });
118
+ }
119
+ const mergedOrders = [];
120
+ const seen = /* @__PURE__ */ new Set();
121
+ preferOrdersMap.forEach((v, k) => {
122
+ seen.add(k);
123
+ mergedOrders.push(v);
124
+ });
125
+ for (let i = 0; i < baseOrders.length; i++) {
126
+ const v = baseOrders[i];
127
+ const k = JSON.stringify(v.path);
128
+ if (!seen.has(k)) {
129
+ seen.add(k);
130
+ mergedOrders.push(v);
131
+ }
132
+ }
133
+ return { granularChanges, orders: mergedOrders };
134
+ }
@@ -36,12 +36,54 @@ function isPlainObject(o) {
36
36
  return o && typeof o === "object" && !Array.isArray(o);
37
37
  }
38
38
  function deepEqual(a, b) {
39
- try {
40
- return JSON.stringify(a) === JSON.stringify(b);
41
- } catch (err) {
42
- console.warn("deepEqual error", err);
39
+ if (Object.is(a, b)) {
40
+ return true;
41
+ }
42
+ if (typeof a === "function" && typeof b === "function") {
43
+ try {
44
+ return a.toString() === b.toString();
45
+ } catch {
46
+ return false;
47
+ }
48
+ }
49
+ if (typeof a === "function" || typeof b === "function") {
43
50
  return false;
44
51
  }
52
+ if (a instanceof Date && b instanceof Date) {
53
+ return a.getTime() === b.getTime();
54
+ }
55
+ if (a instanceof RegExp && b instanceof RegExp) {
56
+ return String(a) === String(b);
57
+ }
58
+ if (Array.isArray(a) && Array.isArray(b)) {
59
+ if (a.length !== b.length) {
60
+ return false;
61
+ }
62
+ for (let i = 0; i < a.length; i++) {
63
+ if (!deepEqual(a[i], b[i])) {
64
+ return false;
65
+ }
66
+ }
67
+ return true;
68
+ }
69
+ if (a && b && typeof a === "object" && typeof b === "object") {
70
+ const aKeys = Object.keys(a);
71
+ const bKeys = Object.keys(b);
72
+ if (aKeys.length !== bKeys.length) {
73
+ return false;
74
+ }
75
+ for (let i = 0; i < aKeys.length; i++) {
76
+ const key = aKeys[i];
77
+ if (!Object.hasOwn(b, key)) {
78
+ return false;
79
+ }
80
+ if (!deepEqual(a[key], b[key])) {
81
+ return false;
82
+ }
83
+ }
84
+ return true;
85
+ }
86
+ return false;
45
87
  }
46
88
  function getRootMap(ydoc) {
47
89
  return ydoc.getMap("root");
@@ -47,14 +47,12 @@ function getParentPathsFromTuples(tuples = []) {
47
47
  "attr",
48
48
  "state",
49
49
  "scope",
50
- "props",
51
50
  "define",
52
51
  "on",
53
52
  "extend",
54
53
  "extends",
55
54
  "childExtend",
56
55
  "childExtends",
57
- "childProps",
58
56
  "children",
59
57
  "component",
60
58
  "context",