@analogjs/router 2.4.0-beta.9 → 3.0.0-alpha.10

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 (60) hide show
  1. package/fesm2022/analogjs-router-server-actions.mjs +327 -31
  2. package/fesm2022/analogjs-router-server.mjs +155 -176
  3. package/fesm2022/analogjs-router-tanstack-query.mjs +58 -0
  4. package/fesm2022/analogjs-router-tokens.mjs +17 -16
  5. package/fesm2022/analogjs-router.mjs +521 -812
  6. package/fesm2022/debug.page.mjs +121 -0
  7. package/fesm2022/routes.mjs +301 -0
  8. package/package.json +44 -26
  9. package/server/actions/package.json +4 -0
  10. package/server/package.json +4 -0
  11. package/tokens/package.json +4 -0
  12. package/types/server/actions/src/actions.d.ts +13 -0
  13. package/types/server/actions/src/define-action.d.ts +54 -0
  14. package/types/server/actions/src/define-page-load.d.ts +55 -0
  15. package/types/server/actions/src/define-server-route.d.ts +68 -0
  16. package/types/server/actions/src/index.d.ts +9 -0
  17. package/types/server/actions/src/parse-request-data.d.ts +9 -0
  18. package/types/server/actions/src/validate.d.ts +8 -0
  19. package/types/server/src/index.d.ts +4 -0
  20. package/types/server/src/provide-server-context.d.ts +11 -0
  21. package/types/server/src/render.d.ts +12 -0
  22. package/types/server/src/server-component-render.d.ts +4 -0
  23. package/types/server/src/tokens.d.ts +7 -0
  24. package/types/src/index.d.ts +16 -0
  25. package/types/src/lib/cache-key.d.ts +3 -0
  26. package/types/src/lib/constants.d.ts +2 -0
  27. package/types/src/lib/cookie-interceptor.d.ts +4 -0
  28. package/types/src/lib/debug/debug.page.d.ts +18 -0
  29. package/types/src/lib/debug/index.d.ts +10 -0
  30. package/types/src/lib/debug/routes.d.ts +10 -0
  31. package/types/src/lib/define-route.d.ts +46 -0
  32. package/types/src/lib/endpoints.d.ts +5 -0
  33. package/types/src/lib/form-action.directive.d.ts +25 -0
  34. package/types/src/lib/get-load-resolver.d.ts +8 -0
  35. package/types/src/lib/inject-load.d.ts +9 -0
  36. package/types/src/lib/inject-route-endpoint-url.d.ts +2 -0
  37. package/types/src/lib/markdown-helpers.d.ts +2 -0
  38. package/types/src/lib/meta-tags.d.ts +33 -0
  39. package/types/src/lib/models.d.ts +29 -0
  40. package/types/src/lib/provide-file-router.d.ts +18 -0
  41. package/types/src/lib/request-context.d.ts +13 -0
  42. package/types/src/lib/route-config.d.ts +2 -0
  43. package/types/src/lib/route-types.d.ts +12 -0
  44. package/types/src/lib/routes.d.ts +19 -0
  45. package/types/src/lib/server.component.d.ts +33 -0
  46. package/types/tanstack-query/src/index.d.ts +2 -0
  47. package/types/tanstack-query/src/provide-analog-query.d.ts +4 -0
  48. package/types/tanstack-query/src/provide-server-analog-query.d.ts +2 -0
  49. package/types/tanstack-query/src/server-query.d.ts +16 -0
  50. package/types/tokens/src/index.d.ts +23 -0
  51. package/fesm2022/analogjs-router-debug.page-jzggTA45.mjs +0 -91
  52. package/fesm2022/analogjs-router-debug.page-jzggTA45.mjs.map +0 -1
  53. package/fesm2022/analogjs-router-server-actions.mjs.map +0 -1
  54. package/fesm2022/analogjs-router-server.mjs.map +0 -1
  55. package/fesm2022/analogjs-router-tokens.mjs.map +0 -1
  56. package/fesm2022/analogjs-router.mjs.map +0 -1
  57. package/types/analogjs-router-server-actions.d.ts +0 -16
  58. package/types/analogjs-router-server.d.ts +0 -28
  59. package/types/analogjs-router-tokens.d.ts +0 -22
  60. package/types/analogjs-router.d.ts +0 -268
