Skip to content

feat(effects-ng): prefer classes from "effects" as injection tokens #67

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,12 @@ export ROUTES = [
]
```

The actions can be dispatched by injecting the `Actions` provider:
The `Actions` class from `@ngneat/effects` has been injectable when using `@ngneat/effects-ng`.

To dispatch an action, simply inject `Actions`:

```ts
import { Actions } from '@ngneat/effects-ng';
import { Actions } from '@ngneat/effects';

@Component(...)
export class AppComponent {
Expand All @@ -206,7 +208,8 @@ export class AppComponent {
`provideDirectiveEffects()` and `EffectsDirective` serve to register effects on the `component injector` level. This means that effects will live as long as the component where effects are registered lives. Do not forget to call `provideEffectsManager` in the root providers.

```ts
import { provideDirectiveEffects, EffectsDirective, Actions } from '@ngneat/effects-ng';
import { Actions } from "@ngneat/effects";
import { provideDirectiveEffects, EffectsDirective } from '@ngneat/effects-ng';

@Component({
...,
Expand Down
3 changes: 3 additions & 0 deletions libs/effects-ng/src/lib/actions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { Actions as _Actions } from '@ngneat/effects';
import { Injectable } from '@angular/core';

/**
* @deprecated Use `Actions` exported from `@ngneat/effects` instead.
*/
@Injectable({
providedIn: 'root',
})
Expand Down
29 changes: 26 additions & 3 deletions libs/effects-ng/src/lib/effects-ng.module.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import { Component, Injectable, NgModule } from '@angular/core';
import { TestBed, flushMicrotasks, fakeAsync } from '@angular/core/testing';
import { createAction, createEffect } from '@ngneat/effects';
import {
Actions,
EffectsManager,
createAction,
createEffect,
} from '@ngneat/effects';
import { tap } from 'rxjs';
import { ofType } from 'ts-action-operators';
import { Actions } from './actions';
import { EffectsNgModule } from './effects-ng.module';
import { EFFECTS_PROVIDERS } from './tokens';
import { EFFECTS_MANAGER, EFFECTS_PROVIDERS } from './tokens';
import { Actions as _Actions } from './actions';
import { Router, RouterModule } from '@angular/router';

const spy = jest.fn();
Expand Down Expand Up @@ -40,6 +45,24 @@ describe('Effects ng module', () => {
spy.mockReset();
});

it('should provide the same instance for different tokens of Actions', () => {
TestBed.configureTestingModule({
imports: [EffectsNgModule.forRoot([])],
});
const actions = TestBed.inject(Actions);
const _actions = TestBed.inject(_Actions);
expect(actions === _actions).toBe(true);
});

it('should provide the same instance for different tokens of EffectsManager', () => {
TestBed.configureTestingModule({
imports: [EffectsNgModule.forRoot([])],
});
const effectsManager = TestBed.inject(EffectsManager);
const _effectsManager = TestBed.inject(EFFECTS_MANAGER);
expect(effectsManager === _effectsManager).toBe(true);
});

it('should provide effects one using forRoot', () => {
TestBed.configureTestingModule({
imports: [EffectsNgModule.forRoot([EffectsOne])],
Expand Down
13 changes: 11 additions & 2 deletions libs/effects-ng/src/lib/effects-ng.module.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { Inject, ModuleWithProviders, NgModule, Type } from '@angular/core';
import {
Actions,
actions,
EffectsConfig,
EffectsManager,
initEffects,
} from '@ngneat/effects';
import { Actions } from './actions';
import { EFFECTS_MANAGER, EFFECTS_PROVIDERS } from './tokens';
import { registerEffectFromProviders } from './provide-effects';
import { Actions as _Actions } from './actions';

/**
* @deprecated Please consider using `provideEffectManager` and `provideEffects` functions instead. This module will be
Expand All @@ -34,9 +35,17 @@ export class EffectsNgModule {
useValue: config?.customActionsStream || actions,
},
{
provide: EFFECTS_MANAGER,
provide: _Actions,
useExisting: Actions,
},
{
provide: EffectsManager,
useFactory: () => initEffects(config),
},
{
provide: EFFECTS_MANAGER,
useExisting: EffectsManager,
},
...providers,
{
provide: EFFECTS_PROVIDERS,
Expand Down
26 changes: 24 additions & 2 deletions libs/effects-ng/src/lib/provide-effects-manager.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { Component, Injectable } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { createAction, createEffect } from '@ngneat/effects';
import {
Actions,
EffectsManager,
createAction,
createEffect,
} from '@ngneat/effects';
import { tap, map } from 'rxjs';
import { ofType } from 'ts-action-operators';
import { Actions } from './actions';
import { provideEffects } from './provide-effects';
import { provideEffectsManager } from './provide-effects-manager';
import { EFFECTS_MANAGER } from './tokens';
import { Actions as _Actions } from './actions';

const spy = jest.fn();

Expand Down Expand Up @@ -69,4 +75,20 @@ describe('provideEffectsManager', () => {
expect((component as any).actions).toBeInstanceOf(CustomActions);
expect(dispatchSpy).toHaveBeenCalled();
});

it('should provide the same instance for different tokens of the same object', () => {
TestBed.configureTestingModule({
providers: [
TodoComponent,
provideEffects(EffectsOne),
provideEffectsManager(),
],
});
const actions = TestBed.inject(Actions);
const _actions = TestBed.inject(_Actions);
expect(actions === _actions).toBe(true);
const manager = TestBed.inject(EffectsManager);
const _manager = TestBed.inject(EFFECTS_MANAGER);
expect(manager === _manager).toBe(true);
});
});
20 changes: 17 additions & 3 deletions libs/effects-ng/src/lib/provide-effects-manager.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';
import { Actions } from './actions';
import { EFFECTS_MANAGER } from './tokens';
import { initEffects, EffectsConfig, actions } from '@ngneat/effects';
import { Actions as _Actions } from './actions';
import {
initEffects,
EffectsConfig,
actions,
Actions,
EffectsManager,
} from '@ngneat/effects';

/**
* Must be called at the root level.
Expand All @@ -19,8 +25,16 @@ export function provideEffectsManager(
useValue: customActionsStream,
},
{
provide: EFFECTS_MANAGER,
provide: _Actions,
useExisting: Actions,
},
{
provide: EffectsManager,
useValue: manager,
},
{
provide: EFFECTS_MANAGER,
useExisting: EffectsManager,
},
]);
}
3 changes: 1 addition & 2 deletions libs/effects-ng/src/lib/provide-effects.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { Component, Injectable } from '@angular/core';
import { TestBed, flushMicrotasks, fakeAsync } from '@angular/core/testing';
import { createAction, createEffect } from '@ngneat/effects';
import { Actions, createAction, createEffect } from '@ngneat/effects';
import { tap } from 'rxjs';
import { ofType } from 'ts-action-operators';
import { Actions } from './actions';
import { provideEffects } from './provide-effects';
import { provideEffectsManager } from './provide-effects-manager';
import { Routes, provideRouter, Router } from '@angular/router';
Expand Down
3 changes: 1 addition & 2 deletions libs/effects-ng/src/lib/provide-effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
makeEnvironmentProviders,
EnvironmentProviders,
} from '@angular/core';
import { EFFECTS_MANAGER } from './tokens';
import { getEffectPropsMap } from './utils';
import { Effect, EffectsManager } from '@ngneat/effects';
import {
Expand All @@ -27,7 +26,7 @@ export function provideEffects(
provide: ENVIRONMENT_INITIALIZER,
multi: true,
useValue: () => {
const manager = inject(EFFECTS_MANAGER, { optional: true });
const manager = inject(EffectsManager, { optional: true });

if (!manager) {
throw new TypeError(
Expand Down
4 changes: 4 additions & 0 deletions libs/effects-ng/src/lib/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import { EffectsManager } from '@ngneat/effects';
export const EFFECTS_PROVIDERS = new InjectionToken<Type<any>[]>(
'@ngneat/effects Effects providers'
);

/**
* @deprecated Use the {@link EffectsManager} class from `@ngneat/effects` instead.
*/
export const EFFECTS_MANAGER = new InjectionToken<EffectsManager>(
'@ngneat/effects Effects Manager'
);
3 changes: 1 addition & 2 deletions libs/effects-ng/src/lib/use-directive-effects.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { Component, Injectable, Type } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { createAction, createEffect } from '@ngneat/effects';
import { Actions, createAction, createEffect } from '@ngneat/effects';
import { tap } from 'rxjs';
import { ofType } from 'ts-action-operators';
import { Actions } from './actions';
import { provideEffectsManager } from './provide-effects-manager';
import {
provideDirectiveEffects,
Expand Down
5 changes: 2 additions & 3 deletions libs/effects-ng/src/lib/use-directive-effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ import {
Provider,
InjectionToken,
} from '@angular/core';
import { EFFECTS_MANAGER } from './tokens';
import { getEffectPropsMap } from './utils';
import { Effect } from '@ngneat/effects';
import { Effect, EffectsManager } from '@ngneat/effects';
import {
isEffectProvided,
increaseProvidedEffectSources,
Expand Down Expand Up @@ -39,7 +38,7 @@ export class EffectsDirective implements OnDestroy {
self: true,
optional: true,
});
private readonly manager = inject(EFFECTS_MANAGER, { optional: true });
private readonly manager = inject(EffectsManager, { optional: true });
private readonly sourceInstancesWithProvidersEffectsTokens = new Map<
any,
ProvidedEffectToken
Expand Down