@analogjs/platform 2.7.3-beta.2 → 2.8.0-beta.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.
- package/package.json +3 -3
- package/src/lib/nx-plugin/src/generators/app/versions/nx_18_X/versions.d.ts +5 -5
- package/src/lib/nx-plugin/src/generators/app/versions/nx_18_X/versions.js +5 -5
- package/src/lib/nx-plugin/src/utils/versions/ng_19_X/versions.d.ts +5 -5
- package/src/lib/nx-plugin/src/utils/versions/ng_19_X/versions.js +5 -5
- package/src/lib/options.d.ts +2 -0
- package/src/lib/platform-plugin.js +14 -1
- package/src/lib/route-file-discovery.d.ts +23 -0
- package/src/lib/route-file-discovery.js +147 -0
- package/src/lib/route-manifest.d.ts +104 -0
- package/src/lib/route-manifest.js +338 -0
- package/src/lib/typed-routes-plugin.d.ts +13 -0
- package/src/lib/typed-routes-plugin.js +100 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@analogjs/platform",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.0-beta.2",
|
|
4
4
|
"description": "The fullstack meta-framework for Angular",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Brandon Roberts <robertsbt@gmail.com>",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"nitropack": "^2.13.1",
|
|
32
|
-
"@analogjs/vite-plugin-angular": "^2.
|
|
33
|
-
"@analogjs/vite-plugin-nitro": "^2.
|
|
32
|
+
"@analogjs/vite-plugin-angular": "^2.8.0-beta.2",
|
|
33
|
+
"@analogjs/vite-plugin-nitro": "^2.8.0-beta.2",
|
|
34
34
|
"oxc-parser": "^0.121.0",
|
|
35
35
|
"vitefu": "^1.1.2"
|
|
36
36
|
},
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export declare const V18_X_NX_DEVKIT = "^20.0.0";
|
|
2
2
|
export declare const V18_X_NX_ANGULAR = "^20.0.0";
|
|
3
|
-
export declare const V18_X_ANALOG_JS_CONTENT = "^2.
|
|
4
|
-
export declare const V18_X_ANALOG_JS_ROUTER = "^2.
|
|
3
|
+
export declare const V18_X_ANALOG_JS_CONTENT = "^2.8.0-beta.2";
|
|
4
|
+
export declare const V18_X_ANALOG_JS_ROUTER = "^2.8.0-beta.2";
|
|
5
5
|
export declare const V18_X_ANALOG_JS_TRPC = "~0.4.0";
|
|
6
|
-
export declare const V18_X_ANALOG_JS_VITE_PLUGIN_ANGULAR = "^2.
|
|
7
|
-
export declare const V18_X_ANALOG_JS_VITEST_ANGULAR = "^2.
|
|
6
|
+
export declare const V18_X_ANALOG_JS_VITE_PLUGIN_ANGULAR = "^2.8.0-beta.2";
|
|
7
|
+
export declare const V18_X_ANALOG_JS_VITEST_ANGULAR = "^2.8.0-beta.2";
|
|
8
8
|
export declare const V18_X_TRPC_CLIENT = "^10.25.0";
|
|
9
9
|
export declare const V18_X_TRPC_SERVER = "^10.25.0";
|
|
10
10
|
export declare const V18_X_ISOMORPHIC_FETCH = "^3.0.0";
|
|
@@ -20,7 +20,7 @@ export declare const V18_X_TAILWINDCSS = "^4.1.4";
|
|
|
20
20
|
export declare const V18_X_TAILWINDCSS_VITE = "^4.1.4";
|
|
21
21
|
export declare const V18_X_POSTCSS = "^8.5.3";
|
|
22
22
|
export declare const V18_X_AUTOPREFIXER = "^10.4.0";
|
|
23
|
-
export declare const V18_X_ANALOG_JS_PLATFORM = "^2.
|
|
23
|
+
export declare const V18_X_ANALOG_JS_PLATFORM = "^2.8.0-beta.2";
|
|
24
24
|
export declare const V18_X_ANGULAR_DEVKIT_BUILD_ANGULAR = "^19.0.0";
|
|
25
25
|
export declare const V18_X_NX_VITE = "^21.0.0";
|
|
26
26
|
export declare const V18_X_NX_LINTER = "^21.0.0";
|
|
@@ -5,11 +5,11 @@ exports.V18_X_ZOD = exports.V18_X_VITEST = exports.V18_X_VITE_TSCONFIG_PATHS = e
|
|
|
5
5
|
// dependencies
|
|
6
6
|
exports.V18_X_NX_DEVKIT = '^20.0.0';
|
|
7
7
|
exports.V18_X_NX_ANGULAR = '^20.0.0';
|
|
8
|
-
exports.V18_X_ANALOG_JS_CONTENT = '^2.
|
|
9
|
-
exports.V18_X_ANALOG_JS_ROUTER = '^2.
|
|
8
|
+
exports.V18_X_ANALOG_JS_CONTENT = '^2.8.0-beta.2';
|
|
9
|
+
exports.V18_X_ANALOG_JS_ROUTER = '^2.8.0-beta.2';
|
|
10
10
|
exports.V18_X_ANALOG_JS_TRPC = '~0.4.0';
|
|
11
|
-
exports.V18_X_ANALOG_JS_VITE_PLUGIN_ANGULAR = '^2.
|
|
12
|
-
exports.V18_X_ANALOG_JS_VITEST_ANGULAR = '^2.
|
|
11
|
+
exports.V18_X_ANALOG_JS_VITE_PLUGIN_ANGULAR = '^2.8.0-beta.2';
|
|
12
|
+
exports.V18_X_ANALOG_JS_VITEST_ANGULAR = '^2.8.0-beta.2';
|
|
13
13
|
exports.V18_X_TRPC_CLIENT = '^10.25.0';
|
|
14
14
|
exports.V18_X_TRPC_SERVER = '^10.25.0';
|
|
15
15
|
exports.V18_X_ISOMORPHIC_FETCH = '^3.0.0';
|
|
@@ -26,7 +26,7 @@ exports.V18_X_TAILWINDCSS_VITE = '^4.1.4';
|
|
|
26
26
|
exports.V18_X_POSTCSS = '^8.5.3';
|
|
27
27
|
exports.V18_X_AUTOPREFIXER = '^10.4.0';
|
|
28
28
|
// devDependencies
|
|
29
|
-
exports.V18_X_ANALOG_JS_PLATFORM = '^2.
|
|
29
|
+
exports.V18_X_ANALOG_JS_PLATFORM = '^2.8.0-beta.2';
|
|
30
30
|
exports.V18_X_ANGULAR_DEVKIT_BUILD_ANGULAR = '^19.0.0';
|
|
31
31
|
exports.V18_X_NX_VITE = '^21.0.0';
|
|
32
32
|
exports.V18_X_NX_LINTER = '^21.0.0';
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
export declare const V19_X_ANALOG_JS_ROUTER = "^2.
|
|
2
|
-
export declare const V19_X_ANALOG_JS_CONTENT = "^2.
|
|
1
|
+
export declare const V19_X_ANALOG_JS_ROUTER = "^2.8.0-beta.2";
|
|
2
|
+
export declare const V19_X_ANALOG_JS_CONTENT = "^2.8.0-beta.2";
|
|
3
3
|
export declare const V19_X_MARKED = "^15.0.7";
|
|
4
4
|
export declare const V19_X_MARKED_GFM_HEADING_ID = "^4.1.1";
|
|
5
5
|
export declare const V19_X_MARKED_HIGHLIGHT = "^2.2.1";
|
|
6
6
|
export declare const V19_X_MARKED_MANGLE = "^1.1.10";
|
|
7
7
|
export declare const V19_X_PRISMJS = "^1.29.0";
|
|
8
|
-
export declare const V19_X_ANALOG_JS_PLATFORM = "^2.
|
|
9
|
-
export declare const V19_X_ANALOG_JS_VITE_PLUGIN_ANGULAR = "^2.
|
|
10
|
-
export declare const V19_X_ANALOG_JS_VITEST_ANGULAR = "^2.
|
|
8
|
+
export declare const V19_X_ANALOG_JS_PLATFORM = "^2.8.0-beta.2";
|
|
9
|
+
export declare const V19_X_ANALOG_JS_VITE_PLUGIN_ANGULAR = "^2.8.0-beta.2";
|
|
10
|
+
export declare const V19_X_ANALOG_JS_VITEST_ANGULAR = "^2.8.0-beta.2";
|
|
11
11
|
export declare const V19_X_NX_ANGULAR = "^22.0.0";
|
|
12
12
|
export declare const V19_X_NX_VITE = "^22.0.0";
|
|
13
13
|
export declare const V19_X_JSDOM = "^22.0.0";
|
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.NX_X_LATEST_NX = exports.NX_X_LATEST_VITEST = exports.NX_X_LATEST_VITE = exports.V19_X_VITE = exports.V19_X_VITEST = exports.V19_X_VITE_TSCONFIG_PATHS = exports.V19_X_JSDOM = exports.V19_X_NX_VITE = exports.V19_X_NX_ANGULAR = exports.V19_X_ANALOG_JS_VITEST_ANGULAR = exports.V19_X_ANALOG_JS_VITE_PLUGIN_ANGULAR = exports.V19_X_ANALOG_JS_PLATFORM = exports.V19_X_PRISMJS = exports.V19_X_MARKED_MANGLE = exports.V19_X_MARKED_HIGHLIGHT = exports.V19_X_MARKED_GFM_HEADING_ID = exports.V19_X_MARKED = exports.V19_X_ANALOG_JS_CONTENT = exports.V19_X_ANALOG_JS_ROUTER = void 0;
|
|
4
4
|
// V19_X
|
|
5
|
-
exports.V19_X_ANALOG_JS_ROUTER = '^2.
|
|
6
|
-
exports.V19_X_ANALOG_JS_CONTENT = '^2.
|
|
5
|
+
exports.V19_X_ANALOG_JS_ROUTER = '^2.8.0-beta.2';
|
|
6
|
+
exports.V19_X_ANALOG_JS_CONTENT = '^2.8.0-beta.2';
|
|
7
7
|
exports.V19_X_MARKED = '^15.0.7';
|
|
8
8
|
exports.V19_X_MARKED_GFM_HEADING_ID = '^4.1.1';
|
|
9
9
|
exports.V19_X_MARKED_HIGHLIGHT = '^2.2.1';
|
|
10
10
|
exports.V19_X_MARKED_MANGLE = '^1.1.10';
|
|
11
11
|
exports.V19_X_PRISMJS = '^1.29.0';
|
|
12
12
|
// devDependencies
|
|
13
|
-
exports.V19_X_ANALOG_JS_PLATFORM = '^2.
|
|
14
|
-
exports.V19_X_ANALOG_JS_VITE_PLUGIN_ANGULAR = '^2.
|
|
15
|
-
exports.V19_X_ANALOG_JS_VITEST_ANGULAR = '^2.
|
|
13
|
+
exports.V19_X_ANALOG_JS_PLATFORM = '^2.8.0-beta.2';
|
|
14
|
+
exports.V19_X_ANALOG_JS_VITE_PLUGIN_ANGULAR = '^2.8.0-beta.2';
|
|
15
|
+
exports.V19_X_ANALOG_JS_VITEST_ANGULAR = '^2.8.0-beta.2';
|
|
16
16
|
exports.V19_X_NX_ANGULAR = '^22.0.0';
|
|
17
17
|
exports.V19_X_NX_VITE = '^22.0.0';
|
|
18
18
|
exports.V19_X_JSDOM = '^22.0.0';
|
package/src/lib/options.d.ts
CHANGED
|
@@ -134,6 +134,8 @@ export interface Options {
|
|
|
134
134
|
* Opt-in experimental features that are not yet stable.
|
|
135
135
|
*/
|
|
136
136
|
experimental?: {
|
|
137
|
+
/** Opt into generated route types and typed navigation helpers. */
|
|
138
|
+
typedRouting?: boolean | import('./typed-routes-plugin.js').TypedRoutingOptions;
|
|
137
139
|
/**
|
|
138
140
|
* Opt into progressive streaming SSR. When enabled, the SSR build patches
|
|
139
141
|
* `@angular/core` with a per-`@defer` block resolution hook so
|
|
@@ -2,6 +2,7 @@ import { createRequire } from 'node:module';
|
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import viteNitroPlugin from '@analogjs/vite-plugin-nitro';
|
|
4
4
|
import angular from '@analogjs/vite-plugin-angular';
|
|
5
|
+
import { typedRoutes } from './typed-routes-plugin.js';
|
|
5
6
|
import { routerPlugin } from './router-plugin.js';
|
|
6
7
|
import { ssrBuildPlugin, i18nDefRegistryPlugin, } from './ssr/ssr-build-plugin.js';
|
|
7
8
|
import { deferStreamingPlugin, streamingSupportedOnAngular, MIN_STREAMING_ANGULAR_MAJOR, } from './ssr/defer-streaming-plugin.js';
|
|
@@ -72,6 +73,18 @@ export function platformPlugin(opts = {}) {
|
|
|
72
73
|
};
|
|
73
74
|
}
|
|
74
75
|
return [
|
|
76
|
+
...(platformOptions.experimental?.typedRouting
|
|
77
|
+
? [
|
|
78
|
+
typedRoutes({
|
|
79
|
+
...(typeof platformOptions.experimental.typedRouting === 'object'
|
|
80
|
+
? platformOptions.experimental.typedRouting
|
|
81
|
+
: {}),
|
|
82
|
+
workspaceRoot: platformOptions.workspaceRoot,
|
|
83
|
+
additionalPagesDirs: platformOptions.additionalPagesDirs,
|
|
84
|
+
additionalContentDirs: platformOptions.additionalContentDirs,
|
|
85
|
+
}),
|
|
86
|
+
]
|
|
87
|
+
: []),
|
|
75
88
|
...viteNitroPlugin(platformOptions, nitroOptions),
|
|
76
89
|
...(platformOptions.ssr ? [ssrBuildPlugin(), ...injectHTMLPlugin()] : []),
|
|
77
90
|
...(platformOptions.ssr && platformOptions.experimental?.streaming
|
|
@@ -107,4 +120,4 @@ export function platformPlugin(opts = {}) {
|
|
|
107
120
|
: []),
|
|
108
121
|
];
|
|
109
122
|
}
|
|
110
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
123
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxhdGZvcm0tcGx1Z2luLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvcGxhdGZvcm0vc3JjL2xpYi9wbGF0Zm9ybS1wbHVnaW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUM1QyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ2pDLE9BQU8sZUFBZSxNQUFNLDZCQUE2QixDQUFDO0FBQzFELE9BQU8sT0FBTyxNQUFNLCtCQUErQixDQUFDO0FBRXBELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUV2RCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDbEQsT0FBTyxFQUNMLGNBQWMsRUFDZCxxQkFBcUIsR0FDdEIsTUFBTSwyQkFBMkIsQ0FBQztBQUNuQyxPQUFPLEVBQ0wsb0JBQW9CLEVBQ3BCLDJCQUEyQixFQUMzQiwyQkFBMkIsR0FDNUIsTUFBTSxpQ0FBaUMsQ0FBQztBQUN6QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDcEQsT0FBTyxFQUFFLDhCQUE4QixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDakYsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDNUQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQy9ELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzVELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBRTdEOzs7OztHQUtHO0FBQ0gsU0FBUyxtQkFBbUIsQ0FBQyxhQUFxQjtJQUNoRCxJQUFJLENBQUM7UUFDSCxNQUFNLEdBQUcsR0FBRyxhQUFhLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDO1FBQzFELE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRyxHQUFHLENBQUMsNEJBQTRCLENBRW5ELENBQUM7UUFDRixNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDekQsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztJQUM1QyxDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0FBQ0gsQ0FBQztBQUVELE1BQU0sVUFBVSxjQUFjLENBQUMsT0FBZ0IsRUFBRTtJQUMvQyxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxLQUFLLE1BQU0sSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM3RSxNQUFNLEVBQUUsR0FBRyxlQUFlLEVBQUUsR0FBRztRQUM3QixHQUFHLEVBQUUsSUFBSTtRQUNULEdBQUcsSUFBSTtLQUNSLENBQUM7SUFFRix1RUFBdUU7SUFDdkUsNkVBQTZFO0lBQzdFLDBFQUEwRTtJQUMxRSw4RUFBOEU7SUFDOUUsa0VBQWtFO0lBQ2xFLElBQUksZUFBZSxDQUFDLEdBQUcsSUFBSSxlQUFlLENBQUMsWUFBWSxFQUFFLFNBQVMsRUFBRSxDQUFDO1FBQ25FLE1BQU0sS0FBSyxHQUFHLG1CQUFtQixDQUMvQixlQUFlLENBQUMsYUFBYSxJQUFJLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FDL0MsQ0FBQztRQUNGLElBQUksQ0FBQywyQkFBMkIsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ3hDLE9BQU8sQ0FBQyxJQUFJLENBQ1YsK0RBQStEO2dCQUM3RCxHQUFHLDJCQUEyQixnQkFBZ0IsS0FBSyxrQkFBa0I7Z0JBQ3JFLG9EQUFvRCxDQUN2RCxDQUFDO1lBQ0YsZUFBZSxDQUFDLFlBQVksR0FBRztnQkFDN0IsR0FBRyxlQUFlLENBQUMsWUFBWTtnQkFDL0IsU0FBUyxFQUFFLEtBQUs7YUFDakIsQ0FBQztRQUNKLENBQUM7SUFDSCxDQUFDO0lBRUQsSUFBSSxZQUFZLEdBQUcsZUFBZSxFQUFFLEtBQUssQ0FBQztJQUUxQyxJQUFJLFlBQVksRUFBRSxVQUFVLEVBQUUsQ0FBQztRQUM3QixZQUFZLEdBQUc7WUFDYixHQUFHLFlBQVk7WUFDZixVQUFVLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsVUFBVSxDQUFDLENBQUMsTUFBTSxDQUNyRCxDQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsRUFBRTtnQkFDZixPQUFPO29CQUNMLEdBQUcsTUFBTTtvQkFDVCxDQUFDLElBQUksQ0FBQyxFQUFFO3dCQUNOLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQzt3QkFDZixPQUFPLEVBQUU7NEJBQ1AsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTzs0QkFDdkIsaUJBQWlCLEVBQ2YsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLEdBQUcsS0FBSyxLQUFLLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsU0FBUzs0QkFDbEQsdUJBQXVCLEVBQ3JCLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxTQUFTLEtBQUssS0FBSyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLFNBQVM7eUJBQ2xEO3FCQUNUO2lCQUNGLENBQUM7WUFDSixDQUFDLEVBQ0QsWUFBWSxDQUFDLFVBQVUsQ0FDeEI7U0FDRixDQUFDO0lBQ0osQ0FBQztJQUVELE9BQU87UUFDTCxHQUFHLENBQUMsZUFBZSxDQUFDLFlBQVksRUFBRSxZQUFZO1lBQzVDLENBQUMsQ0FBQztnQkFDRSxXQUFXLENBQUM7b0JBQ1YsR0FBRyxDQUFDLE9BQU8sZUFBZSxDQUFDLFlBQVksQ0FBQyxZQUFZLEtBQUssUUFBUTt3QkFDL0QsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxZQUFZLENBQUMsWUFBWTt3QkFDM0MsQ0FBQyxDQUFDLEVBQUUsQ0FBQztvQkFDUCxhQUFhLEVBQUUsZUFBZSxDQUFDLGFBQWE7b0JBQzVDLG1CQUFtQixFQUFFLGVBQWUsQ0FBQyxtQkFBbUI7b0JBQ3hELHFCQUFxQixFQUFFLGVBQWUsQ0FBQyxxQkFBcUI7aUJBQzdELENBQUM7YUFDSDtZQUNILENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDUCxHQUFHLGVBQWUsQ0FBQyxlQUFlLEVBQUUsWUFBWSxDQUFDO1FBQ2pELEdBQUcsQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLGNBQWMsRUFBRSxFQUFFLEdBQUcsZ0JBQWdCLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDekUsR0FBRyxDQUFDLGVBQWUsQ0FBQyxHQUFHLElBQUksZUFBZSxDQUFDLFlBQVksRUFBRSxTQUFTO1lBQ2hFLENBQUMsQ0FBQyxDQUFDLG9CQUFvQixFQUFFLENBQUM7WUFDMUIsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUNQLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDL0MsR0FBRyxZQUFZLENBQUMsZUFBZSxDQUFDO1FBQ2hDLEdBQUcsYUFBYSxDQUFDLGVBQWUsRUFBRSxPQUFPLEVBQUUsZUFBZSxDQUFDO1FBQzNELEdBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxLQUFLLEtBQUs7WUFDdkIsQ0FBQyxDQUFDLEVBQUU7WUFDSixDQUFDLENBQUMsT0FBTyxDQUFDO2dCQUNOLEdBQUcsRUFBRSxlQUFlLENBQUMsR0FBRztnQkFDeEIsYUFBYSxFQUFFLGVBQWUsQ0FBQyxhQUFhO2dCQUM1QyxtQkFBbUIsRUFBRSxlQUFlLENBQUMsbUJBQW1CLElBQUksS0FBSztnQkFDakUsT0FBTyxFQUFFO29CQUNQLEdBQUcsQ0FBQyxlQUFlLENBQUMsT0FBTyxJQUFJLEVBQUUsQ0FBQztvQkFDbEMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxtQkFBbUIsSUFBSSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQ2hELENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxHQUFHLE9BQU8sZUFBZSxDQUN2QztpQkFDRjtnQkFDRCxxQkFBcUIsRUFBRSxlQUFlLENBQUMscUJBQXFCO2dCQUM1RCxVQUFVLEVBQUUsZUFBZSxDQUFDLFVBQVU7Z0JBQ3RDLHFCQUFxQixFQUFFLGVBQWUsQ0FBQyxxQkFBcUI7Z0JBQzVELGdCQUFnQixFQUFFLGVBQWUsQ0FBQyxnQkFBZ0I7Z0JBQ2xELFdBQVcsRUFBRSxlQUFlLENBQUMsV0FBVztnQkFDeEMsZUFBZSxFQUFFLGVBQWUsQ0FBQyxlQUFlO2dCQUNoRCxHQUFHLENBQUMsSUFBSSxFQUFFLElBQUksSUFBSSxFQUFFLENBQUM7YUFDdEIsQ0FBQyxDQUFTO1FBQ2YsZ0JBQWdCLEVBQUU7UUFDbEIsaUJBQWlCLEVBQVk7UUFDN0IsOEJBQThCLEVBQVk7UUFDMUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMscUJBQXFCLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDMUQsR0FBRyxDQUFDLGVBQWUsQ0FBQyxJQUFJLEVBQUUsT0FBTztZQUMvQixDQUFDLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDM0MsQ0FBQyxDQUFDLEVBQUUsQ0FBQztLQUNSLENBQUM7QUFDSixDQUFDIn0=
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface RouteFileDiscoveryOptions {
|
|
2
|
+
root: string;
|
|
3
|
+
workspaceRoot: string;
|
|
4
|
+
additionalPagesDirs: string[];
|
|
5
|
+
additionalContentDirs: string[];
|
|
6
|
+
}
|
|
7
|
+
export interface RouteFileDiscovery {
|
|
8
|
+
getRouteFiles(): string[];
|
|
9
|
+
getContentFiles(): string[];
|
|
10
|
+
getDiscoveredFileKind(path: string): 'route' | 'content' | null;
|
|
11
|
+
updateDiscoveredFile(path: string, event: 'add' | 'change' | 'unlink'): void;
|
|
12
|
+
/**
|
|
13
|
+
* Returns true if the normalized filename was discovered from an app-local
|
|
14
|
+
* glob (under the configured root) rather than from an additional directory.
|
|
15
|
+
*
|
|
16
|
+
* Used by collision priority to prefer app-local routes over shared/external
|
|
17
|
+
* routes based on actual configured roots instead of hard-coded path
|
|
18
|
+
* substrings.
|
|
19
|
+
*/
|
|
20
|
+
isAppLocal(normalizedFilename: string): boolean;
|
|
21
|
+
reset(): void;
|
|
22
|
+
}
|
|
23
|
+
export declare function createRouteFileDiscovery(options: RouteFileDiscoveryOptions): RouteFileDiscovery;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { normalizePath } from 'vite';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { globSync } from 'tinyglobby';
|
|
4
|
+
export function createRouteFileDiscovery(options) {
|
|
5
|
+
const { root, workspaceRoot, additionalPagesDirs, additionalContentDirs } = options;
|
|
6
|
+
let routeFilesCache = new Set();
|
|
7
|
+
let contentFilesCache = new Set();
|
|
8
|
+
let appLocalFilesCache = new Set();
|
|
9
|
+
let initialized = false;
|
|
10
|
+
const joinDir = (dir) => isWithinDir(dir, workspaceRoot)
|
|
11
|
+
? normalizePath(dir)
|
|
12
|
+
: dir.startsWith('/')
|
|
13
|
+
? normalizePath(`${workspaceRoot}${dir}`)
|
|
14
|
+
: normalizePath(resolve(workspaceRoot, dir));
|
|
15
|
+
const additionalPagesRoots = additionalPagesDirs.map(joinDir);
|
|
16
|
+
const additionalContentRoots = additionalContentDirs.map(joinDir);
|
|
17
|
+
function normalizePath_(absolutePath) {
|
|
18
|
+
const normalized = normalizePath(absolutePath);
|
|
19
|
+
if (isWithinDir(normalized, root)) {
|
|
20
|
+
return normalized.slice(root.length);
|
|
21
|
+
}
|
|
22
|
+
if (isWithinDir(normalized, workspaceRoot)) {
|
|
23
|
+
return normalized.slice(workspaceRoot.length);
|
|
24
|
+
}
|
|
25
|
+
return normalized;
|
|
26
|
+
}
|
|
27
|
+
function isWithinDir(path, dir) {
|
|
28
|
+
return path === dir || path.startsWith(`${dir}/`);
|
|
29
|
+
}
|
|
30
|
+
function getAppLocalFileKind(path) {
|
|
31
|
+
if (path.endsWith('.md') &&
|
|
32
|
+
['src/app/routes', 'src/app/pages', 'src/content'].some((dir) => isWithinDir(path, `${root}/${dir}`)))
|
|
33
|
+
return 'content';
|
|
34
|
+
if ((path.endsWith('.ts') &&
|
|
35
|
+
['app/routes', 'src/app/routes'].some((dir) => isWithinDir(path, `${root}/${dir}`))) ||
|
|
36
|
+
(path.endsWith('.page.ts') && isWithinDir(path, `${root}/src/app/pages`)))
|
|
37
|
+
return 'route';
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
function getDiscoveredFileKind(path) {
|
|
41
|
+
const normalized = normalizePath(path);
|
|
42
|
+
const localKind = getAppLocalFileKind(normalized);
|
|
43
|
+
if (localKind)
|
|
44
|
+
return localKind;
|
|
45
|
+
if (normalized.endsWith('.md') &&
|
|
46
|
+
additionalContentRoots.some((dir) => isWithinDir(normalized, dir))) {
|
|
47
|
+
return 'content';
|
|
48
|
+
}
|
|
49
|
+
if (normalized.endsWith('.page.ts') &&
|
|
50
|
+
additionalPagesRoots.some((dir) => isWithinDir(normalized, dir))) {
|
|
51
|
+
return 'route';
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
function scanRouteFiles() {
|
|
56
|
+
const appLocalGlobs = [
|
|
57
|
+
`${root}/app/routes/**/*.ts`,
|
|
58
|
+
`${root}/src/app/routes/**/*.ts`,
|
|
59
|
+
`${root}/src/app/pages/**/*.page.ts`,
|
|
60
|
+
];
|
|
61
|
+
const additionalGlobs = additionalPagesDirs.map((dir) => `${joinDir(dir)}/**/*.page.ts`);
|
|
62
|
+
const appLocal = globSync(appLocalGlobs, {
|
|
63
|
+
dot: true,
|
|
64
|
+
absolute: true,
|
|
65
|
+
}).map(normalizePath_);
|
|
66
|
+
const additional = globSync(additionalGlobs, {
|
|
67
|
+
dot: true,
|
|
68
|
+
absolute: true,
|
|
69
|
+
}).map(normalizePath_);
|
|
70
|
+
for (const f of appLocal) {
|
|
71
|
+
appLocalFilesCache.add(f);
|
|
72
|
+
}
|
|
73
|
+
return [...appLocal, ...additional];
|
|
74
|
+
}
|
|
75
|
+
function scanContentFiles() {
|
|
76
|
+
const appLocalGlobs = [
|
|
77
|
+
`${root}/src/app/routes/**/*.md`,
|
|
78
|
+
`${root}/src/app/pages/**/*.md`,
|
|
79
|
+
`${root}/src/content/**/*.md`,
|
|
80
|
+
];
|
|
81
|
+
const additionalGlobs = additionalContentDirs.map((dir) => `${joinDir(dir)}/**/*.md`);
|
|
82
|
+
const appLocal = globSync(appLocalGlobs, {
|
|
83
|
+
dot: true,
|
|
84
|
+
absolute: true,
|
|
85
|
+
}).map(normalizePath_);
|
|
86
|
+
const additional = globSync(additionalGlobs, {
|
|
87
|
+
dot: true,
|
|
88
|
+
absolute: true,
|
|
89
|
+
}).map(normalizePath_);
|
|
90
|
+
for (const f of appLocal) {
|
|
91
|
+
appLocalFilesCache.add(f);
|
|
92
|
+
}
|
|
93
|
+
return [...appLocal, ...additional];
|
|
94
|
+
}
|
|
95
|
+
function isAppLocalByPath(absolutePath) {
|
|
96
|
+
const normalized = normalizePath(absolutePath);
|
|
97
|
+
return getAppLocalFileKind(normalized) !== null;
|
|
98
|
+
}
|
|
99
|
+
function ensureInitialized() {
|
|
100
|
+
if (initialized) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
routeFilesCache = new Set(scanRouteFiles());
|
|
104
|
+
contentFilesCache = new Set(scanContentFiles());
|
|
105
|
+
initialized = true;
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
getRouteFiles() {
|
|
109
|
+
ensureInitialized();
|
|
110
|
+
return [...routeFilesCache].sort();
|
|
111
|
+
},
|
|
112
|
+
getContentFiles() {
|
|
113
|
+
ensureInitialized();
|
|
114
|
+
return [...contentFilesCache].sort();
|
|
115
|
+
},
|
|
116
|
+
getDiscoveredFileKind(path) {
|
|
117
|
+
return getDiscoveredFileKind(path);
|
|
118
|
+
},
|
|
119
|
+
updateDiscoveredFile(path, event) {
|
|
120
|
+
ensureInitialized();
|
|
121
|
+
const kind = getDiscoveredFileKind(path);
|
|
122
|
+
if (!kind) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const normalizedPath = normalizePath_(path);
|
|
126
|
+
const targetCache = kind === 'content' ? contentFilesCache : routeFilesCache;
|
|
127
|
+
if (event === 'unlink') {
|
|
128
|
+
targetCache.delete(normalizedPath);
|
|
129
|
+
appLocalFilesCache.delete(normalizedPath);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
targetCache.add(normalizedPath);
|
|
133
|
+
if (isAppLocalByPath(path)) {
|
|
134
|
+
appLocalFilesCache.add(normalizedPath);
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
isAppLocal(normalizedFilename) {
|
|
138
|
+
ensureInitialized();
|
|
139
|
+
return appLocalFilesCache.has(normalizedFilename);
|
|
140
|
+
},
|
|
141
|
+
reset() {
|
|
142
|
+
initialized = false;
|
|
143
|
+
appLocalFilesCache = new Set();
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUtZmlsZS1kaXNjb3ZlcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9wbGF0Zm9ybS9zcmMvbGliL3JvdXRlLWZpbGUtZGlzY292ZXJ5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDckMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNwQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBMEJ0QyxNQUFNLFVBQVUsd0JBQXdCLENBQ3RDLE9BQWtDO0lBRWxDLE1BQU0sRUFBRSxJQUFJLEVBQUUsYUFBYSxFQUFFLG1CQUFtQixFQUFFLHFCQUFxQixFQUFFLEdBQ3ZFLE9BQU8sQ0FBQztJQUVWLElBQUksZUFBZSxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7SUFDeEMsSUFBSSxpQkFBaUIsR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO0lBQzFDLElBQUksa0JBQWtCLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQUMzQyxJQUFJLFdBQVcsR0FBRyxLQUFLLENBQUM7SUFDeEIsTUFBTSxPQUFPLEdBQUcsQ0FBQyxHQUFXLEVBQUUsRUFBRSxDQUM5QixXQUFXLENBQUMsR0FBRyxFQUFFLGFBQWEsQ0FBQztRQUM3QixDQUFDLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQztRQUNwQixDQUFDLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUM7WUFDbkIsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxHQUFHLGFBQWEsR0FBRyxHQUFHLEVBQUUsQ0FBQztZQUN6QyxDQUFDLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxhQUFhLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNuRCxNQUFNLG9CQUFvQixHQUFHLG1CQUFtQixDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM5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
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route-manifest engine for typed file routes.
|
|
3
|
+
*
|
|
4
|
+
* Pure functions (no Angular dependencies) for converting discovered
|
|
5
|
+
* filenames into typed route manifests and generated declarations.
|
|
6
|
+
*/
|
|
7
|
+
export interface RouteParamInfo {
|
|
8
|
+
name: string;
|
|
9
|
+
type: 'dynamic' | 'catchAll' | 'optionalCatchAll';
|
|
10
|
+
}
|
|
11
|
+
export interface RouteEntry {
|
|
12
|
+
/** Stable structural route id derived from the source filename */
|
|
13
|
+
id: string;
|
|
14
|
+
/** The route path segment relative to the nearest existing parent route */
|
|
15
|
+
path: string;
|
|
16
|
+
/** The fully resolved navigation path pattern (e.g., '/users/[id]') */
|
|
17
|
+
fullPath: string;
|
|
18
|
+
/** Extracted parameter information */
|
|
19
|
+
params: RouteParamInfo[];
|
|
20
|
+
/** Original filename that produced this route */
|
|
21
|
+
filename: string;
|
|
22
|
+
/** Type of source that produced this route */
|
|
23
|
+
kind: 'page' | 'content';
|
|
24
|
+
/** Parent route id, or null for top-level routes */
|
|
25
|
+
parentId: string | null;
|
|
26
|
+
/** Child route ids */
|
|
27
|
+
children: string[];
|
|
28
|
+
/** Whether the source filename represents an index route */
|
|
29
|
+
isIndex: boolean;
|
|
30
|
+
/** Whether the source filename includes route-group/pathless segments */
|
|
31
|
+
isGroup: boolean;
|
|
32
|
+
/** Whether the route contains a required catch-all parameter */
|
|
33
|
+
isCatchAll: boolean;
|
|
34
|
+
/** Whether the route contains an optional catch-all parameter */
|
|
35
|
+
isOptionalCatchAll: boolean;
|
|
36
|
+
}
|
|
37
|
+
export interface RouteCollision {
|
|
38
|
+
fullPath: string;
|
|
39
|
+
keptFile: string;
|
|
40
|
+
droppedFile: string;
|
|
41
|
+
/** True when both files have the same collision priority (hard error). */
|
|
42
|
+
samePriority: boolean;
|
|
43
|
+
}
|
|
44
|
+
export interface RouteManifest {
|
|
45
|
+
routes: RouteEntry[];
|
|
46
|
+
collisions: RouteCollision[];
|
|
47
|
+
/** Canonical route per fullPath — precomputed once to avoid redundant work. */
|
|
48
|
+
canonicalByFullPath: Map<string, RouteEntry>;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Converts a discovered filename to a route path pattern.
|
|
52
|
+
*
|
|
53
|
+
* Uses the same stripping rules as the existing route system
|
|
54
|
+
* but preserves bracket param syntax instead of converting to
|
|
55
|
+
* Angular's `:param` syntax.
|
|
56
|
+
*
|
|
57
|
+
* The regex applies four alternations (left to right, all replaced with ''):
|
|
58
|
+
* 1. `^(.*?)[\\/](?:routes|pages|content)[\\/]` — anchored, strips everything
|
|
59
|
+
* up to and including the first /routes/, /pages/, or /content/ segment.
|
|
60
|
+
* Handles app-local paths (`/src/app/pages/`) AND additional dirs
|
|
61
|
+
* (`/libs/shared/feature/src/content/`) uniformly.
|
|
62
|
+
* 2. `[\\/](?:app[\\/](?:routes|pages)|src[\\/]content)[\\/]` — non-anchored
|
|
63
|
+
* fallback for legacy paths where the directory marker appears mid-string.
|
|
64
|
+
* 3. `\.page\.(js|ts|analog|ag)$` — strips page file extensions.
|
|
65
|
+
* 4. `\.(ts|md|analog|ag)$` — strips remaining file extensions.
|
|
66
|
+
*
|
|
67
|
+
* Examples:
|
|
68
|
+
* - '/app/routes/index.ts' -> '/'
|
|
69
|
+
* - '/app/routes/about.ts' -> '/about'
|
|
70
|
+
* - '/src/app/pages/users/[id].page.ts' -> '/users/[id]'
|
|
71
|
+
* - '/app/routes/blog.[slug].ts' -> '/blog/[slug]'
|
|
72
|
+
* - '/src/app/pages/(auth)/login.page.ts' -> '/login'
|
|
73
|
+
* - '/src/app/pages/docs/[...slug].page.ts' -> '/docs/[...slug]'
|
|
74
|
+
* - '/src/app/pages/shop/[[...category]].page.ts' -> '/shop/[[...category]]'
|
|
75
|
+
* - '/libs/shared/feature/src/content/test.md' -> '/test'
|
|
76
|
+
*/
|
|
77
|
+
export declare function filenameToRoutePath(filename: string): string;
|
|
78
|
+
/**
|
|
79
|
+
* Converts a discovered filename to a stable structural route id.
|
|
80
|
+
*
|
|
81
|
+
* Unlike `filenameToRoutePath`, this preserves route groups and `index`
|
|
82
|
+
* segments so that multiple files resolving to the same URL shape can still
|
|
83
|
+
* have distinct structural identities in the generated route tree metadata.
|
|
84
|
+
*
|
|
85
|
+
* Uses the same directory-stripping regex as `filenameToRoutePath` —
|
|
86
|
+
* changes to the regex must be kept in sync between both functions.
|
|
87
|
+
*/
|
|
88
|
+
export declare function filenameToRouteId(filename: string): string;
|
|
89
|
+
/**
|
|
90
|
+
* Extracts parameter information from a route path pattern.
|
|
91
|
+
*/
|
|
92
|
+
export declare function extractRouteParams(routePath: string): RouteParamInfo[];
|
|
93
|
+
/**
|
|
94
|
+
* Generates a route manifest from a list of discovered filenames.
|
|
95
|
+
*
|
|
96
|
+
* @param collisionPriority - Optional callback that returns a numeric priority
|
|
97
|
+
* for each filename (lower wins). When provided, this replaces the default
|
|
98
|
+
* hard-coded path-substring heuristic with config-derived precedence.
|
|
99
|
+
*/
|
|
100
|
+
export declare function generateRouteManifest(filenames: string[], collisionPriority?: (filename: string) => number): RouteManifest;
|
|
101
|
+
/**
|
|
102
|
+
* Generates the route-table section for the combined generated route module.
|
|
103
|
+
*/
|
|
104
|
+
export declare function generateRouteTableDeclaration(manifest: RouteManifest): string;
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route-manifest engine for typed file routes.
|
|
3
|
+
*
|
|
4
|
+
* Pure functions (no Angular dependencies) for converting discovered
|
|
5
|
+
* filenames into typed route manifests and generated declarations.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Converts a discovered filename to a route path pattern.
|
|
9
|
+
*
|
|
10
|
+
* Uses the same stripping rules as the existing route system
|
|
11
|
+
* but preserves bracket param syntax instead of converting to
|
|
12
|
+
* Angular's `:param` syntax.
|
|
13
|
+
*
|
|
14
|
+
* The regex applies four alternations (left to right, all replaced with ''):
|
|
15
|
+
* 1. `^(.*?)[\\/](?:routes|pages|content)[\\/]` — anchored, strips everything
|
|
16
|
+
* up to and including the first /routes/, /pages/, or /content/ segment.
|
|
17
|
+
* Handles app-local paths (`/src/app/pages/`) AND additional dirs
|
|
18
|
+
* (`/libs/shared/feature/src/content/`) uniformly.
|
|
19
|
+
* 2. `[\\/](?:app[\\/](?:routes|pages)|src[\\/]content)[\\/]` — non-anchored
|
|
20
|
+
* fallback for legacy paths where the directory marker appears mid-string.
|
|
21
|
+
* 3. `\.page\.(js|ts|analog|ag)$` — strips page file extensions.
|
|
22
|
+
* 4. `\.(ts|md|analog|ag)$` — strips remaining file extensions.
|
|
23
|
+
*
|
|
24
|
+
* Examples:
|
|
25
|
+
* - '/app/routes/index.ts' -> '/'
|
|
26
|
+
* - '/app/routes/about.ts' -> '/about'
|
|
27
|
+
* - '/src/app/pages/users/[id].page.ts' -> '/users/[id]'
|
|
28
|
+
* - '/app/routes/blog.[slug].ts' -> '/blog/[slug]'
|
|
29
|
+
* - '/src/app/pages/(auth)/login.page.ts' -> '/login'
|
|
30
|
+
* - '/src/app/pages/docs/[...slug].page.ts' -> '/docs/[...slug]'
|
|
31
|
+
* - '/src/app/pages/shop/[[...category]].page.ts' -> '/shop/[[...category]]'
|
|
32
|
+
* - '/libs/shared/feature/src/content/test.md' -> '/test'
|
|
33
|
+
*/
|
|
34
|
+
export function filenameToRoutePath(filename) {
|
|
35
|
+
let path = filename.replace(/^(?:[a-zA-Z]:[\\/])?(.*?)[\\/](?:routes|pages|content)[\\/]|(?:[\\/](?:app[\\/](?:routes|pages)|src[\\/]content)[\\/])|(\.page\.(js|ts|analog|ag)$)|(\.(ts|md|analog|ag)$)/g, '');
|
|
36
|
+
const brackets = [];
|
|
37
|
+
path = path.replace(/\[\[?\.{0,3}[^\]]*\]?\]/g, (match) => {
|
|
38
|
+
brackets.push(match);
|
|
39
|
+
// eslint-disable-next-line no-control-regex
|
|
40
|
+
return `\0B${brackets.length - 1}\0`;
|
|
41
|
+
});
|
|
42
|
+
// Match beta's toSegment ordering: strip index and named empty segments
|
|
43
|
+
// before expanding dot notation, at every nesting level.
|
|
44
|
+
path = path.replace(/index|\(.*?\)/g, '').replace(/\./g, '/');
|
|
45
|
+
// eslint-disable-next-line no-control-regex
|
|
46
|
+
path = path.replace(/\0B(\d+)\0/g, (_, idx) => brackets[Number(idx)]);
|
|
47
|
+
return '/' + path.split('/').filter(Boolean).join('/');
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Converts a discovered filename to a stable structural route id.
|
|
51
|
+
*
|
|
52
|
+
* Unlike `filenameToRoutePath`, this preserves route groups and `index`
|
|
53
|
+
* segments so that multiple files resolving to the same URL shape can still
|
|
54
|
+
* have distinct structural identities in the generated route tree metadata.
|
|
55
|
+
*
|
|
56
|
+
* Uses the same directory-stripping regex as `filenameToRoutePath` —
|
|
57
|
+
* changes to the regex must be kept in sync between both functions.
|
|
58
|
+
*/
|
|
59
|
+
export function filenameToRouteId(filename) {
|
|
60
|
+
let path = filename.replace(/^(?:[a-zA-Z]:[\\/])?(.*?)[\\/](?:routes|pages|content)[\\/]|(?:[\\/](?:app[\\/](?:routes|pages)|src[\\/]content)[\\/])|(\.page\.(js|ts|analog|ag)$)|(\.(ts|md|analog|ag)$)/g, '');
|
|
61
|
+
const brackets = [];
|
|
62
|
+
path = path.replace(/\(.*?\)|\[\[?\.{0,3}[^\]]*\]?\]/g, (match) => {
|
|
63
|
+
brackets.push(match);
|
|
64
|
+
// eslint-disable-next-line no-control-regex
|
|
65
|
+
return `\0B${brackets.length - 1}\0`;
|
|
66
|
+
});
|
|
67
|
+
path = path.replace(/\./g, '/');
|
|
68
|
+
// eslint-disable-next-line no-control-regex
|
|
69
|
+
path = path.replace(/\0B(\d+)\0/g, (_, idx) => brackets[Number(idx)]);
|
|
70
|
+
const segments = path.split('/').filter(Boolean);
|
|
71
|
+
return '/' + segments.join('/');
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Extracts parameter information from a route path pattern.
|
|
75
|
+
*/
|
|
76
|
+
export function extractRouteParams(routePath) {
|
|
77
|
+
const params = [];
|
|
78
|
+
for (const match of routePath.matchAll(/\[\[\.\.\.([^\]]+)\]\]/g)) {
|
|
79
|
+
params.push({ name: match[1], type: 'optionalCatchAll' });
|
|
80
|
+
}
|
|
81
|
+
for (const match of routePath.matchAll(/(?<!\[)\[\.\.\.([^\]]+)\](?!\])/g)) {
|
|
82
|
+
params.push({ name: match[1], type: 'catchAll' });
|
|
83
|
+
}
|
|
84
|
+
for (const match of routePath.matchAll(/(?<!\[)\[(?!\.)([^\]]+)\](?!\])/g)) {
|
|
85
|
+
params.push({ name: match[1], type: 'dynamic' });
|
|
86
|
+
}
|
|
87
|
+
return params;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Generates a route manifest from a list of discovered filenames.
|
|
91
|
+
*
|
|
92
|
+
* @param collisionPriority - Optional callback that returns a numeric priority
|
|
93
|
+
* for each filename (lower wins). When provided, this replaces the default
|
|
94
|
+
* hard-coded path-substring heuristic with config-derived precedence.
|
|
95
|
+
*/
|
|
96
|
+
export function generateRouteManifest(filenames, collisionPriority) {
|
|
97
|
+
const routes = [];
|
|
98
|
+
const collisions = [];
|
|
99
|
+
const seenByFullPath = new Map();
|
|
100
|
+
const getPriority = collisionPriority ?? getCollisionPriority;
|
|
101
|
+
// Prefer app-local route files over shared/external sources when two files
|
|
102
|
+
// resolve to the same URL. This keeps `additionalPagesDirs` additive instead
|
|
103
|
+
// of unexpectedly overriding the route that lives inside the app itself.
|
|
104
|
+
const prioritizedFilenames = [...filenames].sort((a, b) => {
|
|
105
|
+
const aPriority = getPriority(a);
|
|
106
|
+
const bPriority = getPriority(b);
|
|
107
|
+
if (aPriority !== bPriority) {
|
|
108
|
+
return aPriority - bPriority;
|
|
109
|
+
}
|
|
110
|
+
return a.localeCompare(b);
|
|
111
|
+
});
|
|
112
|
+
for (const filename of prioritizedFilenames) {
|
|
113
|
+
const fullPath = filenameToRoutePath(filename);
|
|
114
|
+
const params = extractRouteParams(fullPath);
|
|
115
|
+
const id = filenameToRouteId(filename);
|
|
116
|
+
const isPathlessLayout = isPathlessLayoutId(id);
|
|
117
|
+
// Different pathless branches can select the same URL with canMatch guards.
|
|
118
|
+
const groupScope = id.slice(0, id.lastIndexOf(')') + 1);
|
|
119
|
+
const collisionKey = JSON.stringify([fullPath, groupScope]);
|
|
120
|
+
const currentPriority = getPriority(filename);
|
|
121
|
+
// Pathless layouts (e.g. (auth).page.ts) are structural wrappers that
|
|
122
|
+
// render a <router-outlet> — they coexist with index.page.ts at the same
|
|
123
|
+
// fullPath without collision. The Angular router handles them as nested
|
|
124
|
+
// layout routes, not competing page components.
|
|
125
|
+
if (!isPathlessLayout) {
|
|
126
|
+
if (seenByFullPath.has(collisionKey)) {
|
|
127
|
+
const winner = seenByFullPath.get(collisionKey);
|
|
128
|
+
if (winner.filename === filename) {
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
// A layout file (e.g., docs.page.ts) and its index child
|
|
132
|
+
// (e.g., docs/index.page.ts) intentionally share the same route
|
|
133
|
+
// path — the layout wraps the index as a parent-child pair.
|
|
134
|
+
const isLayoutIndexPair = (a, b) => {
|
|
135
|
+
const indexRe = /\/index\.(page\.)?(ts|js|md|analog|ag)$/;
|
|
136
|
+
const layoutRe = /\.(page\.)?(ts|js|analog|ag)$/;
|
|
137
|
+
if (indexRe.test(a) && layoutRe.test(b)) {
|
|
138
|
+
const dir = a.replace(indexRe, '');
|
|
139
|
+
const layout = b.replace(layoutRe, '');
|
|
140
|
+
return dir === layout;
|
|
141
|
+
}
|
|
142
|
+
return false;
|
|
143
|
+
};
|
|
144
|
+
if (isLayoutIndexPair(winner.filename, filename) ||
|
|
145
|
+
isLayoutIndexPair(filename, winner.filename)) {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
collisions.push({
|
|
149
|
+
fullPath,
|
|
150
|
+
keptFile: winner.filename,
|
|
151
|
+
droppedFile: filename,
|
|
152
|
+
samePriority: winner.priority === currentPriority,
|
|
153
|
+
});
|
|
154
|
+
console.warn(`[Analog] Route collision: '${fullPath}' is defined by both ` +
|
|
155
|
+
`'${winner.filename}' and '${filename}'. ` +
|
|
156
|
+
`Keeping '${winner.filename}' based on route source precedence and skipping duplicate.`);
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
seenByFullPath.set(collisionKey, { filename, priority: currentPriority });
|
|
160
|
+
}
|
|
161
|
+
routes.push({
|
|
162
|
+
id,
|
|
163
|
+
path: fullPath,
|
|
164
|
+
fullPath,
|
|
165
|
+
params,
|
|
166
|
+
filename,
|
|
167
|
+
kind: filename.endsWith('.md') ? 'content' : 'page',
|
|
168
|
+
parentId: null,
|
|
169
|
+
children: [],
|
|
170
|
+
isIndex: id === '/index' || id.endsWith('/index'),
|
|
171
|
+
isGroup: isPathlessLayout,
|
|
172
|
+
isCatchAll: params.some((param) => param.type === 'catchAll'),
|
|
173
|
+
isOptionalCatchAll: params.some((param) => param.type === 'optionalCatchAll'),
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
routes.sort((a, b) => {
|
|
177
|
+
const aW = getRouteWeight(a.fullPath);
|
|
178
|
+
const bW = getRouteWeight(b.fullPath);
|
|
179
|
+
if (aW !== bW)
|
|
180
|
+
return aW - bW;
|
|
181
|
+
return a.fullPath.localeCompare(b.fullPath);
|
|
182
|
+
});
|
|
183
|
+
const routeByFullPath = canonicalRoutesByFullPath(routes);
|
|
184
|
+
const routeById = new Map(routes.map((route) => [route.id, route]));
|
|
185
|
+
for (const route of routes) {
|
|
186
|
+
// Use structural id-based parent lookup for any route whose id
|
|
187
|
+
// contains a group segment — this wires group children (e.g.
|
|
188
|
+
// /(auth)/sign-up) to their pathless layout parent (/(auth)).
|
|
189
|
+
// This also correctly handles nested groups like
|
|
190
|
+
// /dashboard/(settings)/profile: findNearestParentById walks up
|
|
191
|
+
// id segments and finds /(settings) if it exists, otherwise falls
|
|
192
|
+
// through to fullPathParent which resolves to /dashboard.
|
|
193
|
+
// Non-group routes always use the canonical fullPath-based lookup.
|
|
194
|
+
const hasGroupSegment = route.id.includes('/(');
|
|
195
|
+
const structuralParent = hasGroupSegment
|
|
196
|
+
? findNearestParentById(route.id, routeById)
|
|
197
|
+
: undefined;
|
|
198
|
+
const fullPathParent = findNearestParentRoute(route.fullPath, routeByFullPath);
|
|
199
|
+
const parent = structuralParent ?? fullPathParent;
|
|
200
|
+
route.parentId = parent?.id ?? null;
|
|
201
|
+
route.path = computeLocalPath(route.fullPath, parent?.fullPath ?? null);
|
|
202
|
+
}
|
|
203
|
+
for (const route of routes) {
|
|
204
|
+
if (route.parentId) {
|
|
205
|
+
routeById.get(route.parentId)?.children.push(route.id);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return { routes, collisions, canonicalByFullPath: routeByFullPath };
|
|
209
|
+
}
|
|
210
|
+
function canonicalRoutesByFullPath(routes) {
|
|
211
|
+
const map = new Map();
|
|
212
|
+
for (const route of routes) {
|
|
213
|
+
const existing = map.get(route.fullPath);
|
|
214
|
+
if (!existing) {
|
|
215
|
+
map.set(route.fullPath, route);
|
|
216
|
+
}
|
|
217
|
+
else if (existing.isGroup && !route.isGroup) {
|
|
218
|
+
// Non-group routes always take precedence over group layouts.
|
|
219
|
+
map.set(route.fullPath, route);
|
|
220
|
+
}
|
|
221
|
+
else if (existing.isGroup && route.isGroup) {
|
|
222
|
+
// Both are group layouts — tiebreak by id to ensure stable selection
|
|
223
|
+
// regardless of filesystem or glob ordering across platforms.
|
|
224
|
+
if (route.id.localeCompare(existing.id) < 0) {
|
|
225
|
+
map.set(route.fullPath, route);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return map;
|
|
230
|
+
}
|
|
231
|
+
function isPathlessLayoutId(id) {
|
|
232
|
+
const segments = id.split('/').filter(Boolean);
|
|
233
|
+
if (segments.length === 0)
|
|
234
|
+
return false;
|
|
235
|
+
return /^\([^)]*\)$/.test(segments[segments.length - 1]);
|
|
236
|
+
}
|
|
237
|
+
function getRouteWeight(path) {
|
|
238
|
+
if (path.includes('[[...'))
|
|
239
|
+
return 3;
|
|
240
|
+
if (path.includes('[...'))
|
|
241
|
+
return 2;
|
|
242
|
+
if (path.includes('['))
|
|
243
|
+
return 1;
|
|
244
|
+
return 0;
|
|
245
|
+
}
|
|
246
|
+
function getCollisionPriority(filename) {
|
|
247
|
+
if (filename.includes('/src/app/pages/') ||
|
|
248
|
+
filename.includes('/src/app/routes/') ||
|
|
249
|
+
filename.includes('/app/pages/') ||
|
|
250
|
+
filename.includes('/app/routes/') ||
|
|
251
|
+
filename.includes('/src/content/')) {
|
|
252
|
+
return 0;
|
|
253
|
+
}
|
|
254
|
+
return 1;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Generates the route-table section for the combined generated route module.
|
|
258
|
+
*/
|
|
259
|
+
export function generateRouteTableDeclaration(manifest) {
|
|
260
|
+
const lines = [];
|
|
261
|
+
lines.push('/** @noprettier */');
|
|
262
|
+
lines.push('// This file is auto-generated by @analogjs/platform');
|
|
263
|
+
lines.push("import type {} from '@analogjs/router';");
|
|
264
|
+
lines.push("declare module '@analogjs/router' {");
|
|
265
|
+
lines.push(' interface AnalogRouteTable {');
|
|
266
|
+
for (const route of manifest.canonicalByFullPath.values()) {
|
|
267
|
+
const paramsType = generateParamsType(route.params);
|
|
268
|
+
const queryType = 'Record<string, string | string[] | undefined>';
|
|
269
|
+
lines.push(` ${JSON.stringify(route.fullPath)}: {`);
|
|
270
|
+
lines.push(` params: ${paramsType};`);
|
|
271
|
+
lines.push(` query: ${queryType};`);
|
|
272
|
+
lines.push(` };`);
|
|
273
|
+
}
|
|
274
|
+
lines.push(' }');
|
|
275
|
+
lines.push('}');
|
|
276
|
+
lines.push('');
|
|
277
|
+
lines.push('export {};');
|
|
278
|
+
lines.push('');
|
|
279
|
+
return lines.join('\n');
|
|
280
|
+
}
|
|
281
|
+
function generateParamsType(params) {
|
|
282
|
+
if (params.length === 0)
|
|
283
|
+
return 'Record<string, never>';
|
|
284
|
+
const entries = params.map((p) => {
|
|
285
|
+
const key = isValidIdentifier(p.name) ? p.name : JSON.stringify(p.name);
|
|
286
|
+
switch (p.type) {
|
|
287
|
+
case 'dynamic':
|
|
288
|
+
return `${key}: string`;
|
|
289
|
+
case 'catchAll':
|
|
290
|
+
return `${key}: string[]`;
|
|
291
|
+
case 'optionalCatchAll':
|
|
292
|
+
return `${key}?: string[]`;
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
return `{ ${entries.join('; ')} }`;
|
|
296
|
+
}
|
|
297
|
+
function isValidIdentifier(name) {
|
|
298
|
+
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
|
|
299
|
+
}
|
|
300
|
+
function findNearestParentById(id, routesById) {
|
|
301
|
+
if (id === '/') {
|
|
302
|
+
return undefined;
|
|
303
|
+
}
|
|
304
|
+
const segments = id.split('/').filter(Boolean);
|
|
305
|
+
for (let index = segments.length - 1; index > 0; index--) {
|
|
306
|
+
const candidate = '/' + segments.slice(0, index).join('/');
|
|
307
|
+
const route = routesById.get(candidate);
|
|
308
|
+
if (route) {
|
|
309
|
+
return route;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return undefined;
|
|
313
|
+
}
|
|
314
|
+
function findNearestParentRoute(fullPath, routesByFullPath) {
|
|
315
|
+
if (fullPath === '/') {
|
|
316
|
+
return undefined;
|
|
317
|
+
}
|
|
318
|
+
const segments = fullPath.slice(1).split('/');
|
|
319
|
+
for (let index = segments.length - 1; index > 0; index--) {
|
|
320
|
+
const candidate = '/' + segments.slice(0, index).join('/');
|
|
321
|
+
const route = routesByFullPath.get(candidate);
|
|
322
|
+
if (route) {
|
|
323
|
+
return route;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return undefined;
|
|
327
|
+
}
|
|
328
|
+
function computeLocalPath(fullPath, parentFullPath) {
|
|
329
|
+
if (fullPath === '/') {
|
|
330
|
+
return '/';
|
|
331
|
+
}
|
|
332
|
+
if (!parentFullPath) {
|
|
333
|
+
return fullPath.slice(1);
|
|
334
|
+
}
|
|
335
|
+
const suffix = fullPath.slice(parentFullPath.length).replace(/^\/+/, '');
|
|
336
|
+
return suffix || '/';
|
|
337
|
+
}
|
|
338
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUtbWFuaWZlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9wbGF0Zm9ybS9zcmMvbGliL3JvdXRlLW1hbmlmZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7OztHQUtHO0FBaURIOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTBCRztBQUNILE1BQU0sVUFBVSxtQkFBbUIsQ0FBQyxRQUFnQjtJQUNsRCxJQUFJLElBQUksR0FBRyxRQUFRLENBQUMsT0FBTyxDQUN6Qiw2S0FBNkssRUFDN0ssRUFBRSxDQUNILENBQUM7SUFFRixNQUFNLFFBQVEsR0FBYSxFQUFFLENBQUM7SUFDOUIsSUFBSSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsMEJBQTBCLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRTtRQUN4RCxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3JCLDRDQUE0QztRQUM1QyxPQUFPLE1BQU0sUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQztJQUN2QyxDQUFDLENBQUMsQ0FBQztJQUNILHdFQUF3RTtJQUN4RSx5REFBeUQ7SUFDekQsSUFBSSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLEVBQUUsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQztJQUM5RCw0Q0FBNEM7SUFDNUMsSUFBSSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxFQUFFLENBQUMsQ0FBQyxFQUFFLEdBQUcsRUFBRSxFQUFFLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdEUsT0FBTyxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FB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
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type Plugin } from 'vite';
|
|
2
|
+
export interface TypedRoutingOptions {
|
|
3
|
+
/** Generated declaration path (.d.ts), relative to the app root. */
|
|
4
|
+
outFile?: string;
|
|
5
|
+
/** Fail builds when a checked-in route table is stale. Defaults to true. */
|
|
6
|
+
verifyOnBuild?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface TypedRoutesPluginOptions extends TypedRoutingOptions {
|
|
9
|
+
workspaceRoot?: string;
|
|
10
|
+
additionalPagesDirs?: string[];
|
|
11
|
+
additionalContentDirs?: string[];
|
|
12
|
+
}
|
|
13
|
+
export declare function typedRoutes(options?: TypedRoutesPluginOptions): Plugin;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, join, relative, resolve } from 'node:path';
|
|
3
|
+
import { readConfiguration } from '@angular/compiler-cli';
|
|
4
|
+
import { parseSync } from 'oxc-parser';
|
|
5
|
+
import { normalizePath } from 'vite';
|
|
6
|
+
import { createRouteFileDiscovery, } from './route-file-discovery.js';
|
|
7
|
+
import { generateRouteManifest, generateRouteTableDeclaration, } from './route-manifest.js';
|
|
8
|
+
export function typedRoutes(options = {}) {
|
|
9
|
+
const workspaceRoot = normalizePath(options.workspaceRoot ?? process.cwd());
|
|
10
|
+
const outFile = options.outFile ?? 'src/routeTree.gen.d.ts';
|
|
11
|
+
if (!outFile.endsWith('.d.ts')) {
|
|
12
|
+
throw new Error('[analog] Typed routing outFile must end in .d.ts. Include this declaration in your application tsconfig.');
|
|
13
|
+
}
|
|
14
|
+
let root;
|
|
15
|
+
let command;
|
|
16
|
+
let discovery;
|
|
17
|
+
let getTsConfigPath;
|
|
18
|
+
function verifyTypeInclusion() {
|
|
19
|
+
if (!getTsConfigPath)
|
|
20
|
+
return;
|
|
21
|
+
const tsconfig = getTsConfigPath();
|
|
22
|
+
const { rootNames, errors } = readConfiguration(tsconfig);
|
|
23
|
+
if (errors.length) {
|
|
24
|
+
throw new Error(`[analog] Cannot verify typed routing: unable to read ${tsconfig}.`);
|
|
25
|
+
}
|
|
26
|
+
const outputPath = normalizePath(resolve(root, outFile));
|
|
27
|
+
if (!rootNames.some((file) => normalizePath(resolve(file)) === outputPath)) {
|
|
28
|
+
const declaration = normalizePath(relative(dirname(tsconfig), outputPath));
|
|
29
|
+
throw new Error(`[analog] Typed route declaration is not included in ${tsconfig}. Add "${declaration}" to its "files" or "include" list so typed routing is available to the compiler and editor.`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function generate() {
|
|
33
|
+
const manifest = generateRouteManifest([...discovery.getRouteFiles(), ...discovery.getContentFiles()], (filename) => (discovery.isAppLocal(filename) ? 0 : 1));
|
|
34
|
+
const collisions = manifest.collisions.filter((collision) => collision.samePriority);
|
|
35
|
+
if (command === 'build' && collisions.length) {
|
|
36
|
+
throw new Error(`[analog] Route collisions detected: ${collisions.map((c) => `${c.fullPath}: ${c.keptFile}, ${c.droppedFile}`).join('; ')}`);
|
|
37
|
+
}
|
|
38
|
+
const output = generateRouteTableDeclaration(manifest);
|
|
39
|
+
const outputPath = join(root, outFile);
|
|
40
|
+
const exists = existsSync(outputPath);
|
|
41
|
+
const current = exists ? readFileSync(outputPath, 'utf8') : '';
|
|
42
|
+
if (current !== output && !sameDeclarations(current, output)) {
|
|
43
|
+
if (exists && command === 'build' && (options.verifyOnBuild ?? true)) {
|
|
44
|
+
throw new Error(`[analog] Stale route file: ${outFile}. Run the dev server to regenerate it before building.`);
|
|
45
|
+
}
|
|
46
|
+
mkdirSync(dirname(outputPath), { recursive: true });
|
|
47
|
+
writeFileSync(outputPath, output);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
name: 'analog-typed-routes',
|
|
52
|
+
config(config, env) {
|
|
53
|
+
command = env.command;
|
|
54
|
+
root = normalizePath(resolve(workspaceRoot, config.root ?? '.'));
|
|
55
|
+
discovery = createRouteFileDiscovery({
|
|
56
|
+
root,
|
|
57
|
+
workspaceRoot,
|
|
58
|
+
additionalPagesDirs: options.additionalPagesDirs ?? [],
|
|
59
|
+
additionalContentDirs: options.additionalContentDirs ?? [],
|
|
60
|
+
});
|
|
61
|
+
// Generate before Angular reads the application tsconfig.
|
|
62
|
+
generate();
|
|
63
|
+
},
|
|
64
|
+
configResolved(config) {
|
|
65
|
+
const compiler = config.plugins.find((plugin) => plugin.name === '@analogjs/vite-plugin-angular' ||
|
|
66
|
+
plugin.name === '@analogjs/vite-plugin-angular-fast-compile');
|
|
67
|
+
getTsConfigPath = compiler?.api?.getTsConfigPath;
|
|
68
|
+
if (compiler && !getTsConfigPath) {
|
|
69
|
+
throw new Error('[analog] Typed routing requires a matching @analogjs/vite-plugin-angular version to verify the application tsconfig.');
|
|
70
|
+
}
|
|
71
|
+
verifyTypeInclusion();
|
|
72
|
+
},
|
|
73
|
+
buildStart() {
|
|
74
|
+
discovery.reset();
|
|
75
|
+
generate();
|
|
76
|
+
verifyTypeInclusion();
|
|
77
|
+
},
|
|
78
|
+
configureServer(server) {
|
|
79
|
+
server.watcher.add(join(root, outFile));
|
|
80
|
+
for (const event of ['add', 'change', 'unlink']) {
|
|
81
|
+
server.watcher.on(event, (path) => {
|
|
82
|
+
if (!discovery.getDiscoveredFileKind(path))
|
|
83
|
+
return;
|
|
84
|
+
discovery.updateDiscoveredFile(path, event);
|
|
85
|
+
generate();
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function sameDeclarations(current, output) {
|
|
92
|
+
const left = parseSync('routeTree.gen.d.ts', current);
|
|
93
|
+
const right = parseSync('routeTree.gen.d.ts', output);
|
|
94
|
+
if (left.errors.length || right.errors.length)
|
|
95
|
+
return false;
|
|
96
|
+
const withoutFormatting = (key, value) => key === 'start' || key === 'end' || key === 'raw' ? undefined : value;
|
|
97
|
+
return (JSON.stringify(left.program, withoutFormatting) ===
|
|
98
|
+
JSON.stringify(right.program, withoutFormatting));
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZWQtcm91dGVzLXBsdWdpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL3BsYXRmb3JtL3NyYy9saWIvdHlwZWQtcm91dGVzLXBsdWdpbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsYUFBYSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQzdFLE9BQU8sRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDN0QsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDMUQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUN2QyxPQUFPLEVBQUUsYUFBYSxFQUFlLE1BQU0sTUFBTSxDQUFDO0FBRWxELE9BQU8sRUFDTCx3QkFBd0IsR0FFekIsTUFBTSwyQkFBMkIsQ0FBQztBQUNuQyxPQUFPLEVBQ0wscUJBQXFCLEVBQ3JCLDZCQUE2QixHQUM5QixNQUFNLHFCQUFxQixDQUFDO0FBZTdCLE1BQU0sVUFBVSxXQUFXLENBQUMsVUFBb0MsRUFBRTtJQUNoRSxNQUFNLGFBQWEsR0FBRyxhQUFhLENBQUMsT0FBTyxDQUFDLGFBQWEsSUFBSSxPQUFPLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUM1RSxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsT0FBTyxJQUFJLHdCQUF3QixDQUFDO0lBQzVELElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDL0IsTUFBTSxJQUFJLEtBQUssQ0FDYiwwR0FBMEcsQ0FDM0csQ0FBQztJQUNKLENBQUM7SUFDRCxJQUFJLElBQVksQ0FBQztJQUNqQixJQUFJLE9BQTBCLENBQUM7SUFDL0IsSUFBSSxTQUE2QixDQUFDO0lBRWxDLElBQUksZUFBMkMsQ0FB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
|