Understanding how to manage dependencies in a custom npm library - npm

I am trying to write my first set of npm libraries for a large, distributed application and am running into problems around how to manage dependencies. Npm has the concept of "dependencies" and "peerDependencies".
From what I read, peerDependencies are needed when you want to write a "plugin" where the consuming application is already expected to have the dependency installed on their end. For example, this might be building a plugin for webpack.
Then there are regular dependencies needed at runtime by a library. In my scenario, I am trying to write a library to abstract Authentication and Authorization away from the consuming application. This new library (lets call it #myapp/auth) has a dependency on the #auth0/angular-jwt library as it uses it to deal with JWTs. I want this library to be completely abstracted away from the consuming application and therefore not force that consuming application to install it manually.
With that said, it sounds like I need to add #auth0/angular-jwt to dependencies in my library and then add it to the whitelistedNonPeerDependencies which allows it to build.
This confuses me because the ng-packagr docs say that we should always use peerDependencies when possible. If this is the case, then why when you install a larger library like express, you simply run npm install express --save and you get ALL of the dependencies of express without manually installing each one.
What is the proper way to include package dependencies in a custom library that you do not want the consuming application to install themselves?

Related

How to make a buildable publishable library with Nx that is framework agnostic for browser and node.js

I have a monorepo (Nx Workspace) that has many libraries that were generated with #nrwl/js. These libraries depend on each other. They are small utility libraries that I intend to publish on NPM as separate packages.
According to Nx docs:
#nrwl/js is particularly useful if you want to
Create framework agnostic, just plain TypeScript libraries within an existing Nx workspace (say to use in your React, Node or Angular app)
Publish TypeScript packages to NPM
Yet, I now realize that the build command associated with #nrwl/js does not take into account a library's dependencies on other libraries in order to include them as peerDependencies into its publishable package.json. It also looks like it is making just a simple commonjs build that would be compatible with node.js but not with browsers.
I know that #nrwl/angular takes care of all that stuff for you when you build a library with it if you had marked it as publishable. My question is how do I get the same behavior but for a library that is not meant for Angular but for general purpose Javascript use in any framework or environment.
It's still early in development so if a solution to my problem would involve regenerating the libs using some other Nx generator, it wouldn't be too much of a hassle for me to do so, and I'd consider it.
Edit
I have since changed the build executor to #nrwl/node, which has the buildable and publishable options and behave the way I need.
I believe that #nrwl/js will eventually gain that ability but as of 2022-01-05 it didn't have it. For now, someone looking to publish libraries on NPM probably should use #nrwl/node to generate his new library projects and not #nrwl/js
If you want to publish a NPM package as a "universal package" to be consumed by Node.js and the browser, you would need to build it as UMD, to cover most consumer environments.
Though modern browsers support ES modules (import and export), you might need extra setup steps to consume them.

Is it possible to specify a runtime dependency of a code generator?

I am working on an npm package that is used as a CLI to generate code. It makes sense that this project should generally be used as a devDependency.
But the generated code will require a third-party library at runtime. Is there a way to manage this dependency via package.json? I have seen other libraries include a note in the README that defines this dependency, but there is no guarantee that the end user will read this README, so I would like to be able to enforce this.
One thought I had was to use a preinstall script to validate that this third-party library was already installed, otherwise throw an error and don't allow the user to install. But that feels like more of a hack than a solution.
I anticipate someone saying "but won't it be obvious when none of the generated code works?" which is absolutely correct, but ideally this process should fail well before runtime.
I am not sure the specifics really matter here, but my package generates boilerplate TypeScript code for an API project, from an OpenAPI spec, and depends on Express.js at runtime.
This sounds like a peer dependency. You can specify a peer dependency in package.json with the peerDependencies key.
In npm 6, missing peer dependencies will result in a warning.
In npm 7, missing peer dependencies are installed.

Updating transitive dependencies of a NPM package

Our company has a few web applications which in turn depend on a very long chain of internally created and hosted npm packages (we use JFrog Artifactory) each with their own dependencies (and so on). Whenever a bug is fixed or a feature is implemented in a low-level package the current process requires a developer to check in their changes, wait for the CICD build to complete and tests to run, update the parent package, and rinse / repeat all the way up the chain (which can be a very long process).
This can't possibly be a unique situation yet it impacts our productivity greatly and encourages monolithic package development to limit number of packages to update instead of proper code separation.
I can only think of two solutions:
1) Update the web application to use the transitive dependency directly in package.json. This however breaks "encapsulation" because how a direct dependency manages its job shouldn't be known to the web application. If the direct dependency were to use some other transitive dependency later the web application shouldn't be left referencing a now irrelevant package.
2) Modify the web application's package-lock.json to point at the new version of the transitive dependency. This however seems to only work temporarily as merge conflicts or new installs of direct dependencies tend to revert these changes.
I realize that the answer might be to optimize the build / publish process to be less painful and manual but I was hoping others might have encountered a different solution.
FYI - All dependencies are installed with '~' as a version prefix by default.
The correct way to do this (Be in mind that this feature was introduced recently in npm 8.x) is using the overrides section. This new feature introduced allows replacing a package in your dependency tree with another version, or another package entirely.

