@symbo.ls/sdk 3.1.1 → 3.2.3

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 (83) hide show
  1. package/README.md +174 -13
  2. package/dist/cjs/config/environment.js +32 -42
  3. package/dist/cjs/index.js +31 -24
  4. package/dist/cjs/services/AIService.js +3 -3
  5. package/dist/cjs/services/AuthService.js +44 -3
  6. package/dist/cjs/services/BasedService.js +530 -24
  7. package/dist/cjs/services/CollabService.js +420 -0
  8. package/dist/cjs/services/CoreService.js +2295 -0
  9. package/dist/cjs/services/SocketService.js +207 -59
  10. package/dist/cjs/services/SymstoryService.js +135 -49
  11. package/dist/cjs/services/index.js +8 -16
  12. package/dist/cjs/state/RootStateManager.js +86 -0
  13. package/dist/cjs/state/rootEventBus.js +65 -0
  14. package/dist/cjs/utils/CollabClient.js +157 -0
  15. package/dist/cjs/utils/TokenManager.js +409 -0
  16. package/dist/cjs/utils/basedQuerys.js +120 -0
  17. package/dist/cjs/utils/jsonDiff.js +103 -0
  18. package/dist/cjs/utils/permission.js +4 -4
  19. package/dist/cjs/utils/services.js +133 -69
  20. package/dist/cjs/utils/symstoryClient.js +33 -2
  21. package/dist/esm/config/environment.js +32 -42
  22. package/dist/esm/index.js +20586 -11525
  23. package/dist/esm/services/AIService.js +3 -3
  24. package/dist/esm/services/AuthService.js +48 -7
  25. package/dist/esm/services/BasedService.js +676 -65
  26. package/dist/esm/services/CollabService.js +18028 -0
  27. package/dist/esm/services/CoreService.js +2827 -0
  28. package/dist/esm/services/SocketService.js +323 -58
  29. package/dist/esm/services/SymstoryService.js +287 -111
  30. package/dist/esm/services/index.js +20456 -11470
  31. package/dist/esm/state/RootStateManager.js +102 -0
  32. package/dist/esm/state/rootEventBus.js +47 -0
  33. package/dist/esm/utils/CollabClient.js +17483 -0
  34. package/dist/esm/utils/TokenManager.js +395 -0
  35. package/dist/esm/utils/basedQuerys.js +120 -0
  36. package/dist/esm/utils/jsonDiff.js +6096 -0
  37. package/dist/esm/utils/permission.js +4 -4
  38. package/dist/esm/utils/services.js +133 -69
  39. package/dist/esm/utils/symstoryClient.js +63 -43
  40. package/dist/esm/utils/validation.js +89 -19
  41. package/dist/node/config/environment.js +32 -42
  42. package/dist/node/index.js +37 -28
  43. package/dist/node/services/AIService.js +3 -3
  44. package/dist/node/services/AuthService.js +44 -3
  45. package/dist/node/services/BasedService.js +531 -25
  46. package/dist/node/services/CollabService.js +401 -0
  47. package/dist/node/services/CoreService.js +2266 -0
  48. package/dist/node/services/SocketService.js +197 -59
  49. package/dist/node/services/SymstoryService.js +135 -49
  50. package/dist/node/services/index.js +8 -16
  51. package/dist/node/state/RootStateManager.js +57 -0
  52. package/dist/node/state/rootEventBus.js +46 -0
  53. package/dist/node/utils/CollabClient.js +128 -0
  54. package/dist/node/utils/TokenManager.js +390 -0
  55. package/dist/node/utils/basedQuerys.js +120 -0
  56. package/dist/node/utils/jsonDiff.js +74 -0
  57. package/dist/node/utils/permission.js +4 -4
  58. package/dist/node/utils/services.js +133 -69
  59. package/dist/node/utils/symstoryClient.js +33 -2
  60. package/package.json +23 -14
  61. package/src/config/environment.js +33 -42
  62. package/src/index.js +45 -28
  63. package/src/services/AIService.js +3 -3
  64. package/src/services/AuthService.js +52 -3
  65. package/src/services/BasedService.js +603 -23
  66. package/src/services/CollabService.js +491 -0
  67. package/src/services/CoreService.js +2548 -0
  68. package/src/services/SocketService.js +227 -59
  69. package/src/services/SymstoryService.js +150 -64
  70. package/src/services/index.js +7 -14
  71. package/src/state/RootStateManager.js +71 -0
  72. package/src/state/rootEventBus.js +48 -0
  73. package/src/utils/CollabClient.js +161 -0
  74. package/src/utils/TokenManager.js +462 -0
  75. package/src/utils/basedQuerys.js +123 -0
  76. package/src/utils/jsonDiff.js +109 -0
  77. package/src/utils/permission.js +4 -4
  78. package/src/utils/services.js +144 -69
  79. package/src/utils/symstoryClient.js +36 -2
  80. package/dist/cjs/services/SocketIOService.js +0 -309
  81. package/dist/esm/services/SocketIOService.js +0 -467
  82. package/dist/node/services/SocketIOService.js +0 -280
  83. package/src/services/SocketIOService.js +0 -356
