@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/next-dev-server.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import st from"node:http";import{existsSync as w,readFileSync as S}from"node:fs";import{createRequire as pe}from"node:module";import R from"node:path";import{basename as ge,dirname as x,join as b}from"node:path";import{fileURLToPath as me}from"node:url";import Te from"node:http";import{createHash as ie,randomBytes as He,timingSafeEqual as Be}from"node:crypto";import L from"node:path";import{WebSocket as oe,WebSocketServer as je}from"ws";import{createPreviewSiteEditEngineRuntime as Ae,openFileHistoryStore as De}from"@vcp-dev/site-edit-engine";import{resolveNextAppRouteId as Me,scanNextAppRouterRoutes as Ue}from"@vcp-dev/site-edit-engine/next-app-router";import{SiteEditSourceWatcher as Ne}from"@vcp-dev/site-edit-engine/source-watcher";function U(t){let e=new Map,n=[],s=new Map,r=[],i=t.pageComposition.status==="supported"?t.pageComposition.placementUnitKeys:[],o=new Map(i.map((a,u)=>[a,u])),c=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},d=t.entries.flatMap((a,u)=>a.dynamicDataSummary?[[u,a.dynamicDataSummary]]:[]),h=a=>{let u=e.get(a);if(typeof u=="number")return u;let l=n.length;return n.push(a),e.set(a,l),l},g=a=>{let u=null;for(let l of Ce(a)){let v=`${u??"root"}\0${l}`,I=s.get(v);if(typeof I=="number"){u=I;continue}let m=r.length;r.push([u,h(l)]),s.set(v,m),u=m}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:c,tokens:n,nodes:r,entries:t.entries.map(a=>{let u=a.pageCompositionUnitKey?o.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[g(a.key),ke(a.operationSummary),...u>=0?[u]:[]]}),...d.length>0?{dynamicDataSummaries:d}:{}}}function ke(t){return(t.canUpdateText?1:0)|(t.canInsertChild?2:0)|(t.canMove?4:0)|(t.canRemove?8:0)}function Ce(t){if(!t)return[];let e=[],n=0,s=Y(t,n);if(s<0)return e.push(t),e;for(e.push(t.slice(0,s)),n=s;n<t.length;){if(s=Y(t,n+(t.startsWith("::",n)?2:1)),s<0){e.push(t.slice(n));break}e.push(t.slice(n,s)),n=s}return e}function Y(t,e){let n=t.indexOf("/",e),s=t.indexOf("::",e);return n<0?s:s<0?n:Math.min(n,s)}var p=class t{constructor(){}static parseMessage(e,n={}){let s=JSON.parse(e);if(!t.isMessage(s,n))throw new Error("Invalid site edit bridge message");return s}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 n=e.payload,s=typeof n.id=="string"?n.id:"unknown",r=t.isRequestKind(n.kind)?n.kind:"get-document";return{id:s,kind:r}}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,n={}){return!f(e)||typeof e.type!="string"?!1:e.type==="request"?t.isRequestPayload(e.payload,n):e.type==="response"||e.type==="error"?f(e.payload)&&typeof e.payload.id=="string":e.type==="event"?f(e.payload)&&f(e.payload.event):e.type==="auth"?f(e.payload)&&typeof e.payload.key=="string":e.type==="auth-ok"?f(e.payload)&&e.payload.ok===!0:!1}static isRequestPayload(e,n={}){if(!f(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||N(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 Ee(e.request)&&(e.request.mutationContext===void 0||N(e.request.mutationContext))&&(n.validateOperationRequest?.(e.request)??!0);case"undo":case"redo":return e.mutationContext===void 0||N(e.mutationContext)}}},P=class{constructor(e){this.options=e,this.messageQueue=new V,this.eventDispatcher=new O(n=>{this.sendJson(n)}),this.unsubscribe=e.engine.subscribe(n=>{this.eventDispatcher.push(n)}),e.socket.onmessage=n=>{try{this.messageQueue.enqueue(()=>this.handleRawMessage(n.data))}catch(s){this.sendJson({type:"error",payload:{id:"unknown",kind:"get-document",message:s instanceof Error?s.message:"Bridge queue overflow"}}),e.socket.close(1013,"bridge busy")}},e.socket.onclose=()=>{this.unsubscribe()}}async handleMessage(e){try{let n=e;if(n.type!=="request")return;let s=n.payload,{id:r}=s;switch(s.kind){case"initialize-session":{let i=await this.options.engine.initializeSession({routeId:s.routeId,...s.mutationContext?{mutationContext:s.mutationContext}:{}});this.sendJson({type:"response",payload:{id:r,kind:s.kind,result:{ok:!0,data:{document:U(i.data.document),historyStatus:i.data.historyStatus}}}});return}case"get-document":this.sendJson({type:"response",payload:{id:r,kind:s.kind,result:{ok:!0,data:U((await this.options.engine.getDocument(s.routeId)).data)}}});return;case"get-history-status":this.sendJson({type:"response",payload:{id:r,kind:s.kind,result:await this.options.engine.getHistoryStatus()}});return;case"get-style-context":this.sendJson({type:"response",payload:{id:r,kind:s.kind,result:await this.options.engine.getStyleContext(s.routeId)}});return;case"get-object-edit-context":this.sendJson({type:"response",payload:{id:r,kind:s.kind,result:await this.options.engine.getObjectEditContext(s.key,s.routeId)}});return;case"get-class-name-source":this.sendJson({type:"response",payload:{id:r,kind:s.kind,result:await this.options.engine.getClassNameSource(s.key,s.routeId)}});return;case"get-source-tree":this.sendJson({type:"response",payload:{id:r,kind:s.kind,result:await this.options.engine.getSourceTree()}});return;case"get-source-file":this.sendJson({type:"response",payload:{id:r,kind:s.kind,result:await this.options.engine.getSourceFile({path:s.path})}});return;case"resolve-source-location":this.sendJson({type:"response",payload:{id:r,kind:s.kind,result:await this.options.engine.resolveSourceLocation({key:s.key,routeId:s.routeId})}});return;case"execute":{await this.handleBufferedOperation(r,s.kind,()=>this.options.engine.execute(s.request));return}case"undo":await this.handleBufferedOperation(r,s.kind,()=>this.options.engine.undo());return;case"redo":await this.handleBufferedOperation(r,s.kind,()=>this.options.engine.redo());return}}catch(n){let s=p.extractRequestInfo(e);this.sendJson({type:"error",payload:{...s,message:X(n),code:Z(n)}})}}async handleRawMessage(e){try{await this.handleMessage(p.parseMessage(e,{validateOperationRequest:this.options.validateOperationRequest}))}catch(n){let s=n instanceof Error?n.message:"Invalid websocket message",r=Pe(e);this.sendJson({type:"error",payload:{...r,message:s}})}}sendJson(e){this.options.socket.send(p.stringifyMessage(e))}async handleBufferedOperation(e,n,s){this.eventDispatcher.beginBuffering();try{let r=await s();this.sendJson({type:"response",payload:{id:e,kind:n,result:r}}),this.eventDispatcher.flush()}catch(r){this.sendJson({type:"error",payload:{id:e,kind:n,message:X(r),code:Z(r)}}),this.eventDispatcher.flush()}}},O=class{constructor(e){this.send=e,this.bufferedEvents=null}push(e){let n={type:"event",payload:{event:e}};if(this.bufferedEvents){this.bufferedEvents.push(n);return}this.send(n)}beginBuffering(){this.bufferedEvents=[]}flush(){let e=this.bufferedEvents??[];this.bufferedEvents=null,e.forEach(n=>{this.send(n)})}},V=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 n=async()=>{this.queued-=1,await e()},s=this.queue.then(n,n);return this.queue=s.then(()=>{},()=>{}),s}};function f(t){return typeof t=="object"&&t!==null}function Ee(t){return f(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"&&f(t.target)&&typeof t.documentVersion=="number"&&Number.isInteger(t.documentVersion)&&t.documentVersion>=0&&f(t.params)}function N(t){return _e(t)}function Z(t){if(!t||typeof t!="object")return;let e=t.code;return typeof e=="string"&&e.length>0?e:void 0}function X(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 _e(t){return f(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 Pe(t){try{return p.extractRequestInfo(JSON.parse(t))}catch{return{id:"unknown",kind:"get-document"}}}var T=class{constructor(){this.tail=Promise.resolve()}run(e){let n=this.tail.then(e,e);return this.tail=n.then(()=>{},()=>{}),n}};import{SiteEditOperationRequestSchema as Oe}from"@vcp-dev/contracts";var Ve="127.0.0.1",Fe=30218,Ke="/__vcp/site-edit/bridge",ae=6*1024*1024,Le=ae*2,qe=3e3,ee=50,te="__VCP_SITE_EDIT_BRIDGE_SERVERS__";function ue(t,e,n={}){let s=new q($e(e),t,!1,n);return s.start({listen:!1}),s}var q=class{constructor(e,n=Te.createServer((i,o)=>{o.writeHead(404),o.end("VCP site edit bridge server")}),s=!0,r={}){this.options=e,this.server=n,this.closeHttpServerOnStop=s,this.dependencies=r,this.runtime=null,this.activeHistorySessionId=null,this.historySessionTransition=Promise.resolve(),this.mutationQueue=new T,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 n=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=n.stop,this.stopWatching=new Ne({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??ee,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:s=>this.handleFileChanged(s),on_batch_change:s=>this.handleFilesChanged(s)}).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=We(),n=ze(this.options);e.get(n)===this&&e.delete(n),this.isStarted=!1}createRuntime(e,n=null){let s=this.runtime;this.activeHistoryStore=e??null;let r=(this.dependencies.createRuntime??Ae)({...this.options.tenantId?{tenantId:this.options.tenantId}:{},siteId:this.options.siteId,snapshotId:this.options.snapshotId,projectRoot:this.options.projectRoot,routes:this.routes,onEvent:i=>{"version"in i&&typeof i.version=="number"&&this.recordRuntimeVersion(i.version);for(let o of this.eventListeners)o(i)},...e?{historyStore:e}:{},initialDocumentVersion:this.runtimeVersionFloor});this.runtime=r,this.activeHistorySessionId=n,s?.dispose()}createBridgeEngine(){return{initializeSession:e=>this.mutationQueue.run(async()=>{let n=await this.bindHistorySession(this.options.snapshotId);if(!n.ok)throw new Error(`${n.code}: ${n.message}`);let{runtime:s,resolvedRouteId:r}=await this.activateRoute(e.routeId),i=s.getDocument(r).data;await this.recordRuntimeVersion(i.version);let o=(await s.getHistoryStatus()).data;return{ok:!0,data:{document:i,historyStatus:o}}}),getDocument:async e=>{let{runtime:n,resolvedRouteId:s}=await this.activateRoute(e),r=n.getDocument(s);return await this.recordRuntimeVersion(r.data.version),r},getHistoryStatus:async()=>this.getRuntime().getHistoryStatus(),getStyleContext:async e=>{let{runtime:n,resolvedRouteId:s}=await this.activateRoute(e);return n.getStyleContext(s)},getObjectEditContext:async(e,n)=>this.getRuntime().getObjectEditContext(e,n?this.resolveRouteId(n):void 0),getClassNameSource:async(e,n)=>{let s=this.getRuntime(),r=n?this.resolveRouteId(n):void 0;return s.getClassNameSource(e,r)},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,n)=>this.mutationQueue.run(async()=>{let s=await this.bindHistorySession(this.options.snapshotId);if(!s.ok)return F(s,e);let r=await this.getRuntime().executeOperation(this.normalizeRequest(e));return r.data?.resultVersion!==void 0&&await this.recordRuntimeVersion(r.data.resultVersion),r}),undo:()=>this.mutationQueue.run(async()=>{let e=await this.bindHistorySession(this.options.snapshotId);if(!e.ok)return F(e);let n=await this.getRuntime().undo();return n.data?.resultVersion!==void 0&&await this.recordRuntimeVersion(n.data.resultVersion),n}),redo:()=>this.mutationQueue.run(async()=>{let e=await this.bindHistorySession(this.options.snapshotId);if(!e.ok)return F(e);let n=await this.getRuntime().redo();return n.data?.resultVersion!==void 0&&await this.recordRuntimeVersion(n.data.resultVersion),n}),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 n=this.historySessionTransition.then(async()=>{if(this.activeHistorySessionId===e)return;let s=await(this.dependencies.openHistoryStore??De)(Je({root:this.options.historyRoot,siteId:this.options.siteId,snapshotId:this.options.snapshotId,editingSessionId:e}));if(!this.isStarted)return;let r=s.readDocumentVersion?await s.readDocumentVersion():0;this.runtimeVersionFloor=Math.max(this.runtimeVersionFloor,r),this.createRuntime(s,e)});this.historySessionTransition=n.catch(()=>{});try{return await n,{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 n=this.activeHistoryStore;return n?.writeDocumentVersion?(this.versionPersistence=this.versionPersistence.then(()=>n.writeDocumentVersion(this.runtimeVersionFloor)).catch(()=>{}),this.versionPersistence):Promise.resolve()}async activateRoute(e){let n=this.getRuntime(),s=this.resolveRouteId(e);return await n.setActiveRoute(s),{runtime:n,resolvedRouteId:s}}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 s of e)this.pendingChangedFiles.add(s);this.fileChangeTimer&&clearTimeout(this.fileChangeTimer);let n=this.options.runtime.watch_debounce_ms??ee;this.fileChangeTimer=setTimeout(()=>{this.fileChangeTimer=null,this.flushChangedFiles()},n),this.fileChangeTimer?.unref?.()}flushChangedFiles(){if(this.fileChangeTimer&&(clearTimeout(this.fileChangeTimer),this.fileChangeTimer=null),this.pendingChangedFiles.size===0)return;let e=[...this.pendingChangedFiles].sort((n,s)=>n.localeCompare(s));this.pendingChangedFiles.clear(),this.refreshRoutes();for(let n of e)this.runtime?.notifyFileChanged(n)}refreshRoutes(){let e=this.options.runtime.routes?.length?this.options.runtime.routes:Ue(this.options.projectRoot),n=new Map(this.routes.map(r=>[r.routeId,r.entryFile])),s=new Set(e.map(r=>r.routeId));this.routes=e;for(let r of e)n.get(r.routeId)!==r.entryFile&&this.runtime?.registerRoute(r.routeId,r.entryFile);for(let r of n.keys())s.has(r)||this.runtime?.unregisterRoute(r)}resolveRouteId(e){let n=Me(e,this.routes,this.options.basePath);if(!n)throw new Error(`Route is not indexed by the preview bridge: ${e}`);return n}getRuntime(){if(!this.runtime)throw new Error("VCP site edit preview bridge runtime is not ready");return this.runtime}};function $e(t){return{tenantId:t.tenantId,siteId:t.siteId,snapshotId:t.snapshotId,projectRoot:L.resolve(t.projectRoot??process.cwd()),basePath:t.basePath??"",host:t.host??Ve,port:t.port??Fe,path:t.path??Ke,sessionKey:t.sessionKey??nt(),historyRoot:t.historyRoot,allowedOrigins:t.allowedOrigins??[],runtime:t.runtime??{}}}function Je(t){return L.join(L.resolve(t.root),ne(t.siteId),ne(t.snapshotId),ie("sha256").update(t.editingSessionId).digest("hex").slice(0,32))}function ne(t){return/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(t)&&t!=="."&&t!==".."?t:ie("sha256").update(t).digest("hex").slice(0,32)}function We(){let t=globalThis;return t[te]??=new Map,t[te]}function ze(t){return`${t.projectRoot}:${t.host}:${t.port}:${t.path}:${t.historyRoot??""}`}function F(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 je({maxPayload:ae,noServer:!0}),n=new WeakSet,s=i=>{new P({socket:new $(i),engine:t.engine,validateOperationRequest:o=>Oe.safeParse(o).success})},r=(i,o,c)=>{if(!Qe(i,t))return;let d=Ye(i,t);if(!d){o.write(`HTTP/1.1 401 Unauthorized\r
|
|
1
|
+
import Rt from"node:http";import{existsSync as E,readFileSync as R}from"node:fs";import{createRequire as ve}from"node:module";import k from"node:path";import{basename as _e,dirname as T,join as P}from"node:path";import{fileURLToPath as ke}from"node:url";import $e from"node:http";import Y from"node:fs";import{createHash as ye,randomBytes as ze,timingSafeEqual as Je}from"node:crypto";import S from"node:path";import{WebSocket as Se,WebSocketServer as Ge}from"ws";import{createPreviewSiteEditEngineRuntime as Qe,openFileHistoryStore as Ye,resolveManagedPageTemplateComposition as Ze,scanSiteEditCompositionsFromFiles as Xe}from"@vcp-dev/site-edit-engine";import{resolveNextAppRouteId as et,scanNextAppRouterRoutesFromFiles as tt}from"@vcp-dev/site-edit-engine/next-app-router";import{SiteEditSourceWatcher as nt}from"@vcp-dev/site-edit-engine/source-watcher";function ce(e){let t=new Map,n=[],i=new Map,o=[],s=e.pageComposition.status==="supported"?e.pageComposition.placementUnitKeys:[],r=new Map(s.map((u,h)=>[u,h])),a=e.pageComposition.status==="supported"?{status:"supported",containerKey:e.pageComposition.containerKey,hasBusinessMembers:e.pageComposition.hasBusinessMembers,placementUnitKeys:e.pageComposition.placementUnitKeys,placements:e.pageComposition.placements.map(u=>({placementKey:u.placementKey,placementUnitKey:u.placementUnitKey,relation:u.relation}))}:{status:"unsupported",reason:e.pageComposition.reason,diagnostics:e.pageComposition.diagnostics},c=e.entries.flatMap((u,h)=>u.dynamicDataSummary?[[h,u.dynamicDataSummary]]:[]),d=u=>{let h=t.get(u);if(typeof h=="number")return h;let f=n.length;return n.push(u),t.set(u,f),f},l=u=>{let h=null;for(let f of je(u)){let H=`${h??"root"}\0${f}`,v=i.get(H);if(typeof v=="number"){h=v;continue}let I=o.length;o.push([h,d(f)]),i.set(H,I),h=I}if(h===null)throw new Error("Document key must not be empty");return h};return{encoding:"segment-trie-v1",siteId:e.siteId,snapshotId:e.snapshotId,composition:{...e.composition},routeId:e.composition.routeId,version:e.version,pageComposition:a,tokens:n,nodes:o,entries:e.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[l(u.key),Ne(u.operationSummary),...h>=0?[h]:[]]}),...c.length>0?{dynamicDataSummaries:c}:{}}}function Ne(e){return(e.canUpdateText?1:0)|(e.canInsertChild?2:0)|(e.canMove?4:0)|(e.canRemove?8:0)}function je(e){if(!e)return[];let t=[],n=0,i=ae(e,n);if(i<0)return t.push(e),t;for(t.push(e.slice(0,i)),n=i;n<e.length;){if(i=ae(e,n+(e.startsWith("::",n)?2:1)),i<0){t.push(e.slice(n));break}t.push(e.slice(n,i)),n=i}return t}function ae(e,t){let n=e.indexOf("/",t),i=e.indexOf("::",t);return n<0?i:i<0?n:Math.min(n,i)}var ue="SITE_EDIT_COMPOSITION_SESSION_MISMATCH",Q="SITE_EDIT_COMPOSITION_SESSION_REQUIRED";var m=class e{constructor(){}static parseMessage(t,n={}){let i=JSON.parse(t);if(!e.isMessage(i,n))throw new Error("Invalid site edit bridge message");return i}static stringifyMessage(t){return JSON.stringify(t)}static extractRequestInfo(t){if(p(t)&&p(t.payload)){let n=typeof t.payload.id=="string"?t.payload.id:"unknown",i=this.isRequestKind(t.payload.kind)?t.payload.kind:"get-document";return{id:n,kind:i}}return{id:"unknown",kind:"get-document"}}static isRequestKind(t){return t==="initialize-session"||t==="get-document"||t==="get-history-status"||t==="get-style-context"||t==="get-object-edit-context"||t==="get-class-name-source"||t==="get-source-tree"||t==="get-source-file"||t==="resolve-source-location"||t==="execute"||t==="undo"||t==="redo"}static isMessage(t,n={}){return!p(t)||typeof t.type!="string"?!1:t.type==="request"?Fe(t.payload,n):t.type==="response"||t.type==="error"?p(t.payload)&&typeof t.payload.id=="string":t.type==="event"?p(t.payload)&&p(t.payload.event):t.type==="auth"?p(t.payload)&&typeof t.payload.key=="string":t.type==="auth-ok"&&p(t.payload)&&t.payload.ok===!0}},M=class{constructor(t){this.options=t,this.session={subscribedCompositionKeys:new Set},this.messageQueue=new G,this.eventDispatcher=new J(n=>{this.sendJson(n)}),this.unsubscribe=t.engine.subscribe(n=>{this.handleEngineEvent(n)}),t.socket.onmessage=n=>{try{this.messageQueue.enqueue(()=>this.handleRawMessage(n.data))}catch(i){this.sendJson({type:"error",payload:{id:"unknown",kind:"get-document",message:i instanceof Error?i.message:"Bridge queue overflow"}}),t.socket.close(1013,"bridge busy")}},t.socket.onclose=()=>{this.unsubscribe(),this.session.activeComposition=void 0,this.session.subscribedCompositionKeys.clear()}}async handleMessage(t){try{let n=t;if(n.type!=="request")return;let i=n.payload,{id:o}=i;switch(i.kind){case"initialize-session":{let s=W(i),r=await this.resolve(s),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:y({...a,data:{...a.data,document:he(a.data.document)}},r.context)}});return}case"get-document":{let s=await this.resolveWireContext(i),r=await this.options.engine.getDocument(s);this.sendResult(o,i.kind,We(r,s));return}case"get-history-status":{let s=await this.resolveWireContext(i),r=await this.options.engine.getHistoryStatus(s);this.sendResult(o,i.kind,y(r,s));return}case"get-style-context":{let s=await this.resolveWireContext(i);this.sendResult(o,i.kind,y(await this.options.engine.getStyleContext(s),s));return}case"get-object-edit-context":{let s=await this.resolveWireContext(i);this.sendResult(o,i.kind,y(await this.options.engine.getObjectEditContext(i.key,s),s));return}case"get-class-name-source":{let s=await this.resolveWireContext(i);this.sendResult(o,i.kind,y(await this.options.engine.getClassNameSource(i.key,s),s));return}case"get-source-tree":{let s=await this.resolveWireContext(i);this.sendResult(o,i.kind,y(await this.options.engine.getSourceTree(s),s));return}case"get-source-file":{let s=await this.resolveWireContext(i);this.sendResult(o,i.kind,y(await this.options.engine.getSourceFile({path:i.path,composition:s}),s));return}case"resolve-source-location":{let s=await this.resolveWireContext(i),r=y(await this.options.engine.resolveSourceLocation({key:i.key,composition:s}),s);this.sendResult(o,i.kind,r);return}case"execute":{let s=await this.resolveOperationWireContext(i.request),r=await this.resolveWireContext(i);if(w(s)!==w(r))throw new x(ue,"The execute request composition does not match its operation composition.");let a=await this.normalizeOperationRequest(i.request,s);await this.handleBufferedOperation(o,i.kind,()=>this.options.engine.execute(a));return}case"undo":case"redo":{let s=await this.resolveWireContext(i);await this.handleBufferedOperation(o,i.kind,()=>i.kind==="undo"?this.options.engine.undo(s):this.options.engine.redo(s));return}}}catch(n){let i=m.extractRequestInfo(t);this.sendJson({type:"error",payload:{...i,message:z(n),code:$(n)}})}}async resolve(t){return this.options.engine.resolveComposition(t)}async resolveAndAssert(t){let n=await this.resolve(t),i=this.session.activeComposition;if(!i)throw new x(Q,"Initialize a composition session before issuing this request.");if(w(i)!==w(n.context))throw new x(ue,"The request composition does not match the active socket session.");return n.context}async resolveWireContext(t){let n=W(t);return this.resolveAndAssert(n)}async resolveOperationWireContext(t){let n=Ve(t);return this.resolveAndAssert(n)}activateSession(t){this.session.activeComposition=t,this.session.subscribedCompositionKeys.clear(),this.session.subscribedCompositionKeys.add(w(t))}async normalizeOperationRequest(t,n){let i={...t,composition:de(n)};if(i.target.kind==="route"){let o=i.target,s=W(o),r=await this.resolveAndAssert(s);i.target={...o,composition:de(r)}}return i}handleEngineEvent(t){let n=t?.composition;if(!Ke(n))return;let i=w(n);this.session.subscribedCompositionKeys.has(i)&&(this.eventDispatcher.push(t),t.type==="site-edit.graph.invalidated"&&i===qe(this.session)&&(this.session.activeComposition=void 0,this.session.subscribedCompositionKeys.delete(i)))}sendResult(t,n,i){this.sendJson({type:"response",payload:{id:t,kind:n,result:i}})}async handleRawMessage(t){try{await this.handleMessage(m.parseMessage(t,{validateOperationRequest:this.options.validateOperationRequest}))}catch(n){let i=Le(t);this.sendJson({type:"error",payload:{...i,message:z(n),code:$(n)}})}}sendJson(t){this.options.socket.send(m.stringifyMessage(t))}async handleBufferedOperation(t,n,i){this.eventDispatcher.beginBuffering();try{let o=await i();this.sendResult(t,n,o)}catch(o){this.sendJson({type:"error",payload:{id:t,kind:n,message:z(o),code:$(o)}})}finally{this.eventDispatcher.flush()}}},x=class extends Error{constructor(t,n){super(n),this.code=t,this.name="BridgeProtocolError"}},J=class{constructor(t){this.send=t,this.bufferedEvents=null}push(t){let n={type:"event",payload:{event:t}};if(this.bufferedEvents){this.bufferedEvents.push(n);return}this.send(n)}beginBuffering(){this.bufferedEvents=[]}flush(){let t=this.bufferedEvents??[];this.bufferedEvents=null,t.forEach(n=>this.send(n))}},G=class{constructor(t=64){this.maxQueued=t,this.queue=Promise.resolve(),this.queued=0}enqueue(t){if(this.queued>=this.maxQueued)throw new Error("Bridge request queue is full");this.queued+=1;let n=async()=>{this.queued-=1,await t()},i=this.queue.then(n,n);return this.queue=i.then(()=>{},()=>{}),i}};function Fe(e,t){if(!p(e)||typeof e.id!="string"||!m.isRequestKind(e.kind))return!1;let n=_(e.composition);switch(e.kind){case"initialize-session":return n&&(e.mutationContext===void 0||L(e.mutationContext));case"get-document":case"get-style-context":return n;case"get-object-edit-context":case"get-class-name-source":case"resolve-source-location":return typeof e.key=="string"&&n;case"get-history-status":return n;case"get-source-tree":return n;case"get-source-file":return typeof e.path=="string"&&n;case"execute":return n&&Ue(e.request)&&(e.request.mutationContext===void 0||L(e.request.mutationContext))&&(t.validateOperationRequest?.(e.request)??!0);case"undo":case"redo":return n&&e.mutationContext===void 0||n&&L(e.mutationContext)}}function Ue(e){return p(e)&&typeof e.id=="string"&&typeof e.siteId=="string"&&typeof e.baseSnapshotId=="string"&&_(e.composition)&&typeof e.kind=="string"&&p(e.target)&&(e.target.kind!=="route"||_(e.target.composition))&&typeof e.documentVersion=="number"&&Number.isInteger(e.documentVersion)&&e.documentVersion>=0&&p(e.params)}function _(e){return p(e)&&typeof e.routeId=="string"&&e.routeId.length>0&&(e.templateId===void 0||typeof e.templateId=="string"&&e.templateId.length>0)&&Object.keys(e).every(t=>t==="routeId"||t==="templateId")}function Ke(e){return p(e)&&typeof e.routeId=="string"&&(e.effectiveTemplateId===void 0||typeof e.effectiveTemplateId=="string")}function W(e){if(_(e.composition))return e.composition;throw new x(Q,"A composition selector is required for this request.")}function Ve(e){if(p(e)&&_(e.composition))return e.composition;throw new x(Q,"A composition selector is required for execute.")}function de(e){return{routeId:e.routeId,...e.effectiveTemplateId?{templateId:e.effectiveTemplateId}:{}}}function qe(e){return e.activeComposition?w(e.activeComposition):null}function w(e){return JSON.stringify([e.routeId,e.effectiveTemplateId??null])}function y(e,t){return p(e)&&e.ok===!0?{...e,composition:t}:e}function We(e,t){return!p(e)||e.ok!==!0?e:{...e,...t?{composition:t}:{},data:he(e.data)}}function he(e){let t=e;return ce(t.routeId?t:{...t,routeId:t.composition.routeId})}function p(e){return typeof e=="object"&&e!==null}function L(e){return p(e)&&typeof e.editingSessionId=="string"&&e.editingSessionId.length>0&&typeof e.lockId=="string"&&e.lockId.length>0&&typeof e.ownerId=="string"&&e.ownerId.length>0&&typeof e.leaseAssertion=="string"&&e.leaseAssertion.length>0}function $(e){if(!(!p(e)||typeof e.code!="string"||e.code.length===0))return e.code}function z(e){return e instanceof Error||p(e)&&typeof e.message=="string"&&e.message.length>0?e.message:"Unknown websocket operation failure"}function Le(e){try{return m.extractRequestInfo(JSON.parse(e))}catch{return{id:"unknown",kind:"get-document"}}}var N=class{constructor(){this.tail=Promise.resolve()}run(t){let n=this.tail.then(t,t);return this.tail=n.then(()=>{},()=>{}),n}};import{SiteEditOperationRequestSchema as it,computeSiteEditCompositionKey as C}from"@vcp-dev/contracts";var st="127.0.0.1",ot=30218,rt="/__vcp/site-edit/bridge",Ie=6*1024*1024,at=Ie*2,ct=3e3,pe=50,le="__VCP_SITE_EDIT_BRIDGE_SERVERS__";function we(e,t,n={}){let i=new ee(ut(t),e,!1,n);return i.start({listen:!1}),i}var ee=class{constructor(t,n=$e.createServer((s,r)=>{r.writeHead(404),r.end("VCP site edit bridge server")}),i=!0,o={}){this.options=t,this.server=n,this.closeHttpServerOnStop=i,this.dependencies=o,this.runtime=null,this.activeHistorySessionId=null,this.historySessionTransition=Promise.resolve(),this.mutationQueue=new N,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(t={}){if(this.isStarted)return;this.refreshCompositions(!0),this.isStarted=!0,this.createRuntime();let n=gt({server:this.server,path:this.options.path,sessionKey:this.options.sessionKey,host:this.options.host,allowedOrigins:this.options.allowedOrigins,engine:this.createBridgeEngine()});this.stopWebSocketServer=n.stop,this.stopWatching=new nt({projectRoot:this.options.projectRoot,watch_dirs:dt(this.options.runtime.watch_dirs),interval_ms:this.options.runtime.watch_interval_ms,debounce_ms:this.options.runtime.watch_debounce_ms??pe,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(),t.listen!==!1&&this.server.listen(this.options.port,this.options.host)}getHealth(){let t=!!this.runtime&&!this.compositionResolutionError;return{ok:this.isStarted&&t,bridgePath:this.options.path,runtimeReady:t,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 t=ft(),n=mt(this.options);t.get(n)===this&&t.delete(n),this.isStarted=!1}createRuntime(t,n=null){let i=this.runtime;this.activeHistoryStore=t??null;let o=(this.dependencies.createRuntime??Qe)({...this.options.tenantId?{tenantId:this.options.tenantId}:{},siteId:this.options.siteId,snapshotId:this.options.snapshotId,projectRoot:this.options.projectRoot,compositions:this.compositions,onEvent:s=>{"version"in s&&typeof s.version=="number"&&this.recordRuntimeVersion(s.version,"composition"in s?s.composition:void 0);for(let r of this.eventListeners)r(s)},...t?{historyStore:t}:{},...this.getInitialDocumentVersions().length>0?{initialDocumentVersions:this.getInitialDocumentVersions()}:{}});this.runtime=o,this.activeHistorySessionId=n,i?.dispose()}createBridgeEngine(){return{resolveComposition:t=>this.resolveComposition(t),initializeSession:t=>this.mutationQueue.run(async()=>{let n=await this.bindHistorySession(this.options.snapshotId);if(!n.ok)throw new Error(`${n.code}: ${n.message}`);let i=pt(t.composition),o=this.getRuntime(),s=g(i);await o.initializeComposition(s);let a=o.getDocument(s).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 t=>{let n=this.getRuntime(),i=g(t);await n.initializeComposition(i);let o=n.getDocument(i);return await this.recordRuntimeVersion(o.data.version,t),{...o,composition:t}},getHistoryStatus:async t=>({...await this.getRuntime().getHistoryStatus(),composition:t}),getStyleContext:async t=>this.getRuntime().getStyleContext(g(t)),getObjectEditContext:async(t,n)=>this.getRuntime().getObjectEditContext(t,g(n)),getClassNameSource:async(t,n)=>this.getRuntime().getClassNameSource(t,g(n)),getSourceTree:async t=>this.getRuntime().getSourceTree(g(t)),getSourceFile:async t=>this.getRuntime().getSourceFile({path:t.path,composition:g(t.composition)}),resolveSourceLocation:async t=>this.getRuntime().resolveSourceLocation({key:t.key,composition:g(t.composition)}),execute:(t,n)=>this.mutationQueue.run(async()=>{let i=await this.bindHistorySession(this.options.snapshotId);if(!i.ok)return Z(i,t);let o=await this.getRuntime().executeOperation(t);return o.data?.resultVersion!==void 0&&await this.recordRuntimeVersion(o.data.resultVersion,o.composition),o}),undo:t=>this.mutationQueue.run(async()=>{let n=await this.bindHistorySession(this.options.snapshotId);if(!n.ok)return Z(n,void 0,t);let i=await this.getRuntime().undo();return i.data?.resultVersion!==void 0&&await this.recordRuntimeVersion(i.data.resultVersion,i.composition??t),i.composition?i:{...i,composition:t}}),redo:t=>this.mutationQueue.run(async()=>{let n=await this.bindHistorySession(this.options.snapshotId);if(!n.ok)return Z(n,void 0,t);let i=await this.getRuntime().redo();return i.data?.resultVersion!==void 0&&await this.recordRuntimeVersion(i.data.resultVersion,i.composition??t),i.composition?i:{...i,composition:t}}),subscribe:t=>(this.eventListeners.add(t),()=>this.eventListeners.delete(t))}}async bindHistorySession(t){if(!this.options.historyRoot)return{ok:!1,code:"RECOVERY_PERSIST_FAILED",message:"Durable edit history is not configured."};if(this.activeHistorySessionId===t)return{ok:!0};let n=this.historySessionTransition.then(async()=>{if(this.activeHistorySessionId===t)return;let i=await(this.dependencies.openHistoryStore??Ye)(lt({root:this.options.historyRoot,siteId:this.options.siteId,snapshotId:this.options.snapshotId,editingSessionId:t}));if(!this.isStarted)return;let o=i.readDocumentVersion?await i.readDocumentVersion():0,s=this.compositions[0]?.context;if(s){let r=C(s);this.runtimeVersionFloors.set(r,Math.max(this.runtimeVersionFloors.get(r)??0,o))}this.createRuntime(i,t)});this.historySessionTransition=n.catch(()=>{});try{return await n,{ok:!0}}catch{return{ok:!1,code:"RECOVERY_PERSIST_FAILED",message:"Durable edit history could not be opened."}}}recordRuntimeVersion(t,n){let i=n?C(n):null;i&&this.runtimeVersionFloors.set(i,Math.max(this.runtimeVersionFloors.get(i)??0,t));let o=this.activeHistoryStore;if(!o?.writeDocumentVersion)return Promise.resolve();let s=i?this.runtimeVersionFloors.get(i)??t:t;return this.versionPersistence=this.versionPersistence.then(()=>o.writeDocumentVersion(s)).catch(()=>{}),this.versionPersistence}handleFileChanged(t){this.handleFilesChanged([t])}handleFilesChanged(t){for(let i of t)this.pendingChangedFiles.add(i);this.fileChangeTimer&&clearTimeout(this.fileChangeTimer);let n=this.options.runtime.watch_debounce_ms??pe;this.fileChangeTimer=setTimeout(()=>{this.fileChangeTimer=null,this.flushChangedFiles()},n),this.fileChangeTimer?.unref?.()}flushChangedFiles(){if(this.fileChangeTimer&&(clearTimeout(this.fileChangeTimer),this.fileChangeTimer=null),this.pendingChangedFiles.size===0)return;let t=[...this.pendingChangedFiles].sort((n,i)=>n.localeCompare(i));if(this.pendingChangedFiles.clear(),!!this.refreshCompositions(!1))for(let n of t)this.runtime?.notifyFileChanged(n)}refreshCompositions(t=!1){try{let n=ht(this.options.projectRoot),i=tt(n),o=i.length>0?i:(this.options.runtime.routes??[]).map(c=>({...c})),s=Xe({files:n});if(s.length===0)throw new Error("No canonical App Router composition is indexed by the preview bridge.");let r=new Map(this.compositions.map(c=>[C(c.context),c])),a=new Map(s.map(c=>[C(c.context),c]));if(this.runtime){for(let[c,d]of r){let l=a.get(c);(!l||l.entryFile!==d.entryFile)&&this.runtime.unregisterComposition(g(d.context))}for(let[c,d]of a){let l=r.get(c);(!l||l.entryFile!==d.entryFile)&&this.runtime.registerComposition(d.context,d.entryFile)}}return this.routes=o,this.compositions=s,this.compositionFiles=n,this.compositionResolutionError=null,!0}catch(n){let i=n instanceof Error?n:new Error(String(n));if(this.compositionResolutionError=i,t)throw i;return!1}}resolveComposition(t){if(this.compositionResolutionError)throw this.compositionResolutionError;let n=et(t.routeId,this.routes,this.options.basePath);if(!n)throw new Error(`Route is not indexed by the preview bridge: ${t.routeId}`);let i=this.routes.find(r=>r.routeId===n);if(!i)throw new Error(`Route is not indexed by the preview bridge: ${t.routeId}`);let o=Ze({selector:{routeId:n,...t.templateId?{templateId:t.templateId}:{}},files:this.compositionFiles,canonicalEntryFile:i.entryFile}),s=C(o.context);if(!this.compositions.some(r=>C(r.context)===s))throw new Error(`Composition is not registered by the preview bridge: ${s}`);return o}getInitialDocumentVersions(){return this.compositions.flatMap(t=>{let n=this.runtimeVersionFloors.get(C(t.context));return n===void 0?[]:[{composition:t.context,version:n}]})}getRuntime(){if(!this.runtime)throw new Error("VCP site edit preview bridge runtime is not ready");return this.runtime}};function ut(e){return{tenantId:e.tenantId,siteId:e.siteId,snapshotId:e.snapshotId,projectRoot:S.resolve(e.projectRoot??process.cwd()),basePath:e.basePath??"",host:e.host??st,port:e.port??ot,path:e.path??rt,sessionKey:e.sessionKey??bt(),historyRoot:e.historyRoot,allowedOrigins:e.allowedOrigins??[],runtime:e.runtime??{}}}function dt(e){let t=["app","src/app","components/site","src/components/site","lib/generated","src/lib/generated","public"];return[...new Set([...e?.length?e:t,".vcp"])]}function ht(e){let t=[],n=["app","src/app",".vcp"],i=new Set([".git",".next",".turbo","coverage","dist","node_modules","output","snapshot-store"]),o=s=>{if(!Y.existsSync(s))return;let r;try{r=Y.readdirSync(s,{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(S.join(s,a.name));continue}if(!a.isFile())continue;let c=S.join(s,a.name),d="";try{d=Y.readFileSync(c,"utf8")}catch{}t.push({path:S.relative(e,c).replaceAll(S.sep,"/"),content:d})}};for(let s of n)o(S.join(e,s));return t.sort((s,r)=>s.path.localeCompare(r.path))}function pt(e){if(!e||typeof e!="object"||typeof e.routeId!="string")throw new Error("Normalized composition context is required.");if("effectiveTemplateId"in e)return e;let t=e;return{routeId:t.routeId,...t.templateId?{effectiveTemplateId:t.templateId}:{}}}function g(e){return{routeId:e.routeId,...e.effectiveTemplateId?{templateId:e.effectiveTemplateId}:{}}}function lt(e){return S.join(S.resolve(e.root),fe(e.siteId),fe(e.snapshotId),ye("sha256").update(e.editingSessionId).digest("hex").slice(0,32))}function fe(e){return/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(e)&&e!=="."&&e!==".."?e:ye("sha256").update(e).digest("hex").slice(0,32)}function ft(){let e=globalThis;return e[le]??=new Map,e[le]}function mt(e){return`${e.projectRoot}:${e.host}:${e.port}:${e.path}:${e.historyRoot??""}`}function Z(e,t,n){let i=n??(t?.composition?{routeId:t.composition.routeId,...t.composition.templateId?{effectiveTemplateId:t.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:e.code,message:e.message},data:{requestId:t?.id??"mutation-context",kind:t?.kind??"update-text",composition:i,target:t?.target??{kind:"node",key:""},resultVersion:t?.documentVersion??0}}}function gt(e){let t=new Ge({maxPayload:Ie,noServer:!0}),n=new WeakSet,i=s=>{new M({socket:new te(s),engine:e.engine,validateOperationRequest:r=>it.safeParse(r).success})},o=(s,r,a)=>{if(!yt(s,e))return;let c=St(s,e);if(!c){r.write(`HTTP/1.1 401 Unauthorized\r
|
|
2
2
|
Connection: close\r
|
|
3
3
|
\r
|
|
4
|
-
`),o.destroy();return}d.authenticatedByHeader&&n.add(i),e.handleUpgrade(i,o,c,h=>{e.emit("connection",h,i)})};return t.server.on("upgrade",r),e.on("connection",(i,o)=>{if(n.has(o)){s(i);return}Ze(i,t.sessionKey,()=>{s(i)})}),e.stop=()=>{t.server.off("upgrade",r);for(let i of e.clients)i.close(1001,"bridge stopped");e.close()},e}var $=class{constructor(e){this.socket=e,this.onmessage=null,this.onclose=null,e.on("error",()=>{}),e.on("message",n=>{this.onmessage?.({data:n.toString()})}),e.on("close",()=>{this.onclose?.()})}send(e){if(this.socket.readyState===oe.OPEN){if(this.socket.bufferedAmount+Buffer.byteLength(e,"utf8")>Le){this.socket.close(1013,"bridge backpressure");return}this.socket.send(e)}}close(e,n){this.socket.close(e,n)}};function Qe(t,e){return new URL(t.url??"/","http://localhost").pathname===e.path}function Ye(t,e){if(new URL(t.url??"/","http://localhost").searchParams.has("vcp_bridge_key"))return null;let s=K(t.headers["x-vcp-site-edit-key"]),r=ce(s,e.sessionKey),i=K(t.headers.host),o=K(t.headers.origin);return i&&!Xe(i,e.host,o)?null:o?tt(o,i,e.allowedOrigins)?{authenticatedByHeader:r}:null:r?{authenticatedByHeader:!0}:null}function Ze(t,e,n){let s=setTimeout(()=>{t.close(1008,"bridge authentication timeout")},qe),r,i=()=>{clearTimeout(s),t.off("message",r),t.off("close",i)},o=()=>{i(),t.close(1008,"bridge authentication failed")};r=c=>{try{let d=p.parseMessage(c.toString());if(d.type!=="auth"||!ce(d.payload.key,e)){o();return}i(),t.readyState===oe.OPEN&&t.send(p.stringifyMessage({type:"auth-ok",payload:{ok:!0}})),n()}catch{o()}},t.on("message",r),t.on("close",i)}function ce(t,e){if(!t)return!1;let n=Buffer.from(t),s=Buffer.from(e);return n.length===s.length&&Be(n,s)}function Xe(t,e,n){let s=re(t),r=re(e);return s===r||se(r)&&se(s)&&(!n||J(n,t))||et(r)&&(!n||J(n,t))}function et(t){return t==="0.0.0.0"||t==="::"}function se(t){return t==="localhost"||t==="127.0.0.1"||t==="::1"}function tt(t,e,n){return n.includes(t)||(e?J(t,e):!1)}function J(t,e){try{return new URL(t).host===de(e)}catch{return!1}}function re(t){let e=de(t);return e.startsWith("[")?e.slice(1,e.indexOf("]")):e.split(":").length-1===1?e.split(":",1)[0]??"":e}function de(t){return t.trim().toLowerCase()}function K(t){return Array.isArray(t)?t[0]:t}function nt(){return He(32).toString("base64url")}var rt="next",it="127.0.0.1",ot=3e3,B="/__vcp/site-edit/bridge",ye="/__vcp/site-edit/health",j="/__vcp/site-edit/client/",at=`${j}auto-bootstrap.js`,Se='data-vcp-site-edit-bootstrap="true"',ut=["next.config.ts","next.config.mts","next.config.cts","next.config.js","next.config.mjs","next.config.cjs"],ct="@vcp-dev/site-edit-engine/webpack-loader",dt=/@vcp\/site-edit-engine\/(?:webpack-loader|site-edit-instrumentation-loader)/,ht=[/\bconfig\.webpack\s*=/,/\bwebpack\s*\([^)]*\)\s*\{/,/\bwebpack\s*:\s*(?:async\s*)?(?:\([^)]*\)|[A-Za-z_$][\w$]*)?\s*=>/,/\bwebpack\s*:\s*(?:async\s+)?function\b/],lt=new Set(["auto-bootstrap.js","client.js","designer-trace.js","document-codec.js","protocol.js","window-message.js"]);async function Sn(t={},e={}){let n=e.process??process,s=e.createServer??st.createServer,r=e.attachBridgeServer??ue,i=e.loadNext??Vt,o=R.resolve(t.projectRoot??process.cwd()),c=t.host??it,d=t.port??qt(n.env.PORT)??ot,h=t.bridgePath??B,g=wt(h),a=Dt(),u=t.basePath??n.env.VCP_SITE_PREVIEW_BASE_PATH??"/",l=(t.tenantId??n.env.VCP_TENANT_ID)?.trim()||void 0,v=await i(o),I=ft(o),m=v({dev:!0,dir:o,hostname:c,port:d,...pt(I)}),Re=m.getRequestHandler(),xe=t.siteId??n.env.VCP_SITE_ID??"018f6f4d-a9b8-7120-8000-000000000120",be=t.snapshotId??n.env.VCP_SNAPSHOT_ID??Lt(o),G=t.historyRoot??n.env.VCP_SITE_EDIT_HISTORY_ROOT,Q=G?.trim()?R.resolve(G):void 0,k=null,y=s((M,_)=>{Ct({basePath:u,bridgePath:h,bridgeHealthPath:g,bridgeSessionKey:a,getBridgeHealth:()=>k?.getHealth()??_t(h),handle:Re,request:M,response:_}).catch(ve=>{console.error(ve),_.headersSent||(_.statusCode=500),_.end("site edit preview request failed")})}),A=null,C=null,D=()=>C||(H(()=>n.off("SIGINT",E)),H(()=>n.off("SIGTERM",E)),H(()=>A?.()),A=null,H(()=>k?.stop()),k=null,C=Promise.allSettled([Jt(y),Wt(()=>m.close())]).then(()=>{}),C),E=()=>{D()};try{return await m.prepare(),k=r(y,{...l?{tenantId:l}:{},siteId:xe,snapshotId:be,projectRoot:o,basePath:u,host:c,port:d,path:h,sessionKey:a,...Q?{historyRoot:Q}:{}}),A=yt({server:y,bridgePath:h,handleUpgrade:m.getUpgradeHandler()}),n.on("SIGINT",E),n.on("SIGTERM",E),await $t(y,d,c),{bundler:I,close:D,host:c,port:zt(y,d),server:y}}catch(M){throw await D(),M}}function ft(t){let e=gt(t);return e&&mt(e)?"webpack":"turbopack"}function pt(t){return t==="webpack"?{webpack:!0}:{turbopack:!0}}function gt(t){for(let e of ut){let n=b(t,e);if(w(n))return S(n,"utf8")}return null}function mt(t){return t.includes(ct)?!0:dt.test(t)&&ht.some(e=>e.test(t))}function yt(t){let e=(n,s,r)=>{St(n.url,t.bridgePath)||t.handleUpgrade(n,s,r).catch(i=>{console.error(i),s.destroyed||s.destroy()})};return t.server.on("upgrade",e),()=>t.server.off("upgrade",e)}function St(t,e){return new URL(t??"/","http://localhost").pathname===e}function wt(t=B){if(t===B)return ye;let e=(t.startsWith("/")?t:`/${t}`).replace(/\/+$/,"");return e.endsWith("/bridge")?`${e.slice(0,-7)}/health`:e?`${e}/health`:"/health"}function It(t){let e=JSON.stringify({basePath:t.basePath,wsPath:t.bridgePath,bridge_session_key:t.bridgeSessionKey,defer_initial_sync:!0,runtime_versions:t.runtimeVersions??Rt()});return`<script type="module" ${Se}>import { startSiteEditAutoBootstrap } from ${JSON.stringify(at)};void startSiteEditAutoBootstrap(window, ${e}).catch(() => undefined);</script>`}function Rt(){return{bridge:W("@vcp-dev/site-edit-bridge"),contracts:W("@vcp-dev/contracts"),engine:W("@vcp-dev/site-edit-engine")}}function W(t){let e=pe(import.meta.url);try{let n=e.resolve(t),s=xt(n,t);if(!s)return;let r=JSON.parse(S(s,"utf8"));return typeof r.version=="string"?r.version:void 0}catch{return}}function xt(t,e){let n=R.parse(t).root,s=x(t);for(;s&&s!==n;){let r=b(s,"package.json");if(w(r))try{if(JSON.parse(S(r,"utf8")).name===e)return r}catch{return}s=x(s)}}function bt(t,e){if(t.includes(Se))return t;let n=It(e),s=/<\/body\s*>/i.exec(t);return s?`${t.slice(0,s.index)}${n}${t.slice(s.index)}`:`${t}${n}`}function wn(t,e=x(me(import.meta.url)),n=w){return we(t,e,n)?.path??null}function we(t,e=x(me(import.meta.url)),n=w){let s=new URL(t??"/","http://localhost").pathname;if(!s.startsWith(j))return null;let r=s.slice(j.length);if(!lt.has(r))return null;let i=z(Ft(e),r);if(ge(e)!=="src")return{path:i,requiresTranspile:!1};let o=z(e,r.replace(/\.js$/,".ts"));return n(o)?{path:o,requiresTranspile:!0}:{path:i,requiresTranspile:!1}}async function vt(t,e){let n=we(t.url);if(!n)return!1;if(!w(n.path))return e.writeHead(404),e.end("site edit client asset not found"),!0;let s=n.requiresTranspile?await kt(S(n.path,"utf8")):S(n.path);return e.writeHead(200,{"cache-control":"no-store","content-type":"text/javascript; charset=utf-8"}),e.end(s),!0}async function kt(t){let e=await import("typescript");return e.transpileModule(t,{compilerOptions:{module:e.ModuleKind.ES2022,target:e.ScriptTarget.ES2022}}).outputText}async function Ct({basePath:t,bridgePath:e,bridgeHealthPath:n,bridgeSessionKey:s,getBridgeHealth:r,handle:i,request:o,response:c}){if(Et(o,c,n,r)||await vt(o,c))return;let d=Pt(o),h=Tt(o),g=d||h?jt(c,{basePath:t,bridgePath:e,bridgeSessionKey:s,patchNextDevChunk:h}):()=>{};try{await i(o,c)}catch(a){throw g(),a}}function Et(t,e,n,s){if(t.method!=="GET"||new URL(t.url??"/","http://localhost").pathname!==n)return!1;let i=s();return e.writeHead(i.ok?200:503,{"cache-control":"no-store","content-type":"application/json; charset=utf-8"}),e.end(JSON.stringify(i)),!0}function _t(t){return{ok:!1,bridgePath:t,runtimeReady:!1,routesIndexed:0,sessionRequired:!0}}function Pt(t){return Ht(t)?(t.headers["accept-encoding"]="identity",!0):!1}function Tt(t){return Bt(t)?(t.headers["accept-encoding"]="identity",!0):!1}function Ht(t){if(t.method!=="GET")return!1;let e=new URL(t.url??"/","http://localhost").pathname;if(e.startsWith("/_next/")||e.startsWith(j)||e===B||e===ye)return!1;let n=t.headers.accept??"";return n===""||n.includes("text/html")}function Bt(t){if(t.method!=="GET"||!String(t.headers["user-agent"]??"").includes("Firefox"))return!1;let n=new URL(t.url??"/","http://localhost").pathname;return n.startsWith("/_next/static/chunks/")&&n.endsWith(".js")}function jt(t,e){let n=[],s=t,r=s.flushHeaders.bind(t),i=s.write.bind(t),o=s.end.bind(t);return s.flushHeaders=()=>{},s.write=(c,d,h)=>(c!==void 0&&n.push(he(c,le(d))),fe(d),fe(h),!0),s.end=(c,d,h)=>{let g=typeof c=="function"?void 0:c;g!==void 0&&n.push(he(g,le(d))),s.write=i,s.end=o,s.flushHeaders=r;let a=Buffer.concat(n),u=At(t,a,e);u!==a&&!t.headersSent&&t.removeHeader("content-length");let l=typeof c=="function"?c:typeof d=="function"?d:typeof h=="function"?h:void 0;return l?o(u,l):o(u)},()=>{s.write=i,s.end=o,s.flushHeaders=r}}function At(t,e,n){if(Mt(t,e))return Buffer.from(bt(e.toString("utf8"),n));if(n.patchNextDevChunk&&Ut(t)){let s=e.toString("utf8"),r=Nt(s);if(r!==s)return Buffer.from(r)}return e}function Dt(){let t=new Uint8Array(32);return globalThis.crypto.getRandomValues(t),Buffer.from(t).toString("base64url")}function Mt(t,e){if(t.statusCode<200||t.statusCode>=300)return!1;let n=t.getHeader("content-type"),s=Array.isArray(n)?n.join(";"):String(n??"");return e.toString("utf8",0,256).includes("<html")&&(s===""||s.includes("text/html"))}function Ut(t){if(t.statusCode<200||t.statusCode>=300)return!1;let e=t.getHeader("content-type"),n=Array.isArray(e)?e.join(";"):String(e??"");return n===""||n.includes("javascript")||n.includes("ecmascript")}function Nt(t){return[["debugChannel = createDebugChannel(undefined);","debugChannel = undefined;"],["if (isStreamErrorOrUnfinished(ctr)) {","if (false) {"],["return ctr.desiredSize === null || ctr.desiredSize < 0;","return false;"],[["findSourceMapURL: _appfindsourcemapurl.findSourceMapURL,"," debugChannel,"," startTime: 0"].join(`
|
|
4
|
+
`),r.destroy();return}c.authenticatedByHeader&&n.add(s),t.handleUpgrade(s,r,a,d=>{t.emit("connection",d,s)})};return e.server.on("upgrade",o),t.on("connection",(s,r)=>{if(n.has(r)){i(s);return}It(s,e.sessionKey,()=>{i(s)})}),t.stop=()=>{e.server.off("upgrade",o);for(let s of t.clients)s.close(1001,"bridge stopped");t.close()},t}var te=class{constructor(t){this.socket=t,this.onmessage=null,this.onclose=null,t.on("error",()=>{}),t.on("message",n=>{this.onmessage?.({data:n.toString()})}),t.on("close",()=>{this.onclose?.()})}send(t){if(this.socket.readyState===Se.OPEN){if(this.socket.bufferedAmount+Buffer.byteLength(t,"utf8")>at){this.socket.close(1013,"bridge backpressure");return}this.socket.send(t)}}close(t,n){this.socket.close(t,n)}};function yt(e,t){return new URL(e.url??"/","http://localhost").pathname===t.path}function St(e,t){if(new URL(e.url??"/","http://localhost").searchParams.has("vcp_bridge_key"))return null;let i=X(e.headers["x-vcp-site-edit-key"]),o=xe(i,t.sessionKey),s=X(e.headers.host),r=X(e.headers.origin);return s&&!wt(s,t.host,r)?null:r?Ct(r,s,t.allowedOrigins)?{authenticatedByHeader:o}:null:o?{authenticatedByHeader:!0}:null}function It(e,t,n){let i=setTimeout(()=>{e.close(1008,"bridge authentication timeout")},ct),o,s=()=>{clearTimeout(i),e.off("message",o),e.off("close",s)},r=()=>{s(),e.close(1008,"bridge authentication failed")};o=a=>{try{let c=m.parseMessage(a.toString());if(c.type!=="auth"||!xe(c.payload.key,t)){r();return}s(),e.readyState===Se.OPEN&&e.send(m.stringifyMessage({type:"auth-ok",payload:{ok:!0}})),n()}catch{r()}},e.on("message",o),e.on("close",s)}function xe(e,t){if(!e)return!1;let n=Buffer.from(e),i=Buffer.from(t);return n.length===i.length&&Je(n,i)}function wt(e,t,n){let i=ge(e),o=ge(t);return i===o||me(o)&&me(i)&&(!n||ne(n,e))||xt(o)&&(!n||ne(n,e))}function xt(e){return e==="0.0.0.0"||e==="::"}function me(e){return e==="localhost"||e==="127.0.0.1"||e==="::1"}function Ct(e,t,n){return n.includes(e)||(t?ne(e,t):!1)}function ne(e,t){try{return new URL(e).host===Ce(t)}catch{return!1}}function ge(e){let t=Ce(e);return t.startsWith("[")?t.slice(1,t.indexOf("]")):t.split(":").length-1===1?t.split(":",1)[0]??"":t}function Ce(e){return e.trim().toLowerCase()}function X(e){return Array.isArray(e)?e[0]:e}function bt(){return ze(32).toString("base64url")}var Et="next",vt="127.0.0.1",_t=3e3,F="/__vcp/site-edit/bridge",Te="/__vcp/site-edit/health",U="/__vcp/site-edit/client/",kt=`${U}auto-bootstrap.js`,Pe='data-vcp-site-edit-bootstrap="true"',Tt=["next.config.ts","next.config.mts","next.config.cts","next.config.js","next.config.mjs","next.config.cjs"],Pt="@vcp-dev/site-edit-engine/webpack-loader",Ht=/@vcp\/site-edit-engine\/(?:webpack-loader|site-edit-instrumentation-loader)/,Bt=[/\bconfig\.webpack\s*=/,/\bwebpack\s*\([^)]*\)\s*\{/,/\bwebpack\s*:\s*(?:async\s*)?(?:\([^)]*\)|[A-Za-z_$][\w$]*)?\s*=>/,/\bwebpack\s*:\s*(?:async\s+)?function\b/],At=new Set(["auto-bootstrap.js","client.js","composition-key.js","designer-trace.js","document-codec.js","protocol.js","window-message.js"]);async function Un(e={},t={}){let n=t.process??process,i=t.createServer??Rt.createServer,o=t.attachBridgeServer??we,s=t.loadNext??cn,r=k.resolve(e.projectRoot??process.cwd()),a=e.host??vt,c=e.port??pn(n.env.PORT)??_t,d=e.bridgePath??F,l=Ut(d),u=nn(),h=e.basePath??n.env.VCP_SITE_PREVIEW_BASE_PATH??"/",f=(e.tenantId??n.env.VCP_TENANT_ID)?.trim()||void 0,H=await s(r),v=Ot(r),I=H({dev:!0,dir:r,hostname:a,port:c,...Dt(v)}),Ae=I.getRequestHandler(),Oe=e.siteId??n.env.VCP_SITE_ID??"018f6f4d-a9b8-7120-8000-000000000120",De=e.snapshotId??n.env.VCP_SNAPSHOT_ID??hn(r),oe=e.historyRoot??n.env.VCP_SITE_EDIT_HISTORY_ROOT,re=oe?.trim()?k.resolve(oe):void 0,B=null,b=i((q,D)=>{zt({basePath:h,bridgePath:d,bridgeHealthPath:l,bridgeSessionKey:u,getBridgeHealth:()=>B?.getHealth()??Gt(d),handle:Ae,request:q,response:D}).catch(Me=>{console.error(Me),D.headersSent||(D.statusCode=500),D.end("site edit preview request failed")})}),K=null,A=null,V=()=>A||(j(()=>n.off("SIGINT",O)),j(()=>n.off("SIGTERM",O)),j(()=>K?.()),K=null,j(()=>B?.stop()),B=null,A=Promise.allSettled([fn(b),mn(()=>I.close())]).then(()=>{}),A),O=()=>{V()};try{return await I.prepare(),B=o(b,{...f?{tenantId:f}:{},siteId:Oe,snapshotId:De,projectRoot:r,basePath:h,host:a,port:c,path:d,sessionKey:u,...re?{historyRoot:re}:{}}),K=jt({server:b,bridgePath:d,handleUpgrade:I.getUpgradeHandler()}),n.on("SIGINT",O),n.on("SIGTERM",O),await ln(b,c,a),{bundler:v,close:V,host:a,port:gn(b,c),server:b}}catch(q){throw await V(),q}}function Ot(e){let t=Mt(e);return t&&Nt(t)?"webpack":"turbopack"}function Dt(e){return e==="webpack"?{webpack:!0}:{turbopack:!0}}function Mt(e){for(let t of Tt){let n=P(e,t);if(E(n))return R(n,"utf8")}return null}function Nt(e){return e.includes(Pt)?!0:Ht.test(e)&&Bt.some(t=>t.test(e))}function jt(e){let t=(n,i,o)=>{Ft(n.url,e.bridgePath)||e.handleUpgrade(n,i,o).catch(s=>{console.error(s),i.destroyed||i.destroy()})};return e.server.on("upgrade",t),()=>e.server.off("upgrade",t)}function Ft(e,t){return new URL(e??"/","http://localhost").pathname===t}function Ut(e=F){if(e===F)return Te;let t=(e.startsWith("/")?e:`/${e}`).replace(/\/+$/,"");return t.endsWith("/bridge")?`${t.slice(0,-7)}/health`:t?`${t}/health`:"/health"}function Kt(e){let t=JSON.stringify({basePath:e.basePath,wsPath:e.bridgePath,bridge_session_key:e.bridgeSessionKey,defer_initial_sync:!0,runtime_versions:e.runtimeVersions??Vt()});return`<script type="module" ${Pe}>import { startSiteEditAutoBootstrap } from ${JSON.stringify(kt)};void startSiteEditAutoBootstrap(window, ${t}).catch(() => undefined);</script>`}function Vt(){return{bridge:ie("@vcp-dev/site-edit-bridge"),contracts:ie("@vcp-dev/contracts"),engine:ie("@vcp-dev/site-edit-engine")}}function ie(e){let t=ve(import.meta.url);try{let n=t.resolve(e),i=qt(n,e);if(!i)return;let o=JSON.parse(R(i,"utf8"));return typeof o.version=="string"?o.version:void 0}catch{return}}function qt(e,t){let n=k.parse(e).root,i=T(e);for(;i&&i!==n;){let o=P(i,"package.json");if(E(o))try{if(JSON.parse(R(o,"utf8")).name===t)return o}catch{return}i=T(i)}}function Wt(e,t){if(e.includes(Pe))return e;let n=Kt(t),i=/<\/body\s*>/i.exec(e);return i?`${e.slice(0,i.index)}${n}${e.slice(i.index)}`:`${e}${n}`}function Kn(e,t=T(ke(import.meta.url)),n=E){return He(e,t,n)?.path??null}function He(e,t=T(ke(import.meta.url)),n=E){let i=new URL(e??"/","http://localhost").pathname;if(!i.startsWith(U))return null;let o=i.slice(U.length);if(!At.has(o))return null;let s=se(un(t),o);if(_e(t)!=="src")return{path:s,requiresTranspile:!1};let r=se(t,o.replace(/\.js$/,".ts"));return n(r)?{path:r,requiresTranspile:!0}:{path:s,requiresTranspile:!1}}async function Lt(e,t){let n=He(e.url);if(!n)return!1;if(!E(n.path))return t.writeHead(404),t.end("site edit client asset not found"),!0;let i=n.requiresTranspile?await $t(R(n.path,"utf8")):R(n.path);return t.writeHead(200,{"cache-control":"no-store","content-type":"text/javascript; charset=utf-8"}),t.end(i),!0}async function $t(e){let t=await import("typescript");return t.transpileModule(e,{compilerOptions:{module:t.ModuleKind.ES2022,target:t.ScriptTarget.ES2022}}).outputText}async function zt({basePath:e,bridgePath:t,bridgeHealthPath:n,bridgeSessionKey:i,getBridgeHealth:o,handle:s,request:r,response:a}){if(Jt(r,a,n,o)||await Lt(r,a))return;let c=Qt(r),d=Yt(r),l=c||d?en(a,{basePath:e,bridgePath:t,bridgeSessionKey:i,patchNextDevChunk:d}):()=>{};try{await s(r,a)}catch(u){throw l(),u}}function Jt(e,t,n,i){if(e.method!=="GET"||new URL(e.url??"/","http://localhost").pathname!==n)return!1;let s=i();return t.writeHead(s.ok?200:503,{"cache-control":"no-store","content-type":"application/json; charset=utf-8"}),t.end(JSON.stringify(s)),!0}function Gt(e){return{ok:!1,bridgePath:e,runtimeReady:!1,routesIndexed:0,sessionRequired:!0}}function Qt(e){return Zt(e)?(e.headers["accept-encoding"]="identity",!0):!1}function Yt(e){return Xt(e)?(e.headers["accept-encoding"]="identity",!0):!1}function Zt(e){if(e.method!=="GET")return!1;let t=new URL(e.url??"/","http://localhost").pathname;if(t.startsWith("/_next/")||t.startsWith(U)||t===F||t===Te)return!1;let n=e.headers.accept??"";return n===""||n.includes("text/html")}function Xt(e){if(e.method!=="GET"||!String(e.headers["user-agent"]??"").includes("Firefox"))return!1;let n=new URL(e.url??"/","http://localhost").pathname;return n.startsWith("/_next/static/chunks/")&&n.endsWith(".js")}function en(e,t){let n=[],i=e,o=i.flushHeaders.bind(e),s=i.write.bind(e),r=i.end.bind(e);return i.flushHeaders=()=>{},i.write=(a,c,d)=>(a!==void 0&&n.push(be(a,Re(c))),Ee(c),Ee(d),!0),i.end=(a,c,d)=>{let l=typeof a=="function"?void 0:a;l!==void 0&&n.push(be(l,Re(c))),i.write=s,i.end=r,i.flushHeaders=o;let u=Buffer.concat(n),h=tn(e,u,t);h!==u&&!e.headersSent&&e.removeHeader("content-length");let f=typeof a=="function"?a:typeof c=="function"?c:typeof d=="function"?d:void 0;return f?r(h,f):r(h)},()=>{i.write=s,i.end=r,i.flushHeaders=o}}function tn(e,t,n){if(sn(e,t))return Buffer.from(Wt(t.toString("utf8"),n));if(n.patchNextDevChunk&&on(e)){let i=t.toString("utf8"),o=rn(i);if(o!==i)return Buffer.from(o)}return t}function nn(){let e=new Uint8Array(32);return globalThis.crypto.getRandomValues(e),Buffer.from(e).toString("base64url")}function sn(e,t){if(e.statusCode<200||e.statusCode>=300)return!1;let n=e.getHeader("content-type"),i=Array.isArray(n)?n.join(";"):String(n??"");return t.toString("utf8",0,256).includes("<html")&&(i===""||i.includes("text/html"))}function on(e){if(e.statusCode<200||e.statusCode>=300)return!1;let t=e.getHeader("content-type"),n=Array.isArray(t)?t.join(";"):String(t??"");return n===""||n.includes("javascript")||n.includes("ecmascript")}function rn(e){return[["debugChannel = createDebugChannel(undefined);","debugChannel = undefined;"],["if (isStreamErrorOrUnfinished(ctr)) {","if (false) {"],["return ctr.desiredSize === null || ctr.desiredSize < 0;","return false;"],[["findSourceMapURL: _appfindsourcemapurl.findSourceMapURL,"," debugChannel,"," startTime: 0"].join(`
|
|
5
5
|
`),["unstable_allowPartialStream: true,"," debugChannel,"," startTime: 0"].join(`
|
|
6
|
-
`)],[["findSourceMapURL: _appfindsourcemapurl.findSourceMapURL,"," debugChannel,"," startTime: 0"].join("\\n"),["unstable_allowPartialStream: true,"," debugChannel,"," startTime: 0"].join("\\n")],["debugChannel: createDebugChannel && createDebugChannel(requestHeaders)","debugChannel: undefined"],["debugChannel: createDebugChannel && createDebugChannel(headers)","debugChannel: undefined"]].reduce((n,[
|
|
6
|
+
`)],[["findSourceMapURL: _appfindsourcemapurl.findSourceMapURL,"," debugChannel,"," startTime: 0"].join("\\n"),["unstable_allowPartialStream: true,"," debugChannel,"," startTime: 0"].join("\\n")],["debugChannel: createDebugChannel && createDebugChannel(requestHeaders)","debugChannel: undefined"],["debugChannel: createDebugChannel && createDebugChannel(headers)","debugChannel: undefined"]].reduce((n,[i,o])=>an(n,i,o),e)}function an(e,t,n){if(n.length>t.length)throw new Error("Replacement must not be longer than the search string.");return e.replaceAll(t,n.padEnd(t.length," "))}function be(e,t){return Buffer.isBuffer(e)?e:e instanceof Uint8Array?Buffer.from(e):Buffer.from(String(e),t)}function Re(e){return typeof e=="string"?e:void 0}function Ee(e){typeof e=="function"&&e()}async function cn(e){let n=ve(P(e,"package.json"))(Et);return n.default??n}function un(e){return _e(e)!=="src"?e:se(dn(e),"dist")}function dn(e){return Be(e)?k.posix.dirname(e):T(e)}function se(e,t){return Be(e)?k.posix.join(e,t):P(e,t)}function Be(e){return e.includes("/")&&!e.includes("\\")}function hn(e){let t=P(e,".vcp/current-snapshot.json");if(!E(t))return"sandbox_worktree";try{let n=JSON.parse(R(t,"utf8"));return typeof n.snapshotId=="string"?n.snapshotId:"sandbox_worktree"}catch{return"sandbox_worktree"}}function pn(e){if(!e)return null;let t=Number.parseInt(e,10);return Number.isInteger(t)&&t>0&&t<=65535?t:null}function ln(e,t,n){return new Promise((i,o)=>{e.once("error",o),e.listen(t,n,()=>{e.off("error",o),i()})})}function fn(e){return new Promise(t=>{e.close(()=>t())})}function j(e){try{e()}catch{}}function mn(e){try{return e()}catch(t){return Promise.reject(t)}}function gn(e,t){let n=e.address();return typeof n=="object"&&n?n.port:t}export{jt as attachNextDevUpgradeHandler,Kt as createSiteEditAutoBootstrapHtmlSnippet,Wt as injectSiteEditAutoBootstrap,rn as patchNextFirefoxDevChunk,Yt as prepareFirefoxNextDevChunkPatchRequest,Qt as prepareSiteEditHtmlInjectionRequest,Ut as resolveSiteEditBridgeHealthPath,He as resolveSiteEditClientAsset,Kn as resolveSiteEditClientAssetPath,Ot as resolveSiteEditNextDevBundler,Un as startSiteEditNextDevServer,$t as transpileSiteEditClientSource};
|
package/dist/protocol.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import { type CompactRenderDocument } from "./document-codec.js";
|
|
1
|
+
import type { SiteEditClassNameSourceStyleContext, SiteEditCommandSuccess, SiteEditCompositionContext, SiteEditCompositionSelector, SiteEditEvent, SiteEditGetClassNameSourceCommandResult, SiteEditMutationContext, SiteEditObjectEditContext, SiteEditOperationCommandResult, SiteEditOperationRequest, SiteEditRenderDocument, SiteEditResolveSourceLocationInput, SiteEditSourceFileResponse, SiteEditSourceLocation, SiteEditSourceTreeResponse } from "@vcp-dev/contracts";
|
|
3
2
|
type Awaitable<T> = T | Promise<T>;
|
|
3
|
+
/** The Bridge keeps this old shape at its boundary for compatibility with the
|
|
4
|
+
* durable history adapter. The selected composition is carried beside it. */
|
|
4
5
|
export type SiteEditHistoryStatus = {
|
|
5
6
|
canUndo: boolean;
|
|
6
7
|
canRedo: boolean;
|
|
@@ -8,160 +9,65 @@ export type SiteEditHistoryStatus = {
|
|
|
8
9
|
redoDepth: number;
|
|
9
10
|
recoveryRequired: boolean;
|
|
10
11
|
};
|
|
12
|
+
export type SiteEditBridgeCompositionResolution = {
|
|
13
|
+
context: SiteEditCompositionContext;
|
|
14
|
+
entryFile?: string;
|
|
15
|
+
mode?: "direct" | "delegated";
|
|
16
|
+
};
|
|
17
|
+
export type SiteEditBridgeSessionState = {
|
|
18
|
+
activeComposition?: SiteEditCompositionContext;
|
|
19
|
+
subscribedCompositionKeys: Set<string>;
|
|
20
|
+
};
|
|
21
|
+
export declare const SITE_EDIT_COMPOSITION_SESSION_MISMATCH = "SITE_EDIT_COMPOSITION_SESSION_MISMATCH";
|
|
22
|
+
export declare const SITE_EDIT_COMPOSITION_SESSION_REQUIRED = "SITE_EDIT_COMPOSITION_SESSION_REQUIRED";
|
|
23
|
+
export declare const SITE_EDIT_COMPOSITION_REINITIALIZE_REQUIRED = "SITE_EDIT_COMPOSITION_REINITIALIZE_REQUIRED";
|
|
11
24
|
export type SiteEditBridgeRequestKind = "initialize-session" | "get-document" | "get-history-status" | "get-style-context" | "get-object-edit-context" | "get-class-name-source" | "get-source-tree" | "get-source-file" | "resolve-source-location" | "execute" | "undo" | "redo";
|
|
25
|
+
type CompositionRequestFields = {
|
|
26
|
+
/** Current protocol selector; required for every composition-sensitive wire request. */
|
|
27
|
+
composition: SiteEditCompositionSelector;
|
|
28
|
+
};
|
|
12
29
|
export type SiteEditBridgeRequest = {
|
|
13
30
|
type: "request";
|
|
14
|
-
payload: {
|
|
31
|
+
payload: ({
|
|
15
32
|
id: string;
|
|
16
33
|
kind: "initialize-session";
|
|
17
|
-
routeId: string;
|
|
18
34
|
mutationContext?: SiteEditMutationContext;
|
|
19
|
-
}
|
|
20
|
-
} | {
|
|
21
|
-
type: "request";
|
|
22
|
-
payload: {
|
|
35
|
+
} & CompositionRequestFields) | ({
|
|
23
36
|
id: string;
|
|
24
37
|
kind: "get-document";
|
|
25
|
-
|
|
26
|
-
};
|
|
27
|
-
} | {
|
|
28
|
-
type: "request";
|
|
29
|
-
payload: {
|
|
38
|
+
} & CompositionRequestFields) | ({
|
|
30
39
|
id: string;
|
|
31
40
|
kind: "get-history-status";
|
|
32
|
-
}
|
|
33
|
-
} | {
|
|
34
|
-
type: "request";
|
|
35
|
-
payload: {
|
|
41
|
+
} & CompositionRequestFields) | ({
|
|
36
42
|
id: string;
|
|
37
43
|
kind: "get-style-context";
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
44
|
+
} & CompositionRequestFields) | ({
|
|
45
|
+
id: string;
|
|
46
|
+
kind: "get-object-edit-context" | "get-class-name-source" | "resolve-source-location";
|
|
47
|
+
key: string;
|
|
48
|
+
} & CompositionRequestFields) | ({
|
|
43
49
|
id: string;
|
|
44
50
|
kind: "get-source-tree";
|
|
45
|
-
}
|
|
46
|
-
} | {
|
|
47
|
-
type: "request";
|
|
48
|
-
payload: {
|
|
51
|
+
} & CompositionRequestFields) | ({
|
|
49
52
|
id: string;
|
|
50
53
|
kind: "get-source-file";
|
|
51
54
|
path: string;
|
|
52
|
-
}
|
|
53
|
-
} | {
|
|
54
|
-
type: "request";
|
|
55
|
-
payload: {
|
|
56
|
-
id: string;
|
|
57
|
-
kind: "resolve-source-location";
|
|
58
|
-
key: string;
|
|
59
|
-
routeId?: string;
|
|
60
|
-
};
|
|
61
|
-
} | {
|
|
62
|
-
type: "request";
|
|
63
|
-
payload: {
|
|
64
|
-
id: string;
|
|
65
|
-
kind: "get-object-edit-context";
|
|
66
|
-
key: string;
|
|
67
|
-
routeId?: string;
|
|
68
|
-
};
|
|
69
|
-
} | {
|
|
70
|
-
type: "request";
|
|
71
|
-
payload: {
|
|
72
|
-
id: string;
|
|
73
|
-
kind: "get-class-name-source";
|
|
74
|
-
key: string;
|
|
75
|
-
routeId?: string;
|
|
76
|
-
};
|
|
77
|
-
} | {
|
|
78
|
-
type: "request";
|
|
79
|
-
payload: {
|
|
55
|
+
} & CompositionRequestFields) | ({
|
|
80
56
|
id: string;
|
|
81
57
|
kind: "execute";
|
|
82
|
-
request:
|
|
83
|
-
}
|
|
84
|
-
} | {
|
|
85
|
-
type: "request";
|
|
86
|
-
payload: {
|
|
58
|
+
request: SiteEditOperationRequest | Record<string, unknown>;
|
|
59
|
+
} & CompositionRequestFields) | ({
|
|
87
60
|
id: string;
|
|
88
61
|
kind: "undo" | "redo";
|
|
89
|
-
/** @deprecated Ignored by the runtime. */
|
|
90
62
|
mutationContext?: SiteEditMutationContext;
|
|
91
|
-
};
|
|
63
|
+
} & CompositionRequestFields);
|
|
92
64
|
};
|
|
93
65
|
export type SiteEditBridgeResponse = {
|
|
94
66
|
type: "response";
|
|
95
67
|
payload: {
|
|
96
68
|
id: string;
|
|
97
|
-
kind:
|
|
98
|
-
result:
|
|
99
|
-
document: SiteEditRenderDocument | CompactRenderDocument;
|
|
100
|
-
historyStatus: SiteEditHistoryStatus;
|
|
101
|
-
}>;
|
|
102
|
-
};
|
|
103
|
-
} | {
|
|
104
|
-
type: "response";
|
|
105
|
-
payload: {
|
|
106
|
-
id: string;
|
|
107
|
-
kind: "get-document";
|
|
108
|
-
result: SiteEditCommandSuccess<SiteEditRenderDocument> | SiteEditCommandSuccess<CompactRenderDocument>;
|
|
109
|
-
};
|
|
110
|
-
} | {
|
|
111
|
-
type: "response";
|
|
112
|
-
payload: {
|
|
113
|
-
id: string;
|
|
114
|
-
kind: "get-history-status";
|
|
115
|
-
result: SiteEditCommandSuccess<SiteEditHistoryStatus>;
|
|
116
|
-
};
|
|
117
|
-
} | {
|
|
118
|
-
type: "response";
|
|
119
|
-
payload: {
|
|
120
|
-
id: string;
|
|
121
|
-
kind: "get-style-context";
|
|
122
|
-
result: SiteEditCommandSuccess<SiteEditClassNameSourceStyleContext | null>;
|
|
123
|
-
};
|
|
124
|
-
} | {
|
|
125
|
-
type: "response";
|
|
126
|
-
payload: {
|
|
127
|
-
id: string;
|
|
128
|
-
kind: "get-source-tree";
|
|
129
|
-
result: SiteEditCommandSuccess<SiteEditSourceTreeResponse>;
|
|
130
|
-
};
|
|
131
|
-
} | {
|
|
132
|
-
type: "response";
|
|
133
|
-
payload: {
|
|
134
|
-
id: string;
|
|
135
|
-
kind: "get-source-file";
|
|
136
|
-
result: SiteEditCommandSuccess<SiteEditSourceFileResponse>;
|
|
137
|
-
};
|
|
138
|
-
} | {
|
|
139
|
-
type: "response";
|
|
140
|
-
payload: {
|
|
141
|
-
id: string;
|
|
142
|
-
kind: "resolve-source-location";
|
|
143
|
-
result: SiteEditCommandSuccess<SiteEditSourceLocation>;
|
|
144
|
-
};
|
|
145
|
-
} | {
|
|
146
|
-
type: "response";
|
|
147
|
-
payload: {
|
|
148
|
-
id: string;
|
|
149
|
-
kind: "get-object-edit-context";
|
|
150
|
-
result: SiteEditCommandSuccess<SiteEditObjectEditContext>;
|
|
151
|
-
};
|
|
152
|
-
} | {
|
|
153
|
-
type: "response";
|
|
154
|
-
payload: {
|
|
155
|
-
id: string;
|
|
156
|
-
kind: "get-class-name-source";
|
|
157
|
-
result: SiteEditGetClassNameSourceCommandResult;
|
|
158
|
-
};
|
|
159
|
-
} | {
|
|
160
|
-
type: "response";
|
|
161
|
-
payload: {
|
|
162
|
-
id: string;
|
|
163
|
-
kind: "execute" | "undo" | "redo";
|
|
164
|
-
result: SiteEditOperationCommandResult;
|
|
69
|
+
kind: SiteEditBridgeRequestKind;
|
|
70
|
+
result: unknown;
|
|
165
71
|
};
|
|
166
72
|
};
|
|
167
73
|
export type SiteEditBridgeError = {
|
|
@@ -192,26 +98,40 @@ export type SiteEditBridgeAuthOkMessage = {
|
|
|
192
98
|
};
|
|
193
99
|
};
|
|
194
100
|
export type SiteEditBridgeMessage = SiteEditBridgeAuthMessage | SiteEditBridgeAuthOkMessage | SiteEditBridgeRequest | SiteEditBridgeResponse | SiteEditBridgeError | SiteEditBridgeEventMessage;
|
|
101
|
+
/**
|
|
102
|
+
* Bridge engine contract. Every socket request is resolved to a normalized
|
|
103
|
+
* composition context before the engine is called; no engine method accepts a
|
|
104
|
+
* route-only selector or chooses a shared active route.
|
|
105
|
+
*/
|
|
195
106
|
export type SiteEditBridgeEngine = {
|
|
196
|
-
|
|
107
|
+
resolveComposition: (selector: SiteEditCompositionSelector) => Awaitable<SiteEditBridgeCompositionResolution>;
|
|
108
|
+
initializeSession(input: SiteEditBridgeInitializeInput): Awaitable<SiteEditCommandSuccess<{
|
|
197
109
|
document: SiteEditRenderDocument;
|
|
198
110
|
historyStatus: SiteEditHistoryStatus;
|
|
199
111
|
}>>;
|
|
200
|
-
getDocument(
|
|
201
|
-
getHistoryStatus(): Awaitable<SiteEditCommandSuccess<SiteEditHistoryStatus>>;
|
|
202
|
-
getStyleContext(
|
|
203
|
-
getObjectEditContext(key: string,
|
|
204
|
-
getClassNameSource(key: string,
|
|
205
|
-
getSourceTree(): Awaitable<SiteEditCommandSuccess<SiteEditSourceTreeResponse>>;
|
|
112
|
+
getDocument(composition: SiteEditCompositionContext): Awaitable<SiteEditCommandSuccess<SiteEditRenderDocument>>;
|
|
113
|
+
getHistoryStatus(composition: SiteEditCompositionContext): Awaitable<SiteEditCommandSuccess<SiteEditHistoryStatus>>;
|
|
114
|
+
getStyleContext(composition: SiteEditCompositionContext): Awaitable<SiteEditCommandSuccess<SiteEditClassNameSourceStyleContext | null>>;
|
|
115
|
+
getObjectEditContext(key: string, composition: SiteEditCompositionContext): Awaitable<SiteEditCommandSuccess<SiteEditObjectEditContext>>;
|
|
116
|
+
getClassNameSource(key: string, composition: SiteEditCompositionContext): Awaitable<SiteEditGetClassNameSourceCommandResult>;
|
|
117
|
+
getSourceTree(composition: SiteEditCompositionContext): Awaitable<SiteEditCommandSuccess<SiteEditSourceTreeResponse>>;
|
|
206
118
|
getSourceFile(input: {
|
|
207
119
|
path: string;
|
|
120
|
+
composition: SiteEditCompositionContext;
|
|
208
121
|
}): Awaitable<SiteEditCommandSuccess<SiteEditSourceFileResponse>>;
|
|
209
|
-
resolveSourceLocation(input: SiteEditResolveSourceLocationInput
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
122
|
+
resolveSourceLocation(input: SiteEditResolveSourceLocationInput | {
|
|
123
|
+
key: string;
|
|
124
|
+
composition: SiteEditCompositionContext;
|
|
125
|
+
}): Awaitable<SiteEditCommandSuccess<SiteEditSourceLocation>>;
|
|
126
|
+
execute(request: SiteEditOperationRequest, mutationContext?: SiteEditMutationContext): Awaitable<SiteEditOperationCommandResult>;
|
|
127
|
+
undo(composition: SiteEditCompositionContext): Awaitable<SiteEditOperationCommandResult>;
|
|
128
|
+
redo(composition: SiteEditCompositionContext): Awaitable<SiteEditOperationCommandResult>;
|
|
213
129
|
subscribe(listener: (event: SiteEditEvent) => void): () => void;
|
|
214
130
|
};
|
|
131
|
+
export type SiteEditBridgeInitializeInput = {
|
|
132
|
+
composition: SiteEditCompositionSelector | SiteEditCompositionContext;
|
|
133
|
+
mutationContext?: SiteEditMutationContext;
|
|
134
|
+
};
|
|
215
135
|
export type SiteEditMessageEventLike = {
|
|
216
136
|
data: string;
|
|
217
137
|
};
|
|
@@ -227,7 +147,7 @@ export declare class SiteEditBridgeTransport {
|
|
|
227
147
|
static parseMessage(raw: string, options?: {
|
|
228
148
|
validateOperationRequest?: SiteEditOperationRequestValidator;
|
|
229
149
|
}): SiteEditBridgeMessage;
|
|
230
|
-
static stringifyMessage(message:
|
|
150
|
+
static stringifyMessage(message: unknown): string;
|
|
231
151
|
static extractRequestInfo(message: unknown): {
|
|
232
152
|
id: string;
|
|
233
153
|
kind: SiteEditBridgeRequestKind;
|
|
@@ -236,19 +156,27 @@ export declare class SiteEditBridgeTransport {
|
|
|
236
156
|
static isMessage(value: unknown, options?: {
|
|
237
157
|
validateOperationRequest?: SiteEditOperationRequestValidator;
|
|
238
158
|
}): value is SiteEditBridgeMessage;
|
|
239
|
-
private static isRequestPayload;
|
|
240
159
|
}
|
|
241
160
|
export declare class SiteEditBridgeSocketServer {
|
|
242
161
|
private readonly options;
|
|
243
|
-
|
|
162
|
+
readonly session: SiteEditBridgeSessionState;
|
|
244
163
|
private readonly eventDispatcher;
|
|
245
164
|
private readonly messageQueue;
|
|
165
|
+
private readonly unsubscribe;
|
|
246
166
|
constructor(options: {
|
|
247
167
|
socket: SiteEditSocketLike;
|
|
248
168
|
engine: SiteEditBridgeEngine;
|
|
249
169
|
validateOperationRequest?: SiteEditOperationRequestValidator;
|
|
250
170
|
});
|
|
251
171
|
handleMessage(message: SiteEditBridgeMessage | unknown): Promise<void>;
|
|
172
|
+
private resolve;
|
|
173
|
+
private resolveAndAssert;
|
|
174
|
+
private resolveWireContext;
|
|
175
|
+
private resolveOperationWireContext;
|
|
176
|
+
private activateSession;
|
|
177
|
+
private normalizeOperationRequest;
|
|
178
|
+
private handleEngineEvent;
|
|
179
|
+
private sendResult;
|
|
252
180
|
private handleRawMessage;
|
|
253
181
|
private sendJson;
|
|
254
182
|
private handleBufferedOperation;
|