@finesoft/front 0.5.1 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/README.md +4 -4
  2. package/dist/Outlet.svelte +39 -0
  3. package/dist/Outlet.svelte.d.ts +7 -0
  4. package/dist/browser-DIU6Sxl3.mjs +1237 -0
  5. package/dist/browser-kFMjlLGT.d.mts +262 -0
  6. package/dist/browser.d.mts +7 -2
  7. package/dist/browser.mjs +9 -1
  8. package/dist/controller-types-CgmJ6-le.d.mts +16 -0
  9. package/dist/cookies-Bpf9VayB.d.mts +779 -0
  10. package/dist/fetch-policy-BHT8RtrL.mjs +82 -0
  11. package/dist/host-guard-DDWxLpFL.mjs +222 -0
  12. package/dist/http-B6CJqDyf.d.mts +46 -0
  13. package/dist/http-CaxrMD1A.d.mts +1 -0
  14. package/dist/http-D70PL72H.mjs +257 -0
  15. package/dist/http.d.mts +3 -0
  16. package/dist/http.mjs +2 -0
  17. package/dist/index-node.d.mts +15 -0
  18. package/dist/index-node.mjs +15 -0
  19. package/dist/index.d.mts +48 -697
  20. package/dist/index.mjs +44 -261
  21. package/dist/load-node.d.mts +5 -0
  22. package/dist/load-node.mjs +10 -0
  23. package/dist/load-portable.d.mts +5 -0
  24. package/dist/load-portable.mjs +8 -0
  25. package/dist/lru-map-BKoUAySU.mjs +50 -0
  26. package/dist/messages-CAt2QdGr.mjs +140 -0
  27. package/dist/native-contract-DuR25hYB.d.mts +14 -0
  28. package/dist/native-contract.d.mts +2 -0
  29. package/dist/native-contract.mjs +1 -0
  30. package/dist/node-D9hB4dsz.d.mts +35 -0
  31. package/dist/node.d.mts +2 -0
  32. package/dist/node.mjs +59 -0
  33. package/dist/path-CGFl2w7D.mjs +113 -0
  34. package/dist/path-CXT6xGPO.d.mts +261 -0
  35. package/dist/portable-CaxrMD1A.d.mts +1 -0
  36. package/dist/portable.d.mts +11 -0
  37. package/dist/portable.mjs +12 -0
  38. package/dist/proxy-1SphZ7x7.mjs +436 -0
  39. package/dist/proxy-2dSWO-Xw.d.mts +53 -0
  40. package/dist/public-types-BcJM-AYc.mjs +835 -0
  41. package/dist/react-DhwBRw01.d.mts +16 -0
  42. package/dist/react.d.mts +3 -0
  43. package/dist/react.mjs +29 -0
  44. package/dist/rolldown-runtime-B4iAMlE-.mjs +35 -0
  45. package/dist/secure-fetch-Xlht2jd7.d.mts +30 -0
  46. package/dist/server-controller-proxy-BkVuVWVD.d.mts +38 -0
  47. package/dist/session-DnB4ZC3x.d.mts +1279 -0
  48. package/dist/src-Ftl_0rhu.mjs +28 -0
  49. package/dist/src-qwx7Vw8g.mjs +3807 -0
  50. package/dist/ssr-BEUNDvbj.d.mts +210 -0
  51. package/dist/ssr-C8xnYXoY.mjs +357 -0
  52. package/dist/ssr.d.mts +3 -0
  53. package/dist/ssr.mjs +3 -0
  54. package/dist/svelte-Dr5to3SE.d.mts +16 -0
  55. package/dist/svelte.d.mts +3 -0
  56. package/dist/svelte.mjs +13 -0
  57. package/dist/typegen-C-WeJCtf.d.mts +12 -0
  58. package/dist/typegen-cli.d.mts +1 -0
  59. package/dist/typegen-cli.mjs +11 -0
  60. package/dist/typegen.d.mts +3 -0
  61. package/dist/typegen.mjs +2 -0
  62. package/dist/types-BuaZHRG7.mjs +402 -0
  63. package/dist/undici-CPfL25Hr.mjs +22262 -0
  64. package/dist/vite-Cj4SPA8D.d.mts +277 -0
  65. package/dist/vite.d.mts +4 -0
  66. package/dist/vite.mjs +2354 -0
  67. package/dist/vue-DGmzuKho.d.mts +32 -0
  68. package/dist/vue.d.mts +3 -0
  69. package/dist/vue.mjs +56 -0
  70. package/dist/web.d.mts +6 -0
  71. package/dist/web.mjs +8 -0
  72. package/dist/worker.d.mts +2 -0
  73. package/dist/worker.mjs +2 -0
  74. package/docs/01-getting-started.md +67 -199
  75. package/docs/02-routing-and-controllers.md +163 -241
  76. package/docs/03-middleware.md +10 -212
  77. package/docs/04-rendering-and-hydration.md +6 -333
  78. package/docs/05-i18n.md +7 -237
  79. package/docs/06-http-client.md +20 -263
  80. package/docs/07-di-container.md +23 -257
  81. package/docs/08-observability.md +6 -286
  82. package/docs/09-server-and-deployment.md +59 -219
  83. package/docs/10-features-platform-pwa.md +7 -231
  84. package/docs/11-navigation.md +143 -288
  85. package/docs/12-session-restoration.md +6 -214
  86. package/docs/README.md +7 -7
  87. package/docs/advanced/custom-action-handler.md +29 -229
  88. package/docs/advanced/custom-adapter.md +7 -259
  89. package/docs/advanced/custom-event-recorder.md +7 -312
  90. package/docs/advanced/inline-proxy-codegen.md +6 -185
  91. package/docs/advanced/multi-tenant-scopes.md +10 -323
  92. package/docs/engineering/ci-release-flow.md +35 -222
  93. package/docs/engineering/project-structure.md +34 -277
  94. package/docs/engineering/testing.md +8 -310
  95. package/docs/pitfalls/container-scope-leak.md +2 -214
  96. package/docs/pitfalls/i18n-bundle-size.md +6 -176
  97. package/docs/pitfalls/proxy-binary-payloads.md +8 -12
  98. package/docs/pitfalls/ssr-hydration-mismatch.md +4 -160
  99. package/docs/pitfalls/ssr-vs-csr-globals.md +9 -170
  100. package/docs/zh/01-getting-started.md +67 -199
  101. package/docs/zh/02-routing-and-controllers.md +166 -244
  102. package/docs/zh/03-middleware.md +10 -212
  103. package/docs/zh/04-rendering-and-hydration.md +6 -333
  104. package/docs/zh/05-i18n.md +7 -237
  105. package/docs/zh/06-http-client.md +20 -263
  106. package/docs/zh/07-di-container.md +23 -257
  107. package/docs/zh/08-observability.md +6 -283
  108. package/docs/zh/09-server-and-deployment.md +59 -219
  109. package/docs/zh/10-features-platform-pwa.md +7 -231
  110. package/docs/zh/11-navigation.md +130 -290
  111. package/docs/zh/12-session-restoration.md +6 -214
  112. package/docs/zh/README.md +4 -4
  113. package/docs/zh/advanced/custom-action-handler.md +29 -229
  114. package/docs/zh/advanced/custom-adapter.md +7 -259
  115. package/docs/zh/advanced/custom-event-recorder.md +7 -312
  116. package/docs/zh/advanced/inline-proxy-codegen.md +6 -185
  117. package/docs/zh/advanced/multi-tenant-scopes.md +10 -323
  118. package/docs/zh/engineering/ci-release-flow.md +35 -222
  119. package/docs/zh/engineering/project-structure.md +34 -277
  120. package/docs/zh/engineering/testing.md +8 -310
  121. package/docs/zh/pitfalls/container-scope-leak.md +2 -214
  122. package/docs/zh/pitfalls/i18n-bundle-size.md +6 -176
  123. package/docs/zh/pitfalls/proxy-binary-payloads.md +8 -12
  124. package/docs/zh/pitfalls/ssr-hydration-mismatch.md +4 -160
  125. package/docs/zh/pitfalls/ssr-vs-csr-globals.md +9 -170
  126. package/package.json +118 -20
  127. package/dist/browser-BHhVWXik.mjs +0 -2
  128. package/dist/browser-BV2BBXm7.d.mts +0 -2811
