@analogjs/router 3.0.0-alpha.5 → 3.0.0-alpha.50

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 (75) 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 +309 -1
  7. package/fesm2022/analogjs-router-server-actions.mjs.map +1 -0
  8. package/fesm2022/analogjs-router-server.mjs +60 -3
  9. package/fesm2022/analogjs-router-server.mjs.map +1 -0
  10. package/fesm2022/analogjs-router-tanstack-query-server.mjs +22 -0
  11. package/fesm2022/analogjs-router-tanstack-query-server.mjs.map +1 -0
  12. package/fesm2022/analogjs-router-tanstack-query.mjs +39 -0
  13. package/fesm2022/analogjs-router-tanstack-query.mjs.map +1 -0
  14. package/fesm2022/analogjs-router-tokens.mjs +7 -2
  15. package/fesm2022/analogjs-router-tokens.mjs.map +1 -0
  16. package/fesm2022/analogjs-router.mjs +559 -61
  17. package/fesm2022/analogjs-router.mjs.map +1 -0
  18. package/fesm2022/debug.page.mjs +53 -31
  19. package/fesm2022/debug.page.mjs.map +1 -0
  20. package/fesm2022/provide-analog-query.mjs +23 -0
  21. package/fesm2022/provide-analog-query.mjs.map +1 -0
  22. package/fesm2022/route-files.mjs +361 -0
  23. package/fesm2022/route-files.mjs.map +1 -0
  24. package/fesm2022/routes.mjs +5 -278
  25. package/fesm2022/routes.mjs.map +1 -0
  26. package/i18n/package.json +4 -0
  27. package/package.json +76 -25
  28. package/tanstack-query/package.json +4 -0
  29. package/tanstack-query/server/package.json +4 -0
  30. package/types/content/src/index.d.ts +4 -0
  31. package/types/content/src/lib/debug/routes.d.ts +10 -0
  32. package/types/{src → content/src}/lib/markdown-helpers.d.ts +1 -1
  33. package/types/content/src/lib/routes.d.ts +8 -0
  34. package/types/content/src/lib/with-content-routes.d.ts +2 -0
  35. package/types/i18n/src/index.d.ts +1 -0
  36. package/types/i18n/src/provide-i18n.d.ts +92 -0
  37. package/types/server/actions/src/define-action.d.ts +54 -0
  38. package/types/server/actions/src/define-api-route.d.ts +57 -0
  39. package/types/server/actions/src/define-page-load.d.ts +55 -0
  40. package/types/server/actions/src/define-server-route.d.ts +68 -0
  41. package/types/server/actions/src/index.d.ts +9 -1
  42. package/types/server/actions/src/parse-request-data.d.ts +9 -0
  43. package/types/server/actions/src/validate.d.ts +8 -0
  44. package/types/server/src/provide-server-context.d.ts +15 -1
  45. package/types/server/src/render.d.ts +1 -1
  46. package/types/server/src/server-component-render.d.ts +1 -1
  47. package/types/src/index.d.ts +16 -5
  48. package/types/src/lib/cache-key.d.ts +1 -1
  49. package/types/src/lib/cookie-interceptor.d.ts +1 -1
  50. package/types/src/lib/debug/debug.page.d.ts +4 -2
  51. package/types/src/lib/define-route.d.ts +6 -1
  52. package/types/src/lib/endpoints.d.ts +1 -1
  53. package/types/src/lib/experimental.d.ts +140 -0
  54. package/types/src/lib/form-action.directive.d.ts +12 -5
  55. package/types/src/lib/inject-load.d.ts +5 -2
  56. package/types/src/lib/inject-navigate.d.ts +23 -0
  57. package/types/src/lib/inject-route-context.d.ts +32 -0
  58. package/types/src/lib/inject-typed-params.d.ts +63 -0
  59. package/types/src/lib/json-ld.d.ts +32 -0
  60. package/types/src/lib/meta-tags.d.ts +3 -1
  61. package/types/src/lib/models.d.ts +3 -0
  62. package/types/src/lib/provide-file-router-base.d.ts +4 -0
  63. package/types/src/lib/provide-file-router.d.ts +2 -8
  64. package/types/src/lib/route-builder.d.ts +5 -0
  65. package/types/src/lib/route-files.d.ts +18 -0
  66. package/types/src/lib/route-path.d.ts +124 -0
  67. package/types/src/lib/route-types.d.ts +2 -1
  68. package/types/src/lib/routes.d.ts +2 -10
  69. package/types/src/lib/validation-errors.d.ts +7 -0
  70. package/types/tanstack-query/server/src/index.d.ts +1 -0
  71. package/types/tanstack-query/src/index.d.ts +2 -0
  72. package/types/tanstack-query/src/provide-analog-query.d.ts +4 -0
  73. package/types/tanstack-query/src/provide-server-analog-query.d.ts +2 -0
  74. package/types/tanstack-query/src/server-query.d.ts +16 -0
  75. package/types/tokens/src/index.d.ts +2 -0
