human-ids 1.0.14 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Dictionary management module for human-ids.
3
+ * Handles built-in dictionaries and caching of resolved word arrays.
4
+ * @module dictionaries
5
+ * @internal
6
+ */
7
+ import type { Dictionary } from '../index';
8
+ /**
9
+ * Dictionary with word lists converted to arrays for efficient random selection.
10
+ * @internal
11
+ */
12
+ export interface ResolvedDictionary {
13
+ /** Array of adjective words */
14
+ adjectives: string[];
15
+ /** Array of color words */
16
+ colors: string[];
17
+ /** Array of noun words */
18
+ nouns: string[];
19
+ }
20
+ /**
21
+ * Built-in dictionaries indexed by language code.
22
+ * Currently supports 'en' (English) and 'es' (Spanish).
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * import { dictionaries } from 'human-ids';
27
+ *
28
+ * // Access English adjectives
29
+ * const englishAdjectives = Object.keys(dictionaries.en.adjectives);
30
+ *
31
+ * // Check available languages
32
+ * const languages = Object.keys(dictionaries); // ['en', 'es']
33
+ * ```
34
+ */
35
+ declare const dictionaries: Record<string, Dictionary>;
36
+ /**
37
+ * Converts a Dictionary (with Record objects) to a ResolvedDictionary (with arrays).
38
+ * Results are cached for performance.
39
+ *
40
+ * @param dict - Dictionary to resolve
41
+ * @returns Dictionary with word lists as arrays
42
+ * @internal
43
+ */
44
+ declare function resolveDictionary(dict: Dictionary): ResolvedDictionary;
45
+ export { dictionaries, resolveDictionary };
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ /**
3
+ * Dictionary management module for human-ids.
4
+ * Handles built-in dictionaries and caching of resolved word arrays.
5
+ * @module dictionaries
6
+ * @internal
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.dictionaries = void 0;
10
+ exports.resolveDictionary = resolveDictionary;
11
+ const en_1 = require("./en");
12
+ const es_1 = require("./es");
13
+ /**
14
+ * Built-in dictionaries indexed by language code.
15
+ * Currently supports 'en' (English) and 'es' (Spanish).
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * import { dictionaries } from 'human-ids';
20
+ *
21
+ * // Access English adjectives
22
+ * const englishAdjectives = Object.keys(dictionaries.en.adjectives);
23
+ *
24
+ * // Check available languages
25
+ * const languages = Object.keys(dictionaries); // ['en', 'es']
26
+ * ```
27
+ */
28
+ const dictionaries = {
29
+ en: en_1.en,
30
+ es: es_1.es
31
+ };
32
+ exports.dictionaries = dictionaries;
33
+ /**
34
+ * Cache for resolved dictionaries to avoid repeated Object.values() calls.
35
+ * @internal
36
+ */
37
+ const resolvedCache = new Map();
38
+ /**
39
+ * Converts a Dictionary (with Record objects) to a ResolvedDictionary (with arrays).
40
+ * Results are cached for performance.
41
+ *
42
+ * @param dict - Dictionary to resolve
43
+ * @returns Dictionary with word lists as arrays
44
+ * @internal
45
+ */
46
+ function resolveDictionary(dict) {
47
+ let resolved = resolvedCache.get(dict);
48
+ if (!resolved) {
49
+ resolved = {
50
+ adjectives: Object.values(dict.adjectives),
51
+ colors: Object.values(dict.colors),
52
+ nouns: Object.values(dict.nouns),
53
+ };
54
+ resolvedCache.set(dict, resolved);
55
+ }
56
+ return resolved;
57
+ }
@@ -0,0 +1,246 @@
1
+ /**
2
+ * Human IDs - A library to generate human-readable identifiers
3
+ * @packageDocumentation
4
+ * @module human-ids
5
+ */
6
+ import { dictionaries } from './dictionaries';
7
+ /**
8
+ * Dictionary containing word lists for ID generation.
9
+ * Each property maps word keys to their display values.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * const customDictionary: Dictionary = {
14
+ * adjectives: { happy: 'happy', bright: 'bright' },
15
+ * colors: { red: 'red', blue: 'blue' },
16
+ * nouns: { cat: 'cat', dog: 'dog' }
17
+ * };
18
+ * ```
19
+ */
20
+ export interface Dictionary {
21
+ /** Map of adjective keys to their display values */
22
+ adjectives: Record<string, string>;
23
+ /** Map of color keys to their display values */
24
+ colors: Record<string, string>;
25
+ /** Map of noun keys to their display values */
26
+ nouns: Record<string, string>;
27
+ }
28
+ /**
29
+ * Object containing the individual parts of a generated ID.
30
+ * Returned when `asObject: true` is set in the settings.
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * const parts: IdParts = {
35
+ * adjective: 'happy',
36
+ * color: 'blue',
37
+ * noun: 'cat',
38
+ * number1: '1234'
39
+ * };
40
+ * ```
41
+ */
42
+ export interface IdParts {
43
+ /** The adjective component (if enabled) */
44
+ adjective?: string;
45
+ /** The color component (if enabled) */
46
+ color?: string;
47
+ /** The noun component (if enabled) */
48
+ noun?: string;
49
+ /** Additional properties for number components (number1, number2, etc.) */
50
+ [key: string]: string | undefined;
51
+ }
52
+ /**
53
+ * Configuration options for the number component(s) of generated IDs.
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * // Generate IDs with numbers between 1000-9999, zero-padded
58
+ * const numberSettings: NumberSettings = {
59
+ * min: 1000,
60
+ * max: 9999,
61
+ * sets: 1,
62
+ * completeWithZeros: true
63
+ * };
64
+ * ```
65
+ */
66
+ export interface NumberSettings {
67
+ /**
68
+ * Minimum value for random numbers (inclusive)
69
+ * @default 0
70
+ */
71
+ min?: number;
72
+ /**
73
+ * Maximum value for random numbers (inclusive)
74
+ * @default 9999
75
+ */
76
+ max?: number;
77
+ /**
78
+ * Number of separate number components to include
79
+ * @default 1
80
+ * @example
81
+ * // With sets: 2, generates: "happy-blue-cat-1234-5678"
82
+ */
83
+ sets?: number;
84
+ /**
85
+ * Whether to pad numbers with leading zeros to match max length
86
+ * @default false
87
+ * @example
88
+ * // With max: 9999 and completeWithZeros: true
89
+ * // Number 42 becomes "0042"
90
+ */
91
+ completeWithZeros?: boolean;
92
+ }
93
+ /**
94
+ * Maps language codes to their component ordering.
95
+ * Defines the order in which ID parts appear for each language.
96
+ *
97
+ * @example
98
+ * ```typescript
99
+ * const semantics: SemanticsMap = {
100
+ * en: ['adjective', 'color', 'noun', 'number'], // happy-blue-cat-123
101
+ * es: ['noun', 'color', 'adjective', 'number'] // gato-azul-feliz-123
102
+ * };
103
+ * ```
104
+ */
105
+ export interface SemanticsMap {
106
+ [lang: string]: Array<'noun' | 'adjective' | 'color' | 'number'>;
107
+ }
108
+ /**
109
+ * Configuration options for the ID generator.
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * // Basic usage with Spanish
114
+ * const settings: IdGeneratorSettings = {
115
+ * lang: 'es',
116
+ * separator: '_'
117
+ * };
118
+ *
119
+ * // Advanced usage with custom dictionary
120
+ * const advancedSettings: IdGeneratorSettings = {
121
+ * lang: 'en',
122
+ * adjective: true,
123
+ * color: false, // Exclude colors
124
+ * noun: true,
125
+ * number: { min: 100, max: 999 },
126
+ * dictionary: {
127
+ * adjectives: { cool: 'cool', awesome: 'awesome' }
128
+ * }
129
+ * };
130
+ * ```
131
+ */
132
+ export interface IdGeneratorSettings {
133
+ /**
134
+ * Language code for built-in dictionaries ('en' or 'es').
135
+ * Also accepts locale codes like 'en-US' (falls back to base language).
136
+ * @default 'en'
137
+ */
138
+ lang?: string;
139
+ /**
140
+ * Whether to include an adjective in the ID
141
+ * @default true
142
+ */
143
+ adjective?: boolean;
144
+ /**
145
+ * Whether to include a color in the ID
146
+ * @default true
147
+ */
148
+ color?: boolean;
149
+ /**
150
+ * Whether to include a noun in the ID
151
+ * @default true
152
+ */
153
+ noun?: boolean;
154
+ /**
155
+ * Whether to randomize the order of components
156
+ * @default false
157
+ */
158
+ randomOrder?: boolean;
159
+ /**
160
+ * Character(s) used to separate ID components
161
+ * @default '-'
162
+ */
163
+ separator?: string;
164
+ /**
165
+ * Return an object with individual parts instead of a string
166
+ * @default false
167
+ */
168
+ asObject?: boolean;
169
+ /**
170
+ * Custom component ordering per language.
171
+ * @default { en: ['adjective', 'color', 'noun', 'number'], es: ['noun', 'color', 'adjective', 'number'] }
172
+ */
173
+ semantics?: SemanticsMap;
174
+ /**
175
+ * Configuration for the number component(s)
176
+ * @default { min: 0, max: 9999, sets: 1, completeWithZeros: false }
177
+ */
178
+ number?: NumberSettings;
179
+ /**
180
+ * Custom dictionary to use (can partially override built-in words)
181
+ */
182
+ dictionary?: Partial<Dictionary>;
183
+ }
184
+ /**
185
+ * Generates a human-readable ID by combining adjectives, colors, nouns, and numbers.
186
+ *
187
+ * @param settings - Configuration options (with asObject: true)
188
+ * @returns Object containing individual ID components
189
+ *
190
+ * @example
191
+ * ```typescript
192
+ * // Get ID as object
193
+ * const parts = generateId({ asObject: true });
194
+ * // { adjective: 'happy', color: 'blue', noun: 'cat', number1: '1234' }
195
+ * ```
196
+ */
197
+ declare function generateId(settings?: IdGeneratorSettings & {
198
+ asObject: true;
199
+ }): IdParts;
200
+ /**
201
+ * Generates a human-readable ID by combining adjectives, colors, nouns, and numbers.
202
+ *
203
+ * @param settings - Configuration options
204
+ * @returns Human-readable ID string
205
+ *
206
+ * @example
207
+ * ```typescript
208
+ * // Basic usage - returns string like "happy-blue-cat-1234"
209
+ * const id = generateId();
210
+ *
211
+ * // Spanish language
212
+ * const spanishId = generateId({ lang: 'es' });
213
+ * // "gato-azul-feliz-5678"
214
+ *
215
+ * // Custom separator
216
+ * const underscoreId = generateId({ separator: '_' });
217
+ * // "happy_blue_cat_9012"
218
+ *
219
+ * // Without colors
220
+ * const noColorId = generateId({ color: false });
221
+ * // "happy-cat-3456"
222
+ *
223
+ * // Custom number range
224
+ * const customNumberId = generateId({
225
+ * number: { min: 100, max: 999, completeWithZeros: true }
226
+ * });
227
+ * // "happy-blue-cat-042"
228
+ *
229
+ * // Multiple number sets
230
+ * const multiNumberId = generateId({ number: { sets: 2 } });
231
+ * // "happy-blue-cat-1234-5678"
232
+ *
233
+ * // Random component order
234
+ * const randomOrderId = generateId({ randomOrder: true });
235
+ * // "1234-cat-happy-blue" (random order each time)
236
+ *
237
+ * // Custom dictionary (partial override)
238
+ * const customId = generateId({
239
+ * dictionary: {
240
+ * adjectives: { cool: 'cool', awesome: 'awesome' }
241
+ * }
242
+ * });
243
+ * ```
244
+ */
245
+ declare function generateId(settings?: IdGeneratorSettings): string;
246
+ export { generateId, dictionaries };
package/dist/index.js ADDED
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ /**
3
+ * Human IDs - A library to generate human-readable identifiers
4
+ * @packageDocumentation
5
+ * @module human-ids
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.dictionaries = void 0;
9
+ exports.generateId = generateId;
10
+ const dictionaries_1 = require("./dictionaries");
11
+ Object.defineProperty(exports, "dictionaries", { enumerable: true, get: function () { return dictionaries_1.dictionaries; } });
12
+ /**
13
+ * Default settings applied when options are not specified.
14
+ * @internal
15
+ */
16
+ const defaultSettings = {
17
+ lang: 'en',
18
+ adjective: true,
19
+ color: true,
20
+ noun: true,
21
+ randomOrder: false,
22
+ separator: '-',
23
+ asObject: false,
24
+ semantics: {
25
+ es: ['noun', 'color', 'adjective', 'number'],
26
+ en: ['adjective', 'color', 'noun', 'number'],
27
+ },
28
+ number: {
29
+ min: 0,
30
+ max: 9999,
31
+ sets: 1,
32
+ completeWithZeros: false,
33
+ },
34
+ };
35
+ /**
36
+ * Generates a random integer between min and max (inclusive).
37
+ * @param min - Minimum value (inclusive)
38
+ * @param max - Maximum value (inclusive)
39
+ * @returns Random integer in the range [min, max]
40
+ * @internal
41
+ */
42
+ function getRandomNumber(min, max) {
43
+ return Math.floor(Math.random() * (max - min + 1)) + min;
44
+ }
45
+ /**
46
+ * Picks a random element from an array.
47
+ * @param arr - Array to pick from
48
+ * @returns Random element from the array
49
+ * @internal
50
+ */
51
+ function pickRandom(arr) {
52
+ return arr[Math.floor(Math.random() * arr.length)];
53
+ }
54
+ /**
55
+ * Resolves a language code to a supported language.
56
+ * Supports full locale codes (e.g., 'en-US' resolves to 'en').
57
+ * Falls back to 'en' if language is not supported.
58
+ * @param lang - Language code to resolve
59
+ * @returns Resolved language code ('en' or 'es')
60
+ * @internal
61
+ */
62
+ function resolveLang(lang) {
63
+ if (dictionaries_1.dictionaries[lang])
64
+ return lang;
65
+ const base = lang.split('-')[0];
66
+ if (dictionaries_1.dictionaries[base])
67
+ return base;
68
+ return 'en';
69
+ }
70
+ function generateId(userSettings = {}) {
71
+ var _a, _b, _c;
72
+ const settings = { ...defaultSettings, ...userSettings };
73
+ const lang = resolveLang(settings.lang);
74
+ const numberMin = settings.number && settings.number.min !== undefined ? settings.number.min : 0;
75
+ const numberMax = settings.number && settings.number.max !== undefined ? settings.number.max : 999;
76
+ const numberSets = (settings.number && settings.number.sets) || 1;
77
+ const completeWithZeros = (settings.number && settings.number.completeWithZeros) || false;
78
+ // Resolve dictionary arrays (cached for built-in dictionaries)
79
+ const customDict = settings.dictionary;
80
+ const builtinDict = dictionaries_1.dictionaries[lang];
81
+ const resolved = (0, dictionaries_1.resolveDictionary)(customDict
82
+ ? {
83
+ adjectives: (_a = customDict.adjectives) !== null && _a !== void 0 ? _a : builtinDict.adjectives,
84
+ colors: (_b = customDict.colors) !== null && _b !== void 0 ? _b : builtinDict.colors,
85
+ nouns: (_c = customDict.nouns) !== null && _c !== void 0 ? _c : builtinDict.nouns,
86
+ }
87
+ : builtinDict);
88
+ const parts = {};
89
+ if (settings.adjective) {
90
+ parts.adjective = pickRandom(resolved.adjectives);
91
+ }
92
+ if (settings.color) {
93
+ parts.color = pickRandom(resolved.colors);
94
+ }
95
+ if (settings.noun) {
96
+ parts.noun = pickRandom(resolved.nouns);
97
+ }
98
+ const maxNumberLength = completeWithZeros ? numberMax.toString().length : 0;
99
+ for (let i = 0; i < numberSets; i++) {
100
+ const num = getRandomNumber(numberMin, numberMax);
101
+ parts[`number${i + 1}`] = completeWithZeros
102
+ ? num.toString().padStart(maxNumberLength, '0')
103
+ : num.toString();
104
+ }
105
+ if (settings.randomOrder) {
106
+ const keys = Object.keys(parts);
107
+ const shuffledKeys = keys.sort(() => Math.random() - 0.5);
108
+ const shuffledParts = [];
109
+ for (const key of shuffledKeys) {
110
+ shuffledParts.push(parts[key]);
111
+ }
112
+ return shuffledParts.join(settings.separator);
113
+ }
114
+ if (settings.asObject) {
115
+ return parts;
116
+ }
117
+ const semantics = (settings.semantics && settings.semantics[lang]) || settings.semantics.en;
118
+ const result = semantics.map((key) => {
119
+ if (key !== 'number')
120
+ return parts[key];
121
+ // Collect all number parts directly instead of filtering with isNaN
122
+ const numberParts = [];
123
+ for (let i = 1; i <= numberSets; i++) {
124
+ numberParts.push(parts[`number${i}`]);
125
+ }
126
+ return numberParts.join('-');
127
+ });
128
+ return result.join(settings.separator);
129
+ }
130
+ // CJS backwards compatibility
131
+ // Allows: const generateId = require('human-ids')
132
+ // And: const { generateId, dictionaries } = require('human-ids')
133
+ module.exports = generateId;
134
+ module.exports.generateId = generateId;
135
+ module.exports.dictionaries = dictionaries_1.dictionaries;
package/package.json CHANGED
@@ -1,28 +1,55 @@
1
1
  {
2
2
  "name": "human-ids",
3
- "version": "1.0.14",
4
- "description": "A library to generate human readable IDs",
5
- "main": "index.js",
3
+ "version": "1.2.0",
4
+ "description": "A zero-dependency TypeScript library to generate human-readable IDs. Supports English and Spanish with ~209 billion unique combinations.",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist"
9
+ ],
6
10
  "scripts": {
11
+ "build": "tsc",
12
+ "prepublishOnly": "npm run build",
7
13
  "test": "jest --reporters=default --reporters=jest-html-reporter"
8
14
  },
