@fiyuu/runtime 0.1.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.
@@ -0,0 +1,55 @@
1
+ /**
2
+ * WebSocket server attachment for the Fiyuu runtime.
3
+ * Wires up a ws.WebSocketServer on the HTTP server's upgrade event.
4
+ */
5
+ import { existsSync } from "node:fs";
6
+ import path from "node:path";
7
+ import { WebSocketServer } from "ws";
8
+ import { importModule } from "./server-loader.js";
9
+ export async function attachWebsocketServer(server, options, websocketPath) {
10
+ if (!options.config?.websocket?.enabled) {
11
+ return undefined;
12
+ }
13
+ const socketModulePath = path.join(options.rootDirectory, "server", "socket.ts");
14
+ const socketModule = existsSync(socketModulePath)
15
+ ? (await importModule(socketModulePath, options.mode))
16
+ : null;
17
+ const registration = socketModule?.registerSocketServer?.() ?? {};
18
+ const wss = new WebSocketServer({
19
+ noServer: true,
20
+ maxPayload: options.config?.websocket?.maxPayloadBytes ?? 64 * 1024,
21
+ });
22
+ wss.on("connection", (socket) => {
23
+ socket.send(JSON.stringify({
24
+ type: "fiyuu:ready",
25
+ namespace: registration.namespace ?? "app",
26
+ events: registration.events ?? [],
27
+ }));
28
+ registration.onConnect?.(socket);
29
+ socket.on("message", (message) => {
30
+ registration.onMessage?.(socket, message.toString());
31
+ });
32
+ });
33
+ const handledSockets = new WeakSet();
34
+ server.on("upgrade", (request, socket, head) => {
35
+ if (handledSockets.has(socket))
36
+ return;
37
+ handledSockets.add(socket);
38
+ if (!request.url) {
39
+ socket.destroy();
40
+ return;
41
+ }
42
+ const url = new URL(request.url, "http://localhost");
43
+ if (url.pathname !== websocketPath)
44
+ return;
45
+ try {
46
+ wss.handleUpgrade(request, socket, head, (client) => {
47
+ wss.emit("connection", client, request);
48
+ });
49
+ }
50
+ catch {
51
+ // Another WebSocket handler already processed this socket
52
+ }
53
+ });
54
+ return `ws://localhost:${options.port ?? 4050}${websocketPath}`;
55
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Fiyuu runtime server — main orchestrator.
3
+ *
4
+ * This file wires together the modular pieces:
5
+ * server-types → shared interfaces
6
+ * server-utils → serialise, escapeHtml, sendJson/Text, parseBody, …
7
+ * server-router → buildRouteIndex, matchRoute
8
+ * server-loader → importModule, layout/meta loading, query cache, renderGeaComponent
9
+ * server-renderer → renderDocument, renderStatusPage, serveClientAsset, …
10
+ * server-devtools → renderUnifiedToolsScript (dev only)
11
+ * server-middleware→ runMiddleware
12
+ * server-websocket → attachWebsocketServer
13
+ */
14
+ import { type RenderMode } from "@fiyuu/core";
15
+ export type { StartServerOptions, StartedServer } from "./server-types.js";
16
+ import type { StartedServer, StartServerOptions } from "./server-types.js";
17
+ declare global {
18
+ interface Window {
19
+ __FIYUU_DATA__?: unknown;
20
+ __FIYUU_ROUTE__?: string;
21
+ __FIYUU_INTENT__?: string;
22
+ __FIYUU_RENDER__?: RenderMode;
23
+ __FIYUU_WS_PATH__?: string;
24
+ __FIYUU_DEVTOOLS__?: unknown;
25
+ fiyuu?: {
26
+ theme: {
27
+ get(): "light" | "dark";
28
+ set(value: "light" | "dark"): void;
29
+ toggle(): void;
30
+ bindToggle(elementId: string): void;
31
+ onChange(fn: (theme: "light" | "dark") => void): void;
32
+ };
33
+ bind(elementId: string, value?: unknown, asHtml?: boolean): void;
34
+ partial(elementId: string, url: string, options?: {
35
+ loading?: string;
36
+ }): Promise<void>;
37
+ onError(callback: (event: {
38
+ message: string;
39
+ error: Error | null;
40
+ source: string | null;
41
+ line: number | null;
42
+ }) => void): void;
43
+ state<T>(key: string, initialValue: T): {
44
+ get(): T;
45
+ set(value: T): void;
46
+ bind(elementId: string): object;
47
+ onChange(fn: (value: T) => void): object;
48
+ };
49
+ router: {
50
+ navigate(url: string): Promise<void>;
51
+ on(event: "navigate" | "before", fn: (detail: {
52
+ route: string;
53
+ render?: string;
54
+ title?: string;
55
+ }) => void | false): object;
56
+ };
57
+ ws(overridePath?: string): {
58
+ on(type: string, handler: (data: unknown) => void): object;
59
+ onOpen(handler: () => void): object;
60
+ onClose(handler: () => void): object;
61
+ onError(handler: () => void): object;
62
+ send(data: unknown): object;
63
+ status(): "connecting" | "connected" | "closed" | "unavailable";
64
+ };
65
+ };
66
+ }
67
+ }
68
+ export declare function startServer(options: StartServerOptions): Promise<StartedServer>;