From 1e4953099280a033279671a467eaa90c2c8e407c Mon Sep 17 00:00:00 2001 From: Santosh Yadav Date: Tue, 12 Mar 2019 18:33:17 +0530 Subject: [PATCH] feat(schematics): use plural for entity schematics reducer key (#1596) Closes #1412 --- .../schematics-core/utility/ngrx-utils.ts | 22 +++++++------ .../schematics-core/utility/strings.ts | 19 +++++++++++ .../schematics-core/utility/ngrx-utils.ts | 22 +++++++------ .../entity/schematics-core/utility/strings.ts | 19 +++++++++++ .../schematics-core/utility/ngrx-utils.ts | 22 +++++++------ .../schematics-core/utility/strings.ts | 19 +++++++++++ modules/schematics-core/utility/ngrx-utils.ts | 22 +++++++------ modules/schematics-core/utility/strings.ts | 19 +++++++++++ .../schematics-core/utility/ngrx-utils.ts | 22 +++++++------ .../schematics-core/utility/strings.ts | 19 +++++++++++ modules/schematics/src/entity/index.spec.ts | 32 +++++++++++++++++++ modules/schematics/src/entity/index.ts | 2 +- .../schematics-core/utility/ngrx-utils.ts | 22 +++++++------ .../schematics-core/utility/strings.ts | 19 +++++++++++ .../schematics-core/utility/ngrx-utils.ts | 22 +++++++------ .../store/schematics-core/utility/strings.ts | 19 +++++++++++ 16 files changed, 250 insertions(+), 71 deletions(-) diff --git a/modules/effects/schematics-core/utility/ngrx-utils.ts b/modules/effects/schematics-core/utility/ngrx-utils.ts index 28294e1110..0dd26b3398 100644 --- a/modules/effects/schematics-core/utility/ngrx-utils.ts +++ b/modules/effects/schematics-core/utility/ngrx-utils.ts @@ -79,7 +79,7 @@ export function addReducerToState(options: any): Rule { export function addReducerToStateInterface( source: ts.SourceFile, reducersPath: string, - options: { name: string } + options: { name: string; plural: boolean } ): Change { const stateInterface = source.statements.find( stm => stm.kind === ts.SyntaxKind.InterfaceDeclaration @@ -90,11 +90,12 @@ export function addReducerToStateInterface( return new NoopChange(); } + const state = options.plural + ? stringUtils.pluralize(options.name) + : stringUtils.camelize(options.name); + const keyInsert = - stringUtils.camelize(options.name) + - ': from' + - stringUtils.classify(options.name) + - '.State;'; + state + ': from' + stringUtils.classify(options.name) + '.State;'; const expr = node as any; let position; let toInsert; @@ -125,7 +126,7 @@ export function addReducerToStateInterface( export function addReducerToActionReducerMap( source: ts.SourceFile, reducersPath: string, - options: { name: string } + options: { name: string; plural: boolean } ): Change { let initializer: any; const actionReducerMap: any = source.statements @@ -152,11 +153,12 @@ export function addReducerToActionReducerMap( let node = actionReducerMap.initializer; + const state = options.plural + ? stringUtils.pluralize(options.name) + : stringUtils.camelize(options.name); + const keyInsert = - stringUtils.camelize(options.name) + - ': from' + - stringUtils.classify(options.name) + - '.reducer,'; + state + ': from' + stringUtils.classify(options.name) + '.reducer,'; const expr = node as any; let position; let toInsert; diff --git a/modules/effects/schematics-core/utility/strings.ts b/modules/effects/schematics-core/utility/strings.ts index dae37e563c..5ebec70706 100644 --- a/modules/effects/schematics-core/utility/strings.ts +++ b/modules/effects/schematics-core/utility/strings.ts @@ -110,6 +110,25 @@ export function capitalize(str: string): string { return str.charAt(0).toUpperCase() + str.substr(1); } +/** + Returns the plural form of a string + + ```javascript + 'innerHTML'.pluralize() // 'InnerHTMLs' + 'action_name'.pluralize() // 'actionNames' + 'css-class-name'.pluralize() // 'cssClassNames' + 'regex'.pluralize() // 'regexes' + 'user'.pluralize() // 'users' + ``` + */ +export function pluralize(str: string): string { + return camelize( + [/([^aeiou])y$/, /()fe?$/, /([^aeiou]o|[sxz]|[cs]h)$/].map( + (c, i) => (str = str.replace(c, `$1${'iv'[i] || ''}e`)) + ) && str + 's' + ); +} + export function group(name: string, group: string | undefined) { return group ? `${group}/${name}` : name; } diff --git a/modules/entity/schematics-core/utility/ngrx-utils.ts b/modules/entity/schematics-core/utility/ngrx-utils.ts index 28294e1110..0dd26b3398 100644 --- a/modules/entity/schematics-core/utility/ngrx-utils.ts +++ b/modules/entity/schematics-core/utility/ngrx-utils.ts @@ -79,7 +79,7 @@ export function addReducerToState(options: any): Rule { export function addReducerToStateInterface( source: ts.SourceFile, reducersPath: string, - options: { name: string } + options: { name: string; plural: boolean } ): Change { const stateInterface = source.statements.find( stm => stm.kind === ts.SyntaxKind.InterfaceDeclaration @@ -90,11 +90,12 @@ export function addReducerToStateInterface( return new NoopChange(); } + const state = options.plural + ? stringUtils.pluralize(options.name) + : stringUtils.camelize(options.name); + const keyInsert = - stringUtils.camelize(options.name) + - ': from' + - stringUtils.classify(options.name) + - '.State;'; + state + ': from' + stringUtils.classify(options.name) + '.State;'; const expr = node as any; let position; let toInsert; @@ -125,7 +126,7 @@ export function addReducerToStateInterface( export function addReducerToActionReducerMap( source: ts.SourceFile, reducersPath: string, - options: { name: string } + options: { name: string; plural: boolean } ): Change { let initializer: any; const actionReducerMap: any = source.statements @@ -152,11 +153,12 @@ export function addReducerToActionReducerMap( let node = actionReducerMap.initializer; + const state = options.plural + ? stringUtils.pluralize(options.name) + : stringUtils.camelize(options.name); + const keyInsert = - stringUtils.camelize(options.name) + - ': from' + - stringUtils.classify(options.name) + - '.reducer,'; + state + ': from' + stringUtils.classify(options.name) + '.reducer,'; const expr = node as any; let position; let toInsert; diff --git a/modules/entity/schematics-core/utility/strings.ts b/modules/entity/schematics-core/utility/strings.ts index dae37e563c..5ebec70706 100644 --- a/modules/entity/schematics-core/utility/strings.ts +++ b/modules/entity/schematics-core/utility/strings.ts @@ -110,6 +110,25 @@ export function capitalize(str: string): string { return str.charAt(0).toUpperCase() + str.substr(1); } +/** + Returns the plural form of a string + + ```javascript + 'innerHTML'.pluralize() // 'InnerHTMLs' + 'action_name'.pluralize() // 'actionNames' + 'css-class-name'.pluralize() // 'cssClassNames' + 'regex'.pluralize() // 'regexes' + 'user'.pluralize() // 'users' + ``` + */ +export function pluralize(str: string): string { + return camelize( + [/([^aeiou])y$/, /()fe?$/, /([^aeiou]o|[sxz]|[cs]h)$/].map( + (c, i) => (str = str.replace(c, `$1${'iv'[i] || ''}e`)) + ) && str + 's' + ); +} + export function group(name: string, group: string | undefined) { return group ? `${group}/${name}` : name; } diff --git a/modules/router-store/schematics-core/utility/ngrx-utils.ts b/modules/router-store/schematics-core/utility/ngrx-utils.ts index 28294e1110..0dd26b3398 100644 --- a/modules/router-store/schematics-core/utility/ngrx-utils.ts +++ b/modules/router-store/schematics-core/utility/ngrx-utils.ts @@ -79,7 +79,7 @@ export function addReducerToState(options: any): Rule { export function addReducerToStateInterface( source: ts.SourceFile, reducersPath: string, - options: { name: string } + options: { name: string; plural: boolean } ): Change { const stateInterface = source.statements.find( stm => stm.kind === ts.SyntaxKind.InterfaceDeclaration @@ -90,11 +90,12 @@ export function addReducerToStateInterface( return new NoopChange(); } + const state = options.plural + ? stringUtils.pluralize(options.name) + : stringUtils.camelize(options.name); + const keyInsert = - stringUtils.camelize(options.name) + - ': from' + - stringUtils.classify(options.name) + - '.State;'; + state + ': from' + stringUtils.classify(options.name) + '.State;'; const expr = node as any; let position; let toInsert; @@ -125,7 +126,7 @@ export function addReducerToStateInterface( export function addReducerToActionReducerMap( source: ts.SourceFile, reducersPath: string, - options: { name: string } + options: { name: string; plural: boolean } ): Change { let initializer: any; const actionReducerMap: any = source.statements @@ -152,11 +153,12 @@ export function addReducerToActionReducerMap( let node = actionReducerMap.initializer; + const state = options.plural + ? stringUtils.pluralize(options.name) + : stringUtils.camelize(options.name); + const keyInsert = - stringUtils.camelize(options.name) + - ': from' + - stringUtils.classify(options.name) + - '.reducer,'; + state + ': from' + stringUtils.classify(options.name) + '.reducer,'; const expr = node as any; let position; let toInsert; diff --git a/modules/router-store/schematics-core/utility/strings.ts b/modules/router-store/schematics-core/utility/strings.ts index dae37e563c..5ebec70706 100644 --- a/modules/router-store/schematics-core/utility/strings.ts +++ b/modules/router-store/schematics-core/utility/strings.ts @@ -110,6 +110,25 @@ export function capitalize(str: string): string { return str.charAt(0).toUpperCase() + str.substr(1); } +/** + Returns the plural form of a string + + ```javascript + 'innerHTML'.pluralize() // 'InnerHTMLs' + 'action_name'.pluralize() // 'actionNames' + 'css-class-name'.pluralize() // 'cssClassNames' + 'regex'.pluralize() // 'regexes' + 'user'.pluralize() // 'users' + ``` + */ +export function pluralize(str: string): string { + return camelize( + [/([^aeiou])y$/, /()fe?$/, /([^aeiou]o|[sxz]|[cs]h)$/].map( + (c, i) => (str = str.replace(c, `$1${'iv'[i] || ''}e`)) + ) && str + 's' + ); +} + export function group(name: string, group: string | undefined) { return group ? `${group}/${name}` : name; } diff --git a/modules/schematics-core/utility/ngrx-utils.ts b/modules/schematics-core/utility/ngrx-utils.ts index 28294e1110..0dd26b3398 100644 --- a/modules/schematics-core/utility/ngrx-utils.ts +++ b/modules/schematics-core/utility/ngrx-utils.ts @@ -79,7 +79,7 @@ export function addReducerToState(options: any): Rule { export function addReducerToStateInterface( source: ts.SourceFile, reducersPath: string, - options: { name: string } + options: { name: string; plural: boolean } ): Change { const stateInterface = source.statements.find( stm => stm.kind === ts.SyntaxKind.InterfaceDeclaration @@ -90,11 +90,12 @@ export function addReducerToStateInterface( return new NoopChange(); } + const state = options.plural + ? stringUtils.pluralize(options.name) + : stringUtils.camelize(options.name); + const keyInsert = - stringUtils.camelize(options.name) + - ': from' + - stringUtils.classify(options.name) + - '.State;'; + state + ': from' + stringUtils.classify(options.name) + '.State;'; const expr = node as any; let position; let toInsert; @@ -125,7 +126,7 @@ export function addReducerToStateInterface( export function addReducerToActionReducerMap( source: ts.SourceFile, reducersPath: string, - options: { name: string } + options: { name: string; plural: boolean } ): Change { let initializer: any; const actionReducerMap: any = source.statements @@ -152,11 +153,12 @@ export function addReducerToActionReducerMap( let node = actionReducerMap.initializer; + const state = options.plural + ? stringUtils.pluralize(options.name) + : stringUtils.camelize(options.name); + const keyInsert = - stringUtils.camelize(options.name) + - ': from' + - stringUtils.classify(options.name) + - '.reducer,'; + state + ': from' + stringUtils.classify(options.name) + '.reducer,'; const expr = node as any; let position; let toInsert; diff --git a/modules/schematics-core/utility/strings.ts b/modules/schematics-core/utility/strings.ts index dae37e563c..5ebec70706 100644 --- a/modules/schematics-core/utility/strings.ts +++ b/modules/schematics-core/utility/strings.ts @@ -110,6 +110,25 @@ export function capitalize(str: string): string { return str.charAt(0).toUpperCase() + str.substr(1); } +/** + Returns the plural form of a string + + ```javascript + 'innerHTML'.pluralize() // 'InnerHTMLs' + 'action_name'.pluralize() // 'actionNames' + 'css-class-name'.pluralize() // 'cssClassNames' + 'regex'.pluralize() // 'regexes' + 'user'.pluralize() // 'users' + ``` + */ +export function pluralize(str: string): string { + return camelize( + [/([^aeiou])y$/, /()fe?$/, /([^aeiou]o|[sxz]|[cs]h)$/].map( + (c, i) => (str = str.replace(c, `$1${'iv'[i] || ''}e`)) + ) && str + 's' + ); +} + export function group(name: string, group: string | undefined) { return group ? `${group}/${name}` : name; } diff --git a/modules/schematics/schematics-core/utility/ngrx-utils.ts b/modules/schematics/schematics-core/utility/ngrx-utils.ts index 28294e1110..0dd26b3398 100644 --- a/modules/schematics/schematics-core/utility/ngrx-utils.ts +++ b/modules/schematics/schematics-core/utility/ngrx-utils.ts @@ -79,7 +79,7 @@ export function addReducerToState(options: any): Rule { export function addReducerToStateInterface( source: ts.SourceFile, reducersPath: string, - options: { name: string } + options: { name: string; plural: boolean } ): Change { const stateInterface = source.statements.find( stm => stm.kind === ts.SyntaxKind.InterfaceDeclaration @@ -90,11 +90,12 @@ export function addReducerToStateInterface( return new NoopChange(); } + const state = options.plural + ? stringUtils.pluralize(options.name) + : stringUtils.camelize(options.name); + const keyInsert = - stringUtils.camelize(options.name) + - ': from' + - stringUtils.classify(options.name) + - '.State;'; + state + ': from' + stringUtils.classify(options.name) + '.State;'; const expr = node as any; let position; let toInsert; @@ -125,7 +126,7 @@ export function addReducerToStateInterface( export function addReducerToActionReducerMap( source: ts.SourceFile, reducersPath: string, - options: { name: string } + options: { name: string; plural: boolean } ): Change { let initializer: any; const actionReducerMap: any = source.statements @@ -152,11 +153,12 @@ export function addReducerToActionReducerMap( let node = actionReducerMap.initializer; + const state = options.plural + ? stringUtils.pluralize(options.name) + : stringUtils.camelize(options.name); + const keyInsert = - stringUtils.camelize(options.name) + - ': from' + - stringUtils.classify(options.name) + - '.reducer,'; + state + ': from' + stringUtils.classify(options.name) + '.reducer,'; const expr = node as any; let position; let toInsert; diff --git a/modules/schematics/schematics-core/utility/strings.ts b/modules/schematics/schematics-core/utility/strings.ts index dae37e563c..5ebec70706 100644 --- a/modules/schematics/schematics-core/utility/strings.ts +++ b/modules/schematics/schematics-core/utility/strings.ts @@ -110,6 +110,25 @@ export function capitalize(str: string): string { return str.charAt(0).toUpperCase() + str.substr(1); } +/** + Returns the plural form of a string + + ```javascript + 'innerHTML'.pluralize() // 'InnerHTMLs' + 'action_name'.pluralize() // 'actionNames' + 'css-class-name'.pluralize() // 'cssClassNames' + 'regex'.pluralize() // 'regexes' + 'user'.pluralize() // 'users' + ``` + */ +export function pluralize(str: string): string { + return camelize( + [/([^aeiou])y$/, /()fe?$/, /([^aeiou]o|[sxz]|[cs]h)$/].map( + (c, i) => (str = str.replace(c, `$1${'iv'[i] || ''}e`)) + ) && str + 's' + ); +} + export function group(name: string, group: string | undefined) { return group ? `${group}/${name}` : name; } diff --git a/modules/schematics/src/entity/index.spec.ts b/modules/schematics/src/entity/index.spec.ts index 1ae89a8054..3933d604b6 100644 --- a/modules/schematics/src/entity/index.spec.ts +++ b/modules/schematics/src/entity/index.spec.ts @@ -127,6 +127,7 @@ describe('Entity Schematic', () => { const tree = schematicRunner.runSchematic('entity', options, appTree); const files = tree.files; + expect( files.indexOf(`${projectPath}/src/app/foo/actions/foo.actions.ts`) ).toBeGreaterThanOrEqual(0); @@ -146,6 +147,7 @@ describe('Entity Schematic', () => { const tree = schematicRunner.runSchematic('entity', options, appTree); const files = tree.files; + expect( files.indexOf(`${projectPath}/src/app/actions/foo.actions.ts`) ).toBeGreaterThanOrEqual(0); @@ -159,4 +161,34 @@ describe('Entity Schematic', () => { files.indexOf(`${projectPath}/src/app/reducers/foo.reducer.spec.ts`) ).toBeGreaterThanOrEqual(0); }); + + it('should update the state to plural', () => { + const options = { + ...defaultOptions, + name: 'user', + reducers: 'reducers/index.ts', + spec: true, + }; + + const reducerTree = schematicRunner.runSchematic('store', options, appTree); + const tree = schematicRunner.runSchematic('entity', options, appTree); + const files = tree.files; + const content = tree.readContent( + `${projectPath}/src/app/reducers/index.ts` + ); + expect( + files.indexOf(`${projectPath}/src/app/user.actions.ts`) + ).toBeGreaterThanOrEqual(0); + expect( + files.indexOf(`${projectPath}/src/app/user.model.ts`) + ).toBeGreaterThanOrEqual(0); + expect( + files.indexOf(`${projectPath}/src/app/user.reducer.ts`) + ).toBeGreaterThanOrEqual(0); + expect( + files.indexOf(`${projectPath}/src/app/user.reducer.spec.ts`) + ).toBeGreaterThanOrEqual(0); + expect(content).toMatch(/users\: fromUser.State/); + expect(content).toMatch(/users\: fromUser.reducer/); + }); }); diff --git a/modules/schematics/src/entity/index.ts b/modules/schematics/src/entity/index.ts index 4278b6ad9e..9cf5572a09 100644 --- a/modules/schematics/src/entity/index.ts +++ b/modules/schematics/src/entity/index.ts @@ -55,7 +55,7 @@ export default function(options: EntityOptions): Rule { ]); return chain([ - addReducerToState({ ...options }), + addReducerToState({ ...options, plural: true }), addReducerImportToNgModule({ ...options }), branchAndMerge(chain([mergeWith(templateSource)])), ])(host, context); diff --git a/modules/store-devtools/schematics-core/utility/ngrx-utils.ts b/modules/store-devtools/schematics-core/utility/ngrx-utils.ts index 28294e1110..0dd26b3398 100644 --- a/modules/store-devtools/schematics-core/utility/ngrx-utils.ts +++ b/modules/store-devtools/schematics-core/utility/ngrx-utils.ts @@ -79,7 +79,7 @@ export function addReducerToState(options: any): Rule { export function addReducerToStateInterface( source: ts.SourceFile, reducersPath: string, - options: { name: string } + options: { name: string; plural: boolean } ): Change { const stateInterface = source.statements.find( stm => stm.kind === ts.SyntaxKind.InterfaceDeclaration @@ -90,11 +90,12 @@ export function addReducerToStateInterface( return new NoopChange(); } + const state = options.plural + ? stringUtils.pluralize(options.name) + : stringUtils.camelize(options.name); + const keyInsert = - stringUtils.camelize(options.name) + - ': from' + - stringUtils.classify(options.name) + - '.State;'; + state + ': from' + stringUtils.classify(options.name) + '.State;'; const expr = node as any; let position; let toInsert; @@ -125,7 +126,7 @@ export function addReducerToStateInterface( export function addReducerToActionReducerMap( source: ts.SourceFile, reducersPath: string, - options: { name: string } + options: { name: string; plural: boolean } ): Change { let initializer: any; const actionReducerMap: any = source.statements @@ -152,11 +153,12 @@ export function addReducerToActionReducerMap( let node = actionReducerMap.initializer; + const state = options.plural + ? stringUtils.pluralize(options.name) + : stringUtils.camelize(options.name); + const keyInsert = - stringUtils.camelize(options.name) + - ': from' + - stringUtils.classify(options.name) + - '.reducer,'; + state + ': from' + stringUtils.classify(options.name) + '.reducer,'; const expr = node as any; let position; let toInsert; diff --git a/modules/store-devtools/schematics-core/utility/strings.ts b/modules/store-devtools/schematics-core/utility/strings.ts index dae37e563c..5ebec70706 100644 --- a/modules/store-devtools/schematics-core/utility/strings.ts +++ b/modules/store-devtools/schematics-core/utility/strings.ts @@ -110,6 +110,25 @@ export function capitalize(str: string): string { return str.charAt(0).toUpperCase() + str.substr(1); } +/** + Returns the plural form of a string + + ```javascript + 'innerHTML'.pluralize() // 'InnerHTMLs' + 'action_name'.pluralize() // 'actionNames' + 'css-class-name'.pluralize() // 'cssClassNames' + 'regex'.pluralize() // 'regexes' + 'user'.pluralize() // 'users' + ``` + */ +export function pluralize(str: string): string { + return camelize( + [/([^aeiou])y$/, /()fe?$/, /([^aeiou]o|[sxz]|[cs]h)$/].map( + (c, i) => (str = str.replace(c, `$1${'iv'[i] || ''}e`)) + ) && str + 's' + ); +} + export function group(name: string, group: string | undefined) { return group ? `${group}/${name}` : name; } diff --git a/modules/store/schematics-core/utility/ngrx-utils.ts b/modules/store/schematics-core/utility/ngrx-utils.ts index 28294e1110..0dd26b3398 100644 --- a/modules/store/schematics-core/utility/ngrx-utils.ts +++ b/modules/store/schematics-core/utility/ngrx-utils.ts @@ -79,7 +79,7 @@ export function addReducerToState(options: any): Rule { export function addReducerToStateInterface( source: ts.SourceFile, reducersPath: string, - options: { name: string } + options: { name: string; plural: boolean } ): Change { const stateInterface = source.statements.find( stm => stm.kind === ts.SyntaxKind.InterfaceDeclaration @@ -90,11 +90,12 @@ export function addReducerToStateInterface( return new NoopChange(); } + const state = options.plural + ? stringUtils.pluralize(options.name) + : stringUtils.camelize(options.name); + const keyInsert = - stringUtils.camelize(options.name) + - ': from' + - stringUtils.classify(options.name) + - '.State;'; + state + ': from' + stringUtils.classify(options.name) + '.State;'; const expr = node as any; let position; let toInsert; @@ -125,7 +126,7 @@ export function addReducerToStateInterface( export function addReducerToActionReducerMap( source: ts.SourceFile, reducersPath: string, - options: { name: string } + options: { name: string; plural: boolean } ): Change { let initializer: any; const actionReducerMap: any = source.statements @@ -152,11 +153,12 @@ export function addReducerToActionReducerMap( let node = actionReducerMap.initializer; + const state = options.plural + ? stringUtils.pluralize(options.name) + : stringUtils.camelize(options.name); + const keyInsert = - stringUtils.camelize(options.name) + - ': from' + - stringUtils.classify(options.name) + - '.reducer,'; + state + ': from' + stringUtils.classify(options.name) + '.reducer,'; const expr = node as any; let position; let toInsert; diff --git a/modules/store/schematics-core/utility/strings.ts b/modules/store/schematics-core/utility/strings.ts index dae37e563c..5ebec70706 100644 --- a/modules/store/schematics-core/utility/strings.ts +++ b/modules/store/schematics-core/utility/strings.ts @@ -110,6 +110,25 @@ export function capitalize(str: string): string { return str.charAt(0).toUpperCase() + str.substr(1); } +/** + Returns the plural form of a string + + ```javascript + 'innerHTML'.pluralize() // 'InnerHTMLs' + 'action_name'.pluralize() // 'actionNames' + 'css-class-name'.pluralize() // 'cssClassNames' + 'regex'.pluralize() // 'regexes' + 'user'.pluralize() // 'users' + ``` + */ +export function pluralize(str: string): string { + return camelize( + [/([^aeiou])y$/, /()fe?$/, /([^aeiou]o|[sxz]|[cs]h)$/].map( + (c, i) => (str = str.replace(c, `$1${'iv'[i] || ''}e`)) + ) && str + 's' + ); +} + export function group(name: string, group: string | undefined) { return group ? `${group}/${name}` : name; }