NPM to existing project?

I have an online site and Im going to overhaul it. While I cannot find any information about if I can use npm and some kind of package manager (e.g Webpack) on live site which is on shared host (which has latest Node.js, npm support etc), Im going to develope it locally and worry about "publishing" it later on.
Is there a way to somehow covert my current downloaded project to npm project or Im better off just starting a new project? This is rather confusing, I've never used npm before.
Im using WordPress, everything is run with PHP atm but Im going to overhaul it and use Node.js.
NPM can be used to collect and manage Javascript dependencies for the browser so as to create a stand alone front-end JS app. BUT, bower is probably a better choice.
NPM is designed to manage Javascript dependencies for projects that use NodeJS or use the CommonJS module format for requiring modules.
Bower is specifically a package manager (like npm or composer) but it is meant to manage browser based javascript dependencies.
Currently, javascript doesn't have a formally defined module/import system, so a number of competing require() functions are been produced. NodeJS comes with a require() function that searches the npm/ folder for modules. Browserify is a pre-processor that can scan the npm folder for a dependency and all of its dependencies and bundle them into 1 file for a browser to download (because browser's don't have a require() function because the JS standard doesn't have define one)
I might be rambling here, but you should probably look at bower, and then - at some point in the future - look at either browserify or requirejs to combine and optimize all the JS plugins for your front-end app.
Edit for clarity:
Basically there are 2 engines to run your JS application: the browser or NodeJS. NodeJS needs npm, the browser has no idea what npm is. If you want to write a clean, single page app, all JS front-end for a PHP backend, you don't need NodeJS, and therefore don't need npm. Using npm will prematurely complicate the development of a front-end browser app because it will force you to decide on a require() implementation (Browserify or Requirejs) right from the start.

Appropriate usage, Difference and Exclusivity in installing packages using: npm, bower, ionic, cordova

Yes, I'm aware this has been asked before but the questions were asked in a manner that didn't give me the answer to find out the appropriate usage and if each package manager had exclusive packages that couldn't be found on another.
I understand that the ionic framework has these three frameworks/package managers underneath it and I can obtain the same package into my package making any of these same calls.
npm install [mypackage]
bower install [mypackage]
ionic plugin add [mypackage]
cordova plugin add [mypackage]
I also understand that they rely on each other like so.
Parent>Child [The framework above the other you would need to install the other]
npm>bower
npm>ionic
npm>cordova
npm>ionic[contains cordova]
However from what I've seen so far I don't find any packages that are exclusive to one or the other and was wondering
1. Are there some Packages/Plugins that are exclusive to one package manager?
2. Is it better to make a different call depending on workspaces?
npm- It is called as network packet manager it is just like installing a software or package from terminal without using GUI
bower-It will be used to install the required libraries in our project
cordova plugin add/Ionic plugin add these both commands are same there is no difference between them, but we are using ionic plugin add because we are using Ionic framework.
Having any queries, reply back