human-ids 1.0.14 → 2.0.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.
- package/README.md +178 -112
- package/dist/cjs/dictionaries/en.d.ts +6 -0
- package/dist/cjs/dictionaries/en.js +973 -0
- package/dist/cjs/dictionaries/es.d.ts +6 -0
- package/dist/cjs/dictionaries/es.js +973 -0
- package/dist/cjs/dictionaries/index.d.ts +18 -0
- package/dist/cjs/dictionaries/index.js +25 -0
- package/dist/cjs/index.d.ts +246 -0
- package/dist/cjs/index.js +127 -0
- package/dist/esm/dictionaries/en.d.ts +6 -0
- package/dist/esm/dictionaries/en.js +970 -0
- package/dist/esm/dictionaries/es.d.ts +6 -0
- package/dist/esm/dictionaries/es.js +970 -0
- package/dist/esm/dictionaries/index.d.ts +18 -0
- package/dist/esm/dictionaries/index.js +22 -0
- package/dist/esm/index.d.ts +246 -0
- package/dist/esm/index.js +123 -0
- package/dist/esm/package.json +1 -0
- package/package.json +51 -11
- package/CHANGELOG.md +0 -72
- package/dictionaries/en.js +0 -224
- package/dictionaries/es.js +0 -221
- package/dictionaries/index.js +0 -9
- package/index.d.ts +0 -34
- package/index.js +0 -123
- package/tests/index.test.js +0 -82
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Dictionary } from '../index';
|
|
2
|
+
/**
|
|
3
|
+
* Built-in dictionaries indexed by language code.
|
|
4
|
+
* Currently supports 'en' (English) and 'es' (Spanish).
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { dictionaries } from 'human-ids';
|
|
9
|
+
*
|
|
10
|
+
* // Access English adjectives
|
|
11
|
+
* const englishAdjectives = dictionaries.en.adjectives;
|
|
12
|
+
*
|
|
13
|
+
* // Check available languages
|
|
14
|
+
* const languages = Object.keys(dictionaries); // ['en', 'es']
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
declare const dictionaries: Record<string, Dictionary>;
|
|
18
|
+
export { dictionaries };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.dictionaries = void 0;
|
|
4
|
+
const en_1 = require("./en");
|
|
5
|
+
const es_1 = require("./es");
|
|
6
|
+
/**
|
|
7
|
+
* Built-in dictionaries indexed by language code.
|
|
8
|
+
* Currently supports 'en' (English) and 'es' (Spanish).
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { dictionaries } from 'human-ids';
|
|
13
|
+
*
|
|
14
|
+
* // Access English adjectives
|
|
15
|
+
* const englishAdjectives = dictionaries.en.adjectives;
|
|
16
|
+
*
|
|
17
|
+
* // Check available languages
|
|
18
|
+
* const languages = Object.keys(dictionaries); // ['en', 'es']
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
const dictionaries = {
|
|
22
|
+
en: en_1.en,
|
|
23
|
+
es: es_1.es,
|
|
24
|
+
};
|
|
25
|
+
exports.dictionaries = dictionaries;
|
|
@@ -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
|
+
/** List of adjective words */
|
|
22
|
+
adjectives: string[];
|
|
23
|
+
/** List of color words */
|
|
24
|
+
colors: string[];
|
|
25
|
+
/** List of noun words */
|
|
26
|
+
nouns: 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 };
|
|
@@ -0,0 +1,127 @@
|
|
|
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
|
+
const settings = { ...defaultSettings, ...userSettings };
|
|
72
|
+
const lang = resolveLang(settings.lang);
|
|
73
|
+
const numberMin = settings.number && settings.number.min !== undefined ? settings.number.min : 0;
|
|
74
|
+
const numberMax = settings.number && settings.number.max !== undefined ? settings.number.max : 999;
|
|
75
|
+
const numberSets = (settings.number && settings.number.sets) || 1;
|
|
76
|
+
const completeWithZeros = (settings.number && settings.number.completeWithZeros) || false;
|
|
77
|
+
const customDict = settings.dictionary;
|
|
78
|
+
const builtinDict = dictionaries_1.dictionaries[lang];
|
|
79
|
+
const resolved = customDict
|
|
80
|
+
? {
|
|
81
|
+
adjectives: customDict.adjectives ? [...new Set(customDict.adjectives)] : builtinDict.adjectives,
|
|
82
|
+
colors: customDict.colors ? [...new Set(customDict.colors)] : builtinDict.colors,
|
|
83
|
+
nouns: customDict.nouns ? [...new Set(customDict.nouns)] : builtinDict.nouns,
|
|
84
|
+
}
|
|
85
|
+
: builtinDict;
|
|
86
|
+
const parts = {};
|
|
87
|
+
if (settings.adjective) {
|
|
88
|
+
parts.adjective = pickRandom(resolved.adjectives);
|
|
89
|
+
}
|
|
90
|
+
if (settings.color) {
|
|
91
|
+
parts.color = pickRandom(resolved.colors);
|
|
92
|
+
}
|
|
93
|
+
if (settings.noun) {
|
|
94
|
+
parts.noun = pickRandom(resolved.nouns);
|
|
95
|
+
}
|
|
96
|
+
const maxNumberLength = completeWithZeros ? numberMax.toString().length : 0;
|
|
97
|
+
for (let i = 0; i < numberSets; i++) {
|
|
98
|
+
const num = getRandomNumber(numberMin, numberMax);
|
|
99
|
+
parts[`number${i + 1}`] = completeWithZeros
|
|
100
|
+
? num.toString().padStart(maxNumberLength, '0')
|
|
101
|
+
: num.toString();
|
|
102
|
+
}
|
|
103
|
+
if (settings.randomOrder) {
|
|
104
|
+
const keys = Object.keys(parts);
|
|
105
|
+
const shuffledKeys = keys.sort(() => Math.random() - 0.5);
|
|
106
|
+
const shuffledParts = [];
|
|
107
|
+
for (const key of shuffledKeys) {
|
|
108
|
+
shuffledParts.push(parts[key]);
|
|
109
|
+
}
|
|
110
|
+
return shuffledParts.join(settings.separator);
|
|
111
|
+
}
|
|
112
|
+
if (settings.asObject) {
|
|
113
|
+
return parts;
|
|
114
|
+
}
|
|
115
|
+
const semantics = (settings.semantics && settings.semantics[lang]) || settings.semantics.en;
|
|
116
|
+
const result = semantics.map((key) => {
|
|
117
|
+
if (key !== 'number')
|
|
118
|
+
return parts[key];
|
|
119
|
+
// Collect all number parts directly instead of filtering with isNaN
|
|
120
|
+
const numberParts = [];
|
|
121
|
+
for (let i = 1; i <= numberSets; i++) {
|
|
122
|
+
numberParts.push(parts[`number${i}`]);
|
|
123
|
+
}
|
|
124
|
+
return numberParts.join('-');
|
|
125
|
+
});
|
|
126
|
+
return result.join(settings.separator);
|
|
127
|
+
}
|