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

Already on GitHub? Sign in to your account

Optional peer dependencies #3066

Closed
ForbesLindesay opened this Issue Jan 17, 2013 · 45 comments

Comments

Projects
None yet
Member

ForbesLindesay commented Jan 17, 2013

It would be useful to have a way of specifying something equivalent to peerDependencies but where they are optional. As discussed in #1400

+1
That would be very useful for projects like a CMS.

Contributor

Raynos commented Sep 4, 2013

👍

@domenic any tips on where / how to implement this feature ?

Contributor

rlidwka commented Sep 27, 2013

I saw issues regarding peer dependencies, optional, bundled, dev, optional peer, optional dev, not to mention exotic stuff binDependencies, did I miss something?

Guys, what about declaring those properties as flags? We can use syntax like that:

{
    dependencies: {
        foo: {
             version: "1.2.3",
             dev: true,
             optional: true,
        },
    },
}

It would really reduce this keyword clutter.

Sounds nice. Maybe something like this would be even more flexible and future proof:

{
    dependencies: {
        foo: {
             version: "1.2.3",
             type: "peer | dev | bin | etc.",
             optional: true
        },
    },
}
Member

ForbesLindesay commented Oct 19, 2013

Sadly bin dependencies are not nearly as useful as you'd think. You can't tell whether someone is going to use a module as a binary at install time.

I don't think we should change the syntax like that. It makes things very verbose and what we have works pretty well in practice. It should probably be a separate issue for discussing this though.

Contributor

zxqfox commented Nov 10, 2013

@donaldpipowitch Better array:

type: [ 'peer', 'dev' ],
optional: true

Yes, indeed. This should just be pseudo code. An array would be better :)

👍 yes, npm would really benefit from allowing this

vjpr commented Jan 17, 2014

+1

To all who are still interested in optional peer dependencies, I've released a solution to this at https://github.com/Wizcorp/codependency . In a nutshell, it allows for a "optionalPeerDependencies" field in package.json for middleware.

Features:

  • automatic semver validation.
  • instructive error reporting for your end user.
  • optionality (it won't throw errors if you don't want it to).
  • a developer-friendly environment (allows symlinking to your middleware).

I hope it can help middleware development, and I would love to get any feedback you may wish to share. Thanks!

PS: If you're still interested, I wrote a tumblr post about this.

fixe commented Jan 11, 2015

@othiym23 is this something that will be integrated?

Contributor

othiym23 commented Jan 20, 2015

@fixe It's not something that's on the development team's radar, so probably not anytime soon.

jxm262 commented Apr 2, 2015

👍 would like this as well

nunofgs commented Nov 5, 2015

Optional peer dependencies would be very useful for modules that only conditionally require other modules.

See seegno/validator.js-asserts#35 for an example.

Contributor

othiym23 commented Nov 5, 2015

Given that peerDependencies at most warn in npm@3, and given that npm no longer causes peerDependencies to be installed, in effect all peerDependencies are optional. I'm not exactly declaring victory and going home here, but with the current behavior, I think there's nothing actionable remaining to this issue, so I'm closing it.

@othiym23 othiym23 closed this Nov 5, 2015

Then let me be the one declaring victory :) I think it's a great change and it completely satisfies my request. Thanks!

fyockm commented Nov 12, 2015

As all peerDependencies are now optional, can we change the associated peer warning messages? The red highlighting and capitalization on "UNMET PEER DEPENDENCY" makes me think something is actually wrong, and I need to take action.

Additionally, the ending EPEERINVALID warning message states "mongodb-core@1.2.21 requires a peer of kerberos@~0.0 but none was installed." Perhaps the required verbiage should be changed to something like "packageX has an optional peer of packageY but none was installed"?

This is most evident with a screenshot:

$ npm -v
3.3.9
$ npm i -S mongoose

screen shot 2015-11-12 at 9 32 36 am

@othiym23 I believe updating these messages is a remaining actionable task.

fixe commented Nov 12, 2015

I agree with @fyockm.

i'm in the same shoes with @fyockm. But now i'm stucked, i cannot use npm shrinkwrap

because i got:

npm ERR! peer dep missing: kerberos@~0.0, required by mongodb-core@1.2.24

using npm 3.5.0

optionalPeerDependencies would be useful for declaring dependencies on shims.

