@nx/angular 23.0.0-beta.8 → 23.0.0-beta.9

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.
Files changed (48) hide show
  1. package/generators.d.ts +0 -1
  2. package/generators.d.ts.map +1 -1
  3. package/generators.js +0 -1
  4. package/generators.json +0 -6
  5. package/migrations.json +5 -0
  6. package/package.json +8 -8
  7. package/src/migrations/update-23-0-0/migrate-ngrx-generator-defaults.d.ts +3 -0
  8. package/src/migrations/update-23-0-0/migrate-ngrx-generator-defaults.d.ts.map +1 -0
  9. package/src/migrations/update-23-0-0/migrate-ngrx-generator-defaults.js +120 -0
  10. package/src/utils/backward-compatible-versions.js +2 -2
  11. package/src/utils/versions.d.ts +1 -1
  12. package/src/utils/versions.js +1 -1
  13. package/src/generators/ngrx/files/__directory__/__fileName__.actions.ts__tmpl__ +0 -16
  14. package/src/generators/ngrx/files/__directory__/__fileName__.effects.spec.ts__tmpl__ +0 -37
  15. package/src/generators/ngrx/files/__directory__/__fileName__.effects.ts__tmpl__ +0 -22
  16. package/src/generators/ngrx/files/__directory__/__fileName__.facade.spec.ts__tmpl__ +0 -103
  17. package/src/generators/ngrx/files/__directory__/__fileName__.facade.ts__tmpl__ +0 -27
  18. package/src/generators/ngrx/files/__directory__/__fileName__.models.ts__tmpl__ +0 -7
  19. package/src/generators/ngrx/files/__directory__/__fileName__.reducer.spec.ts__tmpl__ +0 -37
  20. package/src/generators/ngrx/files/__directory__/__fileName__.reducer.ts__tmpl__ +0 -41
  21. package/src/generators/ngrx/files/__directory__/__fileName__.selectors.spec.ts__tmpl__ +0 -58
  22. package/src/generators/ngrx/files/__directory__/__fileName__.selectors.ts__tmpl__ +0 -38
  23. package/src/generators/ngrx/lib/add-exports-barrel.d.ts +0 -7
  24. package/src/generators/ngrx/lib/add-exports-barrel.d.ts.map +0 -1
  25. package/src/generators/ngrx/lib/add-exports-barrel.js +0 -44
  26. package/src/generators/ngrx/lib/add-imports-to-module.d.ts +0 -4
  27. package/src/generators/ngrx/lib/add-imports-to-module.d.ts.map +0 -1
  28. package/src/generators/ngrx/lib/add-imports-to-module.js +0 -181
  29. package/src/generators/ngrx/lib/add-ngrx-to-package-json.d.ts +0 -4
  30. package/src/generators/ngrx/lib/add-ngrx-to-package-json.d.ts.map +0 -1
  31. package/src/generators/ngrx/lib/add-ngrx-to-package-json.js +0 -23
  32. package/src/generators/ngrx/lib/generate-files.d.ts +0 -7
  33. package/src/generators/ngrx/lib/generate-files.d.ts.map +0 -1
  34. package/src/generators/ngrx/lib/generate-files.js +0 -23
  35. package/src/generators/ngrx/lib/index.d.ts +0 -7
  36. package/src/generators/ngrx/lib/index.d.ts.map +0 -1
  37. package/src/generators/ngrx/lib/index.js +0 -15
  38. package/src/generators/ngrx/lib/normalize-options.d.ts +0 -9
  39. package/src/generators/ngrx/lib/normalize-options.d.ts.map +0 -1
  40. package/src/generators/ngrx/lib/normalize-options.js +0 -30
  41. package/src/generators/ngrx/lib/validate-options.d.ts +0 -4
  42. package/src/generators/ngrx/lib/validate-options.d.ts.map +0 -1
  43. package/src/generators/ngrx/lib/validate-options.js +0 -14
  44. package/src/generators/ngrx/ngrx.d.ts +0 -8
  45. package/src/generators/ngrx/ngrx.d.ts.map +0 -1
  46. package/src/generators/ngrx/ngrx.js +0 -28
  47. package/src/generators/ngrx/schema.d.ts +0 -14
  48. package/src/generators/ngrx/schema.json +0 -102
package/generators.d.ts CHANGED
@@ -8,7 +8,6 @@ export * from './src/generators/host/host';
8
8
  export * from './src/generators/init/init';
9
9
  export * from './src/generators/library-secondary-entry-point/library-secondary-entry-point';
10
10
  export * from './src/generators/library/library';
11
- export * from './src/generators/ngrx/ngrx';
12
11
  export * from './src/generators/ngrx-feature-store/ngrx-feature-store';
13
12
  export * from './src/generators/ngrx-root-store/ngrx-root-store';
