@ngrx/signals 19.2.1 → 20.0.0-rc.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.
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { Injectable, inject, assertInInjectionContext, Injector, untracked } from '@angular/core';
3
- import { Subject, filter, map, tap, merge } from 'rxjs';
3
+ import { Subject, filter, map, queueScheduler, tap, merge } from 'rxjs';
4
4
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
5
5
  import { signalStoreFeature, type, withHooks, getState, patchState } from '@ngrx/signals';
6
6
 
@@ -54,18 +54,18 @@ class BaseEvents {
54
54
  * ```
55
55
  */
56
56
  class Events extends BaseEvents {
57
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.3", ngImport: i0, type: Events, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
58
- /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.3", ngImport: i0, type: Events, providedIn: 'root' });
57
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: Events, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
58
+ /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: Events, providedIn: 'root' });
59
59
  }
60
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.3", ngImport: i0, type: Events, decorators: [{
60
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: Events, decorators: [{
61
61
  type: Injectable,
62
62
  args: [{ providedIn: 'root' }]
63
63
  }] });
64
64
  class ReducerEvents extends BaseEvents {
65
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.3", ngImport: i0, type: ReducerEvents, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
66
- /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.3", ngImport: i0, type: ReducerEvents, providedIn: 'root' });
65
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: ReducerEvents, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
66
+ /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: ReducerEvents, providedIn: 'root' });
67
67
  }
68
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.3", ngImport: i0, type: ReducerEvents, decorators: [{
68
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: ReducerEvents, decorators: [{
69
69
  type: Injectable,
70
70
  args: [{ providedIn: 'root' }]
71
71
  }] });
@@ -114,12 +114,12 @@ class Dispatcher {
114
114
  events = inject(Events);
115
115
  dispatch(event) {
116
116
  this.reducerEvents[EVENTS].next(event);
117
- this.events[EVENTS].next(event);
117
+ queueScheduler.schedule(() => this.events[EVENTS].next(event));
118
118
  }
119
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.3", ngImport: i0, type: Dispatcher, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
120
- /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.3", ngImport: i0, type: Dispatcher, providedIn: 'root' });
119
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: Dispatcher, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
120
+ /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: Dispatcher, providedIn: 'root' });
121
121
  }
122
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.3", ngImport: i0, type: Dispatcher, decorators: [{
122
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: Dispatcher, decorators: [{
123
123
  type: Injectable,
124
124
  args: [{ providedIn: 'root' }]
125
125
  }] });
@@ -1 +1 @@
1
- {"version":3,"file":"ngrx-signals-events.mjs","sources":["../../../../modules/signals/events/src/case-reducer.ts","../../../../modules/signals/events/src/events-service.ts","../../../../modules/signals/events/src/dispatcher.ts","../../../../modules/signals/events/src/event-creator.ts","../../../../modules/signals/events/src/event-creator-group.ts","../../../../modules/signals/events/src/inject-dispatch.ts","../../../../modules/signals/events/src/event-instance.ts","../../../../modules/signals/events/src/with-effects.ts","../../../../modules/signals/events/src/with-reducer.ts","../../../../modules/signals/events/ngrx-signals-events.ts"],"sourcesContent":["import { PartialStateUpdater } from '@ngrx/signals';\nimport { EventCreator } from './event-creator';\n\nexport type CaseReducerResult<\n State extends object,\n EventCreators extends EventCreator<string, any>[]\n> = {\n reducer: CaseReducer<State, EventCreators>;\n events: EventCreators;\n};\n\ntype CaseReducer<\n State extends object,\n EventCreators extends EventCreator<string, any>[]\n> = (\n event: { [K in keyof EventCreators]: ReturnType<EventCreators[K]> }[number],\n state: State\n) =>\n | Partial<State>\n | PartialStateUpdater<State>\n | Array<Partial<State> | PartialStateUpdater<State>>;\n\n/**\n * @experimental\n * @description\n *\n * Creates a case reducer that can be used with the `withReducer` feature.\n */\nexport function on<\n State extends object,\n EventCreators extends EventCreator<string, any>[]\n>(\n ...args: [\n ...events: [...EventCreators],\n reducer: CaseReducer<NoInfer<State>, NoInfer<EventCreators>>\n ]\n): CaseReducerResult<State, EventCreators> {\n const reducer = args.pop() as CaseReducer<State, EventCreators>;\n const events = args as unknown as EventCreators;\n\n return { reducer, events };\n}\n","import { Injectable } from '@angular/core';\nimport {\n filter,\n map,\n MonoTypeOperatorFunction,\n Observable,\n Subject,\n} from 'rxjs';\nimport { EventInstance } from './event-instance';\nimport { EventCreator } from './event-creator';\n\nexport const EVENTS = Symbol();\nexport const SOURCE_TYPE = Symbol();\n\nabstract class BaseEvents {\n /**\n * @internal\n */\n readonly [EVENTS] = new Subject<EventInstance<string, unknown>>();\n\n on(): Observable<EventInstance<string, unknown>>;\n on<EventCreators extends EventCreator<string, any>[]>(\n ...events: [...EventCreators]\n ): Observable<\n { [K in keyof EventCreators]: ReturnType<EventCreators[K]> }[number]\n >;\n on(\n ...events: EventCreator<string, unknown>[]\n ): Observable<EventInstance<string, unknown>> {\n return this[EVENTS].pipe(filterByType(events), withSourceType());\n }\n}\n\n/**\n * @experimental\n * @description\n *\n * Globally provided service for listening to dispatched events.\n *\n * @usageNotes\n *\n * ```ts\n * import { event, Events } from '@ngrx/signals/events';\n *\n * const increment = event('[Counter Page] Increment');\n *\n * \\@Component({ \\/* ... *\\/ })\n * class Counter {\n * readonly #events = inject(Events);\n *\n * constructor() {\n * this.#events\n * .on(increment)\n * .pipe(takeUntilDestroyed())\n * .subscribe(() => \\/* handle increment event *\\/);\n * }\n * }\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class Events extends BaseEvents {}\n\n@Injectable({ providedIn: 'root' })\nexport class ReducerEvents extends BaseEvents {}\n\nfunction filterByType<T extends EventInstance<string, unknown>>(\n events: EventCreator<string, unknown>[]\n): MonoTypeOperatorFunction<T> {\n if (events.length === 0) {\n return (source$) => source$;\n }\n\n const eventMap = toEventCreatorMap(events);\n return filter<T>(({ type }) => !!eventMap[type]);\n}\n\nfunction toEventCreatorMap(\n events: EventCreator<string, unknown>[]\n): Record<string, EventCreator<string, unknown>> {\n return events.reduce((acc, event) => ({ ...acc, [event.type]: event }), {});\n}\n\nfunction withSourceType<\n T extends EventInstance<string, unknown>\n>(): MonoTypeOperatorFunction<T> {\n return map(({ ...event }) => {\n Object.defineProperty(event, SOURCE_TYPE, { value: event.type });\n return event;\n });\n}\n","import { inject, Injectable } from '@angular/core';\nimport { EventInstance } from './event-instance';\nimport { Events, EVENTS, ReducerEvents } from './events-service';\n\n/**\n * @experimental\n * @description\n *\n * Globally provided service for dispatching events.\n *\n * @usageNotes\n *\n * ```ts\n * import { Dispatcher, event } from '@ngrx/signals/events';\n *\n * const increment = event('[Counter Page] Increment');\n *\n * \\@Component({ \\/* ... *\\/ })\n * class Counter {\n * readonly #dispatcher = inject(Dispatcher);\n *\n * increment(): void {\n * this.#dispatcher.dispatch(increment());\n * }\n * }\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class Dispatcher {\n protected readonly reducerEvents = inject(ReducerEvents);\n protected readonly events = inject(Events);\n\n dispatch(event: EventInstance<string, unknown>): void {\n this.reducerEvents[EVENTS].next(event);\n this.events[EVENTS].next(event);\n }\n}\n","import { EventInstance } from './event-instance';\n\n/**\n * @experimental\n */\nexport type EventCreator<Type extends string, Payload> = ((\n payload: Payload\n) => EventInstance<Type, Payload>) & { type: Type };\n\nexport function event<Type extends string>(\n type: Type\n): EventCreator<Type, void>;\nexport function event<Type extends string, Payload>(\n type: Type,\n payload: Payload\n): EventCreator<Type, Payload>;\n/**\n * @experimental\n * @description\n *\n * Creates an event creator.\n *\n * @usageNotes\n *\n * ### Creating an event creator without payload\n *\n * ```ts\n * import { event } from '@ngrx/signals/events';\n *\n * const increment = event('[Counter Page] Increment');\n * ```\n *\n * ### Creating an event creator with payload\n *\n * ```ts\n * import { type } from '@ngrx/signals';\n * import { event } from '@ngrx/signals/events';\n *\n * const set = event('[Counter Page] Set', type<number>());\n * ```\n */\nexport function event(type: string): EventCreator<string, any> {\n const creator = (payload?: unknown) => ({ type, payload });\n (creator as any).type = type;\n\n return creator as EventCreator<string, unknown>;\n}\n","import { Prettify } from '@ngrx/signals';\nimport { event, EventCreator } from './event-creator';\n\ntype EventType<\n Source extends string,\n EventName extends string\n> = `[${Source}] ${EventName}`;\n\ntype EventCreatorGroup<\n Source extends string,\n Events extends Record<string, any>\n> = {\n [EventName in keyof Events]: EventName extends string\n ? EventCreator<EventType<Source, EventName>, Events[EventName]>\n : never;\n};\n\n/**\n * @experimental\n * @description\n *\n * Creates a group of event creators.\n *\n * @usageNotes\n *\n * ```ts\n * import { type } from '@ngrx/signals';\n * import { eventGroup } from '@ngrx/signals/events';\n *\n * const counterPageEvents = eventGroup({\n * source: 'Counter Page',\n * events: {\n * increment: type<void>(),\n * decrement: type<void>(),\n * set: type<number>(),\n * },\n * });\n * ```\n */\nexport function eventGroup<\n Source extends string,\n Events extends Record<string, unknown>\n>(config: {\n source: Source;\n events: Events;\n}): Prettify<EventCreatorGroup<Source, Events>> {\n return Object.entries(config.events).reduce((acc, [eventName]) => {\n const eventType = `[${config.source}] ${eventName}`;\n return { ...acc, [eventName]: event(eventType) };\n }, {} as EventCreatorGroup<Source, Events>);\n}\n","import {\n assertInInjectionContext,\n inject,\n Injector,\n untracked,\n} from '@angular/core';\nimport { Prettify } from '@ngrx/signals';\nimport { Dispatcher } from './dispatcher';\nimport { EventCreator } from './event-creator';\n\ntype InjectDispatchResult<\n EventGroup extends Record<string, EventCreator<string, any>>\n> = {\n [EventName in keyof EventGroup]: Parameters<EventGroup[EventName]> extends [\n infer Payload\n ]\n ? (payload: Payload) => void\n : () => void;\n};\n\n/**\n * @experimental\n * @description\n *\n * Creates self-dispatching events for a given event group.\n *\n * @usageNotes\n *\n * ```ts\n * import { type } from '@ngrx/signals';\n * import { eventGroup, injectDispatch } from '@ngrx/signals/events';\n *\n * const counterPageEvents = eventGroup({\n * source: 'Counter Page',\n * events: {\n * increment: type<void>(),\n * decrement: type<void>(),\n * },\n * });\n *\n * \\@Component({ \\/* ... *\\/ })\n * class Counter {\n * readonly dispatch = injectDispatch(counterPageEvents);\n *\n * increment(): void {\n * this.dispatch.increment();\n * }\n *\n * decrement(): void {\n * this.dispatch.decrement();\n * }\n * }\n * ```\n */\nexport function injectDispatch<\n EventGroup extends Record<string, EventCreator<string, any>>\n>(\n events: EventGroup,\n config?: { injector?: Injector }\n): Prettify<InjectDispatchResult<EventGroup>> {\n if (!config?.injector) {\n assertInInjectionContext(injectDispatch);\n }\n\n const injector = config?.injector ?? inject(Injector);\n const dispatcher = injector.get(Dispatcher);\n\n return Object.entries(events).reduce(\n (acc, [eventName, eventCreator]) => ({\n ...acc,\n [eventName]: (payload?: unknown) =>\n untracked(() => dispatcher.dispatch(eventCreator(payload))),\n }),\n {} as InjectDispatchResult<EventGroup>\n );\n}\n","/**\n * @experimental\n */\nexport type EventInstance<Type extends string, Payload> = {\n type: Type;\n payload: Payload;\n};\n\nexport function isEventInstance(\n value: unknown\n): value is EventInstance<string, unknown> {\n return typeof value === 'object' && value !== null && 'type' in value;\n}\n","import { inject } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { merge, Observable, tap } from 'rxjs';\nimport {\n EmptyFeatureResult,\n Prettify,\n signalStoreFeature,\n SignalStoreFeature,\n SignalStoreFeatureResult,\n StateSignals,\n type,\n withHooks,\n WritableStateSource,\n} from '@ngrx/signals';\nimport { Dispatcher } from './dispatcher';\nimport { isEventInstance } from './event-instance';\nimport { SOURCE_TYPE } from './events-service';\n\n/**\n * @experimental\n * @description\n *\n * SignalStore feature for defining side effects.\n *\n * @usageNotes\n *\n * ```ts\n * import { signalStore, withState } from '@ngrx/signals';\n * import { event, Events, withEffects } from '@ngrx/signals/events';\n *\n * const increment = event('[Counter Page] Increment');\n * const decrement = event('[Counter Page] Decrement');\n *\n * const CounterStore = signalStore(\n * withState({ count: 0 }),\n * withEffects(({ count }, events = inject(Events)) => ({\n * logCount$: events.on(increment, decrement).pipe(\n * tap(({ type }) => console.log(type, count())),\n * ),\n * })),\n * );\n * ```\n */\nexport function withEffects<Input extends SignalStoreFeatureResult>(\n effectsFactory: (\n store: Prettify<\n StateSignals<Input['state']> &\n Input['props'] &\n Input['methods'] &\n WritableStateSource<Prettify<Input['state']>>\n >\n ) => Record<string, Observable<unknown>>\n): SignalStoreFeature<Input, EmptyFeatureResult> {\n return signalStoreFeature(\n type<Input>(),\n withHooks({\n onInit(store, dispatcher = inject(Dispatcher)) {\n const effectSources = effectsFactory(store);\n const effects = Object.values(effectSources).map((effectSource$) =>\n effectSource$.pipe(\n tap((value) => {\n if (isEventInstance(value) && !(SOURCE_TYPE in value)) {\n dispatcher.dispatch(value);\n }\n })\n )\n );\n\n merge(...effects)\n .pipe(takeUntilDestroyed())\n .subscribe();\n },\n })\n );\n}\n","import { inject, untracked } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { merge, tap } from 'rxjs';\nimport {\n EmptyFeatureResult,\n getState,\n patchState,\n SignalStoreFeature,\n signalStoreFeature,\n type,\n withHooks,\n} from '@ngrx/signals';\nimport { CaseReducerResult } from './case-reducer';\nimport { EventCreator } from './event-creator';\nimport { ReducerEvents } from './events-service';\n\n/**\n * @experimental\n * @description\n *\n * SignalStore feature for defining state changes based on dispatched events.\n *\n * @usageNotes\n *\n * ```ts\n * import { signalStore, type, withState } from '@ngrx/signals';\n * import { event, on, withReducer } from '@ngrx/signals/events';\n *\n * const set = event('[Counter Page] Set', type<number>());\n *\n * const CounterStore = signalStore(\n * withState({ count: 0 }),\n * withReducer(\n * on(set, ({ payload }) => ({ count: payload })),\n * ),\n * );\n * ```\n */\nexport function withReducer<State extends object>(\n ...caseReducers: CaseReducerResult<State, EventCreator<string, any>[]>[]\n): SignalStoreFeature<\n { state: State; props: {}; methods: {} },\n EmptyFeatureResult\n> {\n return signalStoreFeature(\n { state: type<State>() },\n withHooks({\n onInit(store, events = inject(ReducerEvents)) {\n const updates = caseReducers.map((caseReducer) =>\n events.on(...caseReducer.events).pipe(\n tap((event) => {\n const state = untracked(() => getState(store));\n const result = caseReducer.reducer(event, state);\n const updaters = Array.isArray(result) ? result : [result];\n\n patchState(store, ...updaters);\n })\n )\n );\n\n merge(...updates)\n .pipe(takeUntilDestroyed())\n .subscribe();\n },\n })\n );\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ngrx-signals-events.mjs","sources":["../../../../modules/signals/events/src/case-reducer.ts","../../../../modules/signals/events/src/events-service.ts","../../../../modules/signals/events/src/dispatcher.ts","../../../../modules/signals/events/src/event-creator.ts","../../../../modules/signals/events/src/event-creator-group.ts","../../../../modules/signals/events/src/inject-dispatch.ts","../../../../modules/signals/events/src/event-instance.ts","../../../../modules/signals/events/src/with-effects.ts","../../../../modules/signals/events/src/with-reducer.ts","../../../../modules/signals/events/ngrx-signals-events.ts"],"sourcesContent":["import { PartialStateUpdater } from '@ngrx/signals';\nimport { EventCreator } from './event-creator';\n\nexport type CaseReducerResult<\n State extends object,\n EventCreators extends EventCreator<string, any>[]\n> = {\n reducer: CaseReducer<State, EventCreators>;\n events: EventCreators;\n};\n\ntype CaseReducer<\n State extends object,\n EventCreators extends EventCreator<string, any>[]\n> = (\n event: { [K in keyof EventCreators]: ReturnType<EventCreators[K]> }[number],\n state: State\n) =>\n | Partial<State>\n | PartialStateUpdater<State>\n | Array<Partial<State> | PartialStateUpdater<State>>;\n\n/**\n * @experimental\n * @description\n *\n * Creates a case reducer that can be used with the `withReducer` feature.\n */\nexport function on<\n State extends object,\n EventCreators extends EventCreator<string, any>[]\n>(\n ...args: [\n ...events: [...EventCreators],\n reducer: CaseReducer<NoInfer<State>, NoInfer<EventCreators>>\n ]\n): CaseReducerResult<State, EventCreators> {\n const reducer = args.pop() as CaseReducer<State, EventCreators>;\n const events = args as unknown as EventCreators;\n\n return { reducer, events };\n}\n","import { Injectable } from '@angular/core';\nimport {\n filter,\n map,\n MonoTypeOperatorFunction,\n Observable,\n Subject,\n} from 'rxjs';\nimport { EventInstance } from './event-instance';\nimport { EventCreator } from './event-creator';\n\nexport const EVENTS = Symbol();\nexport const SOURCE_TYPE = Symbol();\n\nabstract class BaseEvents {\n /**\n * @internal\n */\n readonly [EVENTS] = new Subject<EventInstance<string, unknown>>();\n\n on(): Observable<EventInstance<string, unknown>>;\n on<EventCreators extends EventCreator<string, any>[]>(\n ...events: [...EventCreators]\n ): Observable<\n { [K in keyof EventCreators]: ReturnType<EventCreators[K]> }[number]\n >;\n on(\n ...events: EventCreator<string, unknown>[]\n ): Observable<EventInstance<string, unknown>> {\n return this[EVENTS].pipe(filterByType(events), withSourceType());\n }\n}\n\n/**\n * @experimental\n * @description\n *\n * Globally provided service for listening to dispatched events.\n *\n * @usageNotes\n *\n * ```ts\n * import { event, Events } from '@ngrx/signals/events';\n *\n * const increment = event('[Counter Page] Increment');\n *\n * \\@Component({ \\/* ... *\\/ })\n * class Counter {\n * readonly #events = inject(Events);\n *\n * constructor() {\n * this.#events\n * .on(increment)\n * .pipe(takeUntilDestroyed())\n * .subscribe(() => \\/* handle increment event *\\/);\n * }\n * }\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class Events extends BaseEvents {}\n\n@Injectable({ providedIn: 'root' })\nexport class ReducerEvents extends BaseEvents {}\n\nfunction filterByType<T extends EventInstance<string, unknown>>(\n events: EventCreator<string, unknown>[]\n): MonoTypeOperatorFunction<T> {\n if (events.length === 0) {\n return (source$) => source$;\n }\n\n const eventMap = toEventCreatorMap(events);\n return filter<T>(({ type }) => !!eventMap[type]);\n}\n\nfunction toEventCreatorMap(\n events: EventCreator<string, unknown>[]\n): Record<string, EventCreator<string, unknown>> {\n return events.reduce((acc, event) => ({ ...acc, [event.type]: event }), {});\n}\n\nfunction withSourceType<\n T extends EventInstance<string, unknown>\n>(): MonoTypeOperatorFunction<T> {\n return map(({ ...event }) => {\n Object.defineProperty(event, SOURCE_TYPE, { value: event.type });\n return event;\n });\n}\n","import { inject, Injectable } from '@angular/core';\nimport { queueScheduler } from 'rxjs';\nimport { EventInstance } from './event-instance';\nimport { Events, EVENTS, ReducerEvents } from './events-service';\n\n/**\n * @experimental\n * @description\n *\n * Globally provided service for dispatching events.\n *\n * @usageNotes\n *\n * ```ts\n * import { Dispatcher, event } from '@ngrx/signals/events';\n *\n * const increment = event('[Counter Page] Increment');\n *\n * \\@Component({ \\/* ... *\\/ })\n * class Counter {\n * readonly #dispatcher = inject(Dispatcher);\n *\n * increment(): void {\n * this.#dispatcher.dispatch(increment());\n * }\n * }\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class Dispatcher {\n protected readonly reducerEvents = inject(ReducerEvents);\n protected readonly events = inject(Events);\n\n dispatch(event: EventInstance<string, unknown>): void {\n this.reducerEvents[EVENTS].next(event);\n queueScheduler.schedule(() => this.events[EVENTS].next(event));\n }\n}\n","import { EventInstance } from './event-instance';\n\n/**\n * @experimental\n */\nexport type EventCreator<Type extends string, Payload> = ((\n payload: Payload\n) => EventInstance<Type, Payload>) & { type: Type };\n\nexport function event<Type extends string>(\n type: Type\n): EventCreator<Type, void>;\nexport function event<Type extends string, Payload>(\n type: Type,\n payload: Payload\n): EventCreator<Type, Payload>;\n/**\n * @experimental\n * @description\n *\n * Creates an event creator.\n *\n * @usageNotes\n *\n * ### Creating an event creator without payload\n *\n * ```ts\n * import { event } from '@ngrx/signals/events';\n *\n * const increment = event('[Counter Page] Increment');\n * ```\n *\n * ### Creating an event creator with payload\n *\n * ```ts\n * import { type } from '@ngrx/signals';\n * import { event } from '@ngrx/signals/events';\n *\n * const set = event('[Counter Page] Set', type<number>());\n * ```\n */\nexport function event(type: string): EventCreator<string, any> {\n const creator = (payload?: unknown) => ({ type, payload });\n (creator as any).type = type;\n\n return creator as EventCreator<string, unknown>;\n}\n","import { Prettify } from '@ngrx/signals';\nimport { event, EventCreator } from './event-creator';\n\ntype EventType<\n Source extends string,\n EventName extends string\n> = `[${Source}] ${EventName}`;\n\ntype EventCreatorGroup<\n Source extends string,\n Events extends Record<string, any>\n> = {\n [EventName in keyof Events]: EventName extends string\n ? EventCreator<EventType<Source, EventName>, Events[EventName]>\n : never;\n};\n\n/**\n * @experimental\n * @description\n *\n * Creates a group of event creators.\n *\n * @usageNotes\n *\n * ```ts\n * import { type } from '@ngrx/signals';\n * import { eventGroup } from '@ngrx/signals/events';\n *\n * const counterPageEvents = eventGroup({\n * source: 'Counter Page',\n * events: {\n * increment: type<void>(),\n * decrement: type<void>(),\n * set: type<number>(),\n * },\n * });\n * ```\n */\nexport function eventGroup<\n Source extends string,\n Events extends Record<string, unknown>\n>(config: {\n source: Source;\n events: Events;\n}): Prettify<EventCreatorGroup<Source, Events>> {\n return Object.entries(config.events).reduce((acc, [eventName]) => {\n const eventType = `[${config.source}] ${eventName}`;\n return { ...acc, [eventName]: event(eventType) };\n }, {} as EventCreatorGroup<Source, Events>);\n}\n","import {\n assertInInjectionContext,\n inject,\n Injector,\n untracked,\n} from '@angular/core';\nimport { Prettify } from '@ngrx/signals';\nimport { Dispatcher } from './dispatcher';\nimport { EventCreator } from './event-creator';\n\ntype InjectDispatchResult<\n EventGroup extends Record<string, EventCreator<string, any>>\n> = {\n [EventName in keyof EventGroup]: Parameters<EventGroup[EventName]> extends [\n infer Payload\n ]\n ? (payload: Payload) => void\n : () => void;\n};\n\n/**\n * @experimental\n * @description\n *\n * Creates self-dispatching events for a given event group.\n *\n * @usageNotes\n *\n * ```ts\n * import { type } from '@ngrx/signals';\n * import { eventGroup, injectDispatch } from '@ngrx/signals/events';\n *\n * const counterPageEvents = eventGroup({\n * source: 'Counter Page',\n * events: {\n * increment: type<void>(),\n * decrement: type<void>(),\n * },\n * });\n *\n * \\@Component({ \\/* ... *\\/ })\n * class Counter {\n * readonly dispatch = injectDispatch(counterPageEvents);\n *\n * increment(): void {\n * this.dispatch.increment();\n * }\n *\n * decrement(): void {\n * this.dispatch.decrement();\n * }\n * }\n * ```\n */\nexport function injectDispatch<\n EventGroup extends Record<string, EventCreator<string, any>>\n>(\n events: EventGroup,\n config?: { injector?: Injector }\n): Prettify<InjectDispatchResult<EventGroup>> {\n if (!config?.injector) {\n assertInInjectionContext(injectDispatch);\n }\n\n const injector = config?.injector ?? inject(Injector);\n const dispatcher = injector.get(Dispatcher);\n\n return Object.entries(events).reduce(\n (acc, [eventName, eventCreator]) => ({\n ...acc,\n [eventName]: (payload?: unknown) =>\n untracked(() => dispatcher.dispatch(eventCreator(payload))),\n }),\n {} as InjectDispatchResult<EventGroup>\n );\n}\n","/**\n * @experimental\n */\nexport type EventInstance<Type extends string, Payload> = {\n type: Type;\n payload: Payload;\n};\n\nexport function isEventInstance(\n value: unknown\n): value is EventInstance<string, unknown> {\n return typeof value === 'object' && value !== null && 'type' in value;\n}\n","import { inject } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { merge, Observable, tap } from 'rxjs';\nimport {\n EmptyFeatureResult,\n Prettify,\n signalStoreFeature,\n SignalStoreFeature,\n SignalStoreFeatureResult,\n StateSignals,\n type,\n withHooks,\n WritableStateSource,\n} from '@ngrx/signals';\nimport { Dispatcher } from './dispatcher';\nimport { isEventInstance } from './event-instance';\nimport { SOURCE_TYPE } from './events-service';\n\n/**\n * @experimental\n * @description\n *\n * SignalStore feature for defining side effects.\n *\n * @usageNotes\n *\n * ```ts\n * import { signalStore, withState } from '@ngrx/signals';\n * import { event, Events, withEffects } from '@ngrx/signals/events';\n *\n * const increment = event('[Counter Page] Increment');\n * const decrement = event('[Counter Page] Decrement');\n *\n * const CounterStore = signalStore(\n * withState({ count: 0 }),\n * withEffects(({ count }, events = inject(Events)) => ({\n * logCount$: events.on(increment, decrement).pipe(\n * tap(({ type }) => console.log(type, count())),\n * ),\n * })),\n * );\n * ```\n */\nexport function withEffects<Input extends SignalStoreFeatureResult>(\n effectsFactory: (\n store: Prettify<\n StateSignals<Input['state']> &\n Input['props'] &\n Input['methods'] &\n WritableStateSource<Prettify<Input['state']>>\n >\n ) => Record<string, Observable<unknown>>\n): SignalStoreFeature<Input, EmptyFeatureResult> {\n return signalStoreFeature(\n type<Input>(),\n withHooks({\n onInit(store, dispatcher = inject(Dispatcher)) {\n const effectSources = effectsFactory(store);\n const effects = Object.values(effectSources).map((effectSource$) =>\n effectSource$.pipe(\n tap((value) => {\n if (isEventInstance(value) && !(SOURCE_TYPE in value)) {\n dispatcher.dispatch(value);\n }\n })\n )\n );\n\n merge(...effects)\n .pipe(takeUntilDestroyed())\n .subscribe();\n },\n })\n );\n}\n","import { inject, untracked } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { merge, tap } from 'rxjs';\nimport {\n EmptyFeatureResult,\n getState,\n patchState,\n SignalStoreFeature,\n signalStoreFeature,\n type,\n withHooks,\n} from '@ngrx/signals';\nimport { CaseReducerResult } from './case-reducer';\nimport { EventCreator } from './event-creator';\nimport { ReducerEvents } from './events-service';\n\n/**\n * @experimental\n * @description\n *\n * SignalStore feature for defining state changes based on dispatched events.\n *\n * @usageNotes\n *\n * ```ts\n * import { signalStore, type, withState } from '@ngrx/signals';\n * import { event, on, withReducer } from '@ngrx/signals/events';\n *\n * const set = event('[Counter Page] Set', type<number>());\n *\n * const CounterStore = signalStore(\n * withState({ count: 0 }),\n * withReducer(\n * on(set, ({ payload }) => ({ count: payload })),\n * ),\n * );\n * ```\n */\nexport function withReducer<State extends object>(\n ...caseReducers: CaseReducerResult<State, EventCreator<string, any>[]>[]\n): SignalStoreFeature<\n { state: State; props: {}; methods: {} },\n EmptyFeatureResult\n> {\n return signalStoreFeature(\n { state: type<State>() },\n withHooks({\n onInit(store, events = inject(ReducerEvents)) {\n const updates = caseReducers.map((caseReducer) =>\n events.on(...caseReducer.events).pipe(\n tap((event) => {\n const state = untracked(() => getState(store));\n const result = caseReducer.reducer(event, state);\n const updaters = Array.isArray(result) ? result : [result];\n\n patchState(store, ...updaters);\n })\n )\n );\n\n merge(...updates)\n .pipe(takeUntilDestroyed())\n .subscribe();\n },\n })\n );\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -1,14 +1,18 @@
1
1
  import * as i0 from '@angular/core';
2
- import { untracked, isSignal, computed, assertInInjectionContext, inject, Injector, effect, DestroyRef, signal, Injectable } from '@angular/core';
2
+ import { untracked, isSignal, computed, assertInInjectionContext, inject, Injector, effect, DestroyRef, signal, Injectable, linkedSignal } from '@angular/core';
3
3
 
4
+ const DEEP_SIGNAL = Symbol('DEEP_SIGNAL');
4
5
  function toDeepSignal(signal) {
5
- const value = untracked(() => signal());
6
- if (!isRecord(value)) {
7
- return signal;
8
- }
9
6
  return new Proxy(signal, {
7
+ has(target, prop) {
8
+ return !!this.get(target, prop, undefined);
9
+ },
10
10
  get(target, prop) {
11
- if (!(prop in value)) {
11
+ const value = untracked(target);
12
+ if (!isRecord(value) || !(prop in value)) {
13
+ if (isSignal(target[prop]) && target[prop][DEEP_SIGNAL]) {
14
+ delete target[prop];
15
+ }
12
16
  return target[prop];
13
17
  }
14
18
  if (!isSignal(target[prop])) {
@@ -16,6 +20,7 @@ function toDeepSignal(signal) {
16
20
  value: computed(() => target()[prop]),
17
21
  configurable: true,
18
22
  });
23
+ target[prop][DEEP_SIGNAL] = true;
19
24
  }
20
25
  return toDeepSignal(target[prop]);
21
26
  },
@@ -104,21 +109,49 @@ function getCallerInjector() {
104
109
 
105
110
  const STATE_WATCHERS = new WeakMap();
106
111
  const STATE_SOURCE = Symbol('STATE_SOURCE');
112
+ function isWritableSignal(value) {
113
+ return (isSignal(value) &&
114
+ 'set' in value &&
115
+ 'update' in value &&
116
+ typeof value.set === 'function' &&
117
+ typeof value.update === 'function');
118
+ }
107
119
  function isWritableStateSource(stateSource) {
108
- return ('set' in stateSource[STATE_SOURCE] &&
109
- 'update' in stateSource[STATE_SOURCE] &&
110
- typeof stateSource[STATE_SOURCE].set === 'function' &&
111
- typeof stateSource[STATE_SOURCE].update === 'function');
120
+ const signals = stateSource[STATE_SOURCE];
121
+ return Reflect.ownKeys(stateSource[STATE_SOURCE]).every((key) => {
122
+ return isWritableSignal(signals[key]);
123
+ });
112
124
  }
113
125
  function patchState(stateSource, ...updaters) {
114
- stateSource[STATE_SOURCE].update((currentState) => updaters.reduce((nextState, updater) => ({
126
+ const currentState = untracked(() => getState(stateSource));
127
+ const newState = updaters.reduce((nextState, updater) => ({
115
128
  ...nextState,
116
129
  ...(typeof updater === 'function' ? updater(nextState) : updater),
117
- }), currentState));
130
+ }), currentState);
131
+ const signals = stateSource[STATE_SOURCE];
132
+ const stateKeys = Reflect.ownKeys(stateSource[STATE_SOURCE]);
133
+ for (const key of Reflect.ownKeys(newState)) {
134
+ if (stateKeys.includes(key)) {
135
+ const signalKey = key;
136
+ if (currentState[signalKey] !== newState[signalKey]) {
137
+ signals[signalKey].set(newState[signalKey]);
138
+ }
139
+ }
140
+ else if (typeof ngDevMode !== 'undefined' && ngDevMode) {
141
+ console.warn(`@ngrx/signals: patchState was called with an unknown state slice '${String(key)}'.`, 'Ensure that all state properties are explicitly defined in the initial state.', 'Updates to properties not present in the initial state will be ignored.');
142
+ }
143
+ }
118
144
  notifyWatchers(stateSource);
119
145
  }
120
146
  function getState(stateSource) {
121
- return stateSource[STATE_SOURCE]();
147
+ const signals = stateSource[STATE_SOURCE];
148
+ return Reflect.ownKeys(stateSource[STATE_SOURCE]).reduce((state, key) => {
149
+ const value = signals[key]();
150
+ return {
151
+ ...state,
152
+ [key]: value,
153
+ };
154
+ }, {});
122
155
  }
123
156
  function watchState(stateSource, watcher, config) {
124
157
  if (!config?.injector) {
@@ -152,11 +185,20 @@ function removeWatcher(stateSource, watcher) {
152
185
  }
153
186
 
154
187
  function signalState(initialState) {
155
- const stateSource = signal(initialState);
156
- const signalState = toDeepSignal(stateSource.asReadonly());
188
+ const stateKeys = Reflect.ownKeys(initialState);
189
+ const stateSource = stateKeys.reduce((signalsDict, key) => ({
190
+ ...signalsDict,
191
+ [key]: signal(initialState[key]),
192
+ }), {});
193
+ const signalState = computed(() => stateKeys.reduce((state, key) => ({ ...state, [key]: stateSource[key]() }), {}));
157
194
  Object.defineProperty(signalState, STATE_SOURCE, {
158
195
  value: stateSource,
159
196
  });
197
+ for (const key of stateKeys) {
198
+ Object.defineProperty(signalState, key, {
199
+ value: toDeepSignal(stateSource[key]),
200
+ });
201
+ }
160
202
  return signalState;
161
203
  }
162
204
 
@@ -187,10 +229,10 @@ function signalStore(...args) {
187
229
  inject(DestroyRef).onDestroy(onDestroy);
188
230
  }
189
231
  }
190
- /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.3", ngImport: i0, type: SignalStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
191
- /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.3", ngImport: i0, type: SignalStore, providedIn: config.providedIn || null });
232
+ /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: SignalStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
233
+ /** @nocollapse */ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: SignalStore, providedIn: config.providedIn || null });
192
234
  }
193
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.3", ngImport: i0, type: SignalStore, decorators: [{
235
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: SignalStore, decorators: [{
194
236
  type: Injectable,
195
237
  args: [{ providedIn: config.providedIn || null }]
196
238
  }], ctorParameters: () => [] });
@@ -198,7 +240,7 @@ function signalStore(...args) {
198
240
  }
199
241
  function getInitialInnerStore() {
200
242
  return {
201
- [STATE_SOURCE]: signal({}),
243
+ [STATE_SOURCE]: {},
202
244
  stateSignals: {},
203
245
  props: {},
204
246
  methods: {},
@@ -206,10 +248,8 @@ function getInitialInnerStore() {
206
248
  };
207
249
  }
208
250
 
209
- function signalStoreFeature(featureOrInput, ...restFeatures) {
210
- const features = typeof featureOrInput === 'function'
211
- ? [featureOrInput, ...restFeatures]
212
- : restFeatures;
251
+ function signalStoreFeature(...args) {
252
+ const features = (typeof args[0] === 'function' ? args : args.slice(1));
213
253
  return (inputStore) => features.reduce((store, feature) => feature(store), inputStore);
214
254
  }
215
255
  function type() {
@@ -247,8 +287,20 @@ function withProps(propsFactory) {
247
287
  };
248
288
  }
249
289
 
250
- function withComputed(signalsFactory) {
251
- return withProps(signalsFactory);
290
+ function withComputed(computedFactory) {
291
+ return withProps((store) => {
292
+ const computedResult = computedFactory(store);
293
+ const computedResultKeys = Reflect.ownKeys(computedResult);
294
+ return computedResultKeys.reduce((prev, key) => {
295
+ const signalOrComputation = computedResult[key];
296
+ return {
297
+ ...prev,
298
+ [key]: isSignal(signalOrComputation)
299
+ ? signalOrComputation
300
+ : computed(signalOrComputation),
301
+ };
302
+ }, {});
303
+ });
252
304
  }
253
305
 
254
306
  /**
@@ -318,6 +370,69 @@ function withHooks(hooksOrFactory) {
318
370
  };
319
371
  }
320
372
 
373
+ /**
374
+ * @description
375
+ *
376
+ * Adds linked state slices to a SignalStore.
377
+ *
378
+ * @usageNotes
379
+ *
380
+ * ```typescript
381
+ * const OptionsStore = signalStore(
382
+ * withState({ options: [1, 2, 3] }),
383
+ * withLinkedState(({ options }) => ({
384
+ * selectedOption: () => options()[0],
385
+ * }))
386
+ * );
387
+ * ```
388
+ *
389
+ * This returns a state of type `{ options: number[], selectedOption: number | undefined }`.
390
+ * When the `options` signal changes, the `selectedOption` automatically updates.
391
+ *
392
+ * For advanced use cases, `linkedSignal` or any other `WritableSignal` instance can be used within `withLinkedState`:
393
+ *
394
+ * ```typescript
395
+ * type Option = { id: number; label: string };
396
+ *
397
+ * const OptionsStore = signalStore(
398
+ * withState({ options: [] as Option[] }),
399
+ * withLinkedState(({ options }) => ({
400
+ * selectedOption: linkedSignal<Option[], Option>({
401
+ * source: options,
402
+ * computation: (newOptions, previous) => {
403
+ * const option = newOptions.find((o) => o.id === previous?.value.id);
404
+ * return option ?? newOptions[0];
405
+ * },
406
+ * })
407
+ * }))
408
+ * )
409
+ * ```
410
+ *
411
+ * @param linkedStateFactory A function that returns an object literal with properties containing an actual `linkedSignal` or the computation function.
412
+ */
413
+ function withLinkedState(linkedStateFactory) {
414
+ return (store) => {
415
+ const linkedState = linkedStateFactory({
416
+ ...store.stateSignals,
417
+ ...store.props,
418
+ });
419
+ const stateKeys = Reflect.ownKeys(linkedState);
420
+ const stateSource = store[STATE_SOURCE];
421
+ const stateSignals = {};
422
+ for (const key of stateKeys) {
423
+ const signalOrComputationFn = linkedState[key];
424
+ stateSource[key] = isWritableSignal(signalOrComputationFn)
425
+ ? signalOrComputationFn
426
+ : linkedSignal(signalOrComputationFn);
427
+ stateSignals[key] = toDeepSignal(stateSource[key]);
428
+ }
429
+ return {
430
+ ...store,
431
+ stateSignals: { ...store.stateSignals, ...stateSignals },
432
+ };
433
+ };
434
+ }
435
+
321
436
  function withMethods(methodsFactory) {
322
437
  return (store) => {
323
438
  const methods = methodsFactory({
@@ -336,17 +451,15 @@ function withMethods(methodsFactory) {
336
451
 
337
452
  function withState(stateOrFactory) {
338
453
  return (store) => {
339
- const state = typeof stateOrFactory === 'function' ? stateOrFactory() : stateOrFactory;
454
+ const state = (typeof stateOrFactory === 'function' ? stateOrFactory() : stateOrFactory);
340
455
  const stateKeys = Reflect.ownKeys(state);
341
456
  assertUniqueStoreMembers(store, stateKeys);
342
- store[STATE_SOURCE].update((currentState) => ({
343
- ...currentState,
344
- ...state,
345
- }));
346
- const stateSignals = stateKeys.reduce((acc, key) => {
347
- const sliceSignal = computed(() => store[STATE_SOURCE]()[key]);
348
- return { ...acc, [key]: toDeepSignal(sliceSignal) };
349
- }, {});
457
+ const stateSource = store[STATE_SOURCE];
458
+ const stateSignals = {};
459
+ for (const key of stateKeys) {
460
+ stateSource[key] = signal(state[key]);
461
+ stateSignals[key] = toDeepSignal(stateSource[key]);
462
+ }
350
463
  return {
351
464
  ...store,
352
465
  stateSignals: { ...store.stateSignals, ...stateSignals },
@@ -358,5 +471,5 @@ function withState(stateOrFactory) {
358
471
  * Generated bundle index. Do not edit.
359
472
  */
360
473
 
361
- export { deepComputed, getState, isWritableStateSource, patchState, signalMethod, signalState, signalStore, signalStoreFeature, type, watchState, withComputed, withFeature, withHooks, withMethods, withProps, withState };
474
+ export { deepComputed, getState, isWritableStateSource, patchState, signalMethod, signalState, signalStore, signalStoreFeature, type, watchState, withComputed, withFeature, withHooks, withLinkedState, withMethods, withProps, withState };
362
475
  //# sourceMappingURL=ngrx-signals.mjs.map