@arc-js/id-generator 0.0.1
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 +547 -0
- package/id-generator.all.js +447 -0
- package/id-generator.all.min.js +1 -0
- package/index.d.ts +103 -0
- package/index.js +360 -0
- package/index.min.d.ts +103 -0
- package/index.min.js +1 -0
- package/package.json +18 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
class IdentifierGenerator {
|
|
2
|
+
static instance;
|
|
3
|
+
cache = new Map();
|
|
4
|
+
constructor() { }
|
|
5
|
+
static getInstance() {
|
|
6
|
+
if (!IdentifierGenerator.instance) {
|
|
7
|
+
IdentifierGenerator.instance = new IdentifierGenerator();
|
|
8
|
+
}
|
|
9
|
+
return IdentifierGenerator.instance;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Parse un format d'identifiant et génère l'identifiant
|
|
13
|
+
*/
|
|
14
|
+
generate(format, customHandlers = {}) {
|
|
15
|
+
const tokens = this.parseFormat(format);
|
|
16
|
+
return tokens.map(token => this.resolveToken(token, customHandlers)).join('');
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Parse le format en tokens
|
|
20
|
+
*/
|
|
21
|
+
parseFormat(format) {
|
|
22
|
+
const tokens = [];
|
|
23
|
+
let currentIndex = 0;
|
|
24
|
+
while (currentIndex < format.length) {
|
|
25
|
+
const nextHashIndex = format.indexOf('#', currentIndex);
|
|
26
|
+
// Texte littéral avant le prochain token
|
|
27
|
+
if (nextHashIndex > currentIndex) {
|
|
28
|
+
tokens.push({
|
|
29
|
+
type: 'string',
|
|
30
|
+
value: format.substring(currentIndex, nextHashIndex)
|
|
31
|
+
});
|
|
32
|
+
currentIndex = nextHashIndex;
|
|
33
|
+
}
|
|
34
|
+
// Token spécial
|
|
35
|
+
if (format[currentIndex] === '#') {
|
|
36
|
+
const tokenEnd = this.findTokenEnd(format, currentIndex + 1);
|
|
37
|
+
if (tokenEnd === -1) {
|
|
38
|
+
throw new Error(`Format invalide à la position ${currentIndex}`);
|
|
39
|
+
}
|
|
40
|
+
const tokenContent = format.substring(currentIndex + 1, tokenEnd);
|
|
41
|
+
const token = this.parseToken(tokenContent);
|
|
42
|
+
tokens.push(token);
|
|
43
|
+
currentIndex = tokenEnd;
|
|
44
|
+
}
|
|
45
|
+
else if (nextHashIndex === -1) {
|
|
46
|
+
// Reste du texte
|
|
47
|
+
tokens.push({
|
|
48
|
+
type: 'string',
|
|
49
|
+
value: format.substring(currentIndex)
|
|
50
|
+
});
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return tokens;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Trouve la fin d'un token
|
|
58
|
+
*/
|
|
59
|
+
findTokenEnd(format, startIndex) {
|
|
60
|
+
let braceCount = 0;
|
|
61
|
+
let inString = false;
|
|
62
|
+
let escapeNext = false;
|
|
63
|
+
for (let i = startIndex; i < format.length; i++) {
|
|
64
|
+
const char = format[i];
|
|
65
|
+
if (escapeNext) {
|
|
66
|
+
escapeNext = false;
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (char === '\\') {
|
|
70
|
+
escapeNext = true;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (char === '"' || char === "'") {
|
|
74
|
+
inString = !inString;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (!inString) {
|
|
78
|
+
if (char === '{') {
|
|
79
|
+
braceCount++;
|
|
80
|
+
}
|
|
81
|
+
else if (char === '}') {
|
|
82
|
+
if (braceCount === 0) {
|
|
83
|
+
return i;
|
|
84
|
+
}
|
|
85
|
+
braceCount--;
|
|
86
|
+
}
|
|
87
|
+
else if (char === '#' && braceCount === 0) {
|
|
88
|
+
return i;
|
|
89
|
+
}
|
|
90
|
+
else if (/[a-zA-Z0-9]/.test(char) === false && char !== ',' && char !== ':' && char !== '-' && char !== '_' && braceCount === 0) {
|
|
91
|
+
return i;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return format.length;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Parse un token individuel
|
|
99
|
+
*/
|
|
100
|
+
parseToken(tokenContent) {
|
|
101
|
+
// Token personnalisé simple
|
|
102
|
+
if (tokenContent.includes('{') === false) {
|
|
103
|
+
return { type: 'string', value: tokenContent };
|
|
104
|
+
}
|
|
105
|
+
const [type, optionsStr] = tokenContent.split('{', 2);
|
|
106
|
+
const optionsContent = optionsStr.slice(0, -1); // Retirer le '}'
|
|
107
|
+
if (type === 'rand') {
|
|
108
|
+
return {
|
|
109
|
+
type: 'random',
|
|
110
|
+
value: this.parseRandomOptions(optionsContent)
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
else if (type === 'uuid') {
|
|
114
|
+
return {
|
|
115
|
+
type: 'uuid',
|
|
116
|
+
value: this.parseUUIDOptions(optionsContent)
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
else if (type === 'custom') {
|
|
120
|
+
return {
|
|
121
|
+
type: 'custom',
|
|
122
|
+
value: optionsContent
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
throw new Error(`Type de token non supporté: ${type}`);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Parse les options pour un random string
|
|
129
|
+
*/
|
|
130
|
+
parseRandomOptions(optionsStr) {
|
|
131
|
+
const defaults = {
|
|
132
|
+
size: 8,
|
|
133
|
+
type: 'alphanumeric',
|
|
134
|
+
variant: false
|
|
135
|
+
};
|
|
136
|
+
const options = this.parseOptions(optionsStr);
|
|
137
|
+
return {
|
|
138
|
+
size: options.size ? parseInt(options.size) : defaults.size,
|
|
139
|
+
type: options.type || defaults.type,
|
|
140
|
+
variant: options.variant === 'true' ? true : defaults.variant
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Parse les options pour un UUID
|
|
145
|
+
*/
|
|
146
|
+
parseUUIDOptions(optionsStr) {
|
|
147
|
+
const defaults = {
|
|
148
|
+
version: 'v4'
|
|
149
|
+
};
|
|
150
|
+
const options = this.parseOptions(optionsStr);
|
|
151
|
+
return {
|
|
152
|
+
version: options.version || defaults.version
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Parse une chaîne d'options key:value
|
|
157
|
+
*/
|
|
158
|
+
parseOptions(optionsStr) {
|
|
159
|
+
const options = {};
|
|
160
|
+
let currentKey = '';
|
|
161
|
+
let currentValue = '';
|
|
162
|
+
let inString = false;
|
|
163
|
+
let stringChar = '';
|
|
164
|
+
let braceCount = 0;
|
|
165
|
+
for (let i = 0; i < optionsStr.length; i++) {
|
|
166
|
+
const char = optionsStr[i];
|
|
167
|
+
if (char === '"' || char === "'") {
|
|
168
|
+
if (!inString) {
|
|
169
|
+
inString = true;
|
|
170
|
+
stringChar = char;
|
|
171
|
+
}
|
|
172
|
+
else if (stringChar === char) {
|
|
173
|
+
inString = false;
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
currentValue += char;
|
|
177
|
+
}
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
if (inString) {
|
|
181
|
+
currentValue += char;
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
if (char === ':') {
|
|
185
|
+
if (braceCount === 0) {
|
|
186
|
+
currentKey = currentValue.trim();
|
|
187
|
+
currentValue = '';
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
else if (char === '{') {
|
|
192
|
+
braceCount++;
|
|
193
|
+
}
|
|
194
|
+
else if (char === '}') {
|
|
195
|
+
braceCount--;
|
|
196
|
+
}
|
|
197
|
+
else if (char === ',' && braceCount === 0) {
|
|
198
|
+
options[currentKey] = currentValue.trim();
|
|
199
|
+
currentKey = '';
|
|
200
|
+
currentValue = '';
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
currentValue += char;
|
|
204
|
+
}
|
|
205
|
+
if (currentKey) {
|
|
206
|
+
options[currentKey] = currentValue.trim();
|
|
207
|
+
}
|
|
208
|
+
return options;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Résout un token en sa valeur
|
|
212
|
+
*/
|
|
213
|
+
resolveToken(token, customHandlers) {
|
|
214
|
+
switch (token.type) {
|
|
215
|
+
case 'string':
|
|
216
|
+
return token.value;
|
|
217
|
+
case 'random':
|
|
218
|
+
return this.generateRandomString(token.value);
|
|
219
|
+
case 'uuid':
|
|
220
|
+
return this.generateUUID(token.value);
|
|
221
|
+
case 'custom':
|
|
222
|
+
const handlerName = token.value.split('}').join('').split('{').join('');
|
|
223
|
+
const checker = Object.keys(customHandlers).includes(handlerName);
|
|
224
|
+
if (checker) {
|
|
225
|
+
return customHandlers[handlerName]();
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
console.log(`[id-generator -> id-generator] IdentifierGenerator | resolveToken - custom - token:: `, token);
|
|
229
|
+
console.log(`[id-generator -> id-generator] IdentifierGenerator | resolveToken - custom - handlerName:: `, handlerName);
|
|
230
|
+
console.log(`[id-generator -> id-generator] IdentifierGenerator | resolveToken - custom - checker:: `, checker);
|
|
231
|
+
console.log(`[id-generator -> id-generator] IdentifierGenerator | resolveToken - custom - Object.keys(customHandlers):: `, Object.keys(customHandlers));
|
|
232
|
+
console.log(`[id-generator -> id-generator] IdentifierGenerator | resolveToken - custom - customHandlers:: `, customHandlers);
|
|
233
|
+
throw new Error(`Handler personnalisé non trouvé: ${handlerName}`);
|
|
234
|
+
}
|
|
235
|
+
default:
|
|
236
|
+
throw new Error(`Type de token inconnu: ${token.type}`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Génère une chaîne aléatoire
|
|
241
|
+
*/
|
|
242
|
+
generateRandomString(options) {
|
|
243
|
+
const cacheKey = this.getRandomCacheKey(options);
|
|
244
|
+
// Si non variant, on utilise le cache
|
|
245
|
+
if (!options.variant) {
|
|
246
|
+
if (!this.cache.has('random')) {
|
|
247
|
+
this.cache.set('random', new Map());
|
|
248
|
+
}
|
|
249
|
+
const randomCache = this.cache.get('random');
|
|
250
|
+
if (randomCache.has(cacheKey)) {
|
|
251
|
+
return randomCache.get(cacheKey);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
let charset = '';
|
|
255
|
+
let result = '';
|
|
256
|
+
switch (options.type) {
|
|
257
|
+
case 'numeric':
|
|
258
|
+
charset = '0123456789';
|
|
259
|
+
break;
|
|
260
|
+
case 'alphabetic':
|
|
261
|
+
charset = 'abcdefghijklmnopqrstuvwxyz';
|
|
262
|
+
break;
|
|
263
|
+
case 'alphabetic-case':
|
|
264
|
+
charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
265
|
+
break;
|
|
266
|
+
case 'alphanumeric':
|
|
267
|
+
charset = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
|
268
|
+
break;
|
|
269
|
+
case 'alphanumeric-case':
|
|
270
|
+
charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
// Utilisation de crypto.getRandomValues pour une meilleure sécurité/performance
|
|
274
|
+
const randomValues = new Uint32Array(options.size);
|
|
275
|
+
crypto.getRandomValues(randomValues);
|
|
276
|
+
for (let i = 0; i < options.size; i++) {
|
|
277
|
+
result += charset[randomValues[i] % charset.length];
|
|
278
|
+
}
|
|
279
|
+
// Mise en cache si non variant
|
|
280
|
+
if (!options.variant) {
|
|
281
|
+
this.cache.get('random').set(cacheKey, result);
|
|
282
|
+
}
|
|
283
|
+
return result;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Génère un UUID selon la version spécifiée
|
|
287
|
+
*/
|
|
288
|
+
generateUUID(options) {
|
|
289
|
+
const cacheKey = `uuid-${options.version}`;
|
|
290
|
+
if (!this.cache.has('uuid')) {
|
|
291
|
+
this.cache.set('uuid', new Map());
|
|
292
|
+
}
|
|
293
|
+
const uuidCache = this.cache.get('uuid');
|
|
294
|
+
// Les UUID sont par définition variants, mais on peut optimiser la génération
|
|
295
|
+
if (uuidCache.has(cacheKey)) {
|
|
296
|
+
// Pour v4, on ne cache pas car variant
|
|
297
|
+
if (options.version === 'v4') {
|
|
298
|
+
return this.generateUUIDv4();
|
|
299
|
+
}
|
|
300
|
+
return uuidCache.get(cacheKey);
|
|
301
|
+
}
|
|
302
|
+
let uuid;
|
|
303
|
+
switch (options.version) {
|
|
304
|
+
case 'v1':
|
|
305
|
+
uuid = this.generateUUIDv1();
|
|
306
|
+
break;
|
|
307
|
+
case 'v2':
|
|
308
|
+
uuid = this.generateUUIDv2();
|
|
309
|
+
break;
|
|
310
|
+
case 'v3':
|
|
311
|
+
uuid = this.generateUUIDv3();
|
|
312
|
+
break;
|
|
313
|
+
case 'v4':
|
|
314
|
+
uuid = this.generateUUIDv4();
|
|
315
|
+
break;
|
|
316
|
+
case 'v5':
|
|
317
|
+
uuid = this.generateUUIDv5();
|
|
318
|
+
break;
|
|
319
|
+
default:
|
|
320
|
+
uuid = this.generateUUIDv4();
|
|
321
|
+
}
|
|
322
|
+
// On ne cache que les UUID non-variants (v3 et v5 sont basés sur des noms)
|
|
323
|
+
if (options.version === 'v3' || options.version === 'v5') {
|
|
324
|
+
uuidCache.set(cacheKey, uuid);
|
|
325
|
+
}
|
|
326
|
+
return uuid;
|
|
327
|
+
}
|
|
328
|
+
generateUUIDv1() {
|
|
329
|
+
// Implémentation simplifiée de UUID v1
|
|
330
|
+
const now = Date.now();
|
|
331
|
+
const hexTime = now.toString(16).padStart(12, '0');
|
|
332
|
+
return `${hexTime.slice(0, 8)}-${hexTime.slice(8, 12)}-1000-8000-${this.getRandomHex(12)}`;
|
|
333
|
+
}
|
|
334
|
+
generateUUIDv2() {
|
|
335
|
+
// Version 2 rarement utilisée, implémentation de base
|
|
336
|
+
return this.generateUUIDv1();
|
|
337
|
+
}
|
|
338
|
+
generateUUIDv3() {
|
|
339
|
+
return 'xxxxxxxx-xxxx-3xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
340
|
+
const r = Math.random() * 16 | 0;
|
|
341
|
+
const v = c === 'x' ? r : (r & 0x3 | 0x8);
|
|
342
|
+
return v.toString(16);
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
generateUUIDv4() {
|
|
346
|
+
// UUID v4 standard (aléatoire)
|
|
347
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
348
|
+
const r = crypto.getRandomValues(new Uint8Array(1))[0] % 16 | 0;
|
|
349
|
+
const v = c === 'x' ? r : (r & 0x3 | 0x8);
|
|
350
|
+
return v.toString(16);
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
generateUUIDv5() {
|
|
354
|
+
return 'xxxxxxxx-xxxx-5xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
355
|
+
const r = Math.random() * 16 | 0;
|
|
356
|
+
const v = c === 'x' ? r : (r & 0x3 | 0x8);
|
|
357
|
+
return v.toString(16);
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
getRandomHex(size) {
|
|
361
|
+
const bytes = new Uint8Array(Math.ceil(size / 2));
|
|
362
|
+
crypto.getRandomValues(bytes);
|
|
363
|
+
return Array.from(bytes)
|
|
364
|
+
.map(b => b.toString(16).padStart(2, '0'))
|
|
365
|
+
.join('')
|
|
366
|
+
.slice(0, size);
|
|
367
|
+
}
|
|
368
|
+
getRandomCacheKey(options) {
|
|
369
|
+
return `${options.size}-${options.type}-${options.variant}`;
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Vide le cache
|
|
373
|
+
*/
|
|
374
|
+
clearCache() {
|
|
375
|
+
this.cache.clear();
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Méthode utilitaire pour générer un identifiant unique
|
|
379
|
+
*/
|
|
380
|
+
static generateId(format, customHandlers = {}) {
|
|
381
|
+
return this.getInstance().generate(format, customHandlers);
|
|
382
|
+
}
|
|
383
|
+
static exposeToGlobal() {
|
|
384
|
+
if (typeof window !== 'undefined') {
|
|
385
|
+
window.IdentifierGenerator = IdentifierGenerator;
|
|
386
|
+
window.IdentifierGeneratorHandlers = IdentifierGeneratorHandlers;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
const IdentifierGeneratorHandlers = {
|
|
391
|
+
timestamp: () => Date.now().toString(),
|
|
392
|
+
date: () => new Date().toISOString().slice(0, 10).replace(/-/g, ''),
|
|
393
|
+
time: () => new Date().toISOString().slice(11, 19).replace(/:/g, ''),
|
|
394
|
+
counter: (() => {
|
|
395
|
+
let count = 0;
|
|
396
|
+
return () => (++count).toString().padStart(6, '0');
|
|
397
|
+
})(),
|
|
398
|
+
env: (envVar) => process.env[envVar] || ''
|
|
399
|
+
};
|
|
400
|
+
if (typeof window !== 'undefined') {
|
|
401
|
+
window.IdentifierGenerator = IdentifierGenerator;
|
|
402
|
+
window.IdentifierGeneratorHandlers = IdentifierGeneratorHandlers;
|
|
403
|
+
}
|
|
404
|
+
var index_all = {
|
|
405
|
+
IdentifierGenerator,
|
|
406
|
+
IdentifierGeneratorHandlers,
|
|
407
|
+
};
|
|
408
|
+
// Exemple d'utilisation
|
|
409
|
+
/*
|
|
410
|
+
import { IdentifierGenerator, IdentifierGeneratorHandlers } from './identifier';
|
|
411
|
+
|
|
412
|
+
const generator = IdentifierGenerator.getInstance();
|
|
413
|
+
|
|
414
|
+
// Exemple 1
|
|
415
|
+
const id1 = generator.generate(
|
|
416
|
+
'mda#rand{size:10,type:alphanumeric}-#uuid{version:v1}',
|
|
417
|
+
{
|
|
418
|
+
customTimestamp: () => Date.now().toString()
|
|
419
|
+
}
|
|
420
|
+
);
|
|
421
|
+
|
|
422
|
+
// Exemple 2
|
|
423
|
+
const id2 = generator.generate(
|
|
424
|
+
'lorem#rand{type:alphanumeric, variant:true}ipsum',
|
|
425
|
+
{
|
|
426
|
+
user: () => 'john_doe'
|
|
427
|
+
}
|
|
428
|
+
);
|
|
429
|
+
|
|
430
|
+
// Exemple 3 avec handler personnalisé
|
|
431
|
+
const id3 = generator.generate(
|
|
432
|
+
'user-#custom{userId}-#rand{size:6,type:numeric}',
|
|
433
|
+
{
|
|
434
|
+
userId: () => 'USR_' + Math.random().toString(36).substr(2, 9)
|
|
435
|
+
}
|
|
436
|
+
);
|
|
437
|
+
|
|
438
|
+
// Utilisation de la méthode statique
|
|
439
|
+
const id4 = IdentifierGenerator.generateId(
|
|
440
|
+
'order-#custom{timestamp}-#rand{size:8,type:alphanumeric-case}',
|
|
441
|
+
{
|
|
442
|
+
timestamp: IdentifierGeneratorHandlers.timestamp
|
|
443
|
+
}
|
|
444
|
+
);
|
|
445
|
+
*/
|
|
446
|
+
|
|
447
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
class IdentifierGenerator{static instance;cache=new Map;constructor(){}static getInstance(){return IdentifierGenerator.instance||(IdentifierGenerator.instance=new IdentifierGenerator),IdentifierGenerator.instance}generate(e,r={}){return this.parseFormat(e).map(e=>this.resolveToken(e,r)).join("")}parseFormat(e){var r=[];let t=0;for(;t<e.length;){var n=e.indexOf("#",t);if(n>t&&(r.push({type:"string",value:e.substring(t,n)}),t=n),"#"===e[t]){var a=this.findTokenEnd(e,t+1);if(-1===a)throw new Error("Format invalide à la position "+t);var i=e.substring(t+1,a),i=this.parseToken(i);r.push(i),t=a}else if(-1===n){r.push({type:"string",value:e.substring(t)});break}}return r}findTokenEnd(r,t){let n=0,a=!1,i=!1;for(let e=t;e<r.length;e++){var s=r[e];if(i)i=!1;else if("\\"===s)i=!0;else if('"'===s||"'"===s)a=!a;else if(!a)if("{"===s)n++;else if("}"===s){if(0===n)return e;n--}else{if("#"===s&&0===n)return e;if(!1===/[a-zA-Z0-9]/.test(s)&&","!==s&&":"!==s&&"-"!==s&&"_"!==s&&0===n)return e}}return r.length}parseToken(e){if(!1===e.includes("{"))return{type:"string",value:e};var[e,r]=e.split("{",2),r=r.slice(0,-1);if("rand"===e)return{type:"random",value:this.parseRandomOptions(r)};if("uuid"===e)return{type:"uuid",value:this.parseUUIDOptions(r)};if("custom"===e)return{type:"custom",value:r};throw new Error("Type de token non supporté: "+e)}parseRandomOptions(e){const r=8,t="alphanumeric",n=!1;e=this.parseOptions(e);return{size:e.size?parseInt(e.size):r,type:e.type||t,variant:"true"===e.variant||n}}parseUUIDOptions(e){return{version:this.parseOptions(e).version||"v4"}}parseOptions(r){var t={};let n="",a="",i=!1,s="",o=0;for(let e=0;e<r.length;e++){var x=r[e];if('"'===x||"'"===x)i?s===x?i=!1:a+=x:(i=!0,s=x);else{if(!i)if(":"===x){if(0===o){n=a.trim(),a="";continue}}else if("{"===x)o++;else if("}"===x)o--;else if(","===x&&0===o){t[n]=a.trim(),n="",a="";continue}a+=x}}return n&&(t[n]=a.trim()),t}resolveToken(e,r){switch(e.type){case"string":return e.value;case"random":return this.generateRandomString(e.value);case"uuid":return this.generateUUID(e.value);case"custom":var t=e.value.split("}").join("").split("{").join(""),n=Object.keys(r).includes(t);if(n)return r[t]();throw new Error("Handler personnalisé non trouvé: "+t);default:throw new Error("Type de token inconnu: "+e.type)}}generateRandomString(r){var e=this.getRandomCacheKey(r);if(!r.variant){this.cache.has("random")||this.cache.set("random",new Map);var t=this.cache.get("random");if(t.has(e))return t.get(e)}let n="",a="";switch(r.type){case"numeric":n="0123456789";break;case"alphabetic":n="abcdefghijklmnopqrstuvwxyz";break;case"alphabetic-case":n="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";break;case"alphanumeric":n="abcdefghijklmnopqrstuvwxyz0123456789";break;case"alphanumeric-case":n="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"}var i=new Uint32Array(r.size);crypto.getRandomValues(i);for(let e=0;e<r.size;e++)a+=n[i[e]%n.length];return r.variant||this.cache.get("random").set(e,a),a}generateUUID(e){var r="uuid-"+e.version,t=(this.cache.has("uuid")||this.cache.set("uuid",new Map),this.cache.get("uuid"));if(t.has(r))return"v4"===e.version?this.generateUUIDv4():t.get(r);let n;switch(e.version){case"v1":n=this.generateUUIDv1();break;case"v2":n=this.generateUUIDv2();break;case"v3":n=this.generateUUIDv3();break;case"v4":n=this.generateUUIDv4();break;case"v5":n=this.generateUUIDv5();break;default:n=this.generateUUIDv4()}return"v3"!==e.version&&"v5"!==e.version||t.set(r,n),n}generateUUIDv1(){var e=Date.now().toString(16).padStart(12,"0");return`${e.slice(0,8)}-${e.slice(8,12)}-1000-8000-`+this.getRandomHex(12)}generateUUIDv2(){return this.generateUUIDv1()}generateUUIDv3(){return"xxxxxxxx-xxxx-3xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{var r=16*Math.random()|0;return("x"===e?r:3&r|8).toString(16)})}generateUUIDv4(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{var r=crypto.getRandomValues(new Uint8Array(1))[0]%16|0;return("x"===e?r:3&r|8).toString(16)})}generateUUIDv5(){return"xxxxxxxx-xxxx-5xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{var r=16*Math.random()|0;return("x"===e?r:3&r|8).toString(16)})}getRandomHex(e){var r=new Uint8Array(Math.ceil(e/2));return crypto.getRandomValues(r),Array.from(r).map(e=>e.toString(16).padStart(2,"0")).join("").slice(0,e)}getRandomCacheKey(e){return e.size+`-${e.type}-`+e.variant}clearCache(){this.cache.clear()}static generateId(e,r={}){return this.getInstance().generate(e,r)}static exposeToGlobal(){"undefined"!=typeof window&&(window.IdentifierGenerator=IdentifierGenerator,window.IdentifierGeneratorHandlers=IdentifierGeneratorHandlers)}}let IdentifierGeneratorHandlers={timestamp:()=>Date.now().toString(),date:()=>(new Date).toISOString().slice(0,10).replace(/-/g,""),time:()=>(new Date).toISOString().slice(11,19).replace(/:/g,""),counter:(()=>{let e=0;return()=>(++e).toString().padStart(6,"0")})(),env:e=>process.env[e]||""};"undefined"!=typeof window&&(window.IdentifierGenerator=IdentifierGenerator,window.IdentifierGeneratorHandlers=IdentifierGeneratorHandlers);var index_all={IdentifierGenerator:IdentifierGenerator,IdentifierGeneratorHandlers:IdentifierGeneratorHandlers};
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
type RandomType = 'numeric' | 'alphabetic' | 'alphabetic-case' | 'alphanumeric' | 'alphanumeric-case';
|
|
2
|
+
type UUIDVersion = 'v1' | 'v2' | 'v3' | 'v4' | 'v5';
|
|
3
|
+
interface RandomOptions {
|
|
4
|
+
size: number;
|
|
5
|
+
type: RandomType;
|
|
6
|
+
variant: boolean;
|
|
7
|
+
}
|
|
8
|
+
interface UUIDOptions {
|
|
9
|
+
version: UUIDVersion;
|
|
10
|
+
}
|
|
11
|
+
interface TokenDefinition {
|
|
12
|
+
type: 'string' | 'random' | 'uuid' | 'custom';
|
|
13
|
+
value: string | RandomOptions | UUIDOptions | CustomHandler;
|
|
14
|
+
}
|
|
15
|
+
type CustomHandler = () => string;
|
|
16
|
+
declare global {
|
|
17
|
+
interface Window {
|
|
18
|
+
IdentifierGenerator: typeof IdentifierGenerator;
|
|
19
|
+
IdentifierGeneratorHandlers: any;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
declare class IdentifierGenerator {
|
|
23
|
+
private static instance;
|
|
24
|
+
private cache;
|
|
25
|
+
private constructor();
|
|
26
|
+
static getInstance(): IdentifierGenerator;
|
|
27
|
+
/**
|
|
28
|
+
* Parse un format d'identifiant et génère l'identifiant
|
|
29
|
+
*/
|
|
30
|
+
generate(format: string, customHandlers?: Record<string, CustomHandler>): string;
|
|
31
|
+
/**
|
|
32
|
+
* Parse le format en tokens
|
|
33
|
+
*/
|
|
34
|
+
private parseFormat;
|
|
35
|
+
/**
|
|
36
|
+
* Trouve la fin d'un token
|
|
37
|
+
*/
|
|
38
|
+
private findTokenEnd;
|
|
39
|
+
/**
|
|
40
|
+
* Parse un token individuel
|
|
41
|
+
*/
|
|
42
|
+
private parseToken;
|
|
43
|
+
/**
|
|
44
|
+
* Parse les options pour un random string
|
|
45
|
+
*/
|
|
46
|
+
private parseRandomOptions;
|
|
47
|
+
/**
|
|
48
|
+
* Parse les options pour un UUID
|
|
49
|
+
*/
|
|
50
|
+
private parseUUIDOptions;
|
|
51
|
+
/**
|
|
52
|
+
* Parse une chaîne d'options key:value
|
|
53
|
+
*/
|
|
54
|
+
private parseOptions;
|
|
55
|
+
/**
|
|
56
|
+
* Résout un token en sa valeur
|
|
57
|
+
*/
|
|
58
|
+
private resolveToken;
|
|
59
|
+
/**
|
|
60
|
+
* Génère une chaîne aléatoire
|
|
61
|
+
*/
|
|
62
|
+
private generateRandomString;
|
|
63
|
+
/**
|
|
64
|
+
* Génère un UUID selon la version spécifiée
|
|
65
|
+
*/
|
|
66
|
+
private generateUUID;
|
|
67
|
+
private generateUUIDv1;
|
|
68
|
+
private generateUUIDv2;
|
|
69
|
+
private generateUUIDv3;
|
|
70
|
+
private generateUUIDv4;
|
|
71
|
+
private generateUUIDv5;
|
|
72
|
+
private getRandomHex;
|
|
73
|
+
private getRandomCacheKey;
|
|
74
|
+
/**
|
|
75
|
+
* Vide le cache
|
|
76
|
+
*/
|
|
77
|
+
clearCache(): void;
|
|
78
|
+
/**
|
|
79
|
+
* Méthode utilitaire pour générer un identifiant unique
|
|
80
|
+
*/
|
|
81
|
+
static generateId(format: string, customHandlers?: Record<string, CustomHandler>): string;
|
|
82
|
+
static exposeToGlobal(): void;
|
|
83
|
+
}
|
|
84
|
+
declare const IdentifierGeneratorHandlers: {
|
|
85
|
+
timestamp: () => string;
|
|
86
|
+
date: () => string;
|
|
87
|
+
time: () => string;
|
|
88
|
+
counter: () => string;
|
|
89
|
+
env: (envVar: string) => string;
|
|
90
|
+
};
|
|
91
|
+
declare const _default: {
|
|
92
|
+
IdentifierGenerator: typeof IdentifierGenerator;
|
|
93
|
+
IdentifierGeneratorHandlers: {
|
|
94
|
+
timestamp: () => string;
|
|
95
|
+
date: () => string;
|
|
96
|
+
time: () => string;
|
|
97
|
+
counter: () => string;
|
|
98
|
+
env: (envVar: string) => string;
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export { IdentifierGenerator, IdentifierGeneratorHandlers, _default as default };
|
|
103
|
+
export type { CustomHandler, RandomOptions, RandomType, TokenDefinition, UUIDOptions, UUIDVersion };
|