I'd like to specify in my package.json which shims might developers need, but since shims are needed only for certain browsers/node versions, I don't want to require them.

Additionally I agree with @fyockm that the current error messaging is confusing and while I haven't tried it @tgabi333 issue with npm shrinkwrap looks like a legit issue.

For now I'm going to make angular2 use peerDependencies even for shims, but it would be better if we could move those over to optionalPeerDependencies in the future.

@IgorMinar IgorMinar added a commit to IgorMinar/angular that referenced this issue Dec 6, 2015

@IgorMinar IgorMinar fix(npm): move es6-shim from devDependencies to peerDependencies
It would be better to make this one an optionalPeerDependency but npm
currently doesn't support making peerDependencies optional.
See: npm/npm#3066
dcf1a58

@IgorMinar IgorMinar added a commit to IgorMinar/angular that referenced this issue Dec 6, 2015

@IgorMinar IgorMinar fix(npm): move es6-shim from devDependencies to peerDependencies
It would be better to make this one an optionalPeerDependency but npm
currently doesn't support making peerDependencies optional.
See: npm/npm#3066
5a62c7d

@IgorMinar IgorMinar added a commit to IgorMinar/angular that referenced this issue Dec 6, 2015

@IgorMinar IgorMinar fix(npm): move es6-shim from devDependencies to peerDependencies
It would be better to make this one an optionalPeerDependency but npm
currently doesn't support making peerDependencies optional.
See: npm/npm#3066
1d109c4

@IgorMinar IgorMinar added a commit to IgorMinar/angular that referenced this issue Dec 8, 2015

@IgorMinar IgorMinar fix(npm): move es6-shim from devDependencies to dependencies
To be later used as a peerDependency in the generated package.json

It would be better to make this one an optionalPeerDependency but npm
currently doesn't support making peerDependencies optional.
See: npm/npm#3066
d7eba56

@IgorMinar IgorMinar added a commit to IgorMinar/angular that referenced this issue Dec 8, 2015

@IgorMinar IgorMinar build(npm): add es6-promise as a dependency
This is actually an inherited dependency that comes from zone.js.

See related issue: angular/zone.js#212

It would be better to make this one an optionalPeerDependency but npm
currently doesn't support making peerDependencies optional.
See: npm/npm#3066
08f9721

@IgorMinar IgorMinar added a commit to IgorMinar/angular that referenced this issue Dec 8, 2015

@IgorMinar IgorMinar fix(npm): move es6-shim from devDependencies to dependencies
To be later used as a peerDependency in the generated package.json

It would be better to make this one an optionalPeerDependency but npm
currently doesn't support making peerDependencies optional.
See: npm/npm#3066
1243ad6

@IgorMinar IgorMinar added a commit to IgorMinar/angular that referenced this issue Dec 8, 2015

@IgorMinar IgorMinar build(npm): add es6-promise as a dependency
This is actually an inherited dependency that comes from zone.js.

See related issue: angular/zone.js#212

It would be better to make this one an optionalPeerDependency but npm
currently doesn't support making peerDependencies optional.
See: npm/npm#3066
a79b7e0

@IgorMinar IgorMinar added a commit to IgorMinar/angular that referenced this issue Dec 8, 2015

@IgorMinar IgorMinar fix(npm): move es6-shim from devDependencies to dependencies
To be later used as a peerDependency in the generated package.json

It would be better to make this one an optionalPeerDependency but npm
currently doesn't support making peerDependencies optional.
See: npm/npm#3066
217b816

@IgorMinar IgorMinar added a commit to IgorMinar/angular that referenced this issue Dec 8, 2015

@IgorMinar IgorMinar build(npm): add es6-promise as a dependency
This is actually an inherited dependency that comes from zone.js.

See related issue: angular/zone.js#212

It would be better to make this one an optionalPeerDependency but npm
currently doesn't support making peerDependencies optional.
See: npm/npm#3066
3fd6f55

@IgorMinar IgorMinar added a commit to angular/angular that referenced this issue Dec 8, 2015

@IgorMinar @jelbourn IgorMinar + jelbourn fix(npm): move es6-shim from devDependencies to dependencies
To be later used as a peerDependency in the generated package.json

It would be better to make this one an optionalPeerDependency but npm
currently doesn't support making peerDependencies optional.
See: npm/npm#3066
21542ed

@IgorMinar IgorMinar added a commit to angular/angular that referenced this issue Dec 8, 2015