9
15
  "keywords": [
10
- "readable",
16
+ "human-readable",
17
+ "id",
11
18
  "ids",
12
- "humans",
13
- "for-humans",
19
+ "identifier",
20
+ "generator",
21
+ "unique",
22
+ "uuid-alternative",
23
+ "readable-id",
24
+ "friendly-id",
14
25
  "human-ids",
15
- "simple",
16
- "simple-ids"
26
+ "typescript",
27
+ "english",
28
+ "spanish",
29
+ "i18n"
17
30
  ],
18
31
  "author": "JC Mujica",
19
32
  "license": "ISC",
20
33
  "devDependencies": {
34
+ "@types/jest": "^30.0.0",
21
35
  "jest": "^29.6.1",
22
- "jest-html-reporter": "^3.10.1"
36
+ "jest-html-reporter": "^3.10.1",
37
+ "ts-jest": "^29.4.6",
38
+ "typescript": "^5.9.3"
39
+ },
40
+ "jest": {
41
+ "preset": "ts-jest",
42
+ "testEnvironment": "node"
23
43
  },
24
44
  "repository": {
25
45
  "type": "git",
26
- "url": "https://github.com/jcmujica/human-ids"
46
+ "url": "git+https://github.com/jcmujica/human-ids.git"
47
+ },
48
+ "bugs": {
49
+ "url": "https://github.com/jcmujica/human-ids/issues"
50
+ },
51
+ "homepage": "https://github.com/jcmujica/human-ids#readme",
52
+ "engines": {
53
+ "node": ">=14.0.0"
27
54
  }
