mahtis
v0.5.1
Published
Readme
mahtis
A small collection of things I keep rewriting: prefixed sortable IDs, a handful of React hooks and a shared Prettier config. Written in TypeScript, shipped as ESM and CJS.
Install
pnpm add mahtisreact is a peer dependency and only needed for mahtis/hooks and mahtis/react.
Entrypoints
There is no root import, pick the subpath you need.
| Import | Contents | Runtime |
| ----------------- | --------------------------------- | ----------- |
| mahtis/mika | Prefixed, sortable, decodable IDs | Node |
| mahtis/id | Random string IDs | Anywhere |
| mahtis/hooks | React hooks | Browser |
| mahtis/react | React helpers | Browser |
| mahtis/prettier | Shared Prettier config | Config only |
mahtis/mika
IDs like user_NjEyNzIzOTE4MDQwMzEzODU3: a readable prefix plus a snowflake, so every ID
sorts by creation time and can be decoded back into its parts.
import { Mika } from 'mahtis/mika';
const mika = new Mika(['user', { prefix: 'invite', secure: true }]);
const id = mika.gen('user'); // user_NjEyNzIzOTE4MDQwMzEzODU3
mika.validate(id, 'user'); // true
mika.decode(id); // { prefix: 'user', timestamp: 1787079965920n, nodeId: 731, seq: 1, ... }Prefixes marked secure: true get 16 extra random bytes, so they cannot be guessed from a
neighbouring ID. Use that for invite codes and share links.
The registered prefixes drive the types, which you can reuse:
import type { InferIds } from 'mahtis/mika';
type Id = InferIds<typeof mika>; // `user_${string}` | `invite_${string}`Constructor options:
| Option | Default | Purpose |
| ------------------------ | -------------------- | --------------------------------------------- |
| epoch | Jan 1 2022 | Point in time IDs are counted from |
| nodeId | derived from the MAC | 0 to 1023, one per process writing to the set |
| suppressPrefixWarnings | false | Silences warnings for unregistered prefixes |
Keep epoch stable once IDs exist, every ID is decoded against it.
mahtis/id
import { generateId } from 'mahtis/id';
generateId(); // Zkas5DRK8hM3NOSqAJkE
generateId(8); // EQCOrzY8
generateId(8, 'abcdef0123456789');Backed by Math.random, so it is fine for keys and handles, not for secrets.
mahtis/hooks
import { useDebounce, useIsOnline, useDynamicTextSize } from 'mahtis/hooks';
const { debouncedValue } = useDebounce(query, 300);
const online = useIsOnline();
const { fontSize, isMultiline, textRef } = useDynamicTextSize(title, 320);mahtis/react
provideReact turns an async function into React state, refetching whenever the arguments
change and ignoring results of outdated calls.
import { provideReact } from 'mahtis/react';
const { data, error, isLoading, mutate } = provideReact(fetchUser, userId);mahtis/prettier
{
"prettier": "mahtis/prettier"
}License
MIT
