@fjell/registry 4.4.52 → 4.4.54

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.
Files changed (51) hide show
  1. package/package.json +4 -4
  2. package/API.md +0 -62
  3. package/GETTING_STARTED.md +0 -69
  4. package/build.js +0 -38
  5. package/docs/README.md +0 -74
  6. package/docs/TIMING_NODE_OPTIMIZATION.md +0 -207
  7. package/docs/TIMING_README.md +0 -170
  8. package/docs/docs.config.ts +0 -114
  9. package/docs/index.html +0 -26
  10. package/docs/package-lock.json +0 -5129
  11. package/docs/package.json +0 -34
  12. package/docs/public/404.html +0 -53
  13. package/docs/public/GETTING_STARTED.md +0 -69
  14. package/docs/public/README.md +0 -623
  15. package/docs/public/TIMING_NODE_OPTIMIZATION.md +0 -207
  16. package/docs/public/api.md +0 -62
  17. package/docs/public/client-api-overview.md +0 -137
  18. package/docs/public/configuration.md +0 -759
  19. package/docs/public/error-handling/README.md +0 -356
  20. package/docs/public/error-handling/network-errors.md +0 -485
  21. package/docs/public/examples/coordinates-example.ts +0 -253
  22. package/docs/public/examples/multi-level-keys.ts +0 -374
  23. package/docs/public/examples/registry-hub-coordinates-example.ts +0 -370
  24. package/docs/public/examples/registry-hub-types.ts +0 -437
  25. package/docs/public/examples/simple-example.ts +0 -250
  26. package/docs/public/examples-README.md +0 -241
  27. package/docs/public/fjell-icon.svg +0 -1
  28. package/docs/public/icon.png +0 -0
  29. package/docs/public/icon2.png +0 -0
  30. package/docs/public/memory-overhead.svg +0 -120
  31. package/docs/public/memory.md +0 -430
  32. package/docs/public/operations/README.md +0 -121
  33. package/docs/public/operations/all.md +0 -325
  34. package/docs/public/operations/create.md +0 -415
  35. package/docs/public/operations/get.md +0 -389
  36. package/docs/public/package.json +0 -63
  37. package/docs/public/pano.png +0 -0
  38. package/docs/public/pano2.png +0 -0
  39. package/docs/public/timing-range.svg +0 -176
  40. package/docs/public/timing.md +0 -483
  41. package/docs/timing-range.svg +0 -174
  42. package/docs/vitest.config.ts +0 -14
  43. package/examples/README.md +0 -241
  44. package/examples/coordinates-example.ts +0 -253
  45. package/examples/multi-level-keys.ts +0 -382
  46. package/examples/registry-hub-coordinates-example.ts +0 -370
  47. package/examples/registry-hub-types.ts +0 -437
  48. package/examples/registry-statistics-example.ts +0 -264
  49. package/examples/simple-example.ts +0 -250
  50. package/tsconfig.docs.json +0 -28
  51. package/vitest.config.ts +0 -22