@@ -1,301 +1,28 @@
1
- import { NavigationEnd, Router, UrlSegment } from "@angular/router";
1
+ import { n as ANALOG_ROUTE_FILES, r as createRoutes$1 } from "./route-files.mjs";
2
2
  import { InjectionToken, inject } from "@angular/core";
3
- import { HttpClient } from "@angular/common/http";
4
- import { firstValueFrom } from "rxjs";
5
- import { injectAPIPrefix, injectBaseURL, injectInternalServerFetch } from "@analogjs/router/tokens";
6
- import { Meta } from "@angular/platform-browser";
7
- import { filter } from "rxjs/operators";
8
- //#region packages/router/src/lib/meta-tags.ts
9
- var ROUTE_META_TAGS_KEY = Symbol("@analogjs/router Route Meta Tags Key");
10
- var CHARSET_KEY = "charset";
11
- var HTTP_EQUIV_SELECTOR_KEY = "http-equiv";
12
- var NAME_KEY = "name";
13
- var PROPERTY_KEY = "property";
14
- var ITEMPROP_KEY = "itemprop";
15
- function updateMetaTagsOnRouteChange() {
16
- const router = inject(Router);
17
- const metaService = inject(Meta);
18
- router.events.pipe(filter((event) => event instanceof NavigationEnd)).subscribe(() => {
19
- const metaTagMap = getMetaTagMap(router.routerState.snapshot.root);
20
- for (const metaTagSelector in metaTagMap) {
21
- const metaTag = metaTagMap[metaTagSelector];
22
- metaService.updateTag(metaTag, metaTagSelector);
23
- }
24
- });
25
- }
26
- function getMetaTagMap(route) {
27
- const metaTagMap = {};
28
- let currentRoute = route;
29
- while (currentRoute) {
30
- const metaTags = currentRoute.data[ROUTE_META_TAGS_KEY] ?? [];
31
- for (const metaTag of metaTags) metaTagMap[getMetaTagSelector(metaTag)] = metaTag;
32
- currentRoute = currentRoute.firstChild;
33
- }
34
- return metaTagMap;
35
- }
36
- function getMetaTagSelector(metaTag) {
37
- if (metaTag.name) return `${NAME_KEY}="${metaTag.name}"`;
38
- if (metaTag.property) return `${PROPERTY_KEY}="${metaTag.property}"`;
39
- if (metaTag.httpEquiv) return `${HTTP_EQUIV_SELECTOR_KEY}="${metaTag.httpEquiv}"`;
40
- if (metaTag.itemprop) return `${ITEMPROP_KEY}="${metaTag.itemprop}"`;
41
- return CHARSET_KEY;
42
- }
43
- //#endregion
44
- //#region packages/router/src/lib/endpoints.ts
45
- var ANALOG_META_KEY = Symbol("@analogjs/router Analog Route Metadata Key");
46
- /**
47
- * This variable reference is replaced with a glob of all route endpoints.
48
- */
49
- var ANALOG_PAGE_ENDPOINTS = {};
50
- //#endregion
51
- //#region packages/router/src/lib/inject-route-endpoint-url.ts
52
- function injectRouteEndpointURL(route) {
53
- const routeConfig = route.routeConfig;
54
- const apiPrefix = injectAPIPrefix();
55
- const baseUrl = injectBaseURL();
56
- const { queryParams, fragment: hash, params, parent } = route;
57
- const segment = parent?.url.map((segment) => segment.path).join("/") || "";
58
- const url = new URL("", {
59
- "BASE_URL": "/",
60
- "DEV": false,
61
- "MODE": "production",
62
- "PROD": true,
63
- "SSR": false
64
- }["VITE_ANALOG_PUBLIC_BASE_URL"] || baseUrl || (typeof window !== "undefined" && window.location.origin ? window.location.origin : ""));
65
- url.pathname = `${url.pathname.endsWith("/") ? url.pathname : url.pathname + "/"}${apiPrefix}/_analog${routeConfig[ANALOG_META_KEY].endpoint}`;
66
- url.search = `${new URLSearchParams(queryParams).toString()}`;
67
- url.hash = hash ?? "";
68
- Object.keys(params).forEach((param) => {
69
- url.pathname = url.pathname.replace(`[${param}]`, params[param]);
70
- });
71
- url.pathname = url.pathname.replace("**", segment);
72
- return url;
73
- }
74
- //#endregion
75
- //#region packages/router/src/lib/route-config.ts
76
- function toRouteConfig(routeMeta) {
77
- if (routeMeta && isRedirectRouteMeta(routeMeta)) return routeMeta;
78
- const { meta, ...routeConfig } = routeMeta ?? {};
79
- if (Array.isArray(meta)) routeConfig.data = {
80
- ...routeConfig.data,
81
- [ROUTE_META_TAGS_KEY]: meta
82
- };
83
- else if (typeof meta === "function") routeConfig.resolve = {
84
- ...routeConfig.resolve,
85
- [ROUTE_META_TAGS_KEY]: meta
86
- };
87
- routeConfig.runGuardsAndResolvers = routeConfig.runGuardsAndResolvers ?? "paramsOrQueryParamsChange";
88
- routeConfig.resolve = {
89
- ...routeConfig.resolve,
90
- load: async (route) => {
91
- if (ANALOG_PAGE_ENDPOINTS[route.routeConfig[ANALOG_META_KEY].endpointKey]) {
92
- const http = inject(HttpClient);
93
- const url = injectRouteEndpointURL(route);
94
- const internalFetch = injectInternalServerFetch();
95
- if (internalFetch) return internalFetch(url.pathname);
96
- if (!!{
97
- "BASE_URL": "/",
98
- "DEV": false,
99
- "MODE": "production",
100
- "PROD": true,
101
- "SSR": false
102
- }["VITE_ANALOG_PUBLIC_BASE_URL"] && globalThis.$fetch) return globalThis.$fetch(url.pathname);
103
- return firstValueFrom(http.get(`${url.href}`));
104
- }
105
- return {};
106
- }
107
- };
108
- return routeConfig;
109
- }
110
- function isRedirectRouteMeta(routeMeta) {
111
- return !!routeMeta.redirectTo;
112
- }
113
- //#endregion
114
- //#region packages/router/src/lib/markdown-helpers.ts
115
- var isNgZoneEnabled = typeof Zone !== "undefined" && !!Zone.root;
116
- function toMarkdownModule(markdownFileFactory) {
117
- return async () => {
118
- const createLoader = () => Promise.all([import("@analogjs/content"), markdownFileFactory()]);
119
- const [{ parseRawContentFile, MarkdownRouteComponent, ContentRenderer }, markdownFile] = await (isNgZoneEnabled ? Zone.root.run(createLoader) : createLoader());
120
- const { content, attributes } = parseRawContentFile(markdownFile);
121
- const { title, meta } = attributes;
122
- return {
123
- default: MarkdownRouteComponent,
124
- routeMeta: {
125
- data: { _analogContent: content },
126
- title,
127
- meta,
128
- resolve: { renderedAnalogContent: async () => {
129
- const rendered = await inject(ContentRenderer).render(content);
130
- return typeof rendered === "string" ? rendered : rendered.content;
131
- } }
132
- }
133
- };
134
- };
135
- }
136
- //#endregion
137
- //#region packages/router/src/lib/constants.ts
138
- var ENDPOINT_EXTENSION = ".server.ts";
139
- //#endregion
140
3
  //#region packages/router/src/lib/routes.ts
