@fjell/registry 4.4.10 → 4.4.13

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 (41) hide show
  1. package/MIGRATION_SUMMARY.md +200 -0
  2. package/dist/Registry.cjs +36 -3
  3. package/dist/Registry.js +36 -3
  4. package/dist/RegistryStats.cjs +200 -0
  5. package/dist/RegistryStats.d.ts +103 -0
  6. package/dist/RegistryStats.js +196 -0
  7. package/dist/index.cjs +229 -2
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.js +2 -1
  11. package/dist/types.d.ts +7 -0
  12. package/docs/README.md +5 -5
  13. package/docs/docs.config.ts +110 -0
  14. package/docs/index.html +1 -1
  15. package/docs/package.json +2 -4
  16. package/docs/public/api.md +527 -0
  17. package/docs/public/package.json +65 -0
  18. package/docs/src/index.css +1 -7
  19. package/docs/src/main.tsx +4 -2
  20. package/docs/src/types.d.ts +10 -0
  21. package/examples/README.md +19 -0
  22. package/examples/registry-statistics-example.ts +264 -0
  23. package/package.json +8 -7
  24. package/docs/memory-data/scaling-10-instances.json +0 -526
  25. package/docs/memory-data/scaling-100-instances.json +0 -526
  26. package/docs/memory-data/scaling-1000-instances.json +0 -276
  27. package/docs/memory-data/scaling-10000-instances.json +0 -126
  28. package/docs/memory-data/scaling-20-instances.json +0 -526
  29. package/docs/memory-data/scaling-200-instances.json +0 -526
  30. package/docs/memory-data/scaling-2000-instances.json +0 -276
  31. package/docs/memory-data/scaling-50-instances.json +0 -526
  32. package/docs/memory-data/scaling-500-instances.json +0 -276
  33. package/docs/memory-data/scaling-5000-instances.json +0 -126
  34. package/docs/memory-overhead.svg +0 -120
  35. package/docs/memory.md +0 -430
  36. package/docs/src/App.css +0 -1175
  37. package/docs/src/App.test.tsx +0 -50
  38. package/docs/src/App.tsx +0 -583
  39. package/docs/timing-range.svg +0 -174
  40. package/docs/timing.md +0 -483
  41. package/docs/tsconfig.node.json +0 -13
