@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.
- package/LICENSE +21 -0
- package/README.md +76 -0
- package/bin/fluxfast-vite.js +11 -0
- package/dist/agent-knowledge.d.ts +6 -0
- package/dist/agent-knowledge.d.ts.map +1 -0
- package/dist/agent-knowledge.js +157 -0
- package/dist/agent-knowledge.js.map +1 -0
- package/dist/assets.d.ts +9 -0
- package/dist/assets.d.ts.map +1 -0
- package/dist/assets.js +73 -0
- package/dist/assets.js.map +1 -0
- package/dist/bridge.d.ts +6 -0
- package/dist/bridge.d.ts.map +1 -0
- package/dist/bridge.js +66 -0
- package/dist/bridge.js.map +1 -0
- package/dist/build.d.ts +4 -0
- package/dist/build.d.ts.map +1 -0
- package/dist/build.js +68 -0
- package/dist/build.js.map +1 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +141 -0
- package/dist/cli.js.map +1 -0
- package/dist/esm/agent-knowledge.js +152 -0
- package/dist/esm/agent-knowledge.js.map +1 -0
- package/dist/esm/assets.js +65 -0
- package/dist/esm/assets.js.map +1 -0
- package/dist/esm/bridge.js +62 -0
- package/dist/esm/bridge.js.map +1 -0
- package/dist/esm/build.js +62 -0
- package/dist/esm/build.js.map +1 -0
- package/dist/esm/cli.js +135 -0
- package/dist/esm/cli.js.map +1 -0
- package/dist/esm/generation.js +30 -0
- package/dist/esm/generation.js.map +1 -0
- package/dist/esm/health.js +55 -0
- package/dist/esm/health.js.map +1 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/options.js +58 -0
- package/dist/esm/options.js.map +1 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/plugin.js +46 -0
- package/dist/esm/plugin.js.map +1 -0
- package/dist/esm/project.js +88 -0
- package/dist/esm/project.js.map +1 -0
- package/dist/esm/server.js +206 -0
- package/dist/esm/server.js.map +1 -0
- package/dist/esm/setup.js +223 -0
- package/dist/esm/setup.js.map +1 -0
- package/dist/generation.d.ts +14 -0
- package/dist/generation.d.ts.map +1 -0
- package/dist/generation.js +38 -0
- package/dist/generation.js.map +1 -0
- package/dist/health.d.ts +4 -0
- package/dist/health.d.ts.map +1 -0
- package/dist/health.js +59 -0
- package/dist/health.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/options.d.ts +41 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +67 -0
- package/dist/options.js.map +1 -0
- package/dist/plugin.d.ts +5 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +49 -0
- package/dist/plugin.js.map +1 -0
- package/dist/project.d.ts +24 -0
- package/dist/project.d.ts.map +1 -0
- package/dist/project.js +99 -0
- package/dist/project.js.map +1 -0
- package/dist/server.d.ts +18 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +212 -0
- package/dist/server.js.map +1 -0
- package/dist/setup.d.ts +18 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +231 -0
- package/dist/setup.js.map +1 -0
- 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
|
package/dist/cli.js.map
ADDED
|
@@ -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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"}
|