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

dropid

v1.0.0

Published

Human-readable, prefixed unique identifiers for database models

Readme

DropID

npm version npm downloads License: MIT GitHub stars https://github.com/golddick/dropid.git Human-readable, prefixed unique identifiers for your database models.

dropid('user')        // → user_a3f2b9c1d4e5
dropid('post', 'app') // → app_post_x7k9m2n4p1q8

Why DropID?

Before (UUIDs):

550e8400-e29b-41d4-a916-446655440000

Good luck debugging that in your logs.

After (DropID):

user_a3f2b9c1d4e5

Instantly know what you're looking at.

Features

  • 🎯 Human-readable - Know what type of object an ID represents at a glance
  • 🔒 Collision-resistant - Uses nanoid under the hood (cryptographically secure)
  • 🚀 ORM-agnostic - Works with Drizzle, Prisma, TypeORM, or plain JavaScript
  • Lightweight - Single dependency (nanoid), ~2KB bundle
  • 🎨 Customizable - Configure length, alphabet, and separators
  • 🏢 Multi-tenant ready - Built-in prefix support for organization-scoped IDs
  • 📦 TypeScript-native - Full type safety out of the box

Installation

npm install dropid
# or
yarn add dropid
# or
pnpm add dropid

Quick Start

import { dropid } from 'dropapi';

// Basic usage
const userId = dropid('user');
// → user_a3f2b9c1d4e5

// With prefix (for multi-tenant apps)
const postId = dropid('post', 'acme');
// → acme_post_x7k9m2n4p1q8

// Use anywhere you need an ID
const newUser = {
  id: dropid('user'),
  name: 'John Doe',
  email: '[email protected]',
};

Usage with ORMs

Drizzle ORM

import { pgTable, text, timestamp } from 'drizzle-orm/pg-core';
import { dropid } from 'dropapi';

export const users = pgTable('users', {
  id: text('id').primaryKey().$defaultFn(() => dropid('user')),
  name: text('name').notNull(),
  email: text('email').notNull(),
  createdAt: timestamp('created_at').defaultNow(),
});

export const posts = pgTable('posts', {
  id: text('id').primaryKey().$defaultFn(() => dropid('post', 'blog')),
  title: text('title').notNull(),
  authorId: text('author_id').references(() => users.id),
});

Prisma

// In your application code
import { dropid } from 'dropapi';

const user = await prisma.user.create({
  data: {
    id: dropid('user'),
    name: 'Jane Smith',
    email: '[email protected]',
  },
});

const post = await prisma.post.create({
  data: {
    id: dropid('post'),
    title: 'My First Post',
    authorId: user.id,
  },
});

TypeORM

import { Entity, PrimaryColumn, Column } from 'typeorm';
import { dropid } from 'dropapi';

@Entity()
export class User {
  @PrimaryColumn()
  id: string = dropid('user');

  @Column()
  name: string;

  @Column()
  email: string;
}

API Reference

dropid(modelName, prefix?, options?)

Generates a unique ID with optional prefix.

Parameters:

  • modelName (string, required): The name of your model/table (e.g., 'user', 'post')
  • prefix (string, optional): Additional prefix for multi-tenant or namespacing
  • options (DropIdOptions, optional): Override global configuration

Returns: string - The generated ID

Examples:

dropid('user')                           // → user_a3f2b9c1d4e5
dropid('post', 'blog')                   // → blog_post_x7k9m2n4p1q8
dropid('order', 'shop', { length: 16 })  // → shop_order_k8j3m9n2l4p6q1r7

configure(options)

Set global configuration that applies to all subsequent dropid() calls.

Parameters:

  • options (DropIdOptions): Configuration object

Options:

interface DropIdOptions {
  length?: number;      // Length of random ID part (default: 12)
  alphabet?: string;    // Characters to use (default: '0-9a-z')
  separator?: string;   // Separator between parts (default: '_')
}

Examples:

import { configure, dropid } from 'dropaphi';

// Use longer IDs
configure({ length: 16 });
dropid('user'); // → user_a3f2b9c1d4e5k7j9

// Use dashes
configure({ separator: '-' });
dropid('post'); // → post-x7k9m2n4p1q8

// Use custom alphabet
configure({ alphabet: '0123456789ABCDEF' });
dropid('order'); // → order_A3F2B9C1D4E5

createPrefixedId(prefix, options?)

Creates a reusable ID generator with a fixed prefix.

Parameters:

  • prefix (string, required): The prefix to use
  • options (DropIdOptions, optional): Configuration

Returns: (modelName: string) => string

