Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

externalSchematics should install packages locally when they are no present in the node_modules #19301

Open
1 of 16 tasks
d-koppenhagen opened this issue Nov 4, 2020 · 9 comments
Labels
area: devkit/schematics feature: insufficient votes Label to add when the not a sufficient number of votes or comments from unique authors feature Issue that requests a new feature
Milestone

Comments

@d-koppenhagen
Copy link

🚀 Feature request

Command (mark with an x)

  • new
  • build
  • serve
  • test
  • e2e
  • generate
  • add
  • update
  • lint
  • extract-i18n
  • run
  • config
  • help
  • version
  • doc
  • other

Description

when creating own schematics, they can make use of other schematics by calling the externalSchematic function provided by the @angular-devkit/schematics collection.

To call an external schematic, the function can be used like this:

options = {};
externalSchematic('my-schematic-package', 'my-schematic-name', options);

But to execute an external schematic package it has to be part of the node_modules. Internally the CLI uses the function for example for calling the PWA schematic. This won't be problematic as is already installed as part of the @angular/schematics package and in fact it's part of the node_modules.

Once you'll try to install an external schematic which isn't already available in the node_modules the schematic fails.

A workaround is to manually integrate an installation procedure first and then call the function like this:

export const installNpmPackage = (
  context: SchematicContext,
  packageName: string,
): Promise<void> => {
  return new Promise<void>((resolve) => {
    context.logger.info(
      `📦 Installing package '${packageName}' for external schematic setup...`,
    );
    const spawnOptions: SpawnOptions = { stdio: 'inherit' };
    spawn('npm', ['install', packageName], spawnOptions).on(
      'close',
      (code: number) => {
        if (code === 0) {
          context.logger.info(
            `✅ '${packageName}' package installed successfully`,
          );
          resolve();
        } else {
          const errorMessage = `❌ installation of '${packageName}' package failed`;
          context.logger.error(errorMessage);
          throw new Error();
        }
      },
    );
  });
};

const packageName = '@briebug/cypress-schematic';
await installNpmPackage(context, packageName);
return externalSchematic(packageName, 'ng-add', {
  removeProtractor: true,
  addCypressTestScripts: true,
});

Describe the solution you'd like

It would be great to integrate the installation process for a package that's not present in the node_modules in the externalSchematic function.

Describe alternatives you've considered

@alan-agius4
Copy link
Collaborator

Hi @d-koppenhagen,

Thanks for opening this feature request.

I don’t think that externalSchematics should install the package if missing. There are multiple required options that are not available for this method.

  • Should the dependency be save as a devDependency, no-save or direct dependency?
  • Which package manager to use?
  • Which version/tag of package that contains the schematic should be used?
  • Possible alternate private npm registry url.

In most cases when having a schematic that depends on an external schematic, the author should add the package that contains the external schematic as a direct dependency. This also ensures that the correct version of the external schematic is installed as otherwise you might end up with a broken behaviour when the API of the dependent schematic is changed.

If having it as a direct dependency is not possible, running a separate install task prior of running externalSchematics is a more reasonable and cleaner approach IMHO.

@d-koppenhagen
Copy link
Author

Hey @alan-agius4 , I unserstand.
But why no let users pass those options as an extra object. If the object is present, install the package using the definition in the object like this:

const options = {};
const installOptions = {
   type: NodeDependencyType.Dev, // enum with all dependency types, if not defined, it won't be added as dependency to the package.json file
   version: '~2.27.0', // use 'latest' by default when not defined
   overwrite: true, // use 'false' and log an error by default
   packageManager: PackageManager.Npm // or yarn or pnpn. If not defined: take the default that's defined in `angular.json`
   registry: 'https://...' // use "normal" NPM registry by default (or assume that it's already define in .npmrc file (locally or globally)
};
externalSchematic('my-schematic-package', 'my-schematic-name', options, installOptions);
// only install when installOptions object is present

@alan-agius4
Copy link
Collaborator

Mind sharing the use-case of not having the external dependency as a direct dependency of the schematic package?

I still think that the installation of the package should be a separate task and not part of externalSchematic method at least with the current version of schematics.

@alan-agius4 alan-agius4 added area: devkit/schematics feature Issue that requests a new feature labels Nov 4, 2020
@ngbot ngbot bot modified the milestone: Backlog Nov 4, 2020
@d-koppenhagen
Copy link
Author

it might just be relevant when I want to combine external schematics and want to make use of them only once.
For example when I will create a schematics collection for an enterprise that will setup an angular workspace with companies defaults.
If the company for example decided to use always cypress instead of some protractor (to use the example from the description in this issue), it might just make sense to execute the external schematic from @briebug/cypress-schematic initially. This will add all the stuff needed and adds Cypress etc. to the workspace. But this would be an initial one-time-job, so no need to keep @briebug/cypress-schematic as dependency as it just sets up something and can be dropped afterwards, can't it?

@pfeileon
Copy link

@d-koppenhagen
Your workaround isn't feasible, as well, unless you are fine with creating a node_modules folder and package-lock.json file in your working directory and either leaving or deleting these in a cleanup step. It's basically the same outcome as using NodePackageInstallTask (like in this stackoverflow issue).

Since Angular got rid of a built-in linting configuration, I'm trying to ng add @angular-eslint/schematics from a custom ng-new schematic and can't overcome this issue. If externalSchematics would at least accept a path to node_modules, said workaround could be used without side-effects by creating the project folder by hand and installing the packages there.

@angular-robot angular-robot bot added the feature: votes required Feature request which is currently still in the voting phase label Feb 2, 2022
@angular-robot
Copy link
Contributor

angular-robot bot commented Feb 2, 2022

Just a heads up that we kicked off a community voting process for your feature request. There are 20 days until the voting process ends.

Find more details about Angular's feature request process in our documentation.

@ngbot ngbot bot modified the milestones: Backlog, needsTriage Feb 2, 2022
@angular-robot
Copy link
Contributor

angular-robot bot commented Feb 21, 2022

Thank you for submitting your feature request! Looks like during the polling process it didn't collect a sufficient number of votes to move to the next stage.

We want to keep Angular rich and ergonomic and at the same time be mindful about its scope and learning journey. If you think your request could live outside Angular's scope, we'd encourage you to collaborate with the community on publishing it as an open source package.

You can find more details about the feature request process in our documentation.

@angular-robot angular-robot bot added feature: insufficient votes Label to add when the not a sufficient number of votes or comments from unique authors and removed feature: votes required Feature request which is currently still in the voting phase labels Feb 21, 2022
@pfeileon
Copy link

It's kind of sad that the bot closes the voting process after 20 days while the documentation says:

To include the community in the feature request process, we open voting for 60 days.

Anyway, my interpretation is that Schematics is basically dead atm. (Which is really disappointing since it is the one thing which really would've separated Angular from every other frontend framework/library.)

@dgilsonAfelio
Copy link

So sad to see this feature dead

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: devkit/schematics feature: insufficient votes Label to add when the not a sufficient number of votes or comments from unique authors feature Issue that requests a new feature
Projects
None yet
Development

No branches or pull requests

4 participants