@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 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,3 @@
1
+ export { routes } from './lib/routes';
2
+ export { defineRouteMeta, injectActivatedRoute, injectRouter, } from './lib/define-route';
3
+ export { provideFileRouter } from './lib/provide-file-routes';
@@ -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[];
@@ -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
+ }