@@ -1,280 +0,0 @@
1
- import { connect, send, disconnect } from "@symbo.ls/socket/client.js";
2
- import { BaseService } from "./BaseService.js";
3
- import * as utils from "@domql/utils";
4
- import { router } from "@symbo.ls/router";
5
- import environment from "../config/environment.js";
6
- const { deepStringify, deepDestringify, isString } = utils.default || utils;
7
- class SocketService extends BaseService {
8
- constructor(config) {
9
- super(config);
10
- this._socket = null;
11
- this._reconnectAttempts = 0;
12
- this._maxReconnectAttempts = (config == null ? void 0 : config.maxReconnectAttempts) || 5;
13
- this._reconnectDelay = (config == null ? void 0 : config.reconnectDelay) || 1e3;
14
- this._handlers = /* @__PURE__ */ new Map();
15
- this._sessionId = Math.random();
16
- this._ignoreSync = [
17
- "userId",
18
- "username",
19
- "usersName",
20
- "email",
21
- "projects",
22
- "feedbacks",
23
- "userRoles",
24
- "loading",
25
- "appKey",
26
- "projectName",
27
- "followingUser",
28
- "activeProject",
29
- "user",
30
- "sessionId",
31
- "clients"
32
- ];
33
- }
34
- init() {
35
- try {
36
- const { _context, _options } = this;
37
- const socketUrl = environment.socketUrl || _options.socketUrl || "https://socket.symbols.app/";
38
- if (!socketUrl) {
39
- throw new Error("Socket URL is required");
40
- }
41
- this._info = {
42
- config: {
43
- url: socketUrl,
44
- hasToken: Boolean(_context.authToken),
45
- status: "initializing"
46
- }
47
- };
48
- this._setReady();
49
- } catch (error) {
50
- this._setError(error);
51
- throw error;
52
- }
53
- }
54
- connect() {
55
- var _a, _b, _c, _d, _e, _f, _g;
56
- try {
57
- if (this._socket && ["connected", "connecting"].includes((_b = (_a = this._info) == null ? void 0 : _a.config) == null ? void 0 : _b.status)) {
58
- console.warn(
59
- "Socket connection already exists:",
60
- (_d = (_c = this._info) == null ? void 0 : _c.config) == null ? void 0 : _d.status
61
- );
62
- return true;
63
- }
64
- const { _context } = this;
65
- if (!_context.appKey) {
66
- throw new Error("App key is required");
67
- }
68
- this._updateStatus("connecting");
69
- const config = {
70
- source: "platform",
71
- userId: (_e = _context.user) == null ? void 0 : _e.id,
72
- socketUrl: this._info.config.url,
73
- location: window.location.host,
74
- onChange: this._handleMessage.bind(this),
75
- sessionId: this._sessionId,
76
- usersName: (_f = _context.user) == null ? void 0 : _f.name,
77
- route: window.location.pathname,
78
- onDisconnect: this._handleDisconnect.bind(this)
79
- };
80
- if (this._socket) {
81
- this.destroy();
82
- }
83
- this._socket = connect(_context.appKey, config);
84
- this._updateStatus("connected");
85
- if (environment.isDevelopment) {
86
- console.log("Socket connection established:", {
87
- appKey: _context.appKey,
88
- userId: (_g = _context.user) == null ? void 0 : _g.id,
89
- sessionId: this._sessionId,
90
- url: this._info.config.url
91
- });
92
- }
93
- return true;
94
- } catch (error) {
95
- this._updateStatus("failed");
96
- console.error("Socket connection failed:", error);
97
- throw new Error(`Socket connection failed: ${error.message}`);
98
- }
99
- }
100
- send(type, data, opts = {}) {
101
- var _a, _b;
102
- this._requireReady();
103
- if (!this._socket) {
104
- throw new Error("Socket is not connected");
105
- }
106
- const payload = {
107
- sessionId: this._sessionId,
108
- userId: (_a = this._context.user) == null ? void 0 : _a.id,
109
- usersName: (_b = this._context.user) == null ? void 0 : _b.name,
110
- ...data
111
- };
112
- send.call(
113
- this._socket,
114
- type,
115
- opts.preventDeepStringify ? payload : deepStringify(payload)
116
- );
117
- }
118
- _handleMessage(event, data) {
119
- try {
120
- const d = isString(data) ? deepDestringify(JSON.parse(data)) : data;
121
- if (this._sessionId === d.sessionId) {
122
- return;
123
- }
124
- const handlers = this._handlers.get(event);
125
- if (handlers) {
126
- handlers.forEach((handler) => handler(d));
127
- }
128
- switch (event) {
129
- case "change":
130
- this._handleChangeEvent(d);
131
- break;
132
- case "clients":
133
- this._handleClientsEvent(d);
134
- break;
135
- case "route":
136
- this._handleRouteEvent(d);
137
- break;
138
- default:
139
- break;
140
- }
141
- } catch (error) {
142
- this._setError(new Error(`Failed to handle message: ${error.message}`));
143
- }
144
- }
145
- _handleChangeEvent(data) {
146
- var _a, _b, _c;
147
- if (data.canvas) {
148
- const { clients } = data.canvas;
149
- const [firstClientKey] = Object.keys(clients);
150
- const monaco = clients && clients[firstClientKey] && clients[firstClientKey].monaco;
151
- if (monaco) {
152
- const Canvas = this._context.element && this._context.element.getCanvas();
153
- if (Canvas) {
154
- Canvas.Chosen.EditorPanels.update({}, { forceMonacoUpdate: true });
155
- }
156
- }
157
- return;
158
- }
159
- const componentUpdates = ((_a = data.schema) == null ? void 0 : _a.components) || ((_b = data.schema) == null ? void 0 : _b.pages);
160
- if (window.location.pathname.includes("/canvas") && componentUpdates) {
161
- for (const updatedComponent in componentUpdates) {
162
- if (Object.hasOwn(componentUpdates, updatedComponent)) {
163
- (_c = this._context.element) == null ? void 0 : _c.updateComponentOnCanvas(updatedComponent);
164
- }
165
- }
166
- }
167
- }
168
- _handleClientsEvent(data) {
169
- const { root } = Object.getPrototypeOf(this._context.state);
170
- root.replace(
171
- { clients: data },
172
- {
173
- fromSync: true,
174
- preventUpdate: ["Iframe"],
175
- preventModalUpdate: true,
176
- preventStateUpdateListener: true,
177
- execStateFunction: true
178
- }
179
- );
180
- }
181
- _handleRouteEvent(data) {
182
- const { element } = this._context;
183
- const { state } = this._context;
184
- if (data.userId && data.type === "routeChanged") {
185
- const isModalOpen = this.getWindow("modal");
186
- const isFollowing = state.followingUser === data.userId;
187
- const isRouteSyncEnabled = element.getUserSettings("presentMode") && data.userId === state.userId;
188
- if ((isFollowing || isRouteSyncEnabled) && !isModalOpen) {
189
- router(
190
- data.route,
191
- element.__ref.root,
192
- {},
193
- {
194
- fromSync: true,
195
- updateStateOptions: {
196
- fromSync: true,
197
- preventStateUpdateListener: 1
198
- // !isModalRoute(data.route, element)
199
- }
200
- }
201
- );
202
- }
203
- } else if (data.reload) {
204
- window.location.reload();
205
- } else if (data.route && data.type === "routeForced") {
206
- router(
207
- data.route,
208
- element.__ref.root,
209
- {},
210
- {
211
- fromSync: true,
212
- updateStateOptions: {
213
- fromSync: true
214
- }
215
- }
216
- );
217
- } else if (data.componentKey) {
218
- if (!element.getData("components")[data.componentKey]) {
219
- return;
220
- }
221
- element.activateSelected(data.componentKey);
222
- }
223
- }
224
- _handleDisconnect() {
225
- this._updateStatus("disconnected");
226
- this._handleReconnect();
227
- }
228
- _handleReconnect() {
229
- if (this._reconnectAttempts < this._maxReconnectAttempts) {
230
- this._reconnectAttempts++;
231
- this._updateStatus("reconnecting");
232
- setTimeout(() => {
233
- this.connect().then(() => {
234
- this._reconnectAttempts = 0;
235
- }).catch(() => {
236
- this._handleReconnect();
237
- });
238
- }, this._reconnectDelay * this._reconnectAttempts);
239
- } else {
240
- this._updateStatus("failed");
241
- this._setError(new Error("Max reconnection attempts reached"));
242
- }
243
- }
244
- _updateStatus(status) {
245
- this._info = {
246
- ...this._info,
247
- config: {
248
- ...this._info.config,
249
- status
250
- }
251
- };
252
- }
253
- destroy() {
254
- if (this._socket) {
255
- disconnect.call(this._socket);
256
- this._socket = null;
257
- }
258
- this._handlers.clear();
259
- this._setReady(false);
260
- }
261
- reconnect() {
262
- this.destroy();
263
- this.connect();
264
- }
265
- _checkRequiredContext() {
266
- var _a, _b;
267
- return Boolean(
268
- ((_a = this._context) == null ? void 0 : _a.appKey) && ((_b = this._context) == null ? void 0 : _b.authToken) && this._socket
269
- );
270
- }
271
- isReady() {
272
- if (this._checkRequiredContext()) {
273
- this._setReady(true);
274
- }
275
- return this._ready;
276
- }
277
- }
278
- export {
279
- SocketService
280
- };
@@ -1,356 +0,0 @@
1
- import { connect, send, disconnect } from '@symbo.ls/socket/client.js'
2
- import { BaseService } from './BaseService.js'
3
-
4
- import * as utils from '@domql/utils'
5
- import { router } from '@symbo.ls/router'
6
- import environment from '../config/environment.js'
7
-
8
- const { deepStringify, deepDestringify, isString } = utils.default || utils
9
-
10
- export class SocketService extends BaseService {
11
- constructor (config) {
12
- super(config)
13
- this._socket = null
14
- this._reconnectAttempts = 0
15
- this._maxReconnectAttempts = config?.maxReconnectAttempts || 5
16
- this._reconnectDelay = config?.reconnectDelay || 1000
17
- this._handlers = new Map()
18
- this._sessionId = Math.random()
19
-
20
- this._ignoreSync = [
21
- 'userId',
22
- 'username',
23
- 'usersName',
24
- 'email',
25
- 'projects',
26
- 'feedbacks',
27
- 'userRoles',
28
- 'loading',
29
- 'appKey',
30
- 'projectName',
31
- 'followingUser',
32
- 'activeProject',
33
- 'user',
34
- 'sessionId',
35
- 'clients'
36
- ]
37
- }
38
-
39
- init () {
40
- try {
41
- const { _context, _options } = this
42
- const socketUrl =
43
- environment.socketUrl ||
44
- _options.socketUrl ||
45
- 'https://socket.symbols.app/'
46
-
47
- if (!socketUrl) {
48
- throw new Error('Socket URL is required')
49
- }
50
-
51
- this._info = {
52
- config: {
53
- url: socketUrl,
54
- hasToken: Boolean(_context.authToken),
55
- status: 'initializing'
56
- }
57
- }
58
-
59
- this._setReady()
60
- } catch (error) {
61
- this._setError(error)
62
- throw error
63
- }
64
- }
65
-
66
- connect () {
67
- try {
68
- // Check if already connected or connecting
69
- if (
70
- this._socket &&
71
- ['connected', 'connecting'].includes(this._info?.config?.status)
72
- ) {
73
- console.warn(
74
- 'Socket connection already exists:',
75
- this._info?.config?.status
76
- )
77
- return true
78
- }
79
-
80
- const { _context } = this
81
-
82
- if (!_context.appKey) {
83
- throw new Error('App key is required')
84
- }
85
-
86
- // Update status to connecting before attempting connection
87
- this._updateStatus('connecting')
88
-
89
- const config = {
90
- source: 'platform',
91
- userId: _context.user?.id,
92
- socketUrl: this._info.config.url,
93
- location: window.location.host,
94
- onChange: this._handleMessage.bind(this),
95
- sessionId: this._sessionId,
96
- usersName: _context.user?.name,
97
- route: window.location.pathname,
98
- onDisconnect: this._handleDisconnect.bind(this)
99
- }
100
-
101
- // If a previous socket exists but wasn't properly cleaned up, destroy it
102
- if (this._socket) {
103
- this.destroy()
104
- }
105
-
106
- this._socket = connect(_context.appKey, config)
107
- this._updateStatus('connected')
108
-
109
- if (environment.isDevelopment) {
110
- console.log('Socket connection established:', {
111
- appKey: _context.appKey,
112
- userId: _context.user?.id,
113
- sessionId: this._sessionId,
114
- url: this._info.config.url
115
- })
116
- }
117
-
118
- return true
119
- } catch (error) {
120
- this._updateStatus('failed')
121
- console.error('Socket connection failed:', error)
122
- throw new Error(`Socket connection failed: ${error.message}`)
123
- }
124
- }
125
-
126
- send (type, data, opts = {}) {
127
- this._requireReady()
128
-
129
- if (!this._socket) {
130
- throw new Error('Socket is not connected')
131
- }
132
-
133
- const payload = {
134
- sessionId: this._sessionId,
135
- userId: this._context.user?.id,
136
- usersName: this._context.user?.name,
137
- ...data
138
- }
139
-
140
- // console.log('sending')
141
- // console.log(payload)
142
-
143
- send.call(
144
- this._socket,
145
- type,
146
- opts.preventDeepStringify ? payload : deepStringify(payload)
147
- )
148
- }
149
-
150
- _handleMessage (event, data) {
151
- try {
152
- const d = isString(data) ? deepDestringify(JSON.parse(data)) : data
153
- if (this._sessionId === d.sessionId) {
154
- return
155
- }
156
-
157
- const handlers = this._handlers.get(event)
158
- if (handlers) {
159
- handlers.forEach(handler => handler(d))
160
- }
161
-
162
- // Handle specific events
163
- switch (event) {
164
- case 'change':
165
- this._handleChangeEvent(d)
166
- break
167
- case 'clients':
168
- this._handleClientsEvent(d)
169
- break
170
- case 'route':
171
- this._handleRouteEvent(d)
172
- break
173
- default:
174
- break
175
- }
176
- } catch (error) {
177
- this._setError(new Error(`Failed to handle message: ${error.message}`))
178
- }
179
- }
180
-
181
- _handleChangeEvent (data) {
182
- if (data.canvas) {
183
- const { clients } = data.canvas
184
- const [firstClientKey] = Object.keys(clients)
185
- const monaco =
186
- clients && clients[firstClientKey] && clients[firstClientKey].monaco
187
- if (monaco) {
188
- const Canvas =
189
- this._context.element && this._context.element.getCanvas()
190
- if (Canvas) {
191
- Canvas.Chosen.EditorPanels.update({}, { forceMonacoUpdate: true })
192
- }
193
- }
194
- return
195
- }
196
-
197
- // console.log('receiving')
198
- // console.log(data)
199
-
200
- // Handle component updates
201
- const componentUpdates = data.schema?.components || data.schema?.pages
202
- if (window.location.pathname.includes('/canvas') && componentUpdates) {
203
- for (const updatedComponent in componentUpdates) {
204
- if (Object.hasOwn(componentUpdates, updatedComponent)) {
205
- this._context.element?.updateComponentOnCanvas(updatedComponent)
206
- }
207
- }
208
- }
209
-
210
- // // Update state
211
- // // eslint-disable-next-line no-unused-vars
212
- // const { userId, ...restData } = data
213
- // const dataToApply = {}
214
- // Object.keys(restData)
215
- // .filter(v => this._ignoreSync.includes(v))
216
- // .forEach(v => {
217
- // dataToApply[v] = restData[v]
218
- // })
219
-
220
- // console.log('receiving')
221
- // console.log(data)
222
-
223
- // this._context.state?.rootUpdate(dataToApply, {
224
- // fromSync: true,
225
- // preventStateUpdateListener: true,
226
- // execStateFunction: true,
227
- // preventUpdate: ['Iframe'],
228
- // preventModalUpdate: true,
229
- // forceMonacoUpdate: true,
230
- // forcePreviewUpdate: true
231
- // })
232
- }
233
-
234
- _handleClientsEvent (data) {
235
- const { root } = Object.getPrototypeOf(this._context.state)
236
- root.replace(
237
- { clients: data },
238
- {
239
- fromSync: true,
240
- preventUpdate: ['Iframe'],
241
- preventModalUpdate: true,
242
- preventStateUpdateListener: true,
243
- execStateFunction: true
244
- }
245
- )
246
- }
247
-
248
- _handleRouteEvent (data) {
249
- const { element } = this._context
250
- const { state } = this._context
251
-
252
- if (data.userId && data.type === 'routeChanged') {
253
- const isModalOpen = this.getWindow('modal')
254
- const isFollowing = state.followingUser === data.userId
255
- const isRouteSyncEnabled =
256
- element.getUserSettings('presentMode') && data.userId === state.userId
257
-
258
- if ((isFollowing || isRouteSyncEnabled) && !isModalOpen) {
259
- router(
260
- data.route,
261
- element.__ref.root,
262
- {},
263
- {
264
- fromSync: true,
265
- updateStateOptions: {
266
- fromSync: true,
267
- preventStateUpdateListener: 1 // !isModalRoute(data.route, element)
268
- }
269
- }
270
- )
271
- }
272
- } else if (data.reload) {
273
- window.location.reload()
274
- } else if (data.route && data.type === 'routeForced') {
275
- router(
276
- data.route,
277
- element.__ref.root,
278
- {},
279
- {
280
- fromSync: true,
281
- updateStateOptions: {
282
- fromSync: true
283
- }
284
- }
285
- )
286
- } else if (data.componentKey) {
287
- if (!element.getData('components')[data.componentKey]) {
288
- return
289
- }
290
- element.activateSelected(data.componentKey)
291
- }
292
- }
293
-
294
- _handleDisconnect () {
295
- this._updateStatus('disconnected')
296
- this._handleReconnect()
297
- }
298
-
299
- _handleReconnect () {
300
- if (this._reconnectAttempts < this._maxReconnectAttempts) {
301
- this._reconnectAttempts++
302
- this._updateStatus('reconnecting')
303
-
304
- setTimeout(() => {
305
- this.connect()
306
- .then(() => {
307
- this._reconnectAttempts = 0
308
- })
309
- .catch(() => {
310
- this._handleReconnect()
311
- })
312
- }, this._reconnectDelay * this._reconnectAttempts)
313
- } else {
314
- this._updateStatus('failed')
315
- this._setError(new Error('Max reconnection attempts reached'))
316
- }
317
- }
318
-
319
- _updateStatus (status) {
320
- this._info = {
321
- ...this._info,
322
- config: {
323
- ...this._info.config,
324
- status
325
- }
326
- }
327
- }
328
-
329
- destroy () {
330
- if (this._socket) {
331
- disconnect.call(this._socket)
332
- this._socket = null
333
- }
334
- this._handlers.clear()
335
- this._setReady(false)
336
- }
337
-
338
- reconnect () {
339
- this.destroy()
340
- this.connect()
341
- }
342
-
343
- _checkRequiredContext () {
344
- return Boolean(
345
- this._context?.appKey && this._context?.authToken && this._socket
346
- )
347
- }
348
-
349
- isReady () {
350
- if (this._checkRequiredContext()) {
351
- this._setReady(true)
352
- }
353
-
354
- return this._ready
355
- }
356
- }