npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

deno-npm-sync

v1.3.0

Published

A CLI tool to synchronize dependencies between Deno and NPM projects.

Readme

deno-npm-sync

A CLI tool and library to automatically synchronize npm and JSR package versions from package.json to Deno's deno.json imports. This ensures your Deno projects always use the same package versions as defined in your package.json, eliminating version drift and manual updates.

Features

  • 🔄 Automatic Synchronization: Syncs npm and JSR package versions from package.json to deno.json
  • 📦 Dual Registry Support: Works with both npm (npm:) and JSR (jsr:) imports
  • 🎯 Subpath Support: Handles imports with subpaths (e.g., npm:[email protected]/fp, jsr:@std/[email protected]/equals)
  • 🔍 Smart Detection: Only updates packages that have version mismatches
  • 📋 PNPM Catalog Support: Automatically resolves pnpm catalog references from pnpm-workspace.yaml
  • 🎨 Flexible Version Precision: Four modes - auto-detect, major-only, major.minor, or full version
  • 🛡️ Type-Safe: Written in TypeScript with full type definitions
  • 🧪 Well-Tested: Comprehensive test coverage with 29+ test cases
  • 🚀 CLI & Library: Use as a command-line tool or programmatically in your code

Installation

Global Installation (CLI)

pnpm install -g deno-npm-sync
# or
npm install -g deno-npm-sync
# or
yarn global add deno-npm-sync

Local Installation (Library)

pnpm add -D deno-npm-sync
# or
npm install --save-dev deno-npm-sync
# or
yarn add -D deno-npm-sync

CLI Usage

Basic Usage

# Sync from default locations (./package.json and ./deno.json)
deno-npm-sync

# Specify custom paths
deno-npm-sync --deno ./functions/deno.json --package ./package.json

# Silent mode (no output)
deno-npm-sync --silent

CLI Options

Options:
  -V, --version                    output the version number
  -d, --deno <path>                Path to deno.json file (default: "./deno.json")
  -p, --package <path>             Path to package.json file (default: "./package.json")
  -s, --silent                     Suppress console output (default: false)
  -v, --version-precision <mode>   Version precision mode: 'auto' (preserve format),
                                   'major' (x), 'minor' (x.y), or 'full' (x.y.z) (default: "auto")
  -h, --help                       display help for command

Examples

# Sync with custom deno.json location
deno-npm-sync --deno ./src/deno.json

# Sync with custom package.json location
deno-npm-sync --package ./custom-package.json

# Sync both with custom paths
deno-npm-sync -d ./functions/deno.json -p ./package.json

# Run in silent mode (useful for CI/CD)
deno-npm-sync --silent

# Use 'auto' mode to preserve version format from deno.json (default)
deno-npm-sync --version-precision auto

# Use 'major' mode to always use major version only (e.g., npm:lodash@4)
deno-npm-sync --version-precision major

# Use 'minor' mode to always use major.minor version (e.g., npm:[email protected])
deno-npm-sync --version-precision minor

# Use 'full' mode to always use full version (e.g., npm:[email protected])
deno-npm-sync --version-precision full

# Combine options
deno-npm-sync --deno ./functions/deno.json --silent --version-precision minor

Automation & Integration

Add to your package.json scripts for automatic synchronization:

{
  "scripts": {
    "sync:deno": "deno-npm-sync",
    "sync:deno:major": "deno-npm-sync --version-precision major",
    "sync:deno:minor": "deno-npm-sync --version-precision minor",
    "sync:deno:full": "deno-npm-sync --version-precision full",
    "postinstall": "pnpm run sync:deno"
  }
}

Usage Examples

  • Post-install hook: Automatically sync after pnpm install
  • Pre-commit hook: Ensure deno.json is up-to-date before commits
  • CI/CD pipeline: Add to your build process for consistency
  • Development workflow: Run manually or via npm scripts

Version Precision Modes

The tool supports four version precision modes to control how version numbers are formatted in your deno.json:

Auto Mode (Default)

In auto mode, the tool automatically detects and preserves the version format from your existing deno.json entries:

Example:

// deno.json (before)
{
  "imports": {
    "lodash": "npm:lodash@4",           // Major only
    "react": "npm:[email protected]",          // Major.Minor
    "typescript": "npm:[email protected]" // Major.Minor.Patch
  }
}

// package.json
{
  "dependencies": {
    "lodash": "^4.17.21",
    "react": "^18.3.1",
    "typescript": "^5.4.5"
  }
}