@@ -0,0 +1,527 @@
1
+ # Fjell Core API Reference
2
+
3
+ Complete API documentation for all Fjell Core modules and utilities.
4
+
5
+ ## Overview
6
+
7
+ Fjell Core provides essential item management, key utilities, and service coordination for the entire Fjell ecosystem. This reference covers all public APIs, interfaces, and utilities.
8
+
9
+ ## Core Modules
10
+
11
+ ### IFactory - Item Factory
12
+
13
+ The IFactory provides type-safe item creation with validation and configuration support.
14
+
15
+ #### Methods
16
+
17
+ ##### `create<T>(type: string, data: Partial<T>): T`
18
+
19
+ Creates a new item of the specified type with type safety.
20
+
21
+ **Parameters:**
22
+ - `type` - String identifier for the item type
23
+ - `data` - Partial item data to initialize the item
24
+
25
+ **Returns:** Fully constructed item of type T
26
+
27
+ **Example:**
28
+ ```typescript
29
+ import { IFactory } from '@fjell/core'
30
+
31
+ interface User {
32
+ id: string
33
+ name: string
34
+ email: string
35
+ }
36
+
37
+ const user = IFactory.create<User>('user', {
38
+ id: 'user-123',
39
+ name: 'John Doe',
40
+ email: 'john@example.com'
41
+ })
42
+ ```
43
+
44
+ ##### `createWithDefaults<T>(type: string, data: Partial<T>, defaults: Partial<T>): T`
45
+
46
+ Creates an item with default values applied when properties are missing.
47
+
48
+ **Parameters:**
49
+ - `type` - String identifier for the item type
50
+ - `data` - Partial item data
51
+ - `defaults` - Default values to apply for missing properties
52
+
53
+ **Returns:** Constructed item with defaults applied
54
+
55
+ ---
56
+
57
+ ### KUtils - Key Utilities
58
+
59
+ Utilities for hierarchical key generation, parsing, and manipulation.
60
+
61
+ #### Methods
62
+
63
+ ##### `generateKey(components: string[]): string`
64
+
65
+ Generates a hierarchical key from an array of components.
66
+
67
+ **Parameters:**
68
+ - `components` - Array of string components to join
69
+
70
+ **Returns:** Generated key string with proper separators
71
+
72
+ **Example:**
73
+ ```typescript
74
+ import { KUtils } from '@fjell/core'
75
+
76
+ const userKey = KUtils.generateKey(['users', 'user-123'])
77
+ // Returns: "users:user-123"
78
+
79
+ const profileKey = KUtils.generateKey(['users', 'user-123', 'profile'])
80
+ // Returns: "users:user-123:profile"
81
+ ```
82
+
83
+ ##### `parseKey(key: string): string[]`
84
+
85
+ Parses a hierarchical key back into its component parts.
86
+
87
+ **Parameters:**
88
+ - `key` - Key string to parse
89
+
90
+ **Returns:** Array of key components
91
+
92
+ **Example:**
93
+ ```typescript
94
+ const components = KUtils.parseKey('users:user-123:profile')
95
+ // Returns: ['users', 'user-123', 'profile']
96
+ ```
97
+
98
+ ##### `isValidKey(key: string): boolean`
99
+
100
+ Validates whether a key is properly formatted according to Fjell standards.
101
+
102
+ **Parameters:**
103
+ - `key` - Key string to validate
104
+
105
+ **Returns:** Boolean indicating if the key is valid
106
+
107
+ ##### `getParentKey(key: string): string | null`
108
+
109
+ Gets the parent key by removing the last component.
110
+
111
+ **Parameters:**
112
+ - `key` - Child key
113
+
114
+ **Returns:** Parent key string or null if no parent exists
115
+
116
+ **Example:**
117
+ ```typescript
118
+ const parentKey = KUtils.getParentKey('users:user-123:profile')
119
+ // Returns: "users:user-123"
120
+ ```
121
+
122
+ ---
123
+
124
+ ### AItemService - Abstract Service Base
125
+
126
+ Abstract base class for building domain-specific services with common patterns.
127
+
128
+ #### Properties
129
+
130
+ ##### `logger: Logger`
131
+ Logger instance for the service (when logging is configured).
132
+
133
+ #### Methods
134
+
135
+ ##### `validate<T>(item: T): Promise<void>`
136
+
137
+ Validates an item according to service-specific rules. Override in subclasses.
138
+
139
+ **Parameters:**
140
+ - `item` - Item to validate
141
+
142
+ **Throws:** ValidationError if validation fails
143
+
144
+ ##### `save<T>(item: T): Promise<T>`
145
+
146
+ Saves an item to the underlying storage. Override in subclasses.
147
+
148
+ **Parameters:**
149
+ - `item` - Item to save
150
+
151
+ **Returns:** Promise resolving to the saved item
152
+
153
+ ##### `findById<T>(id: string): Promise<T | null>`
154
+
155
+ Finds an item by its identifier. Override in subclasses.
156
+
157
+ **Parameters:**
158
+ - `id` - Item identifier
159
+
160
+ **Returns:** Promise resolving to the found item or null
161
+
162
+ ##### `delete(id: string): Promise<void>`
163
+
164
+ Deletes an item by its identifier. Override in subclasses.
165
+
166
+ **Parameters:**
167
+ - `id` - Item identifier to delete
168
+
169
+ **Example:**
170
+ ```typescript
171
+ import { AItemService, IFactory } from '@fjell/core'
172
+
173
+ class UserService extends AItemService {
174
+ private users = new Map<string, User>()
175
+
176
+ async save<User>(user: User): Promise<User> {
177
+ // Custom save logic
178
+ this.users.set(user.id, user)
179
+ return user
180
+ }
181
+
182
+ async findById(id: string): Promise<User | null> {
183
+ return this.users.get(id) || null
184
+ }
185
+
186
+ async validate(user: User): Promise<void> {
187
+ if (!user.email?.includes('@')) {
188
+ throw new Error('Valid email required')
189
+ }
190
+ }
191
+ }
192
+ ```
193
+
194
+ ---
195
+
196
+ ### IQFactory - Query Factory
197
+
198
+ Factory for building complex queries for data retrieval.
199
+
200
+ #### Methods
201
+
202
+ ##### `create(type: string): QueryBuilder`
203
+
204
+ Creates a new query builder for the specified entity type.
205
+
206
+ **Parameters:**
207
+ - `type` - Entity type to query
208
+
209
+ **Returns:** QueryBuilder instance for method chaining
210
+
211
+ **Example:**
212
+ ```typescript
213
+ import { IQFactory } from '@fjell/core'
214
+
215
+ const query = IQFactory.create('user')
216
+ .where('status', 'active')
217
+ .where('age', '>', 18)
218
+ .orderBy('createdAt', 'desc')
219
+ .limit(10)
220
+ ```
221
+
222
+ ---
223
+
224
+ ### QueryBuilder
225
+
226
+ Fluent interface for constructing queries with filters, sorting, and pagination.
227
+
228
+ #### Methods
229
+
230
+ ##### `where(field: string, value: any): QueryBuilder`
231
+ ##### `where(field: string, operator: string, value: any): QueryBuilder`
232
+
233
+ Adds a where condition to the query.
234
+
235
+ **Parameters:**
236
+ - `field` - Field name to filter on
237
+ - `operator` - Comparison operator ('=', '>', '<', '>=', '<=', '!=', 'like', 'in')
238
+ - `value` - Value to compare against
239
+
240
+ **Returns:** QueryBuilder for method chaining
241
+
242
+ ##### `orderBy(field: string, direction?: 'asc' | 'desc'): QueryBuilder`
243
+
244
+ Adds ordering to the query results.
245
+
246
+ **Parameters:**
247
+ - `field` - Field to order by
248
+ - `direction` - Sort direction (default: 'asc')
249
+
250
+ **Returns:** QueryBuilder for method chaining
251
+
252
+ ##### `limit(count: number): QueryBuilder`
253
+
254
+ Limits the number of results returned.
255
+
256
+ **Parameters:**
257
+ - `count` - Maximum number of results
258
+
259
+ **Returns:** QueryBuilder for method chaining
260
+
261
+ ##### `offset(count: number): QueryBuilder`
262
+
263
+ Sets the number of results to skip (for pagination).
264
+
265
+ **Parameters:**
266
+ - `count` - Number of results to skip
267
+
268
+ **Returns:** QueryBuilder for method chaining
269
+
270
+ ---
271
+
272
+ ### IQUtils - Query Utilities
273
+
274
+ Utilities for executing and manipulating queries.
275
+
276
+ #### Methods
277
+
278
+ ##### `execute<T>(query: QueryBuilder): Promise<T[]>`
279
+
280
+ Executes a query and returns the matching results.
281
+
282
+ **Parameters:**
283
+ - `query` - Query to execute
284
+
285
+ **Returns:** Promise resolving to array of matching items
286
+
287
+ ##### `count(query: QueryBuilder): Promise<number>`
288
+
289
+ Counts the number of results that would be returned by a query.
290
+
291
+ **Parameters:**
292
+ - `query` - Query to count
293
+
294
+ **Returns:** Promise resolving to the count
295
+
296
+ ##### `exists(query: QueryBuilder): Promise<boolean>`
297
+
298
+ Checks if any results exist for the given query.
299
+
300
+ **Parameters:**
301
+ - `query` - Query to check
302
+
303
+ **Returns:** Promise resolving to boolean indicating existence
304
+
305
+ ---
306
+
307
+ ## Core Interfaces
308
+
309
+ ### Item
310
+
311
+ Base interface that all items should extend.
312
+
313
+ ```typescript
314
+ interface Item {
315
+ id: string
316
+ type?: string
317
+ createdAt?: string
318
+ updatedAt?: string
319
+ }
320
+ ```
321
+
322
+ ### ServiceConfig
323
+
324
+ Configuration options for services.
325
+
326
+ ```typescript
327
+ interface ServiceConfig {
328
+ name: string
329
+ version?: string
330
+ logger?: Logger
331
+ enableMetrics?: boolean
332
+ timeout?: number
333
+ }
334
+ ```
335
+
336
+ ### ValidationResult
337
+
338
+ Result of item validation operations.
339
+
340
+ ```typescript
341
+ interface ValidationResult {
342
+ isValid: boolean
343
+ errors: ValidationError[]
344
+ warnings?: ValidationWarning[]
345
+ }
346
+ ```
347
+
348
+ ### WhereCondition
349
+
350
+ Represents a query filter condition.
351
+
352
+ ```typescript
353
+ interface WhereCondition {
354
+ field: string
355
+ operator: string
356
+ value: any
357
+ }
358
+ ```
359
+
360
+ ### OrderByClause
361
+
362
+ Represents a query ordering specification.
363
+
364
+ ```typescript
365
+ interface OrderByClause {
366
+ field: string
367
+ direction: 'asc' | 'desc'
368
+ }
369
+ ```
370
+
371
+ ---
372
+
373
+ ## Error Types
374
+
375
+ ### CoreValidationError
376
+
377
+ Thrown when item validation fails.
378
+
379
+ ```typescript
380
+ class CoreValidationError extends Error {
381
+ details: ValidationDetail[]
382
+ itemType?: string
383
+ }
384
+ ```
385
+
386
+ ### CoreNotFoundError
387
+
388
+ Thrown when a requested item cannot be found.
389
+
390
+ ```typescript
391
+ class CoreNotFoundError extends Error {
392
+ id: string
393
+ itemType?: string
394
+ }
395
+ ```
396
+
397
+ ### CoreOperationError
398
+
399
+ Thrown when a core operation fails.
400
+
401
+ ```typescript
402
+ class CoreOperationError extends Error {
403
+ operation: string
404
+ context?: any
405
+ }
406
+ ```
407
+
408
+ ---
409
+
410
+ ## Usage Patterns
411
+
412
+ ### Repository Pattern
413
+
414
+ ```typescript
415
+ import { AItemService, IFactory, KUtils } from '@fjell/core'
416
+
417
+ class UserRepository extends AItemService {
418
+ private storage = new Map<string, User>()
419
+
420
+ async create(userData: Partial<User>): Promise<User> {
421
+ const user = IFactory.create<User>('user', {
422
+ id: this.generateId(),
423
+ createdAt: new Date().toISOString(),
424
+ ...userData
425
+ })
426
+
427
+ await this.validate(user)
428
+ return this.save(user)
429
+ }
430
+
431
+ async save(user: User): Promise<User> {
432
+ const key = KUtils.generateKey(['users', user.id])
433
+ this.storage.set(key, user)
434
+ return user
435
+ }
436
+
437
+ async findById(id: string): Promise<User | null> {
438
+ const key = KUtils.generateKey(['users', id])
439
+ return this.storage.get(key) || null
440
+ }
441
+
442
+ private generateId(): string {
443
+ return `user-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
444
+ }
445
+ }
446
+ ```
447
+
448
+ ### Query Building
449
+
450
+ ```typescript
451
+ import { IQFactory, IQUtils } from '@fjell/core'
452
+
453
+ // Find active adult users, ordered by creation date
454
+ const activeAdults = await IQUtils.execute(
455
+ IQFactory.create('user')
456
+ .where('status', 'active')
457
+ .where('age', '>=', 18)
458
+ .orderBy('createdAt', 'desc')
459
+ .limit(50)
460
+ )
461
+
462
+ // Check if any admin users exist
463
+ const hasAdmins = await IQUtils.exists(
464
+ IQFactory.create('user')
465
+ .where('role', 'admin')
466
+ )
467
+
468
+ // Count users by status
469
+ const activeCount = await IQUtils.count(
470
+ IQFactory.create('user')
471
+ .where('status', 'active')
472
+ )
473
+ ```
474
+
475
+ ### Service Composition
476
+
477
+ ```typescript
478
+ class UserManagementService extends AItemService {
479
+ constructor(
480
+ private userRepo: UserRepository,
481
+ private emailService: EmailService,
482
+ private auditService: AuditService
483
+ ) {
484
+ super()
485
+ }
486
+
487
+ async registerUser(userData: Partial<User>): Promise<User> {
488
+ // Create user
489
+ const user = await this.userRepo.create(userData)
490
+
491
+ // Send welcome email
492
+ await this.emailService.sendWelcome(user.email)
493
+
494
+ // Log the registration
495
+ await this.auditService.log('user_registered', {
496
+ userId: user.id,
497
+ email: user.email
498
+ })
499
+
500
+ return user
501
+ }
502
+ }
503
+ ```
504
+
505
+ ---
506
+
507
+ ## Testing Utilities
508
+
509
+ Fjell Core provides testing utilities to help with unit and integration tests.
510
+
511
+ ### TestUtils
512
+
513
+ ```typescript
514
+ import { TestUtils } from '@fjell/core/testing'
515
+
516
+ // Create mock instances for testing
517
+ const mockFactory = TestUtils.createMockFactory()
518
+ const mockService = TestUtils.createMockService()
519
+
520
+ // Test helpers
521
+ expect(TestUtils.isValidKey('users:123')).toBe(true)
522
+ expect(TestUtils.getKeyComponents('users:123:profile')).toEqual(['users', '123', 'profile'])
523
+ ```
524
+
525
+ ---
526
+
527
+ This API reference provides comprehensive coverage of all Fjell Core functionality. For practical examples and usage patterns, see the Examples section of the documentation.
@@ -0,0 +1,65 @@
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": "rimraf dist",
28
+ "test": "pnpm run lint && vitest run --coverage",
29
+ "test:memory:optimized": "pnpm run lint && NODE_OPTIONS=\"--max-old-space-size=8192 --max-semi-space-size=1024\" vitest run tests/memory.test.ts",
30
+ "test:timing:optimized": "pnpm run lint && NODE_OPTIONS=\"--max-old-space-size=8192 --max-semi-space-size=1024\" vitest run tests/timing.test.ts",
31
+ "prepublishOnly": "pnpm run clean && pnpm 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
+ "rimraf": "^6.0.1",
52
+ "ts-node": "^10.9.2",
53
+ "tsc-alias": "^1.8.16",
54
+ "typescript": "^5.8.3",
55
+ "vite": "^7.0.5",
56
+ "vite-plugin-dts": "^4.5.4",
57
+ "vite-plugin-node": "^7.0.0",
58
+ "vitest": "^3.2.4"
59
+ },
60
+ "packageManager": "pnpm@10.13.1",
61
+ "repository": {
62
+ "type": "git",
63
+ "url": "git+https://github.com/getfjell/registry.git"
64
+ }
65
+ }
@@ -31,10 +31,4 @@ code {
31
31
  font-size: 0.875em;
32
32
  }
33
33
 
34
- pre code {
35
- display: block;
36
- padding: 1rem;
37
- overflow-x: auto;
38
- border-radius: 0.5rem;
39
- background-color: #1e293b !important;
40
- }
34
+ /* Removed conflicting pre code styles - handled in App.css */
package/docs/src/main.tsx CHANGED
@@ -1,10 +1,12 @@
1
1
  import React from 'react'
2
2
  import ReactDOM from 'react-dom/client'
3
- import App from './App.tsx'
3
+ import { DocsApp } from '@fjell/docs-template'
4
+ import '@fjell/docs-template/dist/index.css'
5
+ import config from '../docs.config'
4
6
  import './index.css'
5
7
 
6
8
  ReactDOM.createRoot(document.getElementById('root')!).render(
7
9
  <React.StrictMode>
8
- <App />
10
+ <DocsApp config={config} />
9
11
  </React.StrictMode>,
10
12
  )
@@ -0,0 +1,10 @@
1
+ declare module '@fjell/docs-template' {
2
+ export * from '../../../fjell-docs-template/src/types'
3
+ export { DocsApp } from '../../../fjell-docs-template/src/components/DocsApp'
4
+ }
5
+
6
+ declare module '../docs.config.js' {
7
+ import type { DocsConfig } from '@fjell/docs-template'
8
+ const config: DocsConfig
9
+ export default config
10
+ }
@@ -33,6 +33,18 @@ Shows how each key path maps to different implementations via scopes using the r
33
33
 
34
34
  Perfect for enterprise applications that need clean separation of concerns and organized service architecture.
35
35
 
36
+ ### 4. `registry-statistics-example.ts` 📊 **Usage Analytics**
37
+ **Track and monitor registry usage patterns with scope-aware analytics!** Demonstrates advanced statistics tracking:
38
+ - **Scope-Aware Tracking**: Separate statistics for each kta + scopes combination
39
+ - **Total Call Monitoring**: Track overall `get()` method usage
40
+ - **Detailed Coordinate Records**: Individual tracking for each service/scope pair
41
+ - **Environment Analysis**: Aggregate statistics by environment (prod/dev)
42
+ - **Most/Least Used Services**: Identify usage patterns and bottlenecks
43
+ - **Immutable Statistics**: Safe access to tracking data without affecting internal state
44
+ - **Normalized Scope Handling**: Consistent tracking regardless of scope order
45
+
46
+ Perfect for monitoring, optimization, understanding service usage patterns, and analyzing environment-specific behavior in production applications.
47
+
36
48
  ## Key Concepts Demonstrated
37
49
 
38
50
  ### Simple Usage (simple-example.ts)
@@ -162,9 +174,16 @@ npx tsx examples/coordinates-example.ts
162
174
  # Run the RegistryHub cross-registry coordinate discovery example
163
175
  npx tsx examples/registry-hub-coordinates-example.ts
164
176
 
177
+ # Run the registry statistics tracking example
178
+ npx tsx examples/registry-statistics-example.ts
179
+
165
180
  # Or in Node.js
166
181
  node -r esbuild-register examples/simple-example.ts
182
+ node -r esbuild-register examples/multi-level-keys.ts
167
183
  node -r esbuild-register examples/registry-hub-types.ts
184
+ node -r esbuild-register examples/coordinates-example.ts
185
+ node -r esbuild-register examples/registry-hub-coordinates-example.ts
186
+ node -r esbuild-register examples/registry-statistics-example.ts
168
187
  ```
169
188
 
170
189
  ## Integration with Real Fjell Registry