Package Management


https://docs.npmjs.com/cli/v11/configuring-npm/package-json
https://docs.npmjs.com/cli/v11/configuring-npm/npmrc
https://docs.npmjs.com/cli/v11/commands/npm-ci
https://docs.npmjs.com/cli/v11/commands/npm-publish
https://nodejs.org/api/packages.html

1. Important Points#

Node.js package management:
    npm is default
    package.json defines metadata/scripts/dependencies
    package-lock.json locks versions
    npm ci for CI/container build
    do not commit auth token

2. Package Metadata / Manifest#

{
  "name": "@my-org/order-client",
  "version": "1.0.0",
  "type": "module",
  "private": false,
  "main": "./src/index.js",
  "exports": {
    ".": "./src/index.js"
  },
  "files": [
    "src",
    "README.md"
  ],
  "scripts": {
    "test": "node --test",
    "prepack": "npm test",
    "pack": "npm pack",
    "publish:dry": "npm publish --dry-run",
    "publish:registry": "npm publish --access restricted"
  },
  "engines": {
    "node": ">=20"
  },
  "publishConfig": {
    "access": "restricted",
    "registry": "https://registry.npmjs.org/"
  }
}

3. Install Dependencies#

npm install express
npm install -D eslint @eslint/js
npm ci
npm install:
    local development

npm ci:
    CI / Docker
    requires package-lock.json

4. Registry#

npm config get registry
npm config set registry https://registry.npmjs.org/
registry=https://registry.npmjs.org/
@my-org:registry=https://npm.pkg.github.com/
always-auth=true

5. Private Registry Auth#

//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
cat > .npmrc <<'EOF'
@my-org:registry=https://npm.pkg.github.com/
//npm.pkg.github.com/:_authToken=${NPM_TOKEN}
always-auth=true
EOF

npm ci

6. TLS / CA#

strict-ssl=true
cafile=/etc/ssl/private/company-ca.pem
export NODE_EXTRA_CA_CERTS=/etc/ssl/private/company-ca.pem
export npm_config_cafile=/etc/ssl/private/company-ca.pem
export npm_config_strict_ssl=true
do not:
    strict-ssl=false in production
    NODE_TLS_REJECT_UNAUTHORIZED=0 in production

7. Docker With Private Packages#

# syntax=docker/dockerfile:1

FROM node:22-bookworm-slim AS deps
WORKDIR /app

COPY package.json package-lock.json ./
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm ci
docker build \
  --secret id=npmrc,src="$HOME/.npmrc" \
  -t order-api:local .

8. Create A Package / Library#

// src/OrderClient.js
export class OrderClient {
  constructor(baseUrl) {
    this.baseUrl = baseUrl;
  }

  async createOrder(request) {
    const response = await fetch(`${this.baseUrl}/orders`, {
      method: "POST",
      headers: {
        "content-type": "application/json"
      },
      body: JSON.stringify(request)
    });

    if (!response.ok) {
      throw new Error(`create order failed: ${response.status}`);
    }

    return response.json();
  }
}
// src/index.js
export { OrderClient } from "./OrderClient.js";

9. Pack And Publish#

npm pack --dry-run
npm pack
npm publish --access restricted
publish checklist:
    version updated
    files allowlist reviewed
    registry reviewed
    access reviewed

10. Monorepo / Workspace#

{
  "name": "order-platform",
  "private": true,
  "workspaces": [
    "packages/*",
    "apps/*"
  ]
}

11. Production Checklist#

install:
    package-lock.json committed
    npm ci used in CI
    registry pinned when required
    token stored in secret manager

security:
    no token in committed .npmrc
    no token copied into Docker image
    strict-ssl enabled
    company CA configured when needed

publish:
    exports reviewed
    files allowlist reviewed
    npm pack --dry-run reviewed
    publishConfig reviewed