Skip to content

Latest commit

 

History

History
127 lines (91 loc) · 4.74 KB

LAB.md

File metadata and controls

127 lines (91 loc) · 4.74 KB

🧵 Lab 14 - Workspace Plugins and Generators - Modifying files

⏰ Estimated time: 25-35 minutes

📚 Learning outcomes:

  • Explore some more advanced, real-world usages of generators
  • Understand how to modify existing source code with generators


🏋️‍♀️ Steps :

  1. Generate another generator called update-scope-schema

  2. As a start let's make it change the defaultProject from store to api in our nx.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.

    ⚠️ When you run the above, it might complain that you haven't supplied a name. Since we don't need this property in the generate, you can remove it from the schema.

  3. 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.

    ⚠️ You can use the function provided in the Hint to extract the scopes

    🐳 Hint
    function getScopes(projectMap: Map<string, ProjectConfiguration>) {
      const projects: any[] = Array.from(projectMap.values());
      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));
    }

  4. 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

  5. The util-lib generator also has a schema.d.ts with a Typescript interface that should be updated. For modifying files that are not JSON we can use host.read(path) and host.write(path, content) methods.

    ⚠️ You can use the function provided in the Hint to replace the scopes

    🐳 Hint
    function updateSchemaInterface(tree: Tree, scopes: string[]) {
      const joinScopes = scopes.map((s) => `'${s}'`).join(' | ');
      const interfaceDefinitionFilePath =
        'libs/internal-plugin/src/generators/util-lib/schema.d.ts';
      const newContent = `export interface UtilLibGeneratorSchema {
        name: string;
        directory: ${joinScopes};
      }`;
      tree.write(interfaceDefinitionFilePath, newContent);
    }

  6. So we can test our changes, create a new app and define a scope for it.

    🐳 Hint
    nx g app videos --tags=scope:videos

  7. Run your generator and notice the resulting changes. Commit them so you start fresh on your next lab.

  8. BONUS - As a bonus, if project doesn't have scope tag defined, we will assume it's the first segment of the name (e.g admin-ui-lib -> scope:admin) and we will go ahead and set one for it. Now run the generator again and see what changed.

  9. 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.

  10. 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 your util-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


➡️ Next lab ➡️