@@ -1,846 +1,555 @@
1
- import { Router, NavigationEnd, UrlSegment, ActivatedRoute, provideRouter, ROUTES } from '@angular/router';
2
- import * as i0 from '@angular/core';
3
- import { inject, PLATFORM_ID, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, Injector, makeStateKey, TransferState, input, output, Directive, InjectionToken, signal, effect, ChangeDetectionStrategy, Component } from '@angular/core';
4
- import { HttpClient, HttpHeaders, ɵHTTP_ROOT_INTERCEPTOR_FNS as _HTTP_ROOT_INTERCEPTOR_FNS, HttpResponse, HttpRequest } from '@angular/common/http';
5
- import { firstValueFrom, map, from, of, throwError, catchError } from 'rxjs';
6
- import { Meta, DomSanitizer } from '@angular/platform-browser';
7
- import { filter } from 'rxjs/operators';
8
- import { injectAPIPrefix, injectBaseURL, injectRequest, API_PREFIX } from '@analogjs/router/tokens';
9
- import { isPlatformServer } from '@angular/common';
10
-
11
- const ROUTE_META_TAGS_KEY = Symbol('@analogjs/router Route Meta Tags Key');
12
- const CHARSET_KEY = 'charset';
13
- const HTTP_EQUIV_KEY = 'httpEquiv';
14
- // httpEquiv selector key needs to be in kebab case format
15
- const HTTP_EQUIV_SELECTOR_KEY = 'http-equiv';
16
- const NAME_KEY = 'name';
17
- const PROPERTY_KEY = 'property';
18
- const CONTENT_KEY = 'content';
19
- const ITEMPROP_KEY = 'itemprop';
20
- function updateMetaTagsOnRouteChange() {
21
- const router = inject(Router);
22
- const metaService = inject(Meta);
23
- router.events
24
- .pipe(filter((event) => event instanceof NavigationEnd))
25
- .subscribe(() => {
26
- const metaTagMap = getMetaTagMap(router.routerState.snapshot.root);
27
- for (const metaTagSelector in metaTagMap) {
28
- const metaTag = metaTagMap[metaTagSelector];
29
- metaService.updateTag(metaTag, metaTagSelector);
30
- }
31
- });
32
- }
33
- function getMetaTagMap(route) {
34
- const metaTagMap = {};
35
- let currentRoute = route;
36
- while (currentRoute) {
37
- const metaTags = currentRoute.data[ROUTE_META_TAGS_KEY] ?? [];
38
- for (const metaTag of metaTags) {
39
- metaTagMap[getMetaTagSelector(metaTag)] = metaTag;
40
- }
41
- currentRoute = currentRoute.firstChild;
42
- }
43
- return metaTagMap;
44
- }
45
- function getMetaTagSelector(metaTag) {
46
- if (metaTag.name) {
47
- return `${NAME_KEY}="${metaTag.name}"`;
48
- }
49
- if (metaTag.property) {
50
- return `${PROPERTY_KEY}="${metaTag.property}"`;
51
- }
52
- if (metaTag.httpEquiv) {
53
- return `${HTTP_EQUIV_SELECTOR_KEY}="${metaTag.httpEquiv}"`;
54
- }
55
- if (metaTag.itemprop) {
56
- return `${ITEMPROP_KEY}="${metaTag.itemprop}"`;
57
- }
58
- return CHARSET_KEY;
59
- }
60
-
61
- const ANALOG_META_KEY = Symbol('@analogjs/router Analog Route Metadata Key');
62
- /**
63
- * This variable reference is replaced with a glob of all route endpoints.
64
- */
65
- let ANALOG_PAGE_ENDPOINTS = {};
66
-
67
- function injectRouteEndpointURL(route) {
68
- const routeConfig = route.routeConfig;
69
- const apiPrefix = injectAPIPrefix();
70
- const baseUrl = injectBaseURL();
71
- const { queryParams, fragment: hash, params, parent } = route;
72
- const segment = parent?.url.map((segment) => segment.path).join('/') || '';
73
- const url = new URL('', import.meta.env['VITE_ANALOG_PUBLIC_BASE_URL'] ||
74
- baseUrl ||
75
- (typeof window !== 'undefined' && window.location.origin
76
- ? window.location.origin
77
- : ''));
78
- url.pathname = `${url.pathname.endsWith('/') ? url.pathname : url.pathname + '/'}${apiPrefix}/_analog${routeConfig[ANALOG_META_KEY].endpoint}`;
79
- url.search = `${new URLSearchParams(queryParams).toString()}`;
80
- url.hash = hash ?? '';
81
- Object.keys(params).forEach((param) => {
82
- url.pathname = url.pathname.replace(`[${param}]`, params[param]);
83
- });
84
- url.pathname = url.pathname.replace('**', segment);
85
- return url;
86
- }
87
-
88
- function toRouteConfig(routeMeta) {
89
- if (routeMeta && isRedirectRouteMeta(routeMeta)) {
90
- return routeMeta;
91
- }
92
- let { meta, ...routeConfig } = routeMeta ?? {};
93
- if (Array.isArray(meta)) {
94
- routeConfig.data = { ...routeConfig.data, [ROUTE_META_TAGS_KEY]: meta };
95
- }
96
- else if (typeof meta === 'function') {
97
- routeConfig.resolve = {
98
- ...routeConfig.resolve,
99
- [ROUTE_META_TAGS_KEY]: meta,
100
- };
101
- }
102
- if (!routeConfig) {
103
- routeConfig = {};
104
- }
105
- routeConfig.runGuardsAndResolvers =
106
- routeConfig.runGuardsAndResolvers ?? 'paramsOrQueryParamsChange';
107
- routeConfig.resolve = {
108
- ...routeConfig.resolve,
109
- load: async (route) => {
110
- const routeConfig = route.routeConfig;
111
- if (ANALOG_PAGE_ENDPOINTS[routeConfig[ANALOG_META_KEY].endpointKey]) {
112
- const http = inject(HttpClient);
113
- const url = injectRouteEndpointURL(route);
114
- if (!!import.meta.env['VITE_ANALOG_PUBLIC_BASE_URL'] &&
115
- globalThis.$fetch) {
116
- return globalThis.$fetch(url.pathname);
117
- }
118
- return firstValueFrom(http.get(`${url.href}`));
119
- }
120
- return {};
121
- },
122
- };
123
- return routeConfig;
124
- }
125
- function isRedirectRouteMeta(routeMeta) {
126
- return !!routeMeta.redirectTo;
127
- }
128
-
129
- // The Zone is currently enabled by default, so we wouldn't need this check.
130
- // However, leaving this open space will be useful if zone.js becomes optional
131
- // in the future. This means we won't have to modify the current code, and it will
132
- // continue to work seamlessly.
133
- const isNgZoneEnabled = typeof Zone !== 'undefined' && !!Zone.root;
134
- function toMarkdownModule(markdownFileFactory) {
135
- return async () => {
136
- const createLoader = () => Promise.all([import('@analogjs/content'), markdownFileFactory()]);
137
- const [{ parseRawContentFile, MarkdownRouteComponent, ContentRenderer }, markdownFile,] = await (isNgZoneEnabled
138
- ? // We are not able to use `runOutsideAngular` because we are not inside
139
- // an injection context to retrieve the `NgZone` instance.
140
- // The `Zone.root.run` is required when the code is running in the
141
- // browser since asynchronous tasks being scheduled in the current context
142
- // are a reason for unnecessary change detection cycles.
143
- Zone.root.run(createLoader)
144
- : createLoader());
145
- const { content, attributes } = parseRawContentFile(markdownFile);
146
- const { title, meta } = attributes;
147
- return {
148
- default: MarkdownRouteComponent,
149
- routeMeta: {
150
- data: { _analogContent: content },
151
- title,
152
- meta,
153
- resolve: {
154
- renderedAnalogContent: async () => {
155
- const contentRenderer = inject(ContentRenderer);
156
- const rendered = await contentRenderer.render(content);
157
- return typeof rendered === 'string'
158
- ? rendered
159
- : rendered.content;
160
- },
161
- },
162
- },
163
- };
164
- };
165
- }
166
-
167
- const ENDPOINT_EXTENSION = '.server.ts';
168
- const APP_DIR = 'src/app';
169
-
1
+ import { a as updateMetaTagsOnRouteChange, i as injectRouteEndpointURL, n as createRoutes, r as routes, t as injectDebugRoutes } from "./routes.mjs";
2
+ import { ActivatedRoute, ROUTES, Router, provideRouter } from "@angular/router";
3
+ import * as i0 from "@angular/core";
4
+ import { ChangeDetectionStrategy, Component, Directive, ENVIRONMENT_INITIALIZER, Injector, PLATFORM_ID, TransferState, effect, inject, input, makeEnvironmentProviders, makeStateKey, output, signal } from "@angular/core";
5
+ import { HttpClient, HttpHeaders, HttpRequest, HttpResponse, ɵHTTP_ROOT_INTERCEPTOR_FNS } from "@angular/common/http";
6
+ import { catchError, from, map, of, throwError } from "rxjs";
7
+ import { API_PREFIX, injectAPIPrefix, injectBaseURL, injectInternalServerFetch, injectRequest } from "@analogjs/router/tokens";
8
+ import { DomSanitizer } from "@angular/platform-browser";
9
+ import { isPlatformServer } from "@angular/common";
10
+ //#region packages/router/src/lib/define-route.ts
170
11
  /**
171
- * This variable reference is replaced with a glob of all page routes.
172
- */
173
- let ANALOG_ROUTE_FILES = {};
174
- /**
175
- * This variable reference is replaced with a glob of all content routes.
176
- */
177
- let ANALOG_CONTENT_ROUTE_FILES = {};
178
- /**
179
- * A function used to parse list of files and create configuration of routes.
180
- *
181
- * @param files
182
- * @returns Array of routes
183
- */
184
- function createRoutes(files, debug = false) {
185
- const filenames = Object.keys(files);
186
- if (filenames.length === 0) {
187
- return [];
188
- }
189
- // map filenames to raw routes and group them by level
190
- const rawRoutesByLevelMap = filenames.reduce((acc, filename) => {
191
- const rawPath = toRawPath(filename);
192
- const rawSegments = rawPath.split('/');
193
- // nesting level starts at 0
194
- // rawPath: /products => level: 0
195
- // rawPath: /products/:id => level: 1
196
- const level = rawSegments.length - 1;
197
- const rawSegment = rawSegments[level];
198
- const ancestorRawSegments = rawSegments.slice(0, level);
199
- return {
200
- ...acc,
201
- [level]: {
202
- ...acc[level],
203
- [rawPath]: {
204
- filename,
205
- rawSegment,
206
- ancestorRawSegments,
207
- segment: toSegment(rawSegment),
208
- level,
209
- children: [],
210
- },
211
- },
212
- };
213
- }, {});
214
- const allLevels = Object.keys(rawRoutesByLevelMap).map(Number);
215
- const maxLevel = Math.max(...allLevels);
216
- // add each raw route to its parent's children array
217
- for (let level = maxLevel; level > 0; level--) {
218
- const rawRoutesMap = rawRoutesByLevelMap[level];
219
- const rawPaths = Object.keys(rawRoutesMap);
220
- for (const rawPath of rawPaths) {
221
- const rawRoute = rawRoutesMap[rawPath];
222
- const parentRawPath = rawRoute.ancestorRawSegments.join('/');
223
- const parentRawSegmentIndex = rawRoute.ancestorRawSegments.length - 1;
224
- const parentRawSegment = rawRoute.ancestorRawSegments[parentRawSegmentIndex];
225
- // create the parent level and/or raw route if it does not exist
226
- // parent route won't exist for nested routes that don't have a layout route
227
- rawRoutesByLevelMap[level - 1] ||= {};
228
- rawRoutesByLevelMap[level - 1][parentRawPath] ||= {
229
- filename: null,
230
- rawSegment: parentRawSegment,
231
- ancestorRawSegments: rawRoute.ancestorRawSegments.slice(0, parentRawSegmentIndex),
232
- segment: toSegment(parentRawSegment),
233
- level: level - 1,
234
- children: [],
235
- };
236
- rawRoutesByLevelMap[level - 1][parentRawPath].children.push(rawRoute);
237
- }
238
- }
239
- // only take raw routes from the root level
240
- // since they already contain nested routes as their children
241
- const rootRawRoutesMap = rawRoutesByLevelMap[0];
242
- const rawRoutes = Object.keys(rootRawRoutesMap).map((segment) => rootRawRoutesMap[segment]);
243
- sortRawRoutes(rawRoutes);
244
- return toRoutes(rawRoutes, files, debug);
245
- }
246
- function toRawPath(filename) {
247
- return (filename
248
- .replace(
249
- // convert to relative path and remove file extension
250
- /^(?:[a-zA-Z]:[\\/])?(.*?)[\\/](?:routes|pages)[\\/]|(?:[\\/](?:app[\\/](?:routes|pages)|src[\\/]content)[\\/])|(\.page\.(js|ts|analog|ag)$)|(\.(ts|md|analog|ag)$)/g, '')
251
- // [[...slug]] => placeholder (named empty) which is stripped by toSegment
252
- .replace(/\[\[\.\.\.([^\]]+)\]\]/g, '(opt-$1)')
253
- .replace(/\[\.{3}.+\]/, '**') // [...not-found] => **
254
- .replace(/\[([^\]]+)\]/g, ':$1')); // [id] => :id
255
- }
256
- function toSegment(rawSegment) {
257
- return rawSegment
258
- .replace(/index|\(.*?\)/g, '') // replace named empty segments
259
- .replace(/\.|\/+/g, '/') // replace dots with slashes and remove redundant slashes
260
- .replace(/^\/+|\/+$/g, ''); // remove trailing slashes
261
- }
262
- function createOptionalCatchAllMatcher(paramName) {
263
- return (segments) => {
264
- if (segments.length === 0) {
265
- return null;
266
- }
267
- const joined = segments.map((s) => s.path).join('/');
268
- return {
269
- consumed: segments,
270
- posParams: { [paramName]: new UrlSegment(joined, {}) },
271
- };
272
- };
273
- }
274
- function toRoutes(rawRoutes, files, debug = false) {
275
- const routes = [];
276
- for (const rawRoute of rawRoutes) {
277
- const children = rawRoute.children.length > 0
278
- ? toRoutes(rawRoute.children, files, debug)
279
- : undefined;
280
- let module = undefined;
281
- let analogMeta = undefined;
282
- if (rawRoute.filename) {
283
- const isMarkdownFile = rawRoute.filename.endsWith('.md');
284
- if (!debug) {
285
- module = isMarkdownFile
286
- ? toMarkdownModule(files[rawRoute.filename])
287
- : files[rawRoute.filename];
288
- }
289
- const endpointKey = rawRoute.filename.replace(/\.page\.(ts|analog|ag)$/, ENDPOINT_EXTENSION);
290
- // get endpoint path
291
- const rawEndpoint = rawRoute.filename
292
- .replace(/\.page\.(ts|analog|ag)$/, '')
293
- .replace(/\[\[\.\.\..+\]\]/, '**')
294
- .replace(/\[\.{3}.+\]/, '**') // [...not-found] => **
295
- .replace(/^(.*?)\/pages/, '/pages');
296
- // replace periods, remove (index) paths
297
- const endpoint = (rawEndpoint || '')
298
- .replace(/\./g, '/')
299
- .replace(/\/\((.*?)\)$/, '/-$1-');
300
- analogMeta = {
301
- endpoint,
302
- endpointKey,
303
- };
304
- }
305
- // Detect Next.js-style optional catch-all at this node: [[...param]]
306
- const optCatchAllMatch = rawRoute.filename?.match(/\[\[\.\.\.([^\]]+)\]\]/);
307
- const optCatchAllParam = optCatchAllMatch ? optCatchAllMatch[1] : null;
308
- const route = module
309
- ? {
310
- path: rawRoute.segment,
311
- loadChildren: () => module().then((m) => {
312
- if (import.meta.env.DEV) {
313
- const hasModuleDefault = !!m.default;
314
- const hasRedirect = !!m.routeMeta?.redirectTo;
315
- if (!hasModuleDefault && !hasRedirect) {
316
- console.warn(`[Analog] Missing default export at ${rawRoute.filename}`);
317
- }
318
- }
319
- const baseChild = {
320
- path: '',
321
- component: m.default,
322
- ...toRouteConfig(m.routeMeta),
323
- children,
324
- [ANALOG_META_KEY]: analogMeta,
325
- };
326
- // Base route first so static matches win, then optional catch-all matcher
327
- return [
328
- {
329
- ...baseChild,
330
- },
331
- ...(optCatchAllParam
332
- ? [
333
- {
334
- matcher: createOptionalCatchAllMatcher(optCatchAllParam),
335
- component: m.default,
336
- ...toRouteConfig(m.routeMeta),
337
- [ANALOG_META_KEY]: analogMeta,
338
- },
339
- ]
340
- : []),
341
- ];
342
- }),
343
- }
344
- : {
345
- path: rawRoute.segment,
346
- ...(debug
347
- ? {
348
- filename: rawRoute.filename ? rawRoute.filename : undefined,
349
- isLayout: children && children.length > 0 ? true : false,
350
- }
351
- : {}),
352
- children,
353
- };
354
- routes.push(route);
355
- }
356
- return routes;
357
- }
358
- function sortRawRoutes(rawRoutes) {
359
- rawRoutes.sort((a, b) => {
360
- let segmentA = deprioritizeSegment(a.segment);
361
- let segmentB = deprioritizeSegment(b.segment);
362
- // prioritize routes with fewer children
363
- if (a.children.length > b.children.length) {
364
- segmentA = `~${segmentA}`;
365
- }
366
- else if (a.children.length < b.children.length) {
367
- segmentB = `~${segmentB}`;
368
- }
369
- return segmentA > segmentB ? 1 : -1;
370
- });
371
- for (const rawRoute of rawRoutes) {
372
- sortRawRoutes(rawRoute.children);
373
- }
374
- }
375
- function deprioritizeSegment(segment) {
376
- // deprioritize param and wildcard segments
377
- return segment.replace(':', '~~').replace('**', '~~~~');
378
- }
379
- const routes = createRoutes({
380
- ...ANALOG_ROUTE_FILES,
381
- ...ANALOG_CONTENT_ROUTE_FILES,
382
- });
383
-
384
- /**
385
- * @deprecated Use `RouteMeta` type instead.
386
- * For more info see: https://github.com/analogjs/analog/issues/223
387
- *
388
- * Defines additional route config metadata. This
389
- * object is merged into the route config with
390
- * the predefined file-based route.
391
- *
392
- * @usageNotes
393
- *
394
- * ```
395
- * import { Component } from '@angular/core';
396
- * import { defineRouteMeta } from '@analogjs/router';
397
- *
398
- * export const routeMeta = defineRouteMeta({
399
- * title: 'Welcome'
400
- * });
401
- *
402
- * @Component({
403
- * template: `Home`,
404
- * standalone: true,
405
- * })
406
- * export default class HomeComponent {}
407
- * ```
408
- *
409
- * @param route
410
- * @returns
411
- */
412
- const defineRouteMeta = (route) => {
413
- return route;
12
+ * @deprecated Use `RouteMeta` type instead.
13
+ * For more info see: https://github.com/analogjs/analog/issues/223
14
+ *
15
+ * Defines additional route config metadata. This
16
+ * object is merged into the route config with
17
+ * the predefined file-based route.
18
+ *
19
+ * @usageNotes
20
+ *
21
+ * ```
22
+ * import { Component } from '@angular/core';
23
+ * import { defineRouteMeta } from '@analogjs/router';
24
+ *
25
+ * export const routeMeta = defineRouteMeta({
26
+ * title: 'Welcome'
27
+ * });
28
+ *
29
+ * @Component({
30
+ * template: `Home`,
31
+ * standalone: true,
32
+ * })
33
+ * export default class HomeComponent {}
34
+ * ```
35
+ *
36
+ * @param route
37
+ * @returns
38
+ */
39
+ var defineRouteMeta = (route) => {
40
+ return route;
414
41
  };
415
42
  /**
416
- * Returns the instance of Angular Router
417
- *
418
- * @returns The router
419
- */
420
- const injectRouter = () => {
421
- return inject(Router);
43
+ * Returns the instance of Angular Router
44
+ *
45
+ * @returns The router
46
+ */
47
+ var injectRouter = () => {
48
+ return inject(Router);
422
49
  };
423
50
  /**
424
- * Returns the instance of the Activate Route for the component
425
- *
426
- * @returns The activated route
427
- */
428
- const injectActivatedRoute = () => {
429
- return inject(ActivatedRoute);
51
+ * Returns the instance of the Activate Route for the component
52
+ *
53
+ * @returns The activated route
54
+ */
55
+ var injectActivatedRoute = () => {
56
+ return inject(ActivatedRoute);
430
57
  };
431
-
58
+ //#endregion
59
+ //#region packages/router/src/lib/cookie-interceptor.ts
432
60
  function cookieInterceptor(req, next, location = inject(PLATFORM_ID), serverRequest = injectRequest()) {
433
- if (isPlatformServer(location) && req.url.includes('/_analog/')) {
434
- let headers = new HttpHeaders();
435
- const cookies = serverRequest?.headers.cookie;
436
- headers = headers.set('cookie', cookies ?? '');
437
- const cookiedRequest = req.clone({
438
- headers,
439
- });
440
- return next(cookiedRequest);
441
- }
442
- else {
443
- return next(req);
444
- }
61
+ if (isPlatformServer(location) && req.url.includes("/_analog/")) {
62
+ let headers = new HttpHeaders();
63
+ const cookies = serverRequest?.headers.cookie;
64
+ headers = headers.set("cookie", cookies ?? "");
65
+ return next(req.clone({ headers }));
66
+ } else return next(req);
445
67
  }
446
-
68
+ //#endregion
69
+ //#region packages/router/src/lib/provide-file-router.ts
447
70
  /**
448
- * Sets up providers for the Angular router, and registers
449
- * file-based routes. Additional features can be provided
450
- * to further configure the behavior of the router.
451
- *
452
- * @param features
453
- * @returns Providers and features to configure the router with routes
454
- */
71
+ * Sets up providers for the Angular router, and registers
72
+ * file-based routes. Additional features can be provided
73
+ * to further configure the behavior of the router.
74
+ *
75
+ * @param features
76
+ * @returns Providers and features to configure the router with routes
77
+ */
455
78
  function provideFileRouter(...features) {
456
- const extraRoutesFeature = features.filter((feat) => feat.ɵkind >= 100);
457
- const routerFeatures = features.filter((feat) => feat.ɵkind < 100);
458
- return makeEnvironmentProviders([
459
- extraRoutesFeature.map((erf) => erf.ɵproviders),
460
- provideRouter(routes, ...routerFeatures),
461
- {
462
- provide: ENVIRONMENT_INITIALIZER,
463
- multi: true,
464
- useValue: () => updateMetaTagsOnRouteChange(),
465
- },
466
- {
467
- provide: _HTTP_ROOT_INTERCEPTOR_FNS,
468
- multi: true,
469
- useValue: cookieInterceptor,
470
- },
471
- {
472
- provide: API_PREFIX,
473
- useFactory() {
474
- return typeof ANALOG_API_PREFIX !== 'undefined'
475
- ? ANALOG_API_PREFIX
476
- : 'api';
477
- },
478
- },
479
- ]);
79
+ const extraRoutesFeature = features.filter((feat) => feat.ɵkind >= 100);
80
+ const routerFeatures = features.filter((feat) => feat.ɵkind < 100);
81
+ return makeEnvironmentProviders([
82
+ extraRoutesFeature.map((erf) => erf.ɵproviders),
83
+ provideRouter(routes, ...routerFeatures),
84
+ {
85
+ provide: ENVIRONMENT_INITIALIZER,
86
+ multi: true,
87
+ useValue: () => updateMetaTagsOnRouteChange()
88
+ },
89
+ {
90
+ provide: ɵHTTP_ROOT_INTERCEPTOR_FNS,
91
+ multi: true,
92
+ useValue: cookieInterceptor
93
+ },
94
+ {
95
+ provide: API_PREFIX,
96
+ useFactory() {
97
+ return typeof ANALOG_API_PREFIX !== "undefined" ? ANALOG_API_PREFIX : "api";
98
+ }
99
+ }
100
+ ]);
480
101
  }
481
102
  /**
482
- * Provides extra custom routes in addition to the routes
483
- * discovered from the filesystem-based routing. These routes are
484
- * inserted before the filesystem-based routes, and take priority in
485
- * route matching.
486
- */
103
+ * Provides extra custom routes in addition to the routes
104
+ * discovered from the filesystem-based routing. These routes are
105
+ * inserted before the filesystem-based routes, and take priority in
106
+ * route matching.
107
+ */
487
108
  function withExtraRoutes(routes) {
488
- return {
489
- ɵkind: 100,
490
- ɵproviders: [{ provide: ROUTES, useValue: routes, multi: true }],
491
- };
109
+ return {
110
+ ɵkind: 100,
111
+ ɵproviders: [{
112
+ provide: ROUTES,
113
+ useValue: routes,
114
+ multi: true
115
+ }]
116
+ };
117
+ }
118
+ //#endregion
119
+ //#region packages/router/src/lib/inject-load.ts
120
+ function isResponse(value) {
121
+ return typeof value === "object" && value instanceof Response;
492
122
  }
493
-
494
123
  function injectLoad(options) {
495
- const injector = options?.injector ?? inject(Injector);
496
- const route = injector.get(ActivatedRoute);
497
- return route.data.pipe(map((data) => data['load']));
124
+ return (options?.injector ?? inject(Injector)).get(ActivatedRoute).data.pipe(map((data) => data["load"]));
498
125
  }
499
-
126
+ function injectLoadData(options) {
127
+ return injectLoad(options).pipe(map((result) => {
128
+ if (isResponse(result)) throw new Error("Expected page load data but received a response.");
129
+ return result;
130
+ }));
131
+ }
132
+ //#endregion
133
+ //#region packages/router/src/lib/get-load-resolver.ts
500
134
  /**
501
- * Get server load resolver data for the route
502
- *
503
- * @param route Provides the route to get server load resolver
504
- * @returns Returns server load resolver data for the route
505
- */
135
+ * Get server load resolver data for the route
136
+ *
137
+ * @param route Provides the route to get server load resolver
138
+ * @returns Returns server load resolver data for the route
139
+ */
506
140
  async function getLoadResolver(route) {
507
- return route.routeConfig?.resolve?.['load']?.(route);
141
+ return route.routeConfig?.resolve?.["load"]?.(route);
508
142
  }
509
-
143
+ //#endregion
144
+ //#region packages/router/src/lib/cache-key.ts
510
145
  function sortAndConcatParams(params) {
511
- return [...params.keys()]
512
- .sort()
513
- .map((k) => `${k}=${params.getAll(k)}`)
514
- .join('&');
146
+ return [...params.keys()].sort().map((k) => `${k}=${params.getAll(k)}`).join("&");
515
147
  }
516
148
  function makeCacheKey(request, mappedRequestUrl) {
517
- // make the params encoded same as a url so it's easy to identify
518
- const { params, method, responseType } = request;
519
- const encodedParams = sortAndConcatParams(params);
520
- let serializedBody = request.serializeBody();
521
- if (serializedBody instanceof URLSearchParams) {
522
- serializedBody = sortAndConcatParams(serializedBody);
523
- }
524
- else if (typeof serializedBody !== 'string') {
525
- serializedBody = '';
526
- }
527
- const key = [
528
- method,
529
- responseType,
530
- mappedRequestUrl,
531
- serializedBody,
532
- encodedParams,
533
- ].join('|');
534
- const hash = generateHash(key);
535
- return makeStateKey(hash);
149
+ const { params, method, responseType } = request;
150
+ const encodedParams = sortAndConcatParams(params);
151
+ let serializedBody = request.serializeBody();
152
+ if (serializedBody instanceof URLSearchParams) serializedBody = sortAndConcatParams(serializedBody);
153
+ else if (typeof serializedBody !== "string") serializedBody = "";
154
+ return makeStateKey(generateHash([
155
+ method,
156
+ responseType,
157
+ mappedRequestUrl,
158
+ serializedBody,
159
+ encodedParams
160
+ ].join("|")));
536
161
  }
537
162
  function generateHash(str) {
538
- let hash = 0;
539
- for (let i = 0, len = str.length; i < len; i++) {
540
- let chr = str.charCodeAt(i);
541
- hash = (hash << 5) - hash + chr;
542
- hash |= 0; // Convert to 32bit integer
543
- }
544
- return `${hash}`;
163
+ let hash = 0;
164
+ for (let i = 0, len = str.length; i < len; i++) {
165
+ const chr = str.charCodeAt(i);
166
+ hash = (hash << 5) - hash + chr;
167
+ hash |= 0;
168
+ }
169
+ return `${hash}`;
545
170
  }
546
-
171
+ //#endregion
172
+ //#region packages/router/src/lib/request-context.ts
547
173
  /**
548
- * Interceptor that is server-aware when making HttpClient requests.
549
- * Server-side requests use the full URL
550
- * Prerendering uses the internal Nitro $fetch function, along with state transfer
551
- * Client-side requests use the window.location.origin
552
- *
553
- * @param req HttpRequest<unknown>
554
- * @param next HttpHandlerFn
555
- * @returns
556
- */
174
+ * Interceptor that is server-aware when making HttpClient requests.
175
+ * Server-side requests use the full URL
176
+ * Prerendering uses the internal Nitro $fetch function, along with state transfer
177
+ * Client-side requests use the window.location.origin
178
+ *
179
+ * @param req HttpRequest<unknown>
180
+ * @param next HttpHandlerFn
181
+ * @returns
182
+ */
557
183
  function requestContextInterceptor(req, next) {
558
- const apiPrefix = injectAPIPrefix();
559
- const baseUrl = injectBaseURL();
560
- const transferState = inject(TransferState);
561
- // during prerendering with Nitro
562
- if (typeof global !== 'undefined' &&
563
- global.$fetch &&
564
- baseUrl &&
565
- (req.url.startsWith('/') ||
566
- req.url.startsWith(baseUrl) ||
567
- req.url.startsWith(`/${apiPrefix}`))) {
568
- const requestUrl = new URL(req.url, baseUrl);
569
- const cacheKey = makeCacheKey(req, new URL(requestUrl).pathname);
570
- const storeKey = makeStateKey(`analog_${cacheKey}`);
571
- const fetchUrl = requestUrl.pathname;
572
- const responseType = req.responseType === 'arraybuffer' ? 'arrayBuffer' : req.responseType;
573
- return from(global.$fetch
574
- .raw(fetchUrl, {
575
- method: req.method,
576
- body: req.body ? req.body : undefined,
577
- params: requestUrl.searchParams,
578
- responseType,
579
- headers: req.headers.keys().reduce((hdrs, current) => {
580
- return {
581
- ...hdrs,
582
- [current]: req.headers.get(current),
583
- };
584
- }, {}),
585
- })
586
- .then((res) => {
587
- const cacheResponse = {
588
- body: res._data,
589
- headers: new HttpHeaders(res.headers),
590
- status: 200,
591
- statusText: 'OK',
592
- url: fetchUrl,
593
- };
594
- const transferResponse = new HttpResponse(cacheResponse);
595
- transferState.set(storeKey, cacheResponse);
596
- return transferResponse;
597
- }));
598
- }
599
- // on the client
600
- if (!import.meta.env.SSR &&
601
- (req.url.startsWith('/') || req.url.includes('/_analog/'))) {
602
- // /_analog/ requests are full URLs
603
- const requestUrl = req.url.includes('/_analog/')
604
- ? req.url
605
- : `${window.location.origin}${req.url}`;
606
- const cacheKey = makeCacheKey(req, new URL(requestUrl).pathname);
607
- const storeKey = makeStateKey(`analog_${cacheKey}`);
608
- const cacheRestoreResponse = transferState.get(storeKey, null);
609
- if (cacheRestoreResponse) {
610
- transferState.remove(storeKey);
611
- return of(new HttpResponse(cacheRestoreResponse));
612
- }
613
- return next(req.clone({
614
- url: requestUrl,
615
- }));
616
- }
617
- // on the server
618
- if (baseUrl && (req.url.startsWith('/') || req.url.startsWith(baseUrl))) {
619
- const requestUrl = req.url.startsWith(baseUrl) && !req.url.startsWith('/')
620
- ? req.url
621
- : `${baseUrl}${req.url}`;
622
- return next(req.clone({
623
- url: requestUrl,
624
- }));
625
- }
626
- return next(req);
184
+ const apiPrefix = injectAPIPrefix();
185
+ const baseUrl = injectBaseURL();
186
+ const transferState = inject(TransferState);
187
+ const nitroGlobal = globalThis;
188
+ const serverFetch = injectInternalServerFetch() ?? nitroGlobal.$fetch;
189
+ if (serverFetch && baseUrl && (req.url.startsWith("/") || req.url.startsWith(baseUrl) || req.url.startsWith(`/${apiPrefix}`))) {
190
+ const requestUrl = new URL(req.url, baseUrl);
191
+ const storeKey = makeStateKey(`analog_${makeCacheKey(req, new URL(requestUrl).pathname)}`);
192
+ const fetchUrl = requestUrl.pathname;
193
+ const responseType = req.responseType === "arraybuffer" ? "arrayBuffer" : req.responseType;
194
+ return from(serverFetch.raw(fetchUrl, {
195
+ method: req.method,
196
+ body: req.body ? req.body : void 0,
197
+ params: requestUrl.searchParams,
198
+ responseType,
199
+ headers: req.headers.keys().reduce((hdrs, current) => {
200
+ return {
201
+ ...hdrs,
202
+ [current]: req.headers.get(current)
203
+ };
204
+ }, {})
205
+ }).then((res) => {
206
+ const cacheResponse = {
207
+ body: res._data,
208
+ headers: new HttpHeaders(res.headers),
209
+ status: res.status ?? 200,
210
+ statusText: res.statusText ?? "OK",
211
+ url: fetchUrl
212
+ };
213
+ const transferResponse = new HttpResponse(cacheResponse);
214
+ transferState.set(storeKey, cacheResponse);
215
+ return transferResponse;
216
+ }));
217
+ }
218
+ if (req.url.startsWith("/") || req.url.includes("/_analog/")) {
219
+ const requestUrl = req.url.includes("/_analog/") ? req.url : `${window.location.origin}${req.url}`;
220
+ const storeKey = makeStateKey(`analog_${makeCacheKey(req, new URL(requestUrl).pathname)}`);
221
+ const cacheRestoreResponse = transferState.get(storeKey, null);
222
+ if (cacheRestoreResponse) {
223
+ transferState.remove(storeKey);
224
+ return of(new HttpResponse(cacheRestoreResponse));
225
+ }
226
+ return next(req.clone({ url: requestUrl }));
227
+ }
228
+ if (baseUrl && (req.url.startsWith("/") || req.url.startsWith(baseUrl))) {
229
+ const requestUrl = req.url.startsWith(baseUrl) && !req.url.startsWith("/") ? req.url : `${baseUrl}${req.url}`;
230
+ return next(req.clone({ url: requestUrl }));
231
+ }
232
+ return next(req);
627
233
  }
628
-
629
- class FormAction {
630
- constructor() {
631
- this.action = input('', ...(ngDevMode ? [{ debugName: "action" }] : []));
632
- this.onSuccess = output();
633
- this.onError = output();
634
- this.state = output();
635
- this.router = inject(Router);
636
- this.route = inject(ActivatedRoute);
637
- this.path = this._getPath();
638
- }
639
- submitted($event) {
640
- $event.preventDefault();
641
- this.state.emit('submitting');
642
- const body = new FormData($event.target);
643
- if ($event.target.method.toUpperCase() === 'GET') {
644
- this._handleGet(body, this.router.url);
645
- }
646
- else {
647
- this._handlePost(body, this.path, $event);
648
- }
649
- }
650
- _handleGet(body, path) {
651
- const params = {};
652
- body.forEach((formVal, formKey) => (params[formKey] = formVal));
653
- this.state.emit('navigate');
654
- const url = path.split('?')[0];
655
- this.router.navigate([url], {
656
- queryParams: params,
657
- onSameUrlNavigation: 'reload',
658
- });
659
- }
660
- _handlePost(body, path, $event) {
661
- fetch(path, {
662
- method: $event.target.method,
663
- body,
664
- })
665
- .then((res) => {
666
- if (res.ok) {
667
- if (res.redirected) {
668
- const redirectUrl = new URL(res.url).pathname;
669
- this.state.emit('redirect');
670
- this.router.navigate([redirectUrl]);
671
- }
672
- else if (this._isJSON(res.headers.get('Content-type'))) {
673
- res.json().then((result) => {
674
- this.onSuccess.emit(result);
675
- this.state.emit('success');
676
- });
677
- }
678
- else {
679
- res.text().then((result) => {
680
- this.onSuccess.emit(result);
681
- this.state.emit('success');
682
- });
683
- }
684
- }
685
- else {
686
- if (res.headers.get('X-Analog-Errors')) {
687
- res.json().then((errors) => {
688
- this.onError.emit(errors);
689
- this.state.emit('error');
690
- });
691
- }
692
- else {
693
- this.state.emit('error');
694
- }
695
- }
696
- })
697
- .catch((_) => {
698
- this.state.emit('error');
699
- });
700
- }
701
- _getPath() {
702
- if (this.route) {
703
- return injectRouteEndpointURL(this.route.snapshot).pathname;
704
- }
705
- return `/api/_analog/pages${window.location.pathname}`;
706
- }
707
- _isJSON(contentType) {
708
- const mime = contentType ? contentType.split(';') : [];
709
- const essence = mime[0];
710
- return essence === 'application/json';
711
- }
712
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: FormAction, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
713
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.1", type: FormAction, isStandalone: true, selector: "form[action],form[method]", inputs: { action: { classPropertyName: "action", publicName: "action", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSuccess: "onSuccess", onError: "onError", state: "state" }, host: { listeners: { "submit": "submitted($event)" } }, ngImport: i0 }); }
714
- }
715
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: FormAction, decorators: [{
716
- type: Directive,
717
- args: [{
718
- selector: 'form[action],form[method]',
719
- host: {
720
- '(submit)': `submitted($event)`,
721
- },
722
- standalone: true,
723
- }]
724
- }], propDecorators: { action: [{ type: i0.Input, args: [{ isSignal: true, alias: "action", required: false }] }], onSuccess: [{ type: i0.Output, args: ["onSuccess"] }], onError: [{ type: i0.Output, args: ["onError"] }], state: [{ type: i0.Output, args: ["state"] }] } });
725
-
726
- const DEBUG_ROUTES = new InjectionToken('@analogjs/router debug routes', {
727
- providedIn: 'root',
728
- factory() {
729
- const debugRoutes = createRoutes({
730
- ...ANALOG_ROUTE_FILES,
731
- ...ANALOG_CONTENT_ROUTE_FILES,
732
- }, true);
733
- return debugRoutes;
734
- },
234
+ //#endregion
235
+ //#region packages/router/src/lib/form-action.directive.ts
236
+ var FormAction = class FormAction {
237
+ constructor() {
238
+ this.action = input("", ...[]);
239
+ this.onSuccess = output();
240
+ this.onError = output();
241
+ this.state = output();
242
+ this.router = inject(Router);
243
+ this.route = inject(ActivatedRoute);
244
+ this.currentState = signal("idle", ...[]);
245
+ /** Cached during construction (injection context) so inject() works. */
246
+ this._endpointUrl = this.route ? injectRouteEndpointURL(this.route.snapshot) : void 0;
247
+ }
248
+ submitted($event) {
249
+ $event.preventDefault();
250
+ const form = $event.target;
251
+ this._emitState("submitting");
252
+ const body = new FormData(form);
253
+ if (form.method.toUpperCase() === "GET") this._handleGet(body, this._getGetPath(form));
254
+ else this._handlePost(body, this._getPostPath(form), form.method);
255
+ }
256
+ _handleGet(body, path) {
257
+ const url = new URL(path, window.location.href);
258
+ const params = new URLSearchParams(url.search);
259
+ body.forEach((value, key) => {
260
+ params.append(key, value instanceof File ? value.name : value);
261
+ });
262
+ url.search = params.toString();
263
+ this._emitState("navigate");
264
+ this._navigateTo(url);
265
+ }
266
+ _handlePost(body, path, method) {
267
+ fetch(path, {
268
+ method,
269
+ body
270
+ }).then((res) => {
271
+ if (res.ok) if (res.redirected) {
272
+ this._emitState("redirect");
273
+ this._navigateTo(new URL(res.url, window.location.href));
274
+ } else if (this._isJSON(res.headers.get("Content-type"))) res.json().then((result) => {
275
+ this.onSuccess.emit(result);
276
+ this._emitState("success");
277
+ });
278
+ else res.text().then((result) => {
279
+ this.onSuccess.emit(result);
280
+ this._emitState("success");
281
+ });
282
+ else if (res.headers.get("X-Analog-Errors")) res.json().then((errors) => {
283
+ this.onError.emit(errors);
284
+ this._emitState("error");
285
+ });
286
+ else this._emitState("error");
287
+ }).catch((_) => {
288
+ this._emitState("error");
289
+ });
290
+ }
291
+ _getExplicitAction(form) {
292
+ return this.action().trim() || form.getAttribute("action")?.trim() || void 0;
293
+ }
294
+ _getGetPath(form) {
295
+ return this._getExplicitAction(form) ?? this.router.url;
296
+ }
297
+ _getPostPath(form) {
298
+ const explicitAction = this._getExplicitAction(form);
299
+ if (explicitAction) return new URL(explicitAction, window.location.href).toString();
300
+ if (this._endpointUrl) return this._endpointUrl.pathname;
301
+ return `/api/_analog/pages${window.location.pathname}`;
302
+ }
303
+ _emitState(state) {
304
+ this.currentState.set(state);
305
+ this.state.emit(state);
306
+ }
307
+ _navigateTo(url) {
308
+ if (url.origin === window.location.origin) {
309
+ this.router.navigateByUrl(`${url.pathname}${url.search}${url.hash}`, { onSameUrlNavigation: "reload" });
310
+ return;
311
+ }
312
+ window.location.assign(url.toString());
313
+ }
314
+ _isJSON(contentType) {
315
+ return (contentType ? contentType.split(";") : [])[0] === "application/json";
316
+ }
317
+ static {
318
+ this.ɵfac = i0.ɵɵngDeclareFactory({
319
+ minVersion: "12.0.0",
320
+ version: "21.1.1",
321
+ ngImport: i0,
322
+ type: FormAction,
323
+ deps: [],
324
+ target: i0.ɵɵFactoryTarget.Directive
325
+ });
326
+ }
327
+ static {
328
+ this.ɵdir = i0.ɵɵngDeclareDirective({
329
+ minVersion: "17.1.0",
330
+ version: "21.1.1",
331
+ type: FormAction,
332
+ isStandalone: true,
333
+ selector: "form[action],form[method]",
334
+ inputs: { action: {
335
+ classPropertyName: "action",
336
+ publicName: "action",
337
+ isSignal: true,
338
+ isRequired: false,
339
+ transformFunction: null
340
+ } },
341
+ outputs: {
342
+ onSuccess: "onSuccess",
343
+ onError: "onError",
344
+ state: "state"
345
+ },
346
+ host: {
347
+ listeners: { "submit": "submitted($event)" },
348
+ properties: {
349
+ "attr.data-state": "currentState()",
350
+ "attr.aria-busy": "currentState() === \"submitting\" ? \"true\" : null"
351
+ }
352
+ },
353
+ ngImport: i0
354
+ });
355
+ }
356
+ };
357
+ i0.ɵɵngDeclareClassMetadata({
358
+ minVersion: "12.0.0",
359
+ version: "21.1.1",
360
+ ngImport: i0,
361
+ type: FormAction,
362
+ decorators: [{
363
+ type: Directive,
364
+ args: [{
365
+ selector: "form[action],form[method]",
366
+ host: {
367
+ "(submit)": `submitted($event)`,
368
+ "[attr.data-state]": "currentState()",
369
+ "[attr.aria-busy]": "currentState() === \"submitting\" ? \"true\" : null"
370
+ },
371
+ standalone: true
372
+ }]
373
+ }],
374
+ propDecorators: {
375
+ action: [{
376
+ type: i0.Input,
377
+ args: [{
378
+ isSignal: true,
379
+ alias: "action",
380
+ required: false
381
+ }]
382
+ }],
383
+ onSuccess: [{
384
+ type: i0.Output,
385
+ args: ["onSuccess"]
386
+ }],
387
+ onError: [{
388
+ type: i0.Output,
389
+ args: ["onError"]
390
+ }],
391
+ state: [{
392
+ type: i0.Output,
393
+ args: ["state"]
394
+ }]
395
+ }
735
396
  });
736
- function injectDebugRoutes() {
737
- return inject(DEBUG_ROUTES);
738
- }
739
-
397
+ //#endregion
398
+ //#region packages/router/src/lib/debug/index.ts
740
399
  /**
741
- * Provides routes that provide additional
742
- * pages for displaying and debugging
743
- * routes.
744
- */
400
+ * Provides routes that provide additional
401
+ * pages for displaying and debugging
402
+ * routes.
403
+ */
745
404
  function withDebugRoutes() {
746
- const routes = [
747
- {
748
- path: '__analog/routes',
749
- loadComponent: () => import('./analogjs-router-debug.page-jzggTA45.mjs'),
750
- },
751
- ];
752
- return {
753
- ɵkind: 101,
754
- ɵproviders: [{ provide: ROUTES, useValue: routes, multi: true }],
755
- };
405
+ return {
406
+ ɵkind: 101,
407
+ ɵproviders: [{
408
+ provide: ROUTES,
409
+ useValue: [{
410
+ path: "__analog/routes",
411
+ loadComponent: () => import("./debug.page.mjs")
412
+ }],
413
+ multi: true
414
+ }]
415
+ };
756
416
  }
757
-
417
+ //#endregion
418
+ //#region packages/router/src/lib/server.component.ts
758
419
  /**
759
- * @description
760
- * Component that defines the bridge between the client and server-only
761
- * components. The component passes the component ID and props to the server
762
- * and retrieves the rendered HTML and outputs from the server-only component.
763
- *
764
- * Status: experimental
765
- */
766
- class ServerOnly {
767
- constructor() {
768
- this.component = input.required(...(ngDevMode ? [{ debugName: "component" }] : []));
769
- this.props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : []));
770
- this.outputs = output();
771
- this.http = inject(HttpClient);
772
- this.sanitizer = inject(DomSanitizer);
773
- this.content = signal('', ...(ngDevMode ? [{ debugName: "content" }] : []));
774
- this.route = inject(ActivatedRoute, { optional: true });
775
- this.baseURL = injectBaseURL();
776
- this.transferState = inject(TransferState);
777
- effect(() => {
778
- const routeComponentId = this.route?.snapshot.data['component'];
779
- const props = this.props() || {};
780
- const componentId = routeComponentId || this.component();
781
- const headers = new HttpHeaders(new Headers({
782
- 'Content-type': 'application/json',
783
- 'X-Analog-Component': componentId,
784
- }));
785
- const componentUrl = this.getComponentUrl(componentId);
786
- const httpRequest = new HttpRequest('POST', componentUrl, props, {
787
- headers,
788
- });
789
- const cacheKey = makeCacheKey(httpRequest, new URL(componentUrl).pathname);
790
- const storeKey = makeStateKey(cacheKey);
791
- const componentState = this.transferState.get(storeKey, null);
792
- if (componentState) {
793
- this.updateContent(componentState);
794
- this.transferState.remove(storeKey);
795
- }
796
- else {
797
- this.http
798
- .request(httpRequest)
799
- .pipe(map((response) => {
800
- if (response instanceof HttpResponse) {
801
- if (import.meta.env.SSR) {
802
- this.transferState.set(storeKey, response.body);
803
- }
804
- return response.body;
805
- }
806
- return throwError(() => ({}));
807
- }), catchError((error) => {
808
- console.log(error);
809
- return of({
810
- html: '',
811
- outputs: {},
812
- });
813
- }))
814
- .subscribe((content) => this.updateContent(content));
815
- }
816
- });
817
- }
818
- updateContent(content) {
819
- this.content.set(this.sanitizer.bypassSecurityTrustHtml(content.html));
820
- this.outputs.emit(content.outputs);
821
- }
822
- getComponentUrl(componentId) {
823
- let baseURL = this.baseURL;
824
- if (!baseURL && typeof window !== 'undefined') {
825
- baseURL = window.location.origin;
826
- }
827
- return `${baseURL}/_analog/components/${componentId}`;
828
- }
829
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: ServerOnly, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
830
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.1", type: ServerOnly, isStandalone: true, selector: "server-only,ServerOnly,Server", inputs: { component: { classPropertyName: "component", publicName: "component", isSignal: true, isRequired: true, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { outputs: "outputs" }, ngImport: i0, template: ` <div [innerHTML]="content()"></div> `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
831
- }
832
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: ServerOnly, decorators: [{
833
- type: Component,
834
- args: [{
835
- selector: 'server-only,ServerOnly,Server',
836
- changeDetection: ChangeDetectionStrategy.OnPush,
837
- template: ` <div [innerHTML]="content()"></div> `,
838
- }]
839
- }], ctorParameters: () => [], propDecorators: { component: [{ type: i0.Input, args: [{ isSignal: true, alias: "component", required: true }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], outputs: [{ type: i0.Output, args: ["outputs"] }] } });
840
-
841
- /**
842
- * Generated bundle index. Do not edit.
843
- */
420
+ * @description
421
+ * Component that defines the bridge between the client and server-only
422
+ * components. The component passes the component ID and props to the server
423
+ * and retrieves the rendered HTML and outputs from the server-only component.
424
+ *
425
+ * Status: experimental
426
+ */
427
+ var ServerOnly = class ServerOnly {
428
+ constructor() {
429
+ this.component = input.required(...[]);
430
+ this.props = input(...[]);
431
+ this.outputs = output();
432
+ this.http = inject(HttpClient);
433
+ this.sanitizer = inject(DomSanitizer);
434
+ this.content = signal("", ...[]);
435
+ this.route = inject(ActivatedRoute, { optional: true });
436
+ this.baseURL = injectBaseURL();
437
+ this.transferState = inject(TransferState);
438
+ effect(() => {
439
+ const routeComponentId = this.route?.snapshot.data["component"];
440
+ const props = this.props() || {};
441
+ const componentId = routeComponentId || this.component();
442
+ const headers = new HttpHeaders(new Headers({
443
+ "Content-type": "application/json",
444
+ "X-Analog-Component": componentId
445
+ }));
446
+ const componentUrl = this.getComponentUrl(componentId);
447
+ const httpRequest = new HttpRequest("POST", componentUrl, props, { headers });
448
+ const storeKey = makeStateKey(makeCacheKey(httpRequest, new URL(componentUrl).pathname));
449
+ const componentState = this.transferState.get(storeKey, null);
450
+ if (componentState) {
451
+ this.updateContent(componentState);
452
+ this.transferState.remove(storeKey);
453
+ } else this.http.request(httpRequest).pipe(map((response) => {
454
+ if (response instanceof HttpResponse) return response.body;
455
+ return throwError(() => ({}));
456
+ }), catchError((error) => {
457
+ console.log(error);
458
+ return of({
459
+ html: "",
460
+ outputs: {}
461
+ });
462
+ })).subscribe((content) => this.updateContent(content));
463
+ });
464
+ }
465
+ updateContent(content) {
466
+ this.content.set(this.sanitizer.bypassSecurityTrustHtml(content.html));
467
+ this.outputs.emit(content.outputs);
468
+ }
469
+ getComponentUrl(componentId) {
470
+ let baseURL = this.baseURL;
471
+ if (!baseURL && typeof window !== "undefined") baseURL = window.location.origin;
472
+ return `${baseURL}/_analog/components/${componentId}`;
473
+ }
474
+ static {
475
+ this.ɵfac = i0.ɵɵngDeclareFactory({
476
+ minVersion: "12.0.0",
477
+ version: "21.1.1",
478
+ ngImport: i0,
479
+ type: ServerOnly,
480
+ deps: [],
481
+ target: i0.ɵɵFactoryTarget.Component
482
+ });
483
+ }
484
+ static {
485
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
486
+ minVersion: "17.1.0",
487
+ version: "21.1.1",
488
+ type: ServerOnly,
489
+ isStandalone: true,
490
+ selector: "server-only,ServerOnly,Server",
491
+ inputs: {
492
+ component: {
493
+ classPropertyName: "component",
494
+ publicName: "component",
495
+ isSignal: true,
496
+ isRequired: true,
497
+ transformFunction: null
498
+ },
499
+ props: {
500
+ classPropertyName: "props",
501
+ publicName: "props",
502
+ isSignal: true,
503
+ isRequired: false,
504
+ transformFunction: null
505
+ }
506
+ },
507
+ outputs: { outputs: "outputs" },
508
+ ngImport: i0,
509
+ template: ` <div [innerHTML]="content()"></div> `,
510
+ isInline: true,
511
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
512
+ });
513
+ }
514
+ };
515
+ i0.ɵɵngDeclareClassMetadata({
516
+ minVersion: "12.0.0",
517
+ version: "21.1.1",
518
+ ngImport: i0,
519
+ type: ServerOnly,
520
+ decorators: [{
521
+ type: Component,
522
+ args: [{
523
+ selector: "server-only,ServerOnly,Server",
524
+ changeDetection: ChangeDetectionStrategy.OnPush,
525
+ template: ` <div [innerHTML]="content()"></div> `
526
+ }]
527
+ }],
528
+ ctorParameters: () => [],
529
+ propDecorators: {
530
+ component: [{
531
+ type: i0.Input,
532
+ args: [{
533
+ isSignal: true,
534
+ alias: "component",
535
+ required: true
536
+ }]
537
+ }],
538
+ props: [{
539
+ type: i0.Input,
540
+ args: [{
541
+ isSignal: true,
542
+ alias: "props",
543
+ required: false
544
+ }]
545
+ }],
546
+ outputs: [{
547
+ type: i0.Output,
548
+ args: ["outputs"]
549
+ }]
550
+ }
551
+ });
552
+ //#endregion
553
+ export { FormAction, ServerOnly, createRoutes, defineRouteMeta, getLoadResolver, injectActivatedRoute, injectDebugRoutes, injectLoad, injectLoadData, injectRouteEndpointURL, injectRouter, provideFileRouter, requestContextInterceptor, routes, withDebugRoutes, withExtraRoutes };
844
554
 
845
- export { FormAction, ServerOnly, createRoutes, defineRouteMeta, getLoadResolver, injectActivatedRoute, injectDebugRoutes, injectLoad, injectRouteEndpointURL, injectRouter, provideFileRouter, requestContextInterceptor, routes, withDebugRoutes, withExtraRoutes };
846
- //# sourceMappingURL=analogjs-router.mjs.map
555
+ //# sourceMappingURL=analogjs-router.mjs.map