Scenario
We want to build a custom schematic for company Aero that will internally do two things:
- build a new ngrx library using Nx workspace naming conventions
- generate ngrx state-management files; include the
*.facade.*
files
Important: This example is valid ONLY for Nx v6.2.x or higher!
Steps to Build/Use Custom Schematics
- Use the following command to generate a custom schematic called
ngrx-lib
.
This custom workspace schematic will:
- Generate a Nx library
- Generate NgRx files inside a folder called
+state
. - Generate NgRx Facade files for the new NgRx state management files
ng g workspace-schematic ngrx-lib
- Then open the new empty schematic at
/tools/schematics/ngrx-lib/index.ts
and replace the contents with your own custom logic.
The schematic code for our requirements is here :
/tools/schematics/ngrx-lib/index.ts
import {
chain,
externalSchematic,
Rule
} from '@angular-devkit/schematics';
import * as path from 'path';
/**
* Build a new custom Nx library with ngrx files.
* Using Nx workspace conventions, these custom libraries are 'state' libraries since
* they will manage ngrx state, REST endpoints, etc.
*/
export default function(schema: any): Rule {
const PREFIX = 'state-';
if (!schema.name.startsWith('state-') && (schema.name != 'state')) {
// custom libraries managing state must have name conventions: 'state' or 'state-<name>'
schema.name = PREFIX + schema.name;
}
const name = schema.name.substring(PREFIX.length);
const libPath = schema.directory ? path.join(schema.directory, schema.name) : schema.name;
const moduleName = schema.directory ? `${schema.directory}-${schema.name}` : schema.name;
const module = path.join('libs',libPath, 'src/lib', `${moduleName}.module.ts`);
return chain([
externalSchematic('@nrwl/schematics', 'lib', {
name: schema.name,
directory : schema.directory,
tags : schema.directory ? `state, ${schema.directory}` : 'state, aero'
}),
externalSchematic('@nrwl/schematics', 'ngrx', {
name,
module,
directory: '+state',
facade : true
})
]);
}
- Now you can use the custom workspace schematic (in your workspace).
In our example, we want a new state library called for airports and we want to group that library in a directory called trip-planner:
npm run workspace-schematic ngrx-lib airports -- --directory=trip-planner
# or
yarn workspace-schematic ngrx-lib planes --directory=trip-planner
Note the extra
--
when using npm. This is required so these options are considered options for theworkspace-schematic
instead of npm itself.
This would output to the console something similar to:
create libs/trip-planner/state-planes/karma.conf.js (508 bytes)
create libs/trip-planner/state-planes/tsconfig.lib.json (828 bytes)
create libs/trip-planner/state-planes/tsconfig.spec.json (283 bytes)
create libs/trip-planner/state-planes/tslint.json (252 bytes)
create libs/trip-planner/state-planes/src/index.ts (205 bytes)
create libs/trip-planner/state-planes/src/test.ts (700 bytes)
create libs/trip-planner/state-planes/src/lib/trip-planner-state-planes.module.ts (720 bytes)
create libs/trip-planner/state-planes/src/lib/trip-planner-state-planes.module.spec.ts (445 bytes)
create libs/trip-planner/state-planes/src/lib/+state/planes.actions.ts (727 bytes)
create libs/trip-planner/state-planes/src/lib/+state/planes.effects.spec.ts (1158 bytes)
create libs/trip-planner/state-planes/src/lib/+state/planes.effects.ts (833 bytes)
create libs/trip-planner/state-planes/src/lib/+state/planes.facade.spec.ts (2848 bytes)
create libs/trip-planner/state-planes/src/lib/+state/planes.facade.ts (606 bytes)
create libs/trip-planner/state-planes/src/lib/+state/planes.reducer.spec.ts (1130 bytes)
create libs/trip-planner/state-planes/src/lib/+state/planes.reducer.ts (960 bytes)
create libs/trip-planner/state-planes/src/lib/+state/planes.selectors.spec.ts (1596 bytes)
create libs/trip-planner/state-planes/src/lib/+state/planes.selectors.ts (962 bytes)
Notice how
trip-planner-state-planes.module.ts
has export class TripPlannerStatePlanesModule and uses the<grouping-folder>-<library-name>.module.ts
convention. This allows developers to easily determine the folder and library associated with that ngModule.
Does the above support camelCase?