@fluixi/start 0.1.0-alpha.43

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 (58) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +101 -0
  3. package/dist/adapter.d.ts +32 -0
  4. package/dist/adapter.d.ts.map +1 -0
  5. package/dist/adapter.js +78 -0
  6. package/dist/api.d.ts +35 -0
  7. package/dist/api.d.ts.map +1 -0
  8. package/dist/api.js +120 -0
  9. package/dist/commands/build.d.ts +8 -0
  10. package/dist/commands/build.d.ts.map +1 -0
  11. package/dist/commands/build.js +67 -0
  12. package/dist/commands/dev.d.ts +8 -0
  13. package/dist/commands/dev.d.ts.map +1 -0
  14. package/dist/commands/dev.js +91 -0
  15. package/dist/commands/prerender.d.ts +11 -0
  16. package/dist/commands/prerender.d.ts.map +1 -0
  17. package/dist/commands/prerender.js +78 -0
  18. package/dist/commands/start.d.ts +9 -0
  19. package/dist/commands/start.d.ts.map +1 -0
  20. package/dist/commands/start.js +18 -0
  21. package/dist/config.d.ts +82 -0
  22. package/dist/config.d.ts.map +1 -0
  23. package/dist/config.js +116 -0
  24. package/dist/di.d.ts +63 -0
  25. package/dist/di.d.ts.map +1 -0
  26. package/dist/di.js +210 -0
  27. package/dist/handler.d.ts +42 -0
  28. package/dist/handler.d.ts.map +1 -0
  29. package/dist/handler.js +152 -0
  30. package/dist/head.d.ts +14 -0
  31. package/dist/head.d.ts.map +1 -0
  32. package/dist/head.js +13 -0
  33. package/dist/index.d.ts +24 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +25 -0
  36. package/dist/interceptors.d.ts +15 -0
  37. package/dist/interceptors.d.ts.map +1 -0
  38. package/dist/interceptors.js +47 -0
  39. package/dist/internal.d.ts +87 -0
  40. package/dist/internal.d.ts.map +1 -0
  41. package/dist/internal.js +302 -0
  42. package/dist/middleware.d.ts +38 -0
  43. package/dist/middleware.d.ts.map +1 -0
  44. package/dist/middleware.js +39 -0
  45. package/dist/router.d.ts +13 -0
  46. package/dist/router.d.ts.map +1 -0
  47. package/dist/router.js +12 -0
  48. package/dist/server-fn-setup.d.ts +8 -0
  49. package/dist/server-fn-setup.d.ts.map +1 -0
  50. package/dist/server-fn-setup.js +17 -0
  51. package/dist/server-fn.d.ts +33 -0
  52. package/dist/server-fn.d.ts.map +1 -0
  53. package/dist/server-fn.js +96 -0
  54. package/dist/tsconfig.lib.tsbuildinfo +1 -0
  55. package/dist/ui.d.ts +35 -0
  56. package/dist/ui.d.ts.map +1 -0
  57. package/dist/ui.js +99 -0
  58. package/package.json +86 -0
