Skip to content

Commit 8228d7e

Browse files
authored
chore: prerelease 15.0.0-rc.0 (#322)
## Build - Update package to prelease version `15.0.0-rc.0` ## Documentation - Log prerelease `15.0.0-rc.0` changes
2 parents fb72ea9 + 3520133 commit 8228d7e

File tree

2 files changed

+288
-2
lines changed

2 files changed

+288
-2
lines changed

CHANGELOG.md

Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,291 @@
11
# Router Component Store changelog
22

3+
## 15.0.0-rc.0 (2024-09-03)
4+
5+
### Features
6+
7+
- `LocalRouterStore` matches `ActivatedRoute` more closely ([#309](https://github.com/ngworker/router-component-store/pull/309))
8+
- Use `ActivatedRoute` to serialize the router state for the local router store implementation (`LocalRouterStore`)
9+
- `LocalRouterStore.currentRoute$` matches `ActivatedRoute.snapshot`
10+
- Remove optional type parameter from `RouterStore#selectRouteData` ([#316](https://github.com/ngworker/router-component-store/pull/316))
11+
- Replace `MinimalRouteData` with `StrictRouteData` ([#319](https://github.com/ngworker/router-component-store/pull/319))
12+
- Change `RouterStore#routeData$` and `MinimalActivatedRouteSnapshot#data` types from `Data` to `StrictRouteData` ([#319](https://github.com/ngworker/router-component-store/pull/319))
13+
- Use strict and immutable route parameters ([#319](https://github.com/ngworker/router-component-store/pull/319), [#321](https://github.com/ngworker/router-component-store/pull/321))
14+
- Use strict and immutable query parameters ([#320](https://github.com/ngworker/router-component-store/pull/320))
15+
16+
**BREAKING CHANGES**
17+
18+
**`LocalRouterStore.currentRoute$` matches `ActivatedRoute.snapshot`**
19+
20+
This change in implementation will make the local router store more closely match `ActivatedRoute` while the global router store matches NgRx Router Store selectors. Through complex route configurations, the router store implementations are exercised to identify edge case differences between them and any breaking changes introduced to the local router store.
21+
22+
BEFORE:
23+
24+
```typescript
25+
// URL: /parent/child/grandchild
26+
27+
@Component({
28+
/* (...) */
29+
providers: [provideLocalRouterStore()],
30+
})
31+
export class ChildComponent implements OnInit {
32+
#route = inject(ActivatedRoute);
33+
#routerStore = inject(RouterStore);
34+
35+
ngOnInit() {
36+
const currentRouteSnapshot = this.#route.snapshot;
37+
console.log(currentRouteSnapshot.routeConfig.path);
38+
// -> "child"
39+
console.log(currentRouteSnapshot.url[0].path);
40+
// -> "child"
41+
42+
firstValueFrom(this.#routerStore.currentRoute$).then((currentRoute) => {
43+
console.log(currentRoute.routeConfig.path);
44+
// -> "grandchild"
45+
console.log(currentRoute.url[0].path);
46+
// -> "grandchild"
47+
});
48+
}
49+
}
50+
```
51+
52+
AFTER:
53+
54+
```typescript
55+
// URL: /parent/child/grandchild
56+
57+
@Component({
58+
/* (...) */
59+
providers: [provideLocalRouterStore()],
60+
})
61+
export class ChildComponent implements OnInit {
62+
#route = inject(ActivatedRoute);
63+
#routerStore = inject(RouterStore);
64+
65+
ngOnInit() {
66+
const currentRouteSnapshot = this.#route.snapshot;
67+
console.log(currentRouteSnapshot.routeConfig.path);
68+
// -> "child"
69+
console.log(currentRouteSnapshot.url[0].path);
70+
// -> "child"
71+
72+
firstValueFrom(this.#routerStore.currentRoute$).then((currentRoute) => {
73+
console.log(currentRoute.routeConfig.path);
74+
// -> "child"
75+
console.log(currentRoute.url[0].path);
76+
// -> "child"
77+
});
78+
}
79+
}
80+
```
81+
82+
**The type parameter is removed from `RouterStore#selectRouteData` for stricter typing and to enforce coercion**
83+
84+
BEFORE:
85+
86+
```typescript
87+
// heroes.component.ts
88+
// (...)
89+
import { RouterStore } from '@ngworker/router-component-store';
90+
@Component({
91+
// (...)
92+
})
93+
export class HeroesComponent {
94+
#routerStore = inject(RouterStore);
95+
limit$ = this.#routerStore.selectRouteData<number>('limit');
96+
}
97+
```
98+
99+
AFTER:
100+
101+
```typescript
102+
// heroes.component.ts
103+
// (...)
104+
import { RouterStore } from '@ngworker/router-component-store';
105+
@Component({
106+
// (...)
107+
})
108+
export class HeroesComponent {
109+
#routerStore = inject(RouterStore);
110+
limit$ = this.#routerStore.selectRouteData('limit').pipe(x => Number(x));
111+
```
112+
113+
**The `RouterStore#routeData$` selector emits `StrictRouteData` instead of `Data`**
114+
115+
BEFORE:
116+
117+
```typescript
118+
// heroes.component.ts
119+
// (...)
120+
import { RouterStore } from '@ngworker/router-component-store';
121+
@Component({
122+
// (...)
123+
})
124+
export class HeroesComponent {
125+
#routerStore = inject(RouterStore);
126+
limit$: Observable<number> = this.#routerStore.routeData$.pipe(
127+
map((routeData) => routeData['limit'])
128+
);
129+
}
130+
```
131+
132+
AFTER:
133+
134+
```typescript
135+
// heroes.component.ts
136+
// (...)
137+
import { RouterStore } from '@ngworker/router-component-store';
138+
@Component({
139+
// (...)
140+
})
141+
export class HeroesComponent {
142+
#routerStore = inject(RouterStore);
143+
limit$: Observable<number> = this.#routerStore.routeData$.pipe(
144+
map(routeData => routeData['limit']),
145+
map(x => Number(x))
146+
);
147+
```
148+
149+
**`RouterStore#routeParams$` and `MinimalActivatedRouteSnapshot#params` use `StrictRouteData` instead of `Params`. Members are read-only and of type `string | undefined` instead of `any`**
150+
151+
TypeScript will fail to compile application code that has assumed a route type parameter type other than `string | undefined`.
152+
153+
BEFORE:
154+
155+
```typescript
156+
// heroes.component.ts
157+
// (...)
158+
import { RouterStore } from '@ngworker/router-component-store';
159+
160+
@Component({
161+
// (...)
162+
})
163+
export class DashboardComponent {
164+
#routerStore = inject(RouterStore);
165+
166+
limit$: Observable<number> = this.#routerStore.routeParams$.pipe(
167+
map((params) => params['limit'])
168+
);
169+
}
170+
```
171+
172+
AFTER:
173+
174+
```typescript
175+
// heroes.component.ts
176+
// (...)
177+
import { RouterStore } from '@ngworker/router-component-store';
178+
179+
@Component({
180+
// (...)
181+
})
182+
export class DashboardComponent {
183+
#routerStore = inject(RouterStore);
184+
185+
limit$: Observable<number> = this.#routerStore.routeParams$.pipe(
186+
map((params) => Number(params['limit'] ?? 10))
187+
);
188+
}
189+
```
190+
191+
**`StrictRouteData` members are now read-only**
192+
193+
TypeScript will fail to compile application code that mutates route data data structures.
194+
195+
BEFORE:
196+
197+
```typescript
198+
// heroes.component.ts
199+
// (...)
200+
import { RouterStore } from '@ngworker/router-component-store';
201+
202+
@Component({
203+
// (...)
204+
})
205+
export class DashboardComponent {
206+
#routerStore = inject(RouterStore);
207+
208+
limit$: Observable<number> = this.#routerStore.routeData$.pipe(
209+
map((data) => {
210+
data['limit'] = Number(data['limit']);
211+
212+
return data;
213+
}),
214+
map((data) => data['limit'])
215+
);
216+
}
217+
```
218+
219+
AFTER:
220+
221+
```typescript
222+
// heroes.component.ts
223+
// (...)
224+
import { RouterStore } from '@ngworker/router-component-store';
225+
226+
@Component({
227+
// (...)
228+
})
229+
export class DashboardComponent {
230+
#routerStore = inject(RouterStore);
231+
232+
limit$: Observable<number> = this.#routerStore.routeData$.pipe(
233+
map((data) => Number(data['limit']))
234+
);
235+
}
236+
```
237+
238+
**`RouterStore#queryParams$` and `MinimalActivatedRouteSnapshot#queryParams` use `StrictRouteParams` instead of `Params`. Members are read-only and of type `string | undefined` instead of `any`**
239+
240+
TypeScript will fail to compile application code that has assumed a query parameter type other than `string | undefined`.
241+
242+
BEFORE:
243+
244+
```typescript
245+
// heroes.component.ts
246+
// (...)
247+
import { RouterStore } from '@ngworker/router-component-store';
248+
249+
@Component({
250+
// (...)
251+
})
252+
export class DashboardComponent {
253+
#routerStore = inject(RouterStore);
254+
255+
limit$: Observable<number> = this.#routerStore.queryParams$.pipe(
256+
map((params) => params['limit'])
257+
);
258+
}
259+
```
260+
261+
AFTER:
262+
263+
```typescript
264+
// heroes.component.ts
265+
// (...)
266+
import { RouterStore } from '@ngworker/router-component-store';
267+
268+
@Component({
269+
// (...)
270+
})
271+
export class DashboardComponent {
272+
#routerStore = inject(RouterStore);
273+
274+
limit$: Observable<number> = this.#routerStore.queryParams$.pipe(
275+
map((params) => Number(params['limit'] ?? 10))
276+
);
277+
}
278+
```
279+
280+
**Compatibility**
281+
282+
To avoid compatibility issues, we now require the same RxJS peer dependency as NgRx ComponentStore, namely at least RxJS version 7.5 ([#311](https://github.com/ngworker/router-component-store/pull/311)).
283+
284+
- Require Angular 15.0
285+
- Require `@ngrx/component-store` 15.0
286+
- Require RxJS 7.5
287+
- Require TypeScript 4.8
288+
3289
## 0.3.2 (2023-01-03)
4290
5291
### Performance optimizations

packages/router-component-store/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@ngworker/router-component-store",
3-
"version": "0.3.2",
4-
"description": "An Angular Router-connecting NgRx component store.",
3+
"version": "15.0.0-rc.0",
4+
"description": "A strictly typed lightweight alternative to NgRx Router Store (@ngrx/router-store) and ActivatedRoute",
55
"license": "MIT",
66
"peerDependencies": {
77
"@angular/core": "^15.0.0",

0 commit comments

Comments
 (0)