@vcp-dev/site-edit-bridge 0.10.32 → 0.10.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/engine-worker.js +2 -2
- package/dist/index.js +6 -6
- package/dist/next-dev-server.js +4 -4
- package/dist/server.d.ts +1 -0
- package/dist/server.js +2 -2
- package/package.json +3 -3
package/dist/engine-worker.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{parentPort as tt,workerData as nt}from"node:worker_threads";function M(t){let e=t&&typeof t=="object"?t:null,n=typeof e?.message=="string"&&e.message.length>0?e.message:String(t);return{name:typeof e?.name=="string"?e.name:"Error",message:n,...typeof e?.code=="string"&&e.code.length>0?{code:e.code}:{}}}import oe from"node:http";import _ from"node:fs";import{createHash as J,randomBytes as Re,timingSafeEqual as xe}from"node:crypto";import m from"node:path";import{WebSocket as re,WebSocketServer as be}from"ws";import{createPreviewSiteEditEngineRuntime as ke,openFileHistoryStore as ve,resolveManagedPageTemplateComposition as _e,scanSiteEditCompositionsFromFiles as Te}from"@vcp-dev/site-edit-engine";import{resolveNextAppRouteId as Oe,scanNextAppRouterRoutesFromFiles as Ae}from"@vcp-dev/site-edit-engine/next-app-router";import{SiteEditSourceWatcher as He}from"@vcp-dev/site-edit-engine/source-watcher";function Y(t){let e=new Map,n=[],i=new Map,o=[],s=t.pageComposition.status==="supported"?t.pageComposition.placementUnitKeys:[],r=new Map(s.map((c,h)=>[c,h])),a=t.pageComposition.status==="supported"?{status:"supported",containerKey:t.pageComposition.containerKey,hasBusinessMembers:t.pageComposition.hasBusinessMembers,placementUnitKeys:t.pageComposition.placementUnitKeys,placements:t.pageComposition.placements.map(c=>({placementKey:c.placementKey,placementUnitKey:c.placementUnitKey,relation:c.relation}))}:{status:"unsupported",reason:t.pageComposition.reason,diagnostics:t.pageComposition.diagnostics},p=t.entries.flatMap((c,h)=>c.dynamicDataSummary?[[h,c.dynamicDataSummary]]:[]),u=new Map(t.entries.map((c,h)=>[c.key,h])),l=[];for(let[c,h]of t.entries.entries()){let g=h.pageCompositionActionScope;if(!g)continue;if(g.kind!=="source-siblings"){l.push([c,{kind:g.kind}]);continue}let O=g.siblingKeys.map(b=>{let k=u.get(b);if(k===void 0)throw new Error("Render entry "+h.key+" references missing source sibling "+b);return k});l.push([c,{kind:"source-siblings",siblingEntryIndexes:O}])}let S=c=>{let h=e.get(c);if(typeof h=="number")return h;let g=n.length;return n.push(c),e.set(c,g),g},Q=c=>{let h=null;for(let g of pe(c)){let O=`${h??"root"}\0${g}`,b=i.get(O);if(typeof b=="number"){h=b;continue}let k=o.length;o.push([h,S(g)]),i.set(O,k),h=k}if(h===null)throw new Error("Document key must not be empty");return h};return{encoding:"segment-trie-v1",siteId:t.siteId,snapshotId:t.snapshotId,composition:{...t.composition},routeId:t.composition.routeId,version:t.version,pageComposition:a,tokens:n,nodes:o,entries:t.entries.map(c=>{let h=c.pageCompositionUnitKey?r.get(c.pageCompositionUnitKey)??-1:-1;if(c.pageCompositionUnitKey&&h<0)throw new Error(`Render entry ${c.key} references unknown page composition unit ${c.pageCompositionUnitKey}`);return[Q(c.key),he(c.operationSummary),...h>=0?[h]:[]]}),...l.length>0?{pageCompositionActionScopes:l}:{},...t.entries.every(c=>c.parentKey!==void 0)?{entryParentNodeIds:t.entries.map(c=>c.parentKey===null?null:Q(c.parentKey))}:{},...p.length>0?{dynamicDataSummaries:p}:{}}}function he(t){return(t.canUpdateText?1:0)|(t.canInsertChild?2:0)|(t.canMove?4:0)|(t.canRemove?8:0)}function pe(t){if(!t)return[];let e=[],n=0,i=G(t,n);if(i<0)return e.push(t),e;for(e.push(t.slice(0,i)),n=i;n<t.length;){if(i=G(t,n+(t.startsWith("::",n)?2:1)),i<0){e.push(t.slice(n));break}e.push(t.slice(n,i)),n=i}return e}function G(t,e){let n=t.indexOf("/",e),i=t.indexOf("::",e);return n<0?i:i<0?n:Math.min(n,i)}var Z="SITE_EDIT_COMPOSITION_SESSION_MISMATCH",V="SITE_EDIT_COMPOSITION_SESSION_REQUIRED";var f=class t{constructor(){}static parseMessage(e,n={}){let i=JSON.parse(e);if(!t.isMessage(i,n))throw new Error("Invalid site edit bridge message");return i}static stringifyMessage(e){return JSON.stringify(e)}static extractRequestInfo(e){if(d(e)&&d(e.payload)){let n=typeof e.payload.id=="string"?e.payload.id:"unknown",i=this.isRequestKind(e.payload.kind)?e.payload.kind:"get-document";return{id:n,kind:i}}return{id:"unknown",kind:"get-document"}}static isRequestKind(e){return e==="initialize-session"||e==="get-document"||e==="get-history-status"||e==="get-style-context"||e==="get-object-edit-context"||e==="get-class-name-source"||e==="get-source-tree"||e==="get-source-file"||e==="resolve-source-location"||e==="execute"||e==="get-operation-result"||e==="undo"||e==="redo"}static isMessage(e,n={}){return!d(e)||typeof e.type!="string"?!1:e.type==="request"?fe(e.payload,n):e.type==="response"||e.type==="error"?d(e.payload)&&typeof e.payload.id=="string":e.type==="event"?d(e.payload)&&d(e.payload.event):e.type==="auth"?d(e.payload)&&typeof e.payload.key=="string":e.type==="ping"||e.type==="pong"?d(e.payload)&&typeof e.payload.id=="string":e.type==="auth-ok"&&d(e.payload)&&e.payload.ok===!0}},A=class{constructor(e){this.options=e,this.session={subscribedCompositionKeys:new Set},this.messageQueue=new P,this.eventDispatcher=new B(n=>{this.sendJson(n)}),this.unsubscribe=e.engine.subscribe(n=>{this.handleEngineEvent(n)}),e.socket.onmessage=n=>{let i=ge(n.data);if(i!==null){this.sendJson({type:"pong",payload:{id:i}});return}try{this.messageQueue.enqueue(()=>this.handleRawMessage(n.data))}catch(o){this.sendJson({type:"error",payload:{id:"unknown",kind:"get-document",message:o instanceof Error?o.message:"Bridge queue overflow"}}),e.socket.close(1013,"bridge busy")}},e.socket.onclose=()=>{this.unsubscribe(),this.session.activeComposition=void 0,this.session.subscribedCompositionKeys.clear()}}async handleMessage(e){try{let n=e;if(n.type!=="request")return;let i=n.payload,{id:o}=i;switch(i.kind){case"initialize-session":{let s=D(i),r=await this.resolve(s),a=await this.options.engine.initializeSession({composition:r.context,...i.mutationContext?{mutationContext:i.mutationContext}:{}});this.activateSession(r.context),this.sendJson({type:"response",payload:{id:o,kind:i.kind,result:I({...a,data:{...a.data,document:ee(a.data.document)}},r.context)}});return}case"get-document":{let s=await this.resolveWireContext(i),r=await this.options.engine.getDocument(s);this.sendResult(o,i.kind,Ee(r,s));return}case"get-history-status":{let s=await this.resolveWireContext(i),r=await this.options.engine.getHistoryStatus(s);this.sendResult(o,i.kind,I(r,s));return}case"get-style-context":{let s=await this.resolveWireContext(i);this.sendResult(o,i.kind,I(await this.options.engine.getStyleContext(s),s));return}case"get-object-edit-context":{let s=await this.resolveWireContext(i);this.sendResult(o,i.kind,I(await this.options.engine.getObjectEditContext(i.key,s,i.selectionRef),s));return}case"get-class-name-source":{let s=await this.resolveWireContext(i);this.sendResult(o,i.kind,I(await this.options.engine.getClassNameSource(i.key,s),s));return}case"get-source-tree":{let s=await this.resolveWireContext(i);this.sendResult(o,i.kind,I(await this.options.engine.getSourceTree(s),s));return}case"get-source-file":{let s=await this.resolveWireContext(i);this.sendResult(o,i.kind,I(await this.options.engine.getSourceFile({path:i.path,composition:s}),s));return}case"resolve-source-location":{let s=await this.resolveWireContext(i),r=I(await this.options.engine.resolveSourceLocation({key:i.key,composition:s}),s);this.sendResult(o,i.kind,r);return}case"execute":case"get-operation-result":{let s=await this.resolveOperationWireContext(i.request),r=await this.resolveWireContext(i);if(w(s)!==w(r))throw new E(Z,"The execute request composition does not match its operation composition.");let a=await this.normalizeOperationRequest(i.request,s);if(i.kind==="get-operation-result"){this.sendResult(o,i.kind,await this.options.engine.getOperationResult?.(a)??null);return}await this.handleBufferedOperation(o,i.kind,()=>this.options.engine.execute(a));return}case"undo":case"redo":{let s=await this.resolveWireContext(i);await this.handleBufferedOperation(o,i.kind,()=>i.kind==="undo"?this.options.engine.undo(s):this.options.engine.redo(s));return}}}catch(n){let i=f.extractRequestInfo(e);this.sendJson({type:"error",payload:{...i,message:F(n),code:K(n)}})}}async resolve(e){return this.options.engine.resolveComposition(e)}async resolveAndAssert(e){let n=await this.resolve(e),i=this.session.activeComposition;if(!i)throw new E(V,"Initialize a composition session before issuing this request.");if(w(i)!==w(n.context))throw new E(Z,"The request composition does not match the active socket session.");return n.context}async resolveWireContext(e){let n=D(e);return this.resolveAndAssert(n)}async resolveOperationWireContext(e){let n=Se(e);return this.resolveAndAssert(n)}activateSession(e){this.session.activeComposition=e,this.session.subscribedCompositionKeys.clear(),this.session.subscribedCompositionKeys.add(w(e))}async normalizeOperationRequest(e,n){let i={...e,composition:X(n)};if(i.target.kind==="route"){let o=i.target,s=D(o),r=await this.resolveAndAssert(s);i.target={...o,composition:X(r)}}return i}handleEngineEvent(e){let n=e?.composition;if(!Ie(n))return;let i=w(n);this.session.subscribedCompositionKeys.has(i)&&(this.eventDispatcher.push(e),e.type==="site-edit.graph.invalidated"&&i===we(this.session)&&(this.session.activeComposition=void 0,this.session.subscribedCompositionKeys.delete(i)))}sendResult(e,n,i){this.sendJson({type:"response",payload:{id:e,kind:n,result:i}})}async handleRawMessage(e){try{await this.handleMessage(f.parseMessage(e,{validateOperationRequest:this.options.validateOperationRequest}))}catch(n){let i=Ce(e);this.sendJson({type:"error",payload:{...i,message:F(n),code:K(n)}})}}sendJson(e){this.options.socket.send(f.stringifyMessage(e))}async handleBufferedOperation(e,n,i){this.eventDispatcher.beginBuffering();try{let o=await i();this.sendResult(e,n,o)}catch(o){this.sendJson({type:"error",payload:{id:e,kind:n,message:F(o),code:K(o)}})}finally{this.eventDispatcher.flush()}}},le=256;function ge(t){if(t.length>le||!t.includes('"ping"'))return null;try{let e=JSON.parse(t);return d(e)&&e.type==="ping"&&d(e.payload)&&typeof e.payload.id=="string"?e.payload.id:null}catch{return null}}var E=class extends Error{constructor(e,n){super(n),this.code=e,this.name="BridgeProtocolError"}},B=class{constructor(e){this.send=e,this.bufferedEvents=null}push(e){let n={type:"event",payload:{event:e}};if(this.bufferedEvents){this.bufferedEvents.push(n);return}this.send(n)}beginBuffering(){this.bufferedEvents=[]}flush(){let e=this.bufferedEvents??[];this.bufferedEvents=null,e.forEach(n=>this.send(n))}},P=class{constructor(e=64){this.maxQueued=e,this.queue=Promise.resolve(),this.queued=0}enqueue(e){if(this.queued>=this.maxQueued)throw new Error("Bridge request queue is full");this.queued+=1;let n=async()=>{this.queued-=1,await e()},i=this.queue.then(n,n);return this.queue=i.then(()=>{},()=>{}),i}};function fe(t,e){if(!d(t)||typeof t.id!="string"||!f.isRequestKind(t.kind))return!1;let n=v(t.composition);switch(t.kind){case"initialize-session":return n&&(t.mutationContext===void 0||N(t.mutationContext));case"get-document":case"get-style-context":return n;case"get-object-edit-context":return typeof t.key=="string"&&n&&me(t.selectionRef);case"get-class-name-source":case"resolve-source-location":return typeof t.key=="string"&&n;case"get-history-status":return n;case"get-source-tree":return n;case"get-source-file":return typeof t.path=="string"&&n;case"execute":case"get-operation-result":return n&&ye(t.request)&&(t.request.mutationContext===void 0||N(t.request.mutationContext))&&(e.validateOperationRequest?.(t.request)??!0);case"undo":case"redo":return n&&t.mutationContext===void 0||n&&N(t.mutationContext)}}function me(t){if(t===void 0)return!0;if(!d(t)||typeof t.key!="string"||t.key.length===0)return!1;let e=t.instanceIndex,n=t.instanceCount;return e!==void 0&&(typeof e!="number"||!Number.isInteger(e)||e<0)||n!==void 0&&(typeof n!="number"||!Number.isInteger(n)||n<=0)||typeof e=="number"&&typeof n=="number"&&e>=n?!1:Object.keys(t).every(i=>i==="key"||i==="instanceIndex"||i==="instanceCount")}function ye(t){return d(t)&&typeof t.id=="string"&&typeof t.siteId=="string"&&typeof t.baseSnapshotId=="string"&&v(t.composition)&&typeof t.kind=="string"&&d(t.target)&&(t.target.kind!=="route"||v(t.target.composition))&&typeof t.documentVersion=="number"&&Number.isInteger(t.documentVersion)&&t.documentVersion>=0&&d(t.params)}function v(t){return d(t)&&typeof t.routeId=="string"&&t.routeId.length>0&&(t.templateId===void 0||typeof t.templateId=="string"&&t.templateId.length>0)&&Object.keys(t).every(e=>e==="routeId"||e==="templateId")}function Ie(t){return d(t)&&typeof t.routeId=="string"&&(t.effectiveTemplateId===void 0||typeof t.effectiveTemplateId=="string")}function D(t){if(v(t.composition))return t.composition;throw new E(V,"A composition selector is required for this request.")}function Se(t){if(d(t)&&v(t.composition))return t.composition;throw new E(V,"A composition selector is required for execute.")}function X(t){return{routeId:t.routeId,...t.effectiveTemplateId?{templateId:t.effectiveTemplateId}:{}}}function we(t){return t.activeComposition?w(t.activeComposition):null}function w(t){return JSON.stringify([t.routeId,t.effectiveTemplateId??null])}function I(t,e){return d(t)&&t.ok===!0?{...t,composition:e}:t}function Ee(t,e){return!d(t)||t.ok!==!0?t:{...t,...e?{composition:e}:{},data:ee(t.data)}}function ee(t){let e=t;return Y(e.routeId?e:{...e,routeId:e.composition.routeId})}function d(t){return typeof t=="object"&&t!==null}function N(t){return d(t)&&typeof t.editingSessionId=="string"&&t.editingSessionId.length>0&&typeof t.lockId=="string"&&t.lockId.length>0&&typeof t.ownerId=="string"&&t.ownerId.length>0&&typeof t.leaseAssertion=="string"&&t.leaseAssertion.length>0}function K(t){if(!(!d(t)||typeof t.code!="string"||t.code.length===0))return t.code}function F(t){return t instanceof Error||d(t)&&typeof t.message=="string"&&t.message.length>0?t.message:"Unknown websocket operation failure"}function Ce(t){try{return f.extractRequestInfo(JSON.parse(t))}catch{return{id:"unknown",kind:"get-document"}}}var H=class{constructor(){this.tail=Promise.resolve()}run(e){let n=this.tail.then(e,e);return this.tail=n.then(()=>{},()=>{}),n}};import{SiteEditOperationRequestSchema as Me,computeSiteEditCompositionKey as C}from"@vcp-dev/contracts";var De="127.0.0.1",Ne=30218,Ke="/__vcp/site-edit/bridge",ae=6*1024*1024,Fe=ae*2,Be=3e3,te=50,j=".vcp/current-snapshot.json",ne="__VCP_SITE_EDIT_BRIDGE_SERVERS__";var $=class{constructor(e,n=oe.createServer((s,r)=>{r.writeHead(404),r.end("VCP site edit bridge server")}),i=!0,o={}){this.options=e,this.server=n,this.closeHttpServerOnStop=i,this.dependencies=o,this.runtime=null,this.activeHistorySessionId=null,this.historySessionTransition=Promise.resolve(),this.mutationQueue=new H,this.operationReceipts=new Map,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(e={}){if(!this.isStarted){this.stopping=!1;try{_.mkdirSync(m.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(),e.webSocket!==!1){let n=ze({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 He({projectRoot:this.options.projectRoot,watch_dirs:Ve(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(),e.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 e=!!this.runtime&&!this.compositionResolutionError;return{ok:this.isStarted&&e,bridgePath:this.options.path,runtimeReady:e,routesIndexed:this.routes.length,sessionRequired:!!this.options.sessionKey}}stop(){this.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 e=$e(),n=qe(this.options);e.get(n)===this&&e.delete(n),this.isStarted=!1,this.notifyHealthChanged()}notifyHealthChanged(){let e=this.options.onHealthChanged;if(!e)return;let n=this.getHealth(),i=JSON.stringify(n);if(i!==this.lastNotifiedHealth){this.lastNotifiedHealth=i;try{e(n)}catch(o){console.warn(`[vcp-site-edit] onHealthChanged callback failed: ${o instanceof Error?o.message:String(o)}`)}}}createRuntime(e,n=null){let i=this.runtime;this.activeHistoryStore=e??null;let o=(this.dependencies.createRuntime??ke)({...this.options.tenantId?{tenantId:this.options.tenantId}:{},siteId:this.options.siteId,snapshotId:this.options.snapshotId,projectRoot:this.options.projectRoot,compositions:this.compositions,onEvent:s=>{"version"in s&&typeof s.version=="number"&&this.recordRuntimeVersion(s.version,"composition"in s?s.composition:void 0);for(let r of this.eventListeners)r(s)},...e?{historyStore:e}:{},...this.getInitialDocumentVersions().length>0?{initialDocumentVersions:this.getInitialDocumentVersions()}:{}});this.runtime=o,this.activeHistorySessionId=n,i?.dispose(),this.notifyHealthChanged()}createBridgeEngine(){return{resolveComposition:e=>this.resolveComposition(e),initializeSession:e=>this.mutationQueue.run(async()=>{let n=await this.bindHistorySession(this.options.snapshotId);if(!n.ok)throw new Error(`${n.code}: ${n.message}`);let i=We(e.composition),o=this.getRuntime(),s=y(i);await o.initializeComposition(s);let a=o.getDocument(s).data;await this.recordRuntimeVersion(a.version,i);let p=(await o.getHistoryStatus()).data;return{ok:!0,composition:i,data:{document:a,historyStatus:p}}}),getDocument:async e=>{let n=this.getRuntime(),i=y(e);await n.initializeComposition(i);let o=n.getDocument(i);return await this.recordRuntimeVersion(o.data.version,e),{...o,composition:e}},getHistoryStatus:async e=>({...await this.getRuntime().getHistoryStatus(),composition:e}),getStyleContext:async e=>this.getRuntime().getStyleContext(y(e)),getObjectEditContext:async(e,n,i)=>this.getRuntime().getObjectEditContext(e,y(n),i),getClassNameSource:async(e,n)=>this.getRuntime().getClassNameSource(e,y(n)),getSourceTree:async e=>this.getRuntime().getSourceTree(y(e)),getSourceFile:async e=>this.getRuntime().getSourceFile({path:e.path,composition:y(e.composition)}),resolveSourceLocation:async e=>this.getRuntime().resolveSourceLocation({key:e.key,composition:y(e.composition)}),execute:(e,n)=>this.executeWithReceipt(e,()=>this.mutationQueue.run(async()=>{let i=await this.bindHistorySession(this.options.snapshotId);if(!i.ok)return U(i,e);let o=await this.getRuntime().executeOperation(e);return o.data?.resultVersion!==void 0&&await this.recordRuntimeVersion(o.data.resultVersion,o.composition),o})),getOperationResult:e=>{if(e.siteId!==this.options.siteId||e.baseSnapshotId!==this.options.snapshotId)return null;let n=this.operationReceipts.get(this.operationReceiptKey(e));return n?.fingerprint===this.operationFingerprint(e)?n.result:null},undo:e=>this.mutationQueue.run(async()=>{let n=await this.bindHistorySession(this.options.snapshotId);if(!n.ok)return U(n,void 0,e);let i=await this.getRuntime().undo();return i.data?.resultVersion!==void 0&&await this.recordRuntimeVersion(i.data.resultVersion,i.composition??e),i.composition?i:{...i,composition:e}}),redo:e=>this.mutationQueue.run(async()=>{let n=await this.bindHistorySession(this.options.snapshotId);if(!n.ok)return U(n,void 0,e);let i=await this.getRuntime().redo();return i.data?.resultVersion!==void 0&&await this.recordRuntimeVersion(i.data.resultVersion,i.composition??e),i.composition?i:{...i,composition:e}}),subscribe:e=>(this.eventListeners.add(e),()=>this.eventListeners.delete(e))}}operationReceiptKey(e){return JSON.stringify([e.siteId,e.baseSnapshotId,e.id])}operationFingerprint(e){return J("sha256").update(JSON.stringify(e)).digest("hex")}executeWithReceipt(e,n){if(e.siteId!==this.options.siteId||e.baseSnapshotId!==this.options.snapshotId)return n();let i=this.operationReceiptKey(e),o=this.operationFingerprint(e),s=this.operationReceipts.get(i);if(s)return s.fingerprint!==o?Promise.reject(new Error("Operation ID was reused with a different request.")):s.result;let r={fingerprint:o,result:n(),settled:!1};return this.operationReceipts.set(i,r),r.result.then(()=>{r.settled=!0;for(let[a,p]of this.operationReceipts){if(this.operationReceipts.size<=256)break;p.settled&&this.operationReceipts.delete(a)}},()=>{this.operationReceipts.delete(i)}),r.result}async bindHistorySession(e){if(!this.options.historyRoot)return{ok:!1,code:"RECOVERY_PERSIST_FAILED",message:"Durable edit history is not configured."};if(this.activeHistorySessionId===e)return{ok:!0};let n=this.historySessionTransition.then(async()=>{if(this.activeHistorySessionId===e)return;let i=await(this.dependencies.openHistoryStore??ve)(je({root:this.options.historyRoot,siteId:this.options.siteId,snapshotId:this.options.snapshotId,editingSessionId:e}));if(!this.isStarted)return;let o=i.readDocumentVersion?await i.readDocumentVersion():0,s=this.compositions[0]?.context;if(s){let r=C(s);this.runtimeVersionFloors.set(r,Math.max(this.runtimeVersionFloors.get(r)??0,o))}this.createRuntime(i,e)});this.historySessionTransition=n.catch(()=>{});try{return await n,{ok:!0}}catch{return{ok:!1,code:"RECOVERY_PERSIST_FAILED",message:"Durable edit history could not be opened."}}}recordRuntimeVersion(e,n){let i=n?C(n):null;i&&this.runtimeVersionFloors.set(i,Math.max(this.runtimeVersionFloors.get(i)??0,e));let o=this.activeHistoryStore;if(!o?.writeDocumentVersion)return Promise.resolve();let s=i?this.runtimeVersionFloors.get(i)??e:e;return this.versionPersistence=this.versionPersistence.then(()=>o.writeDocumentVersion(s)).catch(()=>{}),this.versionPersistence}handleFileChanged(e){this.handleFilesChanged([e])}handleFilesChanged(e){for(let i of e)this.pendingChangedFiles.add(i);this.fileChangeTimer&&clearTimeout(this.fileChangeTimer);let 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 e=[...this.pendingChangedFiles].sort((n,i)=>n.localeCompare(i));if(this.pendingChangedFiles.clear(),e.some(et)&&this.scheduleSnapshotIdentityAdvance(),!!this.refreshCompositions(!1))for(let n of e)this.runtime?.notifyFileChanged(n)}scheduleSnapshotIdentityAdvance(){if(this.stopping||!this.isStarted)return;let e=this.readCurrentSnapshotMarker();!e||e===this.options.snapshotId||this.mutationQueue.run(()=>this.advanceSnapshotId(e)).catch(n=>{console.warn(`[vcp-site-edit] snapshot identity advance failed: ${n instanceof Error?n.message:String(n)}`)})}readCurrentSnapshotMarker(){try{let e=_.readFileSync(m.join(this.options.projectRoot,j),"utf8"),n=JSON.parse(e),i=typeof n.snapshot_id=="string"?n.snapshot_id:"";return!i||q(i)!==i?(console.warn("[vcp-site-edit] current-snapshot marker has no valid snapshot_id"),null):i}catch(e){return console.warn(`[vcp-site-edit] current-snapshot marker unreadable: ${e instanceof Error?e.message:String(e)}`),null}}async advanceSnapshotId(e){if(this.stopping||!this.isStarted||e===this.options.snapshotId)return;let n=this.options.snapshotId;this.options.snapshotId=e;try{if(this.options.historyRoot){let o=await this.bindHistorySession(e);if(!o.ok)throw new Error(`${o.code}: ${o.message}`)}else this.createRuntime()}catch(o){this.options.snapshotId=n,console.warn(`[vcp-site-edit] snapshot identity advance rolled back to ${n}: ${o instanceof Error?o.message:String(o)}`);return}let i=new Date().toISOString();for(let o of this.compositions){let s={type:"site-edit.snapshot.changed",siteId:this.options.siteId,composition:o.context,snapshotId:e,previousSnapshotId:n,at:i};for(let r of this.eventListeners)try{r(s)}catch(a){console.warn(`[vcp-site-edit] snapshot.changed listener failed: ${a instanceof Error?a.message:String(a)}`)}}try{this.options.onSnapshotIdChanged?.(e,n)}catch(o){console.warn(`[vcp-site-edit] onSnapshotIdChanged callback failed: ${o instanceof Error?o.message:String(o)}`)}}refreshCompositions(e=!1){try{let n=Ue(this.options.projectRoot),i=Ae(n),o=i.length>0?i:(this.options.runtime.routes??[]).map(u=>({...u})),s=Te({files:n});if(s.length===0)throw new Error("No canonical App Router composition is indexed by the preview bridge.");let r=JSON.stringify(s.filter(u=>u.context.effectiveTemplateId!==void 0).map(u=>u.entryFile).sort());if(e&&(this.launchCandidateEntries=r),this.launchCandidateEntries!==r)throw new Error("SITE_EDIT_RUNTIME_RELOAD_REQUIRED: Candidate route collection changed since preview launch");let a=new Map(this.compositions.map(u=>[C(u.context),u])),p=new Map(s.map(u=>[C(u.context),u]));if(this.runtime){for(let[u,l]of a){let S=p.get(u);(!S||S.entryFile!==l.entryFile)&&this.runtime.unregisterComposition(y(l.context))}for(let[u,l]of p){let S=a.get(u);(!S||S.entryFile!==l.entryFile)&&this.runtime.registerComposition(l.context,l.entryFile)}}return this.routes=o,this.compositions=s,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,e)throw i;return this.notifyHealthChanged(),!1}}resolveComposition(e){if(this.compositionResolutionError)throw this.compositionResolutionError;let n=Oe(e.routeId,this.routes,this.options.basePath);if(!n)throw new Error(`Route is not indexed by the preview bridge: ${e.routeId}`);let i=this.routes.find(r=>r.routeId===n);if(!i)throw new Error(`Route is not indexed by the preview bridge: ${e.routeId}`);let o=_e({selector:{routeId:n,...e.templateId!==void 0?{templateId:e.templateId}:{}},files:this.compositionFiles,canonicalEntryFile:i.entryFile}),s=C(o.context);if(!this.compositions.some(r=>C(r.context)===s))throw new Error(`Composition is not registered by the preview bridge: ${s}`);return o}getInitialDocumentVersions(){return this.compositions.flatMap(e=>{let n=this.runtimeVersionFloors.get(C(e.context));return n===void 0?[]:[{composition:e.context,version:n}]})}getRuntime(){if(!this.runtime)throw new Error("VCP site edit preview bridge runtime is not ready");return this.runtime}};function ce(t){let e=new $(Pe(t),oe.createServer(),!1);return e.start({listen:!1,webSocket:!1}),{engine:e.getEngine(),getHealth:()=>e.getHealth(),stop:()=>e.stop()}}function Pe(t){return{tenantId:t.tenantId,siteId:t.siteId,snapshotId:t.snapshotId,projectRoot:m.resolve(t.projectRoot??process.cwd()),basePath:t.basePath??"",host:t.host??De,port:t.port??Ne,path:t.path??Ke,sessionKey:t.sessionKey??Xe(),historyRoot:t.historyRoot,allowedOrigins:t.allowedOrigins??[],runtime:t.runtime??{},onSnapshotIdChanged:t.onSnapshotIdChanged,onHealthChanged:t.onHealthChanged}}function Ve(t){let e=["app","src/app","components/site","src/components/site","lib/generated","src/lib/generated","public"];return[...new Set([...t?.length?t:e,".vcp"])]}function Ue(t){let e=[],n=["app","src/app",".vcp"],i=new Set([".git",".next",".turbo","coverage","dist","node_modules","output","snapshot-store"]),o=s=>{if(!_.existsSync(s))return;let r;try{r=_.readdirSync(s,{withFileTypes:!0})}catch{return}for(let a of r){if(a.name.startsWith(".")&&a.name!==".vcp")continue;if(a.isDirectory()){if(i.has(a.name))continue;o(m.join(s,a.name));continue}if(!a.isFile())continue;let p=m.join(s,a.name),u="";try{u=_.readFileSync(p,"utf8")}catch{}e.push({path:m.relative(t,p).replaceAll(m.sep,"/"),content:u})}};for(let s of n)o(m.join(t,s));return e.sort((s,r)=>s.path.localeCompare(r.path))}function We(t){if(!t||typeof t!="object"||typeof t.routeId!="string")throw new Error("Normalized composition context is required.");if("effectiveTemplateId"in t)return t;let e=t;return{routeId:e.routeId,...e.templateId?{effectiveTemplateId:e.templateId}:{}}}function y(t){return{routeId:t.routeId,...t.effectiveTemplateId?{templateId:t.effectiveTemplateId}:{}}}function je(t){return m.join(m.resolve(t.root),q(t.siteId),q(t.snapshotId),J("sha256").update(t.editingSessionId).digest("hex").slice(0,32))}function q(t){return/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(t)&&t!=="."&&t!==".."?t:J("sha256").update(t).digest("hex").slice(0,32)}function $e(){let t=globalThis;return t[ne]??=new Map,t[ne]}function qe(t){return`${t.projectRoot}:${t.host}:${t.port}:${t.path}:${t.historyRoot??""}`}function U(t,e,n){let i=n??(e?.composition?{routeId:e.composition.routeId,...e.composition.templateId?{effectiveTemplateId:e.composition.templateId}:{}}:void 0);if(!i)throw new Error("A normalized composition is required to construct a mutation result.");return{ok:!1,composition:i,error:{code:t.code,message:t.message},data:{requestId:e?.id??"mutation-context",kind:e?.kind??"update-text",composition:i,target:e?.target??{kind:"node",key:""},resultVersion:e?.documentVersion??0}}}function ze(t){let e=new be({maxPayload:ae,noServer:!0}),n=new WeakSet,i=s=>{new A({socket:new z(s),engine:t.engine,validateOperationRequest:r=>Me.safeParse(r).success})},o=(s,r,a)=>{if(!Le(s,t))return;let p=Je(s,t);if(!p){r.write(`HTTP/1.1 401 Unauthorized\r
|
|
1
|
+
import{parentPort as tt,workerData as nt}from"node:worker_threads";function H(t){let e=t&&typeof t=="object"?t:null,n=typeof e?.message=="string"&&e.message.length>0?e.message:String(t);return{name:typeof e?.name=="string"?e.name:"Error",message:n,...typeof e?.code=="string"&&e.code.length>0?{code:e.code}:{}}}import oe from"node:http";import _ from"node:fs";import{createHash as J,randomBytes as Re,timingSafeEqual as be}from"node:crypto";import m from"node:path";import{WebSocket as re,WebSocketServer as xe}from"ws";import{createPreviewSiteEditEngineRuntime as ke,openFileHistoryStore as ve,resolveManagedPageTemplateComposition as _e,scanSiteEditCompositionsFromFiles as Te}from"@vcp-dev/site-edit-engine";import{resolveNextAppRouteId as Oe,scanNextAppRouterRoutesFromFiles as Ae}from"@vcp-dev/site-edit-engine/next-app-router";import{SiteEditSourceWatcher as Me}from"@vcp-dev/site-edit-engine/source-watcher";function Y(t){let e=new Map,n=[],i=new Map,o=[],s=t.pageComposition.status==="supported"?t.pageComposition.placementUnitKeys:[],r=new Map(s.map((c,p)=>[c,p])),a=t.pageComposition.status==="supported"?{status:"supported",containerKey:t.pageComposition.containerKey,hasBusinessMembers:t.pageComposition.hasBusinessMembers,placementUnitKeys:t.pageComposition.placementUnitKeys,placements:t.pageComposition.placements.map(c=>({placementKey:c.placementKey,placementUnitKey:c.placementUnitKey,relation:c.relation}))}:{status:"unsupported",reason:t.pageComposition.reason,diagnostics:t.pageComposition.diagnostics},h=t.entries.flatMap((c,p)=>c.dynamicDataSummary?[[p,c.dynamicDataSummary]]:[]),d=new Map(t.entries.map((c,p)=>[c.key,p])),l=[];for(let[c,p]of t.entries.entries()){let g=p.pageCompositionActionScope;if(!g)continue;if(g.kind!=="source-siblings"){l.push([c,{kind:g.kind}]);continue}let O=g.siblingKeys.map(x=>{let k=d.get(x);if(k===void 0)throw new Error("Render entry "+p.key+" references missing source sibling "+x);return k});l.push([c,{kind:"source-siblings",siblingEntryIndexes:O}])}let S=c=>{let p=e.get(c);if(typeof p=="number")return p;let g=n.length;return n.push(c),e.set(c,g),g},Q=c=>{let p=null;for(let g of pe(c)){let O=`${p??"root"}\0${g}`,x=i.get(O);if(typeof x=="number"){p=x;continue}let k=o.length;o.push([p,S(g)]),i.set(O,k),p=k}if(p===null)throw new Error("Document key must not be empty");return p};return{encoding:"segment-trie-v1",siteId:t.siteId,snapshotId:t.snapshotId,composition:{...t.composition},routeId:t.composition.routeId,version:t.version,pageComposition:a,tokens:n,nodes:o,entries:t.entries.map(c=>{let p=c.pageCompositionUnitKey?r.get(c.pageCompositionUnitKey)??-1:-1;if(c.pageCompositionUnitKey&&p<0)throw new Error(`Render entry ${c.key} references unknown page composition unit ${c.pageCompositionUnitKey}`);return[Q(c.key),he(c.operationSummary),...p>=0?[p]:[]]}),...l.length>0?{pageCompositionActionScopes:l}:{},...t.entries.every(c=>c.parentKey!==void 0)?{entryParentNodeIds:t.entries.map(c=>c.parentKey===null?null:Q(c.parentKey))}:{},...h.length>0?{dynamicDataSummaries:h}:{}}}function he(t){return(t.canUpdateText?1:0)|(t.canInsertChild?2:0)|(t.canMove?4:0)|(t.canRemove?8:0)}function pe(t){if(!t)return[];let e=[],n=0,i=G(t,n);if(i<0)return e.push(t),e;for(e.push(t.slice(0,i)),n=i;n<t.length;){if(i=G(t,n+(t.startsWith("::",n)?2:1)),i<0){e.push(t.slice(n));break}e.push(t.slice(n,i)),n=i}return e}function G(t,e){let n=t.indexOf("/",e),i=t.indexOf("::",e);return n<0?i:i<0?n:Math.min(n,i)}var Z="SITE_EDIT_COMPOSITION_SESSION_MISMATCH",P="SITE_EDIT_COMPOSITION_SESSION_REQUIRED";var f=class t{constructor(){}static parseMessage(e,n={}){let i=JSON.parse(e);if(!t.isMessage(i,n))throw new Error("Invalid site edit bridge message");return i}static stringifyMessage(e){return JSON.stringify(e)}static extractRequestInfo(e){if(u(e)&&u(e.payload)){let n=typeof e.payload.id=="string"?e.payload.id:"unknown",i=this.isRequestKind(e.payload.kind)?e.payload.kind:"get-document";return{id:n,kind:i}}return{id:"unknown",kind:"get-document"}}static isRequestKind(e){return e==="initialize-session"||e==="get-document"||e==="get-history-status"||e==="get-style-context"||e==="get-object-edit-context"||e==="get-class-name-source"||e==="get-source-tree"||e==="get-source-file"||e==="resolve-source-location"||e==="execute"||e==="get-operation-result"||e==="undo"||e==="redo"}static isMessage(e,n={}){return!u(e)||typeof e.type!="string"?!1:e.type==="request"?fe(e.payload,n):e.type==="response"||e.type==="error"?u(e.payload)&&typeof e.payload.id=="string":e.type==="event"?u(e.payload)&&u(e.payload.event):e.type==="auth"?u(e.payload)&&typeof e.payload.key=="string":e.type==="ping"||e.type==="pong"?u(e.payload)&&typeof e.payload.id=="string":e.type==="auth-ok"&&u(e.payload)&&e.payload.ok===!0}},A=class{constructor(e){this.options=e,this.session={subscribedCompositionKeys:new Set},this.messageQueue=new B,this.eventDispatcher=new V(n=>{this.sendJson(n)}),this.unsubscribe=e.engine.subscribe(n=>{this.handleEngineEvent(n)}),e.socket.onmessage=n=>{let i=ge(n.data);if(i!==null){this.sendJson({type:"pong",payload:{id:i}});return}try{this.messageQueue.enqueue(()=>this.handleRawMessage(n.data))}catch(o){this.sendJson({type:"error",payload:{id:"unknown",kind:"get-document",message:o instanceof Error?o.message:"Bridge queue overflow"}}),e.socket.close(1013,"bridge busy")}},e.socket.onclose=()=>{this.unsubscribe(),this.session.activeComposition=void 0,this.session.subscribedCompositionKeys.clear()}}async handleMessage(e){try{let n=e;if(n.type!=="request")return;let i=n.payload,{id:o}=i;switch(i.kind){case"initialize-session":{let s=D(i),r=await this.resolve(s),a=await this.options.engine.initializeSession({composition:r.context,...i.mutationContext?{mutationContext:i.mutationContext}:{}});this.activateSession(r.context),this.sendJson({type:"response",payload:{id:o,kind:i.kind,result:I({...a,data:{...a.data,document:ee(a.data.document)}},r.context)}});return}case"get-document":{let s=await this.resolveWireContext(i),r=await this.options.engine.getDocument(s);this.sendResult(o,i.kind,Ce(r,s));return}case"get-history-status":{let s=await this.resolveWireContext(i),r=await this.options.engine.getHistoryStatus(s);this.sendResult(o,i.kind,I(r,s));return}case"get-style-context":{let s=await this.resolveWireContext(i);this.sendResult(o,i.kind,I(await this.options.engine.getStyleContext(s),s));return}case"get-object-edit-context":{let s=await this.resolveWireContext(i);this.sendResult(o,i.kind,I(await this.options.engine.getObjectEditContext(i.key,s,i.selectionRef),s));return}case"get-class-name-source":{let s=await this.resolveWireContext(i);this.sendResult(o,i.kind,I(await this.options.engine.getClassNameSource(i.key,s),s));return}case"get-source-tree":{let s=await this.resolveWireContext(i);this.sendResult(o,i.kind,I(await this.options.engine.getSourceTree(s),s));return}case"get-source-file":{let s=await this.resolveWireContext(i);this.sendResult(o,i.kind,I(await this.options.engine.getSourceFile({path:i.path,composition:s}),s));return}case"resolve-source-location":{let s=await this.resolveWireContext(i),r=I(await this.options.engine.resolveSourceLocation({key:i.key,composition:s}),s);this.sendResult(o,i.kind,r);return}case"execute":case"get-operation-result":{let s=await this.resolveOperationWireContext(i.request),r=await this.resolveWireContext(i);if(w(s)!==w(r))throw new C(Z,"The execute request composition does not match its operation composition.");let a=await this.normalizeOperationRequest(i.request,s);if(i.kind==="get-operation-result"){this.sendResult(o,i.kind,await this.options.engine.getOperationResult?.(a)??null);return}await this.handleBufferedOperation(o,i.kind,()=>this.options.engine.execute(a));return}case"undo":case"redo":{let s=await this.resolveWireContext(i);await this.handleBufferedOperation(o,i.kind,()=>i.kind==="undo"?this.options.engine.undo(s):this.options.engine.redo(s));return}}}catch(n){let i=f.extractRequestInfo(e);this.sendJson({type:"error",payload:{...i,message:F(n),code:K(n)}})}}async resolve(e){return this.options.engine.resolveComposition(e)}async resolveAndAssert(e){let n=await this.resolve(e),i=this.session.activeComposition;if(!i)throw new C(P,"Initialize a composition session before issuing this request.");if(w(i)!==w(n.context))throw new C(Z,"The request composition does not match the active socket session.");return n.context}async resolveWireContext(e){let n=D(e);return this.resolveAndAssert(n)}async resolveOperationWireContext(e){let n=Se(e);return this.resolveAndAssert(n)}activateSession(e){this.session.activeComposition=e,this.session.subscribedCompositionKeys.clear(),this.session.subscribedCompositionKeys.add(w(e))}async normalizeOperationRequest(e,n){let i={...e,composition:X(n)};if(i.target.kind==="route"){let o=i.target,s=D(o),r=await this.resolveAndAssert(s);i.target={...o,composition:X(r)}}return i}handleEngineEvent(e){let n=e?.composition;if(!Ie(n))return;let i=w(n);this.session.subscribedCompositionKeys.has(i)&&(this.eventDispatcher.push(e),e.type==="site-edit.graph.invalidated"&&i===we(this.session)&&(this.session.activeComposition=void 0,this.session.subscribedCompositionKeys.delete(i)))}sendResult(e,n,i){this.sendJson({type:"response",payload:{id:e,kind:n,result:i}})}async handleRawMessage(e){try{await this.handleMessage(f.parseMessage(e,{validateOperationRequest:this.options.validateOperationRequest}))}catch(n){let i=Ee(e);this.sendJson({type:"error",payload:{...i,message:F(n),code:K(n)}})}}sendJson(e){this.options.socket.send(f.stringifyMessage(e))}async handleBufferedOperation(e,n,i){this.eventDispatcher.beginBuffering();try{let o=await i();this.sendResult(e,n,o)}catch(o){this.sendJson({type:"error",payload:{id:e,kind:n,message:F(o),code:K(o)}})}finally{this.eventDispatcher.flush()}}},le=256;function ge(t){if(t.length>le||!t.includes('"ping"'))return null;try{let e=JSON.parse(t);return u(e)&&e.type==="ping"&&u(e.payload)&&typeof e.payload.id=="string"?e.payload.id:null}catch{return null}}var C=class extends Error{constructor(e,n){super(n),this.code=e,this.name="BridgeProtocolError"}},V=class{constructor(e){this.send=e,this.bufferedEvents=null}push(e){let n={type:"event",payload:{event:e}};if(this.bufferedEvents){this.bufferedEvents.push(n);return}this.send(n)}beginBuffering(){this.bufferedEvents=[]}flush(){let e=this.bufferedEvents??[];this.bufferedEvents=null,e.forEach(n=>this.send(n))}},B=class{constructor(e=64){this.maxQueued=e,this.queue=Promise.resolve(),this.queued=0}enqueue(e){if(this.queued>=this.maxQueued)throw new Error("Bridge request queue is full");this.queued+=1;let n=async()=>{this.queued-=1,await e()},i=this.queue.then(n,n);return this.queue=i.then(()=>{},()=>{}),i}};function fe(t,e){if(!u(t)||typeof t.id!="string"||!f.isRequestKind(t.kind))return!1;let n=v(t.composition);switch(t.kind){case"initialize-session":return n&&(t.mutationContext===void 0||N(t.mutationContext));case"get-document":case"get-style-context":return n;case"get-object-edit-context":return typeof t.key=="string"&&n&&me(t.selectionRef);case"get-class-name-source":case"resolve-source-location":return typeof t.key=="string"&&n;case"get-history-status":return n;case"get-source-tree":return n;case"get-source-file":return typeof t.path=="string"&&n;case"execute":case"get-operation-result":return n&&ye(t.request)&&(t.request.mutationContext===void 0||N(t.request.mutationContext))&&(e.validateOperationRequest?.(t.request)??!0);case"undo":case"redo":return n&&t.mutationContext===void 0||n&&N(t.mutationContext)}}function me(t){if(t===void 0)return!0;if(!u(t)||typeof t.key!="string"||t.key.length===0)return!1;let e=t.instanceIndex,n=t.instanceCount;return e!==void 0&&(typeof e!="number"||!Number.isInteger(e)||e<0)||n!==void 0&&(typeof n!="number"||!Number.isInteger(n)||n<=0)||typeof e=="number"&&typeof n=="number"&&e>=n?!1:Object.keys(t).every(i=>i==="key"||i==="instanceIndex"||i==="instanceCount")}function ye(t){return u(t)&&typeof t.id=="string"&&typeof t.siteId=="string"&&typeof t.baseSnapshotId=="string"&&v(t.composition)&&typeof t.kind=="string"&&u(t.target)&&(t.target.kind!=="route"||v(t.target.composition))&&typeof t.documentVersion=="number"&&Number.isInteger(t.documentVersion)&&t.documentVersion>=0&&u(t.params)}function v(t){return u(t)&&typeof t.routeId=="string"&&t.routeId.length>0&&(t.templateId===void 0||typeof t.templateId=="string"&&t.templateId.length>0)&&Object.keys(t).every(e=>e==="routeId"||e==="templateId")}function Ie(t){return u(t)&&typeof t.routeId=="string"&&(t.effectiveTemplateId===void 0||typeof t.effectiveTemplateId=="string")}function D(t){if(v(t.composition))return t.composition;throw new C(P,"A composition selector is required for this request.")}function Se(t){if(u(t)&&v(t.composition))return t.composition;throw new C(P,"A composition selector is required for execute.")}function X(t){return{routeId:t.routeId,...t.effectiveTemplateId?{templateId:t.effectiveTemplateId}:{}}}function we(t){return t.activeComposition?w(t.activeComposition):null}function w(t){return JSON.stringify([t.routeId,t.effectiveTemplateId??null])}function I(t,e){return u(t)&&t.ok===!0?{...t,composition:e}:t}function Ce(t,e){return!u(t)||t.ok!==!0?t:{...t,...e?{composition:e}:{},data:ee(t.data)}}function ee(t){let e=t;return Y(e.routeId?e:{...e,routeId:e.composition.routeId})}function u(t){return typeof t=="object"&&t!==null}function N(t){return u(t)&&typeof t.editingSessionId=="string"&&t.editingSessionId.length>0&&typeof t.lockId=="string"&&t.lockId.length>0&&typeof t.ownerId=="string"&&t.ownerId.length>0&&typeof t.leaseAssertion=="string"&&t.leaseAssertion.length>0}function K(t){if(!(!u(t)||typeof t.code!="string"||t.code.length===0))return t.code}function F(t){return t instanceof Error||u(t)&&typeof t.message=="string"&&t.message.length>0?t.message:"Unknown websocket operation failure"}function Ee(t){try{return f.extractRequestInfo(JSON.parse(t))}catch{return{id:"unknown",kind:"get-document"}}}var M=class{constructor(){this.tail=Promise.resolve()}run(e){let n=this.tail.then(e,e);return this.tail=n.then(()=>{},()=>{}),n}};import{SiteEditOperationRequestSchema as He,computeSiteEditCompositionKey as E}from"@vcp-dev/contracts";var De="127.0.0.1",Ne=30218,Ke="/__vcp/site-edit/bridge",ae=6*1024*1024,Fe=ae*2,Ve=3e3,te=50,q=".vcp/current-snapshot.json",ne="__VCP_SITE_EDIT_BRIDGE_SERVERS__";var j=class{constructor(e,n=oe.createServer((s,r)=>{r.writeHead(404),r.end("VCP site edit bridge server")}),i=!0,o={}){this.options=e,this.server=n,this.closeHttpServerOnStop=i,this.dependencies=o,this.runtime=null,this.activeHistorySessionId=null,this.historySessionTransition=Promise.resolve(),this.mutationQueue=new M,this.operationReceipts=new Map,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.versionCheckpoints=new WeakMap,this.bridgeEngine=null,this.lastNotifiedHealth=null}start(e={}){if(!this.isStarted){this.stopping=!1;try{_.mkdirSync(m.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(),e.webSocket!==!1){let n=ze({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 Me({projectRoot:this.options.projectRoot,watch_dirs:Pe(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(),e.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 e=!!this.runtime&&!this.compositionResolutionError;return{ok:this.isStarted&&e,bridgePath:this.options.path,runtimeReady:e,routesIndexed:this.routes.length,sessionRequired:!!this.options.sessionKey}}stop(){this.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 e=je(),n=$e(this.options);e.get(n)===this&&e.delete(n),this.isStarted=!1,this.notifyHealthChanged()}notifyHealthChanged(){let e=this.options.onHealthChanged;if(!e)return;let n=this.getHealth(),i=JSON.stringify(n);if(i!==this.lastNotifiedHealth){this.lastNotifiedHealth=i;try{e(n)}catch(o){console.warn(`[vcp-site-edit] onHealthChanged callback failed: ${o instanceof Error?o.message:String(o)}`)}}}createRuntime(e,n=null){let i=this.runtime;this.activeHistoryStore=e??null;let o=(this.dependencies.createRuntime??ke)({...this.options.tenantId?{tenantId:this.options.tenantId}:{},siteId:this.options.siteId,snapshotId:this.options.snapshotId,projectRoot:this.options.projectRoot,compositions:this.compositions,onEvent:s=>{"version"in s&&typeof s.version=="number"&&this.recordRuntimeVersion(s.version,"composition"in s?s.composition:void 0);for(let r of this.eventListeners)r(s)},...e?{historyStore:e}:{},...this.getInitialDocumentVersions().length>0?{initialDocumentVersions:this.getInitialDocumentVersions()}:{}});this.runtime=o,this.activeHistorySessionId=n,i?.dispose(),this.notifyHealthChanged()}createBridgeEngine(){return{resolveComposition:e=>this.resolveComposition(e),initializeSession:e=>this.mutationQueue.run(async()=>{let n=await this.bindHistorySession(this.options.snapshotId);if(!n.ok)throw new Error(`${n.code}: ${n.message}`);let i=Ue(e.composition),o=this.getRuntime(),s=y(i);await o.initializeComposition(s);let a=o.getDocument(s).data;await this.recordRuntimeVersion(a.version,i);let h=(await o.getHistoryStatus()).data;return{ok:!0,composition:i,data:{document:a,historyStatus:h}}}),getDocument:async e=>{let n=this.getRuntime(),i=y(e);await n.initializeComposition(i);let o=n.getDocument(i);return await this.recordRuntimeVersion(o.data.version,e),{...o,composition:e}},getHistoryStatus:async e=>({...await this.getRuntime().getHistoryStatus(),composition:e}),getStyleContext:async e=>this.getRuntime().getStyleContext(y(e)),getObjectEditContext:async(e,n,i)=>this.getRuntime().getObjectEditContext(e,y(n),i),getClassNameSource:async(e,n)=>this.getRuntime().getClassNameSource(e,y(n)),getSourceTree:async e=>this.getRuntime().getSourceTree(y(e)),getSourceFile:async e=>this.getRuntime().getSourceFile({path:e.path,composition:y(e.composition)}),resolveSourceLocation:async e=>this.getRuntime().resolveSourceLocation({key:e.key,composition:y(e.composition)}),execute:(e,n)=>this.executeWithReceipt(e,()=>this.mutationQueue.run(async()=>{let i=await this.bindHistorySession(this.options.snapshotId);if(!i.ok)return W(i,e);let o=await this.getRuntime().executeOperation(e);return o.data?.resultVersion!==void 0&&await this.recordRuntimeVersion(o.data.resultVersion,o.composition),o})),getOperationResult:e=>{if(e.siteId!==this.options.siteId||e.baseSnapshotId!==this.options.snapshotId)return null;let n=this.operationReceipts.get(this.operationReceiptKey(e));return n?.fingerprint===this.operationFingerprint(e)?n.result:null},undo:e=>this.mutationQueue.run(async()=>{let n=await this.bindHistorySession(this.options.snapshotId);if(!n.ok)return W(n,void 0,e);let i=await this.getRuntime().undo();return i.data?.resultVersion!==void 0&&await this.recordRuntimeVersion(i.data.resultVersion,i.composition??e),i.composition?i:{...i,composition:e}}),redo:e=>this.mutationQueue.run(async()=>{let n=await this.bindHistorySession(this.options.snapshotId);if(!n.ok)return W(n,void 0,e);let i=await this.getRuntime().redo();return i.data?.resultVersion!==void 0&&await this.recordRuntimeVersion(i.data.resultVersion,i.composition??e),i.composition?i:{...i,composition:e}}),subscribe:e=>(this.eventListeners.add(e),()=>this.eventListeners.delete(e))}}operationReceiptKey(e){return JSON.stringify([e.siteId,e.baseSnapshotId,e.id])}operationFingerprint(e){return J("sha256").update(JSON.stringify(e)).digest("hex")}executeWithReceipt(e,n){if(e.siteId!==this.options.siteId||e.baseSnapshotId!==this.options.snapshotId)return n();let i=this.operationReceiptKey(e),o=this.operationFingerprint(e),s=this.operationReceipts.get(i);if(s)return s.fingerprint!==o?Promise.reject(new Error("Operation ID was reused with a different request.")):s.result;let r={fingerprint:o,result:n(),settled:!1};return this.operationReceipts.set(i,r),r.result.then(()=>{r.settled=!0;for(let[a,h]of this.operationReceipts){if(this.operationReceipts.size<=256)break;h.settled&&this.operationReceipts.delete(a)}},()=>{this.operationReceipts.delete(i)}),r.result}async bindHistorySession(e){if(!this.options.historyRoot)return{ok:!1,code:"RECOVERY_PERSIST_FAILED",message:"Durable edit history is not configured."};if(this.activeHistorySessionId===e)return{ok:!0};let n=this.historySessionTransition.then(async()=>{if(this.activeHistorySessionId===e)return;let i=await(this.dependencies.openHistoryStore??ve)(qe({root:this.options.historyRoot,siteId:this.options.siteId,snapshotId:this.options.snapshotId,editingSessionId:e}));if(!this.isStarted)return;let o=i.readDocumentVersion?await i.readDocumentVersion():0,s=this.versionCheckpoints.get(i);s?s.durableVersion=Math.max(s.durableVersion,o):this.versionCheckpoints.set(i,{durableVersion:o,requestedVersion:o,pending:null});let r=this.compositions[0]?.context;if(r){let a=E(r);this.runtimeVersionFloors.set(a,Math.max(this.runtimeVersionFloors.get(a)??0,o))}this.createRuntime(i,e)});this.historySessionTransition=n.catch(()=>{});try{return await n,{ok:!0}}catch{return{ok:!1,code:"RECOVERY_PERSIST_FAILED",message:"Durable edit history could not be opened."}}}recordRuntimeVersion(e,n){let i=n?E(n):null;i&&this.runtimeVersionFloors.set(i,Math.max(this.runtimeVersionFloors.get(i)??0,e));let o=this.activeHistoryStore;if(!o?.writeDocumentVersion)return Promise.resolve();let s=i?this.runtimeVersionFloors.get(i)??e:e,r=this.versionCheckpoints.get(o);if(r||(r={durableVersion:0,requestedVersion:0,pending:null},this.versionCheckpoints.set(o,r)),s<=r.durableVersion)return Promise.resolve();if(r.requestedVersion=Math.max(r.requestedVersion,s),r.pending)return r.pending;let a=r,h=this.versionPersistence.then(async()=>{try{for(;a.requestedVersion>a.durableVersion;){let d=a.requestedVersion;await o.writeDocumentVersion(d),a.durableVersion=Math.max(a.durableVersion,d)}}catch{console.warn("[vcp-site-edit] document version checkpoint persistence failed")}finally{a.pending=null}});return a.pending=h,this.versionPersistence=h,h}handleFileChanged(e){this.handleFilesChanged([e])}handleFilesChanged(e){for(let i of e)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 e=[...this.pendingChangedFiles].sort((n,i)=>n.localeCompare(i));if(this.pendingChangedFiles.clear(),e.some(et)&&this.scheduleSnapshotIdentityAdvance(),!!this.refreshCompositions(!1))for(let n of e)this.runtime?.notifyFileChanged(n)}scheduleSnapshotIdentityAdvance(){if(this.stopping||!this.isStarted)return;let e=this.readCurrentSnapshotMarker();!e||e===this.options.snapshotId||this.mutationQueue.run(()=>this.advanceSnapshotId(e)).catch(n=>{console.warn(`[vcp-site-edit] snapshot identity advance failed: ${n instanceof Error?n.message:String(n)}`)})}readCurrentSnapshotMarker(){try{let e=_.readFileSync(m.join(this.options.projectRoot,q),"utf8"),n=JSON.parse(e),i=typeof n.snapshot_id=="string"?n.snapshot_id:"";return!i||$(i)!==i?(console.warn("[vcp-site-edit] current-snapshot marker has no valid snapshot_id"),null):i}catch(e){return console.warn(`[vcp-site-edit] current-snapshot marker unreadable: ${e instanceof Error?e.message:String(e)}`),null}}async advanceSnapshotId(e){if(this.stopping||!this.isStarted||e===this.options.snapshotId)return;let n=this.options.snapshotId;this.options.snapshotId=e;try{if(this.options.historyRoot){let o=await this.bindHistorySession(e);if(!o.ok)throw new Error(`${o.code}: ${o.message}`)}else this.createRuntime()}catch(o){this.options.snapshotId=n,console.warn(`[vcp-site-edit] snapshot identity advance rolled back to ${n}: ${o instanceof Error?o.message:String(o)}`);return}let i=new Date().toISOString();for(let o of this.compositions){let s={type:"site-edit.snapshot.changed",siteId:this.options.siteId,composition:o.context,snapshotId:e,previousSnapshotId:n,at:i};for(let r of this.eventListeners)try{r(s)}catch(a){console.warn(`[vcp-site-edit] snapshot.changed listener failed: ${a instanceof Error?a.message:String(a)}`)}}try{this.options.onSnapshotIdChanged?.(e,n)}catch(o){console.warn(`[vcp-site-edit] onSnapshotIdChanged callback failed: ${o instanceof Error?o.message:String(o)}`)}}refreshCompositions(e=!1){try{let n=We(this.options.projectRoot),i=Ae(n),o=i.length>0?i:(this.options.runtime.routes??[]).map(d=>({...d})),s=Te({files:n});if(s.length===0)throw new Error("No canonical App Router composition is indexed by the preview bridge.");let r=JSON.stringify(s.filter(d=>d.context.effectiveTemplateId!==void 0).map(d=>d.entryFile).sort());if(e&&(this.launchCandidateEntries=r),this.launchCandidateEntries!==r)throw new Error("SITE_EDIT_RUNTIME_RELOAD_REQUIRED: Candidate route collection changed since preview launch");let a=new Map(this.compositions.map(d=>[E(d.context),d])),h=new Map(s.map(d=>[E(d.context),d]));if(this.runtime){for(let[d,l]of a){let S=h.get(d);(!S||S.entryFile!==l.entryFile)&&this.runtime.unregisterComposition(y(l.context))}for(let[d,l]of h){let S=a.get(d);(!S||S.entryFile!==l.entryFile)&&this.runtime.registerComposition(l.context,l.entryFile)}}return this.routes=o,this.compositions=s,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,e)throw i;return this.notifyHealthChanged(),!1}}resolveComposition(e){if(this.compositionResolutionError)throw this.compositionResolutionError;let n=Oe(e.routeId,this.routes,this.options.basePath);if(!n)throw new Error(`Route is not indexed by the preview bridge: ${e.routeId}`);let i=this.routes.find(r=>r.routeId===n);if(!i)throw new Error(`Route is not indexed by the preview bridge: ${e.routeId}`);let o=_e({selector:{routeId:n,...e.templateId!==void 0?{templateId:e.templateId}:{}},files:this.compositionFiles,canonicalEntryFile:i.entryFile}),s=E(o.context);if(!this.compositions.some(r=>E(r.context)===s))throw new Error(`Composition is not registered by the preview bridge: ${s}`);return o}getInitialDocumentVersions(){return this.compositions.flatMap(e=>{let n=this.runtimeVersionFloors.get(E(e.context));return n===void 0?[]:[{composition:e.context,version:n}]})}getRuntime(){if(!this.runtime)throw new Error("VCP site edit preview bridge runtime is not ready");return this.runtime}};function ce(t){let e=new j(Be(t),oe.createServer(),!1);return e.start({listen:!1,webSocket:!1}),{engine:e.getEngine(),getHealth:()=>e.getHealth(),stop:()=>e.stop()}}function Be(t){return{tenantId:t.tenantId,siteId:t.siteId,snapshotId:t.snapshotId,projectRoot:m.resolve(t.projectRoot??process.cwd()),basePath:t.basePath??"",host:t.host??De,port:t.port??Ne,path:t.path??Ke,sessionKey:t.sessionKey??Xe(),historyRoot:t.historyRoot,allowedOrigins:t.allowedOrigins??[],runtime:t.runtime??{},onSnapshotIdChanged:t.onSnapshotIdChanged,onHealthChanged:t.onHealthChanged}}function Pe(t){let e=["app","src/app","components/site","src/components/site","lib/generated","src/lib/generated","public"];return[...new Set([...t?.length?t:e,".vcp"])]}function We(t){let e=[],n=["app","src/app",".vcp"],i=new Set([".git",".next",".turbo","coverage","dist","node_modules","output","snapshot-store"]),o=s=>{if(!_.existsSync(s))return;let r;try{r=_.readdirSync(s,{withFileTypes:!0})}catch{return}for(let a of r){if(a.name.startsWith(".")&&a.name!==".vcp")continue;if(a.isDirectory()){if(i.has(a.name))continue;o(m.join(s,a.name));continue}if(!a.isFile())continue;let h=m.join(s,a.name),d="";try{d=_.readFileSync(h,"utf8")}catch{}e.push({path:m.relative(t,h).replaceAll(m.sep,"/"),content:d})}};for(let s of n)o(m.join(t,s));return e.sort((s,r)=>s.path.localeCompare(r.path))}function Ue(t){if(!t||typeof t!="object"||typeof t.routeId!="string")throw new Error("Normalized composition context is required.");if("effectiveTemplateId"in t)return t;let e=t;return{routeId:e.routeId,...e.templateId?{effectiveTemplateId:e.templateId}:{}}}function y(t){return{routeId:t.routeId,...t.effectiveTemplateId?{templateId:t.effectiveTemplateId}:{}}}function qe(t){return m.join(m.resolve(t.root),$(t.siteId),$(t.snapshotId),J("sha256").update(t.editingSessionId).digest("hex").slice(0,32))}function $(t){return/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(t)&&t!=="."&&t!==".."?t:J("sha256").update(t).digest("hex").slice(0,32)}function je(){let t=globalThis;return t[ne]??=new Map,t[ne]}function $e(t){return`${t.projectRoot}:${t.host}:${t.port}:${t.path}:${t.historyRoot??""}`}function W(t,e,n){let i=n??(e?.composition?{routeId:e.composition.routeId,...e.composition.templateId?{effectiveTemplateId:e.composition.templateId}:{}}:void 0);if(!i)throw new Error("A normalized composition is required to construct a mutation result.");return{ok:!1,composition:i,error:{code:t.code,message:t.message},data:{requestId:e?.id??"mutation-context",kind:e?.kind??"update-text",composition:i,target:e?.target??{kind:"node",key:""},resultVersion:e?.documentVersion??0}}}function ze(t){let e=new xe({maxPayload:ae,noServer:!0}),n=new WeakSet,i=s=>{new A({socket:new z(s),engine:t.engine,validateOperationRequest:r=>He.safeParse(r).success})},o=(s,r,a)=>{if(!Le(s,t))return;let h=Je(s,t);if(!h){r.write(`HTTP/1.1 401 Unauthorized\r
|
|
2
2
|
Connection: close\r
|
|
3
3
|
\r
|
|
4
|
-
`),r.destroy();return}
|
|
4
|
+
`),r.destroy();return}h.authenticatedByHeader&&n.add(s),e.handleUpgrade(s,r,a,d=>{e.emit("connection",d,s)})};return t.server.on("upgrade",o),e.on("connection",(s,r)=>{if(n.has(r)){i(s);return}Qe(s,t.sessionKey,()=>{i(s)})}),e.stop=()=>{t.server.off("upgrade",o);for(let s of e.clients)s.close(1001,"bridge stopped");e.close()},e}var z=class{constructor(e){this.socket=e,this.onmessage=null,this.onclose=null,e.on("error",()=>{}),e.on("message",n=>{this.onmessage?.({data:n.toString()})}),e.on("close",()=>{this.onclose?.()})}send(e){if(this.socket.readyState===re.OPEN){if(this.socket.bufferedAmount+Buffer.byteLength(e,"utf8")>Fe){this.socket.close(1013,"bridge backpressure");return}this.socket.send(e)}}close(e,n){this.socket.close(e,n)}};function Le(t,e){return new URL(t.url??"/","http://localhost").pathname===e.path}function Je(t,e){if(new URL(t.url??"/","http://localhost").searchParams.has("vcp_bridge_key"))return null;let i=U(t.headers["x-vcp-site-edit-key"]),o=de(i,e.sessionKey),s=U(t.headers.host),r=U(t.headers.origin);return s&&!Ge(s,e.host,r)?null:r?Ze(r,s,e.allowedOrigins)?{authenticatedByHeader:o}:null:o?{authenticatedByHeader:!0}:null}function Qe(t,e,n){let i=setTimeout(()=>{t.close(1008,"bridge authentication timeout")},Ve),o,s=()=>{clearTimeout(i),t.off("message",o),t.off("close",s)},r=()=>{s(),t.close(1008,"bridge authentication failed")};o=a=>{try{let h=f.parseMessage(a.toString());if(h.type!=="auth"||!de(h.payload.key,e)){r();return}s(),t.readyState===re.OPEN&&t.send(f.stringifyMessage({type:"auth-ok",payload:{ok:!0}})),n()}catch{r()}},t.on("message",o),t.on("close",s)}function de(t,e){if(!t)return!1;let n=Buffer.from(t),i=Buffer.from(e);return n.length===i.length&&be(n,i)}function Ge(t,e,n){let i=se(t),o=se(e);return i===o||ie(o)&&ie(i)&&(!n||L(n,t))||Ye(o)&&(!n||L(n,t))}function Ye(t){return t==="0.0.0.0"||t==="::"}function ie(t){return t==="localhost"||t==="127.0.0.1"||t==="::1"}function Ze(t,e,n){return n.includes(t)||(e?L(t,e):!1)}function L(t,e){try{return new URL(t).host===ue(e)}catch{return!1}}function se(t){let e=ue(t);return e.startsWith("[")?e.slice(1,e.indexOf("]")):e.split(":").length-1===1?e.split(":",1)[0]??"":e}function ue(t){return t.trim().toLowerCase()}function U(t){return Array.isArray(t)?t[0]:t}function Xe(){return Re(32).toString("base64url")}function et(t){let e=t.replaceAll("\\","/");return e===q||e.endsWith(`/${q}`)}var b=tt;if(!b)throw new Error("site edit engine worker must run inside worker_threads");var R=t=>{b.postMessage(t)},it=(t,e)=>{try{b.postMessage({type:"result",id:t,ok:!0,value:e})}catch(n){if(n instanceof Error&&n.name==="DataCloneError"){b.postMessage({type:"result",id:t,ok:!0,value:e===void 0?void 0:JSON.parse(JSON.stringify(e))});return}throw n}},{options:st}=nt,T;try{T=ce({...st,onSnapshotIdChanged:(t,e)=>{R({type:"snapshot-id-changed",next:t,previous:e})},onHealthChanged:t=>{R({type:"health",health:t})}})}catch(t){R({type:"start-failed",error:H(t)}),process.exit(1)}T.engine.subscribe(t=>{R({type:"event",event:t})});var ot=async t=>{try{let e=T.engine[t.method],n=await e(...t.args);it(t.id,n)}catch(e){R({type:"result",id:t.id,ok:!1,error:H(e)})}};b.on("message",t=>{if(t.type==="call"){ot(t);return}t.type==="stop"&&(T.stop(),b.close())});R({type:"ready",health:T.getHealth()});
|