@analogjs/router 3.0.0-alpha.2 → 3.0.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/analogjs-router-server-actions.mjs +20 -32
- package/fesm2022/analogjs-router-server.mjs +151 -199
- package/fesm2022/analogjs-router-tokens.mjs +15 -18
- package/fesm2022/analogjs-router.mjs +481 -820
- package/fesm2022/debug.page.mjs +121 -0
- package/fesm2022/routes.mjs +301 -0
- package/package.json +8 -8
- package/server/actions/package.json +4 -0
- package/server/package.json +4 -0
- package/tokens/package.json +4 -0
- package/types/server/actions/src/actions.d.ts +13 -0
- package/types/server/actions/src/index.d.ts +1 -0
- package/types/server/src/index.d.ts +4 -0
- package/types/server/src/provide-server-context.d.ts +11 -0
- package/types/server/src/render.d.ts +12 -0
- package/types/server/src/server-component-render.d.ts +4 -0
- package/types/server/src/tokens.d.ts +7 -0
- package/types/src/index.d.ts +16 -0
- package/types/src/lib/cache-key.d.ts +3 -0
- package/types/src/lib/constants.d.ts +2 -0
- package/types/src/lib/cookie-interceptor.d.ts +4 -0
- package/types/src/lib/debug/debug.page.d.ts +18 -0
- package/types/src/lib/debug/index.d.ts +10 -0
- package/types/src/lib/debug/routes.d.ts +10 -0
- package/types/src/lib/define-route.d.ts +46 -0
- package/types/src/lib/endpoints.d.ts +5 -0
- package/types/src/lib/form-action.directive.d.ts +18 -0
- package/types/src/lib/get-load-resolver.d.ts +8 -0
- package/types/src/lib/inject-load.d.ts +6 -0
- package/types/src/lib/inject-route-endpoint-url.d.ts +2 -0
- package/types/src/lib/markdown-helpers.d.ts +2 -0
- package/types/src/lib/meta-tags.d.ts +33 -0
- package/types/src/lib/models.d.ts +29 -0
- package/types/src/lib/provide-file-router.d.ts +18 -0
- package/types/src/lib/request-context.d.ts +13 -0
- package/types/src/lib/route-config.d.ts +2 -0
- package/types/src/lib/route-types.d.ts +11 -0
- package/types/src/lib/routes.d.ts +19 -0
- package/types/src/lib/server.component.d.ts +33 -0
- package/types/tokens/src/index.d.ts +23 -0
- package/fesm2022/analogjs-router-debug.page-jzggTA45.mjs +0 -91
- package/fesm2022/analogjs-router-debug.page-jzggTA45.mjs.map +0 -1
- package/fesm2022/analogjs-router-server-actions.mjs.map +0 -1
- package/fesm2022/analogjs-router-server.mjs.map +0 -1
- package/fesm2022/analogjs-router-tokens.mjs.map +0 -1
- package/fesm2022/analogjs-router.mjs.map +0 -1
- package/types/analogjs-router-server-actions.d.ts +0 -17
- package/types/analogjs-router-server.d.ts +0 -29
- package/types/analogjs-router-tokens.d.ts +0 -27
- package/types/analogjs-router.d.ts +0 -269
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { t as injectDebugRoutes } from "./routes.mjs";
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
import { Component } from "@angular/core";
|
|
4
|
+
//#region packages/router/src/lib/debug/debug.page.ts
|
|
5
|
+
var DebugRoutesComponent = class DebugRoutesComponent {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.collectedRoutes = [];
|
|
8
|
+
this.debugRoutes = injectDebugRoutes();
|
|
9
|
+
}
|
|
10
|
+
ngOnInit() {
|
|
11
|
+
this.traverseRoutes(this.debugRoutes);
|
|
12
|
+
}
|
|
13
|
+
traverseRoutes(routes, parent) {
|
|
14
|
+
routes.forEach((route) => {
|
|
15
|
+
this.collectedRoutes.push({
|
|
16
|
+
path: route.isLayout ? `${parent ? `/${parent}` : ""}${route.path ? `/${route.path}` : ""}` : `${parent ? `/${parent}` : ""}${route.path ? `/${route.path}` : "/"}`,
|
|
17
|
+
filename: route.filename,
|
|
18
|
+
file: route.filename?.replace(/(^.*)pages\//, "") || "",
|
|
19
|
+
isLayout: route.isLayout
|
|
20
|
+
});
|
|
21
|
+
if (route.children) {
|
|
22
|
+
const fullParentPath = [parent, route.path].filter((s) => !!s).join("/");
|
|
23
|
+
this.traverseRoutes(route.children, fullParentPath);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
static {
|
|
28
|
+
this.ɵfac = i0.ɵɵngDeclareFactory({
|
|
29
|
+
minVersion: "12.0.0",
|
|
30
|
+
version: "21.1.1",
|
|
31
|
+
ngImport: i0,
|
|
32
|
+
type: DebugRoutesComponent,
|
|
33
|
+
deps: [],
|
|
34
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
static {
|
|
38
|
+
this.ɵcmp = i0.ɵɵngDeclareComponent({
|
|
39
|
+
minVersion: "17.0.0",
|
|
40
|
+
version: "21.1.1",
|
|
41
|
+
type: DebugRoutesComponent,
|
|
42
|
+
isStandalone: true,
|
|
43
|
+
selector: "analogjs-debug-routes-page",
|
|
44
|
+
ngImport: i0,
|
|
45
|
+
template: `
|
|
46
|
+
<h2>Routes</h2>
|
|
47
|
+
|
|
48
|
+
<div class="table-container">
|
|
49
|
+
<div class="table-header">
|
|
50
|
+
<div class="header-cell">Route Path</div>
|
|
51
|
+
<div class="header-cell">File</div>
|
|
52
|
+
<div class="header-cell">Type</div>
|
|
53
|
+
</div>
|
|
54
|
+
<div class="table-body">
|
|
55
|
+
@for (
|
|
56
|
+
collectedRoute of collectedRoutes;
|
|
57
|
+
track collectedRoute.filename
|
|
58
|
+
) {
|
|
59
|
+
<div class="table-row">
|
|
60
|
+
<div class="table-cell">{{ collectedRoute.path }}</div>
|
|
61
|
+
<div class="table-cell" [title]="collectedRoute.filename">
|
|
62
|
+
{{ collectedRoute.file }}
|
|
63
|
+
</div>
|
|
64
|
+
<div class="table-cell">
|
|
65
|
+
{{ collectedRoute.isLayout ? 'Layout' : 'Page' }}
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
}
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
`,
|
|
72
|
+
isInline: true,
|
|
73
|
+
styles: ["\n :host {\n width: 100%;\n }\n\n .table-container {\n width: 100%;\n max-width: 900px;\n margin: 0 auto;\n background: white;\n border-radius: 8px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n overflow: hidden;\n }\n\n .table-header {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n background: gray;\n border-bottom: 2px solid #e5e7eb;\n }\n\n .header-cell {\n padding: 16px 24px;\n font-weight: 600;\n text-transform: uppercase;\n font-size: 14px;\n letter-spacing: 0.05em;\n color: white;\n }\n\n .table-body {\n display: flex;\n flex-direction: column;\n }\n\n .table-row {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n border-bottom: 1px solid #e5e7eb;\n transition: background-color 0.2s ease;\n }\n\n .table-row:last-child {\n border-bottom: none;\n }\n\n .table-row:hover {\n background-color: #f9fafb;\n }\n\n .table-cell {\n padding: 16px 24px;\n font-size: 16px;\n color: #4b5563;\n }\n\n @media (max-width: 640px) {\n .table-container {\n border-radius: 0;\n margin: 0;\n }\n\n .header-cell,\n .table-cell {\n padding: 12px 16px;\n }\n }\n "]
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
78
|
+
minVersion: "12.0.0",
|
|
79
|
+
version: "21.1.1",
|
|
80
|
+
ngImport: i0,
|
|
81
|
+
type: DebugRoutesComponent,
|
|
82
|
+
decorators: [{
|
|
83
|
+
type: Component,
|
|
84
|
+
args: [{
|
|
85
|
+
selector: "analogjs-debug-routes-page",
|
|
86
|
+
standalone: true,
|
|
87
|
+
template: `
|
|
88
|
+
<h2>Routes</h2>
|
|
89
|
+
|
|
90
|
+
<div class="table-container">
|
|
91
|
+
<div class="table-header">
|
|
92
|
+
<div class="header-cell">Route Path</div>
|
|
93
|
+
<div class="header-cell">File</div>
|
|
94
|
+
<div class="header-cell">Type</div>
|
|
95
|
+
</div>
|
|
96
|
+
<div class="table-body">
|
|
97
|
+
@for (
|
|
98
|
+
collectedRoute of collectedRoutes;
|
|
99
|
+
track collectedRoute.filename
|
|
100
|
+
) {
|
|
101
|
+
<div class="table-row">
|
|
102
|
+
<div class="table-cell">{{ collectedRoute.path }}</div>
|
|
103
|
+
<div class="table-cell" [title]="collectedRoute.filename">
|
|
104
|
+
{{ collectedRoute.file }}
|
|
105
|
+
</div>
|
|
106
|
+
<div class="table-cell">
|
|
107
|
+
{{ collectedRoute.isLayout ? 'Layout' : 'Page' }}
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
}
|
|
111
|
+
</div>
|
|
112
|
+
</div>
|
|
113
|
+
`,
|
|
114
|
+
styles: ["\n :host {\n width: 100%;\n }\n\n .table-container {\n width: 100%;\n max-width: 900px;\n margin: 0 auto;\n background: white;\n border-radius: 8px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n overflow: hidden;\n }\n\n .table-header {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n background: gray;\n border-bottom: 2px solid #e5e7eb;\n }\n\n .header-cell {\n padding: 16px 24px;\n font-weight: 600;\n text-transform: uppercase;\n font-size: 14px;\n letter-spacing: 0.05em;\n color: white;\n }\n\n .table-body {\n display: flex;\n flex-direction: column;\n }\n\n .table-row {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n border-bottom: 1px solid #e5e7eb;\n transition: background-color 0.2s ease;\n }\n\n .table-row:last-child {\n border-bottom: none;\n }\n\n .table-row:hover {\n background-color: #f9fafb;\n }\n\n .table-cell {\n padding: 16px 24px;\n font-size: 16px;\n color: #4b5563;\n }\n\n @media (max-width: 640px) {\n .table-container {\n border-radius: 0;\n margin: 0;\n }\n\n .header-cell,\n .table-cell {\n padding: 12px 16px;\n }\n }\n "]
|
|
115
|
+
}]
|
|
116
|
+
}]
|
|
117
|
+
});
|
|
118
|
+
//#endregion
|
|
119
|
+
export { DebugRoutesComponent as default };
|
|
120
|
+
|
|
121
|
+
//# sourceMappingURL=debug.page.mjs.map
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import { NavigationEnd, Router, UrlSegment } from "@angular/router";
|
|
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
|
+
//#region packages/router/src/lib/routes.ts
|
|
141
|
+
/**
|
|
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
|
+
* A function used to parse list of files and create configuration of routes.
|
|
151
|
+
*
|
|
152
|
+
* @param files
|
|
153
|
+
* @returns Array of routes
|
|
154
|
+
*/
|
|
155
|
+
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");
|
|
208
|
+
}
|
|
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
|
+
});
|
|
284
|
+
//#endregion
|
|
285
|
+
//#region packages/router/src/lib/debug/routes.ts
|
|
286
|
+
var DEBUG_ROUTES = new InjectionToken("@analogjs/router debug routes", {
|
|
287
|
+
providedIn: "root",
|
|
288
|
+
factory() {
|
|
289
|
+
return createRoutes({
|
|
290
|
+
...ANALOG_ROUTE_FILES,
|
|
291
|
+
...ANALOG_CONTENT_ROUTE_FILES
|
|
292
|
+
}, true);
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
function injectDebugRoutes() {
|
|
296
|
+
return inject(DEBUG_ROUTES);
|
|
297
|
+
}
|
|
298
|
+
//#endregion
|
|
299
|
+
export { updateMetaTagsOnRouteChange as a, injectRouteEndpointURL as i, createRoutes as n, routes as r, injectDebugRoutes as t };
|
|
300
|
+
|
|
301
|
+
//# sourceMappingURL=routes.mjs.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@analogjs/router",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.3",
|
|
4
4
|
"description": "Filesystem-based routing for Angular",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Brandon Roberts <robertsbt@gmail.com>",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"url": "https://github.com/sponsors/brandonroberts"
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
|
-
"@analogjs/content": "^3.0.0-alpha.
|
|
27
|
+
"@analogjs/content": "^3.0.0-alpha.3",
|
|
28
28
|
"@angular/core": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0",
|
|
29
29
|
"@angular/router": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0"
|
|
30
30
|
},
|
|
@@ -48,27 +48,27 @@
|
|
|
48
48
|
"provenance": true
|
|
49
49
|
},
|
|
50
50
|
"module": "fesm2022/analogjs-router.mjs",
|
|
51
|
-
"typings": "types/
|
|
51
|
+
"typings": "types/src/index.d.ts",
|
|
52
52
|
"exports": {
|
|
53
53
|
"./package.json": {
|
|
54
54
|
"default": "./package.json"
|
|
55
55
|
},
|
|
56
56
|
".": {
|
|
57
|
-
"types": "./types/
|
|
57
|
+
"types": "./types/src/index.d.ts",
|
|
58
58
|
"default": "./fesm2022/analogjs-router.mjs"
|
|
59
59
|
},
|
|
60
60
|
"./server": {
|
|
61
|
-
"types": "./types/
|
|
61
|
+
"types": "./types/server/src/index.d.ts",
|
|
62
62
|
"default": "./fesm2022/analogjs-router-server.mjs"
|
|
63
63
|
},
|
|
64
64
|
"./server/actions": {
|
|
65
|
-
"types": "./types/
|
|
65
|
+
"types": "./types/server/actions/src/index.d.ts",
|
|
66
66
|
"default": "./fesm2022/analogjs-router-server-actions.mjs"
|
|
67
67
|
},
|
|
68
68
|
"./tokens": {
|
|
69
|
-
"types": "./types/
|
|
69
|
+
"types": "./types/tokens/src/index.d.ts",
|
|
70
70
|
"default": "./fesm2022/analogjs-router-tokens.mjs"
|
|
71
71
|
}
|
|
72
72
|
},
|
|
73
73
|
"sideEffects": false
|
|
74
|
-
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { H3Event, H3EventContext } from 'nitro/h3';
|
|
2
|
+
import type { $Fetch } from 'nitro/types';
|
|
3
|
+
import type { NodeContext } from '../../../src/lib/route-types.js';
|
|
4
|
+
export type PageServerAction = {
|
|
5
|
+
params: H3EventContext['params'];
|
|
6
|
+
req: NodeContext['req'];
|
|
7
|
+
res: NonNullable<NodeContext['res']>;
|
|
8
|
+
fetch: $Fetch;
|
|
9
|
+
event: H3Event;
|
|
10
|
+
};
|
|
11
|
+
export declare function fail<T = object>(status: number, errors: T): Response;
|
|
12
|
+
export declare function json<T = object>(data: T, config?: ResponseInit): Response;
|
|
13
|
+
export declare function redirect(url: string, config?: number | ResponseInit): Response;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PageServerAction, json, redirect, fail } from './actions';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { StaticProvider } from '@angular/core';
|
|
2
|
+
import { ServerInternalFetch, ServerRequest, ServerResponse } from '@analogjs/router/tokens';
|
|
3
|
+
export declare function provideServerContext({ req, res, fetch, }: {
|
|
4
|
+
req: ServerRequest;
|
|
5
|
+
res: ServerResponse;
|
|
6
|
+
fetch?: ServerInternalFetch;
|
|
7
|
+
}): StaticProvider[];
|
|
8
|
+
export declare function getBaseUrl(req: ServerRequest): string;
|
|
9
|
+
export declare function getRequestProtocol(req: ServerRequest, opts?: {
|
|
10
|
+
xForwardedProto?: boolean;
|
|
11
|
+
}): string;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ApplicationConfig, Provider, Type } from '@angular/core';
|
|
2
|
+
import type { ServerContext } from '@analogjs/router/tokens';
|
|
3
|
+
/**
|
|
4
|
+
* Returns a function that accepts the navigation URL,
|
|
5
|
+
* the root HTML, and server context.
|
|
6
|
+
*
|
|
7
|
+
* @param rootComponent
|
|
8
|
+
* @param config
|
|
9
|
+
* @param platformProviders
|
|
10
|
+
* @returns Promise<string | Reponse>
|
|
11
|
+
*/
|
|
12
|
+
export declare function render(rootComponent: Type<unknown>, config: ApplicationConfig, platformProviders?: Provider[]): (url: string, document: string, serverContext: ServerContext) => Promise<string | Response>;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ApplicationConfig } from '@angular/core';
|
|
2
|
+
import { ServerContext } from '@analogjs/router/tokens';
|
|
3
|
+
export declare function serverComponentRequest(serverContext: ServerContext): string | undefined;
|
|
4
|
+
export declare function renderServerComponent(url: string, serverContext: ServerContext, config?: ApplicationConfig): Promise<Response>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { InjectionToken, Provider } from '@angular/core';
|
|
2
|
+
export declare const STATIC_PROPS: InjectionToken<Record<string, any>>;
|
|
3
|
+
export declare function provideStaticProps<T = Record<string, any>>(props: T): Provider;
|
|
4
|
+
export declare function injectStaticProps(): Record<string, any>;
|
|
5
|
+
export declare function injectStaticOutputs<T>(): {
|
|
6
|
+
set(data: T): void;
|
|
7
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type { RouteExport } from './lib/models';
|
|
2
|
+
export type { Files } from './lib/routes';
|
|
3
|
+
export { routes, createRoutes } from './lib/routes';
|
|
4
|
+
export { defineRouteMeta, injectActivatedRoute, injectRouter, } from './lib/define-route';
|
|
5
|
+
export { RouteMeta } from './lib/models';
|
|
6
|
+
export { provideFileRouter, withExtraRoutes } from './lib/provide-file-router';
|
|
7
|
+
export { MetaTag } from './lib/meta-tags';
|
|
8
|
+
export { PageServerLoad, LoadResult } from './lib/route-types';
|
|
9
|
+
export { injectLoad } from './lib/inject-load';
|
|
10
|
+
export { getLoadResolver } from './lib/get-load-resolver';
|
|
11
|
+
export { requestContextInterceptor } from './lib/request-context';
|
|
12
|
+
export { injectRouteEndpointURL } from './lib/inject-route-endpoint-url';
|
|
13
|
+
export { FormAction } from './lib/form-action.directive';
|
|
14
|
+
export { injectDebugRoutes } from './lib/debug/routes';
|
|
15
|
+
export { withDebugRoutes } from './lib/debug';
|
|
16
|
+
export { ServerOnly } from './lib/server.component';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { HttpHandlerFn, HttpRequest, HttpEvent } from '@angular/common/http';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { ServerRequest } from '@analogjs/router/tokens';
|
|
4
|
+
export declare function cookieInterceptor(req: HttpRequest<unknown>, next: HttpHandlerFn, location?: object, serverRequest?: ServerRequest | null): Observable<HttpEvent<unknown>>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { OnInit } from '@angular/core';
|
|
2
|
+
import { DebugRoute } from './routes';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
type CollectedRoute = {
|
|
5
|
+
path: string;
|
|
6
|
+
filename: string;
|
|
7
|
+
file: string;
|
|
8
|
+
isLayout: boolean;
|
|
9
|
+
};
|
|
10
|
+
export default class DebugRoutesComponent implements OnInit {
|
|
11
|
+
collectedRoutes: CollectedRoute[];
|
|
12
|
+
debugRoutes: (import('@angular/router').Route & DebugRoute)[];
|
|
13
|
+
ngOnInit(): void;
|
|
14
|
+
traverseRoutes(routes: DebugRoute[], parent?: string): void;
|
|
15
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<DebugRoutesComponent, never>;
|
|
16
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<DebugRoutesComponent, "analogjs-debug-routes-page", never, {}, {}, never, never, true, never>;
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { EnvironmentProviders, Provider } from '@angular/core';
|
|
2
|
+
/**
|
|
3
|
+
* Provides routes that provide additional
|
|
4
|
+
* pages for displaying and debugging
|
|
5
|
+
* routes.
|
|
6
|
+
*/
|
|
7
|
+
export declare function withDebugRoutes(): {
|
|
8
|
+
ɵkind: number;
|
|
9
|
+
ɵproviders: (Provider | EnvironmentProviders)[];
|
|
10
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { InjectionToken } from '@angular/core';
|
|
2
|
+
import { Route } from '@angular/router';
|
|
3
|
+
export declare const DEBUG_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 injectDebugRoutes(): (Route & DebugRoute)[];
|