@fjell/registry 4.4.11 → 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.
@@ -1,50 +0,0 @@
1
- import { render, screen } from '@testing-library/react'
2
- import { beforeEach, describe, expect, it, vi } from 'vitest'
3
- import App from './App'
4
-
5
- // Mock fetch
6
- const mockFetch = vi.fn()
7
- global.fetch = mockFetch
8
-
9
- describe('App', () => {
10
- beforeEach(() => {
11
- mockFetch.mockClear()
12
- })
13
-
14
- it('renders the main title', () => {
15
- mockFetch.mockResolvedValueOnce({
16
- text: () => Promise.resolve('# Test README\n\nThis is a test.')
17
- })
18
-
19
- render(<App />)
20
-
21
- expect(screen.getByText('🏔️ Fjell Registry')).toBeInTheDocument()
22
- })
23
-
24
- it('renders the subtitle', () => {
25
- mockFetch.mockResolvedValueOnce({
26
- text: () => Promise.resolve('# Test README\n\nThis is a test.')
27
- })
28
-
29
- render(<App />)
30
-
31
- expect(screen.getByText('Common Registry for Fjell - A powerful TypeScript registry system')).toBeInTheDocument()
32
- })
33
-
34
- it('shows loading state initially', () => {
35
- mockFetch.mockImplementationOnce(() => new Promise(() => { })) // Never resolves
36
-
37
- render(<App />)
38
-
39
- expect(screen.getByText('Loading documentation...')).toBeInTheDocument()
40
- })
41
-
42
- it('shows error message when fetch fails', async () => {
43
- mockFetch.mockRejectedValueOnce(new Error('Failed to fetch'))
44
-
45
- render(<App />)
46
-
47
- // Wait for the error state
48
- await screen.findByText(/Error loading documentation/)
49
- })
50
- })
package/docs/src/App.tsx DELETED
@@ -1,606 +0,0 @@
1
- import React, { useEffect, useState } from 'react'
2
- import ReactMarkdown from 'react-markdown'
3
- import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
4
- import { oneLight } from 'react-syntax-highlighter/dist/esm/styles/prism'
5
- import remarkGfm from 'remark-gfm'
6
- import './App.css'
7
-
8
- interface DocumentSection {
9
- id: string;
10
- title: string;
11
- subtitle: string;
12
- file: string;
13
- content?: string;
14
- }
15
-
16
- const documentSections: DocumentSection[] = [
17
- { id: 'overview', title: 'Foundation', subtitle: 'Core concepts & philosophy', file: '/registry/README.md' },
18
- { id: 'getting-started', title: 'Getting Started', subtitle: 'Your first steps with Fjell', file: '/registry/examples-README.md' },
19
- { id: 'examples', title: 'Examples', subtitle: 'Code examples & usage patterns', file: '/registry/examples-README.md' },
20
- { id: 'performance', title: 'Performance', subtitle: 'Memory, timing & optimization', file: '/registry/memory.md' }
21
- ];
22
-
23
- const App: React.FC = () => {
24
- const [currentSection, setCurrentSection] = useState('overview')
25
- const [documents, setDocuments] = useState<{ [key: string]: string }>({})
26
- const [loading, setLoading] = useState(true)
27
- const [sidebarOpen, setSidebarOpen] = useState(false)
28
- const [fullscreenImage, setFullscreenImage] = useState<string | null>(null)
29
- const [version, setVersion] = useState<string>('4.4.10')
30
-
31
- useEffect(() => {
32
- const loadDocuments = async () => {
33
- const loadedDocs: { [key: string]: string } = {}
34
-
35
- for (const section of documentSections) {
36
- try {
37
- const response = await fetch(section.file)
38
-
39
- if (response.ok) {
40
- loadedDocs[section.id] = await response.text()
41
- } else {
42
- // Fallback content for missing files
43
- loadedDocs[section.id] = getFallbackContent(section.id)
44
- }
45
- } catch (error) {
46
- console.error(`Error loading ${section.file}:`, error)
47
- loadedDocs[section.id] = getFallbackContent(section.id)
48
- }
49
- }
50
-
51
- setDocuments(loadedDocs)
52
- setLoading(false)
53
- }
54
-
55
- const loadVersion = async () => {
56
- try {
57
- const response = await fetch('/registry/package.json')
58
- if (response.ok) {
59
- const packageData = await response.json()
60
- setVersion(packageData.version)
61
- console.log('Version loaded:', packageData.version)
62
- } else {
63
- console.error('Failed to fetch package.json:', response.status)
64
- setVersion('4.4.10') // Fallback version
65
- }
66
- } catch (error) {
67
- console.error('Error loading version:', error)
68
- setVersion('4.4.10') // Fallback version
69
- }
70
- }
71
-
72
- loadDocuments()
73
- loadVersion()
74
- }, [])
75
-
76
- const getFallbackContent = (sectionId: string): string => {
77
- switch (sectionId) {
78
- case 'overview':
79
- return `# Fjell Registry
80
-
81
- A comprehensive service location and registry system for the Fjell ecosystem.
82
- The Registry provides a centralized way to register, scope, and retrieve service
83
- instances based on type hierarchies and contextual scopes.
84
-
85
- ## Installation
86
-
87
- \`\`\`bash
88
- npm install @fjell/registry
89
- \`\`\`
90
-
91
- ## Quick Start
92
-
93
- \`\`\`typescript
94
- import { createRegistry, createCoordinate } from '@fjell/registry'
95
-
96
- // Create a registry with mandatory type identifier
97
- const registry = createRegistry('services')
98
-
99
- // Create a coordinate with Key Type Array and scopes
100
- const userCoordinate = createCoordinate(['User'], ['firestore'])
101
- const userInstance = registry.createInstance(userCoordinate, () => new UserService())
102
- \`\`\`
103
-
104
- ## Core Concepts
105
-
106
- - **Registry**: Central service locator with mandatory type identifier
107
- - **Coordinate**: Unique service identifier using Key Type Arrays and scopes
108
- - **Instance**: Registered service with its coordinate and registry reference
109
- - **Scopes**: Context qualifiers enabling multiple implementations`
110
-
111
- case 'getting-started':
112
- return `# Getting Started
113
-
114
- ## Basic Usage
115
-
116
- \`\`\`typescript
117
- import { createRegistry, createCoordinate } from '@fjell/registry'
118
-
119
- // Create a registry with type identifier
120
- const registry = createRegistry('services')
121
-
122
- // Register a service with coordinate
123
- const coordinate = createCoordinate(['User'], ['firestore'])
124
- const instance = registry.createInstance(coordinate, () => new UserService())
125
- \`\`\`
126
-
127
- ## Key Concepts
128
-
129
- - **Coordinates**: Use Key Type Arrays like \`['User', 'Profile']\` for hierarchical types
130
- - **Scopes**: Context qualifiers like \`['firestore']\`, \`['postgresql']\` for multiple implementations
131
- - **Registries**: Each has a mandatory type identifier for organization
132
-
133
- ## Examples
134
-
135
- Check the examples directory for detailed usage patterns with different key structures and scope configurations.`
136
-
137
- case 'examples':
138
- return `# Registry Examples
139
-
140
- This directory contains examples demonstrating how to use the Registry with different key patterns and configurations.
141
-
142
- *Note: This content should be loaded from examples/README.md. If you're seeing this, there may be an issue with file loading.*
143
-
144
- ## Examples Available
145
-
146
- - **simple-example.ts**: Basic usage without complexity
147
- - **multi-level-keys.ts**: Advanced hierarchical patterns
148
- - **registry-hub-types.ts**: Enterprise service organization
149
- - **coordinates-example.ts**: Service introspection patterns
150
- - **registry-hub-coordinates-example.ts**: Cross-registry discovery`
151
-
152
- case 'performance':
153
- return `# Performance Guide
154
-
155
- Comprehensive performance analysis and optimization strategies for Fjell Registry.
156
-
157
- ## Memory Efficiency
158
-
159
- The registry system is designed for memory efficiency with minimal overhead per registered instance and coordinate.
160
-
161
- ### Key Features
162
- - Lightweight coordinate system using arrays
163
- - Efficient instance tree organization
164
- - Minimal memory footprint per service registration
165
-
166
- ### Memory Benchmarks
167
- Performance metrics and memory usage patterns show efficient scaling with large numbers of registered services.
168
-
169
- ## Timing Performance
170
-
171
- Performance benchmarks for Fjell Registry service location operations.
172
-
173
- ### Core Operations
174
- - **Instance creation**: Fast atomic registration with coordinates
175
- - **Registry lookup**: Efficient retrieval by Key Type Arrays and scopes
176
- - **Coordinate resolution**: Quick scope-based service discovery
177
- - **Tree traversal**: Optimized instance tree navigation
178
-
179
- ### Timing Benchmarks
180
- - Instance registration: < 1ms per service
181
- - Coordinate-based lookup: < 0.1ms average
182
- - Scope resolution: < 0.5ms for complex hierarchies
183
- - Memory allocation: Minimal per registered instance
184
-
185
- ## Production Optimization
186
-
187
- Best practices for optimizing Fjell Registry performance in production environments.
188
-
189
- ### Registry Organization
190
- - Use specific type identifiers for different service categories
191
- - Group related services in dedicated registries
192
- - Leverage scopes for environment-specific implementations
193
-
194
- ### Performance Tips
195
- - Design efficient Key Type Array hierarchies
196
- - Minimize scope complexity where possible
197
- - Use appropriate registry types for service organization
198
- - Consider coordinate caching for frequently accessed services
199
-
200
- ### Production Settings
201
- Recommended Node.js heap size settings and monitoring approaches for large-scale registry usage.`
202
-
203
- default:
204
- return `# ${sectionId}\n\nDocumentation section not found.`
205
- }
206
- }
207
-
208
- const currentContent = documents[currentSection] || ''
209
- const currentSectionData = documentSections.find(s => s.id === currentSection)
210
-
211
- return (
212
- <div className="app">
213
- <header className="header">
214
- <div className="header-container">
215
- <div className="brand">
216
- <h1 className="brand-title">
217
- <span className="brand-fjell">Fjell</span>
218
- <span className="brand-registry">Registry</span>
219
- </h1>
220
- <p className="brand-tagline">
221
- Service location that
222
- <span className="gradient-text"> weaves through the mist</span>
223
- </p>
224
- </div>
225
-
226
- <div className="header-actions">
227
- <a
228
- href={`https://github.com/getfjell/registry/releases/tag/v${version}`}
229
- target="_blank"
230
- rel="noopener noreferrer"
231
- className="version-badge"
232
- title={`Release v${version}`}
233
- >
234
- v{version}
235
- </a>
236
- <a
237
- href="https://github.com/getfjell/registry"
238
- target="_blank"
239
- rel="noopener noreferrer"
240
- className="header-link"
241
- >
242
- <span>View Source</span>
243
- </a>
244
- <a
245
- href="https://www.npmjs.com/package/@fjell/registry"
246
- target="_blank"
247
- rel="noopener noreferrer"
248
- className="header-link"
249
- >
250
- <span>Install Package</span>
251
- </a>
252
- <button
253
- className="menu-toggle"
254
- onClick={() => setSidebarOpen(!sidebarOpen)}
255
- >
256
- <span className="menu-line"></span>
257
- <span className="menu-line"></span>
258
- <span className="menu-line"></span>
259
- </button>
260
- </div>
261
- </div>
262
- </header>
263
-
264
- <div className="layout">
265
- <nav className={`sidebar ${sidebarOpen ? 'sidebar-open' : ''}`}>
266
- <div className="nav-content">
267
- <div className="nav-sections">
268
- {documentSections.map((section) => (
269
- <button
270
- key={section.id}
271
- className={`nav-item ${currentSection === section.id ? 'active' : ''}`}
272
- onClick={() => {
273
- setCurrentSection(section.id)
274
- setSidebarOpen(false)
275
- }}
276
- >
277
- <div className="nav-item-content">
278
- <div className="nav-item-title">{section.title}</div>
279
- <div className="nav-item-subtitle">{section.subtitle}</div>
280
- </div>
281
- </button>
282
- ))}
283
- </div>
284
-
285
- {/* Artistic Logo Placement */}
286
- <img
287
- src="/registry/icon.png"
288
- alt="Fjell Registry"
289
- className="fjell-logo"
290
- title="Fjell Registry - Service location that weaves through the mist"
291
- onError={(e) => {
292
- console.log('Icon failed to load, trying alternative path');
293
- e.currentTarget.src = '/icon.png';
294
- }}
295
- onLoad={() => console.log('Fjell logo loaded successfully')}
296
- />
297
- </div>
298
- </nav>
299
-
300
- <main className="main">
301
- <div className="content-container">
302
- {loading ? (
303
- <div className="loading">
304
- <div className="loading-animation">
305
- <div className="loading-dot"></div>
306
- <div className="loading-dot"></div>
307
- <div className="loading-dot"></div>
308
- </div>
309
- <p className="loading-text">Awakening the Registry</p>
310
- </div>
311
- ) : (
312
- <div className="content-wrapper">
313
- <div className="content-header">
314
- <div className="breadcrumb">
315
- <span className="breadcrumb-home">Fjell Registry</span>
316
- <span className="breadcrumb-separator">›</span>
317
- <span className="breadcrumb-current">{currentSectionData?.title}</span>
318
- </div>
319
- </div>
320
-
321
- <div className="section-header">
322
- <h1 className="content-title">
323
- {currentSectionData?.title}
324
- </h1>
325
- <p className="content-subtitle">
326
- {currentSectionData?.subtitle}
327
- </p>
328
- </div>
329
-
330
- <div className="content">
331
- {currentSection === 'examples' ? (
332
- <div className="examples-content">
333
- <ReactMarkdown
334
- remarkPlugins={[remarkGfm]}
335
- components={{
336
- code({ className, children, ...props }: any) {
337
- const match = /language-(\w+)/.exec(className || '')
338
- return !props.inline && match ? (
339
- <SyntaxHighlighter
340
- style={oneLight as { [key: string]: React.CSSProperties }}
341
- language={match[1]}
342
- PreTag="div"
343
- {...props}
344
- >
345
- {String(children).replace(/\n$/, '')}
346
- </SyntaxHighlighter>
347
- ) : (
348
- <code className={className} {...props}>
349
- {children}
350
- </code>
351
- )
352
- },
353
- h1({ children }) {
354
- return <h1 className="content-h1">{children}</h1>
355
- },
356
- h2({ children }) {
357
- return <h2 className="content-h2">{children}</h2>
358
- },
359
- h3({ children }) {
360
- return <h3 className="content-h3">{children}</h3>
361
- }
362
- }}
363
- >
364
- {currentContent}
365
- </ReactMarkdown>
366
-
367
- <div className="examples-grid">
368
- <div className="example-card">
369
- <h3>🟢 Simple Example</h3>
370
- <p>Perfect for beginners! Basic dependency injection without complexity.</p>
371
- <details>
372
- <summary>View Code</summary>
373
- <div className="example-code-block">
374
- <SyntaxHighlighter
375
- style={oneLight as { [key: string]: React.CSSProperties }}
376
- language="bash"
377
- PreTag="div"
378
- >
379
- npx tsx examples/simple-example.ts
380
- </SyntaxHighlighter>
381
- </div>
382
- </details>
383
- </div>
384
-
385
- <div className="example-card">
386
- <h3>🔶 Multi-Level Keys</h3>
387
- <p>Advanced usage with scopes and hierarchical key type arrays.</p>
388
- <details>
389
- <summary>View Code</summary>
390
- <div className="example-code-block">
391
- <SyntaxHighlighter
392
- style={oneLight as { [key: string]: React.CSSProperties }}
393
- language="bash"
394
- PreTag="div"
395
- >
396
- npx tsx examples/multi-level-keys.ts
397
- </SyntaxHighlighter>
398
- </div>
399
- </details>
400
- </div>
401
-
402
- <div className="example-card">
403
- <h3>🏗️ Registry Hub</h3>
404
- <p>Enterprise architecture with organized service categories.</p>
405
- <details>
406
- <summary>View Code</summary>
407
- <div className="example-code-block">
408
- <SyntaxHighlighter
409
- style={oneLight as { [key: string]: React.CSSProperties }}
410
- language="bash"
411
- PreTag="div"
412
- >
413
- npx tsx examples/registry-hub-types.ts
414
- </SyntaxHighlighter>
415
- </div>
416
- </details>
417
- </div>
418
-
419
- <div className="example-card">
420
- <h3>Coordinate Discovery</h3>
421
- <p>Service introspection and discovery patterns.</p>
422
- <details>
423
- <summary>View Code</summary>
424
- <div className="example-code-block">
425
- <SyntaxHighlighter
426
- style={oneLight as { [key: string]: React.CSSProperties }}
427
- language="bash"
428
- PreTag="div"
429
- >
430
- npx tsx examples/coordinates-example.ts
431
- </SyntaxHighlighter>
432
- </div>
433
- </details>
434
- </div>
435
-
436
- <div className="example-card">
437
- <h3>🌐 Hub Coordinates</h3>
438
- <p>Cross-registry coordinate discovery for enterprise apps.</p>
439
- <details>
440
- <summary>View Code</summary>
441
- <div className="example-code-block">
442
- <SyntaxHighlighter
443
- style={oneLight as { [key: string]: React.CSSProperties }}
444
- language="bash"
445
- PreTag="div"
446
- >
447
- npx tsx examples/registry-hub-coordinates-example.ts
448
- </SyntaxHighlighter>
449
- </div>
450
- </details>
451
- </div>
452
- </div>
453
- </div>
454
- ) : currentSection === 'performance' ? (
455
- <div className="performance-content">
456
- <ReactMarkdown
457
- remarkPlugins={[remarkGfm]}
458
- components={{
459
- code({ className, children, ...props }: any) {
460
- const match = /language-(\w+)/.exec(className || '')
461
- return !props.inline && match ? (
462
- <SyntaxHighlighter
463
- style={oneLight as { [key: string]: React.CSSProperties }}
464
- language={match[1]}
465
- PreTag="div"
466
- {...props}
467
- >
468
- {String(children).replace(/\n$/, '')}
469
- </SyntaxHighlighter>
470
- ) : (
471
- <code className={className} {...props}>
472
- {children}
473
- </code>
474
- )
475
- },
476
- h1({ children }) {
477
- return <h1 className="content-h1">{children}</h1>
478
- },
479
- h2({ children }) {
480
- return <h2 className="content-h2">{children}</h2>
481
- },
482
- h3({ children }) {
483
- return <h3 className="content-h3">{children}</h3>
484
- }
485
- }}
486
- >
487
- {currentContent}
488
- </ReactMarkdown>
489
- <div className="performance-charts">
490
- <div className="svg-display">
491
- <h3>Memory Overhead Analysis</h3>
492
- <img
493
- src="/registry/memory-overhead.svg"
494
- alt="Memory Overhead Chart"
495
- className="performance-chart clickable-chart"
496
- onClick={() => setFullscreenImage('/registry/memory-overhead.svg')}
497
- title="Click to view full screen"
498
- />
499
- </div>
500
- <div className="svg-display">
501
- <h3>Timing Performance Analysis</h3>
502
- <img
503
- src="/registry/timing-range.svg"
504
- alt="Timing Performance Chart"
505
- className="performance-chart clickable-chart"
506
- onClick={() => setFullscreenImage('/registry/timing-range.svg')}
507
- title="Click to view full screen"
508
- />
509
- </div>
510
- </div>
511
- </div>
512
- ) : (
513
- <ReactMarkdown
514
- remarkPlugins={[remarkGfm]}
515
- components={{
516
- code({ className, children, ...props }: any) {
517
- const match = /language-(\w+)/.exec(className || '')
518
- return !props.inline && match ? (
519
- <SyntaxHighlighter
520
- style={oneLight as { [key: string]: React.CSSProperties }}
521
- language={match[1]}
522
- PreTag="div"
523
- {...props}
524
- >
525
- {String(children).replace(/\n$/, '')}
526
- </SyntaxHighlighter>
527
- ) : (
528
- <code className={className} {...props}>
529
- {children}
530
- </code>
531
- )
532
- },
533
- h1({ children }) {
534
- return <h1 className="content-h1">{children}</h1>
535
- },
536
- h2({ children }) {
537
- return <h2 className="content-h2">{children}</h2>
538
- },
539
- h3({ children }) {
540
- return <h3 className="content-h3">{children}</h3>
541
- }
542
- }}
543
- >
544
- {currentContent}
545
- </ReactMarkdown>
546
- )}
547
- </div>
548
-
549
- <div className="content-navigation">
550
- {documentSections.map((section) => {
551
- if (section.id === currentSection) return null
552
- return (
553
- <button
554
- key={section.id}
555
- className="nav-suggestion"
556
- onClick={() => setCurrentSection(section.id)}
557
- >
558
- <span className="nav-suggestion-label">Next</span>
559
- <span className="nav-suggestion-title">{section.title}</span>
560
- </button>
561
- )
562
- }).filter(Boolean).slice(0, 1)}
563
- </div>
564
- </div>
565
- )}
566
- </div>
567
- </main>
568
- </div>
569
-
570
- <footer className="footer">
571
- <div className="footer-container">
572
- <div className="footer-content">
573
- <p className="footer-text">
574
- Crafted with intention for the Fjell ecosystem
575
- </p>
576
- <p className="footer-license">
577
- Licensed under Apache-2.0 &nbsp;•&nbsp; 2024
578
- </p>
579
- </div>
580
- </div>
581
- </footer>
582
-
583
- {/* Fullscreen Image Modal */}
584
- {fullscreenImage && (
585
- <div className="fullscreen-modal" onClick={() => setFullscreenImage(null)}>
586
- <div className="fullscreen-content">
587
- <img
588
- src={fullscreenImage}
589
- alt="Performance Chart"
590
- className="fullscreen-image"
591
- />
592
- <button
593
- className="close-button"
594
- onClick={() => setFullscreenImage(null)}
595
- aria-label="Close fullscreen view"
596
- >
597
- ×
598
- </button>
599
- </div>
600
- </div>
601
- )}
602
- </div>
603
- )
604
- }
605
-
606
- export default App