- Explore some more advanced, real-world usages of generators
- Understand how to modify existing source code with generators
-
Generate another generator called
update-scope-schema
-
As a start let's make it change the
defaultProject
fromstore
toapi
in ournx.json
file:🐳 Hint
- Refer to the docs
- Use this utility:
import { updateJson } from '@nx/devkit';
- As always, the answer is in the the solution. Try a few different approaches on your own first.
name
. Since
we don't need this property in the generate, you can remove it from the schema.
- Now that we had some practice with the
updateJson
util - Let's build something even more useful:
-
When large teams work in the same workspace, they will occasionally be adding new projects and hence, new scope tags
-
We want to make sure that scope tags specified in our
util-lib
generator are up to date and take into account all these new scopes that teams have been adding -
We want to check if there is a new scope tag in any of our
project.json
files and update our generator schema -
We can use the
getProjects
util to read all the projects at once. -
BONUS: Modify your generator so it fetches list of scopes from all the
project.json
files and updates the schema in util-lib with any new ones⚠️ You can use the function provided in the Hint to extract thescopes
🐳 Hint
function getScopes(projectMap: Map<string, ProjectConfiguration>) { const projects: any[] = Object.values(projectMap); const allScopes: string[] = projects .map((project) => project.tags // take only those that point to scope .filter((tag: string) => tag.startsWith('scope:')) ) // flatten the array .reduce((acc, tags) => [...acc, ...tags], []) // remove prefix `scope:` .map((scope: string) => scope.slice(6)); // remove duplicates return Array.from(new Set(allScopes)); }
-
It's good practice to have your generator run your modified files through Prettier after modifying them. You might already have this, but just in case you removed it:
- Use
import { formatFiles } from '@nx/devkit';
await
this at the end of your generator
- Use
-
index.ts
also has aSchema
interface that should be updated. For modifying files that are not JSON we will usehost.read(path)
andhost.write(path, content)
methods.⚠️ You can use the function provided in the Hint to replace thescopes
🐳 Hint
function replaceScopes(content: string, scopes: string[]): string { const joinScopes = scopes.map((s) => `'${s}'`).join(' | '); const PATTERN = /interface Schema \{\n.*\n.*\n\}/gm; return content.replace( PATTERN, `interface Schema { name: string; directory: ${joinScopes}; }` ); }
-
So we can test our changes, create a new app and define a scope for it.
🐳 Hint
nx generate app video-games --tags=scope:video-games
-
Run your generator and notice the resulting changes. Commit them so you start fresh on your next lab.
-
BONUS - As a bonus, if project doesn't have
scope
tag defined, we will assume it's the first segment of the name (e.gadmin-ui-lib
->scope:admin
) and we will go ahead and set one for it.
-
BONUS BONUS - use a tool like Husky to run your generator automatically before each commit. This will ensure developers never forget to add their scope files.
-
BONUS BONUS BONUS - create a test to automate verification of this generator in
libs/internal-plugin/src/generators/update-scope-schema/generator.spec.ts
. This will be particularly difficult, as you'll need to create a project with the actual source code of yourutil-lib
generator as part of the setup for this test. (Check the solution if you get stuck!)
🎓If you get stuck, check out the solution