@analogjs/router 0.1.0-alpha.0
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/LICENSE +25 -0
- package/README.md +245 -0
- package/esm2020/analogjs-router.mjs +5 -0
- package/esm2020/index.mjs +4 -0
- package/esm2020/lib/define-route.mjs +48 -0
- package/esm2020/lib/provide-file-routes.mjs +14 -0
- package/esm2020/lib/routes.mjs +110 -0
- package/fesm2015/analogjs-router.mjs +161 -0
- package/fesm2015/analogjs-router.mjs.map +1 -0
- package/fesm2020/analogjs-router.mjs +176 -0
- package/fesm2020/analogjs-router.mjs.map +1 -0
- package/index.d.ts +3 -0
- package/lib/define-route.d.ts +43 -0
- package/lib/provide-file-routes.d.ts +10 -0
- package/lib/routes.d.ts +16 -0
- package/package.json +48 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022-present, Brandon Roberts
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
Credit for original source code adapted from generouted:
|
|
24
|
+
|
|
25
|
+
https://github.com/oedotme/generouted
|
package/README.md
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# @analogjs/router
|
|
2
|
+
|
|
3
|
+
A filesystem-based router for Angular that allows you to configure routing using Angular component files.
|
|
4
|
+
|
|
5
|
+
## Preqrequisites
|
|
6
|
+
|
|
7
|
+
This package:
|
|
8
|
+
|
|
9
|
+
- Only supports using standalone Angular components as routes.
|
|
10
|
+
- Requires usage inside of an **Analog** project, and is not compatible with Webpack-based setups.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
The Analog Router is included when generating a new Analog project. To install the router manually, use your package manager of choice:
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
npm install @analogjs/router
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
or
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
yarn add @analogjs/router
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Setup
|
|
27
|
+
|
|
28
|
+
Import the `provideFileRouter` function from the `@analogjs/router` package and add it to the `providers` array of the `bootstrapApplication` function in an Angular application bootstrapping a standalone component.
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import { bootstrapApplication } from '@angular/platform-browser';
|
|
32
|
+
import { provideFileRouter } from '@analogjs/router';
|
|
33
|
+
|
|
34
|
+
import { AppComponent } from './app/app.component';
|
|
35
|
+
|
|
36
|
+
bootstrapApplication(AppComponent, {
|
|
37
|
+
providers: [provideFileRouter()],
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
This registers the Angular Router, along with the routes generated from the file structure.
|
|
42
|
+
|
|
43
|
+
## Defining Routes
|
|
44
|
+
|
|
45
|
+
Routes are defined using folders and files in the `src/app/routes` folder.
|
|
46
|
+
|
|
47
|
+
> Route components **must** be defined as the default export.
|
|
48
|
+
|
|
49
|
+
There are 4 primary types of routes:
|
|
50
|
+
|
|
51
|
+
- [Static Routes](#static-routes)
|
|
52
|
+
- [Dynamic Routes](#dynamic-routes)
|
|
53
|
+
- [Nested Routes](#nested-routes)
|
|
54
|
+
- [Catch-all Routes](#catch-all-routes)
|
|
55
|
+
|
|
56
|
+
These routes can be combined in different ways to build to URLs for navigation.
|
|
57
|
+
|
|
58
|
+
### Static Routes
|
|
59
|
+
|
|
60
|
+
Static routes are defined by using the filename as the route path.
|
|
61
|
+
|
|
62
|
+
The example route below in `src/app/routes/about.ts` defines an `/about` route.
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
import { Component } from '@angular/core';
|
|
66
|
+
|
|
67
|
+
@Component({
|
|
68
|
+
selector: 'app-about',
|
|
69
|
+
standalone: true,
|
|
70
|
+
template: `
|
|
71
|
+
<h2>Hello Analog</h2>
|
|
72
|
+
|
|
73
|
+
Analog is a meta-framework on top of Angular.
|
|
74
|
+
`,
|
|
75
|
+
})
|
|
76
|
+
export default class AboutPageComponent {}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Dynamic Routes
|
|
80
|
+
|
|
81
|
+
Dynamic routes are defined by using the filename as the route path enclosed in square brackets. Dynamic routes must be placed inside a parent folder, or prefixed with a parent path and a period.
|
|
82
|
+
|
|
83
|
+
The parameter for the route is extracted from the route path.
|
|
84
|
+
|
|
85
|
+
The example route below in `src/app/routes/produtcs.[productId].ts` defines a `/products/:productId` route.
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
import { Component } from '@angular/core';
|
|
89
|
+
import { AsyncPipe, JsonPipe } from '@angular/common';
|
|
90
|
+
import { injectActivatedRoute } from '@analogjs/router';
|
|
91
|
+
import { map } from 'rxjs';
|
|
92
|
+
|
|
93
|
+
@Component({
|
|
94
|
+
selector: 'app-product-details',
|
|
95
|
+
standalone: true,
|
|
96
|
+
imports: [AsyncPipe, JsonPipe],
|
|
97
|
+
template: `
|
|
98
|
+
<h2>Product Details</h2>
|
|
99
|
+
|
|
100
|
+
ID: {{ productId$ | async }}
|
|
101
|
+
`,
|
|
102
|
+
})
|
|
103
|
+
export default class ProductDetailsPageComponent {
|
|
104
|
+
private readonly route = injectActivatedRoute();
|
|
105
|
+
|
|
106
|
+
readonly productId$ = this.route.paramMap.pipe(
|
|
107
|
+
map((params) => params.get('productId'))
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Nested Routes
|
|
113
|
+
|
|
114
|
+
Nested routes are defined by using a parent file and child folder with routes.
|
|
115
|
+
|
|
116
|
+
The following structure below represents a nested route.
|
|
117
|
+
|
|
118
|
+
```treeview
|
|
119
|
+
src/
|
|
120
|
+
└── app/
|
|
121
|
+
└── routes/
|
|
122
|
+
│ └── products/
|
|
123
|
+
│ ├──[productId].ts
|
|
124
|
+
│ └──index.ts
|
|
125
|
+
└── products.ts
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
This defines two routes with a shared layout:
|
|
129
|
+
|
|
130
|
+
- `/products`
|
|
131
|
+
- `/products/:productId`
|
|
132
|
+
|
|
133
|
+
The parent `src/app/routes/products.ts` file contains the parent page with a router outlet.
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
import { Component } from '@angular/core';
|
|
137
|
+
import { RouterOutlet } from '@angular/router';
|
|
138
|
+
|
|
139
|
+
@Component({
|
|
140
|
+
selector: 'app-products',
|
|
141
|
+
standalone: true,
|
|
142
|
+
imports: [RouterOutlet],
|
|
143
|
+
template: `
|
|
144
|
+
<h2>Products</h2>
|
|
145
|
+
|
|
146
|
+
<router-outlet></router-outlet>
|
|
147
|
+
`,
|
|
148
|
+
})
|
|
149
|
+
export default class ProductsComponent {}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
The nested `src/app/routes/products/index.ts` file contains the `/products` list page.
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
import { Component } from '@angular/core';
|
|
156
|
+
import { RouterOutlet } from '@angular/router';
|
|
157
|
+
|
|
158
|
+
@Component({
|
|
159
|
+
selector: 'app-products-list',
|
|
160
|
+
standalone: true,
|
|
161
|
+
imports: [RouterOutlet],
|
|
162
|
+
template: ` <h2>Products List</h2> `,
|
|
163
|
+
})
|
|
164
|
+
export default class ProductsListComponent {}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
The nested `src/app/routes/products/[productId].ts` file contains the `/products/:productId` details page.
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
import { Component } from '@angular/core';
|
|
171
|
+
import { AsyncPipe, JsonPipe } from '@angular/common';
|
|
172
|
+
import { injectActivatedRoute } from '@analogjs/router';
|
|
173
|
+
import { map } from 'rxjs';
|
|
174
|
+
|
|
175
|
+
@Component({
|
|
176
|
+
selector: 'app-product-details',
|
|
177
|
+
standalone: true,
|
|
178
|
+
imports: [AsyncPipe, JsonPipe],
|
|
179
|
+
template: `
|
|
180
|
+
<h2>Product Details</h2>
|
|
181
|
+
|
|
182
|
+
ID: {{ productId$ | async }}
|
|
183
|
+
`,
|
|
184
|
+
})
|
|
185
|
+
export default class ProductDetailsPageComponent {
|
|
186
|
+
private readonly route = injectActivatedRoute();
|
|
187
|
+
|
|
188
|
+
readonly productId$ = this.route.paramMap.pipe(
|
|
189
|
+
map((params) => params.get('productId'))
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Catch-all routes
|
|
195
|
+
|
|
196
|
+
Catch-all routes are defined by using the filename as the route path prefixed with 3 periods enclosed in square brackets.
|
|
197
|
+
|
|
198
|
+
The example route below in `src/app/routes/[...page-not-found].ts` defines a wildcard `**` route. This route is usually for 404 pages.
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
import { Component } from '@angular/core';
|
|
202
|
+
import { RouterLinkWithHref } from '@angular/router';
|
|
203
|
+
|
|
204
|
+
@Component({
|
|
205
|
+
selector: 'app-page-not-found',
|
|
206
|
+
standalone: true,
|
|
207
|
+
imports: [RouterLinkWithHref],
|
|
208
|
+
template: `
|
|
209
|
+
<h2>Page Not Found</h2>
|
|
210
|
+
|
|
211
|
+
<a routerLink="/">Go Back Home</a>
|
|
212
|
+
`,
|
|
213
|
+
})
|
|
214
|
+
export default class PageNotFoundComponent {}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Route Metadata
|
|
218
|
+
|
|
219
|
+
Additional metadata to add to the generated route config for each route can be done using the `defineRouteMeta` function. This is where you can define the page title, any necessary guards, resolvers, providers, and more.
|
|
220
|
+
|
|
221
|
+
```ts
|
|
222
|
+
import { Component } from '@angular/core';
|
|
223
|
+
import { defineRouteMeta } from '@analogjs/router';
|
|
224
|
+
|
|
225
|
+
import { AboutService } from './about.service';
|
|
226
|
+
|
|
227
|
+
export const routeMeta = defineRouteMeta({
|
|
228
|
+
title: 'About Analog',
|
|
229
|
+
canActivate: [() => true],
|
|
230
|
+
providers: [AboutService],
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
@Component({
|
|
234
|
+
selector: 'app-about',
|
|
235
|
+
standalone: true,
|
|
236
|
+
template: `
|
|
237
|
+
<h2>Hello Analog</h2>
|
|
238
|
+
|
|
239
|
+
Analog is a meta-framework on top of Angular.
|
|
240
|
+
`,
|
|
241
|
+
})
|
|
242
|
+
export default class AboutPageComponent {
|
|
243
|
+
private readonly service = inject(AboutService);
|
|
244
|
+
}
|
|
245
|
+
```
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generated bundle index. Do not edit.
|
|
3
|
+
*/
|
|
4
|
+
export * from './index';
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5hbG9nanMtcm91dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcGFja2FnZXMvcm91dGVyL3NyYy9hbmFsb2dqcy1yb3V0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLFNBQVMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogR2VuZXJhdGVkIGJ1bmRsZSBpbmRleC4gRG8gbm90IGVkaXQuXG4gKi9cblxuZXhwb3J0ICogZnJvbSAnLi9pbmRleCc7XG4iXX0=
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { routes } from './lib/routes';
|
|
2
|
+
export { defineRouteMeta, injectActivatedRoute, injectRouter, } from './lib/define-route';
|
|
3
|
+
export { provideFileRouter } from './lib/provide-file-routes';
|
|
4
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wYWNrYWdlcy9yb3V0ZXIvc3JjL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDdEMsT0FBTyxFQUNMLGVBQWUsRUFDZixvQkFBb0IsRUFDcEIsWUFBWSxHQUNiLE1BQU0sb0JBQW9CLENBQUM7QUFDNUIsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sMkJBQTJCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgeyByb3V0ZXMgfSBmcm9tICcuL2xpYi9yb3V0ZXMnO1xuZXhwb3J0IHtcbiAgZGVmaW5lUm91dGVNZXRhLFxuICBpbmplY3RBY3RpdmF0ZWRSb3V0ZSxcbiAgaW5qZWN0Um91dGVyLFxufSBmcm9tICcuL2xpYi9kZWZpbmUtcm91dGUnO1xuZXhwb3J0IHsgcHJvdmlkZUZpbGVSb3V0ZXIgfSBmcm9tICcuL2xpYi9wcm92aWRlLWZpbGUtcm91dGVzJztcbiJdfQ==
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { inject } from '@angular/core';
|
|
2
|
+
import { Router } from '@angular/router';
|
|
3
|
+
import { ActivatedRoute } from '@angular/router';
|
|
4
|
+
/**
|
|
5
|
+
* Defines additional route config metadata. This
|
|
6
|
+
* object is merged into the route config with
|
|
7
|
+
* the predefined file-based route.
|
|
8
|
+
*
|
|
9
|
+
* @usageNotes
|
|
10
|
+
*
|
|
11
|
+
* ```
|
|
12
|
+
* import { Component } from '@angular/core';
|
|
13
|
+
* import { defineRouteMeta } from '@analogjs/router';
|
|
14
|
+
*
|
|
15
|
+
* export const routeMeta = defineRouteMeta({
|
|
16
|
+
* title: 'Welcome'
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* @Component({
|
|
20
|
+
* template: `Home`,
|
|
21
|
+
* standalone: true,
|
|
22
|
+
* })
|
|
23
|
+
* export default class HomeComponent {}
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @param route
|
|
27
|
+
* @returns
|
|
28
|
+
*/
|
|
29
|
+
export const defineRouteMeta = (route) => {
|
|
30
|
+
return route;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Returns the instance of Angular Router
|
|
34
|
+
*
|
|
35
|
+
* @returns The router
|
|
36
|
+
*/
|
|
37
|
+
export const injectRouter = () => {
|
|
38
|
+
return inject(Router);
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Returns the instance of the Activate Route for the component
|
|
42
|
+
*
|
|
43
|
+
* @returns The activated route
|
|
44
|
+
*/
|
|
45
|
+
export const injectActivatedRoute = () => {
|
|
46
|
+
return inject(ActivatedRoute);
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVmaW5lLXJvdXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvcm91dGVyL3NyYy9saWIvZGVmaW5lLXJvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDdkMsT0FBTyxFQUFvQixNQUFNLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFXakQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXdCRztBQUNILE1BQU0sQ0FBQyxNQUFNLGVBQWUsR0FBRyxDQUFDLEtBQXNCLEVBQUUsRUFBRTtJQUN4RCxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUMsQ0FBQztBQUVGOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSxZQUFZLEdBQUcsR0FBRyxFQUFFO0lBQy9CLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQ3hCLENBQUMsQ0FBQztBQUVGOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBRyxHQUFHLEVBQUU7SUFDdkMsT0FBTyxNQUFNLENBQUMsY0FBYyxDQUFDLENBQUM7QUFDaEMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBSb3V0ZSBhcyBOZ1JvdXRlLCBSb3V0ZXIgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGUgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuXG50eXBlIFJvdXRlT21pdHRlZCA9XG4gIHwgJ2NvbXBvbmVudCdcbiAgfCAnbG9hZENvbXBvbmVudCdcbiAgfCAnbG9hZENoaWxkcmVuJ1xuICB8ICdwYXRoJ1xuICB8ICdwYXRoTWF0Y2gnO1xuXG50eXBlIFJlc3RyaWN0ZWRSb3V0ZSA9IE9taXQ8TmdSb3V0ZSwgUm91dGVPbWl0dGVkPjtcblxuLyoqXG4gKiBEZWZpbmVzIGFkZGl0aW9uYWwgcm91dGUgY29uZmlnIG1ldGFkYXRhLiBUaGlzXG4gKiBvYmplY3QgaXMgbWVyZ2VkIGludG8gdGhlIHJvdXRlIGNvbmZpZyB3aXRoXG4gKiB0aGUgcHJlZGVmaW5lZCBmaWxlLWJhc2VkIHJvdXRlLlxuICpcbiAqIEB1c2FnZU5vdGVzXG4gKlxuICogYGBgXG4gKiBpbXBvcnQgeyBDb21wb25lbnQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbiAqIGltcG9ydCB7IGRlZmluZVJvdXRlTWV0YSB9IGZyb20gJ0BhbmFsb2dqcy9yb3V0ZXInO1xuICpcbiAqICBleHBvcnQgY29uc3Qgcm91dGVNZXRhID0gZGVmaW5lUm91dGVNZXRhKHtcbiAqICAgIHRpdGxlOiAnV2VsY29tZSdcbiAqICB9KTtcbiAqXG4gKiBAQ29tcG9uZW50KHtcbiAqICAgdGVtcGxhdGU6IGBIb21lYCxcbiAqICAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAqIH0pXG4gKiBleHBvcnQgZGVmYXVsdCBjbGFzcyBIb21lQ29tcG9uZW50IHt9XG4gKiBgYGBcbiAqXG4gKiBAcGFyYW0gcm91dGVcbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBjb25zdCBkZWZpbmVSb3V0ZU1ldGEgPSAocm91dGU6IFJlc3RyaWN0ZWRSb3V0ZSkgPT4ge1xuICByZXR1cm4gcm91dGU7XG59O1xuXG4vKipcbiAqIFJldHVybnMgdGhlIGluc3RhbmNlIG9mIEFuZ3VsYXIgUm91dGVyXG4gKlxuICogQHJldHVybnMgVGhlIHJvdXRlclxuICovXG5leHBvcnQgY29uc3QgaW5qZWN0Um91dGVyID0gKCkgPT4ge1xuICByZXR1cm4gaW5qZWN0KFJvdXRlcik7XG59O1xuXG4vKipcbiAqIFJldHVybnMgdGhlIGluc3RhbmNlIG9mIHRoZSBBY3RpdmF0ZSBSb3V0ZSBmb3IgdGhlIGNvbXBvbmVudFxuICpcbiAqIEByZXR1cm5zIFRoZSBhY3RpdmF0ZWQgcm91dGVcbiAqL1xuZXhwb3J0IGNvbnN0IGluamVjdEFjdGl2YXRlZFJvdXRlID0gKCkgPT4ge1xuICByZXR1cm4gaW5qZWN0KEFjdGl2YXRlZFJvdXRlKTtcbn07XG4iXX0=
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { provideRouter } from '@angular/router';
|
|
2
|
+
import { routes } from './routes';
|
|
3
|
+
/**
|
|
4
|
+
* Sets up providers for the Angular router, and registers
|
|
5
|
+
* file-based routes. Additional features can be provided
|
|
6
|
+
* to further configure the behavior of the router.
|
|
7
|
+
*
|
|
8
|
+
* @param features
|
|
9
|
+
* @returns Providers and features to configure the router with routes
|
|
10
|
+
*/
|
|
11
|
+
export const provideFileRouter = (...features) => {
|
|
12
|
+
return provideRouter(routes, ...features);
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmlkZS1maWxlLXJvdXRlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL3JvdXRlci9zcmMvbGliL3Byb3ZpZGUtZmlsZS1yb3V0ZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGFBQWEsRUFBa0IsTUFBTSxpQkFBaUIsQ0FBQztBQUNoRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBRWxDOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLENBQUMsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLEdBQUcsUUFBMEIsRUFBRSxFQUFFO0lBQ2pFLE9BQU8sYUFBYSxDQUFDLE1BQU0sRUFBRSxHQUFHLFFBQVEsQ0FBQyxDQUFDO0FBQzVDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHByb3ZpZGVSb3V0ZXIsIFJvdXRlckZlYXR1cmVzIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IHJvdXRlcyB9IGZyb20gJy4vcm91dGVzJztcblxuLyoqXG4gKiBTZXRzIHVwIHByb3ZpZGVycyBmb3IgdGhlIEFuZ3VsYXIgcm91dGVyLCBhbmQgcmVnaXN0ZXJzXG4gKiBmaWxlLWJhc2VkIHJvdXRlcy4gQWRkaXRpb25hbCBmZWF0dXJlcyBjYW4gYmUgcHJvdmlkZWRcbiAqIHRvIGZ1cnRoZXIgY29uZmlndXJlIHRoZSBiZWhhdmlvciBvZiB0aGUgcm91dGVyLlxuICpcbiAqIEBwYXJhbSBmZWF0dXJlc1xuICogQHJldHVybnMgUHJvdmlkZXJzIGFuZCBmZWF0dXJlcyB0byBjb25maWd1cmUgdGhlIHJvdXRlciB3aXRoIHJvdXRlc1xuICovXG5leHBvcnQgY29uc3QgcHJvdmlkZUZpbGVSb3V0ZXIgPSAoLi4uZmVhdHVyZXM6IFJvdXRlckZlYXR1cmVzW10pID0+IHtcbiAgcmV0dXJuIHByb3ZpZGVSb3V0ZXIocm91dGVzLCAuLi5mZWF0dXJlcyk7XG59O1xuIl19
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
|
2
|
+
const FILES = import.meta.glob(['/app/routes/**/*.ts']);
|
|
3
|
+
/**
|
|
4
|
+
* Function used to parse list of files and return
|
|
5
|
+
* configuration of routes.
|
|
6
|
+
*
|
|
7
|
+
* @param files
|
|
8
|
+
* @returns Array of routes
|
|
9
|
+
*/
|
|
10
|
+
export function getRoutes(files) {
|
|
11
|
+
const ROUTES = Object.keys(files).sort((a, b) => a.length - b.length);
|
|
12
|
+
const routeConfigs = ROUTES.reduce((routes, key) => {
|
|
13
|
+
const module = files[key];
|
|
14
|
+
const segments = key
|
|
15
|
+
.replace(/\/app\/routes|\.(js|ts)$/g, '')
|
|
16
|
+
.replace(/\[\.{3}.+\]/, '**')
|
|
17
|
+
.replace(/\[([^\]]+)\]/g, ':$1')
|
|
18
|
+
.split('/')
|
|
19
|
+
.filter(Boolean);
|
|
20
|
+
segments.reduce((parent, segment, index) => {
|
|
21
|
+
const path = segment.replace(/index/g, '').replace('.', '/');
|
|
22
|
+
const isIndex = !path;
|
|
23
|
+
const isCatchall = path === '**';
|
|
24
|
+
const pathMatch = isIndex ? 'full' : 'prefix';
|
|
25
|
+
const root = index === 0;
|
|
26
|
+
const leaf = index === segments.length - 1 && segments.length > 1;
|
|
27
|
+
const node = !root && !leaf;
|
|
28
|
+
const insert = /^\w|\//.test(path) && !isCatchall ? 'unshift' : 'push';
|
|
29
|
+
if (root) {
|
|
30
|
+
const dynamic = path.startsWith(':');
|
|
31
|
+
if (dynamic)
|
|
32
|
+
return parent;
|
|
33
|
+
const last = segments.length === 1;
|
|
34
|
+
if (last) {
|
|
35
|
+
const newRoute = {
|
|
36
|
+
path,
|
|
37
|
+
pathMatch,
|
|
38
|
+
_module: () => module(),
|
|
39
|
+
loadChildren: () => module().then((m) => [
|
|
40
|
+
{
|
|
41
|
+
path: '',
|
|
42
|
+
component: m.default,
|
|
43
|
+
...m.routeMeta,
|
|
44
|
+
},
|
|
45
|
+
]),
|
|
46
|
+
};
|
|
47
|
+
routes?.[insert](newRoute);
|
|
48
|
+
return parent;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (root || node) {
|
|
52
|
+
const current = root ? routes : parent._children;
|
|
53
|
+
const found = current?.find((route) => route.path === path);
|
|
54
|
+
if (found) {
|
|
55
|
+
if (!found._children) {
|
|
56
|
+
found._children = [];
|
|
57
|
+
}
|
|
58
|
+
found.pathMatch = pathMatch;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
current?.[insert]({
|
|
62
|
+
path,
|
|
63
|
+
pathMatch,
|
|
64
|
+
_module: () => module(),
|
|
65
|
+
loadChildren: () => module().then((m) => [
|
|
66
|
+
{
|
|
67
|
+
path: '',
|
|
68
|
+
component: m.default,
|
|
69
|
+
...m.routeMeta,
|
|
70
|
+
},
|
|
71
|
+
]),
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return (found ||
|
|
75
|
+
current?.[insert === 'unshift' ? 0 : current.length - 1]);
|
|
76
|
+
}
|
|
77
|
+
if (leaf) {
|
|
78
|
+
parent?._children?.[insert]({
|
|
79
|
+
path,
|
|
80
|
+
pathMatch,
|
|
81
|
+
_module: () => module(),
|
|
82
|
+
loadChildren: () => module().then((m) => [
|
|
83
|
+
{
|
|
84
|
+
path: '',
|
|
85
|
+
component: m.default,
|
|
86
|
+
...m.routeMeta,
|
|
87
|
+
},
|
|
88
|
+
]),
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
if (parent._children) {
|
|
92
|
+
parent.loadComponent = () => parent._module().then((m) => m.default);
|
|
93
|
+
parent.loadChildren = () => parent._module().then((m) => {
|
|
94
|
+
return [
|
|
95
|
+
{
|
|
96
|
+
path: '',
|
|
97
|
+
children: parent._children,
|
|
98
|
+
...m.routeMeta,
|
|
99
|
+
},
|
|
100
|
+
];
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
return parent;
|
|
104
|
+
}, {});
|
|
105
|
+
return routes;
|
|
106
|
+
}, []);
|
|
107
|
+
return routeConfigs;
|
|
108
|
+
}
|
|
109
|
+
export const routes = [...getRoutes(FILES)];
|
|
110
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvcm91dGVyL3NyYy9saWIvcm91dGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLHFDQUFxQztBQVdyQyxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBYyxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQztBQUVyRTs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsU0FBUyxDQUFDLEtBQWlEO0lBQ3pFLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7SUFFdEUsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FDaEMsQ0FBQyxNQUFlLEVBQUUsR0FBVyxFQUFFLEVBQUU7UUFDL0IsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBRTFCLE1BQU0sUUFBUSxHQUFHLEdBQUc7YUFDakIsT0FBTyxDQUFDLDJCQUEyQixFQUFFLEVBQUUsQ0FBQzthQUN4QyxPQUFPLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQzthQUM1QixPQUFPLENBQUMsZUFBZSxFQUFFLEtBQUssQ0FBQzthQUMvQixLQUFLLENBQUMsR0FBRyxDQUFDO2FBQ1YsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRW5CLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxFQUFFO1lBQ3pDLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDN0Qs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Q0FBQyxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8vIDxyZWZlcmVuY2UgdHlwZXM9XCJ2aXRlL2NsaWVudFwiIC8+XG5cbmltcG9ydCB0eXBlIHsgVHlwZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHR5cGUgeyBSb3V0ZSB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBkZWZpbmVSb3V0ZU1ldGEgfSBmcm9tICcuL2RlZmluZS1yb3V0ZSc7XG5cbmV4cG9ydCB0eXBlIFJvdXRlRXhwb3J0ID0ge1xuICBkZWZhdWx0OiBUeXBlPHVua25vd24+O1xuICByb3V0ZU1ldGE/OiBSZXR1cm5UeXBlPHR5cGVvZiBkZWZpbmVSb3V0ZU1ldGE+O1xufTtcblxuY29uc3QgRklMRVMgPSBpbXBvcnQubWV0YS5nbG9iPFJvdXRlRXhwb3J0PihbJy9hcHAvcm91dGVzLyoqLyoudHMnXSk7XG5cbi8qKlxuICogRnVuY3Rpb24gdXNlZCB0byBwYXJzZSBsaXN0IG9mIGZpbGVzIGFuZCByZXR1cm5cbiAqIGNvbmZpZ3VyYXRpb24gb2Ygcm91dGVzLlxuICpcbiAqIEBwYXJhbSBmaWxlc1xuICogQHJldHVybnMgQXJyYXkgb2Ygcm91dGVzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRSb3V0ZXMoZmlsZXM6IFJlY29yZDxzdHJpbmcsICgpID0+IFByb21pc2U8Um91dGVFeHBvcnQ+Pikge1xuICBjb25zdCBST1VURVMgPSBPYmplY3Qua2V5cyhmaWxlcykuc29ydCgoYSwgYikgPT4gYS5sZW5ndGggLSBiLmxlbmd0aCk7XG5cbiAgY29uc3Qgcm91dGVDb25maWdzID0gUk9VVEVTLnJlZHVjZTxSb3V0ZVtdPihcbiAgICAocm91dGVzOiBSb3V0ZVtdLCBrZXk6IHN0cmluZykgPT4ge1xuICAgICAgY29uc3QgbW9kdWxlID0gZmlsZXNba2V5XTtcblxuICAgICAgY29uc3Qgc2VnbWVudHMgPSBrZXlcbiAgICAgICAgLnJlcGxhY2UoL1xcL2FwcFxcL3JvdXRlc3xcXC4oanN8dHMpJC9nLCAnJylcbiAgICAgICAgLnJlcGxhY2UoL1xcW1xcLnszfS4rXFxdLywgJyoqJylcbiAgICAgICAgLnJlcGxhY2UoL1xcWyhbXlxcXV0rKVxcXS9nLCAnOiQxJylcbiAgICAgICAgLnNwbGl0KCcvJylcbiAgICAgICAgLmZpbHRlcihCb29sZWFuKTtcblxuICAgICAgc2VnbWVudHMucmVkdWNlKChwYXJlbnQsIHNlZ21lbnQsIGluZGV4KSA9PiB7XG4gICAgICAgIGNvbnN0IHBhdGggPSBzZWdtZW50LnJlcGxhY2UoL2luZGV4L2csICcnKS5yZXBsYWNlKCcuJywgJy8nKTtcbiAgICAgICAgY29uc3QgaXNJbmRleCA9ICFwYXRoO1xuICAgICAgICBjb25zdCBpc0NhdGNoYWxsID0gcGF0aCA9PT0gJyoqJztcbiAgICAgICAgY29uc3QgcGF0aE1hdGNoID0gaXNJbmRleCA/ICdmdWxsJyA6ICdwcmVmaXgnO1xuICAgICAgICBjb25zdCByb290ID0gaW5kZXggPT09IDA7XG4gICAgICAgIGNvbnN0IGxlYWYgPSBpbmRleCA9PT0gc2VnbWVudHMubGVuZ3RoIC0gMSAmJiBzZWdtZW50cy5sZW5ndGggPiAxO1xuICAgICAgICBjb25zdCBub2RlID0gIXJvb3QgJiYgIWxlYWY7XG4gICAgICAgIGNvbnN0IGluc2VydCA9IC9eXFx3fFxcLy8udGVzdChwYXRoKSAmJiAhaXNDYXRjaGFsbCA/ICd1bnNoaWZ0JyA6ICdwdXNoJztcblxuICAgICAgICBpZiAocm9vdCkge1xuICAgICAgICAgIGNvbnN0IGR5bmFtaWMgPSBwYXRoLnN0YXJ0c1dpdGgoJzonKTtcbiAgICAgICAgICBpZiAoZHluYW1pYykgcmV0dXJuIHBhcmVudDtcblxuICAgICAgICAgIGNvbnN0IGxhc3QgPSBzZWdtZW50cy5sZW5ndGggPT09IDE7XG4gICAgICAgICAgaWYgKGxhc3QpIHtcbiAgICAgICAgICAgIGNvbnN0IG5ld1JvdXRlID0ge1xuICAgICAgICAgICAgICBwYXRoLFxuICAgICAgICAgICAgICBwYXRoTWF0Y2gsXG4gICAgICAgICAgICAgIF9tb2R1bGU6ICgpID0+IG1vZHVsZSgpLFxuICAgICAgICAgICAgICBsb2FkQ2hpbGRyZW46ICgpID0+XG4gICAgICAgICAgICAgICAgbW9kdWxlKCkudGhlbigobSkgPT4gW1xuICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBwYXRoOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50OiBtLmRlZmF1bHQsXG4gICAgICAgICAgICAgICAgICAgIC4uLm0ucm91dGVNZXRhLFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBdKSxcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHJvdXRlcz8uW2luc2VydF0obmV3Um91dGUgYXMgUm91dGUpO1xuICAgICAgICAgICAgcmV0dXJuIHBhcmVudDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocm9vdCB8fCBub2RlKSB7XG4gICAgICAgICAgY29uc3QgY3VycmVudCA9IHJvb3QgPyByb3V0ZXMgOiBwYXJlbnQuX2NoaWxkcmVuO1xuICAgICAgICAgIGNvbnN0IGZvdW5kID0gY3VycmVudD8uZmluZCgocm91dGU6IGFueSkgPT4gcm91dGUucGF0aCA9PT0gcGF0aCk7XG5cbiAgICAgICAgICBpZiAoZm91bmQpIHtcbiAgICAgICAgICAgIGlmICghZm91bmQuX2NoaWxkcmVuKSB7XG4gICAgICAgICAgICAgIGZvdW5kLl9jaGlsZHJlbiA9IFtdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3VuZC5wYXRoTWF0Y2ggPSBwYXRoTWF0Y2g7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGN1cnJlbnQ/LltpbnNlcnRdKHtcbiAgICAgICAgICAgICAgcGF0aCxcbiAgICAgICAgICAgICAgcGF0aE1hdGNoLFxuICAgICAgICAgICAgICBfbW9kdWxlOiAoKSA9PiBtb2R1bGUoKSxcbiAgICAgICAgICAgICAgbG9hZENoaWxkcmVuOiAoKSA9PlxuICAgICAgICAgICAgICAgIG1vZHVsZSgpLnRoZW4oKG0pID0+IFtcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0aDogJycsXG4gICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudDogbS5kZWZhdWx0LFxuICAgICAgICAgICAgICAgICAgICAuLi5tLnJvdXRlTWV0YSxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgXSksXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgZm91bmQgfHxcbiAgICAgICAgICAgIChjdXJyZW50Py5baW5zZXJ0ID09PSAndW5zaGlmdCcgPyAwIDogY3VycmVudC5sZW5ndGggLSAxXSBhcyBSb3V0ZSlcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGxlYWYpIHtcbiAgICAgICAgICBwYXJlbnQ/Ll9jaGlsZHJlbj8uW2luc2VydF0oe1xuICAgICAgICAgICAgcGF0aCxcbiAgICAgICAgICAgIHBhdGhNYXRjaCxcbiAgICAgICAgICAgIF9tb2R1bGU6ICgpID0+IG1vZHVsZSgpLFxuICAgICAgICAgICAgbG9hZENoaWxkcmVuOiAoKSA9PlxuICAgICAgICAgICAgICBtb2R1bGUoKS50aGVuKChtKSA9PiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgcGF0aDogJycsXG4gICAgICAgICAgICAgICAgICBjb21wb25lbnQ6IG0uZGVmYXVsdCxcbiAgICAgICAgICAgICAgICAgIC4uLm0ucm91dGVNZXRhLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIF0pLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhcmVudC5fY2hpbGRyZW4pIHtcbiAgICAgICAgICBwYXJlbnQubG9hZENvbXBvbmVudCA9ICgpID0+XG4gICAgICAgICAgICBwYXJlbnQuX21vZHVsZSgpLnRoZW4oKG06IFJvdXRlRXhwb3J0KSA9PiBtLmRlZmF1bHQpO1xuICAgICAgICAgIHBhcmVudC5sb2FkQ2hpbGRyZW4gPSAoKSA9PlxuICAgICAgICAgICAgcGFyZW50Ll9tb2R1bGUoKS50aGVuKChtOiBSb3V0ZUV4cG9ydCkgPT4ge1xuICAgICAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIHBhdGg6ICcnLFxuICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IHBhcmVudC5fY2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAuLi5tLnJvdXRlTWV0YSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcGFyZW50O1xuICAgICAgfSwge30gYXMgUm91dGUgJiB7IF9tb2R1bGU6ICgpID0+IFByb21pc2U8Um91dGVFeHBvcnQ+OyBfY2hpbGRyZW46IGFueVtdIH0pO1xuXG4gICAgICByZXR1cm4gcm91dGVzO1xuICAgIH0sXG4gICAgW11cbiAgKTtcblxuICByZXR1cm4gcm91dGVDb25maWdzO1xufVxuXG5leHBvcnQgY29uc3Qgcm91dGVzOiBSb3V0ZVtdID0gWy4uLmdldFJvdXRlcyhGSUxFUyldO1xuIl19
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { inject } from '@angular/core';
|
|
2
|
+
import { Router, ActivatedRoute, provideRouter } from '@angular/router';
|
|
3
|
+
|
|
4
|
+
/// <reference types="vite/client" />
|
|
5
|
+
const FILES = import.meta.glob(['/app/routes/**/*.ts']);
|
|
6
|
+
/**
|
|
7
|
+
* Function used to parse list of files and return
|
|
8
|
+
* configuration of routes.
|
|
9
|
+
*
|
|
10
|
+
* @param files
|
|
11
|
+
* @returns Array of routes
|
|
12
|
+
*/
|
|
13
|
+
function getRoutes(files) {
|
|
14
|
+
const ROUTES = Object.keys(files).sort((a, b) => a.length - b.length);
|
|
15
|
+
const routeConfigs = ROUTES.reduce((routes, key) => {
|
|
16
|
+
const module = files[key];
|
|
17
|
+
const segments = key
|
|
18
|
+
.replace(/\/app\/routes|\.(js|ts)$/g, '')
|
|
19
|
+
.replace(/\[\.{3}.+\]/, '**')
|
|
20
|
+
.replace(/\[([^\]]+)\]/g, ':$1')
|
|
21
|
+
.split('/')
|
|
22
|
+
.filter(Boolean);
|
|
23
|
+
segments.reduce((parent, segment, index) => {
|
|
24
|
+
var _a;
|
|
25
|
+
const path = segment.replace(/index/g, '').replace('.', '/');
|
|
26
|
+
const isIndex = !path;
|
|
27
|
+
const isCatchall = path === '**';
|
|
28
|
+
const pathMatch = isIndex ? 'full' : 'prefix';
|
|
29
|
+
const root = index === 0;
|
|
30
|
+
const leaf = index === segments.length - 1 && segments.length > 1;
|
|
31
|
+
const node = !root && !leaf;
|
|
32
|
+
const insert = /^\w|\//.test(path) && !isCatchall ? 'unshift' : 'push';
|
|
33
|
+
if (root) {
|
|
34
|
+
const dynamic = path.startsWith(':');
|
|
35
|
+
if (dynamic)
|
|
36
|
+
return parent;
|
|
37
|
+
const last = segments.length === 1;
|
|
38
|
+
if (last) {
|
|
39
|
+
const newRoute = {
|
|
40
|
+
path,
|
|
41
|
+
pathMatch,
|
|
42
|
+
_module: () => module(),
|
|
43
|
+
loadChildren: () => module().then((m) => [
|
|
44
|
+
Object.assign({ path: '', component: m.default }, m.routeMeta),
|
|
45
|
+
]),
|
|
46
|
+
};
|
|
47
|
+
routes === null || routes === void 0 ? void 0 : routes[insert](newRoute);
|
|
48
|
+
return parent;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (root || node) {
|
|
52
|
+
const current = root ? routes : parent._children;
|
|
53
|
+
const found = current === null || current === void 0 ? void 0 : current.find((route) => route.path === path);
|
|
54
|
+
if (found) {
|
|
55
|
+
if (!found._children) {
|
|
56
|
+
found._children = [];
|
|
57
|
+
}
|
|
58
|
+
found.pathMatch = pathMatch;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
current === null || current === void 0 ? void 0 : current[insert]({
|
|
62
|
+
path,
|
|
63
|
+
pathMatch,
|
|
64
|
+
_module: () => module(),
|
|
65
|
+
loadChildren: () => module().then((m) => [
|
|
66
|
+
Object.assign({ path: '', component: m.default }, m.routeMeta),
|
|
67
|
+
]),
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
return (found ||
|
|
71
|
+
(current === null || current === void 0 ? void 0 : current[insert === 'unshift' ? 0 : current.length - 1]));
|
|
72
|
+
}
|
|
73
|
+
if (leaf) {
|
|
74
|
+
(_a = parent === null || parent === void 0 ? void 0 : parent._children) === null || _a === void 0 ? void 0 : _a[insert]({
|
|
75
|
+
path,
|
|
76
|
+
pathMatch,
|
|
77
|
+
_module: () => module(),
|
|
78
|
+
loadChildren: () => module().then((m) => [
|
|
79
|
+
Object.assign({ path: '', component: m.default }, m.routeMeta),
|
|
80
|
+
]),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
if (parent._children) {
|
|
84
|
+
parent.loadComponent = () => parent._module().then((m) => m.default);
|
|
85
|
+
parent.loadChildren = () => parent._module().then((m) => {
|
|
86
|
+
return [
|
|
87
|
+
Object.assign({ path: '', children: parent._children }, m.routeMeta),
|
|
88
|
+
];
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
return parent;
|
|
92
|
+
}, {});
|
|
93
|
+
return routes;
|
|
94
|
+
}, []);
|
|
95
|
+
return routeConfigs;
|
|
96
|
+
}
|
|
97
|
+
const routes = [...getRoutes(FILES)];
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Defines additional route config metadata. This
|
|
101
|
+
* object is merged into the route config with
|
|
102
|
+
* the predefined file-based route.
|
|
103
|
+
*
|
|
104
|
+
* @usageNotes
|
|
105
|
+
*
|
|
106
|
+
* ```
|
|
107
|
+
* import { Component } from '@angular/core';
|
|
108
|
+
* import { defineRouteMeta } from '@analogjs/router';
|
|
109
|
+
*
|
|
110
|
+
* export const routeMeta = defineRouteMeta({
|
|
111
|
+
* title: 'Welcome'
|
|
112
|
+
* });
|
|
113
|
+
*
|
|
114
|
+
* @Component({
|
|
115
|
+
* template: `Home`,
|
|
116
|
+
* standalone: true,
|
|
117
|
+
* })
|
|
118
|
+
* export default class HomeComponent {}
|
|
119
|
+
* ```
|
|
120
|
+
*
|
|
121
|
+
* @param route
|
|
122
|
+
* @returns
|
|
123
|
+
*/
|
|
124
|
+
const defineRouteMeta = (route) => {
|
|
125
|
+
return route;
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Returns the instance of Angular Router
|
|
129
|
+
*
|
|
130
|
+
* @returns The router
|
|
131
|
+
*/
|
|
132
|
+
const injectRouter = () => {
|
|
133
|
+
return inject(Router);
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Returns the instance of the Activate Route for the component
|
|
137
|
+
*
|
|
138
|
+
* @returns The activated route
|
|
139
|
+
*/
|
|
140
|
+
const injectActivatedRoute = () => {
|
|
141
|
+
return inject(ActivatedRoute);
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Sets up providers for the Angular router, and registers
|
|
146
|
+
* file-based routes. Additional features can be provided
|
|
147
|
+
* to further configure the behavior of the router.
|
|
148
|
+
*
|
|
149
|
+
* @param features
|
|
150
|
+
* @returns Providers and features to configure the router with routes
|
|
151
|
+
*/
|
|
152
|
+
const provideFileRouter = (...features) => {
|
|
153
|
+
return provideRouter(routes, ...features);
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Generated bundle index. Do not edit.
|
|
158
|
+
*/
|
|
159
|
+
|
|
160
|
+
export { defineRouteMeta, injectActivatedRoute, injectRouter, provideFileRouter, routes };
|
|
161
|
+
//# sourceMappingURL=analogjs-router.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analogjs-router.mjs","sources":["../../../../packages/router/src/lib/routes.ts","../../../../packages/router/src/lib/define-route.ts","../../../../packages/router/src/lib/provide-file-routes.ts","../../../../packages/router/src/analogjs-router.ts"],"sourcesContent":["/// <reference types=\"vite/client\" />\n\nimport type { Type } from '@angular/core';\nimport type { Route } from '@angular/router';\nimport { defineRouteMeta } from './define-route';\n\nexport type RouteExport = {\n default: Type<unknown>;\n routeMeta?: ReturnType<typeof defineRouteMeta>;\n};\n\nconst FILES = import.meta.glob<RouteExport>(['/app/routes/**/*.ts']);\n\n/**\n * Function used to parse list of files and return\n * configuration of routes.\n *\n * @param files\n * @returns Array of routes\n */\nexport function getRoutes(files: Record<string, () => Promise<RouteExport>>) {\n const ROUTES = Object.keys(files).sort((a, b) => a.length - b.length);\n\n const routeConfigs = ROUTES.reduce<Route[]>(\n (routes: Route[], key: string) => {\n const module = files[key];\n\n const segments = key\n .replace(/\\/app\\/routes|\\.(js|ts)$/g, '')\n .replace(/\\[\\.{3}.+\\]/, '**')\n .replace(/\\[([^\\]]+)\\]/g, ':$1')\n .split('/')\n .filter(Boolean);\n\n segments.reduce((parent, segment, index) => {\n const path = segment.replace(/index/g, '').replace('.', '/');\n const isIndex = !path;\n const isCatchall = path === '**';\n const pathMatch = isIndex ? 'full' : 'prefix';\n const root = index === 0;\n const leaf = index === segments.length - 1 && segments.length > 1;\n const node = !root && !leaf;\n const insert = /^\\w|\\//.test(path) && !isCatchall ? 'unshift' : 'push';\n\n if (root) {\n const dynamic = path.startsWith(':');\n if (dynamic) return parent;\n\n const last = segments.length === 1;\n if (last) {\n const newRoute = {\n path,\n pathMatch,\n _module: () => module(),\n loadChildren: () =>\n module().then((m) => [\n {\n path: '',\n component: m.default,\n ...m.routeMeta,\n },\n ]),\n };\n\n routes?.[insert](newRoute as Route);\n return parent;\n }\n }\n\n if (root || node) {\n const current = root ? routes : parent._children;\n const found = current?.find((route: any) => route.path === path);\n\n if (found) {\n if (!found._children) {\n found._children = [];\n }\n\n found.pathMatch = pathMatch;\n } else {\n current?.[insert]({\n path,\n pathMatch,\n _module: () => module(),\n loadChildren: () =>\n module().then((m) => [\n {\n path: '',\n component: m.default,\n ...m.routeMeta,\n },\n ]),\n });\n }\n\n return (\n found ||\n (current?.[insert === 'unshift' ? 0 : current.length - 1] as Route)\n );\n }\n\n if (leaf) {\n parent?._children?.[insert]({\n path,\n pathMatch,\n _module: () => module(),\n loadChildren: () =>\n module().then((m) => [\n {\n path: '',\n component: m.default,\n ...m.routeMeta,\n },\n ]),\n });\n }\n\n if (parent._children) {\n parent.loadComponent = () =>\n parent._module().then((m: RouteExport) => m.default);\n parent.loadChildren = () =>\n parent._module().then((m: RouteExport) => {\n return [\n {\n path: '',\n children: parent._children,\n ...m.routeMeta,\n },\n ];\n });\n }\n\n return parent;\n }, {} as Route & { _module: () => Promise<RouteExport>; _children: any[] });\n\n return routes;\n },\n []\n );\n\n return routeConfigs;\n}\n\nexport const routes: Route[] = [...getRoutes(FILES)];\n","import { inject } from '@angular/core';\nimport { Route as NgRoute, Router } from '@angular/router';\nimport { ActivatedRoute } from '@angular/router';\n\ntype RouteOmitted =\n | 'component'\n | 'loadComponent'\n | 'loadChildren'\n | 'path'\n | 'pathMatch';\n\ntype RestrictedRoute = Omit<NgRoute, RouteOmitted>;\n\n/**\n * Defines additional route config metadata. This\n * object is merged into the route config with\n * the predefined file-based route.\n *\n * @usageNotes\n *\n * ```\n * import { Component } from '@angular/core';\n * import { defineRouteMeta } from '@analogjs/router';\n *\n * export const routeMeta = defineRouteMeta({\n * title: 'Welcome'\n * });\n *\n * @Component({\n * template: `Home`,\n * standalone: true,\n * })\n * export default class HomeComponent {}\n * ```\n *\n * @param route\n * @returns\n */\nexport const defineRouteMeta = (route: RestrictedRoute) => {\n return route;\n};\n\n/**\n * Returns the instance of Angular Router\n *\n * @returns The router\n */\nexport const injectRouter = () => {\n return inject(Router);\n};\n\n/**\n * Returns the instance of the Activate Route for the component\n *\n * @returns The activated route\n */\nexport const injectActivatedRoute = () => {\n return inject(ActivatedRoute);\n};\n","import { provideRouter, RouterFeatures } from '@angular/router';\nimport { routes } from './routes';\n\n/**\n * Sets up providers for the Angular router, and registers\n * file-based routes. Additional features can be provided\n * to further configure the behavior of the router.\n *\n * @param features\n * @returns Providers and features to configure the router with routes\n */\nexport const provideFileRouter = (...features: RouterFeatures[]) => {\n return provideRouter(routes, ...features);\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { inject } from '@angular/core';
|
|
2
|
+
import { Router, ActivatedRoute, provideRouter } from '@angular/router';
|
|
3
|
+
|
|
4
|
+
/// <reference types="vite/client" />
|
|
5
|
+
const FILES = import.meta.glob(['/app/routes/**/*.ts']);
|
|
6
|
+
/**
|
|
7
|
+
* Function used to parse list of files and return
|
|
8
|
+
* configuration of routes.
|
|
9
|
+
*
|
|
10
|
+
* @param files
|
|
11
|
+
* @returns Array of routes
|
|
12
|
+
*/
|
|
13
|
+
function getRoutes(files) {
|
|
14
|
+
const ROUTES = Object.keys(files).sort((a, b) => a.length - b.length);
|
|
15
|
+
const routeConfigs = ROUTES.reduce((routes, key) => {
|
|
16
|
+
const module = files[key];
|
|
17
|
+
const segments = key
|
|
18
|
+
.replace(/\/app\/routes|\.(js|ts)$/g, '')
|
|
19
|
+
.replace(/\[\.{3}.+\]/, '**')
|
|
20
|
+
.replace(/\[([^\]]+)\]/g, ':$1')
|
|
21
|
+
.split('/')
|
|
22
|
+
.filter(Boolean);
|
|
23
|
+
segments.reduce((parent, segment, index) => {
|
|
24
|
+
const path = segment.replace(/index/g, '').replace('.', '/');
|
|
25
|
+
const isIndex = !path;
|
|
26
|
+
const isCatchall = path === '**';
|
|
27
|
+
const pathMatch = isIndex ? 'full' : 'prefix';
|
|
28
|
+
const root = index === 0;
|
|
29
|
+
const leaf = index === segments.length - 1 && segments.length > 1;
|
|
30
|
+
const node = !root && !leaf;
|
|
31
|
+
const insert = /^\w|\//.test(path) && !isCatchall ? 'unshift' : 'push';
|
|
32
|
+
if (root) {
|
|
33
|
+
const dynamic = path.startsWith(':');
|
|
34
|
+
if (dynamic)
|
|
35
|
+
return parent;
|
|
36
|
+
const last = segments.length === 1;
|
|
37
|
+
if (last) {
|
|
38
|
+
const newRoute = {
|
|
39
|
+
path,
|
|
40
|
+
pathMatch,
|
|
41
|
+
_module: () => module(),
|
|
42
|
+
loadChildren: () => module().then((m) => [
|
|
43
|
+
{
|
|
44
|
+
path: '',
|
|
45
|
+
component: m.default,
|
|
46
|
+
...m.routeMeta,
|
|
47
|
+
},
|
|
48
|
+
]),
|
|
49
|
+
};
|
|
50
|
+
routes?.[insert](newRoute);
|
|
51
|
+
return parent;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (root || node) {
|
|
55
|
+
const current = root ? routes : parent._children;
|
|
56
|
+
const found = current?.find((route) => route.path === path);
|
|
57
|
+
if (found) {
|
|
58
|
+
if (!found._children) {
|
|
59
|
+
found._children = [];
|
|
60
|
+
}
|
|
61
|
+
found.pathMatch = pathMatch;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
current?.[insert]({
|
|
65
|
+
path,
|
|
66
|
+
pathMatch,
|
|
67
|
+
_module: () => module(),
|
|
68
|
+
loadChildren: () => module().then((m) => [
|
|
69
|
+
{
|
|
70
|
+
path: '',
|
|
71
|
+
component: m.default,
|
|
72
|
+
...m.routeMeta,
|
|
73
|
+
},
|
|
74
|
+
]),
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return (found ||
|
|
78
|
+
current?.[insert === 'unshift' ? 0 : current.length - 1]);
|
|
79
|
+
}
|
|
80
|
+
if (leaf) {
|
|
81
|
+
parent?._children?.[insert]({
|
|
82
|
+
path,
|
|
83
|
+
pathMatch,
|
|
84
|
+
_module: () => module(),
|
|
85
|
+
loadChildren: () => module().then((m) => [
|
|
86
|
+
{
|
|
87
|
+
path: '',
|
|
88
|
+
component: m.default,
|
|
89
|
+
...m.routeMeta,
|
|
90
|
+
},
|
|
91
|
+
]),
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
if (parent._children) {
|
|
95
|
+
parent.loadComponent = () => parent._module().then((m) => m.default);
|
|
96
|
+
parent.loadChildren = () => parent._module().then((m) => {
|
|
97
|
+
return [
|
|
98
|
+
{
|
|
99
|
+
path: '',
|
|
100
|
+
children: parent._children,
|
|
101
|
+
...m.routeMeta,
|
|
102
|
+
},
|
|
103
|
+
];
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return parent;
|
|
107
|
+
}, {});
|
|
108
|
+
return routes;
|
|
109
|
+
}, []);
|
|
110
|
+
return routeConfigs;
|
|
111
|
+
}
|
|
112
|
+
const routes = [...getRoutes(FILES)];
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Defines additional route config metadata. This
|
|
116
|
+
* object is merged into the route config with
|
|
117
|
+
* the predefined file-based route.
|
|
118
|
+
*
|
|
119
|
+
* @usageNotes
|
|
120
|
+
*
|
|
121
|
+
* ```
|
|
122
|
+
* import { Component } from '@angular/core';
|
|
123
|
+
* import { defineRouteMeta } from '@analogjs/router';
|
|
124
|
+
*
|
|
125
|
+
* export const routeMeta = defineRouteMeta({
|
|
126
|
+
* title: 'Welcome'
|
|
127
|
+
* });
|
|
128
|
+
*
|
|
129
|
+
* @Component({
|
|
130
|
+
* template: `Home`,
|
|
131
|
+
* standalone: true,
|
|
132
|
+
* })
|
|
133
|
+
* export default class HomeComponent {}
|
|
134
|
+
* ```
|
|
135
|
+
*
|
|
136
|
+
* @param route
|
|
137
|
+
* @returns
|
|
138
|
+
*/
|
|
139
|
+
const defineRouteMeta = (route) => {
|
|
140
|
+
return route;
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Returns the instance of Angular Router
|
|
144
|
+
*
|
|
145
|
+
* @returns The router
|
|
146
|
+
*/
|
|
147
|
+
const injectRouter = () => {
|
|
148
|
+
return inject(Router);
|
|
149
|
+
};
|
|
150
|
+
/**
|
|
151
|
+
* Returns the instance of the Activate Route for the component
|
|
152
|
+
*
|
|
153
|
+
* @returns The activated route
|
|
154
|
+
*/
|
|
155
|
+
const injectActivatedRoute = () => {
|
|
156
|
+
return inject(ActivatedRoute);
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Sets up providers for the Angular router, and registers
|
|
161
|
+
* file-based routes. Additional features can be provided
|
|
162
|
+
* to further configure the behavior of the router.
|
|
163
|
+
*
|
|
164
|
+
* @param features
|
|
165
|
+
* @returns Providers and features to configure the router with routes
|
|
166
|
+
*/
|
|
167
|
+
const provideFileRouter = (...features) => {
|
|
168
|
+
return provideRouter(routes, ...features);
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Generated bundle index. Do not edit.
|
|
173
|
+
*/
|
|
174
|
+
|
|
175
|
+
export { defineRouteMeta, injectActivatedRoute, injectRouter, provideFileRouter, routes };
|
|
176
|
+
//# sourceMappingURL=analogjs-router.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analogjs-router.mjs","sources":["../../../../packages/router/src/lib/routes.ts","../../../../packages/router/src/lib/define-route.ts","../../../../packages/router/src/lib/provide-file-routes.ts","../../../../packages/router/src/analogjs-router.ts"],"sourcesContent":["/// <reference types=\"vite/client\" />\n\nimport type { Type } from '@angular/core';\nimport type { Route } from '@angular/router';\nimport { defineRouteMeta } from './define-route';\n\nexport type RouteExport = {\n default: Type<unknown>;\n routeMeta?: ReturnType<typeof defineRouteMeta>;\n};\n\nconst FILES = import.meta.glob<RouteExport>(['/app/routes/**/*.ts']);\n\n/**\n * Function used to parse list of files and return\n * configuration of routes.\n *\n * @param files\n * @returns Array of routes\n */\nexport function getRoutes(files: Record<string, () => Promise<RouteExport>>) {\n const ROUTES = Object.keys(files).sort((a, b) => a.length - b.length);\n\n const routeConfigs = ROUTES.reduce<Route[]>(\n (routes: Route[], key: string) => {\n const module = files[key];\n\n const segments = key\n .replace(/\\/app\\/routes|\\.(js|ts)$/g, '')\n .replace(/\\[\\.{3}.+\\]/, '**')\n .replace(/\\[([^\\]]+)\\]/g, ':$1')\n .split('/')\n .filter(Boolean);\n\n segments.reduce((parent, segment, index) => {\n const path = segment.replace(/index/g, '').replace('.', '/');\n const isIndex = !path;\n const isCatchall = path === '**';\n const pathMatch = isIndex ? 'full' : 'prefix';\n const root = index === 0;\n const leaf = index === segments.length - 1 && segments.length > 1;\n const node = !root && !leaf;\n const insert = /^\\w|\\//.test(path) && !isCatchall ? 'unshift' : 'push';\n\n if (root) {\n const dynamic = path.startsWith(':');\n if (dynamic) return parent;\n\n const last = segments.length === 1;\n if (last) {\n const newRoute = {\n path,\n pathMatch,\n _module: () => module(),\n loadChildren: () =>\n module().then((m) => [\n {\n path: '',\n component: m.default,\n ...m.routeMeta,\n },\n ]),\n };\n\n routes?.[insert](newRoute as Route);\n return parent;\n }\n }\n\n if (root || node) {\n const current = root ? routes : parent._children;\n const found = current?.find((route: any) => route.path === path);\n\n if (found) {\n if (!found._children) {\n found._children = [];\n }\n\n found.pathMatch = pathMatch;\n } else {\n current?.[insert]({\n path,\n pathMatch,\n _module: () => module(),\n loadChildren: () =>\n module().then((m) => [\n {\n path: '',\n component: m.default,\n ...m.routeMeta,\n },\n ]),\n });\n }\n\n return (\n found ||\n (current?.[insert === 'unshift' ? 0 : current.length - 1] as Route)\n );\n }\n\n if (leaf) {\n parent?._children?.[insert]({\n path,\n pathMatch,\n _module: () => module(),\n loadChildren: () =>\n module().then((m) => [\n {\n path: '',\n component: m.default,\n ...m.routeMeta,\n },\n ]),\n });\n }\n\n if (parent._children) {\n parent.loadComponent = () =>\n parent._module().then((m: RouteExport) => m.default);\n parent.loadChildren = () =>\n parent._module().then((m: RouteExport) => {\n return [\n {\n path: '',\n children: parent._children,\n ...m.routeMeta,\n },\n ];\n });\n }\n\n return parent;\n }, {} as Route & { _module: () => Promise<RouteExport>; _children: any[] });\n\n return routes;\n },\n []\n );\n\n return routeConfigs;\n}\n\nexport const routes: Route[] = [...getRoutes(FILES)];\n","import { inject } from '@angular/core';\nimport { Route as NgRoute, Router } from '@angular/router';\nimport { ActivatedRoute } from '@angular/router';\n\ntype RouteOmitted =\n | 'component'\n | 'loadComponent'\n | 'loadChildren'\n | 'path'\n | 'pathMatch';\n\ntype RestrictedRoute = Omit<NgRoute, RouteOmitted>;\n\n/**\n * Defines additional route config metadata. This\n * object is merged into the route config with\n * the predefined file-based route.\n *\n * @usageNotes\n *\n * ```\n * import { Component } from '@angular/core';\n * import { defineRouteMeta } from '@analogjs/router';\n *\n * export const routeMeta = defineRouteMeta({\n * title: 'Welcome'\n * });\n *\n * @Component({\n * template: `Home`,\n * standalone: true,\n * })\n * export default class HomeComponent {}\n * ```\n *\n * @param route\n * @returns\n */\nexport const defineRouteMeta = (route: RestrictedRoute) => {\n return route;\n};\n\n/**\n * Returns the instance of Angular Router\n *\n * @returns The router\n */\nexport const injectRouter = () => {\n return inject(Router);\n};\n\n/**\n * Returns the instance of the Activate Route for the component\n *\n * @returns The activated route\n */\nexport const injectActivatedRoute = () => {\n return inject(ActivatedRoute);\n};\n","import { provideRouter, RouterFeatures } from '@angular/router';\nimport { routes } from './routes';\n\n/**\n * Sets up providers for the Angular router, and registers\n * file-based routes. Additional features can be provided\n * to further configure the behavior of the router.\n *\n * @param features\n * @returns Providers and features to configure the router with routes\n */\nexport const provideFileRouter = (...features: RouterFeatures[]) => {\n return provideRouter(routes, ...features);\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Route as NgRoute, Router } from '@angular/router';
|
|
2
|
+
import { ActivatedRoute } from '@angular/router';
|
|
3
|
+
declare type RouteOmitted = 'component' | 'loadComponent' | 'loadChildren' | 'path' | 'pathMatch';
|
|
4
|
+
declare type RestrictedRoute = Omit<NgRoute, RouteOmitted>;
|
|
5
|
+
/**
|
|
6
|
+
* Defines additional route config metadata. This
|
|
7
|
+
* object is merged into the route config with
|
|
8
|
+
* the predefined file-based route.
|
|
9
|
+
*
|
|
10
|
+
* @usageNotes
|
|
11
|
+
*
|
|
12
|
+
* ```
|
|
13
|
+
* import { Component } from '@angular/core';
|
|
14
|
+
* import { defineRouteMeta } from '@analogjs/router';
|
|
15
|
+
*
|
|
16
|
+
* export const routeMeta = defineRouteMeta({
|
|
17
|
+
* title: 'Welcome'
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* @Component({
|
|
21
|
+
* template: `Home`,
|
|
22
|
+
* standalone: true,
|
|
23
|
+
* })
|
|
24
|
+
* export default class HomeComponent {}
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @param route
|
|
28
|
+
* @returns
|
|
29
|
+
*/
|
|
30
|
+
export declare const defineRouteMeta: (route: RestrictedRoute) => RestrictedRoute;
|
|
31
|
+
/**
|
|
32
|
+
* Returns the instance of Angular Router
|
|
33
|
+
*
|
|
34
|
+
* @returns The router
|
|
35
|
+
*/
|
|
36
|
+
export declare const injectRouter: () => Router;
|
|
37
|
+
/**
|
|
38
|
+
* Returns the instance of the Activate Route for the component
|
|
39
|
+
*
|
|
40
|
+
* @returns The activated route
|
|
41
|
+
*/
|
|
42
|
+
export declare const injectActivatedRoute: () => ActivatedRoute;
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { RouterFeatures } from '@angular/router';
|
|
2
|
+
/**
|
|
3
|
+
* Sets up providers for the Angular router, and registers
|
|
4
|
+
* file-based routes. Additional features can be provided
|
|
5
|
+
* to further configure the behavior of the router.
|
|
6
|
+
*
|
|
7
|
+
* @param features
|
|
8
|
+
* @returns Providers and features to configure the router with routes
|
|
9
|
+
*/
|
|
10
|
+
export declare const provideFileRouter: (...features: RouterFeatures[]) => import("@angular/core").Provider[];
|
package/lib/routes.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Type } from '@angular/core';
|
|
2
|
+
import type { Route } from '@angular/router';
|
|
3
|
+
import { defineRouteMeta } from './define-route';
|
|
4
|
+
export declare type RouteExport = {
|
|
5
|
+
default: Type<unknown>;
|
|
6
|
+
routeMeta?: ReturnType<typeof defineRouteMeta>;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Function used to parse list of files and return
|
|
10
|
+
* configuration of routes.
|
|
11
|
+
*
|
|
12
|
+
* @param files
|
|
13
|
+
* @returns Array of routes
|
|
14
|
+
*/
|
|
15
|
+
export declare function getRoutes(files: Record<string, () => Promise<RouteExport>>): Route[];
|
|
16
|
+
export declare const routes: Route[];
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@analogjs/router",
|
|
3
|
+
"version": "0.1.0-alpha.0",
|
|
4
|
+
"description": "Filesystem-based routing for Angular",
|
|
5
|
+
"author": "Brandon Roberts <robertsbt@gmail.com>",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"angular",
|
|
8
|
+
"router",
|
|
9
|
+
"filesystem-routing",
|
|
10
|
+
"meta-framework"
|
|
11
|
+
],
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/analogjs/analog/issues"
|
|
15
|
+
},
|
|
16
|
+
"homepage": "https://analogjs.org",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/analogjs/analog.git"
|
|
20
|
+
},
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"@angular/core": "^14.0.0",
|
|
23
|
+
"@angular/router": "^14.0.0"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"tslib": "^2.0.0"
|
|
27
|
+
},
|
|
28
|
+
"module": "fesm2015/analogjs-router.mjs",
|
|
29
|
+
"es2020": "fesm2020/analogjs-router.mjs",
|
|
30
|
+
"esm2020": "esm2020/analogjs-router.mjs",
|
|
31
|
+
"fesm2020": "fesm2020/analogjs-router.mjs",
|
|
32
|
+
"fesm2015": "fesm2015/analogjs-router.mjs",
|
|
33
|
+
"typings": "index.d.ts",
|
|
34
|
+
"exports": {
|
|
35
|
+
"./package.json": {
|
|
36
|
+
"default": "./package.json"
|
|
37
|
+
},
|
|
38
|
+
".": {
|
|
39
|
+
"types": "./index.d.ts",
|
|
40
|
+
"esm2020": "./esm2020/analogjs-router.mjs",
|
|
41
|
+
"es2020": "./fesm2020/analogjs-router.mjs",
|
|
42
|
+
"es2015": "./fesm2015/analogjs-router.mjs",
|
|
43
|
+
"node": "./fesm2015/analogjs-router.mjs",
|
|
44
|
+
"default": "./fesm2020/analogjs-router.mjs"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"sideEffects": false
|
|
48
|
+
}
|