@analogjs/router 3.0.0-alpha.7 → 3.0.0-alpha.70

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/content/package.json +4 -0
  2. package/fesm2022/analogjs-router-content.mjs +63 -0
  3. package/fesm2022/analogjs-router-content.mjs.map +1 -0
  4. package/fesm2022/analogjs-router-i18n.mjs +156 -0
  5. package/fesm2022/analogjs-router-i18n.mjs.map +1 -0
  6. package/fesm2022/analogjs-router-server-actions.mjs +2 -27
  7. package/fesm2022/analogjs-router-server.mjs +734 -105
  8. package/fesm2022/analogjs-router-server.mjs.map +1 -0
  9. package/fesm2022/analogjs-router-tanstack-query-server.mjs +71 -0
  10. package/fesm2022/analogjs-router-tanstack-query-server.mjs.map +1 -0
  11. package/fesm2022/analogjs-router-tanstack-query.mjs +39 -0
  12. package/fesm2022/analogjs-router-tanstack-query.mjs.map +1 -0
  13. package/fesm2022/analogjs-router-tokens.mjs +7 -2
  14. package/fesm2022/analogjs-router-tokens.mjs.map +1 -0
  15. package/fesm2022/analogjs-router.mjs +670 -170
  16. package/fesm2022/analogjs-router.mjs.map +1 -0
  17. package/fesm2022/debug.page.mjs +53 -31
  18. package/fesm2022/debug.page.mjs.map +1 -0
  19. package/fesm2022/provide-analog-query.mjs +72 -0
  20. package/fesm2022/provide-analog-query.mjs.map +1 -0
  21. package/fesm2022/route-files.mjs +361 -0
  22. package/fesm2022/route-files.mjs.map +1 -0
  23. package/fesm2022/routes.mjs +5 -278
  24. package/fesm2022/routes.mjs.map +1 -0
  25. package/fesm2022/src.mjs +335 -0
  26. package/fesm2022/src.mjs.map +1 -0
  27. package/i18n/package.json +4 -0
  28. package/package.json +52 -5
  29. package/tanstack-query/package.json +4 -0
  30. package/tanstack-query/server/package.json +4 -0
  31. package/types/content/src/index.d.ts +4 -0
  32. package/types/content/src/lib/debug/routes.d.ts +10 -0
  33. package/types/{src → content/src}/lib/markdown-helpers.d.ts +1 -1
  34. package/types/content/src/lib/routes.d.ts +8 -0
  35. package/types/content/src/lib/with-content-routes.d.ts +2 -0
  36. package/types/i18n/src/index.d.ts +1 -0
  37. package/types/i18n/src/provide-i18n.d.ts +92 -0
  38. package/types/server/actions/src/define-action.d.ts +54 -0
  39. package/types/server/actions/src/define-api-route.d.ts +57 -0
  40. package/types/server/actions/src/define-page-load.d.ts +55 -0
  41. package/types/server/actions/src/define-server-route.d.ts +68 -0
  42. package/types/server/actions/src/index.d.ts +9 -1
  43. package/types/server/actions/src/parse-request-data.d.ts +9 -0
  44. package/types/server/actions/src/validate.d.ts +8 -0
  45. package/types/server/src/defer-reconcile-runtime.d.ts +23 -0
  46. package/types/server/src/index.d.ts +9 -2
  47. package/types/server/src/provide-server-context.d.ts +15 -1
  48. package/types/server/src/render-stream.d.ts +40 -0
  49. package/types/server/src/render.d.ts +3 -3
  50. package/types/server/src/server-fn/app-injector.d.ts +30 -0
  51. package/types/server/src/server-fn/dispatch.d.ts +56 -0
  52. package/types/server/src/server-fn/event-handler.d.ts +22 -0
  53. package/types/server/src/server-fn/interceptors.d.ts +30 -0
  54. package/types/server/src/server-fn/node-context.d.ts +14 -0
  55. package/types/server/src/server-fn/registry.d.ts +7 -0
  56. package/types/server/src/server-fn/same-origin.d.ts +46 -0
  57. package/types/server/src/server-fn/server-fn.d.ts +21 -0
  58. package/types/server/src/server-fn/ssr-dispatcher.d.ts +17 -0
  59. package/types/server/src/utils/reset-component-def-tviews.d.ts +14 -0
  60. package/types/server/src/utils/stream-html.d.ts +13 -0
  61. package/types/server/src/utils/stream-request.d.ts +24 -0
  62. package/types/src/index.d.ts +20 -6
  63. package/types/src/lib/cache-key.d.ts +1 -1
  64. package/types/src/lib/cookie-interceptor.d.ts +1 -1
  65. package/types/src/lib/debug/debug.page.d.ts +4 -2
  66. package/types/src/lib/define-route.d.ts +6 -1
  67. package/types/src/lib/endpoints.d.ts +1 -1
  68. package/types/src/lib/experimental.d.ts +140 -0
  69. package/types/src/lib/form-action.directive.d.ts +12 -5
  70. package/types/src/lib/inject-load.d.ts +5 -2
  71. package/types/src/lib/inject-navigate.d.ts +23 -0
  72. package/types/src/lib/inject-route-context.d.ts +32 -0
  73. package/types/src/lib/inject-typed-params.d.ts +63 -0
  74. package/types/src/lib/json-ld.d.ts +32 -0
  75. package/types/src/lib/meta-tags.d.ts +3 -1
  76. package/types/src/lib/models.d.ts +3 -0
  77. package/types/src/lib/provide-file-router-base.d.ts +4 -0
  78. package/types/src/lib/provide-file-router.d.ts +2 -8
  79. package/types/src/lib/route-builder.d.ts +5 -0
  80. package/types/src/lib/route-files.d.ts +18 -0
  81. package/types/src/lib/route-path.d.ts +124 -0
  82. package/types/src/lib/route-types.d.ts +2 -1
  83. package/types/src/lib/routes.d.ts +2 -10
  84. package/types/src/lib/server-fn/dispatcher.d.ts +23 -0
  85. package/types/src/lib/server-fn/inject-server-fn.d.ts +44 -0
  86. package/types/src/lib/server-fn/server-fn-ref.d.ts +24 -0
  87. package/types/src/lib/server-fn/types.d.ts +55 -0
  88. package/types/src/lib/validation-errors.d.ts +7 -0
  89. package/types/tanstack-query/server/src/define-page-load-queries.d.ts +66 -0
  90. package/types/tanstack-query/server/src/index.d.ts +3 -0
  91. package/types/tanstack-query/src/constants.d.ts +9 -0
  92. package/types/tanstack-query/src/index.d.ts +2 -0
  93. package/types/tanstack-query/src/provide-analog-query.d.ts +4 -0
  94. package/types/tanstack-query/src/provide-server-analog-query.d.ts +2 -0
  95. package/types/tanstack-query/src/server-query.d.ts +16 -0
  96. package/types/tokens/src/index.d.ts +2 -0
  97. package/types/server/src/server-component-render.d.ts +0 -4
  98. package/types/server/src/tokens.d.ts +0 -7
  99. package/types/src/lib/server.component.d.ts +0 -33
