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

apotheke

v0.0.1

Published

JavaScript/TypeScript import organizer — prettier plugin + CLI

Readme

apotheke

Import organizer for JavaScript and TypeScript projects. Groups, sorts, and deduplicates imports based on a simple config file.

// Before
import { useQuery } from '@tanstack/react-query';
import { useMemo } from 'react';
import { createRoute } from '@tanstack/react-router';
import { tsr } from '../api/tsr';
import useLoggedUser from '../hooks/use-logged-user';

// After
// React
import { useMemo } from 'react';

// Hooks
import useLoggedUser from '../hooks/use-logged-user';

// Api
import { tsr } from '../api/tsr';
import { useQuery } from '@tanstack/react-query';

// Navigation
import { createRoute } from '@tanstack/react-router';

Requirements

  • Node.js ≥ 18

Installation

npm install -D apotheke
# or
pnpm add -D apotheke

Usage

apotheke --write src/**/*.{ts,tsx}     # format in place
apotheke --check src/**/*.{ts,tsx}     # CI — exit 1 if anything would change
apotheke --diff  src/**/*.{ts,tsx}     # print diff without writing
apotheke --stdin-filepath src/app.tsx  # read from stdin, write to stdout

Config

Create apotheke.config.mjs at your project root:

// apotheke.config.mjs
export default {
    groups: [
        { name: 'React', match: ['react', 'react-dom', 'react-*'] },
        { name: 'Hooks', match: ['**/hooks/**'] },
        { name: 'Api', match: ['**/api/**', '@tanstack/react-query'] },
        { name: 'Navigation', match: ['@tanstack/react-router'] },
        { name: 'Assets', match: ['lucide-react'] }
    ],
    aliases: {
        '@': './src' // mirrors tsconfig paths — auto-read if omitted
    },
    groupSeparator: true, // blank line between groups
    groupComments: true   // // GroupName header above each group
};

Apotheke also reads tsconfig.json (or jsconfig.json) automatically to pick up paths aliases and baseUrl, so you often don't need to set aliases manually.

Unmatched imports collect in an Others group at the end. Side-effect imports (import './styles.css') always go first.

Monorepo

Place a root config and extend it per-package:

// apps/web/apotheke.config.mjs
export default {
    extends: '../../apotheke.config.mjs',
    groups: [{ name: 'Shared', match: ['@acme/*'] }]
};

Prettier plugin

Apotheke ships as a prettier plugin. When loaded, it runs as a preprocess step — apotheke organises imports first, then prettier formats the result. One pass, correct order, no conflicts.

Requirements: Prettier v3 or later (v3 supports async preprocess; v2 does not).

Permanent setup

1. Install apotheke

pnpm add -D apotheke

2. Add the plugin to your prettier config

// .prettierrc.js
module.exports = {
    plugins: ['apotheke'],
};

That's it — prettier --write will now organise imports automatically.

Quick test (without installing)

cd /path/to/your-project
npx prettier@3 \
  --plugin /path/to/apotheke/dist/index.js \
  --write 'src/App.tsx'

VS Code on-save

Install the Prettier - Code formatter extension. Because prettier.format() calls our plugin's preprocess hook directly, no extra config is needed:

{
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.formatOnSave": true
}

Pre-commit with Husky + lint-staged

{
    "lint-staged": {
        "*.{ts,tsx,js,jsx}": ["prettier --write"]
    }
}

Prettier v2 fallback

If you can't upgrade to prettier v3, use the CLI sequentially via lint-staged:

{
    "lint-staged": {
        "*.{ts,tsx,js,jsx}": [
            "apotheke --write",
            "prettier --write"
        ]
    }
}

Testing locally without publishing

Option 1 — Direct invocation (no setup)

node /path/to/apotheke/dist/cli.js --write 'src/**/*.{ts,tsx}'

Build first if needed: cd /path/to/apotheke && pnpm build

Option 2 — pnpm link (recommended)

In the apotheke repo:

pnpm build
pnpm link --global

In your target repo:

pnpm link --global apotheke

Now apotheke --write src/**/*.tsx works as if it were installed normally. You'll need to re-run pnpm build in the apotheke repo after making source changes.

To unlink when done:

# In your target repo
pnpm unlink --global apotheke

# In the apotheke repo
pnpm unlink --global

Option 3 — Path dependency in package.json

pnpm add /path/to/apotheke

Development

pnpm install

# Build (required before running locally or testing the plugin)
pnpm build

# Run all tests (unit + e2e)
pnpm test

# Unit tests only
pnpm test:unit

# E2E tests against real repos (cloned automatically on first run)
pnpm test:e2e

# Type check
pnpm typecheck

Project structure

src/
  parser.ts        OXC-based import extractor
  grouper.ts       Glob-based group assignment
  sorter.ts        Alphabetical sort, type imports float to top
  deduplicator.ts  Merge named/default imports from same specifier
  printer.ts       Reconstruct import block with group headers
  config.ts        Load apotheke.config.mjs, merge tsconfig aliases
  format.ts        Top-level formatImports(source, config)
  types.ts         Shared types
cli.ts             CLI source (Node.js)
index.ts           Prettier plugin + programmatic API
dist/
  cli.js           Compiled CLI — run with node or via the apotheke bin
  index.js         Compiled prettier plugin
  index.d.ts       Types for programmatic use
tests/
  unit/            76 unit tests
  e2e/             20 e2e tests against sonner and tremor