@IgorMinar @jelbourn IgorMinar + jelbourn build(npm): add es6-promise as a dependency
This is actually an inherited dependency that comes from zone.js.

See related issue: angular/zone.js#212

It would be better to make this one an optionalPeerDependency but npm
currently doesn't support making peerDependencies optional.
See: npm/npm#3066
c1e3ea9

For reference, I think the issue with shrinkwrap is being tracked in #5135

@tjconcept This is not the same issue; the issue there is with an old version of npm1, and happens after creation of the shrinkwrap.json file, when used back at npm install time.

Here the remaining issue with npm3 is that only "npm install" treats peerDependencies as optional. "npm shrinkwrap" fails if peer dependency is missing from the parent (see christkv/mongodb-core#65); and even "npm ls" returns code 1 with an error printed on stderr (I don't know if I can trust the output of "npm ls --json" in this case...).

(all tested with npm 3.5.3)

My mistake. I meant to link to #10836

Please reopen this issue: see christkv/mongodb-core#65 (comment) which says peerDependencies is not the answer for our "optional peer dependencies" feature request, even with npm@3.

Contributor

othiym23 commented Feb 1, 2016

As I said in christkv/mongodb-core#65, optionalPeerDependencies aren't going to be a thing, because they describe a relationship that shouldn't exist (how can a plugin exist without its host?). If you're seein a need for them, I have yet to see a case where the use case wasn't best modeled another way.

Indeed you are right, we got it backward, and the peerDependencies is enough, we just have to put it on the plugin module, not on the main module.

@othiym23 Angular's use-case is polyfills and prolyfills that are only needed by some web applications but not all applications.

I need the core of the framework to specify which version of the polyfill it is compatible with, without requiring that version out of the box. This is what optionalPeerDependencies would a great fit for. Or is there a different way to model this relationship?

@IgorMinar set angular as peer dependency of your polyfill, and let the user explicitly depend on both angular and the polyfill and require both and somehow pass at runtime the polyfill to angular.
It's the standard peerDependency feature (at least now in npm@3): the user is in control.

@triccardi-systran I'm sorry but I don't understand how that would work. es6-shim doesn't and shouldn't know about Angular - so it should not require Angular as it's peer dependency.

We want users to be in control, but we also want to give them hints as to what peer dependencies are hard requirements and which ones are only needed if they are using older runtimes.

nfantone commented Nov 2, 2016 edited

I know this is an old, closed issue - so, apologies in advanced. But this seemed like the proper place to ask this.

I have yet to see a case where the use case wasn't best modeled another way.

@othiym23 What about Typescript 2.0 types being installed over npm? Say a library wants to expose a definitions file via a "types" attribute in package.json which depends on some other external typings. Regular users (i.e.: not on TS projects) should not need to care or even be aware of those. On the other hand, a TS module installing the library would want to consume them.

Declaring something like:

  "peerDependencies": {
    "@types/bluebird": "^3.0.35",
    "@types/node": "^6.0.46"
  }

Does the trick, but outputs warnings when installing:

npm WARN foo@1.0.0 requires a peer of @types/bluebird@^3.0.35 but none was installed.
npm WARN foo@1.0.0 requires a peer of @types/node@^6.0.46 but none was installed.

Which is far from ideal if I'm really not working with Typescript.

Contributor

legodude17 commented Nov 2, 2016

@nfantone, that should probably be just optional dependencies.

nfantone commented Nov 2, 2016

Exactly. Then, how do we declare the intention of them being optional dependencies? Not to mention, needed versions.

Contributor

legodude17 commented Nov 2, 2016

I mean, put them in optionalDependencies.

nfantone commented Nov 2, 2016

@legodude17 AFAIK, optionalDependencies work just as dependencies but won't blow up the whole installation process if the dependency's particular installation fails in any way. That is its use case.

From the docs:

If a dependency can be used, but you would like npm to proceed if it cannot be found or fails to install, then you may put it in the optionalDependencies object.

So, no, using optionalDependencies won't work in my case as it'll just be like putting them under dependencies.

Contributor

legodude17 commented Nov 2, 2016

Ah. I see your point now @nfantone. I don't think that any variant of peerDependencies is correct, because your types dependes on the external types.

nfantone commented Nov 2, 2016 edited

@legodude17 That's right. But that dependency is only needed under certain circumstances.

I don't think that any variant of peerDependencies is correct

Well... optionalPeerDependencies looks like a candidate, wouldn't you say? Or maybe just peerDependencies that do not scare the user with red colored warnings stating that they are missing a requirement when they are actually not.

Contributor

legodude17 commented Nov 2, 2016

Well... optionalPeerDependencies looks like a candidate, wouldn't you say? Or maybe just peerDependencies that do not scare the user with red colored warnings stating that they are missing a requirement.

I agree with you, sort of. I think that peerDependencies are the best option available at the moment, but there could be a better idea. There are already multiple issues to INFO instead of WARN on a missing peerDependencies.

@isiahmeadows isiahmeadows referenced this issue in nikku/karma-browserify Dec 7, 2016

Closed

Move `watchify` to optionalDependencies? #202

mcmath commented Dec 21, 2016 edited

@nfantone This is exactly the problem I would like to see solved. In case this issue is reconsidered, I thought I would offer a more detailed description of the problem and how it might be resolved.

I propose that an "optionalPeerDependencies" field should behave like "peerDependencies", except that a warning should only be emitted if an incompatible version of a dependency is actually installed; missing dependencies should be ignored.

Use case

An "optionalPeerDependencies" field would be useful when a dependency satisfies three conditions:

  1. The dependency should not be installed automatically
  2. The dependency is not required
  3. If the dependency is installed, then must satisfy a particular semver range

For example, lets say I'm writing a package that contains TypeScript declarations. These declarations use syntax that's only available in typescript@2. Then

  1. it does not use typescript at runtime, so typescript should not be installed automatically,
  2. the package may be used without typescript at all, so it is not required,
  3. but if typescript is used, then is needs to be version 2.x.

Example

Let's say my-package has an "optionalPeerDependencies" field that looks like this:

"optionalPeerDependencies": {
  "typescript": "2.x"
}

This should result in a warning only if a user

  1. installs my-package with typescript@1 already installed,
  2. installs typescript@1 with my-package already installed, or
  3. installs my-package and typescript@1 at the same time.

More formally, npm should behave like so:

Run `npm install my-package`:
  If typescript@1 is installed:
    WARN: typescript version is incompatible
  Else:
    No warning

Run `npm install typescript@1`:
  If `my-package` is installed:
    WARN: typescript version is incompatible
  Else:
    No warning

Run `npm install my-package typescript@1`:
    WARN: typescript version is incompatible

nfantone commented Dec 21, 2016 edited

@mcmath I'm aboard with you on that one. Sadly, this doesn't seem the best place for that proposal since this is an (almost) four year old, closed issue. I believe TS in 2016/17 has grown to be a candidate that could made us revisit the optionalPeerDependencies idea that wasn't around in 2013 when all this began.

mcmath commented Dec 21, 2016

@nfantone Yes, I think what we want is a bit different from what was being discussed in 2013. One of us should open a new issue. I'll probably do so later today if you haven't already.

Go for it. You seem to have your wording and proposal idea in order.

GongT commented Jan 5, 2017 edited

that is a good feature!

I'm writing a "helper" about express. the package exports a class (eg. ExpressHandler ), can:

  • handle session with "express-session" and "connect-mongo", "connect-memcached", .... etc
  • handle json body with "body-parser", multipatrt with "multiparty", file upload with "multer"
  • log with "morgan"
  • all of these package 's typescript define from
  • some other thing without dependency

Now I can write all these deps in dependencies, everything works well, but will install many package never use in single project.
or I can use peerDependencies, but it will emit many many WARN message.

@jamesrichford jamesrichford referenced this issue in alsatian-test/alsatian Jun 1, 2017

Merged

Update @types/node to 4.0.0 #394

I am putting the same package in both optionalDependencies and peerDependencies, and it seems to work. Not sure if this is the proper way or not.

madbence commented Aug 31, 2017 edited

another use-case: browserify-ed packages. e.g. react-ionicons uses require to include css, so one has to use browserify-css. but the module can be used with webpack too, which uses a different mechanism to require css files. therefore browserify-css is a dependency that should be installed only when the package is indended to be used with browserify.

@madbence madbence referenced this issue in zamarrowski/react-ionicons Aug 31, 2017

Merged

Support browserify #21

glintik commented Sep 18, 2017

+1 for optional peerDependencies, it will allow to support several date-time libraries, for example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment