Private vs. Restricted Node Packages: What's the Diff?

At work, my team is sharing React components with our client by packaging and publishing each component individually. Publishing Node packages is new territory for me, and the learning curve hasn’t always been gentle. I’ll take some time now to clarify a paradigm I initially found confusing: what’s the difference between making a Node package private and restricting access to it?

Private Node packages

A private package is not shared or distributed on its own, and cannot be published to a registry (such as npmjs.com).

Marking a package as private ensures that its code will not be published, even accidentally. For instance, a one-off marketing site using React will contain a package.json file. Unless this file specifies that the project is private, an errant contributor could publish the project code to a package registry, even if the code were proprietary or simply wouldn’t make sense to distribute on its own.

Here’s a sample package.json for a non-distributable project:

    {
      "name": "specific-website",
      "version": "0.0.1",
      "description": "A bespoke website for <Client>",
      "main": "index.js",
      "private": true,
      "scripts": {
      },
      "dependencies": {
      },
      "devDependencies": {
      }
    }

Privacy only affects the ability to publish to a package registry — it won’t affect other ways of sharing code, such as pushing to a Github repo.

As a sidenote, private packages are generally ignored by packaging utilities. For example, Lerna won’t include private packages in its lerna list output unless you pass in the --all flag.

Restricted Node packages

In contrast to private packages, restricted packages can be distributed via a package registry, but only to whitelisted individuals. To use a restricted package, you need an account with the specific registry to which it was published, and you must belong to the organization or team that has access to that package. Otherwise, the package’s URL will 404.

One use for restricted packages is for sharing proprietary code within a company. For example, a custom lazyloader that conforms to studio standards can be used on multiple projects either through copy-pasting the original code over and over (boo), or through publishing the code once to npmjs.com and including it as a dependency on subsequent projects (yay!).

Here’s a sample package.json for a project with locked-down distribution permissions:

    {
      "name": "@company/awesome-lazyloader",
      "version": "0.0.1",
      "description": "A reusable lazyloader for use at <Company>",
      "main": "index.js",
      "license": "UNLICENSED",
      "publishConfig": {
        "access": "restricted"
      },
      "dependencies": {
      },  
      "devDependencies": {
      }
    }

If you publish to npmjs.com, take note that the site UI diverges from actual Node packaging terminology: a restricted package’s UI will have a “Private” badge even though the package isn’t private. (I can’t explain this; it’s just bad UX.)

Licensing

If you are publishing a restricted package, you probably want it to be unlicensed, which means that no one is inherently authorized to modify or redistribute it. You can set this either by removing the license field from the project’s package.json or by setting it to license: "UNLICENSED".

👋🏻

Thanks for reading! I hope this saved you some time. May 2019 be full of writing and sharing great JavaScript. 🥂🥂

Many thanks to Daniel, Ginger, and Thomas for your time, energy, and expertise.