Create a Master-Detail CRUD workspace schematic for a React Nrwl/Nx project
Tags: react, nx, schematic, automation
Published: 2021-05-14 20:32:22

I love automation, and I hate repeating mindlessly. For data-centric applications, I do not want to handcraft master-detail for every entity repeatedly. So I spent some time designing a module with reusable components that define the look and handle most of the CRUD behaviours. The aim is that for each entity CRUD, I only need to do some configurations specific to the entity.

As a result, I have a few components composed together in four files for each entity. Nrwl/Nx has bundled a set of schematics to generate code, such as generating lib and components. Nx spoils me, and I do not want to copy and paste and change names etc. I want to have it generated automatically by a simple command like this:
```console
nx workspace-schematic crud entity-name lib-name
```
There aren't many official documents for making a custom schematic. There isn't one for making React schematic. Guess what? The source code for the in-house schematics is the best document we could hope for.

I share my `crud` schematic code here for the convenience of like-minded developers who wants to make their own schematics.

1. The Nx project has a tools/generators folder. This is where our schematics live.

1. Nx comes with a schematic to generate custom schematics: `nx g workspace-schematic your-schematic`. It will give us a skeleton to start with. We will have two files: `index.ts` and `schema.json`

1.`index.ts` is where we write our schematic code. Below is mine. 
It is a straightforward one. It takes an entity name and a lib name and creates a folder under the specified lib with four files, and update the lib barrel `index.ts`
{% gist https://gist.github.com/rexebin/5818759297a9a6a866b9d1bb47cad6e7 %}

### How it works:
1. Nx provides a `names` function. It takes a string `name` which will be passed as part of the required options in our command(in my case its the entity name) and returns an object with useful names such as `className` and `propertyName`. For example, if my entity name is "purchase-order", `className` would be "PurchaseOrder" and `propertyName` would be "purchaseOrder".

1. `generateFiles` take files in the sub-folder files and generate code from them. Notice the last parameter. It is the substitutions we can provide for Nx to replace markups in our file names and contents. I provided `name`. Its shape looks like this: 
`{className: string, propertyName: string, constantName: string, fileName: string}`

1. I wanted my CRUD file names to start with entity name, so I name my template files like this: `__className__Form.tsx`. When Nx sees `__lassName__`, it looks for `className` property in my provided `name` object.

1. Same goes with the contents. The markup looks like this: `<%= className%>`. One of my templates looks like this:
{% gist https://gist.github.com/rexebin/b2aa7bc97c210cfcfafce4af5ef1810f %}

One last thing is that if you have `ts` files to generate in your `files` folder, you will need to add `"exclude": ["**/files/**/*.ts]` in your `tsconfig.tools.json` file. It prevents your template TypeScript files gets compiled.

With the above, I can scaffold CRUD very quickly.

Creating schematics is easier than you think.