Skip to content

Commit b82c35d

Browse files
brandonrobertsMikeRyanDev
authored andcommitted
feat(Schematics): Add option to group feature blueprints in respective folders (#736)
1 parent d73989e commit b82c35d

File tree

20 files changed

+106
-10
lines changed

20 files changed

+106
-10
lines changed

modules/schematics/src/action/index.spec.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ describe('Action Schematic', () => {
1313
path: 'app',
1414
sourceDir: 'src',
1515
spec: false,
16+
group: false,
17+
flat: true,
1618
};
1719

1820
it('should create one file', () => {
@@ -44,4 +46,13 @@ describe('Action Schematic', () => {
4446
expect(fileContent).toMatch(/export enum FooActionTypes/);
4547
}
4648
});
49+
50+
it('should group within an "actions" folder if group is set', () => {
51+
const tree = schematicRunner.runSchematic('action', {
52+
...defaultOptions,
53+
group: true,
54+
});
55+
expect(tree.files.length).toEqual(1);
56+
expect(tree.files[0]).toEqual('/src/app/actions/foo.actions.ts');
57+
});
4758
});

modules/schematics/src/action/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@ export default function(options: ActionOptions): Rule {
2525
const templateSource = apply(url('./files'), [
2626
options.spec ? noop() : filter(path => !path.endsWith('__spec.ts')),
2727
template({
28-
'if-flat': (s: string) => (options.flat ? '' : s),
28+
'if-flat': (s: string) =>
29+
stringUtils.group(
30+
options.flat ? '' : s,
31+
options.group ? 'actions' : ''
32+
),
2933
...stringUtils,
3034
...(options as object),
3135
dot: () => '.',

modules/schematics/src/action/schema.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ export interface Schema {
88
*/
99
spec?: boolean;
1010
flat?: boolean;
11+
group?: boolean;
1112
}

modules/schematics/src/action/schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@
2727
"type": "boolean",
2828
"default": true,
2929
"description": "Flag to indicate if a dir is created."
30+
},
31+
"group": {
32+
"type": "boolean",
33+
"default": false,
34+
"description": "Group actions file within 'actions' folder"
3035
}
3136
},
3237
"required": [

modules/schematics/src/effect/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.effects.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Injectable } from '@angular/core';
22
import { Actions, Effect } from '@ngrx/effects';
3-
<% if(feature) { %>import { <%= classify(name) %>Actions, <%= classify(name) %>ActionTypes } from './<%= dasherize(name) %>.actions';<% } %>
3+
<% if(feature) { %>import { <%= classify(name) %>Actions, <%= classify(name) %>ActionTypes } from '<%= featurePath(group, "actions") %><%= dasherize(name) %>.actions';<% } %>
44

55
@Injectable()
66
export class <%= classify(name) %>Effects {

modules/schematics/src/effect/index.spec.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ describe('Effect Schematic', () => {
2222
flat: false,
2323
feature: false,
2424
root: false,
25+
group: false,
2526
};
2627

2728
let appTree: Tree;
@@ -173,4 +174,14 @@ describe('Effect Schematic', () => {
173174

174175
expect(content).not.toMatch(/EffectsModule\.forRoot\(\[FooEffects\]\)/);
175176
});
177+
178+
it('should group within an "effects" folder if group is set', () => {
179+
const options = { ...defaultOptions, flat: true, spec: false, group: true };
180+
181+
const tree = schematicRunner.runSchematic('effect', options, appTree);
182+
const files = tree.files;
183+
expect(
184+
files.indexOf('/src/app/effects/foo.effects.ts')
185+
).toBeGreaterThanOrEqual(0);
186+
});
176187
});

modules/schematics/src/effect/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ function addImportToNgModule(options: EffectOptions): Rule {
6161

6262
const effectsPath =
6363
`/${options.sourceDir}/${options.path}/` +
64+
(options.group ? 'effects/' : '') +
6465
(options.flat ? '' : stringUtils.dasherize(options.name) + '/') +
6566
stringUtils.dasherize(options.name) +
6667
'.effects';
@@ -108,7 +109,11 @@ export default function(options: EffectOptions): Rule {
108109
options.spec ? noop() : filter(path => !path.endsWith('__spec.ts')),
109110
template({
110111
...stringUtils,
111-
'if-flat': (s: string) => (options.flat ? '' : s),
112+
'if-flat': (s: string) =>
113+
stringUtils.group(
114+
options.flat ? '' : s,
115+
options.group ? 'effects' : ''
116+
),
112117
...(options as object),
113118
dot: () => '.',
114119
}),

modules/schematics/src/effect/schema.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ export interface Schema {
1717
module?: string;
1818
root?: boolean;
1919
feature?: boolean;
20+
group?: boolean;
2021
}

modules/schematics/src/effect/schema.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,12 @@
4444
"type": "boolean",
4545
"default": false,
4646
"description": "Flag to indicate if part of a feature schematic."
47-
}
47+
},
48+
"group": {
49+
"type": "boolean",
50+
"default": false,
51+
"description": "Group effects file within 'effects' folder"
52+
}
4853
},
4954
"required": [
5055
"name"

modules/schematics/src/feature/index.spec.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ describe('Feature Schematic', () => {
1717
sourceDir: 'src',
1818
module: '',
1919
spec: true,
20+
group: false,
2021
};
2122

2223
it('should create all files of a feature', () => {
@@ -34,4 +35,26 @@ describe('Feature Schematic', () => {
3435
files.indexOf('/src/app/foo.effects.spec.ts')
3536
).toBeGreaterThanOrEqual(0);
3637
});
38+
39+
it('should create all files of a feature within grouped folders if group is set', () => {
40+
const options = { ...defaultOptions, group: true };
41+
42+
const tree = schematicRunner.runSchematic('feature', options);
43+
const files = tree.files;
44+
expect(
45+
files.indexOf('/src/app/actions/foo.actions.ts')
46+
).toBeGreaterThanOrEqual(0);
47+
expect(
48+
files.indexOf('/src/app/reducers/foo.reducer.ts')
49+
).toBeGreaterThanOrEqual(0);
50+
expect(
51+
files.indexOf('/src/app/reducers/foo.reducer.spec.ts')
52+
).toBeGreaterThanOrEqual(0);
53+
expect(
54+
files.indexOf('/src/app/effects/foo.effects.ts')
55+
).toBeGreaterThanOrEqual(0);
56+
expect(
57+
files.indexOf('/src/app/effects/foo.effects.spec.ts')
58+
).toBeGreaterThanOrEqual(0);
59+
});
3760
});

modules/schematics/src/feature/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,15 @@ export default function(options: FeatureOptions): Rule {
2727
return chain([
2828
schematic('action', {
2929
flat: options.flat,
30+
group: options.group,
3031
name: options.name,
3132
path: options.path,
3233
sourceDir: options.sourceDir,
3334
spec: false,
3435
}),
3536
schematic('reducer', {
3637
flat: options.flat,
38+
group: options.group,
3739
module: options.module,
3840
name: options.name,
3941
path: options.path,
@@ -44,6 +46,7 @@ export default function(options: FeatureOptions): Rule {
4446
}),
4547
schematic('effect', {
4648
flat: options.flat,
49+
group: options.group,
4750
module: options.module,
4851
name: options.name,
4952
path: options.path,

modules/schematics/src/feature/schema.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ export interface Schema {
66
flat?: boolean;
77
spec?: boolean;
88
reducers?: string;
9+
group?: boolean;
910
}

modules/schematics/src/feature/schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@
3535
"type": "string",
3636
"description": "Specifies the reducers file.",
3737
"aliases": ["r"]
38+
},
39+
"group": {
40+
"type": "boolean",
41+
"default": false,
42+
"description": "Group actions, reducers and effects within relative subfolders"
3843
}
3944
},
4045
"required": [

modules/schematics/src/reducer/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.reducer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Action } from '@ngrx/store';
2-
<% if(feature) { %>import { <%= classify(name) %>Actions, <%= classify(name) %>ActionTypes } from './<%= dasherize(name) %>.actions';<% } %>
2+
<% if(feature) { %>import { <%= classify(name) %>Actions, <%= classify(name) %>ActionTypes } from '<%= featurePath(group, "actions") %><%= dasherize(name) %>.actions';<% } %>
33

44
export interface State {
55

modules/schematics/src/reducer/index.spec.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,13 @@ describe('Reducer Schematic', () => {
8989

9090
expect(reducers).toMatch(/foo\: fromFoo.reducer/);
9191
});
92+
93+
it('should group within a "reducers" folder if group is set', () => {
94+
const tree = schematicRunner.runSchematic('reducer', {
95+
...defaultOptions,
96+
group: true,
97+
});
98+
expect(tree.files.length).toEqual(1);
99+
expect(tree.files[0]).toEqual('/src/app/reducers/foo.reducer.ts');
100+
});
92101
});

modules/schematics/src/reducer/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@ export default function(options: ReducerOptions): Rule {
4949
options.spec ? noop() : filter(path => !path.endsWith('__spec.ts')),
5050
template({
5151
...stringUtils,
52-
'if-flat': (s: string) => (options.flat ? '' : s),
52+
'if-flat': (s: string) =>
53+
stringUtils.group(
54+
options.flat ? '' : s,
55+
options.group ? 'reducers' : ''
56+
),
5357
...(options as object),
5458
dot: () => '.',
5559
}),

modules/schematics/src/reducer/schema.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ export interface Schema {
1414
module?: string;
1515
feature?: boolean;
1616
reducers?: string;
17+
group?: boolean;
1718
}

modules/schematics/src/reducer/schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@
4242
"type": "string",
4343
"description": "Specifies the reducers file.",
4444
"aliases": ["r"]
45+
},
46+
"group": {
47+
"type": "boolean",
48+
"default": false,
49+
"description": "Group reducer file within 'reducers' folder"
4550
}
4651
},
4752
"required": [

modules/schematics/src/strings.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,10 @@ export function capitalize(str: string): string {
134134
return str.charAt(0).toUpperCase() + str.substr(1);
135135
}
136136

137-
export function uppercase(str: string): string {
138-
return str.toUpperCase();
137+
export function group(path: string, group: string | undefined) {
138+
return group ? `${group}/${path}` : path;
139139
}
140140

141-
export function lowercase(str: string): string {
142-
return str.toLowerCase();
141+
export function featurePath(group: boolean | undefined, path: string) {
142+
return group ? `../${path}/` : './';
143143
}

modules/schematics/src/utility/ngrx-utils.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export function addReducerToState(options: ReducerOptions): Rule {
3838

3939
const reducerPath =
4040
`/${options.sourceDir}/${options.path}/` +
41+
(options.group ? 'reducers/' : '') +
4142
(options.flat ? '' : stringUtils.dasherize(options.name) + '/') +
4243
stringUtils.dasherize(options.name) +
4344
'.reducer';
@@ -216,6 +217,7 @@ export function addReducerImportToNgModule(options: ReducerOptions): Rule {
216217

217218
const reducerPath =
218219
`/${options.sourceDir}/${options.path}/` +
220+
(options.group ? 'reducers/' : '') +
219221
(options.flat ? '' : stringUtils.dasherize(options.name) + '/') +
220222
stringUtils.dasherize(options.name) +
221223
'.reducer';

0 commit comments

Comments
 (0)