diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a0a015..10170b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,215 @@ # Router Component Store changelog +## 15.0.0-rc.0 (2024-09-03) + +### Features + +- Remove optional type parameter from `RouterStore#selectRouteData` +- Replace `MinimalRouteData` with `StrictRouteData` +- Change `RouterStore#routeData$` and `MinimalActivatedRouteSnapshot#data` types from `Data` to `StrictRouteData` +- Use strict and immutable route parameters +- Use strict and immutable query parameters + +**BREAKING CHANGES** + +The type parameter is removed from `RouterStore#selectRouteData` for stricter typing and to enforce coercion. + +BEFORE: + +```typescript +// heroes.component.ts +// (...) +import { RouterStore } from '@ngworker/router-component-store'; +@Component({ + // (...) +}) +export class HeroesComponent { + #routerStore = inject(RouterStore); + limit$ = this.#routerStore.selectRouteData('limit'); +} +``` + +AFTER: + +```typescript +// heroes.component.ts +// (...) +import { RouterStore } from '@ngworker/router-component-store'; +@Component({ + // (...) +}) +export class HeroesComponent { + #routerStore = inject(RouterStore); + limit$ = this.#routerStore.selectRouteData('limit').pipe(x => Number(x)); +``` + +The `RouterStore#routeData$` selector emits `StrictRouteData` instead of `Data`. + +BEFORE: + +```typescript +// heroes.component.ts +// (...) +import { RouterStore } from '@ngworker/router-component-store'; +@Component({ + // (...) +}) +export class HeroesComponent { + #routerStore = inject(RouterStore); + limit$: Observable = this.#routerStore.routeData$.pipe( + map((routeData) => routeData['limit']) + ); +} +``` + +AFTER: + +```typescript +// heroes.component.ts +// (...) +import { RouterStore } from '@ngworker/router-component-store'; +@Component({ + // (...) +}) +export class HeroesComponent { + #routerStore = inject(RouterStore); + limit$: Observable = this.#routerStore.routeData$.pipe( + map(routeData => routeData['limit']), + map(x => Number(x)) + ); +``` + +`RouterStore#routeParams$` and `MinimalActivatedRouteSnapshot#params` use `StrictRouteData` instead of `Params`. Members are read-only and of type `string | undefined` instead of `any`. + +TypeScript will fail to compile application code that has assumed a route type parameter type other than `string | undefined`. + +BEFORE: + +```typescript +// heroes.component.ts +// (...) +import { RouterStore } from '@ngworker/router-component-store'; + +@Component({ + // (...) +}) +export class DashboardComponent { + #routerStore = inject(RouterStore); + + limit$: Observable = this.#routerStore.routeParams$.pipe( + map((params) => params['limit']) + ); +} +``` + +AFTER: + +```typescript +// heroes.component.ts +// (...) +import { RouterStore } from '@ngworker/router-component-store'; + +@Component({ + // (...) +}) +export class DashboardComponent { + #routerStore = inject(RouterStore); + + limit$: Observable = this.#routerStore.routeParams$.pipe( + map((params) => Number(params['limit'] ?? 10)) + ); +} +``` + +`StrictRouteData` members are now read-only. + +TypeScript will fail to compile application code that mutates route data data structures. + +BEFORE: + +```typescript +// heroes.component.ts +// (...) +import { RouterStore } from '@ngworker/router-component-store'; + +@Component({ + // (...) +}) +export class DashboardComponent { + #routerStore = inject(RouterStore); + + limit$: Observable = this.#routerStore.routeData$.pipe( + map((data) => { + data['limit'] = Number(data['limit']); + + return data; + }), + map((data) => data['limit']) + ); +} +``` + +AFTER: + +```typescript +// heroes.component.ts +// (...) +import { RouterStore } from '@ngworker/router-component-store'; + +@Component({ + // (...) +}) +export class DashboardComponent { + #routerStore = inject(RouterStore); + + limit$: Observable = this.#routerStore.routeData$.pipe( + map((data) => Number(data['limit'])) + ); +} +``` + +`RouterStore#queryParams$` and `MinimalActivatedRouteSnapshot#queryParams` use `StrictRouteParams` instead of `Params`. Members are read-only and of type `string | undefined` instead of `any`. + +TypeScript will fail to compile application code that has assumed a query parameter type other than `string | undefined`. + +BEFORE: + +```typescript +// heroes.component.ts +// (...) +import { RouterStore } from '@ngworker/router-component-store'; + +@Component({ + // (...) +}) +export class DashboardComponent { + #routerStore = inject(RouterStore); + + limit$: Observable = this.#routerStore.queryParams$.pipe( + map((params) => params['limit']) + ); +} +``` + +AFTER: + +```typescript +// heroes.component.ts +// (...) +import { RouterStore } from '@ngworker/router-component-store'; + +@Component({ + // (...) +}) +export class DashboardComponent { + #routerStore = inject(RouterStore); + + limit$: Observable = this.#routerStore.queryParams$.pipe( + map((params) => Number(params['limit'] ?? 10)) + ); +} +``` + ## 0.3.2 (2023-01-03) ### Performance optimizations