@djvlc/runtime-core 1.1.1 → 1.1.2

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/index.cjs CHANGED
@@ -1 +1 @@
1
- var t=require("@djvlc/contracts-types"),e=class extends Error{constructor(e,s,i,n){super(s||t.ErrorMessages[e]||"Unknown error"),this.name="DjvlcRuntimeError",this.code=e,this.details=i,this.traceId=n,this.timestamp=Date.now()}toJSON(){return{name:this.name,code:this.code,message:this.message,details:this.details,traceId:this.traceId,timestamp:this.timestamp}}},s=class extends e{constructor(e,s,i){super(t.ErrorCode.RESOURCE_PAGE_NOT_FOUND,e,s,i),this.name="PageLoadError"}},i=class extends e{constructor(e,s,i,n=t.ErrorCode.COMPONENT_LOAD_FAILED,r){super(n,i,{...r,componentName:e,componentVersion:s}),this.name="ComponentLoadError",this.componentName=e,this.componentVersion=s}},n=class extends e{constructor(e,s,i,n){super(t.ErrorCode.COMPONENT_INTEGRITY_MISMATCH,`Integrity check failed for ${e}@${s}`,{expectedHash:i,actualHash:n}),this.name="IntegrityError",this.componentName=e,this.componentVersion=s,this.expectedHash=i,this.actualHash=n}},r=class extends e{constructor(e,s,i){super(t.ErrorCode.COMPONENT_BLOCKED,`Component ${e}@${s} is blocked`,{componentName:e,componentVersion:s,reason:i}),this.name="ComponentBlockedError",this.componentName=e,this.componentVersion=s,this.reason=i}},o=class extends e{constructor(e,s,i,n){super(t.ErrorCode.VALIDATION_EXPRESSION_ERROR,s,{...n,expression:e,position:i}),this.name="ExpressionError",this.expression=e,this.position=i}},a=class extends e{constructor(e,s,i=t.ErrorCode.SYSTEM_INTERNAL_ERROR,n,r){super(i,s,{...r,actionType:e,actionId:n}),this.name="ActionError",this.actionType=e,this.actionId=n}},c=class extends e{constructor(e,s,i=t.ErrorCode.SYSTEM_INTERNAL_ERROR,n){super(i,s,{...n,queryId:e}),this.name="QueryError",this.queryId=e}},h=class{constructor(t){this.cache=new Map,this.options={env:"prod",cache:{enabled:!0,maxAge:300},...t}}async resolve(t,e){const i=this.getCacheKey(t,e);if(this.options.cache?.enabled){const e=this.cache.get(i);if(e&&this.isCacheValid(e.timestamp))return this.log("debug",`Page ${t} loaded from cache`),e.data}const n=performance.now();try{const s=await this.callResolveViaAdapter(t,e),r=await this.loadFromCdn(s,t);this.options.cache?.enabled&&this.cache.set(i,{data:r,timestamp:Date.now()});const o=performance.now()-n;return this.log("info",`Page ${t} resolved in ${o.toFixed(2)}ms`),r}catch(e){if(e instanceof s)throw e;throw new s(`Failed to resolve page: ${e instanceof Error?e.message:"Unknown error"}`,{pageId:t})}}async callResolveViaAdapter(t,e){const i=await this.options.userApiAdapter.resolvePage({pageId:t,uid:e?.uid,deviceId:e?.deviceId,env:this.options.env,channel:this.options.channel,previewToken:this.options.previewToken});if(!this.isValidPageResolveResponse(i))throw new s("Invalid page resolve response",{pageId:t});return i}async loadFromCdn(t,e){try{const i=await fetch(t.snapshotUrl,{headers:this.buildHeaders()});if(!i.ok)throw new s(`Failed to load snapshot: ${i.status}`,{pageId:e});const n=await i.json();return this.convertSnapshotToResult(n,t,e)}catch(t){if(t instanceof s)throw t;throw new s(`Failed to load from CDN: ${t instanceof Error?t.message:"Unknown error"}`,{pageId:e})}}convertSnapshotToResult(t,e,s){const i=this.convertSnapshotPageToPageSchema(t.page),n=this.convertSnapshotManifestToPageManifest(t.manifest),r=t.definitionsDigest?.actions?.map(t=>t.versionId)||[],o=t.definitionsDigest?.queries?.map(t=>t.versionId)||[];return n.actionDefinitionVersionIds=r,n.dataQueryVersionIds=o,{pageId:e.pageId,pageVersionId:e.resolvedVersionId,pageJson:i,manifest:n,runtimeConfig:{blockedComponents:e.ops.blockedComponents.map(t=>({name:t.name,version:t.version||"",reason:t.reason})),killSwitches:e.ops.killSwitch.map(t=>({type:t.targetType,enabled:t.enabled})),features:e.ops.flags},isPreview:"preview"===this.options.env||!!this.options.previewToken}}convertSnapshotPageToPageSchema(t){const e={layout:{canvasType:t.config.canvasType,canvasSize:t.config.canvasSize},styles:t.config.background||t.config.cssVariables?{background:t.config.background,cssVariables:t.config.cssVariables}:void 0},s=Object.keys(t.initialState).length>0?{fields:Object.keys(t.initialState).reduce((e,s)=>{const i=t.initialState[s];let n="string";return"number"==typeof i?n="number":"boolean"==typeof i?n="boolean":Array.isArray(i)?n="array":null!==i&&"object"==typeof i&&(n="object"),e[s]={type:n,initialValue:i},e},{})}:void 0,i={title:t.title};return{schemaVersion:t.schemaVersion,pageId:t.pageId,pageVersion:t.pageVersion,runtime:{name:"djvlc-runtime",version:"1.0.0"},meta:i,config:e,seo:t.seo,state:s,dataBindings:t.bindings,root:t.root}}convertSnapshotManifestToPageManifest(t){return{id:"",pageVersionId:"",manifestVersion:"1.0.0",createdAt:(new Date).toISOString(),contentHash:"",components:t.components.map(t=>({componentId:"",name:t.name,version:t.version,entry:`${t.assetsUrl}/${t.entrypoints.js}`,styleEntry:t.entrypoints.css?`${t.assetsUrl}/${t.entrypoints.css}`:void 0,integrity:t.integrity,preload:t.preload,priority:t.priority})),actionDefinitionVersionIds:[],dataQueryVersionIds:[],runtimeVersion:{min:t.runtime.minVersion,recommended:t.runtime.version}}}isValidPageResolveResponse(t){if(!t||"object"!=typeof t)return!1;const e=t;return"string"==typeof e.pageId&&"string"==typeof e.resolvedVersionId&&"string"==typeof e.cdnBase&&"string"==typeof e.snapshotUrl&&"string"==typeof e.manifestUrl&&void 0!==e.ops&&"string"==typeof e.etag&&"number"==typeof e.cacheTtlSeconds}preconnect(){const t=document.createElement("link");t.rel="preconnect",t.href=this.options.apiBaseUrl,document.head.appendChild(t)}clearCache(t){if(t)for(const e of this.cache.keys())e.startsWith(t)&&this.cache.delete(e);else this.cache.clear()}buildHeaders(){return{"Content-Type":"application/json",...this.options.headers}}getCacheKey(t,e){const s=[t,this.options.env,this.options.channel];return e?.uid&&s.push(e.uid),e?.deviceId&&s.push(e.deviceId),s.filter(Boolean).join(":")}isCacheValid(t){const e=1e3*(this.options.cache?.maxAge??300);return Date.now()-t<e}log(t,e){this.options.logger&&this.options.logger[t](e)}},l={sha256:"SHA-256",sha384:"SHA-384",sha512:"SHA-512"},u=class{constructor(t){this.loadedComponents=new Map,this.loadingPromises=new Map,this.options={enableSRI:!0,concurrency:4,timeout:3e4,blockedComponents:[],...t},this.blockedSet=new Set(this.options.blockedComponents)}async load(t){const e=this.getComponentKey(t.name,t.version);if(this.isBlocked(t.name,t.version))throw new r(t.name,t.version,"Component is blocked");const s=this.loadedComponents.get(e);if(s)return s;const i=this.loadingPromises.get(e);if(i)return i;const n=this.loadComponent(t);this.loadingPromises.set(e,n);try{const t=await n;return this.loadedComponents.set(e,t),t}finally{this.loadingPromises.delete(e)}}async loadAll(t){const e=new Map,{concurrency:s=4}=this.options,i=t.components;for(let t=0;t<i.length;t+=s){const n=i.slice(t,t+s).map(async t=>{const s=this.getComponentKey(t.name,t.version),i=performance.now();try{const n=await this.load(t);e.set(s,{name:t.name,version:t.version,status:"loaded",component:n.Component,loadTime:performance.now()-i})}catch(n){const o=n instanceof r?"blocked":"failed";if(e.set(s,{name:t.name,version:t.version,status:o,error:n instanceof Error?n.message:"Unknown error",loadTime:performance.now()-i}),"critical"===t.priority)throw n}});await Promise.all(n)}return e}preload(t){t.forEach(t=>{const e=document.createElement("link");e.rel="preload",e.as="script",e.href=this.resolveUrl(t.entry),this.options.enableSRI&&t.integrity&&(e.integrity=t.integrity,e.crossOrigin="anonymous"),document.head.appendChild(e)})}isLoaded(t,e){return this.loadedComponents.has(this.getComponentKey(t,e))}get(t,e){return this.loadedComponents.get(this.getComponentKey(t,e))}isBlocked(t,e){return this.blockedSet.has(`${t}@${e}`)||this.blockedSet.has(t)}updateBlockedList(t){this.blockedSet=new Set(t)}async loadComponent(t){const e=performance.now(),s=this.resolveUrl(t.entry);this.log("debug",`Loading component ${t.name}@${t.version}`);try{const n=await this.fetchWithTimeout(s);if(!n.ok)throw new i(t.name,t.version,`Failed to fetch component: ${n.status} ${n.statusText}`);const r=await n.text();this.options.enableSRI&&t.integrity&&await this.validateIntegrity(t,r);const o=await this.executeScript(r,t),a=performance.now()-e;return this.log("info",`Component ${t.name}@${t.version} loaded in ${a.toFixed(2)}ms`),{name:t.name,version:t.version,Component:o,loadTime:a}}catch(e){if(e instanceof i||e instanceof n||e instanceof r)throw e;throw new i(t.name,t.version,`Failed to load component: ${e instanceof Error?e.message:"Unknown error"}`)}}async fetchWithTimeout(t){const e=new AbortController,s=setTimeout(()=>e.abort(),this.options.timeout),i={signal:e.signal,credentials:"omit",headers:this.options.headers?{...this.options.headers}:void 0},n=this.options.fetchComponentScript??fetch;try{return await n(t,i)}finally{clearTimeout(s)}}async validateIntegrity(t,e){if(!t.integrity)return;const[s,i]=t.integrity.split("-");if(!s||!i)throw new n(t.name,t.version,t.integrity,"Invalid format");const r=l[s.toLowerCase()];if(!r)throw new n(t.name,t.version,t.integrity,`Unsupported SRI algorithm: ${s}, expected sha256/sha384/sha512`);const o=await crypto.subtle.digest(r,(new TextEncoder).encode(e)),a=Array.from(new Uint8Array(o)),c=btoa(String.fromCharCode(...a));if(c!==i)throw new n(t.name,t.version,i,c)}async executeScript(t,e){const s=new Blob([t],{type:"application/javascript"}),n=URL.createObjectURL(s);try{const t=await import(n),s=t.default??t[e.name]??t[this.kebabToPascal(e.name)]??t.Component;if(!s)throw new i(e.name,e.version,"Component module does not export a valid component (expected default or Component)");return s}finally{URL.revokeObjectURL(n)}}kebabToPascal(t){return t.split("-").map(t=>t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()).join("")}resolveUrl(t){return t.startsWith("http://")||t.startsWith("https://")?t:`${this.options.cdnBaseUrl}/${t.replace(/^\//,"")}`}getComponentKey(t,e){return`${t}@${e}`}log(t,e){this.options.logger&&this.options.logger[t](e)}},d=class{constructor(t){this.preconnectedHosts=new Set,this.preloadedAssets=new Set,this.options=t}preconnectAll(){[...this.options.cdnHosts,...this.options.apiHosts].forEach(t=>this.preconnect(t))}preconnect(t){if(this.preconnectedHosts.has(t))return;const e=document.createElement("link");e.rel="preconnect",e.href=t.startsWith("http")?t:`https://${t}`,e.crossOrigin="anonymous",document.head.appendChild(e),this.preconnectedHosts.add(t)}dnsPrefetch(t){const e=document.createElement("link");e.rel="dns-prefetch",e.href=t.startsWith("http")?t:`https://${t}`,document.head.appendChild(e)}preloadScript(t,e){if(this.preloadedAssets.has(t))return;const s=document.createElement("link");s.rel="preload",s.setAttribute("as","script"),s.href=t,e&&(s.setAttribute("integrity",e),s.setAttribute("crossorigin","anonymous")),document.head.appendChild(s),this.preloadedAssets.add(t)}preloadStyle(t,e){if(this.preloadedAssets.has(t))return;const s=document.createElement("link");s.rel="preload",s.setAttribute("as","style"),s.href=t,e&&(s.setAttribute("integrity",e),s.setAttribute("crossorigin","anonymous")),document.head.appendChild(s),this.preloadedAssets.add(t)}preloadImage(t){if(this.preloadedAssets.has(t))return;const e=document.createElement("link");e.rel="preload",e.setAttribute("as","image"),e.href=t,document.head.appendChild(e),this.preloadedAssets.add(t)}prefetch(t,e){const s=document.createElement("link");s.rel="prefetch",s.href=t,e&&s.setAttribute("as",e),document.head.appendChild(s)}loadStylesheet(t,e){return new Promise((s,i)=>{const n=document.createElement("link");n.rel="stylesheet",n.href=t,e&&(n.integrity=e,n.crossOrigin="anonymous"),n.onload=()=>s(),n.onerror=()=>i(new Error(`Failed to load stylesheet: ${t}`)),document.head.appendChild(n)})}loadScript(t,e){return new Promise((s,i)=>{const n=document.createElement("script");n.src=t,n.async=!0,e&&(n.integrity=e,n.crossOrigin="anonymous"),n.onload=()=>s(),n.onerror=()=>i(new Error(`Failed to load script: ${t}`)),document.body.appendChild(n)})}},p=class{constructor(){this.listeners=new Set,this.changeCallbacks=new Set,this.state=this.createInitialState()}getState(){return this.state}getPhase(){return this.state.phase}setPhase(t){this.setState({phase:t})}setPage(t){const e=t.pageJson,s=this.initializePageState(e);t.preloadedData&&Object.assign(s,t.preloadedData),this.setState({page:t,variables:s})}initializePageState(t){const e={};if(t.state&&t.state.fields)for(const[s,i]of Object.entries(t.state.fields))if(i&&"object"==typeof i){const t=i;e[s]=t.initialValue}return e}setError(t){this.setState({phase:"error",error:t})}clearError(){this.state.error&&this.setState({error:null})}getVariable(t){return t.includes(".")?this.getNestedValue(this.state.variables,t):this.state.variables[t]}setVariable(t,e){const s=this.getVariable(t);if(t.includes(".")){const s={...this.state.variables};this.setNestedValue(s,t,e),this.setState({variables:s})}else this.setState({variables:{...this.state.variables,[t]:e}});this.notifyChange({key:t,oldValue:s,newValue:e})}setVariables(t){const e=[];for(const[s,i]of Object.entries(t)){const t=this.getVariable(s);e.push({key:s,oldValue:t,newValue:i})}this.setState({variables:{...this.state.variables,...t}}),e.forEach(t=>this.notifyChange(t))}getQuery(t){return this.state.queries[t]}setQuery(t,e){this.setState({queries:{...this.state.queries,[t]:e}})}clearQuery(t){const{[t]:e,...s}=this.state.queries;this.setState({queries:s})}setComponentStatus(t,e){const s=new Map(this.state.components);s.set(t,e),this.setState({components:s})}getComponentStatus(t){return this.state.components.get(t)}setDestroyed(){this.setState({phase:"destroyed",destroyed:!0})}isDestroyed(){return this.state.destroyed}subscribe(t){return this.listeners.add(t),()=>{this.listeners.delete(t)}}onStateChange(t){return this.changeCallbacks.add(t),()=>{this.changeCallbacks.delete(t)}}reset(){this.state=this.createInitialState(),this.notifyListeners()}getExpressionContext(){return{state:this.state.variables,binding:this.state.queries,local:{},context:{pageVersionId:this.state.page?.pageVersionId,pageId:this.state.page?.pageId,phase:this.state.phase,$now:Date.now()}}}setState(t){this.state={...this.state,...t},this.notifyListeners()}notifyListeners(){this.listeners.forEach(t=>{try{t(this.state)}catch(t){}})}notifyChange(t){this.changeCallbacks.forEach(e=>{try{e(t)}catch(t){}})}getNestedValue(t,e){const s=e.split(".");let i=t;for(const t of s){if(null==i)return;i=i[t]}return i}setNestedValue(t,e,s){const i=e.split(".");let n=t;for(let t=0;t<i.length-1;t++){const e=i[t];void 0!==n[e]&&null!==n[e]||(n[e]={}),n=n[e]}n[i[i.length-1]]=s}createInitialState(){return{phase:"idle",page:null,variables:{},queries:{},components:new Map,error:null,destroyed:!1}}},f=class{constructor(t){this.bindings=new Map,this.dependencyGraph=new Map,this.bindingDependencies=new Map,this.options=t}registerBindings(t){for(const e of t)this.registerBinding(e)}registerBinding(t){if(this.bindings.set(t.id,{binding:t,loading:!1,retryCount:0}),t.dependencies)for(const e of t.dependencies)this.dependencyGraph.has(e)||this.dependencyGraph.set(e,new Set),this.dependencyGraph.get(e).add(t.id);this.updateBindingDependencies(t),this.log("debug",`Registered data binding: ${t.id}`)}updateBindingDependencies(t){for(const[e,s]of this.bindings){if(e===t.id)continue;const i=s.binding;i.dependencies?.includes(t.targetState)&&(this.bindingDependencies.has(t.id)||this.bindingDependencies.set(t.id,new Set),this.bindingDependencies.get(t.id).add(e))}if(t.dependencies)for(const e of t.dependencies)for(const[s,i]of this.bindings)s!==t.id&&i.binding.targetState===e&&(this.bindingDependencies.has(s)||this.bindingDependencies.set(s,new Set),this.bindingDependencies.get(s).add(t.id))}async initializeBindings(t){const e=[];for(const t of this.bindings.values())"eager"===t.binding.loadStrategy&&e.push(t.binding);const s=this.topologicalSort(e),i=this.createLoadBatches(s);for(const e of i){const s=await Promise.allSettled(e.map(e=>this.loadBinding(e.id,t))),i=new Map;s.forEach((t,s)=>{const n=e[s].id;"fulfilled"===t.status?i.set(n,{success:!0,data:t.value}):i.set(n,{success:!1,error:t.reason})}),this.options.onBatchComplete?.(i)}}topologicalSort(t){const e=new Map(t.map(t=>[t.id,t])),s=new Set,i=[],n=t=>{if(!s.has(t.id)){if(s.add(t.id),t.dependencies)for(const i of t.dependencies)for(const[t,r]of e)r.targetState!==i||s.has(t)||n(r);i.push(t)}};for(const e of t)n(e);return i}createLoadBatches(t){const e=[],s=new Set;for(;s.size<t.length;){const i=[];for(const e of t){if(s.has(e.id))continue;let n=!0;if(e.dependencies)for(const i of e.dependencies){for(const e of t)if(e.targetState===i&&!s.has(e.id)){n=!1;break}if(!n)break}n&&i.push(e)}if(0===i.length)for(const e of t)if(!s.has(e.id)){i.push(e),this.log("warn",`Possible circular dependency detected at binding: ${e.id}`);break}i.forEach(t=>s.add(t.id)),i.length>0&&e.push(i)}return e}async loadBinding(t,e,s=!1){const i=this.bindings.get(t);if(!i)throw new c(t,`Data binding not found: ${t}`);const{binding:n}=i;if(!n.condition||this.evaluateCondition(n.condition,e)){if(!s&&this.isCacheValid(i))return this.log("debug",`Binding ${t} returned from cache`),i.cachedData;if(i.loading)this.log("debug",`Binding ${t} is already loading`);else{i.loading=!0;try{const s=this.resolveParams(n.params||{},e),r=await this.executeWithRetry(n,s),o=n.transform?this.applyTransform(r,n.transform,e):r;return i.cachedData=o,i.lastLoadTime=Date.now(),n.cache?.ttl&&(i.cacheExpireTime=Date.now()+1e3*n.cache.ttl),i.retryCount=0,this.options.stateSetter.setVariable(n.targetState,o),this.setupAutoRefresh(i,e),this.options.onDataLoaded?.(t,o),this.log("info",`Binding ${t} loaded successfully`),o}catch(t){throw await this.handleLoadError(i,t,e),t}finally{i.loading=!1}}}else this.log("debug",`Binding ${t} skipped by condition`)}async refreshBinding(t,e){await this.loadBinding(t,e,!0)}async refreshAll(t){const e=Array.from(this.bindings.keys()).map(e=>this.loadBinding(e,t,!0));await Promise.allSettled(e)}async onStateChange(t,e){const s=this.dependencyGraph.get(t);if(!s||0===s.size)return;this.log("debug",`State ${t} changed, refreshing dependent bindings`);const i=Array.from(s).map(t=>this.loadBinding(t,e,!0));await Promise.allSettled(i)}async triggerManualLoad(t,e){const s=this.bindings.get(t);if(!s)throw new c(t,`Data binding not found: ${t}`);return"manual"!==s.binding.loadStrategy&&this.log("warn",`Binding ${t} is not manual strategy`),this.loadBinding(t,e,!0)}checkVisibility(t,e,s){const i=this.bindings.get(t);i&&"lazy"===i.binding.loadStrategy&&e&&!i.lastLoadTime&&this.loadBinding(t,s).catch(e=>{this.log("error",`Lazy binding ${t} failed to load`,e)})}destroy(){for(const t of this.bindings.values())t.refreshTimer&&clearInterval(t.refreshTimer);this.bindings.clear(),this.dependencyGraph.clear(),this.log("debug","DataBindingManager destroyed")}async executeWithRetry(t,e){const s=t.onError?.retry?.maxRetries??0,i=t.onError?.retry?.backoffMs??1e3,n=t.onError?.retry?.backoff??"fixed";let r;for(let o=0;o<=s;o++)try{const s=await this.options.requester.requestData(t.queryVersionId,e);if(!s.success)throw new c(t.queryVersionId,s.message||"Query failed",void 0,{params:e});return s.data}catch(t){if(r=t,this.log("warn",`Query attempt ${o+1}/${s+1} failed:`,t),o<s){const t="exponential"===n?i*Math.pow(2,o):i;await this.delay(t)}}throw r||new Error("Query failed after all retries")}async handleLoadError(t,e,s){const{binding:i}=t,n=i.onError;t.retryCount++,void 0!==n?.fallbackValue&&this.options.stateSetter.setVariable(i.targetState,n.fallbackValue),n?.showError&&this.options.onDataError?.(i.id,e),this.log("error",`Binding ${i.id} load failed:`,e)}setupAutoRefresh(t,e){t.refreshTimer&&(clearInterval(t.refreshTimer),t.refreshTimer=void 0);const s=t.binding.refreshInterval;!s||s<=0||(t.refreshTimer=setInterval(()=>{this.loadBinding(t.binding.id,e,!0).catch(e=>{this.log("error",`Auto refresh for ${t.binding.id} failed:`,e)})},1e3*s))}isCacheValid(t){return!(!t.cachedData||!t.lastLoadTime||t.cacheExpireTime&&Date.now()>t.cacheExpireTime)}resolveParams(t,e){const s={};for(const[i,n]of Object.entries(t))s[i]=this.resolveValue(n,e);return s}resolveValue(t,e){if(null==t)return t;if("object"==typeof t&&!Array.isArray(t)){const s=t;if("expression"===s.type||"binding"===s.type)return this.options.expressionEngine.evaluateWithFallback(s.expression,e,s.fallback);const i={};for(const[t,n]of Object.entries(s))i[t]=this.resolveValue(n,e);return i}return"string"==typeof t&&t.includes("${")?this.options.expressionEngine.evaluateTemplate(t,e):t}evaluateCondition(t,e){const s=void 0===t.fallback||t.fallback,i=this.options.expressionEngine.evaluateWithFallback(t.value,e,s);return Boolean(i)}applyTransform(t,e,s){const i={...s,local:{...s.local||{},$data:t,$response:t}},n=void 0!==e.fallback?e.fallback:t;return this.options.expressionEngine.evaluateWithFallback(e.value,i,n)}delay(t){return new Promise(e=>setTimeout(e,t))}log(t,e,...s){this.options.logger?this.options.logger[t](e,...s):this.options.debug}},m=class{constructor(t={}){this.handlers=new Map,this.options={debug:!1,maxListeners:100,...t}}emit(t){this.options.debug&&this.log("debug",`Event emitted: ${t.type}`,t);const e=this.handlers.get(t.type);e&&e.forEach(e=>{try{e(t)}catch(e){this.log("error",`Error in event handler for ${t.type}:`,e)}})}on(t,e){let s=this.handlers.get(t);return s||(s=new Set,this.handlers.set(t,s)),s.size>=(this.options.maxListeners??100)&&this.log("warn",`Max listeners (${this.options.maxListeners}) reached for event: ${t}`),s.add(e),()=>{s?.delete(e),0===s?.size&&this.handlers.delete(t)}}off(t,e){const s=this.handlers.get(t);s&&(s.delete(e),0===s.size&&this.handlers.delete(t))}once(t,e){const s=this.on(t,t=>{s(),e(t)});return s}clear(t){t?this.handlers.delete(t):this.handlers.clear()}listenerCount(t){return this.handlers.get(t)?.size??0}static createEvent(t,e,s){return{type:t,data:e,timestamp:Date.now(),traceId:s}}log(t,e,...s){this.options.logger?this.options.logger[t](e,...s):this.options.debug}},g=class t{constructor(t){this.debounceTimers=new Map,this.throttleTimers=new Map,this.options=t}async handleEvent(t,e,s){if(t.condition&&!this.evaluateCondition(t.condition,s,e))return void this.log("debug",`Handler ${t.id} skipped by condition`);if(t.throttle&&t.throttle>0&&!this.throttle(t.id,t.throttle))return void this.log("debug",`Handler ${t.id} throttled`);t.debounce&&t.debounce>0&&await this.debounce(t.id,t.debounce);const i={$event:e,$prevResult:void 0,$results:{}};await this.executeActionChain(t.actions,s,i)}async executeActionChain(t,e,s){const i=[];for(let n=0;n<t.length;n++){const r=t[n];if(r.condition){const t=this.buildActionContext(e,s);if(!this.evaluateCondition(r.condition,t,s.$event)){this.log("debug",`Action ${r.id||n} skipped by condition`);continue}}const o=this.executeSingleAction(r,e,s);r.async?i.push(o):await o}i.length>0&&await Promise.allSettled(i)}async executeSingleAction(t,e,s){const i=t.id||t.alias||t.builtinAction||t.actionDefinitionVersionId||"unknown";t.silent||this.options.executor.showLoading();try{const n=this.buildActionContext(e,s),r=this.resolveParams(t.params||{},n);this.options.onActionStart?.(t,r);const o=await this.executeWithRetry(t,r);s.$prevResult=o,t.id&&(s.$results[t.id]=o),this.options.onActionComplete?.(t,{success:!0,data:o}),this.log("debug",`Action ${i} completed successfully`),t.onSuccess&&t.onSuccess.length>0&&await this.executeActionChain(t.onSuccess,e,s)}catch(n){this.log("error",`Action ${i} failed:`,n),this.options.onActionComplete?.(t,{success:!1,error:n}),t.onError&&t.onError.length>0&&await this.executeActionChain(t.onError,e,{...s,$prevResult:{error:n.message}})}finally{t.silent||this.options.executor.hideLoading(),t.onFinally&&t.onFinally.length>0&&await this.executeActionChain(t.onFinally,e,s)}}async executeWithRetry(t,e){const s=t.policy?.retry?.maxAttempts??1,i=t.policy?.retry?.backoffMs??1e3,n=t.policy?.timeoutMs;let r;for(let o=1;o<=s;o++)try{let s;if(t.builtinAction)s=this.executeBuiltinAction(t.builtinAction,e);else{if(!t.actionDefinitionVersionId)throw new a("unknown","Action must specify builtinAction or actionDefinitionVersionId");s=this.executeCustomAction(t.actionDefinitionVersionId,e)}return n&&(s=this.withTimeout(s,n)),await s}catch(t){r=t,this.log("warn",`Action attempt ${o}/${s} failed:`,t),o<s&&await this.delay(i*o)}throw r||new Error("Action failed after all retries")}async executeBuiltinAction(t,e){switch(t){case"setState":return this.options.executor.setState(e.key,e.value),{success:!0};case"navigate":return this.options.executor.navigate({to:e.to??e.url,type:e.replace?"replace":e.external?"external":"push",params:e.params,query:e.query,newWindow:e.newWindow??e.newTab}),{success:!0};case"openDialog":return await this.options.executor.openDialog({type:e.type,content:e.content,title:e.title});case"closeDialog":return this.options.executor.closeDialog(e.dialogId),{success:!0};case"showToast":return this.options.executor.showToast({message:e.message,type:e.type,duration:e.duration}),{success:!0};case"showLoading":return this.options.executor.showLoading(e.message),{success:!0};case"hideLoading":return this.options.executor.hideLoading(),{success:!0};case"refreshData":return await this.options.executor.refreshData(e.queryId),{success:!0};case"track":return this.options.executor.track({eventName:e.eventName,params:e.params}),{success:!0};default:throw new a(t,`Unknown builtin action: ${t}`)}}async executeCustomAction(t,e){const s=t.split("@")[0],i=await this.options.executor.executeAction(s,{...e,actionDefinitionVersionId:t});if(!i.success)throw new a(s,i.errorMessage||"Action execution failed",void 0,t,{errorCode:i.errorCode});return i.data}resolveParams(t,e){const s={};for(const[i,n]of Object.entries(t))s[i]=this.resolveValue(n,e);return s}resolveValue(e,s){if(null==e)return e;if("string"==typeof e){if(e.startsWith("${")&&e.endsWith("}")){const t=e.slice(2,-1);return this.options.expressionEngine.evaluateWithFallback(t,s,e)}return e.includes("${")?this.options.expressionEngine.evaluateTemplate(e,s):e}if("number"==typeof e||"boolean"==typeof e)return e;if(Array.isArray(e))return e.map(t=>this.resolveValue(t,s));if("object"==typeof e){const i=e;if("string"==typeof i.type&&t.EXPRESSION_TYPES.includes(i.type)&&"string"==typeof i.value){const t=i;return this.options.expressionEngine.evaluateWithFallback(t.value,s,t.fallback)}const n={};for(const[t,e]of Object.entries(i))n[t]=this.resolveValue(e,s);return n}return e}evaluateCondition(t,e,s){const i={...e,local:{...e.local||{},$event:s}},n=void 0===t.fallback||t.fallback,r=this.options.expressionEngine.evaluateWithFallback(t.value,i,n);return Boolean(r)}buildActionContext(t,e){return{...t,local:{...t.local||{},$event:e.$event,$prevResult:e.$prevResult,$results:e.$results}}}withTimeout(t,e){return new Promise((s,i)=>{const n=setTimeout(()=>{i(new Error(`Action timed out after ${e}ms`))},e);t.then(t=>{clearTimeout(n),s(t)}).catch(t=>{clearTimeout(n),i(t)})})}debounce(t,e){return new Promise(s=>{const i=this.debounceTimers.get(t);i&&clearTimeout(i);const n=setTimeout(()=>{this.debounceTimers.delete(t),s()},e);this.debounceTimers.set(t,n)})}throttle(t,e){const s=Date.now();return!(s-(this.throttleTimers.get(t)??0)<e||(this.throttleTimers.set(t,s),0))}delay(t){return new Promise(e=>setTimeout(e,t))}destroy(){this.debounceTimers.forEach(t=>clearTimeout(t)),this.debounceTimers.clear(),this.throttleTimers.clear()}log(t,e,...s){this.options.logger?this.options.logger[t](e,...s):this.options.debug}};g.EXPRESSION_TYPES=["state","binding","local","template","computed"];var y=g,b=class{constructor(t){this.pos=0,this.tokens=[],this.input=t}tokenize(){for(this.pos=0,this.tokens=[];this.pos<this.input.length&&(this.skipWhitespace(),!(this.pos>=this.input.length));){const t=this.readToken();t&&this.tokens.push(t)}return this.tokens.push({type:"EOF",value:null,start:this.input.length,end:this.input.length}),this.tokens}readToken(){const t=this.input[this.pos],e=this.pos;if(this.isDigit(t)||"-"===t&&this.isDigit(this.peek(1)))return this.readNumber();if('"'===t||"'"===t)return this.readString(t);if(this.isIdentifierStart(t))return this.readIdentifier();const s=this.readOperator();if(s)return s;switch(t){case".":return this.pos++,{type:"DOT",value:".",start:e,end:this.pos};case"[":return this.pos++,{type:"LBRACKET",value:"[",start:e,end:this.pos};case"]":return this.pos++,{type:"RBRACKET",value:"]",start:e,end:this.pos};case"(":return this.pos++,{type:"LPAREN",value:"(",start:e,end:this.pos};case")":return this.pos++,{type:"RPAREN",value:")",start:e,end:this.pos};case",":return this.pos++,{type:"COMMA",value:",",start:e,end:this.pos};case"?":return this.pos++,{type:"QUESTION",value:"?",start:e,end:this.pos};case":":return this.pos++,{type:"COLON",value:":",start:e,end:this.pos}}throw new Error(`Unexpected character '${t}' at position ${this.pos}`)}readNumber(){const t=this.pos;let e="";for("-"===this.input[this.pos]&&(e+="-",this.pos++);this.isDigit(this.input[this.pos]);)e+=this.input[this.pos],this.pos++;if("."===this.input[this.pos]&&this.isDigit(this.peek(1)))for(e+=".",this.pos++;this.isDigit(this.input[this.pos]);)e+=this.input[this.pos],this.pos++;return{type:"NUMBER",value:parseFloat(e),start:t,end:this.pos}}readString(t){const e=this.pos;this.pos++;let s="";for(;this.pos<this.input.length&&this.input[this.pos]!==t;){if("\\"===this.input[this.pos]){this.pos++;const t=this.input[this.pos];switch(t){case"n":s+="\n";break;case"t":s+="\t";break;case"r":s+="\r";break;case"\\":s+="\\";break;case'"':s+='"';break;case"'":s+="'";break;default:s+=t}}else s+=this.input[this.pos];this.pos++}if(this.input[this.pos]!==t)throw new Error(`Unterminated string at position ${e}`);return this.pos++,{type:"STRING",value:s,start:e,end:this.pos}}readIdentifier(){const t=this.pos;let e="";for(;this.pos<this.input.length&&this.isIdentifierChar(this.input[this.pos]);)e+=this.input[this.pos],this.pos++;return"true"===e?{type:"BOOLEAN",value:!0,start:t,end:this.pos}:"false"===e?{type:"BOOLEAN",value:!1,start:t,end:this.pos}:"null"===e?{type:"NULL",value:null,start:t,end:this.pos}:{type:"IDENTIFIER",value:e,start:t,end:this.pos}}readOperator(){const t=this.pos,e=this.input.slice(this.pos,this.pos+2),s=this.input[this.pos];return["==","!=",">=","<=","&&","||","??"].includes(e)?(this.pos+=2,{type:"OPERATOR",value:e,start:t,end:this.pos}):["+","-","*","/","%",">","<","!"].includes(s)?(this.pos++,{type:"OPERATOR",value:s,start:t,end:this.pos}):null}skipWhitespace(){for(;this.pos<this.input.length&&/\s/.test(this.input[this.pos]);)this.pos++}isDigit(t){return/[0-9]/.test(t)}isIdentifierStart(t){return/[a-zA-Z_$]/.test(t)}isIdentifierChar(t){return/[a-zA-Z0-9_$]/.test(t)}peek(t=1){return this.input[this.pos+t]||""}},w={len:t=>"string"==typeof t||Array.isArray(t)?t.length:0,trim:t=>String(t??"").trim(),upper:t=>String(t??"").toUpperCase(),lower:t=>String(t??"").toLowerCase(),substr:(t,e,s)=>{const i=String(t??""),n=Number(e)||0,r=void 0!==s?Number(s):void 0;return i.substring(n,void 0!==r?n+r:void 0)},concat:(...t)=>t.map(t=>String(t??"")).join(""),replace:(t,e,s)=>String(t??"").split(String(e)).join(String(s)),split:(t,e)=>String(t??"").split(String(e)),join:(t,e)=>Array.isArray(t)?t.join(void 0!==e?String(e):","):"",startsWith:(t,e)=>String(t??"").startsWith(String(e)),endsWith:(t,e)=>String(t??"").endsWith(String(e)),contains:(t,e)=>String(t??"").includes(String(e)),toNumber:t=>{const e=Number(t);return isNaN(e)?0:e},toString:t=>String(t??""),toInt:t=>Math.trunc(Number(t)||0),toFloat:t=>parseFloat(String(t))||0,round:(t,e)=>{const s=Number(t)||0,i=Number(e)||0,n=Math.pow(10,i);return Math.round(s*n)/n},floor:t=>Math.floor(Number(t)||0),ceil:t=>Math.ceil(Number(t)||0),abs:t=>Math.abs(Number(t)||0),min:(...t)=>{const e=t.map(t=>Number(t)).filter(t=>!isNaN(t));return e.length>0?Math.min(...e):0},max:(...t)=>{const e=t.map(t=>Number(t)).filter(t=>!isNaN(t));return e.length>0?Math.max(...e):0},sum:t=>Array.isArray(t)?t.reduce((t,e)=>t+(Number(e)||0),0):0,avg:t=>Array.isArray(t)&&0!==t.length?t.reduce((t,e)=>t+(Number(e)||0),0)/t.length:0,random:()=>Math.random(),randomInt:(t,e)=>{const s=Math.ceil(Number(t)||0),i=Math.floor(Number(e)||100);return Math.floor(Math.random()*(i-s+1))+s},now:()=>Date.now(),today:()=>(new Date).toISOString().split("T")[0],dateFormat:(t,e)=>{const s=new Date(Number(t)||Date.now()),i=t=>t.toString().padStart(2,"0");return String(e||"YYYY-MM-DD").replace("YYYY",s.getFullYear().toString()).replace("MM",i(s.getMonth()+1)).replace("DD",i(s.getDate())).replace("HH",i(s.getHours())).replace("mm",i(s.getMinutes())).replace("ss",i(s.getSeconds()))},dateParse:t=>new Date(String(t)).getTime(),year:t=>new Date(Number(t)||Date.now()).getFullYear(),month:t=>new Date(Number(t)||Date.now()).getMonth()+1,day:t=>new Date(Number(t)||Date.now()).getDate(),addDays:(t,e)=>{const s=new Date(Number(t)||Date.now());return s.setDate(s.getDate()+(Number(e)||0)),s.getTime()},diffDays:(t,e)=>{const s=new Date(Number(t)||Date.now()),i=new Date(Number(e)||Date.now()),n=Math.abs(i.getTime()-s.getTime());return Math.floor(n/864e5)},isNull:t=>null==t,isUndefined:t=>void 0===t,isEmpty:t=>null==t||("string"==typeof t||Array.isArray(t)?0===t.length:"object"==typeof t&&0===Object.keys(t).length),isArray:t=>Array.isArray(t),isObject:t=>null!==t&&"object"==typeof t&&!Array.isArray(t),isString:t=>"string"==typeof t,isNumber:t=>"number"==typeof t&&!isNaN(t),isBoolean:t=>"boolean"==typeof t,typeOf:t=>null===t?"null":Array.isArray(t)?"array":typeof t,default:(t,e)=>t??e,coalesce:(...t)=>{for(const e of t)if(null!=e)return e;return null},ifElse:(t,e,s)=>t?e:s,first:t=>{if(Array.isArray(t))return t[0]},last:t=>{if(Array.isArray(t))return t[t.length-1]},at:(t,e)=>{if(Array.isArray(t))return t[Number(e)||0]},slice:(t,e,s)=>Array.isArray(t)?t.slice(Number(e)||0,void 0!==s?Number(s):void 0):[],includes:(t,e)=>!!Array.isArray(t)&&t.includes(e),indexOf:(t,e)=>Array.isArray(t)?t.indexOf(e):-1,reverse:t=>Array.isArray(t)?[...t].reverse():[],sort:t=>Array.isArray(t)?[...t].sort():[],unique:t=>Array.isArray(t)?[...new Set(t)]:[],flatten:t=>Array.isArray(t)?t.flat():[],count:t=>Array.isArray(t)?t.length:0,get:(t,e,s)=>{if(null==t)return s;const i=String(e).split(".");let n=t;for(const t of i){if(null==n)return s;n=n[t]}return n??s},keys:t=>"object"!=typeof t||null===t?[]:Object.keys(t),values:t=>"object"!=typeof t||null===t?[]:Object.values(t),entries:t=>"object"!=typeof t||null===t?[]:Object.entries(t),has:(t,e)=>"object"==typeof t&&null!==t&&String(e)in t,merge:(...t)=>{const e={};for(const s of t)"object"==typeof s&&null!==s&&Object.assign(e,s);return e},and:(...t)=>t.every(t=>Boolean(t)),or:(...t)=>t.some(t=>Boolean(t)),not:t=>!t,eq:(t,e)=>t===e,ne:(t,e)=>t!==e,gt:(t,e)=>Number(t)>Number(e),gte:(t,e)=>Number(t)>=Number(e),lt:(t,e)=>Number(t)<Number(e),lte:(t,e)=>Number(t)<=Number(e),between:(t,e,s)=>{const i=Number(t);return i>=Number(e)&&i<=Number(s)},formatNumber:(t,e)=>{const s=Number(t)||0,i=Number(e)??0;return s.toLocaleString(void 0,{minimumFractionDigits:i,maximumFractionDigits:i})},formatCurrency:(t,e)=>{const s=Number(t)||0,i=String(e||"CNY");return s.toLocaleString("zh-CN",{style:"currency",currency:i})},formatPercent:(t,e)=>{const s=Number(t)||0,i=Number(e)??0;return(100*s).toFixed(i)+"%"},currency:(t,e,s)=>{const i=Number(t)||0,n=String(e??"¥"),r=Number(s)??2;return`${n}${i.toLocaleString(void 0,{minimumFractionDigits:r,maximumFractionDigits:r})}`},percent:(t,e)=>{const s=Number(t)||0,i=Number(e)??0;return(100*s).toFixed(i)+"%"},number:(t,e)=>{const s=Number(t)||0,i=Number(e)??0;return s.toLocaleString(void 0,{minimumFractionDigits:i,maximumFractionDigits:i})},pluralize:(t,e,s)=>{const i=Number(t)||0;return`${i} ${String(1===i?e:s)}`},mask:(t,e,s,i)=>{const n=String(t??""),r=Number(e)||3,o=Number(s)||4,a=String(i??"*");if(n.length<=r+o)return n;const c=n.slice(0,r),h=n.slice(-o);return c+a.repeat(n.length-r-o)+h},jsonParse:t=>{try{return JSON.parse(String(t))}catch{return null}},jsonStringify:t=>JSON.stringify(t),toJSON:t=>JSON.stringify(t),fromJSON:t=>{try{return JSON.parse(String(t))}catch{return null}},clamp:(t,e,s)=>{const i=Number(t)||0,n=Number(e)||0,r=Number(s)||100;return Math.min(Math.max(i,n),r)},length:t=>Array.isArray(t)||"string"==typeof t?t.length:0,average:t=>Array.isArray(t)&&0!==t.length?t.reduce((t,e)=>t+(Number(e)||0),0)/t.length:0,dateAdd:(t,e,s)=>{const i=new Date(Number(t)||Date.now()),n=Number(e)||0;switch(String(s??"day").toLowerCase()){case"year":case"years":i.setFullYear(i.getFullYear()+n);break;case"month":case"months":i.setMonth(i.getMonth()+n);break;case"week":case"weeks":i.setDate(i.getDate()+7*n);break;case"day":case"days":default:i.setDate(i.getDate()+n);break;case"hour":case"hours":i.setHours(i.getHours()+n);break;case"minute":case"minutes":i.setMinutes(i.getMinutes()+n)}return i.getTime()},dateDiff:(t,e,s)=>{const i=new Date(Number(t)||Date.now()),n=new Date(Number(e)||Date.now()).getTime()-i.getTime();switch(String(s??"day").toLowerCase()){case"year":case"years":return Math.floor(n/31536e6);case"month":case"months":return Math.floor(n/2592e6);case"week":case"weeks":return Math.floor(n/6048e5);case"day":case"days":default:return Math.floor(n/864e5);case"hour":case"hours":return Math.floor(n/36e5);case"minute":case"minutes":return Math.floor(n/6e4)}},$if:(t,e,s)=>t?e:s,toBoolean:t=>"string"==typeof t?"false"!==t.toLowerCase()&&"0"!==t&&""!==t:Boolean(t),substring:(t,e,s)=>{const i=String(t??""),n=Number(e)||0,r=void 0!==s?Number(s):void 0;return i.substring(n,r)},padStart:(t,e,s)=>{const i=String(t??""),n=Number(e)||0,r=String(s??" ");return i.padStart(n,r)},padEnd:(t,e,s)=>{const i=String(t??""),n=Number(e)||0,r=String(s??" ");return i.padEnd(n,r)},repeat:(t,e)=>{const s=String(t??""),i=Math.max(0,Math.floor(Number(e)||0));return s.repeat(i)}},v={"||":1,"??":1,"&&":2,"==":3,"!=":3,"<":4,">":4,"<=":4,">=":4,"+":5,"-":5,"*":6,"/":6,"%":6},$=class{constructor(t){this.pos=0,this.tokens=t}parse(){const t=this.parseExpression();if("EOF"!==this.current().type)throw new Error(`Unexpected token '${this.current().value}' at position ${this.current().start}`);return t}parseExpression(){return this.parseTernary()}parseTernary(){const t=this.parseBinary(0);if("QUESTION"===this.current().type){this.advance();const e=this.parseExpression();return this.expect("COLON"),{type:"conditional",test:t,consequent:e,alternate:this.parseExpression(),raw:void 0}}return t}parseBinary(t){let e=this.parseUnary();for(;;){const s=this.current();if("OPERATOR"!==s.type)break;const i=v[s.value];if(void 0===i||i<t)break;this.advance();const n=this.parseBinary(i+1);e={type:"binary",operator:s.value,left:e,right:n,raw:void 0}}return e}parseUnary(){const t=this.current();if("OPERATOR"===t.type&&("!"===t.value||"-"===t.value)){this.advance();const e=this.parseUnary();return{type:"unary",operator:t.value,argument:e,raw:void 0}}return this.parsePostfix()}parsePostfix(){let t=this.parsePrimary();for(;;){const e=this.current();if("DOT"===e.type)this.advance(),t={type:"member",object:t,property:this.expect("IDENTIFIER").value,computed:!1,raw:void 0};else if("LBRACKET"===e.type){this.advance();const e=this.parseExpression();this.expect("RBRACKET"),t={type:"member",object:t,property:e,computed:!0,raw:void 0}}else{if("LPAREN"!==e.type||"identifier"!==t.type)break;{const s=t.name;if(!(s in w))throw new Error(`Unknown function '${s}' at position ${e.start}`);this.advance();const i=this.parseArguments();this.expect("RPAREN"),t={type:"call",callee:s,arguments:i,raw:void 0}}}}return t}parsePrimary(){const t=this.current();if("NUMBER"===t.type||"STRING"===t.type||"BOOLEAN"===t.type||"NULL"===t.type)return this.advance(),{type:"literal",value:t.value,start:t.start,end:t.end,raw:void 0};if("IDENTIFIER"===t.type)return this.advance(),{type:"identifier",name:t.value,start:t.start,end:t.end,raw:void 0};if("LBRACKET"===t.type)return this.parseArray();if("LPAREN"===t.type){this.advance();const t=this.parseExpression();return this.expect("RPAREN"),t}throw new Error(`Unexpected token '${t.value}' at position ${t.start}`)}parseArray(){const t=this.current().start;this.advance();const e=[];for(;"RBRACKET"!==this.current().type&&(e.push(this.parseExpression()),"COMMA"===this.current().type);)this.advance();const s=this.current().end;return this.expect("RBRACKET"),{type:"array",elements:e,start:t,end:s,raw:void 0}}parseArguments(){const t=[];if("RPAREN"!==this.current().type)for(t.push(this.parseExpression());"COMMA"===this.current().type;)this.advance(),t.push(this.parseExpression());return t}current(){return this.tokens[this.pos]}advance(){return this.tokens[this.pos++]}expect(t){const e=this.current();if(e.type!==t)throw new Error(`Expected '${t}' but got '${e.type}' at position ${e.start}`);return this.advance()}},x=class{constructor(t={}){this.depth=0,this.startTime=0,this.options={maxDepth:100,timeout:1e3,debug:!1,...t}}evaluate(t,e){this.depth=0,this.startTime=Date.now();try{return{value:this.evaluateNode(t,e)}}catch(t){return{value:void 0,error:t instanceof Error?t:new Error(String(t))}}}evaluateNode(t,e){switch(this.checkLimits(),t.type){case"literal":return this.evaluateLiteral(t);case"identifier":return this.evaluateIdentifier(t,e);case"member":return this.evaluateMember(t,e);case"call":return this.evaluateCall(t,e);case"binary":return this.evaluateBinary(t,e);case"unary":return this.evaluateUnary(t,e);case"conditional":return this.evaluateConditional(t,e);case"array":return this.evaluateArray(t,e);default:throw new o("",`Unknown node type: ${t.type}`)}}evaluateLiteral(t){return t.value}evaluateIdentifier(t,e){const s=t.name;switch(s){case"state":return e.state;case"binding":case"query":return e.binding;case"local":return e.local;case"props":return e.props;case"event":return e.event;case"item":return e.local?.item;case"index":return e.local?.index;default:if(e.local&&s in e.local)return e.local[s];throw new o("",`Unknown variable '${s}'. Available: state, binding, local, props, event`)}}evaluateMember(t,e){const s=this.evaluateNode(t.object,e);if(null==s)return;let i;return i=t.computed?this.evaluateNode(t.property,e):t.property,"object"==typeof s&&null!==s?s[i]:void 0}evaluateCall(t,e){const s=w[t.callee];if(!s)throw new o("",`Unknown function '${t.callee}'`);return s(...t.arguments.map(t=>this.evaluateNode(t,e)))}evaluateBinary(t,e){const s=t.operator;if("&&"===s){const s=this.evaluateNode(t.left,e);return s?this.evaluateNode(t.right,e):s}if("||"===s){return this.evaluateNode(t.left,e)||this.evaluateNode(t.right,e)}if("??"===s){const s=this.evaluateNode(t.left,e);return null!=s?s:this.evaluateNode(t.right,e)}const i=this.evaluateNode(t.left,e),n=this.evaluateNode(t.right,e);switch(s){case"+":return"string"==typeof i||"string"==typeof n?String(i)+String(n):i+n;case"-":return i-n;case"*":return i*n;case"/":return i/n;case"%":return i%n;case"==":return i===n;case"!=":return i!==n;case"<":return i<n;case">":return i>n;case"<=":return i<=n;case">=":return i>=n;default:throw new o("",`Unknown operator '${s}'`)}}evaluateUnary(t,e){const s=this.evaluateNode(t.argument,e);switch(t.operator){case"!":return!s;case"-":return-s;default:throw new o("",`Unknown unary operator '${t.operator}'`)}}evaluateConditional(t,e){return this.evaluateNode(t.test,e)?this.evaluateNode(t.consequent,e):this.evaluateNode(t.alternate,e)}evaluateArray(t,e){return t.elements.map(t=>this.evaluateNode(t,e))}checkLimits(){if(this.depth++,this.depth>(this.options.maxDepth??100))throw new o("","Maximum recursion depth exceeded");if(Date.now()-this.startTime>(this.options.timeout??1e3))throw new o("","Expression evaluation timeout")}},S=class{constructor(t={}){this.astCache=new Map,this.options={cacheAST:!0,maxCacheSize:1e3,...t},this.evaluator=new x(t)}evaluate(t,e){try{const s=this.parse(t);return this.evaluator.evaluate(s,e)}catch(t){return{value:void 0,error:t instanceof Error?t:new Error(String(t))}}}evaluateWithFallback(t,e,s){const i="string"==typeof t?t:t.value,n="object"==typeof t&&void 0!==t.fallback?t.fallback:s,r=this.evaluate(i,e);return r.error?(this.log("warn",`Expression evaluation failed: ${r.error.message}`,i),n):r.value}evaluateTemplate(t,e){return t.replace(/\$\{([^}]+)\}/g,(t,s)=>{const i=this.evaluate(s.trim(),e);return i.error?(this.log("warn",`Template expression failed: ${i.error.message}`,s),""):String(i.value??"")})}parse(t){if(this.options.cacheAST){const e=this.astCache.get(t);if(e)return e}try{const e=new b(t).tokenize(),s=new $(e).parse();return this.options.cacheAST&&(this.astCache.size>=(this.options.maxCacheSize??1e3)&&Array.from(this.astCache.keys()).slice(0,Math.floor(this.astCache.size/2)).forEach(t=>this.astCache.delete(t)),this.astCache.set(t,s)),s}catch(e){throw new o(t,e instanceof Error?e.message:"Parse error")}}validate(t){const e=[],s=[],i=[],n=[];try{const e=this.parse(t);return this.collectReferences(e,i,n),{valid:!0,errors:[],warnings:s,referencedPaths:i,usedFunctions:n}}catch(t){return e.push({type:"invalid_syntax",message:t instanceof Error?t.message:"Parse error"}),{valid:!1,errors:e,warnings:s,referencedPaths:i,usedFunctions:n}}}clearCache(){this.astCache.clear()}collectReferences(t,e,s){switch(t.type){case"identifier":e.push(t.name);break;case"member":{const s=this.buildMemberPath(t);s&&e.push(s);break}case"call":s.push(t.callee),t.arguments.forEach(t=>this.collectReferences(t,e,s));break;case"binary":this.collectReferences(t.left,e,s),this.collectReferences(t.right,e,s);break;case"unary":this.collectReferences(t.argument,e,s);break;case"conditional":this.collectReferences(t.test,e,s),this.collectReferences(t.consequent,e,s),this.collectReferences(t.alternate,e,s);break;case"array":t.elements.forEach(t=>this.collectReferences(t,e,s))}}buildMemberPath(t){if("identifier"===t.type)return t.name;if("member"===t.type&&!t.computed){const e=this.buildMemberPath(t.object);if(e)return`${e}.${t.property}`}return null}log(t,e,...s){this.options.logger?this.options.logger[t](e,...s):this.options.debug}},k=class{constructor(t){this.loadingCount=0,this.loadingElement=null,this.clipboard={write:async t=>{try{return await navigator.clipboard.writeText(t),!0}catch(e){return this.log("error","Clipboard write failed:",e),this.fallbackCopy(t)}},read:async()=>{try{return await navigator.clipboard.readText()}catch(t){return this.log("error","Clipboard read failed:",t),null}}},this.storage={get:t=>{const e=`${this.storageNamespace}:${t}`,s=localStorage.getItem(e);if(!s)return null;try{const t=JSON.parse(s);return t.expires&&Date.now()>t.expires?(localStorage.removeItem(e),null):t.value}catch{return null}},set:(t,e,s)=>{const i=`${this.storageNamespace}:${t}`,n={value:e,expires:s?.ttlSeconds?Date.now()+1e3*s.ttlSeconds:void 0};("session"===s?.level?sessionStorage:localStorage).setItem(i,JSON.stringify(n))},remove:t=>{const e=`${this.storageNamespace}:${t}`;localStorage.removeItem(e),sessionStorage.removeItem(e)},clear:()=>{const t=`${this.storageNamespace}:`;for(let e=localStorage.length-1;e>=0;e--){const s=localStorage.key(e);s?.startsWith(t)&&localStorage.removeItem(s)}for(let e=sessionStorage.length-1;e>=0;e--){const s=sessionStorage.key(e);s?.startsWith(t)&&sessionStorage.removeItem(s)}}},this.options=t,this.storageNamespace=`djvlc:${t.context.appId}`}async navigate(t){this.log("debug","Navigate:",t),this.track({eventName:"djvlc_navigate",params:{to:t.to,type:t.type},type:"click"});let e=t.to;if(t.query){const s=new URLSearchParams(t.query);e+=(e.includes("?")?"&":"?")+s.toString()}switch(t.type){case"external":t.newWindow?window.open(e,"_blank","noopener,noreferrer"):window.location.href=e;break;case"replace":window.location.replace(e);break;default:t.newWindow?window.open(e,"_blank"):window.location.href=e}}track(t){this.log("debug","Track event:",t);const e=this.options.context;this.options.userApiAdapter.track({eventName:t.eventName,params:t.params,type:t.type||"custom",timestamp:Date.now(),context:{pageVersionId:e.pageVersionId,runtimeVersion:e.runtimeVersion,userId:e.userId,deviceId:e.deviceId,channel:e.channel,appId:e.appId,env:e.env}})}async requestData(t,e){this.log("debug",`Requesting data: ${t}`,e);const s=performance.now(),i=this.options.context;try{const n=await this.options.userApiAdapter.executeQuery({queryVersionId:t,params:e??{},context:{pageVersionId:i.pageVersionId,uid:i.userId,deviceId:i.deviceId}}),r=performance.now()-s;if(this.log("debug",`Data query completed in ${r.toFixed(2)}ms`),!n.success)throw new Error(n.message||n.errorMessage||"Query failed");return this.options.stateManager.setQuery(t,n.data),n.data}catch(e){const i=performance.now()-s;throw this.log("error",`Data query failed: ${t} (${i.toFixed(2)}ms)`,e),e}}async executeAction(t,e={}){this.log("debug",`Executing action: ${t}`,e);const s=performance.now(),i=this.options.context,n=this.generateIdempotencyKey(t,e);this.track({eventName:"djvlc_action_start",params:{actionType:t,idempotencyKey:n},type:"custom"});try{const r=await this.options.userApiAdapter.executeAction({actionType:t,params:e||{},context:{pageVersionId:i.pageVersionId,uid:i.userId,deviceId:i.deviceId,channel:i.channel,appId:i.appId},idempotencyKey:n}),o=performance.now()-s;return this.log("debug",`Action completed in ${o.toFixed(2)}ms`,{success:r.success}),this.track({eventName:r.success?"djvlc_action_success":"djvlc_action_fail",params:{actionType:t,idempotencyKey:n,duration:Math.round(o),errorCode:r.errorCode},type:"custom"}),r}catch(e){const i=performance.now()-s;return this.log("error",`Action failed: ${t} (${i.toFixed(2)}ms)`,e),this.track({eventName:"djvlc_action_error",params:{actionType:t,idempotencyKey:n,duration:Math.round(i),errorMessage:e instanceof Error?e.message:"Unknown error"},type:"custom"}),{success:!1,errorCode:"NETWORK_ERROR",errorMessage:e instanceof Error?e.message:"Action failed"}}}async openDialog(t){return this.log("debug","Open dialog:",t),new Promise(e=>{const s=new CustomEvent("djvlc:openDialog",{detail:{options:t,resolve:t=>e(t)}});document.dispatchEvent(s),setTimeout(()=>{e({confirmed:!1})},6e4)})}closeDialog(t){this.log("debug","Close dialog:",t);const e=new CustomEvent("djvlc:closeDialog",{detail:{dialogId:t}});document.dispatchEvent(e)}showToast(t){this.log("debug","Show toast:",t);const e=document.createElement("div");switch(e.className=`djvlc-toast djvlc-toast-${t.type||"info"} djvlc-toast-${t.position||"top"}`,e.setAttribute("role","alert"),e.textContent=t.message,Object.assign(e.style,{position:"fixed",left:"50%",transform:"translateX(-50%)",padding:"12px 24px",borderRadius:"8px",color:"#fff",fontSize:"14px",zIndex:"10000",boxShadow:"0 4px 12px rgba(0,0,0,0.15)",transition:"opacity 0.3s, transform 0.3s",opacity:"0"}),e.style.backgroundColor={success:"#52c41a",error:"#ff4d4f",warning:"#faad14",info:"#1890ff"}[t.type||"info"],t.position){case"center":e.style.top="50%",e.style.transform="translate(-50%, -50%)";break;case"bottom":e.style.bottom="20px";break;default:e.style.top="20px"}document.body.appendChild(e),requestAnimationFrame(()=>{e.style.opacity="1"}),setTimeout(()=>{e.style.opacity="0",setTimeout(()=>e.remove(),300)},t.duration||3e3)}showLoading(t){this.loadingCount++,1===this.loadingCount&&(this.loadingElement=document.createElement("div"),this.loadingElement.className="djvlc-loading-overlay",this.loadingElement.innerHTML=`\n <div class="djvlc-loading-content">\n <div class="djvlc-loading-spinner"></div>\n <div class="djvlc-loading-message">${t||"加载中..."}</div>\n </div>\n `,Object.assign(this.loadingElement.style,{position:"fixed",top:"0",left:"0",right:"0",bottom:"0",backgroundColor:"rgba(0,0,0,0.5)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:"10001"}),document.body.appendChild(this.loadingElement))}hideLoading(){this.loadingCount=Math.max(0,this.loadingCount-1),0===this.loadingCount&&this.loadingElement&&(this.loadingElement.remove(),this.loadingElement=null)}async share(t){if(this.log("debug","Share:",t),navigator.share)try{return await navigator.share({title:t.title,text:t.description,url:t.url}),{success:!0,channel:"native"}}catch(t){if("AbortError"===t.name)return{success:!1,cancelReason:"User cancelled"};throw t}return t.url&&await this.clipboard.write(t.url)?(this.showToast({message:"链接已复制",type:"success"}),{success:!0,channel:"link"}):{success:!1,cancelReason:"Share not supported"}}async confirm(t){return this.log("debug","Confirm:",t),window.confirm(t.content)}async showActionSheet(t){return this.log("debug","Show action sheet:",t),new Promise(e=>{const s=new CustomEvent("djvlc:showActionSheet",{detail:{options:t,resolve:t=>e(t)}});document.dispatchEvent(s),setTimeout(()=>{e({cancelled:!0})},6e4)})}previewImage(t){this.log("debug","Preview image:",t);const e=new CustomEvent("djvlc:previewImage",{detail:t});document.dispatchEvent(e)}async scanCode(){return this.log("debug","Scan code"),new Promise(t=>{const e=new CustomEvent("djvlc:scanCode",{detail:{resolve:e=>t(e)}});document.dispatchEvent(e),setTimeout(()=>{t({success:!1,cancelReason:"Timeout"})},6e4)})}getState(t){return this.options.stateManager.getVariable(t)}setState(t,e){this.options.stateManager.setVariable(t,e)}getContext(){const t=this.options.context;return{pageVersionId:t.pageVersionId,componentVersionId:"",instanceId:"",userId:t.userId,deviceId:t.deviceId,channel:t.channel,appId:t.appId,env:t.env}}generateIdempotencyKey(t,e){const s=Date.now(),i=JSON.stringify(e||{});return`${t}:${s}:${this.simpleHash(i)}`}simpleHash(t){let e=0;for(let s=0;s<t.length;s++)e=(e<<5)-e+t.charCodeAt(s),e&=e;return Math.abs(e).toString(36)}fallbackCopy(t){const e=document.createElement("textarea");e.value=t,e.style.position="fixed",e.style.opacity="0",document.body.appendChild(e),e.select();try{return document.execCommand("copy"),!0}catch{return!1}finally{document.body.removeChild(e)}}log(t,e,...s){this.options.logger?this.options.logger[t](e,...s):this.options.debug}},E=class{constructor(t={}){this.blockedComponentsMap=new Map,this.blockedActionsSet=new Set,this.allowedCapabilitiesSet=null,this.options={enableSRI:!0,cdnDomains:[],apiDomains:[],blockedComponents:[],blockedActions:[],applyCSPOnInit:!1,...t},this.updateBlockedList(t.blockedComponents?.map(t=>`${t.name}@${t.version}`)||[],t.blockedActions||[]),t.allowedCapabilities&&(this.allowedCapabilitiesSet=new Set(t.allowedCapabilities)),t.applyCSPOnInit&&this.applyCSP()}updateBlockedList(t,e){this.blockedComponentsMap.clear(),t.forEach(t=>{const[e,s]=t.split("@");e&&s&&this.blockedComponentsMap.set(t,{name:e,version:s,reason:"Blocked by registry"})}),this.blockedActionsSet=new Set(e)}addBlockedComponent(t){const e=`${t.name}@${t.version}`;this.blockedComponentsMap.set(e,t),this.log("warn",`Component blocked: ${e} - ${t.reason}`)}removeBlockedComponent(t,e){const s=`${t}@${e}`;this.blockedComponentsMap.delete(s),this.log("info",`Component unblocked: ${s}`)}isComponentBlocked(t,e){return this.blockedComponentsMap.has(`${t}@${e}`)}getBlockedInfo(t,e){return this.blockedComponentsMap.get(`${t}@${e}`)}getAllBlockedComponents(){return Array.from(this.blockedComponentsMap.values())}isActionBlocked(t){return this.blockedActionsSet.has(t)}isCapabilityAllowed(t){return!this.allowedCapabilitiesSet||this.allowedCapabilitiesSet.has(t)}validateCapabilities(t,e,s){if(!this.allowedCapabilitiesSet)return{valid:!0,disallowed:[]};const i=s.filter(t=>!this.allowedCapabilitiesSet.has(t));return i.length>0&&this.log("warn",`Component ${t}@${e} uses disallowed capabilities: ${i.join(", ")}`),{valid:0===i.length,disallowed:i}}async validateIntegrity(t,e,s,i){if(!this.options.enableSRI)return;const[r,o]=i.split("-");if(!r||!o)throw new n(t,e,i,"Invalid integrity format");const a=await this.computeHash(s,r);if(a!==o)throw this.log("error",`Integrity check failed for ${t}@${e}`),new n(t,e,o,a);this.log("debug",`Integrity check passed for ${t}@${e}`)}async generateIntegrity(t,e="sha384"){return`${e}-${await this.computeHash(t,e)}`}isAllowedUrl(t,e){const s="cdn"===e?this.options.cdnDomains:this.options.apiDomains;if(!s||0===s.length)return!0;try{const e=new URL(t);return s.some(t=>{if(t.startsWith("*.")){const s=t.slice(2);return e.hostname.endsWith(s)||e.hostname===s.slice(1)}return e.hostname===t})}catch{return!1}}validateExternalUrl(t){try{const e=new URL(t);if(!["http:","https:"].includes(e.protocol))return{safe:!1,reason:`Unsafe protocol: ${e.protocol}`};const s=e.hostname;return"localhost"===s||"127.0.0.1"===s||s.startsWith("192.168.")||s.startsWith("10.")||s.startsWith("172.16.")?{safe:!1,reason:"Internal network address not allowed"}:{safe:!0}}catch{return{safe:!1,reason:"Invalid URL format"}}}generateCSPPolicy(){const t=this.options.cdnDomains||[],e=this.options.apiDomains||[],s=["'self'",...t].join(" "),i=["'self'",...e,...t].join(" ");return["default-src 'self'",`script-src ${s}`,`style-src ${["'self'","'unsafe-inline'",...t].join(" ")}`,`img-src ${["'self'","data:","blob:",...t].join(" ")}`,`font-src ${["'self'","data:",...t].join(" ")}`,`connect-src ${i}`,"frame-ancestors 'self'","base-uri 'self'","form-action 'self'","upgrade-insecure-requests"].join("; ")}applyCSP(){if(document.querySelector('meta[http-equiv="Content-Security-Policy"]'))return void this.log("debug","CSP meta tag already exists, skipping");const t=document.createElement("meta");t.httpEquiv="Content-Security-Policy",t.content=this.generateCSPPolicy(),document.head.appendChild(t),this.log("info","CSP policy applied")}assertNotBlocked(t,e){const s=this.getBlockedInfo(t,e);if(s)throw new r(t,e,s.reason)}createSafeEvaluator(){return(t,e)=>{const s=Object.keys(e),i=Object.values(e);return new Function(...s,`"use strict"; return (${t});`)(...i)}}async computeHash(t,e){const s=(new TextEncoder).encode(t),i=await crypto.subtle.digest(e.toUpperCase(),s),n=Array.from(new Uint8Array(i));return btoa(String.fromCharCode(...n))}log(t,e,...s){this.options.logger&&this.options.logger[t](e,...s)}},A=class{constructor(t){this.spans=new Map,this.metrics=[],this.errors=[],this.options={enabled:!0,sampleRate:1,batchSize:50,flushInterval:3e4,...t},this.traceId=this.generateTraceId(),this.shouldSample=Math.random()<(this.options.sampleRate??1),this.options.enabled&&this.options.endpoint&&this.startAutoFlush(),"undefined"!=typeof window&&(window.addEventListener("beforeunload",()=>this.flush()),window.addEventListener("visibilitychange",()=>{"hidden"===document.visibilityState&&this.flush()}))}getTraceId(){return this.traceId}getTraceparent(t){const e=t||this.generateSpanId(),s=this.shouldSample?"01":"00";return`00-${this.traceId}-${e}-${s}`}parseTraceparent(t){const e=t.split("-");if(4!==e.length)return null;const[,s,i,n]=e;return{traceId:s,parentSpanId:i,sampled:"01"===n}}startSpan(t,e,s){const i={spanId:this.generateSpanId(),traceId:this.traceId,parentSpanId:e,name:t,startTime:performance.now(),attributes:{pageVersionId:this.options.pageVersionId,...s}};return this.spans.set(i.spanId,i),this.log("debug",`Span started: ${t} (${i.spanId})`),i}endSpan(t,e="ok",s){const i=this.spans.get(t);if(i){i.endTime=performance.now(),i.status=e,s&&(i.attributes={...i.attributes,...s});const n=i.endTime-i.startTime;this.log("debug",`Span ended: ${i.name} (${t}) - ${n.toFixed(2)}ms [${e}]`)}}recordPageLoad(t){this.recordMetricInternal({type:"pageLoadTime",value:t,pageVersionId:this.options.pageVersionId,timestamp:Date.now()})}recordComponentLoad(t,e,s,i){this.recordMetricInternal({type:"componentLoadTime",value:s,pageVersionId:this.options.pageVersionId,componentName:t,componentVersion:e,timestamp:Date.now()}),i||this.recordError(new Error(`Component load failed: ${t}@${e}`),{componentVersion:`${t}@${e}`})}recordFirstRender(t){this.recordMetricInternal({type:"firstRenderTime",value:t,pageVersionId:this.options.pageVersionId,timestamp:Date.now()})}recordActionExecute(t,e,s,i){this.recordMetricInternal({type:"actionExecuteTime",value:s,pageVersionId:this.options.pageVersionId,actionType:t,timestamp:Date.now()}),i||this.recordError(new Error(`Action failed: ${t}`),{actionId:e})}recordQueryExecute(t,e,s,i=!1){this.recordMetricInternal({type:"queryFetchTime",value:e,pageVersionId:this.options.pageVersionId,queryId:t,timestamp:Date.now()}),this.log("debug",`Query ${t}: ${e.toFixed(2)}ms, cache: ${i}, success: ${s}`)}recordExpressionEval(t,e,s){e>1&&this.recordMetricInternal({type:"expressionEvalTime",value:e,pageVersionId:this.options.pageVersionId,timestamp:Date.now()})}recordError(t,e){const s={type:t.name||"Error",message:t.message,stack:t.stack,traceId:this.traceId,pageVersionId:this.options.pageVersionId,componentVersion:e?.componentVersion,actionId:e?.actionId,context:e,timestamp:Date.now()};this.errors.push(s),this.log("error",`Error recorded: ${t.message}`),this.options.onError?.(s),this.errors.length>=(this.options.batchSize??50)&&this.flush()}getMetrics(){return[...this.metrics]}getSpans(){return Array.from(this.spans.values())}getErrors(){return[...this.errors]}getPerformanceSummary(){const t=this.metrics.filter(t=>"componentLoadTime"===t.type),e=this.metrics.find(t=>"pageLoadTime"===t.type),s=this.metrics.find(t=>"firstRenderTime"===t.type);return{pageLoadTime:e?.value,firstRenderTime:s?.value,componentCount:t.length,avgComponentLoadTime:t.length>0?t.reduce((t,e)=>t+e.value,0)/t.length:0,errorCount:this.errors.length}}clear(){this.spans.clear(),this.metrics=[],this.errors=[]}async flush(){if(!this.shouldSample||!this.options.enabled)return;if(0===this.metrics.length&&0===this.errors.length&&0===this.spans.size)return;const t={traceId:this.traceId,pageVersionId:this.options.pageVersionId,appId:this.options.appId,runtimeVersion:this.options.runtimeVersion,spans:this.getSpans(),metrics:this.metrics,errors:this.errors,timestamp:Date.now()};if(this.clear(),this.options.endpoint)try{await fetch(this.options.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t),keepalive:!0}),this.log("debug","Telemetry flushed successfully")}catch(t){this.log("warn","Failed to flush telemetry:",t)}else this.log("debug","No endpoint configured, telemetry data discarded")}destroy(){this.flushTimer&&clearInterval(this.flushTimer),this.flush()}recordMetricInternal(t){this.metrics.push(t),this.options.onMetric?.(t),this.metrics.length>=(this.options.batchSize??50)&&this.flush()}startAutoFlush(){const t=this.options.flushInterval??3e4;this.flushTimer=setInterval(()=>this.flush(),t)}generateTraceId(){const t=new Uint8Array(16);return crypto.getRandomValues(t),Array.from(t,t=>t.toString(16).padStart(2,"0")).join("")}generateSpanId(){const t=new Uint8Array(8);return crypto.getRandomValues(t),Array.from(t,t=>t.toString(16).padStart(2,"0")).join("")}log(t,e,...s){this.options.logger?this.options.logger[t](e,...s):this.options.debug}},I=class t{constructor(t){this.container=null,this.renderedElements=new Map,this.componentEventListeners=new Map,this.expressionContext={state:{},binding:{},local:{}},this.loopContextStack=[],this.styleElement=null,this.options=t}init(){this.log("debug","Renderer initialized")}render(t,e){this.container=e,this.log("debug","Rendering page",t.pageId),this.cleanup(),e.innerHTML="",this.applyPageConfig(t,e),this.initializePageState(t);const s=this.renderNode(t.root);s&&e.appendChild(s),this.log("info",`Page rendered with root component: ${t.root.componentType}`)}updateComponent(t,e){const s=this.renderedElements.get(t);s?this.applyProps(s,e):this.log("warn",`Component not found: ${t}`)}updateContext(t){this.expressionContext={...this.expressionContext,...t}}getContext(){return{...this.expressionContext}}destroy(){this.cleanup(),this.container&&(this.container.innerHTML=""),this.log("debug","Renderer destroyed")}cleanup(){this.componentEventListeners.forEach((t,e)=>{const s=this.renderedElements.get(e);s&&t.forEach(({event:t,handler:e})=>{s.removeEventListener(t,e)})}),this.componentEventListeners.clear(),this.renderedElements.forEach(t=>{t.remove()}),this.renderedElements.clear(),this.styleElement&&(this.styleElement.remove(),this.styleElement=null),this.loopContextStack=[]}renderNode(t){const{id:e,componentType:s,componentVersion:i}=t;try{if(t.condition&&!this.evaluateCondition(t.condition))return this.log("debug",`Component ${e} hidden by condition`),null;if(t.loop)return this.renderLoop(t);const n=this.createElement(t);if(!n)return null;n.setAttribute("data-component-id",e),n.setAttribute("data-component-type",s),i&&n.setAttribute("data-component-version",i);const r=this.resolveProps(t.props);if(this.applyProps(n,r),t.style&&this.applyStyles(n,t.style),t.layout&&this.applyLayout(n,t.layout),this.options.injectHostApi(n,e),t.eventHandlers&&t.eventHandlers.length>0&&this.bindEventHandlers(n,e,t.eventHandlers),this.renderChildren(n,t),t.ref){const e=this.expressionContext.local,s=e.$refs||{};s[t.ref]=n,this.expressionContext={...this.expressionContext,local:{...e,$refs:s}}}return this.renderedElements.set(e,n),n}catch(t){return this.log("error",`Failed to render component: ${e}`,t),this.options.onRenderError?this.options.onRenderError(e,t):this.createErrorFallback(e,s,t)}}createElement(t){const{componentType:e}=t,s=this.options.components.get(e);if(s&&customElements.get(e))return document.createElement(e);const i=`${e}-${t.componentVersion?.replace(/\./g,"-")}`;if(customElements.get(i))return document.createElement(i);const n=document.createElement("div");return n.className=`djvlc-component djvlc-${e}`,s||(this.log("warn",`Component not loaded: ${e}`),n.classList.add("djvlc-component-fallback")),n}renderLoop(t){const{loop:e}=t;if(!e)return null;const s=this.evaluateExpression(e.items);if(!Array.isArray(s))return this.log("warn",`Loop items is not an array for ${t.id}`),null;const i=document.createDocumentFragment();s.forEach((s,n)=>{this.loopContextStack.push({item:s,index:n,loopConfig:e});const r={...this.expressionContext},o={...this.expressionContext.local,[e.itemName]:s,item:s,index:n};e.indexName&&(o[e.indexName]=n),this.expressionContext={...this.expressionContext,local:o};const a={...t,id:`${t.id}_${n}`,loop:void 0},c=this.renderNode(a);if(c){const t=this.evaluateExpression(e.key);c.setAttribute("data-loop-key",String(t??n)),i.appendChild(c)}this.expressionContext=r,this.loopContextStack.pop()});const n=document.createElement("div");return n.className="djvlc-loop-container",n.setAttribute("data-loop-id",t.id),n.appendChild(i),n}renderChildren(t,e){if(e.slots&&Object.keys(e.slots).length>0)for(const[s,i]of Object.entries(e.slots)){const e=this.createSlotContainer(s);for(const t of i){const s=this.renderNode(t);s&&e.appendChild(s)}t.appendChild(e)}}createSlotContainer(t){const e=document.createElement("div");return e.className=`djvlc-slot djvlc-slot-${t}`,e.setAttribute("data-slot",t),e}bindEventHandlers(t,e,s){const i=[];for(const n of s){const{eventName:s,preventDefault:r,stopPropagation:o,throttle:a,debounce:c,condition:h}=n;let l=t=>{if(h&&!this.evaluateCondition(h))return;r&&t.preventDefault(),o&&t.stopPropagation();const i=t.detail||{};this.options.onComponentEvent&&this.options.onComponentEvent(e,s,[n],i)};a&&a>0&&(l=this.createThrottledHandler(l,a)),c&&c>0&&(l=this.createDebouncedHandler(l,c)),t.addEventListener(s,l),i.push({event:s,handler:l})}this.componentEventListeners.set(e,i)}createThrottledHandler(t,e){let s=0;return i=>{const n=Date.now();n-s>=e&&(s=n,t(i))}}createDebouncedHandler(t,e){let s=null;return i=>{s&&clearTimeout(s),s=setTimeout(()=>{t(i),s=null},e)}}evaluateCondition(t){const e=this.evaluateExpression(t);return Boolean(e)}evaluateExpression(t){if(null==t)return t;if("object"==typeof t&&"type"in t&&"value"in t){const e=t,s=this.buildExpressionContext();return this.options.expressionEngine.evaluateWithFallback(e.value,s,e.fallback)}if("string"==typeof t){const e=this.buildExpressionContext();return this.options.expressionEngine.evaluateWithFallback(t,e,void 0)}return t}buildExpressionContext(){const t={};for(const e of this.loopContextStack)t[e.loopConfig.itemName]=e.item,t.item=e.item,t.index=e.index,e.loopConfig.indexName&&(t[e.loopConfig.indexName]=e.index);return{...this.expressionContext,local:{...this.expressionContext.local,...t}}}resolveProps(t){const e={};for(const[s,i]of Object.entries(t))e[s]=this.resolveValue(i);return e}resolveValue(e){if(null==e)return e;if("string"==typeof e)return e.includes("${")?this.options.expressionEngine.evaluateTemplate(e,this.buildExpressionContext()):e;if("number"==typeof e||"boolean"==typeof e)return e;if(Array.isArray(e))return e.map(t=>this.resolveValue(t));if("object"==typeof e){const s=e;if("string"==typeof s.type&&t.EXPRESSION_TYPES.includes(s.type)&&"string"==typeof s.value){const t=s;return this.options.expressionEngine.evaluateWithFallback(t.value,this.buildExpressionContext(),t.fallback)}const i={};for(const[t,e]of Object.entries(s))i[t]=this.resolveValue(e);return i}return e}applyProps(t,e){for(const[s,i]of Object.entries(e))null!=i&&(t.tagName.includes("-")?t[s]=i:"boolean"==typeof i?i?t.setAttribute(s,""):t.removeAttribute(s):"object"==typeof i?t.setAttribute(s,JSON.stringify(i)):t.setAttribute(s,String(i)))}applyStyles(t,e){if(e.inline)for(const[s,i]of Object.entries(e.inline)){if(null==i)continue;const e=this.resolveValue(i);let n;n="number"==typeof e?["zIndex","opacity","flex","fontWeight","lineHeight"].includes(s)?String(e):`${e}px`:String(e);const r=s.replace(/([A-Z])/g,"-$1").toLowerCase();t.style.setProperty(r,n)}e.className&&t.classList.add(...String(e.className).split(" ").filter(Boolean))}applyLayout(t,e){const{x:s,y:i,width:n,height:r,rotation:o,zIndex:a,responsive:c}=e;t.style.position="absolute",void 0!==s&&(t.style.left=`${s}px`),void 0!==i&&(t.style.top=`${i}px`),void 0!==n&&(t.style.width=`${n}px`),void 0!==r&&(t.style.height=`${r}px`),void 0!==o&&(t.style.transform=`rotate(${o}deg)`),void 0!==a&&(t.style.zIndex=String(a)),c&&this.applyResponsiveLayout(t,c)}applyResponsiveLayout(t,e){const s=t.getAttribute("data-component-id");if(!s)return;let i="";if(e.mobile&&(i+=`\n @media (max-width: 767px) {\n [data-component-id="${s}"] {\n ${this.layoutToCSS(e.mobile)}\n }\n }\n `),e.tablet&&(i+=`\n @media (min-width: 768px) and (max-width: 1023px) {\n [data-component-id="${s}"] {\n ${this.layoutToCSS(e.tablet)}\n }\n }\n `),e.desktop&&(i+=`\n @media (min-width: 1440px) {\n [data-component-id="${s}"] {\n ${this.layoutToCSS(e.desktop)}\n }\n }\n `),i){const t=document.createElement("style");t.setAttribute("data-djvlc-responsive",s),t.textContent=i,document.head.appendChild(t)}}layoutToCSS(t){const e=[];return void 0!==t.x&&e.push(`left: ${t.x}px`),void 0!==t.y&&e.push(`top: ${t.y}px`),void 0!==t.width&&e.push(`width: ${t.width}px`),void 0!==t.height&&e.push(`height: ${t.height}px`),void 0!==t.rotation&&e.push(`transform: rotate(${t.rotation}deg)`),void 0!==t.zIndex&&e.push(`z-index: ${t.zIndex}`),e.join("; ")}applyPageConfig(t,e){e.classList.add("djvlc-page"),e.setAttribute("data-page-id",t.pageId),e.setAttribute("data-page-version",t.pageVersion),e.setAttribute("data-schema-version",t.schemaVersion);const s=t.config;s&&(this.applyLayoutConfig(e,s.layout),s.styles&&this.applyStylesConfig(e,s.styles),s.behavior&&this.applyBehaviorConfig(e,s.behavior))}applyBehaviorConfig(t,e){e.debug&&t.setAttribute("data-debug","true"),e.i18n&&this.applyI18nConfig(t,e.i18n)}applyI18nConfig(t,e){const s=this.detectLocale(e);t.setAttribute("lang",s),t.setAttribute("data-locale",s),t.setAttribute("data-default-locale",e.defaultLocale),t.setAttribute("data-supported-locales",e.supportedLocales.join(",")),e.translationBundleId&&t.setAttribute("data-translation-bundle",e.translationBundleId),t.style.setProperty("--djvlc-locale",s),t.style.setProperty("--djvlc-dir",this.getTextDirection(s)),"rtl"===this.getTextDirection(s)?(t.setAttribute("dir","rtl"),t.classList.add("djvlc-rtl")):t.setAttribute("dir","ltr"),this.expressionContext={...this.expressionContext,local:{...this.expressionContext.local,$locale:s,$defaultLocale:e.defaultLocale,$supportedLocales:e.supportedLocales}},this.log("debug",`I18n configured: locale=${s}, default=${e.defaultLocale}`)}detectLocale(t){const{defaultLocale:e,supportedLocales:s,detection:i="browser"}=t;let n=null;switch(i){case"browser":case"header":n=this.detectBrowserLocale(s);break;case"url":n=this.detectUrlLocale(s);break;case"path":n=this.detectPathLocale(s);break;case"cookie":n=this.detectCookieLocale(s);break;case"manual":n=e;break;default:n=null}return n&&s.includes(n)?n:e}detectBrowserLocale(t){if("undefined"==typeof navigator)return null;const e=navigator.languages||[navigator.language];for(const s of e){if(t.includes(s))return s;const e=s.split("-")[0],i=t.find(t=>t===e||t.startsWith(`${e}-`));if(i)return i}return null}detectUrlLocale(t){if("undefined"==typeof window)return null;const e=new URLSearchParams(window.location.search),s=e.get("lang")||e.get("locale");return s&&t.includes(s)?s:null}detectPathLocale(t){if("undefined"==typeof window)return null;const e=window.location.pathname.split("/").filter(Boolean);if(e.length>0){const s=e[0];if(t.includes(s))return s}return null}detectCookieLocale(t){if("undefined"==typeof document)return null;const e=document.cookie.split(";");for(const s of e){const[e,i]=s.trim().split("=");if("lang"===e||"locale"===e||"language"===e){const e=decodeURIComponent(i);if(t.includes(e))return e}}return null}getTextDirection(t){const e=t.split("-")[0];return["ar","ar-SA","ar-EG","ar-AE","he","he-IL","fa","fa-IR","ur","ur-PK","yi","ps","dv"].some(s=>s===t||s===e)?"rtl":"ltr"}applyLayoutConfig(t,e){if(t.setAttribute("data-canvas-type",e.canvasType),e.canvasSize&&"responsive"!==e.canvasType&&(t.style.width=`${e.canvasSize.width}px`,t.style.minHeight=`${e.canvasSize.height}px`),e.maxWidth&&(t.style.maxWidth=`${e.maxWidth}px`,t.style.marginLeft="auto",t.style.marginRight="auto"),e.padding){const{top:s=0,right:i=0,bottom:n=0,left:r=0}=e.padding;t.style.padding=`${s}px ${i}px ${n}px ${r}px`}e.viewport&&(e.viewport.mobile&&t.style.setProperty("--djvlc-breakpoint-mobile",`${e.viewport.mobile}px`),e.viewport.tablet&&t.style.setProperty("--djvlc-breakpoint-tablet",`${e.viewport.tablet}px`),e.viewport.desktop&&t.style.setProperty("--djvlc-breakpoint-desktop",`${e.viewport.desktop}px`))}applyStylesConfig(t,e){if(e.theme&&this.applyThemeConfig(t,e.theme),e.background&&this.applyBackgroundConfig(t,e.background),e.cssVariables)for(const[s,i]of Object.entries(e.cssVariables)){const e=s.startsWith("--")?s:`--${s}`;t.style.setProperty(e,i)}e.customCSS&&this.injectCustomCSS(e.customCSS)}applyThemeConfig(t,e){if(e.preset&&(t.setAttribute("data-theme",e.preset),"system"===e.preset)){const e=window.matchMedia("(prefers-color-scheme: dark)").matches;t.setAttribute("data-theme-resolved",e?"dark":"light")}if(e.variables)for(const[s,i]of Object.entries(e.variables)){const e=s.startsWith("--")?s:`--theme-${s}`;t.style.setProperty(e,i)}e.transition&&t.style.setProperty("--djvlc-theme-transition","all 0.3s ease")}applyBackgroundConfig(t,e){switch(e.type){case"color":t.style.backgroundColor=e.value;break;case"image":t.style.backgroundImage=`url(${e.value})`,t.style.backgroundSize=e.size||"cover",t.style.backgroundPosition=e.position||"center",t.style.backgroundRepeat=e.repeat||"no-repeat";break;case"gradient":t.style.backgroundImage=e.value}}injectCustomCSS(t){t.trim()&&(this.styleElement=document.createElement("style"),this.styleElement.setAttribute("data-djvlc-custom","true"),this.styleElement.textContent=t,document.head.appendChild(this.styleElement))}initializePageState(t){if(t.state&&t.state.fields){const e={};for(const[s,i]of Object.entries(t.state.fields))i&&"object"==typeof i&&(e[s]=i.initialValue);this.expressionContext={...this.expressionContext,state:e}}}createErrorFallback(t,e,s){const i=document.createElement("div");return i.className="djvlc-error-boundary",i.setAttribute("data-component-id",t),i.setAttribute("data-error","true"),i.innerHTML=`\n <div class="djvlc-error-content">\n <span class="djvlc-error-icon">⚠️</span>\n <span class="djvlc-error-message">组件渲染失败: ${e}</span>\n ${this.options.debug?`<pre class="djvlc-error-detail">${s.message}</pre>`:""}\n </div>\n `,i}log(t,e,...s){this.options.logger?this.options.logger[t](e,...s):this.options.debug}};I.EXPRESSION_TYPES=["state","binding","local","template","computed"];var C=I;function N(){customElements.get("djvlc-fallback")||customElements.define("djvlc-fallback",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).innerHTML='\n <style>\n :host {\n display: block;\n padding: 16px;\n background: #fff2f0;\n border: 1px solid #ffccc7;\n border-radius: 4px;\n color: #ff4d4f;\n font-size: 14px;\n }\n .title {\n font-weight: 600;\n margin-bottom: 8px;\n }\n .message {\n color: #666;\n }\n </style>\n <div class="title">组件加载失败</div>\n <div class="message"><slot>请刷新页面重试</slot></div>\n '}static get observedAttributes(){return["message","component-name"]}attributeChangedCallback(t,e,s){if("message"===t&&this.shadowRoot){const t=this.shadowRoot.querySelector(".message");t&&(t.textContent=s)}if("component-name"===t&&this.shadowRoot){const t=this.shadowRoot.querySelector(".title");t&&(t.textContent=`组件 ${s} 加载失败`)}}}),customElements.get("djvlc-blocked")||customElements.define("djvlc-blocked",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).innerHTML='\n <style>\n :host {\n display: block;\n padding: 16px;\n background: #fffbe6;\n border: 1px solid #ffe58f;\n border-radius: 4px;\n color: #faad14;\n font-size: 14px;\n }\n .icon {\n margin-right: 8px;\n }\n </style>\n <span class="icon">⚠️</span>\n <span>此组件已被暂停使用</span>\n '}}),customElements.get("djvlc-error-boundary")||customElements.define("djvlc-error-boundary",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).innerHTML="\n <style>\n :host {\n display: block;\n padding: 16px;\n background: #f5f5f5;\n border: 1px dashed #d9d9d9;\n border-radius: 4px;\n color: #999;\n font-size: 14px;\n text-align: center;\n }\n </style>\n <slot>渲染出错</slot>\n "}})}function j(t,e,s){const i=`djvlc-${"error"===t?"error-boundary":t}`,n=document.createElement(i);return e&&n.setAttribute("message",e),s&&n.setAttribute("component-name",s),n}var D=class{constructor(t){this.lifecycle=null,this.mounted=!1,this.destroyed=!1,this.cleanupFns=[],this.options=t}register(t){t?(this.lifecycle=t,this.log("debug","Lifecycle hooks registered",{onMounted:t.onMounted?.length??0,onBeforeUnmount:t.onBeforeUnmount?.length??0,onVisibilityChange:t.onVisibilityChange?.length??0}),t.onVisibilityChange&&t.onVisibilityChange.length>0&&this.setupVisibilityListener()):this.log("debug","No lifecycle hooks defined")}async triggerMounted(){this.mounted||this.destroyed||(this.mounted=!0,this.log("debug","Triggering onMounted lifecycle"),await this.executeLifecycleActions("mounted",this.lifecycle?.onMounted),this.options.onLifecycleEvent?.("mounted"))}async triggerBeforeUnmount(){this.mounted&&!this.destroyed&&(this.log("debug","Triggering onBeforeUnmount lifecycle"),await this.executeLifecycleActions("beforeUnmount",this.lifecycle?.onBeforeUnmount),this.options.onLifecycleEvent?.("beforeUnmount"))}async triggerVisibilityChange(t){if(!this.mounted||this.destroyed)return;this.log("debug","Triggering onVisibilityChange lifecycle",{isVisible:t});const e=this.options.getContext(),s={...e,local:{...e.local,$visible:t,$hidden:!t}};await this.executeLifecycleActionsWithContext("visibilityChange",this.lifecycle?.onVisibilityChange,s),this.options.onLifecycleEvent?.("visibilityChange",{isVisible:t})}async destroy(){this.destroyed||(await this.triggerBeforeUnmount(),this.cleanupFns.forEach(t=>t()),this.cleanupFns=[],this.destroyed=!0,this.lifecycle=null,this.log("debug","LifecycleManager destroyed"))}isMounted(){return this.mounted&&!this.destroyed}isDestroyed(){return this.destroyed}setupVisibilityListener(){const t=()=>{const t="visible"===document.visibilityState;this.triggerVisibilityChange(t).catch(t=>{this.log("error","Failed to handle visibility change",t)})};document.addEventListener("visibilitychange",t),this.cleanupFns.push(()=>{document.removeEventListener("visibilitychange",t)}),this.log("debug","Visibility listener registered")}async executeLifecycleActions(t,e){if(!e||0===e.length)return;const s=this.options.getContext();await this.executeLifecycleActionsWithContext(t,e,s)}async executeLifecycleActionsWithContext(t,e,s){if(e&&0!==e.length){this.log("debug",`Executing ${e.length} actions for ${t}`);try{const i={id:`lifecycle_${t}`,eventName:t,actions:e};await this.options.actionBridge.handleEvent(i,{lifecycle:t},s),this.log("debug",`Lifecycle ${t} actions completed`)}catch(e){this.log("error",`Failed to execute lifecycle ${t} actions`,e)}}}log(t,e,...s){this.options.logger?this.options.logger[t](e,...s):this.options.debug}},T=t.CURRENT_SCHEMA_VERSION,R="1.0.0",M=class{constructor(t){if(this.container=null,!t.pageId)throw new Error("pageId is required");if(this.options={channel:"prod",debug:!1,enableSRI:!0,env:"production",...t},this.logger=this.createLogger(),this.stateManager=new p,this.eventBus=new m({debug:t.debug,logger:this.logger}),this.expressionEngine=new S({debug:t.debug,logger:this.logger}),!t.userApiAdapter)throw new Error("userApiAdapter is required. Inject a UserApiAdapter implementation (e.g. from @djvlc/runtime-web or your host).");this.userApiAdapter=t.userApiAdapter,this.pageLoader=new h({apiBaseUrl:t.apiBaseUrl,userApiAdapter:this.userApiAdapter,channel:t.channel,previewToken:t.previewToken,headers:t.headers,logger:this.logger}),this.componentLoader=new u({cdnBaseUrl:t.cdnBaseUrl,enableSRI:t.enableSRI,headers:t.headers,logger:this.logger}),this.assetLoader=new d({cdnHosts:[new URL(t.cdnBaseUrl).host],apiHosts:[new URL(t.apiBaseUrl).host]}),this.securityManager=new E({enableSRI:t.enableSRI,cdnDomains:[new URL(t.cdnBaseUrl).host],apiDomains:[new URL(t.apiBaseUrl).host],logger:this.logger}),this.log("info","Runtime created",{version:R})}async init(){this.log("info","Initializing runtime");const t=performance.now();try{this.container=this.resolveContainer(),this.assetLoader.preconnectAll(),this.pageLoader.preconnect(),N(),this.stateManager.setPhase("resolving");const e=performance.now()-t;this.log("info",`Runtime initialized in ${e.toFixed(2)}ms`)}catch(t){throw this.handleError(t),t}}async load(){this.log("info","Loading page:",this.options.pageId);const t=performance.now();try{this.stateManager.setPhase("resolving");const e=await this.pageLoader.resolve(this.options.pageId,{uid:this.options.userId,deviceId:this.options.deviceId});if(this.validateSchemaVersion(e.pageJson),this.stateManager.setPage(e),this.telemetryManager=new A({pageVersionId:e.pageVersionId,appId:this.options.appId,debug:this.options.debug,logger:this.logger,onMetric:this.options.onMetric}),e.runtimeConfig){const t=e.runtimeConfig.blockedComponents?.map(t=>`${t.name}@${t.version}`)||[];this.securityManager.updateBlockedList(t,[]),this.componentLoader.updateBlockedList(t)}this.stateManager.setPhase("loading"),this.componentLoader.preload(e.manifest.components),(await this.componentLoader.loadAll(e.manifest)).forEach((t,e)=>{this.stateManager.setComponentStatus(e,t),this.telemetryManager.recordComponentLoad(t.name,t.version,t.loadTime||0,"loaded"===t.status)}),this.initHostApi(e),this.initActionBridge(),this.initDataBindingManager(e.pageJson),this.initRenderer(),this.initLifecycleManager(e.pageJson);const s=performance.now()-t;return this.telemetryManager.recordPageLoad(s),this.log("info",`Page loaded in ${s.toFixed(2)}ms`),this.emitEvent("page:loaded",{page:e,loadTime:s}),this.options.onLoad?.(e),e}catch(t){throw this.stateManager.setPhase("error"),this.handleError(t),t}}async render(){const t=this.stateManager.getState();if(!t.page||!this.container)throw new s("Page not loaded");this.log("info","Rendering page");const e=performance.now();try{this.stateManager.setPhase("rendering"),this.renderer.updateContext(this.stateManager.getExpressionContext()),this.renderer.render(t.page.pageJson,this.container),await this.dataBindingManager.initializeBindings(this.stateManager.getExpressionContext()),this.stateManager.setPhase("ready");const s=performance.now()-e;this.telemetryManager.recordFirstRender(s),this.log("info",`Page rendered in ${s.toFixed(2)}ms`),await this.lifecycleManager.triggerMounted(),this.emitEvent("page:rendered",{renderTime:s})}catch(t){throw this.stateManager.setPhase("error"),this.handleError(t),t}}getHostApi(){return this.hostApi}getState(){return this.stateManager.getState()}onStateChange(t){return this.stateManager.subscribe(t)}on(t,e){return this.eventBus.on(t,e)}updateComponent(t,e){this.renderer.updateComponent(t,e)}setVariable(t,e){this.stateManager.setVariable(t,e),this.renderer.updateContext(this.stateManager.getExpressionContext()),this.dataBindingManager.onStateChange(t,this.stateManager.getExpressionContext())}getVariable(t){return this.stateManager.getVariable(t)}async refreshData(t){await this.dataBindingManager.refreshBinding(t,this.stateManager.getExpressionContext()),this.renderer.updateContext(this.stateManager.getExpressionContext())}async executeAction(t,e){return this.hostApi.executeAction(t,e)}async destroy(){this.log("info","Destroying runtime"),await(this.lifecycleManager?.destroy()),this.telemetryManager?.flush(),this.dataBindingManager?.destroy(),this.actionBridge?.destroy(),this.renderer?.destroy(),this.eventBus.clear(),this.stateManager.setDestroyed(),this.container&&(this.container.innerHTML=""),this.emitEvent("page:destroyed",{}),this.log("info","Runtime destroyed")}validateSchemaVersion(t){if(t.schemaVersion!==T)throw new s(`Unsupported schema version: ${t.schemaVersion}. Only ${T} is supported.`,{schemaVersion:t.schemaVersion,supportedVersion:T})}resolveContainer(){const{container:t}=this.options;if("string"==typeof t){const e=document.querySelector(t);if(!e)throw new Error(`Container not found: ${t}`);return e}return t}initHostApi(t){this.hostApi=new k({userApiAdapter:this.userApiAdapter,stateManager:this.stateManager,eventBus:this.eventBus,expressionEngine:this.expressionEngine,context:{pageId:t.pageId,pageVersionId:t.pageVersionId,runtimeVersion:R,userId:this.options.userId,deviceId:this.options.deviceId,channel:this.options.channel,appId:this.options.appId||"",env:this.options.env||"production",isEditMode:!1,isPreviewMode:t.isPreview||!1},debug:this.options.debug,logger:this.logger})}initActionBridge(){this.actionBridge=new y({executor:{executeAction:(t,e)=>this.hostApi.executeAction(t,e),requestData:(t,e)=>this.hostApi.requestData(t,e),navigate:t=>this.hostApi.navigate(t),openDialog:t=>this.hostApi.openDialog(t),closeDialog:()=>this.hostApi.closeDialog(),showToast:t=>this.hostApi.showToast(t),showLoading:t=>this.hostApi.showLoading(t),hideLoading:()=>this.hostApi.hideLoading(),track:t=>this.hostApi.track(t),setState:(t,e)=>this.stateManager.setVariable(t,e),getState:t=>this.stateManager.getVariable(t),refreshData:t=>this.refreshData(t)},expressionEngine:this.expressionEngine,debug:this.options.debug,logger:this.logger,onActionStart:(t,e)=>{this.emitEvent("action:executing",{action:t,params:e})},onActionComplete:(t,e)=>{e.success?this.emitEvent("action:executed",{action:t,data:e.data}):this.emitEvent("action:error",{action:t,error:e.error?.message})}})}initDataBindingManager(t){this.dataBindingManager=new f({requester:{requestData:(t,e)=>this.hostApi.requestData(t,e)},stateSetter:{setVariable:(t,e)=>this.stateManager.setVariable(t,e),getVariable:t=>this.stateManager.getVariable(t)},expressionEngine:this.expressionEngine,debug:this.options.debug,logger:this.logger,onDataLoaded:(t,e)=>{this.emitEvent("query:fetched",{bindingId:t,data:e}),this.renderer?.updateContext(this.stateManager.getExpressionContext())},onDataError:(t,e)=>{this.emitEvent("query:error",{bindingId:t,error:e.message})}}),t.dataBindings&&this.dataBindingManager.registerBindings(t.dataBindings),this.stateManager.onStateChange(({key:t})=>{this.dataBindingManager.onStateChange(t,this.stateManager.getExpressionContext())})}initLifecycleManager(t){this.lifecycleManager=new D({actionBridge:this.actionBridge,getContext:()=>this.stateManager.getExpressionContext(),debug:this.options.debug,logger:this.logger,onLifecycleEvent:(t,e)=>{this.emitEvent(`page:lifecycle:${t}`,e??{})}}),this.lifecycleManager.register(t.lifecycle)}initRenderer(){const t=new Map;this.stateManager.getState().components.forEach((e,s)=>{if("loaded"===e.status&&e.component){const[i,n]=s.split("@");t.set(i,{name:i,version:n,Component:e.component,loadTime:e.loadTime||0})}}),this.renderer=new C({expressionEngine:this.expressionEngine,components:t,injectHostApi:(t,e)=>{t.hostApi=this.hostApi,t.componentId=e},onComponentEvent:(t,e,s,i)=>{this.handleComponentEvent(t,e,s,i)},debug:this.options.debug,logger:this.logger,onRenderError:(t,e)=>(this.log("error",`Render error in ${t}:`,e),this.emitEvent("component:error",{componentId:t,error:e.message}),j("error",e.message))}),this.renderer.init()}handleComponentEvent(t,e,s,i){this.log("debug",`Component event: ${t}.${e}`,i);for(const t of s)this.actionBridge.handleEvent(t,i,this.stateManager.getExpressionContext())}handleError(t){const s=t instanceof e?{type:"LOAD_ERROR",message:t.message,code:t.code,details:t.details,traceId:t.traceId,timestamp:t.timestamp}:{type:"UNKNOWN_ERROR",message:t.message,cause:t,timestamp:Date.now()};this.stateManager.setError(s),this.telemetryManager?.recordError(t),this.emitEvent("page:error",{error:t.message}),this.options.onError&&this.options.onError(s)}emitEvent(t,e){const s=m.createEvent(t,e,this.telemetryManager?.getTraceId());this.eventBus.emit(s),this.options.onEvent&&this.options.onEvent(s)}createLogger(){return{debug:(...t)=>{this.options.debug},info:(...t)=>{},warn:(...t)=>{},error:(...t)=>{}}}log(t,e,...s){this.logger[t](e,...s)}};Object.defineProperty(exports,"ErrorCode",{enumerable:!0,get:function(){return t.ErrorCode}}),Object.defineProperty(exports,"ErrorMessages",{enumerable:!0,get:function(){return t.ErrorMessages}}),exports.ActionBridge=y,exports.ActionError=a,exports.AssetLoader=d,exports.BaseRenderer=C,exports.ComponentBlockedError=r,exports.ComponentLoadError=i,exports.ComponentLoader=u,exports.DjvlcRuntime=M,exports.DjvlcRuntimeError=e,exports.Evaluator=x,exports.EventBus=m,exports.ExpressionEngine=S,exports.ExpressionError=o,exports.HostAPIImpl=k,exports.IntegrityError=n,exports.Lexer=b,exports.LifecycleManager=D,exports.MockUserApiAdapter=class{constructor(t={}){this.options=t,this.calls={resolvePage:[],executeAction:[],executeQuery:[],track:[]}}async resolvePage(t){if(this.calls.resolvePage.push(t),this.options.resolvePageThrow)throw this.options.resolvePageThrow;return this.options.resolvePageResponse?this.options.resolvePageResponse:{pageId:t.pageId,resolvedVersionId:"pv_mock",cdnBase:"https://cdn.example.com",snapshotUrl:"https://cdn.example.com/snapshot.json",manifestUrl:"https://cdn.example.com/manifest.json",ops:{killSwitch:[],blockedComponents:[],flags:{}},etag:"mock-etag",cacheTtlSeconds:30}}async executeAction(t){if(this.calls.executeAction.push(t),this.options.executeActionThrow)throw this.options.executeActionThrow;return this.options.executeActionResponse?this.options.executeActionResponse:{success:!0,data:void 0}}async executeQuery(t){if(this.calls.executeQuery.push(t),this.options.executeQueryThrow)throw this.options.executeQueryThrow;return this.options.executeQueryResponse?this.options.executeQueryResponse:{success:!0,data:{}}}track(t){this.calls.track.push(t)}},exports.PageLoadError=s,exports.PageLoader=h,exports.Parser=$,exports.QueryError=c,exports.RUNTIME_VERSION="1.0.0",exports.RenderError=class extends e{constructor(e,s,i,n){super(t.ErrorCode.SYSTEM_INTERNAL_ERROR,i,{...n,componentId:e,componentType:s}),this.name="RenderError",this.componentId=e,this.componentType=s}},exports.SCHEMA_VERSION=T,exports.SUPPORTED_SCHEMA_VERSION=T,exports.SecurityManager=E,exports.StateManager=p,exports.TelemetryManager=A,exports.builtinFunctions=w,exports.createFallbackElement=j,exports.createRuntime=function(t){return new M(t)},exports.registerFallbackComponents=N;
1
+ "use strict";var t=require("@djvlc/contracts-types"),e=class extends Error{constructor(e,s,i,n){super(s||t.ErrorMessages[e]||"Unknown error"),this.name="DjvlcRuntimeError",this.code=e,this.details=i,this.traceId=n,this.timestamp=Date.now()}toJSON(){return{name:this.name,code:this.code,message:this.message,details:this.details,traceId:this.traceId,timestamp:this.timestamp}}},s=class extends e{constructor(e,s,i){super(t.ErrorCode.RESOURCE_PAGE_NOT_FOUND,e,s,i),this.name="PageLoadError"}},i=class extends e{constructor(e,s,i,n=t.ErrorCode.COMPONENT_LOAD_FAILED,r){super(n,i,{...r,componentName:e,componentVersion:s}),this.name="ComponentLoadError",this.componentName=e,this.componentVersion=s}},n=class extends e{constructor(e,s,i,n){super(t.ErrorCode.COMPONENT_INTEGRITY_MISMATCH,`Integrity check failed for ${e}@${s}`,{expectedHash:i,actualHash:n}),this.name="IntegrityError",this.componentName=e,this.componentVersion=s,this.expectedHash=i,this.actualHash=n}},r=class extends e{constructor(e,s,i){super(t.ErrorCode.COMPONENT_BLOCKED,`Component ${e}@${s} is blocked`,{componentName:e,componentVersion:s,reason:i}),this.name="ComponentBlockedError",this.componentName=e,this.componentVersion=s,this.reason=i}},o=class extends e{constructor(e,s,i,n){super(t.ErrorCode.VALIDATION_EXPRESSION_ERROR,s,{...n,expression:e,position:i}),this.name="ExpressionError",this.expression=e,this.position=i}},a=class extends e{constructor(e,s,i=t.ErrorCode.SYSTEM_INTERNAL_ERROR,n,r){super(i,s,{...r,actionType:e,actionId:n}),this.name="ActionError",this.actionType=e,this.actionId=n}},c=class extends e{constructor(e,s,i=t.ErrorCode.SYSTEM_INTERNAL_ERROR,n){super(i,s,{...n,queryId:e}),this.name="QueryError",this.queryId=e}},h=class{constructor(t){this.cache=new Map,this.options={env:"prod",cache:{enabled:!0,maxAge:300},...t}}async resolve(t,e){const i=this.getCacheKey(t,e);if(this.options.cache?.enabled){const e=this.cache.get(i);if(e&&this.isCacheValid(e.timestamp))return this.log("debug",`Page ${t} loaded from cache`),e.data}const n=performance.now();try{const s=await this.callResolveViaAdapter(t,e),r=await this.loadFromCdn(s,t);this.options.cache?.enabled&&this.cache.set(i,{data:r,timestamp:Date.now()});const o=performance.now()-n;return this.log("info",`Page ${t} resolved in ${o.toFixed(2)}ms`),r}catch(e){if(e instanceof s)throw e;throw new s(`Failed to resolve page: ${e instanceof Error?e.message:"Unknown error"}`,{pageId:t})}}async callResolveViaAdapter(t,e){const i=await this.options.userApiAdapter.resolvePage({pageId:t,uid:e?.uid,deviceId:e?.deviceId,env:this.options.env,channel:this.options.channel,previewToken:this.options.previewToken});if(!this.isValidPageResolveResponse(i))throw new s("Invalid page resolve response",{pageId:t});return i}async loadFromCdn(t,e){try{const i=await fetch(t.snapshotUrl,{headers:this.buildHeaders()});if(!i.ok)throw new s(`Failed to load snapshot: ${i.status}`,{pageId:e});const n=await i.json();return this.convertSnapshotToResult(n,t,e)}catch(t){if(t instanceof s)throw t;throw new s(`Failed to load from CDN: ${t instanceof Error?t.message:"Unknown error"}`,{pageId:e})}}convertSnapshotToResult(t,e,s){const i=this.convertSnapshotPageToPageSchema(t.page),n=this.convertSnapshotManifestToPageManifest(t.manifest),r=t.definitionsDigest?.actions?.map(t=>t.versionId)||[],o=t.definitionsDigest?.queries?.map(t=>t.versionId)||[];return n.actionDefinitionVersionIds=r,n.dataQueryVersionIds=o,{pageId:e.pageId,pageVersionId:e.resolvedVersionId,pageJson:i,manifest:n,runtimeConfig:{blockedComponents:e.ops.blockedComponents.map(t=>({name:t.name,version:t.version||"",reason:t.reason})),killSwitches:e.ops.killSwitch.map(t=>({type:t.targetType,enabled:t.enabled})),features:e.ops.flags},isPreview:"preview"===this.options.env||!!this.options.previewToken}}convertSnapshotPageToPageSchema(t){const e={layout:{canvasType:t.config.canvasType,canvasSize:t.config.canvasSize},styles:t.config.background||t.config.cssVariables?{background:t.config.background,cssVariables:t.config.cssVariables}:void 0},s=Object.keys(t.initialState).length>0?{fields:Object.keys(t.initialState).reduce((e,s)=>{const i=t.initialState[s];let n="string";return"number"==typeof i?n="number":"boolean"==typeof i?n="boolean":Array.isArray(i)?n="array":null!==i&&"object"==typeof i&&(n="object"),e[s]={type:n,initialValue:i},e},{})}:void 0,i={title:t.title};return{schemaVersion:t.schemaVersion,pageId:t.pageId,pageVersion:t.pageVersion,runtime:{name:"djvlc-runtime",version:"1.0.0"},meta:i,config:e,seo:t.seo,state:s,dataBindings:t.bindings,root:t.root}}convertSnapshotManifestToPageManifest(t){return{id:"",pageVersionId:"",manifestVersion:"1.0.0",createdAt:(new Date).toISOString(),contentHash:"",components:t.components.map(t=>({componentId:"",name:t.name,version:t.version,entry:`${t.assetsUrl}/${t.entrypoints.js}`,styleEntry:t.entrypoints.css?`${t.assetsUrl}/${t.entrypoints.css}`:void 0,integrity:t.integrity,preload:t.preload,priority:t.priority})),actionDefinitionVersionIds:[],dataQueryVersionIds:[],runtimeVersion:{min:t.runtime.minVersion,recommended:t.runtime.version}}}isValidPageResolveResponse(t){if(!t||"object"!=typeof t)return!1;const e=t;return"string"==typeof e.pageId&&"string"==typeof e.resolvedVersionId&&"string"==typeof e.cdnBase&&"string"==typeof e.snapshotUrl&&"string"==typeof e.manifestUrl&&void 0!==e.ops&&"string"==typeof e.etag&&"number"==typeof e.cacheTtlSeconds}preconnect(){const t=document.createElement("link");t.rel="preconnect",t.href=this.options.apiBaseUrl,document.head.appendChild(t)}clearCache(t){if(t)for(const e of this.cache.keys())e.startsWith(t)&&this.cache.delete(e);else this.cache.clear()}buildHeaders(){return{"Content-Type":"application/json",...this.options.headers}}getCacheKey(t,e){const s=[t,this.options.env,this.options.channel];return e?.uid&&s.push(e.uid),e?.deviceId&&s.push(e.deviceId),s.filter(Boolean).join(":")}isCacheValid(t){const e=1e3*(this.options.cache?.maxAge??300);return Date.now()-t<e}log(t,e){this.options.logger&&this.options.logger[t](e)}},l={sha256:"SHA-256",sha384:"SHA-384",sha512:"SHA-512"},u=class{constructor(t){this.loadedComponents=new Map,this.loadingPromises=new Map,this.options={enableSRI:!0,concurrency:4,timeout:3e4,blockedComponents:[],...t},this.blockedSet=new Set(this.options.blockedComponents)}async load(t){const e=this.getComponentKey(t.name,t.version);if(this.isBlocked(t.name,t.version))throw new r(t.name,t.version,"Component is blocked");const s=this.loadedComponents.get(e);if(s)return s;const i=this.loadingPromises.get(e);if(i)return i;const n=this.loadComponent(t);this.loadingPromises.set(e,n);try{const t=await n;return this.loadedComponents.set(e,t),t}finally{this.loadingPromises.delete(e)}}async loadAll(t){const e=new Map,{concurrency:s=4}=this.options,i=t.components;for(let t=0;t<i.length;t+=s){const n=i.slice(t,t+s).map(async t=>{const s=this.getComponentKey(t.name,t.version),i=performance.now();try{const n=await this.load(t);e.set(s,{name:t.name,version:t.version,status:"loaded",component:n.Component,loadTime:performance.now()-i})}catch(n){const o=n instanceof r?"blocked":"failed";if(e.set(s,{name:t.name,version:t.version,status:o,error:n instanceof Error?n.message:"Unknown error",loadTime:performance.now()-i}),"critical"===t.priority)throw n}});await Promise.all(n)}return e}preload(t){t.forEach(t=>{const e=document.createElement("link");e.rel="preload",e.as="script",e.href=this.resolveUrl(t.entry),this.options.enableSRI&&t.integrity&&(e.integrity=t.integrity,e.crossOrigin="anonymous"),document.head.appendChild(e)})}isLoaded(t,e){return this.loadedComponents.has(this.getComponentKey(t,e))}get(t,e){return this.loadedComponents.get(this.getComponentKey(t,e))}isBlocked(t,e){return this.blockedSet.has(`${t}@${e}`)||this.blockedSet.has(t)}updateBlockedList(t){this.blockedSet=new Set(t)}async loadComponent(t){const e=performance.now(),s=this.resolveUrl(t.entry);this.log("debug",`Loading component ${t.name}@${t.version}`);try{const n=await this.fetchWithTimeout(s);if(!n.ok)throw new i(t.name,t.version,`Failed to fetch component: ${n.status} ${n.statusText}`);const r=await n.text();this.options.enableSRI&&t.integrity&&await this.validateIntegrity(t,r);const o=await this.executeScript(r,t),a=performance.now()-e;return this.log("info",`Component ${t.name}@${t.version} loaded in ${a.toFixed(2)}ms`),{name:t.name,version:t.version,Component:o,loadTime:a}}catch(e){if(e instanceof i||e instanceof n||e instanceof r)throw e;throw new i(t.name,t.version,`Failed to load component: ${e instanceof Error?e.message:"Unknown error"}`)}}async fetchWithTimeout(t){const e=new AbortController,s=setTimeout(()=>e.abort(),this.options.timeout),i={signal:e.signal,credentials:"omit",headers:this.options.headers?{...this.options.headers}:void 0},n=this.options.fetchComponentScript??fetch;try{return await n(t,i)}finally{clearTimeout(s)}}async validateIntegrity(t,e){if(!t.integrity)return;const[s,i]=t.integrity.split("-");if(!s||!i)throw new n(t.name,t.version,t.integrity,"Invalid format");const r=l[s.toLowerCase()];if(!r)throw new n(t.name,t.version,t.integrity,`Unsupported SRI algorithm: ${s}, expected sha256/sha384/sha512`);const o=await crypto.subtle.digest(r,(new TextEncoder).encode(e)),a=Array.from(new Uint8Array(o)),c=btoa(String.fromCharCode(...a));if(c!==i)throw new n(t.name,t.version,i,c)}async executeScript(t,e){const s=new Blob([t],{type:"application/javascript"}),n=URL.createObjectURL(s);try{const t=await import(n),s=t.default??t[e.name]??t[this.kebabToPascal(e.name)]??t.Component;if(!s)throw new i(e.name,e.version,"Component module does not export a valid component (expected default or Component)");return s}finally{URL.revokeObjectURL(n)}}kebabToPascal(t){return t.split("-").map(t=>t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()).join("")}resolveUrl(t){return t.startsWith("http://")||t.startsWith("https://")?t:`${this.options.cdnBaseUrl}/${t.replace(/^\//,"")}`}getComponentKey(t,e){return`${t}@${e}`}log(t,e){this.options.logger&&this.options.logger[t](e)}},d=class{constructor(t){this.preconnectedHosts=new Set,this.preloadedAssets=new Set,this.options=t}preconnectAll(){[...this.options.cdnHosts,...this.options.apiHosts].forEach(t=>this.preconnect(t))}preconnect(t){if(this.preconnectedHosts.has(t))return;const e=document.createElement("link");e.rel="preconnect",e.href=t.startsWith("http")?t:`https://${t}`,e.crossOrigin="anonymous",document.head.appendChild(e),this.preconnectedHosts.add(t)}dnsPrefetch(t){const e=document.createElement("link");e.rel="dns-prefetch",e.href=t.startsWith("http")?t:`https://${t}`,document.head.appendChild(e)}preloadScript(t,e){if(this.preloadedAssets.has(t))return;const s=document.createElement("link");s.rel="preload",s.setAttribute("as","script"),s.href=t,e&&(s.setAttribute("integrity",e),s.setAttribute("crossorigin","anonymous")),document.head.appendChild(s),this.preloadedAssets.add(t)}preloadStyle(t,e){if(this.preloadedAssets.has(t))return;const s=document.createElement("link");s.rel="preload",s.setAttribute("as","style"),s.href=t,e&&(s.setAttribute("integrity",e),s.setAttribute("crossorigin","anonymous")),document.head.appendChild(s),this.preloadedAssets.add(t)}preloadImage(t){if(this.preloadedAssets.has(t))return;const e=document.createElement("link");e.rel="preload",e.setAttribute("as","image"),e.href=t,document.head.appendChild(e),this.preloadedAssets.add(t)}prefetch(t,e){const s=document.createElement("link");s.rel="prefetch",s.href=t,e&&s.setAttribute("as",e),document.head.appendChild(s)}loadStylesheet(t,e){return new Promise((s,i)=>{const n=document.createElement("link");n.rel="stylesheet",n.href=t,e&&(n.integrity=e,n.crossOrigin="anonymous"),n.onload=()=>s(),n.onerror=()=>i(new Error(`Failed to load stylesheet: ${t}`)),document.head.appendChild(n)})}loadScript(t,e){return new Promise((s,i)=>{const n=document.createElement("script");n.src=t,n.async=!0,e&&(n.integrity=e,n.crossOrigin="anonymous"),n.onload=()=>s(),n.onerror=()=>i(new Error(`Failed to load script: ${t}`)),document.body.appendChild(n)})}},p=class{constructor(){this.listeners=new Set,this.changeCallbacks=new Set,this.state=this.createInitialState()}getState(){return this.state}getPhase(){return this.state.phase}setPhase(t){this.setState({phase:t})}setPage(t){const e=t.pageJson,s=this.initializePageState(e);t.preloadedData&&Object.assign(s,t.preloadedData),this.setState({page:t,variables:s})}initializePageState(t){const e={};if(t.state&&t.state.fields)for(const[s,i]of Object.entries(t.state.fields))if(i&&"object"==typeof i){const t=i;e[s]=t.initialValue}return e}setError(t){this.setState({phase:"error",error:t})}clearError(){this.state.error&&this.setState({error:null})}getVariable(t){return t.includes(".")?this.getNestedValue(this.state.variables,t):this.state.variables[t]}setVariable(t,e){const s=this.getVariable(t);if(t.includes(".")){const s={...this.state.variables};this.setNestedValue(s,t,e),this.setState({variables:s})}else this.setState({variables:{...this.state.variables,[t]:e}});this.notifyChange({key:t,oldValue:s,newValue:e})}setVariables(t){const e=[];for(const[s,i]of Object.entries(t)){const t=this.getVariable(s);e.push({key:s,oldValue:t,newValue:i})}this.setState({variables:{...this.state.variables,...t}}),e.forEach(t=>this.notifyChange(t))}getQuery(t){return this.state.queries[t]}setQuery(t,e){this.setState({queries:{...this.state.queries,[t]:e}})}clearQuery(t){const{[t]:e,...s}=this.state.queries;this.setState({queries:s})}setComponentStatus(t,e){const s=new Map(this.state.components);s.set(t,e),this.setState({components:s})}getComponentStatus(t){return this.state.components.get(t)}setDestroyed(){this.setState({phase:"destroyed",destroyed:!0})}isDestroyed(){return this.state.destroyed}subscribe(t){return this.listeners.add(t),()=>{this.listeners.delete(t)}}onStateChange(t){return this.changeCallbacks.add(t),()=>{this.changeCallbacks.delete(t)}}reset(){this.state=this.createInitialState(),this.notifyListeners()}getExpressionContext(){return{state:this.state.variables,binding:this.state.queries,local:{},context:{pageVersionId:this.state.page?.pageVersionId,pageId:this.state.page?.pageId,phase:this.state.phase,$now:Date.now()}}}setState(t){this.state={...this.state,...t},this.notifyListeners()}notifyListeners(){this.listeners.forEach(t=>{try{t(this.state)}catch(t){}})}notifyChange(t){this.changeCallbacks.forEach(e=>{try{e(t)}catch(t){}})}getNestedValue(t,e){const s=e.split(".");let i=t;for(const t of s){if(null==i)return;i=i[t]}return i}setNestedValue(t,e,s){const i=e.split(".");let n=t;for(let t=0;t<i.length-1;t++){const e=i[t];void 0!==n[e]&&null!==n[e]||(n[e]={}),n=n[e]}n[i[i.length-1]]=s}createInitialState(){return{phase:"idle",page:null,variables:{},queries:{},components:new Map,error:null,destroyed:!1}}},f=class{constructor(t){this.bindings=new Map,this.dependencyGraph=new Map,this.bindingDependencies=new Map,this.options=t}registerBindings(t){for(const e of t)this.registerBinding(e)}registerBinding(t){if(this.bindings.set(t.id,{binding:t,loading:!1,retryCount:0}),t.dependencies)for(const e of t.dependencies)this.dependencyGraph.has(e)||this.dependencyGraph.set(e,new Set),this.dependencyGraph.get(e).add(t.id);this.updateBindingDependencies(t),this.log("debug",`Registered data binding: ${t.id}`)}updateBindingDependencies(t){for(const[e,s]of this.bindings){if(e===t.id)continue;const i=s.binding;i.dependencies?.includes(t.targetState)&&(this.bindingDependencies.has(t.id)||this.bindingDependencies.set(t.id,new Set),this.bindingDependencies.get(t.id).add(e))}if(t.dependencies)for(const e of t.dependencies)for(const[s,i]of this.bindings)s!==t.id&&i.binding.targetState===e&&(this.bindingDependencies.has(s)||this.bindingDependencies.set(s,new Set),this.bindingDependencies.get(s).add(t.id))}async initializeBindings(t){const e=[];for(const t of this.bindings.values())"eager"===t.binding.loadStrategy&&e.push(t.binding);const s=this.topologicalSort(e),i=this.createLoadBatches(s);for(const e of i){const s=await Promise.allSettled(e.map(e=>this.loadBinding(e.id,t))),i=new Map;s.forEach((t,s)=>{const n=e[s].id;"fulfilled"===t.status?i.set(n,{success:!0,data:t.value}):i.set(n,{success:!1,error:t.reason})}),this.options.onBatchComplete?.(i)}}topologicalSort(t){const e=new Map(t.map(t=>[t.id,t])),s=new Set,i=[],n=t=>{if(!s.has(t.id)){if(s.add(t.id),t.dependencies)for(const i of t.dependencies)for(const[t,r]of e)r.targetState!==i||s.has(t)||n(r);i.push(t)}};for(const e of t)n(e);return i}createLoadBatches(t){const e=[],s=new Set;for(;s.size<t.length;){const i=[];for(const e of t){if(s.has(e.id))continue;let n=!0;if(e.dependencies)for(const i of e.dependencies){for(const e of t)if(e.targetState===i&&!s.has(e.id)){n=!1;break}if(!n)break}n&&i.push(e)}if(0===i.length)for(const e of t)if(!s.has(e.id)){i.push(e),this.log("warn",`Possible circular dependency detected at binding: ${e.id}`);break}i.forEach(t=>s.add(t.id)),i.length>0&&e.push(i)}return e}async loadBinding(t,e,s=!1){const i=this.bindings.get(t);if(!i)throw new c(t,`Data binding not found: ${t}`);const{binding:n}=i;if(!n.condition||this.evaluateCondition(n.condition,e)){if(!s&&this.isCacheValid(i))return this.log("debug",`Binding ${t} returned from cache`),i.cachedData;if(i.loading)this.log("debug",`Binding ${t} is already loading`);else{i.loading=!0;try{const s=this.resolveParams(n.params||{},e),r=await this.executeWithRetry(n,s),o=n.transform?this.applyTransform(r,n.transform,e):r;return i.cachedData=o,i.lastLoadTime=Date.now(),n.cache?.ttl&&(i.cacheExpireTime=Date.now()+1e3*n.cache.ttl),i.retryCount=0,this.options.stateSetter.setVariable(n.targetState,o),this.setupAutoRefresh(i,e),this.options.onDataLoaded?.(t,o),this.log("info",`Binding ${t} loaded successfully`),o}catch(t){throw await this.handleLoadError(i,t,e),t}finally{i.loading=!1}}}else this.log("debug",`Binding ${t} skipped by condition`)}async refreshBinding(t,e){await this.loadBinding(t,e,!0)}async refreshAll(t){const e=Array.from(this.bindings.keys()).map(e=>this.loadBinding(e,t,!0));await Promise.allSettled(e)}async onStateChange(t,e){const s=this.dependencyGraph.get(t);if(!s||0===s.size)return;this.log("debug",`State ${t} changed, refreshing dependent bindings`);const i=Array.from(s).map(t=>this.loadBinding(t,e,!0));await Promise.allSettled(i)}async triggerManualLoad(t,e){const s=this.bindings.get(t);if(!s)throw new c(t,`Data binding not found: ${t}`);return"manual"!==s.binding.loadStrategy&&this.log("warn",`Binding ${t} is not manual strategy`),this.loadBinding(t,e,!0)}checkVisibility(t,e,s){const i=this.bindings.get(t);i&&"lazy"===i.binding.loadStrategy&&e&&!i.lastLoadTime&&this.loadBinding(t,s).catch(e=>{this.log("error",`Lazy binding ${t} failed to load`,e)})}destroy(){for(const t of this.bindings.values())t.refreshTimer&&clearInterval(t.refreshTimer);this.bindings.clear(),this.dependencyGraph.clear(),this.log("debug","DataBindingManager destroyed")}async executeWithRetry(t,e){const s=t.onError?.retry?.maxRetries??0,i=t.onError?.retry?.backoffMs??1e3,n=t.onError?.retry?.backoff??"fixed";let r;for(let o=0;o<=s;o++)try{const s=await this.options.requester.requestData(t.queryVersionId,e);if(!s.success)throw new c(t.queryVersionId,s.message||"Query failed",void 0,{params:e});return s.data}catch(t){if(r=t,this.log("warn",`Query attempt ${o+1}/${s+1} failed:`,t),o<s){const t="exponential"===n?i*Math.pow(2,o):i;await this.delay(t)}}throw r||new Error("Query failed after all retries")}async handleLoadError(t,e,s){const{binding:i}=t,n=i.onError;t.retryCount++,void 0!==n?.fallbackValue&&this.options.stateSetter.setVariable(i.targetState,n.fallbackValue),n?.showError&&this.options.onDataError?.(i.id,e),this.log("error",`Binding ${i.id} load failed:`,e)}setupAutoRefresh(t,e){t.refreshTimer&&(clearInterval(t.refreshTimer),t.refreshTimer=void 0);const s=t.binding.refreshInterval;!s||s<=0||(t.refreshTimer=setInterval(()=>{this.loadBinding(t.binding.id,e,!0).catch(e=>{this.log("error",`Auto refresh for ${t.binding.id} failed:`,e)})},1e3*s))}isCacheValid(t){return!(!t.cachedData||!t.lastLoadTime||t.cacheExpireTime&&Date.now()>t.cacheExpireTime)}resolveParams(t,e){const s={};for(const[i,n]of Object.entries(t))s[i]=this.resolveValue(n,e);return s}resolveValue(t,e){if(null==t)return t;if("object"==typeof t&&!Array.isArray(t)){const s=t;if("expression"===s.type||"binding"===s.type)return this.options.expressionEngine.evaluateWithFallback(s.expression,e,s.fallback);const i={};for(const[t,n]of Object.entries(s))i[t]=this.resolveValue(n,e);return i}return"string"==typeof t&&t.includes("${")?this.options.expressionEngine.evaluateTemplate(t,e):t}evaluateCondition(t,e){const s=void 0===t.fallback||t.fallback,i=this.options.expressionEngine.evaluateWithFallback(t.value,e,s);return Boolean(i)}applyTransform(t,e,s){const i={...s,local:{...s.local||{},$data:t,$response:t}},n=void 0!==e.fallback?e.fallback:t;return this.options.expressionEngine.evaluateWithFallback(e.value,i,n)}delay(t){return new Promise(e=>setTimeout(e,t))}log(t,e,...s){this.options.logger?this.options.logger[t](e,...s):this.options.debug}},m=class{constructor(t={}){this.handlers=new Map,this.options={debug:!1,maxListeners:100,...t}}emit(t){this.options.debug&&this.log("debug",`Event emitted: ${t.type}`,t);const e=this.handlers.get(t.type);e&&e.forEach(e=>{try{e(t)}catch(e){this.log("error",`Error in event handler for ${t.type}:`,e)}})}on(t,e){let s=this.handlers.get(t);return s||(s=new Set,this.handlers.set(t,s)),s.size>=(this.options.maxListeners??100)&&this.log("warn",`Max listeners (${this.options.maxListeners}) reached for event: ${t}`),s.add(e),()=>{s?.delete(e),0===s?.size&&this.handlers.delete(t)}}off(t,e){const s=this.handlers.get(t);s&&(s.delete(e),0===s.size&&this.handlers.delete(t))}once(t,e){const s=this.on(t,t=>{s(),e(t)});return s}clear(t){t?this.handlers.delete(t):this.handlers.clear()}listenerCount(t){return this.handlers.get(t)?.size??0}static createEvent(t,e,s){return{type:t,data:e,timestamp:Date.now(),traceId:s}}log(t,e,...s){this.options.logger?this.options.logger[t](e,...s):this.options.debug}},g=class t{constructor(t){this.debounceTimers=new Map,this.throttleTimers=new Map,this.options=t}async handleEvent(t,e,s){if(t.condition&&!this.evaluateCondition(t.condition,s,e))return void this.log("debug",`Handler ${t.id} skipped by condition`);if(t.throttle&&t.throttle>0&&!this.throttle(t.id,t.throttle))return void this.log("debug",`Handler ${t.id} throttled`);t.debounce&&t.debounce>0&&await this.debounce(t.id,t.debounce);const i={$event:e,$prevResult:void 0,$results:{}};await this.executeActionChain(t.actions,s,i)}async executeActionChain(t,e,s){const i=[];for(let n=0;n<t.length;n++){const r=t[n];if(r.condition){const t=this.buildActionContext(e,s);if(!this.evaluateCondition(r.condition,t,s.$event)){this.log("debug",`Action ${r.id||n} skipped by condition`);continue}}const o=this.executeSingleAction(r,e,s);r.async?i.push(o):await o}i.length>0&&await Promise.allSettled(i)}async executeSingleAction(t,e,s){const i=t.id||t.alias||t.builtinAction||t.actionDefinitionVersionId||"unknown";t.silent||this.options.executor.showLoading();try{const n=this.buildActionContext(e,s),r=this.resolveParams(t.params||{},n);this.options.onActionStart?.(t,r);const o=await this.executeWithRetry(t,r);s.$prevResult=o,t.id&&(s.$results[t.id]=o),this.options.onActionComplete?.(t,{success:!0,data:o}),this.log("debug",`Action ${i} completed successfully`),t.onSuccess&&t.onSuccess.length>0&&await this.executeActionChain(t.onSuccess,e,s)}catch(n){this.log("error",`Action ${i} failed:`,n),this.options.onActionComplete?.(t,{success:!1,error:n}),t.onError&&t.onError.length>0&&await this.executeActionChain(t.onError,e,{...s,$prevResult:{error:n.message}})}finally{t.silent||this.options.executor.hideLoading(),t.onFinally&&t.onFinally.length>0&&await this.executeActionChain(t.onFinally,e,s)}}async executeWithRetry(t,e){const s=t.policy?.retry?.maxAttempts??1,i=t.policy?.retry?.backoffMs??1e3,n=t.policy?.timeoutMs;let r;for(let o=1;o<=s;o++)try{let s;if(t.builtinAction)s=this.executeBuiltinAction(t.builtinAction,e);else{if(!t.actionDefinitionVersionId)throw new a("unknown","Action must specify builtinAction or actionDefinitionVersionId");s=this.executeCustomAction(t.actionDefinitionVersionId,e)}return n&&(s=this.withTimeout(s,n)),await s}catch(t){r=t,this.log("warn",`Action attempt ${o}/${s} failed:`,t),o<s&&await this.delay(i*o)}throw r||new Error("Action failed after all retries")}async executeBuiltinAction(t,e){switch(t){case"setState":return this.options.executor.setState(e.key,e.value),{success:!0};case"navigate":return this.options.executor.navigate({to:e.to??e.url,type:e.replace?"replace":e.external?"external":"push",params:e.params,query:e.query,newWindow:e.newWindow??e.newTab}),{success:!0};case"openDialog":return await this.options.executor.openDialog({type:e.type,content:e.content,title:e.title});case"closeDialog":return this.options.executor.closeDialog(e.dialogId),{success:!0};case"showToast":return this.options.executor.showToast({message:e.message,type:e.type,duration:e.duration}),{success:!0};case"showLoading":return this.options.executor.showLoading(e.message),{success:!0};case"hideLoading":return this.options.executor.hideLoading(),{success:!0};case"refreshData":return await this.options.executor.refreshData(e.queryId),{success:!0};case"track":return this.options.executor.track({eventName:e.eventName,params:e.params}),{success:!0};default:throw new a(t,`Unknown builtin action: ${t}`)}}async executeCustomAction(t,e){const s=t.split("@")[0],i=await this.options.executor.executeAction(s,{...e,actionDefinitionVersionId:t});if(!i.success)throw new a(s,i.errorMessage||"Action execution failed",void 0,t,{errorCode:i.errorCode});return i.data}resolveParams(t,e){const s={};for(const[i,n]of Object.entries(t))s[i]=this.resolveValue(n,e);return s}resolveValue(e,s){if(null==e)return e;if("string"==typeof e){if(e.startsWith("${")&&e.endsWith("}")){const t=e.slice(2,-1);return this.options.expressionEngine.evaluateWithFallback(t,s,e)}return e.includes("${")?this.options.expressionEngine.evaluateTemplate(e,s):e}if("number"==typeof e||"boolean"==typeof e)return e;if(Array.isArray(e))return e.map(t=>this.resolveValue(t,s));if("object"==typeof e){const i=e;if("string"==typeof i.type&&t.EXPRESSION_TYPES.includes(i.type)&&"string"==typeof i.value){const t=i;return this.options.expressionEngine.evaluateWithFallback(t.value,s,t.fallback)}const n={};for(const[t,e]of Object.entries(i))n[t]=this.resolveValue(e,s);return n}return e}evaluateCondition(t,e,s){const i={...e,local:{...e.local||{},$event:s}},n=void 0===t.fallback||t.fallback,r=this.options.expressionEngine.evaluateWithFallback(t.value,i,n);return Boolean(r)}buildActionContext(t,e){return{...t,local:{...t.local||{},$event:e.$event,$prevResult:e.$prevResult,$results:e.$results}}}withTimeout(t,e){return new Promise((s,i)=>{const n=setTimeout(()=>{i(new Error(`Action timed out after ${e}ms`))},e);t.then(t=>{clearTimeout(n),s(t)}).catch(t=>{clearTimeout(n),i(t)})})}debounce(t,e){return new Promise(s=>{const i=this.debounceTimers.get(t);i&&clearTimeout(i);const n=setTimeout(()=>{this.debounceTimers.delete(t),s()},e);this.debounceTimers.set(t,n)})}throttle(t,e){const s=Date.now();return!(s-(this.throttleTimers.get(t)??0)<e||(this.throttleTimers.set(t,s),0))}delay(t){return new Promise(e=>setTimeout(e,t))}destroy(){this.debounceTimers.forEach(t=>clearTimeout(t)),this.debounceTimers.clear(),this.throttleTimers.clear()}log(t,e,...s){this.options.logger?this.options.logger[t](e,...s):this.options.debug}};g.EXPRESSION_TYPES=["state","binding","local","template","computed"];var y=g,b=class{constructor(t){this.pos=0,this.tokens=[],this.input=t}tokenize(){for(this.pos=0,this.tokens=[];this.pos<this.input.length&&(this.skipWhitespace(),!(this.pos>=this.input.length));){const t=this.readToken();t&&this.tokens.push(t)}return this.tokens.push({type:"EOF",value:null,start:this.input.length,end:this.input.length}),this.tokens}readToken(){const t=this.input[this.pos],e=this.pos;if(this.isDigit(t)||"-"===t&&this.isDigit(this.peek(1)))return this.readNumber();if('"'===t||"'"===t)return this.readString(t);if(this.isIdentifierStart(t))return this.readIdentifier();const s=this.readOperator();if(s)return s;switch(t){case".":return this.pos++,{type:"DOT",value:".",start:e,end:this.pos};case"[":return this.pos++,{type:"LBRACKET",value:"[",start:e,end:this.pos};case"]":return this.pos++,{type:"RBRACKET",value:"]",start:e,end:this.pos};case"(":return this.pos++,{type:"LPAREN",value:"(",start:e,end:this.pos};case")":return this.pos++,{type:"RPAREN",value:")",start:e,end:this.pos};case",":return this.pos++,{type:"COMMA",value:",",start:e,end:this.pos};case"?":return this.pos++,{type:"QUESTION",value:"?",start:e,end:this.pos};case":":return this.pos++,{type:"COLON",value:":",start:e,end:this.pos}}throw new Error(`Unexpected character '${t}' at position ${this.pos}`)}readNumber(){const t=this.pos;let e="";for("-"===this.input[this.pos]&&(e+="-",this.pos++);this.isDigit(this.input[this.pos]);)e+=this.input[this.pos],this.pos++;if("."===this.input[this.pos]&&this.isDigit(this.peek(1)))for(e+=".",this.pos++;this.isDigit(this.input[this.pos]);)e+=this.input[this.pos],this.pos++;return{type:"NUMBER",value:parseFloat(e),start:t,end:this.pos}}readString(t){const e=this.pos;this.pos++;let s="";for(;this.pos<this.input.length&&this.input[this.pos]!==t;){if("\\"===this.input[this.pos]){this.pos++;const t=this.input[this.pos];switch(t){case"n":s+="\n";break;case"t":s+="\t";break;case"r":s+="\r";break;case"\\":s+="\\";break;case'"':s+='"';break;case"'":s+="'";break;default:s+=t}}else s+=this.input[this.pos];this.pos++}if(this.input[this.pos]!==t)throw new Error(`Unterminated string at position ${e}`);return this.pos++,{type:"STRING",value:s,start:e,end:this.pos}}readIdentifier(){const t=this.pos;let e="";for(;this.pos<this.input.length&&this.isIdentifierChar(this.input[this.pos]);)e+=this.input[this.pos],this.pos++;return"true"===e?{type:"BOOLEAN",value:!0,start:t,end:this.pos}:"false"===e?{type:"BOOLEAN",value:!1,start:t,end:this.pos}:"null"===e?{type:"NULL",value:null,start:t,end:this.pos}:{type:"IDENTIFIER",value:e,start:t,end:this.pos}}readOperator(){const t=this.pos,e=this.input.slice(this.pos,this.pos+2),s=this.input[this.pos];return["==","!=",">=","<=","&&","||","??"].includes(e)?(this.pos+=2,{type:"OPERATOR",value:e,start:t,end:this.pos}):["+","-","*","/","%",">","<","!"].includes(s)?(this.pos++,{type:"OPERATOR",value:s,start:t,end:this.pos}):null}skipWhitespace(){for(;this.pos<this.input.length&&/\s/.test(this.input[this.pos]);)this.pos++}isDigit(t){return/[0-9]/.test(t)}isIdentifierStart(t){return/[a-zA-Z_$]/.test(t)}isIdentifierChar(t){return/[a-zA-Z0-9_$]/.test(t)}peek(t=1){return this.input[this.pos+t]||""}},w={len:t=>"string"==typeof t||Array.isArray(t)?t.length:0,trim:t=>String(t??"").trim(),upper:t=>String(t??"").toUpperCase(),lower:t=>String(t??"").toLowerCase(),substr:(t,e,s)=>{const i=String(t??""),n=Number(e)||0,r=void 0!==s?Number(s):void 0;return i.substring(n,void 0!==r?n+r:void 0)},concat:(...t)=>t.map(t=>String(t??"")).join(""),replace:(t,e,s)=>String(t??"").split(String(e)).join(String(s)),split:(t,e)=>String(t??"").split(String(e)),join:(t,e)=>Array.isArray(t)?t.join(void 0!==e?String(e):","):"",startsWith:(t,e)=>String(t??"").startsWith(String(e)),endsWith:(t,e)=>String(t??"").endsWith(String(e)),contains:(t,e)=>String(t??"").includes(String(e)),toNumber:t=>{const e=Number(t);return isNaN(e)?0:e},toString:t=>String(t??""),toInt:t=>Math.trunc(Number(t)||0),toFloat:t=>parseFloat(String(t))||0,round:(t,e)=>{const s=Number(t)||0,i=Number(e)||0,n=Math.pow(10,i);return Math.round(s*n)/n},floor:t=>Math.floor(Number(t)||0),ceil:t=>Math.ceil(Number(t)||0),abs:t=>Math.abs(Number(t)||0),min:(...t)=>{const e=t.map(t=>Number(t)).filter(t=>!isNaN(t));return e.length>0?Math.min(...e):0},max:(...t)=>{const e=t.map(t=>Number(t)).filter(t=>!isNaN(t));return e.length>0?Math.max(...e):0},sum:t=>Array.isArray(t)?t.reduce((t,e)=>t+(Number(e)||0),0):0,avg:t=>Array.isArray(t)&&0!==t.length?t.reduce((t,e)=>t+(Number(e)||0),0)/t.length:0,random:()=>Math.random(),randomInt:(t,e)=>{const s=Math.ceil(Number(t)||0),i=Math.floor(Number(e)||100);return Math.floor(Math.random()*(i-s+1))+s},now:()=>Date.now(),today:()=>(new Date).toISOString().split("T")[0],dateFormat:(t,e)=>{const s=new Date(Number(t)||Date.now()),i=t=>t.toString().padStart(2,"0");return String(e||"YYYY-MM-DD").replace("YYYY",s.getFullYear().toString()).replace("MM",i(s.getMonth()+1)).replace("DD",i(s.getDate())).replace("HH",i(s.getHours())).replace("mm",i(s.getMinutes())).replace("ss",i(s.getSeconds()))},dateParse:t=>new Date(String(t)).getTime(),year:t=>new Date(Number(t)||Date.now()).getFullYear(),month:t=>new Date(Number(t)||Date.now()).getMonth()+1,day:t=>new Date(Number(t)||Date.now()).getDate(),addDays:(t,e)=>{const s=new Date(Number(t)||Date.now());return s.setDate(s.getDate()+(Number(e)||0)),s.getTime()},diffDays:(t,e)=>{const s=new Date(Number(t)||Date.now()),i=new Date(Number(e)||Date.now()),n=Math.abs(i.getTime()-s.getTime());return Math.floor(n/864e5)},isNull:t=>null==t,isUndefined:t=>void 0===t,isEmpty:t=>null==t||("string"==typeof t||Array.isArray(t)?0===t.length:"object"==typeof t&&0===Object.keys(t).length),isArray:t=>Array.isArray(t),isObject:t=>null!==t&&"object"==typeof t&&!Array.isArray(t),isString:t=>"string"==typeof t,isNumber:t=>"number"==typeof t&&!isNaN(t),isBoolean:t=>"boolean"==typeof t,typeOf:t=>null===t?"null":Array.isArray(t)?"array":typeof t,default:(t,e)=>t??e,coalesce:(...t)=>{for(const e of t)if(null!=e)return e;return null},ifElse:(t,e,s)=>t?e:s,first:t=>{if(Array.isArray(t))return t[0]},last:t=>{if(Array.isArray(t))return t[t.length-1]},at:(t,e)=>{if(Array.isArray(t))return t[Number(e)||0]},slice:(t,e,s)=>Array.isArray(t)?t.slice(Number(e)||0,void 0!==s?Number(s):void 0):[],includes:(t,e)=>!!Array.isArray(t)&&t.includes(e),indexOf:(t,e)=>Array.isArray(t)?t.indexOf(e):-1,reverse:t=>Array.isArray(t)?[...t].reverse():[],sort:t=>Array.isArray(t)?[...t].sort():[],unique:t=>Array.isArray(t)?[...new Set(t)]:[],flatten:t=>Array.isArray(t)?t.flat():[],count:t=>Array.isArray(t)?t.length:0,get:(t,e,s)=>{if(null==t)return s;const i=String(e).split(".");let n=t;for(const t of i){if(null==n)return s;n=n[t]}return n??s},keys:t=>"object"!=typeof t||null===t?[]:Object.keys(t),values:t=>"object"!=typeof t||null===t?[]:Object.values(t),entries:t=>"object"!=typeof t||null===t?[]:Object.entries(t),has:(t,e)=>"object"==typeof t&&null!==t&&String(e)in t,merge:(...t)=>{const e={};for(const s of t)"object"==typeof s&&null!==s&&Object.assign(e,s);return e},and:(...t)=>t.every(t=>Boolean(t)),or:(...t)=>t.some(t=>Boolean(t)),not:t=>!t,eq:(t,e)=>t===e,ne:(t,e)=>t!==e,gt:(t,e)=>Number(t)>Number(e),gte:(t,e)=>Number(t)>=Number(e),lt:(t,e)=>Number(t)<Number(e),lte:(t,e)=>Number(t)<=Number(e),between:(t,e,s)=>{const i=Number(t);return i>=Number(e)&&i<=Number(s)},formatNumber:(t,e)=>{const s=Number(t)||0,i=Number(e)??0;return s.toLocaleString(void 0,{minimumFractionDigits:i,maximumFractionDigits:i})},formatCurrency:(t,e)=>{const s=Number(t)||0,i=String(e||"CNY");return s.toLocaleString("zh-CN",{style:"currency",currency:i})},formatPercent:(t,e)=>{const s=Number(t)||0,i=Number(e)??0;return(100*s).toFixed(i)+"%"},currency:(t,e,s)=>{const i=Number(t)||0,n=String(e??"¥"),r=Number(s)??2;return`${n}${i.toLocaleString(void 0,{minimumFractionDigits:r,maximumFractionDigits:r})}`},percent:(t,e)=>{const s=Number(t)||0,i=Number(e)??0;return(100*s).toFixed(i)+"%"},number:(t,e)=>{const s=Number(t)||0,i=Number(e)??0;return s.toLocaleString(void 0,{minimumFractionDigits:i,maximumFractionDigits:i})},pluralize:(t,e,s)=>{const i=Number(t)||0;return`${i} ${String(1===i?e:s)}`},mask:(t,e,s,i)=>{const n=String(t??""),r=Number(e)||3,o=Number(s)||4,a=String(i??"*");if(n.length<=r+o)return n;const c=n.slice(0,r),h=n.slice(-o);return c+a.repeat(n.length-r-o)+h},jsonParse:t=>{try{return JSON.parse(String(t))}catch{return null}},jsonStringify:t=>JSON.stringify(t),toJSON:t=>JSON.stringify(t),fromJSON:t=>{try{return JSON.parse(String(t))}catch{return null}},clamp:(t,e,s)=>{const i=Number(t)||0,n=Number(e)||0,r=Number(s)||100;return Math.min(Math.max(i,n),r)},length:t=>Array.isArray(t)||"string"==typeof t?t.length:0,average:t=>Array.isArray(t)&&0!==t.length?t.reduce((t,e)=>t+(Number(e)||0),0)/t.length:0,dateAdd:(t,e,s)=>{const i=new Date(Number(t)||Date.now()),n=Number(e)||0;switch(String(s??"day").toLowerCase()){case"year":case"years":i.setFullYear(i.getFullYear()+n);break;case"month":case"months":i.setMonth(i.getMonth()+n);break;case"week":case"weeks":i.setDate(i.getDate()+7*n);break;case"day":case"days":default:i.setDate(i.getDate()+n);break;case"hour":case"hours":i.setHours(i.getHours()+n);break;case"minute":case"minutes":i.setMinutes(i.getMinutes()+n)}return i.getTime()},dateDiff:(t,e,s)=>{const i=new Date(Number(t)||Date.now()),n=new Date(Number(e)||Date.now()).getTime()-i.getTime();switch(String(s??"day").toLowerCase()){case"year":case"years":return Math.floor(n/31536e6);case"month":case"months":return Math.floor(n/2592e6);case"week":case"weeks":return Math.floor(n/6048e5);case"day":case"days":default:return Math.floor(n/864e5);case"hour":case"hours":return Math.floor(n/36e5);case"minute":case"minutes":return Math.floor(n/6e4)}},$if:(t,e,s)=>t?e:s,toBoolean:t=>"string"==typeof t?"false"!==t.toLowerCase()&&"0"!==t&&""!==t:Boolean(t),substring:(t,e,s)=>{const i=String(t??""),n=Number(e)||0,r=void 0!==s?Number(s):void 0;return i.substring(n,r)},padStart:(t,e,s)=>{const i=String(t??""),n=Number(e)||0,r=String(s??" ");return i.padStart(n,r)},padEnd:(t,e,s)=>{const i=String(t??""),n=Number(e)||0,r=String(s??" ");return i.padEnd(n,r)},repeat:(t,e)=>{const s=String(t??""),i=Math.max(0,Math.floor(Number(e)||0));return s.repeat(i)}},v={"||":1,"??":1,"&&":2,"==":3,"!=":3,"<":4,">":4,"<=":4,">=":4,"+":5,"-":5,"*":6,"/":6,"%":6},$=class{constructor(t){this.pos=0,this.tokens=t}parse(){const t=this.parseExpression();if("EOF"!==this.current().type)throw new Error(`Unexpected token '${this.current().value}' at position ${this.current().start}`);return t}parseExpression(){return this.parseTernary()}parseTernary(){const t=this.parseBinary(0);if("QUESTION"===this.current().type){this.advance();const e=this.parseExpression();return this.expect("COLON"),{type:"conditional",test:t,consequent:e,alternate:this.parseExpression(),raw:void 0}}return t}parseBinary(t){let e=this.parseUnary();for(;;){const s=this.current();if("OPERATOR"!==s.type)break;const i=v[s.value];if(void 0===i||i<t)break;this.advance();const n=this.parseBinary(i+1);e={type:"binary",operator:s.value,left:e,right:n,raw:void 0}}return e}parseUnary(){const t=this.current();if("OPERATOR"===t.type&&("!"===t.value||"-"===t.value)){this.advance();const e=this.parseUnary();return{type:"unary",operator:t.value,argument:e,raw:void 0}}return this.parsePostfix()}parsePostfix(){let t=this.parsePrimary();for(;;){const e=this.current();if("DOT"===e.type)this.advance(),t={type:"member",object:t,property:this.expect("IDENTIFIER").value,computed:!1,raw:void 0};else if("LBRACKET"===e.type){this.advance();const e=this.parseExpression();this.expect("RBRACKET"),t={type:"member",object:t,property:e,computed:!0,raw:void 0}}else{if("LPAREN"!==e.type||"identifier"!==t.type)break;{const s=t.name;if(!(s in w))throw new Error(`Unknown function '${s}' at position ${e.start}`);this.advance();const i=this.parseArguments();this.expect("RPAREN"),t={type:"call",callee:s,arguments:i,raw:void 0}}}}return t}parsePrimary(){const t=this.current();if("NUMBER"===t.type||"STRING"===t.type||"BOOLEAN"===t.type||"NULL"===t.type)return this.advance(),{type:"literal",value:t.value,start:t.start,end:t.end,raw:void 0};if("IDENTIFIER"===t.type)return this.advance(),{type:"identifier",name:t.value,start:t.start,end:t.end,raw:void 0};if("LBRACKET"===t.type)return this.parseArray();if("LPAREN"===t.type){this.advance();const t=this.parseExpression();return this.expect("RPAREN"),t}throw new Error(`Unexpected token '${t.value}' at position ${t.start}`)}parseArray(){const t=this.current().start;this.advance();const e=[];for(;"RBRACKET"!==this.current().type&&(e.push(this.parseExpression()),"COMMA"===this.current().type);)this.advance();const s=this.current().end;return this.expect("RBRACKET"),{type:"array",elements:e,start:t,end:s,raw:void 0}}parseArguments(){const t=[];if("RPAREN"!==this.current().type)for(t.push(this.parseExpression());"COMMA"===this.current().type;)this.advance(),t.push(this.parseExpression());return t}current(){return this.tokens[this.pos]}advance(){return this.tokens[this.pos++]}expect(t){const e=this.current();if(e.type!==t)throw new Error(`Expected '${t}' but got '${e.type}' at position ${e.start}`);return this.advance()}},x=class{constructor(t={}){this.depth=0,this.startTime=0,this.options={maxDepth:100,timeout:1e3,debug:!1,...t}}evaluate(t,e){this.depth=0,this.startTime=Date.now();try{return{value:this.evaluateNode(t,e)}}catch(t){return{value:void 0,error:t instanceof Error?t:new Error(String(t))}}}evaluateNode(t,e){switch(this.checkLimits(),t.type){case"literal":return this.evaluateLiteral(t);case"identifier":return this.evaluateIdentifier(t,e);case"member":return this.evaluateMember(t,e);case"call":return this.evaluateCall(t,e);case"binary":return this.evaluateBinary(t,e);case"unary":return this.evaluateUnary(t,e);case"conditional":return this.evaluateConditional(t,e);case"array":return this.evaluateArray(t,e);default:throw new o("",`Unknown node type: ${t.type}`)}}evaluateLiteral(t){return t.value}evaluateIdentifier(t,e){const s=t.name;switch(s){case"state":return e.state;case"binding":case"query":return e.binding;case"local":return e.local;case"props":return e.props;case"event":return e.event;case"item":return e.local?.item;case"index":return e.local?.index;default:if(e.local&&s in e.local)return e.local[s];throw new o("",`Unknown variable '${s}'. Available: state, binding, local, props, event`)}}evaluateMember(t,e){const s=this.evaluateNode(t.object,e);if(null==s)return;let i;return i=t.computed?this.evaluateNode(t.property,e):t.property,"object"==typeof s&&null!==s?s[i]:void 0}evaluateCall(t,e){const s=w[t.callee];if(!s)throw new o("",`Unknown function '${t.callee}'`);return s(...t.arguments.map(t=>this.evaluateNode(t,e)))}evaluateBinary(t,e){const s=t.operator;if("&&"===s){const s=this.evaluateNode(t.left,e);return s?this.evaluateNode(t.right,e):s}if("||"===s){return this.evaluateNode(t.left,e)||this.evaluateNode(t.right,e)}if("??"===s){const s=this.evaluateNode(t.left,e);return null!=s?s:this.evaluateNode(t.right,e)}const i=this.evaluateNode(t.left,e),n=this.evaluateNode(t.right,e);switch(s){case"+":return"string"==typeof i||"string"==typeof n?String(i)+String(n):i+n;case"-":return i-n;case"*":return i*n;case"/":return i/n;case"%":return i%n;case"==":return i===n;case"!=":return i!==n;case"<":return i<n;case">":return i>n;case"<=":return i<=n;case">=":return i>=n;default:throw new o("",`Unknown operator '${s}'`)}}evaluateUnary(t,e){const s=this.evaluateNode(t.argument,e);switch(t.operator){case"!":return!s;case"-":return-s;default:throw new o("",`Unknown unary operator '${t.operator}'`)}}evaluateConditional(t,e){return this.evaluateNode(t.test,e)?this.evaluateNode(t.consequent,e):this.evaluateNode(t.alternate,e)}evaluateArray(t,e){return t.elements.map(t=>this.evaluateNode(t,e))}checkLimits(){if(this.depth++,this.depth>(this.options.maxDepth??100))throw new o("","Maximum recursion depth exceeded");if(Date.now()-this.startTime>(this.options.timeout??1e3))throw new o("","Expression evaluation timeout")}},S=class{constructor(t={}){this.astCache=new Map,this.options={cacheAST:!0,maxCacheSize:1e3,...t},this.evaluator=new x(t)}evaluate(t,e){try{const s=this.parse(t);return this.evaluator.evaluate(s,e)}catch(t){return{value:void 0,error:t instanceof Error?t:new Error(String(t))}}}evaluateWithFallback(t,e,s){const i="string"==typeof t?t:t.value,n="object"==typeof t&&void 0!==t.fallback?t.fallback:s,r=this.evaluate(i,e);return r.error?(this.log("warn",`Expression evaluation failed: ${r.error.message}`,i),n):r.value}evaluateTemplate(t,e){return t.replace(/\$\{([^}]+)\}/g,(t,s)=>{const i=this.evaluate(s.trim(),e);return i.error?(this.log("warn",`Template expression failed: ${i.error.message}`,s),""):String(i.value??"")})}parse(t){if(this.options.cacheAST){const e=this.astCache.get(t);if(e)return e}try{const e=new b(t).tokenize(),s=new $(e).parse();return this.options.cacheAST&&(this.astCache.size>=(this.options.maxCacheSize??1e3)&&Array.from(this.astCache.keys()).slice(0,Math.floor(this.astCache.size/2)).forEach(t=>this.astCache.delete(t)),this.astCache.set(t,s)),s}catch(e){throw new o(t,e instanceof Error?e.message:"Parse error")}}validate(t){const e=[],s=[],i=[],n=[];try{const e=this.parse(t);return this.collectReferences(e,i,n),{valid:!0,errors:[],warnings:s,referencedPaths:i,usedFunctions:n}}catch(t){return e.push({type:"invalid_syntax",message:t instanceof Error?t.message:"Parse error"}),{valid:!1,errors:e,warnings:s,referencedPaths:i,usedFunctions:n}}}clearCache(){this.astCache.clear()}collectReferences(t,e,s){switch(t.type){case"identifier":e.push(t.name);break;case"member":{const s=this.buildMemberPath(t);s&&e.push(s);break}case"call":s.push(t.callee),t.arguments.forEach(t=>this.collectReferences(t,e,s));break;case"binary":this.collectReferences(t.left,e,s),this.collectReferences(t.right,e,s);break;case"unary":this.collectReferences(t.argument,e,s);break;case"conditional":this.collectReferences(t.test,e,s),this.collectReferences(t.consequent,e,s),this.collectReferences(t.alternate,e,s);break;case"array":t.elements.forEach(t=>this.collectReferences(t,e,s))}}buildMemberPath(t){if("identifier"===t.type)return t.name;if("member"===t.type&&!t.computed){const e=this.buildMemberPath(t.object);if(e)return`${e}.${t.property}`}return null}log(t,e,...s){this.options.logger?this.options.logger[t](e,...s):this.options.debug}},k=class{constructor(t){this.loadingCount=0,this.loadingElement=null,this.clipboard={write:async t=>{try{return await navigator.clipboard.writeText(t),!0}catch(e){return this.log("error","Clipboard write failed:",e),this.fallbackCopy(t)}},read:async()=>{try{return await navigator.clipboard.readText()}catch(t){return this.log("error","Clipboard read failed:",t),null}}},this.storage={get:t=>{const e=`${this.storageNamespace}:${t}`,s=localStorage.getItem(e);if(!s)return null;try{const t=JSON.parse(s);return t.expires&&Date.now()>t.expires?(localStorage.removeItem(e),null):t.value}catch{return null}},set:(t,e,s)=>{const i=`${this.storageNamespace}:${t}`,n={value:e,expires:s?.ttlSeconds?Date.now()+1e3*s.ttlSeconds:void 0};("session"===s?.level?sessionStorage:localStorage).setItem(i,JSON.stringify(n))},remove:t=>{const e=`${this.storageNamespace}:${t}`;localStorage.removeItem(e),sessionStorage.removeItem(e)},clear:()=>{const t=`${this.storageNamespace}:`;for(let e=localStorage.length-1;e>=0;e--){const s=localStorage.key(e);s?.startsWith(t)&&localStorage.removeItem(s)}for(let e=sessionStorage.length-1;e>=0;e--){const s=sessionStorage.key(e);s?.startsWith(t)&&sessionStorage.removeItem(s)}}},this.options=t,this.storageNamespace=`djvlc:${t.context.appId}`}async navigate(t){this.log("debug","Navigate:",t),this.track({eventName:"djvlc_navigate",params:{to:t.to,type:t.type},type:"click"});let e=t.to;if(t.query){const s=new URLSearchParams(t.query);e+=(e.includes("?")?"&":"?")+s.toString()}switch(t.type){case"external":t.newWindow?window.open(e,"_blank","noopener,noreferrer"):window.location.href=e;break;case"replace":window.location.replace(e);break;default:t.newWindow?window.open(e,"_blank"):window.location.href=e}}track(t){this.log("debug","Track event:",t);const e=this.options.context;this.options.userApiAdapter.track({eventName:t.eventName,params:t.params,type:t.type||"custom",timestamp:Date.now(),context:{pageVersionId:e.pageVersionId,runtimeVersion:e.runtimeVersion,userId:e.userId,deviceId:e.deviceId,channel:e.channel,appId:e.appId,env:e.env}})}async requestData(t,e){this.log("debug",`Requesting data: ${t}`,e);const s=performance.now(),i=this.options.context;try{const n=await this.options.userApiAdapter.executeQuery({queryVersionId:t,params:e??{},context:{pageVersionId:i.pageVersionId,uid:i.userId,deviceId:i.deviceId}}),r=performance.now()-s;if(this.log("debug",`Data query completed in ${r.toFixed(2)}ms`),!n.success)throw new Error(n.message||n.errorMessage||"Query failed");return this.options.stateManager.setQuery(t,n.data),n.data}catch(e){const i=performance.now()-s;throw this.log("error",`Data query failed: ${t} (${i.toFixed(2)}ms)`,e),e}}async executeAction(t,e={}){this.log("debug",`Executing action: ${t}`,e);const s=performance.now(),i=this.options.context,n=this.generateIdempotencyKey(t,e);this.track({eventName:"djvlc_action_start",params:{actionType:t,idempotencyKey:n},type:"custom"});try{const r=await this.options.userApiAdapter.executeAction({actionType:t,params:e||{},context:{pageVersionId:i.pageVersionId,uid:i.userId,deviceId:i.deviceId,channel:i.channel,appId:i.appId},idempotencyKey:n}),o=performance.now()-s;return this.log("debug",`Action completed in ${o.toFixed(2)}ms`,{success:r.success}),this.track({eventName:r.success?"djvlc_action_success":"djvlc_action_fail",params:{actionType:t,idempotencyKey:n,duration:Math.round(o),errorCode:r.errorCode},type:"custom"}),r}catch(e){const i=performance.now()-s;return this.log("error",`Action failed: ${t} (${i.toFixed(2)}ms)`,e),this.track({eventName:"djvlc_action_error",params:{actionType:t,idempotencyKey:n,duration:Math.round(i),errorMessage:e instanceof Error?e.message:"Unknown error"},type:"custom"}),{success:!1,errorCode:"NETWORK_ERROR",errorMessage:e instanceof Error?e.message:"Action failed"}}}async openDialog(t){return this.log("debug","Open dialog:",t),new Promise(e=>{const s=new CustomEvent("djvlc:openDialog",{detail:{options:t,resolve:t=>e(t)}});document.dispatchEvent(s),setTimeout(()=>{e({confirmed:!1})},6e4)})}closeDialog(t){this.log("debug","Close dialog:",t);const e=new CustomEvent("djvlc:closeDialog",{detail:{dialogId:t}});document.dispatchEvent(e)}showToast(t){this.log("debug","Show toast:",t);const e=document.createElement("div");switch(e.className=`djvlc-toast djvlc-toast-${t.type||"info"} djvlc-toast-${t.position||"top"}`,e.setAttribute("role","alert"),e.textContent=t.message,Object.assign(e.style,{position:"fixed",left:"50%",transform:"translateX(-50%)",padding:"12px 24px",borderRadius:"8px",color:"#fff",fontSize:"14px",zIndex:"10000",boxShadow:"0 4px 12px rgba(0,0,0,0.15)",transition:"opacity 0.3s, transform 0.3s",opacity:"0"}),e.style.backgroundColor={success:"#52c41a",error:"#ff4d4f",warning:"#faad14",info:"#1890ff"}[t.type||"info"],t.position){case"center":e.style.top="50%",e.style.transform="translate(-50%, -50%)";break;case"bottom":e.style.bottom="20px";break;default:e.style.top="20px"}document.body.appendChild(e),requestAnimationFrame(()=>{e.style.opacity="1"}),setTimeout(()=>{e.style.opacity="0",setTimeout(()=>e.remove(),300)},t.duration||3e3)}showLoading(t){this.loadingCount++,1===this.loadingCount&&(this.loadingElement=document.createElement("div"),this.loadingElement.className="djvlc-loading-overlay",this.loadingElement.innerHTML=`\n <div class="djvlc-loading-content">\n <div class="djvlc-loading-spinner"></div>\n <div class="djvlc-loading-message">${t||"加载中..."}</div>\n </div>\n `,Object.assign(this.loadingElement.style,{position:"fixed",top:"0",left:"0",right:"0",bottom:"0",backgroundColor:"rgba(0,0,0,0.5)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:"10001"}),document.body.appendChild(this.loadingElement))}hideLoading(){this.loadingCount=Math.max(0,this.loadingCount-1),0===this.loadingCount&&this.loadingElement&&(this.loadingElement.remove(),this.loadingElement=null)}async share(t){if(this.log("debug","Share:",t),navigator.share)try{return await navigator.share({title:t.title,text:t.description,url:t.url}),{success:!0,channel:"native"}}catch(t){if("AbortError"===t.name)return{success:!1,cancelReason:"User cancelled"};throw t}return t.url&&await this.clipboard.write(t.url)?(this.showToast({message:"链接已复制",type:"success"}),{success:!0,channel:"link"}):{success:!1,cancelReason:"Share not supported"}}async confirm(t){return this.log("debug","Confirm:",t),window.confirm(t.content)}async showActionSheet(t){return this.log("debug","Show action sheet:",t),new Promise(e=>{const s=new CustomEvent("djvlc:showActionSheet",{detail:{options:t,resolve:t=>e(t)}});document.dispatchEvent(s),setTimeout(()=>{e({cancelled:!0})},6e4)})}previewImage(t){this.log("debug","Preview image:",t);const e=new CustomEvent("djvlc:previewImage",{detail:t});document.dispatchEvent(e)}async scanCode(){return this.log("debug","Scan code"),new Promise(t=>{const e=new CustomEvent("djvlc:scanCode",{detail:{resolve:e=>t(e)}});document.dispatchEvent(e),setTimeout(()=>{t({success:!1,cancelReason:"Timeout"})},6e4)})}getState(t){return this.options.stateManager.getVariable(t)}setState(t,e){this.options.stateManager.setVariable(t,e)}getContext(){const t=this.options.context;return{pageVersionId:t.pageVersionId,componentVersionId:"",instanceId:"",userId:t.userId,deviceId:t.deviceId,channel:t.channel,appId:t.appId,env:t.env}}generateIdempotencyKey(t,e){const s=Date.now(),i=JSON.stringify(e||{});return`${t}:${s}:${this.simpleHash(i)}`}simpleHash(t){let e=0;for(let s=0;s<t.length;s++)e=(e<<5)-e+t.charCodeAt(s),e&=e;return Math.abs(e).toString(36)}fallbackCopy(t){const e=document.createElement("textarea");e.value=t,e.style.position="fixed",e.style.opacity="0",document.body.appendChild(e),e.select();try{return document.execCommand("copy"),!0}catch{return!1}finally{document.body.removeChild(e)}}log(t,e,...s){this.options.logger?this.options.logger[t](e,...s):this.options.debug}},E=class{constructor(t={}){this.blockedComponentsMap=new Map,this.blockedActionsSet=new Set,this.allowedCapabilitiesSet=null,this.options={enableSRI:!0,cdnDomains:[],apiDomains:[],blockedComponents:[],blockedActions:[],applyCSPOnInit:!1,...t},this.updateBlockedList(t.blockedComponents?.map(t=>`${t.name}@${t.version}`)||[],t.blockedActions||[]),t.allowedCapabilities&&(this.allowedCapabilitiesSet=new Set(t.allowedCapabilities)),t.applyCSPOnInit&&this.applyCSP()}updateBlockedList(t,e){this.blockedComponentsMap.clear(),t.forEach(t=>{const[e,s]=t.split("@");e&&s&&this.blockedComponentsMap.set(t,{name:e,version:s,reason:"Blocked by registry"})}),this.blockedActionsSet=new Set(e)}addBlockedComponent(t){const e=`${t.name}@${t.version}`;this.blockedComponentsMap.set(e,t),this.log("warn",`Component blocked: ${e} - ${t.reason}`)}removeBlockedComponent(t,e){const s=`${t}@${e}`;this.blockedComponentsMap.delete(s),this.log("info",`Component unblocked: ${s}`)}isComponentBlocked(t,e){return this.blockedComponentsMap.has(`${t}@${e}`)}getBlockedInfo(t,e){return this.blockedComponentsMap.get(`${t}@${e}`)}getAllBlockedComponents(){return Array.from(this.blockedComponentsMap.values())}isActionBlocked(t){return this.blockedActionsSet.has(t)}isCapabilityAllowed(t){return!this.allowedCapabilitiesSet||this.allowedCapabilitiesSet.has(t)}validateCapabilities(t,e,s){if(!this.allowedCapabilitiesSet)return{valid:!0,disallowed:[]};const i=s.filter(t=>!this.allowedCapabilitiesSet.has(t));return i.length>0&&this.log("warn",`Component ${t}@${e} uses disallowed capabilities: ${i.join(", ")}`),{valid:0===i.length,disallowed:i}}async validateIntegrity(t,e,s,i){if(!this.options.enableSRI)return;const[r,o]=i.split("-");if(!r||!o)throw new n(t,e,i,"Invalid integrity format");const a=await this.computeHash(s,r);if(a!==o)throw this.log("error",`Integrity check failed for ${t}@${e}`),new n(t,e,o,a);this.log("debug",`Integrity check passed for ${t}@${e}`)}async generateIntegrity(t,e="sha384"){return`${e}-${await this.computeHash(t,e)}`}isAllowedUrl(t,e){const s="cdn"===e?this.options.cdnDomains:this.options.apiDomains;if(!s||0===s.length)return!0;try{const e=new URL(t);return s.some(t=>{if(t.startsWith("*.")){const s=t.slice(2);return e.hostname.endsWith(s)||e.hostname===s.slice(1)}return e.hostname===t})}catch{return!1}}validateExternalUrl(t){try{const e=new URL(t);if(!["http:","https:"].includes(e.protocol))return{safe:!1,reason:`Unsafe protocol: ${e.protocol}`};const s=e.hostname;return"localhost"===s||"127.0.0.1"===s||s.startsWith("192.168.")||s.startsWith("10.")||s.startsWith("172.16.")?{safe:!1,reason:"Internal network address not allowed"}:{safe:!0}}catch{return{safe:!1,reason:"Invalid URL format"}}}generateCSPPolicy(){const t=this.options.cdnDomains||[],e=this.options.apiDomains||[],s=["'self'",...t].join(" "),i=["'self'",...e,...t].join(" ");return["default-src 'self'",`script-src ${s}`,`style-src ${["'self'","'unsafe-inline'",...t].join(" ")}`,`img-src ${["'self'","data:","blob:",...t].join(" ")}`,`font-src ${["'self'","data:",...t].join(" ")}`,`connect-src ${i}`,"frame-ancestors 'self'","base-uri 'self'","form-action 'self'","upgrade-insecure-requests"].join("; ")}applyCSP(){if(document.querySelector('meta[http-equiv="Content-Security-Policy"]'))return void this.log("debug","CSP meta tag already exists, skipping");const t=document.createElement("meta");t.httpEquiv="Content-Security-Policy",t.content=this.generateCSPPolicy(),document.head.appendChild(t),this.log("info","CSP policy applied")}assertNotBlocked(t,e){const s=this.getBlockedInfo(t,e);if(s)throw new r(t,e,s.reason)}createSafeEvaluator(){return(t,e)=>{const s=Object.keys(e),i=Object.values(e);return new Function(...s,`"use strict"; return (${t});`)(...i)}}async computeHash(t,e){const s=(new TextEncoder).encode(t),i=await crypto.subtle.digest(e.toUpperCase(),s),n=Array.from(new Uint8Array(i));return btoa(String.fromCharCode(...n))}log(t,e,...s){this.options.logger&&this.options.logger[t](e,...s)}},I=class{constructor(t){this.spans=new Map,this.metrics=[],this.errors=[],this.options={enabled:!0,sampleRate:1,batchSize:50,flushInterval:3e4,...t},this.traceId=this.generateTraceId(),this.shouldSample=Math.random()<(this.options.sampleRate??1),this.options.enabled&&this.options.endpoint&&this.startAutoFlush(),"undefined"!=typeof window&&(window.addEventListener("beforeunload",()=>this.flush()),window.addEventListener("visibilitychange",()=>{"hidden"===document.visibilityState&&this.flush()}))}getTraceId(){return this.traceId}getTraceparent(t){const e=t||this.generateSpanId(),s=this.shouldSample?"01":"00";return`00-${this.traceId}-${e}-${s}`}parseTraceparent(t){const e=t.split("-");if(4!==e.length)return null;const[,s,i,n]=e;return{traceId:s,parentSpanId:i,sampled:"01"===n}}startSpan(t,e,s){const i={spanId:this.generateSpanId(),traceId:this.traceId,parentSpanId:e,name:t,startTime:performance.now(),attributes:{pageVersionId:this.options.pageVersionId,...s}};return this.spans.set(i.spanId,i),this.log("debug",`Span started: ${t} (${i.spanId})`),i}endSpan(t,e="ok",s){const i=this.spans.get(t);if(i){i.endTime=performance.now(),i.status=e,s&&(i.attributes={...i.attributes,...s});const n=i.endTime-i.startTime;this.log("debug",`Span ended: ${i.name} (${t}) - ${n.toFixed(2)}ms [${e}]`)}}recordPageLoad(t){this.recordMetricInternal({type:"pageLoadTime",value:t,pageVersionId:this.options.pageVersionId,timestamp:Date.now()})}recordComponentLoad(t,e,s,i){this.recordMetricInternal({type:"componentLoadTime",value:s,pageVersionId:this.options.pageVersionId,componentName:t,componentVersion:e,timestamp:Date.now()}),i||this.recordError(new Error(`Component load failed: ${t}@${e}`),{componentVersion:`${t}@${e}`})}recordFirstRender(t){this.recordMetricInternal({type:"firstRenderTime",value:t,pageVersionId:this.options.pageVersionId,timestamp:Date.now()})}recordActionExecute(t,e,s,i){this.recordMetricInternal({type:"actionExecuteTime",value:s,pageVersionId:this.options.pageVersionId,actionType:t,timestamp:Date.now()}),i||this.recordError(new Error(`Action failed: ${t}`),{actionId:e})}recordQueryExecute(t,e,s,i=!1){this.recordMetricInternal({type:"queryFetchTime",value:e,pageVersionId:this.options.pageVersionId,queryId:t,timestamp:Date.now()}),this.log("debug",`Query ${t}: ${e.toFixed(2)}ms, cache: ${i}, success: ${s}`)}recordExpressionEval(t,e,s){e>1&&this.recordMetricInternal({type:"expressionEvalTime",value:e,pageVersionId:this.options.pageVersionId,timestamp:Date.now()})}recordError(t,e){const s={type:t.name||"Error",message:t.message,stack:t.stack,traceId:this.traceId,pageVersionId:this.options.pageVersionId,componentVersion:e?.componentVersion,actionId:e?.actionId,context:e,timestamp:Date.now()};this.errors.push(s),this.log("error",`Error recorded: ${t.message}`),this.options.onError?.(s),this.errors.length>=(this.options.batchSize??50)&&this.flush()}getMetrics(){return[...this.metrics]}getSpans(){return Array.from(this.spans.values())}getErrors(){return[...this.errors]}getPerformanceSummary(){const t=this.metrics.filter(t=>"componentLoadTime"===t.type),e=this.metrics.find(t=>"pageLoadTime"===t.type),s=this.metrics.find(t=>"firstRenderTime"===t.type);return{pageLoadTime:e?.value,firstRenderTime:s?.value,componentCount:t.length,avgComponentLoadTime:t.length>0?t.reduce((t,e)=>t+e.value,0)/t.length:0,errorCount:this.errors.length}}clear(){this.spans.clear(),this.metrics=[],this.errors=[]}async flush(){if(!this.shouldSample||!this.options.enabled)return;if(0===this.metrics.length&&0===this.errors.length&&0===this.spans.size)return;const t={traceId:this.traceId,pageVersionId:this.options.pageVersionId,appId:this.options.appId,runtimeVersion:this.options.runtimeVersion,spans:this.getSpans(),metrics:this.metrics,errors:this.errors,timestamp:Date.now()};if(this.clear(),this.options.endpoint)try{await fetch(this.options.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t),keepalive:!0}),this.log("debug","Telemetry flushed successfully")}catch(t){this.log("warn","Failed to flush telemetry:",t)}else this.log("debug","No endpoint configured, telemetry data discarded")}destroy(){this.flushTimer&&clearInterval(this.flushTimer),this.flush()}recordMetricInternal(t){this.metrics.push(t),this.options.onMetric?.(t),this.metrics.length>=(this.options.batchSize??50)&&this.flush()}startAutoFlush(){const t=this.options.flushInterval??3e4;this.flushTimer=setInterval(()=>this.flush(),t)}generateTraceId(){const t=new Uint8Array(16);return crypto.getRandomValues(t),Array.from(t,t=>t.toString(16).padStart(2,"0")).join("")}generateSpanId(){const t=new Uint8Array(8);return crypto.getRandomValues(t),Array.from(t,t=>t.toString(16).padStart(2,"0")).join("")}log(t,e,...s){this.options.logger?this.options.logger[t](e,...s):this.options.debug}},A=class t{constructor(t){this.container=null,this.renderedElements=new Map,this.componentEventListeners=new Map,this.expressionContext={state:{},binding:{},local:{}},this.loopContextStack=[],this.styleElement=null,this.options=t}init(){this.log("debug","Renderer initialized")}render(t,e){this.container=e,this.log("debug","Rendering page",t.pageId),this.cleanup(),e.innerHTML="",this.applyPageConfig(t,e),this.initializePageState(t);const s=this.renderNode(t.root);s&&e.appendChild(s),this.log("info",`Page rendered with root component: ${t.root.componentType}`)}updateComponent(t,e){const s=this.renderedElements.get(t);s?this.applyProps(s,e):this.log("warn",`Component not found: ${t}`)}updateContext(t){this.expressionContext={...this.expressionContext,...t}}getContext(){return{...this.expressionContext}}destroy(){this.cleanup(),this.container&&(this.container.innerHTML=""),this.log("debug","Renderer destroyed")}cleanup(){this.componentEventListeners.forEach((t,e)=>{const s=this.renderedElements.get(e);s&&t.forEach(({event:t,handler:e})=>{s.removeEventListener(t,e)})}),this.componentEventListeners.clear(),this.renderedElements.forEach(t=>{t.remove()}),this.renderedElements.clear(),this.styleElement&&(this.styleElement.remove(),this.styleElement=null),this.loopContextStack=[]}renderNode(t){const{id:e,componentType:s,componentVersion:i}=t;try{if(t.condition&&!this.evaluateCondition(t.condition))return this.log("debug",`Component ${e} hidden by condition`),null;if(t.loop)return this.renderLoop(t);const n=this.createElement(t);if(!n)return null;n.setAttribute("data-component-id",e),n.setAttribute("data-component-type",s),i&&n.setAttribute("data-component-version",i);const r=this.resolveProps(t.props);if(this.applyProps(n,r),t.style&&this.applyStyles(n,t.style),t.layout&&this.applyLayout(n,t.layout),this.options.injectHostApi(n,e),t.eventHandlers&&t.eventHandlers.length>0&&this.bindEventHandlers(n,e,t.eventHandlers),this.renderChildren(n,t),t.ref){const e=this.expressionContext.local,s=e.$refs||{};s[t.ref]=n,this.expressionContext={...this.expressionContext,local:{...e,$refs:s}}}return this.renderedElements.set(e,n),n}catch(t){return this.log("error",`Failed to render component: ${e}`,t),this.options.onRenderError?this.options.onRenderError(e,t):this.createErrorFallback(e,s,t)}}createElement(t){const{componentType:e}=t,s=this.options.components.get(e);if(s&&customElements.get(e))return document.createElement(e);const i=`${e}-${t.componentVersion?.replace(/\./g,"-")}`;if(customElements.get(i))return document.createElement(i);const n=document.createElement("div");return n.className=`djvlc-component djvlc-${e}`,s||(this.log("warn",`Component not loaded: ${e}`),n.classList.add("djvlc-component-fallback")),n}renderLoop(t){const{loop:e}=t;if(!e)return null;const s=this.evaluateExpression(e.items);if(!Array.isArray(s))return this.log("warn",`Loop items is not an array for ${t.id}`),null;const i=document.createDocumentFragment();s.forEach((s,n)=>{this.loopContextStack.push({item:s,index:n,loopConfig:e});const r={...this.expressionContext},o={...this.expressionContext.local,[e.itemName]:s,item:s,index:n};e.indexName&&(o[e.indexName]=n),this.expressionContext={...this.expressionContext,local:o};const a={...t,id:`${t.id}_${n}`,loop:void 0},c=this.renderNode(a);if(c){const t=this.evaluateExpression(e.key);c.setAttribute("data-loop-key",String(t??n)),i.appendChild(c)}this.expressionContext=r,this.loopContextStack.pop()});const n=document.createElement("div");return n.className="djvlc-loop-container",n.setAttribute("data-loop-id",t.id),n.appendChild(i),n}renderChildren(t,e){if(e.slots&&Object.keys(e.slots).length>0)for(const[s,i]of Object.entries(e.slots)){const e=this.createSlotContainer(s);for(const t of i){const s=this.renderNode(t);s&&e.appendChild(s)}t.appendChild(e)}}createSlotContainer(t){const e=document.createElement("div");return e.className=`djvlc-slot djvlc-slot-${t}`,e.setAttribute("data-slot",t),e}bindEventHandlers(t,e,s){const i=[];for(const n of s){const{eventName:s,preventDefault:r,stopPropagation:o,throttle:a,debounce:c,condition:h}=n;let l=t=>{if(h&&!this.evaluateCondition(h))return;r&&t.preventDefault(),o&&t.stopPropagation();const i=t.detail||{};this.options.onComponentEvent&&this.options.onComponentEvent(e,s,[n],i)};a&&a>0&&(l=this.createThrottledHandler(l,a)),c&&c>0&&(l=this.createDebouncedHandler(l,c)),t.addEventListener(s,l),i.push({event:s,handler:l})}this.componentEventListeners.set(e,i)}createThrottledHandler(t,e){let s=0;return i=>{const n=Date.now();n-s>=e&&(s=n,t(i))}}createDebouncedHandler(t,e){let s=null;return i=>{s&&clearTimeout(s),s=setTimeout(()=>{t(i),s=null},e)}}evaluateCondition(t){const e=this.evaluateExpression(t);return Boolean(e)}evaluateExpression(t){if(null==t)return t;if("object"==typeof t&&"type"in t&&"value"in t){const e=t,s=this.buildExpressionContext();return this.options.expressionEngine.evaluateWithFallback(e.value,s,e.fallback)}if("string"==typeof t){const e=this.buildExpressionContext();return this.options.expressionEngine.evaluateWithFallback(t,e,void 0)}return t}buildExpressionContext(){const t={};for(const e of this.loopContextStack)t[e.loopConfig.itemName]=e.item,t.item=e.item,t.index=e.index,e.loopConfig.indexName&&(t[e.loopConfig.indexName]=e.index);return{...this.expressionContext,local:{...this.expressionContext.local,...t}}}resolveProps(t){const e={};for(const[s,i]of Object.entries(t))e[s]=this.resolveValue(i);return e}resolveValue(e){if(null==e)return e;if("string"==typeof e)return e.includes("${")?this.options.expressionEngine.evaluateTemplate(e,this.buildExpressionContext()):e;if("number"==typeof e||"boolean"==typeof e)return e;if(Array.isArray(e))return e.map(t=>this.resolveValue(t));if("object"==typeof e){const s=e;if("string"==typeof s.type&&t.EXPRESSION_TYPES.includes(s.type)&&"string"==typeof s.value){const t=s;return this.options.expressionEngine.evaluateWithFallback(t.value,this.buildExpressionContext(),t.fallback)}const i={};for(const[t,e]of Object.entries(s))i[t]=this.resolveValue(e);return i}return e}applyProps(t,e){for(const[s,i]of Object.entries(e))null!=i&&(t.tagName.includes("-")?t[s]=i:"boolean"==typeof i?i?t.setAttribute(s,""):t.removeAttribute(s):"object"==typeof i?t.setAttribute(s,JSON.stringify(i)):t.setAttribute(s,String(i)))}applyStyles(t,e){if(e.inline)for(const[s,i]of Object.entries(e.inline)){if(null==i)continue;const e=this.resolveValue(i);let n;n="number"==typeof e?["zIndex","opacity","flex","fontWeight","lineHeight"].includes(s)?String(e):`${e}px`:String(e);const r=s.replace(/([A-Z])/g,"-$1").toLowerCase();t.style.setProperty(r,n)}e.className&&t.classList.add(...String(e.className).split(" ").filter(Boolean))}applyLayout(t,e){const{x:s,y:i,width:n,height:r,rotation:o,zIndex:a,responsive:c}=e;t.style.position="absolute",void 0!==s&&(t.style.left=`${s}px`),void 0!==i&&(t.style.top=`${i}px`),void 0!==n&&(t.style.width=`${n}px`),void 0!==r&&(t.style.height=`${r}px`),void 0!==o&&(t.style.transform=`rotate(${o}deg)`),void 0!==a&&(t.style.zIndex=String(a)),c&&this.applyResponsiveLayout(t,c)}applyResponsiveLayout(t,e){const s=t.getAttribute("data-component-id");if(!s)return;let i="";if(e.mobile&&(i+=`\n @media (max-width: 767px) {\n [data-component-id="${s}"] {\n ${this.layoutToCSS(e.mobile)}\n }\n }\n `),e.tablet&&(i+=`\n @media (min-width: 768px) and (max-width: 1023px) {\n [data-component-id="${s}"] {\n ${this.layoutToCSS(e.tablet)}\n }\n }\n `),e.desktop&&(i+=`\n @media (min-width: 1440px) {\n [data-component-id="${s}"] {\n ${this.layoutToCSS(e.desktop)}\n }\n }\n `),i){const t=document.createElement("style");t.setAttribute("data-djvlc-responsive",s),t.textContent=i,document.head.appendChild(t)}}layoutToCSS(t){const e=[];return void 0!==t.x&&e.push(`left: ${t.x}px`),void 0!==t.y&&e.push(`top: ${t.y}px`),void 0!==t.width&&e.push(`width: ${t.width}px`),void 0!==t.height&&e.push(`height: ${t.height}px`),void 0!==t.rotation&&e.push(`transform: rotate(${t.rotation}deg)`),void 0!==t.zIndex&&e.push(`z-index: ${t.zIndex}`),e.join("; ")}applyPageConfig(t,e){e.classList.add("djvlc-page"),e.setAttribute("data-page-id",t.pageId),e.setAttribute("data-page-version",t.pageVersion),e.setAttribute("data-schema-version",t.schemaVersion);const s=t.config;s&&(this.applyLayoutConfig(e,s.layout),s.styles&&this.applyStylesConfig(e,s.styles),s.behavior&&this.applyBehaviorConfig(e,s.behavior))}applyBehaviorConfig(t,e){e.debug&&t.setAttribute("data-debug","true"),e.i18n&&this.applyI18nConfig(t,e.i18n)}applyI18nConfig(t,e){const s=this.detectLocale(e);t.setAttribute("lang",s),t.setAttribute("data-locale",s),t.setAttribute("data-default-locale",e.defaultLocale),t.setAttribute("data-supported-locales",e.supportedLocales.join(",")),e.translationBundleId&&t.setAttribute("data-translation-bundle",e.translationBundleId),t.style.setProperty("--djvlc-locale",s),t.style.setProperty("--djvlc-dir",this.getTextDirection(s)),"rtl"===this.getTextDirection(s)?(t.setAttribute("dir","rtl"),t.classList.add("djvlc-rtl")):t.setAttribute("dir","ltr"),this.expressionContext={...this.expressionContext,local:{...this.expressionContext.local,$locale:s,$defaultLocale:e.defaultLocale,$supportedLocales:e.supportedLocales}},this.log("debug",`I18n configured: locale=${s}, default=${e.defaultLocale}`)}detectLocale(t){const{defaultLocale:e,supportedLocales:s,detection:i="browser"}=t;let n=null;switch(i){case"browser":case"header":n=this.detectBrowserLocale(s);break;case"url":n=this.detectUrlLocale(s);break;case"path":n=this.detectPathLocale(s);break;case"cookie":n=this.detectCookieLocale(s);break;case"manual":n=e;break;default:n=null}return n&&s.includes(n)?n:e}detectBrowserLocale(t){if("undefined"==typeof navigator)return null;const e=navigator.languages||[navigator.language];for(const s of e){if(t.includes(s))return s;const e=s.split("-")[0],i=t.find(t=>t===e||t.startsWith(`${e}-`));if(i)return i}return null}detectUrlLocale(t){if("undefined"==typeof window)return null;const e=new URLSearchParams(window.location.search),s=e.get("lang")||e.get("locale");return s&&t.includes(s)?s:null}detectPathLocale(t){if("undefined"==typeof window)return null;const e=window.location.pathname.split("/").filter(Boolean);if(e.length>0){const s=e[0];if(t.includes(s))return s}return null}detectCookieLocale(t){if("undefined"==typeof document)return null;const e=document.cookie.split(";");for(const s of e){const[e,i]=s.trim().split("=");if("lang"===e||"locale"===e||"language"===e){const e=decodeURIComponent(i);if(t.includes(e))return e}}return null}getTextDirection(t){const e=t.split("-")[0];return["ar","ar-SA","ar-EG","ar-AE","he","he-IL","fa","fa-IR","ur","ur-PK","yi","ps","dv"].some(s=>s===t||s===e)?"rtl":"ltr"}applyLayoutConfig(t,e){if(t.setAttribute("data-canvas-type",e.canvasType),e.canvasSize&&"responsive"!==e.canvasType&&(t.style.width=`${e.canvasSize.width}px`,t.style.minHeight=`${e.canvasSize.height}px`),e.maxWidth&&(t.style.maxWidth=`${e.maxWidth}px`,t.style.marginLeft="auto",t.style.marginRight="auto"),e.padding){const{top:s=0,right:i=0,bottom:n=0,left:r=0}=e.padding;t.style.padding=`${s}px ${i}px ${n}px ${r}px`}e.viewport&&(e.viewport.mobile&&t.style.setProperty("--djvlc-breakpoint-mobile",`${e.viewport.mobile}px`),e.viewport.tablet&&t.style.setProperty("--djvlc-breakpoint-tablet",`${e.viewport.tablet}px`),e.viewport.desktop&&t.style.setProperty("--djvlc-breakpoint-desktop",`${e.viewport.desktop}px`))}applyStylesConfig(t,e){if(e.theme&&this.applyThemeConfig(t,e.theme),e.background&&this.applyBackgroundConfig(t,e.background),e.cssVariables)for(const[s,i]of Object.entries(e.cssVariables)){const e=s.startsWith("--")?s:`--${s}`;t.style.setProperty(e,i)}e.customCSS&&this.injectCustomCSS(e.customCSS)}applyThemeConfig(t,e){if(e.preset&&(t.setAttribute("data-theme",e.preset),"system"===e.preset)){const e=window.matchMedia("(prefers-color-scheme: dark)").matches;t.setAttribute("data-theme-resolved",e?"dark":"light")}if(e.variables)for(const[s,i]of Object.entries(e.variables)){const e=s.startsWith("--")?s:`--theme-${s}`;t.style.setProperty(e,i)}e.transition&&t.style.setProperty("--djvlc-theme-transition","all 0.3s ease")}applyBackgroundConfig(t,e){switch(e.type){case"color":t.style.backgroundColor=e.value;break;case"image":t.style.backgroundImage=`url(${e.value})`,t.style.backgroundSize=e.size||"cover",t.style.backgroundPosition=e.position||"center",t.style.backgroundRepeat=e.repeat||"no-repeat";break;case"gradient":t.style.backgroundImage=e.value}}injectCustomCSS(t){t.trim()&&(this.styleElement=document.createElement("style"),this.styleElement.setAttribute("data-djvlc-custom","true"),this.styleElement.textContent=t,document.head.appendChild(this.styleElement))}initializePageState(t){if(t.state&&t.state.fields){const e={};for(const[s,i]of Object.entries(t.state.fields))i&&"object"==typeof i&&(e[s]=i.initialValue);this.expressionContext={...this.expressionContext,state:e}}}createErrorFallback(t,e,s){const i=document.createElement("div");return i.className="djvlc-error-boundary",i.setAttribute("data-component-id",t),i.setAttribute("data-error","true"),i.innerHTML=`\n <div class="djvlc-error-content">\n <span class="djvlc-error-icon">⚠️</span>\n <span class="djvlc-error-message">组件渲染失败: ${e}</span>\n ${this.options.debug?`<pre class="djvlc-error-detail">${s.message}</pre>`:""}\n </div>\n `,i}log(t,e,...s){this.options.logger?this.options.logger[t](e,...s):this.options.debug}};A.EXPRESSION_TYPES=["state","binding","local","template","computed"];var C=A;function N(){customElements.get("djvlc-fallback")||customElements.define("djvlc-fallback",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).innerHTML='\n <style>\n :host {\n display: block;\n padding: 16px;\n background: #fff2f0;\n border: 1px solid #ffccc7;\n border-radius: 4px;\n color: #ff4d4f;\n font-size: 14px;\n }\n .title {\n font-weight: 600;\n margin-bottom: 8px;\n }\n .message {\n color: #666;\n }\n </style>\n <div class="title">组件加载失败</div>\n <div class="message"><slot>请刷新页面重试</slot></div>\n '}static get observedAttributes(){return["message","component-name"]}attributeChangedCallback(t,e,s){if("message"===t&&this.shadowRoot){const t=this.shadowRoot.querySelector(".message");t&&(t.textContent=s)}if("component-name"===t&&this.shadowRoot){const t=this.shadowRoot.querySelector(".title");t&&(t.textContent=`组件 ${s} 加载失败`)}}}),customElements.get("djvlc-blocked")||customElements.define("djvlc-blocked",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).innerHTML='\n <style>\n :host {\n display: block;\n padding: 16px;\n background: #fffbe6;\n border: 1px solid #ffe58f;\n border-radius: 4px;\n color: #faad14;\n font-size: 14px;\n }\n .icon {\n margin-right: 8px;\n }\n </style>\n <span class="icon">⚠️</span>\n <span>此组件已被暂停使用</span>\n '}}),customElements.get("djvlc-error-boundary")||customElements.define("djvlc-error-boundary",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).innerHTML="\n <style>\n :host {\n display: block;\n padding: 16px;\n background: #f5f5f5;\n border: 1px dashed #d9d9d9;\n border-radius: 4px;\n color: #999;\n font-size: 14px;\n text-align: center;\n }\n </style>\n <slot>渲染出错</slot>\n "}})}function j(t,e,s){const i=`djvlc-${"error"===t?"error-boundary":t}`,n=document.createElement(i);return e&&n.setAttribute("message",e),s&&n.setAttribute("component-name",s),n}var D=class{constructor(t){this.lifecycle=null,this.mounted=!1,this.destroyed=!1,this.cleanupFns=[],this.options=t}register(t){t?(this.lifecycle=t,this.log("debug","Lifecycle hooks registered",{onMounted:t.onMounted?.length??0,onBeforeUnmount:t.onBeforeUnmount?.length??0,onVisibilityChange:t.onVisibilityChange?.length??0}),t.onVisibilityChange&&t.onVisibilityChange.length>0&&this.setupVisibilityListener()):this.log("debug","No lifecycle hooks defined")}async triggerMounted(){this.mounted||this.destroyed||(this.mounted=!0,this.log("debug","Triggering onMounted lifecycle"),await this.executeLifecycleActions("mounted",this.lifecycle?.onMounted),this.options.onLifecycleEvent?.("mounted"))}async triggerBeforeUnmount(){this.mounted&&!this.destroyed&&(this.log("debug","Triggering onBeforeUnmount lifecycle"),await this.executeLifecycleActions("beforeUnmount",this.lifecycle?.onBeforeUnmount),this.options.onLifecycleEvent?.("beforeUnmount"))}async triggerVisibilityChange(t){if(!this.mounted||this.destroyed)return;this.log("debug","Triggering onVisibilityChange lifecycle",{isVisible:t});const e=this.options.getContext(),s={...e,local:{...e.local,$visible:t,$hidden:!t}};await this.executeLifecycleActionsWithContext("visibilityChange",this.lifecycle?.onVisibilityChange,s),this.options.onLifecycleEvent?.("visibilityChange",{isVisible:t})}async destroy(){this.destroyed||(await this.triggerBeforeUnmount(),this.cleanupFns.forEach(t=>t()),this.cleanupFns=[],this.destroyed=!0,this.lifecycle=null,this.log("debug","LifecycleManager destroyed"))}isMounted(){return this.mounted&&!this.destroyed}isDestroyed(){return this.destroyed}setupVisibilityListener(){const t=()=>{const t="visible"===document.visibilityState;this.triggerVisibilityChange(t).catch(t=>{this.log("error","Failed to handle visibility change",t)})};document.addEventListener("visibilitychange",t),this.cleanupFns.push(()=>{document.removeEventListener("visibilitychange",t)}),this.log("debug","Visibility listener registered")}async executeLifecycleActions(t,e){if(!e||0===e.length)return;const s=this.options.getContext();await this.executeLifecycleActionsWithContext(t,e,s)}async executeLifecycleActionsWithContext(t,e,s){if(e&&0!==e.length){this.log("debug",`Executing ${e.length} actions for ${t}`);try{const i={id:`lifecycle_${t}`,eventName:t,actions:e};await this.options.actionBridge.handleEvent(i,{lifecycle:t},s),this.log("debug",`Lifecycle ${t} actions completed`)}catch(e){this.log("error",`Failed to execute lifecycle ${t} actions`,e)}}}log(t,e,...s){this.options.logger?this.options.logger[t](e,...s):this.options.debug}},T=t.CURRENT_SCHEMA_VERSION,R="1.0.0",M=class{constructor(t){if(this.container=null,!t.pageId)throw new Error("pageId is required");if(this.options={channel:"prod",debug:!1,enableSRI:!0,env:"production",...t},this.logger=this.createLogger(),this.stateManager=new p,this.eventBus=new m({debug:t.debug,logger:this.logger}),this.expressionEngine=new S({debug:t.debug,logger:this.logger}),!t.userApiAdapter)throw new Error("userApiAdapter is required. Inject a UserApiAdapter implementation (e.g. from @djvlc/runtime-web or your host).");this.userApiAdapter=t.userApiAdapter,this.pageLoader=new h({apiBaseUrl:t.apiBaseUrl,userApiAdapter:this.userApiAdapter,channel:t.channel,previewToken:t.previewToken,headers:t.headers,logger:this.logger}),this.componentLoader=new u({cdnBaseUrl:t.cdnBaseUrl,enableSRI:t.enableSRI,headers:t.headers,logger:this.logger}),this.assetLoader=new d({cdnHosts:[new URL(t.cdnBaseUrl).host],apiHosts:[new URL(t.apiBaseUrl).host]}),this.securityManager=new E({enableSRI:t.enableSRI,cdnDomains:[new URL(t.cdnBaseUrl).host],apiDomains:[new URL(t.apiBaseUrl).host],logger:this.logger}),this.log("info","Runtime created",{version:R})}async init(){this.log("info","Initializing runtime");const t=performance.now();try{this.container=this.resolveContainer(),this.assetLoader.preconnectAll(),this.pageLoader.preconnect(),N(),this.stateManager.setPhase("resolving");const e=performance.now()-t;this.log("info",`Runtime initialized in ${e.toFixed(2)}ms`)}catch(t){throw this.handleError(t),t}}async loadFromResolved(t){this.log("info","Loading from resolved page:",t.pageId);const e=performance.now();try{if(this.stateManager.setPhase("resolving"),this.validateSchemaVersion(t.pageJson),this.stateManager.setPage(t),this.telemetryManager=new I({pageVersionId:t.pageVersionId,appId:this.options.appId,debug:this.options.debug,logger:this.logger,onMetric:this.options.onMetric}),t.runtimeConfig){const e=t.runtimeConfig.blockedComponents?.map(t=>`${t.name}@${t.version}`)||[];this.securityManager.updateBlockedList(e,[]),this.componentLoader.updateBlockedList(e)}this.stateManager.setPhase("loading"),this.componentLoader.preload(t.manifest.components),(await this.componentLoader.loadAll(t.manifest)).forEach((t,e)=>{this.stateManager.setComponentStatus(e,t),this.telemetryManager.recordComponentLoad(t.name,t.version,t.loadTime||0,"loaded"===t.status)}),this.initHostApi(t),this.initActionBridge(),this.initDataBindingManager(t.pageJson),this.initRenderer(),this.initLifecycleManager(t.pageJson);const s=performance.now()-e;return this.telemetryManager.recordPageLoad(s),this.log("info",`Page loaded from resolved in ${s.toFixed(2)}ms`),this.emitEvent("page:loaded",{page:t,loadTime:s}),this.options.onLoad?.(t),t}catch(t){throw this.stateManager.setPhase("error"),this.handleError(t),t}}setPrefetchedData(t){for(const[e,s]of Object.entries(t))this.stateManager.setQuery(e,s)}async load(){this.log("info","Loading page:",this.options.pageId);const t=performance.now();try{this.stateManager.setPhase("resolving");const e=await this.pageLoader.resolve(this.options.pageId,{uid:this.options.userId,deviceId:this.options.deviceId});if(this.validateSchemaVersion(e.pageJson),this.stateManager.setPage(e),this.telemetryManager=new I({pageVersionId:e.pageVersionId,appId:this.options.appId,debug:this.options.debug,logger:this.logger,onMetric:this.options.onMetric}),e.runtimeConfig){const t=e.runtimeConfig.blockedComponents?.map(t=>`${t.name}@${t.version}`)||[];this.securityManager.updateBlockedList(t,[]),this.componentLoader.updateBlockedList(t)}this.stateManager.setPhase("loading"),this.componentLoader.preload(e.manifest.components),(await this.componentLoader.loadAll(e.manifest)).forEach((t,e)=>{this.stateManager.setComponentStatus(e,t),this.telemetryManager.recordComponentLoad(t.name,t.version,t.loadTime||0,"loaded"===t.status)}),this.initHostApi(e),this.initActionBridge(),this.initDataBindingManager(e.pageJson),this.initRenderer(),this.initLifecycleManager(e.pageJson);const s=performance.now()-t;return this.telemetryManager.recordPageLoad(s),this.log("info",`Page loaded in ${s.toFixed(2)}ms`),this.emitEvent("page:loaded",{page:e,loadTime:s}),this.options.onLoad?.(e),e}catch(t){throw this.stateManager.setPhase("error"),this.handleError(t),t}}async render(){const t=this.stateManager.getState();if(!t.page||!this.container)throw new s("Page not loaded");this.log("info","Rendering page");const e=performance.now();try{this.stateManager.setPhase("rendering"),this.renderer.updateContext(this.stateManager.getExpressionContext()),this.renderer.render(t.page.pageJson,this.container),await this.dataBindingManager.initializeBindings(this.stateManager.getExpressionContext()),this.stateManager.setPhase("ready");const s=performance.now()-e;this.telemetryManager.recordFirstRender(s),this.log("info",`Page rendered in ${s.toFixed(2)}ms`),await this.lifecycleManager.triggerMounted(),this.emitEvent("page:rendered",{renderTime:s})}catch(t){throw this.stateManager.setPhase("error"),this.handleError(t),t}}getHostApi(){return this.hostApi}getState(){return this.stateManager.getState()}onStateChange(t){return this.stateManager.subscribe(t)}on(t,e){return this.eventBus.on(t,e)}updateComponent(t,e){this.renderer.updateComponent(t,e)}setVariable(t,e){this.stateManager.setVariable(t,e),this.renderer.updateContext(this.stateManager.getExpressionContext()),this.dataBindingManager.onStateChange(t,this.stateManager.getExpressionContext())}getVariable(t){return this.stateManager.getVariable(t)}async refreshData(t){await this.dataBindingManager.refreshBinding(t,this.stateManager.getExpressionContext()),this.renderer.updateContext(this.stateManager.getExpressionContext())}async executeAction(t,e){return this.hostApi.executeAction(t,e)}async destroy(){this.log("info","Destroying runtime"),await(this.lifecycleManager?.destroy()),this.telemetryManager?.flush(),this.dataBindingManager?.destroy(),this.actionBridge?.destroy(),this.renderer?.destroy(),this.eventBus.clear(),this.stateManager.setDestroyed(),this.container&&(this.container.innerHTML=""),this.emitEvent("page:destroyed",{}),this.log("info","Runtime destroyed")}validateSchemaVersion(t){if(t.schemaVersion!==T)throw new s(`Unsupported schema version: ${t.schemaVersion}. Only ${T} is supported.`,{schemaVersion:t.schemaVersion,supportedVersion:T})}resolveContainer(){const{container:t}=this.options;if("string"==typeof t){const e=document.querySelector(t);if(!e)throw new Error(`Container not found: ${t}`);return e}return t}initHostApi(t){this.hostApi=new k({userApiAdapter:this.userApiAdapter,stateManager:this.stateManager,eventBus:this.eventBus,expressionEngine:this.expressionEngine,context:{pageId:t.pageId,pageVersionId:t.pageVersionId,runtimeVersion:R,userId:this.options.userId,deviceId:this.options.deviceId,channel:this.options.channel,appId:this.options.appId||"",env:this.options.env||"production",isEditMode:!1,isPreviewMode:t.isPreview||!1},debug:this.options.debug,logger:this.logger})}initActionBridge(){this.actionBridge=new y({executor:{executeAction:(t,e)=>this.hostApi.executeAction(t,e),requestData:(t,e)=>this.hostApi.requestData(t,e),navigate:t=>this.hostApi.navigate(t),openDialog:t=>this.hostApi.openDialog(t),closeDialog:()=>this.hostApi.closeDialog(),showToast:t=>this.hostApi.showToast(t),showLoading:t=>this.hostApi.showLoading(t),hideLoading:()=>this.hostApi.hideLoading(),track:t=>this.hostApi.track(t),setState:(t,e)=>this.stateManager.setVariable(t,e),getState:t=>this.stateManager.getVariable(t),refreshData:t=>this.refreshData(t)},expressionEngine:this.expressionEngine,debug:this.options.debug,logger:this.logger,onActionStart:(t,e)=>{this.emitEvent("action:executing",{action:t,params:e})},onActionComplete:(t,e)=>{e.success?this.emitEvent("action:executed",{action:t,data:e.data}):this.emitEvent("action:error",{action:t,error:e.error?.message})}})}initDataBindingManager(t){this.dataBindingManager=new f({requester:{requestData:(t,e)=>this.hostApi.requestData(t,e)},stateSetter:{setVariable:(t,e)=>this.stateManager.setVariable(t,e),getVariable:t=>this.stateManager.getVariable(t)},expressionEngine:this.expressionEngine,debug:this.options.debug,logger:this.logger,onDataLoaded:(t,e)=>{this.emitEvent("query:fetched",{bindingId:t,data:e}),this.renderer?.updateContext(this.stateManager.getExpressionContext())},onDataError:(t,e)=>{this.emitEvent("query:error",{bindingId:t,error:e.message})}}),t.dataBindings&&this.dataBindingManager.registerBindings(t.dataBindings),this.stateManager.onStateChange(({key:t})=>{this.dataBindingManager.onStateChange(t,this.stateManager.getExpressionContext())})}initLifecycleManager(t){this.lifecycleManager=new D({actionBridge:this.actionBridge,getContext:()=>this.stateManager.getExpressionContext(),debug:this.options.debug,logger:this.logger,onLifecycleEvent:(t,e)=>{this.emitEvent(`page:lifecycle:${t}`,e??{})}}),this.lifecycleManager.register(t.lifecycle)}initRenderer(){const t=new Map;this.stateManager.getState().components.forEach((e,s)=>{if("loaded"===e.status&&e.component){const[i,n]=s.split("@");t.set(i,{name:i,version:n,Component:e.component,loadTime:e.loadTime||0})}}),this.renderer=new C({expressionEngine:this.expressionEngine,components:t,injectHostApi:(t,e)=>{t.hostApi=this.hostApi,t.componentId=e},onComponentEvent:(t,e,s,i)=>{this.handleComponentEvent(t,e,s,i)},debug:this.options.debug,logger:this.logger,onRenderError:(t,e)=>(this.log("error",`Render error in ${t}:`,e),this.emitEvent("component:error",{componentId:t,error:e.message}),j("error",e.message))}),this.renderer.init()}handleComponentEvent(t,e,s,i){this.log("debug",`Component event: ${t}.${e}`,i);for(const t of s)this.actionBridge.handleEvent(t,i,this.stateManager.getExpressionContext())}handleError(t){const s=t instanceof e?{type:"LOAD_ERROR",message:t.message,code:t.code,details:t.details,traceId:t.traceId,timestamp:t.timestamp}:{type:"UNKNOWN_ERROR",message:t.message,cause:t,timestamp:Date.now()};this.stateManager.setError(s),this.telemetryManager?.recordError(t),this.emitEvent("page:error",{error:t.message}),this.options.onError&&this.options.onError(s)}emitEvent(t,e){const s=m.createEvent(t,e,this.telemetryManager?.getTraceId());this.eventBus.emit(s),this.options.onEvent&&this.options.onEvent(s)}createLogger(){return{debug:(...t)=>{this.options.debug},info:(...t)=>{},warn:(...t)=>{},error:(...t)=>{}}}log(t,e,...s){this.logger[t](e,...s)}};Object.defineProperty(exports,"ErrorCode",{enumerable:!0,get:function(){return t.ErrorCode}}),Object.defineProperty(exports,"ErrorMessages",{enumerable:!0,get:function(){return t.ErrorMessages}}),exports.ActionBridge=y,exports.ActionError=a,exports.AssetLoader=d,exports.BaseRenderer=C,exports.ComponentBlockedError=r,exports.ComponentLoadError=i,exports.ComponentLoader=u,exports.DjvlcRuntime=M,exports.DjvlcRuntimeError=e,exports.Evaluator=x,exports.EventBus=m,exports.ExpressionEngine=S,exports.ExpressionError=o,exports.HostAPIImpl=k,exports.IntegrityError=n,exports.Lexer=b,exports.LifecycleManager=D,exports.MockUserApiAdapter=class{constructor(t={}){this.calls={resolvePage:[],executeAction:[],executeQuery:[],track:[]},this.options={delay:0,...t}}async resolvePage(t){if(this.calls.resolvePage.push(t),await this.delay(),this.options.resolvePageThrow)throw this.options.resolvePageThrow;return(this.options.resolvePageResponse??this.options.mockPage)||{pageId:t.pageId,resolvedVersionId:"pv_mock",cdnBase:"https://cdn.mock.com",snapshotUrl:"https://cdn.mock.com/snapshot.json",manifestUrl:"https://cdn.mock.com/manifest.json",ops:{killSwitch:[],blockedComponents:[],flags:{}},etag:"mock-etag",cacheTtlSeconds:300}}async executeAction(t){return this.calls.executeAction.push(t),await this.delay(),this.options.mockActionResult?this.options.mockActionResult():{success:!0,data:{result:"mock"}}}async executeQuery(t){return this.calls.executeQuery.push(t),await this.delay(),this.options.mockQueryResult?this.options.mockQueryResult():{success:!0,data:{}}}track(t){this.calls.track.push(t)}delay(){const t=this.options.delay??0;return t<=0?Promise.resolve():new Promise(e=>setTimeout(e,t))}resetCalls(){this.calls={resolvePage:[],executeAction:[],executeQuery:[],track:[]}}},exports.PageLoadError=s,exports.PageLoader=h,exports.Parser=$,exports.QueryError=c,exports.RUNTIME_VERSION="1.0.0",exports.RenderError=class extends e{constructor(e,s,i,n){super(t.ErrorCode.SYSTEM_INTERNAL_ERROR,i,{...n,componentId:e,componentType:s}),this.name="RenderError",this.componentId=e,this.componentType=s}},exports.SCHEMA_VERSION=T,exports.SUPPORTED_SCHEMA_VERSION=T,exports.SecurityManager=E,exports.StateManager=p,exports.TelemetryManager=I,exports.builtinFunctions=w,exports.createFallbackElement=j,exports.createRuntime=function(t){return new M(t)},exports.registerFallbackComponents=N;