@analogjs/platform 3.0.0-alpha.9 → 3.0.0-alpha.91
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/migrations/migration.json +7 -1
- package/package.json +28 -14
- package/src/index.d.ts +4 -2
- package/src/index.js +2 -1
- package/src/index.js.map +1 -1
- package/src/lib/analog-integration-plugin.d.ts +9 -0
- package/src/lib/analog-integration-plugin.js +22 -0
- package/src/lib/analog-integration-plugin.js.map +1 -0
- package/src/lib/clear-client-page-endpoint.d.ts +2 -2
- package/src/lib/clear-client-page-endpoint.js +27 -5
- package/src/lib/clear-client-page-endpoint.js.map +1 -1
- package/src/lib/content/marked/index.d.ts +5 -5
- package/src/lib/content/marked/index.js.map +1 -1
- package/src/lib/content/marked/marked-content-highlighter.d.ts +2 -2
- package/src/lib/content/marked/marked-content-highlighter.js.map +1 -1
- package/src/lib/content/marked/marked-setup.service.d.ts +8 -8
- package/src/lib/content/marked/marked-setup.service.js +7 -5
- package/src/lib/content/marked/marked-setup.service.js.map +1 -1
- package/src/lib/content/prism/angular.js.map +1 -1
- package/src/lib/content/prism/index.d.ts +1 -1
- package/src/lib/content/prism/index.js.map +1 -1
- package/src/lib/content/prism/options.d.ts +1 -1
- package/src/lib/content/prism/prism-highlighter.d.ts +5 -5
- package/src/lib/content/prism/prism-highlighter.js.map +1 -1
- package/src/lib/content/shiki/index.d.ts +3 -3
- package/src/lib/content/shiki/index.js +9 -6
- package/src/lib/content/shiki/index.js.map +1 -1
- package/src/lib/content/shiki/options.d.ts +8 -7
- package/src/lib/content/shiki/shiki-highlighter.d.ts +14 -13
- package/src/lib/content/shiki/shiki-highlighter.js +7 -4
- package/src/lib/content/shiki/shiki-highlighter.js.map +1 -1
- package/src/lib/content/utils/escape-html.d.ts +7 -0
- package/src/lib/content/utils/escape-html.js +16 -0
- package/src/lib/content/utils/escape-html.js.map +1 -0
- package/src/lib/content-plugin.d.ts +19 -19
- package/src/lib/content-plugin.js +34 -9
- package/src/lib/content-plugin.js.map +1 -1
- package/src/lib/deps-plugin.d.ts +2 -2
- package/src/lib/deps-plugin.js +24 -11
- package/src/lib/deps-plugin.js.map +1 -1
- package/src/lib/discover-library-routes.d.ts +19 -0
- package/src/lib/discover-library-routes.js +72 -0
- package/src/lib/discover-library-routes.js.map +1 -0
- package/src/lib/i18n-component-registry-plugin.d.ts +17 -0
- package/src/lib/i18n-component-registry-plugin.js +100 -0
- package/src/lib/i18n-component-registry-plugin.js.map +1 -0
- package/src/lib/i18n-extract-plugin.d.ts +33 -0
- package/src/lib/inject-server-fn-ids.d.ts +17 -0
- package/src/lib/inject-server-fn-ids.js +94 -0
- package/src/lib/inject-server-fn-ids.js.map +1 -0
- package/src/lib/nitro/analog-nitro-plugin.d.ts +18 -0
- package/src/lib/nitro/analog-nitro-plugin.js +582 -0
- package/src/lib/nitro/analog-nitro-plugin.js.map +1 -0
- package/src/lib/nitro/angular-linker-plugin.d.ts +15 -0
- package/src/lib/nitro/angular-linker-plugin.js +64 -0
- package/src/lib/nitro/angular-linker-plugin.js.map +1 -0
- package/src/lib/nitro/build-sitemap.d.ts +23 -0
- package/src/lib/nitro/build-sitemap.js +137 -0
- package/src/lib/nitro/build-sitemap.js.map +1 -0
- package/src/lib/nitro/debug.d.ts +5 -0
- package/src/lib/nitro/debug.js +11 -0
- package/src/lib/nitro/debug.js.map +1 -0
- package/src/lib/nitro/get-content-files.d.ts +13 -0
- package/src/lib/nitro/get-content-files.js +52 -0
- package/src/lib/nitro/get-content-files.js.map +1 -0
- package/src/lib/nitro/get-page-handlers.d.ts +22 -0
- package/src/lib/nitro/get-page-handlers.js +33 -0
- package/src/lib/nitro/get-page-handlers.js.map +1 -0
- package/src/lib/nitro/i18n-prerender.d.ts +29 -0
- package/src/lib/nitro/i18n-prerender.js +61 -0
- package/src/lib/nitro/i18n-prerender.js.map +1 -0
- package/src/lib/nitro/page-endpoints-plugin.d.ts +7 -0
- package/src/lib/nitro/page-endpoints-plugin.js +72 -0
- package/src/lib/nitro/page-endpoints-plugin.js.map +1 -0
- package/src/lib/nitro/post-rendering-hook.d.ts +2 -0
- package/src/lib/nitro/post-rendering-hook.js +10 -0
- package/src/lib/nitro/post-rendering-hook.js.map +1 -0
- package/src/lib/nitro/renderers.d.ts +33 -0
- package/src/lib/nitro/renderers.js +22 -0
- package/src/lib/nitro/renderers.js.map +1 -0
- package/src/lib/nitro/types.d.ts +122 -0
- package/src/lib/nx-plugin/_virtual/_rolldown/runtime.js +23 -0
- package/src/lib/nx-plugin/builders.json +15 -0
- package/src/lib/nx-plugin/executors.json +13 -5
- package/src/lib/nx-plugin/generators.json +25 -0
- package/src/lib/nx-plugin/node_modules/.pnpm/es-toolkit@1.45.1/node_modules/es-toolkit/dist/string/camelCase.js +13 -0
- package/src/lib/nx-plugin/node_modules/.pnpm/es-toolkit@1.45.1/node_modules/es-toolkit/dist/string/camelCase.js.map +1 -0
- package/src/lib/nx-plugin/node_modules/.pnpm/es-toolkit@1.45.1/node_modules/es-toolkit/dist/string/capitalize.js +8 -0
- package/src/lib/nx-plugin/node_modules/.pnpm/es-toolkit@1.45.1/node_modules/es-toolkit/dist/string/capitalize.js.map +1 -0
- package/src/lib/nx-plugin/node_modules/.pnpm/es-toolkit@1.45.1/node_modules/es-toolkit/dist/string/words.js +9 -0
- package/src/lib/nx-plugin/node_modules/.pnpm/es-toolkit@1.45.1/node_modules/es-toolkit/dist/string/words.js.map +1 -0
- package/src/lib/nx-plugin/package.json +1 -3
- package/src/lib/nx-plugin/src/builders/vite/schema.json +39 -0
- package/src/lib/nx-plugin/src/builders/vite/vite-build.d.ts +11 -0
- package/src/lib/nx-plugin/src/builders/vite/vite-build.js +18 -0
- package/src/lib/nx-plugin/src/builders/vite/vite-build.js.map +1 -0
- package/src/lib/nx-plugin/src/builders/vite-dev-server/dev-server.d.ts +7 -0
- package/src/lib/nx-plugin/src/builders/vite-dev-server/dev-server.js +14 -0
- package/src/lib/nx-plugin/src/builders/vite-dev-server/dev-server.js.map +1 -0
- package/src/lib/nx-plugin/src/builders/vite-dev-server/schema.json +27 -0
- package/src/lib/nx-plugin/src/executors/vite-dev-server/compat.d.ts +1 -1
- package/src/lib/nx-plugin/src/executors/vite-dev-server/compat.js +4 -4
- package/src/lib/nx-plugin/src/executors/vite-dev-server/compat.js.map +1 -1
- package/src/lib/nx-plugin/src/executors/vite-dev-server/vite-dev-server.impl.d.ts +1 -1
- package/src/lib/nx-plugin/src/executors/vite-dev-server/vite-dev-server.impl.js +3 -3
- package/src/lib/nx-plugin/src/executors/vite-dev-server/vite-dev-server.impl.js.map +1 -1
- package/src/lib/nx-plugin/src/executors/vitest/compat.d.ts +1 -1
- package/src/lib/nx-plugin/src/executors/vitest/compat.js +4 -4
- package/src/lib/nx-plugin/src/executors/vitest/compat.js.map +1 -1
- package/src/lib/nx-plugin/src/executors/vitest/vitest.impl.d.ts +1 -1
- package/src/lib/nx-plugin/src/executors/vitest/vitest.impl.js +3 -3
- package/src/lib/nx-plugin/src/executors/vitest/vitest.impl.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/app/compat.d.ts +9 -3
- package/src/lib/nx-plugin/src/generators/app/compat.js +15 -4
- package/src/lib/nx-plugin/src/generators/app/compat.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/app/files/agents/AGENTS.md +11 -0
- package/src/lib/nx-plugin/src/generators/app/files/agents/CLAUDE.md +1 -0
- package/src/lib/nx-plugin/src/generators/app/files/root/tsconfig.base.json +3 -6
- package/src/lib/nx-plugin/src/generators/app/files/template-angular/src/test-setup.ts__template__ +1 -0
- package/src/lib/nx-plugin/src/generators/app/files/template-angular/tsconfig.app.json__template__ +1 -3
- package/src/lib/nx-plugin/src/generators/app/files/template-angular/tsconfig.json__template__ +2 -1
- package/src/lib/nx-plugin/src/generators/app/files/template-angular/vite.config.ts__template__ +7 -3
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v17/tsconfig.json__template__ +4 -2
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v17/vite.config.ts__template__ +2 -5
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v18/tsconfig.json__template__ +4 -2
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v18/vite.config.ts__template__ +3 -6
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v19/tsconfig.app.json__template__ +1 -3
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v19/tsconfig.json__template__ +4 -2
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v19/vite.config.ts__template__ +2 -5
- package/src/lib/nx-plugin/src/generators/app/generator.d.ts +11 -11
- package/src/lib/nx-plugin/src/generators/app/generator.js +44 -37
- package/src/lib/nx-plugin/src/generators/app/generator.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/app/lib/add-agent-context.d.ts +2 -0
- package/src/lib/nx-plugin/src/generators/app/lib/add-agent-context.js +16 -0
- package/src/lib/nx-plugin/src/generators/app/lib/add-agent-context.js.map +1 -0
- package/src/lib/nx-plugin/src/generators/app/lib/add-analog-dependencies.d.ts +1 -1
- package/src/lib/nx-plugin/src/generators/app/lib/add-analog-project-config.d.ts +1 -1
- package/src/lib/nx-plugin/src/generators/app/lib/add-analog-project-config.js +6 -5
- package/src/lib/nx-plugin/src/generators/app/lib/add-analog-project-config.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/app/lib/add-angular-app.d.ts +2 -2
- package/src/lib/nx-plugin/src/generators/app/lib/add-angular-app.js +8 -11
- package/src/lib/nx-plugin/src/generators/app/lib/add-angular-app.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/app/lib/add-eslint.d.ts +2 -2
- package/src/lib/nx-plugin/src/generators/app/lib/add-files.d.ts +2 -2
- package/src/lib/nx-plugin/src/generators/app/lib/add-files.js +6 -5
- package/src/lib/nx-plugin/src/generators/app/lib/add-files.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/app/lib/add-home-page.d.ts +2 -2
- package/src/lib/nx-plugin/src/generators/app/lib/add-home-page.js +6 -5
- package/src/lib/nx-plugin/src/generators/app/lib/add-home-page.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/app/lib/add-tailwind-config.d.ts +7 -7
- package/src/lib/nx-plugin/src/generators/app/lib/add-tailwind-config.js +13 -11
- 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 +4 -5
- package/src/lib/nx-plugin/src/generators/app/lib/add-tailwind-helpers.js +34 -40
- package/src/lib/nx-plugin/src/generators/app/lib/add-tailwind-helpers.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/app/lib/add-vite-plugin.d.ts +1 -1
- package/src/lib/nx-plugin/src/generators/app/lib/cleanup-files.d.ts +2 -2
- package/src/lib/nx-plugin/src/generators/app/lib/cleanup-files.js +1 -1
- package/src/lib/nx-plugin/src/generators/app/lib/cleanup-files.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/app/lib/initialize-analog-workspace.d.ts +2 -2
- package/src/lib/nx-plugin/src/generators/app/lib/update-index-html.d.ts +1 -1
- package/src/lib/nx-plugin/src/generators/app/lib/update-index-html.js +5 -4
- package/src/lib/nx-plugin/src/generators/app/lib/update-index-html.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/app/schema.d.ts +3 -0
- package/src/lib/nx-plugin/src/generators/app/schema.json +6 -0
- package/src/lib/nx-plugin/src/generators/app/versions/minimum-supported-versions.d.ts +4 -2
- package/src/lib/nx-plugin/src/generators/app/versions/minimum-supported-versions.js +9 -6
- package/src/lib/nx-plugin/src/generators/app/versions/minimum-supported-versions.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/app/versions/nx-dependencies.d.ts +0 -3
- package/src/lib/nx-plugin/src/generators/app/versions/nx_17_X/versions.d.ts +1 -1
- package/src/lib/nx-plugin/src/generators/app/versions/nx_18_X/versions.d.ts +12 -12
- package/src/lib/nx-plugin/src/generators/app/versions/nx_18_X/versions.js +8 -27
- 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 +6 -5
- package/src/lib/nx-plugin/src/generators/app/versions/tailwind-dependencies.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/app/versions.d.ts +0 -18
- package/src/lib/nx-plugin/src/generators/init/compat.d.ts +9 -3
- package/src/lib/nx-plugin/src/generators/init/compat.js +15 -4
- package/src/lib/nx-plugin/src/generators/init/compat.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/init/files/vite.config.ts__template__ +2 -6
- package/src/lib/nx-plugin/src/generators/init/generator.d.ts +3 -3
- package/src/lib/nx-plugin/src/generators/init/generator.js +35 -34
- package/src/lib/nx-plugin/src/generators/init/generator.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/init/lib/add-analog-dependencies.d.ts +1 -1
- package/src/lib/nx-plugin/src/generators/init/lib/add-analog-dependencies.js +8 -7
- package/src/lib/nx-plugin/src/generators/init/lib/add-analog-dependencies.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/init/lib/update-app-tsconfig.d.ts +2 -2
- package/src/lib/nx-plugin/src/generators/init/lib/update-app-tsconfig.js +6 -5
- package/src/lib/nx-plugin/src/generators/init/lib/update-app-tsconfig.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/init/lib/update-build-target.d.ts +2 -2
- package/src/lib/nx-plugin/src/generators/init/lib/update-build-target.js +15 -14
- package/src/lib/nx-plugin/src/generators/init/lib/update-build-target.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/init/lib/update-git-ignore.d.ts +1 -1
- package/src/lib/nx-plugin/src/generators/init/lib/update-git-ignore.js +1 -1
- package/src/lib/nx-plugin/src/generators/init/lib/update-git-ignore.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/init/lib/update-index-html.d.ts +2 -2
- package/src/lib/nx-plugin/src/generators/init/lib/update-index-html.js +7 -6
- package/src/lib/nx-plugin/src/generators/init/lib/update-index-html.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/init/lib/update-main.d.ts +2 -2
- package/src/lib/nx-plugin/src/generators/init/lib/update-main.js +5 -4
- package/src/lib/nx-plugin/src/generators/init/lib/update-main.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/init/lib/update-package-json.d.ts +2 -2
- package/src/lib/nx-plugin/src/generators/init/lib/update-package-json.js +9 -8
- package/src/lib/nx-plugin/src/generators/init/lib/update-package-json.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/init/lib/update-serve-target.d.ts +2 -2
- package/src/lib/nx-plugin/src/generators/init/lib/update-serve-target.js +6 -5
- package/src/lib/nx-plugin/src/generators/init/lib/update-serve-target.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/init/lib/update-test-target.d.ts +2 -2
- package/src/lib/nx-plugin/src/generators/init/lib/update-test-target.js +6 -5
- package/src/lib/nx-plugin/src/generators/init/lib/update-test-target.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/init/lib/update-test-tsconfig.d.ts +2 -2
- package/src/lib/nx-plugin/src/generators/init/lib/update-test-tsconfig.js +6 -5
- package/src/lib/nx-plugin/src/generators/init/lib/update-test-tsconfig.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/init/test-files/src/test-setup.ts__template__ +1 -0
- package/src/lib/nx-plugin/src/generators/page/__snapshots__/generator.spec.ts.snap +0 -7
- package/src/lib/nx-plugin/src/generators/page/compat.d.ts +9 -0
- package/src/lib/nx-plugin/src/generators/page/compat.js +19 -0
- package/src/lib/nx-plugin/src/generators/page/compat.js.map +1 -0
- package/src/lib/nx-plugin/src/generators/page/files/__fileName__.page.ts__template__ +0 -1
- package/src/lib/nx-plugin/src/generators/page/generator.d.ts +3 -4
- package/src/lib/nx-plugin/src/generators/page/generator.js +14 -13
- package/src/lib/nx-plugin/src/generators/page/generator.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/preset/__snapshots__/generator.spec.ts.snap +9 -7
- package/src/lib/nx-plugin/src/generators/preset/generator.d.ts +3 -3
- package/src/lib/nx-plugin/src/generators/preset/generator.js +24 -7
- package/src/lib/nx-plugin/src/generators/preset/generator.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/preset/schema.d.ts +1 -0
- package/src/lib/nx-plugin/src/generators/preset/schema.json +6 -0
- package/src/lib/nx-plugin/src/generators/setup-vitest/compat.d.ts +9 -3
- package/src/lib/nx-plugin/src/generators/setup-vitest/compat.js +15 -4
- package/src/lib/nx-plugin/src/generators/setup-vitest/compat.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/setup-vitest/files/src/test-setup.ts__template__ +1 -0
- package/src/lib/nx-plugin/src/generators/setup-vitest/files/vite.config.mts__template__ +0 -6
- package/src/lib/nx-plugin/src/generators/setup-vitest/generator.d.ts +3 -3
- package/src/lib/nx-plugin/src/generators/setup-vitest/generator.js +19 -21
- package/src/lib/nx-plugin/src/generators/setup-vitest/generator.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/setup-vitest/lib/add-analog-dependencies.d.ts +1 -1
- package/src/lib/nx-plugin/src/generators/setup-vitest/lib/add-analog-dependencies.js +5 -4
- package/src/lib/nx-plugin/src/generators/setup-vitest/lib/add-analog-dependencies.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/setup-vitest/lib/update-test-target.d.ts +2 -2
- package/src/lib/nx-plugin/src/generators/setup-vitest/lib/update-test-target.js +6 -5
- package/src/lib/nx-plugin/src/generators/setup-vitest/lib/update-test-target.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/setup-vitest/lib/update-tsconfig.d.ts +2 -2
- package/src/lib/nx-plugin/src/generators/setup-vitest/lib/update-tsconfig.js +6 -5
- package/src/lib/nx-plugin/src/generators/setup-vitest/lib/update-tsconfig.js.map +1 -1
- package/src/lib/nx-plugin/src/utils/version-utils.d.ts +1 -1
- package/src/lib/nx-plugin/src/utils/version-utils.js +9 -8
- package/src/lib/nx-plugin/src/utils/version-utils.js.map +1 -1
- package/src/lib/nx-plugin/src/utils/versions/dependencies.js +33 -32
- package/src/lib/nx-plugin/src/utils/versions/dependencies.js.map +1 -1
- package/src/lib/nx-plugin/src/utils/versions/dev-dependencies.js +40 -39
- package/src/lib/nx-plugin/src/utils/versions/dev-dependencies.js.map +1 -1
- package/src/lib/nx-plugin/src/utils/versions/ng_17_X/versions.d.ts +1 -1
- package/src/lib/nx-plugin/src/utils/versions/ng_17_X/versions.js +16 -2
- package/src/lib/nx-plugin/src/utils/versions/ng_17_X/versions.js.map +1 -1
- package/src/lib/nx-plugin/src/utils/versions/ng_18_X/versions.d.ts +1 -1
- package/src/lib/nx-plugin/src/utils/versions/ng_18_X/versions.js +16 -2
- package/src/lib/nx-plugin/src/utils/versions/ng_18_X/versions.js.map +1 -1
- package/src/lib/nx-plugin/src/utils/versions/ng_19_X/versions.d.ts +9 -8
- package/src/lib/nx-plugin/src/utils/versions/ng_19_X/versions.js +27 -10
- package/src/lib/nx-plugin/src/utils/versions/ng_19_X/versions.js.map +1 -1
- package/src/lib/options.d.ts +117 -84
- package/src/lib/platform-plugin.d.ts +2 -2
- package/src/lib/platform-plugin.js +25 -34
- package/src/lib/platform-plugin.js.map +1 -1
- package/src/lib/route-file-discovery.d.ts +25 -0
- package/src/lib/route-file-discovery.js +125 -0
- package/src/lib/route-file-discovery.js.map +1 -0
- package/src/lib/route-idiom-diagnostics.d.ts +13 -0
- package/src/lib/route-idiom-diagnostics.js +160 -0
- package/src/lib/route-idiom-diagnostics.js.map +1 -0
- package/src/lib/route-manifest.d.ts +118 -0
- package/src/lib/route-manifest.js +300 -0
- package/src/lib/route-manifest.js.map +1 -0
- package/src/lib/router-plugin.d.ts +19 -19
- package/src/lib/router-plugin.js +127 -33
- package/src/lib/router-plugin.js.map +1 -1
- package/src/lib/server-fn-client-transform.d.ts +26 -0
- package/src/lib/server-fn-client-transform.js +97 -0
- package/src/lib/server-fn-client-transform.js.map +1 -0
- package/src/lib/server-fn-id.d.ts +25 -0
- package/src/lib/server-fn-id.js +37 -0
- package/src/lib/server-fn-id.js.map +1 -0
- package/src/lib/ssr/defer-streaming-plugin.d.ts +65 -0
- package/src/lib/ssr/inject-html-plugin.d.ts +1 -1
- package/src/lib/ssr/inject-html-plugin.js.map +1 -1
- package/src/lib/ssr/ssr-build-plugin.d.ts +24 -16
- package/src/lib/ssr/ssr-build-plugin.js +2 -18
- package/src/lib/ssr/ssr-build-plugin.js.map +1 -1
- package/src/lib/typed-routes-plugin.d.ts +13 -0
- package/src/lib/typed-routes-plugin.js +119 -0
- package/src/lib/typed-routes-plugin.js.map +1 -0
- package/src/lib/utils/debug-harness.d.ts +23 -0
- package/src/lib/utils/debug-harness.js +88 -0
- package/src/lib/utils/debug-harness.js.map +1 -0
- package/src/lib/utils/debug-log-file.d.ts +5 -0
- package/src/lib/utils/debug-log-file.js +56 -0
- package/src/lib/utils/debug-log-file.js.map +1 -0
- package/src/lib/utils/debug.d.ts +20 -0
- package/src/lib/utils/debug.js +21 -0
- package/src/lib/utils/debug.js.map +1 -0
- package/src/lib/utils/rolldown.d.ts +2 -2
- package/src/lib/utils/rolldown.js.map +1 -1
- package/src/server-mode-plugin.d.ts +11 -5
- package/src/server-mode-plugin.js +16 -6
- package/src/server-mode-plugin.js.map +1 -1
- package/src/lib/nx-plugin/src/executors/vite/compat.d.ts +0 -3
- package/src/lib/nx-plugin/src/executors/vite/compat.js +0 -8
- package/src/lib/nx-plugin/src/executors/vite/compat.js.map +0 -1
- package/src/lib/nx-plugin/src/executors/vite/schema.d.ts +0 -2
- package/src/lib/nx-plugin/src/executors/vite/schema.json +0 -147
- package/src/lib/nx-plugin/src/executors/vite/vite.impl.d.ts +0 -2
- package/src/lib/nx-plugin/src/executors/vite/vite.impl.js +0 -7
- package/src/lib/nx-plugin/src/executors/vite/vite.impl.js.map +0 -1
- 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/nx-plugin/src/generators/app/files/template-angular-v15/index.html__template__ +0 -15
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v15/src/app/app.component.spec.ts__template__ +0 -17
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v15/src/app/app.component.ts__template__ +0 -10
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v15/src/favicon.ico__template__ +0 -0
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v15/src/main.providers.ts__template__ +0 -5
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v15/src/main.server.ts__template__ +0 -23
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v15/src/main.ts__template__ +0 -11
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v15/src/public/assets/.gitkeep__template__ +0 -0
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v15/src/public/assets/analog.svg__template__ +0 -1
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v15/src/public/assets/vite.svg__template__ +0 -1
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v15/src/server/routes/v1/hello.ts__template__ +0 -3
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v15/src/styles.css__template__ +0 -4
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v15/src/test-setup.ts__template__ +0 -12
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v15/src/vite-env.d.ts__template__ +0 -1
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v15/tsconfig.app.json__template__ +0 -16
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v15/tsconfig.editor.json__template__ +0 -7
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v15/tsconfig.json__template__ +0 -32
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v15/tsconfig.spec.json__template__ +0 -14
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v15/vite.config.ts__template__ +0 -61
- package/src/lib/nx-plugin/src/generators/app/lib/add-analog-dependencies.js +0 -14
- package/src/lib/nx-plugin/src/generators/app/lib/add-analog-dependencies.js.map +0 -1
- package/src/lib/nx-plugin/src/generators/app/lib/add-eslint.js +0 -15
- package/src/lib/nx-plugin/src/generators/app/lib/add-eslint.js.map +0 -1
- package/src/lib/nx-plugin/src/generators/app/lib/add-vite-plugin.js +0 -11
- package/src/lib/nx-plugin/src/generators/app/lib/add-vite-plugin.js.map +0 -1
- package/src/lib/nx-plugin/src/generators/app/lib/initialize-analog-workspace.js +0 -64
- package/src/lib/nx-plugin/src/generators/app/lib/initialize-analog-workspace.js.map +0 -1
- package/src/lib/nx-plugin/src/generators/app/versions/dependencies.js +0 -37
- package/src/lib/nx-plugin/src/generators/app/versions/dependencies.js.map +0 -1
- package/src/lib/nx-plugin/src/generators/app/versions/dev-dependencies.js +0 -45
- package/src/lib/nx-plugin/src/generators/app/versions/dev-dependencies.js.map +0 -1
- package/src/lib/nx-plugin/src/generators/app/versions/nx-dependencies.js +0 -27
- package/src/lib/nx-plugin/src/generators/app/versions/nx-dependencies.js.map +0 -1
- package/src/lib/nx-plugin/src/generators/app/versions/nx_17_X/versions.js +0 -30
- package/src/lib/nx-plugin/src/generators/app/versions/nx_17_X/versions.js.map +0 -1
- package/src/lib/nx-plugin/src/generators/app/versions.js +0 -29
- package/src/lib/nx-plugin/src/generators/app/versions.js.map +0 -1
- package/src/lib/nx-plugin/src/index.d.ts +0 -0
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
//#region packages/platform/src/lib/route-manifest.ts
|
|
2
|
+
/**
|
|
3
|
+
* Converts a discovered filename to a route path pattern.
|
|
4
|
+
*
|
|
5
|
+
* Uses the same stripping rules as the existing route system
|
|
6
|
+
* but preserves bracket param syntax instead of converting to
|
|
7
|
+
* Angular's `:param` syntax.
|
|
8
|
+
*
|
|
9
|
+
* The regex applies four alternations (left to right, all replaced with ''):
|
|
10
|
+
* 1. `^(.*?)[\\/](?:routes|pages|content)[\\/]` — anchored, strips everything
|
|
11
|
+
* up to and including the first /routes/, /pages/, or /content/ segment.
|
|
12
|
+
* Handles app-local paths (`/src/app/pages/`) AND additional dirs
|
|
13
|
+
* (`/libs/shared/feature/src/content/`) uniformly.
|
|
14
|
+
* 2. `[\\/](?:app[\\/](?:routes|pages)|src[\\/]content)[\\/]` — non-anchored
|
|
15
|
+
* fallback for legacy paths where the directory marker appears mid-string.
|
|
16
|
+
* 3. `\.page\.(js|ts|analog|ag)$` — strips page file extensions.
|
|
17
|
+
* 4. `\.(ts|md|analog|ag)$` — strips remaining file extensions.
|
|
18
|
+
*
|
|
19
|
+
* Examples:
|
|
20
|
+
* - '/app/routes/index.ts' -> '/'
|
|
21
|
+
* - '/app/routes/about.ts' -> '/about'
|
|
22
|
+
* - '/src/app/pages/users/[id].page.ts' -> '/users/[id]'
|
|
23
|
+
* - '/app/routes/blog.[slug].ts' -> '/blog/[slug]'
|
|
24
|
+
* - '/src/app/pages/(auth)/login.page.ts' -> '/login'
|
|
25
|
+
* - '/src/app/pages/docs/[...slug].page.ts' -> '/docs/[...slug]'
|
|
26
|
+
* - '/src/app/pages/shop/[[...category]].page.ts' -> '/shop/[[...category]]'
|
|
27
|
+
* - '/libs/shared/feature/src/content/test.md' -> '/test'
|
|
28
|
+
*/
|
|
29
|
+
function filenameToRoutePath(filename) {
|
|
30
|
+
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, "");
|
|
31
|
+
const brackets = [];
|
|
32
|
+
path = path.replace(/\[\[?\.{0,3}[^\]]*\]?\]/g, (match) => {
|
|
33
|
+
brackets.push(match);
|
|
34
|
+
return `\0B${brackets.length - 1}\0`;
|
|
35
|
+
});
|
|
36
|
+
path = path.replace(/\(.*?\)/g, "").replace(/(^|[./])index(?=[./]|$)/g, "$1").replace(/\./g, "/");
|
|
37
|
+
path = path.replace(/\0B(\d+)\0/g, (_, idx) => brackets[Number(idx)]);
|
|
38
|
+
return "/" + path.split("/").filter(Boolean).join("/");
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Converts a discovered filename to a stable structural route id.
|
|
42
|
+
*
|
|
43
|
+
* Unlike `filenameToRoutePath`, this preserves route groups and `index`
|
|
44
|
+
* segments so that multiple files resolving to the same URL shape can still
|
|
45
|
+
* have distinct structural identities in the generated route tree metadata.
|
|
46
|
+
*
|
|
47
|
+
* Uses the same directory-stripping regex as `filenameToRoutePath` —
|
|
48
|
+
* changes to the regex must be kept in sync between both functions.
|
|
49
|
+
*/
|
|
50
|
+
function filenameToRouteId(filename) {
|
|
51
|
+
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, "");
|
|
52
|
+
const brackets = [];
|
|
53
|
+
path = path.replace(/\(.*?\)|\[\[?\.{0,3}[^\]]*\]?\]/g, (match) => {
|
|
54
|
+
brackets.push(match);
|
|
55
|
+
return `\0B${brackets.length - 1}\0`;
|
|
56
|
+
});
|
|
57
|
+
path = path.replace(/\./g, "/");
|
|
58
|
+
path = path.replace(/\0B(\d+)\0/g, (_, idx) => brackets[Number(idx)]);
|
|
59
|
+
return "/" + path.split("/").filter(Boolean).join("/");
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Extracts parameter information from a route path pattern.
|
|
63
|
+
*/
|
|
64
|
+
function extractRouteParams(routePath) {
|
|
65
|
+
const params = [];
|
|
66
|
+
for (const match of routePath.matchAll(/\[\[\.\.\.([^\]]+)\]\]/g)) params.push({
|
|
67
|
+
name: match[1],
|
|
68
|
+
type: "optionalCatchAll"
|
|
69
|
+
});
|
|
70
|
+
for (const match of routePath.matchAll(/(?<!\[)\[\.\.\.([^\]]+)\](?!\])/g)) params.push({
|
|
71
|
+
name: match[1],
|
|
72
|
+
type: "catchAll"
|
|
73
|
+
});
|
|
74
|
+
for (const match of routePath.matchAll(/(?<!\[)\[(?!\.)([^\]]+)\](?!\])/g)) params.push({
|
|
75
|
+
name: match[1],
|
|
76
|
+
type: "dynamic"
|
|
77
|
+
});
|
|
78
|
+
return params;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Generates a route manifest from a list of discovered filenames.
|
|
82
|
+
*
|
|
83
|
+
* @param collisionPriority - Optional callback that returns a numeric priority
|
|
84
|
+
* for each filename (lower wins). When provided, this replaces the default
|
|
85
|
+
* hard-coded path-substring heuristic with config-derived precedence.
|
|
86
|
+
*/
|
|
87
|
+
function generateRouteManifest(filenames, collisionPriority) {
|
|
88
|
+
const routes = [];
|
|
89
|
+
const collisions = [];
|
|
90
|
+
const sharedFullPaths = /* @__PURE__ */ new Set();
|
|
91
|
+
const seenByFullPath = /* @__PURE__ */ new Map();
|
|
92
|
+
const getPriority = collisionPriority ?? getCollisionPriority;
|
|
93
|
+
const prioritizedFilenames = [...filenames].sort((a, b) => {
|
|
94
|
+
const aPriority = getPriority(a);
|
|
95
|
+
const bPriority = getPriority(b);
|
|
96
|
+
if (aPriority !== bPriority) return aPriority - bPriority;
|
|
97
|
+
return a.localeCompare(b);
|
|
98
|
+
});
|
|
99
|
+
const layoutByKey = /* @__PURE__ */ new Map();
|
|
100
|
+
for (const filename of prioritizedFilenames) {
|
|
101
|
+
const key = toRouteFileKey(filename);
|
|
102
|
+
if (!filename.endsWith(".md") && !layoutByKey.has(key)) layoutByKey.set(key, filename);
|
|
103
|
+
}
|
|
104
|
+
for (const filename of prioritizedFilenames) {
|
|
105
|
+
const fullPath = filenameToRoutePath(filename);
|
|
106
|
+
const params = extractRouteParams(fullPath);
|
|
107
|
+
const id = filenameToRouteId(filename);
|
|
108
|
+
const isPathlessLayout = isPathlessLayoutId(id);
|
|
109
|
+
const groupScope = id.slice(0, id.lastIndexOf(")") + 1);
|
|
110
|
+
const collisionKey = JSON.stringify([fullPath, groupScope]);
|
|
111
|
+
const currentPriority = getPriority(filename);
|
|
112
|
+
if (!isPathlessLayout) {
|
|
113
|
+
if (seenByFullPath.has(collisionKey)) {
|
|
114
|
+
const winner = seenByFullPath.get(collisionKey);
|
|
115
|
+
if (winner.filename === filename) continue;
|
|
116
|
+
const isLayoutIndexPair = (a, b) => {
|
|
117
|
+
const indexRe = /\/index\.(page\.)?(ts|js|md|analog|ag)$/;
|
|
118
|
+
const layoutRe = /\.(page\.)?(ts|js|analog|ag)$/;
|
|
119
|
+
if (indexRe.test(a) && layoutRe.test(b)) return a.replace(indexRe, "") === b.replace(layoutRe, "");
|
|
120
|
+
return false;
|
|
121
|
+
};
|
|
122
|
+
if (isLayoutIndexPair(winner.filename, filename) || isLayoutIndexPair(filename, winner.filename)) {
|
|
123
|
+
sharedFullPaths.add(fullPath);
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
collisions.push({
|
|
127
|
+
fullPath,
|
|
128
|
+
keptFile: winner.filename,
|
|
129
|
+
droppedFile: filename,
|
|
130
|
+
samePriority: winner.priority === currentPriority
|
|
131
|
+
});
|
|
132
|
+
console.warn(`[Analog] Route collision: '${fullPath}' is defined by both '${winner.filename}' and '${filename}'. Keeping '${winner.filename}' based on route source precedence and skipping duplicate.`);
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
seenByFullPath.set(collisionKey, {
|
|
136
|
+
filename,
|
|
137
|
+
priority: currentPriority
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
const segments = toRouteFileKey(filename).split("/");
|
|
141
|
+
const layouts = [];
|
|
142
|
+
for (let i = 1; i < segments.length; i++) {
|
|
143
|
+
const layout = layoutByKey.get(segments.slice(0, i).join("/"));
|
|
144
|
+
if (layout) layouts.push(layout);
|
|
145
|
+
}
|
|
146
|
+
routes.push({
|
|
147
|
+
id,
|
|
148
|
+
path: fullPath,
|
|
149
|
+
fullPath,
|
|
150
|
+
params,
|
|
151
|
+
filename,
|
|
152
|
+
kind: filename.endsWith(".md") ? "content" : "page",
|
|
153
|
+
parentId: null,
|
|
154
|
+
children: [],
|
|
155
|
+
isIndex: id === "/index" || id.endsWith("/index"),
|
|
156
|
+
isGroup: isPathlessLayout,
|
|
157
|
+
isCatchAll: params.some((param) => param.type === "catchAll"),
|
|
158
|
+
isOptionalCatchAll: params.some((param) => param.type === "optionalCatchAll"),
|
|
159
|
+
layouts
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
routes.sort((a, b) => {
|
|
163
|
+
const aW = getRouteWeight(a.fullPath);
|
|
164
|
+
const bW = getRouteWeight(b.fullPath);
|
|
165
|
+
if (aW !== bW) return aW - bW;
|
|
166
|
+
return a.fullPath.localeCompare(b.fullPath);
|
|
167
|
+
});
|
|
168
|
+
const routeByFullPath = canonicalRoutesByFullPath(routes);
|
|
169
|
+
const routeById = new Map(routes.map((route) => [route.id, route]));
|
|
170
|
+
for (const route of routes) {
|
|
171
|
+
const structuralParent = route.id.includes("/(") ? findNearestParentById(route.id, routeById) : void 0;
|
|
172
|
+
const fullPathParent = findNearestParentRoute(route.fullPath, routeByFullPath);
|
|
173
|
+
const parent = structuralParent ?? fullPathParent;
|
|
174
|
+
route.parentId = parent?.id ?? null;
|
|
175
|
+
route.path = computeLocalPath(route.fullPath, parent?.fullPath ?? null);
|
|
176
|
+
}
|
|
177
|
+
for (const route of routes) {
|
|
178
|
+
if (route.parentId) routeById.get(route.parentId)?.children.push(route.id);
|
|
179
|
+
if (routeByFullPath.get(route.fullPath) !== route) sharedFullPaths.add(route.fullPath);
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
routes,
|
|
183
|
+
collisions,
|
|
184
|
+
canonicalByFullPath: routeByFullPath,
|
|
185
|
+
sharedFullPaths
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
function canonicalRoutesByFullPath(routes) {
|
|
189
|
+
const map = /* @__PURE__ */ new Map();
|
|
190
|
+
for (const route of routes) {
|
|
191
|
+
const existing = map.get(route.fullPath);
|
|
192
|
+
if (!existing) map.set(route.fullPath, route);
|
|
193
|
+
else if (existing.isGroup && !route.isGroup) map.set(route.fullPath, route);
|
|
194
|
+
else if (existing.isGroup && route.isGroup) {
|
|
195
|
+
if (route.id.localeCompare(existing.id) < 0) map.set(route.fullPath, route);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return map;
|
|
199
|
+
}
|
|
200
|
+
/** A route file's path within its pages directory, e.g. `users/[id]`. */
|
|
201
|
+
function toRouteFileKey(filename) {
|
|
202
|
+
return filename.replace(/^.*?[\\/](?:routes|pages|content)[\\/]|\.page\.(?:js|ts|analog|ag)$|\.(?:ts|md|analog|ag)$/g, "");
|
|
203
|
+
}
|
|
204
|
+
function isPathlessLayoutId(id) {
|
|
205
|
+
const segments = id.split("/").filter(Boolean);
|
|
206
|
+
if (segments.length === 0) return false;
|
|
207
|
+
return /^\([^)]*\)$/.test(segments[segments.length - 1]);
|
|
208
|
+
}
|
|
209
|
+
function getRouteWeight(path) {
|
|
210
|
+
if (path.includes("[[...")) return 3;
|
|
211
|
+
if (path.includes("[...")) return 2;
|
|
212
|
+
if (path.includes("[")) return 1;
|
|
213
|
+
return 0;
|
|
214
|
+
}
|
|
215
|
+
function getCollisionPriority(filename) {
|
|
216
|
+
if (filename.includes("/src/app/pages/") || filename.includes("/src/app/routes/") || filename.includes("/app/pages/") || filename.includes("/app/routes/") || filename.includes("/src/content/")) return 0;
|
|
217
|
+
return 1;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Generates the route-table section for the combined generated route module.
|
|
221
|
+
*
|
|
222
|
+
* `resolveModuleImports` adds `routeMeta` and `load` types for pages whose
|
|
223
|
+
* URL is defined by a single file, along with the `routeMeta` of the layouts
|
|
224
|
+
* that wrap them. URLs shared by several files, such as a layout and its
|
|
225
|
+
* index page, are ambiguous and only get params and query types.
|
|
226
|
+
*/
|
|
227
|
+
function generateRouteTableDeclaration(manifest, resolveModuleImports) {
|
|
228
|
+
const lines = [];
|
|
229
|
+
lines.push("/** @noprettier */");
|
|
230
|
+
lines.push("// This file is auto-generated by @analogjs/platform");
|
|
231
|
+
lines.push("import type {} from '@analogjs/router';");
|
|
232
|
+
lines.push("declare module '@analogjs/router' {");
|
|
233
|
+
lines.push(" interface AnalogRouteTable {");
|
|
234
|
+
const importType = (specifier, name) => `typeof import(${JSON.stringify(specifier)}).${name}`;
|
|
235
|
+
for (const route of manifest.canonicalByFullPath.values()) {
|
|
236
|
+
const paramsType = generateParamsType(route.params);
|
|
237
|
+
const queryType = "Record<string, string | string[] | undefined>";
|
|
238
|
+
lines.push(` ${JSON.stringify(route.fullPath)}: {`);
|
|
239
|
+
lines.push(` params: ${paramsType};`);
|
|
240
|
+
lines.push(` query: ${queryType};`);
|
|
241
|
+
if (resolveModuleImports && route.kind === "page" && !manifest.sharedFullPaths.has(route.fullPath)) {
|
|
242
|
+
const layoutRouteMeta = route.layouts.flatMap((layout) => {
|
|
243
|
+
const specifier = resolveModuleImports(layout)?.routeMeta;
|
|
244
|
+
return specifier ? [importType(specifier, "routeMeta")] : [];
|
|
245
|
+
});
|
|
246
|
+
const imports = resolveModuleImports(route.filename);
|
|
247
|
+
if (layoutRouteMeta.length) lines.push(` layoutRouteMeta: [${layoutRouteMeta.join(", ")}];`);
|
|
248
|
+
if (imports?.routeMeta) lines.push(` routeMeta: ${importType(imports.routeMeta, "routeMeta")};`);
|
|
249
|
+
if (imports?.load) lines.push(` load: ${importType(imports.load, "load")};`);
|
|
250
|
+
}
|
|
251
|
+
lines.push(` };`);
|
|
252
|
+
}
|
|
253
|
+
lines.push(" }");
|
|
254
|
+
lines.push("}");
|
|
255
|
+
lines.push("");
|
|
256
|
+
lines.push("export {};");
|
|
257
|
+
lines.push("");
|
|
258
|
+
return lines.join("\n");
|
|
259
|
+
}
|
|
260
|
+
function generateParamsType(params) {
|
|
261
|
+
if (params.length === 0) return "Record<string, never>";
|
|
262
|
+
return `{ ${params.map((p) => {
|
|
263
|
+
const key = isValidIdentifier(p.name) ? p.name : JSON.stringify(p.name);
|
|
264
|
+
switch (p.type) {
|
|
265
|
+
case "dynamic": return `${key}: string`;
|
|
266
|
+
case "catchAll": return `${key}: string[]`;
|
|
267
|
+
case "optionalCatchAll": return `${key}?: string[]`;
|
|
268
|
+
}
|
|
269
|
+
}).join("; ")} }`;
|
|
270
|
+
}
|
|
271
|
+
function isValidIdentifier(name) {
|
|
272
|
+
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
|
|
273
|
+
}
|
|
274
|
+
function findNearestParentById(id, routesById) {
|
|
275
|
+
if (id === "/") return;
|
|
276
|
+
const segments = id.split("/").filter(Boolean);
|
|
277
|
+
for (let index = segments.length - 1; index > 0; index--) {
|
|
278
|
+
const candidate = "/" + segments.slice(0, index).join("/");
|
|
279
|
+
const route = routesById.get(candidate);
|
|
280
|
+
if (route) return route;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
function findNearestParentRoute(fullPath, routesByFullPath) {
|
|
284
|
+
if (fullPath === "/") return;
|
|
285
|
+
const segments = fullPath.slice(1).split("/");
|
|
286
|
+
for (let index = segments.length - 1; index > 0; index--) {
|
|
287
|
+
const candidate = "/" + segments.slice(0, index).join("/");
|
|
288
|
+
const route = routesByFullPath.get(candidate);
|
|
289
|
+
if (route) return route;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
function computeLocalPath(fullPath, parentFullPath) {
|
|
293
|
+
if (fullPath === "/") return "/";
|
|
294
|
+
if (!parentFullPath) return fullPath.slice(1);
|
|
295
|
+
return fullPath.slice(parentFullPath.length).replace(/^\/+/, "") || "/";
|
|
296
|
+
}
|
|
297
|
+
//#endregion
|
|
298
|
+
export { generateRouteManifest, generateRouteTableDeclaration };
|
|
299
|
+
|
|
300
|
+
//# sourceMappingURL=route-manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-manifest.js","names":[],"sources":["../../../src/lib/route-manifest.ts"],"sourcesContent":["/**\n * Route-manifest engine for typed file routes.\n *\n * Pure functions (no Angular dependencies) for converting discovered\n * filenames into typed route manifests and generated declarations.\n */\n\nexport interface RouteParamInfo {\n name: string;\n type: 'dynamic' | 'catchAll' | 'optionalCatchAll';\n}\n\nexport interface RouteEntry {\n /** Stable structural route id derived from the source filename */\n id: string;\n /** The route path segment relative to the nearest existing parent route */\n path: string;\n /** The fully resolved navigation path pattern (e.g., '/users/[id]') */\n fullPath: string;\n /** Extracted parameter information */\n params: RouteParamInfo[];\n /** Original filename that produced this route */\n filename: string;\n /** Type of source that produced this route */\n kind: 'page' | 'content';\n /** Parent route id, or null for top-level routes */\n parentId: string | null;\n /** Child route ids */\n children: string[];\n /** Whether the source filename represents an index route */\n isIndex: boolean;\n /** Whether the source filename includes route-group/pathless segments */\n isGroup: boolean;\n /** Whether the route contains a required catch-all parameter */\n isCatchAll: boolean;\n /** Whether the route contains an optional catch-all parameter */\n isOptionalCatchAll: boolean;\n /** Layout files that wrap this route, outermost first */\n layouts: string[];\n}\n\nexport interface RouteCollision {\n fullPath: string;\n keptFile: string;\n droppedFile: string;\n /** True when both files have the same collision priority (hard error). */\n samePriority: boolean;\n}\n\nexport interface RouteManifest {\n routes: RouteEntry[];\n collisions: RouteCollision[];\n /** Canonical route per fullPath — precomputed once to avoid redundant work. */\n canonicalByFullPath: Map<string, RouteEntry>;\n /** Full paths defined by more than one file, such as a layout and its index page. */\n sharedFullPaths: Set<string>;\n}\n\n/**\n * Converts a discovered filename to a route path pattern.\n *\n * Uses the same stripping rules as the existing route system\n * but preserves bracket param syntax instead of converting to\n * Angular's `:param` syntax.\n *\n * The regex applies four alternations (left to right, all replaced with ''):\n * 1. `^(.*?)[\\\\/](?:routes|pages|content)[\\\\/]` — anchored, strips everything\n * up to and including the first /routes/, /pages/, or /content/ segment.\n * Handles app-local paths (`/src/app/pages/`) AND additional dirs\n * (`/libs/shared/feature/src/content/`) uniformly.\n * 2. `[\\\\/](?:app[\\\\/](?:routes|pages)|src[\\\\/]content)[\\\\/]` — non-anchored\n * fallback for legacy paths where the directory marker appears mid-string.\n * 3. `\\.page\\.(js|ts|analog|ag)$` — strips page file extensions.\n * 4. `\\.(ts|md|analog|ag)$` — strips remaining file extensions.\n *\n * Examples:\n * - '/app/routes/index.ts' -> '/'\n * - '/app/routes/about.ts' -> '/about'\n * - '/src/app/pages/users/[id].page.ts' -> '/users/[id]'\n * - '/app/routes/blog.[slug].ts' -> '/blog/[slug]'\n * - '/src/app/pages/(auth)/login.page.ts' -> '/login'\n * - '/src/app/pages/docs/[...slug].page.ts' -> '/docs/[...slug]'\n * - '/src/app/pages/shop/[[...category]].page.ts' -> '/shop/[[...category]]'\n * - '/libs/shared/feature/src/content/test.md' -> '/test'\n */\nexport function filenameToRoutePath(filename: string): string {\n let path = filename.replace(\n /^(?:[a-zA-Z]:[\\\\/])?(.*?)[\\\\/](?:routes|pages|content)[\\\\/]|(?:[\\\\/](?:app[\\\\/](?:routes|pages)|src[\\\\/]content)[\\\\/])|(\\.page\\.(js|ts|analog|ag)$)|(\\.(ts|md|analog|ag)$)/g,\n '',\n );\n\n const brackets: string[] = [];\n path = path.replace(/\\[\\[?\\.{0,3}[^\\]]*\\]?\\]/g, (match) => {\n brackets.push(match);\n // eslint-disable-next-line no-control-regex\n return `\\0B${brackets.length - 1}\\0`;\n });\n // Match the runtime router: strip index segments and groups before dots.\n path = path\n .replace(/\\(.*?\\)/g, '')\n .replace(/(^|[./])index(?=[./]|$)/g, '$1')\n .replace(/\\./g, '/');\n // eslint-disable-next-line no-control-regex\n path = path.replace(/\\0B(\\d+)\\0/g, (_, idx) => brackets[Number(idx)]);\n return '/' + path.split('/').filter(Boolean).join('/');\n}\n\n/**\n * Converts a discovered filename to a stable structural route id.\n *\n * Unlike `filenameToRoutePath`, this preserves route groups and `index`\n * segments so that multiple files resolving to the same URL shape can still\n * have distinct structural identities in the generated route tree metadata.\n *\n * Uses the same directory-stripping regex as `filenameToRoutePath` —\n * changes to the regex must be kept in sync between both functions.\n */\nexport function filenameToRouteId(filename: string): string {\n let path = filename.replace(\n /^(?:[a-zA-Z]:[\\\\/])?(.*?)[\\\\/](?:routes|pages|content)[\\\\/]|(?:[\\\\/](?:app[\\\\/](?:routes|pages)|src[\\\\/]content)[\\\\/])|(\\.page\\.(js|ts|analog|ag)$)|(\\.(ts|md|analog|ag)$)/g,\n '',\n );\n\n const brackets: string[] = [];\n path = path.replace(/\\(.*?\\)|\\[\\[?\\.{0,3}[^\\]]*\\]?\\]/g, (match) => {\n brackets.push(match);\n // eslint-disable-next-line no-control-regex\n return `\\0B${brackets.length - 1}\\0`;\n });\n path = path.replace(/\\./g, '/');\n // eslint-disable-next-line no-control-regex\n path = path.replace(/\\0B(\\d+)\\0/g, (_, idx) => brackets[Number(idx)]);\n\n const segments = path.split('/').filter(Boolean);\n\n return '/' + segments.join('/');\n}\n\n/**\n * Extracts parameter information from a route path pattern.\n */\nexport function extractRouteParams(routePath: string): RouteParamInfo[] {\n const params: RouteParamInfo[] = [];\n\n for (const match of routePath.matchAll(/\\[\\[\\.\\.\\.([^\\]]+)\\]\\]/g)) {\n params.push({ name: match[1], type: 'optionalCatchAll' });\n }\n for (const match of routePath.matchAll(/(?<!\\[)\\[\\.\\.\\.([^\\]]+)\\](?!\\])/g)) {\n params.push({ name: match[1], type: 'catchAll' });\n }\n for (const match of routePath.matchAll(/(?<!\\[)\\[(?!\\.)([^\\]]+)\\](?!\\])/g)) {\n params.push({ name: match[1], type: 'dynamic' });\n }\n\n return params;\n}\n\n/**\n * Generates a route manifest from a list of discovered filenames.\n *\n * @param collisionPriority - Optional callback that returns a numeric priority\n * for each filename (lower wins). When provided, this replaces the default\n * hard-coded path-substring heuristic with config-derived precedence.\n */\nexport function generateRouteManifest(\n filenames: string[],\n collisionPriority?: (filename: string) => number,\n): RouteManifest {\n const routes: RouteEntry[] = [];\n const collisions: RouteCollision[] = [];\n const sharedFullPaths = new Set<string>();\n const seenByFullPath = new Map<\n string,\n { filename: string; priority: number }\n >();\n const getPriority = collisionPriority ?? getCollisionPriority;\n\n // Prefer app-local route files over shared/external sources when two files\n // resolve to the same URL. This keeps `additionalPagesDirs` additive instead\n // of unexpectedly overriding the route that lives inside the app itself.\n const prioritizedFilenames = [...filenames].sort((a, b) => {\n const aPriority = getPriority(a);\n const bPriority = getPriority(b);\n if (aPriority !== bPriority) {\n return aPriority - bPriority;\n }\n return a.localeCompare(b);\n });\n\n // Layout routes are a file and a folder with the same name, so users.page.ts\n // wraps users/[id].page.ts but not users.[id].page.ts. Folders from all\n // pages dirs share one tree.\n const layoutByKey = new Map<string, string>();\n for (const filename of prioritizedFilenames) {\n const key = toRouteFileKey(filename);\n if (!filename.endsWith('.md') && !layoutByKey.has(key)) {\n layoutByKey.set(key, filename);\n }\n }\n\n for (const filename of prioritizedFilenames) {\n const fullPath = filenameToRoutePath(filename);\n const params = extractRouteParams(fullPath);\n const id = filenameToRouteId(filename);\n const isPathlessLayout = isPathlessLayoutId(id);\n // Different pathless branches can select the same URL with canMatch guards.\n const groupScope = id.slice(0, id.lastIndexOf(')') + 1);\n const collisionKey = JSON.stringify([fullPath, groupScope]);\n\n const currentPriority = getPriority(filename);\n\n // Pathless layouts (e.g. (auth).page.ts) are structural wrappers that\n // render a <router-outlet> — they coexist with index.page.ts at the same\n // fullPath without collision. The Angular router handles them as nested\n // layout routes, not competing page components.\n if (!isPathlessLayout) {\n if (seenByFullPath.has(collisionKey)) {\n const winner = seenByFullPath.get(collisionKey)!;\n if (winner.filename === filename) {\n continue;\n }\n // A layout file (e.g., docs.page.ts) and its index child\n // (e.g., docs/index.page.ts) intentionally share the same route\n // path — the layout wraps the index as a parent-child pair.\n const isLayoutIndexPair = (a: string, b: string) => {\n const indexRe = /\\/index\\.(page\\.)?(ts|js|md|analog|ag)$/;\n const layoutRe = /\\.(page\\.)?(ts|js|analog|ag)$/;\n if (indexRe.test(a) && layoutRe.test(b)) {\n const dir = a.replace(indexRe, '');\n const layout = b.replace(layoutRe, '');\n return dir === layout;\n }\n return false;\n };\n if (\n isLayoutIndexPair(winner.filename, filename) ||\n isLayoutIndexPair(filename, winner.filename)\n ) {\n sharedFullPaths.add(fullPath);\n continue;\n }\n collisions.push({\n fullPath,\n keptFile: winner.filename,\n droppedFile: filename,\n samePriority: winner.priority === currentPriority,\n });\n console.warn(\n `[Analog] Route collision: '${fullPath}' is defined by both ` +\n `'${winner.filename}' and '${filename}'. ` +\n `Keeping '${winner.filename}' based on route source precedence and skipping duplicate.`,\n );\n continue;\n }\n seenByFullPath.set(collisionKey, { filename, priority: currentPriority });\n }\n\n const segments = toRouteFileKey(filename).split('/');\n const layouts: string[] = [];\n for (let i = 1; i < segments.length; i++) {\n const layout = layoutByKey.get(segments.slice(0, i).join('/'));\n if (layout) layouts.push(layout);\n }\n\n routes.push({\n id,\n path: fullPath,\n fullPath,\n params,\n filename,\n kind: filename.endsWith('.md') ? 'content' : 'page',\n parentId: null,\n children: [],\n isIndex: id === '/index' || id.endsWith('/index'),\n isGroup: isPathlessLayout,\n isCatchAll: params.some((param) => param.type === 'catchAll'),\n isOptionalCatchAll: params.some(\n (param) => param.type === 'optionalCatchAll',\n ),\n layouts,\n });\n }\n\n routes.sort((a, b) => {\n const aW = getRouteWeight(a.fullPath);\n const bW = getRouteWeight(b.fullPath);\n if (aW !== bW) return aW - bW;\n return a.fullPath.localeCompare(b.fullPath);\n });\n\n const routeByFullPath = canonicalRoutesByFullPath(routes);\n\n const routeById = new Map(routes.map((route) => [route.id, route]));\n\n for (const route of routes) {\n // Use structural id-based parent lookup for any route whose id\n // contains a group segment — this wires group children (e.g.\n // /(auth)/sign-up) to their pathless layout parent (/(auth)).\n // This also correctly handles nested groups like\n // /dashboard/(settings)/profile: findNearestParentById walks up\n // id segments and finds /(settings) if it exists, otherwise falls\n // through to fullPathParent which resolves to /dashboard.\n // Non-group routes always use the canonical fullPath-based lookup.\n const hasGroupSegment = route.id.includes('/(');\n const structuralParent = hasGroupSegment\n ? findNearestParentById(route.id, routeById)\n : undefined;\n const fullPathParent = findNearestParentRoute(\n route.fullPath,\n routeByFullPath,\n );\n const parent = structuralParent ?? fullPathParent;\n route.parentId = parent?.id ?? null;\n route.path = computeLocalPath(route.fullPath, parent?.fullPath ?? null);\n }\n\n for (const route of routes) {\n if (route.parentId) {\n routeById.get(route.parentId)?.children.push(route.id);\n }\n if (routeByFullPath.get(route.fullPath) !== route) {\n sharedFullPaths.add(route.fullPath);\n }\n }\n\n return {\n routes,\n collisions,\n canonicalByFullPath: routeByFullPath,\n sharedFullPaths,\n };\n}\n\nfunction canonicalRoutesByFullPath(\n routes: RouteEntry[],\n): Map<string, RouteEntry> {\n const map = new Map<string, RouteEntry>();\n for (const route of routes) {\n const existing = map.get(route.fullPath);\n if (!existing) {\n map.set(route.fullPath, route);\n } else if (existing.isGroup && !route.isGroup) {\n // Non-group routes always take precedence over group layouts.\n map.set(route.fullPath, route);\n } else if (existing.isGroup && route.isGroup) {\n // Both are group layouts — tiebreak by id to ensure stable selection\n // regardless of filesystem or glob ordering across platforms.\n if (route.id.localeCompare(existing.id) < 0) {\n map.set(route.fullPath, route);\n }\n }\n }\n return map;\n}\n\n/** A route file's path within its pages directory, e.g. `users/[id]`. */\nfunction toRouteFileKey(filename: string): string {\n return filename.replace(\n /^.*?[\\\\/](?:routes|pages|content)[\\\\/]|\\.page\\.(?:js|ts|analog|ag)$|\\.(?:ts|md|analog|ag)$/g,\n '',\n );\n}\n\nfunction isPathlessLayoutId(id: string): boolean {\n const segments = id.split('/').filter(Boolean);\n if (segments.length === 0) return false;\n return /^\\([^)]*\\)$/.test(segments[segments.length - 1]);\n}\n\nfunction getRouteWeight(path: string): number {\n if (path.includes('[[...')) return 3;\n if (path.includes('[...')) return 2;\n if (path.includes('[')) return 1;\n return 0;\n}\n\nfunction getCollisionPriority(filename: string): number {\n if (\n filename.includes('/src/app/pages/') ||\n filename.includes('/src/app/routes/') ||\n filename.includes('/app/pages/') ||\n filename.includes('/app/routes/') ||\n filename.includes('/src/content/')\n ) {\n return 0;\n }\n\n return 1;\n}\n\n/** Import specifiers for a page module's typed exports. */\nexport interface RouteModuleImports {\n routeMeta?: string;\n load?: string;\n}\n\n/**\n * Generates the route-table section for the combined generated route module.\n *\n * `resolveModuleImports` adds `routeMeta` and `load` types for pages whose\n * URL is defined by a single file, along with the `routeMeta` of the layouts\n * that wrap them. URLs shared by several files, such as a layout and its\n * index page, are ambiguous and only get params and query types.\n */\nexport function generateRouteTableDeclaration(\n manifest: RouteManifest,\n resolveModuleImports?: (filename: string) => RouteModuleImports | undefined,\n): string {\n const lines: string[] = [];\n lines.push('/** @noprettier */');\n lines.push('// This file is auto-generated by @analogjs/platform');\n lines.push(\"import type {} from '@analogjs/router';\");\n lines.push(\"declare module '@analogjs/router' {\");\n lines.push(' interface AnalogRouteTable {');\n\n const importType = (specifier: string, name: string) =>\n `typeof import(${JSON.stringify(specifier)}).${name}`;\n\n for (const route of manifest.canonicalByFullPath.values()) {\n const paramsType = generateParamsType(route.params);\n const queryType = 'Record<string, string | string[] | undefined>';\n\n lines.push(` ${JSON.stringify(route.fullPath)}: {`);\n lines.push(` params: ${paramsType};`);\n lines.push(` query: ${queryType};`);\n if (\n resolveModuleImports &&\n route.kind === 'page' &&\n !manifest.sharedFullPaths.has(route.fullPath)\n ) {\n const layoutRouteMeta = route.layouts.flatMap((layout) => {\n const specifier = resolveModuleImports(layout)?.routeMeta;\n return specifier ? [importType(specifier, 'routeMeta')] : [];\n });\n const imports = resolveModuleImports(route.filename);\n if (layoutRouteMeta.length) {\n lines.push(` layoutRouteMeta: [${layoutRouteMeta.join(', ')}];`);\n }\n if (imports?.routeMeta) {\n lines.push(\n ` routeMeta: ${importType(imports.routeMeta, 'routeMeta')};`,\n );\n }\n if (imports?.load) {\n lines.push(` load: ${importType(imports.load, 'load')};`);\n }\n }\n lines.push(` };`);\n }\n\n lines.push(' }');\n lines.push('}');\n lines.push('');\n lines.push('export {};');\n lines.push('');\n\n return lines.join('\\n');\n}\n\nfunction generateParamsType(params: RouteParamInfo[]): string {\n if (params.length === 0) return 'Record<string, never>';\n\n const entries = params.map((p) => {\n const key = isValidIdentifier(p.name) ? p.name : JSON.stringify(p.name);\n switch (p.type) {\n case 'dynamic':\n return `${key}: string`;\n case 'catchAll':\n return `${key}: string[]`;\n case 'optionalCatchAll':\n return `${key}?: string[]`;\n }\n });\n\n return `{ ${entries.join('; ')} }`;\n}\n\nfunction isValidIdentifier(name: string): boolean {\n return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);\n}\n\nfunction findNearestParentById(\n id: string,\n routesById: Map<string, RouteEntry>,\n): RouteEntry | undefined {\n if (id === '/') {\n return undefined;\n }\n\n const segments = id.split('/').filter(Boolean);\n for (let index = segments.length - 1; index > 0; index--) {\n const candidate = '/' + segments.slice(0, index).join('/');\n const route = routesById.get(candidate);\n if (route) {\n return route;\n }\n }\n\n return undefined;\n}\n\nfunction findNearestParentRoute(\n fullPath: string,\n routesByFullPath: Map<string, RouteEntry>,\n): RouteEntry | undefined {\n if (fullPath === '/') {\n return undefined;\n }\n\n const segments = fullPath.slice(1).split('/');\n for (let index = segments.length - 1; index > 0; index--) {\n const candidate = '/' + segments.slice(0, index).join('/');\n const route = routesByFullPath.get(candidate);\n if (route) {\n return route;\n }\n }\n\n return undefined;\n}\n\nfunction computeLocalPath(\n fullPath: string,\n parentFullPath: string | null,\n): string {\n if (fullPath === '/') {\n return '/';\n }\n\n if (!parentFullPath) {\n return fullPath.slice(1);\n }\n\n const suffix = fullPath.slice(parentFullPath.length).replace(/^\\/+/, '');\n return suffix || '/';\n}\n"],"mappings":"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"}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import { Plugin } from
|
|
2
|
-
import { Options } from
|
|
1
|
+
import { Plugin } from "vite";
|
|
2
|
+
import { Options } from "./options.js";
|
|
3
3
|
/**
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
4
|
+
* Router plugin that handles route file discovery and hot module replacement.
|
|
5
|
+
*
|
|
6
|
+
* This plugin provides three main functionalities:
|
|
7
|
+
* 1. Route invalidation when files are added/deleted (HMR workaround)
|
|
8
|
+
* 2. Dynamic route file discovery and import generation
|
|
9
|
+
* 3. Content route file discovery for markdown and Analog content
|
|
10
|
+
*
|
|
11
|
+
* @param options Configuration options for the router plugin
|
|
12
|
+
* @returns Array of Vite plugins for route handling
|
|
13
|
+
*
|
|
14
|
+
* IMPORTANT: This plugin uses tinyglobby for file discovery.
|
|
15
|
+
* Key behavior with { dot: true, absolute: true }:
|
|
16
|
+
* - Returns absolute paths for ALL discovered files
|
|
17
|
+
* - Path normalization is required to match expected output format
|
|
18
|
+
* - Files within project root must use relative paths in object keys
|
|
19
|
+
* - Files outside project root keep absolute paths in object keys
|
|
20
|
+
*/
|
|
21
21
|
export declare function routerPlugin(options?: Options): Plugin[];
|
package/src/lib/router-plugin.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { analyzeAnalogRouteFile, formatAnalogRouteIdiomDiagnostic } from "./route-idiom-diagnostics.js";
|
|
2
|
+
import { isAbsolute, relative, resolve } from "node:path";
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
1
4
|
import { normalizePath } from "vite";
|
|
2
5
|
import { globSync } from "tinyglobby";
|
|
3
|
-
import { resolve } from "node:path";
|
|
4
6
|
//#region packages/platform/src/lib/router-plugin.ts
|
|
5
7
|
/**
|
|
6
8
|
* Router plugin that handles route file discovery and hot module replacement.
|
|
@@ -21,10 +23,105 @@ import { resolve } from "node:path";
|
|
|
21
23
|
* - Files outside project root keep absolute paths in object keys
|
|
22
24
|
*/
|
|
23
25
|
function routerPlugin(options) {
|
|
24
|
-
const workspaceRoot = normalizePath(options?.workspaceRoot ?? process.cwd());
|
|
26
|
+
const workspaceRoot = normalizePath(options?.workspaceRoot ?? process.env["NX_WORKSPACE_ROOT"] ?? process.cwd());
|
|
25
27
|
let config;
|
|
26
28
|
let root;
|
|
27
|
-
const
|
|
29
|
+
const normalizeWatchedDir = (dir) => {
|
|
30
|
+
const normalizedDir = normalizePath(dir.startsWith(`${workspaceRoot}/`) || dir === workspaceRoot ? dir : dir.startsWith("/") ? `${workspaceRoot}${dir}` : resolve(workspaceRoot, dir));
|
|
31
|
+
return normalizedDir.endsWith("/") ? normalizedDir.slice(0, -1) : normalizedDir;
|
|
32
|
+
};
|
|
33
|
+
const additionalPagesDirs = (options?.additionalPagesDirs || []).map((dir) => normalizeWatchedDir(dir));
|
|
34
|
+
const additionalContentDirs = (options?.additionalContentDirs || []).map((dir) => normalizeWatchedDir(dir));
|
|
35
|
+
const getRouteLikeDirs = () => [
|
|
36
|
+
...root ? [
|
|
37
|
+
normalizeWatchedDir(`${root}/app/routes`),
|
|
38
|
+
normalizeWatchedDir(`${root}/src/app/routes`),
|
|
39
|
+
normalizeWatchedDir(`${root}/src/app/pages`),
|
|
40
|
+
normalizeWatchedDir(`${root}/src/content`)
|
|
41
|
+
] : [],
|
|
42
|
+
"/app/routes",
|
|
43
|
+
"/src/app/routes",
|
|
44
|
+
"/src/app/pages",
|
|
45
|
+
"/src/content",
|
|
46
|
+
...additionalPagesDirs,
|
|
47
|
+
...additionalContentDirs
|
|
48
|
+
];
|
|
49
|
+
let routeFilesCache;
|
|
50
|
+
let pageRouteFilesCache;
|
|
51
|
+
let contentRouteFilesCache;
|
|
52
|
+
let endpointFilesCache;
|
|
53
|
+
const routeDiagnosticCache = /* @__PURE__ */ new Map();
|
|
54
|
+
const isRouteLikeFile = (path) => {
|
|
55
|
+
const normalizedPath = normalizePath(path);
|
|
56
|
+
return getRouteLikeDirs().some((dir) => normalizedPath === dir || normalizedPath.startsWith(`${dir}/`));
|
|
57
|
+
};
|
|
58
|
+
const discoverRouteFiles = () => {
|
|
59
|
+
routeFilesCache ??= globSync([
|
|
60
|
+
`${root}/app/routes/**/*.ts`,
|
|
61
|
+
`${root}/src/app/routes/**/*.ts`,
|
|
62
|
+
`${root}/src/app/pages/**/*.page.ts`,
|
|
63
|
+
...additionalPagesDirs.map((dir) => `${dir}/**/*.page.ts`)
|
|
64
|
+
], {
|
|
65
|
+
dot: true,
|
|
66
|
+
absolute: true
|
|
67
|
+
});
|
|
68
|
+
return routeFilesCache;
|
|
69
|
+
};
|
|
70
|
+
const discoverContentRouteFiles = () => {
|
|
71
|
+
contentRouteFilesCache ??= globSync([
|
|
72
|
+
`${root}/src/app/routes/**/*.md`,
|
|
73
|
+
`${root}/src/app/pages/**/*.md`,
|
|
74
|
+
`${root}/src/content/**/*.md`,
|
|
75
|
+
...additionalContentDirs.map((dir) => `${dir}/**/*.md`)
|
|
76
|
+
], {
|
|
77
|
+
dot: true,
|
|
78
|
+
absolute: true
|
|
79
|
+
});
|
|
80
|
+
return contentRouteFilesCache;
|
|
81
|
+
};
|
|
82
|
+
const discoverEndpointFiles = () => {
|
|
83
|
+
endpointFilesCache ??= globSync([`${root}/src/app/pages/**/*.server.ts`, ...additionalPagesDirs.map((dir) => `${dir}/**/*.server.ts`)], {
|
|
84
|
+
dot: true,
|
|
85
|
+
absolute: true
|
|
86
|
+
});
|
|
87
|
+
return endpointFilesCache;
|
|
88
|
+
};
|
|
89
|
+
const discoverPageRouteFiles = () => {
|
|
90
|
+
pageRouteFilesCache ??= discoverRouteFiles().filter((file) => file.endsWith(".page.ts"));
|
|
91
|
+
return pageRouteFilesCache;
|
|
92
|
+
};
|
|
93
|
+
const invalidateDiscoveryCaches = () => {
|
|
94
|
+
routeFilesCache = void 0;
|
|
95
|
+
pageRouteFilesCache = void 0;
|
|
96
|
+
contentRouteFilesCache = void 0;
|
|
97
|
+
endpointFilesCache = void 0;
|
|
98
|
+
};
|
|
99
|
+
const reportRouteDiagnostics = (path) => {
|
|
100
|
+
if (!path.endsWith(".page.ts")) return;
|
|
101
|
+
try {
|
|
102
|
+
const rendered = analyzeAnalogRouteFile({
|
|
103
|
+
filename: path,
|
|
104
|
+
code: readFileSync(path, "utf-8"),
|
|
105
|
+
routeFiles: discoverPageRouteFiles()
|
|
106
|
+
}).map((diagnostic) => formatAnalogRouteIdiomDiagnostic(diagnostic, path, workspaceRoot));
|
|
107
|
+
const fingerprint = rendered.join("\n\n");
|
|
108
|
+
if (!fingerprint) {
|
|
109
|
+
routeDiagnosticCache.delete(path);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (routeDiagnosticCache.get(path) === fingerprint) return;
|
|
113
|
+
routeDiagnosticCache.set(path, fingerprint);
|
|
114
|
+
rendered.forEach((message) => console.warn(message));
|
|
115
|
+
} catch {
|
|
116
|
+
routeDiagnosticCache.delete(path);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
const getModuleKey = (module) => {
|
|
120
|
+
if (!root) return `/${normalizePath(relative(workspaceRoot, module))}`;
|
|
121
|
+
const relToRoot = normalizePath(relative(root, module));
|
|
122
|
+
if (!relToRoot.startsWith("..") && !isAbsolute(relToRoot)) return `/${relToRoot}`;
|
|
123
|
+
return `/${normalizePath(relative(workspaceRoot, module))}`;
|
|
124
|
+
};
|
|
28
125
|
const invalidateFileModules = (server, path) => {
|
|
29
126
|
const normalizedPath = normalizePath(path);
|
|
30
127
|
(server.moduleGraph.getModulesByFile?.(normalizedPath) ?? server.moduleGraph.fileToModulesMap.get(normalizedPath))?.forEach((mod) => {
|
|
@@ -44,9 +141,16 @@ function routerPlugin(options) {
|
|
|
44
141
|
*
|
|
45
142
|
* @param path The file path that was added or deleted
|
|
46
143
|
*/
|
|
47
|
-
function invalidateRoutes(path) {
|
|
144
|
+
function invalidateRoutes(path, event) {
|
|
48
145
|
if (!isRouteLikeFile(path)) return;
|
|
146
|
+
if (event !== "change") invalidateDiscoveryCaches();
|
|
147
|
+
if (event === "change") reportRouteDiagnostics(path);
|
|
148
|
+
else if (event === "unlink") {
|
|
149
|
+
routeDiagnosticCache.delete(path);
|
|
150
|
+
discoverPageRouteFiles().forEach((file) => reportRouteDiagnostics(file));
|
|
151
|
+
} else discoverPageRouteFiles().forEach((file) => reportRouteDiagnostics(file));
|
|
49
152
|
invalidateFileModules(server, path);
|
|
153
|
+
if (event === "change") return;
|
|
50
154
|
server.moduleGraph.fileToModulesMap.forEach((mods) => {
|
|
51
155
|
mods.forEach((mod) => {
|
|
52
156
|
if (mod.id?.includes("analogjs") && mod.id?.includes("fesm")) {
|
|
@@ -57,11 +161,19 @@ function routerPlugin(options) {
|
|
|
57
161
|
}
|
|
58
162
|
});
|
|
59
163
|
});
|
|
164
|
+
server.ws.send("analog:debug-full-reload", {
|
|
165
|
+
plugin: "platform:router-plugin",
|
|
166
|
+
reason: "route-graph-shape-changed",
|
|
167
|
+
event,
|
|
168
|
+
path
|
|
169
|
+
});
|
|
60
170
|
server.ws.send({ type: "full-reload" });
|
|
61
171
|
}
|
|
62
|
-
server.watcher.on("add", invalidateRoutes);
|
|
63
|
-
server.watcher.on("change", invalidateRoutes);
|
|
64
|
-
server.watcher.on("unlink", invalidateRoutes);
|
|
172
|
+
server.watcher.on("add", (path) => invalidateRoutes(path, "add"));
|
|
173
|
+
server.watcher.on("change", (path) => invalidateRoutes(path, "change"));
|
|
174
|
+
server.watcher.on("unlink", (path) => invalidateRoutes(path, "unlink"));
|
|
175
|
+
for (const dir of [...additionalPagesDirs, ...additionalContentDirs]) server.watcher.add(dir);
|
|
176
|
+
discoverPageRouteFiles().forEach((file) => reportRouteDiagnostics(file));
|
|
65
177
|
}
|
|
66
178
|
},
|
|
67
179
|
{
|
|
@@ -72,37 +184,22 @@ function routerPlugin(options) {
|
|
|
72
184
|
root = normalizePath(resolve(workspaceRoot, config.root || ".") || ".");
|
|
73
185
|
},
|
|
74
186
|
transform: {
|
|
75
|
-
filter: { code: "
|
|
187
|
+
filter: { code: "_ROUTE_FILES" },
|
|
76
188
|
handler(code) {
|
|
77
189
|
if (code.includes("ANALOG_ROUTE_FILES") || code.includes("ANALOG_CONTENT_ROUTE_FILES")) {
|
|
78
|
-
const routeFiles =
|
|
79
|
-
|
|
80
|
-
`${root}/src/app/routes/**/*.ts`,
|
|
81
|
-
`${root}/src/app/pages/**/*.page.ts`,
|
|
82
|
-
...(options?.additionalPagesDirs || []).map((glob) => `${workspaceRoot}${glob}/**/*.page.ts`)
|
|
83
|
-
], {
|
|
84
|
-
dot: true,
|
|
85
|
-
absolute: true
|
|
86
|
-
});
|
|
87
|
-
const contentRouteFiles = globSync([
|
|
88
|
-
`${root}/src/app/routes/**/*.md`,
|
|
89
|
-
`${root}/src/app/pages/**/*.md`,
|
|
90
|
-
`${root}/src/content/**/*.md`,
|
|
91
|
-
...(options?.additionalContentDirs || []).map((glob) => `${workspaceRoot}${glob}/**/*.md`)
|
|
92
|
-
], {
|
|
93
|
-
dot: true,
|
|
94
|
-
absolute: true
|
|
95
|
-
});
|
|
190
|
+
const routeFiles = discoverRouteFiles();
|
|
191
|
+
const contentRouteFiles = discoverContentRouteFiles();
|
|
96
192
|
let result = code.replace("ANALOG_ROUTE_FILES = {};", `
|
|
97
193
|
ANALOG_ROUTE_FILES = {${routeFiles.map((module) => {
|
|
98
|
-
return `"${
|
|
194
|
+
return `"${getModuleKey(module)}": () => import('${module}')`;
|
|
99
195
|
})}};
|
|
100
196
|
`);
|
|
101
197
|
result = result.replace("ANALOG_CONTENT_ROUTE_FILES = {};", `
|
|
102
198
|
ANALOG_CONTENT_ROUTE_FILES = {${contentRouteFiles.map((module) => {
|
|
103
|
-
return `"${
|
|
199
|
+
return `"${getModuleKey(module)}": () => import('${module}?analog-content-file=true').then(m => m.default)`;
|
|
104
200
|
})}};
|
|
105
201
|
`);
|
|
202
|
+
result = result.replace("ANALOG_CONTENT_FILE_COUNT = 0", `ANALOG_CONTENT_FILE_COUNT = ${contentRouteFiles.length}`);
|
|
106
203
|
return {
|
|
107
204
|
code: result,
|
|
108
205
|
map: { mappings: "" }
|
|
@@ -118,14 +215,11 @@ function routerPlugin(options) {
|
|
|
118
215
|
filter: { code: "ANALOG_PAGE_ENDPOINTS" },
|
|
119
216
|
handler(code) {
|
|
120
217
|
if (code.includes("ANALOG_PAGE_ENDPOINTS")) {
|
|
121
|
-
const endpointFiles =
|
|
122
|
-
dot: true,
|
|
123
|
-
absolute: true
|
|
124
|
-
});
|
|
218
|
+
const endpointFiles = discoverEndpointFiles();
|
|
125
219
|
return {
|
|
126
220
|
code: code.replace("ANALOG_PAGE_ENDPOINTS = {};", `
|
|
127
221
|
ANALOG_PAGE_ENDPOINTS = {${endpointFiles.map((module) => {
|
|
128
|
-
return `"${
|
|
222
|
+
return `"${getModuleKey(module)}": () => import('${module}')`;
|
|
129
223
|
})}};
|
|
130
224
|
`),
|
|
131
225
|
map: { mappings: "" }
|