@coreframe/vite 0.2.27 → 0.2.28

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/client.d.ts CHANGED
@@ -13,12 +13,16 @@ interface ImportMeta {
13
13
 
14
14
  declare module "virtual:coreframe-shell" {
15
15
  export const shell: import("@coreframe/lib/shell").CoreframeShell
16
+ export const DocumentScrollLock: typeof import("@coreframe/lib/document-scroll-lock").DocumentScrollLock
16
17
  export const ShellHost: (props: Record<string, never>) => import("react").ReactNode
17
18
  export const NativeRouteLink: (
18
19
  props: import("@coreframe/lib/shell").NativeRouteLinkProps,
19
20
  ) => import("react").ReactNode
20
- export type NativeSurfaceProps = import("@coreframe/flutter-js/composition").NativeSurfaceProps
21
- export const NativeSurface: (props: NativeSurfaceProps) => import("react").ReactNode
21
+ export type NativeSurfaceProps<SurfaceId extends string = string> =
22
+ import("@coreframe/flutter-js/composition").NativeSurfaceProps<SurfaceId>
23
+ export const NativeSurface: (
24
+ props: import("@coreframe/flutter-js/composition").NativeSurfacePropsForRegistry,
25
+ ) => import("react").ReactNode
22
26
  export function configureShellClient(): void
23
27
  }
24
28
 
@@ -1 +1 @@
1
- import{mkdir as e,writeFile as t}from"node:fs/promises";import n from"node:path";import{readProjectConfig as r}from"@coreframe/config";import{randomUUID as i}from"node:crypto";import{managedDevEnv as a,managedDevEvents as o,managedDevFlutterRestartFileEnv as s}from"@coreframe/dev-contracts/managed-dev";import{startManagedDevSession as c}from"@coreframe/dev/managed-dev";import{connectExistingDevSupervisor as l}from"@coreframe/dev/supervisor";const u=Symbol.for(`@coreframe/vite/managed-dev-session-states`),d=(()=>{let e=globalThis;return e[u]??=new Map})();function f({connectSupervisor:u=l,env:d=process.env,startSession:f=c}={}){let h=d[a]===`1`,g,_,v,y,b,x,S,C=!1,w=!1,T=new Map,E={mode:`waiting`,warnings:[]},D=()=>S??=(async()=>{w=!0,await x,C=!1;let e=g,t=_,n=v;g=void 0,_=void 0,v=void 0,y?.(),y=void 0,e&&b&&await m(b,e),t&&(n&&await t.release(n).catch(()=>void 0),t.close())})();return{name:`coreframe:managed-dev`,apply:`serve`,config(){return{define:{"import.meta.env.COREFRAME_MANAGED_DEV":JSON.stringify(h)}}},configureServer(a){if(!h)return;let c=a.config.root;b=c;let l=!1,S=!1,O=()=>g?.getStatus()??E,k=()=>{w||a.ws.send(o.status,{status:O()})},A=()=>{S||w||(S=!0,queueMicrotask(()=>{S=!1,Promise.resolve(a.restart()).catch(e=>{let t=e instanceof Error?e.message:String(e);a.config.logger.error(`Coreframe managed development restart failed: ${t}`,{error:e instanceof Error?e:void 0})})}))},j=e=>{if(w||e.event!==`managed-dev`)return;if(e.kind===`status`){E=e.status,k();return}if(e.kind===`restart`){l=!0,T.size===0&&(l=!1,A());return}let t=T.get(e.requestId);!t||!e.codex||typeof e.codex!=`object`||t.send(o.codex,{...e.codex,requestId:e.requestId})},M=async(e,t)=>{if(_&&C)try{E=(await _.managedDevStatus()).status}catch(e){let t=e instanceof Error?e.message:String(e);a.config.logger.error(`Coreframe managed development status failed: ${t}`,{error:e instanceof Error?e:void 0})}t.send(o.status,{status:O()})},N=async(e,t)=>{let n;try{if(!C)throw Error(`Managed development is still initializing.`);let n=_;if(n){T.set(e.requestId,t);try{let r=await n.managedDevAction({action:e.action,requestId:e.requestId});r.status&&(E=r.status),t.send(o.actionResult,{...r,requestId:e.requestId}),!r.error&&l&&(l=!1,A())}finally{T.delete(e.requestId)}return}let r=g;if(!r)throw Error(`Managed development is still initializing.`);let i=await r.action(e.action,{onCodexEvent:n=>t.send(o.codex,{...n,requestId:e.requestId})});t.send(o.actionResult,{requestId:e.requestId,...i}),l&&(l=!1,queueMicrotask(()=>{D().then(()=>a.restart()).catch(e=>{let t=e instanceof Error?e.message:String(e);a.config.logger.error(`Coreframe managed development restart failed: ${t}`,{error:e instanceof Error?e:void 0})})}));return}catch(e){n=e}let r=n instanceof Error?n.message:String(n);a.config.logger.error(`Coreframe managed development action failed: ${r}`,{error:n instanceof Error?n:void 0}),t.send(o.actionResult,{error:r,requestId:e.requestId,status:O()})};a.ws.on(o.statusRequest,M),a.ws.on(o.action,N),x=(async()=>{let o,h;try{if(o=await u({cwd:c,env:d}),o){if(w){o.close();return}_=o,y=o.onEvent(j),await o.subscribe([`managed-dev`]);let e=await o.acquireManagedDev({env:d});if(v=e.leaseId,E=e.status,w){await o.release(e.leaseId).catch(()=>void 0),v=void 0,y?.(),y=void 0,_=void 0,o.close();return}C=!0;return}let b=await r({cwd:c});if(w)return;if(h=await f({config:b,cwd:c,env:d,onRestart:()=>{l=!0},onFlutterRestart:async()=>{let r=d[s];if(r)try{await e(n.dirname(r),{recursive:!0}),await t(r,`${i()}\n`,{mode:384})}catch(e){let t=e instanceof Error?e.message:String(e);a.config.logger.error(`Coreframe Flutter restart request failed: ${t}`,{error:e instanceof Error?e:void 0})}},onStatusChange:e=>{E=e,k()}}),g=h,E=h.getStatus(),w){g=void 0,await h.close();return}if(await p(c,h),w){g=void 0,await m(c,h);return}C=!0}catch(e){if(o&&_===o&&(y?.(),y=void 0,_=void 0,o.close()),g===h&&(g=void 0),!w){let t=e instanceof Error?e.message:String(e);E={message:t,mode:`error`,warnings:[t]},a.config.logger.error(`Coreframe managed development initialization failed: ${t}`,{error:e instanceof Error?e:void 0}),k()}}})(),a.httpServer?.once(`close`,()=>{a.ws.off(o.statusRequest,M),a.ws.off(o.action,N),D()})},async closeBundle(){await D()}}}async function p(e,t){await h(e,async e=>{let n=e.session;e.session=void 0,await n?.close();try{await t.activate(),e.session=t}catch(e){throw await t.close(),e}})}async function m(e,t){await h(e,async e=>{e.session===t&&(e.session=void 0),await t.close()})}async function h(e,t){let n=d.get(e);n||(n={transition:Promise.resolve()},d.set(e,n));let r=n.transition,i;n.transition=new Promise(e=>{i=()=>e()}),await r;try{await t(n)}finally{i()}}export{f as coreframeManagedDevPlugin};
1
+ import{mkdir as e,writeFile as t}from"node:fs/promises";import n from"node:path";import{readProjectConfig as r}from"@coreframe/config";import{randomUUID as i}from"node:crypto";import{managedDevEnv as a,managedDevEvents as o,managedDevFlutterRestartFileEnv as s}from"@coreframe/dev-contracts/managed-dev";import{startManagedDevSession as c}from"@coreframe/dev/managed-dev";import{connectExistingDevSupervisor as l}from"@coreframe/dev/supervisor";const u=Symbol.for(`@coreframe/vite/managed-dev-session-states`),d=(()=>{let e=globalThis;return e[u]??=new Map})();function f({connectSupervisor:u=l,env:d=process.env,startSession:f=c}={}){let h=d[a]===`1`,g,_,v,y,b,x,S,C=!1,w=!1,T=new Map,E={mode:`waiting`,warnings:[]},D=()=>S??=(async()=>{w=!0,await x,C=!1;let e=g,t=_,n=v;g=void 0,_=void 0,v=void 0,y?.(),y=void 0,e&&b&&await m(b,e),t&&(n&&await t.release(n).catch(()=>void 0),t.close())})();return{name:`coreframe:managed-dev`,apply:`serve`,config(){return{define:{"import.meta.env.COREFRAME_MANAGED_DEV":JSON.stringify(h)}}},configureServer(a){if(!h)return;let c=a.config.root;b=c;let l=!1,S=!1,O=()=>g?.getStatus()??E,k=()=>{w||a.ws.send(o.status,{status:O()})},A=()=>{S||w||(S=!0,queueMicrotask(()=>{S=!1,Promise.resolve(a.restart()).catch(e=>{let t=e instanceof Error?e.message:String(e);a.config.logger.error(`Coreframe managed development restart failed: ${t}`,{error:e instanceof Error?e:void 0})})}))},j=e=>{if(w||e.event!==`managed-dev`)return;if(e.kind===`status`){E=e.status,k();return}if(e.kind===`restart`){l=!0,T.size===0&&(l=!1,A());return}let t=T.get(e.requestId);!t||!e.codex||typeof e.codex!=`object`||t.send(o.codex,{...e.codex,requestId:e.requestId})},M=async(e,t)=>{if(_&&C)try{E=(await _.managedDevStatus()).status}catch(e){let t=e instanceof Error?e.message:String(e);a.config.logger.error(`Coreframe managed development status failed: ${t}`,{error:e instanceof Error?e:void 0})}t.send(o.status,{status:O()})},N=async(e,t)=>{let n;try{if(!C)throw Error(`Managed development is still initializing.`);let n=_;if(n){T.set(e.requestId,t);try{let r=await n.managedDevAction({action:e.action,requestId:e.requestId});r.status&&(E=r.status),t.send(o.actionResult,{...r,requestId:e.requestId}),!r.error&&l&&(l=!1,A())}finally{T.delete(e.requestId)}return}let r=g;if(!r)throw Error(`Managed development is still initializing.`);let i=await r.action(e.action,{onCodexEvent:n=>t.send(o.codex,{...n,requestId:e.requestId})});t.send(o.actionResult,{requestId:e.requestId,...i}),l&&(l=!1,queueMicrotask(()=>{D().then(()=>a.restart()).catch(e=>{let t=e instanceof Error?e.message:String(e);a.config.logger.error(`Coreframe managed development restart failed: ${t}`,{error:e instanceof Error?e:void 0})})}));return}catch(e){n=e}let r=n instanceof Error?n.message:String(n);a.config.logger.error(`Coreframe managed development action failed: ${r}`,{error:n instanceof Error?n:void 0}),t.send(o.actionResult,{error:r,requestId:e.requestId,status:O()})};a.ws.on(o.statusRequest,M),a.ws.on(o.action,N),x=(async()=>{let o,h;try{if(o=await u({cwd:c,env:d,requiredResources:[`managed-dev`]}),o){if(w){o.close();return}_=o,y=o.onEvent(j),await o.subscribe([`managed-dev`]);let e=await o.acquireManagedDev({env:d});if(v=e.leaseId,E=e.status,w){await o.release(e.leaseId).catch(()=>void 0),v=void 0,y?.(),y=void 0,_=void 0,o.close();return}C=!0;return}let b=await r({cwd:c});if(w)return;if(h=await f({config:b,cwd:c,env:d,onRestart:()=>{l=!0},onFlutterRestart:async()=>{let r=d[s];if(r)try{await e(n.dirname(r),{recursive:!0}),await t(r,`${i()}\n`,{mode:384})}catch(e){let t=e instanceof Error?e.message:String(e);a.config.logger.error(`Coreframe Flutter restart request failed: ${t}`,{error:e instanceof Error?e:void 0})}},onStatusChange:e=>{E=e,k()}}),g=h,E=h.getStatus(),w){g=void 0,await h.close();return}if(await p(c,h),w){g=void 0,await m(c,h);return}C=!0}catch(e){if(o&&_===o&&(y?.(),y=void 0,_=void 0,o.close()),g===h&&(g=void 0),!w){let t=e instanceof Error?e.message:String(e);E={message:t,mode:`error`,warnings:[t]},a.config.logger.error(`Coreframe managed development initialization failed: ${t}`,{error:e instanceof Error?e:void 0}),k()}}})(),a.httpServer?.once(`close`,()=>{a.ws.off(o.statusRequest,M),a.ws.off(o.action,N),D()})},async closeBundle(){await D()}}}async function p(e,t){await h(e,async e=>{let n=e.session;e.session=void 0,await n?.close();try{await t.activate(),e.session=t}catch(e){throw await t.close(),e}})}async function m(e,t){await h(e,async e=>{e.session===t&&(e.session=void 0),await t.close()})}async function h(e,t){let n=d.get(e);n||(n={transition:Promise.resolve()},d.set(e,n));let r=n.transition,i;n.transition=new Promise(e=>{i=()=>e()}),await r;try{await t(n)}finally{i()}}export{f as coreframeManagedDevPlugin};
@@ -15,8 +15,7 @@ type NativeRouteRegistration = {
15
15
  statusBarForeground?: "automatic" | "light" | "dark";
16
16
  } & MobileRouteLayerMetadata;
17
17
  type MobileRouteRegistration = {
18
- /** Opts the ordinary DOM implementation into Flutter-owned physical presentation on mobile. */surface: "flutter-dom"; /** Keeps bottom-anchored DOM content visually attached to the animated software keyboard. */
19
- keyboardLayout?: "bottom-anchored"; /** Symbolic Flutter shell transition selected when this route is presented. */
18
+ /** Opts the ordinary DOM implementation into Flutter-owned physical presentation on mobile. */surface: "flutter-dom"; /** Symbolic Flutter shell transition selected when this route is presented. */
20
19
  transitionKey?: string; /** Optional opaque route backdrop used while platform transitions fade route content. */
21
20
  underlayColor?: string; /** Status-bar foreground policy while this route is active. */
22
21
  statusBarForeground?: "automatic" | "light" | "dark";
@@ -48,7 +47,6 @@ type MobileRouteManifestEntry = {
48
47
  stackRoot: boolean;
49
48
  underlayColor: string | null;
50
49
  statusBarForeground: "automatic" | "light" | "dark" | null;
51
- keyboardLayout: "bottom-anchored" | null;
52
50
  };
53
51
  type MobileStackManifestEntry = {
54
52
  id: string;
@@ -1 +1 @@
1
- import{getAppDirectory as e,index as t,layout as n,prefix as r,relative as i,route as a}from"@react-router/dev/routes";const o=`__coreframe_flutter_dom__`,s=`platform`,c=Symbol(`coreframe-route-registration`);function l(e,t,n,r){let i=Array.isArray(n)||n===void 0?void 0:n,o=Array.isArray(n)?n:r,s=i===void 0?void 0:{id:i.id,index:i.index,caseSensitive:i.caseSensitive},l=s===void 0?a(e,t,o):a(e,t,s,o);return i?.native!==void 0&&(l.native=i.native,l[c]={authoredControllerPath:i.native.path}),i?.mobile!==void 0&&(l.mobile=i.mobile),l}function u(e,n){return t(e,n)}function d(e,t,r){return Array.isArray(t)?n(e,t):t===void 0?n(e):n(e,t,r)}function f(e,t){return r(e,t)}function p(e){let t=i(e);return{route(e,n,r,i){let a=l(e,n,r,i);return a.file=t.route(null,n).file,a.native!==void 0&&(a.native={path:t.route(null,a.native.path).file}),a},index(e,n){return t.index(e,n)},layout(e,n,r){return Array.isArray(n)?t.layout(e,n):n===void 0?t.layout(e):t.layout(e,n,r)},prefix:f}}function m(e){if(!Array.isArray(e))throw Error(`Coreframe route config must be an array. Await asynchronous route config before compiling it.`);let t=[],n=[],r=new Map,i=new Map;return{routes:e.map((e,a)=>h(e,`/`,`routes[${a}]`,r,i,t,n)),nativeManifest:t,mobileManifest:n,stacks:_(n)}}function h(e,t,n,r,i,a,o){if(typeof e!=`object`||!e||typeof e.file!=`string`)throw Error(`Invalid Coreframe route registration at ${n}: expected a route helper result.`);if(e.id!==void 0){if(e.id.length===0||e.id.trim()!==e.id)throw Error(`Invalid route id ${JSON.stringify(e.id)} at ${n}: IDs must be non-empty and cannot have surrounding whitespace.`);let t=r.get(e.id);if(t!==void 0)throw Error(`Duplicate route id ${JSON.stringify(e.id)} at ${n}; it is already registered at ${t}.`);r.set(e.id,n)}let s=w(t,e.path);if(e.mobile!==void 0&&e.native!==void 0)throw Error(`Conflicting mobile surface policy for route ${JSON.stringify(e.id)} at ${n}: use either mobile.surface or native, not both.`);if(e.mobile!==void 0&&e.mobile.surface!==`flutter-dom`)throw Error(`Invalid mobile surface policy for route ${JSON.stringify(e.id)} at ${n}: expected "flutter-dom".`);if((e.mobile!==void 0||e.native!==void 0)&&(C(e,n),x(e.native?.statusBarForeground??e.mobile?.statusBarForeground,n)),e.native!==void 0){S(e,n);let t=v(e,n),r=e.id,c=T(s),l=i.get(c);if(l!==void 0)throw Error(`Ambiguous native route ${JSON.stringify(r)} at ${n}: canonical path ${JSON.stringify(s)} conflicts with native route ${JSON.stringify(l)}.`);i.set(c,r),a.push({routeId:r,canonicalPath:s,caseSensitive:e.caseSensitive===!0,routeModulePath:e.file,controllerModulePath:e.native.path,transitionKey:t}),o.push({routeId:r,canonicalPath:s,caseSensitive:e.caseSensitive===!0,routeModulePath:e.file,surface:`native`,transitionKey:t,underlayColor:null,statusBarForeground:e.native.statusBarForeground??null,keyboardLayout:null,...g(e,n)})}else if(e.mobile!==void 0){y(e.mobile.underlayColor,n),b(e.mobile.keyboardLayout,n);let t=v(e,n),r=e.id,a=T(s),c=i.get(a);if(c!==void 0)throw Error(`Ambiguous mobile route ${JSON.stringify(r)} at ${n}: canonical path ${JSON.stringify(s)} conflicts with mobile route ${JSON.stringify(c)}.`);i.set(a,r),o.push({routeId:r,canonicalPath:s,caseSensitive:e.caseSensitive===!0,routeModulePath:e.file,surface:`flutter-dom`,transitionKey:t,underlayColor:e.mobile.underlayColor??null,statusBarForeground:e.mobile.statusBarForeground??null,keyboardLayout:e.mobile.keyboardLayout??null,...g(e,n)})}let c={file:e.file};return`children`in e&&(c.children=e.children?.map((e,t)=>h(e,s,`${n}.children[${t}]`,r,i,a,o))),`path`in e&&(c.path=e.path),`id`in e&&(c.id=e.id),`index`in e&&(c.index=e.index),`caseSensitive`in e&&(c.caseSensitive=e.caseSensitive),c}function g(e,t){let n=e.native??e.mobile;if(n===void 0)return{stackId:null,stackRoot:!1,z:0};let r=n.z??0;if(typeof r!=`number`||!Number.isFinite(r))throw Error(`Invalid mobile route z ${JSON.stringify(r)} for route ${JSON.stringify(e.id)} at ${t}: z must be a finite number.`);let i=n.stack,a=typeof i==`object`?i:void 0,o=typeof i==`string`?i:a?.id,s=a?.root??!1;if(o===void 0&&s)throw Error(`Invalid mobile stack metadata for route ${JSON.stringify(e.id)} at ${t}: stackRoot requires a stack id.`);if(o!==void 0&&(typeof o!=`string`||o.length===0||o.trim()!==o))throw Error(`Invalid mobile stack id ${JSON.stringify(o)} for route ${JSON.stringify(e.id)} at ${t}: IDs must be non-empty and cannot have surrounding whitespace.`);if(typeof s!=`boolean`)throw Error(`Invalid mobile stack root flag for route ${JSON.stringify(e.id)} at ${t}: expected a boolean.`);return{stackId:o??null,stackRoot:s,z:r}}function _(e){let t=new Map;for(let n of e){if(n.stackId===null){if(n.stackRoot)throw Error(`Mobile route ${JSON.stringify(n.routeId)} marks a stack root without a stack.`);continue}let e=t.get(n.stackId)??[];e.push(n),t.set(n.stackId,e)}return[...t.entries()].sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>{let n=t.filter(e=>e.stackRoot);if(n.length!==1)throw Error(`Mobile stack ${JSON.stringify(e)} must declare exactly one Flutter DOM root route.`);let r=n[0];if(r.surface!==`flutter-dom`)throw Error(`Mobile stack ${JSON.stringify(e)} root route ${JSON.stringify(r.routeId)} must use the Flutter DOM surface.`);return{id:e,rootRouteId:r.routeId,routeIds:t.map(({routeId:e})=>e).sort((e,t)=>e.localeCompare(t))}})}function v(e,t){let n=e.native?.transitionKey??e.mobile?.transitionKey;if(n===void 0)return s;if(typeof n!=`string`||n.length===0||n.trim()!==n)throw Error(`Invalid mobile transition key ${JSON.stringify(n)} for route ${JSON.stringify(e.id)} at ${t}: keys must be non-empty and cannot have surrounding whitespace.`);return n}function y(e,t){if(e!==void 0&&(typeof e!=`string`||!/^#[0-9A-Fa-f]{6}$/.test(e)))throw Error(`Invalid mobile underlay color ${JSON.stringify(e)} at ${t}: expected a solid #RRGGBB color.`)}function b(e,t){if(e!==void 0&&e!==`bottom-anchored`)throw Error(`Invalid mobile keyboard layout ${JSON.stringify(e)} at ${t}: expected "bottom-anchored".`)}function x(e,t){if(e!==void 0&&e!==`automatic`&&e!==`light`&&e!==`dark`)throw Error(`Invalid status bar foreground ${JSON.stringify(e)} at ${t}: expected "automatic", "light", or "dark".`)}function S(e,t){C(e,t);let n=e[c]?.authoredControllerPath??e.native?.path;if(typeof n!=`string`||n.trim()!==n||!n.startsWith(`.`)||n.includes(`\\`)||n.includes(`?`)||n.includes(`#`)||!n.endsWith(`.native.tsx`))throw Error(`Invalid native controller path ${JSON.stringify(n)} for route ${JSON.stringify(e.id)} at ${t}: expected a relative *.native.tsx module path without query, hash, or backslash characters.`)}function C(e,t){if(e.id===void 0)throw Error(`Mobile route at ${t} (${JSON.stringify(e.file)}) requires an explicit stable id.`);if(e.id===`root`)throw Error(`Mobile route at ${t} cannot use React Router's reserved id "root".`);if(e.id===o)throw Error(`Mobile route at ${t} cannot use Coreframe's reserved Flutter-DOM route id ${JSON.stringify(o)}.`);if(e.path===void 0&&e.index!==!0)throw Error(`Mobile route ${JSON.stringify(e.id)} at ${t} must have an addressable path or be an index route.`)}function w(e,t){if(t===void 0||t===``)return e;let n=(t.startsWith(`/`)?t:`${e===`/`?``:e}/${t}`).replace(/\/{2,}/g,`/`);return n.startsWith(`/`)?n:`/${n}`}function T(e){return e.split(`/`).map(e=>e.startsWith(`:`)?`:${e.endsWith(`?`)?`?`:``}`:e).join(`/`).toLowerCase()}export{s as DEFAULT_MOBILE_TRANSITION_KEY,m as compileRouteRegistrations,e as getAppDirectory,u as index,d as layout,f as prefix,p as relative,l as route};
1
+ import{getAppDirectory as e,index as t,layout as n,prefix as r,relative as i,route as a}from"@react-router/dev/routes";const o=`__coreframe_flutter_dom__`,s=`platform`,c=Symbol(`coreframe-route-registration`);function l(e,t,n,r){let i=Array.isArray(n)||n===void 0?void 0:n,o=Array.isArray(n)?n:r,s=i===void 0?void 0:{id:i.id,index:i.index,caseSensitive:i.caseSensitive},l=s===void 0?a(e,t,o):a(e,t,s,o);return i?.native!==void 0&&(l.native=i.native,l[c]={authoredControllerPath:i.native.path}),i?.mobile!==void 0&&(l.mobile=i.mobile),l}function u(e,n){return t(e,n)}function d(e,t,r){return Array.isArray(t)?n(e,t):t===void 0?n(e):n(e,t,r)}function f(e,t){return r(e,t)}function p(e){let t=i(e);return{route(e,n,r,i){let a=l(e,n,r,i);return a.file=t.route(null,n).file,a.native!==void 0&&(a.native={path:t.route(null,a.native.path).file}),a},index(e,n){return t.index(e,n)},layout(e,n,r){return Array.isArray(n)?t.layout(e,n):n===void 0?t.layout(e):t.layout(e,n,r)},prefix:f}}function m(e){if(!Array.isArray(e))throw Error(`Coreframe route config must be an array. Await asynchronous route config before compiling it.`);let t=[],n=[],r=new Map,i=new Map;return{routes:e.map((e,a)=>h(e,`/`,`routes[${a}]`,r,i,t,n)),nativeManifest:t,mobileManifest:n,stacks:_(n)}}function h(e,t,n,r,i,a,o){if(typeof e!=`object`||!e||typeof e.file!=`string`)throw Error(`Invalid Coreframe route registration at ${n}: expected a route helper result.`);if(e.id!==void 0){if(e.id.length===0||e.id.trim()!==e.id)throw Error(`Invalid route id ${JSON.stringify(e.id)} at ${n}: IDs must be non-empty and cannot have surrounding whitespace.`);let t=r.get(e.id);if(t!==void 0)throw Error(`Duplicate route id ${JSON.stringify(e.id)} at ${n}; it is already registered at ${t}.`);r.set(e.id,n)}let s=C(t,e.path);if(e.mobile!==void 0&&e.native!==void 0)throw Error(`Conflicting mobile surface policy for route ${JSON.stringify(e.id)} at ${n}: use either mobile.surface or native, not both.`);if(e.mobile!==void 0&&e.mobile.surface!==`flutter-dom`)throw Error(`Invalid mobile surface policy for route ${JSON.stringify(e.id)} at ${n}: expected "flutter-dom".`);if((e.mobile!==void 0||e.native!==void 0)&&(S(e,n),b(e.native?.statusBarForeground??e.mobile?.statusBarForeground,n)),e.native!==void 0){x(e,n);let t=v(e,n),r=e.id,c=w(s),l=i.get(c);if(l!==void 0)throw Error(`Ambiguous native route ${JSON.stringify(r)} at ${n}: canonical path ${JSON.stringify(s)} conflicts with native route ${JSON.stringify(l)}.`);i.set(c,r),a.push({routeId:r,canonicalPath:s,caseSensitive:e.caseSensitive===!0,routeModulePath:e.file,controllerModulePath:e.native.path,transitionKey:t}),o.push({routeId:r,canonicalPath:s,caseSensitive:e.caseSensitive===!0,routeModulePath:e.file,surface:`native`,transitionKey:t,underlayColor:null,statusBarForeground:e.native.statusBarForeground??null,...g(e,n)})}else if(e.mobile!==void 0){y(e.mobile.underlayColor,n);let t=v(e,n),r=e.id,a=w(s),c=i.get(a);if(c!==void 0)throw Error(`Ambiguous mobile route ${JSON.stringify(r)} at ${n}: canonical path ${JSON.stringify(s)} conflicts with mobile route ${JSON.stringify(c)}.`);i.set(a,r),o.push({routeId:r,canonicalPath:s,caseSensitive:e.caseSensitive===!0,routeModulePath:e.file,surface:`flutter-dom`,transitionKey:t,underlayColor:e.mobile.underlayColor??null,statusBarForeground:e.mobile.statusBarForeground??null,...g(e,n)})}let c={file:e.file};return`children`in e&&(c.children=e.children?.map((e,t)=>h(e,s,`${n}.children[${t}]`,r,i,a,o))),`path`in e&&(c.path=e.path),`id`in e&&(c.id=e.id),`index`in e&&(c.index=e.index),`caseSensitive`in e&&(c.caseSensitive=e.caseSensitive),c}function g(e,t){let n=e.native??e.mobile;if(n===void 0)return{stackId:null,stackRoot:!1,z:0};let r=n.z??0;if(typeof r!=`number`||!Number.isFinite(r))throw Error(`Invalid mobile route z ${JSON.stringify(r)} for route ${JSON.stringify(e.id)} at ${t}: z must be a finite number.`);let i=n.stack,a=typeof i==`object`?i:void 0,o=typeof i==`string`?i:a?.id,s=a?.root??!1;if(o===void 0&&s)throw Error(`Invalid mobile stack metadata for route ${JSON.stringify(e.id)} at ${t}: stackRoot requires a stack id.`);if(o!==void 0&&(typeof o!=`string`||o.length===0||o.trim()!==o))throw Error(`Invalid mobile stack id ${JSON.stringify(o)} for route ${JSON.stringify(e.id)} at ${t}: IDs must be non-empty and cannot have surrounding whitespace.`);if(typeof s!=`boolean`)throw Error(`Invalid mobile stack root flag for route ${JSON.stringify(e.id)} at ${t}: expected a boolean.`);return{stackId:o??null,stackRoot:s,z:r}}function _(e){let t=new Map;for(let n of e){if(n.stackId===null){if(n.stackRoot)throw Error(`Mobile route ${JSON.stringify(n.routeId)} marks a stack root without a stack.`);continue}let e=t.get(n.stackId)??[];e.push(n),t.set(n.stackId,e)}return[...t.entries()].sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>{let n=t.filter(e=>e.stackRoot);if(n.length!==1)throw Error(`Mobile stack ${JSON.stringify(e)} must declare exactly one Flutter DOM root route.`);let r=n[0];if(r.surface!==`flutter-dom`)throw Error(`Mobile stack ${JSON.stringify(e)} root route ${JSON.stringify(r.routeId)} must use the Flutter DOM surface.`);return{id:e,rootRouteId:r.routeId,routeIds:t.map(({routeId:e})=>e).sort((e,t)=>e.localeCompare(t))}})}function v(e,t){let n=e.native?.transitionKey??e.mobile?.transitionKey;if(n===void 0)return s;if(typeof n!=`string`||n.length===0||n.trim()!==n)throw Error(`Invalid mobile transition key ${JSON.stringify(n)} for route ${JSON.stringify(e.id)} at ${t}: keys must be non-empty and cannot have surrounding whitespace.`);return n}function y(e,t){if(e!==void 0&&(typeof e!=`string`||!/^#[0-9A-Fa-f]{6}$/.test(e)))throw Error(`Invalid mobile underlay color ${JSON.stringify(e)} at ${t}: expected a solid #RRGGBB color.`)}function b(e,t){if(e!==void 0&&e!==`automatic`&&e!==`light`&&e!==`dark`)throw Error(`Invalid status bar foreground ${JSON.stringify(e)} at ${t}: expected "automatic", "light", or "dark".`)}function x(e,t){S(e,t);let n=e[c]?.authoredControllerPath??e.native?.path;if(typeof n!=`string`||n.trim()!==n||!n.startsWith(`.`)||n.includes(`\\`)||n.includes(`?`)||n.includes(`#`)||!n.endsWith(`.native.tsx`))throw Error(`Invalid native controller path ${JSON.stringify(n)} for route ${JSON.stringify(e.id)} at ${t}: expected a relative *.native.tsx module path without query, hash, or backslash characters.`)}function S(e,t){if(e.id===void 0)throw Error(`Mobile route at ${t} (${JSON.stringify(e.file)}) requires an explicit stable id.`);if(e.id===`root`)throw Error(`Mobile route at ${t} cannot use React Router's reserved id "root".`);if(e.id===o)throw Error(`Mobile route at ${t} cannot use Coreframe's reserved Flutter-DOM route id ${JSON.stringify(o)}.`);if(e.path===void 0&&e.index!==!0)throw Error(`Mobile route ${JSON.stringify(e.id)} at ${t} must have an addressable path or be an index route.`)}function C(e,t){if(t===void 0||t===``)return e;let n=(t.startsWith(`/`)?t:`${e===`/`?``:e}/${t}`).replace(/\/{2,}/g,`/`);return n.startsWith(`/`)?n:`/${n}`}function w(e){return e.split(`/`).map(e=>e.startsWith(`:`)?`:${e.endsWith(`?`)?`?`:``}`:e).join(`/`).toLowerCase()}export{s as DEFAULT_MOBILE_TRANSITION_KEY,m as compileRouteRegistrations,e as getAppDirectory,u as index,d as layout,f as prefix,p as relative,l as route};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coreframe/vite",
3
- "version": "0.2.27",
3
+ "version": "0.2.28",
4
4
  "description": "Vite plugins and build integrations for Coreframe apps",
5
5
  "repository": {
6
6
  "type": "git",
@@ -57,14 +57,14 @@
57
57
  "obug": "^2.1.3",
58
58
  "unplugin": "^2.3.11",
59
59
  "vite-plugin-hashed-favicons": "^2.1.1",
60
- "@coreframe/assets": "^0.1.13",
61
- "@coreframe/dashboard": "^0.3.12",
62
- "@coreframe/dev": "^0.1.17",
60
+ "@coreframe/config": "^0.1.11",
61
+ "@coreframe/assets": "^0.1.14",
62
+ "@coreframe/dashboard": "^0.3.13",
63
+ "@coreframe/dev": "^0.1.18",
63
64
  "@coreframe/dev-contracts": "^0.1.8",
64
- "@coreframe/config": "^0.1.10",
65
- "@coreframe/flutter-js": "^0.1.24",
66
- "@coreframe/flutter-tools": "^0.1.19",
67
- "@coreframe/lib": "^0.2.12"
65
+ "@coreframe/flutter-js": "^0.1.25",
66
+ "@coreframe/flutter-tools": "^0.1.20",
67
+ "@coreframe/lib": "^0.2.13"
68
68
  },
69
69
  "devDependencies": {
70
70
  "@tsdown/css": "0.22.3",