# deadbeef

> deadbeef is a unique key generator that will generate a key for any combo of anything

Latest version **1.1.3** (published 2023-11-26) · MIT license · 0 weekly downloads

## Install

```sh
npm install deadbeef
pnpm add deadbeef
yarn add deadbeef
bun add deadbeef
```

## Health

**Score 25/100 (F)** — status: abandoned.

Positive: has types; no vulnerabilities; high quality score.

Warnings: low downloads; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.1.3 |
| Published | 2023-11-26 |
| First published | 2022-10-09 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | CommonJS |
| Dependencies | 0 |
| Unpacked size | 15.4 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 1 |
| Author | Wyatt Greenway |
| Maintainers | th317erd |
| Keywords | pointer, address, reference, key, unique, identifier, map, cache, equality |

## Links

- npm: https://www.npmjs.com/package/deadbeef
- Repository: https://github.com/th317erd/deadbeef
- Homepage: https://github.com/th317erd/deadbeef#readme
- Issues: https://github.com/th317erd/deadbeef/issues
- npm.io page: https://npm.io/package/deadbeef

## Alternatives

- [@sindresorhus/slugify](https://npm.io/package/@sindresorhus/slugify.md) — 3.7M weekly downloads
- [solid-js](https://npm.io/package/solid-js.md) — 2.7M weekly downloads
- [expo-glass-effect](https://npm.io/package/expo-glass-effect.md) — 2.5M weekly downloads
- [nanoassert](https://npm.io/package/nanoassert.md) — 780.8K weekly downloads
- [@ffmpeg/ffmpeg](https://npm.io/package/@ffmpeg/ffmpeg.md) — 529.5K weekly downloads

## Recent versions

- 1.1.3 (latest) — 2023-11-26
- 1.1.2 — 2023-11-25
- 1.1.1 — 2022-10-17
- 1.1.0 — 2022-10-09
- 1.0.1 — 2022-10-09

## README

# deadbeef

`deadbeef` is a unique key generator that will generate a key for any combo of anything--**without leaking memory**.

`deadbeef` has some design constraints due to how Javascript engines work (to not to leak memory), and so the unique keys generated won't always be the same length, might be very long, and aren't very good to use as an id that can be persisted. The keys generated will also differ across application runs, and engine contexts (i.e. web-workers). However, given a single running context, the keys are guaranteed to be unique and consistent.

The reason I created `deadbeef` was to be able to create keys for caching engines. Any use-case that requires consistent unique keys within a single engine context is a perfect fit for `deadbeef`. If you require unique consistency across machines or different engine contexts, then you are out of luck! Sorry!

## Install

```bash
npm i --save deadbeef
```

## Use

To use `deadbeef`, simply throw any number of arguments at it to get a unique key. Keys generated by `deadbeef` will always be strings. Keys are guaranteed to be unique and consistent for the arguments provided.

For example:

```javascript
const deadbeef = require('deadbeef');

console.log(deadbeef('hello', 'world'));
// -> '2:string:hello:string:world'

console.log(deadbeef('hello', 'world'));
// -> '2:string:hello:string:world'

console.log(deadbeef('world', 'hello'));
// -> '2:string:world:string:hello'
```

However, `deadbeef` is designed such that we shouldn't care what the generated value is. Rather, the importance is in the equality of unique values generated. These can for example be used as keys into a `Map`.

```javascript
const deadbeef = require('deadbeef');

console.log(deadbeef('hello', 'world') === deadbeef('hello', 'world'));
// -> true

console.log(deadbeef('hello', 'world') === deadbeef('hello', 'world1'));
// -> false
```

And the coolest part is that `deadbeef` will accept absolutely *any* value to create a key from, even `null`, `undefined`, functions, objects, symbols, and no arguments at all!

```javascript
assert.strictEqual(deadbeef(), deadbeef());
assert.strictEqual(deadbeef(undefined), deadbeef(undefined));
assert.strictEqual(deadbeef(null), deadbeef(null));
assert.strictEqual(deadbeef(1), deadbeef(1));
assert.strictEqual(deadbeef(1, 1), deadbeef(1, 1));
assert.strictEqual(deadbeef(1, 1, true), deadbeef(1, 1, true));

const myFunction = () => {};
assert.strictEqual(deadbeef(myFunction, true), deadbeef(myFunction, true));
```

## Sorted

`deadbeef` has another method that can be used to generate a unique key: `deadbeef.sorted`. This sorts the generated ids for each argument before combining them. This means that you can check equality across many elements, even if they are not in order. For example, if you would like to know if two arrays contain the same values (even if not in the same order), you can do so:

```javascript
const deadbeef = require('deadbeef');

assert.strictEqual(deadbeef.sorted(...[ 1, 2, 3, 4, 5 ]), deadbeef.sorted(...[ 5, 3, 2, 4, 1 ]));
```

As always, this works with all values, not just numbers or strings. Throw functions at it, objects, symbols, who cares!

Want to check if two objects are identical in their contents? i.e. to check for "prop differences"? No problamo pal!

```javascript
let obj1 = { test: true, 1: 2, node: '.js' };
let obj2 = { 1: 2, node: '.js', test: true };

assert.strictEqual(
  deadbeef.sorted(
    ...Object.keys(obj1),
    ...Object.values(obj1)
  ),
  deadbeef.sorted(
    ...Object.keys(obj2),
    ...Object.values(obj2)
  )
);
```

## Maps

Since you can generate a unique id for any combo of values, you can easily use a `Map`, or a standard `Object` to store metadata on a combination of values, to use in caching engines, or whatever!

```javascript
function getCachedValue(...values) {
  let cacheKey = deadbeef(...values);
  if (!myCacheMap.has(cacheKey));
    return;

  return myCacheMap.get(cacheKey);
}

function setCachedValue(value, ...values) {
  let cacheKey = deadbeef(...values);
  myCacheMap.set(cacheKey, value);
}
```

## Generating your own ids

`deadbeef` will look for a `Symbol.for('@@deadbeefUniqueID')` symbol key on any value it is generating an id for. If this key exists on any given value, and is a function, then `deadbeef` will call it, and generate a unique id on the return value (which could be another generated id).

`deadbeef` has a helper property called `deadbeef.idSym` that is this symbol.

For example, let's say you have `User` models loaded from the database, which might be different references, but might have the same `id`. You could add a `Symbol.for('@@deadbeefUniqueID')` method to your user models, and return the user `id`, which means `deadbeef` would always generate the same unique key for your `User` model instances, even though they might be different instances:

```javascript
class User {
  constructor(userID) {
    this.id = userID;
  }

  [deadbeef.idSym]() {
    return this.id;
  }
}

// Two of the same user...
// but two different instances
let user1 = new User(123);
let user2 = new User(123);

console.log(deadbeef(user1) === deadbeef(user2));
// -> true
```

Or, maybe in your case users are unique when they have the same `id` __and__ `organizationID`. No problamo gentleladies!

```javascript
class User {
  constructor(userID, organizationID) {
    this.id = userID;
    this.organizationID = organizationID;
  }

  [deadbeef.idSym]() {
    // Generate a unique key that
    // will generate a unique key!
    return deadbeef(this.id, this.organizationID);
  }
}

// Two of the same user...
// but two different instances
let user1 = new User(42, 0xDEADBEEF);
let user2 = new User(42, 0xDEADBEEF);

console.log(deadbeef(user1) === deadbeef(user2));
// -> true
```

## Generating ids for foreign types

But what if I want to generate an id for a type I don't control? Let's say for example you want to generate ids in the browser for `Element` types, where the id will be generated based on the elements tag name, and its `id` attribute. No problem!

`deadbeef` has the method `generateIDFor` which will allow you to generate an id for _any_ type of value. The way this works is that you provide `generateIDFor` a `helper` method that will check if the type matches, and a `generator` method that will generate the id for a given type.

In our example, we want to generate an id for `Element` types in the browser. Here is how you would do that:

```javascript
const deadbeef = require('deadbeef');

const isElementHelper = (value) => value instanceof Element;

// Set us up to generate ids for Element types
deadbeef.generateIdFor(
  isElementHelper,
  (element) => deadbeef(element.tagName, element.getAttribute('id')),
);

// Are elements the same?
console.log(deadbeef(document.getElementByID('myDiv1')) === deadbeef(document.getElementByID('myDiv1')));

// Don't forget to cleanup!
// To do so, we pass the `helper`
// method to `removeIDGenerator`
deadbeef.removeIDGenerator(isElementHelper);
```

## The sky is the limit

Though this library is super simple, it allows for some really awesome things to be created. Just think of the possibilities!

1. Check if arrays contain all the same values
2. Check if arrays contain all of the same values _in the same order_
3. Check object equality
4. Generate cache keys for anything, or any combo of anything
5. Check if a UI component is the same, _and_ has the same children
6. Check if two instances of anything are the same
7. Check if multiple instances are the same
8. Generate combo-keys for Maps
9. Check if Elements have the same classes, styles, attributes, or whatever!
10. ... and much more!

Enjoy! Just for kix and giggles, drop us a line to let us know the creative application you have discovered for `deadbeef`.

## What's with the name bro?

Generating unique ids for _anything_ in javascript is no easy task (if you care about memory leaks... which you should). I couldn't think up any better name, and `0xDEADBEEF` has a long history in software development in debugging and memory-related issues. Because of its history, and relation to memory, I figured it was a perfect name for the library.

If you don't like the name, feel free to import it under another name!

```javascript
const ID = require('deadbeef');

if (ID(0xDEADBEEF, 'hello', 'moo moo') === ID(0xDEADBEEF, 'hello', 'moo moo'))
  console.log('We ❤️️ cows! Moo!');
```

## Requirements

The only requirement for `deadbeef` to work properly on your javascript engine is the presence and proper implementation of `WeakMap`. If the engine (or version of the engine) you are using supports `WeakMap`, then `deadbeef` will work for you. For NodeJS, this requires version `0.12.0` or later.

---
_Source: https://npm.io/package/deadbeef · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
