0
# UUID Generation
1
2
RFC 4122 compliant UUID v4 generation with cryptographically strong randomness and cross-platform support. Provides secure unique identifier generation for applications requiring globally unique identifiers.
3
4
## Capabilities
5
6
### UUID Namespace
7
8
Provides RFC 4122 compliant UUID v4 generation using cryptographically strong random number generation.
9
10
```typescript { .api }
11
/**
12
* The namespace for UUID related functionality.
13
*/
14
namespace UUID {
15
/**
16
* A function which generates UUID v4 identifiers.
17
*
18
* @returns A new UUID v4 string.
19
*
20
* Notes:
21
* This implementation complies with RFC 4122.
22
*
23
* This uses `Random.getRandomValues()` for random bytes, which in
24
* turn will use the underlying `crypto` module of the platform if
25
* it is available. The fallback for randomness is `Math.random`.
26
*/
27
const uuid4: () => string;
28
}
29
```
30
31
### UUID Factory Function
32
33
Internal factory function that creates UUID generators with custom random number sources.
34
35
```typescript { .api }
36
/**
37
* A function which creates a function that generates UUID v4 identifiers.
38
*
39
* @param getRandomValues - Function to generate random bytes
40
* @returns A new function that creates a UUID v4 string.
41
*
42
* Notes:
43
* This implementation complies with RFC 4122.
44
*
45
* This uses the provided `getRandomValues` function for random bytes, which
46
* allows for custom random number generators or testing with deterministic values.
47
*/
48
function uuid4Factory(
49
getRandomValues: (bytes: Uint8Array) => void
50
): () => string;
51
```
52
53
**Usage Examples:**
54
55
```typescript
56
import { UUID } from "@lumino/coreutils";
57
58
// Generate a single UUID v4
59
const id = UUID.uuid4();
60
console.log(id); // "f47ac10b-58cc-4372-a567-0e02b2c3d479"
61
62
// Generate multiple UUIDs
63
const userIds = Array.from({ length: 5 }, () => UUID.uuid4());
64
console.log(userIds);
65
// [
66
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
67
// "6ba7b811-9dad-11d1-80b4-00c04fd430c8",
68
// "6ba7b812-9dad-11d1-80b4-00c04fd430c8",
69
// "6ba7b813-9dad-11d1-80b4-00c04fd430c8",
70
// "6ba7b814-9dad-11d1-80b4-00c04fd430c8"
71
// ]
72
73
// UUIDs are always unique
74
const id1 = UUID.uuid4();
75
const id2 = UUID.uuid4();
76
console.log(id1 === id2); // false
77
```
78
79
### Common Use Cases
80
81
**Entity Identification:**
82
83
```typescript
84
import { UUID } from "@lumino/coreutils";
85
86
interface User {
87
id: string;
88
name: string;
89
email: string;
90
createdAt: Date;
91
}
92
93
interface Document {
94
id: string;
95
title: string;
96
content: string;
97
authorId: string;
98
version: string;
99
}
100
101
function createUser(name: string, email: string): User {
102
return {
103
id: UUID.uuid4(),
104
name,
105
email,
106
createdAt: new Date()
107
};
108
}
109
110
function createDocument(title: string, content: string, authorId: string): Document {
111
return {
112
id: UUID.uuid4(),
113
title,
114
content,
115
authorId,
116
version: UUID.uuid4() // Version ID for tracking changes
117
};
118
}
119
120
// Usage
121
const user = createUser("Alice Smith", "alice@example.com");
122
const document = createDocument("My Document", "Document content...", user.id);
123
124
console.log("User ID:", user.id);
125
console.log("Document ID:", document.id);
126
console.log("Document Version:", document.version);
127
```
128
129
**Session Management:**
130
131
```typescript
132
import { UUID } from "@lumino/coreutils";
133
134
interface Session {
135
id: string;
136
userId: string;
137
createdAt: Date;
138
expiresAt: Date;
139
isActive: boolean;
140
}
141
142
class SessionManager {
143
private sessions = new Map<string, Session>();
144
145
createSession(userId: string, durationMs: number = 24 * 60 * 60 * 1000): Session {
146
const session: Session = {
147
id: UUID.uuid4(),
148
userId,
149
createdAt: new Date(),
150
expiresAt: new Date(Date.now() + durationMs),
151
isActive: true
152
};
153
154
this.sessions.set(session.id, session);
155
return session;
156
}
157
158
getSession(sessionId: string): Session | undefined {
159
const session = this.sessions.get(sessionId);
160
if (session && session.expiresAt > new Date()) {
161
return session;
162
}
163
164
// Clean up expired session
165
if (session) {
166
this.sessions.delete(sessionId);
167
}
168
return undefined;
169
}
170
171
invalidateSession(sessionId: string): boolean {
172
const session = this.sessions.get(sessionId);
173
if (session) {
174
session.isActive = false;
175
this.sessions.delete(sessionId);
176
return true;
177
}
178
return false;
179
}
180
}
181
182
// Usage
183
const sessionManager = new SessionManager();
184
const session = sessionManager.createSession("user-123", 2 * 60 * 60 * 1000); // 2 hours
185
186
console.log("Session created:", session.id);
187
console.log("Session expires:", session.expiresAt);
188
```
189
190
**Request Tracking:**
191
192
```typescript
193
import { UUID } from "@lumino/coreutils";
194
195
interface ApiRequest {
196
id: string;
197
method: string;
198
url: string;
199
timestamp: Date;
200
userId?: string;
201
correlationId?: string;
202
}
203
204
interface ApiResponse {
205
requestId: string;
206
status: number;
207
data?: any;
208
error?: string;
209
duration: number;
210
}
211
212
class ApiLogger {
213
private requests = new Map<string, ApiRequest>();
214
215
logRequest(method: string, url: string, userId?: string, correlationId?: string): string {
216
const requestId = UUID.uuid4();
217
const request: ApiRequest = {
218
id: requestId,
219
method,
220
url,
221
timestamp: new Date(),
222
userId,
223
correlationId: correlationId || UUID.uuid4()
224
};
225
226
this.requests.set(requestId, request);
227
console.log(`[${request.correlationId}] ${method} ${url} - Request ID: ${requestId}`);
228
229
return requestId;
230
}
231
232
logResponse(requestId: string, status: number, data?: any, error?: string): void {
233
const request = this.requests.get(requestId);
234
if (!request) {
235
console.warn(`Request ${requestId} not found`);
236
return;
237
}
238
239
const duration = Date.now() - request.timestamp.getTime();
240
const response: ApiResponse = {
241
requestId,
242
status,
243
data,
244
error,
245
duration
246
};
247
248
console.log(`[${request.correlationId}] ${request.method} ${request.url} - ${status} (${duration}ms)`);
249
250
// Clean up after logging
251
this.requests.delete(requestId);
252
}
253
}
254
255
// Usage
256
const logger = new ApiLogger();
257
258
// Log API request
259
const requestId = logger.logRequest("POST", "/api/users", "user-123");
260
261
// Simulate API processing time
262
setTimeout(() => {
263
logger.logResponse(requestId, 201, { id: "user-456", name: "New User" });
264
}, 150);
265
```
266
267
**File and Resource Management:**
268
269
```typescript
270
import { UUID } from "@lumino/coreutils";
271
272
interface FileUpload {
273
id: string;
274
originalName: string;
275
storedName: string;
276
mimeType: string;
277
size: number;
278
uploadedAt: Date;
279
uploadedBy: string;
280
}
281
282
interface TemporaryResource {
283
id: string;
284
type: string;
285
data: any;
286
expiresAt: Date;
287
accessCount: number;
288
}
289
290
class FileManager {
291
private uploads = new Map<string, FileUpload>();
292
293
uploadFile(file: File, userId: string): Promise<FileUpload> {
294
return new Promise((resolve) => {
295
const fileId = UUID.uuid4();
296
const storedName = `${fileId}-${file.name}`;
297
298
const upload: FileUpload = {
299
id: fileId,
300
originalName: file.name,
301
storedName,
302
mimeType: file.type,
303
size: file.size,
304
uploadedAt: new Date(),
305
uploadedBy: userId
306
};
307
308
this.uploads.set(fileId, upload);
309
310
// Simulate file storage
311
setTimeout(() => {
312
console.log(`File uploaded: ${file.name} -> ${storedName}`);
313
resolve(upload);
314
}, 100);
315
});
316
}
317
318
getFile(fileId: string): FileUpload | undefined {
319
return this.uploads.get(fileId);
320
}
321
}
322
323
class TemporaryResourceManager {
324
private resources = new Map<string, TemporaryResource>();
325
326
createResource(type: string, data: any, ttlMs: number = 60000): string {
327
const resourceId = UUID.uuid4();
328
const resource: TemporaryResource = {
329
id: resourceId,
330
type,
331
data,
332
expiresAt: new Date(Date.now() + ttlMs),
333
accessCount: 0
334
};
335
336
this.resources.set(resourceId, resource);
337
338
// Auto-cleanup after expiration
339
setTimeout(() => {
340
this.resources.delete(resourceId);
341
}, ttlMs);
342
343
return resourceId;
344
}
345
346
getResource(resourceId: string): any | undefined {
347
const resource = this.resources.get(resourceId);
348
if (resource && resource.expiresAt > new Date()) {
349
resource.accessCount++;
350
return resource.data;
351
}
352
return undefined;
353
}
354
}
355
356
// Usage
357
const fileManager = new FileManager();
358
const tempManager = new TemporaryResourceManager();
359
360
// File upload simulation
361
const mockFile = new File(["content"], "document.txt", { type: "text/plain" });
362
fileManager.uploadFile(mockFile, "user-123").then(upload => {
363
console.log("File uploaded with ID:", upload.id);
364
});
365
366
// Temporary resource
367
const tempId = tempManager.createResource("cache", { result: "computed data" }, 30000);
368
console.log("Temporary resource created:", tempId);
369
```
370
371
**Testing with Custom UUID Generation:**
372
373
```typescript
374
import { uuid4Factory } from "@lumino/coreutils";
375
376
// Create deterministic UUID generator for testing
377
function createTestUuidGenerator(): () => string {
378
let counter = 0;
379
380
const deterministicRandom = (buffer: Uint8Array): void => {
381
for (let i = 0; i < buffer.length; i++) {
382
buffer[i] = (counter + i) % 256;
383
}
384
counter++;
385
};
386
387
return uuid4Factory(deterministicRandom);
388
}
389
390
// Usage in tests
391
const testUuid = createTestUuidGenerator();
392
393
console.log("Test UUID 1:", testUuid()); // Predictable output
394
console.log("Test UUID 2:", testUuid()); // Different but predictable output
395
396
// Create mock UUID generator that returns specific values
397
function createMockUuidGenerator(values: string[]): () => string {
398
let index = 0;
399
return () => {
400
if (index >= values.length) {
401
throw new Error("No more mock UUIDs available");
402
}
403
return values[index++];
404
};
405
}
406
407
const mockUuid = createMockUuidGenerator([
408
"00000000-0000-4000-8000-000000000001",
409
"00000000-0000-4000-8000-000000000002",
410
"00000000-0000-4000-8000-000000000003"
411
]);
412
413
console.log("Mock UUID 1:", mockUuid());
414
console.log("Mock UUID 2:", mockUuid());
415
console.log("Mock UUID 3:", mockUuid());
416
```
417
418
## UUID Format
419
420
UUID v4 identifiers generated by this library follow the RFC 4122 specification:
421
422
- **Format**: `xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`
423
- **Length**: 36 characters (32 hex digits + 4 hyphens)
424
- **Version**: 4 (indicated by the `4` in the 13th position)
425
- **Variant**: RFC 4122 (indicated by `8`, `9`, `A`, or `B` in the 17th position)
426
- **Randomness**: 122 bits of randomness (6 bits are fixed for version and variant)
427
428
Example: `f47ac10b-58cc-4372-a567-0e02b2c3d479`
429
430
## Platform Support
431
432
UUID generation uses the same cross-platform random number generation as the Random module:
433
434
### Browser Support
435
- **Modern browsers**: Uses `window.crypto.getRandomValues()`
436
- **Internet Explorer 11**: Uses `window.msCrypto.getRandomValues()`
437
- **Fallback**: Uses `Math.random()` if crypto APIs unavailable
438
439
### Node.js Support
440
- **Node.js 7+**: Uses `crypto.randomFillSync()`
441
- **Node.js 0.10+**: Uses `crypto.randomBytes()`
442
- **Fallback**: Uses `Math.random()` if crypto module unavailable
443
444
### Security Considerations
445
446
- UUIDs generated with crypto APIs provide cryptographically strong uniqueness
447
- Fallback `Math.random()` implementation is **not cryptographically secure**
448
- For security-critical applications, ensure crypto APIs are available
449
- The probability of generating duplicate UUIDs is astronomically low with proper random sources