Skip to content

Commit 5259890

Browse files
feat(store): register eslint-plugin-ngrx with ng add (#3014)
1 parent df760f8 commit 5259890

File tree

4 files changed

+96
-0
lines changed

4 files changed

+96
-0
lines changed

modules/store/schematics/ng-add/index.spec.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ describe('Store ng-add Schematic', () => {
1616
);
1717
const defaultOptions: RootStoreOptions = {
1818
skipPackageJson: false,
19+
skipESLintPlugin: false,
1920
project: 'bar',
2021
module: 'app',
2122
minimal: false,
@@ -146,4 +147,45 @@ describe('Store ng-add Schematic', () => {
146147

147148
expect(content).toMatch(/export interface AppState {/);
148149
});
150+
151+
it('should register the NgRx ESLint Plugin', async () => {
152+
const options = { ...defaultOptions };
153+
154+
const initialConfig = {};
155+
appTree.create('.eslintrc.json', JSON.stringify(initialConfig, null, 2));
156+
157+
const tree = await schematicRunner
158+
.runSchematicAsync('ng-add', options, appTree)
159+
.toPromise();
160+
161+
const packageContent = tree.readContent('package.json');
162+
const packageJson = JSON.parse(packageContent);
163+
expect(packageJson.devDependencies['eslint-plugin-ngrx']).toBeDefined();
164+
165+
const eslintContent = tree.readContent(`.eslintrc.json`);
166+
const eslintJson = JSON.parse(eslintContent);
167+
expect(eslintJson).toEqual({
168+
extends: ['plugin:ngrx/recommended'],
169+
plugins: ['ngrx'],
170+
});
171+
});
172+
173+
it('should not register the NgRx ESLint Plugin when skipped', async () => {
174+
const options = { ...defaultOptions, skipESLintPlugin: true };
175+
176+
const initialConfig = {};
177+
appTree.create('.eslintrc.json', JSON.stringify(initialConfig, null, 2));
178+
179+
const tree = await schematicRunner
180+
.runSchematicAsync('ng-add', options, appTree)
181+
.toPromise();
182+
183+
const packageContent = tree.readContent('package.json');
184+
const packageJson = JSON.parse(packageContent);
185+
expect(packageJson.devDependencies['eslint-plugin-ngrx']).not.toBeDefined();
186+
187+
const eslintContent = tree.readContent(`.eslintrc.json`);
188+
const eslintJson = JSON.parse(eslintContent);
189+
expect(eslintJson).toEqual(initialConfig);
190+
});
149191
});

modules/store/schematics/ng-add/index.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,53 @@ function addNgRxStoreToPackageJson() {
115115
};
116116
}
117117

118+
function addNgRxESLintPlugin() {
119+
return (host: Tree, context: SchematicContext) => {
120+
const eslintConfigPath = '.eslintrc.json';
121+
const docs =
122+
'https://github.com/timdeschryver/eslint-plugin-ngrx/#eslint-plugin-ngrx';
123+
124+
const eslint = host.read(eslintConfigPath)?.toString('utf-8');
125+
if (!eslint) {
126+
return host;
127+
}
128+
129+
addPackageToPackageJson(
130+
host,
131+
'devDependencies',
132+
'eslint-plugin-ngrx',
133+
'^1.0.0'
134+
);
135+
context.addTask(new NodePackageInstallTask());
136+
137+
try {
138+
const json = JSON.parse(eslint);
139+
json.plugins = [...(json.plugins || []), 'ngrx'];
140+
json.extends = [...(json.extends || []), 'plugin:ngrx/recommended'];
141+
host.overwrite(eslintConfigPath, JSON.stringify(json, null, 2));
142+
143+
context.logger.info(`
144+
The NgRx ESLint Plugin is installed and configured with the recommended config.
145+
146+
If you want to change the configuration, please see ${docs}.
147+
`);
148+
return host;
149+
} catch (err) {
150+
context.logger.warn(`
151+
Something went wrong while adding the NgRx ESLint Plugin.
152+
The NgRx ESLint Plugin is installed but not configured.
153+
154+
Please see ${docs} to configure the NgRx ESLint Plugin.
155+
156+
Details:
157+
${err.message}
158+
`);
159+
}
160+
161+
return host;
162+
};
163+
}
164+
118165
export default function (options: RootStoreOptions): Rule {
119166
return (host: Tree, context: SchematicContext) => {
120167
options.path = getProjectPath(host, options);
@@ -156,6 +203,7 @@ export default function (options: RootStoreOptions): Rule {
156203
chain([addImportToNgModule(options), mergeWith(templateSource)])
157204
),
158205
options && options.skipPackageJson ? noop() : addNgRxStoreToPackageJson(),
206+
options && options.skipESLintPlugin ? noop() : addNgRxESLintPlugin(),
159207
])(host, context);
160208
};
161209
}

modules/store/schematics/ng-add/schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@
4141
"type": "boolean",
4242
"default": true,
4343
"description": "Setup state management without registering initial reducers."
44+
},
45+
"skipESLintPlugin": {
46+
"type": "boolean",
47+
"default": false,
48+
"description": "Do not register the NgRx ESLint Plugin."
4449
}
4550
},
4651
"required": []

modules/store/schematics/ng-add/schema.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ export interface Schema {
99
* Setup state management without registering initial reducers.
1010
*/
1111
minimal?: boolean;
12+
skipESLintPlugin?: boolean;
1213
}

0 commit comments

Comments
 (0)