{"id":30284029,"url":"https://github.com/riipandi/memorable-ids-ex","last_synced_at":"2026-03-12T14:38:57.205Z","repository":{"id":296760286,"uuid":"994393625","full_name":"riipandi/memorable-ids-ex","owner":"riipandi","description":"A flexible library for generating human-readable, memorable identifiers for Elixir.","archived":false,"fork":false,"pushed_at":"2025-06-01T21:41:49.000Z","size":34,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-17T10:58:12.058Z","etag":null,"topics":["hri","human-readable","identifier","ids","memorable","readable"],"latest_commit_sha":null,"homepage":"https://hex.pm/packages/memorable_ids","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/riipandi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-01T20:54:34.000Z","updated_at":"2025-06-02T07:28:14.000Z","dependencies_parsed_at":"2025-06-02T06:45:01.070Z","dependency_job_id":null,"html_url":"https://github.com/riipandi/memorable-ids-ex","commit_stats":null,"previous_names":["riipandi/memorable-ids-ex"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/riipandi/memorable-ids-ex","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/riipandi%2Fmemorable-ids-ex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/riipandi%2Fmemorable-ids-ex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/riipandi%2Fmemorable-ids-ex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/riipandi%2Fmemorable-ids-ex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/riipandi","download_url":"https://codeload.github.com/riipandi/memorable-ids-ex/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/riipandi%2Fmemorable-ids-ex/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30428498,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-12T14:34:45.044Z","status":"ssl_error","status_checked_at":"2026-03-12T14:09:33.793Z","response_time":114,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hri","human-readable","identifier","ids","memorable","readable"],"created_at":"2025-08-16T18:24:44.058Z","updated_at":"2026-03-12T14:38:57.199Z","avatar_url":"https://github.com/riipandi.png","language":"Elixir","funding_links":["https://github.com/sponsors/riipandi"],"categories":[],"sub_categories":[],"readme":"# MemorableIds\n\nA flexible Elixir library for generating human-readable, memorable identifiers.\nUses combinations of adjectives, nouns, verbs, adverbs, and prepositions with optional numeric/custom suffixes.\n\nTypeScript version of this library: [memorable-ids](https://www.npmjs.com/package/memorable-ids)\n\n## Features\n\n- 🎯 **Human-readable** - Generate IDs like `cute-rabbit`, `quick-owl-dance-quietly`, etc\n- 🔧 **Flexible** - 1-5 word components with customizable separators\n- 📊 **Predictable** - Built-in collision analysis and capacity planning\n- 🎲 **Extensible** - Custom suffix generators and vocabulary\n- 📝 **Elixir** - Full type specs and documentation\n- ⚡ **Fast** - High-performance ID generation\n- 🪶 **Lightweight** - Small vocabulary, zero dependencies\n\n## Installation\n\nAdd `memorable_ids` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:memorable_ids, \"~\u003e 0.1.0\"}\n  ]\nend\n```\n\n## Quick Start\n\n```elixir\n# Basic usage - 2 components\nMemorableIds.generate() # \"cute-rabbit\"\n\n# More components for uniqueness\nMemorableIds.generate(%{components: 3}) # \"large-fox-swim\"\n\n# Add numeric suffix for extra capacity\nsuffix_generators = MemorableIds.suffix_generators()\nMemorableIds.generate(%{\n  components: 2, \n  suffix: suffix_generators.number\n}) # \"quick-mouse-042\"\n\n# Custom separator\nMemorableIds.generate(%{\n  components: 2, \n  separator: \"_\"\n}) # \"warm_duck\"\n```\n\n## API Reference\n\n### `generate(options \\\\ %{})`\n\nGenerate a memorable ID with customizable options.\n\n**Parameters:**\n- `options.components` (integer, 1-5): Number of word components (default: 2)\n- `options.suffix` (function): Suffix generator function (default: nil)\n- `options.separator` (string): Separator between parts (default: \"-\")\n\n**Returns:** `string` - Generated memorable ID\n\n**Examples:**\n\n```elixir\n# Different component counts\nMemorableIds.generate(%{components: 1}) # \"bright\"\nMemorableIds.generate(%{components: 2}) # \"cute-rabbit\" \nMemorableIds.generate(%{components: 3}) # \"large-fox-swim\"\nMemorableIds.generate(%{components: 4}) # \"happy-owl-dance-quietly\"\nMemorableIds.generate(%{components: 5}) # \"clever-fox-run-quickly-through\"\n\n# With suffixes\nsuffix_generators = MemorableIds.suffix_generators()\nMemorableIds.generate(%{\n  components: 2, \n  suffix: suffix_generators.number\n}) # \"safe-rabbit-042\"\n\nMemorableIds.generate(%{\n  components: 2, \n  suffix: suffix_generators.hex\n}) # \"bright-owl-a7\"\n\n# Custom separators\nMemorableIds.generate(%{separator: \"_\"}) # \"warm_duck\"\nMemorableIds.generate(%{separator: \".\"}) # \"cute.rabbit\"\n```\n\n### `parse(id, separator \\\\ \"-\")`\n\nParse a memorable ID back to its components.\n\n**Parameters:**\n- `id` (string): The memorable ID to parse\n- `separator` (string): Separator used (default: \"-\")\n\n**Returns:** `map` - Map with `components` list and `suffix` string\n\n**Examples:**\n\n```elixir\nMemorableIds.parse(\"cute-rabbit-042\")\n# %{components: [\"cute\", \"rabbit\"], suffix: \"042\"}\n\nMemorableIds.parse(\"large-fox-swim\")\n# %{components: [\"large\", \"fox\", \"swim\"], suffix: nil}\n\nMemorableIds.parse(\"warm_duck_123\", \"_\")\n# %{components: [\"warm\", \"duck\"], suffix: \"123\"}\n```\n\n### Suffix Generators\n\nPre-built suffix generators for common use cases:\n\n```elixir\nsuffix_generators = MemorableIds.suffix_generators()\n\n# 3-digit number (000-999) - adds 1,000x multiplier\nsuffix_generators.number.() # \"042\"\n\n# 4-digit number (0000-9999) - adds 10,000x multiplier  \nsuffix_generators.number4.() # \"1337\"\n\n# 2-digit hex (00-ff) - adds 256x multiplier\nsuffix_generators.hex.() # \"a7\"\n\n# Timestamp (last 4 digits) - time-based\nsuffix_generators.timestamp.() # \"8429\"\n\n# Single letter (a-z) - adds 26x multiplier\nsuffix_generators.letter.() # \"k\"\n```\n\n### Analysis Functions\n\nPlan capacity and understand collision probabilities:\n\n```elixir\n# Calculate total possible combinations\nMemorableIds.calculate_combinations(2) # 5,304 (2 components)\nMemorableIds.calculate_combinations(2, 1000) # 5,304,000 (2 components + 3-digit suffix)\nMemorableIds.calculate_combinations(3) # 212,160 (3 components)\n\n# Calculate collision probability (Birthday Paradox)\nMemorableIds.calculate_collision_probability(5304, 100) # 0.0093 (0.93% chance)\n\n# Get comprehensive analysis\nMemorableIds.get_collision_analysis(2)\n# %{\n#   total_combinations: 5304,\n#   scenarios: [\n#     %{ids: 50, probability: 0.0023, percentage: \"0.23%\"},\n#     %{ids: 100, probability: 0.0093, percentage: \"0.93%\"},\n#     %{ids: 200, probability: 0.037, percentage: \"3.7%\"},\n#     %{ids: 500, probability: 0.218, percentage: \"21.8%\"}\n#   ]\n# }\n```\n\n## Capacity \u0026 Collision Analysis\n\n### Total Combinations by Component Count\n\n| Components | Total IDs   | Example                          |\n|------------|-------------|----------------------------------|\n| 1          | 78          | `bright`                         |\n| 2          | 5,304       | `cute-rabbit`                    |\n| 3          | 212,160     | `large-fox-swim`                 |\n| 4          | 5,728,320   | `happy-owl-dance-quietly`        |\n| 5          | 148,936,320 | `clever-fox-run-quickly-through` |\n\n### Suffix Multipliers\n\n| Suffix Type    | Multiplier | Example            |\n|----------------|------------|--------------------|\n| 3-digit number | ×1,000     | `cute-rabbit-042`  |\n| 4-digit number | ×10,000    | `cute-rabbit-1337` |\n| 2-digit hex    | ×256       | `cute-rabbit-a7`   |\n| Single letter  | ×26        | `cute-rabbit-k`    |\n\n### Collision Probability Examples\n\n**For 2 components (5,304 total combinations):**\n- 50 IDs: 0.23% collision chance\n- 100 IDs: 0.93% collision chance  \n- 200 IDs: 3.7% collision chance\n- 500 IDs: 21.8% collision chance\n\n**For 3 components (212,160 total combinations):**\n- 1,000 IDs: 0.002% collision chance\n- 5,000 IDs: 0.059% collision chance\n- 10,000 IDs: 0.235% collision chance\n- 20,000 IDs: 0.94% collision chance\n\n**For 2 components + 3-digit suffix (5,304,000 total combinations):**\n- 10,000 IDs: 0.0009% collision chance\n- 50,000 IDs: 0.023% collision chance\n- 100,000 IDs: 0.094% collision chance\n- 500,000 IDs: 2.35% collision chance\n\n## Configuration Recommendations\n\nChoose the right configuration based on your expected ID volume:\n\n| Use Case                  | Recommendation          | Capacity | Example               |\n|---------------------------|-------------------------|----------|-----------------------|\n| Small apps (\u003c1K IDs)      | 2 components            | 5,304    | `cute-rabbit`         |\n| Medium apps (1K-50K IDs)  | 3 components            | 212,160  | `large-fox-swim`      |\n| Large apps (50K-500K IDs) | 2-3 components + suffix | 5M+      | `cute-rabbit-042`     |\n| Enterprise (500K+ IDs)    | 4+ components + suffix  | 50M+     | `happy-owl-dance-042` |\n\n## Advanced Usage\n\n### Custom Suffix Generators\n\nCreate your own suffix logic:\n\n```elixir\n# Custom timestamp suffix\ntimestamp_suffix = fn -\u003e\n  DateTime.utc_now()\n  |\u003e DateTime.to_unix(:millisecond)\n  |\u003e Integer.to_string()\n  |\u003e String.slice(-6..-1) # Last 6 digits\nend\n\n# Custom random string\nrandom_string = fn -\u003e\n  :crypto.strong_rand_bytes(3)\n  |\u003e Base.encode32(case: :lower, padding: false)\n  |\u003e String.slice(0..2) # 3 random chars\nend\n\n# Use custom suffix\nMemorableIds.generate(%{\n  components: 2, \n  suffix: timestamp_suffix\n}) # \"cute-rabbit-123456\"\n```\n\n### Dictionary Access\n\nAccess the underlying word collections:\n\n```elixir\nalias MemorableIds.Dictionary\n\nIO.puts length(Dictionary.adjectives()) # 78\nIO.puts length(Dictionary.nouns()) # 68\nIO.puts length(Dictionary.verbs()) # 40\nIO.puts length(Dictionary.adverbs()) # 27\nIO.puts length(Dictionary.prepositions()) # 26\n\n# Access individual words\nIO.puts hd(Dictionary.adjectives()) # \"cute\"\nIO.puts hd(Dictionary.nouns()) # \"rabbit\"\n\n# Get statistics\nstats = Dictionary.stats()\nIO.inspect stats\n# %{adjectives: 78, nouns: 68, verbs: 40, adverbs: 27, prepositions: 26}\n```\n\n### Error Handling\n\n```elixir\ntry do\n  MemorableIds.generate(%{components: 6}) # Invalid: max is 5\nrescue\n  ArgumentError -\u003e IO.puts \"Components must be between 1 and 5\"\nend\n```\n\n## Performance Considerations\n\n### Generation Speed\n- **High-performance** ID generation suitable for production use\n- No significant performance difference between component counts\n- Suffix generation adds minimal overhead\n\n### Randomness Quality\n- Uses Erlang's `:rand` module - suitable for non-cryptographic purposes\n- For cryptographic security, replace with `:crypto.strong_rand_bytes/1`\n- Distribution is uniform across all vocabulary combinations\n\n## Security Notes\n\n⚠️ **Important Security Information:**\n\n- IDs are **NOT cryptographically secure**\n- Predictable if random seed is known\n- **Suitable for**: user-friendly identifiers, temporary IDs, non-sensitive references\n- **NOT suitable for**: session tokens, passwords, security-critical identifiers\n\n## Development\n\n### Running Tests\n\n```bash\n# Run all tests\nmix test\n\n# Run with coverage\nmix test --cover\n\n# Run specific test file\nmix test test/memorable_ids_test.exs\n\n# Run doctests only\nmix test --only doctest\n```\n\n### Building Documentation\n\n```bash\n# Generate documentation\nmix docs\n\n# View documentation\nopen doc/index.html\n```\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n### Development Setup\n\n```bash\n# Clone repository\ngit clone \u003crepository-url\u003e\ncd memorable_ids\n\n# Install dependencies\nmix deps.get\n\n# Run tests\nmix test\n\n# Check formatting\nmix format --check-formatted\n\n# Run static analysis\nmix credo\n```\n\n### Adding Custom Vocabulary\n\n1. Extend existing lists in `lib/dictionary.ex`\n2. Ensure words are URL-safe and human-readable\n3. Avoid duplicates to maintain combination count accuracy\n4. Update tests and documentation\n5. Run `mix test` to verify changes\n\n### Documentation\n\nDocumentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)\nand published on [HexDocs](https://hexdocs.pm).\n\nOnce published, the docs can be found at \u003chttps://hexdocs.pm/memorable_ids\u003e.\n\n## License\n\nThis project is open-sourced software licensed under the [MIT license](https://choosealicense.com/licenses/mit/).\n\nCopyrights in this project are retained by their contributors.\nSee the [license file](./LICENSE) for more information.\n\n---\n\n\u003csub\u003e🤫 Psst! If you like my work you can support me via [GitHub sponsors](https://github.com/sponsors/riipandi).\u003c/sub\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Friipandi%2Fmemorable-ids-ex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Friipandi%2Fmemorable-ids-ex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Friipandi%2Fmemorable-ids-ex/lists"}