@vcp-dev/site-edit-bridge 0.6.10 → 0.7.0
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/README.md +27 -8
- package/dist/auto-bootstrap.d.ts +19 -2
- package/dist/auto-bootstrap.js +11 -11
- package/dist/client.d.ts +76 -36
- package/dist/client.js +1 -1
- package/dist/document-codec.d.ts +2 -0
- package/dist/document-codec.js +1 -1
- package/dist/index.js +8 -8
- package/dist/next-dev-server.js +3 -3
- package/dist/protocol.d.ts +71 -143
- package/dist/protocol.js +281 -182
- package/dist/server.d.ts +7 -5
- package/dist/server.js +2 -2
- package/dist/window-message.d.ts +26 -12
- package/dist/window-message.js +1 -1
- package/package.json +3 -3
package/dist/server.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import X from"node:http";import{createHash as F,randomBytes as Z,timingSafeEqual as ee}from"node:crypto";import C from"node:path";import{WebSocket as U,WebSocketServer as te}from"ws";import{createPreviewSiteEditEngineRuntime as se,openFileHistoryStore as ne}from"@vcp-dev/site-edit-engine";import{resolveNextAppRouteId as ie,scanNextAppRouterRoutes as oe}from"@vcp-dev/site-edit-engine/next-app-router";import{SiteEditSourceWatcher as re}from"@vcp-dev/site-edit-engine/source-watcher";function I(t){let e=new Map,s=[],n=new Map,i=[],o=t.pageComposition.status==="supported"?t.pageComposition.placementUnitKeys:[],r=new Map(o.map((a,u)=>[a,u])),p=t.pageComposition.status==="supported"?{status:"supported",containerKey:t.pageComposition.containerKey,hasBusinessMembers:t.pageComposition.hasBusinessMembers,placementUnitKeys:t.pageComposition.placementUnitKeys,placements:t.pageComposition.placements.map(a=>({placementKey:a.placementKey,placementUnitKey:a.placementUnitKey,relation:a.relation}))}:{status:"unsupported",reason:t.pageComposition.reason,diagnostics:t.pageComposition.diagnostics},h=t.entries.flatMap((a,u)=>a.dynamicDataSummary?[[u,a.dynamicDataSummary]]:[]),y=a=>{let u=e.get(a);if(typeof u=="number")return u;let l=s.length;return s.push(a),e.set(a,l),l},$=a=>{let u=null;for(let l of z(a)){let E=`${u??"root"}\0${l}`,_=n.get(E);if(typeof _=="number"){u=_;continue}let T=i.length;i.push([u,y(l)]),n.set(E,T),u=T}if(u===null)throw new Error("Document key must not be empty");return u};return{encoding:"segment-trie-v1",siteId:t.siteId,snapshotId:t.snapshotId,routeId:t.routeId,version:t.version,pageComposition:p,tokens:s,nodes:i,entries:t.entries.map(a=>{let u=a.pageCompositionUnitKey?r.get(a.pageCompositionUnitKey)??-1:-1;if(a.pageCompositionUnitKey&&u<0)throw new Error(`Render entry ${a.key} references unknown page composition unit ${a.pageCompositionUnitKey}`);return[$(a.key),W(a.operationSummary),...u>=0?[u]:[]]}),...h.length>0?{dynamicDataSummaries:h}:{}}}function W(t){return(t.canUpdateText?1:0)|(t.canInsertChild?2:0)|(t.canMove?4:0)|(t.canRemove?8:0)}function z(t){if(!t)return[];let e=[],s=0,n=B(t,s);if(n<0)return e.push(t),e;for(e.push(t.slice(0,n)),s=n;s<t.length;){if(n=B(t,s+(t.startsWith("::",s)?2:1)),n<0){e.push(t.slice(s));break}e.push(t.slice(s,n)),s=n}return e}function B(t,e){let s=t.indexOf("/",e),n=t.indexOf("::",e);return s<0?n:n<0?s:Math.min(s,n)}var d=class t{constructor(){}static parseMessage(e,s={}){let n=JSON.parse(e);if(!t.isMessage(n,s))throw new Error("Invalid site edit bridge message");return n}static stringifyMessage(e){return JSON.stringify(e)}static extractRequestInfo(e){if(typeof e=="object"&&e!==null&&"payload"in e&&typeof e.payload=="object"&&e.payload!==null){let s=e.payload,n=typeof s.id=="string"?s.id:"unknown",i=t.isRequestKind(s.kind)?s.kind:"get-document";return{id:n,kind:i}}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,s={}){return!c(e)||typeof e.type!="string"?!1:e.type==="request"?t.isRequestPayload(e.payload,s):e.type==="response"||e.type==="error"?c(e.payload)&&typeof e.payload.id=="string":e.type==="event"?c(e.payload)&&c(e.payload.event):e.type==="auth"?c(e.payload)&&typeof e.payload.key=="string":e.type==="auth-ok"?c(e.payload)&&e.payload.ok===!0:!1}static isRequestPayload(e,s={}){if(!c(e)||typeof e.id!="string"||!t.isRequestKind(e.kind))return!1;switch(e.kind){case"initialize-session":return typeof e.routeId=="string"&&(e.mutationContext===void 0||R(e.mutationContext));case"get-document":case"get-style-context":return typeof e.routeId=="string";case"get-object-edit-context":case"get-class-name-source":case"resolve-source-location":return typeof e.key=="string"&&(e.routeId===void 0||typeof e.routeId=="string");case"get-history-status":return e.mutationContext===void 0;case"get-source-tree":return!0;case"get-source-file":return typeof e.path=="string";case"execute":return Q(e.request)&&(e.request.mutationContext===void 0||R(e.request.mutationContext))&&(s.validateOperationRequest?.(e.request)??!0);case"undo":case"redo":return e.mutationContext===void 0||R(e.mutationContext)}}},g=class{constructor(e){this.options=e,this.messageQueue=new w,this.eventDispatcher=new S(s=>{this.sendJson(s)}),this.unsubscribe=e.engine.subscribe(s=>{this.eventDispatcher.push(s)}),e.socket.onmessage=s=>{try{this.messageQueue.enqueue(()=>this.handleRawMessage(s.data))}catch(n){this.sendJson({type:"error",payload:{id:"unknown",kind:"get-document",message:n instanceof Error?n.message:"Bridge queue overflow"}}),e.socket.close(1013,"bridge busy")}},e.socket.onclose=()=>{this.unsubscribe()}}async handleMessage(e){try{let s=e;if(s.type!=="request")return;let n=s.payload,{id:i}=n;switch(n.kind){case"initialize-session":{let o=await this.options.engine.initializeSession({routeId:n.routeId,...n.mutationContext?{mutationContext:n.mutationContext}:{}});this.sendJson({type:"response",payload:{id:i,kind:n.kind,result:{ok:!0,data:{document:I(o.data.document),historyStatus:o.data.historyStatus}}}});return}case"get-document":this.sendJson({type:"response",payload:{id:i,kind:n.kind,result:{ok:!0,data:I((await this.options.engine.getDocument(n.routeId)).data)}}});return;case"get-history-status":this.sendJson({type:"response",payload:{id:i,kind:n.kind,result:await this.options.engine.getHistoryStatus()}});return;case"get-style-context":this.sendJson({type:"response",payload:{id:i,kind:n.kind,result:await this.options.engine.getStyleContext(n.routeId)}});return;case"get-object-edit-context":this.sendJson({type:"response",payload:{id:i,kind:n.kind,result:await this.options.engine.getObjectEditContext(n.key,n.routeId)}});return;case"get-class-name-source":this.sendJson({type:"response",payload:{id:i,kind:n.kind,result:await this.options.engine.getClassNameSource(n.key,n.routeId)}});return;case"get-source-tree":this.sendJson({type:"response",payload:{id:i,kind:n.kind,result:await this.options.engine.getSourceTree()}});return;case"get-source-file":this.sendJson({type:"response",payload:{id:i,kind:n.kind,result:await this.options.engine.getSourceFile({path:n.path})}});return;case"resolve-source-location":this.sendJson({type:"response",payload:{id:i,kind:n.kind,result:await this.options.engine.resolveSourceLocation({key:n.key,routeId:n.routeId})}});return;case"execute":{await this.handleBufferedOperation(i,n.kind,()=>this.options.engine.execute(n.request));return}case"undo":await this.handleBufferedOperation(i,n.kind,()=>this.options.engine.undo());return;case"redo":await this.handleBufferedOperation(i,n.kind,()=>this.options.engine.redo());return}}catch(s){let n=d.extractRequestInfo(e);this.sendJson({type:"error",payload:{...n,message:H(s),code:D(s)}})}}async handleRawMessage(e){try{await this.handleMessage(d.parseMessage(e,{validateOperationRequest:this.options.validateOperationRequest}))}catch(s){let n=s instanceof Error?s.message:"Invalid websocket message",i=Y(e);this.sendJson({type:"error",payload:{...i,message:n}})}}sendJson(e){this.options.socket.send(d.stringifyMessage(e))}async handleBufferedOperation(e,s,n){this.eventDispatcher.beginBuffering();try{let i=await n();this.sendJson({type:"response",payload:{id:e,kind:s,result:i}}),this.eventDispatcher.flush()}catch(i){this.sendJson({type:"error",payload:{id:e,kind:s,message:H(i),code:D(i)}}),this.eventDispatcher.flush()}}},S=class{constructor(e){this.send=e,this.bufferedEvents=null}push(e){let s={type:"event",payload:{event:e}};if(this.bufferedEvents){this.bufferedEvents.push(s);return}this.send(s)}beginBuffering(){this.bufferedEvents=[]}flush(){let e=this.bufferedEvents??[];this.bufferedEvents=null,e.forEach(s=>{this.send(s)})}},w=class{constructor(e=64){this.maxQueued=e,this.queue=Promise.resolve(),this.queued=0}enqueue(e){if(this.queued>=this.maxQueued)throw new Error("Bridge request queue is full");this.queued+=1;let s=async()=>{this.queued-=1,await e()},n=this.queue.then(s,s);return this.queue=n.then(()=>{},()=>{}),n}};function c(t){return typeof t=="object"&&t!==null}function Q(t){return c(t)&&typeof t.id=="string"&&typeof t.siteId=="string"&&typeof t.baseSnapshotId=="string"&&(t.routeId===void 0||typeof t.routeId=="string")&&typeof t.kind=="string"&&c(t.target)&&typeof t.documentVersion=="number"&&Number.isInteger(t.documentVersion)&&t.documentVersion>=0&&c(t.params)}function R(t){return G(t)}function D(t){if(!t||typeof t!="object")return;let e=t.code;return typeof e=="string"&&e.length>0?e:void 0}function H(t){if(t instanceof Error)return t.message;if(!t||typeof t!="object")return"Unknown websocket operation failure";let e=t.message;return typeof e=="string"&&e.length>0?e:"Unknown websocket operation failure"}function G(t){return c(t)?typeof t.editingSessionId=="string"&&t.editingSessionId.length>0&&typeof t.lockId=="string"&&t.lockId.length>0&&typeof t.ownerId=="string"&&t.ownerId.length>0&&typeof t.leaseAssertion=="string"&&t.leaseAssertion.length>0:!1}function Y(t){try{return d.extractRequestInfo(JSON.parse(t))}catch{return{id:"unknown",kind:"get-document"}}}var f=class{constructor(){this.tail=Promise.resolve()}run(e){let s=this.tail.then(e,e);return this.tail=s.then(()=>{},()=>{}),s}};import{SiteEditOperationRequestSchema as ae}from"@vcp-dev/contracts";var ue="127.0.0.1",ce=30218,de="/__vcp/site-edit/bridge",P=6*1024*1024,he=P*2,pe=3e3,M=50,O="__VCP_SITE_EDIT_BRIDGE_SERVERS__";function Ae(t){let e=q(t),s=J(e),n=j(),i=n.get(s);if(i)return i;let o=new m(e);n.set(s,o);try{o.start()}catch(r){throw n.delete(s),o.stop(),r}return o}function Ke(t,e,s={}){let n=new m(q(e),t,!1,s);return n.start({listen:!1}),n}var m=class{constructor(e,s=X.createServer((o,r)=>{r.writeHead(404),r.end("VCP site edit bridge server")}),n=!0,i={}){this.options=e,this.server=s,this.closeHttpServerOnStop=n,this.dependencies=i,this.runtime=null,this.activeHistorySessionId=null,this.historySessionTransition=Promise.resolve(),this.mutationQueue=new f,this.eventListeners=new Set,this.routes=[],this.stopWatching=null,this.stopWebSocketServer=null,this.pendingChangedFiles=new Set,this.fileChangeTimer=null,this.isStarted=!1,this.runtimeVersionFloor=0,this.activeHistoryStore=null,this.versionPersistence=Promise.resolve()}start(e={}){if(this.isStarted)return;this.refreshRoutes(),this.isStarted=!0,this.createRuntime();let s=ge({server:this.server,path:this.options.path,sessionKey:this.options.sessionKey,host:this.options.host,allowedOrigins:this.options.allowedOrigins,engine:this.createBridgeEngine()});this.stopWebSocketServer=s.stop,this.stopWatching=new re({projectRoot:this.options.projectRoot,watch_dirs:this.options.runtime.watch_dirs,interval_ms:this.options.runtime.watch_interval_ms,debounce_ms:this.options.runtime.watch_debounce_ms??M,max_dirs:this.options.runtime.watch_max_dirs,max_files:this.options.runtime.watch_max_files,max_depth:this.options.runtime.watch_max_depth,max_startup_ms:this.options.runtime.watch_max_startup_ms,on_change:n=>this.handleFileChanged(n),on_batch_change:n=>this.handleFilesChanged(n)}).start(),e.listen!==!1&&this.server.listen(this.options.port,this.options.host)}getHealth(){let e=!!this.runtime;return{ok:this.isStarted&&e,bridgePath:this.options.path,runtimeReady:e,routesIndexed:this.routes.length,sessionRequired:!!this.options.sessionKey}}stop(){this.stopWatching?.(),this.stopWatching=null,this.flushChangedFiles(),this.fileChangeTimer&&(clearTimeout(this.fileChangeTimer),this.fileChangeTimer=null),this.stopWebSocketServer?.(),this.stopWebSocketServer=null,this.runtime?.dispose(),this.runtime=null,this.closeHttpServerOnStop&&this.server.close();let e=j(),s=J(this.options);e.get(s)===this&&e.delete(s),this.isStarted=!1}createRuntime(e,s=null){let n=this.runtime;this.activeHistoryStore=e??null;let i=(this.dependencies.createRuntime??se)({...this.options.tenantId?{tenantId:this.options.tenantId}:{},siteId:this.options.siteId,snapshotId:this.options.snapshotId,projectRoot:this.options.projectRoot,routes:this.routes,onEvent:o=>{"version"in o&&typeof o.version=="number"&&this.recordRuntimeVersion(o.version);for(let r of this.eventListeners)r(o)},...e?{historyStore:e}:{},initialDocumentVersion:this.runtimeVersionFloor});this.runtime=i,this.activeHistorySessionId=s,n?.dispose()}createBridgeEngine(){return{initializeSession:e=>this.mutationQueue.run(async()=>{let s=await this.bindHistorySession(this.options.snapshotId);if(!s.ok)throw new Error(`${s.code}: ${s.message}`);let{runtime:n,resolvedRouteId:i}=await this.activateRoute(e.routeId),o=n.getDocument(i).data;await this.recordRuntimeVersion(o.version);let r=(await n.getHistoryStatus()).data;return{ok:!0,data:{document:o,historyStatus:r}}}),getDocument:async e=>{let{runtime:s,resolvedRouteId:n}=await this.activateRoute(e),i=s.getDocument(n);return await this.recordRuntimeVersion(i.data.version),i},getHistoryStatus:async()=>this.getRuntime().getHistoryStatus(),getStyleContext:async e=>{let{runtime:s,resolvedRouteId:n}=await this.activateRoute(e);return s.getStyleContext(n)},getObjectEditContext:async(e,s)=>this.getRuntime().getObjectEditContext(e,s?this.resolveRouteId(s):void 0),getClassNameSource:async(e,s)=>{let n=this.getRuntime(),i=s?this.resolveRouteId(s):void 0;return n.getClassNameSource(e,i)},getSourceTree:async()=>this.getRuntime().getSourceTree(),getSourceFile:async e=>this.getRuntime().getSourceFile(e),resolveSourceLocation:async e=>this.getRuntime().resolveSourceLocation({key:e.key,routeId:e.routeId?this.resolveRouteId(e.routeId):void 0}),execute:(e,s)=>this.mutationQueue.run(async()=>{let n=await this.bindHistorySession(this.options.snapshotId);if(!n.ok)return k(n,e);let i=await this.getRuntime().executeOperation(this.normalizeRequest(e));return i.data?.resultVersion!==void 0&&await this.recordRuntimeVersion(i.data.resultVersion),i}),undo:()=>this.mutationQueue.run(async()=>{let e=await this.bindHistorySession(this.options.snapshotId);if(!e.ok)return k(e);let s=await this.getRuntime().undo();return s.data?.resultVersion!==void 0&&await this.recordRuntimeVersion(s.data.resultVersion),s}),redo:()=>this.mutationQueue.run(async()=>{let e=await this.bindHistorySession(this.options.snapshotId);if(!e.ok)return k(e);let s=await this.getRuntime().redo();return s.data?.resultVersion!==void 0&&await this.recordRuntimeVersion(s.data.resultVersion),s}),subscribe:e=>(this.eventListeners.add(e),()=>this.eventListeners.delete(e))}}async bindHistorySession(e){if(!this.options.historyRoot)return{ok:!1,code:"RECOVERY_PERSIST_FAILED",message:"Durable edit history is not configured."};if(this.activeHistorySessionId===e)return{ok:!0};let s=this.historySessionTransition.then(async()=>{if(this.activeHistorySessionId===e)return;let n=await(this.dependencies.openHistoryStore??ne)(le({root:this.options.historyRoot,siteId:this.options.siteId,snapshotId:this.options.snapshotId,editingSessionId:e}));if(!this.isStarted)return;let i=n.readDocumentVersion?await n.readDocumentVersion():0;this.runtimeVersionFloor=Math.max(this.runtimeVersionFloor,i),this.createRuntime(n,e)});this.historySessionTransition=s.catch(()=>{});try{return await s,{ok:!0}}catch{return{ok:!1,code:"RECOVERY_PERSIST_FAILED",message:"Durable edit history could not be opened."}}}recordRuntimeVersion(e){this.runtimeVersionFloor=Math.max(this.runtimeVersionFloor,e);let s=this.activeHistoryStore;return s?.writeDocumentVersion?(this.versionPersistence=this.versionPersistence.then(()=>s.writeDocumentVersion(this.runtimeVersionFloor)).catch(()=>{}),this.versionPersistence):Promise.resolve()}async activateRoute(e){let s=this.getRuntime(),n=this.resolveRouteId(e);return await s.setActiveRoute(n),{runtime:s,resolvedRouteId:n}}normalizeRequest(e){return e.target.kind!=="route"?e.routeId?{...e,routeId:this.resolveRouteId(e.routeId)}:e:{...e,target:{...e.target,routeId:this.resolveRouteId(e.target.routeId)}}}handleFileChanged(e){this.handleFilesChanged([e])}handleFilesChanged(e){for(let n of e)this.pendingChangedFiles.add(n);this.fileChangeTimer&&clearTimeout(this.fileChangeTimer);let s=this.options.runtime.watch_debounce_ms??M;this.fileChangeTimer=setTimeout(()=>{this.fileChangeTimer=null,this.flushChangedFiles()},s),this.fileChangeTimer?.unref?.()}flushChangedFiles(){if(this.fileChangeTimer&&(clearTimeout(this.fileChangeTimer),this.fileChangeTimer=null),this.pendingChangedFiles.size===0)return;let e=[...this.pendingChangedFiles].sort((s,n)=>s.localeCompare(n));this.pendingChangedFiles.clear(),this.refreshRoutes();for(let s of e)this.runtime?.notifyFileChanged(s)}refreshRoutes(){let e=this.options.runtime.routes?.length?this.options.runtime.routes:oe(this.options.projectRoot),s=new Map(this.routes.map(i=>[i.routeId,i.entryFile])),n=new Set(e.map(i=>i.routeId));this.routes=e;for(let i of e)s.get(i.routeId)!==i.entryFile&&this.runtime?.registerRoute(i.routeId,i.entryFile);for(let i of s.keys())n.has(i)||this.runtime?.unregisterRoute(i)}resolveRouteId(e){let s=ie(e,this.routes,this.options.basePath);if(!s)throw new Error(`Route is not indexed by the preview bridge: ${e}`);return s}getRuntime(){if(!this.runtime)throw new Error("VCP site edit preview bridge runtime is not ready");return this.runtime}};function q(t){return{tenantId:t.tenantId,siteId:t.siteId,snapshotId:t.snapshotId,projectRoot:C.resolve(t.projectRoot??process.cwd()),basePath:t.basePath??"",host:t.host??ue,port:t.port??ce,path:t.path??de,sessionKey:t.sessionKey??we(),historyRoot:t.historyRoot,allowedOrigins:t.allowedOrigins??[],runtime:t.runtime??{}}}function le(t){return C.join(C.resolve(t.root),V(t.siteId),V(t.snapshotId),F("sha256").update(t.editingSessionId).digest("hex").slice(0,32))}function V(t){return/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(t)&&t!=="."&&t!==".."?t:F("sha256").update(t).digest("hex").slice(0,32)}function j(){let t=globalThis;return t[O]??=new Map,t[O]}function J(t){return`${t.projectRoot}:${t.host}:${t.port}:${t.path}:${t.historyRoot??""}`}function k(t,e){return{ok:!1,error:{code:t.code,message:t.message},data:{requestId:e?.id??"mutation-context",kind:e?.kind??"update-text",target:e?.target??{kind:"node",key:""},resultVersion:e?.documentVersion??0}}}function ge(t){let e=new te({maxPayload:P,noServer:!0}),s=new WeakSet,n=o=>{new g({socket:new b(o),engine:t.engine,validateOperationRequest:r=>ae.safeParse(r).success})},i=(o,r,p)=>{if(!fe(o,t))return;let h=me(o,t);if(!h){r.write(`HTTP/1.1 401 Unauthorized\r
|
|
1
|
+
import me from"node:http";import A from"node:fs";import{createHash as Y,randomBytes as fe,timingSafeEqual as ge}from"node:crypto";import g from"node:path";import{WebSocket as Z,WebSocketServer as ye}from"ws";import{createPreviewSiteEditEngineRuntime as Ie,openFileHistoryStore as Se,resolveManagedPageTemplateComposition as we,scanSiteEditCompositionsFromFiles as Ce}from"@vcp-dev/site-edit-engine";import{resolveNextAppRouteId as xe,scanNextAppRouterRoutesFromFiles as Re}from"@vcp-dev/site-edit-engine/next-app-router";import{SiteEditSourceWatcher as Ee}from"@vcp-dev/site-edit-engine/source-watcher";function U(t){let e=new Map,s=[],i=new Map,o=[],n=t.pageComposition.status==="supported"?t.pageComposition.placementUnitKeys:[],r=new Map(n.map((u,h)=>[u,h])),a=t.pageComposition.status==="supported"?{status:"supported",containerKey:t.pageComposition.containerKey,hasBusinessMembers:t.pageComposition.hasBusinessMembers,placementUnitKeys:t.pageComposition.placementUnitKeys,placements:t.pageComposition.placements.map(u=>({placementKey:u.placementKey,placementUnitKey:u.placementUnitKey,relation:u.relation}))}:{status:"unsupported",reason:t.pageComposition.reason,diagnostics:t.pageComposition.diagnostics},c=t.entries.flatMap((u,h)=>u.dynamicDataSummary?[[h,u.dynamicDataSummary]]:[]),p=u=>{let h=e.get(u);if(typeof h=="number")return h;let C=s.length;return s.push(u),e.set(u,C),C},y=u=>{let h=null;for(let C of re(u)){let H=`${h??"root"}\0${C}`,V=i.get(H);if(typeof V=="number"){h=V;continue}let P=o.length;o.push([h,p(C)]),i.set(H,P),h=P}if(h===null)throw new Error("Document key must not be empty");return h};return{encoding:"segment-trie-v1",siteId:t.siteId,snapshotId:t.snapshotId,composition:{...t.composition},routeId:t.composition.routeId,version:t.version,pageComposition:a,tokens:s,nodes:o,entries:t.entries.map(u=>{let h=u.pageCompositionUnitKey?r.get(u.pageCompositionUnitKey)??-1:-1;if(u.pageCompositionUnitKey&&h<0)throw new Error(`Render entry ${u.key} references unknown page composition unit ${u.pageCompositionUnitKey}`);return[y(u.key),oe(u.operationSummary),...h>=0?[h]:[]]}),...c.length>0?{dynamicDataSummaries:c}:{}}}function oe(t){return(t.canUpdateText?1:0)|(t.canInsertChild?2:0)|(t.canMove?4:0)|(t.canRemove?8:0)}function re(t){if(!t)return[];let e=[],s=0,i=N(t,s);if(i<0)return e.push(t),e;for(e.push(t.slice(0,i)),s=i;s<t.length;){if(i=N(t,s+(t.startsWith("::",s)?2:1)),i<0){e.push(t.slice(s));break}e.push(t.slice(s,i)),s=i}return e}function N(t,e){let s=t.indexOf("/",e),i=t.indexOf("::",e);return s<0?i:i<0?s:Math.min(s,i)}var W="SITE_EDIT_COMPOSITION_SESSION_MISMATCH",M="SITE_EDIT_COMPOSITION_SESSION_REQUIRED";var l=class t{constructor(){}static parseMessage(e,s={}){let i=JSON.parse(e);if(!t.isMessage(i,s))throw new Error("Invalid site edit bridge message");return i}static stringifyMessage(e){return JSON.stringify(e)}static extractRequestInfo(e){if(d(e)&&d(e.payload)){let s=typeof e.payload.id=="string"?e.payload.id:"unknown",i=this.isRequestKind(e.payload.kind)?e.payload.kind:"get-document";return{id:s,kind:i}}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,s={}){return!d(e)||typeof e.type!="string"?!1:e.type==="request"?ae(e.payload,s):e.type==="response"||e.type==="error"?d(e.payload)&&typeof e.payload.id=="string":e.type==="event"?d(e.payload)&&d(e.payload.event):e.type==="auth"?d(e.payload)&&typeof e.payload.key=="string":e.type==="auth-ok"&&d(e.payload)&&e.payload.ok===!0}},R=class{constructor(e){this.options=e,this.session={subscribedCompositionKeys:new Set},this.messageQueue=new D,this.eventDispatcher=new O(s=>{this.sendJson(s)}),this.unsubscribe=e.engine.subscribe(s=>{this.handleEngineEvent(s)}),e.socket.onmessage=s=>{try{this.messageQueue.enqueue(()=>this.handleRawMessage(s.data))}catch(i){this.sendJson({type:"error",payload:{id:"unknown",kind:"get-document",message:i instanceof Error?i.message:"Bridge queue overflow"}}),e.socket.close(1013,"bridge busy")}},e.socket.onclose=()=>{this.unsubscribe(),this.session.activeComposition=void 0,this.session.subscribedCompositionKeys.clear()}}async handleMessage(e){try{let s=e;if(s.type!=="request")return;let i=s.payload,{id:o}=i;switch(i.kind){case"initialize-session":{let n=v(i),r=await this.resolve(n),a=await this.options.engine.initializeSession({composition:r.context,...i.mutationContext?{mutationContext:i.mutationContext}:{}});this.activateSession(r.context),this.sendJson({type:"response",payload:{id:o,kind:i.kind,result:f({...a,data:{...a.data,document:z(a.data.document)}},r.context)}});return}case"get-document":{let n=await this.resolveWireContext(i),r=await this.options.engine.getDocument(n);this.sendResult(o,i.kind,pe(r,n));return}case"get-history-status":{let n=await this.resolveWireContext(i),r=await this.options.engine.getHistoryStatus(n);this.sendResult(o,i.kind,f(r,n));return}case"get-style-context":{let n=await this.resolveWireContext(i);this.sendResult(o,i.kind,f(await this.options.engine.getStyleContext(n),n));return}case"get-object-edit-context":{let n=await this.resolveWireContext(i);this.sendResult(o,i.kind,f(await this.options.engine.getObjectEditContext(i.key,n),n));return}case"get-class-name-source":{let n=await this.resolveWireContext(i);this.sendResult(o,i.kind,f(await this.options.engine.getClassNameSource(i.key,n),n));return}case"get-source-tree":{let n=await this.resolveWireContext(i);this.sendResult(o,i.kind,f(await this.options.engine.getSourceTree(n),n));return}case"get-source-file":{let n=await this.resolveWireContext(i);this.sendResult(o,i.kind,f(await this.options.engine.getSourceFile({path:i.path,composition:n}),n));return}case"resolve-source-location":{let n=await this.resolveWireContext(i),r=f(await this.options.engine.resolveSourceLocation({key:i.key,composition:n}),n);this.sendResult(o,i.kind,r);return}case"execute":{let n=await this.resolveOperationWireContext(i.request),r=await this.resolveWireContext(i);if(I(n)!==I(r))throw new S(W,"The execute request composition does not match its operation composition.");let a=await this.normalizeOperationRequest(i.request,n);await this.handleBufferedOperation(o,i.kind,()=>this.options.engine.execute(a));return}case"undo":case"redo":{let n=await this.resolveWireContext(i);await this.handleBufferedOperation(o,i.kind,()=>i.kind==="undo"?this.options.engine.undo(n):this.options.engine.redo(n));return}}}catch(s){let i=l.extractRequestInfo(e);this.sendJson({type:"error",payload:{...i,message:T(s),code:_(s)}})}}async resolve(e){return this.options.engine.resolveComposition(e)}async resolveAndAssert(e){let s=await this.resolve(e),i=this.session.activeComposition;if(!i)throw new S(M,"Initialize a composition session before issuing this request.");if(I(i)!==I(s.context))throw new S(W,"The request composition does not match the active socket session.");return s.context}async resolveWireContext(e){let s=v(e);return this.resolveAndAssert(s)}async resolveOperationWireContext(e){let s=de(e);return this.resolveAndAssert(s)}activateSession(e){this.session.activeComposition=e,this.session.subscribedCompositionKeys.clear(),this.session.subscribedCompositionKeys.add(I(e))}async normalizeOperationRequest(e,s){let i={...e,composition:j(s)};if(i.target.kind==="route"){let o=i.target,n=v(o),r=await this.resolveAndAssert(n);i.target={...o,composition:j(r)}}return i}handleEngineEvent(e){let s=e?.composition;if(!ue(s))return;let i=I(s);this.session.subscribedCompositionKeys.has(i)&&(this.eventDispatcher.push(e),e.type==="site-edit.graph.invalidated"&&i===he(this.session)&&(this.session.activeComposition=void 0,this.session.subscribedCompositionKeys.delete(i)))}sendResult(e,s,i){this.sendJson({type:"response",payload:{id:e,kind:s,result:i}})}async handleRawMessage(e){try{await this.handleMessage(l.parseMessage(e,{validateOperationRequest:this.options.validateOperationRequest}))}catch(s){let i=le(e);this.sendJson({type:"error",payload:{...i,message:T(s),code:_(s)}})}}sendJson(e){this.options.socket.send(l.stringifyMessage(e))}async handleBufferedOperation(e,s,i){this.eventDispatcher.beginBuffering();try{let o=await i();this.sendResult(e,s,o)}catch(o){this.sendJson({type:"error",payload:{id:e,kind:s,message:T(o),code:_(o)}})}finally{this.eventDispatcher.flush()}}},S=class extends Error{constructor(e,s){super(s),this.code=e,this.name="BridgeProtocolError"}},O=class{constructor(e){this.send=e,this.bufferedEvents=null}push(e){let s={type:"event",payload:{event:e}};if(this.bufferedEvents){this.bufferedEvents.push(s);return}this.send(s)}beginBuffering(){this.bufferedEvents=[]}flush(){let e=this.bufferedEvents??[];this.bufferedEvents=null,e.forEach(s=>this.send(s))}},D=class{constructor(e=64){this.maxQueued=e,this.queue=Promise.resolve(),this.queued=0}enqueue(e){if(this.queued>=this.maxQueued)throw new Error("Bridge request queue is full");this.queued+=1;let s=async()=>{this.queued-=1,await e()},i=this.queue.then(s,s);return this.queue=i.then(()=>{},()=>{}),i}};function ae(t,e){if(!d(t)||typeof t.id!="string"||!l.isRequestKind(t.kind))return!1;let s=x(t.composition);switch(t.kind){case"initialize-session":return s&&(t.mutationContext===void 0||k(t.mutationContext));case"get-document":case"get-style-context":return s;case"get-object-edit-context":case"get-class-name-source":case"resolve-source-location":return typeof t.key=="string"&&s;case"get-history-status":return s;case"get-source-tree":return s;case"get-source-file":return typeof t.path=="string"&&s;case"execute":return s&&ce(t.request)&&(t.request.mutationContext===void 0||k(t.request.mutationContext))&&(e.validateOperationRequest?.(t.request)??!0);case"undo":case"redo":return s&&t.mutationContext===void 0||s&&k(t.mutationContext)}}function ce(t){return d(t)&&typeof t.id=="string"&&typeof t.siteId=="string"&&typeof t.baseSnapshotId=="string"&&x(t.composition)&&typeof t.kind=="string"&&d(t.target)&&(t.target.kind!=="route"||x(t.target.composition))&&typeof t.documentVersion=="number"&&Number.isInteger(t.documentVersion)&&t.documentVersion>=0&&d(t.params)}function x(t){return d(t)&&typeof t.routeId=="string"&&t.routeId.length>0&&(t.templateId===void 0||typeof t.templateId=="string"&&t.templateId.length>0)&&Object.keys(t).every(e=>e==="routeId"||e==="templateId")}function ue(t){return d(t)&&typeof t.routeId=="string"&&(t.effectiveTemplateId===void 0||typeof t.effectiveTemplateId=="string")}function v(t){if(x(t.composition))return t.composition;throw new S(M,"A composition selector is required for this request.")}function de(t){if(d(t)&&x(t.composition))return t.composition;throw new S(M,"A composition selector is required for execute.")}function j(t){return{routeId:t.routeId,...t.effectiveTemplateId?{templateId:t.effectiveTemplateId}:{}}}function he(t){return t.activeComposition?I(t.activeComposition):null}function I(t){return JSON.stringify([t.routeId,t.effectiveTemplateId??null])}function f(t,e){return d(t)&&t.ok===!0?{...t,composition:e}:t}function pe(t,e){return!d(t)||t.ok!==!0?t:{...t,...e?{composition:e}:{},data:z(t.data)}}function z(t){let e=t;return U(e.routeId?e:{...e,routeId:e.composition.routeId})}function d(t){return typeof t=="object"&&t!==null}function k(t){return d(t)&&typeof t.editingSessionId=="string"&&t.editingSessionId.length>0&&typeof t.lockId=="string"&&t.lockId.length>0&&typeof t.ownerId=="string"&&t.ownerId.length>0&&typeof t.leaseAssertion=="string"&&t.leaseAssertion.length>0}function _(t){if(!(!d(t)||typeof t.code!="string"||t.code.length===0))return t.code}function T(t){return t instanceof Error||d(t)&&typeof t.message=="string"&&t.message.length>0?t.message:"Unknown websocket operation failure"}function le(t){try{return l.extractRequestInfo(JSON.parse(t))}catch{return{id:"unknown",kind:"get-document"}}}var E=class{constructor(){this.tail=Promise.resolve()}run(e){let s=this.tail.then(e,e);return this.tail=s.then(()=>{},()=>{}),s}};import{SiteEditOperationRequestSchema as be,computeSiteEditCompositionKey as w}from"@vcp-dev/contracts";var ve="127.0.0.1",ke=30218,_e="/__vcp/site-edit/bridge",X=6*1024*1024,Te=X*2,Oe=3e3,L=50,$="__VCP_SITE_EDIT_BRIDGE_SERVERS__";function nt(t){let e=ee(t),s=se(e),i=te(),o=i.get(s);if(o)return o;let n=new b(e);i.set(s,n);try{n.start()}catch(r){throw i.delete(s),n.stop(),r}return n}function ot(t,e,s={}){let i=new b(ee(e),t,!1,s);return i.start({listen:!1}),i}var b=class{constructor(e,s=me.createServer((n,r)=>{r.writeHead(404),r.end("VCP site edit bridge server")}),i=!0,o={}){this.options=e,this.server=s,this.closeHttpServerOnStop=i,this.dependencies=o,this.runtime=null,this.activeHistorySessionId=null,this.historySessionTransition=Promise.resolve(),this.mutationQueue=new E,this.eventListeners=new Set,this.routes=[],this.compositions=[],this.compositionFiles=[],this.compositionResolutionError=null,this.stopWatching=null,this.stopWebSocketServer=null,this.pendingChangedFiles=new Set,this.fileChangeTimer=null,this.isStarted=!1,this.runtimeVersionFloors=new Map,this.activeHistoryStore=null,this.versionPersistence=Promise.resolve()}start(e={}){if(this.isStarted)return;this.refreshCompositions(!0),this.isStarted=!0,this.createRuntime();let s=Be({server:this.server,path:this.options.path,sessionKey:this.options.sessionKey,host:this.options.host,allowedOrigins:this.options.allowedOrigins,engine:this.createBridgeEngine()});this.stopWebSocketServer=s.stop,this.stopWatching=new Ee({projectRoot:this.options.projectRoot,watch_dirs:De(this.options.runtime.watch_dirs),interval_ms:this.options.runtime.watch_interval_ms,debounce_ms:this.options.runtime.watch_debounce_ms??L,max_dirs:this.options.runtime.watch_max_dirs,max_files:this.options.runtime.watch_max_files,max_depth:this.options.runtime.watch_max_depth,max_startup_ms:this.options.runtime.watch_max_startup_ms,on_change:i=>this.handleFileChanged(i),on_batch_change:i=>this.handleFilesChanged(i)}).start(),e.listen!==!1&&this.server.listen(this.options.port,this.options.host)}getHealth(){let e=!!this.runtime&&!this.compositionResolutionError;return{ok:this.isStarted&&e,bridgePath:this.options.path,runtimeReady:e,routesIndexed:this.routes.length,sessionRequired:!!this.options.sessionKey}}stop(){this.stopWatching?.(),this.stopWatching=null,this.flushChangedFiles(),this.fileChangeTimer&&(clearTimeout(this.fileChangeTimer),this.fileChangeTimer=null),this.stopWebSocketServer?.(),this.stopWebSocketServer=null,this.runtime?.dispose(),this.runtime=null,this.compositions=[],this.compositionFiles=[],this.compositionResolutionError=null,this.closeHttpServerOnStop&&this.server.close();let e=te(),s=se(this.options);e.get(s)===this&&e.delete(s),this.isStarted=!1}createRuntime(e,s=null){let i=this.runtime;this.activeHistoryStore=e??null;let o=(this.dependencies.createRuntime??Ie)({...this.options.tenantId?{tenantId:this.options.tenantId}:{},siteId:this.options.siteId,snapshotId:this.options.snapshotId,projectRoot:this.options.projectRoot,compositions:this.compositions,onEvent:n=>{"version"in n&&typeof n.version=="number"&&this.recordRuntimeVersion(n.version,"composition"in n?n.composition:void 0);for(let r of this.eventListeners)r(n)},...e?{historyStore:e}:{},...this.getInitialDocumentVersions().length>0?{initialDocumentVersions:this.getInitialDocumentVersions()}:{}});this.runtime=o,this.activeHistorySessionId=s,i?.dispose()}createBridgeEngine(){return{resolveComposition:e=>this.resolveComposition(e),initializeSession:e=>this.mutationQueue.run(async()=>{let s=await this.bindHistorySession(this.options.snapshotId);if(!s.ok)throw new Error(`${s.code}: ${s.message}`);let i=Ae(e.composition),o=this.getRuntime(),n=m(i);await o.initializeComposition(n);let a=o.getDocument(n).data;await this.recordRuntimeVersion(a.version,i);let c=(await o.getHistoryStatus()).data;return{ok:!0,composition:i,data:{document:a,historyStatus:c}}}),getDocument:async e=>{let s=this.getRuntime(),i=m(e);await s.initializeComposition(i);let o=s.getDocument(i);return await this.recordRuntimeVersion(o.data.version,e),{...o,composition:e}},getHistoryStatus:async e=>({...await this.getRuntime().getHistoryStatus(),composition:e}),getStyleContext:async e=>this.getRuntime().getStyleContext(m(e)),getObjectEditContext:async(e,s)=>this.getRuntime().getObjectEditContext(e,m(s)),getClassNameSource:async(e,s)=>this.getRuntime().getClassNameSource(e,m(s)),getSourceTree:async e=>this.getRuntime().getSourceTree(m(e)),getSourceFile:async e=>this.getRuntime().getSourceFile({path:e.path,composition:m(e.composition)}),resolveSourceLocation:async e=>this.getRuntime().resolveSourceLocation({key:e.key,composition:m(e.composition)}),execute:(e,s)=>this.mutationQueue.run(async()=>{let i=await this.bindHistorySession(this.options.snapshotId);if(!i.ok)return F(i,e);let o=await this.getRuntime().executeOperation(e);return o.data?.resultVersion!==void 0&&await this.recordRuntimeVersion(o.data.resultVersion,o.composition),o}),undo:e=>this.mutationQueue.run(async()=>{let s=await this.bindHistorySession(this.options.snapshotId);if(!s.ok)return F(s,void 0,e);let i=await this.getRuntime().undo();return i.data?.resultVersion!==void 0&&await this.recordRuntimeVersion(i.data.resultVersion,i.composition??e),i.composition?i:{...i,composition:e}}),redo:e=>this.mutationQueue.run(async()=>{let s=await this.bindHistorySession(this.options.snapshotId);if(!s.ok)return F(s,void 0,e);let i=await this.getRuntime().redo();return i.data?.resultVersion!==void 0&&await this.recordRuntimeVersion(i.data.resultVersion,i.composition??e),i.composition?i:{...i,composition:e}}),subscribe:e=>(this.eventListeners.add(e),()=>this.eventListeners.delete(e))}}async bindHistorySession(e){if(!this.options.historyRoot)return{ok:!1,code:"RECOVERY_PERSIST_FAILED",message:"Durable edit history is not configured."};if(this.activeHistorySessionId===e)return{ok:!0};let s=this.historySessionTransition.then(async()=>{if(this.activeHistorySessionId===e)return;let i=await(this.dependencies.openHistoryStore??Se)(Fe({root:this.options.historyRoot,siteId:this.options.siteId,snapshotId:this.options.snapshotId,editingSessionId:e}));if(!this.isStarted)return;let o=i.readDocumentVersion?await i.readDocumentVersion():0,n=this.compositions[0]?.context;if(n){let r=w(n);this.runtimeVersionFloors.set(r,Math.max(this.runtimeVersionFloors.get(r)??0,o))}this.createRuntime(i,e)});this.historySessionTransition=s.catch(()=>{});try{return await s,{ok:!0}}catch{return{ok:!1,code:"RECOVERY_PERSIST_FAILED",message:"Durable edit history could not be opened."}}}recordRuntimeVersion(e,s){let i=s?w(s):null;i&&this.runtimeVersionFloors.set(i,Math.max(this.runtimeVersionFloors.get(i)??0,e));let o=this.activeHistoryStore;if(!o?.writeDocumentVersion)return Promise.resolve();let n=i?this.runtimeVersionFloors.get(i)??e:e;return this.versionPersistence=this.versionPersistence.then(()=>o.writeDocumentVersion(n)).catch(()=>{}),this.versionPersistence}handleFileChanged(e){this.handleFilesChanged([e])}handleFilesChanged(e){for(let i of e)this.pendingChangedFiles.add(i);this.fileChangeTimer&&clearTimeout(this.fileChangeTimer);let s=this.options.runtime.watch_debounce_ms??L;this.fileChangeTimer=setTimeout(()=>{this.fileChangeTimer=null,this.flushChangedFiles()},s),this.fileChangeTimer?.unref?.()}flushChangedFiles(){if(this.fileChangeTimer&&(clearTimeout(this.fileChangeTimer),this.fileChangeTimer=null),this.pendingChangedFiles.size===0)return;let e=[...this.pendingChangedFiles].sort((s,i)=>s.localeCompare(i));if(this.pendingChangedFiles.clear(),!!this.refreshCompositions(!1))for(let s of e)this.runtime?.notifyFileChanged(s)}refreshCompositions(e=!1){try{let s=Me(this.options.projectRoot),i=Re(s),o=i.length>0?i:(this.options.runtime.routes??[]).map(c=>({...c})),n=Ce({files:s});if(n.length===0)throw new Error("No canonical App Router composition is indexed by the preview bridge.");let r=new Map(this.compositions.map(c=>[w(c.context),c])),a=new Map(n.map(c=>[w(c.context),c]));if(this.runtime){for(let[c,p]of r){let y=a.get(c);(!y||y.entryFile!==p.entryFile)&&this.runtime.unregisterComposition(m(p.context))}for(let[c,p]of a){let y=r.get(c);(!y||y.entryFile!==p.entryFile)&&this.runtime.registerComposition(p.context,p.entryFile)}}return this.routes=o,this.compositions=n,this.compositionFiles=s,this.compositionResolutionError=null,!0}catch(s){let i=s instanceof Error?s:new Error(String(s));if(this.compositionResolutionError=i,e)throw i;return!1}}resolveComposition(e){if(this.compositionResolutionError)throw this.compositionResolutionError;let s=xe(e.routeId,this.routes,this.options.basePath);if(!s)throw new Error(`Route is not indexed by the preview bridge: ${e.routeId}`);let i=this.routes.find(r=>r.routeId===s);if(!i)throw new Error(`Route is not indexed by the preview bridge: ${e.routeId}`);let o=we({selector:{routeId:s,...e.templateId?{templateId:e.templateId}:{}},files:this.compositionFiles,canonicalEntryFile:i.entryFile}),n=w(o.context);if(!this.compositions.some(r=>w(r.context)===n))throw new Error(`Composition is not registered by the preview bridge: ${n}`);return o}getInitialDocumentVersions(){return this.compositions.flatMap(e=>{let s=this.runtimeVersionFloors.get(w(e.context));return s===void 0?[]:[{composition:e.context,version:s}]})}getRuntime(){if(!this.runtime)throw new Error("VCP site edit preview bridge runtime is not ready");return this.runtime}};function ee(t){return{tenantId:t.tenantId,siteId:t.siteId,snapshotId:t.snapshotId,projectRoot:g.resolve(t.projectRoot??process.cwd()),basePath:t.basePath??"",host:t.host??ve,port:t.port??ke,path:t.path??_e,sessionKey:t.sessionKey??Ue(),historyRoot:t.historyRoot,allowedOrigins:t.allowedOrigins??[],runtime:t.runtime??{}}}function De(t){let e=["app","src/app","components/site","src/components/site","lib/generated","src/lib/generated","public"];return[...new Set([...t?.length?t:e,".vcp"])]}function Me(t){let e=[],s=["app","src/app",".vcp"],i=new Set([".git",".next",".turbo","coverage","dist","node_modules","output","snapshot-store"]),o=n=>{if(!A.existsSync(n))return;let r;try{r=A.readdirSync(n,{withFileTypes:!0})}catch{return}for(let a of r){if(a.name.startsWith(".")&&a.name!==".vcp")continue;if(a.isDirectory()){if(i.has(a.name))continue;o(g.join(n,a.name));continue}if(!a.isFile())continue;let c=g.join(n,a.name),p="";try{p=A.readFileSync(c,"utf8")}catch{}e.push({path:g.relative(t,c).replaceAll(g.sep,"/"),content:p})}};for(let n of s)o(g.join(t,n));return e.sort((n,r)=>n.path.localeCompare(r.path))}function Ae(t){if(!t||typeof t!="object"||typeof t.routeId!="string")throw new Error("Normalized composition context is required.");if("effectiveTemplateId"in t)return t;let e=t;return{routeId:e.routeId,...e.templateId?{effectiveTemplateId:e.templateId}:{}}}function m(t){return{routeId:t.routeId,...t.effectiveTemplateId?{templateId:t.effectiveTemplateId}:{}}}function Fe(t){return g.join(g.resolve(t.root),J(t.siteId),J(t.snapshotId),Y("sha256").update(t.editingSessionId).digest("hex").slice(0,32))}function J(t){return/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(t)&&t!=="."&&t!==".."?t:Y("sha256").update(t).digest("hex").slice(0,32)}function te(){let t=globalThis;return t[$]??=new Map,t[$]}function se(t){return`${t.projectRoot}:${t.host}:${t.port}:${t.path}:${t.historyRoot??""}`}function F(t,e,s){let i=s??(e?.composition?{routeId:e.composition.routeId,...e.composition.templateId?{effectiveTemplateId:e.composition.templateId}:{}}:void 0);if(!i)throw new Error("A normalized composition is required to construct a mutation result.");return{ok:!1,composition:i,error:{code:t.code,message:t.message},data:{requestId:e?.id??"mutation-context",kind:e?.kind??"update-text",composition:i,target:e?.target??{kind:"node",key:""},resultVersion:e?.documentVersion??0}}}function Be(t){let e=new ye({maxPayload:X,noServer:!0}),s=new WeakSet,i=n=>{new R({socket:new K(n),engine:t.engine,validateOperationRequest:r=>be.safeParse(r).success})},o=(n,r,a)=>{if(!Ke(n,t))return;let c=qe(n,t);if(!c){r.write(`HTTP/1.1 401 Unauthorized\r
|
|
2
2
|
Connection: close\r
|
|
3
3
|
\r
|
|
4
|
-
`),r.destroy();return}
|
|
4
|
+
`),r.destroy();return}c.authenticatedByHeader&&s.add(n),e.handleUpgrade(n,r,a,p=>{e.emit("connection",p,n)})};return t.server.on("upgrade",o),e.on("connection",(n,r)=>{if(s.has(r)){i(n);return}He(n,t.sessionKey,()=>{i(n)})}),e.stop=()=>{t.server.off("upgrade",o);for(let n of e.clients)n.close(1001,"bridge stopped");e.close()},e}var K=class{constructor(e){this.socket=e,this.onmessage=null,this.onclose=null,e.on("error",()=>{}),e.on("message",s=>{this.onmessage?.({data:s.toString()})}),e.on("close",()=>{this.onclose?.()})}send(e){if(this.socket.readyState===Z.OPEN){if(this.socket.bufferedAmount+Buffer.byteLength(e,"utf8")>Te){this.socket.close(1013,"bridge backpressure");return}this.socket.send(e)}}close(e,s){this.socket.close(e,s)}};function Ke(t,e){return new URL(t.url??"/","http://localhost").pathname===e.path}function qe(t,e){if(new URL(t.url??"/","http://localhost").searchParams.has("vcp_bridge_key"))return null;let i=B(t.headers["x-vcp-site-edit-key"]),o=ie(i,e.sessionKey),n=B(t.headers.host),r=B(t.headers.origin);return n&&!Ve(n,e.host,r)?null:r?Ne(r,n,e.allowedOrigins)?{authenticatedByHeader:o}:null:o?{authenticatedByHeader:!0}:null}function He(t,e,s){let i=setTimeout(()=>{t.close(1008,"bridge authentication timeout")},Oe),o,n=()=>{clearTimeout(i),t.off("message",o),t.off("close",n)},r=()=>{n(),t.close(1008,"bridge authentication failed")};o=a=>{try{let c=l.parseMessage(a.toString());if(c.type!=="auth"||!ie(c.payload.key,e)){r();return}n(),t.readyState===Z.OPEN&&t.send(l.stringifyMessage({type:"auth-ok",payload:{ok:!0}})),s()}catch{r()}},t.on("message",o),t.on("close",n)}function ie(t,e){if(!t)return!1;let s=Buffer.from(t),i=Buffer.from(e);return s.length===i.length&&ge(s,i)}function Ve(t,e,s){let i=G(t),o=G(e);return i===o||Q(o)&&Q(i)&&(!s||q(s,t))||Pe(o)&&(!s||q(s,t))}function Pe(t){return t==="0.0.0.0"||t==="::"}function Q(t){return t==="localhost"||t==="127.0.0.1"||t==="::1"}function Ne(t,e,s){return s.includes(t)||(e?q(t,e):!1)}function q(t,e){try{return new URL(t).host===ne(e)}catch{return!1}}function G(t){let e=ne(t);return e.startsWith("[")?e.slice(1,e.indexOf("]")):e.split(":").length-1===1?e.split(":",1)[0]??"":e}function ne(t){return t.trim().toLowerCase()}function B(t){return Array.isArray(t)?t[0]:t}function Ue(){return fe(32).toString("base64url")}export{Te as SITE_EDIT_BRIDGE_MAX_BUFFERED_BYTES,X as SITE_EDIT_BRIDGE_MAX_PAYLOAD_BYTES,b as SiteEditBridgeServer,ot as attachSiteEditBridgeServer,Be as attachSiteEditWebSocketServer,nt as ensureSiteEditBridgeServerStarted};
|
package/dist/window-message.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SiteEditCommandSuccess, SiteEditClassNameSourceStyleContext, SiteEditEvent, SiteEditObjectEditContext, SiteEditGetClassNameSourceCommandResult, SiteEditOperationCommandResult, SiteEditOperationRequest, SiteEditRenderDocument, SiteEditSourceFileResponse, SiteEditSourceLocation, SiteEditSourceTreeResponse } from "@vcp-dev/contracts";
|
|
1
|
+
import type { SiteEditCommandSuccess, SiteEditClassNameSourceStyleContext, SiteEditCompositionContext, SiteEditCompositionSelector, SiteEditEvent, SiteEditObjectEditContext, SiteEditGetClassNameSourceCommandResult, SiteEditOperationCommandResult, SiteEditOperationRequest, SiteEditRenderDocument, SiteEditSourceFileResponse, SiteEditSourceLocation, SiteEditSourceTreeResponse } from "@vcp-dev/contracts";
|
|
2
2
|
import type { SiteEditHistoryStatus } from "./protocol.js";
|
|
3
3
|
export declare const VCP_WINDOW_MESSAGE_SOURCE = "vcp-window-message";
|
|
4
4
|
export declare const VCP_WINDOW_MESSAGE_VERSION = 1;
|
|
@@ -62,6 +62,7 @@ export type SiteEditFrameRuntimeResizeSession = {
|
|
|
62
62
|
startHeight: number;
|
|
63
63
|
width: number;
|
|
64
64
|
height: number;
|
|
65
|
+
baselineStyleDeclarations?: SiteEditFrameRuntimeStyleDeclaration[];
|
|
65
66
|
};
|
|
66
67
|
export type SiteEditFrameRuntimeNodePatch = {
|
|
67
68
|
attributes?: Record<string, string | null>;
|
|
@@ -114,7 +115,8 @@ export type SiteEditFrameRuntimeDropTarget = {
|
|
|
114
115
|
export type SiteEditFrameRuntimeBridgeStatusCode = "connecting" | "ready" | "reconnecting" | "failed" | "reload-required";
|
|
115
116
|
export type SiteEditFrameRuntimeBridgeStatus = {
|
|
116
117
|
state: SiteEditFrameRuntimeBridgeStatusCode;
|
|
117
|
-
|
|
118
|
+
composition: SiteEditCompositionContext;
|
|
119
|
+
sequence: number;
|
|
118
120
|
attempt?: number;
|
|
119
121
|
retryInMs?: number;
|
|
120
122
|
messageKey?: string;
|
|
@@ -132,13 +134,16 @@ export type SiteEditFrameRuntimeRequestBody = {
|
|
|
132
134
|
type: "request";
|
|
133
135
|
id: string;
|
|
134
136
|
kind: "bridge-get-source-tree";
|
|
135
|
-
payload:
|
|
137
|
+
payload: {
|
|
138
|
+
composition: SiteEditCompositionSelector;
|
|
139
|
+
};
|
|
136
140
|
} | {
|
|
137
141
|
type: "request";
|
|
138
142
|
id: string;
|
|
139
143
|
kind: "bridge-get-source-file";
|
|
140
144
|
payload: {
|
|
141
145
|
path: string;
|
|
146
|
+
composition: SiteEditCompositionSelector;
|
|
142
147
|
};
|
|
143
148
|
} | {
|
|
144
149
|
type: "request";
|
|
@@ -146,7 +151,7 @@ export type SiteEditFrameRuntimeRequestBody = {
|
|
|
146
151
|
kind: "bridge-resolve-source-location";
|
|
147
152
|
payload: {
|
|
148
153
|
key: string;
|
|
149
|
-
|
|
154
|
+
composition: SiteEditCompositionSelector;
|
|
150
155
|
};
|
|
151
156
|
} | {
|
|
152
157
|
type: "request";
|
|
@@ -270,14 +275,14 @@ export type SiteEditFrameRuntimeRequestBody = {
|
|
|
270
275
|
id: string;
|
|
271
276
|
kind: "bridge-initialize-session";
|
|
272
277
|
payload: {
|
|
273
|
-
|
|
278
|
+
composition: SiteEditCompositionSelector;
|
|
274
279
|
};
|
|
275
280
|
} | {
|
|
276
281
|
type: "request";
|
|
277
282
|
id: string;
|
|
278
283
|
kind: "bridge-get-document" | "bridge-ensure-document-version" | "bridge-acknowledge-document-version";
|
|
279
284
|
payload: {
|
|
280
|
-
|
|
285
|
+
composition: SiteEditCompositionSelector;
|
|
281
286
|
minVersion?: number;
|
|
282
287
|
version?: number;
|
|
283
288
|
};
|
|
@@ -285,13 +290,15 @@ export type SiteEditFrameRuntimeRequestBody = {
|
|
|
285
290
|
type: "request";
|
|
286
291
|
id: string;
|
|
287
292
|
kind: "bridge-get-history-status";
|
|
288
|
-
payload:
|
|
293
|
+
payload: {
|
|
294
|
+
composition: SiteEditCompositionSelector;
|
|
295
|
+
};
|
|
289
296
|
} | {
|
|
290
297
|
type: "request";
|
|
291
298
|
id: string;
|
|
292
299
|
kind: "bridge-get-style-context";
|
|
293
300
|
payload: {
|
|
294
|
-
|
|
301
|
+
composition: SiteEditCompositionSelector;
|
|
295
302
|
};
|
|
296
303
|
} | {
|
|
297
304
|
type: "request";
|
|
@@ -299,26 +306,30 @@ export type SiteEditFrameRuntimeRequestBody = {
|
|
|
299
306
|
kind: "bridge-get-object-edit-context" | "bridge-get-class-name-source";
|
|
300
307
|
payload: {
|
|
301
308
|
key: string;
|
|
302
|
-
|
|
309
|
+
composition: SiteEditCompositionSelector;
|
|
303
310
|
};
|
|
304
311
|
} | {
|
|
305
312
|
type: "request";
|
|
306
313
|
id: string;
|
|
307
314
|
kind: "bridge-execute";
|
|
308
315
|
payload: {
|
|
316
|
+
composition: SiteEditCompositionSelector;
|
|
309
317
|
request: SiteEditOperationRequest;
|
|
310
318
|
};
|
|
311
319
|
} | {
|
|
312
320
|
type: "request";
|
|
313
321
|
id: string;
|
|
314
322
|
kind: "bridge-undo" | "bridge-redo";
|
|
315
|
-
payload:
|
|
323
|
+
payload: {
|
|
324
|
+
composition: SiteEditCompositionSelector;
|
|
325
|
+
};
|
|
316
326
|
} | {
|
|
317
327
|
type: "request";
|
|
318
328
|
id: string;
|
|
319
329
|
kind: "bridge-subscribe" | "bridge-unsubscribe";
|
|
320
330
|
payload: {
|
|
321
331
|
subscriptionId: string;
|
|
332
|
+
composition: SiteEditCompositionSelector;
|
|
322
333
|
};
|
|
323
334
|
};
|
|
324
335
|
export type SiteEditFrameRuntimeMargin = {
|
|
@@ -501,6 +512,7 @@ export type SiteEditFrameRuntimeEventBody = {
|
|
|
501
512
|
kind: "bridge-event";
|
|
502
513
|
payload: {
|
|
503
514
|
subscriptionId: string;
|
|
515
|
+
composition: SiteEditCompositionContext;
|
|
504
516
|
event: SiteEditEvent;
|
|
505
517
|
};
|
|
506
518
|
} | {
|
|
@@ -522,8 +534,10 @@ export type SiteEditFrameRuntimeEventBody = {
|
|
|
522
534
|
type: "event";
|
|
523
535
|
kind: "route-ready";
|
|
524
536
|
payload: {
|
|
525
|
-
|
|
526
|
-
|
|
537
|
+
composition: SiteEditCompositionContext;
|
|
538
|
+
editEngineVersion: string;
|
|
539
|
+
sequence: number;
|
|
540
|
+
version: number;
|
|
527
541
|
};
|
|
528
542
|
} | {
|
|
529
543
|
type: "event";
|
package/dist/window-message.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var _="vcp-window-message",ce=1;function M(e){return{source:_,version:1,namespace:e.namespace,channel:e.channel,...e.sessionKey?{sessionKey:e.sessionKey}:{},body:e.body}}function W(e){try{return i(e)?d(e,"source",_)&&d(e,"version",1)&&s(e,"namespace")&&s(e,"channel")&&u(e,"body")&&(!l(e,"sessionKey")||s(e,"sessionKey")):!1}catch{return!1}}var O="site-edit",N="frame-runtime",C=1,R=1,w=1,ae=24;function de(e,r={}){return M({namespace:O,channel:N,sessionKey:r.sessionKey,body:e})}function ue(e){try{return!W(e)||e.namespace!==O||e.channel!==N?!1:oe(e.body)}catch{return!1}}var l=(e,r)=>Object.prototype.hasOwnProperty.call(e,r);function u(e,r){let t=Object.getOwnPropertyDescriptor(e,r);return t!==void 0&&"value"in t}function n(e,r){return Object.getOwnPropertyDescriptor(e,r)?.value}function d(e,r,t){return u(e,r)&&n(e,r)===t}function s(e,r){return u(e,r)&&typeof n(e,r)=="string"}function S(e,r){return u(e,r)&&typeof n(e,r)=="boolean"}function o(e,r){let t=n(e,r);return u(e,r)&&typeof t=="number"&&Number.isFinite(t)}function K(e,r){let t=n(e,r);return u(e,r)&&typeof t=="number"&&Number.isInteger(t)&&t>0}function g(e,r){return!l(e,r)||n(e,r)===void 0||s(e,r)}function y(e,r){return!l(e,r)||n(e,r)===void 0||o(e,r)}function b(e,r){let t=n(e,r);return!l(e,r)||t===void 0||u(e,r)&&typeof t=="number"&&Number.isInteger(t)&&t>=0}function a(e,r){return!l(e,r)||n(e,r)===void 0}function i(e){if(typeof e!="object"||e===null||Array.isArray(e))return!1;let r=Object.getPrototypeOf(e);return r===Object.prototype||r===null}function G(e){return i(e)&&Reflect.ownKeys(e).length===0}function A(e){if(!Array.isArray(e))return!1;for(let r=0;r<e.length;r+=1){let t=Object.getOwnPropertyDescriptor(e,String(r));if(t===void 0||!("value"in t)||typeof t.value!="string")return!1}return!0}function p(e){return i(e)&&s(e,"key")&&b(e,"instanceIndex")&&b(e,"instanceCount")&&b(e,"textSegmentIndex")}function B(e){return i(e)&&s(e,"blockId")&&p(n(e,"ref"))&&h(n(e,"rect"))&&S(e,"targetIsSectionRoot")}function L(e){if(!i(e))return!1;let r=n(e,"placement"),t=n(e,"boundary");return s(e,"anchorBlockId")&&p(n(e,"anchorRef"))&&(r==="before"||r==="after")&&i(t)&&o(t,"top")&&o(t,"left")&&o(t,"width")}function h(e){return i(e)&&["top","left","width","height"].every(r=>o(e,r))}function x(e){if(!i(e))return!1;let r=n(e,"rect"),t=n(e,"layout"),c=i(t)?n(t,"containingBlock"):null,f=n(e,"scrollContext"),E=i(c)&&(d(c,"kind","viewport")&&Reflect.ownKeys(c).length===1||d(c,"kind","document")&&Reflect.ownKeys(c).length===1||d(c,"kind","element")&&s(c,"runtimeNodeId"));return d(e,"version",C)&&s(e,"runtimeNodeId")&&i(r)&&h(n(r,"viewport"))&&h(n(r,"document"))&&i(t)&&s(t,"position")&&s(t,"transform")&&E&&i(f)&&["scrollX","scrollY","viewportWidth","viewportHeight"].every(m=>o(f,m))&&u(f,"scrollContainers")&&z(n(f,"scrollContainers"))}function z(e){return Array.isArray(e)&&e.every(r=>i(r)&&s(r,"runtimeNodeId")&&o(r,"scrollLeft")&&o(r,"scrollTop"))}function I(e){return i(e)&&(a(e,"layoutSnapshot")||x(n(e,"layoutSnapshot")))}function U(e){return i(e)&&p(n(e,"ref"))&&u(e,"layoutSnapshot")&&x(n(e,"layoutSnapshot"))&&(a(e,"childBoxes")||H(n(e,"childBoxes")))&&(a(e,"childRects")||q(n(e,"childRects")))&&(a(e,"layout")||j(n(e,"layout")))&&(a(e,"spacing")||X(n(e,"spacing")))}function j(e){if(!i(e))return!1;let r=n(e,"indicatorOrientation");return s(e,"display")&&(r==="horizontal"||r==="vertical")&&g(e,"flexDirection")&&g(e,"gridAutoFlow")}function q(e){return Array.isArray(e)&&e.every(r=>h(r))}function H(e){return Array.isArray(e)&&e.every(r=>i(r)&&h(n(r,"rect"))&&T(n(r,"margin")))}function T(e){return i(e)&&["marginTop","marginRight","marginBottom","marginLeft"].every(r=>o(e,r))}function X(e){return T(e)&&["paddingTop","paddingRight","paddingBottom","paddingLeft","borderTopWidth","borderRightWidth","borderBottomWidth","borderLeftWidth","columnGap","rowGap"].every(r=>o(e,r))}function Y(e){if(!Array.isArray(e))return!1;for(let r=0;r<e.length;r+=1){let t=Object.getOwnPropertyDescriptor(e,String(r));if(t===void 0||!("value"in t)||!U(t.value))return!1}return!0}function Z(e){return i(e)&&Reflect.ownKeys(e).every(r=>typeof r=="string"&&u(e,r)&&(typeof n(e,r)=="string"||n(e,r)===null))}function V(e){return e==null||typeof e=="string"||typeof e=="number"&&Number.isFinite(e)}function k(e){return i(e)&&Reflect.ownKeys(e).every(r=>typeof r=="string"&&u(e,r)&&V(n(e,r)))}function J(e){if(!i(e))return!1;let r=n(e,"priority");return s(e,"property")&&u(e,"value")&&V(n(e,"value"))&&(!l(e,"priority")||r===void 0||r==="important")}function Q(e){return i(e)?(a(e,"attributes")||Z(n(e,"attributes")))&&g(e,"className")&&(a(e,"style")||k(n(e,"style")))&&(a(e,"styleDeclarations")||Array.isArray(n(e,"styleDeclarations"))&&n(e,"styleDeclarations").every(J)):!1}function $(e){return i(e)&&o(e,"x")&&o(e,"y")&&(a(e,"detailLevel")||d(e,"detailLevel","summary")||d(e,"detailLevel","full"))}function v(e){return i(e)&&p(n(e,"ref"))}function ee(e){if(!i(e)||!i(n(e,"variables")))return!1;let r=n(e,"variables");return Reflect.ownKeys(r).every(t=>typeof t=="string"&&s(r,t))?a(e,"stylesheets")||A(n(e,"stylesheets")):!1}function te(e){if(!d(e,"type","request")||!s(e,"id")||!s(e,"kind")||!u(e,"payload"))return!1;let r=n(e,"kind"),t=n(e,"payload");switch(r){case"hit-test-at-point":case"start-text-edit-at-point":return $(t);case"bridge-get-source-tree":case"get-scroll-metrics":case"clear-theme-override":case"bridge-get-history-status":case"bridge-undo":case"bridge-redo":return G(t);case"bridge-get-source-file":return i(t)&&s(t,"path");case"bridge-resolve-source-location":case"bridge-get-object-edit-context":case"bridge-get-class-name-source":return i(t)&&s(t,"key")&&g(t,"routeId");case"scroll-to":return i(t)&&o(t,"x")&&o(t,"y");case"scroll-by":return i(t)&&o(t,"deltaX")&&o(t,"deltaY");case"set-interaction-mode":return i(t)&&S(t,"enabled");case"set-selection-visual":return i(t)&&d(t,"version",R)&&p(n(t,"ref"))&&d(t,"visible",!0);case"clear-selection-visual":return i(t)&&d(t,"version",R);case"set-resize-visual":return i(t)&&d(t,"version",w)&&p(n(t,"ref"))&&d(t,"visible",!0);case"clear-resize-visual":return i(t)&&d(t,"version",w);case"set-theme-override":return ee(t);case"get-theme-variables":return i(t)&&A(n(t,"names"));case"compute-drop-target-at-point":return i(t)&&o(t,"x")&&o(t,"y")&&(d(t,"dragKind","insert")||d(t,"dragKind","move"))&&(a(t,"movingRef")||p(n(t,"movingRef")));case"observe-node-bounds":case"clear-node-bounds-observer":return i(t)&&(a(t,"ref")||p(n(t,"ref")));case"apply-node-patch":return i(t)&&p(n(t,"ref"))&&Q(n(t,"patch"))&&(a(t,"preview")||i(n(t,"preview"))&&s(n(t,"preview"),"sessionId")&&b(n(t,"preview"),"revision")&&l(n(t,"preview"),"revision"));case"get-hit-by-ref":case"get-path-by-ref":case"restore-text-edit":case"clear-text-edit-rollback":return v(t);case"bridge-initialize-session":case"bridge-get-style-context":return i(t)&&s(t,"routeId");case"bridge-get-document":case"bridge-ensure-document-version":case"bridge-acknowledge-document-version":return i(t)&&s(t,"routeId")&&y(t,"minVersion")&&y(t,"version");case"bridge-execute":return i(t)&&i(n(t,"request"));case"bridge-subscribe":case"bridge-unsubscribe":return i(t)&&s(t,"subscriptionId");default:return!1}}function re(e){return d(e,"type","response")&&s(e,"id")&&S(e,"ok")&&(a(e,"error")||s(e,"error"))}var ne=new Set(["pointer-down","pointer-move","pointer-leave","pointer-up","pointer-cancel","pointer-click","pointer-double-click"]),F=new Set(["e","s","se"]);function ie(e,r){if(a(e,"resizeSession"))return!0;let t=n(e,"resizeSession");if(!i(t))return!1;let c=n(e,"pointerId"),f=n(t,"pointerId"),E=n(t,"phase"),m=n(t,"edge"),D=r==="pointer-down"?"start":r==="pointer-up"?"commit":r==="pointer-cancel"?"cancel":null;return n(t,"version")===1&&E===D&&s(t,"sessionId")&&String(n(t,"sessionId")).length>0&&typeof c=="number"&&Number.isInteger(c)&&typeof f=="number"&&Number.isInteger(f)&&c===f&&typeof m=="string"&&F.has(m)&&n(e,"resizeEdge")===m&&p(n(t,"ref"))&&["startWidth","startHeight","width","height"].every(P=>o(t,P))}function se(e){if(!d(e,"type","event")||!s(e,"kind")||!i(n(e,"payload")))return!1;let r=n(e,"kind"),t=n(e,"payload");switch(r){case"text-edit-commit":case"text-edit-cancel":case"text-edit-exit":case"text-edit-input":return p(n(t,"ref"))&&g(t,"value")&&(a(t,"hit")||I(n(t,"hit")));case"node-bounds-change":return I(n(t,"hit"));case"geometry-batch":{let c=n(t,"reason");return K(t,"sequence")&&o(t,"sourceEventAt")&&o(t,"captureStartedAt")&&o(t,"capturedAt")&&(c==="scroll"||c==="resize"||c==="mutation")&&Y(n(t,"snapshots"))}case"bridge-event":return s(t,"subscriptionId")&&i(n(t,"event"));case"route-ready":return s(t,"routeId")&&y(t,"version");case"bridge-status":{let c=n(t,"state");return(c==="connecting"||c==="ready"||c==="reconnecting"||c==="failed"||c==="reload-required")&&g(t,"routeId")&&y(t,"attempt")&&y(t,"retryInMs")&&g(t,"messageKey")}case"scroll":{let c=n(t,"metrics");return i(c)&&["scrollX","scrollY","scrollWidth","scrollHeight","viewportWidth","viewportHeight"].every(f=>o(c,f))}default:return ne.has(r)&&o(t,"clientX")&&o(t,"clientY")&&y(t,"buttons")&&y(t,"pointerId")&&(a(t,"hoverVisualOwned")||S(t,"hoverVisualOwned"))&&(a(t,"resizeEdge")||s(t,"resizeEdge")&&F.has(n(t,"resizeEdge")))&&ie(t,r)&&(n(t,"hit")===null||I(n(t,"hit")))&&(a(t,"section")||n(t,"section")===null||B(n(t,"section")))&&(a(t,"sectionGap")||n(t,"sectionGap")===null||L(n(t,"sectionGap")))}}function oe(e){if(!i(e))return!1;switch(n(e,"type")){case"request":return te(e);case"response":return re(e);case"event":return se(e);default:return!1}}export{N as SITE_EDIT_FRAME_RUNTIME_CHANNEL,C as SITE_EDIT_FRAME_RUNTIME_LAYOUT_SNAPSHOT_VERSION,w as SITE_EDIT_FRAME_RUNTIME_RESIZE_VISUAL_VERSION,R as SITE_EDIT_FRAME_RUNTIME_SELECTION_VISUAL_VERSION,ae as SITE_EDIT_FRAME_SECTION_GAP_RADIUS_PX,O as SITE_EDIT_WINDOW_MESSAGE_NAMESPACE,_ as VCP_WINDOW_MESSAGE_SOURCE,ce as VCP_WINDOW_MESSAGE_VERSION,de as createSiteEditFrameRuntimeMessage,M as createVcpWindowMessageEnvelope,x as isSiteEditFrameRuntimeLayoutSnapshot,ue as isSiteEditFrameRuntimeMessage,W as isVcpWindowMessageEnvelope};
|
|
1
|
+
function S(e){return JSON.stringify([e.routeId,e.effectiveTemplateId??null])}var T="vcp-window-message",F=1;function B(e){return{source:T,version:F,namespace:e.namespace,channel:e.channel,...e.sessionKey?{sessionKey:e.sessionKey}:{},body:e.body}}function G(e){try{return i(e)?d(e,"source",T)&&d(e,"version",F)&&o(e,"namespace")&&o(e,"channel")&&f(e,"body")&&(!h(e,"sessionKey")||o(e,"sessionKey")):!1}catch{return!1}}var V="site-edit",C="frame-runtime",z=1,A=1,N=1,le=24;function ge(e,r={}){return B({namespace:V,channel:C,sessionKey:r.sessionKey,body:e})}function he(e){try{return!G(e)||e.namespace!==V||e.channel!==C?!1:ue(e.body)}catch{return!1}}function y(e){return i(e)&&o(e,"routeId")&&g(e,"templateId")&&m(e,["routeId","templateId"])}function R(e){return i(e)&&o(e,"routeId")&&g(e,"effectiveTemplateId")&&m(e,["routeId","effectiveTemplateId"])}function m(e,r){let t=new Set(r);return Reflect.ownKeys(e).every(s=>typeof s=="string"&&t.has(s))}var h=(e,r)=>Object.prototype.hasOwnProperty.call(e,r);function f(e,r){let t=Object.getOwnPropertyDescriptor(e,r);return t!==void 0&&"value"in t}function n(e,r){return Object.getOwnPropertyDescriptor(e,r)?.value}function d(e,r,t){return f(e,r)&&n(e,r)===t}function o(e,r){return f(e,r)&&typeof n(e,r)=="string"}function _(e,r){return f(e,r)&&typeof n(e,r)=="boolean"}function c(e,r){let t=n(e,r);return f(e,r)&&typeof t=="number"&&Number.isFinite(t)}function q(e,r){let t=n(e,r);return f(e,r)&&typeof t=="number"&&Number.isInteger(t)&&t>0}function g(e,r){return!h(e,r)||n(e,r)===void 0||o(e,r)}function b(e,r){return!h(e,r)||n(e,r)===void 0||c(e,r)}function w(e,r){let t=n(e,r);return!h(e,r)||t===void 0||f(e,r)&&typeof t=="number"&&Number.isInteger(t)&&t>=0}function a(e,r){return!h(e,r)||n(e,r)===void 0}function i(e){if(typeof e!="object"||e===null||Array.isArray(e))return!1;let r=Object.getPrototypeOf(e);return r===Object.prototype||r===null}function U(e){return i(e)&&Reflect.ownKeys(e).length===0}function O(e){if(!Array.isArray(e))return!1;for(let r=0;r<e.length;r+=1){let t=Object.getOwnPropertyDescriptor(e,String(r));if(t===void 0||!("value"in t)||typeof t.value!="string")return!1}return!0}function u(e){return i(e)&&o(e,"key")&&w(e,"instanceIndex")&&w(e,"instanceCount")&&w(e,"textSegmentIndex")}function j(e){return i(e)&&o(e,"blockId")&&u(n(e,"ref"))&&E(n(e,"rect"))&&_(e,"targetIsSectionRoot")}function H(e){if(!i(e))return!1;let r=n(e,"placement"),t=n(e,"boundary");return o(e,"anchorBlockId")&&u(n(e,"anchorRef"))&&(r==="before"||r==="after")&&i(t)&&c(t,"top")&&c(t,"left")&&c(t,"width")}function E(e){return i(e)&&["top","left","width","height"].every(r=>c(e,r))}function P(e){if(!i(e))return!1;let r=n(e,"rect"),t=n(e,"layout"),s=i(t)?n(t,"containingBlock"):null,p=n(e,"scrollContext"),l=i(s)&&(d(s,"kind","viewport")&&Reflect.ownKeys(s).length===1||d(s,"kind","document")&&Reflect.ownKeys(s).length===1||d(s,"kind","element")&&o(s,"runtimeNodeId"));return d(e,"version",z)&&o(e,"runtimeNodeId")&&i(r)&&E(n(r,"viewport"))&&E(n(r,"document"))&&i(t)&&o(t,"position")&&o(t,"transform")&&l&&i(p)&&["scrollX","scrollY","viewportWidth","viewportHeight"].every(I=>c(p,I))&&f(p,"scrollContainers")&&X(n(p,"scrollContainers"))}function X(e){return Array.isArray(e)&&e.every(r=>i(r)&&o(r,"runtimeNodeId")&&c(r,"scrollLeft")&&c(r,"scrollTop"))}function x(e){return i(e)&&(a(e,"layoutSnapshot")||P(n(e,"layoutSnapshot")))}function Y(e){return i(e)&&u(n(e,"ref"))&&f(e,"layoutSnapshot")&&P(n(e,"layoutSnapshot"))&&(a(e,"childBoxes")||J(n(e,"childBoxes")))&&(a(e,"childRects")||Z(n(e,"childRects")))&&(a(e,"layout")||k(n(e,"layout")))&&(a(e,"spacing")||Q(n(e,"spacing")))}function k(e){if(!i(e))return!1;let r=n(e,"indicatorOrientation");return o(e,"display")&&(r==="horizontal"||r==="vertical")&&g(e,"flexDirection")&&g(e,"gridAutoFlow")}function Z(e){return Array.isArray(e)&&e.every(r=>E(r))}function J(e){return Array.isArray(e)&&e.every(r=>i(r)&&E(n(r,"rect"))&&D(n(r,"margin")))}function D(e){return i(e)&&["marginTop","marginRight","marginBottom","marginLeft"].every(r=>c(e,r))}function Q(e){return D(e)&&["paddingTop","paddingRight","paddingBottom","paddingLeft","borderTopWidth","borderRightWidth","borderBottomWidth","borderLeftWidth","columnGap","rowGap"].every(r=>c(e,r))}function $(e){if(!Array.isArray(e))return!1;for(let r=0;r<e.length;r+=1){let t=Object.getOwnPropertyDescriptor(e,String(r));if(t===void 0||!("value"in t)||!Y(t.value))return!1}return!0}function v(e){return i(e)&&Reflect.ownKeys(e).every(r=>typeof r=="string"&&f(e,r)&&(typeof n(e,r)=="string"||n(e,r)===null))}function K(e){return e==null||typeof e=="string"||typeof e=="number"&&Number.isFinite(e)}function ee(e){return i(e)&&Reflect.ownKeys(e).every(r=>typeof r=="string"&&f(e,r)&&K(n(e,r)))}function te(e){if(!i(e))return!1;let r=n(e,"priority");return o(e,"property")&&f(e,"value")&&K(n(e,"value"))&&(!h(e,"priority")||r===void 0||r==="important")}function re(e){return i(e)?(a(e,"attributes")||v(n(e,"attributes")))&&g(e,"className")&&(a(e,"style")||ee(n(e,"style")))&&(a(e,"styleDeclarations")||Array.isArray(n(e,"styleDeclarations"))&&n(e,"styleDeclarations").every(te)):!1}function ne(e){return i(e)&&c(e,"x")&&c(e,"y")&&(a(e,"detailLevel")||d(e,"detailLevel","summary")||d(e,"detailLevel","full"))}function ie(e){return i(e)&&u(n(e,"ref"))}function oe(e){if(!i(e)||!i(n(e,"variables")))return!1;let r=n(e,"variables");return Reflect.ownKeys(r).every(t=>typeof t=="string"&&o(r,t))?a(e,"stylesheets")||O(n(e,"stylesheets")):!1}function se(e){if(!d(e,"type","request")||!o(e,"id")||!o(e,"kind")||!f(e,"payload"))return!1;let r=n(e,"kind"),t=n(e,"payload");switch(r){case"hit-test-at-point":case"start-text-edit-at-point":return ne(t);case"bridge-get-source-tree":return i(t)&&y(n(t,"composition"))&&m(t,["composition"]);case"get-scroll-metrics":case"clear-theme-override":return U(t);case"bridge-get-history-status":case"bridge-undo":case"bridge-redo":return i(t)&&y(n(t,"composition"))&&m(t,["composition"]);case"bridge-get-source-file":return i(t)&&o(t,"path")&&y(n(t,"composition"))&&m(t,["path","composition"]);case"bridge-resolve-source-location":case"bridge-get-object-edit-context":case"bridge-get-class-name-source":return i(t)&&o(t,"key")&&y(n(t,"composition"))&&m(t,["key","composition"]);case"scroll-to":return i(t)&&c(t,"x")&&c(t,"y");case"scroll-by":return i(t)&&c(t,"deltaX")&&c(t,"deltaY");case"set-interaction-mode":return i(t)&&_(t,"enabled");case"set-selection-visual":return i(t)&&d(t,"version",A)&&u(n(t,"ref"))&&d(t,"visible",!0);case"clear-selection-visual":return i(t)&&d(t,"version",A);case"set-resize-visual":return i(t)&&d(t,"version",N)&&u(n(t,"ref"))&&d(t,"visible",!0);case"clear-resize-visual":return i(t)&&d(t,"version",N);case"set-theme-override":return oe(t);case"get-theme-variables":return i(t)&&O(n(t,"names"));case"compute-drop-target-at-point":return i(t)&&c(t,"x")&&c(t,"y")&&(d(t,"dragKind","insert")||d(t,"dragKind","move"))&&(a(t,"movingRef")||u(n(t,"movingRef")));case"observe-node-bounds":case"clear-node-bounds-observer":return i(t)&&(a(t,"ref")||u(n(t,"ref")));case"apply-node-patch":return i(t)&&u(n(t,"ref"))&&re(n(t,"patch"))&&(a(t,"preview")||i(n(t,"preview"))&&o(n(t,"preview"),"sessionId")&&w(n(t,"preview"),"revision")&&h(n(t,"preview"),"revision"));case"get-hit-by-ref":case"get-path-by-ref":case"restore-text-edit":case"clear-text-edit-rollback":return ie(t);case"bridge-initialize-session":case"bridge-get-style-context":return i(t)&&y(n(t,"composition"))&&m(t,["composition"]);case"bridge-get-document":case"bridge-ensure-document-version":case"bridge-acknowledge-document-version":return i(t)&&y(n(t,"composition"))&&b(t,"minVersion")&&b(t,"version")&&m(t,["composition","minVersion","version"]);case"bridge-execute":{if(!i(t))return!1;let s=n(t,"request"),p=n(t,"composition"),l=i(s)?n(s,"composition"):null;return!y(p)||!i(s)||!y(l)?!1:S({routeId:p.routeId,...p.templateId?{effectiveTemplateId:p.templateId}:{}})===S({routeId:l.routeId,...l.templateId?{effectiveTemplateId:l.templateId}:{}})&&m(t,["composition","request"])}case"bridge-subscribe":case"bridge-unsubscribe":return i(t)&&o(t,"subscriptionId")&&y(n(t,"composition"))&&m(t,["subscriptionId","composition"]);default:return!1}}function ce(e){return d(e,"type","response")&&o(e,"id")&&_(e,"ok")&&(a(e,"error")||o(e,"error"))}function ae(e){if(!i(e))return!1;let r=n(e,"type");if(typeof r!="string"||!R(n(e,"composition"))||!o(e,"siteId")||!o(e,"at"))return!1;switch(r){case"site-edit.document.changed":return o(e,"snapshotId")&&c(e,"version");case"site-edit.operation.planned":return o(e,"operationId")&&o(e,"baseSnapshotId")&&O(n(e,"changedFiles"));case"site-edit.operation.completed":return i(n(e,"result"));case"site-edit.operation.failed":return o(e,"requestId")&&i(n(e,"error"));case"site-edit.capability.changed":return O(n(e,"keys"));case"site-edit.graph.invalidated":return!0;case"site-edit.graph.ready":return c(e,"version");case"site-edit.graph.error":return o(e,"message");default:return!1}}var de=new Set(["pointer-down","pointer-move","pointer-leave","pointer-up","pointer-cancel","pointer-click","pointer-double-click"]),M=new Set(["e","s","se"]);function pe(e,r){if(a(e,"resizeSession"))return!0;let t=n(e,"resizeSession");if(!i(t))return!1;let s=n(e,"pointerId"),p=n(t,"pointerId"),l=n(t,"phase"),I=n(t,"edge"),L=r==="pointer-down"?"start":r==="pointer-up"?"commit":r==="pointer-cancel"?"cancel":null;return n(t,"version")===1&&l===L&&o(t,"sessionId")&&String(n(t,"sessionId")).length>0&&typeof s=="number"&&Number.isInteger(s)&&typeof p=="number"&&Number.isInteger(p)&&s===p&&typeof I=="string"&&M.has(I)&&n(e,"resizeEdge")===I&&u(n(t,"ref"))&&["startWidth","startHeight","width","height"].every(W=>c(t,W))}function fe(e){if(!d(e,"type","event")||!o(e,"kind")||!i(n(e,"payload")))return!1;let r=n(e,"kind"),t=n(e,"payload");switch(r){case"text-edit-commit":case"text-edit-cancel":case"text-edit-exit":case"text-edit-input":return u(n(t,"ref"))&&g(t,"value")&&(a(t,"hit")||x(n(t,"hit")));case"node-bounds-change":return x(n(t,"hit"));case"geometry-batch":{let s=n(t,"reason");return q(t,"sequence")&&c(t,"sourceEventAt")&&c(t,"captureStartedAt")&&c(t,"capturedAt")&&(s==="scroll"||s==="resize"||s==="mutation")&&$(n(t,"snapshots"))}case"bridge-event":{let s=n(t,"event"),p=n(t,"composition");return!ae(s)||!R(p)?!1:o(t,"subscriptionId")&&S(p)===S(s.composition)}case"route-ready":return R(n(t,"composition"))&&o(t,"editEngineVersion")&&c(t,"sequence")&&c(t,"version");case"bridge-status":{let s=n(t,"state");return(s==="connecting"||s==="ready"||s==="reconnecting"||s==="failed"||s==="reload-required")&&R(n(t,"composition"))&&c(t,"sequence")&&b(t,"attempt")&&b(t,"retryInMs")&&g(t,"messageKey")}case"scroll":{let s=n(t,"metrics");return i(s)&&["scrollX","scrollY","scrollWidth","scrollHeight","viewportWidth","viewportHeight"].every(p=>c(s,p))}default:return de.has(r)&&c(t,"clientX")&&c(t,"clientY")&&b(t,"buttons")&&b(t,"pointerId")&&(a(t,"hoverVisualOwned")||_(t,"hoverVisualOwned"))&&(a(t,"resizeEdge")||o(t,"resizeEdge")&&M.has(n(t,"resizeEdge")))&&pe(t,r)&&(n(t,"hit")===null||x(n(t,"hit")))&&(a(t,"section")||n(t,"section")===null||j(n(t,"section")))&&(a(t,"sectionGap")||n(t,"sectionGap")===null||H(n(t,"sectionGap")))}}function ue(e){if(!i(e))return!1;switch(n(e,"type")){case"request":return se(e);case"response":return ce(e);case"event":return fe(e);default:return!1}}export{C as SITE_EDIT_FRAME_RUNTIME_CHANNEL,z as SITE_EDIT_FRAME_RUNTIME_LAYOUT_SNAPSHOT_VERSION,N as SITE_EDIT_FRAME_RUNTIME_RESIZE_VISUAL_VERSION,A as SITE_EDIT_FRAME_RUNTIME_SELECTION_VISUAL_VERSION,le as SITE_EDIT_FRAME_SECTION_GAP_RADIUS_PX,V as SITE_EDIT_WINDOW_MESSAGE_NAMESPACE,T as VCP_WINDOW_MESSAGE_SOURCE,F as VCP_WINDOW_MESSAGE_VERSION,ge as createSiteEditFrameRuntimeMessage,B as createVcpWindowMessageEnvelope,P as isSiteEditFrameRuntimeLayoutSnapshot,he as isSiteEditFrameRuntimeMessage,G as isVcpWindowMessageEnvelope};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vcp-dev/site-edit-bridge",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"repository": {
|
|
@@ -74,8 +74,8 @@
|
|
|
74
74
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
75
75
|
},
|
|
76
76
|
"dependencies": {
|
|
77
|
-
"@vcp-dev/contracts": "0.
|
|
78
|
-
"@vcp-dev/site-edit-engine": "0.
|
|
77
|
+
"@vcp-dev/contracts": "0.7.0",
|
|
78
|
+
"@vcp-dev/site-edit-engine": "0.7.0",
|
|
79
79
|
"@types/ws": "^8.18.1",
|
|
80
80
|
"ws": "^8.20.1"
|
|
81
81
|
},
|