@@ -1,389 +0,0 @@
1
- # `get` Operation
2
-
3
- Retrieve a single item by its key with automatic error handling and retry logic.
4
-
5
- ## Syntax
6
-
7
- ### Primary Items (PItemApi)
8
- ```typescript
9
- async get(key: PriKey<S>): Promise<V | null>
10
- ```
11
-
12
- ### Contained Items (CItemApi)
13
- ```typescript
14
- async get(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<V | null>
15
- ```
16
-
17
- ## Parameters
18
-
19
- | Parameter | Type | Required | Description |
20
- |-----------|------|----------|-------------|
21
- | `key` | `PriKey<S>` or `ComKey<S, ...>` | Yes | Key identifying the item to retrieve |
22
-
23
- ### Key Types
24
-
25
- ```typescript
26
- // Primary Key (for PItemApi)
27
- interface PriKey<S> {
28
- keyType: S;
29
- pk: string;
30
- }
31
-
32
- // Composite Key (for CItemApi)
33
- interface ComKey<S, L1, L2, L3, L4, L5> {
34
- keyType: S;
35
- pk: string;
36
- l1?: LocKey<L1>;
37
- l2?: LocKey<L2>;
38
- // ... up to l5
39
- }
40
- ```
41
-
42
- ## Examples
43
-
44
- ### Basic Usage
45
-
46
- ```typescript
47
- // Get a user by ID
48
- const userKey = { keyType: 'user', pk: 'user-123' };
49
- const user = await userApi.get(userKey);
50
-
51
- if (user) {
52
- console.log('Found user:', user.name);
53
- } else {
54
- console.log('User not found');
55
- }
56
- ```
57
-
58
- ### Contained Items
59
-
60
- ```typescript
61
- // Get a task with composite key
62
- const taskKey = {
63
- keyType: 'task',
64
- pk: 'task-456',
65
- l1: { lkType: 'user', lk: 'user-123' }
66
- };
67
-
68
- const task = await taskApi.get(taskKey);
69
- ```
70
-
71
- ### Error Handling
72
-
73
- ```typescript
74
- try {
75
- const user = await userApi.get(userKey);
76
-
77
- if (!user) {
78
- console.log('User not found - this is normal');
79
- return;
80
- }
81
-
82
- console.log('User found:', user.name);
83
-
84
- } catch (error) {
85
- if (error.code === 'NETWORK_ERROR') {
86
- console.error('Network issue - operation was automatically retried');
87
- } else if (error.code === 'AUTHENTICATION_ERROR') {
88
- console.error('Authentication failed - check credentials');
89
- } else {
90
- console.error('Unexpected error:', error.message);
91
- }
92
- }
93
- ```
94
-
95
- ### Null Handling Patterns
96
-
97
- ```typescript
98
- // Pattern 1: Explicit null check
99
- const user = await userApi.get(userKey);
100
- if (user === null) {
101
- throw new Error('User not found');
102
- }
103
- // user is now typed as V (not null)
104
-
105
- // Pattern 2: Default fallback
106
- const user = await userApi.get(userKey) ?? createDefaultUser();
107
-
108
- // Pattern 3: Optional chaining
109
- const userName = (await userApi.get(userKey))?.name ?? 'Unknown';
110
- ```
111
-
112
- ## Return Value
113
-
114
- Returns `Promise<V | null>`:
115
- - **V**: The found item with all its properties
116
- - **null**: When item is not found (404 response)
117
-
118
- ```typescript
119
- // Found item structure
120
- const user = await userApi.get(userKey);
121
- // {
122
- // id: 'user-123',
123
- // name: 'John Doe',
124
- // email: 'john@example.com',
125
- // active: true,
126
- // createdAt: '2024-01-15T10:30:00Z',
127
- // updatedAt: '2024-01-20T14:22:00Z',
128
- // keyType: 'user'
129
- // }
130
-
131
- // Not found
132
- const missingUser = await userApi.get({ keyType: 'user', pk: 'nonexistent' });
133
- // null
134
- ```
135
-
136
- ## Performance Optimization
137
-
138
- ### Caching Strategies
139
-
140
- ```typescript
141
- // Simple memory cache
142
- const userCache = new Map<string, User>();
143
-
144
- async function getCachedUser(userKey: PriKey<'user'>): Promise<User | null> {
145
- const cacheKey = `user:${userKey.pk}`;
146
-
147
- // Check cache first
148
- if (userCache.has(cacheKey)) {
149
- return userCache.get(cacheKey)!;
150
- }
151
-
152
- // Fetch from API
153
- const user = await userApi.get(userKey);
154
-
155
- // Cache the result (including null)
156
- if (user) {
157
- userCache.set(cacheKey, user);
158
- }
159
-
160
- return user;
161
- }
162
- ```
163
-
164
- ### Batch Loading
165
-
166
- ```typescript
167
- // Load multiple items efficiently
168
- async function getUsersBatch(userKeys: PriKey<'user'>[]): Promise<(User | null)[]> {
169
- // Use Promise.all for parallel requests
170
- const promises = userKeys.map(key =>
171
- userApi.get(key).catch(error => {
172
- console.error(`Failed to load user ${key.pk}:`, error.message);
173
- return null;
174
- })
175
- );
176
-
177
- return Promise.all(promises);
178
- }
179
- ```
180
-
181
- ## Advanced Patterns
182
-
183
- ### Safe Get with Type Guards
184
-
185
- ```typescript
186
- // Type-safe retrieval with validation
187
- async function getValidUser(userKey: PriKey<'user'>): Promise<User> {
188
- const user = await userApi.get(userKey);
189
-
190
- if (!user) {
191
- throw new Error(`User ${userKey.pk} not found`);
192
- }
193
-
194
- if (!user.active) {
195
- throw new Error(`User ${userKey.pk} is inactive`);
196
- }
197
-
198
- return user;
199
- }
200
- ```
201
-
202
- ### Retry with Custom Logic
203
-
204
- ```typescript
205
- // Get with custom retry behavior
206
- async function getWithRetry<T>(
207
- apiCall: () => Promise<T | null>,
208
- maxAttempts: number = 3,
209
- delay: number = 1000
210
- ): Promise<T | null> {
211
- for (let attempt = 1; attempt <= maxAttempts; attempt++) {
212
- try {
213
- return await apiCall();
214
- } catch (error) {
215
- if (attempt === maxAttempts) throw error;
216
-
217
- console.log(`Attempt ${attempt} failed, retrying in ${delay}ms...`);
218
- await new Promise(resolve => setTimeout(resolve, delay));
219
- delay *= 2; // Exponential backoff
220
- }
221
- }
222
- return null;
223
- }
224
-
225
- // Usage
226
- const user = await getWithRetry(() => userApi.get(userKey));
227
- ```
228
-
229
- ### Get with Fallback Chain
230
-
231
- ```typescript
232
- // Try multiple sources for data
233
- async function getUserWithFallbacks(userId: string): Promise<User | null> {
234
- const userKey = { keyType: 'user' as const, pk: userId };
235
-
236
- // Try primary API
237
- try {
238
- const user = await userApi.get(userKey);
239
- if (user) return user;
240
- } catch (error) {
241
- console.warn('Primary API failed:', error.message);
242
- }
243
-
244
- // Try backup API
245
- try {
246
- const user = await backupUserApi.get(userKey);
247
- if (user) return user;
248
- } catch (error) {
249
- console.warn('Backup API failed:', error.message);
250
- }
251
-
252
- // Try cache
253
- try {
254
- const cachedUser = await getUserFromCache(userId);
255
- if (cachedUser) return cachedUser;
256
- } catch (error) {
257
- console.warn('Cache failed:', error.message);
258
- }
259
-
260
- return null;
261
- }
262
- ```
263
-
264
- ## Common Use Cases
265
-
266
- ### User Profile Loading
267
-
268
- ```typescript
269
- // Load user with profile data
270
- async function loadUserProfile(userId: string) {
271
- const userKey = { keyType: 'user' as const, pk: userId };
272
- const user = await userApi.get(userKey);
273
-
274
- if (!user) {
275
- throw new Error('User not found');
276
- }
277
-
278
- // Load related data
279
- const [profile, preferences, activity] = await Promise.all([
280
- profileApi.get({ keyType: 'profile', pk: userId }),
281
- preferencesApi.get({ keyType: 'preferences', pk: userId }),
282
- activityApi.allFacet('recent-activity', { limit: 10 }, [userId])
283
- ]);
284
-
285
- return {
286
- user,
287
- profile,
288
- preferences,
289
- activity
290
- };
291
- }
292
- ```
293
-
294
- ### Resource Validation
295
-
296
- ```typescript
297
- // Validate resource exists before operation
298
- async function updateUserIfExists(
299
- userKey: PriKey<'user'>,
300
- updates: Partial<User>
301
- ): Promise<User | null> {
302
- const user = await userApi.get(userKey);
303
-
304
- if (!user) {
305
- console.log('User not found, skipping update');
306
- return null;
307
- }
308
-
309
- // User exists, proceed with update
310
- return await userApi.update(userKey, updates);
311
- }
312
- ```
313
-
314
- ### Conditional Operations
315
-
316
- ```typescript
317
- // Perform operation based on item state
318
- async function processUserBasedOnState(userKey: PriKey<'user'>) {
319
- const user = await userApi.get(userKey);
320
-
321
- if (!user) {
322
- console.log('User not found');
323
- return;
324
- }
325
-
326
- switch (user.status) {
327
- case 'pending':
328
- await userApi.action(userKey, 'send-welcome-email');
329
- break;
330
-
331
- case 'active':
332
- await userApi.action(userKey, 'update-last-seen');
333
- break;
334
-
335
- case 'suspended':
336
- console.log('User is suspended, no action taken');
337
- break;
338
-
339
- default:
340
- console.log('Unknown user status:', user.status);
341
- }
342
- }
343
- ```
344
-
345
- ## Error Scenarios
346
-
347
- ### Network Issues
348
-
349
- ```typescript
350
- // Automatic retry handles network issues
351
- try {
352
- const user = await userApi.get(userKey);
353
- // Network errors are automatically retried
354
- } catch (error) {
355
- // Only non-retryable errors reach here
356
- if (error.code === 'NETWORK_ERROR') {
357
- // All retries exhausted
358
- console.error('Network completely unavailable');
359
- }
360
- }
361
- ```
362
-
363
- ### Authorization
364
-
365
- ```typescript
366
- // Handle permission issues
367
- try {
368
- const user = await userApi.get(userKey);
369
- } catch (error) {
370
- if (error.code === 'AUTHORIZATION_ERROR') {
371
- console.error('Insufficient permissions to access user');
372
- // Redirect to login or show error message
373
- }
374
- }
375
- ```
376
-
377
- ## Related Operations
378
-
379
- - [`all`](./all.md) - Get multiple items
380
- - [`one`](./one.md) - Get single item with query
381
- - [`find`](./find.md) - Find items with custom finders
382
- - [`create`](./create.md) - Create new items
383
- - [`update`](./update.md) - Update existing items
384
-
385
- ## Next Steps
386
-
387
- - Explore [Caching Strategies](../guides/caching.md)
388
- - Learn about [Error Handling](../error-handling/README.md)
389
- - Review [Performance Optimization](../guides/performance.md)
@@ -1,63 +0,0 @@
1
- {
2
- "name": "@fjell/registry",
3
- "version": "4.4.11",
4
- "keywords": [
5
- "registry",
6
- "fjell"
7
- ],
8
- "license": "Apache-2.0",
9
- "description": "Common Registry for Fjell",
10
- "engines": {
11
- "node": ">=21"
12
- },
13
- "main": "dist/index.cjs",
14
- "module": "dist/index.js",
15
- "exports": {
16
- ".": {
17
- "types": "./dist/index.d.ts",
18
- "require": "./dist/index.cjs",
19
- "import": "./dist/index.js"
20
- }
21
- },
22
- "type": "module",
23
- "scripts": {
24
- "build": "tsc --noEmit && vite build",
25
- "dev": "concurrently \"tsc --watch --noEmit\" \"vite build --watch\"",
26
- "lint": "eslint . --ext .ts --fix",
27
- "clean": "rm -rf dist",
28
- "test": "npm run lint && vitest run --coverage",
29
- "test:memory:optimized": "npm run lint && NODE_OPTIONS=\"--max-old-space-size=8192 --max-semi-space-size=1024\" vitest run tests/memory.test.ts",
30
- "test:timing:optimized": "npm run lint && NODE_OPTIONS=\"--max-old-space-size=8192 --max-semi-space-size=1024\" vitest run tests/timing.test.ts",
31
- "prepublishOnly": "npm run clean && npm run build"
32
- },
33
- "dependencies": {
34
- "@fjell/core": "^4.4.7",
35
- "@fjell/logging": "^4.4.7",
36
- "deepmerge": "^4.3.1"
37
- },
38
- "devDependencies": {
39
- "@eslint/eslintrc": "^3.3.1",
40
- "@eslint/js": "^9.31.0",
41
- "@swc/core": "^1.13.1",
42
- "@tsconfig/recommended": "^1.0.10",
43
- "@types/multer": "^2.0.0",
44
- "@types/node": "^24.0.15",
45
- "@typescript-eslint/eslint-plugin": "^8.37.0",
46
- "@typescript-eslint/parser": "^8.37.0",
47
- "@vitest/coverage-v8": "^3.2.4",
48
- "concurrently": "^9.2.0",
49
- "eslint": "^9.31.0",
50
- "nodemon": "^3.1.10",
51
- "ts-node": "^10.9.2",
52
- "tsc-alias": "^1.8.16",
53
- "typescript": "^5.8.3",
54
- "vite": "^7.0.5",
55
- "vite-plugin-dts": "^4.5.4",
56
- "vite-plugin-node": "^7.0.0",
57
- "vitest": "^3.2.4"
58
- },
59
- "repository": {
60
- "type": "git",
61
- "url": "git+https://github.com/getfjell/registry.git"
62
- }
63
- }
Binary file
Binary file
@@ -1,176 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <svg width="1200" height="800" xmlns="http://www.w3.org/2000/svg">
3
- <style>
4
- .axis { stroke: #333; stroke-width: 1; }
5
- .grid { stroke: #ddd; stroke-width: 0.5; }
6
- .label { font-family: Arial, sans-serif; font-size: 14px; fill: #333; }
7
- .title { font-family: Arial, sans-serif; font-size: 16px; font-weight: bold; fill: #333; }
8
- .subtitle { font-family: Arial, sans-serif; font-size: 12px; fill: #666; }
9
- .register-mean { stroke: #e74c3c; stroke-width: 3; fill: none; }
10
- .lookup-mean { stroke: #3498db; stroke-width: 3; fill: none; }
11
- .register-band { fill: rgba(231, 76, 60, 0.2); stroke: #e74c3c; stroke-width: 1; }
12
- .lookup-band { fill: rgba(52, 152, 219, 0.2); stroke: #3498db; stroke-width: 1; }
13
- .register-dot { fill: #e74c3c; }
14
- .lookup-dot { fill: #3498db; }
15
- .legend { font-family: Arial, sans-serif; font-size: 12px; fill: #333; }
16
- .axis-title { font-family: Arial, sans-serif; font-size: 16px; font-weight: bold; fill: #333; }
17
- .metadata-title { font-family: Arial, sans-serif; font-size: 14px; font-weight: bold; fill: #333; }
18
- .metadata-section { font-family: Arial, sans-serif; font-size: 14px; font-weight: bold; fill: #444; }
19
- .metadata-label { font-family: Arial, sans-serif; font-size: 10px; fill: #666; }
20
- .metadata-value { font-family: Arial, sans-serif; font-size: 10px; fill: #333; }
21
- </style>
22
-
23
- <!-- Background -->
24
- <rect width="1200" height="800" fill="white"/>
25
-
26
- <!-- Title -->
27
- <text x="600" y="25" text-anchor="middle" class="title">Timing of Common Registry Operations</text>
28
- <text x="600" y="45" text-anchor="middle" class="subtitle">Performance measurements across varying tree sizes</text>
29
-
30
- <!-- Plot area -->
31
- <g transform="translate(110,60)">
32
-
33
- <!-- Grid lines (logarithmic scale) -->
34
- <line x1="0" y1="405.47941100296094" x2="1015" y2="405.47941100296094" class="grid"/>
35
- <text x="-10" y="409.47941100296094" text-anchor="end" class="label">0.05µs</text>
36
- <line x1="0" y1="344.44867833493345" x2="1015" y2="344.44867833493345" class="grid"/>
37
- <text x="-10" y="348.44867833493345" text-anchor="end" class="label">0.10µs</text>
38
- <line x1="0" y1="283.41794566690595" x2="1015" y2="283.41794566690595" class="grid"/>
39
- <text x="-10" y="287.41794566690595" text-anchor="end" class="label">0.20µs</text>
40
- <line x1="0" y1="202.7397055014805" x2="1015" y2="202.7397055014805" class="grid"/>
41
- <text x="-10" y="206.7397055014805" text-anchor="end" class="label">0.50µs</text>
42
- <line x1="0" y1="141.708972833453" x2="1015" y2="141.708972833453" class="grid"/>
43
- <text x="-10" y="145.708972833453" text-anchor="end" class="label">1.0µs</text>
44
- <line x1="0" y1="80.6782401654255" x2="1015" y2="80.6782401654255" class="grid"/>
45
- <text x="-10" y="84.6782401654255" text-anchor="end" class="label">2.0µs</text>
46
- <line x1="0" y1="0" x2="1015" y2="0" class="grid"/>
47
- <text x="-10" y="4" text-anchor="end" class="label">5.0µs</text>
48
- <line x1="0" y1="0" x2="0" y2="460" class="grid"/>
49
- <text x="0" y="480" text-anchor="middle" class="label">10</text>
50
- <line x1="76.38636139973525" y1="0" x2="76.38636139973525" y2="460" class="grid"/>
51
- <text x="76.38636139973525" y="480" text-anchor="middle" class="label">20</text>
52
- <line x1="177.36363860026475" y1="0" x2="177.36363860026475" y2="460" class="grid"/>
53
- <text x="177.36363860026475" y="480" text-anchor="middle" class="label">50</text>
54
- <line x1="253.75" y1="0" x2="253.75" y2="460" class="grid"/>
55
- <text x="253.75" y="480" text-anchor="middle" class="label">100</text>
56
- <line x1="330.1363613997352" y1="0" x2="330.1363613997352" y2="460" class="grid"/>
57
- <text x="330.1363613997352" y="480" text-anchor="middle" class="label">200</text>
58
- <line x1="431.1136386002648" y1="0" x2="431.1136386002648" y2="460" class="grid"/>
59
- <text x="431.1136386002648" y="480" text-anchor="middle" class="label">500</text>
60
- <line x1="507.5" y1="0" x2="507.5" y2="460" class="grid"/>
61
- <text x="507.5" y="480" text-anchor="middle" class="label">1k</text>
62
- <line x1="583.8863613997353" y1="0" x2="583.8863613997353" y2="460" class="grid"/>
63
- <text x="583.8863613997353" y="480" text-anchor="middle" class="label">2k</text>
64
- <line x1="684.8636386002647" y1="0" x2="684.8636386002647" y2="460" class="grid"/>
65
- <text x="684.8636386002647" y="480" text-anchor="middle" class="label">5k</text>
66
- <line x1="761.25" y1="0" x2="761.25" y2="460" class="grid"/>
67
- <text x="761.25" y="480" text-anchor="middle" class="label">10k</text>
68
- <line x1="837.6363613997353" y1="0" x2="837.6363613997353" y2="460" class="grid"/>
69
- <text x="837.6363613997353" y="480" text-anchor="middle" class="label">20k</text>
70
- <line x1="938.6136386002647" y1="0" x2="938.6136386002647" y2="460" class="grid"/>
71
- <text x="938.6136386002647" y="480" text-anchor="middle" class="label">50k</text>
72
- <line x1="1015" y1="0" x2="1015" y2="460" class="grid"/>
73
- <text x="1015" y="480" text-anchor="middle" class="label">100k</text>
74
- <!-- Y-axis -->
75
- <line x1="0" y1="0" x2="0" y2="460" class="axis"/>
76
-
77
- <!-- X-axis -->
78
- <line x1="0" y1="460" x2="1015" y2="460" class="axis"/>
79
-
80
- <!-- Axis labels -->
81
- <text x="507.5" y="510" text-anchor="middle" class="axis-title">Tree Size (items) - Log Scale</text>
82
- <text transform="rotate(-90,-70,230)" x="-70" y="230" text-anchor="middle" class="axis-title">Execution Time (µs)</text>
83
- <path d="M 0 148.74050590256667 L 76.38636139973525 148.7524277923311 L 177.36363860026475 148.44013071796422 L 253.75 163.96828165051454 L 330.1363613997352 162.08556246017355 L 431.1136386002648 172.30055096042298 L 507.5 164.83245476448178 L 583.8863613997353 182.97393995516205 L 684.8636386002647 169.94194464665668 L 761.25 151.0989993965061 L 837.6363613997353 160.0780931612813 L 938.6136386002647 148.48776057676235 L 1015 120.43534569475918" class="register-mean"/>
84
- <path d="M 0 391.3646719514693 L 76.38636139973525 388.54139718542586 L 177.36363860026475 389.0557369024966 L 253.75 374.3747740786199 L 330.1363613997352 398.9692673319725 L 431.1136386002648 360.0500990825511 L 507.5 360.0275016662577 L 583.8863613997353 305.0657993375811 L 684.8636386002647 300.3208350816295 L 761.25 264.9832596121842 L 837.6363613997353 268.5823457977558 L 938.6136386002647 288.5555639615857 L 1015 247.60931540724576" class="lookup-mean"/>
85
- <circle cx="0" cy="148.74050590256667" r="4" class="register-dot"/>
86
- <circle cx="76.38636139973525" cy="148.7524277923311" r="4" class="register-dot"/>
87
- <circle cx="177.36363860026475" cy="148.44013071796422" r="4" class="register-dot"/>
88
- <circle cx="253.75" cy="163.96828165051454" r="4" class="register-dot"/>
89
- <circle cx="330.1363613997352" cy="162.08556246017355" r="4" class="register-dot"/>
90
- <circle cx="431.1136386002648" cy="172.30055096042298" r="4" class="register-dot"/>
91
- <circle cx="507.5" cy="164.83245476448178" r="4" class="register-dot"/>
92
- <circle cx="583.8863613997353" cy="182.97393995516205" r="4" class="register-dot"/>
93
- <circle cx="684.8636386002647" cy="169.94194464665668" r="4" class="register-dot"/>
94
- <circle cx="761.25" cy="151.0989993965061" r="4" class="register-dot"/>
95
- <circle cx="837.6363613997353" cy="160.0780931612813" r="4" class="register-dot"/>
96
- <circle cx="938.6136386002647" cy="148.48776057676235" r="4" class="register-dot"/>
97
- <circle cx="1015" cy="120.43534569475918" r="4" class="register-dot"/>
98
- <circle cx="0" cy="391.3646719514693" r="4" class="lookup-dot"/>
99
- <circle cx="76.38636139973525" cy="388.54139718542586" r="4" class="lookup-dot"/>
100
- <circle cx="177.36363860026475" cy="389.0557369024966" r="4" class="lookup-dot"/>
101
- <circle cx="253.75" cy="374.3747740786199" r="4" class="lookup-dot"/>
102
- <circle cx="330.1363613997352" cy="398.9692673319725" r="4" class="lookup-dot"/>
103
- <circle cx="431.1136386002648" cy="360.0500990825511" r="4" class="lookup-dot"/>
104
- <circle cx="507.5" cy="360.0275016662577" r="4" class="lookup-dot"/>
105
- <circle cx="583.8863613997353" cy="305.0657993375811" r="4" class="lookup-dot"/>
106
- <circle cx="684.8636386002647" cy="300.3208350816295" r="4" class="lookup-dot"/>
107
- <circle cx="761.25" cy="264.9832596121842" r="4" class="lookup-dot"/>
108
- <circle cx="837.6363613997353" cy="268.5823457977558" r="4" class="lookup-dot"/>
109
- <circle cx="938.6136386002647" cy="288.5555639615857" r="4" class="lookup-dot"/>
110
- <circle cx="1015" cy="247.60931540724576" r="4" class="lookup-dot"/>
111
- <!-- Legend -->
112
- <g transform="translate(20, 20)">
113
- <rect x="0" y="0" width="190" height="80" fill="white" stroke="#ccc" stroke-width="1"/>
114
-
115
- <!-- Register Instance Legend -->
116
- <text x="10" y="20" class="legend" font-weight="bold">Register Instance</text>
117
- <line x1="10" y1="30" x2="40" y2="30" class="register-mean"/>
118
- <circle cx="25" cy="30" r="3" class="register-dot"/>
119
- <text x="45" y="34" class="legend">Average Timing</text>
120
-
121
- <!-- Lookup Instance Legend -->
122
- <text x="10" y="55" class="legend" font-weight="bold">Lookup Instance</text>
123
- <line x1="10" y1="65" x2="40" y2="65" class="lookup-mean"/>
124
- <circle cx="25" cy="65" r="3" class="lookup-dot"/>
125
- <text x="45" y="69" class="legend">Average Timing</text>
126
- </g>
127
-
128
- </g>
129
-
130
- <!-- Test Metadata Section -->
131
- <g transform="translate(50, 620)">
132
- <!-- Left Column: System Information -->
133
- <g transform="translate(20, 20)">
134
- <text x="0" y="0" class="metadata-section">System Information</text>
135
-
136
- <text x="0" y="25" class="metadata-label">Test Date:</text>
137
- <text x="150" y="25" class="metadata-value">2025-07-21</text>
138
-
139
- <text x="0" y="45" class="metadata-label">Package Version:</text>
140
- <text x="150" y="45" class="metadata-value">@fjell/registry v4.4.5</text>
141
-
142
- <text x="0" y="65" class="metadata-label">Node.js Version:</text>
143
- <text x="150" y="65" class="metadata-value">v22.0.0 (darwin arm64)</text>
144
-
145
- <text x="0" y="85" class="metadata-label">Platform:</text>
146
- <text x="150" y="85" class="metadata-value">darwin arm64</text>
147
-
148
- <text x="0" y="105" class="metadata-label">Compiler:</text>
149
- <text x="150" y="105" class="metadata-value">TypeScript + Vite</text>
150
- </g>
151
-
152
- <!-- Center Column: Test Configuration -->
153
- <g transform="translate(330, 20)">
154
- <text x="0" y="0" class="metadata-section">Test Configuration</text>
155
-
156
- <text x="0" y="25" class="metadata-label">Test Rounds:</text>
157
- <text x="120" y="25" class="metadata-value">100 per tree size</text>
158
-
159
- <text x="0" y="45" class="metadata-label">Iterations per Round:</text>
160
- <text x="120" y="45" class="metadata-value">200 operations</text>
161
-
162
- <text x="0" y="65" class="metadata-label">Total Measurements:</text>
163
- <text x="120" y="65" class="metadata-value">20,000 per data point</text>
164
- </g>
165
-
166
- <!-- Right Column: Test Notes -->
167
- <g transform="translate(600, 20)">
168
- <text x="0" y="0" class="metadata-section">Test Notes</text>
169
- <text x="0" y="25" class="metadata-label">• Performance measurements use Node.js performance.now() with microsecond precision</text>
170
- <text x="0" y="42" class="metadata-label">• Each test includes warm-up iterations to minimize JIT compilation effects</text>
171
- <text x="0" y="59" class="metadata-label">• Logging is mocked during timing tests to eliminate I/O overhead</text>
172
- <text x="0" y="76" class="metadata-label">• Tests verify both mean performance and consistency (low standard deviation)</text>
173
- <text x="0" y="93" class="metadata-label">• Statistical analysis ensures reliable performance measurements across all tree sizes</text>
174
- </g>
175
- </g>
176
- </svg>