@@ -0,0 +1,152 @@
1
+ import { createServer as createHttpServer } from 'node:http';
2
+ import { stat } from 'node:fs/promises';
3
+ import { createReadStream } from 'node:fs';
4
+ import { Readable } from 'node:stream';
5
+ import { join, extname } from 'node:path';
6
+ /**
7
+ * Compose a streamed HTML Response: flush `head` immediately (browser starts fetching
8
+ * assets while the server awaits data), then pipe the app `body` stream into the mount
9
+ * point, then `tail` (client script + closing tags). A render error after the head is
10
+ * flushed can only error the stream (status is already 200) — truncated HTML; callers
11
+ * should guard the pre-flush path for a real 500.
12
+ */
13
+ export function streamDocument(head, body, tail) {
14
+ const enc = new TextEncoder();
15
+ const stream = new ReadableStream({
16
+ async start(controller) {
17
+ try {
18
+ controller.enqueue(enc.encode(head));
19
+ const reader = body.getReader();
20
+ for (;;) {
21
+ const { done, value } = await reader.read();
22
+ if (done)
23
+ break;
24
+ controller.enqueue(value);
25
+ }
26
+ controller.enqueue(enc.encode(tail));
27
+ controller.close();
28
+ }
29
+ catch (err) {
30
+ controller.error(err);
31
+ }
32
+ },
33
+ });
34
+ return new Response(stream, {
35
+ status: 200,
36
+ headers: { 'content-type': 'text/html; charset=utf-8' },
37
+ });
38
+ }
39
+ /** Wrap a render function as a fetch handler (Node/Bun/Deno/edge-portable). */
40
+ export function createRequestHandler(render) {
41
+ return async (request) => {
42
+ const url = new URL(request.url);
43
+ try {
44
+ const html = await render(url.pathname + url.search, request);
45
+ return new Response(html, {
46
+ status: 200,
47
+ headers: { 'content-type': 'text/html; charset=utf-8' },
48
+ });
49
+ }
50
+ catch (e) {
51
+ return new Response(String(e?.stack || e), {
52
+ status: 500,
53
+ headers: { 'content-type': 'text/plain; charset=utf-8' },
54
+ });
55
+ }
56
+ };
57
+ }
58
+ // ─── Node bridge (the built-in "node adapter") ──────────────────────────────
59
+ /** Build a Web `Request` from a Node `IncomingMessage`. */
60
+ export function nodeToRequest(req) {
61
+ const host = req.headers.host ?? 'localhost';
62
+ const url = `http://${host}${req.url ?? '/'}`;
63
+ const headers = new Headers();
64
+ for (const [k, v] of Object.entries(req.headers)) {
65
+ if (Array.isArray(v))
66
+ v.forEach((x) => headers.append(k, x));
67
+ else if (v != null)
68
+ headers.set(k, v);
69
+ }
70
+ const method = req.method ?? 'GET';
71
+ const init = { method, headers };
72
+ if (method !== 'GET' && method !== 'HEAD') {
73
+ init.body = req; // Node readable — fine for undici/Node fetch
74
+ init.duplex = 'half';
75
+ }
76
+ return new Request(url, init);
77
+ }
78
+ /** Write a Web `Response` (string or streamed body) to a Node `ServerResponse`. */
79
+ export async function sendResponse(res, response) {
80
+ res.statusCode = response.status;
81
+ response.headers.forEach((value, key) => res.setHeader(key, value));
82
+ const body = response.body;
83
+ if (!body) {
84
+ res.end(await response.text().catch(() => ''));
85
+ return;
86
+ }
87
+ const reader = body.getReader();
88
+ try {
89
+ for (;;) {
90
+ const { done, value } = await reader.read();
91
+ if (done)
92
+ break;
93
+ res.write(value);
94
+ }
95
+ }
96
+ finally {
97
+ res.end();
98
+ }
99
+ }
100
+ /** Adapt a `FetchHandler` to a Node `(req, res)` handler. */
101
+ export function toNodeHandler(handler) {
102
+ return async (req, res) => {
103
+ const response = await handler(nodeToRequest(req));
104
+ await sendResponse(res, response);
105
+ };
106
+ }
107
+ /** The reference **Node adapter**: serve a `FetchHandler` over `node:http`. */
108
+ export function serveNode(handler, opts = {}) {
109
+ const port = opts.port ?? 3000;
110
+ const node = toNodeHandler(handler);
111
+ const server = createHttpServer((req, res) => {
112
+ node(req, res).catch((e) => {
113
+ res.statusCode = 500;
114
+ res.end(String(e?.stack || e));
115
+ });
116
+ });
117
+ server.listen(port, () => opts.onListen ? opts.onListen(port) : console.log(` fluixi → http://localhost:${port}`));
118
+ return server;
119
+ }
120
+ const MIME = {
121
+ '.js': 'text/javascript', '.mjs': 'text/javascript', '.css': 'text/css',
122
+ '.html': 'text/html', '.json': 'application/json', '.svg': 'image/svg+xml',
123
+ '.png': 'image/png', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.webp': 'image/webp',
124
+ '.ico': 'image/x-icon', '.woff': 'font/woff', '.woff2': 'font/woff2', '.map': 'application/json',
125
+ };
126
+ /**
127
+ * Wrap a handler to serve static files from `dir` first (for filesystem runtimes —
128
+ * Node/Bun/Deno). Edge runtimes serve assets via the platform, so they use the bare
129
+ * handler instead.
130
+ */
131
+ export function withStaticFiles(handler, dir) {
132
+ return async (request) => {
133
+ const { pathname } = new URL(request.url);
134
+ if (pathname !== '/' && extname(pathname)) {
135
+ const file = join(dir, decodeURIComponent(pathname));
136
+ try {
137
+ const s = await stat(file);
138
+ if (s.isFile()) {
139
+ const body = Readable.toWeb(createReadStream(file));
140
+ return new Response(body, {
141
+ headers: {
142
+ 'content-type': MIME[extname(file).toLowerCase()] ?? 'application/octet-stream',
143
+ 'content-length': String(s.size),
144
+ },
145
+ });
146
+ }
147
+ }
148
+ catch { /* not a static file → fall through to SSR */ }
149
+ }
150
+ return handler(request);
151
+ };
152
+ }
package/dist/head.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * `@fluixi/start/head` — the app-facing SEO & document-head surface, re-exported from the
3
+ * framework-agnostic `@fluixi/head` engine. Importing from the meta-framework gives apps a single,
4
+ * stable dependency (like `@fluixi/start/router`) instead of reaching into the engine directly:
5
+ *
6
+ * import { seo, jsonld, Title, Meta, Link, JsonLD } from '@fluixi/start/head';
7
+ *
8
+ * seo({ title: 'Home', description: '…', canonical: 'https://site.com/' });
9
+ *
10
+ * SSR injection, route `seo` exports + nested-layout inheritance, and build-time
11
+ * robots.txt/sitemap.xml emission are wired through @fluixi/start (see server + build).
12
+ */
13
+ export * from '@fluixi/head';
14
+ //# sourceMappingURL=head.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"head.d.ts","sourceRoot":"","sources":["../src/head.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,cAAc,cAAc,CAAC"}
package/dist/head.js ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * `@fluixi/start/head` — the app-facing SEO & document-head surface, re-exported from the
3
+ * framework-agnostic `@fluixi/head` engine. Importing from the meta-framework gives apps a single,
4
+ * stable dependency (like `@fluixi/start/router`) instead of reaching into the engine directly:
5
+ *
6
+ * import { seo, jsonld, Title, Meta, Link, JsonLD } from '@fluixi/start/head';
7
+ *
8
+ * seo({ title: 'Home', description: '…', canonical: 'https://site.com/' });
9
+ *
10
+ * SSR injection, route `seo` exports + nested-layout inheritance, and build-time
11
+ * robots.txt/sitemap.xml emission are wired through @fluixi/start (see server + build).
12
+ */
13
+ export * from '@fluixi/head';
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @fluixi/start — the Fluixi meta-framework.
3
+ *
4
+ * Packages the dev server, build, and production SSR server over @fluixi/server +
5
+ * Vite, so apps stop hand-rolling server.mjs. Use the `fluixi` CLI (dev/build/start)
6
+ * or call the commands programmatically.
7
+ */
8
+ export { defineConfig, resolveConfig, loadConfig } from './config.js';
9
+ export type { FluixiConfig, ResolvedConfig } from './config.js';
10
+ export { dev } from './commands/dev.js';
11
+ export { build } from './commands/build.js';
12
+ export { start } from './commands/start.js';
13
+ export { prerender } from './commands/prerender.js';
14
+ export { injectApp, injectAppAndHead, splitTemplate } from './internal.js';
15
+ export { createRequestHandler, toNodeHandler, nodeToRequest, sendResponse, serveNode, streamDocument, withStaticFiles, } from './handler.js';
16
+ export type { FetchHandler, RenderFn, StreamRenderFn, ServeNodeOptions } from './handler.js';
17
+ export { createProdHandler, nodeAdapter, webAdapter } from './adapter.js';
18
+ export type { Adapter, AdapterContext } from './adapter.js';
19
+ export { defineMiddleware, composeMiddleware, normalizeMiddleware } from './middleware.js';
20
+ export type { Middleware, MiddlewareNext } from './middleware.js';
21
+ export { addInterceptor, clearInterceptors, fetchWithInterceptors } from './interceptors.js';
22
+ export type { Interceptor } from './interceptors.js';
23
+ export { getRequestLocals, getLocals, type RequestLocals } from '@fluixi/server';
24
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACtE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE3E,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,aAAa,EACb,YAAY,EACZ,SAAS,EACT,cAAc,EACd,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAE7F,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1E,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE5D,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAC3F,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAElE,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC7F,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrD,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,25 @@
1
+ /**
2
+ * @fluixi/start — the Fluixi meta-framework.
3
+ *
4
+ * Packages the dev server, build, and production SSR server over @fluixi/server +
5
+ * Vite, so apps stop hand-rolling server.mjs. Use the `fluixi` CLI (dev/build/start)
6
+ * or call the commands programmatically.
7
+ */
8
+ export { defineConfig, resolveConfig, loadConfig } from './config.js';
9
+ export { dev } from './commands/dev.js';
10
+ export { build } from './commands/build.js';
11
+ export { start } from './commands/start.js';
12
+ export { prerender } from './commands/prerender.js';
13
+ export { injectApp, injectAppAndHead, splitTemplate } from './internal.js';
14
+ // The runtime-neutral request layer — the seam adapters (edge/worker/Bun/Deno) build on.
15
+ export { createRequestHandler, toNodeHandler, nodeToRequest, sendResponse, serveNode, streamDocument, withStaticFiles, } from './handler.js';
16
+ // Deploy adapters: the portable prod handler + the node/web reference adapters.
17
+ export { createProdHandler, nodeAdapter, webAdapter } from './adapter.js';
18
+ // Request middleware — a `(request, next) => Response` chain run before render.
19
+ export { defineMiddleware, composeMiddleware, normalizeMiddleware } from './middleware.js';
20
+ // HTTP interceptors — request/response/error pipeline around fetch (server-fn RPC + app fetch).
21
+ export { addInterceptor, clearInterceptors, fetchWithInterceptors } from './interceptors.js';
22
+ // Middleware→render locals bridge: write `getRequestLocals(request).x = …` in middleware;
23
+ // read it back in loaders/server-fns/render via getLocals() (the app entry forwards
24
+ // `request` on the render event — `renderRequestAsync(App, { url, request })`).
25
+ export { getRequestLocals, getLocals } from '@fluixi/server';
@@ -0,0 +1,15 @@
1
+ export interface Interceptor {
2
+ /** Transform the outgoing request (e.g. add an Authorization header). */
3
+ request?: (request: Request) => Request | Promise<Request>;
4
+ /** Transform the incoming response (e.g. unwrap, refresh-on-401). */
5
+ response?: (response: Response, request: Request) => Response | Promise<Response>;
6
+ /** Handle a network error; return a Response to recover, or nothing to rethrow. */
7
+ error?: (error: unknown, request: Request) => Response | void | Promise<Response | void>;
8
+ }
9
+ /** Register an interceptor. Returns a remover. The first call wires server-fn RPC through it. */
10
+ export declare function addInterceptor(interceptor: Interceptor): () => void;
11
+ /** Remove all interceptors (and restore the plain fetch for server-fn RPC). */
12
+ export declare function clearInterceptors(): void;
13
+ /** fetch() run through the interceptor chain: request → fetch → response, with error recovery. */
14
+ export declare function fetchWithInterceptors(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
15
+ //# sourceMappingURL=interceptors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interceptors.d.ts","sourceRoot":"","sources":["../src/interceptors.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,WAAW;IAC1B,yEAAyE;IACzE,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3D,qEAAqE;IACrE,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClF,mFAAmF;IACnF,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,KAAK,QAAQ,GAAG,IAAI,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;CAC1F;AAID,iGAAiG;AACjG,wBAAgB,cAAc,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,IAAI,CAOnE;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC;AAED,kGAAkG;AAClG,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,WAAW,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAkB3G"}
@@ -0,0 +1,47 @@
1
+ // HTTP interceptors — a request/response/error pipeline around fetch (Angular-style).
2
+ // Register interceptors to attach auth headers, handle 401s, log, or retry. Server-function
3
+ // RPC calls route through this automatically once any interceptor is added; use
4
+ // `fetchWithInterceptors` for your own data fetching too.
5
+ import { setServerFnFetch } from './server-fn.js';
6
+ const interceptors = [];
7
+ /** Register an interceptor. Returns a remover. The first call wires server-fn RPC through it. */
8
+ export function addInterceptor(interceptor) {
9
+ if (interceptors.length === 0)
10
+ setServerFnFetch(fetchWithInterceptors);
11
+ interceptors.push(interceptor);
12
+ return () => {
13
+ const i = interceptors.indexOf(interceptor);
14
+ if (i >= 0)
15
+ interceptors.splice(i, 1);
16
+ };
17
+ }
18
+ /** Remove all interceptors (and restore the plain fetch for server-fn RPC). */
19
+ export function clearInterceptors() {
20
+ interceptors.length = 0;
21
+ setServerFnFetch(((...a) => fetch(...a)));
22
+ }
23
+ /** fetch() run through the interceptor chain: request → fetch → response, with error recovery. */
24
+ export async function fetchWithInterceptors(input, init) {
25
+ let request = input instanceof Request && !init ? input : new Request(input, init);
26
+ for (const i of interceptors)
27
+ if (i.request)
28
+ request = await i.request(request);
29
+ let response;
30
+ try {
31
+ response = await fetch(request);
32
+ }
33
+ catch (error) {
34
+ for (const i of interceptors) {
35
+ if (!i.error)
36
+ continue;
37
+ const recovered = await i.error(error, request);
38
+ if (recovered)
39
+ return recovered;
40
+ }
41
+ throw error;
42
+ }
43
+ for (const i of interceptors)
44
+ if (i.response)
45
+ response = await i.response(response, request);
46
+ return response;
47
+ }
@@ -0,0 +1,87 @@
1
+ import type { ResolvedConfig } from './config.js';
2
+ import type { FetchHandler } from './handler.js';
3
+ /** The virtual module that registers every `"use server"` fn + re-exports the dispatcher. */
4
+ export declare const SERVER_FNS_VMOD = "virtual:fluixi-server-fns";
5
+ /** The virtual module exposing auto-discovered translations: `{ messages, locales, defaultLocale }`. */
6
+ export declare const I18N_VMOD = "virtual:fluixi-i18n";
7
+ /**
8
+ * Auto-discover translations. Scans `<dir>/<locale>.json` (e.g. `src/i18n/en.json`, `fr.json`)
9
+ * and provides `virtual:fluixi-i18n` exporting `{ messages, locales, defaultLocale }` — wire it
10
+ * into the built-in i18n in one line:
11
+ *
12
+ * import { createI18n } from '@fluixi/core/i18n';
13
+ * import { messages, locales, defaultLocale } from 'virtual:fluixi-i18n';
14
+ * export const { t, locale, setLocale } = createI18n({ locale: defaultLocale, locales, messages });
15
+ *
16
+ * Configured via `fluixi.config`'s `i18n` (folder / locales / defaultLocale); `i18n: false` disables it.
17
+ */
18
+ export declare function i18nVitePlugin(opts: {
19
+ dir: string;
20
+ defaultLocale?: string;
21
+ locales?: string[];
22
+ }): any;
23
+ /**
24
+ * Load env files into `process.env` for SERVER code — the framework's environment manager.
25
+ *
26
+ * SECURITY MODEL (Vite-aligned): only `VITE_`-prefixed vars are exposed to the client (via
27
+ * `import.meta.env`, inlined into the browser bundle). Everything else is server-only. This
28
+ * loads ALL vars (`.env`, `.env.local`, `.env.[mode]`, `.env.[mode].local`) into `process.env`
29
+ * so loaders + `"use server"` functions can read secrets — WITHOUT ever exposing non-`VITE_`
30
+ * vars to the browser. A real (OS) env var always wins, so deploys/secret managers override files.
31
+ *
32
+ * Result: `process.env.STRIPE_SECRET` works on the server and never ships to the web; only
33
+ * `VITE_*` reaches the client. Apps stop hand-rolling dotenv loaders + risking secret leaks.
34
+ */
35
+ export declare function loadServerEnv(root: string, mode: string): Promise<void>;
36
+ /**
37
+ * Auto-generate ambient TypeScript declarations for @fluixi/start's virtual modules
38
+ * (`virtual:fluixi-server-fns`, `virtual:fluixi-i18n`) into `src/fluixi-start-env.d.ts`, the
39
+ * way the routes plugin writes `fluixi-env.d.ts`. So apps NEVER hand-write these `declare
40
+ * module` blocks — the modules AND their types are both generated. Idempotent (only writes on
41
+ * change), runs in dev + build.
42
+ */
43
+ export declare function startTypesPlugin(cfg: ResolvedConfig): any;
44
+ /**
45
+ * The fluixi build plugins @fluixi/start provides by default: file-based routing
46
+ * (fluixiRoutesPlugin → virtual:fluixi-routes) + the JSX/SSR transform
47
+ * (createVitePlugin). This is what makes start "sit on top of fluixi" — apps get
48
+ * zero-config routing + SSR. Apps using `fluixi dev|build` should therefore NOT add
49
+ * these to their own vite.config (start owns them); keep vite.config for app-specific
50
+ * bits only (optimizeDeps, ssr.noExternal via config, etc.).
51
+ */
52
+ export declare function fluixiPlugins(cfg: ResolvedConfig): Promise<any[]>;
53
+ /**
54
+ * Inject server-rendered app HTML into the template's mount element
55
+ * (`<div id="root"></div>`). Falls back to a `<!--ssr-outlet-->` marker, then to
56
+ * just before `</body>`.
57
+ */
58
+ export declare function injectApp(template: string, appHtml: string, mountId?: string): string;
59
+ /**
60
+ * Split the template at the mount point for streaming: `head` is everything up to and
61
+ * including the open mount tag (flushed first so the browser fetches assets while the
62
+ * server awaits data); `tail` is the close tag onward (client script + `</body>`).
63
+ * Mirrors injectApp's three cases (mount div, `<!--ssr-outlet-->`, before `</body>`).
64
+ */
65
+ export declare function splitTemplate(template: string, mountId?: string): {
66
+ head: string;
67
+ tail: string;
68
+ };
69
+ /**
70
+ * Inject the rendered app into the mount point AND lift any @fluixi/head metadata (carried back as
71
+ * a marker by renderRequestAsync) into <head> + <html>. If the page set a title, the template's own
72
+ * <title> is dropped so there's only one. No marker → identical to injectApp.
73
+ */
74
+ export declare function injectAppAndHead(template: string, rendered: string, mountId?: string): string;
75
+ /**
76
+ * Wrap a fetch handler so a thrown/rejected error becomes a 500 instead of an
77
+ * unhandled rejection. `createRequestHandler` already guards the renderer; this
78
+ * covers the middleware chain that wraps it. `onError` lets dev map the stack first.
79
+ */
80
+ export declare function guardHandler(handler: FetchHandler, onError?: (e: unknown) => void): FetchHandler;
81
+ /**
82
+ * A render fires the route's data fetches eagerly; if the backend is down those
83
+ * promises can reject AFTER we've already responded, with nothing awaiting them —
84
+ * a floating rejection would kill the dev server. Swallow + log instead.
85
+ */
86
+ export declare function installCrashGuards(): void;
87
+ //# sourceMappingURL=internal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,6FAA6F;AAC7F,eAAO,MAAM,eAAe,8BAA8B,CAAC;AAE3D,wGAAwG;AACxG,eAAO,MAAM,SAAS,wBAAwB,CAAC;AAE/C;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,GAAG,CAoCrG;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM7E;AA6DD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,GAAG,CA4BzD;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAoBvE;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,SAAS,GAAG,MAAM,CASrF;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAwBhG;AASD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,SAAS,GAAG,MAAM,CAW7F;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,YAAY,EACrB,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,GAC7B,YAAY,CAYd;AAID;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CASzC"}