@@ -0,0 +1,4 @@
1
+ {
2
+ "module": "../fesm2022/analogjs-router-content.mjs",
3
+ "typings": "../types/content/src/index.d.ts"
4
+ }
@@ -0,0 +1,63 @@
1
+ import { r as createRoutes, t as ANALOG_EXTRA_ROUTE_FILE_SOURCES } from "./route-files.mjs";
2
+ import { InjectionToken, inject } from "@angular/core";
3
+ import { ContentRenderer, MarkdownRouteComponent, parseRawContentFile } from "@analogjs/content";
4
+ //#region packages/router/content/src/lib/markdown-helpers.ts
5
+ var isNgZoneEnabled = typeof Zone !== "undefined" && !!Zone.root;
6
+ function toMarkdownModule(markdownFileFactory) {
7
+ return async () => {
8
+ const { content, attributes } = parseRawContentFile(await (isNgZoneEnabled ? Zone.root.run(markdownFileFactory) : markdownFileFactory()));
9
+ const { title, meta, jsonLd } = attributes;
10
+ return {
11
+ default: MarkdownRouteComponent,
12
+ routeMeta: {
13
+ data: { _analogContent: content },
14
+ title,
15
+ meta,
16
+ jsonLd,
17
+ resolve: { renderedAnalogContent: async () => {
18
+ const rendered = await inject(ContentRenderer).render(content);
19
+ return typeof rendered === "string" ? rendered : rendered.content;
20
+ } }
21
+ }
22
+ };
23
+ };
24
+ }
25
+ //#endregion
26
+ //#region packages/router/content/src/lib/routes.ts
27
+ /**
28
+ * This variable reference is replaced with a glob of all content routes.
29
+ */
30
+ var ANALOG_CONTENT_ROUTE_FILES = {};
31
+ function createContentRoutes(files, debug = false) {
32
+ return createRoutes(files, (filename, fileLoader) => filename.endsWith(".md") ? toMarkdownModule(fileLoader) : fileLoader, debug);
33
+ }
34
+ //#endregion
35
+ //#region packages/router/content/src/lib/with-content-routes.ts
36
+ function withContentRoutes() {
37
+ return {
38
+ ɵkind: 101,
39
+ ɵproviders: [{
40
+ provide: ANALOG_EXTRA_ROUTE_FILE_SOURCES,
41
+ multi: true,
42
+ useValue: {
43
+ files: ANALOG_CONTENT_ROUTE_FILES,
44
+ resolveModule: (filename, fileLoader) => filename.endsWith(".md") ? toMarkdownModule(fileLoader) : fileLoader
45
+ }
46
+ }]
47
+ };
48
+ }
49
+ //#endregion
50
+ //#region packages/router/content/src/lib/debug/routes.ts
51
+ var DEBUG_CONTENT_ROUTES = new InjectionToken("@analogjs/router/content debug routes", {
52
+ providedIn: "root",
53
+ factory() {
54
+ return createContentRoutes(ANALOG_CONTENT_ROUTE_FILES, true);
55
+ }
56
+ });
57
+ function injectDebugContentRoutes() {
58
+ return inject(DEBUG_CONTENT_ROUTES);
59
+ }
60
+ //#endregion
61
+ export { ANALOG_CONTENT_ROUTE_FILES, createContentRoutes, injectDebugContentRoutes, withContentRoutes };
62
+
63
+ //# sourceMappingURL=analogjs-router-content.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analogjs-router-content.mjs","names":[],"sources":["../../content/src/lib/markdown-helpers.ts","../../content/src/lib/routes.ts","../../content/src/lib/with-content-routes.ts","../../content/src/lib/debug/routes.ts"],"sourcesContent":["import { inject } from '@angular/core';\nimport {\n ContentRenderer,\n MarkdownRouteComponent,\n parseRawContentFile,\n} from '@analogjs/content';\n\nimport type { RouteExport } from '../../../src/lib/models';\n\ndeclare const Zone: any;\n\ntype RenderResult = string | { content: string };\ntype ContentRendererLike = {\n render: (content: string) => Promise<RenderResult>;\n};\n\nconst isNgZoneEnabled = typeof Zone !== 'undefined' && !!Zone.root;\n\nexport function toMarkdownModule(\n markdownFileFactory: () => Promise<string>,\n): () => Promise<RouteExport> {\n return async () => {\n const markdownFile = await (isNgZoneEnabled\n ? Zone.root.run(markdownFileFactory)\n : markdownFileFactory());\n\n const { content, attributes } = parseRawContentFile(markdownFile);\n const { title, meta, jsonLd } = attributes;\n\n return {\n default: MarkdownRouteComponent,\n routeMeta: {\n data: { _analogContent: content },\n title,\n meta,\n jsonLd,\n resolve: {\n renderedAnalogContent: async () => {\n const contentRenderer = inject<any>(\n ContentRenderer as any,\n ) as ContentRendererLike;\n const rendered = await contentRenderer.render(content);\n return typeof rendered === 'string' ? rendered : rendered.content;\n },\n },\n },\n };\n };\n}\n","import type { Route } from '@angular/router';\n\nimport type { RouteExport } from '../../../src/lib/models';\nimport { createRoutes as createBaseRoutes } from '../../../src/lib/route-builder';\nimport { toMarkdownModule } from './markdown-helpers';\n\n/**\n * This variable reference is replaced with a glob of all content routes.\n */\nexport const ANALOG_CONTENT_ROUTE_FILES = {};\n\nexport type Files = Record<string, () => Promise<RouteExport | string>>;\n\nexport function createContentRoutes(files: Files, debug = false): Route[] {\n return createBaseRoutes(\n files,\n (filename, fileLoader) =>\n filename.endsWith('.md')\n ? toMarkdownModule(fileLoader as () => Promise<string>)\n : (fileLoader as () => Promise<RouteExport>),\n debug,\n );\n}\n","import { type RouterFeatures } from '@angular/router';\n\nimport { ANALOG_CONTENT_ROUTE_FILES } from './routes';\nimport { toMarkdownModule } from './markdown-helpers';\nimport type { RouteExport } from '../../../src/lib/models';\nimport {\n ANALOG_EXTRA_ROUTE_FILE_SOURCES,\n type ExtraRouteFileSource,\n} from '../../../src/lib/route-files';\n\nexport function withContentRoutes(): RouterFeatures {\n return {\n ɵkind: 101 as number,\n ɵproviders: [\n {\n provide: ANALOG_EXTRA_ROUTE_FILE_SOURCES,\n multi: true,\n useValue: {\n files: ANALOG_CONTENT_ROUTE_FILES,\n resolveModule: (\n filename: string,\n fileLoader: () => Promise<unknown>,\n ) =>\n filename.endsWith('.md')\n ? toMarkdownModule(fileLoader as () => Promise<string>)\n : (fileLoader as () => Promise<RouteExport>),\n } satisfies ExtraRouteFileSource,\n },\n ],\n };\n}\n","import { inject, InjectionToken } from '@angular/core';\nimport { Route } from '@angular/router';\n\nimport { ANALOG_CONTENT_ROUTE_FILES, createContentRoutes } from '../routes';\n\nexport const DEBUG_CONTENT_ROUTES: InjectionToken<(Route & DebugRoute)[]> =\n new InjectionToken<(Route & DebugRoute)[]>(\n '@analogjs/router/content debug routes',\n {\n providedIn: 'root',\n factory() {\n const debugRoutes = createContentRoutes(\n ANALOG_CONTENT_ROUTE_FILES as Record<string, () => Promise<string>>,\n true,\n );\n\n return debugRoutes as (Route & DebugRoute)[];\n },\n },\n );\n\nexport type DebugRoute = {\n path: string;\n filename: string;\n isLayout: boolean;\n children?: DebugRoute[];\n};\n\nexport function injectDebugContentRoutes(): (Route & DebugRoute)[] {\n return inject(DEBUG_CONTENT_ROUTES);\n}\n"],"mappings":";;;;AAgBA,IAAM,kBAAkB,OAAO,SAAS,eAAe,CAAC,CAAC,KAAK;AAE9D,SAAgB,iBACd,qBAC4B;AAC5B,QAAO,YAAY;EAQjB,MAAO,EAAA,SAAA,eAAA,oBAPc,OAAO,kBAIpB,KAAS,KAAA,IAAA,oBAAe,GACxB,qBAAwB,EAEzB;EACL,MAAS,EAAA,OAAA,MAAA,WAAA;AACT,SAAW;GACD,SAAA;GACR,WAAA;IACA,MAAA,EAAA,gBAAA,SAAA;IACA;IAEE;IACQ;IAGA,SAAW,EACH,uBAAwB,YAAW;;AAIxD,YAAA,OAAA,aAAA,WAAA,WAAA,SAAA;;;;;;;;;;;ACrCL,IAAa,6BAA6B,EAAE;AAI5C,SAAgB,oBAAoB,OAAc,QAAQ,OAAgB;AACxE,QAAO,aACL,QACC,UAAU,eACT,SAAS,SAAS,MACd,GAAA,iBAAA,WAAA,GAAA,YAAA,MAAA;;;;ACRV,SAAgB,oBAAoC;AAClD,QAAO;EACL,OAAO;EACP,YACE,CACW;GACF,SAAA;GACG,OAAA;GACD,UAAA;IAEL,OAAA;wEAOL,iBAAA,WAAA,GAEJ;;;;;;;ACxBH,IAAa,uBACX,IAAI,eACF,yCACA;CACE,YAAY;CACZ,UAAU;AAMR,SALoB,oBAClB,4BAED,KAAA;;CAIJ,CACF;AASH,SAAgB,2BAAmD;AACjE,QAAO,OAAO,qBAAqB"}
@@ -0,0 +1,156 @@
1
+ import { InjectionToken, assertInInjectionContext, inject, makeEnvironmentProviders, provideAppInitializer } from "@angular/core";
2
+ import { LOCALE, REQUEST } from "@analogjs/router/tokens";
3
+ //#region packages/router/i18n/src/provide-i18n.ts
4
+ /**
5
+ * Injection token for the resolved i18n configuration.
6
+ * Provided by `provideI18n()` and consumed by `injectSwitchLocale()`.
7
+ * @internal
8
+ */
9
+ var I18N_CONFIG = new InjectionToken("@analogjs/router I18n Config");
10
+ /**
11
+ * Resolves the full i18n config by merging explicit values with
12
+ * build-time globals injected by the platform plugin.
13
+ */
14
+ function resolveI18nConfig(config) {
15
+ const defaultLocale = config.defaultLocale ?? (typeof ANALOG_I18N_DEFAULT_LOCALE !== "undefined" ? ANALOG_I18N_DEFAULT_LOCALE : void 0);
16
+ const locales = config.locales ?? (typeof ANALOG_I18N_LOCALES !== "undefined" ? ANALOG_I18N_LOCALES : void 0);
17
+ if (!defaultLocale || !locales) throw new Error("[@analogjs/router] provideI18n() requires defaultLocale and locales. Either pass them explicitly or configure i18n in the analog() plugin in vite.config.ts.");
18
+ return {
19
+ defaultLocale,
20
+ locales,
21
+ loader: config.loader
22
+ };
23
+ }
24
+ /**
25
+ * Provides runtime i18n support using Angular's $localize.
26
+ *
27
+ * This provider:
28
+ * 1. Detects the active locale from the URL or falls back to the default.
29
+ * 2. Makes the current locale available via the LOCALE injection token.
30
+ * 3. Loads translations for the active locale at startup using $localize.
31
+ *
32
+ * Works in both SSR and client-only modes. On the client, locale is detected
33
+ * from `window.location.pathname`. On the server, locale is detected from
34
+ * the request in `provideServerContext()` and provided at the platform level;
35
+ * this function does not shadow it.
36
+ *
37
+ * When the platform plugin is configured with `i18n` in `vite.config.ts`,
38
+ * `defaultLocale` and `locales` are injected automatically — only
39
+ * `loader` is required:
40
+ *
41
+ * ```typescript
42
+ * provideI18n({
43
+ * loader: (locale) => import(`./i18n/${locale}.json`),
44
+ * })
45
+ * ```
46
+ */
47
+ function provideI18n(config) {
48
+ const resolved = resolveI18nConfig(config);
49
+ const localeProviders = typeof window !== "undefined" ? [{
50
+ provide: LOCALE,
51
+ useValue: detectClientLocale(resolved)
52
+ }] : [];
53
+ return makeEnvironmentProviders([
54
+ {
55
+ provide: I18N_CONFIG,
56
+ useValue: resolved
57
+ },
58
+ ...localeProviders,
59
+ provideAppInitializer(async () => {
60
+ await initI18n(resolved, resolveActiveLocale(resolved));
61
+ })
62
+ ]);
63
+ }
64
+ /**
65
+ * Resolves the active locale, preferring the injected `LOCALE` token
66
+ * (which on the server reads from the platform-level provider set by
67
+ * `provideServerContext()`) and falling back to the request URL,
68
+ * `window.location.pathname`, or `defaultLocale`.
69
+ */
70
+ function resolveActiveLocale(config) {
71
+ const injected = inject(LOCALE, { optional: true });
72
+ if (injected && config.locales.includes(injected)) return injected;
73
+ const req = inject(REQUEST, { optional: true });
74
+ const first = (req?.originalUrl ?? req?.url ?? (typeof window !== "undefined" ? window.location.pathname : "/")).split("?")[0].split("/").filter(Boolean)[0];
75
+ if (first && config.locales.includes(first)) return first;
76
+ return config.defaultLocale;
77
+ }
78
+ function detectClientLocale(config) {
79
+ if (typeof window === "undefined") return config.defaultLocale;
80
+ const firstSegment = window.location.pathname.split("/").filter(Boolean)[0];
81
+ if (firstSegment && config.locales.includes(firstSegment)) return firstSegment;
82
+ return config.defaultLocale;
83
+ }
84
+ /**
85
+ * Loads translations for the given locale and registers them with $localize.
86
+ *
87
+ * Always clears any previously loaded translations first so that switching
88
+ * between locales in a single SSR process does not mix translation maps.
89
+ */
90
+ async function initI18n(config, locale) {
91
+ const activeLocale = locale ?? config.defaultLocale;
92
+ await clearTranslationsRuntime();
93
+ if (activeLocale === config.locales[0]) return;
94
+ const translations = await config.loader(activeLocale);
95
+ if (translations && Object.keys(translations).length > 0) await loadTranslationsRuntime(translations);
96
+ }
97
+ /**
98
+ * Loads translations into the global $localize translation map.
99
+ *
100
+ * Uses `@angular/localize`'s `loadTranslations` when available so that
101
+ * each translation string is parsed into the `{text, messageParts,
102
+ * placeholderNames}` shape that `$localize.translate` expects. Falls back
103
+ * to writing raw strings only as a last resort (in which case lookups
104
+ * will not succeed — the fallback exists to keep error messages useful
105
+ * for users who have not installed `@angular/localize`).
106
+ *
107
+ * Requires `@angular/localize/init` to be imported in the application
108
+ * entry point so that `globalThis.$localize` is defined.
109
+ */
110
+ async function loadTranslationsRuntime(translations) {
111
+ const $localize = globalThis.$localize;
112
+ if (!$localize) {
113
+ console.warn("[@analogjs/router] $localize is not available. Make sure to import @angular/localize/init in your application entry point.");
114
+ return;
115
+ }
116
+ try {
117
+ const { loadTranslations } = await import("@angular/localize");
118
+ loadTranslations(translations);
119
+ } catch {
120
+ console.warn("[@analogjs/router] Unable to import @angular/localize. Install it as a dependency to enable runtime translation loading.");
121
+ $localize.TRANSLATIONS ??= {};
122
+ for (const [id, message] of Object.entries(translations)) $localize.TRANSLATIONS[id] = message;
123
+ }
124
+ }
125
+ /** @internal — exported for tests; not re-exported from the package entry. */
126
+ async function clearTranslationsRuntime() {
127
+ const $localize = globalThis.$localize;
128
+ if (!$localize) return;
129
+ try {
130
+ const { clearTranslations } = await import("@angular/localize");
131
+ clearTranslations();
132
+ } catch {
133
+ $localize.translate = void 0;
134
+ $localize.TRANSLATIONS = {};
135
+ }
136
+ }
137
+ function injectSwitchLocale() {
138
+ assertInInjectionContext(injectSwitchLocale);
139
+ const config = inject(I18N_CONFIG);
140
+ return (targetLocale) => {
141
+ if (typeof window === "undefined") return;
142
+ const { pathname, search, hash } = window.location;
143
+ const newPath = replaceLocaleInPath(pathname, targetLocale, config.locales);
144
+ window.location.href = `${newPath}${search}${hash}`;
145
+ };
146
+ }
147
+ function replaceLocaleInPath(pathname, targetLocale, locales) {
148
+ const segments = pathname.split("/").filter(Boolean);
149
+ if (segments.length > 0 && locales.includes(segments[0])) segments[0] = targetLocale;
150
+ else segments.unshift(targetLocale);
151
+ return "/" + segments.join("/");
152
+ }
153
+ //#endregion
154
+ export { injectSwitchLocale, loadTranslationsRuntime, provideI18n };
155
+
156
+ //# sourceMappingURL=analogjs-router-i18n.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analogjs-router-i18n.mjs","names":[],"sources":["../../i18n/src/provide-i18n.ts"],"sourcesContent":["import {\n EnvironmentProviders,\n InjectionToken,\n Type,\n assertInInjectionContext,\n inject,\n makeEnvironmentProviders,\n provideAppInitializer,\n} from '@angular/core';\nimport { LOCALE, REQUEST, ServerRequest } from '@analogjs/router/tokens';\n\ndeclare const ANALOG_I18N_DEFAULT_LOCALE: string;\ndeclare const ANALOG_I18N_LOCALES: string[];\n\n/**\n * Configuration for runtime i18n support.\n *\n * `defaultLocale` and `locales` are optional when the platform plugin\n * is configured with `i18n` in `vite.config.ts` — the values are\n * injected as build-time globals automatically.\n */\nexport interface I18nConfig {\n /**\n * The default locale to use when no locale is detected.\n * If omitted, reads from the platform plugin's `i18n.defaultLocale`.\n */\n defaultLocale?: string;\n\n /**\n * List of supported locale identifiers.\n * If omitted, reads from the platform plugin's `i18n.locales`.\n */\n locales?: string[];\n\n /**\n * A function that returns translations for a given locale.\n * The returned record maps message IDs to translated strings.\n */\n loader: (\n locale: string,\n ) => Promise<Record<string, string>> | Record<string, string>;\n}\n\n/**\n * Fully resolved i18n config with all required fields.\n */\nexport type ResolvedI18nConfig = Required<I18nConfig>;\n\n/**\n * Injection token for the resolved i18n configuration.\n * Provided by `provideI18n()` and consumed by `injectSwitchLocale()`.\n * @internal\n */\nconst I18N_CONFIG = new InjectionToken<ResolvedI18nConfig>(\n '@analogjs/router I18n Config',\n);\n\n/**\n * Resolves the full i18n config by merging explicit values with\n * build-time globals injected by the platform plugin.\n */\nexport function resolveI18nConfig(config: I18nConfig): Required<I18nConfig> {\n const defaultLocale =\n config.defaultLocale ??\n (typeof ANALOG_I18N_DEFAULT_LOCALE !== 'undefined'\n ? ANALOG_I18N_DEFAULT_LOCALE\n : undefined);\n\n const locales =\n config.locales ??\n (typeof ANALOG_I18N_LOCALES !== 'undefined'\n ? ANALOG_I18N_LOCALES\n : undefined);\n\n if (!defaultLocale || !locales) {\n throw new Error(\n '[@analogjs/router] provideI18n() requires defaultLocale and locales. ' +\n 'Either pass them explicitly or configure i18n in the analog() plugin in vite.config.ts.',\n );\n }\n\n return { defaultLocale, locales, loader: config.loader };\n}\n\n/**\n * Provides runtime i18n support using Angular's $localize.\n *\n * This provider:\n * 1. Detects the active locale from the URL or falls back to the default.\n * 2. Makes the current locale available via the LOCALE injection token.\n * 3. Loads translations for the active locale at startup using $localize.\n *\n * Works in both SSR and client-only modes. On the client, locale is detected\n * from `window.location.pathname`. On the server, locale is detected from\n * the request in `provideServerContext()` and provided at the platform level;\n * this function does not shadow it.\n *\n * When the platform plugin is configured with `i18n` in `vite.config.ts`,\n * `defaultLocale` and `locales` are injected automatically — only\n * `loader` is required:\n *\n * ```typescript\n * provideI18n({\n * loader: (locale) => import(`./i18n/${locale}.json`),\n * })\n * ```\n */\nexport function provideI18n(config: I18nConfig): EnvironmentProviders {\n const resolved = resolveI18nConfig(config);\n\n // Only provide LOCALE at the environment level on the client. On the\n // server, the platform-level LOCALE set by `provideServerContext()` is\n // authoritative and must not be shadowed by an environment-level provider.\n const localeProviders =\n typeof window !== 'undefined'\n ? [{ provide: LOCALE, useValue: detectClientLocale(resolved) }]\n : [];\n\n return makeEnvironmentProviders([\n { provide: I18N_CONFIG, useValue: resolved },\n ...localeProviders,\n provideAppInitializer(async () => {\n const locale = resolveActiveLocale(resolved);\n await initI18n(resolved, locale);\n }),\n ]);\n}\n\n/**\n * Resolves the active locale, preferring the injected `LOCALE` token\n * (which on the server reads from the platform-level provider set by\n * `provideServerContext()`) and falling back to the request URL,\n * `window.location.pathname`, or `defaultLocale`.\n */\nfunction resolveActiveLocale(config: ResolvedI18nConfig): string {\n const injected = inject(LOCALE, { optional: true });\n if (injected && config.locales.includes(injected)) {\n return injected;\n }\n\n // Fallback: read the path directly from the request on the server or\n // from the browser URL on the client. This covers cases where a locale\n // prefix is present in the URL but no token provider set it explicitly.\n const req = inject(REQUEST, { optional: true }) as ServerRequest | null;\n const pathname =\n req?.originalUrl ??\n req?.url ??\n (typeof window !== 'undefined' ? window.location.pathname : '/');\n const first = pathname.split('?')[0].split('/').filter(Boolean)[0];\n if (first && config.locales.includes(first)) {\n return first;\n }\n\n return config.defaultLocale;\n}\n\nexport function detectClientLocale(config: ResolvedI18nConfig): string {\n if (typeof window === 'undefined') {\n return config.defaultLocale;\n }\n\n const pathname = window.location.pathname;\n const segments = pathname.split('/').filter(Boolean);\n const firstSegment = segments[0];\n\n if (firstSegment && config.locales.includes(firstSegment)) {\n return firstSegment;\n }\n\n return config.defaultLocale;\n}\n\n/**\n * Loads translations for the given locale and registers them with $localize.\n *\n * Always clears any previously loaded translations first so that switching\n * between locales in a single SSR process does not mix translation maps.\n */\nexport async function initI18n(\n config: ResolvedI18nConfig,\n locale?: string,\n): Promise<void> {\n const activeLocale = locale ?? config.defaultLocale;\n await clearTranslationsRuntime();\n\n // The source locale (first entry in `locales`) has its messages baked\n // directly into the template source, so there is nothing to load.\n if (activeLocale === config.locales[0]) {\n return;\n }\n\n const translations = await config.loader(activeLocale);\n if (translations && Object.keys(translations).length > 0) {\n await loadTranslationsRuntime(translations);\n }\n}\n\n/**\n * Loads translations into the global $localize translation map.\n *\n * Uses `@angular/localize`'s `loadTranslations` when available so that\n * each translation string is parsed into the `{text, messageParts,\n * placeholderNames}` shape that `$localize.translate` expects. Falls back\n * to writing raw strings only as a last resort (in which case lookups\n * will not succeed — the fallback exists to keep error messages useful\n * for users who have not installed `@angular/localize`).\n *\n * Requires `@angular/localize/init` to be imported in the application\n * entry point so that `globalThis.$localize` is defined.\n */\nexport async function loadTranslationsRuntime(\n translations: Record<string, string>,\n): Promise<void> {\n const $localize = (globalThis as any).$localize;\n if (!$localize) {\n console.warn(\n '[@analogjs/router] $localize is not available. ' +\n 'Make sure to import @angular/localize/init in your application entry point.',\n );\n return;\n }\n\n try {\n const localizePkg = '@angular/localize';\n const { loadTranslations } = (await import(\n /* @vite-ignore */ localizePkg\n )) as {\n loadTranslations: (t: Record<string, string>) => void;\n };\n loadTranslations(translations);\n } catch {\n console.warn(\n '[@analogjs/router] Unable to import @angular/localize. ' +\n 'Install it as a dependency to enable runtime translation loading.',\n );\n $localize.TRANSLATIONS ??= {};\n for (const [id, message] of Object.entries(translations)) {\n $localize.TRANSLATIONS[id] = message;\n }\n }\n}\n\n/** @internal — exported for tests; not re-exported from the package entry. */\nexport async function clearTranslationsRuntime(): Promise<void> {\n const $localize = (globalThis as any).$localize;\n if (!$localize) {\n return;\n }\n try {\n const localizePkg = '@angular/localize';\n const { clearTranslations } = (await import(\n /* @vite-ignore */ localizePkg\n )) as {\n clearTranslations: () => void;\n };\n clearTranslations();\n } catch {\n $localize.translate = undefined;\n $localize.TRANSLATIONS = {};\n }\n}\n\n// ---------------------------------------------------------------------------\n// Component definition registry\n// ---------------------------------------------------------------------------\n\nconst componentDefRegistry = new Set<any>();\n\n/** @internal */\nexport function ɵregisterI18nComponentDef(typeOrDef: Type<any> | any): void {\n if (!typeOrDef) return;\n const def = (typeOrDef as any).ɵcmp ?? typeOrDef;\n if (def && typeof def === 'object' && 'template' in def) {\n componentDefRegistry.add(def);\n }\n}\n\n/** @internal */\nexport function ɵresetI18nComponentDefCache(): void {\n for (const def of componentDefRegistry) {\n def.tView = null;\n }\n}\n\n/** @internal */\nexport function getI18nComponentDefRegistrySize(): number {\n return componentDefRegistry.size;\n}\n\n/** @internal */\nexport function clearI18nComponentDefRegistry(): void {\n componentDefRegistry.clear();\n}\n\nexport function injectSwitchLocale(): (targetLocale: string) => void {\n assertInInjectionContext(injectSwitchLocale);\n const config = inject(I18N_CONFIG);\n\n return (targetLocale: string) => {\n if (typeof window === 'undefined') {\n return;\n }\n\n const { pathname, search, hash } = window.location;\n const newPath = replaceLocaleInPath(pathname, targetLocale, config.locales);\n window.location.href = `${newPath}${search}${hash}`;\n };\n}\n\nexport function replaceLocaleInPath(\n pathname: string,\n targetLocale: string,\n locales: string[],\n): string {\n const segments = pathname.split('/').filter(Boolean);\n\n if (segments.length > 0 && locales.includes(segments[0])) {\n segments[0] = targetLocale;\n } else {\n segments.unshift(targetLocale);\n }\n\n return '/' + segments.join('/');\n}\n"],"mappings":";;;;;;;;AAqDA,IAAM,cAAc,IAAI,eACtB,+BACD;;;;;AAMD,SAAgB,kBAAkB,QAA0C;CAC1E,MAAM,gBACJ,OAAO,kBAKH,OAAA,+BAEI,cAIL,6BACO,KAAA;oCAML,OAAA,wBAAA,cAAE,sBAAe,KAAA;AAAS,KAAA,CAAA,iBAAe,CAAA,QAAQ,OAAA,IAAA,MAAA,+JAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;SAkCtC,YAAA,QAAA;CAAQ,MAAA,WAAU,kBAAmB,OAAA;CAInD,MAAA,kBAAS,OAAA,WAAA,cAAa,CAAA;EAAU,SAAA;EAAA,UAAA,mBAAA,SAAA;EAAA,CAAA,GAAU,EAAA;AAC5C,QAAG,yBAAA;EACH;GAAA,SAAA;GAAsB,UAAY;GAAA;EAChC,GAAM;EACN,sBAAyB,YAAO;AAElC,SAAA,SAAA,UAAA,oBAAA,SAAA,CAAA;;;;;;;;;;AAWF,SAAI,oBAAmB,QAAQ;CAC7B,MAAO,WAAA,OAAA,QAAA,EAAA,UAAA,MAAA,CAAA;mDAMH,QAAM;;CAcZ,MAAI,SAJU,KAAA,eAAA,KAAA,QAGT,OAAS,WAAA,cAAmB,OAAoC,SAAA,WAAA,MAC/C,MAAA,IAAa,CAAA,GAAA,MAAA,IAAA,CAAA,OAAA,QAAA,CAAA;AACjC,KAAA,SAAc,OAAA,QAAA,SAAA,MAAA,CAAA,QAAA;AAIhB,QAAM,OAAW;;AAGjB,SAAI,mBAAuB,QAAQ;AACjC,KAAA,OAAO,WAAA,YAAA,QAAA,OAAA;;;;;;;;;;;AA0BT,eAAoB,SAAO,QAAK,QAAc;CAC5C,MAAM,eAAA,UAAwB,OAAA;;;;;;;;;;;;;;;;;;;;CAgCT,MAAA,YAAA,WAAA;;AAIrB,UAAA,KAAiB,6HACX;AACN;;AAKA,KAAK;4CACoB;;SAMtB;AACC,UAAA,KAAa,2HACH;AACd,YAAA,iBAAA,EAAA;2DAEE,WAAA,aAAA,MAAA;;;;;CAOF,MAAA,YAAmB,WAAA;MACb,UACN;;EASE,MAAA,EAAA,sBAAqC,MAAA,OAAA;AAGpC,qBAAS;SAER;AACF,YAAO,YAAe,KAAA;AACxB,YAAA,eAA6B,EAAA;;;SAyCzB,qBAA8B;AAEpC,0BAA2B,mBAAiB;CAC1C,MAAA,SAAc,OAAA,YAAA;SACT,iBAAA;AACL,MAAS,OAAQ,WAAA,YAAA"}
@@ -1,27 +1,2 @@
1
- //#region packages/router/server/actions/src/actions.ts
2
- function fail(status, errors) {
3
- return new Response(JSON.stringify(errors), {
4
- status,
5
- headers: { "X-Analog-Errors": "true" }
6
- });
7
- }
8
- function json(data, config) {
9
- return new Response(JSON.stringify(data), {
10
- headers: { "Content-Type": "application/json; charset=utf-8" },
11
- ...config
12
- });
13
- }
14
- function redirect(url, config = 302) {
15
- if (typeof config === "number") return new Response(null, {
16
- status: config,
17
- headers: { Location: `${url}` }
18
- });
19
- return new Response(null, {
20
- headers: { Location: `${url}` },
21
- ...config
22
- });
23
- }
24
- //#endregion
25
- export { fail, json, redirect };
26
-
27
- //# sourceMappingURL=analogjs-router-server-actions.mjs.map
1
+ import { a as fail, i as validateWithSchema, n as defineServerRoute, o as json, r as defineAction, s as redirect, t as definePageLoad } from "./src.mjs";
2
+ export { defineAction, definePageLoad, defineServerRoute, fail, json, redirect, validateWithSchema };