@vcp-dev/site-edit-bridge 0.10.15 → 0.10.17
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/auto-bootstrap.js +14 -14
- package/dist/client.d.ts +1 -0
- package/dist/client.js +1 -1
- package/dist/document-codec.d.ts +1 -0
- package/dist/document-codec.js +1 -1
- package/dist/index.js +16 -16
- package/dist/next-dev-server.js +3 -3
- package/dist/server.js +2 -2
- package/package.json +3 -3
package/dist/client.d.ts
CHANGED
|
@@ -84,6 +84,7 @@ export declare class SiteEditWebSocketClient implements SiteEditBridgeClient {
|
|
|
84
84
|
canMove: boolean;
|
|
85
85
|
canRemove: boolean;
|
|
86
86
|
};
|
|
87
|
+
parentKey?: string | null | undefined;
|
|
87
88
|
pageCompositionUnitKey?: string | undefined;
|
|
88
89
|
dynamicDataSummary?: {
|
|
89
90
|
hasDynamicData: boolean;
|
package/dist/client.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function T(n){if(!N(n))return n;let e=new Map,t=n.pageComposition.status==="supported"?n.pageComposition.placementUnitKeys:[],o=new Map(n.dynamicDataSummaries??[]),s=i=>{let r=e.get(i);if(r)return r;let c=n.nodes[i];if(!c)throw new Error(`Missing compact document node ${i}`);let[a,u]=c,d=n.tokens[u];if(typeof d!="string")throw new Error(`Missing compact document token ${u}`);let g=`${a===null?"":s(a)}${d}`;return e.set(i,g),g};return{siteId:n.siteId,snapshotId:n.snapshotId,composition:{...n.composition},routeId:n.composition.routeId,version:n.version,pageComposition:n.pageComposition,entries:n.entries.map((i,r)=>{let[c,a,u]=i,d=u===void 0?void 0:t[u];if(u!==void 0&&!d)throw new Error(`Missing page composition unit ${u}`);return{key:s(c),...d?{pageCompositionUnitKey:d}:{},operationSummary:v(a),...o.get(r)?{dynamicDataSummary:o.get(r)}:{}}})}}function v(n){return{canUpdateText:(n&1)!==0,canInsertChild:(n&2)!==0,canMove:(n&4)!==0,canRemove:(n&8)!==0}}function N(n){if(typeof n!="object"||n===null)return!1;let e=n;if(e.encoding!=="segment-trie-v1"||typeof e.siteId!="string"||typeof e.snapshotId!="string"||!K(e.composition)||typeof e.routeId!="string"||e.routeId!==e.composition.routeId||!Number.isInteger(e.version)||e.version<0||!x(e.pageComposition)||!Array.isArray(e.tokens)||!e.tokens.every(s=>typeof s=="string")||!Array.isArray(e.nodes)||!Array.isArray(e.entries))return!1;let t=e.nodes;if(!t.every((s,i)=>Array.isArray(s)&&s.length===2&&(s[0]===null||f(s[0])&&s[0]<i)&&f(s[1])&&s[1]<e.tokens.length)||!e.entries.every(s=>Array.isArray(s)&&(s.length===2||s.length===3)&&f(s[0])&&s[0]<t.length&&f(s[1])&&s[1]<=15&&(s.length===2||f(s[2]))))return!1;let o=e.dynamicDataSummaries;return o===void 0||Array.isArray(o)&&o.every(s=>Array.isArray(s)&&s.length===2&&f(s[0])&&s[0]<e.entries.length&&x(s[1]))}function x(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)}function K(n){return!x(n)||typeof n.routeId!="string"?!1:n.effectiveTemplateId===void 0||typeof n.effectiveTemplateId=="string"}function f(n){return typeof n=="number"&&Number.isInteger(n)&&n>=0}var p=class n{constructor(){}static parseMessage(e,t={}){let o=JSON.parse(e);if(!n.isMessage(o,t))throw new Error("Invalid site edit bridge message");return o}static stringifyMessage(e){return JSON.stringify(e)}static extractRequestInfo(e){if(h(e)&&h(e.payload)){let t=typeof e.payload.id=="string"?e.payload.id:"unknown",o=this.isRequestKind(e.payload.kind)?e.payload.kind:"get-document";return{id:t,kind:o}}return{id:"unknown",kind:"get-document"}}static isRequestKind(e){return e==="initialize-session"||e==="get-document"||e==="get-history-status"||e==="get-style-context"||e==="get-object-edit-context"||e==="get-class-name-source"||e==="get-source-tree"||e==="get-source-file"||e==="resolve-source-location"||e==="execute"||e==="undo"||e==="redo"}static isMessage(e,t={}){return!h(e)||typeof e.type!="string"?!1:e.type==="request"?B(e.payload,t):e.type==="response"||e.type==="error"?h(e.payload)&&typeof e.payload.id=="string":e.type==="event"?h(e.payload)&&h(e.payload.event):e.type==="auth"?h(e.payload)&&typeof e.payload.key=="string":e.type==="auth-ok"&&h(e.payload)&&e.payload.ok===!0}};function B(n,e){if(!h(n)||typeof n.id!="string"||!p.isRequestKind(n.kind))return!1;let t=w(n.composition);switch(n.kind){case"initialize-session":return t&&(n.mutationContext===void 0||b(n.mutationContext));case"get-document":case"get-style-context":return t;case"get-object-edit-context":return typeof n.key=="string"&&t&&j(n.selectionRef);case"get-class-name-source":case"resolve-source-location":return typeof n.key=="string"&&t;case"get-history-status":return t;case"get-source-tree":return t;case"get-source-file":return typeof n.path=="string"&&t;case"execute":return t&&F(n.request)&&(n.request.mutationContext===void 0||b(n.request.mutationContext))&&(e.validateOperationRequest?.(n.request)??!0);case"undo":case"redo":return t&&n.mutationContext===void 0||t&&b(n.mutationContext)}}function j(n){if(n===void 0)return!0;if(!h(n)||typeof n.key!="string"||n.key.length===0)return!1;let e=n.instanceIndex,t=n.instanceCount;return e!==void 0&&(typeof e!="number"||!Number.isInteger(e)||e<0)||t!==void 0&&(typeof t!="number"||!Number.isInteger(t)||t<=0)||typeof e=="number"&&typeof t=="number"&&e>=t?!1:Object.keys(n).every(o=>o==="key"||o==="instanceIndex"||o==="instanceCount")}function F(n){return h(n)&&typeof n.id=="string"&&typeof n.siteId=="string"&&typeof n.baseSnapshotId=="string"&&w(n.composition)&&typeof n.kind=="string"&&h(n.target)&&(n.target.kind!=="route"||w(n.target.composition))&&typeof n.documentVersion=="number"&&Number.isInteger(n.documentVersion)&&n.documentVersion>=0&&h(n.params)}function w(n){return h(n)&&typeof n.routeId=="string"&&n.routeId.length>0&&(n.templateId===void 0||typeof n.templateId=="string"&&n.templateId.length>0)&&Object.keys(n).every(e=>e==="routeId"||e==="templateId")}function h(n){return typeof n=="object"&&n!==null}function b(n){return h(n)&&typeof n.editingSessionId=="string"&&n.editingSessionId.length>0&&typeof n.lockId=="string"&&n.lockId.length>0&&typeof n.ownerId=="string"&&n.ownerId.length>0&&typeof n.leaseAssertion=="string"&&n.leaseAssertion.length>0}var U="vcp:designer:trace",P="designer_trace",R="__VCP_DESIGNER_TRACE__";var W=/(authorization|cookie|token|secret|providerTrace|headers?|sourceCode|rawSource|fullSource)/i;function $(n=globalThis){let e=n;try{if(e.localStorage?.getItem(U)==="1")return!0}catch{}try{let t=e.location?.search??"";return new URLSearchParams(t).get(P)==="1"}catch{return!1}}function l(n,e={},t=globalThis){if(!$(t))return;let o={type:n,timestamp:Date.now(),payload:z(e)},s=t,i=s[R]??[];i.push(o),i.length>1e3&&i.splice(0,i.length-1e3),s[R]=i;let r=t.console?.debug;o.payload.diagnosticOnly!==!0&&typeof r=="function"&&r.call(t.console,"[designer-trace]",o)}function z(n){return E(n,0)}function E(n,e){if(e>4)return"[truncated]";if(Array.isArray(n))return n.map(o=>E(o,e+1));if(!n||typeof n!="object")return n;let t={};for(let[o,s]of Object.entries(n)){if(W.test(o)){t[o]="[redacted]";continue}t[o]=E(s,e+1)}return t}var D=class{constructor(e){this.options=e,this.socket=null,this.connectPromise=null,this.connectAttempt=null,this.connectionState="idle",this.intentionalClose=!1,this.sequence=0,this.pending=new Map,this.listeners=new Set,this.connectionStatusListeners=new Set}connect(){return this.socket?.readyState===k&&this.connectionState==="open"?(this.setConnectionState("open"),Promise.resolve()):this.connectPromise?this.connectPromise:(this.intentionalClose=!1,this.setConnectionState("connecting"),this.connectPromise=new Promise((e,t)=>{let o;try{o=this.createSocket(this.options.url)}catch(c){let a=y(c,"WebSocket failed");this.socket=null,this.connectAttempt=null,this.connectPromise=null,this.setConnectionState("failed",a.message),t(a);return}let s={socket:o,settled:!1,reject:t};this.connectAttempt=s,this.socket=o;let i=()=>{this.socket!==o||this.connectAttempt!==s||(s.settled=!0,this.connectAttempt=null,this.connectPromise=null,this.setConnectionState("open"),e())},r=(c,a)=>{this.cleanupSocket(o,c,a)};o.onopen=()=>{if(!(this.socket!==o||this.connectAttempt!==s)){if(this.options.authKey){try{o.send(p.stringifyMessage({type:"auth",payload:{key:this.options.authKey}}))}catch(c){r(y(c,"WebSocket auth failed"),"failed")}return}i()}},o.onerror=c=>{if(this.socket!==o)return;let a=y(c,"WebSocket failed");r(a,"failed")},o.onmessage=c=>{if(this.socket===o){if(this.options.authKey&&this.connectAttempt===s&&!s.settled){this.handleAuthHandshakeMessage(c.data,o,s,()=>{i()});return}this.handleMessage(c.data)}},o.onclose=c=>{if(this.socket!==o)return;let a=this.intentionalClose,u=new Error(V(c,{intentional:a}));r(u,a?"closed":"failed")}}),this.connectPromise)}disconnect(){this.intentionalClose=!0,this.setConnectionState("closing");let e=this.socket;if(!e){this.rejectAll(new Error("WebSocket disconnected")),this.connectAttempt=null,this.connectPromise=null,this.setConnectionState("closed");return}this.cleanupSocket(e,new Error("WebSocket disconnected"),"closed")}getConnectionState(){return this.connectionState}subscribeConnectionStatus(e){return this.connectionStatusListeners.add(e),e({state:this.connectionState}),()=>{this.connectionStatusListeners.delete(e)}}getDocument(e){let t=this.selector(e);return this.request("get-document",{composition:t})}async initializeSession(e){let t=this.selector(e.composition);return await this.request("initialize-session",{composition:t,...e.mutationContext?{mutationContext:e.mutationContext}:{}})}getHistoryStatus(e){return this.request("get-history-status",{composition:this.selector(e)})}getStyleContext(e){let t=this.selector(e);return this.request("get-style-context",{composition:t})}getObjectEditContext(e,t,o){let s=this.selector(t);return this.request("get-object-edit-context",{key:e,composition:s,...o?{selectionRef:o}:{}})}getClassNameSource(e,t){let o=this.selector(t);return this.request("get-class-name-source",{key:e,composition:o})}getSourceTree(e){return this.request("get-source-tree",{composition:this.selector(e)})}getSourceFile(e){return this.request("get-source-file",{path:e.path,composition:this.selector(e.composition)})}resolveSourceLocation(e){return this.request("resolve-source-location",{key:e.key,composition:this.selector(e.composition)})}execute(e,t){let o=S(e),s={...e,composition:m(o)};return this.request("execute",{request:s})}undo(e,t){return this.request("undo",{composition:this.selector(e)})}redo(e,t){return this.request("redo",{composition:this.selector(e)})}subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}selector(e){return m(e)}request(e,t){let o=this.socket;if(!o||o.readyState!==k||this.connectionState!=="open")return Promise.reject(new Error(`WebSocket is not open (state: ${this.connectionState}, readyState: ${o?.readyState??"none"})`));let s=`${e}-${this.sequence+=1}`,i=Z(s,e,t);return l("bridge.request",{id:s,kind:e,routeId:typeof t.routeId=="string"?t.routeId:null,key:typeof t.key=="string"?t.key:null,operationKind:_(t.request,"kind"),documentVersion:_(t.request,"documentVersion")}),new Promise((r,c)=>{let a=this.resolveRequestTimeoutMs(e),u=a>0?setTimeout(()=>{let d=this.pending.get(s);d&&(this.pending.delete(s),l("bridge.response",{id:s,kind:e,ok:!1,timedOut:!0}),d.reject(new Error(`Bridge request timed out after ${a}ms: ${e}`)))},a):null;u?.unref?.(),this.pending.set(s,{kind:e,timeout:u,resolve:d=>r(d),reject:c});try{o.send(p.stringifyMessage(i))}catch(d){let g=y(d,"WebSocket send failed");this.clearPendingRequest(s),c(g),this.cleanupSocket(o,g,"failed")}})}handleAuthHandshakeMessage(e,t,o,s){try{if(p.parseMessage(e).type==="auth-ok"){s();return}throw new Error("Bridge authentication failed")}catch(i){let r=y(i,"Bridge authentication failed");this.connectAttempt===o&&this.cleanupSocket(t,r,"failed")}}handleMessage(e){let t=p.parseMessage(e);if(t.type==="event"){for(let s of this.listeners)s(t.payload.event);return}if(t.type!=="response"&&t.type!=="error")return;let o=this.pending.get(t.payload.id);if(o){if(this.clearPendingRequest(t.payload.id),t.type==="error"){l("bridge.response",{id:t.payload.id,kind:o.kind,ok:!1});let s=new Error(t.payload.message);t.payload.code&&(s.code=t.payload.code),o.reject(s);return}l("bridge.response",{id:t.payload.id,kind:o.kind,ok:!0,resultVersion:Q(t.payload.result)}),o.resolve(o.kind==="get-document"?{...t.payload.result,data:A(t.payload.result.data,t.payload.result.composition)}:o.kind==="initialize-session"?H(t.payload.result):t.payload.result)}}rejectAll(e){for(let[t,o]of[...this.pending])this.clearPendingRequest(t),o.reject(e)}clearPendingRequest(e){let t=this.pending.get(e);t&&(t.timeout&&clearTimeout(t.timeout),this.pending.delete(e))}resolveRequestTimeoutMs(e){let t=this.options.requestTimeoutMsByKind?.[e];return typeof t=="number"?Math.max(0,t):typeof this.options.requestTimeoutMs=="number"?Math.max(0,this.options.requestTimeoutMs):G[e]??J}cleanupSocket(e,t,o){if(this.socket===e&&(this.socket=null),this.connectAttempt?.socket===e){let s=this.connectAttempt;this.connectAttempt=null,s.settled||(s.settled=!0,s.reject(t))}this.connectPromise=null,this.rejectAll(t),this.setConnectionState(o,t.message),e.onopen=null,e.onmessage=null,e.onerror=null,e.onclose=null;try{(e.readyState===L||e.readyState===k)&&e.close()}catch{}}setConnectionState(e,t){if(this.connectionState===e&&!t)return;this.connectionState=e;let o={state:e,...t?{message:t}:{}};this.options.onConnectionStatus?.(o);for(let s of this.connectionStatusListeners)s(o)}createSocket(e){if(this.options.createSocket)return this.options.createSocket(e);if(typeof WebSocket>"u")throw new Error("Site edit preview bridge requires WebSocket");return new WebSocket(e)}},L=0,k=1,J=15e3,G={"get-source-tree":1e4,"get-source-file":1e4,"resolve-source-location":1e4,execute:6e4,undo:2e4,redo:2e4};function y(n,e){return n instanceof Error?n:new Error(e)}function V(n,e){return e.intentional?"WebSocket disconnected":n?.code===1008?n.reason?`Bridge session authentication failed: ${n.reason}`:"Bridge session authentication failed":n?.reason?`WebSocket closed: ${n.reason}`:typeof n?.code=="number"&&n.code!==1005?`WebSocket closed with code ${n.code}`:"WebSocket closed"}function _(n,e){if(!n||typeof n!="object")return null;let o=n[e];return typeof o=="string"||typeof o=="number"?o:null}function Q(n){if(!n||typeof n!="object")return null;let e=n,t=e.data?.resultVersion??e.data?.version??null;return typeof t=="number"?t:null}function ce(n){let e="composition"in n?m(n.composition):m({routeId:n.routeId});return new q({composition:e,initialDocument:n.initialDocument,client:n.client})}var q=class{constructor(e){this.params=e,this.serverConfirmedComposition=null,this.refreshInFlight=null,this.objectGeneration=0,this.styleGeneration=0,this.editContextCache=new Map,this.editContextInFlight=new Map,this.classNameSourceCache=new Map,this.classNameSourceInFlight=new Map,this.styleContextCache=new Map,this.styleContextInFlight=new Map,this.snapshotIdentityStale=!1,this.composition=m(e.composition);let t=e.initialDocument.composition.effectiveTemplateId;if(t!==void 0&&(this.composition.templateId===void 0||this.composition.templateId!==t))throw new Error(`Site edit bridge requires a matching templateId for initial document composition ${JSON.stringify(e.initialDocument.composition)}`);this.currentDocument=e.initialDocument,this.observedDocumentVersion=e.initialDocument.version,this.sessionInitialized=!O(e.initialDocument),this.activeCompositionContext=this.sessionInitialized?{...e.initialDocument.composition}:null}async getDocument(e){this.requireBoundComposition(e);let t=O(this.currentDocument)||this.snapshotIdentityStale;return(t||this.currentDocument.version<this.observedDocumentVersion)&&(this.currentDocument=await this.refreshSnapshot(t?void 0:this.observedDocumentVersion,"get-document"),this.snapshotIdentityStale=!1,this.sessionInitialized=!0),{ok:!0,data:this.currentDocument}}async initializeSession(e){let t=this.requireBoundComposition(e.composition);if(!this.params.client.initializeSession)throw new Error("Site edit bridge client does not support initialize-session");let o=await this.params.client.initializeSession({...e,composition:t});return this.currentDocument=o.data.document,this.observedDocumentVersion=o.data.document.version,this.activeCompositionContext={...o.composition},this.rememberServerConfirmedComposition(o.composition),this.sessionInitialized=!0,this.clearObjectCaches(),o}async getHistoryStatus(e){return this.params.client.getHistoryStatus(this.requireBoundComposition(e))}async getStyleContext(e){let t=this.requireBoundComposition(e),o=C(t),s=this.styleContextCache.get(o);if(s?.generation===this.styleGeneration)return{ok:!0,data:s.value};let i=this.styleContextInFlight.get(o);if(i?.generation===this.styleGeneration)return i.request;let r=this.styleGeneration,c=this.params.client.getStyleContext(t).then(a=>(this.styleGeneration===r&&this.styleContextCache.set(o,{generation:r,value:a.data}),a)).finally(()=>{this.styleContextInFlight.get(o)?.request===c&&this.styleContextInFlight.delete(o)});return this.styleContextInFlight.set(o,{generation:r,request:c}),c}async ensureDocumentVersion(e,t){this.requireBoundComposition(e);let o=await this.refreshSnapshot(t,"ensure-version");if(o.version<t)throw new Error(`Document refresh returned version ${o.version}, expected at least ${t}`);return{ok:!0,data:o}}async acknowledgeDocumentVersion(e,t){if(this.requireBoundComposition(e),t>this.currentDocument.version){if(this.currentDocument.pageComposition.status==="supported"){let o=await this.refreshSnapshot(t,"ensure-version");if(o.version<t)throw new Error(`Document refresh returned version ${o.version}, expected at least ${t}`);return{ok:!0,data:o}}this.currentDocument={...this.currentDocument,version:t},this.clearObjectCaches({preserveStyleContext:!0})}return this.observedDocumentVersion=Math.max(this.observedDocumentVersion,t),{ok:!0,data:this.currentDocument}}async getObjectEditContext(e,t,o){let s=this.requireBoundComposition(t),i=this.objectCacheKey(e,s,o),r=this.editContextCache.get(i);if(r)return{ok:!0,data:r};let c=this.editContextInFlight.get(i);if(c)return c;let a=this.objectGeneration,u=this.params.client.getObjectEditContext(e,s,...o?[o]:[]).then(d=>(this.objectGeneration===a&&this.editContextCache.set(i,d.data),d)).finally(()=>{this.editContextInFlight.get(i)===u&&this.editContextInFlight.delete(i)});return this.editContextInFlight.set(i,u),u}async getClassNameSource(e,t){let o=this.requireBoundComposition(t),s=this.objectCacheKey(e,o),i=this.classNameSourceCache.get(s);if(i)return i;let r=this.classNameSourceInFlight.get(s);if(r)return r;let c=this.objectGeneration,a=this.params.client.getClassNameSource(e,o).then(u=>(this.objectGeneration===c&&this.classNameSourceCache.set(s,u),u)).finally(()=>{this.classNameSourceInFlight.get(s)===a&&this.classNameSourceInFlight.delete(s)});return this.classNameSourceInFlight.set(s,a),a}async getSourceTree(e){return this.params.client.getSourceTree(this.requireBoundComposition(e))}async getSourceFile(e){return this.params.client.getSourceFile({path:e.path,composition:this.requireBoundComposition(e.composition)})}async resolveSourceLocation(e){return this.params.client.resolveSourceLocation({key:e.key,composition:this.requireBoundComposition(e.composition)})}async execute(e,t){let o=S(e);o&&this.composition.templateId!==void 0&&this.requireBoundComposition(o);let s={...e,composition:o??this.composition};return this.params.client.execute(s)}async undo(e,t){return this.params.client.undo(this.requireBoundComposition(e))}async redo(e,t){return this.params.client.redo(this.requireBoundComposition(e))}subscribe(e){return this.params.client.subscribe(t=>{if(t.type==="site-edit.snapshot.changed"&&this.sessionInitialized&&this.isActiveComposition(t.composition)){this.snapshotIdentityStale=!0,this.clearObjectCaches(),e(t);return}if(t.type==="site-edit.document.changed"&&this.sessionInitialized&&this.isActiveComposition(t.composition)){this.observedDocumentVersion=Math.max(this.observedDocumentVersion,t.version),t.version>this.currentDocument.version&&this.clearObjectCaches(),e(t);return}e(t)})}async refreshSnapshot(e,t="ensure-version"){if(typeof e=="number"&&this.currentDocument.version>=e)return l("bridge.document-refresh",{composition:this.composition,routeId:this.composition.routeId,minVersion:e,currentVersion:this.currentDocument.version,deduped:!0,skipped:!0,source:t}),this.currentDocument;let o=C(this.composition),s=this.refreshInFlight;if(s?.compositionKey===o){l("bridge.document-refresh",{composition:this.composition,routeId:this.composition.routeId,minVersion:e,currentVersion:this.currentDocument.version,deduped:!0,source:t});let r=await s.request;if(typeof e!="number"||r.version>=e||this.currentDocument.version>=e)return this.currentDocument}l("bridge.document-refresh",{composition:this.composition,routeId:this.composition.routeId,minVersion:e,currentVersion:this.currentDocument.version,deduped:!1,source:t});let i=this.params.client.getDocument(this.composition).then(r=>(this.currentDocument=r.data,this.activeCompositionContext={...r.data.composition},this.rememberServerConfirmedComposition(r.data.composition),this.observedDocumentVersion=Math.max(this.observedDocumentVersion,r.data.version),this.clearObjectCaches(),this.currentDocument));this.refreshInFlight={compositionKey:o,request:i};try{return await i}finally{this.refreshInFlight?.request===i&&(this.refreshInFlight=null)}}clearObjectCaches(e){this.objectGeneration+=1,this.editContextCache.clear(),this.editContextInFlight.clear(),this.classNameSourceCache.clear(),this.classNameSourceInFlight.clear(),!e?.preserveStyleContext&&(this.styleGeneration+=1,this.styleContextCache.clear(),this.styleContextInFlight.clear())}objectCacheKey(e,t,o){return`${C(t)}\0${e}\0${Y(o)}`}rememberServerConfirmedComposition(e){!e||typeof e.routeId!="string"||(this.serverConfirmedComposition={...e})}isAcceptedComposition(e){if(C(e)===C(this.composition))return!0;let t=this.serverConfirmedComposition;return t!==null&&I(t)===I(M(e))}requireBoundComposition(e){let t=e===void 0?this.composition:m(e);if(!this.isAcceptedComposition(t))throw new Error(`Site edit bridge is bound to composition ${JSON.stringify(this.composition)}, received ${JSON.stringify(t)}`);return m(t)}isActiveComposition(e){let t=this.activeCompositionContext??M(this.composition);return I(e)===I(t)}};function O(n){return n.version===0&&n.entries.length===0}function H(n){let e=n;return{...e,data:{...e.data,document:A(e.data.document,e.composition)}}}function A(n,e){let t=n,o=T(t.routeId?t:{...t,routeId:e?.routeId??t.composition?.routeId});return e?{...o,composition:e}:o}function m(n){if(n&&typeof n=="object"&&typeof n.routeId=="string"){let e="effectiveTemplateId"in n?n.effectiveTemplateId:"templateId"in n?n.templateId:void 0;return{routeId:n.routeId,...typeof e=="string"?{templateId:e}:{}}}throw new Error("SITE_EDIT_COMPOSITION_SESSION_REQUIRED: a composition selector is required")}function C(n){return JSON.stringify([n.routeId,n.templateId??null])}function Y(n){return n?JSON.stringify([n.key,n.instanceIndex??null,n.instanceCount??null]):""}function I(n){return JSON.stringify([n.routeId,n.effectiveTemplateId??null])}function M(n){return{routeId:n.routeId,...n.templateId?{effectiveTemplateId:n.templateId}:{}}}function S(n){if(n&&typeof n=="object"){let e=n;if(e.composition&&typeof e.composition=="object"){let t=e.composition;if(typeof t.routeId=="string")return{routeId:t.routeId,...typeof t.templateId=="string"?{templateId:t.templateId}:{}}}}}function Z(n,e,t){let o=m(e==="execute"?S(t.request):t.composition),s={id:n,kind:e,composition:o};switch(e){case"initialize-session":case"get-document":case"get-history-status":case"get-style-context":case"get-source-tree":case"undo":case"redo":return{type:"request",payload:{...s,...t.mutationContext?{mutationContext:t.mutationContext}:{}}};case"get-object-edit-context":return{type:"request",payload:{...s,key:String(t.key),...t.selectionRef?{selectionRef:t.selectionRef}:{}}};case"get-class-name-source":case"resolve-source-location":return{type:"request",payload:{...s,key:String(t.key)}};case"get-source-file":return{type:"request",payload:{...s,path:String(t.path)}};case"execute":return{type:"request",payload:{...s,request:{...t.request,composition:S(t.request)??o}}}}}export{D as SiteEditWebSocketClient,ce as createSiteEditBridge};
|
|
1
|
+
function T(n){if(!N(n)){if(n.encoding==="segment-trie-v1")throw new Error("Invalid compact render document");return n}let e=new Map,t=n.pageComposition.status==="supported"?n.pageComposition.placementUnitKeys:[],o=new Map(n.dynamicDataSummaries??[]),s=i=>{let r=e.get(i);if(r)return r;let c=n.nodes[i];if(!c)throw new Error(`Missing compact document node ${i}`);let[a,u]=c,d=n.tokens[u];if(typeof d!="string")throw new Error(`Missing compact document token ${u}`);let p=`${a===null?"":s(a)}${d}`;return e.set(i,p),p};return{siteId:n.siteId,snapshotId:n.snapshotId,composition:{...n.composition},routeId:n.composition.routeId,version:n.version,pageComposition:n.pageComposition,entries:n.entries.map((i,r)=>{let[c,a,u]=i,d=u===void 0?void 0:t[u];if(u!==void 0&&!d)throw new Error(`Missing page composition unit ${u}`);let p=n.entryParentNodeIds?.[r];return{key:s(c),...n.entryParentNodeIds?{parentKey:p===null?null:s(p)}:{},...d?{pageCompositionUnitKey:d}:{},operationSummary:v(a),...o.get(r)?{dynamicDataSummary:o.get(r)}:{}}})}}function v(n){return{canUpdateText:(n&1)!==0,canInsertChild:(n&2)!==0,canMove:(n&4)!==0,canRemove:(n&8)!==0}}function N(n){if(typeof n!="object"||n===null)return!1;let e=n;if(e.encoding!=="segment-trie-v1"||typeof e.siteId!="string"||typeof e.snapshotId!="string"||!K(e.composition)||typeof e.routeId!="string"||e.routeId!==e.composition.routeId||!Number.isInteger(e.version)||e.version<0||!x(e.pageComposition)||!Array.isArray(e.tokens)||!e.tokens.every(i=>typeof i=="string")||!Array.isArray(e.nodes)||!Array.isArray(e.entries))return!1;let t=e.nodes;if(!t.every((i,r)=>Array.isArray(i)&&i.length===2&&(i[0]===null||g(i[0])&&i[0]<r)&&g(i[1])&&i[1]<e.tokens.length)||!e.entries.every(i=>Array.isArray(i)&&(i.length===2||i.length===3)&&g(i[0])&&i[0]<t.length&&g(i[1])&&i[1]<=15&&(i.length===2||g(i[2]))))return!1;let o=e.entryParentNodeIds;if(o!==void 0&&(!Array.isArray(o)||o.length!==e.entries.length||!o.every(i=>i===null||g(i)&&i<t.length)))return!1;let s=e.dynamicDataSummaries;return s===void 0||Array.isArray(s)&&s.every(i=>Array.isArray(i)&&i.length===2&&g(i[0])&&i[0]<e.entries.length&&x(i[1]))}function x(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)}function K(n){return!x(n)||typeof n.routeId!="string"?!1:n.effectiveTemplateId===void 0||typeof n.effectiveTemplateId=="string"}function g(n){return typeof n=="number"&&Number.isInteger(n)&&n>=0}var l=class n{constructor(){}static parseMessage(e,t={}){let o=JSON.parse(e);if(!n.isMessage(o,t))throw new Error("Invalid site edit bridge message");return o}static stringifyMessage(e){return JSON.stringify(e)}static extractRequestInfo(e){if(h(e)&&h(e.payload)){let t=typeof e.payload.id=="string"?e.payload.id:"unknown",o=this.isRequestKind(e.payload.kind)?e.payload.kind:"get-document";return{id:t,kind:o}}return{id:"unknown",kind:"get-document"}}static isRequestKind(e){return e==="initialize-session"||e==="get-document"||e==="get-history-status"||e==="get-style-context"||e==="get-object-edit-context"||e==="get-class-name-source"||e==="get-source-tree"||e==="get-source-file"||e==="resolve-source-location"||e==="execute"||e==="undo"||e==="redo"}static isMessage(e,t={}){return!h(e)||typeof e.type!="string"?!1:e.type==="request"?B(e.payload,t):e.type==="response"||e.type==="error"?h(e.payload)&&typeof e.payload.id=="string":e.type==="event"?h(e.payload)&&h(e.payload.event):e.type==="auth"?h(e.payload)&&typeof e.payload.key=="string":e.type==="auth-ok"&&h(e.payload)&&e.payload.ok===!0}};function B(n,e){if(!h(n)||typeof n.id!="string"||!l.isRequestKind(n.kind))return!1;let t=w(n.composition);switch(n.kind){case"initialize-session":return t&&(n.mutationContext===void 0||b(n.mutationContext));case"get-document":case"get-style-context":return t;case"get-object-edit-context":return typeof n.key=="string"&&t&&j(n.selectionRef);case"get-class-name-source":case"resolve-source-location":return typeof n.key=="string"&&t;case"get-history-status":return t;case"get-source-tree":return t;case"get-source-file":return typeof n.path=="string"&&t;case"execute":return t&&F(n.request)&&(n.request.mutationContext===void 0||b(n.request.mutationContext))&&(e.validateOperationRequest?.(n.request)??!0);case"undo":case"redo":return t&&n.mutationContext===void 0||t&&b(n.mutationContext)}}function j(n){if(n===void 0)return!0;if(!h(n)||typeof n.key!="string"||n.key.length===0)return!1;let e=n.instanceIndex,t=n.instanceCount;return e!==void 0&&(typeof e!="number"||!Number.isInteger(e)||e<0)||t!==void 0&&(typeof t!="number"||!Number.isInteger(t)||t<=0)||typeof e=="number"&&typeof t=="number"&&e>=t?!1:Object.keys(n).every(o=>o==="key"||o==="instanceIndex"||o==="instanceCount")}function F(n){return h(n)&&typeof n.id=="string"&&typeof n.siteId=="string"&&typeof n.baseSnapshotId=="string"&&w(n.composition)&&typeof n.kind=="string"&&h(n.target)&&(n.target.kind!=="route"||w(n.target.composition))&&typeof n.documentVersion=="number"&&Number.isInteger(n.documentVersion)&&n.documentVersion>=0&&h(n.params)}function w(n){return h(n)&&typeof n.routeId=="string"&&n.routeId.length>0&&(n.templateId===void 0||typeof n.templateId=="string"&&n.templateId.length>0)&&Object.keys(n).every(e=>e==="routeId"||e==="templateId")}function h(n){return typeof n=="object"&&n!==null}function b(n){return h(n)&&typeof n.editingSessionId=="string"&&n.editingSessionId.length>0&&typeof n.lockId=="string"&&n.lockId.length>0&&typeof n.ownerId=="string"&&n.ownerId.length>0&&typeof n.leaseAssertion=="string"&&n.leaseAssertion.length>0}var P="vcp:designer:trace",U="designer_trace",R="__VCP_DESIGNER_TRACE__";var W=/(authorization|cookie|token|secret|providerTrace|headers?|sourceCode|rawSource|fullSource)/i;function $(n=globalThis){let e=n;try{if(e.localStorage?.getItem(P)==="1")return!0}catch{}try{let t=e.location?.search??"";return new URLSearchParams(t).get(U)==="1"}catch{return!1}}function m(n,e={},t=globalThis){if(!$(t))return;let o={type:n,timestamp:Date.now(),payload:z(e)},s=t,i=s[R]??[];i.push(o),i.length>1e3&&i.splice(0,i.length-1e3),s[R]=i;let r=t.console?.debug;o.payload.diagnosticOnly!==!0&&typeof r=="function"&&r.call(t.console,"[designer-trace]",o)}function z(n){return E(n,0)}function E(n,e){if(e>4)return"[truncated]";if(Array.isArray(n))return n.map(o=>E(o,e+1));if(!n||typeof n!="object")return n;let t={};for(let[o,s]of Object.entries(n)){if(W.test(o)){t[o]="[redacted]";continue}t[o]=E(s,e+1)}return t}var D=class{constructor(e){this.options=e,this.socket=null,this.connectPromise=null,this.connectAttempt=null,this.connectionState="idle",this.intentionalClose=!1,this.sequence=0,this.pending=new Map,this.listeners=new Set,this.connectionStatusListeners=new Set}connect(){return this.socket?.readyState===k&&this.connectionState==="open"?(this.setConnectionState("open"),Promise.resolve()):this.connectPromise?this.connectPromise:(this.intentionalClose=!1,this.setConnectionState("connecting"),this.connectPromise=new Promise((e,t)=>{let o;try{o=this.createSocket(this.options.url)}catch(c){let a=y(c,"WebSocket failed");this.socket=null,this.connectAttempt=null,this.connectPromise=null,this.setConnectionState("failed",a.message),t(a);return}let s={socket:o,settled:!1,reject:t};this.connectAttempt=s,this.socket=o;let i=()=>{this.socket!==o||this.connectAttempt!==s||(s.settled=!0,this.connectAttempt=null,this.connectPromise=null,this.setConnectionState("open"),e())},r=(c,a)=>{this.cleanupSocket(o,c,a)};o.onopen=()=>{if(!(this.socket!==o||this.connectAttempt!==s)){if(this.options.authKey){try{o.send(l.stringifyMessage({type:"auth",payload:{key:this.options.authKey}}))}catch(c){r(y(c,"WebSocket auth failed"),"failed")}return}i()}},o.onerror=c=>{if(this.socket!==o)return;let a=y(c,"WebSocket failed");r(a,"failed")},o.onmessage=c=>{if(this.socket===o){if(this.options.authKey&&this.connectAttempt===s&&!s.settled){this.handleAuthHandshakeMessage(c.data,o,s,()=>{i()});return}this.handleMessage(c.data)}},o.onclose=c=>{if(this.socket!==o)return;let a=this.intentionalClose,u=new Error(V(c,{intentional:a}));r(u,a?"closed":"failed")}}),this.connectPromise)}disconnect(){this.intentionalClose=!0,this.setConnectionState("closing");let e=this.socket;if(!e){this.rejectAll(new Error("WebSocket disconnected")),this.connectAttempt=null,this.connectPromise=null,this.setConnectionState("closed");return}this.cleanupSocket(e,new Error("WebSocket disconnected"),"closed")}getConnectionState(){return this.connectionState}subscribeConnectionStatus(e){return this.connectionStatusListeners.add(e),e({state:this.connectionState}),()=>{this.connectionStatusListeners.delete(e)}}getDocument(e){let t=this.selector(e);return this.request("get-document",{composition:t})}async initializeSession(e){let t=this.selector(e.composition);return await this.request("initialize-session",{composition:t,...e.mutationContext?{mutationContext:e.mutationContext}:{}})}getHistoryStatus(e){return this.request("get-history-status",{composition:this.selector(e)})}getStyleContext(e){let t=this.selector(e);return this.request("get-style-context",{composition:t})}getObjectEditContext(e,t,o){let s=this.selector(t);return this.request("get-object-edit-context",{key:e,composition:s,...o?{selectionRef:o}:{}})}getClassNameSource(e,t){let o=this.selector(t);return this.request("get-class-name-source",{key:e,composition:o})}getSourceTree(e){return this.request("get-source-tree",{composition:this.selector(e)})}getSourceFile(e){return this.request("get-source-file",{path:e.path,composition:this.selector(e.composition)})}resolveSourceLocation(e){return this.request("resolve-source-location",{key:e.key,composition:this.selector(e.composition)})}execute(e,t){let o=S(e),s={...e,composition:f(o)};return this.request("execute",{request:s})}undo(e,t){return this.request("undo",{composition:this.selector(e)})}redo(e,t){return this.request("redo",{composition:this.selector(e)})}subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}selector(e){return f(e)}request(e,t){let o=this.socket;if(!o||o.readyState!==k||this.connectionState!=="open")return Promise.reject(new Error(`WebSocket is not open (state: ${this.connectionState}, readyState: ${o?.readyState??"none"})`));let s=`${e}-${this.sequence+=1}`,i=Z(s,e,t);return m("bridge.request",{id:s,kind:e,routeId:typeof t.routeId=="string"?t.routeId:null,key:typeof t.key=="string"?t.key:null,operationKind:_(t.request,"kind"),documentVersion:_(t.request,"documentVersion")}),new Promise((r,c)=>{let a=this.resolveRequestTimeoutMs(e),u=a>0?setTimeout(()=>{let d=this.pending.get(s);d&&(this.pending.delete(s),m("bridge.response",{id:s,kind:e,ok:!1,timedOut:!0}),d.reject(new Error(`Bridge request timed out after ${a}ms: ${e}`)))},a):null;u?.unref?.(),this.pending.set(s,{kind:e,timeout:u,resolve:d=>r(d),reject:c});try{o.send(l.stringifyMessage(i))}catch(d){let p=y(d,"WebSocket send failed");this.clearPendingRequest(s),c(p),this.cleanupSocket(o,p,"failed")}})}handleAuthHandshakeMessage(e,t,o,s){try{if(l.parseMessage(e).type==="auth-ok"){s();return}throw new Error("Bridge authentication failed")}catch(i){let r=y(i,"Bridge authentication failed");this.connectAttempt===o&&this.cleanupSocket(t,r,"failed")}}handleMessage(e){let t=l.parseMessage(e);if(t.type==="event"){for(let s of this.listeners)s(t.payload.event);return}if(t.type!=="response"&&t.type!=="error")return;let o=this.pending.get(t.payload.id);if(o){if(this.clearPendingRequest(t.payload.id),t.type==="error"){m("bridge.response",{id:t.payload.id,kind:o.kind,ok:!1});let s=new Error(t.payload.message);t.payload.code&&(s.code=t.payload.code),o.reject(s);return}m("bridge.response",{id:t.payload.id,kind:o.kind,ok:!0,resultVersion:Q(t.payload.result)}),o.resolve(o.kind==="get-document"?{...t.payload.result,data:M(t.payload.result.data,t.payload.result.composition)}:o.kind==="initialize-session"?H(t.payload.result):t.payload.result)}}rejectAll(e){for(let[t,o]of[...this.pending])this.clearPendingRequest(t),o.reject(e)}clearPendingRequest(e){let t=this.pending.get(e);t&&(t.timeout&&clearTimeout(t.timeout),this.pending.delete(e))}resolveRequestTimeoutMs(e){let t=this.options.requestTimeoutMsByKind?.[e];return typeof t=="number"?Math.max(0,t):typeof this.options.requestTimeoutMs=="number"?Math.max(0,this.options.requestTimeoutMs):G[e]??J}cleanupSocket(e,t,o){if(this.socket===e&&(this.socket=null),this.connectAttempt?.socket===e){let s=this.connectAttempt;this.connectAttempt=null,s.settled||(s.settled=!0,s.reject(t))}this.connectPromise=null,this.rejectAll(t),this.setConnectionState(o,t.message),e.onopen=null,e.onmessage=null,e.onerror=null,e.onclose=null;try{(e.readyState===L||e.readyState===k)&&e.close()}catch{}}setConnectionState(e,t){if(this.connectionState===e&&!t)return;this.connectionState=e;let o={state:e,...t?{message:t}:{}};this.options.onConnectionStatus?.(o);for(let s of this.connectionStatusListeners)s(o)}createSocket(e){if(this.options.createSocket)return this.options.createSocket(e);if(typeof WebSocket>"u")throw new Error("Site edit preview bridge requires WebSocket");return new WebSocket(e)}},L=0,k=1,J=15e3,G={"get-source-tree":1e4,"get-source-file":1e4,"resolve-source-location":1e4,execute:6e4,undo:2e4,redo:2e4};function y(n,e){return n instanceof Error?n:new Error(e)}function V(n,e){return e.intentional?"WebSocket disconnected":n?.code===1008?n.reason?`Bridge session authentication failed: ${n.reason}`:"Bridge session authentication failed":n?.reason?`WebSocket closed: ${n.reason}`:typeof n?.code=="number"&&n.code!==1005?`WebSocket closed with code ${n.code}`:"WebSocket closed"}function _(n,e){if(!n||typeof n!="object")return null;let o=n[e];return typeof o=="string"||typeof o=="number"?o:null}function Q(n){if(!n||typeof n!="object")return null;let e=n,t=e.data?.resultVersion??e.data?.version??null;return typeof t=="number"?t:null}function ce(n){let e="composition"in n?f(n.composition):f({routeId:n.routeId});return new q({composition:e,initialDocument:n.initialDocument,client:n.client})}var q=class{constructor(e){this.params=e,this.serverConfirmedComposition=null,this.refreshInFlight=null,this.objectGeneration=0,this.styleGeneration=0,this.editContextCache=new Map,this.editContextInFlight=new Map,this.classNameSourceCache=new Map,this.classNameSourceInFlight=new Map,this.styleContextCache=new Map,this.styleContextInFlight=new Map,this.snapshotIdentityStale=!1,this.composition=f(e.composition);let t=e.initialDocument.composition.effectiveTemplateId;if(t!==void 0&&(this.composition.templateId===void 0||this.composition.templateId!==t))throw new Error(`Site edit bridge requires a matching templateId for initial document composition ${JSON.stringify(e.initialDocument.composition)}`);this.currentDocument=e.initialDocument,this.observedDocumentVersion=e.initialDocument.version,this.sessionInitialized=!O(e.initialDocument),this.activeCompositionContext=this.sessionInitialized?{...e.initialDocument.composition}:null}async getDocument(e){this.requireBoundComposition(e);let t=O(this.currentDocument)||this.snapshotIdentityStale;return(t||this.currentDocument.version<this.observedDocumentVersion)&&(this.currentDocument=await this.refreshSnapshot(t?void 0:this.observedDocumentVersion,"get-document"),this.snapshotIdentityStale=!1,this.sessionInitialized=!0),{ok:!0,data:this.currentDocument}}async initializeSession(e){let t=this.requireBoundComposition(e.composition);if(!this.params.client.initializeSession)throw new Error("Site edit bridge client does not support initialize-session");let o=await this.params.client.initializeSession({...e,composition:t});return this.currentDocument=o.data.document,this.observedDocumentVersion=o.data.document.version,this.activeCompositionContext={...o.composition},this.rememberServerConfirmedComposition(o.composition),this.sessionInitialized=!0,this.clearObjectCaches(),o}async getHistoryStatus(e){return this.params.client.getHistoryStatus(this.requireBoundComposition(e))}async getStyleContext(e){let t=this.requireBoundComposition(e),o=I(t),s=this.styleContextCache.get(o);if(s?.generation===this.styleGeneration)return{ok:!0,data:s.value};let i=this.styleContextInFlight.get(o);if(i?.generation===this.styleGeneration)return i.request;let r=this.styleGeneration,c=this.params.client.getStyleContext(t).then(a=>(this.styleGeneration===r&&this.styleContextCache.set(o,{generation:r,value:a.data}),a)).finally(()=>{this.styleContextInFlight.get(o)?.request===c&&this.styleContextInFlight.delete(o)});return this.styleContextInFlight.set(o,{generation:r,request:c}),c}async ensureDocumentVersion(e,t){this.requireBoundComposition(e);let o=await this.refreshSnapshot(t,"ensure-version");if(o.version<t)throw new Error(`Document refresh returned version ${o.version}, expected at least ${t}`);return{ok:!0,data:o}}async acknowledgeDocumentVersion(e,t){if(this.requireBoundComposition(e),t>this.currentDocument.version){if(this.currentDocument.pageComposition.status==="supported"){let o=await this.refreshSnapshot(t,"ensure-version");if(o.version<t)throw new Error(`Document refresh returned version ${o.version}, expected at least ${t}`);return{ok:!0,data:o}}this.currentDocument={...this.currentDocument,version:t},this.clearObjectCaches({preserveStyleContext:!0})}return this.observedDocumentVersion=Math.max(this.observedDocumentVersion,t),{ok:!0,data:this.currentDocument}}async getObjectEditContext(e,t,o){let s=this.requireBoundComposition(t),i=this.objectCacheKey(e,s,o),r=this.editContextCache.get(i);if(r)return{ok:!0,data:r};let c=this.editContextInFlight.get(i);if(c)return c;let a=this.objectGeneration,u=this.params.client.getObjectEditContext(e,s,...o?[o]:[]).then(d=>(this.objectGeneration===a&&this.editContextCache.set(i,d.data),d)).finally(()=>{this.editContextInFlight.get(i)===u&&this.editContextInFlight.delete(i)});return this.editContextInFlight.set(i,u),u}async getClassNameSource(e,t){let o=this.requireBoundComposition(t),s=this.objectCacheKey(e,o),i=this.classNameSourceCache.get(s);if(i)return i;let r=this.classNameSourceInFlight.get(s);if(r)return r;let c=this.objectGeneration,a=this.params.client.getClassNameSource(e,o).then(u=>(this.objectGeneration===c&&this.classNameSourceCache.set(s,u),u)).finally(()=>{this.classNameSourceInFlight.get(s)===a&&this.classNameSourceInFlight.delete(s)});return this.classNameSourceInFlight.set(s,a),a}async getSourceTree(e){return this.params.client.getSourceTree(this.requireBoundComposition(e))}async getSourceFile(e){return this.params.client.getSourceFile({path:e.path,composition:this.requireBoundComposition(e.composition)})}async resolveSourceLocation(e){return this.params.client.resolveSourceLocation({key:e.key,composition:this.requireBoundComposition(e.composition)})}async execute(e,t){let o=S(e);o&&this.composition.templateId!==void 0&&this.requireBoundComposition(o);let s={...e,composition:o??this.composition};return this.params.client.execute(s)}async undo(e,t){return this.params.client.undo(this.requireBoundComposition(e))}async redo(e,t){return this.params.client.redo(this.requireBoundComposition(e))}subscribe(e){return this.params.client.subscribe(t=>{if(t.type==="site-edit.snapshot.changed"&&this.sessionInitialized&&this.isActiveComposition(t.composition)){this.snapshotIdentityStale=!0,this.clearObjectCaches(),e(t);return}if(t.type==="site-edit.document.changed"&&this.sessionInitialized&&this.isActiveComposition(t.composition)){this.observedDocumentVersion=Math.max(this.observedDocumentVersion,t.version),t.version>this.currentDocument.version&&this.clearObjectCaches(),e(t);return}e(t)})}async refreshSnapshot(e,t="ensure-version"){if(typeof e=="number"&&this.currentDocument.version>=e)return m("bridge.document-refresh",{composition:this.composition,routeId:this.composition.routeId,minVersion:e,currentVersion:this.currentDocument.version,deduped:!0,skipped:!0,source:t}),this.currentDocument;let o=I(this.composition),s=this.refreshInFlight;if(s?.compositionKey===o){m("bridge.document-refresh",{composition:this.composition,routeId:this.composition.routeId,minVersion:e,currentVersion:this.currentDocument.version,deduped:!0,source:t});let r=await s.request;if(typeof e!="number"||r.version>=e||this.currentDocument.version>=e)return this.currentDocument}m("bridge.document-refresh",{composition:this.composition,routeId:this.composition.routeId,minVersion:e,currentVersion:this.currentDocument.version,deduped:!1,source:t});let i=this.params.client.getDocument(this.composition).then(r=>(this.currentDocument=r.data,this.activeCompositionContext={...r.data.composition},this.rememberServerConfirmedComposition(r.data.composition),this.observedDocumentVersion=Math.max(this.observedDocumentVersion,r.data.version),this.clearObjectCaches(),this.currentDocument));this.refreshInFlight={compositionKey:o,request:i};try{return await i}finally{this.refreshInFlight?.request===i&&(this.refreshInFlight=null)}}clearObjectCaches(e){this.objectGeneration+=1,this.editContextCache.clear(),this.editContextInFlight.clear(),this.classNameSourceCache.clear(),this.classNameSourceInFlight.clear(),!e?.preserveStyleContext&&(this.styleGeneration+=1,this.styleContextCache.clear(),this.styleContextInFlight.clear())}objectCacheKey(e,t,o){return`${I(t)}\0${e}\0${Y(o)}`}rememberServerConfirmedComposition(e){!e||typeof e.routeId!="string"||(this.serverConfirmedComposition={...e})}isAcceptedComposition(e){if(I(e)===I(this.composition))return!0;let t=this.serverConfirmedComposition;return t!==null&&C(t)===C(A(e))}requireBoundComposition(e){let t=e===void 0?this.composition:f(e);if(!this.isAcceptedComposition(t))throw new Error(`Site edit bridge is bound to composition ${JSON.stringify(this.composition)}, received ${JSON.stringify(t)}`);return f(t)}isActiveComposition(e){let t=this.activeCompositionContext??A(this.composition);return C(e)===C(t)}};function O(n){return n.version===0&&n.entries.length===0}function H(n){let e=n;return{...e,data:{...e.data,document:M(e.data.document,e.composition)}}}function M(n,e){let t=n,o=T(t.routeId?t:{...t,routeId:e?.routeId??t.composition?.routeId});return e?{...o,composition:e}:o}function f(n){if(n&&typeof n=="object"&&typeof n.routeId=="string"){let e="effectiveTemplateId"in n?n.effectiveTemplateId:"templateId"in n?n.templateId:void 0;return{routeId:n.routeId,...typeof e=="string"?{templateId:e}:{}}}throw new Error("SITE_EDIT_COMPOSITION_SESSION_REQUIRED: a composition selector is required")}function I(n){return JSON.stringify([n.routeId,n.templateId??null])}function Y(n){return n?JSON.stringify([n.key,n.instanceIndex??null,n.instanceCount??null]):""}function C(n){return JSON.stringify([n.routeId,n.effectiveTemplateId??null])}function A(n){return{routeId:n.routeId,...n.templateId?{effectiveTemplateId:n.templateId}:{}}}function S(n){if(n&&typeof n=="object"){let e=n;if(e.composition&&typeof e.composition=="object"){let t=e.composition;if(typeof t.routeId=="string")return{routeId:t.routeId,...typeof t.templateId=="string"?{templateId:t.templateId}:{}}}}}function Z(n,e,t){let o=f(e==="execute"?S(t.request):t.composition),s={id:n,kind:e,composition:o};switch(e){case"initialize-session":case"get-document":case"get-history-status":case"get-style-context":case"get-source-tree":case"undo":case"redo":return{type:"request",payload:{...s,...t.mutationContext?{mutationContext:t.mutationContext}:{}}};case"get-object-edit-context":return{type:"request",payload:{...s,key:String(t.key),...t.selectionRef?{selectionRef:t.selectionRef}:{}}};case"get-class-name-source":case"resolve-source-location":return{type:"request",payload:{...s,key:String(t.key)}};case"get-source-file":return{type:"request",payload:{...s,path:String(t.path)}};case"execute":return{type:"request",payload:{...s,request:{...t.request,composition:S(t.request)??o}}}}}export{D as SiteEditWebSocketClient,ce as createSiteEditBridge};
|
package/dist/document-codec.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export type CompactRenderDocument = {
|
|
|
11
11
|
tokens: string[];
|
|
12
12
|
nodes: CompactRenderDocumentNode[];
|
|
13
13
|
entries: CompactRenderDocumentEntry[];
|
|
14
|
+
entryParentNodeIds?: Array<number | null>;
|
|
14
15
|
dynamicDataSummaries?: Array<[
|
|
15
16
|
entryIndex: number,
|
|
16
17
|
summary: SiteEditDynamicDataSummary
|
package/dist/document-codec.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function
|
|
1
|
+
function v(e){let t=new Map,i=[],s=new Map,a=[],n=e.pageComposition.status==="supported"?e.pageComposition.placementUnitKeys:[],p=new Map(n.map((o,r)=>[o,r])),d=e.pageComposition.status==="supported"?{status:"supported",containerKey:e.pageComposition.containerKey,hasBusinessMembers:e.pageComposition.hasBusinessMembers,placementUnitKeys:e.pageComposition.placementUnitKeys,placements:e.pageComposition.placements.map(o=>({placementKey:o.placementKey,placementUnitKey:o.placementUnitKey,relation:o.relation}))}:{status:"unsupported",reason:e.pageComposition.reason,diagnostics:e.pageComposition.diagnostics},u=e.entries.flatMap((o,r)=>o.dynamicDataSummary?[[r,o.dynamicDataSummary]]:[]),c=o=>{let r=t.get(o);if(typeof r=="number")return r;let f=i.length;return i.push(o),t.set(o,f),f},m=o=>{let r=null;for(let f of x(o)){let y=`${r??"root"}\0${f}`,h=s.get(y);if(typeof h=="number"){r=h;continue}let I=a.length;a.push([r,c(f)]),s.set(y,I),r=I}if(r===null)throw new Error("Document key must not be empty");return r};return{encoding:"segment-trie-v1",siteId:e.siteId,snapshotId:e.snapshotId,composition:{...e.composition},routeId:e.composition.routeId,version:e.version,pageComposition:d,tokens:i,nodes:a,entries:e.entries.map(o=>{let r=o.pageCompositionUnitKey?p.get(o.pageCompositionUnitKey)??-1:-1;if(o.pageCompositionUnitKey&&r<0)throw new Error(`Render entry ${o.key} references unknown page composition unit ${o.pageCompositionUnitKey}`);return[m(o.key),K(o.operationSummary),...r>=0?[r]:[]]}),...e.entries.every(o=>o.parentKey!==void 0)?{entryParentNodeIds:e.entries.map(o=>o.parentKey===null?null:m(o.parentKey))}:{},...u.length>0?{dynamicDataSummaries:u}:{}}}function M(e){if(!A(e)){if(e.encoding==="segment-trie-v1")throw new Error("Invalid compact render document");return e}let t=new Map,i=e.pageComposition.status==="supported"?e.pageComposition.placementUnitKeys:[],s=new Map(e.dynamicDataSummaries??[]),a=n=>{let p=t.get(n);if(p)return p;let d=e.nodes[n];if(!d)throw new Error(`Missing compact document node ${n}`);let[u,c]=d,m=e.tokens[c];if(typeof m!="string")throw new Error(`Missing compact document token ${c}`);let o=`${u===null?"":a(u)}${m}`;return t.set(n,o),o};return{siteId:e.siteId,snapshotId:e.snapshotId,composition:{...e.composition},routeId:e.composition.routeId,version:e.version,pageComposition:e.pageComposition,entries:e.entries.map((n,p)=>{let[d,u,c]=n,m=c===void 0?void 0:i[c];if(c!==void 0&&!m)throw new Error(`Missing page composition unit ${c}`);let o=e.entryParentNodeIds?.[p];return{key:a(d),...e.entryParentNodeIds?{parentKey:o===null?null:a(o)}:{},...m?{pageCompositionUnitKey:m}:{},operationSummary:w(u),...s.get(p)?{dynamicDataSummary:s.get(p)}:{}}})}}function K(e){return(e.canUpdateText?1:0)|(e.canInsertChild?2:0)|(e.canMove?4:0)|(e.canRemove?8:0)}function w(e){return{canUpdateText:(e&1)!==0,canInsertChild:(e&2)!==0,canMove:(e&4)!==0,canRemove:(e&8)!==0}}function A(e){if(typeof e!="object"||e===null)return!1;let t=e;if(t.encoding!=="segment-trie-v1"||typeof t.siteId!="string"||typeof t.snapshotId!="string"||!U(t.composition)||typeof t.routeId!="string"||t.routeId!==t.composition.routeId||!Number.isInteger(t.version)||t.version<0||!l(t.pageComposition)||!Array.isArray(t.tokens)||!t.tokens.every(n=>typeof n=="string")||!Array.isArray(t.nodes)||!Array.isArray(t.entries))return!1;let i=t.nodes;if(!i.every((n,p)=>Array.isArray(n)&&n.length===2&&(n[0]===null||g(n[0])&&n[0]<p)&&g(n[1])&&n[1]<t.tokens.length)||!t.entries.every(n=>Array.isArray(n)&&(n.length===2||n.length===3)&&g(n[0])&&n[0]<i.length&&g(n[1])&&n[1]<=15&&(n.length===2||g(n[2]))))return!1;let s=t.entryParentNodeIds;if(s!==void 0&&(!Array.isArray(s)||s.length!==t.entries.length||!s.every(n=>n===null||g(n)&&n<i.length)))return!1;let a=t.dynamicDataSummaries;return a===void 0||Array.isArray(a)&&a.every(n=>Array.isArray(n)&&n.length===2&&g(n[0])&&n[0]<t.entries.length&&l(n[1]))}function l(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function U(e){return!l(e)||typeof e.routeId!="string"?!1:e.effectiveTemplateId===void 0||typeof e.effectiveTemplateId=="string"}function g(e){return typeof e=="number"&&Number.isInteger(e)&&e>=0}function x(e){if(!e)return[];let t=[],i=0,s=C(e,i);if(s<0)return t.push(e),t;for(t.push(e.slice(0,s)),i=s;i<e.length;){if(s=C(e,i+(e.startsWith("::",i)?2:1)),s<0){t.push(e.slice(i));break}t.push(e.slice(i,s)),i=s}return t}function C(e,t){let i=e.indexOf("/",t),s=e.indexOf("::",t);return i<0?s:s<0?i:Math.min(i,s)}export{M as decodeRenderDocument,v as encodeRenderDocument,A as isCompactRenderDocument};
|