@symbo.ls/sync 3.14.0 → 3.14.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/CHANGELOG.md +12 -0
- package/dist/cjs/SyncNotifications.cjs +1 -0
- package/dist/cjs/applier.cjs +1 -0
- package/dist/cjs/handlers.cjs +1 -0
- package/dist/cjs/index.cjs +1 -0
- package/dist/esm/SyncNotifications.js +1 -82
- package/dist/esm/applier.js +1 -0
- package/dist/esm/handlers.js +1 -0
- package/dist/esm/index.js +1 -210
- package/package.json +33 -24
- package/Inspect.js +0 -190
- package/SyncNotifications.js +0 -120
- package/client.js +0 -129
- package/dist/cjs/Inspect.js +0 -191
- package/dist/cjs/SyncNotifications.js +0 -102
- package/dist/cjs/client.js +0 -129
- package/dist/cjs/index.js +0 -229
- package/dist/cjs/server.js +0 -115
- package/dist/esm/Inspect.js +0 -161
- package/dist/esm/client.js +0 -100
- package/dist/esm/server.js +0 -85
- package/dist/iife/index.js +0 -498
- package/dynamic.json +0 -1
- package/index.js +0 -256
- package/server.js +0 -102
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# @symbo.ls/sync
|
|
2
|
+
|
|
3
|
+
## 3.14.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Auto-generated patch release for changed packages.
|
|
8
|
+
- Updated dependencies
|
|
9
|
+
- @symbo.ls/default-config@3.14.2
|
|
10
|
+
- @symbo.ls/scratch@3.14.2
|
|
11
|
+
- @symbo.ls/utils@3.14.2
|
|
12
|
+
- @symbo.ls/router@3.14.1
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var c=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var a=Object.getOwnPropertyNames;var s=Object.prototype.hasOwnProperty;var l=(t,e)=>{for(var n in e)c(t,n,{get:e[n],enumerable:!0})},f=(t,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of a(e))!s.call(t,i)&&i!==n&&c(t,i,{get:()=>e[i],enumerable:!(o=d(e,i))||o.enumerable});return t};var r=t=>f(c({},"__esModule",{value:!0}),t);var x={};l(x,{Notifications:()=>m,connectedToSymbols:()=>p});module.exports=r(x);const u={success:"green",error:"red",warning:"yellow"},p=(t,e,n)=>{if(t.symbols){if(!n.connected){n.notifications.connected={title:"Connected",message:"to the Symbols live server"},n.update({connected:!0});const o=setTimeout(()=>{delete n.notifications.connected,e.notifications.content.connected.update({animation:"fadeOutDown"}),n.update({connected:!0}),clearTimeout(o)},3e3)}}else if(n.connected){n.notifications.connected={title:"Disconnected",type:"error"},n.update({connected:!1});const o=setTimeout(()=>{delete n.notifications.connected,e.notifications.content.connected&&e.notifications.content.connected.update({animation:"fadeOutDown"}),n.update({connected:!0}),clearTimeout(o)},3e3)}},m={state:{notifications:[]},Notifications:{position:"fixed",left:"A2",bottom:"Z2",zIndex:"999",childExtends:"Notification",childProps:({state:t})=>({animationDuration:"C",background:u[t.type||"success"],icon:null,Flex:{Title:{text:"{{ title }}"},P:{text:"{{ title }}"}},onRender:(e,n,o)=>{n.update({animation:"fadeInUp"})},onClick:(e,n,o)=>{delete o.notifications[n.key],n.update({animation:"fadeOutDown"}),o.onClose&&o.onClose(e,n,o)}}),IconText:null,childrenAs:"state",children:({state:t})=>t.notifications}};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var s=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var h=Object.getOwnPropertyNames;var A=Object.prototype.hasOwnProperty;var g=(r,e)=>{for(var n in e)s(r,n,{get:e[n],enumerable:!0})},x=(r,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of h(e))!A.call(r,t)&&t!==n&&s(r,t,{get:()=>e[t],enumerable:!(o=y(e,t))||o.enumerable});return r};var S=r=>x(s({},"__esModule",{value:!0}),r);var k={};g(k,{FORBIDDEN_SEGMENTS:()=>f,applyOpsToCtx:()=>_,deletePath:()=>a,isSafePath:()=>u,setPath:()=>l});module.exports=S(k);const f=new Set(["__proto__","constructor","prototype"]),u=r=>{if(!Array.isArray(r))return!1;for(let e=0;e<r.length;e++)if(f.has(r[e]))return!1;return!0},a=(r,e)=>{!r||!u(e)||e.reduce((n,o,t,i)=>{if(n&&o in n){if(t!==i.length-1)return n[o];delete n[o]}},r)},l=(r,e,n,o=!1)=>{!r||!u(e)||e.reduce((t,i,d,p)=>{if(t){if(d!==p.length-1)return!t[i]&&o&&(t[i]={}),t[i];t[i]=n}},r)},_=(r,e)=>{const n=new Set;if(!Array.isArray(e))return n;for(const[o,t,i]of e)if(!(!Array.isArray(t)||!t.length))switch(n.add(t[0]),o){case"delete":a(r,t);break;case"update":case"set":l(r,t,i,!0);break;default:break}return n};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var p=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var d=Object.prototype.hasOwnProperty;var y=(t,o)=>{for(var e in o)p(t,e,{get:o[e],enumerable:!0})},u=(t,o,e,n)=>{if(o&&typeof o=="object"||typeof o=="function")for(let s of g(o))!d.call(t,s)&&s!==e&&p(t,s,{get:()=>o[s],enumerable:!(n=l(o,s))||n.enumerable});return t};var A=t=>u(p({},"__esModule",{value:!0}),t);var O={};y(O,{onOps:()=>w,onSnapshot:()=>S});module.exports=A(O);var f=require("smbls/src/init.js"),c=require("@symbo.ls/utils"),h=require("./applier.js");const S=(t,o,e)=>(n={})=>{let{data:s}=n;const{schema:i}=n;s&&(s=t.call("deepDestringifyFunctions",s,Array.isArray(s)?[]:{}),Object.entries(s).forEach(([r,a])=>{e[r]&&typeof e[r]=="object"?r==="designSystem"?(0,f.init)(a):(0,c.overwriteShallow)(e[r],a):e[r]=a}),i&&(e.schema=i))},w=(t,o,e)=>(n={})=>{let{changes:s}=n;if(!s||!Array.isArray(s)||!s.length)return;s=t.call("deepDestringifyFunctions",s,Array.isArray(s)?[]:{});const i=(0,h.applyOpsToCtx)(e,s);if(i.has("state")&&o.update(e.state),["pages","components","snippets","functions","assets"].some(r=>i.has(r))){const{pathname:r,search:a,hash:m}=e.window.location;t.call("router",r+a+m,t.__ref.root,{},{scrollToTop:!1})}i.has("designSystem")&&(0,f.init)(e.designSystem)};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var d=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var T=(e,n)=>{for(var o in n)d(e,o,{get:n[o],enumerable:!0})},E=(e,n,o,t)=>{if(n&&typeof n=="object"||typeof n=="function")for(let r of g(n))!U.call(e,r)&&r!==o&&d(e,r,{get:()=>n[r],enumerable:!(t=w(n,r))||t.enumerable});return e};var A=e=>E(d({},"__esModule",{value:!0}),e);var R={};T(R,{DefaultSyncApp:()=>O,FORBIDDEN_SEGMENTS:()=>s.FORBIDDEN_SEGMENTS,Notifications:()=>c.Notifications,SyncComponent:()=>u,applyOpsToCtx:()=>s.applyOpsToCtx,connectToSocket:()=>v,deletePath:()=>s.deletePath,isSafePath:()=>s.isSafePath,notificationsPlugin:()=>M,onOps:()=>i.onOps,onSnapshot:()=>i.onSnapshot,setPath:()=>s.setPath,syncPlugin:()=>B});module.exports=A(R);var G=require("@symbo.ls/router"),f=require("socket.io-client"),l=require("@symbo.ls/utils"),s=require("./applier.js"),i=require("./handlers.js"),c=require("./SyncNotifications.js");const C=!1,D=()=>C?"http://localhost:8080":"https://api.symbols.app",I=e=>{const n=e&&e.editor&&e.editor.socketUrl||e&&e.settings&&e.settings.socketUrl;return typeof n=="string"&&n?{mode:"collab",baseUrl:n}:e&&e.editor&&e.editor.runtime==="runner"?{mode:"runner",baseUrl:null}:{mode:null,baseUrl:null}},j=async e=>{try{const n=e||D(),o=await l.window.fetch(`${n}/service-token`,{method:"GET"});let t;try{const r=await o.clone().json();if(r&&typeof r.token=="string")return r.token.trim();t=await o.text()}catch{t=await o.text()}return(t||"").replace(/\s+/gu,"")||void 0}catch(n){console.error("[sync] Failed to fetch service-token",n)}},y=(e,n,o,t)=>{e.on("snapshot",(0,i.onSnapshot)(n,o,t)),e.on("ops",(0,i.onOps)(n,o,t)),e.on("clients",r=>{t.editor?.verbose&&(0,c.connectedToSymbols)(r,n,o)}),e.on("disconnect",r=>{t.editor?.verbose&&console.info("[sync] disconnected",r)})},N=async(e,n,o,t)=>{const r=await j(t);if(!r)return console.warn("[sync] no service token \u2014 collab disabled"),null;const p=o.key;if(!p)return console.warn("[sync] ctx.key missing \u2014 collab cannot authenticate"),null;const S=o.editor?.projectId||null,a=(0,f.io)(t,{path:"/collab-socket",transports:["websocket"],auth:{token:r,projectId:S,projectKey:p,branch:"main",live:!0,clientType:"platform"},reconnectionAttempts:1/0,reconnectionDelayMax:4e3});return a.on("connect",()=>{o.editor?.verbose&&console.info("[sync] connected (collab)")}),y(a,e,n,o),a},P=(e,n,o)=>{const t=(0,f.io)({transports:["websocket","polling"],reconnectionAttempts:1/0,reconnectionDelayMax:4e3});return t.on("connect",()=>{o.editor?.verbose!==!1&&console.info("[sync] connected (runner)")}),y(t,e,n,o),t.on("reload",()=>{typeof l.window<"u"&&l.window.location&&l.window.location.reload()}),t},v=async(e,n,o)=>{const{mode:t,baseUrl:r}=I(o);return t?t==="collab"?N(e,n,o,r):t==="runner"?P(e,n,o):null:null},u={onInit:v},O={extends:[u,c.Notifications]},m=e=>typeof e>"u",b=e=>!!(e?.editor?.socketUrl||e?.settings?.socketUrl),h=e=>e?.editor?.runtime==="runner",k=(e,n)=>{Array.isArray(e.extends)?e.extends.push(n):e.extends?e.extends=[e.extends,n]:e.extends=[n]},B={name:"sync",beforeCreate(e,n){const o=n&&n.editor;(o&&!m(o.liveSync)?o.liveSync:b(n)||h(n))&&(b(n)&&!h(n)&&!n?.key||k(e,u))}},M={name:"notifications",beforeCreate(e,n){if(!n)return;const o=m(n.notifications)?null:n.notifications,t=n.editor&&n.editor.verbose===!0;(o===!0||o!==!1&&t)&&k(e,c.Notifications)}};
|
|
@@ -1,82 +1 @@
|
|
|
1
|
-
const
|
|
2
|
-
success: "green",
|
|
3
|
-
error: "red",
|
|
4
|
-
warning: "yellow"
|
|
5
|
-
};
|
|
6
|
-
const connectedToSymbols = (clients, element, state) => {
|
|
7
|
-
if (clients.symbols) {
|
|
8
|
-
if (!state.connected) {
|
|
9
|
-
state.notifications.connected = {
|
|
10
|
-
title: "Connected",
|
|
11
|
-
message: "to the Symbols live server"
|
|
12
|
-
};
|
|
13
|
-
state.update({ connected: true });
|
|
14
|
-
const t = setTimeout(() => {
|
|
15
|
-
delete state.notifications.connected;
|
|
16
|
-
element.notifications.content.connected.update({
|
|
17
|
-
animation: "fadeOutDown"
|
|
18
|
-
});
|
|
19
|
-
state.update({ connected: true });
|
|
20
|
-
clearTimeout(t);
|
|
21
|
-
}, 3e3);
|
|
22
|
-
}
|
|
23
|
-
} else {
|
|
24
|
-
if (state.connected) {
|
|
25
|
-
state.notifications.connected = {
|
|
26
|
-
title: "Disconnected",
|
|
27
|
-
type: "error"
|
|
28
|
-
};
|
|
29
|
-
state.update({ connected: false });
|
|
30
|
-
const t = setTimeout(() => {
|
|
31
|
-
delete state.notifications.connected;
|
|
32
|
-
if (element.notifications.content.connected) {
|
|
33
|
-
element.notifications.content.connected.update({
|
|
34
|
-
animation: "fadeOutDown"
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
state.update({ connected: true });
|
|
38
|
-
clearTimeout(t);
|
|
39
|
-
}, 3e3);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
const Notifications = {
|
|
44
|
-
state: {
|
|
45
|
-
notifications: []
|
|
46
|
-
},
|
|
47
|
-
Notifications: {
|
|
48
|
-
position: "fixed",
|
|
49
|
-
left: "A2",
|
|
50
|
-
bottom: "Z2",
|
|
51
|
-
zIndex: "999",
|
|
52
|
-
childExtends: "Notification",
|
|
53
|
-
childProps: ({ state }) => ({
|
|
54
|
-
animationDuration: "C",
|
|
55
|
-
background: NOTIF_COLORS[state.type || "success"],
|
|
56
|
-
icon: null,
|
|
57
|
-
Flex: {
|
|
58
|
-
Title: {
|
|
59
|
-
text: "{{ title }}"
|
|
60
|
-
},
|
|
61
|
-
P: {
|
|
62
|
-
text: "{{ title }}"
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
onRender: (e, el, s) => {
|
|
66
|
-
el.update({ animation: "fadeInUp" });
|
|
67
|
-
},
|
|
68
|
-
onClick: (e, el, s) => {
|
|
69
|
-
delete s.notifications[el.key];
|
|
70
|
-
el.update({ animation: "fadeOutDown" });
|
|
71
|
-
if (s.onClose) s.onClose(e, el, s);
|
|
72
|
-
}
|
|
73
|
-
}),
|
|
74
|
-
IconText: null,
|
|
75
|
-
childrenAs: "state",
|
|
76
|
-
children: ({ state }) => state.notifications
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
export {
|
|
80
|
-
Notifications,
|
|
81
|
-
connectedToSymbols
|
|
82
|
-
};
|
|
1
|
+
const i={success:"green",error:"red",warning:"yellow"},c=(o,t,n)=>{if(o.symbols){if(!n.connected){n.notifications.connected={title:"Connected",message:"to the Symbols live server"},n.update({connected:!0});const e=setTimeout(()=>{delete n.notifications.connected,t.notifications.content.connected.update({animation:"fadeOutDown"}),n.update({connected:!0}),clearTimeout(e)},3e3)}}else if(n.connected){n.notifications.connected={title:"Disconnected",type:"error"},n.update({connected:!1});const e=setTimeout(()=>{delete n.notifications.connected,t.notifications.content.connected&&t.notifications.content.connected.update({animation:"fadeOutDown"}),n.update({connected:!0}),clearTimeout(e)},3e3)}},d={state:{notifications:[]},Notifications:{position:"fixed",left:"A2",bottom:"Z2",zIndex:"999",childExtends:"Notification",childProps:({state:o})=>({animationDuration:"C",background:i[o.type||"success"],icon:null,Flex:{Title:{text:"{{ title }}"},P:{text:"{{ title }}"}},onRender:(t,n,e)=>{n.update({animation:"fadeInUp"})},onClick:(t,n,e)=>{delete e.notifications[n.key],n.update({animation:"fadeOutDown"}),e.onClose&&e.onClose(t,n,e)}}),IconText:null,childrenAs:"state",children:({state:o})=>o.notifications}};export{d as Notifications,c as connectedToSymbols};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const a=new Set(["__proto__","constructor","prototype"]),s=r=>{if(!Array.isArray(r))return!1;for(let t=0;t<r.length;t++)if(a.has(r[t]))return!1;return!0},l=(r,t)=>{!r||!s(t)||t.reduce((n,i,e,o)=>{if(n&&i in n){if(e!==o.length-1)return n[i];delete n[i]}},r)},d=(r,t,n,i=!1)=>{!r||!s(t)||t.reduce((e,o,u,f)=>{if(e){if(u!==f.length-1)return!e[o]&&i&&(e[o]={}),e[o];e[o]=n}},r)},p=(r,t)=>{const n=new Set;if(!Array.isArray(t))return n;for(const[i,e,o]of t)if(!(!Array.isArray(e)||!e.length))switch(n.add(e[0]),i){case"delete":l(r,e);break;case"update":case"set":d(r,e,o,!0);break;default:break}return n};export{a as FORBIDDEN_SEGMENTS,p as applyOpsToCtx,l as deletePath,s as isSafePath,d as setPath};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{init as p}from"smbls/src/init.js";import{overwriteShallow as c}from"@symbo.ls/utils";import{applyOpsToCtx as h}from"./applier.js";const d=(r,a,e)=>(i={})=>{let{data:s}=i;const{schema:o}=i;s&&(s=r.call("deepDestringifyFunctions",s,Array.isArray(s)?[]:{}),Object.entries(s).forEach(([t,n])=>{e[t]&&typeof e[t]=="object"?t==="designSystem"?p(n):c(e[t],n):e[t]=n}),o&&(e.schema=o))},y=(r,a,e)=>(i={})=>{let{changes:s}=i;if(!s||!Array.isArray(s)||!s.length)return;s=r.call("deepDestringifyFunctions",s,Array.isArray(s)?[]:{});const o=h(e,s);if(o.has("state")&&a.update(e.state),["pages","components","snippets","functions","assets"].some(t=>o.has(t))){const{pathname:t,search:n,hash:f}=e.window.location;r.call("router",t+n+f,r.__ref.root,{},{scrollToTop:!1})}o.has("designSystem")&&p(e.designSystem)};export{y as onOps,d as onSnapshot};
|
package/dist/esm/index.js
CHANGED
|
@@ -1,210 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { init } from "smbls/src/init.js";
|
|
3
|
-
import { io } from "socket.io-client";
|
|
4
|
-
import { window, overwriteShallow, overwriteDeep } from "@symbo.ls/utils";
|
|
5
|
-
import { connectedToSymbols, Notifications } from "./SyncNotifications";
|
|
6
|
-
import { Inspect } from "./Inspect";
|
|
7
|
-
const isLocal = process.env.NODE_ENV === "local";
|
|
8
|
-
const deletePath = (obj, path) => {
|
|
9
|
-
if (!obj || !Array.isArray(path)) {
|
|
10
|
-
return;
|
|
11
|
-
}
|
|
12
|
-
path.reduce((acc, v, i, arr) => {
|
|
13
|
-
if (acc && v in acc) {
|
|
14
|
-
if (i !== arr.length - 1) {
|
|
15
|
-
return acc[v];
|
|
16
|
-
}
|
|
17
|
-
delete acc[v];
|
|
18
|
-
}
|
|
19
|
-
return void 0;
|
|
20
|
-
}, obj);
|
|
21
|
-
};
|
|
22
|
-
const setPath = (obj, path, value, createNestedObjects = false) => {
|
|
23
|
-
if (!obj || !Array.isArray(path)) {
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
path.reduce((acc, v, i, arr) => {
|
|
27
|
-
if (!acc) {
|
|
28
|
-
return void 0;
|
|
29
|
-
}
|
|
30
|
-
if (i !== arr.length - 1) {
|
|
31
|
-
if (!acc[v] && createNestedObjects) {
|
|
32
|
-
acc[v] = {};
|
|
33
|
-
}
|
|
34
|
-
return acc[v];
|
|
35
|
-
}
|
|
36
|
-
acc[v] = value;
|
|
37
|
-
return void 0;
|
|
38
|
-
}, obj);
|
|
39
|
-
};
|
|
40
|
-
const applyOpsToCtx = (ctx, changes) => {
|
|
41
|
-
const topLevelChanged = /* @__PURE__ */ new Set();
|
|
42
|
-
if (!Array.isArray(changes)) {
|
|
43
|
-
return topLevelChanged;
|
|
44
|
-
}
|
|
45
|
-
for (const [action, path, change] of changes) {
|
|
46
|
-
if (!Array.isArray(path) || !path.length) {
|
|
47
|
-
continue;
|
|
48
|
-
}
|
|
49
|
-
topLevelChanged.add(path[0]);
|
|
50
|
-
switch (action) {
|
|
51
|
-
case "delete":
|
|
52
|
-
deletePath(ctx, path);
|
|
53
|
-
break;
|
|
54
|
-
case "update":
|
|
55
|
-
case "set":
|
|
56
|
-
setPath(ctx, path, change, true);
|
|
57
|
-
break;
|
|
58
|
-
default:
|
|
59
|
-
break;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
return topLevelChanged;
|
|
63
|
-
};
|
|
64
|
-
const fetchServiceToken = async () => {
|
|
65
|
-
try {
|
|
66
|
-
const urlBase = isLocal ? "http://localhost:8080" : "https://api.symbols.app";
|
|
67
|
-
const res = await window.fetch(`${urlBase}/service-token`, {
|
|
68
|
-
method: "GET"
|
|
69
|
-
});
|
|
70
|
-
let txt;
|
|
71
|
-
try {
|
|
72
|
-
const json = await res.clone().json();
|
|
73
|
-
if (json && typeof json.token === "string") {
|
|
74
|
-
return json.token.trim();
|
|
75
|
-
}
|
|
76
|
-
txt = await res.text();
|
|
77
|
-
} catch {
|
|
78
|
-
txt = await res.text();
|
|
79
|
-
}
|
|
80
|
-
return (txt || "").replace(/\s+/gu, "") || void 0;
|
|
81
|
-
} catch (e) {
|
|
82
|
-
console.error("[sync] Failed to fetch service-token", e);
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
const onSnapshot = (el, s, ctx) => (payload = {}) => {
|
|
86
|
-
let { data } = payload;
|
|
87
|
-
const { schema } = payload;
|
|
88
|
-
if (!data) {
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
data = el.call(
|
|
92
|
-
"deepDestringifyFunctions",
|
|
93
|
-
data,
|
|
94
|
-
Array.isArray(data) ? [] : {}
|
|
95
|
-
);
|
|
96
|
-
Object.entries(data).forEach(([key, val]) => {
|
|
97
|
-
if (ctx[key] && typeof ctx[key] === "object") {
|
|
98
|
-
if (key === "designSystem") {
|
|
99
|
-
init(val);
|
|
100
|
-
} else {
|
|
101
|
-
overwriteShallow(ctx[key], val);
|
|
102
|
-
}
|
|
103
|
-
} else {
|
|
104
|
-
ctx[key] = val;
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
if (schema) {
|
|
108
|
-
ctx.schema = schema;
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
const onOps = (el, s, ctx) => (payload = {}) => {
|
|
112
|
-
let { changes } = payload;
|
|
113
|
-
if (!changes || !Array.isArray(changes) || !changes.length) {
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
changes = el.call(
|
|
117
|
-
"deepDestringifyFunctions",
|
|
118
|
-
changes,
|
|
119
|
-
Array.isArray(changes) ? [] : {}
|
|
120
|
-
);
|
|
121
|
-
const changed = applyOpsToCtx(ctx, changes);
|
|
122
|
-
if (changed.has("state")) {
|
|
123
|
-
const route = ctx.state?.route;
|
|
124
|
-
if (route) {
|
|
125
|
-
el.call(
|
|
126
|
-
"router",
|
|
127
|
-
route.replace("/state", "") || "/",
|
|
128
|
-
el.__ref.root,
|
|
129
|
-
{},
|
|
130
|
-
{ scrollToTop: false }
|
|
131
|
-
);
|
|
132
|
-
} else {
|
|
133
|
-
s.update(ctx.state);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
if (["pages", "components", "snippets", "functions"].some(
|
|
137
|
-
(k) => changed.has(k)
|
|
138
|
-
)) {
|
|
139
|
-
const { pathname, search, hash } = ctx.window.location;
|
|
140
|
-
el.call(
|
|
141
|
-
"router",
|
|
142
|
-
pathname + search + hash,
|
|
143
|
-
el.__ref.root,
|
|
144
|
-
{},
|
|
145
|
-
{ scrollToTop: false }
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
if (changed.has("designSystem")) {
|
|
149
|
-
init(ctx.designSystem);
|
|
150
|
-
}
|
|
151
|
-
};
|
|
152
|
-
const connectToSocket = async (el, s, ctx) => {
|
|
153
|
-
const token = await fetchServiceToken();
|
|
154
|
-
if (!token) {
|
|
155
|
-
console.warn("[sync] No service token \u2013 live collaboration disabled");
|
|
156
|
-
return null;
|
|
157
|
-
}
|
|
158
|
-
const projectKey = ctx.key;
|
|
159
|
-
if (!projectKey) {
|
|
160
|
-
console.warn(
|
|
161
|
-
"[sync] ctx.key missing \u2013 cannot establish collaborative connection"
|
|
162
|
-
);
|
|
163
|
-
return null;
|
|
164
|
-
}
|
|
165
|
-
const socketBaseUrl = isLocal ? "http://localhost:8080" : "https://api.symbols.app";
|
|
166
|
-
const socket = io(socketBaseUrl, {
|
|
167
|
-
path: "/collab-socket",
|
|
168
|
-
transports: ["websocket"],
|
|
169
|
-
auth: {
|
|
170
|
-
token,
|
|
171
|
-
projectKey,
|
|
172
|
-
branch: "main",
|
|
173
|
-
live: true,
|
|
174
|
-
clientType: "platform"
|
|
175
|
-
},
|
|
176
|
-
reconnectionAttempts: Infinity,
|
|
177
|
-
reconnectionDelayMax: 4e3
|
|
178
|
-
});
|
|
179
|
-
socket.on("connect", () => {
|
|
180
|
-
if (ctx.editor?.verbose) {
|
|
181
|
-
console.info("[sync] Connected to collab socket");
|
|
182
|
-
}
|
|
183
|
-
});
|
|
184
|
-
socket.on("snapshot", onSnapshot(el, s, ctx));
|
|
185
|
-
socket.on("ops", onOps(el, s, ctx));
|
|
186
|
-
socket.on("clients", (data) => {
|
|
187
|
-
if (ctx.editor?.verbose) {
|
|
188
|
-
connectedToSymbols(data, el, s);
|
|
189
|
-
}
|
|
190
|
-
});
|
|
191
|
-
socket.on("disconnect", (reason) => {
|
|
192
|
-
if (ctx.editor?.verbose) {
|
|
193
|
-
console.info("[sync] Disconnected from collab socket", reason);
|
|
194
|
-
}
|
|
195
|
-
});
|
|
196
|
-
return socket;
|
|
197
|
-
};
|
|
198
|
-
const SyncComponent = {
|
|
199
|
-
onInitSync: connectToSocket
|
|
200
|
-
};
|
|
201
|
-
const DefaultSyncApp = {
|
|
202
|
-
extends: [SyncComponent, Inspect, Notifications]
|
|
203
|
-
};
|
|
204
|
-
export {
|
|
205
|
-
DefaultSyncApp,
|
|
206
|
-
Inspect,
|
|
207
|
-
Notifications,
|
|
208
|
-
SyncComponent,
|
|
209
|
-
connectToSocket
|
|
210
|
-
};
|
|
1
|
+
import"@symbo.ls/router";import{io as a}from"socket.io-client";import{window as s}from"@symbo.ls/utils";import{FORBIDDEN_SEGMENTS as v,isSafePath as S,deletePath as w,setPath as g,applyOpsToCtx as U}from"./applier.js";import{onSnapshot as d,onOps as f}from"./handlers.js";import{connectedToSymbols as T,Notifications as c}from"./SyncNotifications.js";const E=!1,A=()=>E?"http://localhost:8080":"https://api.symbols.app",C=e=>{const n=e&&e.editor&&e.editor.socketUrl||e&&e.settings&&e.settings.socketUrl;return typeof n=="string"&&n?{mode:"collab",baseUrl:n}:e&&e.editor&&e.editor.runtime==="runner"?{mode:"runner",baseUrl:null}:{mode:null,baseUrl:null}},D=async e=>{try{const n=e||A(),o=await s.fetch(`${n}/service-token`,{method:"GET"});let t;try{const r=await o.clone().json();if(r&&typeof r.token=="string")return r.token.trim();t=await o.text()}catch{t=await o.text()}return(t||"").replace(/\s+/gu,"")||void 0}catch(n){console.error("[sync] Failed to fetch service-token",n)}},u=(e,n,o,t)=>{e.on("snapshot",d(n,o,t)),e.on("ops",f(n,o,t)),e.on("clients",r=>{t.editor?.verbose&&T(r,n,o)}),e.on("disconnect",r=>{t.editor?.verbose&&console.info("[sync] disconnected",r)})},I=async(e,n,o,t)=>{const r=await D(t);if(!r)return console.warn("[sync] no service token \u2014 collab disabled"),null;const l=o.key;if(!l)return console.warn("[sync] ctx.key missing \u2014 collab cannot authenticate"),null;const k=o.editor?.projectId||null,i=a(t,{path:"/collab-socket",transports:["websocket"],auth:{token:r,projectId:k,projectKey:l,branch:"main",live:!0,clientType:"platform"},reconnectionAttempts:1/0,reconnectionDelayMax:4e3});return i.on("connect",()=>{o.editor?.verbose&&console.info("[sync] connected (collab)")}),u(i,e,n,o),i},j=(e,n,o)=>{const t=a({transports:["websocket","polling"],reconnectionAttempts:1/0,reconnectionDelayMax:4e3});return t.on("connect",()=>{o.editor?.verbose!==!1&&console.info("[sync] connected (runner)")}),u(t,e,n,o),t.on("reload",()=>{typeof s<"u"&&s.location&&s.location.reload()}),t},N=async(e,n,o)=>{const{mode:t,baseUrl:r}=C(o);return t?t==="collab"?I(e,n,o,r):t==="runner"?j(e,n,o):null:null},p={onInit:N},V={extends:[p,c]},y=e=>typeof e>"u",m=e=>!!(e?.editor?.socketUrl||e?.settings?.socketUrl),b=e=>e?.editor?.runtime==="runner",h=(e,n)=>{Array.isArray(e.extends)?e.extends.push(n):e.extends?e.extends=[e.extends,n]:e.extends=[n]},_={name:"sync",beforeCreate(e,n){const o=n&&n.editor;(o&&!y(o.liveSync)?o.liveSync:m(n)||b(n))&&(m(n)&&!b(n)&&!n?.key||h(e,p))}},K={name:"notifications",beforeCreate(e,n){if(!n)return;const o=y(n.notifications)?null:n.notifications,t=n.editor&&n.editor.verbose===!0;(o===!0||o!==!1&&t)&&h(e,c)}};export{V as DefaultSyncApp,v as FORBIDDEN_SEGMENTS,c as Notifications,p as SyncComponent,U as applyOpsToCtx,N as connectToSocket,w as deletePath,S as isSafePath,K as notificationsPlugin,f as onOps,d as onSnapshot,g as setPath,_ as syncPlugin};
|
package/package.json
CHANGED
|
@@ -1,45 +1,54 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbo.ls/sync",
|
|
3
|
-
"version": "3.14.
|
|
4
|
-
"main": "./index.
|
|
5
|
-
"module": "./index.js",
|
|
3
|
+
"version": "3.14.2",
|
|
4
|
+
"main": "./dist/cjs/index.cjs",
|
|
5
|
+
"module": "./dist/esm/index.js",
|
|
6
6
|
"gitHead": "9fc1b79b41cdc725ca6b24aec64920a599634681",
|
|
7
7
|
"files": [
|
|
8
8
|
"dist",
|
|
9
|
-
"*.
|
|
10
|
-
"
|
|
9
|
+
"*.md",
|
|
10
|
+
"LICENSE"
|
|
11
11
|
],
|
|
12
12
|
"repository": "https://github.com/symbo-ls/scratch",
|
|
13
13
|
"type": "module",
|
|
14
14
|
"license": "CC-BY-NC-4.0",
|
|
15
|
-
"unpkg": "./dist/iife/index.js",
|
|
16
|
-
"jsdelivr": "./dist/iife/index.js",
|
|
17
15
|
"exports": {
|
|
18
|
-
".":
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
".": {
|
|
17
|
+
"development": "./index.js",
|
|
18
|
+
"import": "./dist/esm/index.js",
|
|
19
|
+
"require": "./dist/cjs/index.cjs",
|
|
20
|
+
"default": "./dist/esm/index.js"
|
|
21
|
+
},
|
|
22
|
+
"./package.json": "./package.json",
|
|
23
|
+
"./applier": {
|
|
24
|
+
"development": "./applier.js",
|
|
25
|
+
"import": "./dist/esm/applier.js",
|
|
26
|
+
"require": "./dist/cjs/applier.cjs",
|
|
27
|
+
"default": "./dist/esm/applier.js"
|
|
28
|
+
},
|
|
29
|
+
"./handlers": {
|
|
30
|
+
"development": "./handlers.js",
|
|
31
|
+
"import": "./dist/esm/handlers.js",
|
|
32
|
+
"require": "./dist/cjs/handlers.cjs",
|
|
33
|
+
"default": "./dist/esm/handlers.js"
|
|
34
|
+
}
|
|
22
35
|
},
|
|
23
36
|
"source": "index.js",
|
|
24
37
|
"publishConfig": {
|
|
25
|
-
"access": "
|
|
38
|
+
"access": "restricted"
|
|
26
39
|
},
|
|
27
40
|
"scripts": {
|
|
28
|
-
"
|
|
29
|
-
"build:
|
|
30
|
-
"build
|
|
31
|
-
"
|
|
32
|
-
"build": "node ../../build/build.js",
|
|
33
|
-
"prepublish": "npm run build && npm run copy:package:cjs"
|
|
41
|
+
"build:esm": "esbuild $(find . -type f -name \"*.js\" -not -path \"*/dist/*\" -not -path \"*/node_modules/*\" -not -path \"*/__tests__/*\" -not -path \"*/test/*\" -not -name \"*.test.js\") --target=es2020 --format=esm --outbase=. --outdir=dist/esm --minify --log-level=warning",
|
|
42
|
+
"build:cjs": "esbuild $(find . -type f -name \"*.js\" -not -path \"*/dist/*\" -not -path \"*/node_modules/*\" -not -path \"*/__tests__/*\" -not -path \"*/test/*\" -not -name \"*.test.js\") --target=node18 --format=cjs --outbase=. --outdir=dist/cjs --out-extension:.js=.cjs --minify --log-level=warning",
|
|
43
|
+
"build": "rimraf dist && npm run build:esm && npm run build:cjs",
|
|
44
|
+
"prepublishOnly": "npm run build"
|
|
34
45
|
},
|
|
35
46
|
"dependencies": {
|
|
36
|
-
"@symbo.ls/router": "^3.14.
|
|
37
|
-
"@symbo.ls/utils": "^3.14.
|
|
38
|
-
"@symbo.ls/scratch": "^3.14.
|
|
39
|
-
"@symbo.ls/default-config": "^3.14.
|
|
47
|
+
"@symbo.ls/router": "^3.14.1",
|
|
48
|
+
"@symbo.ls/utils": "^3.14.2",
|
|
49
|
+
"@symbo.ls/scratch": "^3.14.2",
|
|
50
|
+
"@symbo.ls/default-config": "^3.14.2",
|
|
40
51
|
"chalk": "^5.4.1",
|
|
41
|
-
"express": "^4.21.2",
|
|
42
|
-
"socket.io": "^4.8.1",
|
|
43
52
|
"socket.io-client": "^4.8.1"
|
|
44
53
|
},
|
|
45
54
|
"devDependencies": {
|
package/Inspect.js
DELETED
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
import * as smblsUI from '@symbo.ls/default-config/components'
|
|
4
|
-
import { isObject, isString, isArray } from '@symbo.ls/utils'
|
|
5
|
-
import { send } from './client.js'
|
|
6
|
-
|
|
7
|
-
function returnStringExtend (_extends) {
|
|
8
|
-
return isString(_extends) ? _extends : isArray(_extends) ? _extends.find(extItem => isString(extItem)) : ''
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function getComponentKey (el) {
|
|
12
|
-
if (!el) return
|
|
13
|
-
const __componentKey = el.__ref.__componentKey
|
|
14
|
-
const extendsStr = el.extends && returnStringExtend(el.extends)
|
|
15
|
-
const parentChildExtendStr = el.parent && el.parent.childExtends && returnStringExtend(el.parent.childExtends)
|
|
16
|
-
return (__componentKey || extendsStr || parentChildExtendStr || '').split('_')[0].split('.')[0].split('+')[0]
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function findComponent (el) {
|
|
20
|
-
if (!el || !el.__ref) return
|
|
21
|
-
const { components, pages, editor } = el.context
|
|
22
|
-
const componentKey = getComponentKey(el)
|
|
23
|
-
if (editor && editor.onInitInspect) {
|
|
24
|
-
const initInspectReturns = editor.onInitInspect(componentKey, el, el.state)
|
|
25
|
-
if (!initInspectReturns) return findComponent(el.parent)
|
|
26
|
-
}
|
|
27
|
-
if (componentKey && (components[componentKey] || pages[componentKey])) {
|
|
28
|
-
return el
|
|
29
|
-
}
|
|
30
|
-
return findComponent(el.parent)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const onInspect = (app, state, ctx) => {
|
|
34
|
-
const windowOpts = ctx.window || window
|
|
35
|
-
windowOpts.onkeydown = (ev) => {
|
|
36
|
-
if (ev.altKey && ev.shiftKey) {
|
|
37
|
-
app.state.update({ debugging: true, preventSelect: true }, {
|
|
38
|
-
preventUpdate: true,
|
|
39
|
-
preventContentUpdate: true,
|
|
40
|
-
preventRecursive: true
|
|
41
|
-
})
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
windowOpts.onkeyup = (ev) => {
|
|
45
|
-
if (app.state.preventSelect && (!ev.altKey || !ev.shiftKey)) {
|
|
46
|
-
app.state.replace({ debugging: false, preventSelect: false }, {
|
|
47
|
-
preventUpdate: true,
|
|
48
|
-
preventContentUpdate: true,
|
|
49
|
-
preventRecursive: true
|
|
50
|
-
})
|
|
51
|
-
app.Inspector.state.update({ area: false })
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export const Inspect = {
|
|
57
|
-
'.preventSelect': { userSelect: 'none' },
|
|
58
|
-
'!preventSelect': { userSelect: 'auto' },
|
|
59
|
-
|
|
60
|
-
onInspect,
|
|
61
|
-
|
|
62
|
-
onMousemove: (ev, e, state) => {
|
|
63
|
-
const el = ev.target.ref
|
|
64
|
-
const component = findComponent(el)
|
|
65
|
-
const focusState = e.Inspector.state
|
|
66
|
-
|
|
67
|
-
if (!component || !state.debugging || !component.__ref) return focusState.update({ area: false })
|
|
68
|
-
|
|
69
|
-
const componentKey = getComponentKey(component)
|
|
70
|
-
const updateValue = (area) => {
|
|
71
|
-
focusState.update({ area, focusKey: componentKey })
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const update = () => {
|
|
75
|
-
if (ev.altKey && ev.shiftKey) {
|
|
76
|
-
const { x, y, width, height } = component.node.getBoundingClientRect()
|
|
77
|
-
const area = { x, y, width, height }
|
|
78
|
-
|
|
79
|
-
if (!focusState.area) return updateValue(area)
|
|
80
|
-
if (focusState.area.x !== area.x) updateValue(area)
|
|
81
|
-
} else if (focusState.area) {
|
|
82
|
-
focusState.update({ area: false })
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
window.requestAnimationFrame(() => {
|
|
87
|
-
update()
|
|
88
|
-
window.requestAnimationFrame(update)
|
|
89
|
-
})
|
|
90
|
-
},
|
|
91
|
-
|
|
92
|
-
onMousedown: (ev, elem, state) => {
|
|
93
|
-
if (!state.debugging) return
|
|
94
|
-
const el = ev.target.ref
|
|
95
|
-
const component = findComponent(el)
|
|
96
|
-
if (!component) return
|
|
97
|
-
const componentKey = getComponentKey(component)
|
|
98
|
-
if (!componentKey) return
|
|
99
|
-
|
|
100
|
-
const editor = el.context.editor
|
|
101
|
-
if (editor && editor.onInspect) {
|
|
102
|
-
return editor.onInspect(componentKey, el, el.state, { allowRouterWhileInspect: true })
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const data = JSON.stringify({
|
|
106
|
-
componentKey: `${componentKey}`
|
|
107
|
-
})
|
|
108
|
-
send.call(el.context.socket, 'route', data)
|
|
109
|
-
|
|
110
|
-
ev.preventDefault()
|
|
111
|
-
ev.stopPropagation()
|
|
112
|
-
return false
|
|
113
|
-
},
|
|
114
|
-
|
|
115
|
-
Inspector: {
|
|
116
|
-
state: {},
|
|
117
|
-
|
|
118
|
-
transition: 'all, defaultBezier, X',
|
|
119
|
-
position: 'fixed',
|
|
120
|
-
hide: (el, s) => !(s.area && s.parent.debugging),
|
|
121
|
-
style: {
|
|
122
|
-
boxShadow: '0 0 10px #3686F733, 0 0 0 3px #3686F766, 0 0 100vmax 100vmax #000A',
|
|
123
|
-
zIndex: '9999999',
|
|
124
|
-
borderRadius: '10px',
|
|
125
|
-
pointerEvents: 'none'
|
|
126
|
-
},
|
|
127
|
-
|
|
128
|
-
Span: {
|
|
129
|
-
position: 'absolute',
|
|
130
|
-
margin: 'A2 0',
|
|
131
|
-
fontSize: 'Z',
|
|
132
|
-
color: 'text',
|
|
133
|
-
// color: 'blue',
|
|
134
|
-
zIndex: '99999999',
|
|
135
|
-
transition: 'all, defaultBezier, X',
|
|
136
|
-
textDecoration: 'underline',
|
|
137
|
-
fontWeight: '500',
|
|
138
|
-
top: '100%',
|
|
139
|
-
style: {
|
|
140
|
-
boxShadow: '0 25px 10px 35px black',
|
|
141
|
-
textShadow: '0 0 10px black'
|
|
142
|
-
},
|
|
143
|
-
text: '{{ focusKey }}'
|
|
144
|
-
},
|
|
145
|
-
|
|
146
|
-
onInit: ({ context }) => {
|
|
147
|
-
const { components } = context
|
|
148
|
-
|
|
149
|
-
if (isObject(components)) {
|
|
150
|
-
const { Content, ...rest } = components
|
|
151
|
-
for (const key in rest) {
|
|
152
|
-
if (smblsUI[key]) continue
|
|
153
|
-
if (!rest[key].__ref) rest[key].__ref = {}
|
|
154
|
-
if (!rest[key].__ref.__componentKey) {
|
|
155
|
-
rest[key].__ref.__componentKey = key
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
},
|
|
160
|
-
onBeforeUpdate: (ch, el, s) => {
|
|
161
|
-
const { area } = s
|
|
162
|
-
const isDebugging = s.area && s.parent.debugging
|
|
163
|
-
|
|
164
|
-
let style
|
|
165
|
-
if (!isDebugging) {
|
|
166
|
-
style = 'display: none !important'
|
|
167
|
-
} else if (area) {
|
|
168
|
-
const { x, y, width, height } = area
|
|
169
|
-
// el.node.style = Object.stringify({
|
|
170
|
-
// top: y - 6 + 'px',
|
|
171
|
-
// left: x - 6 + 'px',
|
|
172
|
-
// width: width + 12 + 'px',
|
|
173
|
-
// height: height + 12 + 'px'
|
|
174
|
-
// })
|
|
175
|
-
style = `
|
|
176
|
-
display: block !important;
|
|
177
|
-
top: ${y - 6}px;
|
|
178
|
-
left: ${x - 6}px;
|
|
179
|
-
width: ${width + 12}px;
|
|
180
|
-
height: ${height + 12}px;
|
|
181
|
-
`
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
el.node.style = style
|
|
185
|
-
el.Span.node.innerText = s.focusKey
|
|
186
|
-
|
|
187
|
-
return false
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|