@zenithbuild/router 0.5.0-beta.2.3

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/README.md ADDED
@@ -0,0 +1,130 @@
1
+ # @zenith/router
2
+
3
+ > **⚠️ Internal API:** This package is an internal implementation detail of the Zenith framework. It is not intended for public use and its API may break without warning. Please use `@zenithbuild/core` instead.
4
+
5
+
6
+ File-based SPA router for Zenith framework with **deterministic, compile-time route resolution**.
7
+
8
+ ## Features
9
+
10
+ - 📁 **File-based routing** — Pages in `pages/` directory become routes automatically
11
+ - ⚡ **Compile-time resolution** — Route manifest generated at build time, not runtime
12
+ - 🔗 **ZenLink component** — Declarative navigation with prefetching
13
+ - 🧭 **Programmatic navigation** — `navigate()`, `prefetch()`, `isActive()` APIs
14
+ - 🎯 **Type-safe** — Full TypeScript support with route parameter inference
15
+ - 🚀 **Hydration-safe** — No runtime hacks, works seamlessly with SSR/SSG
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ bun add @zenith/router
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ ### Programmatic Navigation
26
+
27
+ ```ts
28
+ import { navigate, prefetch, isActive, getRoute } from '@zenith/router'
29
+
30
+ // Navigate to a route
31
+ navigate('/about')
32
+
33
+ // Navigate with replace (no history entry)
34
+ navigate('/dashboard', { replace: true })
35
+
36
+ // Prefetch a route for faster navigation
37
+ prefetch('/blog')
38
+
39
+ // Check if a route is active
40
+ if (isActive('/blog')) {
41
+ console.log('Currently on blog section')
42
+ }
43
+
44
+ // Get current route state
45
+ const { path, params, query } = getRoute()
46
+ ```
47
+
48
+ ### ZenLink Component (in .zen files)
49
+
50
+ ```html
51
+ <ZenLink href="/about">About Us</ZenLink>
52
+
53
+ <!-- With prefetching on hover -->
54
+ <ZenLink href="/blog" preload>Blog</ZenLink>
55
+
56
+ <!-- External links automatically open in new tab -->
57
+ <ZenLink href="https://github.com">GitHub</ZenLink>
58
+ ```
59
+
60
+ ### Build-time Route Manifest
61
+
62
+ The router generates a route manifest at compile time:
63
+
64
+ ```ts
65
+ import { generateRouteManifest, discoverPages } from '@zenith/router/manifest'
66
+
67
+ const pagesDir = './src/pages'
68
+ const manifest = generateRouteManifest(pagesDir)
69
+
70
+ // manifest contains:
71
+ // - path: Route pattern (e.g., /blog/:id)
72
+ // - regex: Compiled RegExp for matching
73
+ // - paramNames: Dynamic segment names
74
+ // - score: Priority for deterministic matching
75
+ ```
76
+
77
+ ## Route Patterns
78
+
79
+ | File Path | Route Pattern |
80
+ |-----------|---------------|
81
+ | `pages/index.zen` | `/` |
82
+ | `pages/about.zen` | `/about` |
83
+ | `pages/blog/index.zen` | `/blog` |
84
+ | `pages/blog/[id].zen` | `/blog/:id` |
85
+ | `pages/posts/[...slug].zen` | `/posts/*slug` |
86
+ | `pages/[[...all]].zen` | `/*all?` (optional) |
87
+
88
+ ## Architecture
89
+
90
+ ```
91
+ @zenith/router
92
+ ├── src/
93
+ │ ├── index.ts # Main exports
94
+ │ ├── types.ts # Core types
95
+ │ ├── manifest.ts # Build-time manifest generation
96
+ │ ├── runtime.ts # Client-side SPA router
97
+ │ └── navigation/
98
+ │ ├── index.ts # Navigation exports
99
+ │ ├── zen-link.ts # Navigation API
100
+ │ └── ZenLink.zen # Declarative component
101
+ ```
102
+
103
+ ## API Reference
104
+
105
+ ### Navigation Functions
106
+
107
+ - `navigate(path, options?)` — Navigate to a path
108
+ - `prefetch(path)` — Prefetch a route for faster navigation
109
+ - `isActive(path, exact?)` — Check if path is currently active
110
+ - `getRoute()` — Get current route state
111
+ - `back()`, `forward()`, `go(delta)` — History navigation
112
+
113
+ ### Manifest Generation
114
+
115
+ - `discoverPages(pagesDir)` — Find all .zen files in pages directory
116
+ - `generateRouteManifest(pagesDir)` — Generate complete route manifest
117
+ - `filePathToRoutePath(filePath, pagesDir)` — Convert file path to route
118
+ - `routePathToRegex(routePath)` — Compile route to RegExp
119
+
120
+ ### Types
121
+
122
+ - `RouteState` — Current route state (path, params, query)
123
+ - `RouteRecord` — Compiled route definition
124
+ - `NavigateOptions` — Options for navigation
125
+ - `ZenLinkProps` — Props for ZenLink component
126
+
127
+ ## License
128
+
129
+ MIT
130
+ # zenith-router
@@ -0,0 +1,7 @@
1
+ <script setup="ts">
2
+ export const props = { href: "", class: "", target: "", rel: "" };
3
+ </script>
4
+
5
+ <a data-zen-link="true" href={props.href} class={props.class} target={props.target} rel={props.rel}>
6
+ <slot></slot>
7
+ </a>
package/dist/events.js ADDED
@@ -0,0 +1,53 @@
1
+ // ---------------------------------------------------------------------------
2
+ // events.js — Zenith Router V0
3
+ // ---------------------------------------------------------------------------
4
+ // Route change event system.
5
+ //
6
+ // Subscribers receive route change notifications.
7
+ // Returns unsubscribe function.
8
+ // No batching. No queue. Synchronous dispatch.
9
+ // ---------------------------------------------------------------------------
10
+
11
+ /** @type {Set<(detail: object) => void>} */
12
+ const _subscribers = new Set();
13
+
14
+ /**
15
+ * Subscribe to route change events.
16
+ *
17
+ * @param {(detail: { path: string, params?: Record<string, string>, matched: boolean }) => void} callback
18
+ * @returns {() => void} unsubscribe
19
+ */
20
+ export function onRouteChange(callback) {
21
+ _subscribers.add(callback);
22
+
23
+ return () => {
24
+ _subscribers.delete(callback);
25
+ };
26
+ }
27
+
28
+ /**
29
+ * Dispatch a route change to all subscribers.
30
+ *
31
+ * @param {{ path: string, params?: Record<string, string>, matched: boolean }} detail
32
+ */
33
+ export function _dispatchRouteChange(detail) {
34
+ for (const cb of _subscribers) {
35
+ cb(detail);
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Clear all subscribers. Used for testing and teardown.
41
+ */
42
+ export function _clearSubscribers() {
43
+ _subscribers.clear();
44
+ }
45
+
46
+ /**
47
+ * Get the current subscriber count. Used for leak detection.
48
+ *
49
+ * @returns {number}
50
+ */
51
+ export function _getSubscriberCount() {
52
+ return _subscribers.size;
53
+ }
@@ -0,0 +1,84 @@
1
+ // ---------------------------------------------------------------------------
2
+ // history.js — Zenith Router V0
3
+ // ---------------------------------------------------------------------------
4
+ // Minimal navigation helpers without History API mutation.
5
+ //
6
+ // - push(path) → hard navigation (assign)
7
+ // - replace(path) → hard navigation (replace)
8
+ // - listen(cb) → popstate listener, returns unlisten
9
+ // - current() → location.pathname
10
+ //
11
+ // No hash routing. No scroll restoration. No batching.
12
+ // ---------------------------------------------------------------------------
13
+
14
+ /** @type {Set<(path: string) => void>} */
15
+ const _listeners = new Set();
16
+
17
+ /** @type {boolean} */
18
+ let _listening = false;
19
+
20
+ /**
21
+ * Internal popstate handler — fires all registered listeners.
22
+ */
23
+ function _onPopState() {
24
+ const path = current();
25
+ for (const cb of _listeners) {
26
+ cb(path);
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Ensure the global popstate listener is attached (once).
32
+ */
33
+ function _ensureListening() {
34
+ if (_listening) return;
35
+ window.addEventListener('popstate', _onPopState);
36
+ _listening = true;
37
+ }
38
+
39
+ /**
40
+ * Push a new path to the browser history.
41
+ *
42
+ * @param {string} path
43
+ */
44
+ export function push(path) {
45
+ window.location.assign(path);
46
+ }
47
+
48
+ /**
49
+ * Replace the current path in browser history.
50
+ *
51
+ * @param {string} path
52
+ */
53
+ export function replace(path) {
54
+ window.location.replace(path);
55
+ }
56
+
57
+ /**
58
+ * Subscribe to popstate (back/forward) events.
59
+ * Returns an unlisten function.
60
+ *
61
+ * @param {(path: string) => void} callback
62
+ * @returns {() => void} unlisten
63
+ */
64
+ export function listen(callback) {
65
+ _ensureListening();
66
+ _listeners.add(callback);
67
+
68
+ return () => {
69
+ _listeners.delete(callback);
70
+ if (_listeners.size === 0) {
71
+ window.removeEventListener('popstate', _onPopState);
72
+ _listening = false;
73
+ }
74
+ };
75
+ }
76
+
77
+ /**
78
+ * Get the current pathname.
79
+ *
80
+ * @returns {string}
81
+ */
82
+ export function current() {
83
+ return window.location.pathname;
84
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * @zenithbuild/router
3
+ *
4
+ * File-based SPA router for Zenith framework.
5
+ * Includes routing, navigation, and ZenLink components.
6
+ *
7
+ * Features:
8
+ * - Deterministic, compile-time route resolution
9
+ * - File-based routing (pages/ directory → routes)
10
+ * - SPA navigation with prefetching
11
+ * - ZenLink component for declarative links
12
+ * - Type-safe route parameters
13
+ * - Hydration-safe, no runtime hacks
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * import { navigate, isActive, prefetch } from '@zenithbuild/router'
18
+ *
19
+ * // Navigate programmatically
20
+ * navigate('/about')
21
+ *
22
+ * // Check active state
23
+ * if (isActive('/blog')) {
24
+ * console.log('On blog section')
25
+ * }
26
+ * ```
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * // Build-time manifest generation
31
+ * import { generateRouteManifest, discoverPages } from '@zenithbuild/router/manifest'
32
+ *
33
+ * const manifest = generateRouteManifest('./src/pages')
34
+ * ```
35
+ */
36
+ export * from "./types";
37
+ export { generateRouteManifest, generateRouteManifestCode } from "./manifest";
38
+ export { initRouter, resolveRoute, navigate, getRoute, onRouteChange, isActive, prefetch, isPrefetched, generateRuntimeRouterCode, zenRoute } from "./runtime";
39
+ export { zenNavigate, zenBack, zenForward, zenGo, zenIsActive, zenPrefetch, zenIsPrefetched, zenGetRoute, zenGetParam, zenGetQuery, createZenLink, zenLink, back, forward, go, getParam, getQuery, isExternalUrl, shouldUseSPANavigation, normalizePath, setGlobalTransition, getGlobalTransition, createTransitionContext } from "./navigation/index";
40
+ export type { ZenLinkProps, TransitionContext, TransitionHandler } from "./navigation/index";
41
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAMH,cAAc,SAAS,CAAA;AAMvB,OAAO,EACH,qBAAqB,EACrB,yBAAyB,EAC5B,MAAM,YAAY,CAAA;AAMnB,OAAO,EACH,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,yBAAyB,EACzB,QAAQ,EACX,MAAM,WAAW,CAAA;AAMlB,OAAO,EAEH,WAAW,EACX,OAAO,EACP,UAAU,EACV,KAAK,EACL,WAAW,EACX,WAAW,EACX,eAAe,EACf,WAAW,EACX,WAAW,EACX,WAAW,EACX,aAAa,EACb,OAAO,EAEP,IAAI,EACJ,OAAO,EACP,EAAE,EACF,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,sBAAsB,EACtB,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,EAC1B,MAAM,oBAAoB,CAAA;AAM3B,YAAY,EACR,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACpB,MAAM,oBAAoB,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ // ---------------------------------------------------------------------------
2
+ // index.js — Zenith Router V0 Public API
3
+ // ---------------------------------------------------------------------------
4
+ // Seven exports. No more.
5
+ // ---------------------------------------------------------------------------
6
+
7
+ export { createRouter } from './router.js';
8
+ export { navigate, back, forward, getCurrentPath } from './navigate.js';
9
+ export { onRouteChange } from './events.js';
10
+ export { matchRoute } from './match.js';
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,+CAA+C;AAC/C,aAAa;AACb,+CAA+C;AAE/C,cAAc,SAAS,CAAA;AAEvB,+CAA+C;AAC/C,iCAAiC;AACjC,+CAA+C;AAE/C,OAAO,EACH,qBAAqB,EACrB,yBAAyB,EAC5B,MAAM,YAAY,CAAA;AAEnB,+CAA+C;AAC/C,iBAAiB;AACjB,+CAA+C;AAE/C,OAAO,EACH,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,yBAAyB,EACzB,QAAQ,EACX,MAAM,WAAW,CAAA;AAElB,+CAA+C;AAC/C,uBAAuB;AACvB,+CAA+C;AAE/C,OAAO;AACH,uCAAuC;AACvC,WAAW,EACX,OAAO,EACP,UAAU,EACV,KAAK,EACL,WAAW,EACX,WAAW,EACX,eAAe,EACf,WAAW,EACX,WAAW,EACX,WAAW,EACX,aAAa,EACb,OAAO;AACP,kCAAkC;AAClC,IAAI,EACJ,OAAO,EACP,EAAE,EACF,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,sBAAsB,EACtB,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,EAC1B,MAAM,oBAAoB,CAAA"}
@@ -0,0 +1,32 @@
1
+ import { type RouteDefinition, type ParsedSegment } from "./types";
2
+ /**
3
+ * Discover all .zen files in the pages directory
4
+ */
5
+ export declare function discoverPages(pagesDir: string): string[];
6
+ /**
7
+ * Convert a file path to a route path
8
+ */
9
+ export declare function filePathToRoutePath(filePath: string, pagesDir: string): string;
10
+ /**
11
+ * Parse a route path into segments
12
+ */
13
+ export declare function parseRouteSegments(routePath: string): ParsedSegment[];
14
+ /**
15
+ * Calculate route score
16
+ */
17
+ export declare function calculateRouteScore(segments: ParsedSegment[]): number;
18
+ /**
19
+ * Extract parameter names
20
+ */
21
+ export declare function extractParamNames(segments: ParsedSegment[]): string[];
22
+ /**
23
+ * Convert route path to regex pattern
24
+ */
25
+ export declare function routePathToRegex(routePath: string): RegExp;
26
+ /**
27
+ * Generate a route definition from a file path
28
+ */
29
+ export declare function generateRouteDefinition(filePath: string, pagesDir: string): RouteDefinition;
30
+ export declare function generateRouteManifest(pagesDir: string): RouteDefinition[];
31
+ export declare function generateRouteManifestCode(definitions: RouteDefinition[]): string;
32
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAGA,OAAO,EACH,KAAK,eAAe,EACpB,KAAK,aAAa,EAErB,MAAM,SAAS,CAAA;AAchB;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAqBxD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAgC9E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,EAAE,CAuBrE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,MAAM,CASrE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,MAAM,EAAE,CAIrE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CA2B1D;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,CAc3F;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,EAAE,CAMzE;AAED,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,eAAe,EAAE,GAAG,MAAM,CAahF"}
@@ -0,0 +1,180 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import native from "../index.js";
4
+ const { generateRouteManifestNative } = native;
5
+ /**
6
+ * Scoring constants for route ranking
7
+ */
8
+ const SEGMENT_SCORES = {
9
+ [0 /* SegmentType.Static */]: 10,
10
+ [1 /* SegmentType.Dynamic */]: 5,
11
+ [2 /* SegmentType.CatchAll */]: 1,
12
+ [3 /* SegmentType.OptionalCatchAll */]: 0
13
+ };
14
+ /**
15
+ * Discover all .zen files in the pages directory
16
+ */
17
+ export function discoverPages(pagesDir) {
18
+ const pages = [];
19
+ function walk(dir) {
20
+ if (!fs.existsSync(dir))
21
+ return;
22
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
23
+ for (const entry of entries) {
24
+ const fullPath = path.join(dir, entry.name);
25
+ if (entry.isDirectory()) {
26
+ walk(fullPath);
27
+ }
28
+ else if (entry.isFile() && entry.name.endsWith(".zen")) {
29
+ pages.push(fullPath);
30
+ }
31
+ }
32
+ }
33
+ walk(pagesDir);
34
+ return pages;
35
+ }
36
+ /**
37
+ * Convert a file path to a route path
38
+ */
39
+ export function filePathToRoutePath(filePath, pagesDir) {
40
+ const relativePath = path.relative(pagesDir, filePath);
41
+ const withoutExt = relativePath.replace(/\.zen$/, "");
42
+ const segmentsList = withoutExt.split(path.sep);
43
+ const routeSegments = [];
44
+ for (const segment of segmentsList) {
45
+ if (segment === "index")
46
+ continue;
47
+ const optionalCatchAllMatch = segment.match(/^\[\[\.\.\.(\w+)\]\]$/);
48
+ if (optionalCatchAllMatch) {
49
+ routeSegments.push(`*${optionalCatchAllMatch[1]}?`);
50
+ continue;
51
+ }
52
+ const catchAllMatch = segment.match(/^\[\.\.\.(\w+)\]$/);
53
+ if (catchAllMatch) {
54
+ routeSegments.push(`*${catchAllMatch[1]}`);
55
+ continue;
56
+ }
57
+ const dynamicMatch = segment.match(/^\[(\w+)\]$/);
58
+ if (dynamicMatch) {
59
+ routeSegments.push(`:${dynamicMatch[1]}`);
60
+ continue;
61
+ }
62
+ routeSegments.push(segment);
63
+ }
64
+ const routePath = "/" + routeSegments.join("/");
65
+ return routePath === "/" ? "/" : routePath.replace(/\/$/, "");
66
+ }
67
+ /**
68
+ * Parse a route path into segments
69
+ */
70
+ export function parseRouteSegments(routePath) {
71
+ if (routePath === "/")
72
+ return [];
73
+ const segmentsList = routePath.slice(1).split("/");
74
+ const parsed = [];
75
+ for (const segment of segmentsList) {
76
+ if (segment.startsWith("*") && segment.endsWith("?")) {
77
+ parsed.push({ segmentType: 3 /* SegmentType.OptionalCatchAll */, paramName: segment.slice(1, -1), raw: segment });
78
+ continue;
79
+ }
80
+ if (segment.startsWith("*")) {
81
+ parsed.push({ segmentType: 2 /* SegmentType.CatchAll */, paramName: segment.slice(1), raw: segment });
82
+ continue;
83
+ }
84
+ if (segment.startsWith(":")) {
85
+ parsed.push({ segmentType: 1 /* SegmentType.Dynamic */, paramName: segment.slice(1), raw: segment });
86
+ continue;
87
+ }
88
+ parsed.push({ segmentType: 0 /* SegmentType.Static */, raw: segment });
89
+ }
90
+ return parsed;
91
+ }
92
+ /**
93
+ * Calculate route score
94
+ */
95
+ export function calculateRouteScore(segments) {
96
+ if (segments.length === 0)
97
+ return 100;
98
+ let score = 0;
99
+ for (const segment of segments) {
100
+ score += SEGMENT_SCORES[segment.segmentType];
101
+ }
102
+ const staticCount = segments.filter(s => s.segmentType === 0 /* SegmentType.Static */).length;
103
+ score += staticCount * 2;
104
+ return score;
105
+ }
106
+ /**
107
+ * Extract parameter names
108
+ */
109
+ export function extractParamNames(segments) {
110
+ return segments
111
+ .filter(s => s.paramName !== undefined)
112
+ .map(s => s.paramName);
113
+ }
114
+ /**
115
+ * Convert route path to regex pattern
116
+ */
117
+ export function routePathToRegex(routePath) {
118
+ if (routePath === "/")
119
+ return /^\/$/;
120
+ const segmentsList = routePath.slice(1).split("/");
121
+ const regexParts = [];
122
+ for (let i = 0; i < segmentsList.length; i++) {
123
+ const segment = segmentsList[i];
124
+ if (!segment)
125
+ continue;
126
+ if (segment.startsWith("*") && segment.endsWith("?")) {
127
+ regexParts.push("(?:\\/(.*))?");
128
+ continue;
129
+ }
130
+ if (segment.startsWith("*")) {
131
+ regexParts.push("\\/(.+)");
132
+ continue;
133
+ }
134
+ if (segment.startsWith(":")) {
135
+ regexParts.push("\\/([^/]+)");
136
+ continue;
137
+ }
138
+ const escaped = segment.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
139
+ regexParts.push(`\\/${escaped}`);
140
+ }
141
+ return new RegExp(`^${regexParts.join("")}\\/?$`);
142
+ }
143
+ /**
144
+ * Generate a route definition from a file path
145
+ */
146
+ export function generateRouteDefinition(filePath, pagesDir) {
147
+ const routePath = filePathToRoutePath(filePath, pagesDir);
148
+ const segments = parseRouteSegments(routePath);
149
+ const paramNames = extractParamNames(segments);
150
+ const score = calculateRouteScore(segments);
151
+ // Note: RouteDefinition extends RouteRecord, which no longer has segments
152
+ return {
153
+ path: routePath,
154
+ paramNames,
155
+ score,
156
+ filePath,
157
+ regex: routePathToRegex(routePath)
158
+ };
159
+ }
160
+ export function generateRouteManifest(pagesDir) {
161
+ // Optional: use native generator if available, but for now we keep the TS one for build-time safety
162
+ const pages = discoverPages(pagesDir);
163
+ const definitions = pages.map(filePath => generateRouteDefinition(filePath, pagesDir));
164
+ definitions.sort((a, b) => b.score - a.score);
165
+ return definitions;
166
+ }
167
+ export function generateRouteManifestCode(definitions) {
168
+ const routeEntries = definitions.map(def => {
169
+ const regex = routePathToRegex(def.path);
170
+ return ` {
171
+ path: ${JSON.stringify(def.path)},
172
+ regex: ${regex.toString()},
173
+ paramNames: ${JSON.stringify(def.paramNames)},
174
+ score: ${def.score},
175
+ filePath: ${JSON.stringify(def.filePath)}
176
+ }`;
177
+ });
178
+ return `// Auto-generated route manifest\n// Do not edit directly\n\nexport const routeManifest = [\n${routeEntries.join(",\n")}\n];\n`;
179
+ }
180
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"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"}