@janit/fu 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,87 @@
1
+ /** One client asset the HTML shell should reference. */
2
+ export interface Asset {
3
+ href: string;
4
+ }
5
+ /** Client assets for a page, as produced by a driver. */
6
+ export interface Assets {
7
+ js: Asset[];
8
+ css: Asset[];
9
+ }
10
+ /**
11
+ * Document metadata the shell renders into `<head>`.
12
+ *
13
+ * Middleware and route handlers both write here; it is deliberately separate
14
+ * from user `state` so the shell's contract stays explicit and typing an app's
15
+ * own state does not mean re-declaring these.
16
+ */
17
+ export interface Head {
18
+ title?: string;
19
+ description?: string;
20
+ canonical?: string;
21
+ /** `<meta name="robots">` content, e.g. "noindex, nofollow". */
22
+ robots?: string;
23
+ /** og:image URL. */
24
+ image?: string;
25
+ /** `<html lang>`; defaults to "en". */
26
+ lang?: string;
27
+ /** Raw `<link>` descriptors, e.g. hreflang alternates or preloads. */
28
+ links?: Record<string, string>[];
29
+ /** Serialized as a JSON-LD script tag when present. */
30
+ jsonLd?: unknown;
31
+ }
32
+ /** A request that failed, normalised for the error page. */
33
+ export interface RouteError {
34
+ status: number;
35
+ /** Safe to render. For a 500 this is generic, never the underlying message. */
36
+ message: string;
37
+ /** What was actually thrown. Log it; do not render it. */
38
+ cause?: unknown;
39
+ }
40
+ /** Request context handed to middleware, handlers and page components. */
41
+ export interface Ctx<S = Record<string, unknown>> {
42
+ req: Request;
43
+ url: URL;
44
+ /** Route params. Empty until routing has run, so middleware sees `{}`. */
45
+ params: Record<string, string>;
46
+ /** Whatever the app puts here. Shared across middleware, handler and page. */
47
+ state: S;
48
+ /** Document metadata for the shell. */
49
+ head: Head;
50
+ /** Value returned by the route's matching handler, if any. */
51
+ data?: unknown;
52
+ /** Set only when rendering the error page. */
53
+ error?: RouteError;
54
+ /** Run the rest of the chain. Returns the Response for outer middleware. */
55
+ next(): Promise<Response>;
56
+ }
57
+ /**
58
+ * A middleware. Return a Response to short-circuit, or `ctx.next()` to
59
+ * continue — optionally awaiting it first to inspect or mutate the result.
60
+ * Registration order is outermost first, so the first registered unwinds last.
61
+ */
62
+ export type Middleware<S = Record<string, unknown>> = (ctx: Ctx<S>) => Response | Promise<Response>;
63
+ /** What a page component receives. */
64
+ export type PageContext<S = Record<string, unknown>> = Ctx<S>;
65
+ /** A route handler: return a Response to short-circuit, or data for the page. */
66
+ export type RouteHandler<S = Record<string, unknown>> = (ctx: Ctx<S>) => unknown | Promise<unknown>;
67
+ /** A user-authored route module. */
68
+ export interface RouteModule<S = Record<string, unknown>> {
69
+ default?: (ctx: Ctx<S>) => unknown;
70
+ handlers?: Record<string, RouteHandler<S>>;
71
+ }
72
+ /**
73
+ * Lazy map of route file path to module loader — the only shape the core needs
74
+ * from a driver. Keys are root-relative, e.g. "/routes/blog/[slug].tsx".
75
+ */
76
+ export type RouteManifest<S = Record<string, unknown>> = Record<string, () => Promise<RouteModule<S>>>;
77
+ /** Options shared by the dev and build drivers. */
78
+ export interface FuOptions {
79
+ /** Project root containing `routes/` and `islands/`. */
80
+ root: string;
81
+ /** Dev server port. Defaults to 1337. */
82
+ port?: number;
83
+ /** Dev server bind address. Defaults to 0.0.0.0 (all interfaces). */
84
+ hostname?: string;
85
+ /** Build output directory. Defaults to `<root>/.output`. */
86
+ outDir?: string;
87
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,98 @@
1
+ {
2
+ "name": "@janit/fu",
3
+ "version": "0.0.2",
4
+ "type": "module",
5
+ "description": "A minimal islands framework on Preact 11, rolldown and Nitro. Runs on Deno, Node and Bun.",
6
+ "license": "MIT",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/mod.d.ts",
10
+ "default": "./dist/mod.js"
11
+ },
12
+ "./build": {
13
+ "types": "./dist/build.d.ts",
14
+ "default": "./dist/build.js"
15
+ },
16
+ "./dev": {
17
+ "types": "./dist/dev.d.ts",
18
+ "default": "./dist/dev.js"
19
+ },
20
+ "./client": {
21
+ "types": "./dist/client.d.ts",
22
+ "default": "./dist/client.js"
23
+ },
24
+ "./render": {
25
+ "types": "./dist/render.d.ts",
26
+ "default": "./dist/render.js"
27
+ },
28
+ "./router": {
29
+ "types": "./dist/router.d.ts",
30
+ "default": "./dist/router.js"
31
+ },
32
+ "./plugins": {
33
+ "types": "./dist/plugins.d.ts",
34
+ "default": "./dist/plugins.js"
35
+ },
36
+ "./errors": {
37
+ "types": "./dist/errors.d.ts",
38
+ "default": "./dist/errors.js"
39
+ },
40
+ "./cli": {
41
+ "types": "./dist/cli.d.ts",
42
+ "default": "./dist/cli.js"
43
+ },
44
+ "./package.json": "./package.json"
45
+ },
46
+ "bin": {
47
+ "fu": "./src/cli.ts"
48
+ },
49
+ "dependencies": {
50
+ "crossws": "^0.4.12",
51
+ "lightningcss": "^1.33.0",
52
+ "nitro": "^3.0.260903-beta",
53
+ "preact-render-to-string": "^6.7.0",
54
+ "rolldown": "^1.2.7",
55
+ "urlpattern-polyfill": "^10.1.0"
56
+ },
57
+ "peerDependencies": {
58
+ "@preact/signals": "^2",
59
+ "preact": "^11.0.0-rc.1"
60
+ },
61
+ "devDependencies": {
62
+ "@preact/signals": "^2.11.2",
63
+ "@types/node": "^26.4.1",
64
+ "preact": "11.0.0-rc.1",
65
+ "typescript": "^7.0.2"
66
+ },
67
+ "engines": {
68
+ "node": ">=22"
69
+ },
70
+ "files": [
71
+ "dist",
72
+ "README.md",
73
+ "LICENSE"
74
+ ],
75
+ "types": "./dist/mod.d.ts",
76
+ "repository": {
77
+ "type": "git",
78
+ "url": "git+https://github.com/janit/fu.git"
79
+ },
80
+ "homepage": "https://github.com/janit/fu",
81
+ "bugs": {
82
+ "url": "https://github.com/janit/fu/issues"
83
+ },
84
+ "keywords": [
85
+ "islands",
86
+ "preact",
87
+ "ssr",
88
+ "rolldown",
89
+ "nitro",
90
+ "deno",
91
+ "framework"
92
+ ],
93
+ "scripts": {
94
+ "build": "tsc -p tsconfig.build.json && cp src/hmr-runtime.js dist/hmr-runtime.js",
95
+ "prepack": "rm -rf dist && npm run build"
96
+ },
97
+ "main": "./dist/mod.js"
98
+ }
package/src/cli.ts ADDED
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env -S deno run -A
2
+ import { build } from "./build.ts";
3
+ import { dev } from "./dev.ts";
4
+
5
+ export async function main(argv: string[]): Promise<void> {
6
+ const [cmd = "dev", ...rest] = argv;
7
+ const portArg = rest.find((a) => a.startsWith("--port="));
8
+ const hostArg = rest.find((a) => a.startsWith("--host="));
9
+ const rootArg = rest.find((a) => !a.startsWith("-"));
10
+ const opts = {
11
+ root: rootArg ?? Deno?.cwd?.() ?? process.cwd(),
12
+ port: portArg ? Number(portArg.slice("--port=".length)) : undefined,
13
+ hostname: hostArg ? hostArg.slice("--host=".length) : undefined,
14
+ };
15
+ if (cmd === "build") await build(opts);
16
+ else if (cmd === "dev") await dev(opts);
17
+ else {
18
+ console.error(`fu: unknown command "${cmd}" (expected dev|build)`);
19
+ throw new Error(`unknown command: ${cmd}`);
20
+ }
21
+ }
22
+
23
+ declare const Deno: { cwd?: () => string } | undefined;
24
+
25
+ if (import.meta.main) await main(globalThis.process?.argv.slice(2) ?? []);