{"id":13440,"library":"libnpmpublish","title":"Programmatic npm Publish API","description":"libnpmpublish provides the programmatic interface used internally by the npm CLI for publishing and unpublishing packages to a configured registry. As of the provided metadata, its stable version is 11.1.3, making it a current and actively maintained component within the broader npm ecosystem. The library is typically released as part of the npm CLI monorepo, suggesting a consistent and frequent release cadence aligned with the CLI's development. It is a critical tool for automating package lifecycle operations in Node.js environments, abstracting the complexities of package tarball creation, manifest handling, registry communication, and authentication. Its key differentiator is being the official, low-level API that ensures full compatibility with npm's internal logic and registry interaction protocols, making it the canonical choice for developers building tools that interact directly with the npm registry.","status":"active","version":"11.1.3","language":"javascript","source_language":"en","source_url":"https://github.com/npm/cli","tags":["javascript"],"install":[{"cmd":"npm install libnpmpublish","lang":"bash","label":"npm"},{"cmd":"yarn add libnpmpublish","lang":"bash","label":"yarn"},{"cmd":"pnpm add libnpmpublish","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Handles all HTTP requests to the npm registry, including authentication and retries.","package":"npm-registry-fetch","optional":false},{"reason":"Used for fetching package manifests and creating tarballs from package directories or existing tarballs, which are crucial inputs for publish operations.","package":"pacote","optional":false},{"reason":"Likely used for dependency tree resolution and metadata manipulation during package preparation, especially in complex monorepo or workspace scenarios.","package":"@npmcli/arborist","optional":true}],"imports":[{"note":"While CommonJS `require` still works for basic usage, ESM `import` is the recommended standard for modern Node.js applications and aligns with the package's engine requirements.","wrong":"const publish = require('libnpmpublish').publish","symbol":"publish","correct":"import { publish } from 'libnpmpublish'"},{"note":"Similar to `publish`, ESM `import` is preferred. Unpublishing has specific registry limitations and often requires an exact `spec` (name@version).","wrong":"const unpublish = require('libnpmpublish').unpublish","symbol":"unpublish","correct":"import { unpublish } from 'libnpmpublish'"},{"note":"For environments restricted to CommonJS, this `require` pattern is fully supported.","symbol":"publish (CommonJS)","correct":"const { publish } = require('libnpmpublish')"}],"quickstart":{"code":"import { publish } from 'libnpmpublish';\nimport * as pacote from 'pacote';\nimport * as fs from 'fs/promises';\nimport * as path from 'path';\nimport * as os from 'os';\n\nasync function programmaticPublish() {\n  const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'my-temp-package-'));\n  const packageName = `@yourscope/test-publish-${Date.now()}`;\n\n  const packageJsonContent = {\n    name: packageName,\n    version: '1.0.0',\n    description: 'A test package published programmatically.',\n    main: 'index.js',\n    license: 'MIT',\n    // Ensure this matches the access you intend for scoped packages\n    publishConfig: {\n      access: 'public'\n    }\n  };\n\n  await fs.writeFile(path.join(tempDir, 'package.json'), JSON.stringify(packageJsonContent, null, 2));\n  await fs.writeFile(path.join(tempDir, 'index.js'), 'console.log(\"Hello from test package!\");');\n\n  console.log(`Created temporary package at: ${tempDir}`);\n\n  try {\n    // Get manifest and tarball data using pacote\n    const manifest = await pacote.manifest(tempDir, {});\n    const tarData = await pacote.tarball.stream(tempDir);\n    \n    // Convert stream to Buffer\n    const chunks: Buffer[] = [];\n    for await (const chunk of tarData) {\n      chunks.push(chunk);\n    }\n    const tarballBuffer = Buffer.concat(chunks);\n\n    const npmToken = process.env.NPM_TOKEN ?? ''; // Use granular access token for CI/CD\n    if (!npmToken) {\n      throw new Error('NPM_TOKEN environment variable is not set. Cannot publish without authentication.');\n    }\n\n    await publish(manifest, tarballBuffer, {\n      // Use a test registry or ensure token is for public npmjs.com\n      // registry: 'https://registry.npmjs.org/', \n      token: npmToken,\n      npmVersion: 'my-publish-script@1.0.0', // Custom user-agent string\n      access: 'public' // Required for public scoped packages\n    });\n\n    console.log(`Successfully published ${packageName}@1.0.0`);\n  } catch (error) {\n    console.error('Error during publish:', error);\n    throw error;\n  } finally {\n    await fs.rm(tempDir, { recursive: true, force: true });\n    console.log(`Cleaned up temporary directory: ${tempDir}`);\n  }\n}\n\nprogrammaticPublish();","lang":"typescript","description":"This quickstart demonstrates how to programmatically publish a new npm package using `libnpmpublish`. It creates a temporary package directory, generates a `package.json` and a simple `index.js`, then uses `pacote` to obtain the manifest and tarball buffer. Finally, it calls the `publish` function with an authentication token (from `NPM_TOKEN` environment variable) and configuration options like access level. It includes error handling and cleanup."},"warnings":[{"fix":"Upgrade your Node.js environment to a compatible version (20.17.0+ or 22.9.0+).","message":"libnpmpublish, as part of the npm CLI, adheres to its Node.js engine requirements. Versions 11+ require Node.js `^20.17.0 || >=22.9.0`, dropping support for older Node.js runtimes. Users on unsupported versions will encounter errors.","severity":"breaking","affected_versions":">=11.0.0"},{"fix":"Pass an `opts.token` (e.g., `process.env.NPM_TOKEN`) or ensure your execution environment has an `~/.npmrc` file with an `_authToken` entry for the target registry. For scoped packages published as public, `access: 'public'` must be set.","message":"Publishing to npm requires proper authentication. You must provide a valid `token` option or ensure the environment is configured with `npm login` credentials. For CI/CD, granular access tokens or trusted publishing (for npm CLI >=11.5.1) are highly recommended.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Ensure your package version is a valid semver increment. For pre-release versions (e.g., `1.0.0-beta.1`), always include `defaultTag: 'beta'` in the options to avoid errors.","message":"With npm v11 (and thus libnpmpublish v11+), publishing now performs more stringent semver checks. To apply a default 'latest' dist tag, the command retrieves all prior versions and requires the new version to be semver-greater than the latest non-prerelease version in the registry. Pre-release versions must explicitly specify a tag using `opts.defaultTag` (e.g., `next`, `beta`).","severity":"breaking","affected_versions":">=11.0.0"},{"fix":"Include `access: 'public'` in the options object passed to `publish` if you intend to make your scoped package publicly available.","message":"When publishing scoped packages (e.g., `@myorg/mypackage`), they are private by default. To make them publicly accessible on npm, you must explicitly set the `access` option to `'public'`. Failure to do so will result in a private package or an error if you do not have a paid npm Org plan.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Before calling `publish`, use `pacote.manifest()` to get the package manifest and `pacote.tarball.stream()` (and convert to Buffer) to get the tarball data from your package source.","message":"libnpmpublish expects a parsed `manifest` object (equivalent to `package.json` content) and `tarData` as a `Buffer` representing the gzipped tarball. It does not directly accept a file path for the package directory or tarball for `publish`. Use a utility like `pacote` to prepare these inputs.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure an `opts.token` is provided to `publish` with a valid npm token, or that `npm login` has been executed in the environment and a token is available in the `~/.npmrc` file. For CI/CD, use environment variables for `NPM_TOKEN`.","cause":"Missing or invalid authentication token when attempting to publish.","error":"npm ERR! code E401 npm ERR! 401 Unauthorized - PUT https://registry.npmjs.org/@yourscope%2fpackage - You must be logged in to publish packages."},{"fix":"Verify that the package name is unique or that you have publishing rights. If it's a new scoped package intended to be public, ensure `access: 'public'` is passed in the options.","cause":"The package name already exists and you lack ownership, or for a scoped package, `access: 'public'` was not set for a public publish.","error":"npm ERR! code E403 npm ERR! 403 Forbidden - PUT https://registry.npmjs.org/@yourscope%2fpackage - You do not have permission to publish this package."},{"fix":"Ensure you are using `pacote.manifest()` or similar to correctly parse and pass the package's `package.json` content as the first argument to `publish`.","cause":"The `manifest` object (parsed `package.json`) was not provided or was `null`/`undefined` to the `publish` function.","error":"Error: \"manifest\" is required"},{"fix":"Upgrade your Node.js runtime to a version compatible with `^20.17.0 || >=22.9.0`.","cause":"The `engines.node` requirement for libnpmpublish is not met by the current Node.js version.","error":"npm ERR! code EBADPLATFORM npm ERR! Not compatible with your operating system or architecture: libnpmpublish@11.1.3"}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":"","cli_version":null}