14
13
  export * from './src/generators/pipe/pipe';
@@ -1 +1 @@
1
- {"version":3,"file":"generators.d.ts","sourceRoot":"","sources":["../../../packages/angular/generators.ts"],"names":[],"mappings":"AAAA,cAAc,0CAA0C,CAAC;AACzD,cAAc,0CAA0C,CAAC;AACzD,cAAc,kDAAkD,CAAC;AACjE,cAAc,sCAAsC,CAAC;AACrD,cAAc,sCAAsC,CAAC;AACrD,cAAc,kDAAkD,CAAC;AACjE,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8EAA8E,CAAC;AAC7F,cAAc,kCAAkC,CAAC;AACjD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wDAAwD,CAAC;AACvE,cAAc,kDAAkD,CAAC;AACjE,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,gDAAgD,CAAC;AAC/D,cAAc,sCAAsC,CAAC;AACrD,cAAc,wDAAwD,CAAC;AACvE,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oCAAoC,CAAC;AACnD,cAAc,sCAAsC,CAAC;AACrD,cAAc,kCAAkC,CAAC;AACjD,cAAc,kEAAkE,CAAC;AACjF,cAAc,wCAAwC,CAAC;AACvD,OAAO,EAAE,6BAA6B,EAAE,MAAM,kFAAkF,CAAC;AACjI,cAAc,gDAAgD,CAAC;AAC/D,cAAc,0BAA0B,CAAC"}
1
+ {"version":3,"file":"generators.d.ts","sourceRoot":"","sources":["../../../packages/angular/generators.ts"],"names":[],"mappings":"AAAA,cAAc,0CAA0C,CAAC;AACzD,cAAc,0CAA0C,CAAC;AACzD,cAAc,kDAAkD,CAAC;AACjE,cAAc,sCAAsC,CAAC;AACrD,cAAc,sCAAsC,CAAC;AACrD,cAAc,kDAAkD,CAAC;AACjE,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8EAA8E,CAAC;AAC7F,cAAc,kCAAkC,CAAC;AACjD,cAAc,wDAAwD,CAAC;AACvE,cAAc,kDAAkD,CAAC;AACjE,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,gDAAgD,CAAC;AAC/D,cAAc,sCAAsC,CAAC;AACrD,cAAc,wDAAwD,CAAC;AACvE,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oCAAoC,CAAC;AACnD,cAAc,sCAAsC,CAAC;AACrD,cAAc,kCAAkC,CAAC;AACjD,cAAc,kEAAkE,CAAC;AACjF,cAAc,wCAAwC,CAAC;AACvD,OAAO,EAAE,6BAA6B,EAAE,MAAM,kFAAkF,CAAC;AACjI,cAAc,gDAAgD,CAAC;AAC/D,cAAc,0BAA0B,CAAC"}
package/generators.js CHANGED
@@ -12,7 +12,6 @@ tslib_1.__exportStar(require("./src/generators/host/host"), exports);
12
12
  tslib_1.__exportStar(require("./src/generators/init/init"), exports);
13
13
  tslib_1.__exportStar(require("./src/generators/library-secondary-entry-point/library-secondary-entry-point"), exports);
14
14
  tslib_1.__exportStar(require("./src/generators/library/library"), exports);
15
- tslib_1.__exportStar(require("./src/generators/ngrx/ngrx"), exports);
16
15
  tslib_1.__exportStar(require("./src/generators/ngrx-feature-store/ngrx-feature-store"), exports);
17
16
  tslib_1.__exportStar(require("./src/generators/ngrx-root-store/ngrx-root-store"), exports);
18
17
  tslib_1.__exportStar(require("./src/generators/pipe/pipe"), exports);
package/generators.json CHANGED
@@ -99,12 +99,6 @@
99
99
  "description": "Migrates an Angular CLI workspace to Nx or adds the Angular plugin to an Nx workspace.",
100
100
  "hidden": true
101
101
  },
102
- "ngrx": {
103
- "factory": "./src/generators/ngrx/ngrx",
104
- "schema": "./src/generators/ngrx/schema.json",
105
- "description": "Adds NgRx support to an application or library.",
106
- "x-deprecated": "Use the 'ngrx-root-store' and 'ngrx-feature-store' generators instead. It will be removed in Nx v22."
107
- },
108
102
  "ngrx-feature-store": {
109
103
  "factory": "./src/generators/ngrx-feature-store/ngrx-feature-store",
110
104
  "schema": "./src/generators/ngrx-feature-store/schema.json",
package/migrations.json CHANGED
@@ -394,6 +394,11 @@
394
394
  "version": "23.0.0-beta.0",
395
395
  "description": "Update the @nx/angular/module-federation import to use @nx/module-federation/angular.",
396
396
  "factory": "./src/migrations/update-23-0-0/migrate-with-mf-import-to-new-package"
397
+ },
398
+ "update-23-0-0-migrate-ngrx-generator-defaults": {
399
+ "version": "23.0.0-beta.7",
400
+ "description": "Split @nx/angular:ngrx generator defaults in nx.json across the @nx/angular:ngrx-root-store and @nx/angular:ngrx-feature-store generators.",
401
+ "factory": "./src/migrations/update-23-0-0/migrate-ngrx-generator-defaults"
397
402
  }
