@analogjs/platform 3.0.0-alpha.13 → 3.0.0-alpha.14
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 +6 -4
- package/src/index.d.ts +2 -1
- package/src/index.js +2 -1
- package/src/index.js.map +1 -1
- package/src/lib/json-ld-manifest-plugin.d.ts +41 -0
- package/src/lib/json-ld-manifest-plugin.js +84 -0
- package/src/lib/json-ld-manifest-plugin.js.map +1 -0
- package/src/lib/nx-plugin/src/generators/app/files/template-angular/vite.config.ts__template__ +6 -0
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v17/vite.config.ts__template__ +0 -1
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v18/vite.config.ts__template__ +0 -1
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v19/vite.config.ts__template__ +0 -1
- package/src/lib/nx-plugin/src/generators/app/lib/add-tailwind-config.js +0 -2
- package/src/lib/nx-plugin/src/generators/app/lib/add-tailwind-config.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/app/lib/add-tailwind-helpers.d.ts +0 -2
- package/src/lib/nx-plugin/src/generators/app/lib/add-tailwind-helpers.js +1 -26
- package/src/lib/nx-plugin/src/generators/app/lib/add-tailwind-helpers.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/app/versions/nx_18_X/versions.d.ts +7 -9
- package/src/lib/nx-plugin/src/generators/app/versions/nx_18_X/versions.js +2 -4
- package/src/lib/nx-plugin/src/generators/app/versions/nx_18_X/versions.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/app/versions/tailwind-dependencies.d.ts +1 -1
- package/src/lib/nx-plugin/src/generators/app/versions/tailwind-dependencies.js +1 -2
- package/src/lib/nx-plugin/src/generators/app/versions/tailwind-dependencies.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/preset/__snapshots__/generator.spec.ts.snap +3 -1
- 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/nx-plugin/src/utils/versions/ng_19_X/versions.js.map +1 -1
- package/src/lib/options.d.ts +78 -4
- package/src/lib/platform-plugin.js +10 -2
- package/src/lib/platform-plugin.js.map +1 -1
- package/src/lib/route-file-discovery.d.ts +23 -0
- package/src/lib/route-file-discovery.js +114 -0
- package/src/lib/route-file-discovery.js.map +1 -0
- package/src/lib/route-generation-plugin.d.ts +3 -0
- package/src/lib/route-generation-plugin.js +34 -0
- package/src/lib/route-generation-plugin.js.map +1 -0
- package/src/lib/route-manifest.d.ts +104 -0
- package/src/lib/route-manifest.js +363 -0
- package/src/lib/route-manifest.js.map +1 -0
- package/src/lib/typed-routes-plugin.d.ts +50 -0
- package/src/lib/typed-routes-plugin.js +204 -0
- package/src/lib/typed-routes-plugin.js.map +1 -0
- package/src/lib/nx-plugin/src/generators/app/files/tailwind/v4/.postcssrc.json +0 -5
- package/src/lib/nx-plugin/src/generators/app/files/tailwind/v4/tailwind.config.ts__template__ +0 -14
package/src/lib/options.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { PluginOptions } from "@analogjs/vite-plugin-angular";
|
|
2
2
|
import type { NitroConfig, PrerenderRoute } from "nitro/types";
|
|
3
|
-
import type { SitemapConfig, PrerenderContentDir, PrerenderContentFile, PrerenderRouteConfig } from "@analogjs/vite-plugin-nitro";
|
|
4
|
-
import { ContentPluginOptions } from "./content-plugin.js";
|
|
3
|
+
import type { SitemapConfig, SitemapEntry, SitemapExcludeRule, SitemapPriority, SitemapRouteDefinition, SitemapRouteInput, SitemapRouteSource, SitemapTransform, PrerenderContentDir, PrerenderContentFile, PrerenderSitemapConfig, PrerenderRouteConfig } from "@analogjs/vite-plugin-nitro";
|
|
4
|
+
import type { ContentPluginOptions } from "./content-plugin.js";
|
|
5
5
|
declare module "nitro/types" {
|
|
6
6
|
interface NitroRouteConfig {
|
|
7
7
|
ssr?: boolean;
|
|
@@ -34,11 +34,20 @@ export interface Options {
|
|
|
34
34
|
entryServer?: string;
|
|
35
35
|
/**
|
|
36
36
|
* Pass configuration options to the internal `@analogjs/vite-plugin-angular`
|
|
37
|
-
* plugin. Set to false to disable the internal vite plugin.
|
|
37
|
+
* plugin. Set to `false` to disable the internal vite plugin (e.g. when
|
|
38
|
+
* using an alternative compiler like `@oxc-angular/vite`).
|
|
38
39
|
*
|
|
39
40
|
* `vite.build` uses Vite's native config shape and is forwarded to the
|
|
40
41
|
* internal Nitro/Vite build pipeline, while the remaining fields are passed
|
|
41
42
|
* to `@analogjs/vite-plugin-angular`.
|
|
43
|
+
*
|
|
44
|
+
* When `false`, the following top-level options are ignored because they
|
|
45
|
+
* are only forwarded to the internal Angular plugin: `jit`,
|
|
46
|
+
* `disableTypeChecking`, `liveReload`, `inlineStylesExtension`,
|
|
47
|
+
* `fileReplacements`, and `include`.
|
|
48
|
+
*
|
|
49
|
+
* Use this to configure the embedded Angular integration itself, not as the
|
|
50
|
+
* primary home for Analog-owned experimental features.
|
|
42
51
|
*/
|
|
43
52
|
vite?: PluginOptions | false;
|
|
44
53
|
nitro?: NitroConfig;
|
|
@@ -85,5 +94,70 @@ export interface Options {
|
|
|
85
94
|
* File replacements
|
|
86
95
|
*/
|
|
87
96
|
fileReplacements?: PluginOptions["fileReplacements"];
|
|
97
|
+
/**
|
|
98
|
+
* Experimental features. These APIs are subject to change.
|
|
99
|
+
*
|
|
100
|
+
* `@analogjs/platform` is the default rollout and orchestration surface for
|
|
101
|
+
* Analog-owned experiments. These flags may delegate to dedicated feature
|
|
102
|
+
* plugins or forward options into lower-level integrations while preserving
|
|
103
|
+
* a single Analog-first authoring surface.
|
|
104
|
+
*/
|
|
105
|
+
experimental?: {
|
|
106
|
+
/**
|
|
107
|
+
* Use Angular's experimental compilation API.
|
|
108
|
+
*
|
|
109
|
+
* This is forwarded to `@analogjs/vite-plugin-angular`'s
|
|
110
|
+
* `experimental.useAngularCompilationAPI`.
|
|
111
|
+
*
|
|
112
|
+
* Also accepted at `vite.experimental.useAngularCompilationAPI`
|
|
113
|
+
* for backwards compatibility.
|
|
114
|
+
*
|
|
115
|
+
* Has no effect when `vite` is set to `false`.
|
|
116
|
+
*/
|
|
117
|
+
useAngularCompilationAPI?: boolean;
|
|
118
|
+
/**
|
|
119
|
+
* Enable typed route table generation for type-safe navigation.
|
|
120
|
+
*
|
|
121
|
+
* When enabled, `@analogjs/platform` generates a single route module
|
|
122
|
+
* that augments `AnalogRouteTable` with typed params and query for each
|
|
123
|
+
* file-based route. JSON-LD manifest generation is configured on the same
|
|
124
|
+
* object so both codegen features share one generated file.
|
|
125
|
+
*
|
|
126
|
+
* - `true` — generates `src/routeTree.gen.ts` with `routeJsonLdManifest`
|
|
127
|
+
* - `TypedRouterOptions` — customize output path or disable just the
|
|
128
|
+
* JSON-LD manifest piece
|
|
129
|
+
*
|
|
130
|
+
* Unlocks type-safe usage of:
|
|
131
|
+
* - `routePath()` — build route link objects for `[routerLink]`
|
|
132
|
+
* - `injectNavigate()` — typed navigation
|
|
133
|
+
* - `injectParams(from)` — typed params signal
|
|
134
|
+
* - `injectQuery(from)` — typed query signal
|
|
135
|
+
*
|
|
136
|
+
* Inspired by TanStack Router's `routeTree.gen.ts` codegen.
|
|
137
|
+
*/
|
|
138
|
+
typedRouter?: boolean | TypedRouterOptions;
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
export interface TypedRouterOptions {
|
|
142
|
+
/**
|
|
143
|
+
* Output path for the single generated route module,
|
|
144
|
+
* relative to the app root.
|
|
145
|
+
*
|
|
146
|
+
* @default 'src/routeTree.gen.ts'
|
|
147
|
+
*/
|
|
148
|
+
outFile?: string;
|
|
149
|
+
/**
|
|
150
|
+
* Include generated `routeJsonLdManifest` data in the generated route file.
|
|
151
|
+
*
|
|
152
|
+
* @default true
|
|
153
|
+
*/
|
|
154
|
+
jsonLdManifest?: boolean;
|
|
155
|
+
/**
|
|
156
|
+
* Fail production builds after regenerating a stale checked-in route file.
|
|
157
|
+
* Development and watch mode continue to update the file automatically.
|
|
158
|
+
*
|
|
159
|
+
* @default true
|
|
160
|
+
*/
|
|
161
|
+
verifyOnBuild?: boolean;
|
|
88
162
|
}
|
|
89
|
-
export { PrerenderContentDir, PrerenderContentFile };
|
|
163
|
+
export type { PrerenderContentDir, PrerenderContentFile, PrerenderSitemapConfig, SitemapConfig, SitemapEntry, SitemapExcludeRule, SitemapPriority, SitemapRouteDefinition, SitemapRouteInput, SitemapRouteSource, SitemapTransform };
|
|
@@ -5,6 +5,7 @@ import { clearClientPageEndpointsPlugin } from "./clear-client-page-endpoint.js"
|
|
|
5
5
|
import { depsPlugin } from "./deps-plugin.js";
|
|
6
6
|
import { injectHTMLPlugin } from "./ssr/inject-html-plugin.js";
|
|
7
7
|
import { serverModePlugin } from "../server-mode-plugin.js";
|
|
8
|
+
import { routeGenerationPlugin } from "./route-generation-plugin.js";
|
|
8
9
|
import viteNitroPlugin from "@analogjs/vite-plugin-nitro";
|
|
9
10
|
import angular from "@analogjs/vite-plugin-angular";
|
|
10
11
|
//#region packages/platform/src/lib/platform-plugin.ts
|
|
@@ -13,10 +14,12 @@ function externalPlugins(plugins) {
|
|
|
13
14
|
}
|
|
14
15
|
function platformPlugin(opts = {}) {
|
|
15
16
|
const isTest = process.env.NODE_ENV === "test" || !!process.env["VITEST"];
|
|
17
|
+
const viteOptions = opts?.vite === false ? void 0 : opts?.vite;
|
|
16
18
|
const { ...platformOptions } = {
|
|
17
19
|
ssr: true,
|
|
18
20
|
...opts
|
|
19
21
|
};
|
|
22
|
+
const useAngularCompilationAPI = platformOptions.experimental?.useAngularCompilationAPI ?? viteOptions?.experimental?.useAngularCompilationAPI;
|
|
20
23
|
let nitroOptions = platformOptions?.nitro;
|
|
21
24
|
if (nitroOptions?.routeRules) nitroOptions = {
|
|
22
25
|
...nitroOptions,
|
|
@@ -38,17 +41,22 @@ function platformPlugin(opts = {}) {
|
|
|
38
41
|
...platformOptions.ssr ? [...ssrBuildPlugin(), ...injectHTMLPlugin()] : [],
|
|
39
42
|
...!isTest ? depsPlugin(platformOptions) : [],
|
|
40
43
|
...routerPlugin(platformOptions),
|
|
44
|
+
routeGenerationPlugin(platformOptions),
|
|
41
45
|
...contentPlugin(platformOptions?.content, platformOptions),
|
|
42
46
|
...opts?.vite === false ? [] : externalPlugins(angular({
|
|
43
47
|
jit: platformOptions.jit,
|
|
44
48
|
workspaceRoot: platformOptions.workspaceRoot,
|
|
45
|
-
disableTypeChecking: platformOptions.disableTypeChecking
|
|
49
|
+
disableTypeChecking: platformOptions.disableTypeChecking,
|
|
46
50
|
include: [...platformOptions.include ?? [], ...(platformOptions.additionalPagesDirs ?? []).map((pageDir) => `${pageDir}/**/*.page.ts`)],
|
|
47
51
|
additionalContentDirs: platformOptions.additionalContentDirs,
|
|
48
52
|
liveReload: platformOptions.liveReload,
|
|
49
53
|
inlineStylesExtension: platformOptions.inlineStylesExtension,
|
|
50
54
|
fileReplacements: platformOptions.fileReplacements,
|
|
51
|
-
...
|
|
55
|
+
...viteOptions ?? {},
|
|
56
|
+
experimental: {
|
|
57
|
+
...viteOptions?.experimental ?? {},
|
|
58
|
+
useAngularCompilationAPI
|
|
59
|
+
}
|
|
52
60
|
})),
|
|
53
61
|
...serverModePlugin(),
|
|
54
62
|
...clearClientPageEndpointsPlugin()
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-plugin.js","names":[],"sources":["../../../../../packages/platform/src/lib/platform-plugin.ts"],"sourcesContent":["import { Plugin } from 'vite';\nimport viteNitroPlugin from '@analogjs/vite-plugin-nitro';\nimport angular from '@analogjs/vite-plugin-angular';\n\nimport { Options } from './options.js';\nimport { routerPlugin } from './router-plugin.js';\nimport { ssrBuildPlugin } from './ssr/ssr-build-plugin.js';\nimport { contentPlugin } from './content-plugin.js';\nimport { clearClientPageEndpointsPlugin } from './clear-client-page-endpoint.js';\nimport { depsPlugin } from './deps-plugin.js';\nimport { injectHTMLPlugin } from './ssr/inject-html-plugin.js';\nimport { serverModePlugin } from '../server-mode-plugin.js';\n\n// Bridge Plugin types from external @analogjs packages that resolve a different vite instance\nfunction externalPlugins(plugins: unknown): Plugin[] {\n return plugins as Plugin[];\n}\n\nexport function platformPlugin(opts: Options = {}): Plugin[] {\n const isTest = process.env['NODE_ENV'] === 'test' || !!process.env['VITEST'];\n const { ...platformOptions } = {\n ssr: true,\n ...opts,\n };\n let nitroOptions = platformOptions?.nitro;\n\n if (nitroOptions?.routeRules) {\n nitroOptions = {\n ...nitroOptions,\n routeRules: Object.keys(nitroOptions.routeRules).reduce(\n (config, curr) => {\n return {\n ...config,\n [curr]: {\n ...config[curr],\n headers: {\n ...config[curr].headers,\n 'x-analog-no-ssr':\n config[curr]?.ssr === false ? 'true' : undefined,\n } as any,\n },\n };\n },\n nitroOptions.routeRules,\n ),\n };\n }\n\n return [\n ...externalPlugins(viteNitroPlugin(platformOptions as any, nitroOptions)),\n ...(platformOptions.ssr\n ? [...ssrBuildPlugin(), ...injectHTMLPlugin()]\n : []),\n ...(!isTest ? depsPlugin(platformOptions) : []),\n ...routerPlugin(platformOptions),\n ...contentPlugin(platformOptions?.content, platformOptions),\n ...(opts?.vite === false\n ? []\n : externalPlugins(\n angular({\n jit: platformOptions.jit,\n workspaceRoot: platformOptions.workspaceRoot,\n disableTypeChecking: platformOptions.disableTypeChecking
|
|
1
|
+
{"version":3,"file":"platform-plugin.js","names":[],"sources":["../../../../../packages/platform/src/lib/platform-plugin.ts"],"sourcesContent":["import { Plugin } from 'vite';\nimport viteNitroPlugin from '@analogjs/vite-plugin-nitro';\nimport angular from '@analogjs/vite-plugin-angular';\n\nimport { Options } from './options.js';\nimport { routerPlugin } from './router-plugin.js';\nimport { ssrBuildPlugin } from './ssr/ssr-build-plugin.js';\nimport { contentPlugin } from './content-plugin.js';\nimport { clearClientPageEndpointsPlugin } from './clear-client-page-endpoint.js';\nimport { depsPlugin } from './deps-plugin.js';\nimport { injectHTMLPlugin } from './ssr/inject-html-plugin.js';\nimport { serverModePlugin } from '../server-mode-plugin.js';\nimport { routeGenerationPlugin } from './route-generation-plugin.js';\n\n// Bridge Plugin types from external @analogjs packages that resolve a different vite instance\nfunction externalPlugins(plugins: unknown): Plugin[] {\n return plugins as Plugin[];\n}\n\nexport function platformPlugin(opts: Options = {}): Plugin[] {\n const isTest = process.env['NODE_ENV'] === 'test' || !!process.env['VITEST'];\n const viteOptions = opts?.vite === false ? undefined : opts?.vite;\n const { ...platformOptions } = {\n ssr: true,\n ...opts,\n };\n const useAngularCompilationAPI =\n platformOptions.experimental?.useAngularCompilationAPI ??\n viteOptions?.experimental?.useAngularCompilationAPI;\n let nitroOptions = platformOptions?.nitro;\n\n if (nitroOptions?.routeRules) {\n nitroOptions = {\n ...nitroOptions,\n routeRules: Object.keys(nitroOptions.routeRules).reduce(\n (config, curr) => {\n return {\n ...config,\n [curr]: {\n ...config[curr],\n headers: {\n ...config[curr].headers,\n 'x-analog-no-ssr':\n config[curr]?.ssr === false ? 'true' : undefined,\n } as any,\n },\n };\n },\n nitroOptions.routeRules,\n ),\n };\n }\n\n return [\n ...externalPlugins(viteNitroPlugin(platformOptions as any, nitroOptions)),\n ...(platformOptions.ssr\n ? [...ssrBuildPlugin(), ...injectHTMLPlugin()]\n : []),\n ...(!isTest ? depsPlugin(platformOptions) : []),\n ...routerPlugin(platformOptions),\n routeGenerationPlugin(platformOptions),\n ...contentPlugin(platformOptions?.content, platformOptions),\n ...(opts?.vite === false\n ? []\n : externalPlugins(\n angular({\n jit: platformOptions.jit,\n workspaceRoot: platformOptions.workspaceRoot,\n // Let the Angular plugin keep its own dev-friendly default unless the\n // app explicitly opts into stricter serve-time diagnostics.\n disableTypeChecking: platformOptions.disableTypeChecking,\n include: [\n ...(platformOptions.include ?? []),\n ...(platformOptions.additionalPagesDirs ?? []).map(\n (pageDir) => `${pageDir}/**/*.page.ts`,\n ),\n ],\n additionalContentDirs: platformOptions.additionalContentDirs,\n liveReload: platformOptions.liveReload,\n inlineStylesExtension: platformOptions.inlineStylesExtension,\n fileReplacements: platformOptions.fileReplacements,\n ...(viteOptions ?? {}),\n experimental: {\n ...(viteOptions?.experimental ?? {}),\n useAngularCompilationAPI,\n },\n }),\n )),\n ...serverModePlugin(),\n ...clearClientPageEndpointsPlugin(),\n ];\n}\n"],"mappings":";;;;;;;;;;;AAeA,SAAS,gBAAgB,SAA4B;AACnD,QAAO;;AAGT,SAAgB,eAAe,OAAgB,EAAE,EAAY;CAC3D,MAAM,SAAA,QAAA,IAAA,aAAqC,UAAU,CAAC,CAAC,QAAQ,IAAI;CACnE,MAAM,cAAc,MAAM,SAAS,QAAQ,KAAA,IAAY,MAAM;CAC7D,MAAM,EAAE,GAAG,oBAAoB;EAC7B,KAAK;EACL,GAAG;EACJ;CACD,MAAM,2BACJ,gBAAgB,cAAc,4BAC9B,aAAa,cAAc;CAC7B,IAAI,eAAe,iBAAiB;AAEpC,KAAI,cAAc,WAChB,gBAAe;EACb,GAAG;EACH,YAAY,OAAO,KAAK,aAAa,WAAW,CAAC,QAC9C,QAAQ,SAAS;AAChB,UAAO;IACL,GAAG;KACF,OAAO;KACN,GAAG,OAAO;KACV,SAAS;MACP,GAAG,OAAO,MAAM;MAChB,mBACE,OAAO,OAAO,QAAQ,QAAQ,SAAS,KAAA;MAC1C;KACF;IACF;KAEH,aAAa,WACd;EACF;AAGH,QAAO;EACL,GAAG,gBAAgB,gBAAgB,iBAAwB,aAAa,CAAC;EACzE,GAAI,gBAAgB,MAChB,CAAC,GAAG,gBAAgB,EAAE,GAAG,kBAAkB,CAAC,GAC5C,EAAE;EACN,GAAI,CAAC,SAAS,WAAW,gBAAgB,GAAG,EAAE;EAC9C,GAAG,aAAa,gBAAgB;EAChC,sBAAsB,gBAAgB;EACtC,GAAG,cAAc,iBAAiB,SAAS,gBAAgB;EAC3D,GAAI,MAAM,SAAS,QACf,EAAE,GACF,gBACE,QAAQ;GACN,KAAK,gBAAgB;GACrB,eAAe,gBAAgB;GAG/B,qBAAqB,gBAAgB;GACrC,SAAS,CACP,GAAI,gBAAgB,WAAW,EAAE,EACjC,IAAI,gBAAgB,uBAAuB,EAAE,EAAE,KAC5C,YAAY,GAAG,QAAQ,eACzB,CACF;GACD,uBAAuB,gBAAgB;GACvC,YAAY,gBAAgB;GAC5B,uBAAuB,gBAAgB;GACvC,kBAAkB,gBAAgB;GAClC,GAAI,eAAe,EAAE;GACrB,cAAc;IACZ,GAAI,aAAa,gBAAgB,EAAE;IACnC;IACD;GACF,CAAC,CACH;EACL,GAAG,kBAAkB;EACrB,GAAG,gCAAgC;EACpC"}
|
|
@@ -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,114 @@
|
|
|
1
|
+
import { normalizePath } from "vite";
|
|
2
|
+
import { globSync } from "tinyglobby";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
//#region packages/platform/src/lib/route-file-discovery.ts
|
|
5
|
+
function createRouteFileDiscovery(options) {
|
|
6
|
+
const { root, workspaceRoot, additionalPagesDirs, additionalContentDirs } = options;
|
|
7
|
+
let routeFilesCache = /* @__PURE__ */ new Set();
|
|
8
|
+
let contentFilesCache = /* @__PURE__ */ new Set();
|
|
9
|
+
let appLocalFilesCache = /* @__PURE__ */ new Set();
|
|
10
|
+
let initialized = false;
|
|
11
|
+
const joinDir = (dir) => dir.startsWith(workspaceRoot) ? normalizePath(dir) : dir.startsWith("/") ? normalizePath(`${workspaceRoot}${dir}`) : normalizePath(resolve(workspaceRoot, dir));
|
|
12
|
+
const additionalPagesRoots = additionalPagesDirs.map(joinDir);
|
|
13
|
+
const additionalContentRoots = additionalContentDirs.map(joinDir);
|
|
14
|
+
function normalizePath_(absolutePath) {
|
|
15
|
+
const normalized = normalizePath(absolutePath);
|
|
16
|
+
if (normalized.startsWith(root)) return normalized.slice(root.length);
|
|
17
|
+
if (normalized.startsWith(workspaceRoot)) return normalized.slice(workspaceRoot.length);
|
|
18
|
+
return normalized;
|
|
19
|
+
}
|
|
20
|
+
function isWithinDir(path, dir) {
|
|
21
|
+
return path === dir || path.startsWith(`${dir}/`);
|
|
22
|
+
}
|
|
23
|
+
function getDiscoveredFileKind(path) {
|
|
24
|
+
const normalized = normalizePath(path);
|
|
25
|
+
if (normalized.endsWith(".md") && (normalized.includes("/src/app/routes/") || normalized.includes("/src/app/pages/") || normalized.includes("/src/content/") || additionalContentRoots.some((dir) => isWithinDir(normalized, dir)))) return "content";
|
|
26
|
+
if ((normalized.includes("/app/routes/") || normalized.includes("/src/app/routes/")) && normalized.endsWith(".ts")) return "route";
|
|
27
|
+
if (normalized.endsWith(".page.ts") && (normalized.includes("/src/app/pages/") || additionalPagesRoots.some((dir) => isWithinDir(normalized, dir)))) return "route";
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
function scanRouteFiles() {
|
|
31
|
+
const appLocalGlobs = [
|
|
32
|
+
`${root}/app/routes/**/*.ts`,
|
|
33
|
+
`${root}/src/app/routes/**/*.ts`,
|
|
34
|
+
`${root}/src/app/pages/**/*.page.ts`
|
|
35
|
+
];
|
|
36
|
+
const additionalGlobs = additionalPagesDirs.map((dir) => `${joinDir(dir)}/**/*.page.ts`);
|
|
37
|
+
const appLocal = globSync(appLocalGlobs, {
|
|
38
|
+
dot: true,
|
|
39
|
+
absolute: true
|
|
40
|
+
}).map(normalizePath_);
|
|
41
|
+
const additional = globSync(additionalGlobs, {
|
|
42
|
+
dot: true,
|
|
43
|
+
absolute: true
|
|
44
|
+
}).map(normalizePath_);
|
|
45
|
+
for (const f of appLocal) appLocalFilesCache.add(f);
|
|
46
|
+
return [...appLocal, ...additional];
|
|
47
|
+
}
|
|
48
|
+
function scanContentFiles() {
|
|
49
|
+
const appLocalGlobs = [
|
|
50
|
+
`${root}/src/app/routes/**/*.md`,
|
|
51
|
+
`${root}/src/app/pages/**/*.md`,
|
|
52
|
+
`${root}/src/content/**/*.md`
|
|
53
|
+
];
|
|
54
|
+
const additionalGlobs = additionalContentDirs.map((dir) => `${joinDir(dir)}/**/*.md`);
|
|
55
|
+
const appLocal = globSync(appLocalGlobs, {
|
|
56
|
+
dot: true,
|
|
57
|
+
absolute: true
|
|
58
|
+
}).map(normalizePath_);
|
|
59
|
+
const additional = globSync(additionalGlobs, {
|
|
60
|
+
dot: true,
|
|
61
|
+
absolute: true
|
|
62
|
+
}).map(normalizePath_);
|
|
63
|
+
for (const f of appLocal) appLocalFilesCache.add(f);
|
|
64
|
+
return [...appLocal, ...additional];
|
|
65
|
+
}
|
|
66
|
+
function isAppLocalByPath(absolutePath) {
|
|
67
|
+
return normalizePath(absolutePath).startsWith(root);
|
|
68
|
+
}
|
|
69
|
+
function ensureInitialized() {
|
|
70
|
+
if (initialized) return;
|
|
71
|
+
routeFilesCache = new Set(scanRouteFiles());
|
|
72
|
+
contentFilesCache = new Set(scanContentFiles());
|
|
73
|
+
initialized = true;
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
getRouteFiles() {
|
|
77
|
+
ensureInitialized();
|
|
78
|
+
return [...routeFilesCache].sort();
|
|
79
|
+
},
|
|
80
|
+
getContentFiles() {
|
|
81
|
+
ensureInitialized();
|
|
82
|
+
return [...contentFilesCache].sort();
|
|
83
|
+
},
|
|
84
|
+
getDiscoveredFileKind(path) {
|
|
85
|
+
return getDiscoveredFileKind(path);
|
|
86
|
+
},
|
|
87
|
+
updateDiscoveredFile(path, event) {
|
|
88
|
+
ensureInitialized();
|
|
89
|
+
const kind = getDiscoveredFileKind(path);
|
|
90
|
+
if (!kind) return;
|
|
91
|
+
const normalizedPath = normalizePath_(path);
|
|
92
|
+
const targetCache = kind === "content" ? contentFilesCache : routeFilesCache;
|
|
93
|
+
if (event === "unlink") {
|
|
94
|
+
targetCache.delete(normalizedPath);
|
|
95
|
+
appLocalFilesCache.delete(normalizedPath);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
targetCache.add(normalizedPath);
|
|
99
|
+
if (isAppLocalByPath(path)) appLocalFilesCache.add(normalizedPath);
|
|
100
|
+
},
|
|
101
|
+
isAppLocal(normalizedFilename) {
|
|
102
|
+
ensureInitialized();
|
|
103
|
+
return appLocalFilesCache.has(normalizedFilename);
|
|
104
|
+
},
|
|
105
|
+
reset() {
|
|
106
|
+
initialized = false;
|
|
107
|
+
appLocalFilesCache = /* @__PURE__ */ new Set();
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
//#endregion
|
|
112
|
+
export { createRouteFileDiscovery };
|
|
113
|
+
|
|
114
|
+
//# sourceMappingURL=route-file-discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-file-discovery.js","names":[],"sources":["../../../../../packages/platform/src/lib/route-file-discovery.ts"],"sourcesContent":["import { normalizePath } from 'vite';\nimport { resolve } from 'node:path';\nimport { globSync } from 'tinyglobby';\n\nexport interface RouteFileDiscoveryOptions {\n root: string;\n workspaceRoot: string;\n additionalPagesDirs: string[];\n additionalContentDirs: string[];\n}\n\nexport interface RouteFileDiscovery {\n getRouteFiles(): string[];\n getContentFiles(): string[];\n getDiscoveredFileKind(path: string): 'route' | 'content' | null;\n updateDiscoveredFile(path: string, event: 'add' | 'change' | 'unlink'): void;\n /**\n * Returns true if the normalized filename was discovered from an app-local\n * glob (under the configured root) rather than from an additional directory.\n *\n * Used by collision priority to prefer app-local routes over shared/external\n * routes based on actual configured roots instead of hard-coded path\n * substrings.\n */\n isAppLocal(normalizedFilename: string): boolean;\n reset(): void;\n}\n\nexport function createRouteFileDiscovery(\n options: RouteFileDiscoveryOptions,\n): RouteFileDiscovery {\n const { root, workspaceRoot, additionalPagesDirs, additionalContentDirs } =\n options;\n\n let routeFilesCache = new Set<string>();\n let contentFilesCache = new Set<string>();\n let appLocalFilesCache = new Set<string>();\n let initialized = false;\n const joinDir = (dir: string) =>\n dir.startsWith(workspaceRoot)\n ? normalizePath(dir)\n : dir.startsWith('/')\n ? normalizePath(`${workspaceRoot}${dir}`)\n : normalizePath(resolve(workspaceRoot, dir));\n const additionalPagesRoots = additionalPagesDirs.map(joinDir);\n const additionalContentRoots = additionalContentDirs.map(joinDir);\n\n function normalizePath_(absolutePath: string): string {\n const normalized = normalizePath(absolutePath);\n if (normalized.startsWith(root)) {\n return normalized.slice(root.length);\n }\n if (normalized.startsWith(workspaceRoot)) {\n return normalized.slice(workspaceRoot.length);\n }\n return normalized;\n }\n\n function isWithinDir(path: string, dir: string): boolean {\n return path === dir || path.startsWith(`${dir}/`);\n }\n\n function getDiscoveredFileKind(path: string): 'route' | 'content' | null {\n const normalized = normalizePath(path);\n\n if (\n normalized.endsWith('.md') &&\n (normalized.includes('/src/app/routes/') ||\n normalized.includes('/src/app/pages/') ||\n normalized.includes('/src/content/') ||\n additionalContentRoots.some((dir) => isWithinDir(normalized, dir)))\n ) {\n return 'content';\n }\n\n if (\n (normalized.includes('/app/routes/') ||\n normalized.includes('/src/app/routes/')) &&\n normalized.endsWith('.ts')\n ) {\n return 'route';\n }\n\n // Keep the dev watcher aligned with the build-time route scan. In\n // particular, `src/server/routes/**` must stay out of typed route codegen\n // because Nitro API handlers are not client-navigable pages.\n if (\n normalized.endsWith('.page.ts') &&\n (normalized.includes('/src/app/pages/') ||\n additionalPagesRoots.some((dir) => isWithinDir(normalized, dir)))\n ) {\n return 'route';\n }\n\n return null;\n }\n\n function scanRouteFiles(): string[] {\n const appLocalGlobs = [\n `${root}/app/routes/**/*.ts`,\n `${root}/src/app/routes/**/*.ts`,\n `${root}/src/app/pages/**/*.page.ts`,\n ];\n const additionalGlobs = additionalPagesDirs.map(\n (dir) => `${joinDir(dir)}/**/*.page.ts`,\n );\n\n const appLocal = globSync(appLocalGlobs, {\n dot: true,\n absolute: true,\n }).map(normalizePath_);\n\n const additional = globSync(additionalGlobs, {\n dot: true,\n absolute: true,\n }).map(normalizePath_);\n\n for (const f of appLocal) {\n appLocalFilesCache.add(f);\n }\n\n return [...appLocal, ...additional];\n }\n\n function scanContentFiles(): string[] {\n const appLocalGlobs = [\n `${root}/src/app/routes/**/*.md`,\n `${root}/src/app/pages/**/*.md`,\n `${root}/src/content/**/*.md`,\n ];\n const additionalGlobs = additionalContentDirs.map(\n (dir) => `${joinDir(dir)}/**/*.md`,\n );\n\n const appLocal = globSync(appLocalGlobs, {\n dot: true,\n absolute: true,\n }).map(normalizePath_);\n\n const additional = globSync(additionalGlobs, {\n dot: true,\n absolute: true,\n }).map(normalizePath_);\n\n for (const f of appLocal) {\n appLocalFilesCache.add(f);\n }\n\n return [...appLocal, ...additional];\n }\n\n function isAppLocalByPath(absolutePath: string): boolean {\n const normalized = normalizePath(absolutePath);\n return normalized.startsWith(root);\n }\n\n function ensureInitialized(): void {\n if (initialized) {\n return;\n }\n\n routeFilesCache = new Set(scanRouteFiles());\n contentFilesCache = new Set(scanContentFiles());\n initialized = true;\n }\n\n return {\n getRouteFiles(): string[] {\n ensureInitialized();\n return [...routeFilesCache].sort();\n },\n\n getContentFiles(): string[] {\n ensureInitialized();\n return [...contentFilesCache].sort();\n },\n\n getDiscoveredFileKind(path: string): 'route' | 'content' | null {\n return getDiscoveredFileKind(path);\n },\n\n updateDiscoveredFile(\n path: string,\n event: 'add' | 'change' | 'unlink',\n ): void {\n ensureInitialized();\n const kind = getDiscoveredFileKind(path);\n if (!kind) {\n return;\n }\n\n const normalizedPath = normalizePath_(path);\n const targetCache =\n kind === 'content' ? contentFilesCache : routeFilesCache;\n\n if (event === 'unlink') {\n targetCache.delete(normalizedPath);\n appLocalFilesCache.delete(normalizedPath);\n return;\n }\n\n targetCache.add(normalizedPath);\n if (isAppLocalByPath(path)) {\n appLocalFilesCache.add(normalizedPath);\n }\n },\n\n isAppLocal(normalizedFilename: string): boolean {\n ensureInitialized();\n return appLocalFilesCache.has(normalizedFilename);\n },\n\n reset(): void {\n initialized = false;\n appLocalFilesCache = new Set<string>();\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { typedRoutes } from "./typed-routes-plugin.js";
|
|
2
|
+
//#region packages/platform/src/lib/route-generation-plugin.ts
|
|
3
|
+
function resolveTypedRouterOptions(experimental) {
|
|
4
|
+
const typedRouter = experimental?.typedRouter;
|
|
5
|
+
if (!typedRouter) return {
|
|
6
|
+
enabled: false,
|
|
7
|
+
options: {}
|
|
8
|
+
};
|
|
9
|
+
if (typedRouter === true) return {
|
|
10
|
+
enabled: true,
|
|
11
|
+
options: { jsonLdManifest: true }
|
|
12
|
+
};
|
|
13
|
+
return {
|
|
14
|
+
enabled: true,
|
|
15
|
+
options: {
|
|
16
|
+
...typedRouter,
|
|
17
|
+
jsonLdManifest: typedRouter.jsonLdManifest ?? true
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function routeGenerationPlugin(options) {
|
|
22
|
+
const { enabled, options: typedRouterOptions } = resolveTypedRouterOptions(options?.experimental);
|
|
23
|
+
if (!enabled) return { name: "analog-route-generation-disabled" };
|
|
24
|
+
return typedRoutes({
|
|
25
|
+
...typedRouterOptions,
|
|
26
|
+
workspaceRoot: options?.workspaceRoot,
|
|
27
|
+
additionalPagesDirs: options?.additionalPagesDirs,
|
|
28
|
+
additionalContentDirs: options?.additionalContentDirs
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
export { routeGenerationPlugin };
|
|
33
|
+
|
|
34
|
+
//# sourceMappingURL=route-generation-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-generation-plugin.js","names":[],"sources":["../../../../../packages/platform/src/lib/route-generation-plugin.ts"],"sourcesContent":["import type { Plugin } from 'vite';\n\nimport type { Options, TypedRouterOptions } from './options.js';\nimport {\n typedRoutes,\n type TypedRoutesPluginOptions,\n} from './typed-routes-plugin.js';\n\nfunction resolveTypedRouterOptions(experimental: Options['experimental']): {\n enabled: boolean;\n options: TypedRouterOptions;\n} {\n const typedRouter = experimental?.typedRouter;\n if (!typedRouter) {\n return { enabled: false, options: {} };\n }\n if (typedRouter === true) {\n return { enabled: true, options: { jsonLdManifest: true } };\n }\n return {\n enabled: true,\n options: {\n ...typedRouter,\n jsonLdManifest: typedRouter.jsonLdManifest ?? true,\n },\n };\n}\n\nexport function routeGenerationPlugin(options?: Options): Plugin {\n const { enabled, options: typedRouterOptions } = resolveTypedRouterOptions(\n options?.experimental,\n );\n\n if (!enabled) {\n return {\n name: 'analog-route-generation-disabled',\n };\n }\n\n const pluginOptions: TypedRoutesPluginOptions = {\n ...typedRouterOptions,\n workspaceRoot: options?.workspaceRoot,\n additionalPagesDirs: options?.additionalPagesDirs,\n additionalContentDirs: options?.additionalContentDirs,\n };\n\n return typedRoutes(pluginOptions);\n}\n"],"mappings":";;AAQA,SAAS,0BAA0B,cAGjC;CACA,MAAM,cAAc,cAAc;AAClC,KAAI,CAAC,YACH,QAAO;EAAE,SAAS;EAAO,SAAS,EAAE;EAAE;AAExC,KAAI,gBAAgB,KAClB,QAAO;EAAE,SAAS;EAAM,SAAS,EAAE,gBAAgB,MAAM;EAAE;AAE7D,QAAO;EACL,SAAS;EACT,SAAS;GACP,GAAG;GACH,gBAAgB,YAAY,kBAAkB;GAC/C;EACF;;AAGH,SAAgB,sBAAsB,SAA2B;CAC/D,MAAM,EAAE,SAAS,SAAS,uBAAuB,0BAC/C,SAAS,aACV;AAED,KAAI,CAAC,QACH,QAAO,EACL,MAAM,oCACP;AAUH,QAAO,YAPyC;EAC9C,GAAG;EACH,eAAe,SAAS;EACxB,qBAAqB,SAAS;EAC9B,uBAAuB,SAAS;EACjC,CAEgC"}
|
|
@@ -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 RouteSchemaInfo {
|
|
12
|
+
hasParamsSchema: boolean;
|
|
13
|
+
hasQuerySchema: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface GenerateRouteTreeDeclarationOptions {
|
|
16
|
+
jsonLdPaths?: Iterable<string>;
|
|
17
|
+
}
|
|
18
|
+
export interface RouteEntry {
|
|
19
|
+
/** Stable structural route id derived from the source filename */
|
|
20
|
+
id: string;
|
|
21
|
+
/** The route path segment relative to the nearest existing parent route */
|
|
22
|
+
path: string;
|
|
23
|
+
/** The fully resolved navigation path pattern (e.g., '/users/[id]') */
|
|
24
|
+
fullPath: string;
|
|
25
|
+
/** Extracted parameter information */
|
|
26
|
+
params: RouteParamInfo[];
|
|
27
|
+
/** Original filename that produced this route */
|
|
28
|
+
filename: string;
|
|
29
|
+
/** Schema export info (detected from file content) */
|
|
30
|
+
schemas: RouteSchemaInfo;
|
|
31
|
+
/** Type of source that produced this route */
|
|
32
|
+
kind: "page" | "content";
|
|
33
|
+
/** Parent route id, or null for top-level routes */
|
|
34
|
+
parentId: string | null;
|
|
35
|
+
/** Child route ids */
|
|
36
|
+
children: string[];
|
|
37
|
+
/** Whether the source filename represents an index route */
|
|
38
|
+
isIndex: boolean;
|
|
39
|
+
/** Whether the source filename includes route-group/pathless segments */
|
|
40
|
+
isGroup: boolean;
|
|
41
|
+
/** Whether the route contains a required catch-all parameter */
|
|
42
|
+
isCatchAll: boolean;
|
|
43
|
+
/** Whether the route contains an optional catch-all parameter */
|
|
44
|
+
isOptionalCatchAll: boolean;
|
|
45
|
+
}
|
|
46
|
+
export interface RouteManifest {
|
|
47
|
+
routes: RouteEntry[];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Converts a discovered filename to a route path pattern.
|
|
51
|
+
*
|
|
52
|
+
* Uses the same stripping rules as the existing route system
|
|
53
|
+
* but preserves bracket param syntax instead of converting to
|
|
54
|
+
* Angular's `:param` syntax.
|
|
55
|
+
*
|
|
56
|
+
* Examples:
|
|
57
|
+
* - '/app/routes/index.ts' -> '/'
|
|
58
|
+
* - '/app/routes/about.ts' -> '/about'
|
|
59
|
+
* - '/src/app/pages/users/[id].page.ts' -> '/users/[id]'
|
|
60
|
+
* - '/app/routes/blog.[slug].ts' -> '/blog/[slug]'
|
|
61
|
+
* - '/src/app/pages/(auth)/login.page.ts' -> '/login'
|
|
62
|
+
* - '/src/app/pages/docs/[...slug].page.ts' -> '/docs/[...slug]'
|
|
63
|
+
* - '/src/app/pages/shop/[[...category]].page.ts' -> '/shop/[[...category]]'
|
|
64
|
+
*/
|
|
65
|
+
export declare function filenameToRoutePath(filename: string): string;
|
|
66
|
+
/**
|
|
67
|
+
* Converts a discovered filename to a stable structural route id.
|
|
68
|
+
*
|
|
69
|
+
* Unlike `filenameToRoutePath`, this preserves route groups and `index`
|
|
70
|
+
* segments so that multiple files resolving to the same URL shape can still
|
|
71
|
+
* have distinct structural identities in the generated route tree metadata.
|
|
72
|
+
*/
|
|
73
|
+
export declare function filenameToRouteId(filename: string): string;
|
|
74
|
+
/**
|
|
75
|
+
* Extracts parameter information from a route path pattern.
|
|
76
|
+
*/
|
|
77
|
+
export declare function extractRouteParams(routePath: string): RouteParamInfo[];
|
|
78
|
+
/**
|
|
79
|
+
* Detects whether a route file exports schema constants.
|
|
80
|
+
*/
|
|
81
|
+
export declare function detectSchemaExports(fileContent: string): RouteSchemaInfo;
|
|
82
|
+
/**
|
|
83
|
+
* Generates a route manifest from a list of discovered filenames.
|
|
84
|
+
*
|
|
85
|
+
* @param collisionPriority - Optional callback that returns a numeric priority
|
|
86
|
+
* for each filename (lower wins). When provided, this replaces the default
|
|
87
|
+
* hard-coded path-substring heuristic with config-derived precedence.
|
|
88
|
+
*/
|
|
89
|
+
export declare function generateRouteManifest(filenames: string[], schemaDetector?: (filename: string) => RouteSchemaInfo, collisionPriority?: (filename: string) => number): RouteManifest;
|
|
90
|
+
/**
|
|
91
|
+
* Produces a human-readable summary of the generated route manifest.
|
|
92
|
+
*/
|
|
93
|
+
export declare function formatManifestSummary(manifest: RouteManifest): string;
|
|
94
|
+
/**
|
|
95
|
+
* Generates the route-table section for the combined generated route module.
|
|
96
|
+
*/
|
|
97
|
+
export declare function generateRouteTableDeclaration(manifest: RouteManifest): string;
|
|
98
|
+
/**
|
|
99
|
+
* Generates the route-tree section for the combined generated route module.
|
|
100
|
+
*/
|
|
101
|
+
export declare function generateRouteTreeDeclaration(manifest: RouteManifest, options?: GenerateRouteTreeDeclarationOptions): string;
|
|
102
|
+
export type JsonLdObject = Record<string, unknown>;
|
|
103
|
+
export declare function isJsonLdObject(value: unknown): value is JsonLdObject;
|
|
104
|
+
export declare function normalizeJsonLd(value: unknown): JsonLdObject[];
|