
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
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
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.
npm install dropid
# or
yarn add dropid
# or
pnpm add dropid
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: 'john@example.com',
};
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),
});
// In your application code
import { dropid } from 'dropapi';
const user = await prisma.user.create({
data: {
id: dropid('user'),
name: 'Jane Smith',
email: 'jane@example.com',
},
});
const post = await prisma.post.create({
data: {
id: dropid('post'),
title: 'My First Post',
authorId: user.id,
},
});
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;
}
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 namespacingoptions (DropIdOptions, optional): Override global configurationReturns: 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 objectOptions:
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 useoptions (DropIdOptions, optional): ConfigurationReturns: (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
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
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);
});
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
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
DropID uses nanoid which is cryptographically secure:
Unlike sequential IDs (user_1, user_2, user_3), Drop-API-ID generates random IDs that prevent:
Default alphabet (0-9a-z) and separator (_) are URL-safe and work in:
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');
| Feature | Drop-API-ID | UUID | ULID | CUID |
|---|---|---|---|---|
| Human-readable prefix | ✅ | ❌ | ❌ | ❌ |
| Customizable format | ✅ | ❌ | ❌ | Limited |
| Collision-resistant | ✅ | ✅ | ✅ | ✅ |
| Short length | ✅ | ❌ | ❌ | ✅ |
| Multi-tenant support | ✅ | ❌ | ❌ | ❌ |
| TypeScript native | ✅ | ✅ | ✅ | ✅ |
Contributions are welcome! Please feel free to submit a Pull Request.
git checkout -b feature/amazing-feature)git commit -m 'Add some amazing feature')git push origin feature/amazing-feature)MIT © Gold Dick
Made with ❤️ by developers who are tired of debugging UUIDs
FAQs
Human-readable, prefixed unique identifiers for database models
We found that dropid demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.