Examples:

import { createPrefixedId } from 'dropaphi';

// Create organization-specific generators
const acmeId = createPrefixedId('acme');
const globexId = createPrefixedId('globex');

acmeId('user');   // → acme_user_a3f2b9c1d4e5
acmeId('post');   // → acme_post_x7k9m2n4p1q8

globexId('user'); // → globex_user_k2j8n9m3l1p5

Presets

Alphabet presets:

import { alphabets } from 'dropaphi';

alphabets.alphanumeric // '0123456789abcdefghijklmnopqrstuvwxyz' (default)
alphabets.base58       // Bitcoin-style (no 0/O, 1/l/I confusion)
alphabets.hex          // '0123456789abcdef'
alphabets.base64url    // URL-safe base64
alphabets.numeric      // '0123456789' (not recommended)

Length presets:

import { lengths } from 'dropaphi';

lengths.short      // 8 chars  - ~4 years to 1% collision
lengths.medium     // 12 chars - ~200 years to 1% collision (default)
lengths.long       // 16 chars - ~10^12 years to 1% collision
lengths.extraLong  // 21 chars - essentially collision-proof

Advanced Usage

Multi-tenant SaaS

import { createPrefixedId } from 'dropaphi';

function getTenantIdGenerator(tenantId: string) {
  return createPrefixedId(tenantId);
}

// In your request handler
app.post('/api/:tenantId/users', async (req, res) => {
  const genId = getTenantIdGenerator(req.params.tenantId);
  
  const user = {
    id: genId('user'),           // → acme_user_x7k9m2n4p1q8
    name: req.body.name,
    tenantId: req.params.tenantId,
  };
  
  await db.users.insert(user);
  res.json(user);
});

Different Alphabets

import { configure, dropid, alphabets } from 'dropaphi';

// Base58 (no confusing characters)
configure({ alphabet: alphabets.base58 });
dropid('token'); // → token_Kx7mN3pQ2rT8

// Hexadecimal
configure({ alphabet: alphabets.hex });
dropid('log'); // → log_a3f2b9c1d4e5

Per-Call Options

import { dropid } from 'dropaphi';

// Override global config for specific calls
const shortId = dropid('temp', undefined, { length: 6 });
// → temp_a3f2b9

const customId = dropid('special', 'app', { 
  length: 16, 
  separator: '-' 
});
// → app-special-k8j3m9n2l4p6q1r7

Security

Collision Resistance

DropID uses nanoid which is cryptographically secure:

  • Default (12 chars): ~200 years to 1% collision at 1,000 IDs/second
  • 16 chars: ~10^12 years to 1% collision at 1,000 IDs/second
  • 21 chars: Even safer (nanoid default)

No Sequential Enumeration

Unlike sequential IDs (user_1, user_2, user_3), Drop-API-ID generates random IDs that prevent:

  • Enumerating all users
  • Guessing valid IDs
  • Inferring business metrics

URL Safety

Default alphabet (0-9a-z) and separator (_) are URL-safe and work in:

  • URLs without encoding
  • Filenames
  • Database queries
  • Log files

Performance

  • Generation speed: ~2-3 million IDs per second
  • Memory usage: Negligible (single function call)
  • Bundle size: ~2KB minified + gzipped
  • No external dependencies except nanoid

TypeScript Support

DropID is written in TypeScript and provides full type safety:

import { dropid, configure, createPrefixedId, DropIdOptions } from 'dropaphi';

// All functions are fully typed
const id: string = dropid('user');

// Options are type-checked
const options: DropIdOptions = {
  length: 12,
  alphabet: '0123456789abcdefghijklmnopqrstuvwxyz',
  separator: '_',
};

configure(options);

// Generators are typed
const genId: (modelName: string) => string = createPrefixedId('acme');

Comparison

| Feature | Drop-API-ID | UUID | ULID | CUID | |---------|-------------|------|------|------| | Human-readable prefix | ✅ | ❌ | ❌ | ❌ | | Customizable format | ✅ | ❌ | ❌ | Limited | | Collision-resistant | ✅ | ✅ | ✅ | ✅ | | Short length | ✅ | ❌ | ❌ | ✅ | | Multi-tenant support | ✅ | ❌ | ❌ | ❌ | | TypeScript native | ✅ | ✅ | ✅ | ✅ |

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

MIT © Gold Dick

Acknowledgments

  • Built with nanoid by Andrey Sitnik
  • Inspired by Stripe's ID format
  • Thanks to the open source community

Made with ❤️ by developers who are tired of debugging UUIDs