@finesoft/front 0.3.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.
- package/dist/browser-BIetJHp_.mjs +2 -0
- package/dist/{server-data-HVSgxEac.d.mts → browser-DMw76sEo.d.mts} +470 -11
- package/dist/browser.d.mts +2 -2
- package/dist/browser.mjs +1 -1
- package/dist/index.d.mts +11 -2
- package/dist/index.mjs +22 -22
- package/docs/04-rendering-and-hydration.md +71 -1
- package/docs/11-navigation.md +13 -13
- package/docs/12-session-restoration.md +219 -0
- package/docs/zh/04-rendering-and-hydration.md +71 -1
- package/docs/zh/11-navigation.md +13 -13
- package/docs/zh/12-session-restoration.md +219 -0
- package/package.json +3 -3
- package/dist/src-BI4eMjHk.mjs +0 -2
package/dist/browser.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as
|
|
2
|
-
export { ACTION_KINDS, Action, ActionDispatcher, ActionHandler,
|
|
1
|
+
import { $ as IntersectionImpressionObserver, $i as FeatureFlagsProvider, $n as isLeafNode, $r as ConsoleLogger, $t as HydrateOperation, A as ActionHandlerDependencies, Aa as ActionHandler, Ai as AfterLoadGuard, An as SerializedStack, Ar as classifyHost, At as NavigationScopedState, B as getTextDirection, Ba as makeFlowAction, Bi as next, Bn as popTo, Br as BaseShelf, Bt as SessionUrlLocation, C as SessionBridgeOptions, Ca as SecureFetchOptions, Ci as InferOutput, Cn as createFullStateCodec, Cr as AsyncMapper, Ct as createUrlSessionAdapter, D as NavigationBridgeDependencies, Da as IntentController, Di as StandardSchemaV1, Dn as SerializedNavigation, Dr as pipeAsync, Dt as sessionEntryKey, E as defaultShouldRestore, Ea as Intent, Ei as StandardResult, En as SerializedLeaf, Er as pipe, Et as createNavigationScopedState, F as ExternalUrlDependencies, Fa as FlowAction, Fi as NextResult, Fn as collectAllLeaves, Fr as HttpError, Ft as SessionNavigationAdapter, G as PluralCategory, Gi as FINESOFT_PUBLIC, Gn as selectColumn, Gr as PrefetchedIntent, Gt as defineRoutes, H as makeLocaleInfo, Hi as rewrite, Hn as push, Hr as safeErrorPage, Ht as DefineRoutesOptions, I as registerExternalUrlHandler, Ia as isCompoundAction, Ii as PostLoadContext, In as collectVisibleDestinations, Ir as RequestInterceptor, It as SessionSnapshot, J as interpolate, Ji as markPublic, Jn as visibleSplitColumns, Jr as LocaleInfo, Jt as NavigationBrowserConfig, K as PluralRuleProvider, Ki as getPublicFields, Kn as selectTab, Kr as PrefetchedIntents, Kt as route, L as SimpleTranslator, La as isExternalUrlAction, Li as RedirectResult, Ln as findNearestStack, Lr as ResponseInterceptor, Lt as SessionStateProvider, M as FlowActionCallbacks, Ma as Action, Mi as DenyResult, Mn as deserializeNavigation, Mr as HostGuardError, Mt as SESSION_DEFAULT_VERSION, N as FlowActionDependencies, Na as CompoundAction, Ni as MiddlewareResult, Nn as serializeNavigation, Nr as HttpClient, Nt as SessionError, O as NavigationHandle, Oa as Container, Oi as makeSchema, On as SerializedSplit, Or as BaseController, Ot as decodeSnapshot, P as registerFlowActionHandler, Pa as ExternalUrlAction, Pi as NavigationContext, Pn as serializeNavigationStable, Pr as HttpClientConfig, Pt as SessionErrorContext, Q as ImpressionObserverOptions, Qi as FeatureFlags, Qn as TabsInit, Qr as shouldLog, Qt as defineNavigation, R as SimpleTranslatorOptions, Ra as isFlowAction, Ri as RewriteResult, Rn as findNode, Rr as stableStringify, Rt as SessionStore, S as SESSION_DEFAULT_DEBOUNCE_MS, Sa as LoggerFactory, Si as Router, Sn as createFlatStackCodec, Sr as TabsNode, St as createNavigationSessionAdapter, T as createSessionBridge, Ta as IntentDispatcher, Ti as StandardIssue, Tn as encodeNavigationTreeParam, Tr as mapEach, Tt as collectLeafKeys, U as resolveLocaleFromUrl, Ui as BASE_PAGE_FIELDS, Un as replaceTop, Ur as Framework, Ut as RenderMode, V as isRtl, Vi as redirect, Vn as popToRoot, Vr as SafeErrorPageOptions, Vt as isUrlLocation, W as setHtmlLocaleAttributes, Wi as BasePage, Wn as resolveActivePath, Wr as FrameworkConfig, Wt as RouteDefinition, X as WithFieldsRecorder, Xi as defineRequestScopedKey, Xn as islandContainerAttributes, Xr as Translator, Xt as NavigationInitial, Y as resolvePluralKey, Yi as RequestScopedKey, Yn as ResolvedEntry, Yr as TextDirection, Yt as NavigationDefinition, Z as VoidEventRecorder, Zi as DEP_KEYS, Zn as SplitColumnInit, Zr as resetFilterCache, Zt as NavigationSSRDefinition, _ as IslandOrchestratorOptions, _a as ReportingLogger, _i as str, _n as DEFAULT_NAV_PARAM, _r as SPLIT_VISIBILITIES, _t as Optional, a as DomRestore, aa as MessagesLoader, ai as InferQuery, an as NavigationOpKind, ar as stack, at as ServerContextOptions, b as AppHandle, ba as BaseLogger, bi as RouteAddOptions, bn as NavigationRouterLike, br as SplitVisibility, bt as LruMap, c as createWebStorage, ca as resolveConfiguredMessages, ci as StripOptional, cn as PopToOperation, cr as NAVIGATION_NODE_KINDS, ct as generateUuid, d as BrowserAppConfig, da as detectPlatform, di as NumOptions, dn as PushOptions, dr as NavigationNodeKind, dt as removeHost, ea as MakeDependenciesOptions, ei as ConsoleLoggerFactory, en as NAVIGATION_OP_KINDS, er as isSplitNode, et as ConsoleEventRecorder, f as BrowserNavigationConfig, fa as EventRecorder, fi as StrOptions, fn as ReplaceTopOperation, fr as NavigationPath, ft as removeQueryParams, g as IslandOrchestrator, ga as ReportCallback, gi as oneOf, gn as createNavigationController, gr as ResolvedDestination, gt as None, h as IslandHandle, ha as MetricsFieldsProvider, hi as num, hn as SetVisibilityOperation, hr as Page, ht as getPWADisplayMode, i as History, ia as makeDependencies, ii as InferParams, in as NavigationDispatchContext, ir as split, it as BrowserContextOptions, j as registerActionHandlers, ja as ACTION_KINDS, ji as BeforeLoadGuard, jn as SerializedTabs, jr as classifyUrl, jt as SESSION_DEFAULT_KEY, k as createNavigationBridge, ka as ActionDispatcher, ki as runStandard, kn as SerializedSplitColumn, kr as HostCheckResult, kt as encodeSnapshot, l as IslandsShell, la as resolveMessages, li as optional, ln as PopToRootOperation, lr as NavigationError, lt as buildUrl, m as startBrowserApp, ma as ImpressionObserver, mi as int, mn as SelectTabOperation, mr as NavigationSnapshot, mt as PWADisplayMode, n as deserializeServerData, na as Net, ni as CompositeLoggerFactory, nn as NavigationController, nr as isTabsNode, nt as runAfterLoadGuards, o as DomRestoreOptions, oa as MessagesLoaderContext, oi as ParamsFor, on as NavigationOperation, or as tabs, ot as createBrowserContext, p as BrowserSessionConfig, pa as ImpressionEntry, pi as bool, pn as SelectColumnOperation, pr as NavigationPathStep, pt as removeScheme, q as englishPlural, qi as isPublicMarked, qn as setVisibility, qr as LocaleAttributes, qt as DefineNavigationOptions, r as tryScroll, ra as Storage, ri as ExtractParamNames, rn as NavigationControllerOptions, rr as leaf, rt as runBeforeLoadGuards, s as createDomRestore, sa as TranslationMessages, si as QuerySchemaMap, sn as PopOperation, sr as LeafNode, st as createServerContext, t as createPrefetchedIntentsFromDom, ta as MetricsRecorder, ti as CompositeLogger, tn as NavigationContextInput, tr as isStackNode, tt as CompositeEventRecorder, u as resolveIslandsShell, ua as PlatformInfo, ui as withDefault, un as PushOperation, ur as NavigationNode, ut as getBaseUrl, v as MountEntry, va as ReportingLoggerFactory, vi as uuid, vn as FullStateCodecOptions, vr as SplitColumn, vt as isNone, w as SessionHandle, wa as secureFetch, wi as ParamSchema, wn as decodeNavigationTreeParam, wr as Mapper, wt as createSessionStore, x as createAppHandle, xa as Logger, xi as RouteMatch, xn as createActiveLeafCodec, xr as StackNode, xt as UrlAdapterOptions, y as createIslandOrchestrator, ya as ReportingLoggerOptions, yi as RouteParams, yn as NavigationCodec, yr as SplitNode, yt as isSome, z as getLocaleAttributes, za as makeExternalUrlAction, zi as deny, zn as pop, zr as BaseItem, zt as SessionStoreOptions } from "./browser-DMw76sEo.mjs";
|
|
2
|
+
export { ACTION_KINDS, Action, ActionDispatcher, ActionHandler, ActionHandlerDependencies, AfterLoadGuard, AppHandle, AsyncMapper, BASE_PAGE_FIELDS, BaseController, BaseItem, BaseLogger, BasePage, BaseShelf, BeforeLoadGuard, BrowserAppConfig, BrowserContextOptions, BrowserNavigationConfig, BrowserSessionConfig, CompositeEventRecorder, CompositeLogger, CompositeLoggerFactory, CompoundAction, ConsoleEventRecorder, ConsoleLogger, ConsoleLoggerFactory, Container, DEFAULT_NAV_PARAM, DEP_KEYS, DefineNavigationOptions, DefineRoutesOptions, DenyResult, DomRestore, DomRestoreOptions, EventRecorder, ExternalUrlAction, ExternalUrlDependencies, ExtractParamNames, FINESOFT_PUBLIC, FeatureFlags, FeatureFlagsProvider, FlowAction, FlowActionCallbacks, FlowActionDependencies, Framework, FrameworkConfig, FullStateCodecOptions, History, HostCheckResult, HostGuardError, HttpClient, HttpClientConfig, HttpError, HydrateOperation, ImpressionEntry, ImpressionObserver, ImpressionObserverOptions, InferOutput, InferParams, InferQuery, Intent, IntentController, IntentDispatcher, IntersectionImpressionObserver, IslandHandle, IslandOrchestrator, IslandOrchestratorOptions, IslandsShell, LeafNode, LocaleAttributes, LocaleInfo, Logger, Logger as LoggerInterface, LoggerFactory, LruMap, MakeDependenciesOptions, Mapper, MessagesLoader, MessagesLoaderContext, MetricsFieldsProvider, MetricsRecorder, MiddlewareResult, MountEntry, NAVIGATION_NODE_KINDS, NAVIGATION_OP_KINDS, NavigationBridgeDependencies, NavigationBrowserConfig, NavigationCodec, NavigationContext, NavigationContextInput, NavigationController, NavigationControllerOptions, NavigationDefinition, NavigationDispatchContext, NavigationError, NavigationHandle, NavigationInitial, NavigationNode, NavigationNodeKind, NavigationOpKind, NavigationOperation, NavigationPath, NavigationPathStep, NavigationRouterLike, NavigationSSRDefinition, NavigationScopedState, NavigationSnapshot, Net, NextResult, None, NumOptions, Optional, PWADisplayMode, Page, ParamSchema, ParamsFor, PlatformInfo, PluralCategory, PluralRuleProvider, PopOperation, PopToOperation, PopToRootOperation, PostLoadContext, PrefetchedIntent, PrefetchedIntents, PushOperation, PushOptions, QuerySchemaMap, RedirectResult, RenderMode, ReplaceTopOperation, ReportCallback, ReportingLogger, ReportingLoggerFactory, ReportingLoggerOptions, RequestInterceptor, RequestScopedKey, ResolvedDestination, ResolvedEntry, ResponseInterceptor, RewriteResult, RouteAddOptions, RouteDefinition, RouteMatch, RouteParams, Router, SESSION_DEFAULT_DEBOUNCE_MS, SESSION_DEFAULT_KEY, SESSION_DEFAULT_VERSION, SPLIT_VISIBILITIES, SafeErrorPageOptions, SecureFetchOptions, SelectColumnOperation, SelectTabOperation, SerializedLeaf, SerializedNavigation, SerializedSplit, SerializedSplitColumn, SerializedStack, SerializedTabs, ServerContextOptions, SessionBridgeOptions, SessionError, SessionErrorContext, SessionHandle, SessionNavigationAdapter, SessionSnapshot, SessionStateProvider, SessionStore, SessionStoreOptions, SessionUrlLocation, SetVisibilityOperation, SimpleTranslator, SimpleTranslatorOptions, SplitColumn, SplitColumnInit, SplitNode, SplitVisibility, StackNode, StandardIssue, StandardResult, StandardSchemaV1, Storage, StrOptions, StripOptional, TabsInit, TabsNode, TextDirection, TranslationMessages, Translator, UrlAdapterOptions, VoidEventRecorder, WithFieldsRecorder, bool, buildUrl, classifyHost, classifyUrl, collectAllLeaves, collectLeafKeys, collectVisibleDestinations, createActiveLeafCodec, createAppHandle, createBrowserContext, createDomRestore, createFlatStackCodec, createFullStateCodec, createIslandOrchestrator, createNavigationBridge, createNavigationController, createNavigationScopedState, createNavigationSessionAdapter, createPrefetchedIntentsFromDom, createServerContext, createSessionBridge, createSessionStore, createUrlSessionAdapter, createWebStorage, decodeNavigationTreeParam, decodeSnapshot, defaultShouldRestore, defineNavigation, defineRequestScopedKey, defineRoutes, deny, deserializeNavigation, deserializeServerData, detectPlatform, encodeNavigationTreeParam, encodeSnapshot, englishPlural, findNearestStack, findNode, generateUuid, getBaseUrl, getLocaleAttributes, getPWADisplayMode, getPublicFields, getTextDirection, int, interpolate, isCompoundAction, isExternalUrlAction, isFlowAction, isLeafNode, isNone, isPublicMarked, isRtl, isSome, isSplitNode, isStackNode, isTabsNode, isUrlLocation, islandContainerAttributes, leaf, makeDependencies, makeExternalUrlAction, makeFlowAction, makeLocaleInfo, makeSchema, mapEach, markPublic, next, num, oneOf, optional, pipe, pipeAsync, pop, popTo, popToRoot, push, redirect, registerActionHandlers, registerExternalUrlHandler, registerFlowActionHandler, removeHost, removeQueryParams, removeScheme, replaceTop, resetFilterCache, resolveActivePath, resolveConfiguredMessages, resolveIslandsShell, resolveLocaleFromUrl, resolveMessages, resolvePluralKey, rewrite, route, runAfterLoadGuards, runBeforeLoadGuards, runStandard, safeErrorPage, secureFetch, selectColumn, selectTab, serializeNavigation, serializeNavigationStable, sessionEntryKey, setHtmlLocaleAttributes, setVisibility, shouldLog, split, stableStringify, stack, startBrowserApp, str, tabs, tryScroll, uuid, visibleSplitColumns, withDefault };
|
package/dist/browser.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{$ as e,$t as t,A as n,
|
|
1
|
+
import{$ as e,$t as t,A as n,An as r,At as i,B as a,Bn as o,Bt as s,C as c,Cn as l,Ct as u,D as d,Dn as f,Dt as p,E as m,En as h,Et as g,F as _,Fn as v,Ft as y,G as b,Gn as x,Gt as S,H as C,Hn as w,Ht as T,I as E,In as D,It as O,J as k,Jn as A,Jt as j,K as M,Kn as N,Kt as P,L as F,Ln as I,Lt as L,M as R,Mn as z,Mt as B,N as V,Nn as H,Nt as U,O as W,On as G,Ot as K,P as q,Pn as J,Pt as Y,Q as X,Qt as Z,R as Q,Rn as $,Rt as ee,S as te,Sn as ne,St as re,T as ie,Tn as ae,Tt as oe,U as se,Un as ce,Ut as le,V as ue,Vn as de,Vt as fe,W as pe,Wn as me,Wt as he,X as ge,Xt as _e,Y as ve,Yt as ye,Z as be,Zt as xe,_ as Se,_n as Ce,_t as we,a as Te,an as Ee,at as De,b as Oe,bn as ke,bt as Ae,c as je,cn as Me,ct as Ne,d as Pe,dn as Fe,dt as Ie,en as Le,et as Re,f as ze,fn as Be,ft as Ve,g as He,gn as Ue,gt as We,h as Ge,hn as Ke,ht as qe,i as Je,in as Ye,it as Xe,j as Ze,jn as Qe,jt as $e,k as et,kn as tt,kt as nt,l as rt,ln as it,lt as at,m as ot,mn as st,mt as ct,n as lt,nn as ut,nt as dt,o as ft,on as pt,ot as mt,p as ht,pn as gt,pt as _t,q as vt,qn as yt,qt as bt,r as xt,rn as St,rt as Ct,s as wt,sn as Tt,st as Et,t as Dt,tn as Ot,tt as kt,u as At,un as jt,ut as Mt,v as Nt,vn as Pt,vt as Ft,w as It,wn as Lt,wt as Rt,x as zt,xn as Bt,xt as Vt,y as Ht,yn as Ut,yt as Wt,z as Gt,zn as Kt,zt as qt}from"./browser-BIetJHp_.mjs";export{ce as ACTION_KINDS,w as ActionDispatcher,fe as BASE_PAGE_FIELDS,qt as BaseController,Ut as BaseLogger,zt as CompositeEventRecorder,ke as CompositeLogger,Bt as CompositeLoggerFactory,Be as ConsoleEventRecorder,Ke as ConsoleLogger,Ue as ConsoleLoggerFactory,o as Container,kt as DEFAULT_NAV_PARAM,it as DEP_KEYS,T as FINESOFT_PUBLIC,P as Framework,Ge as History,v as HostGuardError,D as HttpClient,I as HttpError,de as IntentDispatcher,Oe as IntersectionImpressionObserver,F as LruMap,U as NAVIGATION_NODE_KINDS,e as NAVIGATION_OP_KINDS,Y as NavigationError,bt as PrefetchedIntents,gt as ReportingLogger,st as ReportingLoggerFactory,Ee as Router,Je as SESSION_DEFAULT_DEBOUNCE_MS,M as SESSION_DEFAULT_KEY,vt as SESSION_DEFAULT_VERSION,y as SPLIT_VISIBILITIES,k as SessionError,ne as SimpleTranslator,Ht as VoidEventRecorder,Nt as WithFieldsRecorder,t as bool,et as buildUrl,$ as classifyHost,Kt as classifyUrl,Mt as collectAllLeaves,ue as collectLeafKeys,Ie as collectVisibleDestinations,dt as createActiveLeafCodec,ze as createAppHandle,m as createBrowserContext,Pe as createDomRestore,Ct as createFlatStackCodec,Xe as createFullStateCodec,At as createIslandOrchestrator,rt as createNavigationBridge,Re as createNavigationController,C as createNavigationScopedState,Q as createNavigationSessionAdapter,wt as createPrefetchedIntentsFromDom,d as createServerContext,Te as createSessionBridge,a as createSessionStore,Gt as createUrlSessionAdapter,xt as createWebStorage,De as decodeNavigationTreeParam,pe as decodeSnapshot,ft as defaultShouldRestore,X as defineNavigation,Me as defineRequestScopedKey,ge as defineRoutes,te as deny,Et as deserializeNavigation,je as deserializeServerData,Fe as detectPlatform,mt as encodeNavigationTreeParam,b as encodeSnapshot,l as englishPlural,Ve as findNearestStack,_t as findNode,W as generateUuid,n as getBaseUrl,G as getLocaleAttributes,q as getPWADisplayMode,le as getPublicFields,tt as getTextDirection,Le as int,Lt as interpolate,me as isCompoundAction,x as isExternalUrlAction,N as isFlowAction,oe as isLeafNode,_ as isNone,he as isPublicMarked,r as isRtl,E as isSome,g as isSplitNode,p as isStackNode,K as isTabsNode,ve as isUrlLocation,Rt as islandContainerAttributes,nt as leaf,jt as makeDependencies,yt as makeExternalUrlAction,A as makeFlowAction,Qe as makeLocaleInfo,pt as makeSchema,O as mapEach,S as markPublic,c as next,Ot as num,ut as oneOf,xe as optional,L as pipe,ee as pipeAsync,ct as pop,qe as popTo,We as popToRoot,we as push,It as redirect,ht as registerActionHandlers,Se as registerExternalUrlHandler,ot as registerFlowActionHandler,Ze as removeHost,R as removeQueryParams,V as removeScheme,Ft as replaceTop,Ce as resetFilterCache,Wt as resolveActivePath,h as resolveConfiguredMessages,Dt as resolveIslandsShell,z as resolveLocaleFromUrl,f as resolveMessages,ae as resolvePluralKey,ie as rewrite,be as route,ye as runAfterLoadGuards,_e as runBeforeLoadGuards,Tt as runStandard,s as safeErrorPage,J as secureFetch,Ae as selectColumn,Vt as selectTab,Ne as serializeNavigation,at as serializeNavigationStable,se as sessionEntryKey,H as setHtmlLocaleAttributes,re as setVisibility,Pt as shouldLog,i as split,j as stableStringify,$e as stack,lt as startBrowserApp,St as str,B as tabs,He as tryScroll,Ye as uuid,u as visibleSplitColumns,Z as withDefault};
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as
|
|
1
|
+
import { $ as IntersectionImpressionObserver, $i as FeatureFlagsProvider, $n as isLeafNode, $r as ConsoleLogger, $t as HydrateOperation, A as ActionHandlerDependencies, Aa as ActionHandler, Ai as AfterLoadGuard, An as SerializedStack, Ar as classifyHost, At as NavigationScopedState, B as getTextDirection, Ba as makeFlowAction, Bi as next, Bn as popTo, Br as BaseShelf, Bt as SessionUrlLocation, C as SessionBridgeOptions, Ca as SecureFetchOptions, Ci as InferOutput, Cn as createFullStateCodec, Cr as AsyncMapper, Ct as createUrlSessionAdapter, D as NavigationBridgeDependencies, Da as IntentController, Di as StandardSchemaV1, Dn as SerializedNavigation, Dr as pipeAsync, Dt as sessionEntryKey, E as defaultShouldRestore, Ea as Intent, Ei as StandardResult, En as SerializedLeaf, Er as pipe, Et as createNavigationScopedState, F as ExternalUrlDependencies, Fa as FlowAction, Fi as NextResult, Fn as collectAllLeaves, Fr as HttpError, Ft as SessionNavigationAdapter, G as PluralCategory, Gi as FINESOFT_PUBLIC, Gn as selectColumn, Gr as PrefetchedIntent, Gt as defineRoutes, H as makeLocaleInfo, Hi as rewrite, Hn as push, Hr as safeErrorPage, Ht as DefineRoutesOptions, I as registerExternalUrlHandler, Ia as isCompoundAction, Ii as PostLoadContext, In as collectVisibleDestinations, Ir as RequestInterceptor, It as SessionSnapshot, J as interpolate, Ji as markPublic, Jn as visibleSplitColumns, Jr as LocaleInfo, Jt as NavigationBrowserConfig, K as PluralRuleProvider, Ki as getPublicFields, Kn as selectTab, Kr as PrefetchedIntents, Kt as route, L as SimpleTranslator, La as isExternalUrlAction, Li as RedirectResult, Ln as findNearestStack, Lr as ResponseInterceptor, Lt as SessionStateProvider, M as FlowActionCallbacks, Ma as Action, Mi as DenyResult, Mn as deserializeNavigation, Mr as HostGuardError, Mt as SESSION_DEFAULT_VERSION, N as FlowActionDependencies, Na as CompoundAction, Ni as MiddlewareResult, Nn as serializeNavigation, Nr as HttpClient, Nt as SessionError, O as NavigationHandle, Oa as Container, Oi as makeSchema, On as SerializedSplit, Or as BaseController, Ot as decodeSnapshot, P as registerFlowActionHandler, Pa as ExternalUrlAction, Pi as NavigationContext, Pn as serializeNavigationStable, Pr as HttpClientConfig, Pt as SessionErrorContext, Q as ImpressionObserverOptions, Qi as FeatureFlags, Qn as TabsInit, Qr as shouldLog, Qt as defineNavigation, R as SimpleTranslatorOptions, Ra as isFlowAction, Ri as RewriteResult, Rn as findNode, Rr as stableStringify, Rt as SessionStore, S as SESSION_DEFAULT_DEBOUNCE_MS, Sa as LoggerFactory, Si as Router, Sn as createFlatStackCodec, Sr as TabsNode, St as createNavigationSessionAdapter, T as createSessionBridge, Ta as IntentDispatcher, Ti as StandardIssue, Tn as encodeNavigationTreeParam, Tr as mapEach, Tt as collectLeafKeys, U as resolveLocaleFromUrl, Ui as BASE_PAGE_FIELDS, Un as replaceTop, Ur as Framework, Ut as RenderMode, V as isRtl, Vi as redirect, Vn as popToRoot, Vr as SafeErrorPageOptions, Vt as isUrlLocation, W as setHtmlLocaleAttributes, Wi as BasePage, Wn as resolveActivePath, Wr as FrameworkConfig, Wt as RouteDefinition, X as WithFieldsRecorder, Xi as defineRequestScopedKey, Xn as islandContainerAttributes, Xr as Translator, Xt as NavigationInitial, Y as resolvePluralKey, Yi as RequestScopedKey, Yn as ResolvedEntry, Yr as TextDirection, Yt as NavigationDefinition, Z as VoidEventRecorder, Zi as DEP_KEYS, Zn as SplitColumnInit, Zr as resetFilterCache, Zt as NavigationSSRDefinition, _ as IslandOrchestratorOptions, _a as ReportingLogger, _i as str, _n as DEFAULT_NAV_PARAM, _r as SPLIT_VISIBILITIES, _t as Optional, a as DomRestore, aa as MessagesLoader, ai as InferQuery, an as NavigationOpKind, ar as stack, at as ServerContextOptions, b as AppHandle, ba as BaseLogger, bi as RouteAddOptions, bn as NavigationRouterLike, br as SplitVisibility, bt as LruMap, c as createWebStorage, ca as resolveConfiguredMessages, ci as StripOptional, cn as PopToOperation, cr as NAVIGATION_NODE_KINDS, ct as generateUuid, d as BrowserAppConfig, da as detectPlatform, di as NumOptions, dn as PushOptions, dr as NavigationNodeKind, dt as removeHost, ea as MakeDependenciesOptions, ei as ConsoleLoggerFactory, en as NAVIGATION_OP_KINDS, er as isSplitNode, et as ConsoleEventRecorder, f as BrowserNavigationConfig, fa as EventRecorder, fi as StrOptions, fn as ReplaceTopOperation, fr as NavigationPath, ft as removeQueryParams, g as IslandOrchestrator, ga as ReportCallback, gi as oneOf, gn as createNavigationController, gr as ResolvedDestination, gt as None, h as IslandHandle, ha as MetricsFieldsProvider, hi as num, hn as SetVisibilityOperation, hr as Page, ht as getPWADisplayMode, i as History, ia as makeDependencies, ii as InferParams, in as NavigationDispatchContext, ir as split, it as BrowserContextOptions, j as registerActionHandlers, ja as ACTION_KINDS, ji as BeforeLoadGuard, jn as SerializedTabs, jr as classifyUrl, jt as SESSION_DEFAULT_KEY, k as createNavigationBridge, ka as ActionDispatcher, ki as runStandard, kn as SerializedSplitColumn, kr as HostCheckResult, kt as encodeSnapshot, l as IslandsShell, la as resolveMessages, li as optional, ln as PopToRootOperation, lr as NavigationError, lt as buildUrl, m as startBrowserApp, ma as ImpressionObserver, mi as int, mn as SelectTabOperation, mr as NavigationSnapshot, mt as PWADisplayMode, n as deserializeServerData, na as Net, ni as CompositeLoggerFactory, nn as NavigationController, nr as isTabsNode, nt as runAfterLoadGuards, o as DomRestoreOptions, oa as MessagesLoaderContext, oi as ParamsFor, on as NavigationOperation, or as tabs, ot as createBrowserContext, p as BrowserSessionConfig, pa as ImpressionEntry, pi as bool, pn as SelectColumnOperation, pr as NavigationPathStep, pt as removeScheme, q as englishPlural, qi as isPublicMarked, qn as setVisibility, qr as LocaleAttributes, qt as DefineNavigationOptions, r as tryScroll, ra as Storage, ri as ExtractParamNames, rn as NavigationControllerOptions, rr as leaf, rt as runBeforeLoadGuards, s as createDomRestore, sa as TranslationMessages, si as QuerySchemaMap, sn as PopOperation, sr as LeafNode, st as createServerContext, t as createPrefetchedIntentsFromDom, ta as MetricsRecorder, ti as CompositeLogger, tn as NavigationContextInput, tr as isStackNode, tt as CompositeEventRecorder, u as resolveIslandsShell, ua as PlatformInfo, ui as withDefault, un as PushOperation, ur as NavigationNode, ut as getBaseUrl, v as MountEntry, va as ReportingLoggerFactory, vi as uuid, vn as FullStateCodecOptions, vr as SplitColumn, vt as isNone, w as SessionHandle, wa as secureFetch, wi as ParamSchema, wn as decodeNavigationTreeParam, wr as Mapper, wt as createSessionStore, x as createAppHandle, xa as Logger, xi as RouteMatch, xn as createActiveLeafCodec, xr as StackNode, xt as UrlAdapterOptions, y as createIslandOrchestrator, ya as ReportingLoggerOptions, yi as RouteParams, yn as NavigationCodec, yr as SplitNode, yt as isSome, z as getLocaleAttributes, za as makeExternalUrlAction, zi as deny, zn as pop, zr as BaseItem, zt as SessionStoreOptions } from "./browser-DMw76sEo.mjs";
|
|
2
2
|
import { Hono } from "hono";
|
|
3
3
|
import * as _$node_fs0 from "node:fs";
|
|
4
4
|
import { ViteDevServer } from "vite";
|
|
@@ -288,6 +288,15 @@ interface SerializeServerDataOptions {
|
|
|
288
288
|
}
|
|
289
289
|
declare function serializeServerData(data: PrefetchedIntent[], options?: SerializeServerDataOptions): string;
|
|
290
290
|
//#endregion
|
|
291
|
+
//#region ../ssr/src/islands.d.ts
|
|
292
|
+
/** 应用提供:把一个目标渲成 HTML(mountEntry 的 SSR 平行物)。可异步(容纳 Vue renderToString)。 */
|
|
293
|
+
type RenderEntry = (entry: ResolvedEntry) => string | Promise<string>;
|
|
294
|
+
/**
|
|
295
|
+
* 渲染快照里所有可见目标为 outlet 内的 island HTML 串。
|
|
296
|
+
* 无可见目标 → 空串;`renderEntry` 按 destinations 顺序依次 await(顺序对 split 多列有意义)。
|
|
297
|
+
*/
|
|
298
|
+
declare function renderIslandsHtml(snapshot: NavigationSnapshot, renderEntry: RenderEntry): Promise<string>;
|
|
299
|
+
//#endregion
|
|
291
300
|
//#region ../server/src/proxy.d.ts
|
|
292
301
|
/** 代理路由认证配置 */
|
|
293
302
|
interface ProxyAuthConfig {
|
|
@@ -686,5 +695,5 @@ declare function finesoftFrontViteConfig(options?: FinesoftFrontViteOptions): {
|
|
|
686
695
|
closeBundle(): Promise<void>;
|
|
687
696
|
};
|
|
688
697
|
//#endregion
|
|
689
|
-
export { ACTION_KINDS, Action, ActionDispatcher, ActionHandler,
|
|
698
|
+
export { ACTION_KINDS, Action, ActionDispatcher, ActionHandler, ActionHandlerDependencies, type Adapter, type AdapterContext, AfterLoadGuard, AppHandle, AsyncMapper, BASE_PAGE_FIELDS, BaseController, BaseItem, BaseLogger, BasePage, BaseShelf, BeforeLoadGuard, BrowserAppConfig, BrowserContextOptions, BrowserNavigationConfig, BrowserSessionConfig, CompositeEventRecorder, CompositeLogger, CompositeLoggerFactory, CompoundAction, ConsoleEventRecorder, ConsoleLogger, ConsoleLoggerFactory, Container, DEFAULT_NAV_PARAM, DEP_KEYS, DefineNavigationOptions, DefineRoutesOptions, DenyResult, DomRestore, DomRestoreOptions, EventRecorder, ExternalUrlAction, ExternalUrlDependencies, ExtractParamNames, FINESOFT_PUBLIC, FeatureFlags, FeatureFlagsProvider, type FinesoftFrontViteOptions, FlowAction, FlowActionCallbacks, FlowActionDependencies, Framework, FrameworkConfig, FullStateCodecOptions, History, HostCheckResult, HostGuardError, HttpClient, HttpClientConfig, HttpError, HydrateOperation, ImpressionEntry, ImpressionObserver, ImpressionObserverOptions, InferOutput, InferParams, InferQuery, type InjectSSROptions, Intent, IntentController, IntentDispatcher, IntersectionImpressionObserver, IslandHandle, IslandOrchestrator, IslandOrchestratorOptions, IslandsShell, LeafNode, LocaleAttributes, LocaleInfo, Logger, Logger as LoggerInterface, LoggerFactory, LruMap, MakeDependenciesOptions, Mapper, MessagesLoader, MessagesLoaderContext, MetricsFieldsProvider, MetricsRecorder, MiddlewareResult, MountEntry, NAVIGATION_NODE_KINDS, NAVIGATION_OP_KINDS, NAVIGATION_TREE_INTENT_ID, NavigationBridgeDependencies, NavigationBrowserConfig, NavigationCodec, NavigationContext, NavigationContextInput, NavigationController, NavigationControllerOptions, NavigationDefinition, NavigationDispatchContext, NavigationError, NavigationHandle, NavigationInitial, NavigationNode, NavigationNodeKind, NavigationOpKind, NavigationOperation, NavigationPath, NavigationPathStep, NavigationRouterLike, NavigationSSRDefinition, NavigationScopedState, NavigationSnapshot, Net, NextResult, None, NumOptions, Optional, PWADisplayMode, Page, ParamSchema, ParamsFor, PlatformInfo, PluralCategory, PluralRuleProvider, PopOperation, PopToOperation, PopToRootOperation, PostLoadContext, PrefetchedIntent, PrefetchedIntents, type ProxyAuthConfig, type ProxyRouteConfig, PushOperation, PushOptions, QuerySchemaMap, RedirectResult, type RenderEntry, RenderMode, ReplaceTopOperation, ReportCallback, ReportingLogger, ReportingLoggerFactory, ReportingLoggerOptions, RequestInterceptor, RequestScopedKey, ResolvedDestination, ResolvedEntry, ResponseInterceptor, RewriteResult, RouteAddOptions, RouteDefinition, RouteMatch, RouteParams, Router, type RuntimeInfo, SESSION_DEFAULT_DEBOUNCE_MS, SESSION_DEFAULT_KEY, SESSION_DEFAULT_VERSION, SPLIT_VISIBILITIES, type SSRAppOptions, type SSRContext, type SSRModule, type SSRNavigationDefinition, type SSRNavigationRenderConfig, type SSRRenderConfig, type SSRRenderNavigationOptions, type SSRRenderNavigationResult, type SSRRenderOptions, type SSRRenderResult, SSR_PLACEHOLDERS, SafeErrorPageOptions, SecureFetchOptions, SelectColumnOperation, SelectTabOperation, type SerializeServerDataOptions, SerializedLeaf, SerializedNavigation, type SerializedNavigationTreePayload, SerializedSplit, SerializedSplitColumn, SerializedStack, SerializedTabs, type ServerConfig, ServerContextOptions, type ServerInstance, SessionBridgeOptions, SessionError, SessionErrorContext, SessionHandle, SessionNavigationAdapter, SessionSnapshot, SessionStateProvider, SessionStore, SessionStoreOptions, SessionUrlLocation, SetVisibilityOperation, SimpleTranslator, SimpleTranslatorOptions, SplitColumn, SplitColumnInit, SplitNode, SplitVisibility, StackNode, StandardIssue, StandardResult, StandardSchemaV1, type StartServerOptions, Storage, StrOptions, StripOptional, TabsInit, TabsNode, TextDirection, TranslationMessages, Translator, UrlAdapterOptions, VoidEventRecorder, WithFieldsRecorder, autoAdapter, bool, buildUrl, classifyHost, classifyUrl, cloudflareAdapter, collectAllLeaves, collectLeafKeys, collectVisibleDestinations, createActiveLeafCodec, createAppHandle, createBrowserContext, createDomRestore, createFlatStackCodec, createFullStateCodec, createIslandOrchestrator, createNavigationBridge, createNavigationController, createNavigationScopedState, createNavigationSessionAdapter, createPrefetchedIntentsFromDom, createSSRApp, createSSRNavigationRender, createSSRRender, createServer, createServerContext, createSessionBridge, createSessionStore, createUrlSessionAdapter, createWebStorage, decodeNavigationTreeParam, decodeSnapshot, defaultShouldRestore, defineNavigation, defineRequestScopedKey, defineRoutes, deny, deserializeNavigation, deserializeServerData, detectPlatform, detectRuntime, encodeNavigationTreeParam, encodeSnapshot, englishPlural, extractNavigationTree, findNearestStack, findNode, finesoftFrontViteConfig, generateProxyCode, generateUuid, getBaseUrl, getLocaleAttributes, getPWADisplayMode, getPublicFields, getTextDirection, injectCSRShell, injectSSRContent, int, interpolate, isCompoundAction, isExternalUrlAction, isFlowAction, isLeafNode, isNone, isPublicMarked, isRtl, isSome, isSplitNode, isStackNode, isTabsNode, isUrlLocation, islandContainerAttributes, leaf, makeDependencies, makeExternalUrlAction, makeFlowAction, makeLocaleInfo, makeSchema, mapEach, markPublic, netlifyAdapter, next, nodeAdapter, num, oneOf, optional, parseAcceptLanguage, pipe, pipeAsync, pop, popTo, popToRoot, push, redirect, registerActionHandlers, registerExternalUrlHandler, registerFlowActionHandler, registerProxyRoutes, removeHost, removeQueryParams, removeScheme, renderIslandsHtml, replaceTop, resetFilterCache, resolveActivePath, resolveAdapter, resolveConfiguredMessages, resolveIslandsShell, resolveLocaleFromUrl, resolveMessages, resolvePluralKey, resolveRoot, rewrite, route, runAfterLoadGuards, runBeforeLoadGuards, runStandard, safeErrorPage, secureFetch, selectColumn, selectTab, serializeNavigation, serializeNavigationStable, serializeServerData, sessionEntryKey, setHtmlLocaleAttributes, setVisibility, shouldLog, split, ssrRender, ssrRenderNavigation, stableStringify, stack, startBrowserApp, startServer, staticAdapter, str, stripNavigationTree, tabs, tryScroll, uuid, vercelAdapter, visibleSplitColumns, withDefault };
|
|
690
699
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{$ as e,$t as t,A as n,At as r,B as i,Bt as a,C as o,Cn as s,Ct as c,D as l,Dt as u,E as d,Et as f,F as p,Ft as m,G as h,Gt as g,H as _,Ht as v,I as y,It as b,J as x,Jt as S,K as ee,Kt as C,L as w,Lt as T,M as E,Mt as te,N as ne,Nt as re,O as ie,Ot as ae,P as D,Pt as oe,Q as se,Qt as ce,R as le,Rt as ue,S as de,Sn as fe,St as O,T as pe,Tn as me,Tt as he,U as ge,Ut as _e,V as ve,Vt as ye,W as be,Wt as xe,X as Se,Xt as Ce,Y as we,Yt as Te,Z as Ee,Zt as De,_ as Oe,_n as ke,_t as Ae,a as je,an as k,at as Me,b as Ne,bn as Pe,bt as A,c as Fe,cn as Ie,ct as Le,d as Re,dn as ze,dt as Be,en as Ve,et as He,f as Ue,fn as We,ft as Ge,g as Ke,gn as qe,gt as Je,h as Ye,hn as Xe,ht as Ze,i as Qe,in as $e,it as et,j as tt,jt as nt,k as j,kt as rt,l as it,ln as at,lt as ot,m as st,mn as ct,mt as lt,n as ut,nn as dt,nt as ft,o as pt,on as mt,ot as M,p as ht,pn as gt,pt as _t,q as vt,qt as yt,r as bt,rn as N,rt as xt,s as St,sn as Ct,st as wt,t as Tt,tn as Et,tt as Dt,u as Ot,un as kt,ut as At,v as jt,vn as Mt,vt as P,w as Nt,wn as Pt,wt as Ft,x as It,xn as Lt,xt as Rt,y as F,yn as zt,yt as Bt,z as Vt,zt as Ht}from"./src-BI4eMjHk.mjs";import{Hono as I}from"hono";async function L(e){return Ut(e,0)}async function Ut(e,t){if(t>=5)throw Error(`[SSR] Rewrite recursion depth exceeded (max 5) at "${e.url}"`);let{url:n,frameworkConfig:r,bootstrap:i,getErrorPage:o,renderApp:s,ssrContext:l,resolveLocale:u,loadMessages:d}=e,f=new URL(n,`http://localhost`),p=f.pathname+f.search,m=u?.(n,l?.request),h=m?{...r,locale:m.lang}:r,g=await N({locale:h.locale,loadMessages:d,context:h.locale?{runtime:`server`,fetch:Wt(l?.fetch??h.fetch),url:p,request:l?.request}:void 0}),_={...h,fetch:l?.fetch??h.fetch},v=c.create({..._,_resolvedMessages:g});i(v);try{let n=await v.routeUrl(p);if(n?.renderMode===`csr`)return{html:``,head:``,css:``,serverData:[],renderMode:`csr`};let r,i=[],c;if(n){let u=F({url:p,intent:n.intent,container:v.container,request:l?.request}),d=await v.runBeforeLoad(u,n.beforeGuards);if(d.kind===`rewrite`)return Ut({...e,url:d.url},t+1);if(d.kind!==`next`){let e=await R(d,o,s,v);if(e)return e}try{r=await v.dispatch(n.intent),i=[{intent:n.intent,data:r}]}catch(e){v.container.resolve(a.LOGGER).error(`[SSR] dispatch failed for intent "${n.intent.id}":`,e),r=o(500,`Internal error`)}let f={...u,page:r},m=await v.runAfterLoad(f,n.afterGuards);if(m.kind===`rewrite`)c=m.url;else if(m.kind!==`next`){let e=await R(m,o,s,v);if(e)return e}}else r=o(404,`Page not found`);let u=await s(r,v),d=m??v.getLocale();return{html:u.html,head:u.head,css:u.css,serverData:i,renderMode:n?.renderMode,slots:u.slots,locale:d,rewriteUrl:c}}finally{v.dispose()}}function Wt(e){return(e??globalThis.fetch?.bind(globalThis))||(()=>{throw Error(`[ssrRender] loadMessages requires a fetch implementation.`)})}async function R(e,t,n,r){switch(e.kind){case`next`:case`rewrite`:return null;case`redirect`:return{html:``,head:``,css:``,serverData:[],redirect:{url:e.url,status:e.status}};case`deny`:{let i=await n(t(e.status,e.message),r);return{html:i.html,head:i.head,css:i.css,serverData:[],slots:i.slots,status:e.status}}}}function Gt(e){let{bootstrap:t,getErrorPage:n,renderApp:r,frameworkConfig:i,resolveLocale:a,loadMessages:o}=e;return(e,s)=>L({url:e,frameworkConfig:i??{},bootstrap:t,getErrorPage:n,renderApp:(e,t)=>r(e,t),ssrContext:s,resolveLocale:a,loadMessages:o})}const Kt={HEAD:`<!--ssr-head-->`,BODY:`<!--ssr-body-->`,DATA:`<!--ssr-data-->`},z=/<!--ssr-([a-z][a-z0-9-]*)-->/g;function B(e){let{template:t,head:n,css:r,html:i,serializedData:a,slots:o,locale:s}=e,c={head:`${n}\n${r?`<style>${r}</style>`:``}`,body:i,data:`<script id="serialized-server-data" type="application/json">${a}<\/script>`,...o},l=t.replace(z,(e,t)=>c[t]??``);return s&&(l=Yt(l,s)),l}function V(e,t){let n=e.replace(z,()=>``);return t&&(n=Yt(n,t)),n}const qt=/\s+lang=("[^"]*"|'[^']*'|[^\s>]+)/gi,Jt=/\s+dir=("[^"]*"|'[^']*'|[^\s>]+)/gi;function Yt(e,t){return e.replace(/(<html)([^>]*)(>)/i,(e,n,r,i)=>`${n}${r.replace(qt,``).replace(Jt,``)} lang="${t.lang}" dir="${t.dir}"${i}`)}const Xt=`@finesoft/navigation-tree`;async function Zt(e){let{url:t,frameworkConfig:n,bootstrap:r,getErrorPage:i,renderApp:a,navigation:o,ssrContext:s,resolveLocale:l,loadMessages:u}=e,d=new URL(t,`http://localhost`),f=d.pathname+d.search,p=l?.(t,s?.request),m=p?{...n,locale:p.lang}:n,h=await N({locale:m.locale,loadMessages:u,context:m.locale?{runtime:`server`,fetch:un(s?.fetch??m.fetch),url:f,request:s?.request}:void 0}),g={...m,fetch:s?.fetch??m.fetch},_=c.create({...g,_resolvedMessages:h});r(_);try{let e=await Qt(_,o,f);if(e===void 0)return ln({framework:_,resolvedLocale:p,renderApp:a,page:i(404,`Page not found`),snapshot:{tree:M(`@finesoft/not-found`),destinations:[]},serverData:[],renderMode:void 0,status:void 0});let{tree:t,renderMode:n}=e;if(n===`csr`)return{html:``,head:``,css:``,serverData:[],renderMode:`csr`,snapshot:{tree:t,destinations:[]}};let r,c=await $t({framework:_,navigation:o,initialTree:t,fullPath:f,request:s?.request,getErrorPage:i,onRedirect:e=>{r??=e}}).resolve();if(r!==void 0)return{html:``,head:``,css:``,serverData:[],redirect:r,snapshot:c};let l=en(c,i);return ln({framework:_,resolvedLocale:p,renderApp:a,page:l.page,snapshot:c,serverData:rn(c),renderMode:n,status:l.status})}finally{_.dispose()}}async function Qt(e,t,n){let r=t.codec.decode(n,e.router);if(r!==void 0)return{tree:r,renderMode:void 0};let i=t.initial?.(n);if(i!==void 0)return{tree:i,renderMode:void 0};let a=await e.routeUrl(n);if(a!==null)return{tree:M(a.intent.id,a.intent.params??{}),renderMode:a.renderMode}}function $t(e){let{framework:t,navigation:n,initialTree:r,fullPath:i,request:a,getErrorPage:o,onRedirect:s}=e;return D({intentDispatcher:t.intentDispatcher,router:t.router,initial:r,beforeLoad:n.beforeLoad,afterLoad:n.afterLoad,getErrorPage:o,onRedirect:s,createContext:({intent:e,params:n})=>({container:t.container,url:i,navigation:F({url:i,intent:{id:e,params:n},container:t.container,request:a})})})}function en(e,t){let n=tn(e.tree);if(n!==void 0){let t=e.destinations.find(e=>e.intent===n.intent&&nn(e.params,n.params));if(t!==void 0)return t}return e.destinations.length>0?e.destinations[0]:{intent:`@finesoft/empty`,params:{},page:t(404,`Page not found`),status:404}}function tn(e){let t=e;for(;;)switch(t.kind){case`leaf`:return{intent:t.intent,params:t.params};case`stack`:if(t.entries.length===0)return;t=t.entries[t.entries.length-1];break;case`tabs`:{let e=t.branches[t.active];if(e===void 0)return;t=e;break}case`split`:{let e;for(let n of t.columns)n.content!==void 0&&(e=n.content);if(e===void 0)return;t=e;break}}}function nn(e,t){let n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return!1;for(let r of n)if(e[r]!==t[r])return!1;return!0}function rn(e){let t=[];for(let n of e.destinations)t.push({intent:{id:n.intent,params:n.params},data:n.page});return t.push(an(e.tree)),t}function an(e){let t={__finesoftNavigationTree:!0,tree:ve(e)};return{intent:{id:Xt},data:O(t,!0)}}function on(e){for(let t of e)if(cn(t))return i(t.data.tree)}function sn(e){return e.filter(e=>!cn(e))}function cn(e){if(e.intent.id!==`@finesoft/navigation-tree`)return!1;let t=e.data;return typeof t==`object`&&!!t&&t.__finesoftNavigationTree===!0}async function ln(e){let{framework:t,resolvedLocale:n,renderApp:r,page:i,snapshot:a,serverData:o,renderMode:s,status:c}=e,l=await r(i,t,a),u=n??t.getLocale();return{html:l.html,head:l.head,css:l.css,serverData:o,renderMode:s,slots:l.slots,locale:u,status:c,snapshot:a}}function un(e){return(e??globalThis.fetch?.bind(globalThis))||(()=>{throw Error(`[ssrRenderNavigation] loadMessages requires a fetch implementation.`)})}function dn(e){let{bootstrap:t,getErrorPage:n,renderApp:r,navigation:i,frameworkConfig:a,resolveLocale:o,loadMessages:s}=e;return(e,c)=>Zt({url:e,frameworkConfig:a??{},bootstrap:t,getErrorPage:n,renderApp:r,navigation:i,ssrContext:c,resolveLocale:o,loadMessages:s})}const fn={"<":`\\u003C`,">":`\\u003E`,"/":`\\u002F`,"\u2028":`\\u2028`,"\u2029":`\\u2029`},pn=RegExp(`[<>/\\u2028\\u2029]`,`g`);let mn=!1;function hn(e,t={}){let n=t.onUnmarkedPage??`all`,r=e.map(e=>gn(e,n));return JSON.stringify(r).replace(pn,e=>fn[e]??e)}function gn(e,t){let n=e.data,r=A(n);if(r===!0)return e;if(Array.isArray(r))return{...e,data:_n(n,r)};if(t===`strict`)throw Error(`[serializeServerData] page for intent "${e.intent.id}" has no markPublic marker; wrap it with markPublic(page, ["field", ...]) to declare client-visible fields.`);return t===`base-fields`?{...e,data:_n(n,P)}:(vn(e.intent.id),e)}function _n(e,t){let n={};for(let r of t)r in e&&(n[r]=e[r]);return n}function vn(e){mn||(mn=!0,yn()&&console.warn(`[finesoft/ssr] Page for intent "${e}" was serialized without markPublic(); all fields (including any sensitive data) are exposed in the SSR HTML. Wrap your page with markPublic(page, ["field", ...]) to declare client-visible fields explicitly. The next major version will default to BasePage-only fields when no marker is present.`))}function yn(){try{return globalThis.process?.env?.NODE_ENV!==`production`}catch{return!1}}const bn=new Map,xn=e=>import(e),Sn=typeof process<`u`&&process.env?.FINESOFT_DEBUG===`1`;function Cn(e){Sn&&console.debug(`[finesoft:dynamic-import] ${e}`)}async function H(e){let t=!e.startsWith(`file:`)&&!e.startsWith(`/`);if(t){let t=bn.get(e);if(t)return Cn(`cache hit → ${e}`),t}Cn(`importing → ${e}`);let n=await xn(e);return t&&bn.set(e,n),n}const U=10*1024*1024;function wn(e){if(e.length>2048)return null;try{if(decodeURIComponent(e)!==e)return null}catch{return null}return e.startsWith(`//`)||!/^[/\w.\-~%:@!$&'()*+,;=]*$/.test(e)?null:e.startsWith(`/`)?e:`/${e}`}function Tn(e){if(!e.prefix.startsWith(`/`))throw Error(`[proxy] prefix must start with "/": "${e.prefix}"`);let t=e.target.startsWith(`https://`),n=e.target.startsWith(`http://`);if(!t&&!n)throw Error(`[proxy] target must start with "https://" or "http://": "${e.target}"`);n&&console.warn(`[proxy] ⚠ target "${e.target}" uses plain HTTP — traffic will not be encrypted. Use HTTPS in production to prevent data interception.`)}function W(e,t){for(let n of t){Tn(n);let t=n.methods??[`all`],r=`${n.prefix}/*`,i=async e=>{let t=wn(e.req.path.replace(n.prefix,``));if(!t)return e.text(`Invalid path`,400);let r=new URL(t,n.target),i=new URL(n.target).origin;if(r.origin!==i)return e.text(`Invalid proxy target`,400);new URL(e.req.url).searchParams.forEach((e,t)=>r.searchParams.set(t,e));let a={...n.headers};if(n.auth){let e=process.env[n.auth.envKey];e?a.Authorization=n.auth.type===`bearer`?`Bearer ${e}`:`Basic ${e}`:console.warn(`[Proxy ${n.prefix}] Auth env var "${n.auth.envKey}" is not set`)}try{let t=await fetch(r.toString(),{headers:a,redirect:n.followRedirects?`follow`:`manual`}),i=t.headers.get(`Content-Length`);if(i&&parseInt(i,10)>U)return e.text(`Proxy response too large`,502);let o=await t.arrayBuffer();if(o.byteLength>U)return e.text(`Proxy response too large`,502);let s={"Content-Type":t.headers.get(`Content-Type`)??`application/json`};return n.cache&&(s[`Cache-Control`]=n.cache),e.newResponse(o,t.status,s)}catch(t){return console.error(`[Proxy ${n.prefix}]`,t),e.json({error:`Proxy request failed`},502)}};for(let n of t)e[n](r,i)}}function En(e){if(!e||e.length===0)return``;for(let t of e)Tn(t);let t=[];t.push(`
|
|
1
|
+
import{$ as e,$t as t,A as n,An as r,At as i,B as a,Bn as o,Bt as s,C as c,Cn as l,Ct as u,D as d,Dn as f,Dt as p,E as m,En as h,Et as g,F as _,Fn as v,Ft as y,G as b,Gn as x,Gt as S,H as C,Hn as w,Ht as T,I as E,In as D,It as ee,J as te,Jn as ne,Jt as re,K as ie,Kn as ae,Kt as O,L as k,Ln as oe,Lt as se,M as ce,Mn as le,Mt as ue,N as de,Nn as fe,Nt as pe,O as me,On as A,Ot as he,P as ge,Pn as _e,Pt as ve,Q as ye,Qt as be,R as xe,Rn as Se,Rt as Ce,S as we,Sn as Te,St as Ee,T as De,Tn as Oe,Tt as ke,U as Ae,Un as je,Ut as Me,V as Ne,Vn as Pe,Vt as j,W as Fe,Wn as Ie,Wt as Le,X as Re,Xt as ze,Y as Be,Yt as Ve,Z as He,Zt as Ue,_ as We,_n as Ge,_t as Ke,a as qe,an as Je,at as Ye,b as Xe,bn as Ze,bt as Qe,c as $e,cn as et,ct as M,d as tt,dn as nt,dt as rt,en as it,et as at,f as ot,fn as st,ft as ct,g as lt,gn as ut,gt as dt,h as ft,hn as pt,ht as mt,i as ht,in as gt,it as _t,j as vt,jn as yt,jt as bt,k as xt,kn as St,kt as N,l as Ct,ln as wt,lt as Tt,m as Et,mn as Dt,mt as Ot,n as kt,nn as At,nt as jt,o as Mt,on as Nt,ot as Pt,p as Ft,pn as It,pt as Lt,q as Rt,qn as zt,qt as Bt,r as Vt,rn as Ht,rt as Ut,s as Wt,sn as Gt,st as Kt,t as qt,tn as Jt,tt as Yt,u as Xt,un as Zt,ut as Qt,v as $t,vn as en,vt as tn,w as nn,wn as rn,wt as an,x as on,xn as sn,xt as cn,y as ln,yn as un,yt as dn,z as fn,zn as pn,zt as mn}from"./browser-BIetJHp_.mjs";import{Hono as P}from"hono";async function hn(e){return F(e,0)}async function F(e,t){if(t>=5)throw Error(`[SSR] Rewrite recursion depth exceeded (max 5) at "${e.url}"`);let{url:n,frameworkConfig:r,bootstrap:i,getErrorPage:a,renderApp:o,ssrContext:s,resolveLocale:c,loadMessages:l}=e,u=new URL(n,`http://localhost`),f=u.pathname+u.search,p=c?.(n,s?.request),m=p?{...r,locale:p.lang}:r,g=await h({locale:m.locale,loadMessages:l,context:m.locale?{runtime:`server`,fetch:gn(s?.fetch??m.fetch),url:f,request:s?.request}:void 0}),_={...m,fetch:s?.fetch??m.fetch},v=O.create({..._,_resolvedMessages:g});i(v);try{let n=await v.routeUrl(f);if(n?.renderMode===`csr`)return{html:``,head:``,css:``,serverData:[],renderMode:`csr`};let r,i=[],c;if(n){let l=d({url:f,intent:n.intent,container:v.container,request:s?.request}),u=await v.runBeforeLoad(l,n.beforeGuards);if(u.kind===`rewrite`)return F({...e,url:u.url},t+1);if(u.kind!==`next`){let e=await I(u,a,o,v);if(e)return e}try{r=await v.dispatch(n.intent),i=[{intent:n.intent,data:r}]}catch(e){v.container.resolve(wt.LOGGER).error(`[SSR] dispatch failed for intent "${n.intent.id}":`,e),r=a(500,`Internal error`)}let p={...l,page:r},m=await v.runAfterLoad(p,n.afterGuards);if(m.kind===`rewrite`)c=m.url;else if(m.kind!==`next`){let e=await I(m,a,o,v);if(e)return e}}else r=a(404,`Page not found`);let l=await o(r,v),u=p??v.getLocale();return{html:l.html,head:l.head,css:l.css,serverData:i,renderMode:n?.renderMode,slots:l.slots,locale:u,rewriteUrl:c}}finally{v.dispose()}}function gn(e){return(e??globalThis.fetch?.bind(globalThis))||(()=>{throw Error(`[ssrRender] loadMessages requires a fetch implementation.`)})}async function I(e,t,n,r){switch(e.kind){case`next`:case`rewrite`:return null;case`redirect`:return{html:``,head:``,css:``,serverData:[],redirect:{url:e.url,status:e.status}};case`deny`:{let i=await n(t(e.status,e.message),r);return{html:i.html,head:i.head,css:i.css,serverData:[],slots:i.slots,status:e.status}}}}function _n(e){let{bootstrap:t,getErrorPage:n,renderApp:r,frameworkConfig:i,resolveLocale:a,loadMessages:o}=e;return(e,s)=>hn({url:e,frameworkConfig:i??{},bootstrap:t,getErrorPage:n,renderApp:(e,t)=>r(e,t),ssrContext:s,resolveLocale:a,loadMessages:o})}const vn={HEAD:`<!--ssr-head-->`,BODY:`<!--ssr-body-->`,DATA:`<!--ssr-data-->`},L=/<!--ssr-([a-z][a-z0-9-]*)-->/g;function R(e){let{template:t,head:n,css:r,html:i,serializedData:a,slots:o,locale:s}=e,c={head:`${n}\n${r?`<style>${r}</style>`:``}`,body:i,data:`<script id="serialized-server-data" type="application/json">${a}<\/script>`,...o},l=t.replace(L,(e,t)=>c[t]??``);return s&&(l=B(l,s)),l}function z(e,t){let n=e.replace(L,()=>``);return t&&(n=B(n,t)),n}const yn=/\s+lang=("[^"]*"|'[^']*'|[^\s>]+)/gi,bn=/\s+dir=("[^"]*"|'[^']*'|[^\s>]+)/gi;function B(e,t){return e.replace(/(<html)([^>]*)(>)/i,(e,n,r,i)=>`${n}${r.replace(yn,``).replace(bn,``)} lang="${t.lang}" dir="${t.dir}"${i}`)}const V=`@finesoft/navigation-tree`;async function H(e){let{url:t,frameworkConfig:n,bootstrap:r,getErrorPage:i,renderApp:a,navigation:o,ssrContext:s,resolveLocale:c,loadMessages:l}=e,u=new URL(t,`http://localhost`),d=u.pathname+u.search,f=c?.(t,s?.request),p=f?{...n,locale:f.lang}:n,m=await h({locale:p.locale,loadMessages:l,context:p.locale?{runtime:`server`,fetch:Mn(s?.fetch??p.fetch),url:d,request:s?.request}:void 0}),g={...p,fetch:s?.fetch??p.fetch},_=O.create({...g,_resolvedMessages:m});r(_);try{let e=await xn(_,o,d);if(e===void 0)return jn({framework:_,resolvedLocale:f,renderApp:a,page:i(404,`Page not found`),snapshot:{tree:N(`@finesoft/not-found`),destinations:[]},serverData:[],renderMode:void 0,status:void 0});let{tree:t,renderMode:n}=e;if(n===`csr`)return{html:``,head:``,css:``,serverData:[],renderMode:`csr`,snapshot:{tree:t,destinations:[]}};let r,c=await Sn({framework:_,navigation:o,initialTree:t,fullPath:d,request:s?.request,getErrorPage:i,onRedirect:e=>{r??=e}}).resolve();if(r!==void 0)return{html:``,head:``,css:``,serverData:[],redirect:r,snapshot:c};let l=Cn(c,i);return jn({framework:_,resolvedLocale:f,renderApp:a,page:l.page,snapshot:c,serverData:En(c),renderMode:n,status:l.status})}finally{_.dispose()}}async function xn(e,t,n){let r=t.codec.decode(n,e.router);if(r!==void 0)return{tree:r,renderMode:void 0};let i=t.initial?.(n);if(i!==void 0)return{tree:i,renderMode:void 0};let a=await e.routeUrl(n);if(a!==null)return{tree:N(a.intent.id,a.intent.params??{}),renderMode:a.renderMode}}function Sn(e){let{framework:t,navigation:n,initialTree:r,fullPath:i,request:a,getErrorPage:o,onRedirect:s}=e;return at({intentDispatcher:t.intentDispatcher,router:t.router,initial:r,beforeLoad:n.beforeLoad,afterLoad:n.afterLoad,getErrorPage:o,onRedirect:s,createContext:({intent:e,params:n})=>({container:t.container,url:i,navigation:d({url:i,intent:{id:e,params:n},container:t.container,request:a})})})}function Cn(e,t){let n=wn(e.tree);if(n!==void 0){let t=e.destinations.find(e=>e.intent===n.intent&&Tn(e.params,n.params));if(t!==void 0)return t}return e.destinations.length>0?e.destinations[0]:{intent:`@finesoft/empty`,params:{},page:t(404,`Page not found`),status:404}}function wn(e){let t=e;for(;;)switch(t.kind){case`leaf`:return{intent:t.intent,params:t.params};case`stack`:if(t.entries.length===0)return;t=t.entries[t.entries.length-1];break;case`tabs`:{let e=t.branches[t.active];if(e===void 0)return;t=e;break}case`split`:{let e;for(let n of t.columns)n.content!==void 0&&(e=n.content);if(e===void 0)return;t=e;break}}}function Tn(e,t){let n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return!1;for(let r of n)if(e[r]!==t[r])return!1;return!0}function En(e){let t=[];for(let n of e.destinations)t.push({intent:{id:n.intent,params:n.params},data:n.page});return t.push(Dn(e.tree)),t}function Dn(e){let t={__finesoftNavigationTree:!0,tree:M(e)};return{intent:{id:V},data:S(t,!0)}}function On(e){for(let t of e)if(An(t))return Kt(t.data.tree)}function kn(e){return e.filter(e=>!An(e))}function An(e){if(e.intent.id!==`@finesoft/navigation-tree`)return!1;let t=e.data;return typeof t==`object`&&!!t&&t.__finesoftNavigationTree===!0}async function jn(e){let{framework:t,resolvedLocale:n,renderApp:r,page:i,snapshot:a,serverData:o,renderMode:s,status:c}=e,l=await r(i,t,a),u=n??t.getLocale();return{html:l.html,head:l.head,css:l.css,serverData:o,renderMode:s,slots:l.slots,locale:u,status:c,snapshot:a}}function Mn(e){return(e??globalThis.fetch?.bind(globalThis))||(()=>{throw Error(`[ssrRenderNavigation] loadMessages requires a fetch implementation.`)})}function Nn(e){let{bootstrap:t,getErrorPage:n,renderApp:r,navigation:i,frameworkConfig:a,resolveLocale:o,loadMessages:s}=e;return(e,c)=>H({url:e,frameworkConfig:a??{},bootstrap:t,getErrorPage:n,renderApp:r,navigation:i,ssrContext:c,resolveLocale:o,loadMessages:s})}const Pn={"<":`\\u003C`,">":`\\u003E`,"/":`\\u002F`,"\u2028":`\\u2028`,"\u2029":`\\u2029`},Fn=RegExp(`[<>/\\u2028\\u2029]`,`g`);let In=!1;function Ln(e,t={}){let n=t.onUnmarkedPage??`all`,r=e.map(e=>Rn(e,n));return JSON.stringify(r).replace(Fn,e=>Pn[e]??e)}function Rn(e,t){let n=e.data,r=Me(n);if(r===!0)return e;if(Array.isArray(r))return{...e,data:zn(n,r)};if(t===`strict`)throw Error(`[serializeServerData] page for intent "${e.intent.id}" has no markPublic marker; wrap it with markPublic(page, ["field", ...]) to declare client-visible fields.`);return t===`base-fields`?{...e,data:zn(n,j)}:(Bn(e.intent.id),e)}function zn(e,t){let n={};for(let r of t)r in e&&(n[r]=e[r]);return n}function Bn(e){In||(In=!0,Vn()&&console.warn(`[finesoft/ssr] Page for intent "${e}" was serialized without markPublic(); all fields (including any sensitive data) are exposed in the SSR HTML. Wrap your page with markPublic(page, ["field", ...]) to declare client-visible fields explicitly. The next major version will default to BasePage-only fields when no marker is present.`))}function Vn(){try{return globalThis.process?.env?.NODE_ENV!==`production`}catch{return!1}}function Hn(e){return Object.entries(e).map(([e,t])=>t===``?e:`${e}="${Un(t)}"`).join(` `)}function Un(e){return e.replace(/&/g,`&`).replace(/"/g,`"`).replace(/</g,`<`)}async function Wn(e,t){let n=[];for(let r of e.destinations){let e=Ae(r.intent,r.params),i=await t({intent:r.intent,params:r.params,entryKey:e,page:r.page}),a=Hn(an(r.intent,e));n.push(`<div ${a}>${i}</div>`)}return n.join(``)}const Gn=new Map,Kn=e=>import(e),qn=typeof process<`u`&&process.env?.FINESOFT_DEBUG===`1`;function Jn(e){qn&&console.debug(`[finesoft:dynamic-import] ${e}`)}async function U(e){let t=!e.startsWith(`file:`)&&!e.startsWith(`/`);if(t){let t=Gn.get(e);if(t)return Jn(`cache hit → ${e}`),t}Jn(`importing → ${e}`);let n=await Kn(e);return t&&Gn.set(e,n),n}const W=10*1024*1024;function Yn(e){if(e.length>2048)return null;try{if(decodeURIComponent(e)!==e)return null}catch{return null}return e.startsWith(`//`)||!/^[/\w.\-~%:@!$&'()*+,;=]*$/.test(e)?null:e.startsWith(`/`)?e:`/${e}`}function Xn(e){if(!e.prefix.startsWith(`/`))throw Error(`[proxy] prefix must start with "/": "${e.prefix}"`);let t=e.target.startsWith(`https://`),n=e.target.startsWith(`http://`);if(!t&&!n)throw Error(`[proxy] target must start with "https://" or "http://": "${e.target}"`);n&&console.warn(`[proxy] ⚠ target "${e.target}" uses plain HTTP — traffic will not be encrypted. Use HTTPS in production to prevent data interception.`)}function G(e,t){for(let n of t){Xn(n);let t=n.methods??[`all`],r=`${n.prefix}/*`,i=async e=>{let t=Yn(e.req.path.replace(n.prefix,``));if(!t)return e.text(`Invalid path`,400);let r=new URL(t,n.target),i=new URL(n.target).origin;if(r.origin!==i)return e.text(`Invalid proxy target`,400);new URL(e.req.url).searchParams.forEach((e,t)=>r.searchParams.set(t,e));let a={...n.headers};if(n.auth){let e=process.env[n.auth.envKey];e?a.Authorization=n.auth.type===`bearer`?`Bearer ${e}`:`Basic ${e}`:console.warn(`[Proxy ${n.prefix}] Auth env var "${n.auth.envKey}" is not set`)}try{let t=await fetch(r.toString(),{headers:a,redirect:n.followRedirects?`follow`:`manual`}),i=t.headers.get(`Content-Length`);if(i&&parseInt(i,10)>W)return e.text(`Proxy response too large`,502);let o=await t.arrayBuffer();if(o.byteLength>W)return e.text(`Proxy response too large`,502);let s={"Content-Type":t.headers.get(`Content-Type`)??`application/json`};return n.cache&&(s[`Cache-Control`]=n.cache),e.newResponse(o,t.status,s)}catch(t){return console.error(`[Proxy ${n.prefix}]`,t),e.json({error:`Proxy request failed`},502)}};for(let n of t)e[n](r,i)}}function Zn(e){if(!e||e.length===0)return``;for(let t of e)Xn(t);let t=[];t.push(`
|
|
2
2
|
// ─── 框架声明式代理路由 ───
|
|
3
3
|
function _sanitizeProxyPath(raw) {
|
|
4
4
|
if (raw.length > 2048) return null;
|
|
@@ -21,12 +21,12 @@ function _sanitizeProxyPath(raw) {
|
|
|
21
21
|
const _resp = await fetch(_target.toString(), { headers: _headers, redirect: ${o} });
|
|
22
22
|
// Content-Length 快速拒绝,防止 serverless/edge 加载超大响应到内存
|
|
23
23
|
const _cl = _resp.headers.get("Content-Length");
|
|
24
|
-
if (_cl && parseInt(_cl, 10) > ${
|
|
24
|
+
if (_cl && parseInt(_cl, 10) > ${W}) {
|
|
25
25
|
return c.text("Proxy response too large", 502);
|
|
26
26
|
}
|
|
27
27
|
// arrayBuffer 保留二进制完整性
|
|
28
28
|
const _body = await _resp.arrayBuffer();
|
|
29
|
-
if (_body.byteLength > ${
|
|
29
|
+
if (_body.byteLength > ${W}) {
|
|
30
30
|
return c.text("Proxy response too large", 502);
|
|
31
31
|
}
|
|
32
32
|
const _rh = { "Content-Type": _resp.headers.get("Content-Type") || "application/json" };
|
|
@@ -37,7 +37,7 @@ function _sanitizeProxyPath(raw) {
|
|
|
37
37
|
return c.json({ error: "Proxy request failed" }, 502);
|
|
38
38
|
}
|
|
39
39
|
}`;for(let n of e)t.push(`app.${n}(${r}, ${c});`)}return t.join(`
|
|
40
|
-
`)}const
|
|
40
|
+
`)}const Qn=[`vite`,`esbuild`,`rollup`,`fsevents`,`lightningcss`],$n=[`node:async_hooks`,`node:buffer`,`node:crypto`,`node:fs`,`node:http`,`node:http2`,`node:module`,`node:net`,`node:os`,`node:path`,`node:stream`,`node:url`,`node:util`,`node:zlib`,`crypto`,`http`,`http2`,`stream`];function K(e,t){let n=e.setupPath?`import _setupDefault from "./${e.setupPath}";`:``,r=e.setupPath?`if (typeof _setupDefault === "function") await _setupDefault(app);`:``,i=JSON.stringify(e.renderModes??{}),a=t.platformCache?t.platformCache:`
|
|
41
41
|
const ISR_CACHE_MAX = 1000;
|
|
42
42
|
const _isrMap = new Map();
|
|
43
43
|
async function platformCacheGet(url) {
|
|
@@ -109,7 +109,7 @@ function matchRenderMode(url) {
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
const app = new Hono();
|
|
112
|
-
${
|
|
112
|
+
${Zn(e.proxies??[])}
|
|
113
113
|
${r}
|
|
114
114
|
${t.platformMiddleware??``}
|
|
115
115
|
|
|
@@ -173,8 +173,8 @@ app.get("*", async (c) => {
|
|
|
173
173
|
});
|
|
174
174
|
|
|
175
175
|
${t.platformExport}
|
|
176
|
-
`}async function
|
|
177
|
-
<style>`+i+`</style>`,body:n,data:`<script id="serialized-server-data" type="application/json">`+s+`<\/script>`})[t]??``);if(o){let{getLocaleAttributes:e}=await
|
|
176
|
+
`}async function q(e,t){await e.vite.build({root:e.root,build:{ssr:t.entry,outDir:t.outDir,emptyOutDir:t.emptyOutDir??!0,target:t.target??`node18`,rollupOptions:{output:{entryFileNames:t.fileName??`index.mjs`}}},ssr:{noExternal:t.noExternal!==!1,external:[...t.external??Qn,...$n]},resolve:e.resolvedResolve,css:e.resolvedCss})}function J(e,t,n){let{fs:r,path:i}=e;r.cpSync(i.resolve(e.root,`dist/client`),t,{recursive:!0}),n?.excludeHtml!==!1&&r.rmSync(i.join(t,`index.html`),{force:!0})}async function Y(e){let{fs:t,path:n,root:r,vite:i}=e,{pathToFileURL:a}=await U(`node:url`),o=e.bootstrapEntry??`src/lib/bootstrap.ts`,s=[];if(t.existsSync(n.resolve(r,o))){await i.build({root:r,build:{ssr:o,outDir:n.resolve(r,`dist/server`),emptyOutDir:!1,rollupOptions:{output:{entryFileNames:`_routes_prerender.mjs`}}},resolve:e.resolvedResolve});let c=a(n.resolve(r,`dist/server/_routes_prerender.mjs`)).href,l=await U(c);s=l.routes??l.default??[],t.rmSync(n.resolve(r,`dist/server/_routes_prerender.mjs`),{force:!0})}let c=new Set;for(let e of s)e.renderMode===`prerender`&&e.path&&!e.path.includes(`:`)&&c.add(e.path);if(e.renderModes)for(let[t,n]of Object.entries(e.renderModes))n===`prerender`&&!t.includes(`*`)&&!t.includes(`:`)&&c.add(t);if(e.locales?.length){let t=[...c];for(let n of e.locales)for(let e of t){let t=e===`/`?`/${n}`:`/${n}${e}`;c.add(t)}}if(c.size===0)return[];let l=a(n.resolve(r,`dist/server/ssr.js`)).href,u=await U(l),d=[];for(let t of c)try{let{html:n,head:r,css:i,serverData:a,locale:o}=await u.render(t),s=u.serializeServerData(a),c=e.templateHtml.replace(/<!--ssr-([a-z][a-z0-9-]*)-->/g,(e,t)=>({head:r+`
|
|
177
|
+
<style>`+i+`</style>`,body:n,data:`<script id="serialized-server-data" type="application/json">`+s+`<\/script>`})[t]??``);if(o){let{getLocaleAttributes:e}=await U(`@finesoft/core`),t=e(o);c=c.replace(/<html([^>]*)>/i,(e,n)=>`<html${n.replace(/\s+lang=("[^"]*"|'[^']*'|[^\s>]+)/gi,``).replace(/\s+dir=("[^"]*"|'[^']*'|[^\s>]+)/gi,``)} lang="${t.lang}" dir="${t.dir}">`)}d.push({url:t,html:c})}catch(e){console.warn(` [prerender] Failed to render ${t}:`,e)}return d.length>0&&console.log(` Pre-rendered ${d.length} pages (${c.size} routes)\n`),d}function er(){return{name:`cloudflare`,async build(e){let{fs:t,path:n,root:r}=e,i=n.resolve(r,`dist/cloudflare`);t.rmSync(i,{recursive:!0,force:!0});let a=K(e,{platformImport:``,platformExport:`export default app;`,platformCache:`
|
|
178
178
|
const ISR_CACHE_TTL = 3600; // 1 hour
|
|
179
179
|
async function platformCacheGet(url) {
|
|
180
180
|
try {
|
|
@@ -194,8 +194,8 @@ async function platformCacheSet(url, html) {
|
|
|
194
194
|
});
|
|
195
195
|
await cache.put(cacheKey, resp);
|
|
196
196
|
} catch {}
|
|
197
|
-
}`}),o=n.resolve(r,`.cf-entry.tmp.mjs`);t.writeFileSync(o,a);try{await
|
|
198
|
-
`)}}}function
|
|
197
|
+
}`}),o=n.resolve(r,`.cf-entry.tmp.mjs`);t.writeFileSync(o,a);try{await q(e,{entry:`.cf-entry.tmp.mjs`,outDir:i,target:`es2022`,fileName:`_worker.js`}),J(e,n.resolve(i,`assets`));let r=await Y(e);for(let{url:e,html:a}of r){let r=e===`/`?n.join(i,`assets`,`index.html`):n.join(i,`assets`,e,`index.html`);t.mkdirSync(n.resolve(r,`..`),{recursive:!0}),t.writeFileSync(r,a)}}finally{t.rmSync(o,{force:!0})}console.log(` Cloudflare output → dist/cloudflare/
|
|
198
|
+
`)}}}function tr(){return{name:`netlify`,async build(e){let{fs:t,path:n,root:r}=e,i=n.resolve(r,`.netlify/functions-internal/ssr`);t.rmSync(n.resolve(r,`.netlify`),{recursive:!0,force:!0});let a=K(e,{platformImport:`import { handle } from "hono/netlify";`,platformExport:`export default handle(app);
|
|
199
199
|
export const config = { path: "/*", preferStatic: true };`,platformCache:`
|
|
200
200
|
const ISR_SWR_TTL = 3600;
|
|
201
201
|
const ISR_CACHE_MAX = 1000;
|
|
@@ -210,10 +210,10 @@ async function platformCacheSet(url, html) {
|
|
|
210
210
|
}
|
|
211
211
|
_isrMap.set(url, html);
|
|
212
212
|
}`,platformPrerenderResponseHook:`c.header("Cache-Control", "public, max-age=0, must-revalidate");
|
|
213
|
-
c.header("Netlify-CDN-Cache-Control", "public, max-age=" + ISR_SWR_TTL + ", stale-while-revalidate=" + ISR_SWR_TTL + ", durable");`}),o=n.resolve(r,`.netlify-entry.tmp.mjs`);t.writeFileSync(o,a);try{await
|
|
214
|
-
`);let s=await
|
|
213
|
+
c.header("Netlify-CDN-Cache-Control", "public, max-age=" + ISR_SWR_TTL + ", stale-while-revalidate=" + ISR_SWR_TTL + ", durable");`}),o=n.resolve(r,`.netlify-entry.tmp.mjs`);t.writeFileSync(o,a);try{await q(e,{entry:`.netlify-entry.tmp.mjs`,outDir:i,target:`node18`})}finally{t.rmSync(o,{force:!0})}t.writeFileSync(n.resolve(r,`dist/client/_redirects`),`/* /.netlify/functions/ssr 200
|
|
214
|
+
`);let s=await Y(e),c=n.resolve(r,`dist/client`);for(let{url:e,html:r}of s){let i=e===`/`?n.join(c,`index.html`):n.join(c,e,`index.html`);t.mkdirSync(n.resolve(i,`..`),{recursive:!0}),t.writeFileSync(i,r)}console.log(` Netlify output → .netlify/functions-internal/ssr/
|
|
215
215
|
Publish dir: dist/client/
|
|
216
|
-
`)}}}function
|
|
216
|
+
`)}}}function nr(){return{name:`node`,async build(e){let{fs:t,path:n,root:r}=e,i=K(e,{platformImport:`import { serve } from "@hono/node-server";
|
|
217
217
|
import { readFileSync, existsSync } from "node:fs";
|
|
218
218
|
import { resolve, dirname } from "node:path";
|
|
219
219
|
import { fileURLToPath } from "node:url";`,platformMiddleware:`
|
|
@@ -241,14 +241,14 @@ const port = +(process.env.PORT || 3000);
|
|
|
241
241
|
serve({ fetch: app.fetch, port }, (info) => {
|
|
242
242
|
console.log(\`Server running at http://localhost:\${info.port}\`);
|
|
243
243
|
});
|
|
244
|
-
`}),a=n.resolve(r,`.node-entry.tmp.mjs`);t.writeFileSync(a,i);try{await
|
|
244
|
+
`}),a=n.resolve(r,`.node-entry.tmp.mjs`);t.writeFileSync(a,i);try{await q(e,{entry:`.node-entry.tmp.mjs`,outDir:n.resolve(r,`dist/server`),target:`node18`,emptyOutDir:!1})}finally{t.rmSync(a,{force:!0})}let o=await Y(e);if(o.length>0){let e=n.resolve(r,`dist/prerender`);t.mkdirSync(e,{recursive:!0});for(let{url:r,html:i}of o){let a=r===`/`?n.join(e,`index.html`):n.join(e,r,`index.html`);t.mkdirSync(n.resolve(a,`..`),{recursive:!0}),t.writeFileSync(a,i)}}console.log(` Node output → dist/server/index.mjs
|
|
245
245
|
Run: node dist/server/index.mjs
|
|
246
|
-
`)}}}function
|
|
247
|
-
`)}}}async function
|
|
248
|
-
<style>`+n+`</style>`,body:r,data:`<script id="serialized-server-data" type="application/json">`+i+`<\/script>`};return e.replace(a,(e,t)=>o[t]??``)}function
|
|
249
|
-
`)}),o=n.resolve(r,`.vercel-entry.tmp.mjs`);t.writeFileSync(o,a);try{let i=n.resolve(r,`.vercel/output/functions/ssr.func`);await
|
|
250
|
-
`)}}}function
|
|
251
|
-
`))}if(u)return{vite:a};if(!i){let e=a;if(!e){let{createServer:t}=await
|
|
246
|
+
`)}}}function rr(e={}){return{name:`static`,async build(t){let{fs:n,path:r,root:i}=t,a=r.resolve(i,`dist/static`);n.rmSync(a,{recursive:!0,force:!0}),n.mkdirSync(a,{recursive:!0});let{pathToFileURL:o}=await U(`node:url`),s=o(r.resolve(i,`dist/server/ssr.js`)).href,c=await U(s);t.copyStaticAssets(a,{excludeHtml:!0});let{paths:l,defs:u}=await ir(t,e);console.log(` Pre-rendering ${l.length} pages...\n`);for(let e of l)try{let i=sr(e,u.find(t=>t.path===e)?.renderMode,t.renderModes),o;if(i===`csr`)o=or(t.templateHtml);else{let{html:n,head:r,css:i,serverData:a}=await c.render(e),s=c.serializeServerData(a);o=ar(t.templateHtml,r,i,n,s)}let s=e===`/`?r.join(a,`index.html`):r.join(a,e,`index.html`);n.mkdirSync(r.resolve(s,`..`),{recursive:!0}),n.writeFileSync(s,o)}catch(t){console.warn(` [static] Failed to render ${e}:`,t)}console.log(` Static output → dist/static/
|
|
247
|
+
`)}}}async function ir(e,t){let n=t.routesExport??`src/lib/bootstrap.ts`,r=[],i=[];try{let{pathToFileURL:t}=await U(`node:url`);await e.vite.build({root:e.root,build:{ssr:n,outDir:e.path.resolve(e.root,`dist/server`),emptyOutDir:!1,rollupOptions:{output:{entryFileNames:`_routes.mjs`}}},resolve:e.resolvedResolve});let a=t(e.path.resolve(e.root,`dist/server/_routes.mjs`)).href,o=await U(a),s=o.routes??o.default;if(Array.isArray(s))for(let e of s)e.path&&!e.path.includes(`:`)&&(r.push(e.path),i.push({path:e.path,renderMode:e.renderMode}));e.fs.rmSync(e.path.resolve(e.root,`dist/server/_routes.mjs`),{force:!0})}catch(e){console.warn(` [static] Could not load routes from "${n}". Using "/" only.`,e),r.length===0&&r.push(`/`)}if(t.dynamicRoutes)for(let e of t.dynamicRoutes)r.includes(e)||r.push(e);return r.length===0&&r.push(`/`),{paths:r,defs:i}}function ar(e,t,n,r,i){let a=/<!--ssr-([a-z][a-z0-9-]*)-->/g,o={head:t+`
|
|
248
|
+
<style>`+n+`</style>`,body:r,data:`<script id="serialized-server-data" type="application/json">`+i+`<\/script>`};return e.replace(a,(e,t)=>o[t]??``)}function or(e){return e.replace(/<!--ssr-([a-z][a-z0-9-]*)-->/g,()=>``)}function sr(e,t,n){if(n){if(n[e])return n[e];for(let[t,r]of Object.entries(n))if(t.includes(`*`)){let n=t.replace(/[.+?^${}()|[\]\\]/g,`\\$&`);if(RegExp(`^`+n.replace(/\*/g,`.*`)+`$`).test(e))return r}}return t??`ssr`}function cr(){return{name:`vercel`,async build(e){let{fs:t,path:n,root:r}=e,i=n.resolve(r,`.vercel/output`);t.rmSync(i,{recursive:!0,force:!0});let a=K(e,{platformImport:`import { getRequestListener } from "@hono/node-server";`,platformExport:[`const _listener = getRequestListener(app.fetch);`,`export default (req, res) => {`,` const m = req.headers["x-now-route-matches"];`,` if (typeof m === "string") {`,` try {`,` const p = new URLSearchParams(m);`,` const c = p.get("1");`,` if (c != null) {`,` const qi = (req.url || "").indexOf("?");`,` const qs = qi !== -1 ? req.url.slice(qi) : "";`,` req.url = "/" + decodeURIComponent(c) + qs;`,` }`,` } catch {}`,` }`,` return _listener(req, res);`,`};`].join(`
|
|
249
|
+
`)}),o=n.resolve(r,`.vercel-entry.tmp.mjs`);t.writeFileSync(o,a);try{let i=n.resolve(r,`.vercel/output/functions/ssr.func`);await q(e,{entry:`.vercel-entry.tmp.mjs`,outDir:i,target:`node18`}),t.writeFileSync(n.resolve(i,`.vc-config.json`),JSON.stringify({runtime:`nodejs20.x`,handler:`index.mjs`,launcherType:`Nodejs`},null,2)),J(e,n.resolve(r,`.vercel/output/static`)),t.writeFileSync(n.resolve(r,`.vercel/output/config.json`),JSON.stringify({version:3,routes:[{handle:`filesystem`},{src:`/(.*)`,dest:`/ssr`}]},null,2))}finally{t.rmSync(o,{force:!0})}let s=await Y(e),c=n.resolve(r,`.vercel/output/static`);for(let{url:e,html:r}of s){let i=e===`/`?n.join(c,`index.html`):n.join(c,e,`index.html`);t.mkdirSync(n.resolve(i,`..`),{recursive:!0}),t.writeFileSync(i,r)}if(s.length>0){let e=n.resolve(r,`.vercel/output/config.json`),i=JSON.parse(t.readFileSync(e,`utf-8`));i.overrides=i.overrides??{};for(let{url:e}of s){let t=e===`/`?`index.html`:`${e.replace(/^\//,``)}/index.html`;i.overrides[t]={path:e===`/`?`/`:e,contentType:`text/html; charset=utf-8`}}t.writeFileSync(e,JSON.stringify(i,null,2))}console.log(` Vercel output → .vercel/output/
|
|
250
|
+
`)}}}function X(e){if(typeof e!=`string`)return e;switch(e){case`vercel`:return cr();case`cloudflare`:return er();case`netlify`:return tr();case`node`:return nr();case`static`:return rr();case`auto`:return lr();default:throw Error(`[finesoft] Unknown adapter: "${e}". Available: vercel, cloudflare, netlify, node, static, auto`)}}function lr(){return{name:`auto`,async build(e){let t=ur();return console.log(` [auto] Detected platform: ${t}\n`),X(t).build(e)}}}function ur(){return process.env.VERCEL?`vercel`:process.env.CF_PAGES?`cloudflare`:process.env.NETLIFY?`netlify`:`node`}function dr(e,t=1){return((n,r)=>{if(typeof n==`string`&&n.startsWith(`/`)){let i=new Request(`http://localhost${n}`,r);return i.headers.set(`x-ssr-depth`,String(t)),Promise.resolve(e(i))}return globalThis.fetch(n,r)})}function fr(e,t){if(!t)return null;let n=e.split(`?`)[0];if(t[n])return t[n];for(let[e,r]of Object.entries(t))if(e.includes(`*`)){let t=e.replace(/[.+?^${}()|[\]\\]/g,`\\$&`);if(RegExp(`^`+t.replace(/\*/g,`.*`)+`$`).test(n))return r}return null}function Z(e){let{root:t,vite:n,isProduction:r,ssrEntryPath:i=`/src/ssr.ts`,ssrProductionModule:a,parentFetch:o,renderModes:s,defaultLocale:c}=e,l=new P,u=new k(1e3),d;async function f(e){if(!r&&n){let{readFileSync:r}=await U(`node:fs`),i=r((await U(`node:path`)).resolve(t,`index.html`),`utf-8`);return n.transformIndexHtml(e,i)}if(d)return d;if(globalThis.Deno!==void 0){let e=import.meta.url;return d=globalThis.Deno.readTextFileSync(new URL(`../dist/client/index.html`,e)),d}let{readFileSync:i}=await U(`node:fs`);return d=i((await U(`node:path`)).resolve(t,`dist/client/index.html`),`utf-8`),d}async function p(){if(!r&&n)return await n.ssrLoadModule(i);if(a)return U(a);let e=await U(`node:path`),{pathToFileURL:o}=await U(`node:url`),s=o(e.resolve(t,`dist/server/ssr.js`)).href;return U(s)}return l.get(`*`,async e=>{let t=parseInt(e.req.header(`x-ssr-depth`)??`0`,10);if(t>=5)return e.text(`SSR recursion loop detected`,508);let i=e.req.path+(e.req.url.includes(`?`)?`?`+e.req.url.split(`?`)[1]:``);try{let n=await f(i),r=await p();if(typeof r.render!=`function`||typeof r.serializeServerData!=`function`)throw Error(`[SSR] Module missing required exports: render, serializeServerData`);let{render:a,serializeServerData:l}=r,d=fr(i,s);if(d===`csr`)return e.html(z(n,c?A(c):void 0));let m=u.get(i);if(m)return e.html(m);let h=o?dr(o,t+1):void 0,g={request:e.req.raw};h&&(g.fetch=h);let{html:_,head:v,css:y,serverData:b,renderMode:x,redirect:S,slots:C,locale:w,status:T,rewriteUrl:E}=await a(i,g);if(S)return e.redirect(S.url,S.status);if(x===`csr`)return e.html(z(n,w));let D=R({template:n,head:v,css:y,html:_,serializedData:l(b),slots:C,locale:w});return(x===`prerender`||d===`prerender`)&&!T&&!E&&u.set(i,D),E&&e.header(`Content-Location`,E),T&&T>=400?e.html(D,T):e.html(D)}catch(t){return!r&&n&&n.ssrFixStacktrace(t),console.error(`[SSR Error]`,t),e.text(`Internal Server Error`,500)}}),l}function Q(){return{isDeno:globalThis.Deno!==void 0,isBun:globalThis.Bun!==void 0,isVercel:!!process.env.VERCEL,isProduction:process.env.NODE_ENV===`production`}}async function pr(e,t=0){if(globalThis.Deno!==void 0){let n=new URL(e);for(let e=0;e<t;e++)n=new URL(`..`,n);return n.pathname}let n=await U(`node:path`),{fileURLToPath:r}=await U(`node:url`),i=n.normalize(n.dirname(r(e)));for(let e=0;e<t;e++)i=n.resolve(i,`..`);return i}async function mr(e){let{app:t,root:n,port:r=3e3,isProduction:i,vite:a,routes:o,ssrEntryPath:s}=e,{isDeno:c,isBun:l,isVercel:u}=e.runtime??Q();function d(){let e=[`\n Server running at http://localhost:${r}\n`];if(o&&o.length>0){e.push(` Routes:`);for(let t of o)e.push(` ${t}`);e.push(``)}s&&e.push(` SSR Entry: ${s}`),s&&e.push(``),console.log(e.join(`
|
|
251
|
+
`))}if(u)return{vite:a};if(!i){let e=a;if(!e){let{createServer:t}=await U(`vite`);e=await t({root:n,server:{middlewareMode:!0},appType:`custom`})}let{getRequestListener:i}=await U(`@hono/node-server`),{createServer:o}=await U(`node:http`),s=i(t.fetch);return o((t,n)=>{e.middlewares(t,n,()=>s(t,n))}).listen(r,()=>{d()}),{vite:e}}if(c)globalThis.Deno.serve({port:r},t.fetch);else if(!l){let{serveStatic:e}=await U(`@hono/node-server/serve-static`),i=await U(`node:path`),a=new P,o=i.resolve(n,`dist/client`);a.use(`/*`,e({root:o,rewriteRequestPath:e=>e.endsWith(`/`)?`/__nosuchfile__`:e})),a.route(`/`,t);let{serve:s}=await U(`@hono/node-server`);s({fetch:a.fetch,port:r},()=>{d()})}return{vite:a}}async function hr(e={}){let{root:t,port:n=Number(process.env.PORT)||3e3,setup:r,proxies:i,ssr:a}=e,o=t??process.cwd(),{existsSync:s}=await U(`node:fs`),c=(await U(`node:path`)).resolve(o,`.env`);if(s(c))try{let{config:e}=await U(`dotenv`);e({path:c})}catch(e){console.warn(`[Server] Failed to load .env: ${e.message}`)}let l=Q(),u;if(!l.isProduction&&!l.isVercel){let{createServer:e}=await U(`vite`);u=await e({root:o,server:{middlewareMode:!0},appType:`custom`})}let d=new P;i?.length&&G(d,i),r&&await r(d);let f=Z({root:o,vite:u,isProduction:l.isProduction,parentFetch:d.fetch.bind(d),...a});return d.route(`/`,f),await mr({app:d,root:o,port:n,isProduction:l.isProduction,vite:u,runtime:l,ssrEntryPath:a?.ssrEntryPath}),{app:d,vite:u,runtime:l}}function gr(e,t,n){let r=t??[`zh`,`en`],i=n??r[0]??`en`;if(!e||e.length>1024)return i;let a=e.split(`,`);if(a.length>50)return i;let o=a.map(e=>{let[t,n]=e.trim().split(`;q=`),r=n?parseFloat(n):1;return{lang:t.trim().toLowerCase(),q:Number.isFinite(r)&&r>=0&&r<=1?r:0}}).filter(e=>e.q>0).sort((e,t)=>t.q-e.q);for(let{lang:e}of o){let t=e.split(`-`)[0];if(r.includes(t))return t}return i}const $=`virtual:finesoft-front/i18n-loader`,_r=`\0${$}`;function vr(e){return typeof e.default==`function`?e.default:typeof e.setup==`function`?e.setup:Object.values(e).find(e=>typeof e==`function`)??null}function yr(e,t){if(!t)return null;let n=e.split(`?`)[0];if(t[n])return t[n];for(let[e,r]of Object.entries(t))if(e.includes(`*`)){let t=e.replace(/[.+?^${}()|[\]\\]/g,`\\$&`);if(RegExp(`^`+t.replace(/\*/g,`.*`)+`$`).test(n))return r}return null}function br(e){return e.replace(/\\/g,`/`)}let xr=!1;function Sr(){xr||(xr=!0,console.log(`\n${(e=>`\x1b[33m${e}\x1b[0m`)(`[finesoft]`)} dev server is exposing source via /src/* and /@fs/* (HMR).\n`+(e=>`\x1b[2m${e}\x1b[0m`)(" Do NOT expose this server to untrusted networks; run `vp build && vp preview` for production.\n")))}async function Cr(e,t){let{existsSync:n}=await U(`node:fs`),r=await U(`node:path`),i=r.isAbsolute(t)?t:r.resolve(e,t);if(!n(i))throw Error(`[finesoftFrontViteConfig] i18n.messagesDir not found: ${t}`);let a=br(r.relative(e,i));if(!a||a.startsWith(`..`))throw Error(`[finesoftFrontViteConfig] i18n.messagesDir must stay inside the project root: ${t}`);return a.replace(/^\.\/+/,``)}function wr(e={}){let t=e.ssr?.entry??`src/ssr.ts`,n=process.cwd(),r,i,a,o=/\.(css|scss|less|sass|styl|stylus|pcss|postcss)($|\?)/;return{name:`finesoft-front`,config(t){let n={appType:`custom`,define:{__FINESOFT_I18N_LOADER_SPECIFIER__:e.i18n?.messagesDir?JSON.stringify($):`undefined`}};return process.env.__FINESOFT_SUB_BUILD__||(n.build={outDir:t.build?.outDir??`dist/client`}),n},configResolved(e){r=e.command,i=e.resolve,a=e.css,n=e.root},resolveId(t){return t===$&&e.i18n?.messagesDir?_r:null},async load(t){if(t!==_r||!e.i18n?.messagesDir)return null;let r=`/${await Cr(n,e.i18n.messagesDir)}`,i=`${r}/*.json`,a=`${r}/`;return`
|
|
252
252
|
const localeModules = import.meta.glob(${JSON.stringify(i)}, { import: "default" });
|
|
253
253
|
|
|
254
254
|
export async function loadMessages(locale) {
|
|
@@ -257,8 +257,8 @@ export async function loadMessages(locale) {
|
|
|
257
257
|
const messages = await loader();
|
|
258
258
|
return messages ?? undefined;
|
|
259
259
|
}
|
|
260
|
-
`},transformIndexHtml:{order:`pre`,async handler(e,t){let n=t.server;if(!n)return;let r=(t.originalUrl||t.path||``).split(`?`)[0];if(/\.\w+$/.test(r)&&!r.endsWith(`.html`))return;let i=[...e.matchAll(/<script\b[^>]*\bsrc=["']([^"']+)["'][^>]*>/g)].find(e=>!e[1].startsWith(`/@`));if(!i)return;let a=i[1];try{await n.transformRequest(a)}catch{return}let s=[],c=new Set;function l(e,t=0){if(!(t>100)&&!(!e?.url||c.has(e.url))&&(c.add(e.url),o.test(e.url)&&!e.url.includes(`.svelte`)&&s.push(e.url),e.importedModules))for(let n of e.importedModules)l(n,t+1)}let u=await n.moduleGraph.getModuleByUrl(a);if(u&&l(u),s.length===0)return;let d=[];for(let e of s)try{let t=(await n.ssrLoadModule(e))?.default;typeof t==`string`&&t.length>0&&d.push({tag:`style`,attrs:{"data-vite-dev-id":e},children:t,injectTo:`head`})}catch{}return d}},configureServer(r){return async()=>{let{Hono:i}=await
|
|
260
|
+
`},transformIndexHtml:{order:`pre`,async handler(e,t){let n=t.server;if(!n)return;let r=(t.originalUrl||t.path||``).split(`?`)[0];if(/\.\w+$/.test(r)&&!r.endsWith(`.html`))return;let i=[...e.matchAll(/<script\b[^>]*\bsrc=["']([^"']+)["'][^>]*>/g)].find(e=>!e[1].startsWith(`/@`));if(!i)return;let a=i[1];try{await n.transformRequest(a)}catch{return}let s=[],c=new Set;function l(e,t=0){if(!(t>100)&&!(!e?.url||c.has(e.url))&&(c.add(e.url),o.test(e.url)&&!e.url.includes(`.svelte`)&&s.push(e.url),e.importedModules))for(let n of e.importedModules)l(n,t+1)}let u=await n.moduleGraph.getModuleByUrl(a);if(u&&l(u),s.length===0)return;let d=[];for(let e of s)try{let t=(await n.ssrLoadModule(e))?.default;typeof t==`string`&&t.length>0&&d.push({tag:`style`,attrs:{"data-vite-dev-id":e},children:t,injectTo:`head`})}catch{}return d}},configureServer(r){return async()=>{let{Hono:i}=await U(`hono`),{getRequestListener:a}=await U(`@hono/node-server`);Sr();let o=new i;if(e.proxies?.length&&G(o,e.proxies),typeof e.setup==`function`)await e.setup(o);else if(typeof e.setup==`string`){let t=vr(await r.ssrLoadModule(`/`+e.setup));t&&await t(o)}let s=Z({root:n,vite:r,isProduction:!1,ssrEntryPath:`/`+t,parentFetch:o.fetch.bind(o),renderModes:e.renderModes,defaultLocale:e.defaultLocale});o.route(`/`,s);let c=a(o.fetch);r.middlewares.use((e,t)=>{c(e,t)})}},configurePreviewServer(t){return async()=>{let{readFileSync:r}=await U(`node:fs`),i=await U(`node:path`),{pathToFileURL:a}=await U(`node:url`),{Hono:o}=await U(`hono`),{getRequestListener:s}=await U(`@hono/node-server`),c=new o,l=new k(1e3);if(e.proxies?.length&&G(c,e.proxies),typeof e.setup==`function`)await e.setup(c);else if(typeof e.setup==`string`)try{let e=a(i.resolve(n,`dist/server/setup.mjs`)).href,t=vr(await U(e));t&&await t(c)}catch{console.warn(`[finesoft] Could not load setup module for preview. API routes disabled.`)}let u=r(i.resolve(n,`dist/client/index.html`),`utf-8`),d=a(i.resolve(n,`dist/server/ssr.js`)).href,f=await U(d);c.get(`*`,async t=>{let n=parseInt(t.req.header(`x-ssr-depth`)??`0`,10);if(n>=5)return t.text(`SSR recursion loop detected`,508);let r=t.req.path+(t.req.url.includes(`?`)?`?`+t.req.url.split(`?`)[1]:``);try{let i=yr(r,e.renderModes);if(i===`csr`)return t.html(z(u,e.defaultLocale?A(e.defaultLocale):void 0));let a=l.get(r);if(a)return t.html(a);let{html:o,head:s,css:d,serverData:p,renderMode:m,redirect:h,slots:g,locale:_,status:v,rewriteUrl:y}=await f.render(r,{fetch:dr(c.fetch.bind(c),n+1)});if(h)return t.redirect(h.url,h.status);if(m===`csr`)return t.html(z(u,_));let b=R({template:u,head:s,css:d,html:o,serializedData:f.serializeServerData(p),slots:g,locale:_});return(m===`prerender`||i===`prerender`)&&!v&&!y&&l.set(r,b),y&&t.header(`Content-Location`,y),v&&v>=400?t.html(b,v):t.html(b)}catch(e){return console.error(`[SSR Preview Error]`,e),t.text(`Internal Server Error`,500)}});let p=s(c.fetch);t.middlewares.use((e,t)=>{p(e,t)})}},async closeBundle(){if(!process.env.__FINESOFT_SUB_BUILD__&&r===`build`){process.env.__FINESOFT_SUB_BUILD__=`1`;try{let r=await U(`vite`),o=await U(`node:fs`),s=await U(`node:path`);if(console.log(`
|
|
261
261
|
Building SSR bundle...
|
|
262
|
-
`),await r.build({root:n,build:{ssr:t,outDir:`dist/server`},ssr:{external
|
|
263
|
-
`),await r.build({root:n,build:{ssr:e.setup,outDir:`dist/server`,emptyOutDir:!1,rollupOptions:{output:{entryFileNames:`setup.mjs`}}},resolve:i})),e.adapter){let c=
|
|
262
|
+
`),await r.build({root:n,build:{ssr:t,outDir:`dist/server`},ssr:{external:$n},resolve:i,css:a}),typeof e.setup==`string`&&(console.log(` Building setup module...
|
|
263
|
+
`),await r.build({root:n,build:{ssr:e.setup,outDir:`dist/server`,emptyOutDir:!1,rollupOptions:{output:{entryFileNames:`setup.mjs`}}},resolve:i})),e.adapter){let c=X(e.adapter),l=o.readFileSync(s.resolve(n,`dist/client/index.html`),`utf-8`),u={root:n,ssrEntry:t,setupPath:typeof e.setup==`string`?e.setup:void 0,bootstrapEntry:e.bootstrapEntry,templateHtml:l,renderModes:e.renderModes,proxies:e.proxies,locales:e.locales,defaultLocale:e.defaultLocale,resolvedResolve:i,resolvedCss:a,vite:r,fs:o,path:s,generateSSREntry(e){return K(u,e)},buildBundle(e){return q(u,e)},copyStaticAssets(e,t){return J(u,e,t)}};console.log(` Running adapter: ${c.name}...\n`),await c.build(u)}}finally{delete process.env.__FINESOFT_SUB_BUILD__}}}}}export{je as ACTION_KINDS,w as ActionDispatcher,j as BASE_PAGE_FIELDS,mn as BaseController,un as BaseLogger,on as CompositeEventRecorder,Ze as CompositeLogger,sn as CompositeLoggerFactory,st as ConsoleEventRecorder,pt as ConsoleLogger,ut as ConsoleLoggerFactory,o as Container,Yt as DEFAULT_NAV_PARAM,wt as DEP_KEYS,T as FINESOFT_PUBLIC,O as Framework,ft as History,v as HostGuardError,D as HttpClient,oe as HttpError,Pe as IntentDispatcher,Xe as IntersectionImpressionObserver,k as LruMap,pe as NAVIGATION_NODE_KINDS,e as NAVIGATION_OP_KINDS,V as NAVIGATION_TREE_INTENT_ID,ve as NavigationError,Bt as PrefetchedIntents,It as ReportingLogger,Dt as ReportingLoggerFactory,Je as Router,ht as SESSION_DEFAULT_DEBOUNCE_MS,ie as SESSION_DEFAULT_KEY,Rt as SESSION_DEFAULT_VERSION,y as SPLIT_VISIBILITIES,vn as SSR_PLACEHOLDERS,te as SessionError,Te as SimpleTranslator,ln as VoidEventRecorder,$t as WithFieldsRecorder,lr as autoAdapter,t as bool,xt as buildUrl,Se as classifyHost,pn as classifyUrl,er as cloudflareAdapter,Qt as collectAllLeaves,Ne as collectLeafKeys,rt as collectVisibleDestinations,jt as createActiveLeafCodec,ot as createAppHandle,m as createBrowserContext,tt as createDomRestore,Ut as createFlatStackCodec,_t as createFullStateCodec,Xt as createIslandOrchestrator,Ct as createNavigationBridge,at as createNavigationController,C as createNavigationScopedState,xe as createNavigationSessionAdapter,Wt as createPrefetchedIntentsFromDom,Z as createSSRApp,Nn as createSSRNavigationRender,_n as createSSRRender,hr as createServer,d as createServerContext,qe as createSessionBridge,a as createSessionStore,fn as createUrlSessionAdapter,Vt as createWebStorage,Ye as decodeNavigationTreeParam,Fe as decodeSnapshot,Mt as defaultShouldRestore,ye as defineNavigation,et as defineRequestScopedKey,Re as defineRoutes,we as deny,Kt as deserializeNavigation,$e as deserializeServerData,nt as detectPlatform,Q as detectRuntime,Pt as encodeNavigationTreeParam,b as encodeSnapshot,l as englishPlural,On as extractNavigationTree,ct as findNearestStack,Lt as findNode,wr as finesoftFrontViteConfig,Zn as generateProxyCode,me as generateUuid,n as getBaseUrl,A as getLocaleAttributes,ge as getPWADisplayMode,Me as getPublicFields,St as getTextDirection,z as injectCSRShell,R as injectSSRContent,it as int,rn as interpolate,Ie as isCompoundAction,x as isExternalUrlAction,ae as isFlowAction,ke as isLeafNode,_ as isNone,Le as isPublicMarked,r as isRtl,E as isSome,g as isSplitNode,p as isStackNode,he as isTabsNode,Be as isUrlLocation,an as islandContainerAttributes,N as leaf,Zt as makeDependencies,zt as makeExternalUrlAction,ne as makeFlowAction,yt as makeLocaleInfo,Nt as makeSchema,ee as mapEach,S as markPublic,tr as netlifyAdapter,c as next,nr as nodeAdapter,Jt as num,At as oneOf,Ue as optional,gr as parseAcceptLanguage,se as pipe,Ce as pipeAsync,Ot as pop,mt as popTo,dt as popToRoot,Ke as push,nn as redirect,Ft as registerActionHandlers,We as registerExternalUrlHandler,Et as registerFlowActionHandler,G as registerProxyRoutes,vt as removeHost,ce as removeQueryParams,de as removeScheme,Wn as renderIslandsHtml,tn as replaceTop,Ge as resetFilterCache,dn as resolveActivePath,X as resolveAdapter,h as resolveConfiguredMessages,qt as resolveIslandsShell,le as resolveLocaleFromUrl,f as resolveMessages,Oe as resolvePluralKey,pr as resolveRoot,De as rewrite,He as route,Ve as runAfterLoadGuards,ze as runBeforeLoadGuards,Gt as runStandard,s as safeErrorPage,_e as secureFetch,Qe as selectColumn,cn as selectTab,M as serializeNavigation,Tt as serializeNavigationStable,Ln as serializeServerData,Ae as sessionEntryKey,fe as setHtmlLocaleAttributes,Ee as setVisibility,en as shouldLog,i as split,hn as ssrRender,H as ssrRenderNavigation,re as stableStringify,bt as stack,kt as startBrowserApp,mr as startServer,rr as staticAdapter,Ht as str,kn as stripNavigationTree,ue as tabs,lt as tryScroll,gt as uuid,cr as vercelAdapter,u as visibleSplitColumns,be as withDefault};
|
|
264
264
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 4. Rendering & hydration
|
|
2
2
|
|
|
3
|
-
How a page travels from controller output to bytes on the wire, then back into a live browser app. This chapter covers SSR, CSR, prerender, and the `PrefetchedIntents` machinery that ties them together.
|
|
3
|
+
How a page travels from controller output to bytes on the wire, then back into a live browser app. This chapter covers SSR, CSR, prerender, the second axis they compose with — **app architecture** (flat single page vs structured navigation + islands) — and the `PrefetchedIntents` machinery that ties them together.
|
|
4
4
|
|
|
5
5
|
## The three modes side by side
|
|
6
6
|
|
|
@@ -15,6 +15,25 @@ How a page travels from controller output to bytes on the wire, then back into a
|
|
|
15
15
|
|
|
16
16
|
Mode is **per-route**. Mix freely.
|
|
17
17
|
|
|
18
|
+
## Two axes: render mode × app architecture
|
|
19
|
+
|
|
20
|
+
Render mode is one axis. The **app architecture** is a second, orthogonal axis:
|
|
21
|
+
|
|
22
|
+
- **Flat single page** — `createSSRRender` on the server, a single client mount that re-renders on each navigation. One root, one visible page. (See [SSR pipeline](#ssr-pipeline) below.)
|
|
23
|
+
- **Structured navigation + islands** — `createSSRNavigationRender` on the server, per-destination _islands_ on the client: independent roots that stay alive across tab/stack switches. (See [Navigation](./11-navigation.md) and [Islands SSR](#islands-ssr-structured-architecture-approach-c) below.)
|
|
24
|
+
|
|
25
|
+
The two axes compose into a matrix — render mode decides _when/where_ HTML is produced; architecture decides _how_ the app is structured:
|
|
26
|
+
|
|
27
|
+
| | Flat single page | Structured nav + islands (approach C) |
|
|
28
|
+
| ------------- | ------------------------- | ------------------------------------- |
|
|
29
|
+
| **ssr** | ✅ `svelte-minimal` | ✅ `vue-minimal`, `react-minimal` |
|
|
30
|
+
| **csr** | ◐ shell → one client root | ◐ shell → islands mount client-side |
|
|
31
|
+
| **prerender** | ◐ cached flat SSR | ◐ cached approach-C SSR |
|
|
32
|
+
|
|
33
|
+
✅ demonstrated by a starter template · ◐ composes by design, no starter template yet.
|
|
34
|
+
|
|
35
|
+
**Islands are SSR'd or CSR'd as a consequence of the mode, not as a separate choice:** under `ssr`/`prerender` the framework server-renders each visible island and the client _adopts and hydrates_ it; under `csr` there is no server HTML, so every island mounts fresh on the client. The per-mode sub-dimensions still apply on top — CSR has two triggers ([below](#csr-client-side-render)), prerender has build-time-static and runtime-ISR forms ([below](#prerender-static--isr)). Session restoration + DOM restore are a further orthogonal layer (client-side, post-hydration) that stacks onto any cell — see [Session restoration](./12-session-restoration.md).
|
|
36
|
+
|
|
18
37
|
## SSR pipeline
|
|
19
38
|
|
|
20
39
|
```
|
|
@@ -83,6 +102,57 @@ The Vite plugin and adapters call `render(url, options)` for you. You return `{
|
|
|
83
102
|
- Sets HTTP status from `deny()` / `redirect()` / `rewrite()` results
|
|
84
103
|
- Adds `Content-Location` header when `afterLoad` signaled a rewrite
|
|
85
104
|
|
|
105
|
+
## Islands SSR (structured architecture, "approach C")
|
|
106
|
+
|
|
107
|
+
The structured architecture renders the **chrome** (tab bar, headers — the persistent frame) and the **island content** (the active page) as **independent hydration roots**, placed as siblings under the mount node:
|
|
108
|
+
|
|
109
|
+
```html
|
|
110
|
+
<div id="app">
|
|
111
|
+
<div data-fs-chrome><!-- chrome SSR'd here --></div>
|
|
112
|
+
<main data-fs-outlet><!-- each visible island SSR'd here --></main>
|
|
113
|
+
</div>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Server** — `renderApp` renders the chrome; `renderIslandsHtml(snapshot, renderEntry)` renders each visible destination into the outlet with shared markers (`data-fs-entry` / `data-fs-intent` / `data-fs-key`) so the client can match them:
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
// src/ssr.ts — structured entry (createSSRNavigationRender)
|
|
120
|
+
async renderApp(page, _framework, snapshot) {
|
|
121
|
+
const chromeHtml = await renderToString(createSSRApp(App, { snapshot }));
|
|
122
|
+
const islandsHtml = await renderIslandsHtml(snapshot, (entry) =>
|
|
123
|
+
renderToString(createSSRApp(VIEWS[entry.intent], { page: entry.page })),
|
|
124
|
+
);
|
|
125
|
+
return {
|
|
126
|
+
html: `<div data-fs-chrome>${chromeHtml}</div><main data-fs-outlet>${islandsHtml}</main>`,
|
|
127
|
+
head: `<title>${page.title}</title>`,
|
|
128
|
+
css: "",
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**Client** — `resolveIslandsShell(target)` locates (or creates) the chrome/outlet siblings and reports whether the chrome was server-rendered (`hydrate`). The island orchestrator adopts each SSR'd container by `data-fs-key` and calls your `mountEntry(entry, container)` with `entry.hydrate = true`, so you hydrate the existing DOM rather than create new:
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
// src/main.ts
|
|
137
|
+
const mountEntry = (entry, container) => {
|
|
138
|
+
const factory = entry.hydrate ? createSSRApp : createApp; // hydrate SSR'd vs mount fresh (client nav)
|
|
139
|
+
const app = factory(VIEWS[entry.intent], { page: entry.page, controller: ctx.app });
|
|
140
|
+
app.mount(container);
|
|
141
|
+
return { unmount: () => app.unmount() };
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
startBrowserApp({
|
|
145
|
+
bootstrap,
|
|
146
|
+
mount,
|
|
147
|
+
callbacks,
|
|
148
|
+
navigation: { ...navigation.toBrowserConfig(), mountEntry },
|
|
149
|
+
});
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
> **Synchronous-mount contract.** After `mountEntry` returns, the island's DOM must already exist: the framework restores `data-restore-root` fields on the next animation frame (see [Session restoration](./12-session-restoration.md)). Vue/Svelte `.mount()` satisfies this synchronously. **React** commits asynchronously, so wrap the **client-mount** path in `flushSync(() => root.render(view))` — only client-mounted islands need it (SSR'd islands already have their DOM from the server). See `templates/react-minimal/src/main.tsx`.
|
|
153
|
+
|
|
154
|
+
Complete examples: `templates/vue-minimal` and `templates/react-minimal` (both `ssr` + structured navigation + islands + session restoration).
|
|
155
|
+
|
|
86
156
|
## CSR (client-side render)
|
|
87
157
|
|
|
88
158
|
For routes marked `renderMode: "csr"`, the server returns a minimal shell:
|