# keysmith [![CI Status][ci-img]][ci] [![Lint Status][lint-img]][lint] [![Hex.pm Version][hex-img]][hex] [![Minimum Erlang Version][erlang-img]][erlang] [![License][license-img]][license]
KeySmith is a library for generating unique IDs. It supports two types of
IDs:
* UUID ([RFC-9562](https://www.rfc-editor.org/rfc/rfc9562.html))
* The 'nil' uuid (`00000000-0000-0000-0000-000000000000`)
* The 'max' uuid (`ffffffff-ffff-ffff-ffff-ffffffffffff`)
* Version 4 (random)
* Version 7 (time-based and random)
* TypeID ([specification](https://github.com/jetify-com/typeid/tree/main/spec))
* TypeID's embed a UUID v7 by default, but can be customized with any
supported UUID version
Keysmith is a well tested, secure and performant:
* Full test coverage
* Property-based tests
* Uses `crypto` for secure random number generation
* Fast and efficient using binary pattern matching
## Usage
KeySmith provides functions to generate UUIDs and TypeIDs. Here are some basic
examples:
### Generating UUIDs
You can generate UUIDs version 4 (random) and version 7 (time-based):
```erlang
% Generate a UUID v4
1> keysmith:uuid(4).
<<"79782daf-ff7d-4426-a8f5-e12672e89e32">>
% Generate a UUID v7
2> keysmith:uuid(7).
<<"01922919-44d3-779c-84ad-20ab20fc7dbb">>
% Generate a UUID v7 with a specific timestamp
3> keysmith:uuid({7, 1234567890}).
<<"00004996-02d2-7bf9-9b68-599f55d37931">>
```
UUIDs can be generated in different formats:
```erlang
4> keysmith:uuid(4, binary).
<<193,169,209,27,160,43,73,83,147,64,63,136,127,77,166,39>>
5> keysmith:uuid(4, hex_nodash).
<<"01922919d63d7de990a0209e23b50747">>
```
### Generating TypeIDs
TypeIDs are a combination of a type prefix and a UUID. They are useful for
creating namespaced unique identifiers:
```erlang
% Generate a TypeID with default UUID v7
6> keysmith:type_id(user).
<<"user_01j8mhm5vafn8vprb7g6dz4q90">>
% Generate a TypeID with a specific UUID
7> keysmith:type_id(product, 4).
<<"product_7fv003jbwg9ptvecwr68p6n5k6">>
```
### Parsing IDs
KeySmith can also parse UUIDs and TypeIDs back into their components:
```erlang
8> UUID = keysmith:uuid(7).
<<"019228d7-b720-7484-ab83-25332e9b0a33">>
9> keysmith:parse(uuid, UUID).
#{var => rfc,
ver => 7,
bin => <<1,146,40,215,183,32,116,132,171,131,37,51,46,155,10,51>>,
hex => <<"019228d7-b720-7484-ab83-25332e9b0a33">>,
val =>
#{rand_a => <<72,4:4>>,
rand_b => <<174,12,148,204,186,108,40,51:6>>,
unix_ts => {millisecond,1727262078752}}}
10> TypeID = keysmith:type_id(order).
<<"order_01j9p6jwxyfzjawx1ksjyzp9gy">>
11> keysmith:parse(type_id, TypeID).
{type_id,order,
#{var => rfc,
ver => 7,
bin => <<1,146,108,105,115,190,127,228,174,116,51,204,189,251,38,30>>,
hex => <<"01926c69-73be-7fe4-ae74-33ccbdfb261e">>,
val =>
#{rand_a => <<254,4:4>>,
rand_b => <<185,208,207,50,247,236,152,30:6>>,
unix_ts => {millisecond,1728395703230}}}}
```
For more detailed information on available functions and options, please refer
to the module documentation.
## Changelog
See [CHANGELOG](https://github.com/eproxus/keysmith/blob/main/CHANGELOG.md) or
the [Releases](https://github.com/eproxus/keysmith/releases) page.
## Code of Conduct
Find this project's code of conduct in
[Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md).
## Contributing
First of all, thank you for contributing with your time and energy.
If you want to request a new feature make sure to
[open a feature request](https://github.com/eproxus/keysmith/issues/new?template=feature_request.yaml)
so we can discuss it first.
Bug reports and questions are also welcome. If you believe you've found a bug,
feel free to [report an issue](https://github.com/eproxus/keysmith/issues/new?template=bug_report.yaml).
If you have a question, search the discussions and issues since it might have
already been answered before. If you can't find an answer, you
can [open a new discussion](https://github.com/eproxus/keysmith/discussions/new/choose).
Contributions will be subject to the MIT License. You will retain the copyright.
For more information check out [CONTRIBUTING.md](CONTRIBUTING.md).
## Security
This project's security policy is made explicit in [SECURITY.md](SECURITY.md).
## Conventions
### Versions
This project adheres to
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
### License
This project uses the [MIT License][license].
[ci]: https://github.com/eproxus/keysmith/actions/workflows/erlang.yml?query=branch%3Amain
[ci-img]: https://img.shields.io/github/actions/workflow/status/eproxus/keysmith/erlang.yml?label=ci
[lint]: https://github.com/eproxus/keysmith/actions/workflows/lint.yml
[lint-img]: https://img.shields.io/github/actions/workflow/status/eproxus/keysmith/lint.yml?label=lint
[hex]: https://hex.pm/packages/keysmith
[hex-img]: https://img.shields.io/hexpm/v/keysmith
[license]: LICENSE.md
[license-img]: https://img.shields.io/hexpm/l/keysmith
[erlang]: https://github.com/eproxus/keysmith/blob/main/.tool-versions
[erlang-img]: https://img.shields.io/badge/erlang-27+-blue.svg?style=flat-square