@vcp-dev/site-edit-bridge 0.10.24 → 0.10.25

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.
@@ -1,6 +1,7 @@
1
- import we from"node:http";import{existsSync as U,readFileSync as j}from"node:fs";import{randomUUID as Qt}from"node:crypto";import{createRequire as $e}from"node:module";import{Socket as Ke}from"node:net";import q from"node:path";import{basename as Le,dirname as z,join as G}from"node:path";import{fileURLToPath as qe}from"node:url";import{Worker as Kt}from"node:worker_threads";var Ce=["resolveComposition","initializeSession","getDocument","getHistoryStatus","getStyleContext","getObjectEditContext","getClassNameSource","getSourceTree","getSourceFile","resolveSourceLocation","execute","undo","redo"];function te(e){let t=new Error(e.message);return t.name=e.name,e.code!==void 0&&(t.code=e.code),t}import dt from"node:http";import L from"node:fs";import{createHash as Ne,randomBytes as ht,timingSafeEqual as pt}from"node:crypto";import R from"node:path";import{WebSocket as Me,WebSocketServer as lt}from"ws";import{createPreviewSiteEditEngineRuntime as ft,openFileHistoryStore as gt,resolveManagedPageTemplateComposition as mt,scanSiteEditCompositionsFromFiles as yt}from"@vcp-dev/site-edit-engine";import{resolveNextAppRouteId as St,scanNextAppRouterRoutesFromFiles as It}from"@vcp-dev/site-edit-engine/next-app-router";import{SiteEditSourceWatcher as Et}from"@vcp-dev/site-edit-engine/source-watcher";function be(e){let t=new Map,n=[],i=new Map,s=[],o=e.pageComposition.status==="supported"?e.pageComposition.placementUnitKeys:[],r=new Map(o.map((d,g)=>[d,g])),c=e.pageComposition.status==="supported"?{status:"supported",containerKey:e.pageComposition.containerKey,hasBusinessMembers:e.pageComposition.hasBusinessMembers,placementUnitKeys:e.pageComposition.placementUnitKeys,placements:e.pageComposition.placements.map(d=>({placementKey:d.placementKey,placementUnitKey:d.placementUnitKey,relation:d.relation}))}:{status:"unsupported",reason:e.pageComposition.reason,diagnostics:e.pageComposition.diagnostics},l=e.entries.flatMap((d,g)=>d.dynamicDataSummary?[[g,d.dynamicDataSummary]]:[]),a=new Map(e.entries.map((d,g)=>[d.key,g])),f=[];for(let[d,g]of e.entries.entries()){let m=g.pageCompositionActionScope;if(!m)continue;if(m.kind!=="source-siblings"){f.push([d,{kind:m.kind}]);continue}let x=m.siblingKeys.map(E=>{let w=a.get(E);if(w===void 0)throw new Error("Render entry "+g.key+" references missing source sibling "+E);return w});f.push([d,{kind:"source-siblings",siblingEntryIndexes:x}])}let u=d=>{let g=t.get(d);if(typeof g=="number")return g;let m=n.length;return n.push(d),t.set(d,m),m},S=d=>{let g=null;for(let m of tt(d)){let x=`${g??"root"}\0${m}`,E=i.get(x);if(typeof E=="number"){g=E;continue}let w=s.length;s.push([g,u(m)]),i.set(x,w),g=w}if(g===null)throw new Error("Document key must not be empty");return g};return{encoding:"segment-trie-v1",siteId:e.siteId,snapshotId:e.snapshotId,composition:{...e.composition},routeId:e.composition.routeId,version:e.version,pageComposition:c,tokens:n,nodes:s,entries:e.entries.map(d=>{let g=d.pageCompositionUnitKey?r.get(d.pageCompositionUnitKey)??-1:-1;if(d.pageCompositionUnitKey&&g<0)throw new Error(`Render entry ${d.key} references unknown page composition unit ${d.pageCompositionUnitKey}`);return[S(d.key),et(d.operationSummary),...g>=0?[g]:[]]}),...f.length>0?{pageCompositionActionScopes:f}:{},...e.entries.every(d=>d.parentKey!==void 0)?{entryParentNodeIds:e.entries.map(d=>d.parentKey===null?null:S(d.parentKey))}:{},...l.length>0?{dynamicDataSummaries:l}:{}}}function et(e){return(e.canUpdateText?1:0)|(e.canInsertChild?2:0)|(e.canMove?4:0)|(e.canRemove?8:0)}function tt(e){if(!e)return[];let t=[],n=0,i=ve(e,n);if(i<0)return t.push(e),t;for(t.push(e.slice(0,i)),n=i;n<e.length;){if(i=ve(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 ve(e,t){let n=e.indexOf("/",t),i=e.indexOf("::",t);return n<0?i:i<0?n:Math.min(n,i)}var Re="SITE_EDIT_COMPOSITION_SESSION_MISMATCH",ce="SITE_EDIT_COMPOSITION_SESSION_REQUIRED";var b=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(y(t)&&y(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!y(t)||typeof t.type!="string"?!1:t.type==="request"?nt(t.payload,n):t.type==="response"||t.type==="error"?y(t.payload)&&typeof t.payload.id=="string":t.type==="event"?y(t.payload)&&y(t.payload.event):t.type==="auth"?y(t.payload)&&typeof t.payload.key=="string":t.type==="auth-ok"&&y(t.payload)&&t.payload.ok===!0}},J=class{constructor(t){this.options=t,this.session={subscribedCompositionKeys:new Set},this.messageQueue=new ae,this.eventDispatcher=new re(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:s}=i;switch(i.kind){case"initialize-session":{let o=ne(i),r=await this.resolve(o),c=await this.options.engine.initializeSession({composition:r.context,...i.mutationContext?{mutationContext:i.mutationContext}:{}});this.activateSession(r.context),this.sendJson({type:"response",payload:{id:s,kind:i.kind,result:A({...c,data:{...c.data,document:ke(c.data.document)}},r.context)}});return}case"get-document":{let o=await this.resolveWireContext(i),r=await this.options.engine.getDocument(o);this.sendResult(s,i.kind,ct(r,o));return}case"get-history-status":{let o=await this.resolveWireContext(i),r=await this.options.engine.getHistoryStatus(o);this.sendResult(s,i.kind,A(r,o));return}case"get-style-context":{let o=await this.resolveWireContext(i);this.sendResult(s,i.kind,A(await this.options.engine.getStyleContext(o),o));return}case"get-object-edit-context":{let o=await this.resolveWireContext(i);this.sendResult(s,i.kind,A(await this.options.engine.getObjectEditContext(i.key,o,i.selectionRef),o));return}case"get-class-name-source":{let o=await this.resolveWireContext(i);this.sendResult(s,i.kind,A(await this.options.engine.getClassNameSource(i.key,o),o));return}case"get-source-tree":{let o=await this.resolveWireContext(i);this.sendResult(s,i.kind,A(await this.options.engine.getSourceTree(o),o));return}case"get-source-file":{let o=await this.resolveWireContext(i);this.sendResult(s,i.kind,A(await this.options.engine.getSourceFile({path:i.path,composition:o}),o));return}case"resolve-source-location":{let o=await this.resolveWireContext(i),r=A(await this.options.engine.resolveSourceLocation({key:i.key,composition:o}),o);this.sendResult(s,i.kind,r);return}case"execute":{let o=await this.resolveOperationWireContext(i.request),r=await this.resolveWireContext(i);if(H(o)!==H(r))throw new N(Re,"The execute request composition does not match its operation composition.");let c=await this.normalizeOperationRequest(i.request,o);await this.handleBufferedOperation(s,i.kind,()=>this.options.engine.execute(c));return}case"undo":case"redo":{let o=await this.resolveWireContext(i);await this.handleBufferedOperation(s,i.kind,()=>i.kind==="undo"?this.options.engine.undo(o):this.options.engine.redo(o));return}}}catch(n){let i=b.extractRequestInfo(t);this.sendJson({type:"error",payload:{...i,message:oe(n),code:se(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 N(ce,"Initialize a composition session before issuing this request.");if(H(i)!==H(n.context))throw new N(Re,"The request composition does not match the active socket session.");return n.context}async resolveWireContext(t){let n=ne(t);return this.resolveAndAssert(n)}async resolveOperationWireContext(t){let n=rt(t);return this.resolveAndAssert(n)}activateSession(t){this.session.activeComposition=t,this.session.subscribedCompositionKeys.clear(),this.session.subscribedCompositionKeys.add(H(t))}async normalizeOperationRequest(t,n){let i={...t,composition:_e(n)};if(i.target.kind==="route"){let s=i.target,o=ne(s),r=await this.resolveAndAssert(o);i.target={...s,composition:_e(r)}}return i}handleEngineEvent(t){let n=t?.composition;if(!ot(n))return;let i=H(n);this.session.subscribedCompositionKeys.has(i)&&(this.eventDispatcher.push(t),t.type==="site-edit.graph.invalidated"&&i===at(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(b.parseMessage(t,{validateOperationRequest:this.options.validateOperationRequest}))}catch(n){let i=ut(t);this.sendJson({type:"error",payload:{...i,message:oe(n),code:se(n)}})}}sendJson(t){this.options.socket.send(b.stringifyMessage(t))}async handleBufferedOperation(t,n,i){this.eventDispatcher.beginBuffering();try{let s=await i();this.sendResult(t,n,s)}catch(s){this.sendJson({type:"error",payload:{id:t,kind:n,message:oe(s),code:se(s)}})}finally{this.eventDispatcher.flush()}}},N=class extends Error{constructor(t,n){super(n),this.code=t,this.name="BridgeProtocolError"}},re=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))}},ae=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 nt(e,t){if(!y(e)||typeof e.id!="string"||!b.isRequestKind(e.kind))return!1;let n=$(e.composition);switch(e.kind){case"initialize-session":return n&&(e.mutationContext===void 0||ie(e.mutationContext));case"get-document":case"get-style-context":return n;case"get-object-edit-context":return typeof e.key=="string"&&n&&it(e.selectionRef);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&&st(e.request)&&(e.request.mutationContext===void 0||ie(e.request.mutationContext))&&(t.validateOperationRequest?.(e.request)??!0);case"undo":case"redo":return n&&e.mutationContext===void 0||n&&ie(e.mutationContext)}}function it(e){if(e===void 0)return!0;if(!y(e)||typeof e.key!="string"||e.key.length===0)return!1;let t=e.instanceIndex,n=e.instanceCount;return t!==void 0&&(typeof t!="number"||!Number.isInteger(t)||t<0)||n!==void 0&&(typeof n!="number"||!Number.isInteger(n)||n<=0)||typeof t=="number"&&typeof n=="number"&&t>=n?!1:Object.keys(e).every(i=>i==="key"||i==="instanceIndex"||i==="instanceCount")}function st(e){return y(e)&&typeof e.id=="string"&&typeof e.siteId=="string"&&typeof e.baseSnapshotId=="string"&&$(e.composition)&&typeof e.kind=="string"&&y(e.target)&&(e.target.kind!=="route"||$(e.target.composition))&&typeof e.documentVersion=="number"&&Number.isInteger(e.documentVersion)&&e.documentVersion>=0&&y(e.params)}function $(e){return y(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 ot(e){return y(e)&&typeof e.routeId=="string"&&(e.effectiveTemplateId===void 0||typeof e.effectiveTemplateId=="string")}function ne(e){if($(e.composition))return e.composition;throw new N(ce,"A composition selector is required for this request.")}function rt(e){if(y(e)&&$(e.composition))return e.composition;throw new N(ce,"A composition selector is required for execute.")}function _e(e){return{routeId:e.routeId,...e.effectiveTemplateId?{templateId:e.effectiveTemplateId}:{}}}function at(e){return e.activeComposition?H(e.activeComposition):null}function H(e){return JSON.stringify([e.routeId,e.effectiveTemplateId??null])}function A(e,t){return y(e)&&e.ok===!0?{...e,composition:t}:e}function ct(e,t){return!y(e)||e.ok!==!0?e:{...e,...t?{composition:t}:{},data:ke(e.data)}}function ke(e){let t=e;return be(t.routeId?t:{...t,routeId:t.composition.routeId})}function y(e){return typeof e=="object"&&e!==null}function ie(e){return y(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 se(e){if(!(!y(e)||typeof e.code!="string"||e.code.length===0))return e.code}function oe(e){return e instanceof Error||y(e)&&typeof e.message=="string"&&e.message.length>0?e.message:"Unknown websocket operation failure"}function ut(e){try{return b.extractRequestInfo(JSON.parse(e))}catch{return{id:"unknown",kind:"get-document"}}}var Q=class{constructor(){this.tail=Promise.resolve()}run(t){let n=this.tail.then(t,t);return this.tail=n.then(()=>{},()=>{}),n}};import{SiteEditOperationRequestSchema as wt,computeSiteEditCompositionKey as M}from"@vcp-dev/contracts";var xt="127.0.0.1",Ct=30218,vt="/__vcp/site-edit/bridge",Oe=6*1024*1024,bt=Oe*2,Rt=3e3,Te=50,he=".vcp/current-snapshot.json",Pe="__VCP_SITE_EDIT_BRIDGE_SERVERS__";function De(e,t,n={}){let i=new pe(je(t),e,!1,n);return i.start({listen:!1}),i}var pe=class{constructor(t,n=dt.createServer((o,r)=>{r.writeHead(404),r.end("VCP site edit bridge server")}),i=!0,s={}){this.options=t,this.server=n,this.closeHttpServerOnStop=i,this.dependencies=s,this.runtime=null,this.activeHistorySessionId=null,this.historySessionTransition=Promise.resolve(),this.mutationQueue=new Q,this.eventListeners=new Set,this.routes=[],this.compositions=[],this.compositionFiles=[],this.compositionResolutionError=null,this.launchCandidateEntries=null,this.stopWatching=null,this.stopWebSocketServer=null,this.pendingChangedFiles=new Set,this.fileChangeTimer=null,this.isStarted=!1,this.stopping=!1,this.runtimeVersionFloors=new Map,this.activeHistoryStore=null,this.versionPersistence=Promise.resolve(),this.bridgeEngine=null,this.lastNotifiedHealth=null}start(t={}){if(!this.isStarted){this.stopping=!1;try{L.mkdirSync(R.join(this.options.projectRoot,".vcp"),{recursive:!0})}catch(n){console.warn(`[vcp-site-edit] failed to ensure .vcp directory: ${n instanceof Error?n.message:String(n)}`)}if(this.refreshCompositions(!0),this.isStarted=!0,this.createRuntime(),this.bridgeEngine=this.createBridgeEngine(),t.webSocket!==!1){let n=me({server:this.server,path:this.options.path,sessionKey:this.options.sessionKey,host:this.options.host,allowedOrigins:this.options.allowedOrigins,engine:this.bridgeEngine});this.stopWebSocketServer=n.stop}this.stopWatching=new Et({projectRoot:this.options.projectRoot,watch_dirs:_t(this.options.runtime.watch_dirs),interval_ms:this.options.runtime.watch_interval_ms,debounce_ms:this.options.runtime.watch_debounce_ms??Te,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(),t.listen!==!1&&this.server.listen(this.options.port,this.options.host),this.notifyHealthChanged()}}getEngine(){if(!this.bridgeEngine)throw new Error("VCP site edit preview bridge runtime is not ready");return this.bridgeEngine}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.stopping=!0,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=At(),n=Ht(this.options);t.get(n)===this&&t.delete(n),this.isStarted=!1,this.notifyHealthChanged()}notifyHealthChanged(){let t=this.options.onHealthChanged;if(!t)return;let n=this.getHealth(),i=JSON.stringify(n);if(i!==this.lastNotifiedHealth){this.lastNotifiedHealth=i;try{t(n)}catch(s){console.warn(`[vcp-site-edit] onHealthChanged callback failed: ${s instanceof Error?s.message:String(s)}`)}}}createRuntime(t,n=null){let i=this.runtime;this.activeHistoryStore=t??null;let s=(this.dependencies.createRuntime??ft)({...this.options.tenantId?{tenantId:this.options.tenantId}:{},siteId:this.options.siteId,snapshotId:this.options.snapshotId,projectRoot:this.options.projectRoot,compositions:this.compositions,onEvent:o=>{"version"in o&&typeof o.version=="number"&&this.recordRuntimeVersion(o.version,"composition"in o?o.composition:void 0);for(let r of this.eventListeners)r(o)},...t?{historyStore:t}:{},...this.getInitialDocumentVersions().length>0?{initialDocumentVersions:this.getInitialDocumentVersions()}:{}});this.runtime=s,this.activeHistorySessionId=n,i?.dispose(),this.notifyHealthChanged()}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=Tt(t.composition),s=this.getRuntime(),o=_(i);await s.initializeComposition(o);let c=s.getDocument(o).data;await this.recordRuntimeVersion(c.version,i);let l=(await s.getHistoryStatus()).data;return{ok:!0,composition:i,data:{document:c,historyStatus:l}}}),getDocument:async t=>{let n=this.getRuntime(),i=_(t);await n.initializeComposition(i);let s=n.getDocument(i);return await this.recordRuntimeVersion(s.data.version,t),{...s,composition:t}},getHistoryStatus:async t=>({...await this.getRuntime().getHistoryStatus(),composition:t}),getStyleContext:async t=>this.getRuntime().getStyleContext(_(t)),getObjectEditContext:async(t,n,i)=>this.getRuntime().getObjectEditContext(t,_(n),i),getClassNameSource:async(t,n)=>this.getRuntime().getClassNameSource(t,_(n)),getSourceTree:async t=>this.getRuntime().getSourceTree(_(t)),getSourceFile:async t=>this.getRuntime().getSourceFile({path:t.path,composition:_(t.composition)}),resolveSourceLocation:async t=>this.getRuntime().resolveSourceLocation({key:t.key,composition:_(t.composition)}),execute:(t,n)=>this.mutationQueue.run(async()=>{let i=await this.bindHistorySession(this.options.snapshotId);if(!i.ok)return ue(i,t);let s=await this.getRuntime().executeOperation(t);return s.data?.resultVersion!==void 0&&await this.recordRuntimeVersion(s.data.resultVersion,s.composition),s}),undo:t=>this.mutationQueue.run(async()=>{let n=await this.bindHistorySession(this.options.snapshotId);if(!n.ok)return ue(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 ue(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??gt)(Pt({root:this.options.historyRoot,siteId:this.options.siteId,snapshotId:this.options.snapshotId,editingSessionId:t}));if(!this.isStarted)return;let s=i.readDocumentVersion?await i.readDocumentVersion():0,o=this.compositions[0]?.context;if(o){let r=M(o);this.runtimeVersionFloors.set(r,Math.max(this.runtimeVersionFloors.get(r)??0,s))}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?M(n):null;i&&this.runtimeVersionFloors.set(i,Math.max(this.runtimeVersionFloors.get(i)??0,t));let s=this.activeHistoryStore;if(!s?.writeDocumentVersion)return Promise.resolve();let o=i?this.runtimeVersionFloors.get(i)??t:t;return this.versionPersistence=this.versionPersistence.then(()=>s.writeDocumentVersion(o)).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??Te;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(),t.some(Ft)&&this.scheduleSnapshotIdentityAdvance(),!!this.refreshCompositions(!1))for(let n of t)this.runtime?.notifyFileChanged(n)}scheduleSnapshotIdentityAdvance(){if(this.stopping||!this.isStarted)return;let t=this.readCurrentSnapshotMarker();!t||t===this.options.snapshotId||this.mutationQueue.run(()=>this.advanceSnapshotId(t)).catch(n=>{console.warn(`[vcp-site-edit] snapshot identity advance failed: ${n instanceof Error?n.message:String(n)}`)})}readCurrentSnapshotMarker(){try{let t=L.readFileSync(R.join(this.options.projectRoot,he),"utf8"),n=JSON.parse(t),i=typeof n.snapshot_id=="string"?n.snapshot_id:"";return!i||le(i)!==i?(console.warn("[vcp-site-edit] current-snapshot marker has no valid snapshot_id"),null):i}catch(t){return console.warn(`[vcp-site-edit] current-snapshot marker unreadable: ${t instanceof Error?t.message:String(t)}`),null}}async advanceSnapshotId(t){if(this.stopping||!this.isStarted||t===this.options.snapshotId)return;let n=this.options.snapshotId;this.options.snapshotId=t;try{if(this.options.historyRoot){let s=await this.bindHistorySession(t);if(!s.ok)throw new Error(`${s.code}: ${s.message}`)}else this.createRuntime()}catch(s){this.options.snapshotId=n,console.warn(`[vcp-site-edit] snapshot identity advance rolled back to ${n}: ${s instanceof Error?s.message:String(s)}`);return}let i=new Date().toISOString();for(let s of this.compositions){let o={type:"site-edit.snapshot.changed",siteId:this.options.siteId,composition:s.context,snapshotId:t,previousSnapshotId:n,at:i};for(let r of this.eventListeners)try{r(o)}catch(c){console.warn(`[vcp-site-edit] snapshot.changed listener failed: ${c instanceof Error?c.message:String(c)}`)}}try{this.options.onSnapshotIdChanged?.(t,n)}catch(s){console.warn(`[vcp-site-edit] onSnapshotIdChanged callback failed: ${s instanceof Error?s.message:String(s)}`)}}refreshCompositions(t=!1){try{let n=kt(this.options.projectRoot),i=It(n),s=i.length>0?i:(this.options.runtime.routes??[]).map(a=>({...a})),o=yt({files:n});if(o.length===0)throw new Error("No canonical App Router composition is indexed by the preview bridge.");let r=JSON.stringify(o.filter(a=>a.context.effectiveTemplateId!==void 0).map(a=>a.entryFile).sort());if(t&&(this.launchCandidateEntries=r),this.launchCandidateEntries!==r)throw new Error("SITE_EDIT_RUNTIME_RELOAD_REQUIRED: Candidate route collection changed since preview launch");let c=new Map(this.compositions.map(a=>[M(a.context),a])),l=new Map(o.map(a=>[M(a.context),a]));if(this.runtime){for(let[a,f]of c){let u=l.get(a);(!u||u.entryFile!==f.entryFile)&&this.runtime.unregisterComposition(_(f.context))}for(let[a,f]of l){let u=c.get(a);(!u||u.entryFile!==f.entryFile)&&this.runtime.registerComposition(f.context,f.entryFile)}}return this.routes=s,this.compositions=o,this.compositionFiles=n,this.compositionResolutionError=null,this.notifyHealthChanged(),!0}catch(n){let i=n instanceof Error?n:new Error(String(n));if(this.compositionResolutionError=i,t)throw i;return this.notifyHealthChanged(),!1}}resolveComposition(t){if(this.compositionResolutionError)throw this.compositionResolutionError;let n=St(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 s=mt({selector:{routeId:n,...t.templateId!==void 0?{templateId:t.templateId}:{}},files:this.compositionFiles,canonicalEntryFile:i.entryFile}),o=M(s.context);if(!this.compositions.some(r=>M(r.context)===o))throw new Error(`Composition is not registered by the preview bridge: ${o}`);return s}getInitialDocumentVersions(){return this.compositions.flatMap(t=>{let n=this.runtimeVersionFloors.get(M(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 Be(e){return je(e)}function je(e){return{tenantId:e.tenantId,siteId:e.siteId,snapshotId:e.snapshotId,projectRoot:R.resolve(e.projectRoot??process.cwd()),basePath:e.basePath??"",host:e.host??xt,port:e.port??Ct,path:e.path??vt,sessionKey:e.sessionKey??Ut(),historyRoot:e.historyRoot,allowedOrigins:e.allowedOrigins??[],runtime:e.runtime??{},onSnapshotIdChanged:e.onSnapshotIdChanged,onHealthChanged:e.onHealthChanged}}function _t(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 kt(e){let t=[],n=["app","src/app",".vcp"],i=new Set([".git",".next",".turbo","coverage","dist","node_modules","output","snapshot-store"]),s=o=>{if(!L.existsSync(o))return;let r;try{r=L.readdirSync(o,{withFileTypes:!0})}catch{return}for(let c of r){if(c.name.startsWith(".")&&c.name!==".vcp")continue;if(c.isDirectory()){if(i.has(c.name))continue;s(R.join(o,c.name));continue}if(!c.isFile())continue;let l=R.join(o,c.name),a="";try{a=L.readFileSync(l,"utf8")}catch{}t.push({path:R.relative(e,l).replaceAll(R.sep,"/"),content:a})}};for(let o of n)s(R.join(e,o));return t.sort((o,r)=>o.path.localeCompare(r.path))}function Tt(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 _(e){return{routeId:e.routeId,...e.effectiveTemplateId?{templateId:e.effectiveTemplateId}:{}}}function Pt(e){return R.join(R.resolve(e.root),le(e.siteId),le(e.snapshotId),Ne("sha256").update(e.editingSessionId).digest("hex").slice(0,32))}function le(e){return/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(e)&&e!=="."&&e!==".."?e:Ne("sha256").update(e).digest("hex").slice(0,32)}function At(){let e=globalThis;return e[Pe]??=new Map,e[Pe]}function Ht(e){return`${e.projectRoot}:${e.host}:${e.port}:${e.path}:${e.historyRoot??""}`}function ue(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 me(e){let t=new lt({maxPayload:Oe,noServer:!0}),n=new WeakSet,i=o=>{new J({socket:new fe(o),engine:e.engine,validateOperationRequest:r=>wt.safeParse(r).success})},s=(o,r,c)=>{if(!Nt(o,e))return;let l=Mt(o,e);if(!l){r.write(`HTTP/1.1 401 Unauthorized\r
1
+ import xe from"node:http";import{existsSync as F,readFileSync as U}from"node:fs";import{randomUUID as Zt}from"node:crypto";import{createRequire as Le}from"node:module";import{Socket as We}from"node:net";import z from"node:path";import{basename as qe,dirname as J,join as G}from"node:path";import{fileURLToPath as ze}from"node:url";import{createRequire as Kt}from"node:module";import{pathToFileURL as Wt}from"node:url";import{Worker as $t}from"node:worker_threads";var ve=["resolveComposition","initializeSession","getDocument","getHistoryStatus","getStyleContext","getObjectEditContext","getClassNameSource","getSourceTree","getSourceFile","resolveSourceLocation","execute","undo","redo"];function ne(e){let t=new Error(e.message);return t.name=e.name,e.code!==void 0&&(t.code=e.code),t}import dt from"node:http";import q from"node:fs";import{createHash as Oe,randomBytes as ht,timingSafeEqual as pt}from"node:crypto";import b from"node:path";import{WebSocket as Me,WebSocketServer as lt}from"ws";import{createPreviewSiteEditEngineRuntime as ft,openFileHistoryStore as gt,resolveManagedPageTemplateComposition as mt,scanSiteEditCompositionsFromFiles as yt}from"@vcp-dev/site-edit-engine";import{resolveNextAppRouteId as St,scanNextAppRouterRoutesFromFiles as It}from"@vcp-dev/site-edit-engine/next-app-router";import{SiteEditSourceWatcher as Et}from"@vcp-dev/site-edit-engine/source-watcher";function Re(e){let t=new Map,n=[],i=new Map,s=[],o=e.pageComposition.status==="supported"?e.pageComposition.placementUnitKeys:[],r=new Map(o.map((d,f)=>[d,f])),c=e.pageComposition.status==="supported"?{status:"supported",containerKey:e.pageComposition.containerKey,hasBusinessMembers:e.pageComposition.hasBusinessMembers,placementUnitKeys:e.pageComposition.placementUnitKeys,placements:e.pageComposition.placements.map(d=>({placementKey:d.placementKey,placementUnitKey:d.placementUnitKey,relation:d.relation}))}:{status:"unsupported",reason:e.pageComposition.reason,diagnostics:e.pageComposition.diagnostics},p=e.entries.flatMap((d,f)=>d.dynamicDataSummary?[[f,d.dynamicDataSummary]]:[]),a=new Map(e.entries.map((d,f)=>[d.key,f])),l=[];for(let[d,f]of e.entries.entries()){let m=f.pageCompositionActionScope;if(!m)continue;if(m.kind!=="source-siblings"){l.push([d,{kind:m.kind}]);continue}let x=m.siblingKeys.map(E=>{let w=a.get(E);if(w===void 0)throw new Error("Render entry "+f.key+" references missing source sibling "+E);return w});l.push([d,{kind:"source-siblings",siblingEntryIndexes:x}])}let u=d=>{let f=t.get(d);if(typeof f=="number")return f;let m=n.length;return n.push(d),t.set(d,m),m},S=d=>{let f=null;for(let m of tt(d)){let x=`${f??"root"}\0${m}`,E=i.get(x);if(typeof E=="number"){f=E;continue}let w=s.length;s.push([f,u(m)]),i.set(x,w),f=w}if(f===null)throw new Error("Document key must not be empty");return f};return{encoding:"segment-trie-v1",siteId:e.siteId,snapshotId:e.snapshotId,composition:{...e.composition},routeId:e.composition.routeId,version:e.version,pageComposition:c,tokens:n,nodes:s,entries:e.entries.map(d=>{let f=d.pageCompositionUnitKey?r.get(d.pageCompositionUnitKey)??-1:-1;if(d.pageCompositionUnitKey&&f<0)throw new Error(`Render entry ${d.key} references unknown page composition unit ${d.pageCompositionUnitKey}`);return[S(d.key),et(d.operationSummary),...f>=0?[f]:[]]}),...l.length>0?{pageCompositionActionScopes:l}:{},...e.entries.every(d=>d.parentKey!==void 0)?{entryParentNodeIds:e.entries.map(d=>d.parentKey===null?null:S(d.parentKey))}:{},...p.length>0?{dynamicDataSummaries:p}:{}}}function et(e){return(e.canUpdateText?1:0)|(e.canInsertChild?2:0)|(e.canMove?4:0)|(e.canRemove?8:0)}function tt(e){if(!e)return[];let t=[],n=0,i=be(e,n);if(i<0)return t.push(e),t;for(t.push(e.slice(0,i)),n=i;n<e.length;){if(i=be(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 be(e,t){let n=e.indexOf("/",t),i=e.indexOf("::",t);return n<0?i:i<0?n:Math.min(n,i)}var _e="SITE_EDIT_COMPOSITION_SESSION_MISMATCH",ue="SITE_EDIT_COMPOSITION_SESSION_REQUIRED";var v=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(y(t)&&y(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!y(t)||typeof t.type!="string"?!1:t.type==="request"?nt(t.payload,n):t.type==="response"||t.type==="error"?y(t.payload)&&typeof t.payload.id=="string":t.type==="event"?y(t.payload)&&y(t.payload.event):t.type==="auth"?y(t.payload)&&typeof t.payload.key=="string":t.type==="auth-ok"&&y(t.payload)&&t.payload.ok===!0}},Q=class{constructor(t){this.options=t,this.session={subscribedCompositionKeys:new Set},this.messageQueue=new ce,this.eventDispatcher=new ae(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:s}=i;switch(i.kind){case"initialize-session":{let o=ie(i),r=await this.resolve(o),c=await this.options.engine.initializeSession({composition:r.context,...i.mutationContext?{mutationContext:i.mutationContext}:{}});this.activateSession(r.context),this.sendJson({type:"response",payload:{id:s,kind:i.kind,result:H({...c,data:{...c.data,document:Te(c.data.document)}},r.context)}});return}case"get-document":{let o=await this.resolveWireContext(i),r=await this.options.engine.getDocument(o);this.sendResult(s,i.kind,ct(r,o));return}case"get-history-status":{let o=await this.resolveWireContext(i),r=await this.options.engine.getHistoryStatus(o);this.sendResult(s,i.kind,H(r,o));return}case"get-style-context":{let o=await this.resolveWireContext(i);this.sendResult(s,i.kind,H(await this.options.engine.getStyleContext(o),o));return}case"get-object-edit-context":{let o=await this.resolveWireContext(i);this.sendResult(s,i.kind,H(await this.options.engine.getObjectEditContext(i.key,o,i.selectionRef),o));return}case"get-class-name-source":{let o=await this.resolveWireContext(i);this.sendResult(s,i.kind,H(await this.options.engine.getClassNameSource(i.key,o),o));return}case"get-source-tree":{let o=await this.resolveWireContext(i);this.sendResult(s,i.kind,H(await this.options.engine.getSourceTree(o),o));return}case"get-source-file":{let o=await this.resolveWireContext(i);this.sendResult(s,i.kind,H(await this.options.engine.getSourceFile({path:i.path,composition:o}),o));return}case"resolve-source-location":{let o=await this.resolveWireContext(i),r=H(await this.options.engine.resolveSourceLocation({key:i.key,composition:o}),o);this.sendResult(s,i.kind,r);return}case"execute":{let o=await this.resolveOperationWireContext(i.request),r=await this.resolveWireContext(i);if(N(o)!==N(r))throw new O(_e,"The execute request composition does not match its operation composition.");let c=await this.normalizeOperationRequest(i.request,o);await this.handleBufferedOperation(s,i.kind,()=>this.options.engine.execute(c));return}case"undo":case"redo":{let o=await this.resolveWireContext(i);await this.handleBufferedOperation(s,i.kind,()=>i.kind==="undo"?this.options.engine.undo(o):this.options.engine.redo(o));return}}}catch(n){let i=v.extractRequestInfo(t);this.sendJson({type:"error",payload:{...i,message:re(n),code:oe(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 O(ue,"Initialize a composition session before issuing this request.");if(N(i)!==N(n.context))throw new O(_e,"The request composition does not match the active socket session.");return n.context}async resolveWireContext(t){let n=ie(t);return this.resolveAndAssert(n)}async resolveOperationWireContext(t){let n=rt(t);return this.resolveAndAssert(n)}activateSession(t){this.session.activeComposition=t,this.session.subscribedCompositionKeys.clear(),this.session.subscribedCompositionKeys.add(N(t))}async normalizeOperationRequest(t,n){let i={...t,composition:ke(n)};if(i.target.kind==="route"){let s=i.target,o=ie(s),r=await this.resolveAndAssert(o);i.target={...s,composition:ke(r)}}return i}handleEngineEvent(t){let n=t?.composition;if(!ot(n))return;let i=N(n);this.session.subscribedCompositionKeys.has(i)&&(this.eventDispatcher.push(t),t.type==="site-edit.graph.invalidated"&&i===at(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(v.parseMessage(t,{validateOperationRequest:this.options.validateOperationRequest}))}catch(n){let i=ut(t);this.sendJson({type:"error",payload:{...i,message:re(n),code:oe(n)}})}}sendJson(t){this.options.socket.send(v.stringifyMessage(t))}async handleBufferedOperation(t,n,i){this.eventDispatcher.beginBuffering();try{let s=await i();this.sendResult(t,n,s)}catch(s){this.sendJson({type:"error",payload:{id:t,kind:n,message:re(s),code:oe(s)}})}finally{this.eventDispatcher.flush()}}},O=class extends Error{constructor(t,n){super(n),this.code=t,this.name="BridgeProtocolError"}},ae=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))}},ce=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 nt(e,t){if(!y(e)||typeof e.id!="string"||!v.isRequestKind(e.kind))return!1;let n=L(e.composition);switch(e.kind){case"initialize-session":return n&&(e.mutationContext===void 0||se(e.mutationContext));case"get-document":case"get-style-context":return n;case"get-object-edit-context":return typeof e.key=="string"&&n&&it(e.selectionRef);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&&st(e.request)&&(e.request.mutationContext===void 0||se(e.request.mutationContext))&&(t.validateOperationRequest?.(e.request)??!0);case"undo":case"redo":return n&&e.mutationContext===void 0||n&&se(e.mutationContext)}}function it(e){if(e===void 0)return!0;if(!y(e)||typeof e.key!="string"||e.key.length===0)return!1;let t=e.instanceIndex,n=e.instanceCount;return t!==void 0&&(typeof t!="number"||!Number.isInteger(t)||t<0)||n!==void 0&&(typeof n!="number"||!Number.isInteger(n)||n<=0)||typeof t=="number"&&typeof n=="number"&&t>=n?!1:Object.keys(e).every(i=>i==="key"||i==="instanceIndex"||i==="instanceCount")}function st(e){return y(e)&&typeof e.id=="string"&&typeof e.siteId=="string"&&typeof e.baseSnapshotId=="string"&&L(e.composition)&&typeof e.kind=="string"&&y(e.target)&&(e.target.kind!=="route"||L(e.target.composition))&&typeof e.documentVersion=="number"&&Number.isInteger(e.documentVersion)&&e.documentVersion>=0&&y(e.params)}function L(e){return y(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 ot(e){return y(e)&&typeof e.routeId=="string"&&(e.effectiveTemplateId===void 0||typeof e.effectiveTemplateId=="string")}function ie(e){if(L(e.composition))return e.composition;throw new O(ue,"A composition selector is required for this request.")}function rt(e){if(y(e)&&L(e.composition))return e.composition;throw new O(ue,"A composition selector is required for execute.")}function ke(e){return{routeId:e.routeId,...e.effectiveTemplateId?{templateId:e.effectiveTemplateId}:{}}}function at(e){return e.activeComposition?N(e.activeComposition):null}function N(e){return JSON.stringify([e.routeId,e.effectiveTemplateId??null])}function H(e,t){return y(e)&&e.ok===!0?{...e,composition:t}:e}function ct(e,t){return!y(e)||e.ok!==!0?e:{...e,...t?{composition:t}:{},data:Te(e.data)}}function Te(e){let t=e;return Re(t.routeId?t:{...t,routeId:t.composition.routeId})}function y(e){return typeof e=="object"&&e!==null}function se(e){return y(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 oe(e){if(!(!y(e)||typeof e.code!="string"||e.code.length===0))return e.code}function re(e){return e instanceof Error||y(e)&&typeof e.message=="string"&&e.message.length>0?e.message:"Unknown websocket operation failure"}function ut(e){try{return v.extractRequestInfo(JSON.parse(e))}catch{return{id:"unknown",kind:"get-document"}}}var Y=class{constructor(){this.tail=Promise.resolve()}run(t){let n=this.tail.then(t,t);return this.tail=n.then(()=>{},()=>{}),n}};import{SiteEditOperationRequestSchema as wt,computeSiteEditCompositionKey as M}from"@vcp-dev/contracts";var xt="127.0.0.1",Ct=30218,vt="/__vcp/site-edit/bridge",De=6*1024*1024,bt=De*2,Rt=3e3,Pe=50,pe=".vcp/current-snapshot.json",Ae="__VCP_SITE_EDIT_BRIDGE_SERVERS__";function Be(e,t,n={}){let i=new le(Ue(t),e,!1,n);return i.start({listen:!1}),i}var le=class{constructor(t,n=dt.createServer((o,r)=>{r.writeHead(404),r.end("VCP site edit bridge server")}),i=!0,s={}){this.options=t,this.server=n,this.closeHttpServerOnStop=i,this.dependencies=s,this.runtime=null,this.activeHistorySessionId=null,this.historySessionTransition=Promise.resolve(),this.mutationQueue=new Y,this.eventListeners=new Set,this.routes=[],this.compositions=[],this.compositionFiles=[],this.compositionResolutionError=null,this.launchCandidateEntries=null,this.stopWatching=null,this.stopWebSocketServer=null,this.pendingChangedFiles=new Set,this.fileChangeTimer=null,this.isStarted=!1,this.stopping=!1,this.runtimeVersionFloors=new Map,this.activeHistoryStore=null,this.versionPersistence=Promise.resolve(),this.bridgeEngine=null,this.lastNotifiedHealth=null}start(t={}){if(!this.isStarted){this.stopping=!1;try{q.mkdirSync(b.join(this.options.projectRoot,".vcp"),{recursive:!0})}catch(n){console.warn(`[vcp-site-edit] failed to ensure .vcp directory: ${n instanceof Error?n.message:String(n)}`)}if(this.refreshCompositions(!0),this.isStarted=!0,this.createRuntime(),this.bridgeEngine=this.createBridgeEngine(),t.webSocket!==!1){let n=ye({server:this.server,path:this.options.path,sessionKey:this.options.sessionKey,host:this.options.host,allowedOrigins:this.options.allowedOrigins,engine:this.bridgeEngine});this.stopWebSocketServer=n.stop}this.stopWatching=new Et({projectRoot:this.options.projectRoot,watch_dirs:_t(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:n=>this.handleFileChanged(n),on_batch_change:n=>this.handleFilesChanged(n)}).start(),t.listen!==!1&&this.server.listen(this.options.port,this.options.host),this.notifyHealthChanged()}}getEngine(){if(!this.bridgeEngine)throw new Error("VCP site edit preview bridge runtime is not ready");return this.bridgeEngine}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.stopping=!0,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=At(),n=Ht(this.options);t.get(n)===this&&t.delete(n),this.isStarted=!1,this.notifyHealthChanged()}notifyHealthChanged(){let t=this.options.onHealthChanged;if(!t)return;let n=this.getHealth(),i=JSON.stringify(n);if(i!==this.lastNotifiedHealth){this.lastNotifiedHealth=i;try{t(n)}catch(s){console.warn(`[vcp-site-edit] onHealthChanged callback failed: ${s instanceof Error?s.message:String(s)}`)}}}createRuntime(t,n=null){let i=this.runtime;this.activeHistoryStore=t??null;let s=(this.dependencies.createRuntime??ft)({...this.options.tenantId?{tenantId:this.options.tenantId}:{},siteId:this.options.siteId,snapshotId:this.options.snapshotId,projectRoot:this.options.projectRoot,compositions:this.compositions,onEvent:o=>{"version"in o&&typeof o.version=="number"&&this.recordRuntimeVersion(o.version,"composition"in o?o.composition:void 0);for(let r of this.eventListeners)r(o)},...t?{historyStore:t}:{},...this.getInitialDocumentVersions().length>0?{initialDocumentVersions:this.getInitialDocumentVersions()}:{}});this.runtime=s,this.activeHistorySessionId=n,i?.dispose(),this.notifyHealthChanged()}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=Tt(t.composition),s=this.getRuntime(),o=_(i);await s.initializeComposition(o);let c=s.getDocument(o).data;await this.recordRuntimeVersion(c.version,i);let p=(await s.getHistoryStatus()).data;return{ok:!0,composition:i,data:{document:c,historyStatus:p}}}),getDocument:async t=>{let n=this.getRuntime(),i=_(t);await n.initializeComposition(i);let s=n.getDocument(i);return await this.recordRuntimeVersion(s.data.version,t),{...s,composition:t}},getHistoryStatus:async t=>({...await this.getRuntime().getHistoryStatus(),composition:t}),getStyleContext:async t=>this.getRuntime().getStyleContext(_(t)),getObjectEditContext:async(t,n,i)=>this.getRuntime().getObjectEditContext(t,_(n),i),getClassNameSource:async(t,n)=>this.getRuntime().getClassNameSource(t,_(n)),getSourceTree:async t=>this.getRuntime().getSourceTree(_(t)),getSourceFile:async t=>this.getRuntime().getSourceFile({path:t.path,composition:_(t.composition)}),resolveSourceLocation:async t=>this.getRuntime().resolveSourceLocation({key:t.key,composition:_(t.composition)}),execute:(t,n)=>this.mutationQueue.run(async()=>{let i=await this.bindHistorySession(this.options.snapshotId);if(!i.ok)return de(i,t);let s=await this.getRuntime().executeOperation(t);return s.data?.resultVersion!==void 0&&await this.recordRuntimeVersion(s.data.resultVersion,s.composition),s}),undo:t=>this.mutationQueue.run(async()=>{let n=await this.bindHistorySession(this.options.snapshotId);if(!n.ok)return de(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 de(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??gt)(Pt({root:this.options.historyRoot,siteId:this.options.siteId,snapshotId:this.options.snapshotId,editingSessionId:t}));if(!this.isStarted)return;let s=i.readDocumentVersion?await i.readDocumentVersion():0,o=this.compositions[0]?.context;if(o){let r=M(o);this.runtimeVersionFloors.set(r,Math.max(this.runtimeVersionFloors.get(r)??0,s))}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?M(n):null;i&&this.runtimeVersionFloors.set(i,Math.max(this.runtimeVersionFloors.get(i)??0,t));let s=this.activeHistoryStore;if(!s?.writeDocumentVersion)return Promise.resolve();let o=i?this.runtimeVersionFloors.get(i)??t:t;return this.versionPersistence=this.versionPersistence.then(()=>s.writeDocumentVersion(o)).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(),t.some(Ft)&&this.scheduleSnapshotIdentityAdvance(),!!this.refreshCompositions(!1))for(let n of t)this.runtime?.notifyFileChanged(n)}scheduleSnapshotIdentityAdvance(){if(this.stopping||!this.isStarted)return;let t=this.readCurrentSnapshotMarker();!t||t===this.options.snapshotId||this.mutationQueue.run(()=>this.advanceSnapshotId(t)).catch(n=>{console.warn(`[vcp-site-edit] snapshot identity advance failed: ${n instanceof Error?n.message:String(n)}`)})}readCurrentSnapshotMarker(){try{let t=q.readFileSync(b.join(this.options.projectRoot,pe),"utf8"),n=JSON.parse(t),i=typeof n.snapshot_id=="string"?n.snapshot_id:"";return!i||fe(i)!==i?(console.warn("[vcp-site-edit] current-snapshot marker has no valid snapshot_id"),null):i}catch(t){return console.warn(`[vcp-site-edit] current-snapshot marker unreadable: ${t instanceof Error?t.message:String(t)}`),null}}async advanceSnapshotId(t){if(this.stopping||!this.isStarted||t===this.options.snapshotId)return;let n=this.options.snapshotId;this.options.snapshotId=t;try{if(this.options.historyRoot){let s=await this.bindHistorySession(t);if(!s.ok)throw new Error(`${s.code}: ${s.message}`)}else this.createRuntime()}catch(s){this.options.snapshotId=n,console.warn(`[vcp-site-edit] snapshot identity advance rolled back to ${n}: ${s instanceof Error?s.message:String(s)}`);return}let i=new Date().toISOString();for(let s of this.compositions){let o={type:"site-edit.snapshot.changed",siteId:this.options.siteId,composition:s.context,snapshotId:t,previousSnapshotId:n,at:i};for(let r of this.eventListeners)try{r(o)}catch(c){console.warn(`[vcp-site-edit] snapshot.changed listener failed: ${c instanceof Error?c.message:String(c)}`)}}try{this.options.onSnapshotIdChanged?.(t,n)}catch(s){console.warn(`[vcp-site-edit] onSnapshotIdChanged callback failed: ${s instanceof Error?s.message:String(s)}`)}}refreshCompositions(t=!1){try{let n=kt(this.options.projectRoot),i=It(n),s=i.length>0?i:(this.options.runtime.routes??[]).map(a=>({...a})),o=yt({files:n});if(o.length===0)throw new Error("No canonical App Router composition is indexed by the preview bridge.");let r=JSON.stringify(o.filter(a=>a.context.effectiveTemplateId!==void 0).map(a=>a.entryFile).sort());if(t&&(this.launchCandidateEntries=r),this.launchCandidateEntries!==r)throw new Error("SITE_EDIT_RUNTIME_RELOAD_REQUIRED: Candidate route collection changed since preview launch");let c=new Map(this.compositions.map(a=>[M(a.context),a])),p=new Map(o.map(a=>[M(a.context),a]));if(this.runtime){for(let[a,l]of c){let u=p.get(a);(!u||u.entryFile!==l.entryFile)&&this.runtime.unregisterComposition(_(l.context))}for(let[a,l]of p){let u=c.get(a);(!u||u.entryFile!==l.entryFile)&&this.runtime.registerComposition(l.context,l.entryFile)}}return this.routes=s,this.compositions=o,this.compositionFiles=n,this.compositionResolutionError=null,this.notifyHealthChanged(),!0}catch(n){let i=n instanceof Error?n:new Error(String(n));if(this.compositionResolutionError=i,t)throw i;return this.notifyHealthChanged(),!1}}resolveComposition(t){if(this.compositionResolutionError)throw this.compositionResolutionError;let n=St(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 s=mt({selector:{routeId:n,...t.templateId!==void 0?{templateId:t.templateId}:{}},files:this.compositionFiles,canonicalEntryFile:i.entryFile}),o=M(s.context);if(!this.compositions.some(r=>M(r.context)===o))throw new Error(`Composition is not registered by the preview bridge: ${o}`);return s}getInitialDocumentVersions(){return this.compositions.flatMap(t=>{let n=this.runtimeVersionFloors.get(M(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 je(e){return Ue(e)}function Ue(e){return{tenantId:e.tenantId,siteId:e.siteId,snapshotId:e.snapshotId,projectRoot:b.resolve(e.projectRoot??process.cwd()),basePath:e.basePath??"",host:e.host??xt,port:e.port??Ct,path:e.path??vt,sessionKey:e.sessionKey??Ut(),historyRoot:e.historyRoot,allowedOrigins:e.allowedOrigins??[],runtime:e.runtime??{},onSnapshotIdChanged:e.onSnapshotIdChanged,onHealthChanged:e.onHealthChanged}}function _t(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 kt(e){let t=[],n=["app","src/app",".vcp"],i=new Set([".git",".next",".turbo","coverage","dist","node_modules","output","snapshot-store"]),s=o=>{if(!q.existsSync(o))return;let r;try{r=q.readdirSync(o,{withFileTypes:!0})}catch{return}for(let c of r){if(c.name.startsWith(".")&&c.name!==".vcp")continue;if(c.isDirectory()){if(i.has(c.name))continue;s(b.join(o,c.name));continue}if(!c.isFile())continue;let p=b.join(o,c.name),a="";try{a=q.readFileSync(p,"utf8")}catch{}t.push({path:b.relative(e,p).replaceAll(b.sep,"/"),content:a})}};for(let o of n)s(b.join(e,o));return t.sort((o,r)=>o.path.localeCompare(r.path))}function Tt(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 _(e){return{routeId:e.routeId,...e.effectiveTemplateId?{templateId:e.effectiveTemplateId}:{}}}function Pt(e){return b.join(b.resolve(e.root),fe(e.siteId),fe(e.snapshotId),Oe("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:Oe("sha256").update(e).digest("hex").slice(0,32)}function At(){let e=globalThis;return e[Ae]??=new Map,e[Ae]}function Ht(e){return`${e.projectRoot}:${e.host}:${e.port}:${e.path}:${e.historyRoot??""}`}function de(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 ye(e){let t=new lt({maxPayload:De,noServer:!0}),n=new WeakSet,i=o=>{new Q({socket:new ge(o),engine:e.engine,validateOperationRequest:r=>wt.safeParse(r).success})},s=(o,r,c)=>{if(!Nt(o,e))return;let p=Ot(o,e);if(!p){r.write(`HTTP/1.1 401 Unauthorized\r
2
2
  Connection: close\r
3
3
  \r
4
- `),r.destroy();return}l.authenticatedByHeader&&n.add(o),t.handleUpgrade(o,r,c,a=>{t.emit("connection",a,o)})};return e.server.on("upgrade",s),t.on("connection",(o,r)=>{if(n.has(r)){i(o);return}Ot(o,e.sessionKey,()=>{i(o)})}),t.stop=()=>{e.server.off("upgrade",s);for(let o of t.clients)o.close(1001,"bridge stopped");t.close()},t}var fe=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===Me.OPEN){if(this.socket.bufferedAmount+Buffer.byteLength(t,"utf8")>bt){this.socket.close(1013,"bridge backpressure");return}this.socket.send(t)}}close(t,n){this.socket.close(t,n)}};function Nt(e,t){return new URL(e.url??"/","http://localhost").pathname===t.path}function Mt(e,t){if(new URL(e.url??"/","http://localhost").searchParams.has("vcp_bridge_key"))return null;let i=de(e.headers["x-vcp-site-edit-key"]),s=Ue(i,t.sessionKey),o=de(e.headers.host),r=de(e.headers.origin);return o&&!Dt(o,t.host,r)?null:r?jt(r,o,t.allowedOrigins)?{authenticatedByHeader:s}:null:s?{authenticatedByHeader:!0}:null}function Ot(e,t,n){let i=setTimeout(()=>{e.close(1008,"bridge authentication timeout")},Rt),s,o=()=>{clearTimeout(i),e.off("message",s),e.off("close",o)},r=()=>{o(),e.close(1008,"bridge authentication failed")};s=c=>{try{let l=b.parseMessage(c.toString());if(l.type!=="auth"||!Ue(l.payload.key,t)){r();return}o(),e.readyState===Me.OPEN&&e.send(b.stringifyMessage({type:"auth-ok",payload:{ok:!0}})),n()}catch{r()}},e.on("message",s),e.on("close",o)}function Ue(e,t){if(!e)return!1;let n=Buffer.from(e),i=Buffer.from(t);return n.length===i.length&&pt(n,i)}function Dt(e,t,n){let i=He(e),s=He(t);return i===s||Ae(s)&&Ae(i)&&(!n||ge(n,e))||Bt(s)&&(!n||ge(n,e))}function Bt(e){return e==="0.0.0.0"||e==="::"}function Ae(e){return e==="localhost"||e==="127.0.0.1"||e==="::1"}function jt(e,t,n){return n.includes(e)||(t?ge(e,t):!1)}function ge(e,t){try{return new URL(e).host===Fe(t)}catch{return!1}}function He(e){let t=Fe(e);return t.startsWith("[")?t.slice(1,t.indexOf("]")):t.split(":").length-1===1?t.split(":",1)[0]??"":t}function Fe(e){return e.trim().toLowerCase()}function de(e){return Array.isArray(e)?e[0]:e}function Ut(){return ht(32).toString("base64url")}function Ft(e){let t=e.replaceAll("\\","/");return t===he||t.endsWith(`/${he}`)}var Wt="SITE_EDIT_ENGINE_UNAVAILABLE",Vt=5e3,$t=1024,Lt="VCP_SITE_EDIT_ENGINE_MAX_HEAP_MB",qt=3,zt=10*6e4,Gt=1012;function ye(e,t,n={}){let i=Be(t),{onSnapshotIdChanged:s,onHealthChanged:o,...r}=i,c={options:r},l=n.maxHeapMb??Jt(process.env[Lt])??$t,a=n.maxRestarts??qt,f=n.restartWindowMs??zt,u="starting",S,d=0,g=[],m=null,x=0,E=new Map,w=new Set,F,O,K=new Promise((h,p)=>{F=h,O=p});K.catch(()=>{});let v=h=>{let p=new Error(`VCP site edit preview bridge runtime is not ready: ${h}`);return p.code=Wt,p},W=h=>{for(let p of E.values())p.reject(h);E.clear()},k=h=>{switch(h.type){case"ready":m=h.health,u==="starting"?(u="ready",F()):u==="restarting"&&(u="ready",console.warn("[vcp-site-edit] engine worker restarted"));return;case"start-failed":u==="starting"&&T(te(h.error));return;case"result":{let p=E.get(h.id);if(!p)return;E.delete(h.id),h.ok?p.resolve(h.value):p.reject(te(h.error));return}case"event":for(let p of w)try{p(h.event)}catch(I){console.warn(`[vcp-site-edit] engine event listener failed: ${I instanceof Error?I.message:String(I)}`)}return;case"health":m=h.health;return;case"snapshot-id-changed":c.options.snapshotId=h.next;try{s?.(h.next,h.previous)}catch(p){console.warn(`[vcp-site-edit] onSnapshotIdChanged callback failed: ${p instanceof Error?p.message:String(p)}`)}return}},D=()=>{let h=d+=1,p=new Kt(n.workerUrl??new URL("./engine-worker.js",import.meta.url),{workerData:c,resourceLimits:{maxOldGenerationSizeMb:l},...n.execArgv?{execArgv:n.execArgv}:{}});p.unref();let I=()=>h===d;p.on("message",C=>{I()&&k(C)}),p.on("error",C=>{I()&&T(C instanceof Error?C:new Error(String(C)))}),p.on("exit",C=>{I()&&T(new Error(`engine worker exited with code ${C}`))}),S=p,n.onWorker?.(p)},T=h=>{if(u==="stopped"||u==="failed")return;if(W(v(h.message)),m=null,u==="starting"){u="failed",console.error(`[vcp-site-edit] engine worker failed to start: ${h.message}`),O(h);return}let p=Date.now();for(;g.length>0&&p-g[0]>f;)g.shift();if(g.length>=a){u="failed",console.error(`[vcp-site-edit] engine worker stopped unexpectedly and exhausted ${a} restarts: ${h.message}`);return}g.push(p),u="restarting";for(let I of P.clients)I.close(Gt,"site edit engine restarting");console.error(`[vcp-site-edit] engine worker stopped unexpectedly, restarting (${g.length}/${a}): ${h.message}`),D()},V=(h,p)=>{if(u==="failed"||u==="stopped"||u==="restarting")return Promise.reject(v(u));let I=x+=1;return new Promise((C,Xe)=>{E.set(I,{resolve:C,reject:Xe});let Ze={type:"call",id:I,method:h,args:p};S.postMessage(Ze)})},B=Object.fromEntries(Ce.map(h=>[h,(...p)=>V(h,p)])),P=me({server:e,path:i.path,sessionKey:i.sessionKey,host:i.host,allowedOrigins:i.allowedOrigins,engine:{...B,subscribe(h){return w.add(h),()=>w.delete(h)}}});return D(),{getHealth(){return u==="ready"&&m?m:{ok:!1,bridgePath:i.path,runtimeReady:!1,routesIndexed:m?.routesIndexed??0,sessionRequired:!!i.sessionKey}},stop(){if(u==="stopped")return;let h=u==="starting";u="stopped",P.stop(),h&&O(v("bridge stopped")),W(v("bridge stopped")),w.clear();let p=S,I={type:"stop"};p.postMessage(I);let C=setTimeout(()=>{p.terminate()},Vt);C.unref(),p.once("exit",()=>clearTimeout(C))},whenReady(){return K},eventListeners:w}}function Jt(e){if(!e||!/^\d+$/.test(e.trim()))return;let t=Number(e.trim());return Number.isSafeInteger(t)&&t>0?t:void 0}var Yt="next",Xt="VCP_SITE_EDIT_ENGINE_IN_PROCESS",ze="127.0.0.1",Zt=3e3,Z="/__vcp/site-edit/bridge",Ge="/__vcp/site-edit/health",en="probe",tn="render",We="/_error",ee="/__vcp/site-edit/client/",nn=`${ee}auto-bootstrap.js`,Je='data-vcp-site-edit-bootstrap="true"',sn=["next.config.ts","next.config.mts","next.config.cts","next.config.js","next.config.mjs","next.config.cjs"],on="@vcp-dev/site-edit-engine/webpack-loader",rn=/@vcp\/site-edit-engine\/(?:webpack-loader|site-edit-instrumentation-loader)/,an=[/\bconfig\.webpack\s*=/,/\bwebpack\s*\([^)]*\)\s*\{/,/\bwebpack\s*:\s*(?:async\s*)?(?:\([^)]*\)|[A-Za-z_$][\w$]*)?\s*=>/,/\bwebpack\s*:\s*(?:async\s+)?function\b/],cn=new Set(["auto-bootstrap.js","client.js","composition-key.js","designer-trace.js","document-codec.js","property-preview.js","protocol.js","window-message.js"]);async function bi(e={},t={}){let n=t.process??process,i=t.createServer??we.createServer,s=t.attachBridgeServer??(n.env[Xt]==="1"?De:ye),o=t.loadNext??Un,r=q.resolve(e.projectRoot??process.cwd()),c=e.host??ze,l=e.port??Vn(n.env.PORT)??Zt,a=e.bridgePath??Z,f=gn(a),u=Mn(),S=e.basePath??n.env.VCP_SITE_PREVIEW_BASE_PATH??"/",d=(e.tenantId??n.env.VCP_TENANT_ID)?.trim()||void 0,g=await o(r),m=un(r),x=g({dev:!0,dir:r,hostname:c,port:l,...dn(m)}),E=x.getRequestHandler(),w=e.siteId??n.env.VCP_SITE_ID??"018f6f4d-a9b8-7120-8000-000000000120",F=e.snapshotId??n.env.VCP_SNAPSHOT_ID??Wn(r),O=e.historyRoot??n.env.VCP_SITE_EDIT_HISTORY_ROOT,K=O?.trim()?q.resolve(O):void 0,v=null,W={launchId:Qt(),pid:process.pid,snapshotId:F},k=i((P,h)=>{xn({basePath:S,bridgePath:a,bridgeHealthPath:f,bridgeSessionKey:u,getBridgeHealth:()=>v?.getHealth()??kn(a),launch:W,runRenderProbe:()=>bn(x),handle:E,request:P,response:h}).catch(p=>{console.error(p),h.headersSent||(h.statusCode=500),h.end("site edit preview request failed")})}),D=null,T=null,V=()=>T||(X(()=>n.off("SIGINT",B)),X(()=>n.off("SIGTERM",B)),X(()=>D?.()),D=null,X(()=>v?.stop()),v=null,T=Promise.allSettled([Ln(k),qn(()=>x.close())]).then(()=>{}),T),B=()=>{V()};try{return await x.prepare(),v=s(k,{...d?{tenantId:d}:{},siteId:w,snapshotId:F,projectRoot:r,basePath:S,host:c,port:l,path:a,sessionKey:u,...K?{historyRoot:K}:{},onSnapshotIdChanged:P=>{W.snapshotId=P}}),D=ln({server:k,bridgePath:a,handleUpgrade:x.getUpgradeHandler()}),n.on("SIGINT",B),n.on("SIGTERM",B),await v.whenReady?.(),await $n(k,l,c),{bundler:m,close:V,host:c,port:zn(k,l),server:k}}catch(P){throw await V(),P}}function un(e){let t=hn(e);return t&&pn(t)?"webpack":"turbopack"}function dn(e){return e==="webpack"?{webpack:!0}:{turbopack:!0}}function hn(e){for(let t of sn){let n=G(e,t);if(U(n))return j(n,"utf8")}return null}function pn(e){return e.includes(on)?!0:rn.test(e)&&an.some(t=>t.test(e))}function ln(e){let t=(n,i,s)=>{fn(n.url,e.bridgePath)||e.handleUpgrade(n,i,s).catch(o=>{console.error(o),i.destroyed||i.destroy()})};return e.server.on("upgrade",t),()=>e.server.off("upgrade",t)}function fn(e,t){return new URL(e??"/","http://localhost").pathname===t}function gn(e=Z){if(e===Z)return Ge;let t=(e.startsWith("/")?e:`/${e}`).replace(/\/+$/,"");return t.endsWith("/bridge")?`${t.slice(0,-7)}/health`:t?`${t}/health`:"/health"}function mn(e){let t=JSON.stringify({basePath:e.basePath,launch_id:e.launch?.launchId,snapshot_id:e.launch?.snapshotId,wsPath:e.bridgePath,bridge_session_key:e.bridgeSessionKey,defer_initial_sync:!0,runtime_versions:e.runtimeVersions??yn()});return`<script type="module" ${Je}>import { startSiteEditAutoBootstrap } from ${JSON.stringify(nn)};void startSiteEditAutoBootstrap(window, ${t}).catch(() => undefined);</script>`}function yn(){return{bridge:Se("@vcp-dev/site-edit-bridge"),contracts:Se("@vcp-dev/contracts"),engine:Se("@vcp-dev/site-edit-engine")}}function Se(e){let t=$e(import.meta.url);try{let n=t.resolve(e),i=Sn(n,e);if(!i)return;let s=JSON.parse(j(i,"utf8"));return typeof s.version=="string"?s.version:void 0}catch{return}}function Sn(e,t){let n=q.parse(e).root,i=z(e);for(;i&&i!==n;){let s=G(i,"package.json");if(U(s))try{if(JSON.parse(j(s,"utf8")).name===t)return s}catch{return}i=z(i)}}function In(e,t){if(e.includes(Je))return e;let n=mn(t),i=/<\/body\s*>/i.exec(e);return i?`${e.slice(0,i.index)}${n}${e.slice(i.index)}`:`${e}${n}`}function Ri(e,t=z(qe(import.meta.url)),n=U){return Qe(e,t,n)?.path??null}function Qe(e,t=z(qe(import.meta.url)),n=U){let i=new URL(e??"/","http://localhost").pathname;if(!i.startsWith(ee))return null;let s=i.slice(ee.length);if(!cn.has(s))return null;let o=xe(Fn(t),s);if(Le(t)!=="src")return{path:o,requiresTranspile:!1};let r=xe(t,s.replace(/\.js$/,".ts"));return n(r)?{path:r,requiresTranspile:!0}:{path:o,requiresTranspile:!1}}async function En(e,t){let n=Qe(e.url);if(!n)return!1;if(!U(n.path))return t.writeHead(404),t.end("site edit client asset not found"),!0;let i=n.requiresTranspile?await wn(j(n.path,"utf8")):j(n.path);return t.writeHead(200,{"cache-control":"no-store","content-type":"text/javascript; charset=utf-8"}),t.end(i),!0}async function wn(e){let t=await import("typescript");return t.transpileModule(e,{compilerOptions:{module:t.ModuleKind.ES2022,target:t.ScriptTarget.ES2022}}).outputText}async function xn({basePath:e,bridgePath:t,bridgeHealthPath:n,bridgeSessionKey:i,getBridgeHealth:s,launch:o,runRenderProbe:r,handle:c,request:l,response:a}){if(Cn(l.url,e)){a.statusCode=404,a.end();return}if(await _n(l,a,n,s,o,r)||await En(l,a))return;let f=Tn(l),u=Pn(l),S=f||u?Nn(a,{basePath:e,bridgePath:t,bridgeSessionKey:i,patchNextDevChunk:u,launch:{...o}}):()=>{};try{await c(l,a)}catch(d){throw S(),d}}function Cn(e,t){let n=(e??"/").split(/[?#]/,1)[0]??"/";if(!/(\\|\/\/)/.test(n))return!1;let i;try{i=decodeURIComponent(n).replace(/\\/g,"/").replace(/\/{2,}/g,"/")}catch{return!1}let s=new URL(i,"http://namespace.invalid").pathname,o=t.replace(/\/+$/,"");return(o&&(s===o||s.startsWith(o+"/"))?s.slice(o.length)||"/":s).startsWith("/.vcp")}function vn(e){let t=e instanceof Error?e.message:String(e),n=e&&typeof e=="object"&&"code"in e?e.code:void 0;return/\.next[/\\]/.test(t)||/chunks[/\\]ssr[/\\]/.test(t)?n==="ENOENT"||n==="MODULE_NOT_FOUND"?{verdict:"artifact_broken",detail:t}:t.includes("Cannot find module")?{verdict:"artifact_broken",detail:t}:{verdict:"inconclusive",detail:t}:{verdict:"inconclusive",detail:t}}async function bn(e){let t=new we.IncomingMessage(new Ke);t.method="GET",t.url=We,t.headers={host:ze};let n=new we.ServerResponse(t);n.assignSocket(new Ke);try{return await e.renderToHTML(t,n,We,{}),{verdict:"ok"}}catch(i){return vn(i)}finally{try{let i=n.socket;i&&(n.detachSocket(i),i.destroy())}catch{}}}function Rn(e){return new URL(e??"/","http://localhost").searchParams.get(en)===tn}async function _n(e,t,n,i,s,o){if(e.method!=="GET"||new URL(e.url??"/","http://localhost").pathname!==n)return!1;let c=i(),l=Rn(e.url)?await o():void 0,a={...c,launch:s,...l?{render:l}:{}};return t.writeHead(c.ok?200:503,{"cache-control":"no-store","content-type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a)),!0}function kn(e){return{ok:!1,bridgePath:e,runtimeReady:!1,routesIndexed:0,sessionRequired:!0}}function Tn(e){return An(e)?(e.headers["accept-encoding"]="identity",!0):!1}function Pn(e){return Hn(e)?(e.headers["accept-encoding"]="identity",!0):!1}function An(e){if(e.method!=="GET")return!1;let t=new URL(e.url??"/","http://localhost");if(e.headers["x-template-id"]!==void 0&&!t.searchParams.has("template_id"))return!1;let n=t.pathname;if(n.startsWith("/_next/")||n.startsWith(ee)||n===Z||n===Ge)return!1;let i=e.headers.accept??"";return i===""||i.includes("text/html")}function Hn(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 Nn(e,t){let n=[],i=e,s=i.flushHeaders.bind(e),o=i.write.bind(e),r=i.end.bind(e),c=!1;i.flushHeaders=()=>{};let l=()=>{if(t.patchNextDevChunk||c)return!1;let a=Buffer.concat(n);if(!/<body\b[^>]*>/iu.test(a.toString("utf8")))return!1;let f=Ve(e,a,t);return f!==a&&!e.headersSent&&e.removeHeader("content-length"),o(f),n.length=0,c=!0,!0};return i.write=(a,f,u)=>c?(a!==void 0&&o(Ie(a,Ee(f))),Y(f),Y(u),!0):(a!==void 0&&(n.push(Ie(a,Ee(f))),l()),Y(f),Y(u),!0),i.end=(a,f,u)=>{let S=typeof a=="function"?void 0:a;if(c)return i.write=o,i.end=r,i.flushHeaders=s,S===void 0?typeof a=="function"?r(a):typeof f=="function"?r(f):typeof u=="function"?r(u):r():typeof f=="function"?r(S,f):typeof u=="function"?r(S,f,u):r(S,f);S!==void 0&&n.push(Ie(S,Ee(f))),i.write=o,i.end=r,i.flushHeaders=s;let d=Buffer.concat(n),g=Ve(e,d,t);g!==d&&!e.headersSent&&e.removeHeader("content-length");let m=typeof a=="function"?a:typeof f=="function"?f:typeof u=="function"?u:void 0;return m?r(g,m):r(g)},()=>{i.write=o,i.end=r,i.flushHeaders=s}}function Ve(e,t,n){if(On(e,t))return Buffer.from(In(t.toString("utf8"),n));if(n.patchNextDevChunk&&Dn(e)){let i=t.toString("utf8"),s=Bn(i);if(s!==i)return Buffer.from(s)}return t}function Mn(){let e=new Uint8Array(32);return globalThis.crypto.getRandomValues(e),Buffer.from(e).toString("base64url")}function On(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 Dn(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 Bn(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(`
4
+ `),r.destroy();return}p.authenticatedByHeader&&n.add(o),t.handleUpgrade(o,r,c,a=>{t.emit("connection",a,o)})};return e.server.on("upgrade",s),t.on("connection",(o,r)=>{if(n.has(r)){i(o);return}Mt(o,e.sessionKey,()=>{i(o)})}),t.stop=()=>{e.server.off("upgrade",s);for(let o of t.clients)o.close(1001,"bridge stopped");t.close()},t}var ge=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===Me.OPEN){if(this.socket.bufferedAmount+Buffer.byteLength(t,"utf8")>bt){this.socket.close(1013,"bridge backpressure");return}this.socket.send(t)}}close(t,n){this.socket.close(t,n)}};function Nt(e,t){return new URL(e.url??"/","http://localhost").pathname===t.path}function Ot(e,t){if(new URL(e.url??"/","http://localhost").searchParams.has("vcp_bridge_key"))return null;let i=he(e.headers["x-vcp-site-edit-key"]),s=Fe(i,t.sessionKey),o=he(e.headers.host),r=he(e.headers.origin);return o&&!Dt(o,t.host,r)?null:r?jt(r,o,t.allowedOrigins)?{authenticatedByHeader:s}:null:s?{authenticatedByHeader:!0}:null}function Mt(e,t,n){let i=setTimeout(()=>{e.close(1008,"bridge authentication timeout")},Rt),s,o=()=>{clearTimeout(i),e.off("message",s),e.off("close",o)},r=()=>{o(),e.close(1008,"bridge authentication failed")};s=c=>{try{let p=v.parseMessage(c.toString());if(p.type!=="auth"||!Fe(p.payload.key,t)){r();return}o(),e.readyState===Me.OPEN&&e.send(v.stringifyMessage({type:"auth-ok",payload:{ok:!0}})),n()}catch{r()}},e.on("message",s),e.on("close",o)}function Fe(e,t){if(!e)return!1;let n=Buffer.from(e),i=Buffer.from(t);return n.length===i.length&&pt(n,i)}function Dt(e,t,n){let i=Ne(e),s=Ne(t);return i===s||He(s)&&He(i)&&(!n||me(n,e))||Bt(s)&&(!n||me(n,e))}function Bt(e){return e==="0.0.0.0"||e==="::"}function He(e){return e==="localhost"||e==="127.0.0.1"||e==="::1"}function jt(e,t,n){return n.includes(e)||(t?me(e,t):!1)}function me(e,t){try{return new URL(e).host===Ke(t)}catch{return!1}}function Ne(e){let t=Ke(e);return t.startsWith("[")?t.slice(1,t.indexOf("]")):t.split(":").length-1===1?t.split(":",1)[0]??"":t}function Ke(e){return e.trim().toLowerCase()}function he(e){return Array.isArray(e)?e[0]:e}function Ut(){return ht(32).toString("base64url")}function Ft(e){let t=e.replaceAll("\\","/");return t===pe||t.endsWith(`/${pe}`)}var Vt="SITE_EDIT_ENGINE_UNAVAILABLE",Lt=5e3,qt=1024,zt="VCP_SITE_EDIT_ENGINE_MAX_HEAP_MB",Jt=3,Gt=10*6e4,Qt=1012;function Se(e,t,n={}){let i=je(t),{onSnapshotIdChanged:s,onHealthChanged:o,...r}=i,c={options:r},p=n.maxHeapMb??Xt(process.env[zt])??qt,a=n.maxRestarts??Jt,l=n.restartWindowMs??Gt,u="starting",S,d=0,f=[],m=null,x=0,E=new Map,w=new Set,K,D,W=new Promise((h,g)=>{K=h,D=g});W.catch(()=>{});let C=h=>{let g=new Error(`VCP site edit preview bridge runtime is not ready: ${h}`);return g.code=Vt,g},$=h=>{for(let g of E.values())g.reject(h);E.clear()},k=h=>{switch(h.type){case"ready":m=h.health,u==="starting"?(u="ready",K()):u==="restarting"&&(u="ready",console.warn("[vcp-site-edit] engine worker restarted"));return;case"start-failed":u==="starting"&&T(ne(h.error));return;case"result":{let g=E.get(h.id);if(!g)return;E.delete(h.id),h.ok?g.resolve(h.value):g.reject(ne(h.error));return}case"event":for(let g of w)try{g(h.event)}catch(I){console.warn(`[vcp-site-edit] engine event listener failed: ${I instanceof Error?I.message:String(I)}`)}return;case"health":m=h.health;return;case"snapshot-id-changed":c.options.snapshotId=h.next;try{s?.(h.next,h.previous)}catch(g){console.warn(`[vcp-site-edit] onSnapshotIdChanged callback failed: ${g instanceof Error?g.message:String(g)}`)}return}},B=()=>{let h=d+=1,g=n.workerUrl??new URL("./engine-worker.js",import.meta.url),I=new $t(Yt(g),{workerData:c,resourceLimits:{maxOldGenerationSizeMb:p},...n.execArgv?{execArgv:n.execArgv}:{}});I.unref();let A=()=>h===d;I.on("message",R=>{A()&&k(R)}),I.on("error",R=>{A()&&T(R instanceof Error?R:new Error(String(R)))}),I.on("exit",R=>{A()&&T(new Error(`engine worker exited with code ${R}`))}),S=I,n.onWorker?.(I)},T=h=>{if(u==="stopped"||u==="failed")return;if($(C(h.message)),m=null,u==="starting"){u="failed",console.error(`[vcp-site-edit] engine worker failed to start: ${h.message}`),D(h);return}let g=Date.now();for(;f.length>0&&g-f[0]>l;)f.shift();if(f.length>=a){u="failed",console.error(`[vcp-site-edit] engine worker stopped unexpectedly and exhausted ${a} restarts: ${h.message}`);return}f.push(g),u="restarting";for(let I of P.clients)I.close(Qt,"site edit engine restarting");console.error(`[vcp-site-edit] engine worker stopped unexpectedly, restarting (${f.length}/${a}): ${h.message}`),B()},V=(h,g)=>{if(u==="failed"||u==="stopped"||u==="restarting")return Promise.reject(C(u));let I=x+=1;return new Promise((A,R)=>{E.set(I,{resolve:A,reject:R});let Ze={type:"call",id:I,method:h,args:g};S.postMessage(Ze)})},j=Object.fromEntries(ve.map(h=>[h,(...g)=>V(h,g)])),P=ye({server:e,path:i.path,sessionKey:i.sessionKey,host:i.host,allowedOrigins:i.allowedOrigins,engine:{...j,subscribe(h){return w.add(h),()=>w.delete(h)}}});return B(),{getHealth(){return u==="ready"&&m?m:{ok:!1,bridgePath:i.path,runtimeReady:!1,routesIndexed:m?.routesIndexed??0,sessionRequired:!!i.sessionKey}},stop(){if(u==="stopped")return;let h=u==="starting";u="stopped",P.stop(),h&&D(C("bridge stopped")),$(C("bridge stopped")),w.clear();let g=S,I={type:"stop"};g.postMessage(I);let A=setTimeout(()=>{g.terminate()},Lt);A.unref(),g.once("exit",()=>clearTimeout(A))},whenReady(){return W},eventListeners:w}}function Yt(e){if(!e.pathname.endsWith(".ts"))return e;let t=Wt(Kt(import.meta.url).resolve("tsx/esm/api")).href,n=[`import { tsImport } from ${JSON.stringify(t)};`,`await tsImport(${JSON.stringify(e.href)}, ${JSON.stringify(e.href)});`].join(`
5
+ `);return new URL(`data:text/javascript,${encodeURIComponent(n)}`)}function Xt(e){if(!e||!/^\d+$/.test(e.trim()))return;let t=Number(e.trim());return Number.isSafeInteger(t)&&t>0?t:void 0}var en="next",tn="VCP_SITE_EDIT_ENGINE_IN_PROCESS",Je="127.0.0.1",nn=3e3,ee="/__vcp/site-edit/bridge",Ge="/__vcp/site-edit/health",sn="probe",on="render",$e="/_error",te="/__vcp/site-edit/client/",rn=`${te}auto-bootstrap.js`,Qe='data-vcp-site-edit-bootstrap="true"',an=["next.config.ts","next.config.mts","next.config.cts","next.config.js","next.config.mjs","next.config.cjs"],cn="@vcp-dev/site-edit-engine/webpack-loader",un=/@vcp\/site-edit-engine\/(?:webpack-loader|site-edit-instrumentation-loader)/,dn=[/\bconfig\.webpack\s*=/,/\bwebpack\s*\([^)]*\)\s*\{/,/\bwebpack\s*:\s*(?:async\s*)?(?:\([^)]*\)|[A-Za-z_$][\w$]*)?\s*=>/,/\bwebpack\s*:\s*(?:async\s+)?function\b/],hn=new Set(["auto-bootstrap.js","client.js","composition-key.js","designer-trace.js","document-codec.js","property-preview.js","protocol.js","window-message.js"]);async function Pi(e={},t={}){let n=t.process??process,i=t.createServer??xe.createServer,s=t.attachBridgeServer??(n.env[tn]==="1"?Be:Se),o=t.loadNext??Wn,r=z.resolve(e.projectRoot??process.cwd()),c=e.host??Je,p=e.port??qn(n.env.PORT)??nn,a=e.bridgePath??ee,l=Sn(a),u=Bn(),S=e.basePath??n.env.VCP_SITE_PREVIEW_BASE_PATH??"/",d=(e.tenantId??n.env.VCP_TENANT_ID)?.trim()||void 0,f=await o(r),m=pn(r),x=f({dev:!0,dir:r,hostname:c,port:p,...ln(m)}),E=x.getRequestHandler(),w=e.siteId??n.env.VCP_SITE_ID??"018f6f4d-a9b8-7120-8000-000000000120",K=e.snapshotId??n.env.VCP_SNAPSHOT_ID??Ln(r),D=e.historyRoot??n.env.VCP_SITE_EDIT_HISTORY_ROOT,W=D?.trim()?z.resolve(D):void 0,C=null,$={launchId:Zt(),pid:process.pid,snapshotId:K},k=i((P,h)=>{bn({basePath:S,bridgePath:a,bridgeHealthPath:l,bridgeSessionKey:u,getBridgeHealth:()=>C?.getHealth()??An(a),launch:$,runRenderProbe:()=>kn(x),handle:E,request:P,response:h}).catch(g=>{console.error(g),h.headersSent||(h.statusCode=500),h.end("site edit preview request failed")})}),B=null,T=null,V=()=>T||(Z(()=>n.off("SIGINT",j)),Z(()=>n.off("SIGTERM",j)),Z(()=>B?.()),B=null,Z(()=>C?.stop()),C=null,T=Promise.allSettled([Jn(k),Gn(()=>x.close())]).then(()=>{}),T),j=()=>{V()};try{return await x.prepare(),C=s(k,{...d?{tenantId:d}:{},siteId:w,snapshotId:K,projectRoot:r,basePath:S,host:c,port:p,path:a,sessionKey:u,...W?{historyRoot:W}:{},onSnapshotIdChanged:P=>{$.snapshotId=P}}),B=mn({server:k,bridgePath:a,handleUpgrade:x.getUpgradeHandler()}),n.on("SIGINT",j),n.on("SIGTERM",j),await C.whenReady?.(),await zn(k,p,c),{bundler:m,close:V,host:c,port:Qn(k,p),server:k}}catch(P){throw await V(),P}}function pn(e){let t=fn(e);return t&&gn(t)?"webpack":"turbopack"}function ln(e){return e==="webpack"?{webpack:!0}:{turbopack:!0}}function fn(e){for(let t of an){let n=G(e,t);if(F(n))return U(n,"utf8")}return null}function gn(e){return e.includes(cn)?!0:un.test(e)&&dn.some(t=>t.test(e))}function mn(e){let t=(n,i,s)=>{yn(n.url,e.bridgePath)||e.handleUpgrade(n,i,s).catch(o=>{console.error(o),i.destroyed||i.destroy()})};return e.server.on("upgrade",t),()=>e.server.off("upgrade",t)}function yn(e,t){return new URL(e??"/","http://localhost").pathname===t}function Sn(e=ee){if(e===ee)return Ge;let t=(e.startsWith("/")?e:`/${e}`).replace(/\/+$/,"");return t.endsWith("/bridge")?`${t.slice(0,-7)}/health`:t?`${t}/health`:"/health"}function In(e){let t=JSON.stringify({basePath:e.basePath,launch_id:e.launch?.launchId,snapshot_id:e.launch?.snapshotId,wsPath:e.bridgePath,bridge_session_key:e.bridgeSessionKey,defer_initial_sync:!0,runtime_versions:e.runtimeVersions??En()});return`<script type="module" ${Qe}>import { startSiteEditAutoBootstrap } from ${JSON.stringify(rn)};void startSiteEditAutoBootstrap(window, ${t}).catch(() => undefined);</script>`}function En(){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=Le(import.meta.url);try{let n=t.resolve(e),i=wn(n,e);if(!i)return;let s=JSON.parse(U(i,"utf8"));return typeof s.version=="string"?s.version:void 0}catch{return}}function wn(e,t){let n=z.parse(e).root,i=J(e);for(;i&&i!==n;){let s=G(i,"package.json");if(F(s))try{if(JSON.parse(U(s,"utf8")).name===t)return s}catch{return}i=J(i)}}function xn(e,t){if(e.includes(Qe))return e;let n=In(t),i=/<\/body\s*>/i.exec(e);return i?`${e.slice(0,i.index)}${n}${e.slice(i.index)}`:`${e}${n}`}function Ai(e,t=J(ze(import.meta.url)),n=F){return Ye(e,t,n)?.path??null}function Ye(e,t=J(ze(import.meta.url)),n=F){let i=new URL(e??"/","http://localhost").pathname;if(!i.startsWith(te))return null;let s=i.slice(te.length);if(!hn.has(s))return null;let o=Ce($n(t),s);if(qe(t)!=="src")return{path:o,requiresTranspile:!1};let r=Ce(t,s.replace(/\.js$/,".ts"));return n(r)?{path:r,requiresTranspile:!0}:{path:o,requiresTranspile:!1}}async function Cn(e,t){let n=Ye(e.url);if(!n)return!1;if(!F(n.path))return t.writeHead(404),t.end("site edit client asset not found"),!0;let i=n.requiresTranspile?await vn(U(n.path,"utf8")):U(n.path);return t.writeHead(200,{"cache-control":"no-store","content-type":"text/javascript; charset=utf-8"}),t.end(i),!0}async function vn(e){let t=await import("typescript");return t.transpileModule(e,{compilerOptions:{module:t.ModuleKind.ES2022,target:t.ScriptTarget.ES2022}}).outputText}async function bn({basePath:e,bridgePath:t,bridgeHealthPath:n,bridgeSessionKey:i,getBridgeHealth:s,launch:o,runRenderProbe:r,handle:c,request:p,response:a}){if(Rn(p.url,e)){a.statusCode=404,a.end();return}if(await Pn(p,a,n,s,o,r)||await Cn(p,a))return;let l=Hn(p),u=Nn(p),S=l||u?Dn(a,{basePath:e,bridgePath:t,bridgeSessionKey:i,patchNextDevChunk:u,launch:{...o}}):()=>{};try{await c(p,a)}catch(d){throw S(),d}}function Rn(e,t){let n=(e??"/").split(/[?#]/,1)[0]??"/";if(!/(\\|\/\/)/.test(n))return!1;let i;try{i=decodeURIComponent(n).replace(/\\/g,"/").replace(/\/{2,}/g,"/")}catch{return!1}let s=new URL(i,"http://namespace.invalid").pathname,o=t.replace(/\/+$/,"");return(o&&(s===o||s.startsWith(o+"/"))?s.slice(o.length)||"/":s).startsWith("/.vcp")}function _n(e){let t=e instanceof Error?e.message:String(e),n=e&&typeof e=="object"&&"code"in e?e.code:void 0;return/\.next[/\\]/.test(t)||/chunks[/\\]ssr[/\\]/.test(t)?n==="ENOENT"||n==="MODULE_NOT_FOUND"?{verdict:"artifact_broken",detail:t}:t.includes("Cannot find module")?{verdict:"artifact_broken",detail:t}:{verdict:"inconclusive",detail:t}:{verdict:"inconclusive",detail:t}}async function kn(e){let t=new xe.IncomingMessage(new We);t.method="GET",t.url=$e,t.headers={host:Je};let n=new xe.ServerResponse(t);n.assignSocket(new We);try{return await e.renderToHTML(t,n,$e,{}),{verdict:"ok"}}catch(i){return _n(i)}finally{try{let i=n.socket;i&&(n.detachSocket(i),i.destroy())}catch{}}}function Tn(e){return new URL(e??"/","http://localhost").searchParams.get(sn)===on}async function Pn(e,t,n,i,s,o){if(e.method!=="GET"||new URL(e.url??"/","http://localhost").pathname!==n)return!1;let c=i(),p=Tn(e.url)?await o():void 0,a={...c,launch:s,...p?{render:p}:{}};return t.writeHead(c.ok?200:503,{"cache-control":"no-store","content-type":"application/json; charset=utf-8"}),t.end(JSON.stringify(a)),!0}function An(e){return{ok:!1,bridgePath:e,runtimeReady:!1,routesIndexed:0,sessionRequired:!0}}function Hn(e){return On(e)?(e.headers["accept-encoding"]="identity",!0):!1}function Nn(e){return Mn(e)?(e.headers["accept-encoding"]="identity",!0):!1}function On(e){if(e.method!=="GET")return!1;let t=new URL(e.url??"/","http://localhost");if(e.headers["x-template-id"]!==void 0&&!t.searchParams.has("template_id"))return!1;let n=t.pathname;if(n.startsWith("/_next/")||n.startsWith(te)||n===ee||n===Ge)return!1;let i=e.headers.accept??"";return i===""||i.includes("text/html")}function Mn(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 Dn(e,t){let n=[],i=e,s=i.flushHeaders.bind(e),o=i.write.bind(e),r=i.end.bind(e),c=!1;i.flushHeaders=()=>{};let p=()=>{if(t.patchNextDevChunk||c)return!1;let a=Buffer.concat(n);if(!/<body\b[^>]*>/iu.test(a.toString("utf8")))return!1;let l=Ve(e,a,t);return l!==a&&!e.headersSent&&e.removeHeader("content-length"),o(l),n.length=0,c=!0,!0};return i.write=(a,l,u)=>c?(a!==void 0&&o(Ee(a,we(l))),X(l),X(u),!0):(a!==void 0&&(n.push(Ee(a,we(l))),p()),X(l),X(u),!0),i.end=(a,l,u)=>{let S=typeof a=="function"?void 0:a;if(c)return i.write=o,i.end=r,i.flushHeaders=s,S===void 0?typeof a=="function"?r(a):typeof l=="function"?r(l):typeof u=="function"?r(u):r():typeof l=="function"?r(S,l):typeof u=="function"?r(S,l,u):r(S,l);S!==void 0&&n.push(Ee(S,we(l))),i.write=o,i.end=r,i.flushHeaders=s;let d=Buffer.concat(n),f=Ve(e,d,t);f!==d&&!e.headersSent&&e.removeHeader("content-length");let m=typeof a=="function"?a:typeof l=="function"?l:typeof u=="function"?u:void 0;return m?r(f,m):r(f)},()=>{i.write=o,i.end=r,i.flushHeaders=s}}function Ve(e,t,n){if(jn(e,t))return Buffer.from(xn(t.toString("utf8"),n));if(n.patchNextDevChunk&&Un(e)){let i=t.toString("utf8"),s=Fn(i);if(s!==i)return Buffer.from(s)}return t}function Bn(){let e=new Uint8Array(32);return globalThis.crypto.getRandomValues(e),Buffer.from(e).toString("base64url")}function jn(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 Un(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 Fn(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
6
  `),["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,[i,s])=>jn(n,i,s),e)}function jn(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 Ie(e,t){return Buffer.isBuffer(e)?e:e instanceof Uint8Array?Buffer.from(e):Buffer.from(String(e),t)}function Ee(e){return typeof e=="string"?e:void 0}function Y(e){typeof e=="function"&&e()}async function Un(e){let n=$e(G(e,"package.json"))(Yt);return n.default??n}function Fn(e){return Le(e)!=="src"?e:xe(Kn(e),"dist")}function Kn(e){return Ye(e)?q.posix.dirname(e):z(e)}function xe(e,t){return Ye(e)?q.posix.join(e,t):G(e,t)}function Ye(e){return e.includes("/")&&!e.includes("\\")}function Wn(e){let t=G(e,".vcp/current-snapshot.json");if(!U(t))return"sandbox_worktree";try{let n=JSON.parse(j(t,"utf8"));return typeof n.snapshot_id=="string"&&n.snapshot_id?n.snapshot_id:typeof n.snapshotId=="string"&&n.snapshotId?n.snapshotId:"sandbox_worktree"}catch{return"sandbox_worktree"}}function Vn(e){if(!e)return null;let t=Number.parseInt(e,10);return Number.isInteger(t)&&t>0&&t<=65535?t:null}function $n(e,t,n){return new Promise((i,s)=>{e.once("error",s),e.listen(t,n,()=>{e.off("error",s),i()})})}function Ln(e){return new Promise(t=>{e.close(()=>t())})}function X(e){try{e()}catch{}}function qn(e){try{return e()}catch(t){return Promise.reject(t)}}function zn(e,t){let n=e.address();return typeof n=="object"&&n?n.port:t}export{ln as attachNextDevUpgradeHandler,ye as attachSiteEditBridgeServerInWorker,vn as classifySiteEditRenderProbeError,mn as createSiteEditAutoBootstrapHtmlSnippet,In as injectSiteEditAutoBootstrap,Rn as isSiteEditRenderProbeRequested,Bn as patchNextFirefoxDevChunk,Pn as prepareFirefoxNextDevChunkPatchRequest,Tn as prepareSiteEditHtmlInjectionRequest,gn as resolveSiteEditBridgeHealthPath,Qe as resolveSiteEditClientAsset,Ri as resolveSiteEditClientAssetPath,un as resolveSiteEditNextDevBundler,bn as runSiteEditRenderProbe,bi as startSiteEditNextDevServer,wn as transpileSiteEditClientSource};
7
+ `)],[["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,s])=>Kn(n,i,s),e)}function Kn(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 Ee(e,t){return Buffer.isBuffer(e)?e:e instanceof Uint8Array?Buffer.from(e):Buffer.from(String(e),t)}function we(e){return typeof e=="string"?e:void 0}function X(e){typeof e=="function"&&e()}async function Wn(e){let n=Le(G(e,"package.json"))(en);return n.default??n}function $n(e){return qe(e)!=="src"?e:Ce(Vn(e),"dist")}function Vn(e){return Xe(e)?z.posix.dirname(e):J(e)}function Ce(e,t){return Xe(e)?z.posix.join(e,t):G(e,t)}function Xe(e){return e.includes("/")&&!e.includes("\\")}function Ln(e){let t=G(e,".vcp/current-snapshot.json");if(!F(t))return"sandbox_worktree";try{let n=JSON.parse(U(t,"utf8"));return typeof n.snapshot_id=="string"&&n.snapshot_id?n.snapshot_id:typeof n.snapshotId=="string"&&n.snapshotId?n.snapshotId:"sandbox_worktree"}catch{return"sandbox_worktree"}}function qn(e){if(!e)return null;let t=Number.parseInt(e,10);return Number.isInteger(t)&&t>0&&t<=65535?t:null}function zn(e,t,n){return new Promise((i,s)=>{e.once("error",s),e.listen(t,n,()=>{e.off("error",s),i()})})}function Jn(e){return new Promise(t=>{e.close(()=>t())})}function Z(e){try{e()}catch{}}function Gn(e){try{return e()}catch(t){return Promise.reject(t)}}function Qn(e,t){let n=e.address();return typeof n=="object"&&n?n.port:t}export{mn as attachNextDevUpgradeHandler,Se as attachSiteEditBridgeServerInWorker,_n as classifySiteEditRenderProbeError,In as createSiteEditAutoBootstrapHtmlSnippet,xn as injectSiteEditAutoBootstrap,Tn as isSiteEditRenderProbeRequested,Fn as patchNextFirefoxDevChunk,Nn as prepareFirefoxNextDevChunkPatchRequest,Hn as prepareSiteEditHtmlInjectionRequest,Sn as resolveSiteEditBridgeHealthPath,Ye as resolveSiteEditClientAsset,Ai as resolveSiteEditClientAssetPath,pn as resolveSiteEditNextDevBundler,kn as runSiteEditRenderProbe,Pi as startSiteEditNextDevServer,vn as transpileSiteEditClientSource};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vcp-dev/site-edit-bridge",
3
- "version": "0.10.24",
3
+ "version": "0.10.25",
4
4
  "type": "module",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
@@ -79,8 +79,8 @@
79
79
  "typecheck": "tsc -p tsconfig.json --noEmit"
80
80
  },
81
81
  "dependencies": {
82
- "@vcp-dev/contracts": "0.10.24",
83
- "@vcp-dev/site-edit-engine": "0.10.24",
82
+ "@vcp-dev/contracts": "0.10.25",
83
+ "@vcp-dev/site-edit-engine": "0.10.25",
84
84
  "@types/ws": "^8.18.1",
85
85
  "ws": "^8.20.1"
86
86
  },