@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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 FluxFast Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,76 @@
1
+ # @fluxfast/vite
2
+
3
+ Same-origin React SSR host and Vite tooling introduced in FluxFast 1.2. Match
4
+ Python, Core, Codegen, React and Vite package versions; see the
5
+ [release notes](https://github.com/El37628/FluxFast/blob/main/docs/releases/v1.2.0.md)
6
+ for installation and availability. Existing Next applications keep their adapter.
7
+
8
+ Vite owns compilation, lazy chunks and development HMR. The host serves actual
9
+ React SSR documents, browser assets and FluxFast protocol traffic on one public
10
+ origin. FastAPI remains private and owns application routes and resources.
11
+ Production imports a built Node renderer without loading Vite or source config.
12
+
13
+ After installing matching Core, Codegen, React and Vite packages and declaring
14
+ the React/React DOM/Vite peers in your frontend, initialize with the local binary:
15
+
16
+ ```sh
17
+ npm exec --no -- fluxfast-vite init --dry-run
18
+ npm exec --no -- fluxfast-vite init --yes
19
+ npm exec --no -- fluxfast-vite init --check
20
+ npm exec --no -- fluxfast-vite doctor
21
+ ```
22
+
23
+ This preserves your SPA entries, source Vite config, custom scripts and user
24
+ agent instructions. It adds a dedicated `fluxfast.vite.config.mjs`, separate SSR
25
+ template, starter page, generated React registry/agent knowledge, bounded
26
+ `AGENTS.md`/`CLAUDE.md` references, and scoped `fluxfast:dev`, `fluxfast:build`,
27
+ `fluxfast:start` scripts. No dependencies are downloaded or configuration executed
28
+ by setup/check commands. Export your authoritative backend schema, then use
29
+ `fluxfast-vite generate --schema-file PATH` for all six typed artifacts and
30
+ `generate --check` for read-only drift detection. Codegen is loaded only for
31
+ these tooling commands, not by the production host.
32
+
33
+ With the matching Python package, run the complete initialized app
34
+ from its backend project directory:
35
+
36
+ ```sh
37
+ fluxfast types backend.main:app --frontend frontend
38
+ fluxfast dev backend.main:app --frontend frontend
39
+ fluxfast build --app backend.main:app --frontend frontend
40
+ fluxfast doctor --production --app backend.main:app --frontend frontend --strict
41
+ fluxfast start backend.main:app --frontend frontend
42
+ ```
43
+
44
+ Python detects the declared `@fluxfast/vite` host and runs its scoped scripts,
45
+ not your existing SPA scripts. It supervises FastAPI privately and the public
46
+ Node host as one service; do not start a second FastAPI service manually.
47
+ Production consumes `dist/fluxfast/` and never builds/generates at startup.
48
+ Python 1.2+ selects this host; older 1.1 Python does not.
49
+
50
+ Alternatively configure the host manually:
51
+
52
+ ```ts
53
+ // vite.config.ts, after installing the matching packages
54
+ import { defineConfig } from "vite";
55
+ import { fluxfast } from "@fluxfast/vite";
56
+
57
+ export default defineConfig({ plugins: [fluxfast()] });
58
+ ```
59
+
60
+ The plugin defaults to `src/.fluxfast/pages.generated.ts` (`FluxApplication`) and
61
+ `fluxfast.html`. Use `fluxfast-vite dev`, `fluxfast-vite build`, and
62
+ `fluxfast-vite start`, not the SPA `vite`/`vite preview` commands.
63
+ The development server and HMR share the public port. Production serves only
64
+ allowlisted client build files and never exposes the SSR template or renderer.
65
+
66
+ Supported tooling: Node 22.12+ or 24, Vite `>=7.3.6 <8`, React/React DOM 19+.
67
+ The framework-neutral runtime does not depend on this host.
68
+ The shared browser gates run the same contracts as Next in development and
69
+ production, plus initialized packed consumers and three-worker Redis tests.
70
+ Cold hydration/navigation and automatic source synchronization use one public
71
+ origin; production also hydrates without source or build tooling. Publication
72
+ gates test the exact archives and then matching registry-only installations.
73
+
74
+ See the [Vite host guide](https://github.com/El37628/FluxFast/blob/main/docs/vite-host.md)
75
+ for template/configuration examples, installation, server APIs, output
76
+ ownership and production limitations.
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ if (process.argv[2] === "start" || process.argv[2] === "build") {
4
+ if (process.env.NODE_ENV !== undefined && process.env.NODE_ENV !== "production") {
5
+ console.error("fluxfast-vite build/start require NODE_ENV=production (or unset).");
6
+ process.exit(1);
7
+ }
8
+ process.env.NODE_ENV = "production";
9
+ }
10
+ const { runViteCli } = require("../dist/cli.js");
11
+ runViteCli(process.argv.slice(2)).then(code => { if (code) process.exitCode = code; }, () => { process.exitCode = 1; });
@@ -0,0 +1,6 @@
1
+ import { type FrontendProject } from "./project.js";
2
+ export declare const KNOWLEDGE_MARKER = "<!-- GENERATED BY FLUXFAST. Run `fluxfast-vite init` to refresh this file. -->";
3
+ /** Replace only the one bounded managed block; preserve surrounding text and CRLF. */
4
+ export declare function mergeAgentBlock(existing: string, knowledge: string): string;
5
+ export declare function renderKnowledge(project: FrontendProject): string;
6
+ //# sourceMappingURL=agent-knowledge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-knowledge.d.ts","sourceRoot":"","sources":["../src/agent-knowledge.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/E,eAAO,MAAM,gBAAgB,mFAAmF,CAAC;AAIjH,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAU3E;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAoIhE"}
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KNOWLEDGE_MARKER = void 0;
4
+ exports.mergeAgentBlock = mergeAgentBlock;
5
+ exports.renderKnowledge = renderKnowledge;
6
+ const project_js_1 = require("./project.js");
7
+ exports.KNOWLEDGE_MARKER = "<!-- GENERATED BY FLUXFAST. Run `fluxfast-vite init` to refresh this file. -->";
8
+ const START = "<!-- fluxfast-agent-knowledge:start -->";
9
+ const END = "<!-- fluxfast-agent-knowledge:end -->";
10
+ /** Replace only the one bounded managed block; preserve surrounding text and CRLF. */
11
+ function mergeAgentBlock(existing, knowledge) {
12
+ const newline = existing.includes("\r\n") ? "\r\n" : "\n";
13
+ const block = [START, "## FluxFast", "", "@" + knowledge, "",
14
+ `Read [the generated FluxFast knowledge](${knowledge}) before changing FluxFast application code or configuration.`, END].join(newline);
15
+ const start = existing.indexOf(START);
16
+ const end = existing.indexOf(END);
17
+ if ((start === -1) !== (end === -1) || end < start ||
18
+ start !== -1 && (existing.indexOf(START, start + 1) !== -1 || existing.indexOf(END, end + 1) !== -1))
19
+ throw new Error("Malformed or duplicate FluxFast agent blocks; repair the markers without deleting user instructions");
20
+ if (start === -1)
21
+ return existing + (existing ? (existing.endsWith("\n") ? newline : newline + newline) : "") + block + newline;
22
+ return existing.slice(0, start) + block + existing.slice(end + END.length);
23
+ }
24
+ function renderKnowledge(project) {
25
+ const pages = (0, project_js_1.relativeFile)(project, project.pages);
26
+ const generated = (0, project_js_1.relativeFile)(project, project.generated);
27
+ return `${exports.KNOWLEDGE_MARKER}
28
+
29
+ # FluxFast React/Vite agent knowledge
30
+
31
+ This is generated integration knowledge, not user instructions. Do not edit this
32
+ file; refresh it with the installed \`fluxfast-vite init\` command. Resolve exact
33
+ package versions from the lockfile, not framework or protocol version guesses.
34
+
35
+ ## Architecture and ownership
36
+
37
+ - FastAPI owns application URLs, authentication, authorization, input validation,
38
+ named resources, mutations, redirects and selected component identifiers.
39
+ - \`@fluxfast/core\` owns the framework-neutral stores, router, reconciliation,
40
+ deferred/live lifecycle and protocol validation. Never put framework imports in Core.
41
+ - \`@fluxfast/react\` provides hooks, registry rendering, SSR and exact-envelope
42
+ hydration. \`@fluxfast/vite\` provides compilation, assets and the Node host.
43
+ - The allowlist in \`${generated}/pages.generated.ts\` selects modules under
44
+ \`${pages}/\`. Never dynamically import arbitrary backend component strings.
45
+ - Python package, JavaScript packages, \`fluxfast/1\` and \`fluxfast-schema/2\`
46
+ are separate versioned contracts; do not infer a protocol version from a package.
47
+
48
+ ## Files and commands
49
+
50
+ The dedicated host config is \`${project_js_1.HOST_CONFIG}\`, extending an existing Vite
51
+ config when present. It is evaluated during development/build, never production
52
+ startup. \`fluxfast.html\` contains exactly one SSR marker inside
53
+ \`#fluxfast-root\` and one payload marker outside it. Preserve both.
54
+
55
+ Existing SPA entry files and scripts are user-owned. Use the scoped host scripts:
56
+
57
+ \`\`\`sh
58
+ npm run fluxfast:dev
59
+ npm run fluxfast:build
60
+ npm run fluxfast:start
61
+ npm exec --no -- fluxfast-vite generate
62
+ npm exec --no -- fluxfast-vite generate --check
63
+ npm exec --no -- fluxfast-vite init --check
64
+ npm exec --no -- fluxfast-vite doctor
65
+ \`\`\`
66
+
67
+ With matching Python and JavaScript packages, run the whole application from its
68
+ backend project directory. Python detects \`@fluxfast/vite\` and selects the
69
+ scoped scripts without changing your SPA scripts:
70
+
71
+ \`\`\`sh
72
+ fluxfast types backend.main:app --frontend frontend
73
+ fluxfast types backend.main:app --frontend frontend --check
74
+ fluxfast dev backend.main:app --frontend frontend
75
+ fluxfast build --app backend.main:app --frontend frontend
76
+ fluxfast doctor --production --app backend.main:app --frontend frontend --strict
77
+ fluxfast start backend.main:app --frontend frontend
78
+ \`\`\`
79
+
80
+ Development and production supervise FastAPI and the Node host behind one public
81
+ origin. Do not run a second FastAPI service alongside these supervised commands.
82
+ The frontend-only scripts above are for advanced, manually supervised hosts;
83
+ only that mode requires setting the private backend URL yourself.
84
+
85
+ Use the project's installed npm, pnpm, Yarn or Bun tooling; initialization never
86
+ downloads dependencies. Full-stack generation starts from the authoritative Python
87
+ contracts and the developer schema. Do not patch generated TypeScript to pass a build.
88
+ All six artifacts under \`${generated}/\` and this guide are generated.
89
+
90
+ ## Page declaration and input/output
91
+
92
+ \`\`\`python
93
+ from fastapi import FastAPI
94
+ from fluxfast import FluxFast, Page, resource, scope
95
+
96
+ app = FastAPI()
97
+ flux = FluxFast(app)
98
+ GREETING = flux.define_resource("greeting", str)
99
+
100
+ @flux.page("/", name="home")
101
+ async def home() -> Page:
102
+ return Page(component="home/index", resources=[
103
+ resource(GREETING, lambda: "Hello", scope=scope.public(), ttl=30),
104
+ ])
105
+ \`\`\`
106
+
107
+ \`\`\`tsx
108
+ import { useResource, Link } from "@fluxfast/react";
109
+
110
+ export default function Home() {
111
+ const greeting = useResource<string>("greeting");
112
+ return <main><h1>{greeting}</h1><Link href="/rooms">Rooms</Link></main>;
113
+ }
114
+ \`\`\`
115
+
116
+ The backend selects \`home/index\` and the canonical greeting. The matching
117
+ \`${pages}/home/index.tsx\` (or JSX) produces \`<h1>Hello</h1>\` in the initial
118
+ HTML. Hydration must reuse that exact envelope and opaque resource version,
119
+ not perform an immediate duplicate initial fetch or replace SSR with an empty SPA.
120
+
121
+ ## Resources, mutations and isolation
122
+
123
+ - Public scope is only for values identical for every caller. Protected caches
124
+ require \`scope.user(id)\`, \`scope.tenant(id)\`, request scope or no caching.
125
+ - Authorize every page, partial/deferred load, mutation and live subscription.
126
+ Consider logout, tenant changes and multiple FastAPI workers in every change.
127
+ - Keep canonical loaders and structured mutation patches/invalidation. Cancellation
128
+ does not imply that a server mutation rolled back.
129
+ - Use \`useDeferredResource\` for pending/error/retry UI and \`useLiveStatus\`
130
+ for connection state. Do not add a competing store or ad hoc SSE/fetch lifecycle.
131
+ - Redis coordinates shared caches and live brokers across workers; memory is local.
132
+ - Pydantic validation and authorization remain authoritative even with client validators.
133
+
134
+ ## Same-origin runtime and review
135
+
136
+ The browser sees one public host for documents, assets and protocol requests.
137
+ Only Node receives server-private \`FLUXFAST_BACKEND_URL\`; never put it in a
138
+ \`VITE_*\` variable, browser source or serialized page data. The incoming Host
139
+ and forwarded headers must not select the backend. Forward only bounded safe headers.
140
+ Production uses \`dist/fluxfast/\`, not source config or a Vite development server;
141
+ starting must never install, generate or build implicitly. Keep session cookies,
142
+ multiple Set-Cookie fields, streams and cancellation intact. Health probes are minimal.
143
+
144
+ For synchronization bugs, reproduce with development \`@fluxfast/devtools\`
145
+ and inspect Timeline/Resources/Cache/Mutations/Live/Protocol evidence. Diagnostics
146
+ must remain value-free and inert in production. Never log credentials, resource
147
+ values, request bodies or cache scope identities to compensate.
148
+
149
+ Before finishing: regenerate/check contracts, run relevant Python and frontend
150
+ typecheck/build/tests, inspect the browser graph for server/tooling imports, and
151
+ verify SSR, hydration, navigation, deferred/live cleanup and tenant isolation.
152
+ Keep FastAPI authoritative and fix the layer that owns the observed behavior.
153
+
154
+ References: https://el37628.github.io/FluxFast-Docs/ and the installed package README.
155
+ `;
156
+ }
157
+ //# sourceMappingURL=agent-knowledge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-knowledge.js","sourceRoot":"","sources":["../src/agent-knowledge.ts"],"names":[],"mappings":";;;;;AAAA,6CAA+E;AAElE,QAAA,gBAAgB,GAAG,gFAAgF,CAAC;AACjH,MAAM,KAAK,GAAG,yCAAyC,CAAC;AACxD,MAAM,GAAG,GAAG,uCAAuC,CAAC;AAEpD,sFAAsF;AACtF,yBAAgC,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,yBAAgC,OAAwB;IACtD,MAAM,KAAK,GAAG,IAAA,yBAAY,EAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IACnD,MAAM,SAAS,GAAG,IAAA,yBAAY,EAAC,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAC3D,OAAO,GAAG,QAAA,gBAAgB;;;;;;;;;;;;;;;;uBAgBL,SAAS;MAC1B,KAAK;;;;;;iCAMsB,wBAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BAsChB,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA6BjC,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCR,CAAC;AACF,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface BuiltHostManifest {
2
+ version: 1;
3
+ template: string;
4
+ assets: string[];
5
+ }
6
+ export declare function readHostManifest(value: unknown): BuiltHostManifest;
7
+ export declare function containedFile(root: string, name: string): Promise<string>;
8
+ export declare function createAssetHandler(root: string, names: readonly string[], templateName?: string): (request: Request) => Promise<Response | undefined>;
9
+ //# sourceMappingURL=assets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../src/assets.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,iBAAiB;IAAG,OAAO,EAAE,CAAC,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE;AAErF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,iBAAiB,CAQlE;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAO/E;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,YAAY,SAAkB,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAuB9J"}
package/dist/assets.js ADDED
@@ -0,0 +1,73 @@
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.readHostManifest = readHostManifest;
7
+ exports.containedFile = containedFile;
8
+ exports.createAssetHandler = createAssetHandler;
9
+ const promises_1 = __importDefault(require("node:fs/promises"));
10
+ const node_path_1 = __importDefault(require("node:path"));
11
+ const node_stream_1 = require("node:stream");
12
+ const node_fs_1 = require("node:fs");
13
+ const options_js_1 = require("./options.js");
14
+ const CONTENT_TYPES = {
15
+ ".js": "text/javascript; charset=utf-8", ".mjs": "text/javascript; charset=utf-8", ".css": "text/css; charset=utf-8",
16
+ ".json": "application/json; charset=utf-8", ".svg": "image/svg+xml", ".png": "image/png", ".jpg": "image/jpeg",
17
+ ".jpeg": "image/jpeg", ".webp": "image/webp", ".gif": "image/gif", ".ico": "image/x-icon", ".woff": "font/woff", ".woff2": "font/woff2",
18
+ };
19
+ function readHostManifest(value) {
20
+ if (!value || typeof value !== "object" || Array.isArray(value))
21
+ throw new Error("Invalid FluxFast production manifest");
22
+ const data = value;
23
+ if (data.version !== 1 || typeof data.template !== "string" || !(0, options_js_1.safeAssetName)(data.template.replace(/\.html?$/i, ".template")) ||
24
+ !/\.html?$/i.test(data.template) || !Array.isArray(data.assets) ||
25
+ data.assets.some(name => typeof name !== "string" || !(0, options_js_1.safeAssetName)(name)) ||
26
+ new Set(data.assets).size !== data.assets.length)
27
+ throw new Error("Invalid FluxFast production manifest");
28
+ return { version: 1, template: data.template, assets: data.assets };
29
+ }
30
+ async function containedFile(root, name) {
31
+ const realRoot = await promises_1.default.realpath(root);
32
+ const candidate = await promises_1.default.realpath(node_path_1.default.join(root, name));
33
+ const relative = node_path_1.default.relative(realRoot, candidate);
34
+ if (!relative || relative.startsWith(".." + node_path_1.default.sep) || relative === ".." || node_path_1.default.isAbsolute(relative) ||
35
+ !(await promises_1.default.stat(candidate)).isFile())
36
+ throw new Error("FluxFast output is not a contained regular file");
37
+ return candidate;
38
+ }
39
+ function createAssetHandler(root, names, templateName = "fluxfast.html") {
40
+ const assets = new Set(names);
41
+ return async (request) => {
42
+ const pathname = new URL(request.url).pathname;
43
+ let name;
44
+ try {
45
+ name = decodeURIComponent(pathname.slice(1));
46
+ }
47
+ catch {
48
+ return new Response(null, { status: 400 });
49
+ }
50
+ if (!assets.has(name)) {
51
+ // Reserved tooling/output paths and missing assets cannot become a SPA
52
+ // fallback or expose the raw SSR template, source or renderer.
53
+ if (name === templateName || /^\/(?:assets(?:\/|$)|@|src(?:\/|$)|node_modules(?:\/|$)|dist(?:\/|$)|\.)(?:.*)$/.test("/" + name)) {
54
+ return new Response(null, { status: 404, headers: { "cache-control": "no-store" } });
55
+ }
56
+ return;
57
+ }
58
+ if (request.method !== "GET" && request.method !== "HEAD")
59
+ return new Response(null, { status: 405, headers: { allow: "GET, HEAD" } });
60
+ try {
61
+ const file = await containedFile(root, name);
62
+ const headers = { "content-type": CONTENT_TYPES[node_path_1.default.extname(file).toLowerCase()] ?? "application/octet-stream", "cache-control": "public, max-age=0, must-revalidate", "x-content-type-options": "nosniff" };
63
+ if (request.method === "HEAD")
64
+ return new Response(null, { headers });
65
+ const stream = (0, node_fs_1.createReadStream)(file);
66
+ return new Response(node_stream_1.Readable.toWeb(stream), { headers });
67
+ }
68
+ catch {
69
+ return new Response(null, { status: 404, headers: { "cache-control": "no-store" } });
70
+ }
71
+ };
72
+ }
73
+ //# 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,6 @@
1
+ import type { IncomingMessage, ServerResponse } from "node:http";
2
+ /** Preserve raw path/query; neither Host nor forwarded headers select a target. */
3
+ export declare function webRequest(incoming: IncomingMessage, signal: AbortSignal): Request;
4
+ /** Unbuffered response bridge with cookie separation, backpressure, cancellation. */
5
+ export declare function writeWebResponse(response: Response, outgoing: ServerResponse, signal: AbortSignal): Promise<void>;
6
+ //# sourceMappingURL=bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAKjE,mFAAmF;AACnF,wBAAgB,UAAU,CAAC,QAAQ,EAAE,eAAe,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAiBlF;AAED,qFAAqF;AACrF,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBvH"}
package/dist/bridge.js ADDED
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.webRequest = webRequest;
4
+ exports.writeWebResponse = writeWebResponse;
5
+ const node_stream_1 = require("node:stream");
6
+ const node_events_1 = require("node:events");
7
+ const server_1 = require("@fluxfast/core/server");
8
+ /** Preserve raw path/query; neither Host nor forwarded headers select a target. */
9
+ function webRequest(incoming, signal) {
10
+ const raw = incoming.url ?? "/";
11
+ if (!raw.startsWith("/") || raw.startsWith("//") || /[\\\x00-\x1f\x7f]/.test(raw)) {
12
+ throw new TypeError("Invalid request path");
13
+ }
14
+ const headers = new Headers();
15
+ for (let index = 0; index < incoming.rawHeaders.length; index += 2) {
16
+ headers.append(incoming.rawHeaders[index], incoming.rawHeaders[index + 1]);
17
+ }
18
+ // Cookie uses '; ', not Fetch Headers' generic comma separator. Node already
19
+ // combines repeated Cookie fields correctly (including HTTP/2 compatibility).
20
+ if (typeof incoming.headers.cookie === "string")
21
+ headers.set("cookie", incoming.headers.cookie);
22
+ const method = incoming.method ?? "GET";
23
+ const body = method === "GET" || method === "HEAD" ? undefined : node_stream_1.Readable.toWeb(incoming);
24
+ return new Request("http://fluxfast.invalid" + raw, {
25
+ method, headers, signal, ...(body === undefined ? {} : { body, duplex: "half" }),
26
+ });
27
+ }
28
+ /** Unbuffered response bridge with cookie separation, backpressure, cancellation. */
29
+ async function writeWebResponse(response, outgoing, signal) {
30
+ const headers = (0, server_1.removeFluxHopByHopHeaders)(response.headers);
31
+ outgoing.statusCode = response.status;
32
+ for (const [name, value] of headers)
33
+ if (name !== "set-cookie")
34
+ outgoing.setHeader(name, value);
35
+ const cookies = headers.getSetCookie();
36
+ if (cookies.length)
37
+ outgoing.setHeader("set-cookie", cookies);
38
+ const reader = response.body?.getReader();
39
+ const cancel = () => { void reader?.cancel().catch(() => undefined); };
40
+ signal.addEventListener("abort", cancel, { once: true });
41
+ try {
42
+ if (signal.aborted) {
43
+ cancel();
44
+ return;
45
+ }
46
+ outgoing.flushHeaders();
47
+ if (reader) {
48
+ while (!signal.aborted) {
49
+ const { done, value } = await reader.read();
50
+ if (done)
51
+ break;
52
+ if (!outgoing.write(value))
53
+ await (0, node_events_1.once)(outgoing, "drain", { signal });
54
+ }
55
+ }
56
+ if (!signal.aborted)
57
+ outgoing.end();
58
+ }
59
+ finally {
60
+ signal.removeEventListener("abort", cancel);
61
+ if (signal.aborted)
62
+ cancel();
63
+ reader?.releaseLock();
64
+ }
65
+ }
66
+ //# sourceMappingURL=bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":";;;;AACA,6CAAuC;AACvC,6CAAmC;AACnC,kDAAkE;AAElE,mFAAmF;AACnF,oBAA2B,QAAyB,EAAE,MAAmB;IACvE,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,IAAI,GAAG,CAAC;IAChC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAClF,MAAM,IAAI,SAAS,CAAC,sBAAsB,CAAC,CAAC;IAC9C,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAC9B,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACnE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;IAC7E,CAAC;IACD,6EAA6E;IAC7E,8EAA8E;IAC9E,IAAI,OAAO,QAAQ,CAAC,OAAO,CAAC,MAAM,KAAK,QAAQ;QAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAChG,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,IAAI,KAAK,CAAC;IACxC,MAAM,IAAI,GAAG,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,sBAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC1F,OAAO,IAAI,OAAO,CAAC,yBAAyB,GAAG,GAAG,EAAE;QAClD,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;KAClE,CAAC,CAAC;AACpB,CAAC;AAED,qFAAqF;AAC9E,KAAK,2BAA2B,QAAkB,EAAE,QAAwB,EAAE,MAAmB;IACtG,MAAM,OAAO,GAAG,IAAA,kCAAyB,EAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC5D,QAAQ,CAAC,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC;IACtC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,OAAO;QAAE,IAAI,IAAI,KAAK,YAAY;YAAE,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAChG,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IACvC,IAAI,OAAO,CAAC,MAAM;QAAE,QAAQ,CAAC,SAAS,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAC9D,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC;IAC1C,MAAM,MAAM,GAAG,GAAG,EAAE,GAAG,KAAK,MAAM,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IACvE,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,IAAI,CAAC;QACH,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YAAC,MAAM,EAAE,CAAC;YAAC,OAAO;QAAC,CAAC;QACzC,QAAQ,CAAC,YAAY,EAAE,CAAC;QACxB,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACvB,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;gBAC5C,IAAI,IAAI;oBAAE,MAAM;gBAChB,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC;oBAAE,MAAM,IAAA,kBAAI,EAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YACxE,CAAC;QACH,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,QAAQ,CAAC,GAAG,EAAE,CAAC;IACtC,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC5C,IAAI,MAAM,CAAC,OAAO;YAAE,MAAM,EAAE,CAAC;QAC7B,MAAM,EAAE,WAAW,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { type FluxViteBuildOptions } from "./options.js";
2
+ /** Produce separate client assets and a Node renderer; never contact FastAPI. */
3
+ export declare function buildFluxViteApp(options?: FluxViteBuildOptions): Promise<void>;
4
+ //# sourceMappingURL=build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAEA,OAAO,EAAuE,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAE9H,iFAAiF;AACjF,wBAAsB,gBAAgB,CAAC,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CA+CxF"}
package/dist/build.js ADDED
@@ -0,0 +1,68 @@
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.buildFluxViteApp = buildFluxViteApp;
7
+ const promises_1 = __importDefault(require("node:fs/promises"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const options_js_1 = require("./options.js");
10
+ /** Produce separate client assets and a Node renderer; never contact FastAPI. */
11
+ async function buildFluxViteApp(options = {}) {
12
+ if (process.env.NODE_ENV !== undefined && process.env.NODE_ENV !== "production") {
13
+ throw new Error("FluxFast production builds require NODE_ENV=production (or unset)");
14
+ }
15
+ const vite = await import("vite");
16
+ const root = node_path_1.default.resolve(options.root ?? process.cwd());
17
+ const common = { root, ...(options.configFile === undefined ? {} : { configFile: options.configFile }), mode: "production" };
18
+ const config = await vite.resolveConfig(common, "build");
19
+ const flux = (0, options_js_1.configuredFluxOptions)(config);
20
+ const output = node_path_1.default.join(config.root, options_js_1.BUILD_DIRECTORY);
21
+ const templateSource = await promises_1.default.readFile(flux.template, "utf8");
22
+ for (const marker of ["<!--fluxfast:ssr-->", "<!--fluxfast:payload-->"]) {
23
+ if (templateSource.split(marker).length !== 2)
24
+ throw new Error("FluxFast template requires exactly one SSR and payload marker");
25
+ }
26
+ // Reject output symlinks before either build can clear a directory.
27
+ for (const name of ["dist", options_js_1.BUILD_DIRECTORY, options_js_1.BUILD_DIRECTORY + "/client", options_js_1.BUILD_DIRECTORY + "/server"]) {
28
+ try {
29
+ const stat = await promises_1.default.lstat(node_path_1.default.join(config.root, name));
30
+ if (!stat.isDirectory() || stat.isSymbolicLink())
31
+ throw new Error("FluxFast build output must use regular, non-symlinked directories");
32
+ }
33
+ catch (error) {
34
+ if (error.code !== "ENOENT")
35
+ throw error;
36
+ }
37
+ }
38
+ await promises_1.default.unlink(node_path_1.default.join(output, "host.json")).catch(error => { if (error.code !== "ENOENT")
39
+ throw error; });
40
+ // Fixed, owned leaf directories only. Never clear an arbitrary config outDir.
41
+ await vite.build({ ...common, build: {
42
+ outDir: node_path_1.default.join(output, "client"), emptyOutDir: true, sourcemap: false,
43
+ rollupOptions: { input: flux.template },
44
+ } });
45
+ await vite.build({ ...common, build: {
46
+ ssr: true, outDir: node_path_1.default.join(output, "server"), emptyOutDir: true,
47
+ sourcemap: false, copyPublicDir: false,
48
+ rollupOptions: { input: options_js_1.SERVER_ENTRY, output: { format: "es", entryFileNames: "renderer.mjs", chunkFileNames: "chunks/[name]-[hash].mjs" } },
49
+ } });
50
+ const client = node_path_1.default.join(output, "client");
51
+ const template = node_path_1.default.relative(config.root, flux.template).replace(/\\/g, "/");
52
+ // Vite emits the HTML at its relative input path. Record exactly what built,
53
+ // rather than evaluating configuration again during production startup.
54
+ await promises_1.default.access(node_path_1.default.join(client, template));
55
+ const assets = [];
56
+ async function scan(directory, prefix = "") {
57
+ for (const item of await promises_1.default.readdir(directory, { withFileTypes: true })) {
58
+ const name = prefix + item.name;
59
+ if (item.isDirectory() && !item.name.startsWith("."))
60
+ await scan(node_path_1.default.join(directory, item.name), name + "/");
61
+ else if (item.isFile() && (0, options_js_1.safeAssetName)(name))
62
+ assets.push(name);
63
+ }
64
+ }
65
+ await scan(client);
66
+ await promises_1.default.writeFile(node_path_1.default.join(output, "host.json"), JSON.stringify({ version: 1, template, assets: assets.sort() }) + "\n");
67
+ }
68
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ export interface ViteCliIo {
2
+ cwd: string;
3
+ stdout(message: string): void;
4
+ stderr(message: string): void;
5
+ }
6
+ export declare function runViteCli(args: string[], io?: ViteCliIo): Promise<number>;
7
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,SAAS;IAAG,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE;AA+CxG,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,GAAE,SAA8E,GAAG,OAAO,CAAC,MAAM,CAAC,CAsCpJ"}