28
- }
55
+ }
package/CHANGELOG.md DELETED
@@ -1,72 +0,0 @@
1
- # Changelog
2
-
3
- All notable changes to this project will be documented in this file.
4
-
5
- ## [Unreleased]
6
-
7
- ## [1.0.14] - 2023-07-19
8
-
9
- ### Added
10
- - Added semantics support to be passed as user settings to oder words according to the language
11
- - Added default semantics for english and spanish languages
12
-
13
- ## [1.0.13] - 2023-07-10
14
-
15
- ### Added
16
- - Added asObject setting to return an object with the words
17
- ## [1.0.12] - 2023-07-07
18
-
19
- ### Fixed
20
- - Fixed bug with undefined disctionaries
21
- ## [1.0.11] - 2023-07-07
22
-
23
- ### Fixed
24
- - Fixed bug with custom dictionaries
25
- ## [1.0.10] - 2023-07-07
26
-
27
- ### Added
28
- - Added separator customization
29
- - Added random ordering for segments
30
- - Added support for custom dictionary
31
- ## [1.0.9] - 2023-07-07
32
-
33
- ### Changed
34
- - Changed removed init console.log
35
- ## [1.0.8] - 2023-07-07
36
-
37
- ### Changed
38
- - Changed README.md to correctly display usage information
39
- ## [1.0.7] - 2023-07-07
40
-
41
- ### Changed
42
- - Changed README.md to correctly display usage information
43
- ## [1.0.6] - 2023-07-07
44
-
45
- ### Changed
46
- - Changed README.md to correctly display usage information
47
- ## [1.0.5] - 2023-07-07
48
-
49
- ### Remove
50
- - Removed tests file
51
- ## [1.0.4] - 2023-07-07
52
-
53
- ### Fixed
54
- - Fixed module definition
55
- ## [1.0.3] - 2023-07-07
56
-
57
- ### Added
58
- - Added default settings
59
- ## [1.0.2] - 2023-07-07
60
-
61
- ### Changed
62
- - Refactor into function
63
- ## [1.0.1] - 2023-07-07
64
-
65
- ### Added
66
- - Added Changelog
67
- - Added gitignore and git link in package.json
68
-
69
- ## [1.0.0] - 2023-07-07
70
-
71
- ### Added
72
- - A library to generate human-readable IDs.