@analogjs/router 3.0.0-alpha.3 → 3.0.0-alpha.30
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/content/package.json +4 -0
- package/fesm2022/analogjs-router-content.mjs +63 -0
- package/fesm2022/analogjs-router-content.mjs.map +1 -0
- package/fesm2022/analogjs-router-server-actions.mjs +309 -1
- package/fesm2022/analogjs-router-server-actions.mjs.map +1 -0
- package/fesm2022/analogjs-router-server.mjs +2 -2
- package/fesm2022/analogjs-router-server.mjs.map +1 -0
- package/fesm2022/analogjs-router-tanstack-query-server.mjs +22 -0
- package/fesm2022/analogjs-router-tanstack-query-server.mjs.map +1 -0
- package/fesm2022/analogjs-router-tanstack-query.mjs +39 -0
- package/fesm2022/analogjs-router-tanstack-query.mjs.map +1 -0
- package/fesm2022/analogjs-router-tokens.mjs.map +1 -0
- package/fesm2022/analogjs-router.mjs +560 -62
- package/fesm2022/analogjs-router.mjs.map +1 -0
- package/fesm2022/debug.page.mjs +53 -31
- package/fesm2022/debug.page.mjs.map +1 -0
- package/fesm2022/provide-analog-query.mjs +23 -0
- package/fesm2022/provide-analog-query.mjs.map +1 -0
- package/fesm2022/route-files.mjs +362 -0
- package/fesm2022/route-files.mjs.map +1 -0
- package/fesm2022/routes.mjs +5 -278
- package/fesm2022/routes.mjs.map +1 -0
- package/package.json +71 -25
- package/tanstack-query/package.json +4 -0
- package/tanstack-query/server/package.json +4 -0
- package/types/content/src/index.d.ts +4 -0
- package/types/content/src/lib/debug/routes.d.ts +10 -0
- package/types/{src → content/src}/lib/markdown-helpers.d.ts +1 -1
- package/types/content/src/lib/routes.d.ts +8 -0
- package/types/content/src/lib/with-content-routes.d.ts +2 -0
- package/types/server/actions/src/define-action.d.ts +54 -0
- package/types/server/actions/src/define-api-route.d.ts +57 -0
- package/types/server/actions/src/define-page-load.d.ts +55 -0
- package/types/server/actions/src/define-server-route.d.ts +68 -0
- package/types/server/actions/src/index.d.ts +9 -1
- package/types/server/actions/src/parse-request-data.d.ts +9 -0
- package/types/server/actions/src/validate.d.ts +8 -0
- package/types/server/src/provide-server-context.d.ts +1 -1
- package/types/server/src/render.d.ts +1 -1
- package/types/server/src/server-component-render.d.ts +1 -1
- package/types/src/index.d.ts +16 -5
- package/types/src/lib/cache-key.d.ts +1 -1
- package/types/src/lib/cookie-interceptor.d.ts +1 -1
- package/types/src/lib/debug/debug.page.d.ts +4 -2
- package/types/src/lib/define-route.d.ts +6 -1
- package/types/src/lib/endpoints.d.ts +1 -1
- package/types/src/lib/experimental.d.ts +140 -0
- package/types/src/lib/form-action.directive.d.ts +12 -5
- package/types/src/lib/inject-load.d.ts +5 -2
- package/types/src/lib/inject-navigate.d.ts +23 -0
- package/types/src/lib/inject-route-context.d.ts +32 -0
- package/types/src/lib/inject-typed-params.d.ts +63 -0
- package/types/src/lib/json-ld.d.ts +32 -0
- package/types/src/lib/meta-tags.d.ts +3 -1
- package/types/src/lib/models.d.ts +3 -0
- package/types/src/lib/provide-file-router-base.d.ts +4 -0
- package/types/src/lib/provide-file-router.d.ts +2 -8
- package/types/src/lib/route-builder.d.ts +5 -0
- package/types/src/lib/route-files.d.ts +18 -0
- package/types/src/lib/route-path.d.ts +124 -0
- package/types/src/lib/route-types.d.ts +2 -1
- package/types/src/lib/routes.d.ts +2 -10
- package/types/src/lib/validation-errors.d.ts +7 -0
- package/types/tanstack-query/server/src/index.d.ts +1 -0
- package/types/tanstack-query/src/index.d.ts +2 -0
- package/types/tanstack-query/src/provide-analog-query.d.ts +4 -0
- package/types/tanstack-query/src/provide-server-analog-query.d.ts +2 -0
- package/types/tanstack-query/src/server-query.d.ts +16 -0
package/fesm2022/routes.mjs
CHANGED
|
@@ -1,301 +1,28 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
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"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,49 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@analogjs/router",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.30",
|
|
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
|
+
"./server": {
|
|
22
|
+
"types": "./types/server/src/index.d.ts",
|
|
23
|
+
"import": "./fesm2022/analogjs-router-server.mjs",
|
|
24
|
+
"default": "./fesm2022/analogjs-router-server.mjs"
|
|
25
|
+
},
|
|
26
|
+
"./server/actions": {
|
|
27
|
+
"types": "./types/server/actions/src/index.d.ts",
|
|
28
|
+
"import": "./fesm2022/analogjs-router-server-actions.mjs",
|
|
29
|
+
"default": "./fesm2022/analogjs-router-server-actions.mjs"
|
|
30
|
+
},
|
|
31
|
+
"./tanstack-query": {
|
|
32
|
+
"types": "./types/tanstack-query/src/index.d.ts",
|
|
33
|
+
"import": "./fesm2022/analogjs-router-tanstack-query.mjs",
|
|
34
|
+
"default": "./fesm2022/analogjs-router-tanstack-query.mjs"
|
|
35
|
+
},
|
|
36
|
+
"./tanstack-query/server": {
|
|
37
|
+
"types": "./types/tanstack-query/server/src/index.d.ts",
|
|
38
|
+
"import": "./fesm2022/analogjs-router-tanstack-query-server.mjs",
|
|
39
|
+
"default": "./fesm2022/analogjs-router-tanstack-query-server.mjs"
|
|
40
|
+
},
|
|
41
|
+
"./tokens": {
|
|
42
|
+
"types": "./types/tokens/src/index.d.ts",
|
|
43
|
+
"import": "./fesm2022/analogjs-router-tokens.mjs",
|
|
44
|
+
"default": "./fesm2022/analogjs-router-tokens.mjs"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
7
47
|
"keywords": [
|
|
8
48
|
"angular",
|
|
9
49
|
"router",
|
|
@@ -24,12 +64,39 @@
|
|
|
24
64
|
"url": "https://github.com/sponsors/brandonroberts"
|
|
25
65
|
},
|
|
26
66
|
"peerDependencies": {
|
|
27
|
-
"@analogjs/content": "
|
|
67
|
+
"@analogjs/content": "3.0.0-alpha.30",
|
|
68
|
+
"@standard-schema/spec": "^1.1.0",
|
|
28
69
|
"@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/
|
|
70
|
+
"@angular/platform-server": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0",
|
|
71
|
+
"@angular/router": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0",
|
|
72
|
+
"@tanstack/angular-query-experimental": ">=5.95.0",
|
|
73
|
+
"schema-dts": "^2.0.0"
|
|
74
|
+
},
|
|
75
|
+
"peerDependenciesMeta": {
|
|
76
|
+
"@analogjs/content": {
|
|
77
|
+
"optional": true
|
|
78
|
+
},
|
|
79
|
+
"@standard-schema/spec": {
|
|
80
|
+
"optional": true
|
|
81
|
+
},
|
|
82
|
+
"@angular/platform-server": {
|
|
83
|
+
"optional": true
|
|
84
|
+
},
|
|
85
|
+
"@tanstack/angular-query-experimental": {
|
|
86
|
+
"optional": true
|
|
87
|
+
},
|
|
88
|
+
"schema-dts": {
|
|
89
|
+
"optional": true
|
|
90
|
+
}
|
|
30
91
|
},
|
|
31
92
|
"dependencies": {
|
|
32
|
-
"
|
|
93
|
+
"@standard-schema/spec": "^1.1.0",
|
|
94
|
+
"es-toolkit": "^1.45.1",
|
|
95
|
+
"tslib": "^2.3.0"
|
|
96
|
+
},
|
|
97
|
+
"devDependencies": {
|
|
98
|
+
"@analogjs/vite-plugin-angular": "3.0.0-alpha.30",
|
|
99
|
+
"@analogjs/vitest-angular": "3.0.0-alpha.30"
|
|
33
100
|
},
|
|
34
101
|
"ng-update": {
|
|
35
102
|
"packageGroup": [
|
|
@@ -49,26 +116,5 @@
|
|
|
49
116
|
},
|
|
50
117
|
"module": "fesm2022/analogjs-router.mjs",
|
|
51
118
|
"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
119
|
"sideEffects": false
|
|
74
120
|
}
|
|
@@ -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 '
|
|
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,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 {};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
+
import type { H3Event } from 'nitro/h3';
|
|
3
|
+
export type DefineApiRouteResult = Response | unknown;
|
|
4
|
+
type OptionalSchema = StandardSchemaV1 | undefined;
|
|
5
|
+
type InferSchema<TSchema extends OptionalSchema, TFallback = unknown> = TSchema extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TSchema> : TFallback;
|
|
6
|
+
type ResolveDataSchema<TInput extends OptionalSchema, TQuery extends OptionalSchema, TBody extends OptionalSchema> = TInput extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TInput> : TQuery extends StandardSchemaV1 ? TBody extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TQuery> | StandardSchemaV1.InferOutput<TBody> : StandardSchemaV1.InferOutput<TQuery> : TBody extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TBody> : unknown;
|
|
7
|
+
export interface DefineApiRouteContext<TInput extends StandardSchemaV1 | undefined = undefined, TQuery extends StandardSchemaV1 | undefined = undefined, TBody extends StandardSchemaV1 | undefined = undefined, TParams extends StandardSchemaV1 | undefined = undefined> {
|
|
8
|
+
data: ResolveDataSchema<TInput, TQuery, TBody>;
|
|
9
|
+
query: InferSchema<TQuery, undefined>;
|
|
10
|
+
body: InferSchema<TBody, undefined>;
|
|
11
|
+
params: InferSchema<TParams, H3Event['context']['params']>;
|
|
12
|
+
event: H3Event;
|
|
13
|
+
}
|
|
14
|
+
export interface DefineApiRouteOptions<TInput extends StandardSchemaV1 | undefined = undefined, TOutput extends StandardSchemaV1 | undefined = undefined, TQuery extends StandardSchemaV1 | undefined = undefined, TBody extends StandardSchemaV1 | undefined = undefined, TParams extends StandardSchemaV1 | undefined = undefined, TResult extends DefineApiRouteResult = DefineApiRouteResult> {
|
|
15
|
+
input?: TInput;
|
|
16
|
+
query?: TQuery;
|
|
17
|
+
body?: TBody;
|
|
18
|
+
params?: TParams;
|
|
19
|
+
output?: TOutput;
|
|
20
|
+
handler: (context: DefineApiRouteContext<TInput, TQuery, TBody, TParams>) => Promise<TResult> | TResult;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Creates an h3-compatible event handler with Standard Schema validation.
|
|
24
|
+
*
|
|
25
|
+
* - `input` schema validates the request body (POST/PUT/PATCH) or query
|
|
26
|
+
* params (GET). Returns 422 with `StandardSchemaV1.Issue[]` on failure.
|
|
27
|
+
* - `output` schema validates the response in development only (stripped
|
|
28
|
+
* in production for zero overhead). Logs a warning on mismatch.
|
|
29
|
+
* - Plain return values are serialized with `json(...)`; raw `Response`
|
|
30
|
+
* objects are returned unchanged.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* import { defineApiRoute } from '@analogjs/router/server/actions';
|
|
35
|
+
* import * as v from 'valibot';
|
|
36
|
+
*
|
|
37
|
+
* const Input = v.object({
|
|
38
|
+
* name: v.pipe(v.string(), v.minLength(1)),
|
|
39
|
+
* email: v.pipe(v.string(), v.email()),
|
|
40
|
+
* });
|
|
41
|
+
* const Output = v.object({
|
|
42
|
+
* id: v.string(),
|
|
43
|
+
* name: v.string(),
|
|
44
|
+
* });
|
|
45
|
+
*
|
|
46
|
+
* export default defineApiRoute({
|
|
47
|
+
* input: Input,
|
|
48
|
+
* output: Output,
|
|
49
|
+
* handler: async ({ data }) => {
|
|
50
|
+
* const user = await db.users.create(data);
|
|
51
|
+
* return user;
|
|
52
|
+
* },
|
|
53
|
+
* });
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export declare function defineApiRoute<TInput extends StandardSchemaV1 | undefined = undefined, TOutput extends StandardSchemaV1 | undefined = undefined, TQuery extends StandardSchemaV1 | undefined = undefined, TBody extends StandardSchemaV1 | undefined = undefined, TParams extends StandardSchemaV1 | undefined = undefined, TResult extends DefineApiRouteResult = DefineApiRouteResult>(options: DefineApiRouteOptions<TInput, TOutput, TQuery, TBody, TParams, TResult>): (event: H3Event) => Promise<Response>;
|
|
57
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
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 PageLoadContext<TParamsSchema extends OptionalSchema = undefined, TQuerySchema extends OptionalSchema = undefined> {
|
|
8
|
+
params: InferSchema<TParamsSchema, H3EventContext['params']>;
|
|
9
|
+
query: InferSchema<TQuerySchema, Record<string, string | string[] | undefined>>;
|
|
10
|
+
req: NodeContext['req'];
|
|
11
|
+
res: NonNullable<NodeContext['res']>;
|
|
12
|
+
fetch: $Fetch;
|
|
13
|
+
event: H3Event;
|
|
14
|
+
}
|
|
15
|
+
export interface DefinePageLoadOptions<TParamsSchema extends OptionalSchema = undefined, TQuerySchema extends OptionalSchema = undefined, TResult = unknown> {
|
|
16
|
+
params?: TParamsSchema;
|
|
17
|
+
query?: TQuerySchema;
|
|
18
|
+
handler: (context: PageLoadContext<TParamsSchema, TQuerySchema>) => Promise<TResult> | TResult;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Creates a typed page server load function with optional
|
|
22
|
+
* Standard Schema validation for route params and query.
|
|
23
|
+
*
|
|
24
|
+
* Follows the same validation patterns as `defineAction` and
|
|
25
|
+
* `defineServerRoute`: validates before invoking the handler,
|
|
26
|
+
* returns `fail(422, issues)` on validation failure.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* // src/app/pages/users/[id].server.ts
|
|
31
|
+
* import { definePageLoad } from '@analogjs/router/server/actions';
|
|
32
|
+
* import * as v from 'valibot';
|
|
33
|
+
*
|
|
34
|
+
* export const routeParamsSchema = v.object({
|
|
35
|
+
* id: v.pipe(v.string(), v.regex(/^\d+$/)),
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
38
|
+
* export const load = definePageLoad({
|
|
39
|
+
* params: routeParamsSchema,
|
|
40
|
+
* handler: async ({ params, fetch }) => {
|
|
41
|
+
* // params.id is typed as string (validated)
|
|
42
|
+
* const user = await fetch(`/api/users/${params.id}`);
|
|
43
|
+
* return user;
|
|
44
|
+
* },
|
|
45
|
+
* });
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare function definePageLoad<TParamsSchema extends OptionalSchema = undefined, TQuerySchema extends OptionalSchema = undefined, TResult = unknown>(options: DefinePageLoadOptions<TParamsSchema, TQuerySchema, TResult>): (ctx: {
|
|
49
|
+
params: H3EventContext['params'];
|
|
50
|
+
req: NodeContext['req'];
|
|
51
|
+
res: NonNullable<NodeContext['res']>;
|
|
52
|
+
fetch: $Fetch;
|
|
53
|
+
event: H3Event;
|
|
54
|
+
}) => Promise<TResult | Response>;
|
|
55
|
+
export {};
|