398
403
  },
399
404
  "packageJsonUpdates": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/angular",
3
- "version": "23.0.0-beta.8",
3
+ "version": "23.0.0-beta.9",
4
4
  "private": false,
5
5
  "description": "The Nx Plugin for Angular contains executors, generators, and utilities for managing Angular applications and libraries within an Nx workspace. It provides: \n\n- Integration with libraries such as Storybook, Jest, ESLint, Playwright and Cypress. \n\n- Generators to help scaffold code quickly (like: Micro Frontends, Libraries, both internal to your codebase and publishable to npm) \n\n- Single Component Application Modules (SCAMs) \n\n- NgRx helpers. \n\n- Utilities for automatic workspace refactoring.",
6
6
  "repository": {
@@ -61,13 +61,13 @@
61
61
  "migrations": "./migrations.json"
62
62
  },
63
63
  "dependencies": {
64
- "@nx/devkit": "23.0.0-beta.8",
65
- "@nx/eslint": "23.0.0-beta.8",
66
- "@nx/js": "23.0.0-beta.8",
67
- "@nx/module-federation": "23.0.0-beta.8",
68
- "@nx/rspack": "23.0.0-beta.8",
69
- "@nx/web": "23.0.0-beta.8",
70
- "@nx/webpack": "23.0.0-beta.8",
64
+ "@nx/devkit": "23.0.0-beta.9",
65
+ "@nx/eslint": "23.0.0-beta.9",
66
+ "@nx/js": "23.0.0-beta.9",
67
+ "@nx/module-federation": "23.0.0-beta.9",
68
+ "@nx/rspack": "23.0.0-beta.9",
69
+ "@nx/web": "23.0.0-beta.9",
70
+ "@nx/webpack": "23.0.0-beta.9",
71
71
  "@phenomnomnominal/tsquery": "~6.2.0",
72
72
  "@typescript-eslint/type-utils": "^8.0.0",
73
73
  "enquirer": "~2.3.6",
@@ -0,0 +1,3 @@
1
+ import { type Tree } from '@nx/devkit';
2
+ export default function (tree: Tree): Promise<void>;
3
+ //# sourceMappingURL=migrate-ngrx-generator-defaults.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate-ngrx-generator-defaults.d.ts","sourceRoot":"","sources":["../../../../../../packages/angular/src/migrations/update-23-0-0/migrate-ngrx-generator-defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,IAAI,EACV,MAAM,YAAY,CAAC;AAsCpB,yBAA+B,IAAI,EAAE,IAAI,iBAcxC"}
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = default_1;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const COLLECTION = '@nx/angular';
6
+ const OLD_GENERATOR = 'ngrx';
7
+ const OLD_KEY = `${COLLECTION}:${OLD_GENERATOR}`;
8
+ const ROOT_STORE = 'ngrx-root-store';
9
+ const FEATURE_STORE = 'ngrx-feature-store';
10
+ // Options supported by ngrx-root-store. The `minimal` option is included here
11
+ // because its semantics match the old generator (skip generating root feature
12
+ // state files).
13
+ const ROOT_STORE_OPTIONS = [
14
+ 'name',
15
+ 'route',
16
+ 'directory',
17
+ 'facade',
18
+ 'minimal',
19
+ 'skipImport',
20
+ 'skipPackageJson',
21
+ 'skipFormat',
22
+ ];
23
+ // Options supported by ngrx-feature-store. `minimal` is intentionally excluded:
24
+ // in the old generator it was a no-op for feature usage, but in
25
+ // ngrx-feature-store it skips template generation while still wiring imports,
26
+ // which would produce broken modules.
27
+ const FEATURE_STORE_OPTIONS = [
28
+ 'name',
29
+ 'parent',
30
+ 'route',
31
+ 'directory',
32
+ 'facade',
33
+ 'barrels',
34
+ 'skipImport',
35
+ 'skipPackageJson',
36
+ 'skipFormat',
37
+ ];
38
+ async function default_1(tree) {
39
+ const nxJson = (0, devkit_1.readNxJson)(tree);
40
+ if (nxJson?.generators && migrateGenerators(nxJson.generators)) {
41
+ (0, devkit_1.updateNxJson)(tree, nxJson);
42
+ }
43
+ const projects = (0, devkit_1.getProjects)(tree);
44
+ for (const [projectName, project] of projects) {
45
+ if (project.generators && migrateGenerators(project.generators)) {
46
+ (0, devkit_1.updateProjectConfiguration)(tree, projectName, project);
47
+ }
48
+ }
49
+ await (0, devkit_1.formatFiles)(tree);
50
+ }
51
+ function migrateGenerators(generators) {
52
+ const flatDefaults = generators[OLD_KEY];
53
+ const nestedDefaults = generators[COLLECTION]?.[OLD_GENERATOR];
54
+ if (!flatDefaults && !nestedDefaults) {
55
+ return false;
56
+ }
57
+ // Match Nx's runtime merge: nested first, then flat overrides.
58
+ // See `getGeneratorDefaults` in packages/nx/src/utils/params.ts.
59
+ const oldDefaults = {
60
+ ...(nestedDefaults ?? {}),
61
+ ...(flatDefaults ?? {}),
62
+ };
63
+ // Prefer flat when both shapes exist (it's the dominant runtime shape).
64
+ const useNestedFormat = !flatDefaults && !!nestedDefaults;
65
+ // The deprecated `module` option was an alias for `parent`. The old
66
+ // generator resolved `options.module ?? options.parent`, so `module` won
67
+ // when both were set — preserve that precedence here.
68
+ if (oldDefaults.module !== undefined) {
69
+ oldDefaults.parent = oldDefaults.module;
70
+ }
71
+ const rootStoreDefaults = pick(oldDefaults, ROOT_STORE_OPTIONS);
72
+ const featureStoreDefaults = pick(oldDefaults, FEATURE_STORE_OPTIONS);
73
+ if (Object.keys(rootStoreDefaults).length > 0) {
74
+ setNewDefaults(generators, ROOT_STORE, rootStoreDefaults, useNestedFormat);
75
+ }
76
+ if (Object.keys(featureStoreDefaults).length > 0) {
77
+ setNewDefaults(generators, FEATURE_STORE, featureStoreDefaults, useNestedFormat);
78
+ }
79
+ delete generators[OLD_KEY];
80
+ if (generators[COLLECTION]?.[OLD_GENERATOR] !== undefined) {
81
+ delete generators[COLLECTION][OLD_GENERATOR];
82
+ if (Object.keys(generators[COLLECTION]).length === 0) {
83
+ delete generators[COLLECTION];
84
+ }
85
+ }
86
+ return true;
87
+ }
88
+ function pick(obj, keys) {
89
+ const result = {};
90
+ for (const key of keys) {
91
+ if (obj[key] !== undefined) {
92
+ result[key] = obj[key];
93
+ }
94
+ }
95
+ return result;
96
+ }
97
+ function setNewDefaults(generators, generator, newDefaults, preferNestedFormat) {
98
+ const flatKey = `${COLLECTION}:${generator}`;
99
+ const existingFlat = generators[flatKey];
100
+ const existingNested = generators[COLLECTION]?.[generator];
101
+ // Per-generator destination: prefer whichever shape the user already uses
102
+ // for the replacement key, so the migrated defaults layer correctly under
103
+ // their existing values. Fall back to the input shape when neither exists.
104
+ const writeNested = existingNested !== undefined
105
+ ? true
106
+ : existingFlat !== undefined
107
+ ? false
108
+ : preferNestedFormat;
109
+ if (writeNested) {
110
+ generators[COLLECTION] ??= {};
111
+ // Existing user-set defaults take precedence over the migrated ones.
112
+ generators[COLLECTION][generator] = {
113
+ ...newDefaults,
114
+ ...(existingNested ?? {}),
115
+ };
116
+ }
117
+ else {
118
+ generators[flatKey] = { ...newDefaults, ...(existingFlat ?? {}) };
119
+ }
120
+ }
@@ -29,7 +29,7 @@ exports.backwardCompatibleVersions = {
29
29
  tsNodeVersion: '10.9.1',
30
30
  lessVersion: '^4.3.0',
31
31
  jestPresetAngularVersion: '~14.6.1',
32
- typesNodeVersion: '20.19.9',
32
+ typesNodeVersion: '^22.0.0',
33
33
  jasmineMarblesVersion: '^0.9.2',
34
34
  jsoncEslintParserVersion: '^2.1.0',
35
35
  webpackMergeVersion: '^5.8.0',
@@ -61,7 +61,7 @@ exports.backwardCompatibleVersions = {
61
61
  tsNodeVersion: '10.9.1',
62
62
  lessVersion: '^4.3.0',
63
63
  jestPresetAngularVersion: '~14.4.0',
64
- typesNodeVersion: '20.19.9',
64
+ typesNodeVersion: '^22.0.0',
65
65
  jasmineMarblesVersion: '^0.9.2',
66
66
  jsoncEslintParserVersion: '^2.1.0',
67
67
  webpackMergeVersion: '^5.8.0',
@@ -22,7 +22,7 @@ export declare const autoprefixerVersion = "^10.4.0";
22
22
  export declare const tsNodeVersion = "10.9.1";
23
23
  export declare const lessVersion = "^4.3.0";
24
24
  export declare const jestPresetAngularVersion = "~16.0.0";
25
- export declare const typesNodeVersion = "20.19.9";
25
+ export declare const typesNodeVersion = "^22.0.0";
26
26
  export declare const jasmineMarblesVersion = "^0.9.2";
27
27
  export declare const vitestVersion = "^4.0.8";
28
28
  export declare const jsdomVersion = "^27.1.0";
@@ -25,7 +25,7 @@ exports.autoprefixerVersion = '^10.4.0';
25
25
  exports.tsNodeVersion = '10.9.1';
26
26
  exports.lessVersion = '^4.3.0';
27
27
  exports.jestPresetAngularVersion = '~16.0.0';
28
- exports.typesNodeVersion = '20.19.9';
28
+ exports.typesNodeVersion = '^22.0.0';
29
29
  exports.jasmineMarblesVersion = '^0.9.2';
30
30
  exports.vitestVersion = '^4.0.8';
31
31
  exports.jsdomVersion = '^27.1.0';
@@ -1,16 +0,0 @@
1
- import { createAction, props } from '@ngrx/store';
2
- import { <%= className %>Entity } from './<%= fileName %>.models';
3
-
4
- export const init<%= className %> = createAction(
5
- '[<%= className %> Page] Init'
6
- );
7
-
8
- export const load<%= className %>Success = createAction(
9
- '[<%= className %>/API] Load <%= className %> Success',
10
- props<{ <%= propertyName %>: <%= className %>Entity[] }>()
11
- );
12
-
13
- export const load<%= className %>Failure = createAction(
14
- '[<%= className %>/API] Load <%= className %> Failure',
15
- props<{ error: any }>()
16
- );
@@ -1,37 +0,0 @@
1
- import { TestBed } from '@angular/core/testing';
2
- import { provideMockActions } from '@ngrx/effects/testing';
3
- import { Action } from '@ngrx/store';
4
- import { provideMockStore } from '@ngrx/store/testing';
5
- import { hot } from 'jasmine-marbles';
6
- import { Observable } from 'rxjs';
7
-
8
- import * as <%= className %>Actions from './<%= fileName %>.actions';
9
- import { <%= className %>Effects } from './<%= fileName %>.effects';
10
-
11
- describe('<%= className %>Effects', () => {
12
- let actions: Observable<Action>;
13
- let effects: <%= className %>Effects;
14
-
15
- beforeEach(() => {
16
- TestBed.configureTestingModule({
17
- imports: [],
18
- providers: [
19
- <%= className %>Effects,
20
- provideMockActions(() => actions),
21
- provideMockStore()
22
- ],
23
- });
24
-
25
- effects = TestBed.inject(<%= className %>Effects);
26
- });
27
-
28
- describe('init$', () => {
29
- it('should work', () => {
30
- actions = hot('-a-|', { a: <%= className %>Actions.init<%= className %>() });
31
-
32
- const expected = hot('-a-|', { a: <%= className %>Actions.load<%= className %>Success({ <%= propertyName %>: [] }) });
33
-
34
- expect(effects.init$).toBeObservable(expected);
35
- });
36
- });
37
- });
@@ -1,22 +0,0 @@
1
- import { Injectable, inject } from '@angular/core';
2
- import { createEffect, Actions, ofType } from '@ngrx/effects';<% if (!importFromOperators) { %>
3
- import { switchMap, catchError, of } from 'rxjs';<% } else { %>
4
- import { of } from 'rxjs';
5
- import { switchMap, catchError } from 'rxjs/operators';<% } %>
6
- import * as <%= className %>Actions from './<%= fileName %>.actions';
7
- import * as <%= className %>Feature from './<%= fileName %>.reducer';
8
-
9
- @Injectable()
10
- export class <%= className %>Effects {
11
- private actions$ = inject(Actions);
12
-
13
- init$ = createEffect(() => this.actions$.pipe(
14
- ofType(<%= className %>Actions.init<%= className %>),
15
- switchMap(() => of(<%= className %>Actions.load<%= className %>Success({ <%= propertyName %>: [] }))),
16
- catchError((error) => {
17
- console.error('Error', error);
18
- return of(<%= className %>Actions.load<%= className %>Failure({ error }));
19
- }
20
- )
21
- ));
22
- }
@@ -1,103 +0,0 @@
1
- import { NgModule } from '@angular/core';
2
- import { TestBed } from '@angular/core/testing';
3
- import { EffectsModule } from '@ngrx/effects';
4
- import { StoreModule, Store } from '@ngrx/store';
5
- <%_ if (isRxJs7) { _%>
6
- import { firstValueFrom } from 'rxjs';
7
- <%_ } else { _%>
8
- import { first } from 'rxjs/operators';
9
- <%_ } _%>
10
-
11
- import * as <%= className %>Actions from './<%= fileName %>.actions';
12
- import { <%= className %>Effects } from './<%= fileName %>.effects';
13
- import { <%= className %>Facade } from './<%= fileName %>.facade';
14
- import { <%= className %>Entity } from './<%= fileName %>.models';
15
- import {
16
- <%= constantName %>_FEATURE_KEY,
17
- <%= className %>State,
18
- initial<%= className %>State,
19
- <%= propertyName %>Reducer
20
- } from './<%= fileName %>.reducer';
21
- import * as <%= className %>Selectors from './<%= fileName %>.selectors';
22
-
23
- interface TestSchema {
24
- <%= propertyName %>: <%= className %>State;
25
- }
26
-
27
- describe('<%= className %>Facade', () => {
28
- let facade: <%= className %>Facade;
29
- let store: Store<TestSchema>;
30
- const create<%= className %>Entity = (id: string, name = ''): <%= className %>Entity => ({
31
- id,
32
- name: name || `name-${id}`
33
- });
34
-
35
- describe('used in NgModule', () => {
36
- beforeEach(() => {
37
- @NgModule({
38
- imports: [
39
- StoreModule.forFeature(<%= constantName %>_FEATURE_KEY, <%= propertyName %>Reducer),
40
- EffectsModule.forFeature([<%= className %>Effects])
41
- ],
42
- providers: [<%= className %>Facade]
43
- })
44
- class CustomFeatureModule {}
45
-
46
- @NgModule({
47
- imports: [
48
- StoreModule.forRoot({}),
49
- EffectsModule.forRoot([]),
50
- CustomFeatureModule,
51
- ]
52
- })
53
- class RootModule {}
54
- TestBed.configureTestingModule({ imports: [RootModule] });
55
-
56
- store = TestBed.inject(Store);
57
- facade = TestBed.inject(<%= className %>Facade);
58
- });
59
-
60
- /**
61
- * The initially generated facade::loadAll() returns empty array
62
- */
63
- it('loadAll() should return empty list with loaded == true', async () => {
64
- let list = await <% if (isRxJs7) { %>firstValueFrom(facade.all<%= className %>$)<% } else { %>facade.all<%= className %>$.pipe(first()).toPromise()<% } %>;
65
- let isLoaded = await <% if (isRxJs7) { %>firstValueFrom(facade.loaded$)<% } else { %>facade.loaded$.pipe(first()).toPromise()<% } %>;
66
-
67
- expect(list.length).toBe(0);
68
- expect(isLoaded).toBe(false);
69
-
70
- facade.init();
71
-
72
- list = await <% if (isRxJs7) { %>firstValueFrom(facade.all<%= className %>$)<% } else { %>facade.all<%= className %>$.pipe(first()).toPromise()<% } %>;
73
- isLoaded = await <% if (isRxJs7) { %>firstValueFrom(facade.loaded$)<% } else { %>facade.loaded$.pipe(first()).toPromise()<% } %>;
74
-
75
- expect(list.length).toBe(0);
76
- expect(isLoaded).toBe(true);
77
- });
78
-
79
- /**
80
- * Use `load<%= className %>Success` to manually update list
81
- */
82
- it('all<%= className %>$ should return the loaded list; and loaded flag == true', async () => {
83
- let list = await <% if (isRxJs7) { %>firstValueFrom(facade.all<%= className %>$)<% } else { %>facade.all<%= className %>$.pipe(first()).toPromise()<% } %>;
84
- let isLoaded = await <% if (isRxJs7) { %>firstValueFrom(facade.loaded$)<% } else { %>facade.loaded$.pipe(first()).toPromise()<% } %>;
85
-
86
- expect(list.length).toBe(0);
87
- expect(isLoaded).toBe(false);
88
-
89
- store.dispatch(<%= className %>Actions.load<%= className %>Success({
90
- <%= propertyName %>: [
91
- create<%= className %>Entity('AAA'),
92
- create<%= className %>Entity('BBB')
93
- ]})
94
- );
95
-
96
- list = await <% if (isRxJs7) { %>firstValueFrom(facade.all<%= className %>$)<% } else { %>facade.all<%= className %>$.pipe(first()).toPromise()<% } %>;
97
- isLoaded = await <% if (isRxJs7) { %>firstValueFrom(facade.loaded$)<% } else { %>facade.loaded$.pipe(first()).toPromise()<% } %>;
98
-
99
- expect(list.length).toBe(2);
100
- expect(isLoaded).toBe(true);
101
- });
102
- });
103
- });
@@ -1,27 +0,0 @@
1
- import { Injectable, inject } from '@angular/core';
2
- import { select, Store, Action } from '@ngrx/store';
3
-
4
- import * as <%= className %>Actions from './<%= fileName %>.actions';
5
- import * as <%= className %>Feature from './<%= fileName %>.reducer';
6
- import * as <%= className %>Selectors from './<%= fileName %>.selectors';
7
-
8
- @Injectable()
9
- export class <%= className %>Facade {
10
- private readonly store = inject(Store);
11
-
12
- /**
13
- * Combine pieces of state using createSelector,
14
- * and expose them as observables through the facade.
15
- */
16
- loaded$ = this.store.pipe(select(<%= className %>Selectors.select<%= className %>Loaded));
17
- all<%= className %>$ = this.store.pipe(select(<%= className %>Selectors.selectAll<%= className %>));
18
- selected<%= className %>$ = this.store.pipe(select(<%= className %>Selectors.selectEntity));
19
-
20
- /**
21
- * Use the initialization action to perform one
22
- * or more tasks in your Effects.
23
- */
24
- init() {
25
- this.store.dispatch(<%= className %>Actions.init<%= className %>());
26
- }
27
- }
@@ -1,7 +0,0 @@
1
- /**
2
- * Interface for the '<%= className %>' data
3
- */
4
- export interface <%= className %>Entity {
5
- id: string | number; // Primary ID
6
- name: string;
7
- }
@@ -1,37 +0,0 @@
1
- import { Action } from '@ngrx/store';
2
-
3
- import * as <%= className %>Actions from './<%= fileName %>.actions';
4
- import { <%= className %>Entity } from './<%= fileName %>.models';
5
- import { <%= className %>State, initial<%= className %>State, <%= propertyName %>Reducer } from './<%= fileName %>.reducer';
6
-
7
- describe('<%= className %> Reducer', () => {
8
- const create<%= className %>Entity = (id: string, name = ''): <%= className %>Entity => ({
9
- id,
10
- name: name || `name-${id}`
11
- });
12
-
13
- describe('valid <%= className %> actions', () => {
14
- it('load<%= className %>Success should return the list of known <%= className %>', () => {
15
- const <%= propertyName %> = [
16
- create<%= className %>Entity('PRODUCT-AAA'),
17
- create<%= className %>Entity('PRODUCT-zzz')
18
- ];
19
- const action = <%= className %>Actions.load<%= className %>Success({ <%= propertyName %> });
20
-
21
- const result: <%= className %>State = <%= propertyName %>Reducer(initial<%= className %>State, action);
22
-
23
- expect(result.loaded).toBe(true);
24
- expect(result.ids.length).toBe(2);
25
- });
26
- });
27
-
28
- describe('unknown action', () => {
29
- it('should return the previous state', () => {
30
- const action = {} as Action;
31
-
32
- const result = <%= propertyName %>Reducer(initial<%= className %>State, action);
33
-
34
- expect(result).toBe(initial<%= className %>State);
35
- });
36
- });
37
- });
@@ -1,41 +0,0 @@
1
- import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
2
- import { createReducer, on, Action } from '@ngrx/store';
3
-
4
- import * as <%= className %>Actions from './<%= fileName %>.actions';
5
- import { <%= className %>Entity } from './<%= fileName %>.models';
6
-
7
- export const <%= constantName %>_FEATURE_KEY = '<%= propertyName %>';
8
-
9
- export interface <%= className %>State extends EntityState<<%= className %>Entity> {
10
- selectedId?: string | number; // which <%= className %> record has been selected
11
- loaded: boolean; // has the <%= className %> list been loaded
12
- error?: string | null; // last known error (if any)
13
- }
14
-
15
- export interface <%= className %>PartialState {
16
- readonly [<%= constantName %>_FEATURE_KEY]: <%= className %>State;
17
- }
18
-
19
- export const <%= propertyName %>Adapter: EntityAdapter<<%= className %>Entity> = createEntityAdapter<<%= className %>Entity>();
20
-
21
- export const initial<%= className %>State: <%= className %>State = <%= propertyName %>Adapter.getInitialState({
22
- // set initial required properties
23
- loaded: false
24
- });
25
-
26
- const reducer = createReducer(
27
- initial<%= className %>State,
28
- on(<%= className %>Actions.init<%= className %>,
29
- state => ({ ...state, loaded: false, error: null })
30
- ),
31
- on(<%= className %>Actions.load<%= className %>Success,
32
- (state, { <%= propertyName %> }) => <%= propertyName %>Adapter.setAll(<%= propertyName %>, { ...state, loaded: true })
33
- ),
34
- on(<%= className %>Actions.load<%= className %>Failure,
35
- (state, { error }) => ({ ...state, error })
36
- ),
37
- );
38
-
39
- export function <%= propertyName %>Reducer(state: <%= className %>State | undefined, action: Action) {
40
- return reducer(state, action);
41
- }
@@ -1,58 +0,0 @@
1
- import { <%= className %>Entity } from './<%= fileName %>.models';
2
- import { <%= propertyName %>Adapter, <%= className %>PartialState, initial<%= className %>State } from './<%= fileName %>.reducer';
3
- import * as <%= className %>Selectors from './<%= fileName %>.selectors';
4
-
5
- describe('<%= className %> Selectors', () => {
6
- const ERROR_MSG = 'No Error Available';
7
- const get<%= className %>Id = (it: <%= className %>Entity) => it.id;
8
- const create<%= className %>Entity = (id: string, name = '') => ({
9
- id,
10
- name: name || `name-${id}`
11
- }) as <%= className %>Entity;
12
-
13
- let state: <%= className %>PartialState;
14
-
15
- beforeEach(() => {
16
- state = {
17
- <%= propertyName %>: <%= propertyName %>Adapter.setAll([
18
- create<%= className %>Entity('PRODUCT-AAA'),
19
- create<%= className %>Entity('PRODUCT-BBB'),
20
- create<%= className %>Entity('PRODUCT-CCC')
21
- ], {
22
- ...initial<%= className %>State,
23
- selectedId: 'PRODUCT-BBB',
24
- error: ERROR_MSG,
25
- loaded: true
26
- })
27
- };
28
- });
29
-
30
- describe('<%= className %> Selectors', () => {
31
- it('selectAll<%= className %>() should return the list of <%= className %>', () => {
32
- const results = <%= className %>Selectors.selectAll<%= className %>(state);
33
- const selId = get<%= className %>Id(results[1]);
34
-
35
- expect(results.length).toBe(3);
36
- expect(selId).toBe('PRODUCT-BBB');
37
- });
38
-
39
- it('selectEntity() should return the selected Entity', () => {
40
- const result = <%= className %>Selectors.selectEntity(state) as <%= className %>Entity;
41
- const selId = get<%= className %>Id(result);
42
-
43
- expect(selId).toBe('PRODUCT-BBB');
44
- });
45
-
46
- it('select<%= className %>Loaded() should return the current "loaded" status', () => {
47
- const result = <%= className %>Selectors.select<%= className %>Loaded(state);
48
-
49
- expect(result).toBe(true);
50
- });
51
-
52
- it('select<%= className %>Error() should return the current "error" state', () => {
53
- const result = <%= className %>Selectors.select<%= className %>Error(state);
54
-
55
- expect(result).toBe(ERROR_MSG);
56
- });
57
- });
58
- });
@@ -1,38 +0,0 @@
1
- import { createFeatureSelector, createSelector } from '@ngrx/store';
2
- import { <%= constantName %>_FEATURE_KEY, <%= className %>State, <%= propertyName %>Adapter } from './<%= fileName %>.reducer';
3
-
4
- // Lookup the '<%= className %>' feature state managed by NgRx
5
- export const select<%= className %>State = createFeatureSelector<<%= className %>State>(<%= constantName %>_FEATURE_KEY);
6
-
7
- const { selectAll, selectEntities } = <%= propertyName %>Adapter.getSelectors();
8
-
9
- export const select<%= className %>Loaded = createSelector(
10
- select<%= className %>State,
11
- (state: <%= className %>State) => state.loaded
12
- );
13
-
14
- export const select<%= className %>Error = createSelector(
15
- select<%= className %>State,
16
- (state: <%= className %>State) => state.error
17
- );
18
-
19
- export const selectAll<%= className %> = createSelector(
20
- select<%= className %>State,
21
- (state: <%= className %>State) => selectAll(state)
22
- );
23
-
24
- export const select<%= className %>Entities = createSelector(
25
- select<%= className %>State,
26
- (state: <%= className %>State) => selectEntities(state)
27
- );
28
-
29
- export const selectSelectedId = createSelector(
30
- select<%= className %>State,
31
- (state: <%= className %>State) => state.selectedId
32
- );
33
-
34
- export const selectEntity = createSelector(
35
- select<%= className %>Entities,
36
- selectSelectedId,
37
- (entities, selectedId) => (selectedId ? entities[selectedId] : undefined)
38
- );
@@ -1,7 +0,0 @@
1
- import type { Tree } from '@nx/devkit';
2
- import type { NormalizedNgRxGeneratorOptions } from './normalize-options';
3
- /**
4
- * Add ngrx feature exports to the public barrel in the feature library
5
- */
6
- export declare function addExportsToBarrel(tree: Tree, options: NormalizedNgRxGeneratorOptions): void;
7
- //# sourceMappingURL=add-exports-barrel.d.ts.map