@fluxfast/vite 0.0.0-oidc-bootstrap.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.
Files changed (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +76 -0
  3. package/bin/fluxfast-vite.js +11 -0
  4. package/dist/agent-knowledge.d.ts +6 -0
  5. package/dist/agent-knowledge.d.ts.map +1 -0
  6. package/dist/agent-knowledge.js +157 -0
  7. package/dist/agent-knowledge.js.map +1 -0
  8. package/dist/assets.d.ts +9 -0
  9. package/dist/assets.d.ts.map +1 -0
  10. package/dist/assets.js +73 -0
  11. package/dist/assets.js.map +1 -0
  12. package/dist/bridge.d.ts +6 -0
  13. package/dist/bridge.d.ts.map +1 -0
  14. package/dist/bridge.js +66 -0
  15. package/dist/bridge.js.map +1 -0
  16. package/dist/build.d.ts +4 -0
  17. package/dist/build.d.ts.map +1 -0
  18. package/dist/build.js +68 -0
  19. package/dist/build.js.map +1 -0
  20. package/dist/cli.d.ts +7 -0
  21. package/dist/cli.d.ts.map +1 -0
  22. package/dist/cli.js +141 -0
  23. package/dist/cli.js.map +1 -0
  24. package/dist/esm/agent-knowledge.js +152 -0
  25. package/dist/esm/agent-knowledge.js.map +1 -0
  26. package/dist/esm/assets.js +65 -0
  27. package/dist/esm/assets.js.map +1 -0
  28. package/dist/esm/bridge.js +62 -0
  29. package/dist/esm/bridge.js.map +1 -0
  30. package/dist/esm/build.js +62 -0
  31. package/dist/esm/build.js.map +1 -0
  32. package/dist/esm/cli.js +135 -0
  33. package/dist/esm/cli.js.map +1 -0
  34. package/dist/esm/generation.js +30 -0
  35. package/dist/esm/generation.js.map +1 -0
  36. package/dist/esm/health.js +55 -0
  37. package/dist/esm/health.js.map +1 -0
  38. package/dist/esm/index.js +3 -0
  39. package/dist/esm/index.js.map +1 -0
  40. package/dist/esm/options.js +58 -0
  41. package/dist/esm/options.js.map +1 -0
  42. package/dist/esm/package.json +3 -0
  43. package/dist/esm/plugin.js +46 -0
  44. package/dist/esm/plugin.js.map +1 -0
  45. package/dist/esm/project.js +88 -0
  46. package/dist/esm/project.js.map +1 -0
  47. package/dist/esm/server.js +206 -0
  48. package/dist/esm/server.js.map +1 -0
  49. package/dist/esm/setup.js +223 -0
  50. package/dist/esm/setup.js.map +1 -0
  51. package/dist/generation.d.ts +14 -0
  52. package/dist/generation.d.ts.map +1 -0
  53. package/dist/generation.js +38 -0
  54. package/dist/generation.js.map +1 -0
  55. package/dist/health.d.ts +4 -0
  56. package/dist/health.d.ts.map +1 -0
  57. package/dist/health.js +59 -0
  58. package/dist/health.js.map +1 -0
  59. package/dist/index.d.ts +4 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +8 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/options.d.ts +41 -0
  64. package/dist/options.d.ts.map +1 -0
  65. package/dist/options.js +67 -0
  66. package/dist/options.js.map +1 -0
  67. package/dist/plugin.d.ts +5 -0
  68. package/dist/plugin.d.ts.map +1 -0
  69. package/dist/plugin.js +49 -0
  70. package/dist/plugin.js.map +1 -0
  71. package/dist/project.d.ts +24 -0
  72. package/dist/project.d.ts.map +1 -0
  73. package/dist/project.js +99 -0
  74. package/dist/project.js.map +1 -0
  75. package/dist/server.d.ts +18 -0
  76. package/dist/server.d.ts.map +1 -0
  77. package/dist/server.js +212 -0
  78. package/dist/server.js.map +1 -0
  79. package/dist/setup.d.ts +18 -0
  80. package/dist/setup.d.ts.map +1 -0
  81. package/dist/setup.js +231 -0
  82. package/dist/setup.js.map +1 -0
  83. package/package.json +72 -0
package/dist/cli.js ADDED
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.runViteCli = runViteCli;
7
+ const build_js_1 = require("./build.js");
8
+ const server_js_1 = require("./server.js");
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const USAGE = `Usage:
11
+ fluxfast-vite init [--dry-run] [--yes] [--force]
12
+ fluxfast-vite init --check
13
+ fluxfast-vite generate [--check] [--schema-file PATH]
14
+ fluxfast-vite doctor
15
+ fluxfast-vite dev [--config PATH] [--hostname HOST] [--port PORT]
16
+ fluxfast-vite build [--config PATH]
17
+ fluxfast-vite start [--hostname HOST] [--port PORT]
18
+ Build and serve use the configured fluxfast() Vite plugin; start reads built artifacts only.`;
19
+ async function runSetup(command, args, io) {
20
+ const allowed = command === "init" ? ["--dry-run", "--yes", "--force", "--check"] : command === "generate" ? ["--check", "--schema-file"] : [];
21
+ const seen = new Set();
22
+ let schemaFile;
23
+ for (let index = 0; index < args.length; index++) {
24
+ const flag = args[index];
25
+ if (!allowed.includes(flag) || seen.has(flag)) {
26
+ io.stderr(USAGE);
27
+ return 2;
28
+ }
29
+ seen.add(flag);
30
+ if (flag === "--schema-file") {
31
+ schemaFile = args[++index];
32
+ if (!schemaFile || schemaFile.startsWith("--")) {
33
+ io.stderr(USAGE);
34
+ return 2;
35
+ }
36
+ }
37
+ }
38
+ if (command === "init" && seen.has("--check") && args.length !== 1) {
39
+ io.stderr(USAGE);
40
+ return 2;
41
+ }
42
+ try {
43
+ const { projectAt, relativeFile, validatePackages } = await import("./project.js");
44
+ const { planSetup, applySetup, checkSetup } = await import("./setup.js");
45
+ const { generateProject } = await import("./generation.js");
46
+ const project = projectAt(io.cwd);
47
+ validatePackages(project);
48
+ if (command === "generate") {
49
+ const result = generateProject(project, seen.has("--check"), schemaFile);
50
+ io.stdout(result.current ? (seen.has("--check") ? "Generated FluxFast files are current." : "Generated FluxFast registry/contracts.") : "Generated FluxFast files are missing or stale; rerun generation without --check.");
51
+ return result.current ? 0 : 1;
52
+ }
53
+ if (command === "doctor" || seen.has("--check")) {
54
+ const problems = [...checkSetup(project)];
55
+ if (!generateProject(project, true).current)
56
+ problems.push("Generated FluxFast files are missing or stale");
57
+ problems.forEach(problem => io.stderr(problem));
58
+ if (!problems.length)
59
+ io.stdout("FluxFast React/Vite setup and generated files are current. Production/runtime diagnostics remain separate.");
60
+ return problems.length ? 1 : 0;
61
+ }
62
+ const plan = planSetup(project, seen.has("--force"));
63
+ if (seen.has("--dry-run")) {
64
+ plan.changes.forEach(change => io.stdout("Would update " + relativeFile(project, change.file)));
65
+ io.stdout("Would generate the React registry/contracts. No files were changed.");
66
+ return 0;
67
+ }
68
+ applySetup(plan);
69
+ io.stdout("FluxFast React/Vite initialized. Existing SPA entries, configuration and scripts were preserved.");
70
+ io.stdout("Use npm run fluxfast:dev, fluxfast:build and fluxfast:start (or the project's package manager).");
71
+ return 0;
72
+ }
73
+ catch (error) {
74
+ io.stderr(error instanceof Error ? error.message : "FluxFast setup failed");
75
+ return 1;
76
+ }
77
+ }
78
+ async function runViteCli(args, io = { cwd: process.cwd(), stdout: console.log, stderr: console.error }) {
79
+ if (!args.length || args.length === 1 && ["--help", "-h"].includes(args[0])) {
80
+ io.stdout(USAGE);
81
+ return 0;
82
+ }
83
+ const [command, ...flags] = args;
84
+ if (["init", "generate", "doctor"].includes(command))
85
+ return runSetup(command, flags, io);
86
+ if (!["dev", "build", "start"].includes(command)) {
87
+ io.stderr(USAGE);
88
+ return 2;
89
+ }
90
+ let host = "127.0.0.1";
91
+ let port = 3000;
92
+ let configFile;
93
+ const seen = new Set();
94
+ for (let index = 0; index < flags.length; index += 1) {
95
+ const flag = flags[index];
96
+ const value = flags[++index];
97
+ const allowed = command === "build" ? ["--config"] : command === "start" ? ["--hostname", "--port"] : ["--config", "--hostname", "--port"];
98
+ if (!allowed.includes(flag) || seen.has(flag) || !value || value.startsWith("--")) {
99
+ io.stderr(USAGE);
100
+ return 2;
101
+ }
102
+ seen.add(flag);
103
+ if (flag === "--config")
104
+ configFile = node_path_1.default.resolve(io.cwd, value);
105
+ else if (flag === "--hostname")
106
+ host = value;
107
+ else if (/^\d+$/.test(value) && Number(value) >= 1 && Number(value) <= 65535)
108
+ port = Number(value);
109
+ else {
110
+ io.stderr(USAGE);
111
+ return 2;
112
+ }
113
+ }
114
+ try {
115
+ if (command === "build") {
116
+ await (0, build_js_1.buildFluxViteApp)({ root: io.cwd, configFile });
117
+ return 0;
118
+ }
119
+ const server = await (0, server_js_1.createFluxViteServer)({ root: io.cwd, configFile, mode: command === "start" ? "production" : "development", host, port });
120
+ io.stdout(`FluxFast ${command === "start" ? "production" : "development"} host listening on ${server.url}`);
121
+ let stopping = false;
122
+ const stop = () => {
123
+ if (stopping)
124
+ return;
125
+ stopping = true;
126
+ void server.close().then(() => {
127
+ process.removeListener("SIGINT", stop);
128
+ process.removeListener("SIGTERM", stop);
129
+ process.exitCode = 0;
130
+ }, () => { process.exitCode = 1; });
131
+ };
132
+ process.on("SIGINT", stop);
133
+ process.on("SIGTERM", stop);
134
+ return 0;
135
+ }
136
+ catch {
137
+ io.stderr("FluxFast host failed. Check the application, fluxfast() configuration, built artifacts, and private backend configuration.");
138
+ return 1;
139
+ }
140
+ }
141
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,152 @@
1
+ import { relativeFile, HOST_CONFIG } from "./project.js";
2
+ export const KNOWLEDGE_MARKER = "<!-- GENERATED BY FLUXFAST. Run `fluxfast-vite init` to refresh this file. -->";
3
+ const START = "<!-- fluxfast-agent-knowledge:start -->";
4
+ const END = "<!-- fluxfast-agent-knowledge:end -->";
5
+ /** Replace only the one bounded managed block; preserve surrounding text and CRLF. */
6
+ export function mergeAgentBlock(existing, knowledge) {
7
+ const newline = existing.includes("\r\n") ? "\r\n" : "\n";
8
+ const block = [START, "## FluxFast", "", "@" + knowledge, "",
9
+ `Read [the generated FluxFast knowledge](${knowledge}) before changing FluxFast application code or configuration.`, END].join(newline);
10
+ const start = existing.indexOf(START);
11
+ const end = existing.indexOf(END);
12
+ if ((start === -1) !== (end === -1) || end < start ||
13
+ start !== -1 && (existing.indexOf(START, start + 1) !== -1 || existing.indexOf(END, end + 1) !== -1))
14
+ throw new Error("Malformed or duplicate FluxFast agent blocks; repair the markers without deleting user instructions");
15
+ if (start === -1)
16
+ return existing + (existing ? (existing.endsWith("\n") ? newline : newline + newline) : "") + block + newline;
17
+ return existing.slice(0, start) + block + existing.slice(end + END.length);
18
+ }
19
+ export function renderKnowledge(project) {
20
+ const pages = relativeFile(project, project.pages);
21
+ const generated = relativeFile(project, project.generated);
22
+ return `${KNOWLEDGE_MARKER}
23
+
24
+ # FluxFast React/Vite agent knowledge
25
+
26
+ This is generated integration knowledge, not user instructions. Do not edit this
27
+ file; refresh it with the installed \`fluxfast-vite init\` command. Resolve exact
28
+ package versions from the lockfile, not framework or protocol version guesses.
29
+
30
+ ## Architecture and ownership
31
+
32
+ - FastAPI owns application URLs, authentication, authorization, input validation,
33
+ named resources, mutations, redirects and selected component identifiers.
34
+ - \`@fluxfast/core\` owns the framework-neutral stores, router, reconciliation,
35
+ deferred/live lifecycle and protocol validation. Never put framework imports in Core.
36
+ - \`@fluxfast/react\` provides hooks, registry rendering, SSR and exact-envelope
37
+ hydration. \`@fluxfast/vite\` provides compilation, assets and the Node host.
38
+ - The allowlist in \`${generated}/pages.generated.ts\` selects modules under
39
+ \`${pages}/\`. Never dynamically import arbitrary backend component strings.
40
+ - Python package, JavaScript packages, \`fluxfast/1\` and \`fluxfast-schema/2\`
41
+ are separate versioned contracts; do not infer a protocol version from a package.
42
+
43
+ ## Files and commands
44
+
45
+ The dedicated host config is \`${HOST_CONFIG}\`, extending an existing Vite
46
+ config when present. It is evaluated during development/build, never production
47
+ startup. \`fluxfast.html\` contains exactly one SSR marker inside
48
+ \`#fluxfast-root\` and one payload marker outside it. Preserve both.
49
+
50
+ Existing SPA entry files and scripts are user-owned. Use the scoped host scripts:
51
+
52
+ \`\`\`sh
53
+ npm run fluxfast:dev
54
+ npm run fluxfast:build
55
+ npm run fluxfast:start
56
+ npm exec --no -- fluxfast-vite generate
57
+ npm exec --no -- fluxfast-vite generate --check
58
+ npm exec --no -- fluxfast-vite init --check
59
+ npm exec --no -- fluxfast-vite doctor
60
+ \`\`\`
61
+
62
+ With matching Python and JavaScript packages, run the whole application from its
63
+ backend project directory. Python detects \`@fluxfast/vite\` and selects the
64
+ scoped scripts without changing your SPA scripts:
65
+
66
+ \`\`\`sh
67
+ fluxfast types backend.main:app --frontend frontend
68
+ fluxfast types backend.main:app --frontend frontend --check
69
+ fluxfast dev backend.main:app --frontend frontend
70
+ fluxfast build --app backend.main:app --frontend frontend
71
+ fluxfast doctor --production --app backend.main:app --frontend frontend --strict
72
+ fluxfast start backend.main:app --frontend frontend
73
+ \`\`\`
74
+
75
+ Development and production supervise FastAPI and the Node host behind one public
76
+ origin. Do not run a second FastAPI service alongside these supervised commands.
77
+ The frontend-only scripts above are for advanced, manually supervised hosts;
78
+ only that mode requires setting the private backend URL yourself.
79
+
80
+ Use the project's installed npm, pnpm, Yarn or Bun tooling; initialization never
81
+ downloads dependencies. Full-stack generation starts from the authoritative Python
82
+ contracts and the developer schema. Do not patch generated TypeScript to pass a build.
83
+ All six artifacts under \`${generated}/\` and this guide are generated.
84
+
85
+ ## Page declaration and input/output
86
+
87
+ \`\`\`python
88
+ from fastapi import FastAPI
89
+ from fluxfast import FluxFast, Page, resource, scope
90
+
91
+ app = FastAPI()
92
+ flux = FluxFast(app)
93
+ GREETING = flux.define_resource("greeting", str)
94
+
95
+ @flux.page("/", name="home")
96
+ async def home() -> Page:
97
+ return Page(component="home/index", resources=[
98
+ resource(GREETING, lambda: "Hello", scope=scope.public(), ttl=30),
99
+ ])
100
+ \`\`\`
101
+
102
+ \`\`\`tsx
103
+ import { useResource, Link } from "@fluxfast/react";
104
+
105
+ export default function Home() {
106
+ const greeting = useResource<string>("greeting");
107
+ return <main><h1>{greeting}</h1><Link href="/rooms">Rooms</Link></main>;
108
+ }
109
+ \`\`\`
110
+
111
+ The backend selects \`home/index\` and the canonical greeting. The matching
112
+ \`${pages}/home/index.tsx\` (or JSX) produces \`<h1>Hello</h1>\` in the initial
113
+ HTML. Hydration must reuse that exact envelope and opaque resource version,
114
+ not perform an immediate duplicate initial fetch or replace SSR with an empty SPA.
115
+
116
+ ## Resources, mutations and isolation
117
+
118
+ - Public scope is only for values identical for every caller. Protected caches
119
+ require \`scope.user(id)\`, \`scope.tenant(id)\`, request scope or no caching.
120
+ - Authorize every page, partial/deferred load, mutation and live subscription.
121
+ Consider logout, tenant changes and multiple FastAPI workers in every change.
122
+ - Keep canonical loaders and structured mutation patches/invalidation. Cancellation
123
+ does not imply that a server mutation rolled back.
124
+ - Use \`useDeferredResource\` for pending/error/retry UI and \`useLiveStatus\`
125
+ for connection state. Do not add a competing store or ad hoc SSE/fetch lifecycle.
126
+ - Redis coordinates shared caches and live brokers across workers; memory is local.
127
+ - Pydantic validation and authorization remain authoritative even with client validators.
128
+
129
+ ## Same-origin runtime and review
130
+
131
+ The browser sees one public host for documents, assets and protocol requests.
132
+ Only Node receives server-private \`FLUXFAST_BACKEND_URL\`; never put it in a
133
+ \`VITE_*\` variable, browser source or serialized page data. The incoming Host
134
+ and forwarded headers must not select the backend. Forward only bounded safe headers.
135
+ Production uses \`dist/fluxfast/\`, not source config or a Vite development server;
136
+ starting must never install, generate or build implicitly. Keep session cookies,
137
+ multiple Set-Cookie fields, streams and cancellation intact. Health probes are minimal.
138
+
139
+ For synchronization bugs, reproduce with development \`@fluxfast/devtools\`
140
+ and inspect Timeline/Resources/Cache/Mutations/Live/Protocol evidence. Diagnostics
141
+ must remain value-free and inert in production. Never log credentials, resource
142
+ values, request bodies or cache scope identities to compensate.
143
+
144
+ Before finishing: regenerate/check contracts, run relevant Python and frontend
145
+ typecheck/build/tests, inspect the browser graph for server/tooling imports, and
146
+ verify SSR, hydration, navigation, deferred/live cleanup and tenant isolation.
147
+ Keep FastAPI authoritative and fix the layer that owns the observed behavior.
148
+
149
+ References: https://el37628.github.io/FluxFast-Docs/ and the installed package README.
150
+ `;
151
+ }
152
+ //# sourceMappingURL=agent-knowledge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-knowledge.js","sourceRoot":"","sources":["../../src/agent-knowledge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAwB,MAAM,cAAc,CAAC;AAE/E,MAAM,CAAC,MAAM,gBAAgB,GAAG,gFAAgF,CAAC;AACjH,MAAM,KAAK,GAAG,yCAAyC,CAAC;AACxD,MAAM,GAAG,GAAG,uCAAuC,CAAC;AAEpD,sFAAsF;AACtF,MAAM,UAAU,eAAe,CAAC,QAAgB,EAAE,SAAiB;IACjE,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1D,MAAM,KAAK,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,EAAE,GAAG,GAAG,SAAS,EAAE,EAAE;QAC1D,2CAA2C,SAAS,+DAA+D,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC1I,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACtC,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,KAAK;QAC9C,KAAK,KAAK,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,qGAAqG,CAAC,CAAC;IACjO,IAAI,KAAK,KAAK,CAAC,CAAC;QAAE,OAAO,QAAQ,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,GAAG,OAAO,CAAC;IAChI,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;AAC7E,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAwB;IACtD,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IACnD,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAC3D,OAAO,GAAG,gBAAgB;;;;;;;;;;;;;;;;uBAgBL,SAAS;MAC1B,KAAK;;;;;;iCAMsB,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BAsChB,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA6BjC,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCR,CAAC;AACF,CAAC"}
@@ -0,0 +1,65 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { Readable } from "node:stream";
4
+ import { createReadStream } from "node:fs";
5
+ import { safeAssetName } from "./options.js";
6
+ const CONTENT_TYPES = {
7
+ ".js": "text/javascript; charset=utf-8", ".mjs": "text/javascript; charset=utf-8", ".css": "text/css; charset=utf-8",
8
+ ".json": "application/json; charset=utf-8", ".svg": "image/svg+xml", ".png": "image/png", ".jpg": "image/jpeg",
9
+ ".jpeg": "image/jpeg", ".webp": "image/webp", ".gif": "image/gif", ".ico": "image/x-icon", ".woff": "font/woff", ".woff2": "font/woff2",
10
+ };
11
+ export function readHostManifest(value) {
12
+ if (!value || typeof value !== "object" || Array.isArray(value))
13
+ throw new Error("Invalid FluxFast production manifest");
14
+ const data = value;
15
+ if (data.version !== 1 || typeof data.template !== "string" || !safeAssetName(data.template.replace(/\.html?$/i, ".template")) ||
16
+ !/\.html?$/i.test(data.template) || !Array.isArray(data.assets) ||
17
+ data.assets.some(name => typeof name !== "string" || !safeAssetName(name)) ||
18
+ new Set(data.assets).size !== data.assets.length)
19
+ throw new Error("Invalid FluxFast production manifest");
20
+ return { version: 1, template: data.template, assets: data.assets };
21
+ }
22
+ export async function containedFile(root, name) {
23
+ const realRoot = await fs.realpath(root);
24
+ const candidate = await fs.realpath(path.join(root, name));
25
+ const relative = path.relative(realRoot, candidate);
26
+ if (!relative || relative.startsWith(".." + path.sep) || relative === ".." || path.isAbsolute(relative) ||
27
+ !(await fs.stat(candidate)).isFile())
28
+ throw new Error("FluxFast output is not a contained regular file");
29
+ return candidate;
30
+ }
31
+ export function createAssetHandler(root, names, templateName = "fluxfast.html") {
32
+ const assets = new Set(names);
33
+ return async (request) => {
34
+ const pathname = new URL(request.url).pathname;
35
+ let name;
36
+ try {
37
+ name = decodeURIComponent(pathname.slice(1));
38
+ }
39
+ catch {
40
+ return new Response(null, { status: 400 });
41
+ }
42
+ if (!assets.has(name)) {
43
+ // Reserved tooling/output paths and missing assets cannot become a SPA
44
+ // fallback or expose the raw SSR template, source or renderer.
45
+ if (name === templateName || /^\/(?:assets(?:\/|$)|@|src(?:\/|$)|node_modules(?:\/|$)|dist(?:\/|$)|\.)(?:.*)$/.test("/" + name)) {
46
+ return new Response(null, { status: 404, headers: { "cache-control": "no-store" } });
47
+ }
48
+ return;
49
+ }
50
+ if (request.method !== "GET" && request.method !== "HEAD")
51
+ return new Response(null, { status: 405, headers: { allow: "GET, HEAD" } });
52
+ try {
53
+ const file = await containedFile(root, name);
54
+ const headers = { "content-type": CONTENT_TYPES[path.extname(file).toLowerCase()] ?? "application/octet-stream", "cache-control": "public, max-age=0, must-revalidate", "x-content-type-options": "nosniff" };
55
+ if (request.method === "HEAD")
56
+ return new Response(null, { headers });
57
+ const stream = createReadStream(file);
58
+ return new Response(Readable.toWeb(stream), { headers });
59
+ }
60
+ catch {
61
+ return new Response(null, { status: 404, headers: { "cache-control": "no-store" } });
62
+ }
63
+ };
64
+ }
65
+ //# sourceMappingURL=assets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets.js","sourceRoot":"","sources":["../../src/assets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ import { Readable } from "node:stream";
2
+ import { once } from "node:events";
3
+ import { removeFluxHopByHopHeaders } from "@fluxfast/core/server";
4
+ /** Preserve raw path/query; neither Host nor forwarded headers select a target. */
5
+ export function webRequest(incoming, signal) {
6
+ const raw = incoming.url ?? "/";
7
+ if (!raw.startsWith("/") || raw.startsWith("//") || /[\\\x00-\x1f\x7f]/.test(raw)) {
8
+ throw new TypeError("Invalid request path");
9
+ }
10
+ const headers = new Headers();
11
+ for (let index = 0; index < incoming.rawHeaders.length; index += 2) {
12
+ headers.append(incoming.rawHeaders[index], incoming.rawHeaders[index + 1]);
13
+ }
14
+ // Cookie uses '; ', not Fetch Headers' generic comma separator. Node already
15
+ // combines repeated Cookie fields correctly (including HTTP/2 compatibility).
16
+ if (typeof incoming.headers.cookie === "string")
17
+ headers.set("cookie", incoming.headers.cookie);
18
+ const method = incoming.method ?? "GET";
19
+ const body = method === "GET" || method === "HEAD" ? undefined : Readable.toWeb(incoming);
20
+ return new Request("http://fluxfast.invalid" + raw, {
21
+ method, headers, signal, ...(body === undefined ? {} : { body, duplex: "half" }),
22
+ });
23
+ }
24
+ /** Unbuffered response bridge with cookie separation, backpressure, cancellation. */
25
+ export async function writeWebResponse(response, outgoing, signal) {
26
+ const headers = removeFluxHopByHopHeaders(response.headers);
27
+ outgoing.statusCode = response.status;
28
+ for (const [name, value] of headers)
29
+ if (name !== "set-cookie")
30
+ outgoing.setHeader(name, value);
31
+ const cookies = headers.getSetCookie();
32
+ if (cookies.length)
33
+ outgoing.setHeader("set-cookie", cookies);
34
+ const reader = response.body?.getReader();
35
+ const cancel = () => { void reader?.cancel().catch(() => undefined); };
36
+ signal.addEventListener("abort", cancel, { once: true });
37
+ try {
38
+ if (signal.aborted) {
39
+ cancel();
40
+ return;
41
+ }
42
+ outgoing.flushHeaders();
43
+ if (reader) {
44
+ while (!signal.aborted) {
45
+ const { done, value } = await reader.read();
46
+ if (done)
47
+ break;
48
+ if (!outgoing.write(value))
49
+ await once(outgoing, "drain", { signal });
50
+ }
51
+ }
52
+ if (!signal.aborted)
53
+ outgoing.end();
54
+ }
55
+ finally {
56
+ signal.removeEventListener("abort", cancel);
57
+ if (signal.aborted)
58
+ cancel();
59
+ reader?.releaseLock();
60
+ }
61
+ }
62
+ //# sourceMappingURL=bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../src/bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { BUILD_DIRECTORY, SERVER_ENTRY, configuredFluxOptions, safeAssetName } from "./options.js";
4
+ /** Produce separate client assets and a Node renderer; never contact FastAPI. */
5
+ export async function buildFluxViteApp(options = {}) {
6
+ if (process.env.NODE_ENV !== undefined && process.env.NODE_ENV !== "production") {
7
+ throw new Error("FluxFast production builds require NODE_ENV=production (or unset)");
8
+ }
9
+ const vite = await import("vite");
10
+ const root = path.resolve(options.root ?? process.cwd());
11
+ const common = { root, ...(options.configFile === undefined ? {} : { configFile: options.configFile }), mode: "production" };
12
+ const config = await vite.resolveConfig(common, "build");
13
+ const flux = configuredFluxOptions(config);
14
+ const output = path.join(config.root, BUILD_DIRECTORY);
15
+ const templateSource = await fs.readFile(flux.template, "utf8");
16
+ for (const marker of ["<!--fluxfast:ssr-->", "<!--fluxfast:payload-->"]) {
17
+ if (templateSource.split(marker).length !== 2)
18
+ throw new Error("FluxFast template requires exactly one SSR and payload marker");
19
+ }
20
+ // Reject output symlinks before either build can clear a directory.
21
+ for (const name of ["dist", BUILD_DIRECTORY, BUILD_DIRECTORY + "/client", BUILD_DIRECTORY + "/server"]) {
22
+ try {
23
+ const stat = await fs.lstat(path.join(config.root, name));
24
+ if (!stat.isDirectory() || stat.isSymbolicLink())
25
+ throw new Error("FluxFast build output must use regular, non-symlinked directories");
26
+ }
27
+ catch (error) {
28
+ if (error.code !== "ENOENT")
29
+ throw error;
30
+ }
31
+ }
32
+ await fs.unlink(path.join(output, "host.json")).catch(error => { if (error.code !== "ENOENT")
33
+ throw error; });
34
+ // Fixed, owned leaf directories only. Never clear an arbitrary config outDir.
35
+ await vite.build({ ...common, build: {
36
+ outDir: path.join(output, "client"), emptyOutDir: true, sourcemap: false,
37
+ rollupOptions: { input: flux.template },
38
+ } });
39
+ await vite.build({ ...common, build: {
40
+ ssr: true, outDir: path.join(output, "server"), emptyOutDir: true,
41
+ sourcemap: false, copyPublicDir: false,
42
+ rollupOptions: { input: SERVER_ENTRY, output: { format: "es", entryFileNames: "renderer.mjs", chunkFileNames: "chunks/[name]-[hash].mjs" } },
43
+ } });
44
+ const client = path.join(output, "client");
45
+ const template = path.relative(config.root, flux.template).replace(/\\/g, "/");
46
+ // Vite emits the HTML at its relative input path. Record exactly what built,
47
+ // rather than evaluating configuration again during production startup.
48
+ await fs.access(path.join(client, template));
49
+ const assets = [];
50
+ async function scan(directory, prefix = "") {
51
+ for (const item of await fs.readdir(directory, { withFileTypes: true })) {
52
+ const name = prefix + item.name;
53
+ if (item.isDirectory() && !item.name.startsWith("."))
54
+ await scan(path.join(directory, item.name), name + "/");
55
+ else if (item.isFile() && safeAssetName(name))
56
+ assets.push(name);
57
+ }
58
+ }
59
+ await scan(client);
60
+ await fs.writeFile(path.join(output, "host.json"), JSON.stringify({ version: 1, template, assets: assets.sort() }) + "\n");
61
+ }
62
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/build.ts"],"names":[],"mappings":"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"}