141
4
  /**
142
- * This variable reference is replaced with a glob of all page routes.
143
- */
144
- var ANALOG_ROUTE_FILES = {};
145
- /**
146
- * This variable reference is replaced with a glob of all content routes.
147
- */
148
- var ANALOG_CONTENT_ROUTE_FILES = {};
149
- /**
150
5
  * A function used to parse list of files and create configuration of routes.
151
6
  *
152
7
  * @param files
153
8
  * @returns Array of routes
154
9
  */
155
10
  function createRoutes(files, debug = false) {
156
- const filenames = Object.keys(files);
157
- if (filenames.length === 0) return [];
158
- const rawRoutesByLevelMap = filenames.reduce((acc, filename) => {
159
- const rawPath = toRawPath(filename);
160
- const rawSegments = rawPath.split("/");
161
- const level = rawSegments.length - 1;
162
- const rawSegment = rawSegments[level];
163
- const ancestorRawSegments = rawSegments.slice(0, level);
164
- return {
165
- ...acc,
166
- [level]: {
167
- ...acc[level],
168
- [rawPath]: {
169
- filename,
170
- rawSegment,
171
- ancestorRawSegments,
172
- segment: toSegment(rawSegment),
173
- level,
174
- children: []
175
- }
176
- }
177
- };
178
- }, {});
179
- const allLevels = Object.keys(rawRoutesByLevelMap).map(Number);
180
- const maxLevel = Math.max(...allLevels);
181
- for (let level = maxLevel; level > 0; level--) {
182
- const rawRoutesMap = rawRoutesByLevelMap[level];
183
- const rawPaths = Object.keys(rawRoutesMap);
184
- for (const rawPath of rawPaths) {
185
- const rawRoute = rawRoutesMap[rawPath];
186
- const parentRawPath = rawRoute.ancestorRawSegments.join("/");
187
- const parentRawSegmentIndex = rawRoute.ancestorRawSegments.length - 1;
188
- const parentRawSegment = rawRoute.ancestorRawSegments[parentRawSegmentIndex];
189
- rawRoutesByLevelMap[level - 1] ||= {};
190
- rawRoutesByLevelMap[level - 1][parentRawPath] ||= {
191
- filename: null,
192
- rawSegment: parentRawSegment,
193
- ancestorRawSegments: rawRoute.ancestorRawSegments.slice(0, parentRawSegmentIndex),
194
- segment: toSegment(parentRawSegment),
195
- level: level - 1,
196
- children: []
197
- };
198
- rawRoutesByLevelMap[level - 1][parentRawPath].children.push(rawRoute);
199
- }
200
- }
201
- const rootRawRoutesMap = rawRoutesByLevelMap[0];
202
- const rawRoutes = Object.keys(rootRawRoutesMap).map((segment) => rootRawRoutesMap[segment]);
203
- sortRawRoutes(rawRoutes);
204
- return toRoutes(rawRoutes, files, debug);
205
- }
206
- function toRawPath(filename) {
207
- return filename.replace(/^(?:[a-zA-Z]:[\\/])?(.*?)[\\/](?:routes|pages)[\\/]|(?:[\\/](?:app[\\/](?:routes|pages)|src[\\/]content)[\\/])|(\.page\.(js|ts|analog|ag)$)|(\.(ts|md|analog|ag)$)/g, "").replace(/\[\[\.\.\.([^\]]+)\]\]/g, "(opt-$1)").replace(/\[\.{3}.+\]/, "**").replace(/\[([^\]]+)\]/g, ":$1");
11
+ return createRoutes$1(files, (_filename, fileLoader) => fileLoader, debug);
208
12
  }
