Skip to content

A subdomain-safe name generator

Notifications You must be signed in to change notification settings

jsonmaur/namor.js

Repository files navigation

Namor.js

Namor.js is a name generator for Node that creates random, url-friendly names. This comes in handy if you need to generate unique subdomains like many PaaS/SaaS providers do, or unique names for anything else. Supports subdomain validation with reserved names, custom dictionaries and reserved word lists, alternate dictionaries, and more.

See a demo here. Also available for Elixir.

Please Note: Generated names are not always guaranteed to be unique. To reduce the chances of collision, you can increase the length of the trailing number (see here for collision stats). Always be sure to check your database before assuming a generated value is unique.

Installation

$ npm install namor

Getting Started

import namor from "namor"

namor.generate()
// "sandwich-invent"

namor.generate({ salt: 5 })
// "sandwich-invent-s86uo"

namor.generate({ words: 3, dictionary: "rugged" })
// "savage-whiskey-stain"

Collision Stats

The following stats give you the total number of permutations based on the word count (without a salt), and can help you make a decision on how long to make your salt. This data is based on the number of words we currently have in our dictionary files.

default dictionary
  • 1-word combinations: 7,948
  • 2-word combinations: 11,386,875
  • 3-word combinations: 12,382,548,750
  • 4-word combinations: 23,217,278,906,250
rugged dictionary
  • 1-word combinations: 735
  • 2-word combinations: 127,400
  • 3-word combinations: 14,138,880
  • 4-word combinations: 3,958,886,400

API

.generate (options:Object)

Generates a new name, in all its glory.

  • options

    • words default: 2 The number of words to include in the generated name. Must be a positive integer no higher than 4.

    • separator default: "-" The character to use between words when generating a name.

    • salt default: 0 The number of characters in the trailing salt. Must be a positive integer.

    • saltType default: "mixed" The type of characters to use for the trailing salt. Can be numbers, letters, or mixed.

    • dictionary default: "default" The dictionary to use. Can be set to "default", "rugged", or a custom dictionary using getDict.

.valid_subdomain (name:String, options:Object)

Checks whether a string is valid for use as a subdomain including special characters, length (max of 63 characters), and checking against a list of reserved subdomains.

  • name - The name to check.

  • options

    • reserved default: false Whether to check the name against the reserved word list, which is a predefined set of values that shouldn't be offered as subdomains. This can also be set to an array of strings for a custom reserved word list (consider using getDictFile).

.getDict (name:String, basePath:String)

Reads word lists from a base folder and returns a parsed dictionary object. A dictionary folder is expected to be a directory containing three files: adjectives.txt, nouns.txt, and verbs.txt. Each file should have one word per line with no duplicate words. If basePath is not defined, it will look for the dictionary in Namor's internal dictionary folder. Use this function to define a custom dictionary like so:

 ┌── dictionaries/
 │ ┌── custom/
 │ │ ┌── adjectives.txt
 │ │ ├── nouns.txt
 │ │ └── verbs.txt
const dictionaryPath = path.resolve(__dirname, "dictionaries")
const dictionary = namor.getDict("custom", dictionaryPath)

namor.generate({ dictionary: dictionary })

.getDictFile (name:String, basePath:String)

Reads a single word file with one word per line, and returns the words trimmed and parsed into an array. If basePath is not defined, it will look for the dictionary in Namor's internal dictionary folder. Use this function to define a custom reserved word list like so:

 ┌── dictionaries/
 │ ┌── reserved.txt
const dictionaryPath = path.resolve(__dirname, "dictionaries")
const reservedWords = namor.getDictFile("reserved.txt", dictionaryPath)

namor.valid_subdomain("value", { reserved: reservedWords })

A note on custom dictionaries

Reading large word lists can be slow, so it's very highly recommended to only call getDict and getDictFile once when the application starts.