// deno.json (after sync with --version-precision auto)
{
  "imports": {
    "lodash": "npm:lodash@4",           // Preserved as major only
    "react": "npm:[email protected]",          // Preserved as major.minor
    "typescript": "npm:[email protected]" // Preserved as full version
  }
}

Major Mode

In major mode, the tool always uses only the major version number (e.g., 4):

Example:

// deno.json (before)
{
  "imports": {
    "lodash": "npm:[email protected]",
    "react": "npm:[email protected]",
    "typescript": "npm:[email protected]"
  }
}

// package.json
{
  "dependencies": {
    "lodash": "^4.17.21",
    "react": "^18.3.1",
    "typescript": "^5.4.5"
  }
}

// deno.json (after sync with --version-precision major)
{
  "imports": {
    "lodash": "npm:lodash@4",      // Forced to major only
    "react": "npm:react@18",       // Forced to major only
    "typescript": "npm:typescript@5" // Forced to major only
  }
}

Minor Mode

In minor mode, the tool always uses major.minor version format (e.g., 4.17):

Example:

// deno.json (before)
{
  "imports": {
    "lodash": "npm:lodash@4",
    "react": "npm:[email protected]",
    "typescript": "npm:[email protected]"
  }
}

// package.json
{
  "dependencies": {
    "lodash": "^4.17.21",
    "react": "^18.3.1",
    "typescript": "^5.4.5"
  }
}

// deno.json (after sync with --version-precision minor)
{
  "imports": {
    "lodash": "npm:[email protected]",      // Forced to major.minor
    "react": "npm:[email protected]",        // Forced to major.minor
    "typescript": "npm:[email protected]" // Forced to major.minor
  }
}

Full Mode

In full mode, the tool always uses the complete version (e.g., 4.17.21):

Example:

// deno.json (before)
{
  "imports": {
    "lodash": "npm:lodash@4",
    "react": "npm:[email protected]",
    "typescript": "npm:[email protected]"
  }
}

// package.json
{
  "dependencies": {
    "lodash": "^4.17.21",
    "react": "^18.3.1",
    "typescript": "^5.4.5"
  }
}

// deno.json (after sync with --version-precision full)
{
  "imports": {
    "lodash": "npm:[email protected]",    // Forced to full version
    "react": "npm:[email protected]",       // Forced to full version
    "typescript": "npm:[email protected]" // Forced to full version
  }
}

Use Cases:

  • Auto mode: Perfect for projects where you want to maintain existing version precision per package
  • Major mode: Ideal when you want to lock to major versions only for maximum compatibility
  • Minor mode: Good balance between stability and getting minor updates
  • Full mode: When you need exact version matching and full control

PNPM Catalog Support

The tool automatically resolves pnpm catalog references from pnpm-workspace.yaml, making it easy to manage centralized dependencies in monorepos.

Default Catalog

Use the default catalog with catalog: prefix:

# pnpm-workspace.yaml
catalog:
  zod: ^3.22.0
  react: ^18.2.0
  lodash: ^4.17.21
// package.json
{
  "dependencies": {
    "zod": "catalog:",
    "react": "catalog:",
    "lodash": "catalog:"
  }
}

The tool will automatically resolve these to ^3.22.0, ^18.2.0, and ^4.17.21 respectively.

Named Catalogs

Use named catalogs for different dependency groups:

# pnpm-workspace.yaml
catalogs:
  prod:
    zod: ^3.22.0
    lodash: ^4.17.21
  dev:
    typescript: ^5.0.0
    vitest: ^1.0.0
// package.json
{
  "dependencies": {
    "zod": "catalog:prod",
    "lodash": "catalog:prod"
  },
  "devDependencies": {
    "typescript": "catalog:dev",
    "vitest": "catalog:dev"
  }
}

The tool will resolve these references to the actual versions from the specified catalog.

How It Works

  1. The tool detects you're using pnpm (via package-manager-detector)
  2. It looks for pnpm-workspace.yaml in your workspace root
  3. When it finds a catalog: or catalog:name reference in package.json, it resolves the actual version
  4. The resolved version is then used to sync with your deno.json

Example:

// deno.json (before)
{
  "imports": {
    "zod": "npm:[email protected]"
  }
}

// package.json
{
  "dependencies": {
    "zod": "catalog:prod"  // Resolves to ^3.22.0
  }
}

// deno.json (after sync)
{
  "imports": {
    "zod": "npm:[email protected]"
  }
}

Registry Support

NPM Registry

The tool syncs npm packages with the npm: specifier:

# deno.json
{
  "imports": {
    "lodash": "npm:[email protected]",
    "react": "npm:[email protected]"
  }
}