209
- function toSegment(rawSegment) {
210
- return rawSegment.replace(/index|\(.*?\)/g, "").replace(/\.|\/+/g, "/").replace(/^\/+|\/+$/g, "");
211
- }
212
- function createOptionalCatchAllMatcher(paramName) {
213
- return (segments) => {
214
- if (segments.length === 0) return null;
215
- const joined = segments.map((s) => s.path).join("/");
216
- return {
217
- consumed: segments,
218
- posParams: { [paramName]: new UrlSegment(joined, {}) }
219
- };
220
- };
221
- }
222
- function toRoutes(rawRoutes, files, debug = false) {
223
- const routes = [];
224
- for (const rawRoute of rawRoutes) {
225
- const children = rawRoute.children.length > 0 ? toRoutes(rawRoute.children, files, debug) : void 0;
226
- let module = void 0;
227
- let analogMeta = void 0;
228
- if (rawRoute.filename) {
229
- const isMarkdownFile = rawRoute.filename.endsWith(".md");
230
- if (!debug) module = isMarkdownFile ? toMarkdownModule(files[rawRoute.filename]) : files[rawRoute.filename];
231
- const endpointKey = rawRoute.filename.replace(/\.page\.(ts|analog|ag)$/, ENDPOINT_EXTENSION);
232
- analogMeta = {
233
- endpoint: (rawRoute.filename.replace(/\.page\.(ts|analog|ag)$/, "").replace(/\[\[\.\.\..+\]\]/, "**").replace(/\[\.{3}.+\]/, "**").replace(/^(.*?)\/pages/, "/pages") || "").replace(/\./g, "/").replace(/\/\((.*?)\)$/, "/-$1-"),
234
- endpointKey
235
- };
236
- }
237
- const optCatchAllMatch = rawRoute.filename?.match(/\[\[\.\.\.([^\]]+)\]\]/);
238
- const optCatchAllParam = optCatchAllMatch ? optCatchAllMatch[1] : null;
239
- const route = module ? {
240
- path: rawRoute.segment,
241
- loadChildren: () => module().then((m) => {
242
- return [{
243
- path: "",
244
- component: m.default,
245
- ...toRouteConfig(m.routeMeta),
246
- children,
247
- [ANALOG_META_KEY]: analogMeta
248
- }, ...optCatchAllParam ? [{
249
- matcher: createOptionalCatchAllMatcher(optCatchAllParam),
250
- component: m.default,
251
- ...toRouteConfig(m.routeMeta),
252
- [ANALOG_META_KEY]: analogMeta
253
- }] : []];
254
- })
255
- } : {
256
- path: rawRoute.segment,
257
- ...debug ? {
258
- filename: rawRoute.filename ? rawRoute.filename : void 0,
259
- isLayout: children && children.length > 0 ? true : false
260
- } : {},
261
- children
262
- };
263
- routes.push(route);
264
- }
265
- return routes;
266
- }
267
- function sortRawRoutes(rawRoutes) {
268
- rawRoutes.sort((a, b) => {
269
- let segmentA = deprioritizeSegment(a.segment);
270
- let segmentB = deprioritizeSegment(b.segment);
271
- if (a.children.length > b.children.length) segmentA = `~${segmentA}`;
272
- else if (a.children.length < b.children.length) segmentB = `~${segmentB}`;
273
- return segmentA > segmentB ? 1 : -1;
274
- });
275
- for (const rawRoute of rawRoutes) sortRawRoutes(rawRoute.children);
276
- }
277
- function deprioritizeSegment(segment) {
278
- return segment.replace(":", "~~").replace("**", "~~~~");
279
- }
280
- var routes = createRoutes({
281
- ...ANALOG_ROUTE_FILES,
282
- ...ANALOG_CONTENT_ROUTE_FILES
283
- });
13
+ var routes = createRoutes(ANALOG_ROUTE_FILES);
284
14
  //#endregion
