@symbo.ls/sync 2.29.56 → 2.29.58
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/cjs/index.js +64 -29
- package/dist/esm/index.js +64 -28
- package/index.js +106 -61
- package/package.json +8 -8
package/dist/cjs/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var __defProp = Object.defineProperty;
|
|
3
2
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
3
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -31,23 +30,33 @@ var import_socket = require("socket.io-client");
|
|
|
31
30
|
var import_utils = require("@domql/utils");
|
|
32
31
|
var import_SyncNotifications = require("./SyncNotifications");
|
|
33
32
|
var import_Inspect = require("./Inspect");
|
|
34
|
-
const
|
|
33
|
+
const isLocal = false;
|
|
35
34
|
const deletePath = (obj, path) => {
|
|
36
|
-
if (!obj || !Array.isArray(path))
|
|
35
|
+
if (!obj || !Array.isArray(path)) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
37
38
|
path.reduce((acc, v, i, arr) => {
|
|
38
39
|
if (acc && v in acc) {
|
|
39
|
-
if (i !== arr.length - 1)
|
|
40
|
+
if (i !== arr.length - 1) {
|
|
41
|
+
return acc[v];
|
|
42
|
+
}
|
|
40
43
|
delete acc[v];
|
|
41
44
|
}
|
|
42
45
|
return void 0;
|
|
43
46
|
}, obj);
|
|
44
47
|
};
|
|
45
48
|
const setPath = (obj, path, value, createNestedObjects = false) => {
|
|
46
|
-
if (!obj || !Array.isArray(path))
|
|
49
|
+
if (!obj || !Array.isArray(path)) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
47
52
|
path.reduce((acc, v, i, arr) => {
|
|
48
|
-
if (!acc)
|
|
53
|
+
if (!acc) {
|
|
54
|
+
return void 0;
|
|
55
|
+
}
|
|
49
56
|
if (i !== arr.length - 1) {
|
|
50
|
-
if (!acc[v] && createNestedObjects)
|
|
57
|
+
if (!acc[v] && createNestedObjects) {
|
|
58
|
+
acc[v] = {};
|
|
59
|
+
}
|
|
51
60
|
return acc[v];
|
|
52
61
|
}
|
|
53
62
|
acc[v] = value;
|
|
@@ -56,9 +65,13 @@ const setPath = (obj, path, value, createNestedObjects = false) => {
|
|
|
56
65
|
};
|
|
57
66
|
const applyOpsToCtx = (ctx, changes) => {
|
|
58
67
|
const topLevelChanged = /* @__PURE__ */ new Set();
|
|
59
|
-
if (!Array.isArray(changes))
|
|
68
|
+
if (!Array.isArray(changes)) {
|
|
69
|
+
return topLevelChanged;
|
|
70
|
+
}
|
|
60
71
|
for (const [action, path, change] of changes) {
|
|
61
|
-
if (!Array.isArray(path) || !path.length)
|
|
72
|
+
if (!Array.isArray(path) || !path.length) {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
62
75
|
topLevelChanged.add(path[0]);
|
|
63
76
|
switch (action) {
|
|
64
77
|
case "delete":
|
|
@@ -76,26 +89,33 @@ const applyOpsToCtx = (ctx, changes) => {
|
|
|
76
89
|
};
|
|
77
90
|
const fetchServiceToken = async () => {
|
|
78
91
|
try {
|
|
79
|
-
const urlBase =
|
|
80
|
-
const res = await import_utils.window.fetch(`${urlBase}/service-token`, {
|
|
92
|
+
const urlBase = isLocal ? "http://localhost:8080" : "https://api.symbols.app";
|
|
93
|
+
const res = await import_utils.window.fetch(`${urlBase}/service-token`, {
|
|
94
|
+
method: "GET"
|
|
95
|
+
});
|
|
81
96
|
let txt;
|
|
82
97
|
try {
|
|
83
98
|
const json = await res.clone().json();
|
|
84
|
-
if (json && typeof json.token === "string")
|
|
99
|
+
if (json && typeof json.token === "string") {
|
|
100
|
+
return json.token.trim();
|
|
101
|
+
}
|
|
85
102
|
txt = await res.text();
|
|
86
103
|
} catch {
|
|
87
104
|
txt = await res.text();
|
|
88
105
|
}
|
|
89
|
-
return (txt || "").replace(/\s+/
|
|
106
|
+
return (txt || "").replace(/\s+/gu, "") || void 0;
|
|
90
107
|
} catch (e) {
|
|
91
108
|
console.error("[sync] Failed to fetch service-token", e);
|
|
92
|
-
return void 0;
|
|
93
109
|
}
|
|
94
110
|
};
|
|
95
111
|
const onSnapshot = (el, s, ctx) => (payload = {}) => {
|
|
96
112
|
var _a;
|
|
97
|
-
|
|
98
|
-
|
|
113
|
+
let { data } = payload;
|
|
114
|
+
const { schema } = payload;
|
|
115
|
+
if (!data) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
data = el.call("deepDestringify", data, Array.isArray(data) ? [] : {});
|
|
99
119
|
Object.entries(data).forEach(([key, val]) => {
|
|
100
120
|
if (ctx[key] && typeof ctx[key] === "object") {
|
|
101
121
|
(0, import_utils.overwriteShallow)(ctx[key], val);
|
|
@@ -103,28 +123,37 @@ const onSnapshot = (el, s, ctx) => (payload = {}) => {
|
|
|
103
123
|
ctx[key] = val;
|
|
104
124
|
}
|
|
105
125
|
});
|
|
106
|
-
if (schema)
|
|
126
|
+
if (schema) {
|
|
127
|
+
ctx.schema = schema;
|
|
128
|
+
}
|
|
107
129
|
const { pathname, search, hash } = ctx.window.location;
|
|
108
130
|
(((_a = ctx.utils) == null ? void 0 : _a.router) || import_router.router)(pathname + search + hash, el, {});
|
|
109
131
|
};
|
|
110
132
|
const onOps = (el, s, ctx) => (payload = {}) => {
|
|
111
|
-
var _a
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
133
|
+
var _a;
|
|
134
|
+
let { changes } = payload;
|
|
135
|
+
if (!changes || !Array.isArray(changes) || !changes.length) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
changes = el.call(
|
|
139
|
+
"deepDestringify",
|
|
140
|
+
changes,
|
|
141
|
+
Array.isArray(changes) ? [] : {}
|
|
142
|
+
);
|
|
115
143
|
const changed = applyOpsToCtx(ctx, changes);
|
|
116
144
|
if (changed.has("state")) {
|
|
117
145
|
const route = (_a = ctx.state) == null ? void 0 : _a.route;
|
|
118
146
|
if (route) {
|
|
119
|
-
;
|
|
120
|
-
(((_b = ctx.utils) == null ? void 0 : _b.router) || import_router.router)(route.replace("/state", "") || "/", el, {});
|
|
147
|
+
el.call("router", route.replace("/state", "") || "/");
|
|
121
148
|
} else {
|
|
122
149
|
s.update(ctx.state);
|
|
123
150
|
}
|
|
124
151
|
}
|
|
125
|
-
if (["pages", "components", "snippets", "functions"].some(
|
|
152
|
+
if (["pages", "components", "snippets", "functions"].some(
|
|
153
|
+
(k) => changed.has(k)
|
|
154
|
+
)) {
|
|
126
155
|
const { pathname, search, hash } = ctx.window.location;
|
|
127
|
-
(
|
|
156
|
+
el.call("router", pathname + search + hash);
|
|
128
157
|
}
|
|
129
158
|
if (changed.has("designSystem")) {
|
|
130
159
|
(0, import_init.init)(ctx.designSystem);
|
|
@@ -138,10 +167,12 @@ const connectToSocket = async (el, s, ctx) => {
|
|
|
138
167
|
}
|
|
139
168
|
const projectKey = ctx.key;
|
|
140
169
|
if (!projectKey) {
|
|
141
|
-
console.warn(
|
|
170
|
+
console.warn(
|
|
171
|
+
"[sync] ctx.key missing \u2013 cannot establish collaborative connection"
|
|
172
|
+
);
|
|
142
173
|
return null;
|
|
143
174
|
}
|
|
144
|
-
const socketBaseUrl =
|
|
175
|
+
const socketBaseUrl = isLocal ? "http://localhost:8080" : "https://api.symbols.app";
|
|
145
176
|
const socket = (0, import_socket.io)(socketBaseUrl, {
|
|
146
177
|
path: "/collab-socket",
|
|
147
178
|
transports: ["websocket"],
|
|
@@ -157,7 +188,9 @@ const connectToSocket = async (el, s, ctx) => {
|
|
|
157
188
|
});
|
|
158
189
|
socket.on("connect", () => {
|
|
159
190
|
var _a;
|
|
160
|
-
if ((_a = ctx.editor) == null ? void 0 : _a.verbose)
|
|
191
|
+
if ((_a = ctx.editor) == null ? void 0 : _a.verbose) {
|
|
192
|
+
console.info("[sync] Connected to collab socket");
|
|
193
|
+
}
|
|
161
194
|
});
|
|
162
195
|
socket.on("snapshot", onSnapshot(el, s, ctx));
|
|
163
196
|
socket.on("ops", onOps(el, s, ctx));
|
|
@@ -169,7 +202,9 @@ const connectToSocket = async (el, s, ctx) => {
|
|
|
169
202
|
});
|
|
170
203
|
socket.on("disconnect", (reason) => {
|
|
171
204
|
var _a;
|
|
172
|
-
if ((_a = ctx.editor) == null ? void 0 : _a.verbose)
|
|
205
|
+
if ((_a = ctx.editor) == null ? void 0 : _a.verbose) {
|
|
206
|
+
console.info("[sync] Disconnected from collab socket", reason);
|
|
207
|
+
}
|
|
173
208
|
});
|
|
174
209
|
return socket;
|
|
175
210
|
};
|
package/dist/esm/index.js
CHANGED
|
@@ -4,23 +4,33 @@ import { io } from "socket.io-client";
|
|
|
4
4
|
import { window, overwriteShallow } from "@domql/utils";
|
|
5
5
|
import { connectedToSymbols, Notifications } from "./SyncNotifications";
|
|
6
6
|
import { Inspect } from "./Inspect";
|
|
7
|
-
const
|
|
7
|
+
const isLocal = false;
|
|
8
8
|
const deletePath = (obj, path) => {
|
|
9
|
-
if (!obj || !Array.isArray(path))
|
|
9
|
+
if (!obj || !Array.isArray(path)) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
10
12
|
path.reduce((acc, v, i, arr) => {
|
|
11
13
|
if (acc && v in acc) {
|
|
12
|
-
if (i !== arr.length - 1)
|
|
14
|
+
if (i !== arr.length - 1) {
|
|
15
|
+
return acc[v];
|
|
16
|
+
}
|
|
13
17
|
delete acc[v];
|
|
14
18
|
}
|
|
15
19
|
return void 0;
|
|
16
20
|
}, obj);
|
|
17
21
|
};
|
|
18
22
|
const setPath = (obj, path, value, createNestedObjects = false) => {
|
|
19
|
-
if (!obj || !Array.isArray(path))
|
|
23
|
+
if (!obj || !Array.isArray(path)) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
20
26
|
path.reduce((acc, v, i, arr) => {
|
|
21
|
-
if (!acc)
|
|
27
|
+
if (!acc) {
|
|
28
|
+
return void 0;
|
|
29
|
+
}
|
|
22
30
|
if (i !== arr.length - 1) {
|
|
23
|
-
if (!acc[v] && createNestedObjects)
|
|
31
|
+
if (!acc[v] && createNestedObjects) {
|
|
32
|
+
acc[v] = {};
|
|
33
|
+
}
|
|
24
34
|
return acc[v];
|
|
25
35
|
}
|
|
26
36
|
acc[v] = value;
|
|
@@ -29,9 +39,13 @@ const setPath = (obj, path, value, createNestedObjects = false) => {
|
|
|
29
39
|
};
|
|
30
40
|
const applyOpsToCtx = (ctx, changes) => {
|
|
31
41
|
const topLevelChanged = /* @__PURE__ */ new Set();
|
|
32
|
-
if (!Array.isArray(changes))
|
|
42
|
+
if (!Array.isArray(changes)) {
|
|
43
|
+
return topLevelChanged;
|
|
44
|
+
}
|
|
33
45
|
for (const [action, path, change] of changes) {
|
|
34
|
-
if (!Array.isArray(path) || !path.length)
|
|
46
|
+
if (!Array.isArray(path) || !path.length) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
35
49
|
topLevelChanged.add(path[0]);
|
|
36
50
|
switch (action) {
|
|
37
51
|
case "delete":
|
|
@@ -49,26 +63,33 @@ const applyOpsToCtx = (ctx, changes) => {
|
|
|
49
63
|
};
|
|
50
64
|
const fetchServiceToken = async () => {
|
|
51
65
|
try {
|
|
52
|
-
const urlBase =
|
|
53
|
-
const res = await window.fetch(`${urlBase}/service-token`, {
|
|
66
|
+
const urlBase = isLocal ? "http://localhost:8080" : "https://api.symbols.app";
|
|
67
|
+
const res = await window.fetch(`${urlBase}/service-token`, {
|
|
68
|
+
method: "GET"
|
|
69
|
+
});
|
|
54
70
|
let txt;
|
|
55
71
|
try {
|
|
56
72
|
const json = await res.clone().json();
|
|
57
|
-
if (json && typeof json.token === "string")
|
|
73
|
+
if (json && typeof json.token === "string") {
|
|
74
|
+
return json.token.trim();
|
|
75
|
+
}
|
|
58
76
|
txt = await res.text();
|
|
59
77
|
} catch (e) {
|
|
60
78
|
txt = await res.text();
|
|
61
79
|
}
|
|
62
|
-
return (txt || "").replace(/\s+/
|
|
80
|
+
return (txt || "").replace(/\s+/gu, "") || void 0;
|
|
63
81
|
} catch (e) {
|
|
64
82
|
console.error("[sync] Failed to fetch service-token", e);
|
|
65
|
-
return void 0;
|
|
66
83
|
}
|
|
67
84
|
};
|
|
68
85
|
const onSnapshot = (el, s, ctx) => (payload = {}) => {
|
|
69
86
|
var _a;
|
|
70
|
-
|
|
71
|
-
|
|
87
|
+
let { data } = payload;
|
|
88
|
+
const { schema } = payload;
|
|
89
|
+
if (!data) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
data = el.call("deepDestringify", data, Array.isArray(data) ? [] : {});
|
|
72
93
|
Object.entries(data).forEach(([key, val]) => {
|
|
73
94
|
if (ctx[key] && typeof ctx[key] === "object") {
|
|
74
95
|
overwriteShallow(ctx[key], val);
|
|
@@ -76,28 +97,37 @@ const onSnapshot = (el, s, ctx) => (payload = {}) => {
|
|
|
76
97
|
ctx[key] = val;
|
|
77
98
|
}
|
|
78
99
|
});
|
|
79
|
-
if (schema)
|
|
100
|
+
if (schema) {
|
|
101
|
+
ctx.schema = schema;
|
|
102
|
+
}
|
|
80
103
|
const { pathname, search, hash } = ctx.window.location;
|
|
81
104
|
(((_a = ctx.utils) == null ? void 0 : _a.router) || router)(pathname + search + hash, el, {});
|
|
82
105
|
};
|
|
83
106
|
const onOps = (el, s, ctx) => (payload = {}) => {
|
|
84
|
-
var _a
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
107
|
+
var _a;
|
|
108
|
+
let { changes } = payload;
|
|
109
|
+
if (!changes || !Array.isArray(changes) || !changes.length) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
changes = el.call(
|
|
113
|
+
"deepDestringify",
|
|
114
|
+
changes,
|
|
115
|
+
Array.isArray(changes) ? [] : {}
|
|
116
|
+
);
|
|
88
117
|
const changed = applyOpsToCtx(ctx, changes);
|
|
89
118
|
if (changed.has("state")) {
|
|
90
119
|
const route = (_a = ctx.state) == null ? void 0 : _a.route;
|
|
91
120
|
if (route) {
|
|
92
|
-
;
|
|
93
|
-
(((_b = ctx.utils) == null ? void 0 : _b.router) || router)(route.replace("/state", "") || "/", el, {});
|
|
121
|
+
el.call("router", route.replace("/state", "") || "/");
|
|
94
122
|
} else {
|
|
95
123
|
s.update(ctx.state);
|
|
96
124
|
}
|
|
97
125
|
}
|
|
98
|
-
if (["pages", "components", "snippets", "functions"].some(
|
|
126
|
+
if (["pages", "components", "snippets", "functions"].some(
|
|
127
|
+
(k) => changed.has(k)
|
|
128
|
+
)) {
|
|
99
129
|
const { pathname, search, hash } = ctx.window.location;
|
|
100
|
-
(
|
|
130
|
+
el.call("router", pathname + search + hash);
|
|
101
131
|
}
|
|
102
132
|
if (changed.has("designSystem")) {
|
|
103
133
|
init(ctx.designSystem);
|
|
@@ -111,10 +141,12 @@ const connectToSocket = async (el, s, ctx) => {
|
|
|
111
141
|
}
|
|
112
142
|
const projectKey = ctx.key;
|
|
113
143
|
if (!projectKey) {
|
|
114
|
-
console.warn(
|
|
144
|
+
console.warn(
|
|
145
|
+
"[sync] ctx.key missing \u2013 cannot establish collaborative connection"
|
|
146
|
+
);
|
|
115
147
|
return null;
|
|
116
148
|
}
|
|
117
|
-
const socketBaseUrl =
|
|
149
|
+
const socketBaseUrl = isLocal ? "http://localhost:8080" : "https://api.symbols.app";
|
|
118
150
|
const socket = io(socketBaseUrl, {
|
|
119
151
|
path: "/collab-socket",
|
|
120
152
|
transports: ["websocket"],
|
|
@@ -130,7 +162,9 @@ const connectToSocket = async (el, s, ctx) => {
|
|
|
130
162
|
});
|
|
131
163
|
socket.on("connect", () => {
|
|
132
164
|
var _a;
|
|
133
|
-
if ((_a = ctx.editor) == null ? void 0 : _a.verbose)
|
|
165
|
+
if ((_a = ctx.editor) == null ? void 0 : _a.verbose) {
|
|
166
|
+
console.info("[sync] Connected to collab socket");
|
|
167
|
+
}
|
|
134
168
|
});
|
|
135
169
|
socket.on("snapshot", onSnapshot(el, s, ctx));
|
|
136
170
|
socket.on("ops", onOps(el, s, ctx));
|
|
@@ -142,7 +176,9 @@ const connectToSocket = async (el, s, ctx) => {
|
|
|
142
176
|
});
|
|
143
177
|
socket.on("disconnect", (reason) => {
|
|
144
178
|
var _a;
|
|
145
|
-
if ((_a = ctx.editor) == null ? void 0 : _a.verbose)
|
|
179
|
+
if ((_a = ctx.editor) == null ? void 0 : _a.verbose) {
|
|
180
|
+
console.info("[sync] Disconnected from collab socket", reason);
|
|
181
|
+
}
|
|
146
182
|
});
|
|
147
183
|
return socket;
|
|
148
184
|
};
|
package/index.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
1
|
import { router } from '@domql/router'
|
|
4
2
|
import { init } from '@symbo.ls/init'
|
|
5
3
|
import { io } from 'socket.io-client'
|
|
@@ -8,41 +6,54 @@ import { connectedToSymbols, Notifications } from './SyncNotifications'
|
|
|
8
6
|
import { Inspect } from './Inspect'
|
|
9
7
|
export { Inspect, Notifications }
|
|
10
8
|
|
|
11
|
-
const
|
|
12
|
-
window && window.location && window.location.host.includes('local')
|
|
9
|
+
const isLocal = process.env.NODE_ENV === 'local'
|
|
13
10
|
|
|
14
11
|
// ---------------------------------------------
|
|
15
12
|
// Utility helpers to apply ops
|
|
16
13
|
|
|
17
14
|
const deletePath = (obj, path) => {
|
|
18
|
-
if (!obj || !Array.isArray(path))
|
|
15
|
+
if (!obj || !Array.isArray(path)) {
|
|
16
|
+
return
|
|
17
|
+
}
|
|
19
18
|
path.reduce((acc, v, i, arr) => {
|
|
20
19
|
if (acc && v in acc) {
|
|
21
|
-
if (i !== arr.length - 1)
|
|
20
|
+
if (i !== arr.length - 1) {
|
|
21
|
+
return acc[v]
|
|
22
|
+
}
|
|
22
23
|
delete acc[v]
|
|
23
24
|
}
|
|
24
|
-
return
|
|
25
|
+
return void 0
|
|
25
26
|
}, obj)
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
const setPath = (obj, path, value, createNestedObjects = false) => {
|
|
29
|
-
if (!obj || !Array.isArray(path))
|
|
30
|
+
if (!obj || !Array.isArray(path)) {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
30
33
|
path.reduce((acc, v, i, arr) => {
|
|
31
|
-
if (!acc)
|
|
34
|
+
if (!acc) {
|
|
35
|
+
return void 0
|
|
36
|
+
}
|
|
32
37
|
if (i !== arr.length - 1) {
|
|
33
|
-
if (!acc[v] && createNestedObjects)
|
|
38
|
+
if (!acc[v] && createNestedObjects) {
|
|
39
|
+
acc[v] = {}
|
|
40
|
+
}
|
|
34
41
|
return acc[v]
|
|
35
42
|
}
|
|
36
43
|
acc[v] = value
|
|
37
|
-
return
|
|
44
|
+
return void 0
|
|
38
45
|
}, obj)
|
|
39
46
|
}
|
|
40
47
|
|
|
41
48
|
const applyOpsToCtx = (ctx, changes) => {
|
|
42
49
|
const topLevelChanged = new Set()
|
|
43
|
-
if (!Array.isArray(changes))
|
|
50
|
+
if (!Array.isArray(changes)) {
|
|
51
|
+
return topLevelChanged
|
|
52
|
+
}
|
|
44
53
|
for (const [action, path, change] of changes) {
|
|
45
|
-
if (!Array.isArray(path) || !path.length)
|
|
54
|
+
if (!Array.isArray(path) || !path.length) {
|
|
55
|
+
continue
|
|
56
|
+
}
|
|
46
57
|
topLevelChanged.add(path[0])
|
|
47
58
|
switch (action) {
|
|
48
59
|
case 'delete':
|
|
@@ -64,15 +75,21 @@ const applyOpsToCtx = (ctx, changes) => {
|
|
|
64
75
|
|
|
65
76
|
const fetchServiceToken = async () => {
|
|
66
77
|
try {
|
|
67
|
-
const urlBase =
|
|
68
|
-
|
|
78
|
+
const urlBase = isLocal
|
|
79
|
+
? 'http://localhost:8080'
|
|
80
|
+
: 'https://api.symbols.app'
|
|
81
|
+
const res = await window.fetch(`${urlBase}/service-token`, {
|
|
82
|
+
method: 'GET'
|
|
83
|
+
})
|
|
69
84
|
|
|
70
85
|
// Attempt to parse JSON first – recent versions return `{ token: "..." }`
|
|
71
86
|
// Fall back to treating the response as raw text for backward-compatibility.
|
|
72
87
|
let txt
|
|
73
88
|
try {
|
|
74
89
|
const json = await res.clone().json()
|
|
75
|
-
if (json && typeof json.token === 'string')
|
|
90
|
+
if (json && typeof json.token === 'string') {
|
|
91
|
+
return json.token.trim()
|
|
92
|
+
}
|
|
76
93
|
// If json parsing succeeds but no token field, fall back to text below.
|
|
77
94
|
txt = await res.text()
|
|
78
95
|
} catch {
|
|
@@ -80,60 +97,80 @@ const fetchServiceToken = async () => {
|
|
|
80
97
|
txt = await res.text()
|
|
81
98
|
}
|
|
82
99
|
|
|
83
|
-
return (txt || '').replace(/\s+/
|
|
100
|
+
return (txt || '').replace(/\s+/gu, '') || void 0
|
|
84
101
|
} catch (e) {
|
|
85
102
|
console.error('[sync] Failed to fetch service-token', e)
|
|
86
|
-
return undefined
|
|
87
103
|
}
|
|
88
104
|
}
|
|
89
105
|
|
|
90
|
-
const onSnapshot =
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
overwriteShallow(ctx[key], val)
|
|
98
|
-
} else {
|
|
99
|
-
ctx[key] = val
|
|
106
|
+
const onSnapshot =
|
|
107
|
+
(el, s, ctx) =>
|
|
108
|
+
(payload = {}) => {
|
|
109
|
+
let { data } = payload
|
|
110
|
+
const { schema } = payload
|
|
111
|
+
if (!data) {
|
|
112
|
+
return
|
|
100
113
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
const changed = applyOpsToCtx(ctx, changes)
|
|
117
|
-
|
|
118
|
-
// React to specific top-level changes
|
|
119
|
-
if (changed.has('state')) {
|
|
120
|
-
const route = ctx.state?.route
|
|
121
|
-
if (route) {
|
|
122
|
-
;(ctx.utils?.router || router)(route.replace('/state', '') || '/', el, {})
|
|
123
|
-
} else {
|
|
124
|
-
s.update(ctx.state)
|
|
114
|
+
data = el.call('deepDestringify', data, Array.isArray(data) ? [] : {})
|
|
115
|
+
|
|
116
|
+
// Overwrite high-level objects shallowly so references are preserved
|
|
117
|
+
Object.entries(data).forEach(([key, val]) => {
|
|
118
|
+
if (ctx[key] && typeof ctx[key] === 'object') {
|
|
119
|
+
overwriteShallow(ctx[key], val)
|
|
120
|
+
} else {
|
|
121
|
+
ctx[key] = val
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
// Optionally make schema available on ctx
|
|
126
|
+
if (schema) {
|
|
127
|
+
ctx.schema = schema
|
|
125
128
|
}
|
|
126
|
-
}
|
|
127
129
|
|
|
128
|
-
|
|
130
|
+
// Trigger routing so UI reflects latest data
|
|
129
131
|
const { pathname, search, hash } = ctx.window.location
|
|
130
132
|
;(ctx.utils?.router || router)(pathname + search + hash, el, {})
|
|
131
133
|
}
|
|
132
134
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
+
const onOps =
|
|
136
|
+
(el, s, ctx) =>
|
|
137
|
+
(payload = {}) => {
|
|
138
|
+
let { changes } = payload
|
|
139
|
+
if (!changes || !Array.isArray(changes) || !changes.length) {
|
|
140
|
+
return
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
changes = el.call(
|
|
144
|
+
'deepDestringify',
|
|
145
|
+
changes,
|
|
146
|
+
Array.isArray(changes) ? [] : {}
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
const changed = applyOpsToCtx(ctx, changes)
|
|
150
|
+
|
|
151
|
+
// React to specific top-level changes
|
|
152
|
+
if (changed.has('state')) {
|
|
153
|
+
const route = ctx.state?.route
|
|
154
|
+
if (route) {
|
|
155
|
+
el.call('router', route.replace('/state', '') || '/')
|
|
156
|
+
} else {
|
|
157
|
+
s.update(ctx.state)
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (
|
|
162
|
+
['pages', 'components', 'snippets', 'functions'].some((k) =>
|
|
163
|
+
changed.has(k)
|
|
164
|
+
)
|
|
165
|
+
) {
|
|
166
|
+
const { pathname, search, hash } = ctx.window.location
|
|
167
|
+
el.call('router', pathname + search + hash)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (changed.has('designSystem')) {
|
|
171
|
+
init(ctx.designSystem)
|
|
172
|
+
}
|
|
135
173
|
}
|
|
136
|
-
}
|
|
137
174
|
|
|
138
175
|
export const connectToSocket = async (el, s, ctx) => {
|
|
139
176
|
const token = await fetchServiceToken()
|
|
@@ -144,11 +181,15 @@ export const connectToSocket = async (el, s, ctx) => {
|
|
|
144
181
|
|
|
145
182
|
const projectKey = ctx.key
|
|
146
183
|
if (!projectKey) {
|
|
147
|
-
console.warn(
|
|
184
|
+
console.warn(
|
|
185
|
+
'[sync] ctx.key missing – cannot establish collaborative connection'
|
|
186
|
+
)
|
|
148
187
|
return null
|
|
149
188
|
}
|
|
150
189
|
|
|
151
|
-
const socketBaseUrl =
|
|
190
|
+
const socketBaseUrl = isLocal
|
|
191
|
+
? 'http://localhost:8080'
|
|
192
|
+
: 'https://api.symbols.app'
|
|
152
193
|
|
|
153
194
|
const socket = io(socketBaseUrl, {
|
|
154
195
|
path: '/collab-socket',
|
|
@@ -165,7 +206,9 @@ export const connectToSocket = async (el, s, ctx) => {
|
|
|
165
206
|
})
|
|
166
207
|
|
|
167
208
|
socket.on('connect', () => {
|
|
168
|
-
if (ctx.editor?.verbose)
|
|
209
|
+
if (ctx.editor?.verbose) {
|
|
210
|
+
console.info('[sync] Connected to collab socket')
|
|
211
|
+
}
|
|
169
212
|
})
|
|
170
213
|
|
|
171
214
|
socket.on('snapshot', onSnapshot(el, s, ctx))
|
|
@@ -178,7 +221,9 @@ export const connectToSocket = async (el, s, ctx) => {
|
|
|
178
221
|
})
|
|
179
222
|
|
|
180
223
|
socket.on('disconnect', (reason) => {
|
|
181
|
-
if (ctx.editor?.verbose)
|
|
224
|
+
if (ctx.editor?.verbose) {
|
|
225
|
+
console.info('[sync] Disconnected from collab socket', reason)
|
|
226
|
+
}
|
|
182
227
|
})
|
|
183
228
|
|
|
184
229
|
return socket
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbo.ls/sync",
|
|
3
|
-
"version": "2.29.
|
|
3
|
+
"version": "2.29.58",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"module": "index.js",
|
|
6
|
-
"gitHead": "
|
|
6
|
+
"gitHead": "d32818a7552e84853d4dcc9dec1dcc7e3e5c7dab",
|
|
7
7
|
"files": [
|
|
8
8
|
"*.js",
|
|
9
9
|
"dist"
|
|
@@ -29,12 +29,12 @@
|
|
|
29
29
|
"prepublish": "rimraf -I dist && npm run build && npm run copy:package:cjs"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@domql/router": "^2.29.
|
|
33
|
-
"@domql/utils": "^2.29.
|
|
34
|
-
"@symbo.ls/init": "^2.29.
|
|
35
|
-
"@symbo.ls/scratch": "^2.29.
|
|
36
|
-
"@symbo.ls/socket": "^2.29.
|
|
37
|
-
"@symbo.ls/uikit": "^2.29.
|
|
32
|
+
"@domql/router": "^2.29.58",
|
|
33
|
+
"@domql/utils": "^2.29.58",
|
|
34
|
+
"@symbo.ls/init": "^2.29.58",
|
|
35
|
+
"@symbo.ls/scratch": "^2.29.58",
|
|
36
|
+
"@symbo.ls/socket": "^2.29.58",
|
|
37
|
+
"@symbo.ls/uikit": "^2.29.58",
|
|
38
38
|
"socket.io-client": "^4.8.1"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|