angular-typed-router 0.1.1-2 → 0.1.1-4
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/README.md +43 -24
- package/fesm2022/angular-typed-router.mjs +14 -3
- package/fesm2022/angular-typed-router.mjs.map +1 -1
- package/index.d.ts +4 -4
- package/package.json +1 -1
- package/schematics/ng-add/steps/add-declaration-file.js +2 -2
- package/schematics/ng-add/steps/add-declaration-file.js.map +1 -1
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@ Type-safe ergonomic primitives on top of Angular's standalone router. Automatica
|
|
|
7
7
|
## Why
|
|
8
8
|
|
|
9
9
|
Angular's router is powerful but untyped for URL literals – a misspelled path or an outdated segment only fails at runtime. This library lets your application declare routes once, then:
|
|
10
|
+
|
|
10
11
|
- Navigate with `TypedRouter.navigateByUrl(path)` where `path` is validated at compile time.
|
|
11
12
|
- Use `<a routerLink="...">` with type checking via an augmented `TypedRouterLink` directive.
|
|
12
13
|
- Build command tuples with correct literal segments (`Commands` type).
|
|
@@ -15,6 +16,10 @@ No decorators, no custom builders, no code generation – just TypeScript type i
|
|
|
15
16
|
|
|
16
17
|
## Installation
|
|
17
18
|
|
|
19
|
+
`ng add angular-ryped-router` will set up the package and create a declaration file for you.
|
|
20
|
+
|
|
21
|
+
Or install manually:
|
|
22
|
+
|
|
18
23
|
```bash
|
|
19
24
|
npm install angular-typed-router
|
|
20
25
|
# or
|
|
@@ -34,24 +39,24 @@ import { DashboardComponent } from './dashboard.component';
|
|
|
34
39
|
|
|
35
40
|
export const appRoutes = [
|
|
36
41
|
{ path: 'dashboard', component: DashboardComponent },
|
|
37
|
-
{ path: 'projects/:id', loadComponent: () => import('./project.component').then(m => m.ProjectComponent) },
|
|
38
|
-
{ path: '**', redirectTo: 'dashboard' }
|
|
42
|
+
{ path: 'projects/:id', loadComponent: () => import('./project.component').then((m) => m.ProjectComponent) },
|
|
43
|
+
{ path: '**', redirectTo: 'dashboard' },
|
|
39
44
|
] as const satisfies Routes;
|
|
40
45
|
```
|
|
41
46
|
|
|
42
47
|
2. Create the augmentation file so the library can “see” your routes:
|
|
43
48
|
|
|
44
49
|
```ts
|
|
45
|
-
//
|
|
50
|
+
// typed-router.d.ts (sibling to main.ts or inside src/ root)
|
|
46
51
|
import type { appRoutes } from './app/app.routes';
|
|
47
52
|
|
|
48
53
|
declare module 'angular-typed-router' {
|
|
49
54
|
interface UserTypedRoutes {
|
|
50
55
|
routes: typeof appRoutes;
|
|
51
56
|
}
|
|
52
|
-
// Customize route param types here
|
|
53
|
-
interface
|
|
54
|
-
|
|
57
|
+
// Customize route param types here, the keys of this interface match your route param names
|
|
58
|
+
interface RouteParamTypes {
|
|
59
|
+
id: `${number}`;
|
|
55
60
|
// other params...
|
|
56
61
|
}
|
|
57
62
|
}
|
|
@@ -63,13 +68,14 @@ declare module 'angular-typed-router' {
|
|
|
63
68
|
// tsconfig.app.json
|
|
64
69
|
{
|
|
65
70
|
"extends": "./tsconfig.json",
|
|
66
|
-
"compilerOptions": {
|
|
71
|
+
"compilerOptions": {},
|
|
67
72
|
"include": [
|
|
68
73
|
"src/**/*.ts",
|
|
69
|
-
"
|
|
74
|
+
"typed-router.d.ts" // <— add this line
|
|
70
75
|
]
|
|
71
76
|
}
|
|
72
77
|
```
|
|
78
|
+
|
|
73
79
|
If you have multiple tsconfigs, ensure the specific app tsconfig that drives the build/test includes the file.
|
|
74
80
|
|
|
75
81
|
4. Use the typed router & link:
|
|
@@ -83,12 +89,13 @@ import { TypedRouter, Path } from 'angular-typed-router';
|
|
|
83
89
|
template: `
|
|
84
90
|
<a routerLink="dashboard">Dashboard</a>
|
|
85
91
|
<a routerLink="projects/123">Project 123</a>
|
|
86
|
-
|
|
92
|
+
`,
|
|
87
93
|
})
|
|
88
94
|
export class NavComponent {
|
|
89
95
|
private readonly router = inject(TypedRouter);
|
|
90
96
|
|
|
91
|
-
go(p: Path) {
|
|
97
|
+
go(p: Path) {
|
|
98
|
+
// p must be one of the inferred paths
|
|
92
99
|
this.router.navigateByUrl(p);
|
|
93
100
|
}
|
|
94
101
|
|
|
@@ -104,7 +111,7 @@ If you try `this.router.navigateByUrl('projcts/123')` (typo) or `<a routerLink="
|
|
|
104
111
|
## Exports
|
|
105
112
|
|
|
106
113
|
```ts
|
|
107
|
-
import { TypedRouter, TypedRouterLink, Path, Commands, UserTypedRoutes } from 'angular-typed-router';
|
|
114
|
+
import { TypedRouter, TypedRouterLink, Path, Commands, UserTypedRoutes, RouteParamTypes } from 'angular-typed-router';
|
|
108
115
|
```
|
|
109
116
|
|
|
110
117
|
- `TypedRouter` – Extends Angular `Router`, overrides `navigateByUrl` & `navigate` signatures to accept `Path` / `Commands`.
|
|
@@ -113,12 +120,13 @@ import { TypedRouter, TypedRouterLink, Path, Commands, UserTypedRoutes } from 'a
|
|
|
113
120
|
- `Commands` – Union of tuple command arrays representing valid `Router.navigate()` inputs (each static segment as a literal, each parameter position as `string`).
|
|
114
121
|
- `UserTypedRoutes` – Empty interface you augment with your `routes` reference.
|
|
115
122
|
- `ExtractPathsFromRoutes<Routes>` – Utility type if you need to compute from an arbitrary `Routes` array manually.
|
|
123
|
+
- `RouteParamTypes` – Interface you can augment to specify types for route parameters by name (e.g. `id: ${number}`).
|
|
116
124
|
|
|
117
125
|
## How It Works
|
|
118
126
|
|
|
119
127
|
1. You augment `UserTypedRoutes` with the literal `const` route array.
|
|
120
128
|
2. Type utilities recursively walk the route tree (including lazily loaded routes via `loadChildren` returning `Route[]` or `{ routes }`).
|
|
121
|
-
3. Each navigable route (component / loadComponent / redirectTo) contributes a path string. Param segments (`:id`)
|
|
129
|
+
3. Each navigable route (component / loadComponent / redirectTo) contributes a path string. Param segments (e.g. `:id`) can be typed through declaration merging of `RouteParamTypes`.
|
|
122
130
|
4. Child paths are joined with parents to form final concrete path unions.
|
|
123
131
|
5. A tuple transformation creates the `Commands` variants.
|
|
124
132
|
|
|
@@ -127,6 +135,7 @@ All compile-time only; nothing ships to runtime.
|
|
|
127
135
|
## Lazy Routes
|
|
128
136
|
|
|
129
137
|
Works with any lazy route whose `loadChildren` resolves to:
|
|
138
|
+
|
|
130
139
|
- `Promise<Route[]>`
|
|
131
140
|
- `Promise<{ routes: Route[] }>` (Angular v17+ pattern)
|
|
132
141
|
|
|
@@ -141,59 +150,68 @@ Those child paths get prefixed (`admin/...`) in `Path` & `Commands`.
|
|
|
141
150
|
## Parameter Segments
|
|
142
151
|
|
|
143
152
|
A pattern `projects/:id/details/:section` produces a `Path` variant like:
|
|
153
|
+
|
|
144
154
|
```
|
|
145
|
-
'projects/' +
|
|
155
|
+
'projects/' + IdParamType + '/details/' + SectionParamType
|
|
146
156
|
```
|
|
157
|
+
|
|
147
158
|
and a `Commands` tuple like:
|
|
159
|
+
|
|
148
160
|
```
|
|
149
|
-
['projects',
|
|
161
|
+
['projects', IdParamType, 'details', SectionParamType]
|
|
150
162
|
```
|
|
151
|
-
|
|
163
|
+
|
|
164
|
+
You pass real runtime values for the `IdParamType` and `SectionParamType` positions. Empty string values and values like 'param/still-param' cannot currently be prevented at the type level without hurting DX (see Limitations).
|
|
152
165
|
|
|
153
166
|
## Usage Patterns
|
|
154
167
|
|
|
155
168
|
Navigate by full path (typed):
|
|
169
|
+
|
|
156
170
|
```ts
|
|
157
171
|
router.navigateByUrl('/dashboard');
|
|
158
172
|
```
|
|
173
|
+
|
|
159
174
|
Navigate with commands array:
|
|
175
|
+
|
|
160
176
|
```ts
|
|
161
177
|
router.navigate(['/', 'projects', someId]);
|
|
162
178
|
```
|
|
179
|
+
|
|
163
180
|
Generate a `UrlTree`:
|
|
181
|
+
|
|
164
182
|
```ts
|
|
165
183
|
router.createUrlTree(['/', 'projects', id]);
|
|
166
184
|
```
|
|
185
|
+
|
|
167
186
|
Template links:
|
|
187
|
+
|
|
168
188
|
```html
|
|
169
|
-
<a routerLink="/projects/42">Project 42</a>
|
|
170
|
-
<a [routerLink]="['/', 'projects', projectId]"></a>
|
|
189
|
+
<a routerLink="/projects/42">Project 42</a> <a [routerLink]="['/', 'projects', projectId]"></a>
|
|
171
190
|
```
|
|
172
191
|
|
|
173
|
-
|
|
174
192
|
## Augmentation Placement
|
|
175
193
|
|
|
176
194
|
Keep the augmentation in a `.d.ts` that is included by `tsconfig.app.json` (`include` array). If you see `Path` still as `never`, ensure:
|
|
195
|
+
|
|
177
196
|
- The augmentation file is included.
|
|
178
197
|
- The `routes` constant is `as const satisfies Routes`.
|
|
179
198
|
- No circular import (augmentation file should only import the routes, nothing else runtime-heavy).
|
|
180
199
|
|
|
181
200
|
## Limitations & Tradeoffs
|
|
182
201
|
|
|
183
|
-
| Concern
|
|
184
|
-
|
|
202
|
+
| Concern | Status / Rationale |
|
|
203
|
+
| ---------------------------------- | ------------------------------------------------------------------------------------- |
|
|
185
204
|
| `relativeTo` (relative navigation) | Not supported – all inferred `Path` / `Commands` are absolute. Use absolute commands. |
|
|
186
205
|
|
|
187
|
-
|
|
188
206
|
## ESLint Recommendation (Optional)
|
|
189
207
|
|
|
190
208
|
You can use `angular-typed-router-eslint` plugin to forbid untyped navigation calls.
|
|
191
209
|
|
|
192
210
|
## Troubleshooting
|
|
193
211
|
|
|
194
|
-
| Symptom
|
|
195
|
-
|
|
196
|
-
| `Path` is `never`
|
|
212
|
+
| Symptom | Fix |
|
|
213
|
+
| --------------------- | -------------------------------------------------------------- |
|
|
214
|
+
| `Path` is `never` | Check augmentation file is included in tsconfig. |
|
|
197
215
|
| Lazy children missing | Ensure promise resolves to `Route[]` or `{ routes: Route[] }`. |
|
|
198
216
|
|
|
199
217
|
## Contributing
|
|
@@ -205,4 +223,5 @@ PRs welcome.
|
|
|
205
223
|
MIT
|
|
206
224
|
|
|
207
225
|
---
|
|
226
|
+
|
|
208
227
|
Happy routing.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, Input, Directive } from '@angular/core';
|
|
2
|
+
import { Injectable, forwardRef, Input, Directive } from '@angular/core';
|
|
3
3
|
import { Router, RouterLink } from '@angular/router';
|
|
4
4
|
|
|
5
5
|
class TypedRouter extends Router {
|
|
@@ -27,12 +27,23 @@ class TypedRouterLink extends RouterLink {
|
|
|
27
27
|
super.routerLink = commandsOrUrlTree;
|
|
28
28
|
}
|
|
29
29
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: TypedRouterLink, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
30
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.2.4", type: TypedRouterLink, isStandalone: true, selector: "[routerLink]", inputs: { routerLink: "routerLink" },
|
|
30
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.2.4", type: TypedRouterLink, isStandalone: true, selector: "[routerLink]", inputs: { routerLink: "routerLink" }, providers: [
|
|
31
|
+
{
|
|
32
|
+
provide: RouterLink,
|
|
33
|
+
useExisting: forwardRef(() => TypedRouterLink),
|
|
34
|
+
}
|
|
35
|
+
], usesInheritance: true, ngImport: i0 });
|
|
31
36
|
}
|
|
32
37
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: TypedRouterLink, decorators: [{
|
|
33
38
|
type: Directive,
|
|
34
39
|
args: [{
|
|
35
|
-
selector: '[routerLink]'
|
|
40
|
+
selector: '[routerLink]',
|
|
41
|
+
providers: [
|
|
42
|
+
{
|
|
43
|
+
provide: RouterLink,
|
|
44
|
+
useExisting: forwardRef(() => TypedRouterLink),
|
|
45
|
+
}
|
|
46
|
+
]
|
|
36
47
|
}]
|
|
37
48
|
}], propDecorators: { routerLink: [{
|
|
38
49
|
type: Input
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"angular-typed-router.mjs","sources":["../tmp-esm2022/lib/router.js","../tmp-esm2022/lib/router-link.js","../tmp-esm2022/angular-typed-router.js"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { Router, } from '@angular/router';\nimport * as i0 from \"@angular/core\";\nexport class TypedRouter extends Router {\n navigate(commands, extras) {\n return super.navigate(commands, extras);\n }\n navigateByUrl(url, extras) {\n return super.navigateByUrl(url, extras);\n }\n createUrlTree(commands, navigationExtras) {\n return super.createUrlTree(commands, navigationExtras);\n }\n static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: \"12.0.0\", version: \"20.2.4\", ngImport: i0, type: TypedRouter, deps: null, target: i0.ɵɵFactoryTarget.Injectable });\n static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: \"12.0.0\", version: \"20.2.4\", ngImport: i0, type: TypedRouter, providedIn: 'root' });\n}\ni0.ɵɵngDeclareClassMetadata({ minVersion: \"12.0.0\", version: \"20.2.4\", ngImport: i0, type: TypedRouter, decorators: [{\n type: Injectable,\n args: [{\n providedIn: 'root',\n }]\n }] });\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vbGlicy90eXBlZC1yb3V0ZXIvc3JjL2xpYi9yb3V0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzQyxPQUFPLEVBR0wsTUFBTSxHQUdQLE1BQU0saUJBQWlCLENBQUM7O0FBTXpCLE1BQU0sT0FBTyxXQUFZLFNBQVEsTUFBTTtJQUM1QixRQUFRLENBQ2YsUUFBa0IsRUFDbEIsTUFBeUI7UUFFekIsT0FBTyxLQUFLLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUMxQyxDQUFDO0lBRVEsYUFBYSxDQUNwQixHQUFTLEVBQ1QsTUFBa0M7UUFFbEMsT0FBTyxLQUFLLENBQUMsYUFBYSxDQUFDLEdBQUcsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUMxQyxDQUFDO0lBRVEsYUFBYSxDQUNwQixRQUFrQixFQUNsQixnQkFBcUM7UUFFckMsT0FBTyxLQUFLLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO0lBQ3pELENBQUM7dUdBcEJVLFdBQVc7MkdBQVgsV0FBVyxjQUZWLE1BQU07OzJGQUVQLFdBQVc7a0JBSHZCLFVBQVU7bUJBQUM7b0JBQ1YsVUFBVSxFQUFFLE1BQU07aUJBQ25CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgTmF2aWdhdGlvbkJlaGF2aW9yT3B0aW9ucyxcbiAgTmF2aWdhdGlvbkV4dHJhcyxcbiAgUm91dGVyLFxuICBVcmxDcmVhdGlvbk9wdGlvbnMsXG4gIFVybFRyZWUsXG59IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBDb21tYW5kcywgUGF0aCB9IGZyb20gJy4vdHlwZWQtcm91dGVzJztcblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCcsXG59KVxuZXhwb3J0IGNsYXNzIFR5cGVkUm91dGVyIGV4dGVuZHMgUm91dGVyIHtcbiAgb3ZlcnJpZGUgbmF2aWdhdGUoXG4gICAgY29tbWFuZHM6IENvbW1hbmRzLFxuICAgIGV4dHJhcz86IE5hdmlnYXRpb25FeHRyYXNcbiAgKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIHN1cGVyLm5hdmlnYXRlKGNvbW1hbmRzLCBleHRyYXMpO1xuICB9XG5cbiAgb3ZlcnJpZGUgbmF2aWdhdGVCeVVybChcbiAgICB1cmw6IFBhdGgsXG4gICAgZXh0cmFzPzogTmF2aWdhdGlvbkJlaGF2aW9yT3B0aW9uc1xuICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICByZXR1cm4gc3VwZXIubmF2aWdhdGVCeVVybCh1cmwsIGV4dHJhcyk7XG4gIH1cblxuICBvdmVycmlkZSBjcmVhdGVVcmxUcmVlKFxuICAgIGNvbW1hbmRzOiBDb21tYW5kcyxcbiAgICBuYXZpZ2F0aW9uRXh0cmFzPzogVXJsQ3JlYXRpb25PcHRpb25zXG4gICk6IFVybFRyZWUge1xuICAgIHJldHVybiBzdXBlci5jcmVhdGVVcmxUcmVlKGNvbW1hbmRzLCBuYXZpZ2F0aW9uRXh0cmFzKTtcbiAgfVxufVxuIl19","import { Directive, Input } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport * as i0 from \"@angular/core\";\nexport class TypedRouterLink extends RouterLink {\n set routerLink(commandsOrUrlTree) {\n super.routerLink = commandsOrUrlTree;\n }\n static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: \"12.0.0\", version: \"20.2.4\", ngImport: i0, type: TypedRouterLink, deps: null, target: i0.ɵɵFactoryTarget.Directive });\n static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: \"14.0.0\", version: \"20.2.4\", type: TypedRouterLink, isStandalone: true, selector: \"[routerLink]\", inputs: { routerLink: \"routerLink\" }, usesInheritance: true, ngImport: i0 });\n}\ni0.ɵɵngDeclareClassMetadata({ minVersion: \"12.0.0\", version: \"20.2.4\", ngImport: i0, type: TypedRouterLink, decorators: [{\n type: Directive,\n args: [{\n selector: '[routerLink]'\n }]\n }], propDecorators: { routerLink: [{\n type: Input\n }] } });\n//# sourceMappingURL=data:application/json;base64,
|
|
1
|
+
{"version":3,"file":"angular-typed-router.mjs","sources":["../tmp-esm2022/lib/router.js","../tmp-esm2022/lib/router-link.js","../tmp-esm2022/angular-typed-router.js"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { Router, } from '@angular/router';\nimport * as i0 from \"@angular/core\";\nexport class TypedRouter extends Router {\n navigate(commands, extras) {\n return super.navigate(commands, extras);\n }\n navigateByUrl(url, extras) {\n return super.navigateByUrl(url, extras);\n }\n createUrlTree(commands, navigationExtras) {\n return super.createUrlTree(commands, navigationExtras);\n }\n static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: \"12.0.0\", version: \"20.2.4\", ngImport: i0, type: TypedRouter, deps: null, target: i0.ɵɵFactoryTarget.Injectable });\n static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: \"12.0.0\", version: \"20.2.4\", ngImport: i0, type: TypedRouter, providedIn: 'root' });\n}\ni0.ɵɵngDeclareClassMetadata({ minVersion: \"12.0.0\", version: \"20.2.4\", ngImport: i0, type: TypedRouter, decorators: [{\n type: Injectable,\n args: [{\n providedIn: 'root',\n }]\n }] });\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vbGlicy90eXBlZC1yb3V0ZXIvc3JjL2xpYi9yb3V0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzQyxPQUFPLEVBR0wsTUFBTSxHQUdQLE1BQU0saUJBQWlCLENBQUM7O0FBTXpCLE1BQU0sT0FBTyxXQUFZLFNBQVEsTUFBTTtJQUM1QixRQUFRLENBQ2YsUUFBa0IsRUFDbEIsTUFBeUI7UUFFekIsT0FBTyxLQUFLLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUMxQyxDQUFDO0lBRVEsYUFBYSxDQUNwQixHQUFTLEVBQ1QsTUFBa0M7UUFFbEMsT0FBTyxLQUFLLENBQUMsYUFBYSxDQUFDLEdBQUcsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUMxQyxDQUFDO0lBRVEsYUFBYSxDQUNwQixRQUFrQixFQUNsQixnQkFBcUM7UUFFckMsT0FBTyxLQUFLLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO0lBQ3pELENBQUM7dUdBcEJVLFdBQVc7MkdBQVgsV0FBVyxjQUZWLE1BQU07OzJGQUVQLFdBQVc7a0JBSHZCLFVBQVU7bUJBQUM7b0JBQ1YsVUFBVSxFQUFFLE1BQU07aUJBQ25CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgTmF2aWdhdGlvbkJlaGF2aW9yT3B0aW9ucyxcbiAgTmF2aWdhdGlvbkV4dHJhcyxcbiAgUm91dGVyLFxuICBVcmxDcmVhdGlvbk9wdGlvbnMsXG4gIFVybFRyZWUsXG59IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBDb21tYW5kcywgUGF0aCB9IGZyb20gJy4vdHlwZWQtcm91dGVzJztcblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCcsXG59KVxuZXhwb3J0IGNsYXNzIFR5cGVkUm91dGVyIGV4dGVuZHMgUm91dGVyIHtcbiAgb3ZlcnJpZGUgbmF2aWdhdGUoXG4gICAgY29tbWFuZHM6IENvbW1hbmRzLFxuICAgIGV4dHJhcz86IE5hdmlnYXRpb25FeHRyYXNcbiAgKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIHN1cGVyLm5hdmlnYXRlKGNvbW1hbmRzLCBleHRyYXMpO1xuICB9XG5cbiAgb3ZlcnJpZGUgbmF2aWdhdGVCeVVybChcbiAgICB1cmw6IFBhdGgsXG4gICAgZXh0cmFzPzogTmF2aWdhdGlvbkJlaGF2aW9yT3B0aW9uc1xuICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICByZXR1cm4gc3VwZXIubmF2aWdhdGVCeVVybCh1cmwsIGV4dHJhcyk7XG4gIH1cblxuICBvdmVycmlkZSBjcmVhdGVVcmxUcmVlKFxuICAgIGNvbW1hbmRzOiBDb21tYW5kcyxcbiAgICBuYXZpZ2F0aW9uRXh0cmFzPzogVXJsQ3JlYXRpb25PcHRpb25zXG4gICk6IFVybFRyZWUge1xuICAgIHJldHVybiBzdXBlci5jcmVhdGVVcmxUcmVlKGNvbW1hbmRzLCBuYXZpZ2F0aW9uRXh0cmFzKTtcbiAgfVxufVxuIl19","import { Directive, forwardRef, Input } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport * as i0 from \"@angular/core\";\nexport class TypedRouterLink extends RouterLink {\n set routerLink(commandsOrUrlTree) {\n super.routerLink = commandsOrUrlTree;\n }\n static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: \"12.0.0\", version: \"20.2.4\", ngImport: i0, type: TypedRouterLink, deps: null, target: i0.ɵɵFactoryTarget.Directive });\n static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: \"14.0.0\", version: \"20.2.4\", type: TypedRouterLink, isStandalone: true, selector: \"[routerLink]\", inputs: { routerLink: \"routerLink\" }, providers: [\n {\n provide: RouterLink,\n useExisting: forwardRef(() => TypedRouterLink),\n }\n ], usesInheritance: true, ngImport: i0 });\n}\ni0.ɵɵngDeclareClassMetadata({ minVersion: \"12.0.0\", version: \"20.2.4\", ngImport: i0, type: TypedRouterLink, decorators: [{\n type: Directive,\n args: [{\n selector: '[routerLink]',\n providers: [\n {\n provide: RouterLink,\n useExisting: forwardRef(() => TypedRouterLink),\n }\n ]\n }]\n }], propDecorators: { routerLink: [{\n type: Input\n }] } });\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGVyLWxpbmsuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9saWJzL3R5cGVkLXJvdXRlci9zcmMvbGliL3JvdXRlci1saW5rLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM3RCxPQUFPLEVBQUUsVUFBVSxFQUFXLE1BQU0saUJBQWlCLENBQUM7O0FBWXRELE1BQU0sT0FBTyxlQUFnQixTQUFRLFVBQVU7SUFDN0MsSUFDYSxVQUFVLENBQUMsaUJBQStEO1FBQ3JGLEtBQUssQ0FBQyxVQUFVLEdBQUcsaUJBQWlCLENBQUM7SUFDdkMsQ0FBQzt1R0FKVSxlQUFlOzJGQUFmLGVBQWUsaUdBUGY7WUFDVDtnQkFDRSxPQUFPLEVBQUUsVUFBVTtnQkFDbkIsV0FBVyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxlQUFlLENBQUM7YUFDL0M7U0FDRjs7MkZBRVUsZUFBZTtrQkFUM0IsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsY0FBYztvQkFDeEIsU0FBUyxFQUFFO3dCQUNUOzRCQUNFLE9BQU8sRUFBRSxVQUFVOzRCQUNuQixXQUFXLEVBQUUsVUFBVSxDQUFDLEdBQUcsRUFBRSxnQkFBZ0IsQ0FBQzt5QkFDL0M7cUJBQ0Y7aUJBQ0Y7OEJBR2MsVUFBVTtzQkFEdEIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERpcmVjdGl2ZSwgZm9yd2FyZFJlZiwgSW5wdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFJvdXRlckxpbmssIFVybFRyZWUgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgQ29tbWFuZHMsIFBhdGggfSBmcm9tICcuL3R5cGVkLXJvdXRlcyc7XG5cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ1tyb3V0ZXJMaW5rXScsXG4gIHByb3ZpZGVyczogW1xuICAgIHtcbiAgICAgIHByb3ZpZGU6IFJvdXRlckxpbmssXG4gICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBUeXBlZFJvdXRlckxpbmspLFxuICAgIH1cbiAgXVxufSlcbmV4cG9ydCBjbGFzcyBUeXBlZFJvdXRlckxpbmsgZXh0ZW5kcyBSb3V0ZXJMaW5rIHtcbiAgQElucHV0KClcbiAgb3ZlcnJpZGUgc2V0IHJvdXRlckxpbmsoY29tbWFuZHNPclVybFRyZWU6IENvbW1hbmRzIHwgUGF0aCB8IFVybFRyZWUgfCBudWxsIHwgdW5kZWZpbmVkKSB7XG4gICAgc3VwZXIucm91dGVyTGluayA9IGNvbW1hbmRzT3JVcmxUcmVlO1xuICB9XG59XG4iXX0=","/**\n * Generated bundle index. Do not edit.\n */\nexport * from './index';\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5ndWxhci10eXBlZC1yb3V0ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9saWJzL3R5cGVkLXJvdXRlci9zcmMvYW5ndWxhci10eXBlZC1yb3V0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLFNBQVMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogR2VuZXJhdGVkIGJ1bmRsZSBpbmRleC4gRG8gbm90IGVkaXQuXG4gKi9cblxuZXhwb3J0ICogZnJvbSAnLi9pbmRleCc7XG4iXX0="],"names":[],"mappings":"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"}
|
package/index.d.ts
CHANGED
|
@@ -16,10 +16,10 @@ declare const __rootCatchAll: unique symbol;
|
|
|
16
16
|
type RootCatchAll = string & {
|
|
17
17
|
readonly [__rootCatchAll]: true;
|
|
18
18
|
};
|
|
19
|
-
interface
|
|
19
|
+
interface RouteParamTypes {
|
|
20
20
|
}
|
|
21
|
-
type
|
|
22
|
-
type _ReplaceParams<S extends string> = S extends `${infer Start}:${
|
|
21
|
+
type ParamValueType<Name extends string> = Name extends keyof RouteParamTypes ? RouteParamTypes[Name] : never;
|
|
22
|
+
type _ReplaceParams<S extends string> = S extends `${infer Start}:${infer Param}/${infer Rest}` ? `${Start}${ParamValueType<Param>}/${_ReplaceParams<Rest>}` : S extends `${infer Start}:${infer Param}` ? `${Start}${ParamValueType<Param>}` : S extends `${infer Start}**/${infer Rest}` ? `${Start}${string}/${_ReplaceParams<Rest>}` : S extends `${infer Start}**` ? Start extends '' ? RootCatchAll : `${Start}${string}` : S;
|
|
23
23
|
type ReplaceParams<S extends string> = _ReplaceParams<S>;
|
|
24
24
|
|
|
25
25
|
type PathOrEmptyString<R extends Route> = R['path'] extends string ? R['path'] : '';
|
|
@@ -65,4 +65,4 @@ declare class TypedRouterLink extends RouterLink {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
export { TypedRouter, TypedRouterLink };
|
|
68
|
-
export type {
|
|
68
|
+
export type { Commands, ExtractPathsFromRoutes, Path, RouteParamTypes, UserTypedRoutes };
|
package/package.json
CHANGED
|
@@ -21,7 +21,7 @@ const addDeclarationFile = (options) => (host, context) => __awaiter(void 0, voi
|
|
|
21
21
|
if (project &&
|
|
22
22
|
project.extensions['projectType'] === workspace_models_1.ProjectType.Application) {
|
|
23
23
|
const projectRoot = project.root;
|
|
24
|
-
const augmentationFileName = '
|
|
24
|
+
const augmentationFileName = 'typed-router.d.ts';
|
|
25
25
|
const declarationFilePath = (0, path_1.join)(projectRoot, augmentationFileName);
|
|
26
26
|
// TODO: Check if app.routes.ts exists and if it has the correct export
|
|
27
27
|
const augmentationFileContent = `import type { routes } from './src/app/app.routes';
|
|
@@ -30,7 +30,7 @@ declare module 'angular-typed-router' {
|
|
|
30
30
|
interface UserTypedRoutes {
|
|
31
31
|
routes: typeof routes;
|
|
32
32
|
}
|
|
33
|
-
interface
|
|
33
|
+
interface RouteParamTypes {
|
|
34
34
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add-declaration-file.js","sourceRoot":"","sources":["../../../../../../libs/typed-router/schematics/ng-add/steps/add-declaration-file.ts"],"names":[],"mappings":";;;;;;;;;;;;AAEA,yDAA4D;AAC5D,mFAA2E;AAC3E,+BAA+C;AAC/C,qEAAiE;AAE1D,MAAM,kBAAkB,GAC7B,CAAC,OAAe,EAAE,EAAE,CAAC,CAAO,IAAU,EAAE,OAAyB,EAAE,EAAE;;IACnE,MAAM,SAAS,GAAG,MAAM,IAAA,uBAAa,EAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,OAAQ,CAAC,CAAC;IACzD,IACE,OAAO;QACP,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,KAAK,8BAAW,CAAC,WAAW,EAC7D,CAAC;QACD,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;QACjC,MAAM,oBAAoB,GAAG,
|
|
1
|
+
{"version":3,"file":"add-declaration-file.js","sourceRoot":"","sources":["../../../../../../libs/typed-router/schematics/ng-add/steps/add-declaration-file.ts"],"names":[],"mappings":";;;;;;;;;;;;AAEA,yDAA4D;AAC5D,mFAA2E;AAC3E,+BAA+C;AAC/C,qEAAiE;AAE1D,MAAM,kBAAkB,GAC7B,CAAC,OAAe,EAAE,EAAE,CAAC,CAAO,IAAU,EAAE,OAAyB,EAAE,EAAE;;IACnE,MAAM,SAAS,GAAG,MAAM,IAAA,uBAAa,EAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,OAAQ,CAAC,CAAC;IACzD,IACE,OAAO;QACP,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,KAAK,8BAAW,CAAC,WAAW,EAC7D,CAAC;QACD,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;QACjC,MAAM,oBAAoB,GAAG,mBAAmB,CAAC;QACjD,MAAM,mBAAmB,GAAG,IAAA,WAAI,EAAC,WAAW,EAAE,oBAAoB,CAAC,CAAC;QACpE,uEAAuE;QACvE,MAAM,uBAAuB,GAAG;;;;;;;;;;CAUrC,CAAC;QACI,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,uBAAuB,CAAC,CAAC;QAE1D,MAAM,aAAa,GAAG,MAAA,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,0CAAE,OAAO,0CAAE,QAAQ,CAAC;QACvE,MAAM,YAAY,GAAG,MAAA,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,0CAAE,OAAO,0CAAE,QAAQ,CAAC;QAErE,IAAI,aAAa,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE,CAAC;YACvD,4BAA4B,CAAC,IAAI,EAAE,aAAa,EAAE,mBAAmB,CAAC,CAAC;QACzE,CAAC;QACD,IAAI,YAAY,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;YACrD,4BAA4B,CAAC,IAAI,EAAE,YAAY,EAAE,mBAAmB,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,MAAM,CAAC,IAAI,CACjB,YAAY,OAAO,CAAC,OAAO,uCAAuC,CACnE,CAAC;IACJ,CAAC;AACH,CAAC,CAAA,CAAC;AAvCS,QAAA,kBAAkB,sBAuC3B;AAEJ,SAAS,4BAA4B,CACnC,IAAU,EACV,YAAoB,EACpB,mBAA2B;IAE3B,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,IAAI,oBAAQ,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QAE9C,MAAM,YAAY,GAAI,IAAI,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,CAAc,IAAI,EAAE,CAAC;QAE/D,MAAM,YAAY,GAAG,IAAA,eAAQ,EAAC,IAAA,cAAO,EAAC,YAAY,CAAC,EAAE,mBAAmB,CAAC,CAAC;QAE1E,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;YACzC,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAChC,IAAI,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,EAAE,YAAY,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;AACH,CAAC"}
|