285
15
  //#region packages/router/src/lib/debug/routes.ts
286
16
  var DEBUG_ROUTES = new InjectionToken("@analogjs/router debug routes", {
287
17
  providedIn: "root",
288
18
  factory() {
289
- return createRoutes({
290
- ...ANALOG_ROUTE_FILES,
291
- ...ANALOG_CONTENT_ROUTE_FILES
292
- }, true);
19
+ return createRoutes(ANALOG_ROUTE_FILES, true);
293
20
  }
294
21
  });
295
22
  function injectDebugRoutes() {
296
23
  return inject(DEBUG_ROUTES);
297
24
  }
298
25
  //#endregion
299
- export { updateMetaTagsOnRouteChange as a, injectRouteEndpointURL as i, createRoutes as n, routes as r, injectDebugRoutes as t };
26
+ export { createRoutes as n, routes as r, injectDebugRoutes as t };
300
27
 
301
28
  //# sourceMappingURL=routes.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.mjs","names":[],"sources":["../../src/lib/routes.ts","../../src/lib/debug/routes.ts"],"sourcesContent":["import type { Route } from '@angular/router';\n\nimport type { RouteExport } from './models';\nimport { createRoutes as createBaseRoutes } from './route-builder';\nimport { ANALOG_ROUTE_FILES, type Files } from './route-files';\n\n/**\n * A function used to parse list of files and create configuration of routes.\n *\n * @param files\n * @returns Array of routes\n */\nexport function createRoutes(files: Files, debug = false): Route[] {\n return createBaseRoutes(\n files,\n (_filename, fileLoader) => fileLoader as () => Promise<RouteExport>,\n debug,\n );\n}\n\nexport { ANALOG_ROUTE_FILES } from './route-files';\n\nexport const routes: Route[] = createRoutes(ANALOG_ROUTE_FILES);\n","import { inject, InjectionToken } from '@angular/core';\nimport { Route } from '@angular/router';\n\nimport { ANALOG_ROUTE_FILES, createRoutes } from '../routes';\n\nexport const DEBUG_ROUTES: InjectionToken<(Route & DebugRoute)[]> =\n new InjectionToken<(Route & DebugRoute)[]>('@analogjs/router debug routes', {\n providedIn: 'root',\n factory() {\n const debugRoutes = createRoutes(ANALOG_ROUTE_FILES, true);\n\n return debugRoutes as (Route & DebugRoute)[];\n },\n });\n\nexport type DebugRoute = {\n path: string;\n filename: string;\n isLayout: boolean;\n children?: DebugRoute[];\n};\n\nexport function injectDebugRoutes(): (Route & DebugRoute)[] {\n return inject(DEBUG_ROUTES);\n}\n"],"mappings":";;;;;;;;;AAYA,SAAgB,aAAa,OAAc,QAAQ,OAAgB;AACjE,QAAO,eACL,QACC,WAAW,eAAe,YAC3B,MACD;;AAKH,IAAa,SAAkB,aAAa,mBAAmB;;;ACjB/D,IAAa,eACX,IAAI,eAAuC,iCAAiC;CAC1E,YAAY;CACZ,UAAU;AAGR,SAFoB,aAAa,oBAAyB,KAAA;;CAI7D,CAAC;AASJ,SAAgB,oBAA4C;AAC1D,QAAO,OAAO,aAAa"}
