@finesoft/front 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +0,0 @@
1
- const e={FLOW:`flow`,EXTERNAL_URL:`externalUrl`,COMPOUND:`compound`};function t(t){return t.kind===e.FLOW}function n(t){return t.kind===e.EXTERNAL_URL}function r(t){return t.kind===e.COMPOUND}function i(t,n){return{kind:e.FLOW,url:t,presentationContext:n}}function a(t){return{kind:e.EXTERNAL_URL,url:t}}var o=class{handlers=new Map;onAction(e,t){if(this.handlers.has(e)){console.warn(`[ActionDispatcher] kind="${e}" already registered, skipping`);return}this.handlers.set(e,t)}removeAction(e){return this.handlers.delete(e)}async perform(e,t=0){if(r(e)){if(t>=32)throw Error(`[ActionDispatcher] CompoundAction recursion depth exceeded (max 32)`);for(let n of e.actions)await this.perform(n,t+1);return}let n=this.handlers.get(e.kind);if(!n){console.warn(`[ActionDispatcher] No handler for kind="${e.kind}"`);return}await n(e)}},s=class{controllers=new Map;register(e){this.controllers.set(e.intentId,e)}async dispatch(e,t){let n=this.controllers.get(e.id);if(!n)throw Error(`[IntentDispatcher] No controller for "${e.id}". Registered: [${Array.from(this.controllers.keys()).join(`, `)}]`);return n.perform(e,t)}has(e){return this.controllers.has(e)}},c=class e{registrations=new Map;resolutionStack=new Set;parent;children=new Set;register(e,t,n=!0){return this.registrations.set(e,{factory:t,singleton:n}),this}resolve(e){let t=this.registrations.get(e);if(!t){if(this.parent)return this.parent.resolve(e);throw Error(`[Container] No registration for key: "${e}"`)}if(t.singleton){if(t.instance===void 0){if(this.resolutionStack.has(e))throw Error(`[Container] Circular dependency detected: ${[...this.resolutionStack,e].join(` → `)}`);this.resolutionStack.add(e);try{t.instance=t.factory()}finally{this.resolutionStack.delete(e)}}return t.instance}return t.factory()}has(e){return this.registrations.has(e)||(this.parent?.has(e)??!1)}unregister(e){return this.registrations.delete(e)}createScope(){let t=new e;return t.parent=this,this.children.add(t),t}dispose(){let e=Array.from(this.children);for(let t of e)t.dispose();this.children.clear();for(let e of this.registrations.values())e.instance=void 0;this.registrations.clear(),this.parent&&=(this.parent.children.delete(this),void 0)}};function l(e){if(!e)return{ok:!1,reason:`empty host`};let t=e.toLowerCase(),n=t.startsWith(`[`)&&t.endsWith(`]`)?t.slice(1,-1):t;if(n===`localhost`||n.endsWith(`.localhost`))return{ok:!1,reason:`loopback host forbidden`};if(n.includes(`:`))return m(n);let r=d(n);return r?p(r):{ok:!0}}function u(e){let t;try{t=new URL(e)}catch{return{ok:!1,reason:`invalid URL`}}return t.protocol!==`http:`&&t.protocol!==`https:`?{ok:!1,reason:`scheme "${t.protocol}" not allowed (only http/https)`}:l(t.hostname)}function d(e){if(e.length===0)return null;if(!e.includes(`.`)){let t=f(e);return t===null||t<0||t>4294967295?null:[t>>>24&255,t>>>16&255,t>>>8&255,t&255]}let t=e.split(`.`);if(t.length!==4)return null;let n=[];for(let e of t){let t=f(e);if(t===null||t<0||t>255)return null;n.push(t)}return n}function f(e){if(e.length===0)return null;if(e.startsWith(`0x`)||e.startsWith(`0X`)){let t=e.slice(2);return/^[0-9a-f]+$/i.test(t)?parseInt(t,16):null}return e.length>1&&e.startsWith(`0`)?/^[0-7]+$/.test(e)?parseInt(e,8):null:/^[0-9]+$/.test(e)?parseInt(e,10):null}function p(e){let[t,n]=e;return t===0?{ok:!1,reason:`unspecified IPv4 forbidden`}:t===127?{ok:!1,reason:`loopback IPv4 forbidden`}:t===10?{ok:!1,reason:`private IPv4 (10/8) forbidden`}:t===172&&n>=16&&n<=31?{ok:!1,reason:`private IPv4 (172.16/12) forbidden`}:t===192&&n===168?{ok:!1,reason:`private IPv4 (192.168/16) forbidden`}:t===169&&n===254?{ok:!1,reason:`link-local IPv4 forbidden`}:t===100&&n>=64&&n<=127?{ok:!1,reason:`CGNAT IPv4 forbidden`}:t>=224&&t<=239?{ok:!1,reason:`multicast IPv4 forbidden`}:t>=240?{ok:!1,reason:`reserved IPv4 forbidden`}:{ok:!0}}function m(e){let t=e.toLowerCase();if(t===`::`||t===`::0`)return{ok:!1,reason:`unspecified IPv6 forbidden`};if(t===`::1`)return{ok:!1,reason:`loopback IPv6 forbidden`};if(t.startsWith(`fe8`)||t.startsWith(`fe9`)||t.startsWith(`fea`)||t.startsWith(`feb`))return{ok:!1,reason:`link-local IPv6 forbidden`};if(t.startsWith(`fc`)||t.startsWith(`fd`))return{ok:!1,reason:`ULA IPv6 forbidden`};if(t.startsWith(`ff`))return{ok:!1,reason:`multicast IPv6 forbidden`};let n=h(t);if(n){let e=p(n);if(!e.ok)return{ok:!1,reason:`IPv4-in-IPv6 ${e.reason}`}}return{ok:!0}}function h(e){let t=e.match(/(?:^|:)((?:\d{1,3}\.){3}\d{1,3})$/);if(t){let e=d(t[1]);if(e)return e}let n=e.match(/(?:^|:)([0-9a-f]{1,4}):([0-9a-f]{1,4})$/);if(n&&(e.startsWith(`::ffff:`)||e.includes(`:ffff:`))){let e=parseInt(n[1],16),t=parseInt(n[2],16);return[e>>>8&255,e&255,t>>>8&255,t&255]}return null}var g=class extends Error{constructor(e,t,n){super(`HTTP ${e}: ${t}`),this.status=e,this.statusText=t,this.body=n,this.name=`HttpError`}},_=class extends Error{constructor(e,t){super(`Refused to fetch ${e}: ${t}`),this.url=e,this.reason=t,this.name=`HostGuardError`}},v=class{baseUrl;defaultHeaders;fetchFn;requestInterceptors;responseInterceptors;allowInternalHosts;validateDns;constructor(e){this.baseUrl=e.baseUrl,this.defaultHeaders=e.defaultHeaders??{},this.fetchFn=e.fetch??globalThis.fetch.bind(globalThis),this.requestInterceptors=[...e.requestInterceptors??[]],this.responseInterceptors=[...e.responseInterceptors??[]],this.allowInternalHosts=e.allowInternalHosts??!1,this.validateDns=e.validateDns??!0}useRequestInterceptor(e){return this.requestInterceptors.push(e),this}useResponseInterceptor(e){return this.responseInterceptors.push(e),this}async get(e,t){return this.request(`GET`,e,{params:t})}async post(e,t,n){return this.request(`POST`,e,{body:t,params:n})}async put(e,t,n){return this.request(`PUT`,e,{body:t,params:n})}async del(e,t){return this.request(`DELETE`,e,{params:t})}async request(e,t,n){let r=this.buildUrl(t,n?.params);this.allowInternalHosts||await this.enforceHostGuard(r);let i={...this.defaultHeaders,...n?.headers},a={method:e,headers:i};n?.body!==void 0&&(Object.keys(i).some(e=>e.toLowerCase()===`content-type`)||(i[`Content-Type`]=`application/json`),a.body=JSON.stringify(n.body));for(let e of this.requestInterceptors)a=await e(r,a);let o=await this.fetchFn(r,a);for(let e of this.responseInterceptors)o=await e(o,r);if(!o.ok){let e=await o.text().catch(()=>void 0);throw new g(o.status,o.statusText,e)}try{return await o.json()}catch(e){throw e instanceof SyntaxError?new g(o.status,`Invalid JSON response`,await o.text().catch(()=>void 0)):e}}buildUrl(e,t){let n=this.baseUrl.endsWith(`/`)?this.baseUrl.slice(0,-1):this.baseUrl,r=e.startsWith(`/`)?e:`/${e}`,i=new URL(`${n}${r}`,`http://placeholder`);if(t)for(let[e,n]of Object.entries(t))i.searchParams.set(e,n);return this.baseUrl.startsWith(`http`)?i.toString():`${i.pathname}${i.search}`}async enforceHostGuard(e){let t;try{t=new URL(e)}catch{return}let n=u(e);if(!n.ok)throw new _(e,n.reason);if(this.validateDns&&t.hostname&&!ee(t.hostname)){let n=await te(t.hostname);if(!n.ok)throw new _(e,n.reason)}}};function ee(e){return e.includes(`:`)?!0:/^[0-9.]+$/.test(e)||/^0x[0-9a-f]+$/i.test(e)}async function te(e){let t;try{let e=await import(`node:dns/promises`);t=e.default??e}catch{return{ok:!0}}let n=await Promise.allSettled([t.resolve4(e),t.resolve6(e)]),r=[];for(let e of n)e.status===`fulfilled`&&r.push(...e.value);if(r.length===0)return{ok:!0};for(let e of r){let t=u(`http://${e.includes(`:`)?`[${e}]`:e}/`);if(!t.ok)return{ok:!1,reason:`host resolves to ${e} (${t.reason})`}}return{ok:!0}}function y(e,t={}){let n=t.allowInternalHosts??!1,r=t.validateDns??!0;return async function(t,i){if(!n){let e=re(t);if(e&&ne(e)){let t=u(e);if(!t.ok)throw new _(e,t.reason);if(r){let t=new URL(e);if(t.hostname&&!ie(t.hostname)){let n=await ae(t.hostname);if(!n.ok)throw new _(e,n.reason)}}}}return e(t,i)}}function ne(e){try{return new URL(e),!0}catch{return!1}}function re(e){return typeof e==`string`?e:e instanceof URL?e.toString():typeof Request<`u`&&e instanceof Request?e.url:null}function ie(e){return e.includes(`:`)?!0:/^[0-9.]+$/.test(e)||/^0x[0-9a-f]+$/i.test(e)}async function ae(e){let t;try{let e=await import(`node:dns/promises`);t=e.default??e}catch{return{ok:!0}}let n;try{n=await t.lookup(e,{all:!0})}catch{return{ok:!0}}if(n.length===0)return{ok:!0};for(let{address:e}of n){let t=u(`http://${e.includes(`:`)?`[${e}]`:e}/`);if(!t.ok)return{ok:!1,reason:`host resolves to ${e} (${t.reason})`}}return{ok:!0}}const oe=new Set([`ar`,`arc`,`dv`,`fa`,`ha`,`he`,`khw`,`ks`,`ku`,`ps`,`ur`,`yi`]);function b(e){let t=e.split(`-`)[0].toLowerCase();return oe.has(t)}function x(e){return b(e)?`rtl`:`ltr`}function se(e){return{lang:e,dir:x(e)}}function ce(e,t){return{language:e,region:t,bcp47:t?`${e}-${t}`:e,dir:x(e)}}function le(e){document.documentElement.lang=e.lang,document.documentElement.dir=e.dir}function ue(e,t){let n=e.split(`?`)[0].match(/^\/([^/]+)(\/.*)?$/);if(!n)return null;let r=n[1],i=t.find(e=>e.toLowerCase()===r.toLowerCase());return i?{locale:i,strippedUrl:n[2]||`/`}:null}async function de(e,t){if(!e||!t)return;let n=await fe();if(n)return n(e,t)}async function fe(){if(typeof globalThis.__FINESOFT_I18N_LOADER__==`function`)return globalThis.__FINESOFT_I18N_LOADER__;if(typeof __FINESOFT_I18N_LOADER_SPECIFIER__==`string`)try{let e=await import(__FINESOFT_I18N_LOADER_SPECIFIER__),t=typeof e==`function`?e:typeof e?.loadMessages==`function`?e.loadMessages:void 0;return t?(globalThis.__FINESOFT_I18N_LOADER__=t,t):void 0}catch{return}}async function pe(e){let{locale:t,loadMessages:n,context:r}=e;if(!(!t||!r))return n?n(t,r):de(t,r)}function me(e,t){let n=Object.entries(e);if(n.length===0)return;if(typeof n[0][1]==`string`)return e;let r=e[t];if(!r)return;let i={};for(let[e,t]of Object.entries(r)){if(typeof t==`string`){i[e]=t;continue}for(let[n,r]of Object.entries(t))i[`${e}.${n}`]=r}return i}function he(e,t){return t?e.replace(/\{(\w+)\}/g,(e,n)=>{let r=t[n];return r===void 0?`{${n}}`:String(r)}):e}function ge(e){return e===1?`one`:`other`}function _e(e,t){return`${e}.${t}`}var ve=class{locale;messages;pluralRule;fallback;constructor(e){this.locale=e.locale,this.messages=e.messages,this.pluralRule=e.pluralRule??ge,this.fallback=e.fallback??(e=>e)}t(e,t){let n=this.messages[e];return n===void 0?this.fallback(e):he(n,t)}plural(e,t,n){let r=_e(e,this.pluralRule(t)),i={count:t,...n};return this.t(r,i)}},S=class{constructor(e){this.factories=e}loggerFor(e){return new C(this.factories.map(t=>t.loggerFor(e)))}},C=class{constructor(e){this.loggers=e}debug(...e){return this.callAll(`debug`,e)}info(...e){return this.callAll(`info`,e)}warn(...e){return this.callAll(`warn`,e)}error(...e){return this.callAll(`error`,e)}callAll(e,t){for(let n of this.loggers)n[e](...t);return``}},w=class{category;constructor(e){this.category=e}};const T={"*":4,debug:4,info:3,warn:2,error:1,off:0,"":0};let E,D;function ye(){if(globalThis.localStorage===void 0)return{};let e;try{e=globalThis.localStorage.getItem(`onyxLog`)}catch{return{}}if(!e)return{};if(e===D&&E)return E;D=e;let t={},n=e.split(`,`);for(let e of n){let[n,r]=e.trim().split(`=`);if(!n||r===void 0)continue;let i=T[r.toLowerCase()]??void 0;i!==void 0&&(n===`*`?t.defaultLevel=i:(t.named??={},t.named[n]=i))}return E=t,t}function O(e,t){let n=ye();if(n.defaultLevel===void 0&&!n.named)return!0;let r=T[t]??4;return n.named?.[e]===void 0?n.defaultLevel===void 0?!0:r<=n.defaultLevel:r<=n.named[e]}function be(){E=void 0,D=void 0}var k=class extends w{debug(...e){return O(this.category,`debug`)&&console.debug(`[${this.category}]`,...e),``}info(...e){return O(this.category,`info`)&&console.info(`[${this.category}]`,...e),``}warn(...e){return O(this.category,`warn`)&&console.warn(`[${this.category}]`,...e),``}error(...e){return console.error(`[${this.category}]`,...e),``}},A=class{loggerFor(e){return new k(e)}};const j={debug:0,info:1,warn:2,error:3};var M=class extends w{minPriority;report;constructor(e,t){super(e),this.minPriority=j[t.minLevel??`warn`],this.report=t.report}debug(...e){return this.maybeReport(`debug`,e),``}info(...e){return this.maybeReport(`info`,e),``}warn(...e){return this.maybeReport(`warn`,e),``}error(...e){return this.maybeReport(`error`,e),``}maybeReport(e,t){if(!(j[e]<this.minPriority))try{this.report(e,this.category,t)}catch(e){console.error(`[ReportingLogger] report callback threw:`,e)}}},N=class{options;constructor(e){this.options=e}loggerFor(e){return new M(e,this.options)}},P=class{prefix;constructor(e=`Metrics`){this.prefix=e}record(e,t){console.info(`[${this.prefix}:${e}]`,t??``)}async flush(){}destroy(){}};function F(e){let t=e??(typeof navigator<`u`?navigator.userAgent:``),n=t.toLowerCase();return{os:xe(n),browser:Se(n),engine:Ce(n),isMobile:/mobile|android|iphone|ipad|ipod/i.test(t),isTouch:typeof navigator<`u`&&`maxTouchPoints`in navigator?navigator.maxTouchPoints>0:!1}}function xe(e){return/iphone|ipad|ipod/.test(e)?`ios`:/android/.test(e)?`android`:/macintosh|mac os x/.test(e)?`macos`:/windows/.test(e)?`windows`:/linux/.test(e)?`linux`:`unknown`}function Se(e){return/edg\//.test(e)?`edge`:/opr\/|opera/.test(e)?`opera`:/samsungbrowser/.test(e)?`samsung`:/chrome|crios/.test(e)&&!/edg\//.test(e)?`chrome`:/firefox|fxios/.test(e)?`firefox`:/safari/.test(e)&&!/chrome/.test(e)?`safari`:`unknown`}function Ce(e){return/applewebkit/.test(e)&&!/chrome/.test(e)?`webkit`:/applewebkit/.test(e)&&/chrome/.test(e)?`blink`:/gecko\//.test(e)?`gecko`:`unknown`}const I={LOGGER:`logger`,LOGGER_FACTORY:`loggerFactory`,NET:`net`,STORAGE:`storage`,FEATURE_FLAGS:`featureFlags`,METRICS:`metrics`,FETCH:`fetch`,SAFE_FETCH:`safeFetch`,EVENT_RECORDER:`eventRecorder`,LOCALE:`locale`,PLATFORM:`platform`,TRANSLATOR:`translator`};var we=class{store=new Map;get(e){return this.store.get(e)}set(e,t){this.store.set(e,t)}delete(e){this.store.delete(e)}},Te=class{flags;providers=[];constructor(e={}){this.flags=e}addProvider(e){this.providers.push(e)}isEnabled(e){for(let t=this.providers.length-1;t>=0;t--)if(this.providers[t].isEnabled(e))return!0;return this.flags[e]===!0}getString(e){for(let t=this.providers.length-1;t>=0;t--){let n=this.providers[t].getString?.(e);if(n!==void 0)return n}let t=this.flags[e];return typeof t==`string`?t:void 0}getNumber(e){for(let t=this.providers.length-1;t>=0;t--){let n=this.providers[t].getNumber?.(e);if(n!==void 0)return n}let t=this.flags[e];return typeof t==`number`?t:void 0}},Ee=class{record(e,t){console.info(`[Metrics:${e}]`,t??``)}recordPageView(e,t){this.record(`PageView`,{page:e,...t})}recordEvent(e,t){this.record(`Event`,{name:e,...t})}};function L(e,t={}){let{_resolvedMessages:n}=t,{fetch:r=globalThis.fetch?.bind(globalThis),featureFlags:i={},featureFlagsProviders:a=[],reportCallback:o,eventRecorder:s,locale:c,platform:l}=t,u=new A,d=o?new S([u,new N({report:o})]):u;e.register(I.LOGGER_FACTORY,()=>d),e.register(I.LOGGER,()=>d.loggerFor(`framework`)),e.register(I.NET,()=>({fetch:(e,t)=>r(e,t)})),e.register(I.STORAGE,()=>new we);let f=new Te(i);for(let e of a)f.addProvider(e);if(e.register(I.FEATURE_FLAGS,()=>f),e.register(I.METRICS,()=>new Ee),e.register(I.EVENT_RECORDER,()=>s??new P),c&&e.register(I.LOCALE,()=>se(c)),c&&n){let t=me(n,c);t&&e.register(I.TRANSLATOR,()=>new ve({locale:c,messages:t}))}e.register(I.PLATFORM,()=>l??F(typeof navigator<`u`?navigator.userAgent:void 0)),e.register(I.FETCH,()=>r);let p=t.safeFetch??{};e.register(I.SAFE_FETCH,()=>y(r,p))}function R(e){return`container`in e?e.container:e}function De(e){return{key:e,set(t,n){R(t).register(e,()=>n)},get(t){let n=R(t);return n.has(e)?n.resolve(e):void 0},clear(t){return R(t).unregister(e)}}}function z(e){return{"~standard":{version:1,vendor:`finesoft`,validate:e}}}async function B(e,t){let n=await e[`~standard`].validate(t);return n.issues?{ok:!1,issues:n.issues}:{ok:!0,value:n.value}}function V(e){return Object.assign(Object.create(null),e)}var H=class{routes=[];constructor(e){this.debug=e}add(e,t,n){let r=typeof n==`string`?{renderMode:n}:n??{},i=[],a=e.split(/(\/:[\w]+\??)/).map(t=>{let n=t.match(/^\/:(\w+)(\?)?$/);if(n){if(i.includes(n[1]))throw Error(`[Router] Duplicate parameter name ":${n[1]}" in pattern "${e}"`);return i.push(n[1]),n[2]?`(?:/([^/]+))?`:`/([^/]+)`}return t.replace(/[.+?^${}()|[\]\\]/g,`\\$&`)}).join(``);return this.routes.push({pattern:e,intentId:t,regex:RegExp(`^${a}/?$`),paramNames:i,renderMode:r.renderMode,beforeGuards:r.beforeGuards,afterGuards:r.afterGuards,paramCodecs:r.paramCodecs,queryCodecs:r.queryCodecs}),this}async resolve(e){let{path:t,queryParams:n}=this.parseUrl(e);for(let r of this.routes){let a=t.match(r.regex);if(!a)continue;let o=V(),s=!0;for(let e=0;e<r.paramNames.length;e++){let t=r.paramNames[e],n=a[e+1],i=r.paramCodecs?.[t];if(i){let e=await B(i,n);if(!e.ok){this.debug?.(`[Router] route "${r.pattern}" skipped: path param "${t}" failed validation: ${e.issues[0]?.message??`invalid`}`),s=!1;break}e.value!==void 0&&(o[t]=e.value)}else n&&(o[t]=n)}if(s){if(r.queryCodecs)for(let e of Object.keys(r.queryCodecs)){let t=await B(r.queryCodecs[e],n[e]);if(!t.ok){this.debug?.(`[Router] route "${r.pattern}" skipped: query param "${e}" failed validation: ${t.issues[0]?.message??`invalid`}`),s=!1;break}t.value!==void 0&&(o[e]=t.value)}if(s){for(let e of Object.keys(n))!(e in o)&&!r.queryCodecs?.[e]&&(o[e]=n[e]);return{intent:{id:r.intentId,params:o},action:i(e),renderMode:r.renderMode,beforeGuards:r.beforeGuards,afterGuards:r.afterGuards}}}}return null}getRoutes(){return this.routes.map(e=>`${e.pattern} → ${e.intentId}`)}parseUrl(e){try{let t=new URL(e,`http://localhost`),n=V(Object.fromEntries(t.searchParams));return{path:t.pathname,queryParams:n}}catch{return{path:e.split(`?`)[0].split(`#`)[0],queryParams:V()}}}};const U=e=>({issues:[{message:e}]});function Oe(e={}){return z(t=>typeof t==`string`?e.minLength!==void 0&&t.length<e.minLength?U(`must be at least ${e.minLength} characters`):e.maxLength!==void 0&&t.length>e.maxLength?U(`must be at most ${e.maxLength} characters`):e.pattern&&!e.pattern.test(t)?U(`must match ${e.pattern}`):{value:t}:U(`expected a string`))}function ke(e,t){return t.min!==void 0&&e<t.min?U(`must be >= ${t.min}`):t.max!==void 0&&e>t.max?U(`must be <= ${t.max}`):null}function Ae(e={}){return z(t=>{if(typeof t!=`string`||!/^-?\d+$/.test(t))return U(`"${String(t)}" is not an integer`);let n=Number(t);return ke(n,e)??{value:n}})}function je(e={}){return z(t=>{if(typeof t!=`string`||!/^-?\d+(\.\d+)?$/.test(t))return U(`"${String(t)}" is not a number`);let n=Number(t);return ke(n,e)??{value:n}})}const Me=new Set([`true`,`1`]),Ne=new Set([`false`,`0`]);function Pe(){return z(e=>typeof e==`string`&&Me.has(e)?{value:!0}:typeof e==`string`&&Ne.has(e)?{value:!1}:U(`"${String(e)}" is not a boolean (true/false/1/0)`))}function Fe(e){return z(t=>typeof t==`string`&&e.includes(t)?{value:t}:U(`"${String(t)}" is not one of: ${e.join(`, `)}`))}const Ie=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;function Le(){return z(e=>typeof e==`string`&&Ie.test(e)?{value:e}:U(`"${String(e)}" is not a valid UUID`))}function Re(e){return z(t=>t===void 0?{value:void 0}:e[`~standard`].validate(t))}function ze(e,t){return z(n=>n===void 0?{value:t}:e[`~standard`].validate(n))}async function Be(e,t){for(let n of e){let e=await n(t);if(e.kind!==`next`)return e}return{kind:`next`}}async function Ve(e,t){for(let n of e){let e=await n(t);if(e.kind!==`next`)return e}return{kind:`next`}}const He=new WeakMap;function W(e){return G(e,new Set,0)}function G(e,t,n){if(e==null)return String(e);if(typeof e!=`object`)return JSON.stringify(e);let r=He.get(e);if(r!==void 0)return r;if(n>50)return`"[Max Depth]"`;if(t.has(e))return`"[Circular]"`;t.add(e);try{let r;if(Array.isArray(e))r=`[`+e.map(e=>G(e,t,n+1)).join(`,`)+`]`;else{let i=Object.keys(e).sort(),a=[];for(let r of i){let i=e[r];i!==void 0&&a.push(JSON.stringify(r)+`:`+G(i,t,n+1))}r=`{`+a.join(`,`)+`}`}return He.set(e,r),r}finally{t.delete(e)}}var K=class e{intents;constructor(e){this.intents=e}static fromArray(t){let n=new Map;for(let e of t)if(e.intent&&e.data!==void 0){let t=W(e.intent);n.set(t,e.data)}return new e(n)}static empty(){return new e(new Map)}get(e){let t=W(e),n=this.intents.get(t);if(n!==void 0)return this.intents.delete(t),n}has(e){return this.intents.has(W(e))}get size(){return this.intents.size}},Ue=class e{container;intentDispatcher;actionDispatcher;router;prefetchedIntents;beforeGuards=[];afterGuards=[];_logger;constructor(e,t){this.container=e,this.intentDispatcher=new s,this.actionDispatcher=new o,this.router=new H(e=>this.getLogger().debug(e)),this.prefetchedIntents=t}static create(t={}){let n=new c;L(n,t);let r=new e(n,t.prefetchedIntents??K.empty());return t.setupRoutes?.(r.router),r}getLogger(){return this._logger??=this.container.resolve(I.LOGGER)}async dispatch(e){let t=this.getLogger(),n=this.prefetchedIntents.get(e);return n===void 0?(t.debug(`[Framework] dispatch intent: ${e.id}`,e.params),this.intentDispatcher.dispatch(e,this.container)):(t.debug(`[Framework] re-using prefetched intent response for: ${e.id}`,e.params),n)}async perform(e){return this.getLogger().debug(`[Framework] perform action: ${e.kind}`),this.actionDispatcher.perform(e)}async routeUrl(e){return this.router.resolve(e)}didEnterPage(e){this.container.resolve(I.METRICS).recordPageView(e.pageType,{pageId:e.id,title:e.title})}getLocale(){return this.container.has(I.LOCALE)?this.container.resolve(I.LOCALE):void 0}getTranslator(){return this.container.has(I.TRANSLATOR)?this.container.resolve(I.TRANSLATOR):void 0}getPlatform(){return this.container.resolve(I.PLATFORM)}onAction(e,t){this.actionDispatcher.onAction(e,t)}registerIntent(e){this.intentDispatcher.register(e)}beforeLoad(e){this.beforeGuards.push(e)}afterLoad(e){this.afterGuards.push(e)}runBeforeLoad(e,t){return Be(t?.length?[...this.beforeGuards,...t]:this.beforeGuards,e)}runAfterLoad(e,t){return Ve(t?.length?[...this.afterGuards,...t]:this.afterGuards,e)}dispose(){this.container.dispose()}};const q=Symbol.for(`finesoft.publicFields`),We=[`id`,`pageType`,`title`,`description`,`url`];function Ge(e,t){return t===!0?(Object.defineProperty(e,q,{value:!0,enumerable:!1,configurable:!0,writable:!1}),e):(Object.defineProperty(e,q,{value:Object.freeze([...t]),enumerable:!1,configurable:!0,writable:!1}),e)}function Ke(e){return typeof e==`object`&&!!e&&e[q]!==void 0}function qe(e){if(typeof e!=`object`||!e)return null;let t=e[q];return t===void 0?null:t===!0?!0:Array.isArray(t)?t:null}function Je(){try{let e=globalThis.process?.env?.NODE_ENV;return e===void 0?!0:e===`production`}catch{return!0}}function Ye(e){if(e instanceof Error)return e.stack??`${e.name}: ${e.message}`;if(typeof e==`string`)return e;try{return JSON.stringify(e)}catch{return String(e)}}function Xe(e){let{status:t,publicMessage:n,devError:r,isProduction:i=Je()}=e,a=!i&&r!==void 0;return{id:`error`,pageType:`error`,title:`Error ${t}`,description:a?`${n}\n\n[dev only]\n${Ye(r)}`:n}}var Ze=class{fallback(e,t){throw t}async perform(e,t){let n=e.params??{};try{return await this.execute(n,t)}catch(e){return this.fallback(n,e instanceof Error?e:Error(String(e)))}}};function Qe(...e){return t=>e.reduce((e,t)=>t(e),t)}function $e(...e){return async t=>{let n=t;for(let t of e)n=await t(n);return n}}function et(e){return t=>t.map(e)}function tt(e,t){return{path:e,...t}}function nt(e,t,n){let r=new Set;for(let i of t){i.controller&&!r.has(i.intentId)&&(e.registerIntent(i.controller),r.add(i.intentId));let t={renderMode:i.renderMode,beforeGuards:i.beforeLoad,afterGuards:i.afterLoad,paramCodecs:i.params,queryCodecs:i.query};if(e.router.add(i.path,i.intentId,t),n?.locales?.length){let n=i.path===`/`?`/:locale`:`/:locale${i.path}`;e.router.add(n,i.intentId,t)}}}var rt=class{map=new Map;capacity;constructor(e){if(e<1)throw Error(`[LruMap] capacity must be >= 1, got ${e}`);this.capacity=e}get(e){if(!this.map.has(e))return;let t=this.map.get(e);return this.map.delete(e),this.map.set(e,t),t}set(e,t){if(this.map.has(e))this.map.delete(e);else if(this.map.size>=this.capacity){let e=this.map.keys().next().value;e!==void 0&&this.map.delete(e)}this.map.set(e,t)}has(e){return this.map.has(e)}delete(e){return this.map.delete(e)}get size(){return this.map.size}clear(){this.map.clear()}};function it(e){return e!=null}function at(e){return e==null}function ot(){return typeof window>`u`?`browser`:document.referrer.startsWith(`android-app://`)?`twa`:window.matchMedia(`(display-mode: standalone)`).matches||`standalone`in window.navigator&&window.navigator.standalone===!0?`standalone`:`browser`}function st(e){return e.replace(/^https?:\/\//,``)}function ct(e){try{let t=new URL(e);return t.pathname+t.search+t.hash}catch{return e}}function lt(e){return e.split(`?`)[0]}function ut(e){return e.split(`?`)[0].split(`#`)[0]}function dt(e,t){if(!t)return e;let n=new URLSearchParams;for(let[e,r]of Object.entries(t))r!==void 0&&n.set(e,r);let r=n.toString();return r?`${e}?${r}`:e}function J(){return typeof crypto<`u`&&crypto.randomUUID?crypto.randomUUID():`xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`.replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e===`x`?t:t&3|8).toString(16)})}function ft(e){let t=new Map;if(!e)return t;for(let n of e.split(`;`)){let e=n.indexOf(`=`);if(e===-1)continue;let r=n.slice(0,e).trim(),i=n.slice(e+1).trim();r&&t.set(r,i)}return t}function pt(e){let{url:t,intent:n,container:r,request:i}=e,a=new URL(t,`http://localhost`),o=ft(i?.headers.get(`cookie`)??``);return{url:t,path:a.pathname,params:n.params??{},intent:n,isServer:!0,container:r,getCookie:e=>o.get(e),getHeader:e=>i?.headers.get(e)??void 0}}function Y(e){let{url:t,intent:n,container:r}=e;return{url:t,path:new URL(t,window.location.origin).pathname,params:n.params??{},intent:n,isServer:!1,container:r,getCookie:e=>ft(document.cookie).get(e),getHeader:()=>void 0}}function mt(){return{kind:`next`}}function ht(e,t=302){return{kind:`redirect`,url:e,status:t}}function gt(e){return{kind:`rewrite`,url:e}}function _t(e=403,t=`Forbidden`){return{kind:`deny`,status:e,message:t}}var vt=class{recorders;constructor(e){this.recorders=e}record(e,t){for(let n of this.recorders)n.record(e,t)}async flush(){let e=[];for(let t of this.recorders)t.flush&&e.push(t.flush());await Promise.all(e)}destroy(){for(let e of this.recorders)e.destroy?.()}},yt=class{observer;tracked=new Map;captured=[];minDuration;constructor(e={}){this.minDuration=e.minVisibleDuration??1e3,this.observer=new IntersectionObserver(e=>{let t=Date.now();for(let n of e){let e=this.tracked.get(n.target);e&&(n.isIntersecting?e.visibleSince===null&&(e.visibleSince=t):e.visibleSince!==null&&(t-e.visibleSince>=this.minDuration&&this.captured.push({id:e.id,timestamp:e.visibleSince,metadata:e.metadata}),e.visibleSince=null))}},{threshold:e.threshold??.5})}observe(e,t,n){this.tracked.set(e,{id:t,metadata:n,visibleSince:null}),this.observer.observe(e)}unobserve(e){this.observer.unobserve(e),this.tracked.delete(e)}consume(){let e=Date.now();for(let[,t]of this.tracked)t.visibleSince!==null&&e-t.visibleSince>=this.minDuration&&(this.captured.push({id:t.id,timestamp:t.visibleSince,metadata:t.metadata}),t.visibleSince=e);return this.captured.splice(0)}destroy(){this.observer.disconnect(),this.tracked.clear(),this.captured.length=0}},bt=class{record(){}async flush(){}destroy(){}},xt=class{constructor(e,t){this.inner=e,this.providers=t}record(e,t){let n={};for(let e of this.providers)Object.assign(n,e.getFields());t&&Object.assign(n,t),this.inner.record(e,n)}async flush(){return this.inner.flush?.()}destroy(){this.inner.destroy?.()}};function St(t){let{framework:n,log:r}=t;n.onAction(e.EXTERNAL_URL,e=>{r.debug(`ExternalUrlAction → ${e.url}`),window.open(e.url,`_blank`,`noopener,noreferrer`)})}const X=5e3;let Z=null;function Q(){Z?.()}function Ct(e,t,n){Q();let r=Math.max(0,n),i=Date.now(),a=!1,o=null,s=null,c=null,l=null;Z=p,f(),document.addEventListener(`load`,u,!0),s=setInterval(u,100),c=setTimeout(u,X),u();function u(){a||o!==null||(o=requestAnimationFrame(()=>{o=null,d()}))}function d(){if(a)return;let n=Date.now()-i,o=t();if(!o){n>=X&&(e.warn(`tryScroll: timed out waiting for the scrollable element`,{target:r,elapsedMs:n}),p());return}o.scrollTop=r;let s=o.scrollTop;if(s>=r-2){e.info(`scroll restored`,{target:r,actual:s,elapsedMs:n}),p();return}n>=X&&(e.warn(`tryScroll: timed out before reaching the target`,{target:r,actual:s,elapsedMs:n,scrollHeight:o.scrollHeight,clientHeight:o.clientHeight}),p())}function f(){if(typeof MutationObserver>`u`)return;let e=document.body??document.documentElement;e&&(l=new MutationObserver(()=>{u()}),l.observe(e,{childList:!0,subtree:!0}))}function p(){a||(a=!0,Z===p&&(Z=null),o!==null&&(cancelAnimationFrame(o),o=null),s!==null&&(clearInterval(s),s=null),c!==null&&(clearTimeout(c),c=null),l?.disconnect(),l=null,document.removeEventListener(`load`,u,!0))}}var wt=class{entries;log;getScrollablePageElement;currentStateId;constructor(e,t,n=10){this.entries=new rt(n),this.log=e,this.getScrollablePageElement=t.getScrollablePageElement}replaceState(e,t){Q();let n=J();window.history.replaceState({id:n},``,t),this.currentStateId=n,this.entries.set(n,{state:e,scrollY:0}),this.scrollTop=0,this.log.info(`replaceState`,e,t,n)}pushState(e,t){Q();let n=J();window.history.pushState({id:n},``,t),this.currentStateId=n,this.entries.set(n,{state:e,scrollY:0}),this.scrollTop=0,this.log.info(`pushState`,e,t,n)}beforeTransition(){Q();let{state:e}=window.history;if(!e)return;let t=this.entries.get(e.id);if(!t){this.log.info(`current history state evicted from LRU, not saving scroll position`);return}let{scrollTop:n}=this;this.entries.set(e.id,{...t,scrollY:n}),this.log.info(`saving scroll position`,n)}onPopState(e){window.addEventListener(`popstate`,t=>{Q(),this.currentStateId=t.state?.id,this.currentStateId||this.log.warn(`encountered a null event.state.id in onPopState event:`,window.location.href),this.log.info(`popstate`,this.entries,this.currentStateId);let n=this.currentStateId?this.entries.get(this.currentStateId):void 0;if(Promise.resolve(e(window.location.href,n?.state)).catch(e=>{this.log.error(`onPopState listener error:`,e)}),!n)return;let{scrollY:r}=n;this.log.info(`restoring scroll to`,r),Ct(this.log,()=>this.getScrollablePageElement(),r)})}pushUrl(e){Q();let t=J();window.history.pushState({id:t},``,e),this.currentStateId=t,this.scrollTop=0,this.log.info(`pushUrl (no state)`,e,t)}replaceUrl(e){Q();let t=J();window.history.replaceState({id:t},``,e),this.currentStateId=t,this.scrollTop=0,this.log.info(`replaceUrl (no state)`,e,t)}updateState(e){if(!this.currentStateId){this.log.warn(`failed: encountered a null currentStateId inside updateState`);return}let t=this.entries.get(this.currentStateId),n=e(t?.state);this.log.info(`updateState`,n,this.currentStateId),this.entries.set(this.currentStateId,{scrollY:t?.scrollY??0,state:n})}get scrollTop(){return this.getScrollablePageElement()?.scrollTop||0}set scrollTop(e){let t=this.getScrollablePageElement();t&&(t.scrollTop=e)}};function Tt(t){let{framework:n,log:r,callbacks:i,updateApp:a}=t,o=!0,s=0,c=new wt(r,{getScrollablePageElement:t.getScrollablePageElement??(()=>document.getElementById(`scrollable-page-override`)||document.getElementById(`scrollable-page`)||document.documentElement)});async function l(e,t,d){if(t>=5){r.error(`Navigation redirect loop detected (5 redirects), stopping at: ${e}`);return}let f=o||e===window.location.pathname+window.location.search,p=await n.routeUrl(e);if(!p){r.warn(`FlowAction: no route for ${e}`);return}let m=Y({url:e,intent:p.intent,container:n.container}),h=await n.runBeforeLoad(m,p.beforeGuards);if(h.kind===`redirect`){r.debug(`beforeLoad → redirect to ${h.url}`),await l(h.url,t+1,d);return}if(h.kind===`deny`){r.warn(`beforeLoad → denied (${h.status}): ${h.message}`);return}if(h.kind===`rewrite`){r.debug(`beforeLoad → rewrite to ${h.url}`),await l(h.url,t+1,d);return}let g=n.dispatch(p.intent);if(await Promise.race([g,new Promise(e=>setTimeout(e,500))]).catch(()=>{}),d!==s){r.info(`FlowAction superseded by newer navigation`,e);return}c.beforeTransition(),a({page:g.then(async a=>{if(d!==s)return r.info(`FlowAction commit superseded`,e),a;let o={...m,page:a},h=await n.runAfterLoad(o,p.afterGuards);if(h.kind===`redirect`)return r.debug(`afterLoad → redirect to ${h.url}`),l(h.url,t+1,d),a;let g=e;return h.kind===`rewrite`&&(g=h.url,r.debug(`afterLoad → rewrite URL to ${g}`)),h.kind===`deny`?(r.warn(`afterLoad → denied (${h.status})`),a):(f?c.replaceState({page:a},g):c.pushState({page:a},g),i.onNavigate(new URL(g,window.location.origin).pathname),u(a),a)},t=>{if(d===s){let t=e;f?c.replaceUrl(t):c.pushUrl(t),i.onNavigate(new URL(t,window.location.origin).pathname)}throw t}),isFirstPage:o}),o=!1}n.onAction(e.FLOW,async e=>{let t=e,a=t.url;if(r.debug(`FlowAction → ${a}`),t.presentationContext===`modal`){let e=await n.routeUrl(a);if(e){let t=await n.dispatch(e.intent);i.onModal(t)}return}await l(a,0,++s)}),c.onPopState(async(e,t)=>{if(r.debug(`popstate → ${e}, cached=${!!t}`),i.onNavigate(new URL(e).pathname),t){let{page:e}=t;u(e),a({page:e,isFirstPage:o});return}let c=new URL(e),d=await n.routeUrl(c.pathname+c.search);if(!d){r.error(`received popstate without data, but URL was unroutable:`,e),u(null),a({page:Promise.reject(Error(`404`)),isFirstPage:o});return}let f=Y({url:c.pathname+c.search,intent:d.intent,container:n.container}),p=await n.runBeforeLoad(f,d.beforeGuards);if(p.kind===`redirect`){r.debug(`popstate beforeLoad → redirect to ${p.url}`);let e=++s;await l(p.url,0,e);return}if(p.kind===`deny`||p.kind===`rewrite`){if(p.kind===`deny`)r.warn(`popstate beforeLoad → denied`);else{let e=++s;await l(p.url,0,e)}return}let m=n.dispatch(d.intent);await Promise.race([m,new Promise(e=>setTimeout(e,500))]).catch(()=>{}),a({page:m.then(async e=>{let t={...f,page:e},a=await n.runAfterLoad(t,d.afterGuards);if(a.kind===`redirect`){r.debug(`popstate afterLoad → redirect to ${a.url}`);let t=++s;return l(a.url,0,t),e}if(a.kind===`rewrite`){r.debug(`popstate afterLoad → rewrite URL to ${a.url}`);let t=window.history.state?.id;return window.history.replaceState({id:t},``,a.url),i.onNavigate(new URL(a.url,window.location.origin).pathname),u(e),e}return a.kind===`deny`?(r.warn(`popstate afterLoad → denied (${a.status})`),e):(u(e),e)}),isFirstPage:o})});function u(e){(async()=>{try{e&&n.didEnterPage(e)}catch(e){r.error(`didEnterPage error:`,e)}})()}}function $(e){let{framework:t,log:n,callbacks:r,updateApp:i}=e;Tt({framework:t,log:n,callbacks:r,updateApp:i,getScrollablePageElement:e.getScrollablePageElement}),St({framework:t,log:n})}function Et(){let e=document.getElementById(`serialized-server-data`);if(e?.textContent){e.parentNode?.removeChild(e);try{return JSON.parse(e.textContent)}catch{return}}}function Dt(){let e=Et();return!e||!Array.isArray(e)?K.empty():K.fromArray(e)}async function Ot(e){let{bootstrap:t,mountId:n=`app`,mount:r,callbacks:i,onBeforeStart:a,onAfterStart:o,frameworkConfig:s={},loadMessages:c}=e,l=Dt(),u=window.location.pathname+window.location.search,d=kt(s.locale),f=await pe({locale:d,loadMessages:c,context:d?{runtime:`browser`,fetch:At(s.fetch),url:u}:void 0}),p=Ue.create({...s,locale:d,_resolvedMessages:f,prefetchedIntents:l});t(p);let m=p.container.resolve(I.LOGGER_FACTORY).loggerFor(`browser`),h=p.getLocale();h&&(le(h),m.debug(`[startBrowserApp] Applied locale attributes:`,h)),await a?.(p);let g=await p.routeUrl(u),_=document.getElementById(n);if(!_)throw Error(`[startBrowserApp] Mount target not found: #${n}. Ensure your HTML has <div id="${n}"></div>.`);let v=r(_,{framework:p});$({framework:p,log:m,callbacks:i,updateApp:v,getScrollablePageElement:e.getScrollablePageElement}),g?await p.perform(g.action):v({page:Promise.reject(Error(`404`)),isFirstPage:!0}),await o?.(p)}function kt(e){return e||document.documentElement.lang.trim()||void 0}function At(e){return(e??globalThis.fetch?.bind(globalThis))||(()=>{throw Error(`[startBrowserApp] loadMessages requires a fetch implementation.`)})}export{Le as $,tt as A,_ as At,Ge as B,n as Bt,lt as C,se as Ct,it as D,ue as Dt,at as E,ce as Et,Xe as F,c as Ft,Be as G,K as H,a as Ht,We as I,s as It,Pe as J,Re as K,q as L,o as Lt,Qe as M,g as Mt,$e as N,l as Nt,rt as O,le as Ot,Ze as P,u as Pt,Oe as Q,qe as R,e as Rt,ct as S,me as St,ot as T,b as Tt,W as U,i as Ut,Ue as V,t as Vt,Ve as W,je as X,Ae as Y,Fe as Z,Y as _,ve as _t,Tt as a,L as at,dt as b,_e as bt,St as c,M as ct,yt as d,A as dt,H as et,vt as f,be as ft,gt as g,S as gt,ht as h,C as ht,$ as i,I as it,et as j,v as jt,nt as k,y as kt,xt as l,N as lt,mt as m,w as mt,Dt as n,B as nt,wt as o,F as ot,_t as p,O as pt,ze as q,Et as r,De as rt,Ct as s,P as st,Ot as t,z as tt,bt as u,k as ut,pt as v,ge as vt,st as w,x as wt,ut as x,pe as xt,J as y,he as yt,Ke as z,r as zt};
2
- //# sourceMappingURL=start-app-S4DH-40i.mjs.map