fibrae 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.
Files changed (70) hide show
  1. package/dist/components.d.ts +40 -0
  2. package/dist/components.js +63 -0
  3. package/dist/components.js.map +1 -0
  4. package/dist/core.d.ts +25 -0
  5. package/dist/core.js +46 -0
  6. package/dist/core.js.map +1 -0
  7. package/dist/dom.d.ts +16 -0
  8. package/dist/dom.js +67 -0
  9. package/dist/dom.js.map +1 -0
  10. package/dist/fiber-render.d.ts +33 -0
  11. package/dist/fiber-render.js +1069 -0
  12. package/dist/fiber-render.js.map +1 -0
  13. package/dist/h.d.ts +19 -0
  14. package/dist/h.js +26 -0
  15. package/dist/h.js.map +1 -0
  16. package/dist/hydration.d.ts +30 -0
  17. package/dist/hydration.js +375 -0
  18. package/dist/hydration.js.map +1 -0
  19. package/dist/index.d.ts +26 -0
  20. package/dist/index.js +28 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/jsx-runtime/index.d.ts +29 -0
  23. package/dist/jsx-runtime/index.js +61 -0
  24. package/dist/jsx-runtime/index.js.map +1 -0
  25. package/dist/render.d.ts +19 -0
  26. package/dist/render.js +325 -0
  27. package/dist/render.js.map +1 -0
  28. package/dist/router/History.d.ts +129 -0
  29. package/dist/router/History.js +241 -0
  30. package/dist/router/History.js.map +1 -0
  31. package/dist/router/Link.d.ts +52 -0
  32. package/dist/router/Link.js +131 -0
  33. package/dist/router/Link.js.map +1 -0
  34. package/dist/router/Navigator.d.ts +108 -0
  35. package/dist/router/Navigator.js +225 -0
  36. package/dist/router/Navigator.js.map +1 -0
  37. package/dist/router/Route.d.ts +65 -0
  38. package/dist/router/Route.js +143 -0
  39. package/dist/router/Route.js.map +1 -0
  40. package/dist/router/Router.d.ts +167 -0
  41. package/dist/router/Router.js +328 -0
  42. package/dist/router/Router.js.map +1 -0
  43. package/dist/router/RouterBuilder.d.ts +128 -0
  44. package/dist/router/RouterBuilder.js +112 -0
  45. package/dist/router/RouterBuilder.js.map +1 -0
  46. package/dist/router/RouterOutlet.d.ts +57 -0
  47. package/dist/router/RouterOutlet.js +132 -0
  48. package/dist/router/RouterOutlet.js.map +1 -0
  49. package/dist/router/RouterState.d.ts +102 -0
  50. package/dist/router/RouterState.js +94 -0
  51. package/dist/router/RouterState.js.map +1 -0
  52. package/dist/router/index.d.ts +28 -0
  53. package/dist/router/index.js +31 -0
  54. package/dist/router/index.js.map +1 -0
  55. package/dist/runtime.d.ts +55 -0
  56. package/dist/runtime.js +68 -0
  57. package/dist/runtime.js.map +1 -0
  58. package/dist/scope-utils.d.ts +14 -0
  59. package/dist/scope-utils.js +29 -0
  60. package/dist/scope-utils.js.map +1 -0
  61. package/dist/server.d.ts +112 -0
  62. package/dist/server.js +313 -0
  63. package/dist/server.js.map +1 -0
  64. package/dist/shared.d.ts +136 -0
  65. package/dist/shared.js +53 -0
  66. package/dist/shared.js.map +1 -0
  67. package/dist/tracking.d.ts +23 -0
  68. package/dist/tracking.js +53 -0
  69. package/dist/tracking.js.map +1 -0
  70. package/package.json +62 -0