# package.json
{
  "dependencies": {
    "lodash": "^4.17.21",
    "react": "^18.2.0"
  }
}

JSR (JavaScript Registry)

The tool also syncs JSR packages with the jsr: specifier:

# deno.json
{
  "imports": {
    "@std/assert": "jsr:@std/[email protected]",
    "@std/path": "jsr:@std/[email protected]"
  }
}

# package.json
{
  "dependencies": {
    "@std/assert": "^1.0.0",
    "@std/path": "^0.225.0"
  }
}

Mixed Registries

You can use both npm and JSR imports in the same project:

// deno.json
{
  "imports": {
    "lodash": "npm:[email protected]",
    "@std/assert": "jsr:@std/[email protected]",
    "react": "npm:[email protected]"
  }
}

The tool will automatically detect and sync the correct registry for each package.

Programmatic Usage

You can also use the library programmatically in your Node.js or TypeScript code:

import { syncDenoNpmDependencies } from 'deno-npm-sync';

// Basic usage with auto mode (default)
const result = syncDenoNpmDependencies({
  denoJsonPath: './deno.json',
  packageJsonPath: './package.json',
  silent: false,
});

// Using major mode to always use major version only
const result2 = syncDenoNpmDependencies({
  denoJsonPath: './deno.json',
  packageJsonPath: './package.json',
  silent: false,
  versionPrecision: 'major',
});

// Using minor mode for major.minor versions
const result3 = syncDenoNpmDependencies({
  denoJsonPath: './deno.json',
  packageJsonPath: './package.json',
  silent: false,
  versionPrecision: 'minor',
});

// Using full mode for complete versions
const result4 = syncDenoNpmDependencies({
  denoJsonPath: './deno.json',
  packageJsonPath: './package.json',
  silent: false,
  versionPrecision: 'full',
});

// Check results
if (result.hasUpdates) {
  console.log(`Updated ${result.updates.length} packages:`);
  result.updates.forEach((update) => {
    console.log(`  ${update.name}: ${update.oldVersion} → ${update.newVersion}`);
  });
} else {
  console.log('All packages are already in sync!');
}

API

syncDenoNpmDependencies(options: SyncOptions): SyncResult

Synchronizes npm package versions from package.json to deno.json imports.

Parameters:

  • options.denoJsonPath (string): Path to deno.json file
  • options.packageJsonPath (string): Path to package.json file
  • options.silent (boolean, optional): If true, suppresses console output (default: false)
  • options.versionPrecision ('auto' | 'major' | 'minor' | 'full', optional): Version precision mode (default: 'auto')
    • 'auto': Preserves the version format from deno.json (e.g., 1, 1.0, 1.0.0)
    • 'major': Always uses only major version (e.g., 1)
    • 'minor': Always uses major.minor version (e.g., 1.0)
    • 'full': Always uses full version (e.g., 1.0.0)

Returns:

  • hasUpdates (boolean): Whether any updates were made
  • updates (array): Array of update objects containing:
    • name (string): Package name
    • oldVersion (string): Previous version in deno.json
    • newVersion (string): New version from package.json

How It Works

The tool scans your deno.json imports for npm and JSR-prefixed packages:

{
  "imports": {
    "lodash": "npm:[email protected]",
    "typescript": "npm:[email protected]/lib/typescript.d.ts",
    "@std/assert": "jsr:@std/[email protected]",
    "@std/path": "jsr:@std/[email protected]/posix"
  }
}

Then it checks your package.json for the same packages:

{
  "dependencies": {
    "lodash": "^4.17.21",
    "@std/assert": "^1.0.0",
    "@std/path": "^0.225.0"
  },
  "devDependencies": {
    "typescript": "^5.0.0"
  }
}

And updates the deno.json to match:

{
  "imports": {
    "lodash": "npm:[email protected]",
    "typescript": "npm:[email protected]/lib/typescript.d.ts",
    "@std/assert": "jsr:@std/[email protected]",
    "@std/path": "jsr:@std/[email protected]/posix"
  }
}

Use Cases

  • Monorepos: Keep Deno and Node.js dependencies in sync
  • Hybrid Projects: Projects using both Deno and Node.js
  • JSR + npm: Projects using both JSR and npm registries
  • CI/CD Pipelines: Automate dependency synchronization in your build process
  • Development Workflow: Ensure consistency between package managers

Integration with Scripts

Add to your package.json scripts:

{
  "scripts": {
    "sync:deno": "deno-npm-sync",
    "postinstall": "deno-npm-sync --silent"
  }
}