@@ -0,0 +1,210 @@
1
+ import { E as ParamSchema, c as ExecutionContext, j as Container } from "./path-CXT6xGPO.mjs";
2
+ import { B as ControllerContext, En as LocaleAttributes, H as SERVER_CONTROLLER, Jn as QuerySchemaMap, Mn as BaseController, P as WebConfiguration, Pn as ControllerInput, W as ServerRequestState, en as NavigationContext, g as WebAppView, mt as RouteDefinition, vn as RouteIntent, z as WebAppDefinition } from "./session-DnB4ZC3x.mjs";
3
+ import { t as SecureFetchOptions } from "./secure-fetch-Xlht2jd7.mjs";
4
+ import { a as WebHydration, r as ServerControllerRequest } from "./server-controller-proxy-BkVuVWVD.mjs";
5
+ import { r as HttpHandler } from "./http-B6CJqDyf.mjs";
6
+ //#region ../ssr/src/render.d.ts
7
+ interface SSRContext {
8
+ identity?: string;
9
+ traceId?: string;
10
+ safeFetch?: SecureFetchOptions;
11
+ fetch?: typeof globalThis.fetch;
12
+ request?: Request;
13
+ bindings?: Readonly<Record<string, unknown>>;
14
+ /** Request metadata and explicit response mutations scoped to this render. */
15
+ requestState?: ServerRequestState;
16
+ }
17
+ interface SSRAppResult {
18
+ html: string;
19
+ head?: string;
20
+ css?: string;
21
+ slots?: Record<string, string>;
22
+ }
23
+ interface SSRRenderResult {
24
+ headers?: HeadersInit;
25
+ cache?: "public";
26
+ html: string;
27
+ head: string;
28
+ css: string;
29
+ serverData: WebHydration;
30
+ renderMode?: string;
31
+ redirect?: {
32
+ url: string;
33
+ status: number;
34
+ };
35
+ slots?: Record<string, string>;
36
+ locale?: {
37
+ lang: string;
38
+ dir: string;
39
+ };
40
+ status?: number;
41
+ rewriteUrl?: string;
42
+ }
43
+ //#endregion
44
+ //#region ../ssr/src/create-render.d.ts
45
+ interface SSRRenderConfig<Definition extends WebAppDefinition = WebAppDefinition> {
46
+ readonly definition: Definition;
47
+ readonly configuration?: WebConfiguration;
48
+ readonly render: (app: WebAppView<Definition>) => string | SSRAppResult | Promise<string | SSRAppResult>;
49
+ readonly resolveLocale?: (url: string, request?: Request) => LocaleAttributes | undefined;
50
+ }
51
+ /** One request scope and one native root serve ordinary and composed navigation. */
52
+ declare function createSSRRender<Definition extends WebAppDefinition>(config: SSRRenderConfig<Definition>): ((url: string, context?: SSRContext, remote?: ServerControllerRequest) => Promise<SSRRenderResult>) & {
53
+ controller: (input: ServerControllerRequest, context: SSRContext) => Promise<SSRRenderResult>;
54
+ routes: readonly RouteDefinition<string, Record<string, ParamSchema>, QuerySchemaMap>[];
55
+ dispose: () => Promise<void>;
56
+ };
57
+ //#endregion
58
+ //#region ../ssr/src/inject.d.ts
59
+ /**
60
+ * injectSSRContent — 将 SSR 渲染结果注入 HTML 模板
61
+ */
62
+ /** SSR HTML 模板占位符常量 */
63
+ declare const SSR_PLACEHOLDERS: {
64
+ readonly HEAD: "<!--ssr-head-->";
65
+ readonly BODY: "<!--ssr-body-->";
66
+ readonly DATA: "<!--ssr-data-->";
67
+ };
68
+ interface InjectSSROptions {
69
+ template: string;
70
+ head: string;
71
+ css: string;
72
+ html: string;
73
+ serializedData: string;
74
+ /** 自定义 slot 替换:`{ "my-slot": "<div>content</div>" }` 会替换 `<!--ssr-my-slot-->`(含 `<!--ssr-lang-->`) */
75
+ slots?: Record<string, string>;
76
+ /** Locale 属性,自动注入到 <html> 标签 */
77
+ locale?: {
78
+ lang: string;
79
+ dir: string;
80
+ };
81
+ }
82
+ declare function injectSSRContent(options: InjectSSROptions): string;
83
+ /**
84
+ * CSR 空壳注入 — 清空所有占位符
85
+ * 用于 renderMode === "csr" 的路由
86
+ *
87
+ * @param locale - 可选的 locale 属性,注入到 `<html lang="" dir="">`
88
+ */
89
+ declare function injectCSRShell(template: string, locale?: {
90
+ lang: string;
91
+ dir: string;
92
+ }): string;
93
+ //#endregion
94
+ //#region ../ssr/src/server-data.d.ts
95
+ interface SerializeServerDataOptions {
96
+ readonly buildId?: string;
97
+ readonly onUnmarkedPage?: "base-fields" | "strict";
98
+ }
99
+ /** Copy declared public data now; never keep request-backed objects/getters in a response. */
100
+ declare function materializeServerData(data: WebHydration, options?: SerializeServerDataOptions): WebHydration;
101
+ /** The shared response assembler remains the single HTML-safe wire serializer owner. */
102
+ declare function serializeServerData(data: WebHydration, options?: SerializeServerDataOptions): string;
103
+ //#endregion
104
+ //#region ../ssr/src/middleware/context.d.ts
105
+ interface ServerContextOptions {
106
+ url: string;
107
+ intent: RouteIntent;
108
+ container: Container;
109
+ /** 原始 Request 对象(提取 cookie 和 header) */
110
+ request?: Request;
111
+ }
112
+ /** 从 Request 对象构建服务端上下文 */
113
+ declare function createServerContext(options: ServerContextOptions): NavigationContext;
114
+ //#endregion
115
+ //#region ../ssr/src/server-controller.d.ts
116
+ interface CookieOptions {
117
+ readonly path?: string;
118
+ readonly domain?: string;
119
+ readonly maxAge?: number;
120
+ readonly expires?: Date;
121
+ readonly httpOnly?: boolean;
122
+ readonly secure?: boolean;
123
+ readonly sameSite?: "Strict" | "Lax" | "None";
124
+ }
125
+ interface ServerControllerContext extends ControllerContext {
126
+ readonly isServer: true;
127
+ readonly request: Request;
128
+ readonly responseHeaders: Headers;
129
+ /** Write response cookies; request cookies remain the values supplied by the caller. */
130
+ setCookie(name: string, value: string, options?: CookieOptions): void;
131
+ deleteCookie(name: string, options?: CookieOptions): void;
132
+ }
133
+ type ServerControllerInput<P extends Record<string, unknown> = Record<string, unknown>, Q extends Record<string, unknown> = Record<string, unknown>> = ControllerInput<P, Q, ServerControllerContext>;
134
+ /** Server execution reuses the ordinary controller lifecycle; the Vite boundary removes its module from clients. */
135
+ declare abstract class BaseServerController<I extends ServerControllerInput = ServerControllerInput, R = unknown> extends BaseController<I, R> {
136
+ readonly [SERVER_CONTROLLER] = true;
137
+ protected prepareContext(context: ExecutionContext): I["context"];
138
+ }
139
+ //#endregion
140
+ //#region ../server/src/ssr-handler.d.ts
141
+ interface SSRRequestContext {
142
+ readonly request: Request;
143
+ readonly bindings: Readonly<Record<string, unknown>>;
144
+ readonly fetch?: typeof globalThis.fetch;
145
+ readonly safeFetch?: SecureFetchOptions;
146
+ readonly requestState?: ServerRequestState;
147
+ }
148
+ interface SSRResponseResult<TData = unknown> {
149
+ html: string;
150
+ head: string;
151
+ css: string;
152
+ serverData: TData;
153
+ renderMode?: string;
154
+ redirect?: {
155
+ url: string;
156
+ status: number;
157
+ };
158
+ slots?: Record<string, string>;
159
+ locale?: {
160
+ lang: string;
161
+ dir: string;
162
+ } | string;
163
+ status?: number;
164
+ headers?: HeadersInit;
165
+ rewriteUrl?: string;
166
+ /** Explicit guarantee that this result is public and independent of request bindings. */
167
+ cache?: "public";
168
+ }
169
+ interface SSRModule<TData = unknown> {
170
+ render: ((url: string, context?: SSRRequestContext) => SSRResponseResult<TData> | Promise<SSRResponseResult<TData>>) & {
171
+ dispose?(): Promise<void>;
172
+ readonly routes?: readonly {
173
+ readonly path: string;
174
+ readonly renderMode?: string;
175
+ }[];
176
+ controller?(input: ServerControllerRequest, context: SSRRequestContext): Promise<SSRResponseResult<TData>>;
177
+ };
178
+ serializeServerData: (data: TData) => string;
179
+ }
180
+ interface SSRCache {
181
+ get(key: string): string | null | undefined | Promise<string | null | undefined>;
182
+ set(key: string, html: string): void | Promise<void>;
183
+ }
184
+ interface SSRHandlerBaseOptions {
185
+ /** Transfer loaded renderer shutdown to this handler. Default: borrowed renderers. */
186
+ readonly ownRenderers?: boolean;
187
+ template: string | ((request: Request) => string | Promise<string>);
188
+ renderModes?: Record<string, string>;
189
+ defaultLocale?: string;
190
+ /** Internal dispatcher; receives the current invocation bindings. */
191
+ fetch?: (request: Request, bindings?: Readonly<Record<string, unknown>>) => Response | Promise<Response>;
192
+ safeFetch?: SecureFetchOptions;
193
+ /** Omit to use a bounded process-local cache. Only explicitly public responses qualify. */
194
+ cache?: SSRCache;
195
+ onError?: (error: unknown) => void;
196
+ publicCacheHeaders?: Record<string, string>;
197
+ }
198
+ /** Load a module per invocation when the host selects its renderer/serializer dynamically. */
199
+ type SSRHandlerOptions<TData = unknown> = SSRHandlerBaseOptions & (SSRModule<TData> | {
200
+ loadModule: (request: Request) => SSRModule<TData> | Promise<SSRModule<TData>>;
201
+ });
202
+ declare function matchRenderModeOverride(url: string, renderModes?: Record<string, string>): string | undefined;
203
+ interface SSRHandler extends HttpHandler {
204
+ dispose(this: void): Promise<void>;
205
+ }
206
+ /** Standard Request/Response HTML assembly; owns no Node, Hono, filesystem or Vite state. */
207
+ declare function createSSRHandler<TData = unknown>(options: SSRHandlerOptions<TData>): SSRHandler;
208
+ //#endregion
209
+ export { createSSRRender as C, SSRRenderResult as E, SSRRenderConfig as S, SSRContext as T, serializeServerData as _, SSRRequestContext as a, injectCSRShell as b, matchRenderModeOverride as c, ServerControllerContext as d, ServerControllerInput as f, materializeServerData as g, SerializeServerDataOptions as h, SSRModule as i, BaseServerController as l, createServerContext as m, SSRHandler as n, SSRResponseResult as o, ServerContextOptions as p, SSRHandlerOptions as r, createSSRHandler as s, SSRCache as t, CookieOptions as u, InjectSSROptions as v, SSRAppResult as w, injectSSRContent as x, SSR_PLACEHOLDERS as y };
210
+ //# sourceMappingURL=ssr-BEUNDvbj.d.mts.map
@@ -0,0 +1,357 @@
1
+ import { D as SERVER_REQUEST, E as SERVER_CONTROLLER, F as serializeNavigation, P as deserializeNavigation, T as getWebPlan, at as stack, d as createWebSession, i as createWebRuntime, r as resolveInitialNavigation, rt as leaf, t as parseCookieString, x as getFrameworkBuildId } from "./src-qwx7Vw8g.mjs";
2
+ import { n as ExecutionError } from "./path-CGFl2w7D.mjs";
3
+ import { i as getPublicFields, n as BASE_PAGE_FIELDS, s as BaseController, t as resolveConfiguredMessages } from "./messages-CAt2QdGr.mjs";
4
+ import "./src-Ftl_0rhu.mjs";
5
+ import "./proxy-1SphZ7x7.mjs";
6
+ //#region ../ssr/src/server-data.ts
7
+ const MATERIALIZED = Symbol("materialized-public-data");
8
+ /** Copy declared public data now; never keep request-backed objects/getters in a response. */
9
+ function materializeServerData(data, options = {}) {
10
+ const materialized = data[MATERIALIZED];
11
+ if (materialized) {
12
+ if (options.onUnmarkedPage === "strict" && materialized === "unmarked") throw Error("markPublic-required");
13
+ return data;
14
+ }
15
+ let allMarked = true;
16
+ const pages = data.pages.map((entry) => {
17
+ const marked = getPublicFields(entry.data) !== null;
18
+ allMarked &&= marked;
19
+ if (options.onUnmarkedPage === "strict" && !marked) throw Error("markPublic-required");
20
+ try {
21
+ return {
22
+ ...entry.entryId ? { entryId: entry.entryId } : {},
23
+ intent: {
24
+ id: entry.intent.id,
25
+ ...entry.intent.params === void 0 ? {} : { params: cloneJson(entry.intent.params, /* @__PURE__ */ new Set()) },
26
+ ...entry.intent.query === void 0 ? {} : { query: cloneJson(entry.intent.query, /* @__PURE__ */ new Set()) }
27
+ },
28
+ data: project(entry.data, void 0, true, /* @__PURE__ */ new Set())
29
+ };
30
+ } catch {
31
+ throw Error("public-materialization-failed");
32
+ }
33
+ });
34
+ const result = {
35
+ tree: data.tree && serializeNavigation(deserializeNavigation(data.tree)),
36
+ pages
37
+ };
38
+ Object.defineProperty(result, MATERIALIZED, { value: allMarked ? "marked" : "unmarked" });
39
+ return result;
40
+ }
41
+ /** The shared response assembler remains the single HTML-safe wire serializer owner. */
42
+ function serializeServerData(data, options = {}) {
43
+ const json = JSON.stringify({
44
+ protocolVersion: 2,
45
+ buildId: options.buildId ?? getFrameworkBuildId(),
46
+ payload: materializeServerData(data, options)
47
+ });
48
+ const escapes = {
49
+ "<": "\\u003C",
50
+ ">": "\\u003E",
51
+ "/": "\\u002F",
52
+ "&": "\\u0026",
53
+ "\u2028": "\\u2028",
54
+ "\u2029": "\\u2029"
55
+ };
56
+ return json.replace(/[<>/&\u2028\u2029]/g, (value) => escapes[value]);
57
+ }
58
+ function scalar(value) {
59
+ return value === null || value === void 0 || typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value);
60
+ }
61
+ function isCodec(value) {
62
+ return value.kind === "codec" && typeof value.encode === "function";
63
+ }
64
+ function project(value, declaration, base, ancestors) {
65
+ if (declaration && declaration !== true && isCodec(declaration)) return cloneJson(declaration.encode(value), /* @__PURE__ */ new Set());
66
+ if (scalar(value)) return value;
67
+ if (typeof value !== "object" || value === null) throw Error("invalid-public-value");
68
+ if (ancestors.has(value)) throw Error("cyclic-public-value");
69
+ ancestors.add(value);
70
+ try {
71
+ if (Array.isArray(value)) {
72
+ if (!declaration || declaration === true) {
73
+ if (!value.every((item) => getPublicFields(item) !== null)) return [];
74
+ }
75
+ return value.map((item) => project(item, declaration, false, ancestors));
76
+ }
77
+ const marker = declaration && declaration !== true ? declaration : getPublicFields(value);
78
+ const projection = marker && marker !== true && !Array.isArray(marker) ? marker : void 0;
79
+ const fields = marker === true ? Object.keys(value) : [...base ? BASE_PAGE_FIELDS : [], ...Array.isArray(marker) ? marker : projection ? Object.keys(projection) : []];
80
+ const result = Object.create(null);
81
+ for (const field of new Set(fields)) {
82
+ if (!(field in value)) continue;
83
+ const item = project(value[field], projection?.[field], false, ancestors);
84
+ if (item !== void 0) result[field] = item;
85
+ }
86
+ return result;
87
+ } finally {
88
+ ancestors.delete(value);
89
+ }
90
+ }
91
+ /** Explicit codecs may emit JSON records/arrays; methods, class instances and cycles are rejected. */
92
+ function cloneJson(value, ancestors) {
93
+ if (scalar(value)) return value;
94
+ if (typeof value !== "object" || value === null || ancestors.has(value)) throw Error("invalid-codec-value");
95
+ if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) throw Error("invalid-codec-value");
96
+ ancestors.add(value);
97
+ try {
98
+ if (Array.isArray(value)) return value.map((item) => cloneJson(item, ancestors));
99
+ const result = Object.create(null);
100
+ for (const field of Object.keys(value)) {
101
+ const item = cloneJson(value[field], ancestors);
102
+ if (item !== void 0) result[field] = item;
103
+ }
104
+ return result;
105
+ } finally {
106
+ ancestors.delete(value);
107
+ }
108
+ }
109
+ //#endregion
110
+ //#region ../ssr/src/create-render.ts
111
+ /** One request scope and one native root serve ordinary and composed navigation. */
112
+ function createSSRRender(config) {
113
+ const owner = createWebRuntime({
114
+ ...config.configuration,
115
+ definition: config.definition,
116
+ storageScope: "execution"
117
+ });
118
+ const active = /* @__PURE__ */ new Set();
119
+ let closing;
120
+ const render = async (url, context = {}, remote) => {
121
+ const request = context.request ?? new Request(new URL(url || "/", "http://localhost"));
122
+ const requestState = context.requestState ?? {
123
+ request,
124
+ responseHeaders: new Headers(),
125
+ remote: !!remote,
126
+ cookies: parseCookieString(request.headers.get("cookie") ?? "")
127
+ };
128
+ const configuration = {
129
+ ...config.definition.configuration,
130
+ ...config.configuration
131
+ };
132
+ const resolvedLocale = config.resolveLocale?.(url, context.request);
133
+ const locale = resolvedLocale?.lang ?? configuration.locale;
134
+ const fetch = context.fetch ?? configuration.fetch ?? globalThis.fetch?.bind(globalThis);
135
+ const messages = await resolveConfiguredMessages({
136
+ locale,
137
+ loadMessages: config.definition.loadMessages,
138
+ context: locale ? {
139
+ runtime: "server",
140
+ url,
141
+ request: context.request,
142
+ fetch
143
+ } : void 0
144
+ });
145
+ const web = createWebRuntime({
146
+ ...configuration,
147
+ definition: config.definition,
148
+ runtime: owner.runtime,
149
+ storageScope: "execution",
150
+ locale,
151
+ localeAttributes: resolvedLocale,
152
+ messages,
153
+ fetch,
154
+ safeFetch: {
155
+ ...context.safeFetch,
156
+ ...configuration.safeFetch
157
+ },
158
+ invocation: {
159
+ signal: context.request?.signal,
160
+ identity: context.identity,
161
+ traceId: context.traceId,
162
+ fetch,
163
+ bindings: {
164
+ ...context.bindings,
165
+ request: context.request,
166
+ [SERVER_REQUEST]: {
167
+ ...requestState,
168
+ remote: !!remote
169
+ }
170
+ }
171
+ }
172
+ });
173
+ let controller;
174
+ const execution = web.createExecution();
175
+ let failed = false;
176
+ try {
177
+ const resolved = remote ? void 0 : await resolveInitialNavigation(web, url);
178
+ const initial = remote ? stack(leaf(remote.intent, remote.params, {
179
+ query: remote.query,
180
+ ...remote.url ? { url: remote.url } : {}
181
+ })) : resolved?.tree ?? stack(leaf("@finesoft/not-found", {}, { url }));
182
+ const base = {
183
+ head: "",
184
+ css: "",
185
+ html: "",
186
+ serverData: { pages: [] },
187
+ locale: await web.getLocale(execution),
188
+ headers: requestState.responseHeaders
189
+ };
190
+ if (!remote && resolved?.renderMode === "csr") return {
191
+ ...base,
192
+ renderMode: "csr"
193
+ };
194
+ let redirect;
195
+ const cookies = requestState.cookies;
196
+ controller = createWebSession({
197
+ web,
198
+ execution,
199
+ initial,
200
+ isServer: true,
201
+ onRedirect: (value) => {
202
+ redirect ??= value;
203
+ },
204
+ createContext: ({ intent, params, query, url: matchedUrl }) => ({
205
+ url: matchedUrl ?? url,
206
+ path: new URL(matchedUrl ?? url, "http://localhost").pathname,
207
+ intent: {
208
+ id: intent,
209
+ params,
210
+ query
211
+ },
212
+ params,
213
+ query: query ?? {},
214
+ container: execution.context.container,
215
+ isServer: true,
216
+ getCookie: (name) => cookies.get(name),
217
+ getHeader: (name) => context.request?.headers.get(name) ?? void 0
218
+ })
219
+ });
220
+ for (const kind of ["flow", "externalUrl"]) controller.onAction(kind, () => {
221
+ throw new ExecutionError("configuration", "SSR views cannot initiate browser actions");
222
+ });
223
+ const candidate = await controller.start();
224
+ if (redirect || candidate.redirect) return {
225
+ ...base,
226
+ redirect: redirect ?? candidate.redirect
227
+ };
228
+ const snapshot = candidate;
229
+ const status = snapshot.destinations.at(-1)?.status;
230
+ execution.context.signal.throwIfAborted();
231
+ const serverData = materializeServerData(status ? { pages: [] } : {
232
+ tree: serializeNavigation(snapshot.tree),
233
+ pages: snapshot.destinations.map((entry) => ({
234
+ entryId: entry.entryId,
235
+ intent: {
236
+ id: entry.intent,
237
+ params: entry.params,
238
+ ...entry.query ? { query: entry.query } : {}
239
+ },
240
+ data: entry.page
241
+ }))
242
+ });
243
+ const native = remote ? "" : await config.render(controller);
244
+ execution.context.signal.throwIfAborted();
245
+ const output = typeof native === "string" ? { html: native } : native;
246
+ return {
247
+ ...base,
248
+ ...output,
249
+ head: output.head ?? "",
250
+ css: output.css ?? "",
251
+ serverData,
252
+ renderMode: snapshot.destinations.at(-1)?.renderMode ?? resolved?.renderMode,
253
+ status,
254
+ rewriteUrl: snapshot.destinations.at(-1)?.rewriteUrl,
255
+ ...!status && snapshot.destinations.length && snapshot.destinations.every((d) => d.cache === "public") ? { cache: "public" } : {}
256
+ };
257
+ } catch (error) {
258
+ failed = true;
259
+ throw error;
260
+ } finally {
261
+ const errors = (await Promise.allSettled([
262
+ controller?.dispose(),
263
+ execution.dispose(),
264
+ web.dispose()
265
+ ])).filter((result) => result.status === "rejected").map((result) => result.reason);
266
+ if (!failed && errors.length) throw new AggregateError(errors, "SSR cleanup failed");
267
+ }
268
+ };
269
+ const run = (url, context, remote) => {
270
+ if (closing) return Promise.reject(Error("SSR renderer disposed"));
271
+ const work = render(url, context, remote);
272
+ active.add(work);
273
+ work.then(() => active.delete(work), () => active.delete(work));
274
+ return work;
275
+ };
276
+ return Object.assign(run, {
277
+ controller: (input, context) => run(input.url || "/", context, input),
278
+ routes: getWebPlan(config.definition).routes,
279
+ dispose: () => closing ??= (async () => {
280
+ while (active.size) await Promise.allSettled(active);
281
+ await owner.dispose();
282
+ })()
283
+ });
284
+ }
285
+ //#endregion
286
+ //#region ../ssr/src/middleware/context.ts
287
+ /** 从 Request 对象构建服务端上下文 */
288
+ function createServerContext(options) {
289
+ const { url, intent, container, request } = options;
290
+ const parsed = new URL(url, "http://localhost");
291
+ const cookieHeader = request?.headers.get("cookie") ?? "";
292
+ const cookies = parseCookieString(cookieHeader);
293
+ return {
294
+ url,
295
+ path: parsed.pathname,
296
+ params: intent.params ?? {},
297
+ query: intent.query ?? {},
298
+ intent,
299
+ isServer: true,
300
+ container,
301
+ getCookie: (name) => cookies.get(name),
302
+ getHeader: (name) => request?.headers.get(name) ?? void 0
303
+ };
304
+ }
305
+ //#endregion
306
+ //#region ../ssr/src/server-controller.ts
307
+ /** Server execution reuses the ordinary controller lifecycle; the Vite boundary removes its module from clients. */
308
+ var BaseServerController = class extends BaseController {
309
+ [SERVER_CONTROLLER] = true;
310
+ prepareContext(context) {
311
+ const state = context.bindings[SERVER_REQUEST];
312
+ if (!state || !(state.request instanceof Request) || !context.isServer) throw new ExecutionError("capability", "BaseServerController requires a server request");
313
+ const setCookie = (name, value, options = {}) => {
314
+ context.signal.throwIfAborted();
315
+ if (!/^[!#$%&'*+.^_`|~\w-]+$/.test(name)) throw new TypeError("Invalid cookie name");
316
+ const parts = [`${name}=${encodeURIComponent(value)}`];
317
+ for (const [key, item] of [["Path", options.path ?? "/"], ["Domain", options.domain]]) if (item !== void 0) {
318
+ if (/[;\r\n]/.test(item)) throw new TypeError("Invalid cookie attribute");
319
+ parts.push(`${key}=${item}`);
320
+ }
321
+ if (options.maxAge !== void 0) {
322
+ if (!Number.isSafeInteger(options.maxAge)) throw new TypeError("Invalid cookie maxAge");
323
+ parts.push(`Max-Age=${options.maxAge}`);
324
+ }
325
+ if (options.expires) {
326
+ if (!Number.isFinite(options.expires.getTime())) throw new TypeError("Invalid cookie expiry");
327
+ parts.push(`Expires=${options.expires.toUTCString()}`);
328
+ }
329
+ if (options.httpOnly) parts.push("HttpOnly");
330
+ if (options.secure) parts.push("Secure");
331
+ if (options.sameSite) {
332
+ if (![
333
+ "Strict",
334
+ "Lax",
335
+ "None"
336
+ ].includes(options.sameSite)) throw new TypeError("Invalid SameSite");
337
+ parts.push(`SameSite=${options.sameSite}`);
338
+ }
339
+ state.responseHeaders.append("set-cookie", parts.join("; "));
340
+ };
341
+ return Object.freeze({
342
+ ...context,
343
+ isServer: true,
344
+ request: state.request,
345
+ responseHeaders: state.responseHeaders,
346
+ setCookie,
347
+ deleteCookie: (name, options) => setCookie(name, "", {
348
+ ...options,
349
+ maxAge: 0
350
+ })
351
+ });
352
+ }
353
+ };
354
+ //#endregion
355
+ export { serializeServerData as a, materializeServerData as i, createServerContext as n, createSSRRender as r, BaseServerController as t };
356
+
357
+ //# sourceMappingURL=ssr-C8xnYXoY.mjs.map
package/dist/ssr.d.mts ADDED
@@ -0,0 +1,3 @@
1
+ import { C as createSSRRender, E as SSRRenderResult, S as SSRRenderConfig, T as SSRContext, _ as serializeServerData, a as SSRRequestContext, b as injectCSRShell, c as matchRenderModeOverride, d as ServerControllerContext, f as ServerControllerInput, g as materializeServerData, h as SerializeServerDataOptions, i as SSRModule, l as BaseServerController, m as createServerContext, n as SSRHandler, o as SSRResponseResult, p as ServerContextOptions, r as SSRHandlerOptions, s as createSSRHandler, t as SSRCache, u as CookieOptions, v as InjectSSROptions, w as SSRAppResult, x as injectSSRContent, y as SSR_PLACEHOLDERS } from "./ssr-BEUNDvbj.mjs";
2
+ import { a as registerProxyRoutes, n as ProxyRouteConfig, r as ProxyRouter, t as ProxyAuthConfig } from "./proxy-2dSWO-Xw.mjs";
3
+ export { BaseServerController, type CookieOptions, type InjectSSROptions, type ProxyAuthConfig, type ProxyRouteConfig, type ProxyRouter, type SSRAppResult, SSRCache, type SSRContext, SSRHandler, SSRHandlerOptions, SSRModule, type SSRRenderConfig, type SSRRenderResult, SSRRequestContext, SSRResponseResult, SSR_PLACEHOLDERS, type SerializeServerDataOptions, type ServerContextOptions, type ServerControllerContext, type ServerControllerInput, createSSRHandler, createSSRRender, createServerContext, injectCSRShell, injectSSRContent, matchRenderModeOverride, materializeServerData, registerProxyRoutes, serializeServerData };
package/dist/ssr.mjs ADDED
@@ -0,0 +1,3 @@
1
+ import { a as serializeServerData, i as materializeServerData, n as createServerContext, r as createSSRRender, t as BaseServerController } from "./ssr-C8xnYXoY.mjs";
2
+ import { c as injectSSRContent, i as matchRenderModeOverride, n as registerProxyRoutes, o as SSR_PLACEHOLDERS, r as createSSRHandler, s as injectCSRShell } from "./proxy-1SphZ7x7.mjs";
3
+ export { BaseServerController, SSR_PLACEHOLDERS, createSSRHandler, createSSRRender, createServerContext, injectCSRShell, injectSSRContent, matchRenderModeOverride, materializeServerData, registerProxyRoutes, serializeServerData };
@@ -0,0 +1,16 @@
1
+ import { g as WebAppView, h as ViewProps } from "./session-DnB4ZC3x.mjs";
2
+ import Outlet from "./Outlet.svelte";
3
+ import { Component } from "svelte";
4
+ declare namespace svelte_d_exports {
5
+ export { NativeView, NativeViews, Outlet, ViewProps, WebAppView, useSnapshot };
6
+ }
7
+ /** Views choose their page subtype; Outlet supplies the common runtime props. */
8
+ type NativeView = Component<never>;
9
+ type NativeViews = Readonly<Record<string, NativeView>>;
10
+ /** Svelte components consume this small store with `$snapshot`. */
11
+ declare function useSnapshot(app: WebAppView): {
12
+ subscribe(run: (value: ReturnType<WebAppView["getSnapshot"]>) => void): () => void;
13
+ };
14
+ //#endregion
15
+ export { useSnapshot as a, svelte_d_exports as i, NativeViews as n, Outlet as r, NativeView as t };
16
+ //# sourceMappingURL=svelte-Dr5to3SE.d.mts.map
@@ -0,0 +1,3 @@
1
+ import { g as WebAppView, h as ViewProps } from "./session-DnB4ZC3x.mjs";
2
+ import { a as useSnapshot, n as NativeViews, r as Outlet, t as NativeView } from "./svelte-Dr5to3SE.mjs";
3
+ export { NativeView, NativeViews, Outlet, type ViewProps, type WebAppView, useSnapshot };
@@ -0,0 +1,13 @@
1
+ import Outlet from "./Outlet.svelte";
2
+ //#region src/svelte.ts
3
+ /** Svelte components consume this small store with `$snapshot`. */
4
+ function useSnapshot(app) {
5
+ return { subscribe(run) {
6
+ run(app.getSnapshot());
7
+ return app.subscribe(() => run(app.getSnapshot()));
8
+ } };
9
+ }
10
+ //#endregion
11
+ export { Outlet, useSnapshot };
12
+
13
+ //# sourceMappingURL=svelte.mjs.map
@@ -0,0 +1,12 @@
1
+ //#region ../server/src/public-types.d.ts
2
+ interface FrontTypeOptions {
3
+ /** Project directory; defaults to the current working directory. */
4
+ root?: string;
5
+ /** Project tsconfig, relative to root. Existing options and comments are preserved. */
6
+ tsconfig?: string;
7
+ }
8
+ /** Maintain an exact root alias with only the project's installed platform/native contracts. */
9
+ declare function generateFrontTypes(options?: FrontTypeOptions): readonly string[];
10
+ //#endregion
11
+ export { generateFrontTypes as n, FrontTypeOptions as t };
12
+ //# sourceMappingURL=typegen-C-WeJCtf.d.mts.map
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ import { r as generateControllerTypes, t as generateFrontTypes } from "./public-types-BcJM-AYc.mjs";
3
+ import "./typegen.mjs";
4
+ //#region src/typegen-cli.ts
5
+ const root = process.argv[2] ?? process.cwd();
6
+ generateFrontTypes({ root });
7
+ generateControllerTypes({ root });
8
+ //#endregion
9
+ export {};
10
+
11
+ //# sourceMappingURL=typegen-cli.mjs.map
@@ -0,0 +1,3 @@
1
+ import { n as ControllerTypeResult, r as generateControllerTypes, t as ControllerTypeOptions } from "./controller-types-CgmJ6-le.mjs";
2
+ import { n as generateFrontTypes, t as FrontTypeOptions } from "./typegen-C-WeJCtf.mjs";
3
+ export { type ControllerTypeOptions, type ControllerTypeResult, type FrontTypeOptions, generateControllerTypes, generateFrontTypes };
@@ -0,0 +1,2 @@
1
+ import { r as generateControllerTypes, t as generateFrontTypes } from "./public-types-BcJM-AYc.mjs";
2
+ export { generateControllerTypes, generateFrontTypes };