@@ -0,0 +1,225 @@
1
+ /**
2
+ * Navigator service - type-safe route-aware navigation.
3
+ *
4
+ * Provides route-aware navigation on top of History:
5
+ * - nav.go("routeName", { path: {...}, searchParams: {...} })
6
+ * - nav.back, nav.forward
7
+ * - nav.isActive("routeName", params) for active link detection
8
+ * - currentRoute Atom reflects matched route info
9
+ *
10
+ * Design: Navigator uses History internally but provides route-aware API.
11
+ * It knows about routes and can build URLs from route names.
12
+ */
13
+ import * as Effect from "effect/Effect";
14
+ import * as Context from "effect/Context";
15
+ import * as Layer from "effect/Layer";
16
+ import * as Option from "effect/Option";
17
+ import { Atom, Registry as AtomRegistry } from "@effect-atom/atom";
18
+ import { History } from "./History.js";
19
+ // =============================================================================
20
+ // Service Tag
21
+ // =============================================================================
22
+ /**
23
+ * Navigator service tag for Effect dependency injection.
24
+ */
25
+ export class Navigator extends Context.Tag("fibrae/Navigator")() {
26
+ }
27
+ // =============================================================================
28
+ // Helpers
29
+ // =============================================================================
30
+ /**
31
+ * Parse search params from URL search string.
32
+ */
33
+ function parseSearchParams(search) {
34
+ const params = {};
35
+ const searchParams = new URLSearchParams(search);
36
+ searchParams.forEach((value, key) => {
37
+ params[key] = value;
38
+ });
39
+ return params;
40
+ }
41
+ /**
42
+ * Build search string from params object.
43
+ */
44
+ function buildSearchString(params) {
45
+ const searchParams = new URLSearchParams();
46
+ for (const [key, value] of Object.entries(params)) {
47
+ if (value !== undefined && value !== null) {
48
+ searchParams.set(key, String(value));
49
+ }
50
+ }
51
+ const str = searchParams.toString();
52
+ return str ? `?${str}` : "";
53
+ }
54
+ /**
55
+ * Strip basePath prefix from pathname for route matching.
56
+ */
57
+ function stripBasePath(pathname, basePath) {
58
+ if (!basePath || basePath === "/") {
59
+ return pathname;
60
+ }
61
+ // Normalize: remove trailing slash from basePath
62
+ const normalizedBase = basePath.endsWith("/") ? basePath.slice(0, -1) : basePath;
63
+ if (pathname.startsWith(normalizedBase)) {
64
+ const stripped = pathname.slice(normalizedBase.length);
65
+ // Ensure we return "/" not "" for root
66
+ return stripped || "/";
67
+ }
68
+ return pathname;
69
+ }
70
+ /**
71
+ * Match current location against router and return CurrentRoute.
72
+ */
73
+ function matchLocation(router, location, basePath = "") {
74
+ const pathname = stripBasePath(location.pathname, basePath);
75
+ const match = router.matchRoute(pathname);
76
+ if (Option.isNone(match)) {
77
+ return Option.none();
78
+ }
79
+ return Option.some({
80
+ routeName: match.value.route.name,
81
+ params: match.value.params,
82
+ searchParams: parseSearchParams(location.search),
83
+ });
84
+ }
85
+ /**
86
+ * Find a route by name in the router.
87
+ */
88
+ function findRouteByName(router, name) {
89
+ for (const group of router.groups) {
90
+ for (const route of group.routes) {
91
+ if (route.name === name) {
92
+ return Option.some(route);
93
+ }
94
+ }
95
+ }
96
+ return Option.none();
97
+ }
98
+ /**
99
+ * Create a Navigator layer for the given router.
100
+ *
101
+ * Features:
102
+ * - Type-safe navigation by route name
103
+ * - Automatic URL building via route.interpolate
104
+ * - Tracks current matched route in an Atom
105
+ * - Delegates to History for actual navigation
106
+ * - Supports basePath for apps mounted at non-root paths
107
+ */
108
+ export function NavigatorLive(router, options = {}) {
109
+ const basePath = options.basePath ?? "";
110
+ return Layer.effect(Navigator, Effect.gen(function* () {
111
+ const history = yield* History;
112
+ const registry = yield* AtomRegistry.AtomRegistry;
113
+ // Get initial location and match
114
+ const initialLocation = yield* Atom.get(history.location);
115
+ const initialRoute = matchLocation(router, initialLocation, basePath);
116
+ // Create currentRoute Atom
117
+ const currentRouteAtom = Atom.make(initialRoute);
118
+ // Create a derived effect that updates currentRoute when location changes
119
+ // This is a reactive subscription
120
+ const updateCurrentRoute = (location) => {
121
+ const matched = matchLocation(router, location, basePath);
122
+ registry.set(currentRouteAtom, matched);
123
+ };
124
+ // Note: The actual subscription to location changes should be handled
125
+ // by by component rendering - currentRoute will be updated when go/back/forward are called
126
+ const service = {
127
+ basePath,
128
+ currentRoute: currentRouteAtom,
129
+ go: (routeName, options = {}) => Effect.gen(function* () {
130
+ const route = findRouteByName(router, routeName);
131
+ if (Option.isNone(route)) {
132
+ yield* Effect.logWarning(`Route not found: ${routeName}`);
133
+ return;
134
+ }
135
+ // Build URL from route and params
136
+ const pathParams = options.path ?? {};
137
+ const routePathname = route.value.interpolate(pathParams);
138
+ // Prepend basePath to route pathname
139
+ const pathname = basePath + routePathname;
140
+ const search = options.searchParams
141
+ ? buildSearchString(options.searchParams)
142
+ : "";
143
+ const url = `${pathname}${search}`;
144
+ // Navigate
145
+ if (options.replace) {
146
+ yield* history.replace(url);
147
+ }
148
+ else {
149
+ yield* history.push(url);
150
+ }
151
+ // Update currentRoute
152
+ const newLocation = yield* Atom.get(history.location);
153
+ updateCurrentRoute(newLocation);
154
+ }),
155
+ back: Effect.gen(function* () {
156
+ yield* history.back;
157
+ // Wait a tick for popstate to fire, then update
158
+ yield* Effect.sleep("10 millis");
159
+ const location = yield* Atom.get(history.location);
160
+ updateCurrentRoute(location);
161
+ }),
162
+ forward: Effect.gen(function* () {
163
+ yield* history.forward;
164
+ // Wait a tick for popstate to fire, then update
165
+ yield* Effect.sleep("10 millis");
166
+ const location = yield* Atom.get(history.location);
167
+ updateCurrentRoute(location);
168
+ }),
169
+ isActive: (routeName, params) => Effect.gen(function* () {
170
+ const current = yield* Atom.get(currentRouteAtom);
171
+ if (Option.isNone(current)) {
172
+ return false;
173
+ }
174
+ if (current.value.routeName !== routeName) {
175
+ return false;
176
+ }
177
+ // If params provided, check they match
178
+ if (params) {
179
+ for (const [key, value] of Object.entries(params)) {
180
+ if (current.value.params[key] !== value) {
181
+ return false;
182
+ }
183
+ }
184
+ }
185
+ return true;
186
+ }),
187
+ };
188
+ return service;
189
+ }));
190
+ }
191
+ // =============================================================================
192
+ // Convenience Accessors
193
+ // =============================================================================
194
+ /**
195
+ * Navigate to a route by name.
196
+ */
197
+ export const go = (routeName, options) => Effect.gen(function* () {
198
+ const nav = yield* Navigator;
199
+ yield* nav.go(routeName, options);
200
+ });
201
+ /**
202
+ * Go back in history.
203
+ */
204
+ /* is-tree-shakable-suppress */
205
+ export const back = Effect.gen(function* () {
206
+ const nav = yield* Navigator;
207
+ yield* nav.back;
208
+ });
209
+ /**
210
+ * Go forward in history.
211
+ */
212
+ /* is-tree-shakable-suppress */
213
+ export const forward = Effect.gen(function* () {
214
+ const nav = yield* Navigator;
215
+ yield* nav.forward;
216
+ });
217
+ /**
218
+ * Get current route info.
219
+ */
220
+ /* is-tree-shakable-suppress */
221
+ export const getCurrentRoute = Effect.gen(function* () {
222
+ const nav = yield* Navigator;
223
+ return yield* Atom.get(nav.currentRoute);
224
+ });
225
+ //# sourceMappingURL=Navigator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Navigator.js","sourceRoot":"","sources":["../../src/router/Navigator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Route declaration module for Fibrae router.
3
+ *
4
+ * Mirrors Effect HttpApiEndpoint patterns:
5
+ * - Route.get("name", "/path") for static routes
6
+ * - Route.get("name")`/path/${param}` for dynamic routes with template literals
7
+ * - Route.param for schema-validated path parameters
8
+ * - .setSearchParams for query string validation
9
+ */
10
+ import * as Schema from "effect/Schema";
11
+ import * as Option from "effect/Option";
12
+ /**
13
+ * Annotation symbol for storing parameter name in schema metadata.
14
+ * Mirrors HttpApiSchema.AnnotationParam pattern.
15
+ */
16
+ export declare const AnnotationParam: unique symbol;
17
+ /**
18
+ * Represents a single route with path and optional search params validation.
19
+ * This is immutable data that describes a route.
20
+ */
21
+ export interface Route<Name extends string = string, PathParams extends Record<string, unknown> = Record<string, unknown>, SearchParams extends Record<string, unknown> = Record<string, unknown>> {
22
+ readonly name: Name;
23
+ readonly path: string;
24
+ readonly pathSchema: Option.Option<Schema.Schema<PathParams>>;
25
+ readonly searchSchema: Option.Option<Schema.Schema<SearchParams>>;
26
+ /**
27
+ * Match a pathname against this route.
28
+ * Returns the decoded path parameters if matched, None otherwise.
29
+ */
30
+ readonly match: (pathname: string) => Option.Option<PathParams>;
31
+ /**
32
+ * Build a URL from path parameters.
33
+ * Throws if required params are missing.
34
+ */
35
+ readonly interpolate: (params: PathParams) => string;
36
+ /**
37
+ * Set search parameter schema for this route.
38
+ */
39
+ readonly setSearchParams: <NewSearch extends Record<string, unknown>>(schema: Schema.Schema<NewSearch>) => Route<Name, PathParams, NewSearch>;
40
+ }
41
+ /**
42
+ * Constructor for building routes with different method types.
43
+ * Supports both static paths and template literal syntax.
44
+ */
45
+ export interface RouteConstructor {
46
+ <const Name extends string>(name: Name, path: string): Route<Name, {}, {}>;
47
+ <const Name extends string>(name: Name): <const T extends readonly any[]>(segments: TemplateStringsArray, ...params: T) => Route<Name, Record<string, unknown>, {}>;
48
+ }
49
+ /**
50
+ * Route.get("name", "/path") creates a GET route
51
+ * Route.get("name")`/path/${param}` creates a GET route with typed path params
52
+ */
53
+ export declare const get: RouteConstructor;
54
+ /**
55
+ * Route.post("name", "/path") creates a POST route
56
+ * Route.post("name")`/path/${param}` creates a POST route with typed path params
57
+ */
58
+ export declare const post: RouteConstructor;
59
+ /**
60
+ * Route.param("name", schema) creates a path parameter with validation.
61
+ * Use in template literals: Route.get("name")`/posts/${Route.param("id", Schema.NumberFromString)}`
62
+ *
63
+ * Stores the parameter name in the schema's annotations for extraction during template literal parsing.
64
+ */
65
+ export declare function param<T>(name: string, schema: Schema.Schema<T>): Schema.Schema<T>;
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Route declaration module for Fibrae router.
3
+ *
4
+ * Mirrors Effect HttpApiEndpoint patterns:
5
+ * - Route.get("name", "/path") for static routes
6
+ * - Route.get("name")`/path/${param}` for dynamic routes with template literals
7
+ * - Route.param for schema-validated path parameters
8
+ * - .setSearchParams for query string validation
9
+ */
10
+ import * as Schema from "effect/Schema";
11
+ import * as Option from "effect/Option";
12
+ /**
13
+ * Annotation symbol for storing parameter name in schema metadata.
14
+ * Mirrors HttpApiSchema.AnnotationParam pattern.
15
+ */
16
+ export const AnnotationParam = Symbol.for("fibrae/Route/AnnotationParam");
17
+ /**
18
+ * Parse path template to extract param names and build a URL pattern.
19
+ *
20
+ * Example: "/posts/:id/comments/:commentId" → { paramNames: ["id", "commentId"], pattern: ... }
21
+ */
22
+ function parsePathTemplate(segments, schemas) {
23
+ let path = segments[0];
24
+ const paramNames = [];
25
+ const pathSchemaObj = {};
26
+ for (let i = 0; i < schemas.length; i++) {
27
+ const schema = schemas[i];
28
+ // Get param name from schema annotation (if provided) or use index
29
+ const paramName = getParamName(schema) ?? String(i);
30
+ paramNames.push(paramName);
31
+ pathSchemaObj[paramName] = schema;
32
+ path += `:${paramName}${segments[i + 1]}`;
33
+ }
34
+ const pathSchema = paramNames.length > 0
35
+ ? Option.some(Schema.Struct(pathSchemaObj))
36
+ : Option.none();
37
+ return { path, paramNames, pathSchema };
38
+ }
39
+ /**
40
+ * Get param name from a Schema's annotations.
41
+ * Mirrors HttpApiSchema.getParam pattern.
42
+ */
43
+ function getParamName(schema) {
44
+ const ast = schema.ast;
45
+ const annotations = ast.annotations;
46
+ const paramAnnotation = annotations[AnnotationParam];
47
+ return paramAnnotation?.name;
48
+ }
49
+ /**
50
+ * Match a pathname against a route pattern.
51
+ * Pattern: "/posts/:id/comments/:commentId"
52
+ * Pathname: "/posts/123/comments/456"
53
+ * Returns: { id: "123", commentId: "456" }
54
+ */
55
+ function matchPath(pattern, pathname, pathSchema) {
56
+ // Convert pattern with :params to regex
57
+ const regexPattern = pattern.replace(/:(\w+)/g, "(?<$1>[^/]+)");
58
+ const regex = new RegExp(`^${regexPattern}/?$`);
59
+ const match = pathname.match(regex);
60
+ if (!match) {
61
+ return Option.none();
62
+ }
63
+ const params = match.groups ?? {};
64
+ // Decode and validate with schema if present
65
+ if (Option.isSome(pathSchema)) {
66
+ try {
67
+ const decoded = Schema.decodeSync(pathSchema.value)(params);
68
+ return Option.some(decoded);
69
+ }
70
+ catch (_) {
71
+ return Option.none();
72
+ }
73
+ }
74
+ return Option.some(params);
75
+ }
76
+ /**
77
+ * Build a URL from a route pattern and parameters.
78
+ * Pattern: "/posts/:id/comments/:commentId"
79
+ * Params: { id: 123, commentId: 456 }
80
+ * Returns: "/posts/123/comments/456"
81
+ */
82
+ function interpolatePath(pattern, params) {
83
+ return pattern.replace(/:(\w+)/g, (_, key) => {
84
+ const value = params[key];
85
+ if (value === undefined) {
86
+ throw new Error(`Missing required parameter: ${key}`);
87
+ }
88
+ return String(value);
89
+ });
90
+ }
91
+ /**
92
+ * Create a route with static path.
93
+ */
94
+ function makeRoute(_name, path, pathSchema = Option.none(), searchSchema = Option.none()) {
95
+ return {
96
+ name: _name,
97
+ path,
98
+ pathSchema,
99
+ searchSchema,
100
+ match: (pathname) => matchPath(path, pathname, pathSchema),
101
+ interpolate: (params) => interpolatePath(path, params),
102
+ setSearchParams: (schema) => makeRoute(_name, path, pathSchema, Option.some(schema)),
103
+ };
104
+ }
105
+ /**
106
+ * Create a route getter function supporting both static and template literal syntax.
107
+ */
108
+ function makeGetter() {
109
+ return ((name, path) => {
110
+ // Static path case
111
+ if (typeof path === "string") {
112
+ return makeRoute(name, path);
113
+ }
114
+ // Return template literal handler
115
+ return (segments, ...schemas) => {
116
+ const { path: parsedPath, pathSchema } = parsePathTemplate(segments, Array.from(schemas));
117
+ return makeRoute(name, parsedPath, pathSchema);
118
+ };
119
+ });
120
+ }
121
+ /**
122
+ * Route.get("name", "/path") creates a GET route
123
+ * Route.get("name")`/path/${param}` creates a GET route with typed path params
124
+ */
125
+ export const get = makeGetter();
126
+ /**
127
+ * Route.post("name", "/path") creates a POST route
128
+ * Route.post("name")`/path/${param}` creates a POST route with typed path params
129
+ */
130
+ export const post = makeGetter();
131
+ /**
132
+ * Route.param("name", schema) creates a path parameter with validation.
133
+ * Use in template literals: Route.get("name")`/posts/${Route.param("id", Schema.NumberFromString)}`
134
+ *
135
+ * Stores the parameter name in the schema's annotations for extraction during template literal parsing.
136
+ */
137
+ export function param(name, schema) {
138
+ const annotations = {
139
+ [AnnotationParam]: { name, schema }
140
+ };
141
+ return schema.annotations(annotations);
142
+ }
143
+ //# sourceMappingURL=Route.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Route.js","sourceRoot":"","sources":["../../src/router/Route.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Router module for organizing and matching routes.
3
+ *
4
+ * Mirrors Effect HttpApiGroup/HttpApi patterns:
5
+ * - Router.group("name") creates a group for organizing routes
6
+ * - Router.make("name") creates the top-level router
7
+ * - Routes are added via .add(route)
8
+ * - Router holds the complete route tree for efficient matching
9
+ *
10
+ * SSR Integration:
11
+ * - Router.serverLayer() - For SSR rendering with loaders
12
+ * - Router.browserLayer() - For client hydration with initial state
13
+ */
14
+ import type { Route } from "./Route.js";
15
+ import * as Option from "effect/Option";
16
+ import * as Layer from "effect/Layer";
17
+ import * as Context from "effect/Context";
18
+ import { Registry as AtomRegistry } from "@effect-atom/atom";
19
+ import { History } from "./History.js";
20
+ import { Navigator } from "./Navigator.js";
21
+ import { RouterHandlers } from "./RouterBuilder.js";
22
+ import type { VElement } from "../shared.js";
23
+ /**
24
+ * A group of routes for organizational purposes.
25
+ * Groups provide namespacing for handler implementation.
26
+ */
27
+ export interface RouteGroup<Name extends string = string> {
28
+ readonly name: Name;
29
+ readonly routes: readonly Route[];
30
+ readonly add: (route: Route) => RouteGroup<Name>;
31
+ }
32
+ /**
33
+ * The complete router holding all route groups and enabling route matching.
34
+ */
35
+ export interface Router<Name extends string = string> {
36
+ readonly name: Name;
37
+ readonly groups: readonly RouteGroup[];
38
+ readonly add: (group: RouteGroup) => Router<Name>;
39
+ /**
40
+ * Match a pathname against all routes in the router.
41
+ * Returns the matched route, group name, and decoded path parameters.
42
+ */
43
+ readonly matchRoute: (pathname: string) => Option.Option<{
44
+ readonly groupName: string;
45
+ readonly route: Route;
46
+ readonly params: Record<string, unknown>;
47
+ }>;
48
+ }
49
+ /**
50
+ * Create a route group with the given name.
51
+ * Routes are added via group.add(route).
52
+ */
53
+ export declare function group<const Name extends string>(name: Name): RouteGroup<Name>;
54
+ /**
55
+ * Create a router with the given name.
56
+ * Groups are added via router.add(group).
57
+ */
58
+ export declare function make<const Name extends string>(name: Name): Router<Name>;
59
+ /**
60
+ * Options for server-side rendering layer.
61
+ */
62
+ export interface ServerLayerOptions {
63
+ /** The router instance */
64
+ readonly router: Router;
65
+ /** Current request pathname */
66
+ readonly pathname: string;
67
+ /** Current request search string (with or without leading ?) */
68
+ readonly search?: string;
69
+ /** Base path prefix for the app (e.g., "/ssr/router") */
70
+ readonly basePath?: string;
71
+ }
72
+ /**
73
+ * Options for browser/client hydration layer.
74
+ */
75
+ export interface BrowserLayerOptions {
76
+ /** The router instance */
77
+ readonly router: Router;
78
+ /**
79
+ * @deprecated Use atom hydration instead. RouterStateAtom is automatically
80
+ * hydrated from __FIBRAE_STATE__ and used by RouterOutlet.
81
+ */
82
+ readonly initialState?: DehydratedRouterState;
83
+ /** Base path prefix for the app (e.g., "/ssr/router") */
84
+ readonly basePath?: string;
85
+ }
86
+ /**
87
+ * Dehydrated state from SSR for hydration.
88
+ * Contains matched route info and loader data.
89
+ */
90
+ export interface DehydratedRouterState {
91
+ /** Name of the matched route */
92
+ readonly routeName: string;
93
+ /** Decoded path parameters */
94
+ readonly params: Record<string, unknown>;
95
+ /** Search parameters */
96
+ readonly searchParams: Record<string, string>;
97
+ /** Data returned by the loader */
98
+ readonly loaderData: unknown;
99
+ }
100
+ /**
101
+ * Result of SSR rendering a route.
102
+ */
103
+ export interface SSRRouteResult {
104
+ /** The rendered VElement */
105
+ readonly element: VElement;
106
+ /** Dehydrated state for client hydration */
107
+ readonly dehydratedState: DehydratedRouterState;
108
+ }
109
+ declare const CurrentRouteElement_base: Context.TagClass<CurrentRouteElement, "fibrae/CurrentRouteElement", {
110
+ readonly element: VElement;
111
+ readonly state: DehydratedRouterState;
112
+ }>;
113
+ /**
114
+ * Service tag for the current route's rendered element.
115
+ * Used by SSR to provide the matched route's component.
116
+ */
117
+ export declare class CurrentRouteElement extends CurrentRouteElement_base {
118
+ }
119
+ /**
120
+ * Create a server-side layer for SSR rendering.
121
+ *
122
+ * This layer:
123
+ * 1. Matches the pathname against the router
124
+ * 2. Runs the matched route's loader
125
+ * 3. Renders the component with loader data
126
+ * 4. Provides the rendered element and dehydrated state
127
+ *
128
+ * Usage in SSR:
129
+ * ```typescript
130
+ * const serverLayer = Router.serverLayer({
131
+ * router: AppRouter,
132
+ * pathname: "/posts/42",
133
+ * search: "?sort=date",
134
+ * basePath: "/ssr/router"
135
+ * });
136
+ *
137
+ * const { element, dehydratedState } = yield* Router.CurrentRouteElement;
138
+ * ```
139
+ */
140
+ export declare function serverLayer(options: ServerLayerOptions): Layer.Layer<CurrentRouteElement | History | Navigator, unknown, RouterHandlers | AtomRegistry.AtomRegistry>;
141
+ /**
142
+ * Create a browser layer for client-side hydration.
143
+ *
144
+ * This layer:
145
+ * 1. Sets up browser history with popstate listener
146
+ * 2. Checks RouterStateAtom for hydrated SSR state
147
+ * 3. If hydrated, uses that for initial render (skips loader)
148
+ * 4. Provides Navigator for subsequent navigation
149
+ *
150
+ * SSR hydration works automatically via atom hydration - no need to
151
+ * pass initialState manually. The RouterStateAtom is hydrated from
152
+ * __FIBRAE_STATE__ before this layer is created.
153
+ *
154
+ * Usage in client:
155
+ * ```typescript
156
+ * // Hydrate atoms first (includes RouterStateAtom)
157
+ * hydrate(container, app, window.__FIBRAE_STATE__);
158
+ *
159
+ * // Browser layer reads from hydrated RouterStateAtom
160
+ * const browserLayer = Router.browserLayer({
161
+ * router: AppRouter,
162
+ * basePath: "/ssr/router"
163
+ * });
164
+ * ```
165
+ */
166
+ export declare function browserLayer(options: BrowserLayerOptions): Layer.Layer<History | Navigator | CurrentRouteElement, unknown, AtomRegistry.AtomRegistry | RouterHandlers>;
167
+ export {};