@@ -0,0 +1,4 @@
1
+ {
2
+ "module": "../fesm2022/analogjs-router-i18n.mjs",
3
+ "typings": "../types/i18n/src/index.d.ts"
4
+ }
package/package.json CHANGED
@@ -1,9 +1,54 @@
1
1
  {
2
2
  "name": "@analogjs/router",
3
- "version": "3.0.0-alpha.5",
3
+ "version": "3.0.0-alpha.50",
4
4
  "description": "Filesystem-based routing for Angular",
5
5
  "type": "module",
6
6
  "author": "Brandon Roberts <robertsbt@gmail.com>",
7
+ "exports": {
8
+ "./package.json": {
9
+ "default": "./package.json"
10
+ },
11
+ ".": {
12
+ "types": "./types/src/index.d.ts",
13
+ "import": "./fesm2022/analogjs-router.mjs",
14
+ "default": "./fesm2022/analogjs-router.mjs"
15
+ },
16
+ "./content": {
17
+ "types": "./types/content/src/index.d.ts",
18
+ "import": "./fesm2022/analogjs-router-content.mjs",
19
+ "default": "./fesm2022/analogjs-router-content.mjs"
20
+ },
21
+ "./i18n": {
22
+ "types": "./types/i18n/src/index.d.ts",
23
+ "import": "./fesm2022/analogjs-router-i18n.mjs",
24
+ "default": "./fesm2022/analogjs-router-i18n.mjs"
25
+ },
26
+ "./server": {
27
+ "types": "./types/server/src/index.d.ts",
28
+ "import": "./fesm2022/analogjs-router-server.mjs",
29
+ "default": "./fesm2022/analogjs-router-server.mjs"
30
+ },
31
+ "./server/actions": {
32
+ "types": "./types/server/actions/src/index.d.ts",
33
+ "import": "./fesm2022/analogjs-router-server-actions.mjs",
34
+ "default": "./fesm2022/analogjs-router-server-actions.mjs"
35
+ },
36
+ "./tanstack-query": {
37
+ "types": "./types/tanstack-query/src/index.d.ts",
38
+ "import": "./fesm2022/analogjs-router-tanstack-query.mjs",
39
+ "default": "./fesm2022/analogjs-router-tanstack-query.mjs"
40
+ },
41
+ "./tanstack-query/server": {
42
+ "types": "./types/tanstack-query/server/src/index.d.ts",
43
+ "import": "./fesm2022/analogjs-router-tanstack-query-server.mjs",
44
+ "default": "./fesm2022/analogjs-router-tanstack-query-server.mjs"
45
+ },
46
+ "./tokens": {
47
+ "types": "./types/tokens/src/index.d.ts",
48
+ "import": "./fesm2022/analogjs-router-tokens.mjs",
49
+ "default": "./fesm2022/analogjs-router-tokens.mjs"
50
+ }
51
+ },
7
52
  "keywords": [
8
53
  "angular",
9
54
  "router",
@@ -24,12 +69,39 @@
24
69
  "url": "https://github.com/sponsors/brandonroberts"
25
70
  },
26
71
  "peerDependencies": {
27
- "@analogjs/content": "^3.0.0-alpha.5",
72
+ "@analogjs/content": "3.0.0-alpha.50",
73
+ "@standard-schema/spec": "^1.1.0",
28
74
  "@angular/core": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0",
29
- "@angular/router": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0"
75
+ "@angular/platform-server": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0",
76
+ "@angular/router": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0",
77
+ "@tanstack/angular-query-experimental": ">=5.95.0",
78
+ "schema-dts": "^2.0.0"
79
+ },
80
+ "peerDependenciesMeta": {
81
+ "@analogjs/content": {
82
+ "optional": true
83
+ },
84
+ "@standard-schema/spec": {
85
+ "optional": true
86
+ },
87
+ "@angular/platform-server": {
88
+ "optional": true
89
+ },
90
+ "@tanstack/angular-query-experimental": {
91
+ "optional": true
92
+ },
93
+ "schema-dts": {
94
+ "optional": true
95
+ }
30
96
  },
31
97
  "dependencies": {
32
- "tslib": "^2.0.0"
98
+ "@standard-schema/spec": "^1.1.0",
99
+ "es-toolkit": "^1.45.1",
100
+ "tslib": "^2.3.0"
101
+ },
102
+ "devDependencies": {
103
+ "@analogjs/vite-plugin-angular": "3.0.0-alpha.50",
104
+ "@analogjs/vitest-angular": "3.0.0-alpha.50"
33
105
  },
34
106
  "ng-update": {
35
107
  "packageGroup": [
@@ -49,26 +121,5 @@
49
121
  },
50
122
  "module": "fesm2022/analogjs-router.mjs",
51
123
  "typings": "types/src/index.d.ts",
52
- "exports": {
53
- "./package.json": {
54
- "default": "./package.json"
55
- },
56
- ".": {
57
- "types": "./types/src/index.d.ts",
58
- "default": "./fesm2022/analogjs-router.mjs"
59
- },
60
- "./server": {
61
- "types": "./types/server/src/index.d.ts",
62
- "default": "./fesm2022/analogjs-router-server.mjs"
63
- },
64
- "./server/actions": {
65
- "types": "./types/server/actions/src/index.d.ts",
66
- "default": "./fesm2022/analogjs-router-server-actions.mjs"
67
- },
68
- "./tokens": {
69
- "types": "./types/tokens/src/index.d.ts",
70
- "default": "./fesm2022/analogjs-router-tokens.mjs"
71
- }
72
- },
73
124
  "sideEffects": false
74
125
  }
@@ -0,0 +1,4 @@
1
+ {
2
+ "module": "../fesm2022/analogjs-router-tanstack-query.mjs",
3
+ "typings": "../types/tanstack-query/src/index.d.ts"
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "module": "../../fesm2022/analogjs-router-tanstack-query-server.mjs",
3
+ "typings": "../../types/tanstack-query/server/src/index.d.ts"
4
+ }
@@ -0,0 +1,4 @@
1
+ export { withContentRoutes } from './lib/with-content-routes';
2
+ export { ANALOG_CONTENT_ROUTE_FILES, createContentRoutes } from './lib/routes';
3
+ export type { Files } from './lib/routes';
4
+ export { injectDebugContentRoutes } from './lib/debug/routes';
@@ -0,0 +1,10 @@
1
+ import { InjectionToken } from '@angular/core';
2
+ import { Route } from '@angular/router';
3
+ export declare const DEBUG_CONTENT_ROUTES: InjectionToken<(Route & DebugRoute)[]>;
4
+ export type DebugRoute = {
5
+ path: string;
6
+ filename: string;
7
+ isLayout: boolean;
8
+ children?: DebugRoute[];
9
+ };
10
+ export declare function injectDebugContentRoutes(): (Route & DebugRoute)[];
@@ -1,2 +1,2 @@
1
- import { RouteExport } from './models';
1
+ import type { RouteExport } from '../../../src/lib/models';
2
2
  export declare function toMarkdownModule(markdownFileFactory: () => Promise<string>): () => Promise<RouteExport>;
@@ -0,0 +1,8 @@
1
+ import type { Route } from '@angular/router';
2
+ import type { RouteExport } from '../../../src/lib/models';
3
+ /**
4
+ * This variable reference is replaced with a glob of all content routes.
5
+ */
6
+ export declare const ANALOG_CONTENT_ROUTE_FILES: {};
7
+ export type Files = Record<string, () => Promise<RouteExport | string>>;
8
+ export declare function createContentRoutes(files: Files, debug?: boolean): Route[];
@@ -0,0 +1,2 @@
1
+ import { type RouterFeatures } from '@angular/router';
2
+ export declare function withContentRoutes(): RouterFeatures;
@@ -0,0 +1 @@
1
+ export { provideI18n, I18nConfig, injectSwitchLocale, loadTranslationsRuntime, } from './provide-i18n';
@@ -0,0 +1,92 @@
1
+ import { EnvironmentProviders, Type } from '@angular/core';
2
+ /**
3
+ * Configuration for runtime i18n support.
4
+ *
5
+ * `defaultLocale` and `locales` are optional when the platform plugin
6
+ * is configured with `i18n` in `vite.config.ts` — the values are
7
+ * injected as build-time globals automatically.
8
+ */
9
+ export interface I18nConfig {
10
+ /**
11
+ * The default locale to use when no locale is detected.
12
+ * If omitted, reads from the platform plugin's `i18n.defaultLocale`.
13
+ */
14
+ defaultLocale?: string;
15
+ /**
16
+ * List of supported locale identifiers.
17
+ * If omitted, reads from the platform plugin's `i18n.locales`.
18
+ */
19
+ locales?: string[];
20
+ /**
21
+ * A function that returns translations for a given locale.
22
+ * The returned record maps message IDs to translated strings.
23
+ */
24
+ loader: (locale: string) => Promise<Record<string, string>> | Record<string, string>;
25
+ }
26
+ /**
27
+ * Fully resolved i18n config with all required fields.
28
+ */
29
+ export type ResolvedI18nConfig = Required<I18nConfig>;
30
+ /**
31
+ * Resolves the full i18n config by merging explicit values with
32
+ * build-time globals injected by the platform plugin.
33
+ */
34
+ export declare function resolveI18nConfig(config: I18nConfig): Required<I18nConfig>;
35
+ /**
36
+ * Provides runtime i18n support using Angular's $localize.
37
+ *
38
+ * This provider:
39
+ * 1. Detects the active locale from the URL or falls back to the default.
40
+ * 2. Makes the current locale available via the LOCALE injection token.
41
+ * 3. Loads translations for the active locale at startup using $localize.
42
+ *
43
+ * Works in both SSR and client-only modes. On the client, locale is detected
44
+ * from `window.location.pathname`. On the server, locale is detected from
45
+ * the request in `provideServerContext()` and provided at the platform level;
46
+ * this function does not shadow it.
47
+ *
48
+ * When the platform plugin is configured with `i18n` in `vite.config.ts`,
49
+ * `defaultLocale` and `locales` are injected automatically — only
50
+ * `loader` is required:
51
+ *
52
+ * ```typescript
53
+ * provideI18n({
54
+ * loader: (locale) => import(`./i18n/${locale}.json`),
55
+ * })
56
+ * ```
57
+ */
58
+ export declare function provideI18n(config: I18nConfig): EnvironmentProviders;
59
+ export declare function detectClientLocale(config: ResolvedI18nConfig): string;
60
+ /**
61
+ * Loads translations for the given locale and registers them with $localize.
62
+ *
63
+ * Always clears any previously loaded translations first so that switching
64
+ * between locales in a single SSR process does not mix translation maps.
65
+ */
66
+ export declare function initI18n(config: ResolvedI18nConfig, locale?: string): Promise<void>;
67
+ /**
68
+ * Loads translations into the global $localize translation map.
69
+ *
70
+ * Uses `@angular/localize`'s `loadTranslations` when available so that
71
+ * each translation string is parsed into the `{text, messageParts,
72
+ * placeholderNames}` shape that `$localize.translate` expects. Falls back
73
+ * to writing raw strings only as a last resort (in which case lookups
74
+ * will not succeed — the fallback exists to keep error messages useful
75
+ * for users who have not installed `@angular/localize`).
76
+ *
77
+ * Requires `@angular/localize/init` to be imported in the application
78
+ * entry point so that `globalThis.$localize` is defined.
79
+ */
80
+ export declare function loadTranslationsRuntime(translations: Record<string, string>): Promise<void>;
81
+ /** @internal — exported for tests; not re-exported from the package entry. */
82
+ export declare function clearTranslationsRuntime(): Promise<void>;
83
+ /** @internal */
84
+ export declare function ɵregisterI18nComponentDef(typeOrDef: Type<any> | any): void;
85
+ /** @internal */
86
+ export declare function ɵresetI18nComponentDefCache(): void;
87
+ /** @internal */
88
+ export declare function getI18nComponentDefRegistrySize(): number;
89
+ /** @internal */
90
+ export declare function clearI18nComponentDefRegistry(): void;
91
+ export declare function injectSwitchLocale(): (targetLocale: string) => void;
92
+ export declare function replaceLocaleInPath(pathname: string, targetLocale: string, locales: string[]): string;
@@ -0,0 +1,54 @@
1
+ import type { StandardSchemaV1 } from '@standard-schema/spec';
2
+ import type { H3Event, H3EventContext } from 'nitro/h3';
3
+ import type { $Fetch } from 'nitro/types';
4
+ type NodeContext = NonNullable<H3Event['node']>;
5
+ type OptionalSchema = StandardSchemaV1 | undefined;
6
+ type InferSchema<TSchema extends OptionalSchema, TFallback> = TSchema extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TSchema> : TFallback;
7
+ export interface DefineActionContext<TSchema extends OptionalSchema = undefined, TParamsSchema extends OptionalSchema = undefined> {
8
+ data: InferSchema<TSchema, Record<string, unknown>>;
9
+ params: InferSchema<TParamsSchema, H3EventContext['params']>;
10
+ req: NodeContext['req'];
11
+ res: NonNullable<NodeContext['res']>;
12
+ fetch: $Fetch;
13
+ event: H3Event;
14
+ }
15
+ export interface DefineActionOptions<TSchema extends OptionalSchema = undefined, TParamsSchema extends OptionalSchema = undefined> {
16
+ schema?: TSchema;
17
+ params?: TParamsSchema;
18
+ handler: (context: DefineActionContext<TSchema, TParamsSchema>) => Promise<Response> | Response;
19
+ }
20
+ /**
21
+ * Creates a server action handler with Standard Schema input validation.
22
+ *
23
+ * Parses the request body (JSON or FormData) and validates it against the
24
+ * provided schema before invoking the handler. On validation failure,
25
+ * returns `fail(422, issues)` with `StandardSchemaV1.Issue[]`.
26
+ * Repeated form fields are preserved as arrays instead of being collapsed
27
+ * to the last value.
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * import { defineAction, json } from '@analogjs/router/server/actions';
32
+ * import * as v from 'valibot';
33
+ *
34
+ * const Schema = v.object({
35
+ * email: v.pipe(v.string(), v.email()),
36
+ * });
37
+ *
38
+ * export const action = defineAction({
39
+ * schema: Schema,
40
+ * handler: async ({ data }) => {
41
+ * // data is typed as { email: string }
42
+ * return json({ ok: true });
43
+ * },
44
+ * });
45
+ * ```
46
+ */
47
+ export declare function defineAction<TSchema extends OptionalSchema = undefined, TParamsSchema extends OptionalSchema = undefined>(options: DefineActionOptions<TSchema, TParamsSchema>): (ctx: {
48
+ params: H3EventContext["params"];
49
+ req: NodeContext["req"];
50
+ res: NonNullable<NodeContext["res"]>;
51
+ fetch: $Fetch;
52
+ event: H3Event;
53
+ }) => Promise<Response>;
54
+ export {};