- Understand what an internal plugin is
- Understanding generators in internal plugin, including:
- How to create them
- How to invoke them
- How to use one to simplify usages of other, more powerful generators
We just learned how important tags are. But we don't want to constantly and manually
have to maintain them. In this workshop, we'll create an internal plugin called
internal-plugin
, and create a library generator
for this plugin that knows
about the folders in our workspace and automatically tags the new project with a correct
scope and type tag.
-
Use the
@nx/plugin:plugin
generator to generate a new plugin calledinternal-plugin
.
Make sure that theminimal
option is set.
-
Use the
@nx/plugin:generator
generator to generate a new generator calledutil-lib
.
-
Inspect the files that got generated and then commit everything.
-
Try to run your generator (you can append
--dry-run
to avoid reverting using Git)🐳 Hint
Run
npx nx list
to see your newly created plugin in the list of installed plugins:% npx nx list > NX Local workspace plugins: @bg-hoard/internal-plugin (generators)
Run
npx nx list @bg-hoard/internal-plugin
to see our generator details:% npx nx list @bg-hoard/internal-plugin > NX Capabilities in @bg-hoard/internal-plugin: GENERATORS util-lib : util-lib generator
You call generators from this local plugin using the same syntax you would with any plugin:
nx generate <plugin name>:<generator name> [...options]
⚠️ The code we generated creates a very bare-bones new library, with only aproject.json
and asrc/index.ts
file; you will see these files created if you run it. You can use Git to undo those changes (hence why it's recommended to commit before running a generator).
-
We can call other generators inside of our custom generator. Import the
@nx/js:library
generator and call it inside of the default exported function oflibs/internal-plugin/src/generators/util-lib/generator.ts
🐳 Hint
import { libraryGenerator } from '@nx/js/generators'; export default async function (tree: Tree, schema: UtilLibGeneratorSchema) { await libraryGenerator(tree, schema); // ... }
-
In
libs/internal-plugin/src/generators/util-lib/generator.ts
try to make itconsole.log()
the value of the--name
property you passed to it (can use--dry-run
again to test it)
-
Now that we're more familiar with how command line options are passed to the generator, let's revert all locally generated files, as we're about to start making actually useful changes to the generator.
-
The generator should prefix any name you give to your lib with
util-
For example:
nx generate @bg-hoard/internal-plugin:util-lib dates
- Should generate a lib with the name
util-dates
⚠️ You can keep trying out your changes safely with the--dry-run
flag.️
-
Add a new property to its schema called
directory
. It should have only 3 possible values:"store", "api", "shared"
. If you do not pass--directory
as an option when invoking the schema it should prompt the user to select from the 3 different values (similar to when you got asked about which CSS framework to use when creating React libs).🐳 Hint
-
The generator should generate the lib in the directory you pass to it.
-
Because it's a
util
lib, it should automatically be generated with thetype:util
tags.🐳 Hint
Consult the
@nx/js:lib
docs for possible options you can pass to it.
-
We also need to add
scope
tag to it. We can use thedirectory
value for this, since it signifies our scope.
-
Before testing your changes, remember to commit them, in case you need to revert locally generated files again.
-
Invoke your generator and test if the above requirements work
- Let's give it the name
notifications
- Select
api
as the directory
- Let's give it the name
-
Let's add some functionality to the lib you just created:
- In
libs/api/util-notifications/src/lib/api-util-notifications.ts
- Add:
export function sendNotification(clientId: string) { console.log('sending notification to client: ', clientId); }
- In
-
Now try to import the above function in
apps/api/src/main.ts
- Try to lint all the apps
- It should work because everything is in the
api
scope
-
Try to import it in
apps/store/src/app/app.tsx
- It should fail because it's not within the same scope
- It should fail because it's not within the same scope
-
In
libs/api/util-notifications/src/lib/api-util-notifications.ts
- Try to import a
feature
lib - It should correctly fail because the type hierarchy is not respected
- Try to import a
-
BONUS - A
generator.spec.ts
file was created when we ran our generator. Try writing some meaningful tests for this generator.
-
BONUS BONUS - try to create another similar generator, but for "feature" libs.
-
Commit everything before the next lab.
🎓If you get stuck, check out the solution