@owlmeans/context 0.1.0

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 (56) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +750 -0
  3. package/build/.gitkeep +0 -0
  4. package/build/config.d.ts +4 -0
  5. package/build/config.d.ts.map +1 -0
  6. package/build/config.js +15 -0
  7. package/build/config.js.map +1 -0
  8. package/build/consts.d.ts +50 -0
  9. package/build/consts.d.ts.map +1 -0
  10. package/build/consts.js +56 -0
  11. package/build/consts.js.map +1 -0
  12. package/build/context.d.ts +3 -0
  13. package/build/context.d.ts.map +1 -0
  14. package/build/context.js +203 -0
  15. package/build/context.js.map +1 -0
  16. package/build/helper.d.ts +8 -0
  17. package/build/helper.d.ts.map +1 -0
  18. package/build/helper.js +31 -0
  19. package/build/helper.js.map +1 -0
  20. package/build/index.d.ts +7 -0
  21. package/build/index.d.ts.map +1 -0
  22. package/build/index.js +6 -0
  23. package/build/index.js.map +1 -0
  24. package/build/service.d.ts +7 -0
  25. package/build/service.d.ts.map +1 -0
  26. package/build/service.js +27 -0
  27. package/build/service.js.map +1 -0
  28. package/build/types.d.ts +80 -0
  29. package/build/types.d.ts.map +1 -0
  30. package/build/types.js +2 -0
  31. package/build/types.js.map +1 -0
  32. package/build/utils/context.d.ts +11 -0
  33. package/build/utils/context.d.ts.map +1 -0
  34. package/build/utils/context.js +15 -0
  35. package/build/utils/context.js.map +1 -0
  36. package/build/utils/index.d.ts +3 -0
  37. package/build/utils/index.d.ts.map +1 -0
  38. package/build/utils/index.js +3 -0
  39. package/build/utils/index.js.map +1 -0
  40. package/build/utils/layer.d.ts +6 -0
  41. package/build/utils/layer.d.ts.map +1 -0
  42. package/build/utils/layer.js +12 -0
  43. package/build/utils/layer.js.map +1 -0
  44. package/package.json +31 -0
  45. package/src/config.ts +17 -0
  46. package/src/consts.ts +58 -0
  47. package/src/context.ts +261 -0
  48. package/src/helper.ts +43 -0
  49. package/src/index.ts +7 -0
  50. package/src/service.ts +49 -0
  51. package/src/types.ts +96 -0
  52. package/src/utils/context.ts +34 -0
  53. package/src/utils/index.ts +3 -0
  54. package/src/utils/layer.ts +17 -0
  55. package/tsconfig.json +14 -0
  56. package/tsconfig.tsbuildinfo +1 -0
package/README.md ADDED
@@ -0,0 +1,750 @@
1
+ # @owlmeans/context
2
+
3
+ The **@owlmeans/context** package provides dependency management for OwlMeans Common libraries, specifically designed for fullstack microservices and microclients development.
4
+
5
+ ## Purpose
6
+
7
+ This package serves as a foundational dependency injection and management system that enables:
8
+
9
+ - **Service Registration and Resolution**: Register and access services across different application layers
10
+ - **Module Management**: Handle URL units that declare routes and nesting for both frontend and backend
11
+ - **Resource Management**: Manage data sources and external resources with proper initialization
12
+ - **Middleware System**: Apply cross-cutting concerns at different stages of the application lifecycle
13
+ - **Multi-layer Architecture**: Support hierarchical layers (System, Global, Service, Entity, User) for complex applications
14
+
15
+ ## Key Concepts
16
+
17
+ ### Context
18
+ A context acts as an application instance that manages the lifecycle and dependencies of services, modules, and resources. Multiple contexts can exist within one application with different capabilities.
19
+
20
+ ### Layers
21
+ The package supports a hierarchical layer system:
22
+ - **System**: System-wide components
23
+ - **Global**: Global application components
24
+ - **Service**: Service-specific components
25
+ - **Entity**: Entity-specific components
26
+ - **User**: User-specific components
27
+
28
+ ### Modules
29
+ In the context of OwlMeans Common libraries, a "module" is not a programmatic module but a URL unit in the system. Modules allow you to:
30
+ - Declare URLs and nesting structure
31
+ - Transform URLs to routes and attach handlers on the backend
32
+ - Specify which components to render on the frontend
33
+ - Generate final URLs for navigation or API calls
34
+ - Maintain a single source of truth for all possible routes
35
+
36
+ ### Services
37
+ Services are components that provide functionality and can be initialized either immediately or lazily.
38
+
39
+ ### Resources
40
+ Resources are components that provide data or external functionality and can be initialized when needed.
41
+
42
+ ### Middlewares
43
+ Middlewares are components that can be applied at different stages of the context lifecycle to provide cross-cutting functionality.
44
+
45
+ ## API Reference
46
+
47
+ ### Factory Functions
48
+
49
+ The package uses factory functions instead of constructors for object creation:
50
+
51
+ #### `makeBasicContext<C extends BasicConfig>(cfg: C): BasicContext<C>`
52
+
53
+ Creates a basic context instance.
54
+
55
+ ```typescript
56
+ import { makeBasicContext, makeBasicConfig, AppType } from '@owlmeans/context'
57
+
58
+ const config = makeBasicConfig(AppType.Backend, 'my-service')
59
+ const context = makeBasicContext(config)
60
+ ```
61
+
62
+ #### `makeBasicConfig<C extends BasicConfig>(type: AppType, service: string, cfg?: Partial<C>): C`
63
+
64
+ Creates a basic configuration object.
65
+
66
+ **Parameters:**
67
+ - `type`: Application type (Frontend or Backend)
68
+ - `service`: Service name
69
+ - `cfg`: Additional configuration options
70
+
71
+ ```typescript
72
+ import { makeBasicConfig, AppType, Layer } from '@owlmeans/context'
73
+
74
+ const config = makeBasicConfig(AppType.Frontend, 'web-client', {
75
+ layer: Layer.Service,
76
+ debug: { all: true }
77
+ })
78
+ ```
79
+
80
+ #### `createService<S extends InitializedService>(alias: string, service: Partial<S>, init?: InitMethod<S>): S`
81
+
82
+ Creates a service that initializes immediately.
83
+
84
+ ```typescript
85
+ import { createService } from '@owlmeans/context'
86
+
87
+ const myService = createService('my-service', {
88
+ // service implementation
89
+ }, (service) => async () => {
90
+ // initialization logic
91
+ console.log('Service initialized')
92
+ service.initialized = true
93
+ })
94
+ ```
95
+
96
+ #### `createLazyService<S extends LazyService>(alias: string, service: Partial<S>, init?: InitMethod<S>): S`
97
+
98
+ Creates a service that initializes only when first accessed.
99
+
100
+ ```typescript
101
+ import { createLazyService } from '@owlmeans/context'
102
+
103
+ const lazyService = createLazyService('lazy-service', {
104
+ // service implementation
105
+ }, (service) => async () => {
106
+ // lazy initialization logic
107
+ console.log('Lazy service initialized')
108
+ service.initialized = true
109
+ })
110
+ ```
111
+
112
+ #### `appendContextual<T extends Contextual>(alias: string, contextual: Partial<T>): T`
113
+
114
+ Helps make objects contextual by adding context management capabilities.
115
+
116
+ ```typescript
117
+ import { appendContextual } from '@owlmeans/context'
118
+
119
+ const contextualObject = appendContextual('my-object', {
120
+ // object implementation
121
+ })
122
+ ```
123
+
124
+ ### Core Interfaces
125
+
126
+ #### `BasicContext<C extends BasicConfig>`
127
+
128
+ The main context interface that provides comprehensive dependency management. Each method serves a specific purpose in the context lifecycle and dependency resolution:
129
+
130
+ ```typescript
131
+ interface BasicContext<C extends BasicConfig> {
132
+ cfg: C
133
+ stage: ContextStage
134
+
135
+ // Lifecycle methods
136
+ waitForConfigured(): Promise<boolean>
137
+ waitForInitialized(): Promise<boolean>
138
+ configure<T extends BasicContext<C>>(): T
139
+ init<T extends BasicContext<C>>(): Promise<T>
140
+
141
+ // Registration methods
142
+ registerService<T extends BasicContext<C>>(service: Service): T
143
+ registerModule<T extends BasicContext<C>>(module: BasicModule): T
144
+ registerModules<T extends BasicContext<C>>(modules: BasicModule[]): T
145
+ registerResource<T extends BasicContext<C>>(resource: BasicResource): T
146
+ registerMiddleware<T extends BasicContext<C>>(middleware: Middleware): T
147
+
148
+ // Access methods
149
+ service<T extends Service>(alias: string): T
150
+ module<T extends BasicModule>(alias: string): T
151
+ resource<T extends BasicResource>(alias: string): T
152
+ modules<T extends BasicModule>(): T[]
153
+
154
+ // Utility methods
155
+ hasResource(alias: string): boolean
156
+ hasService(alias: string): boolean
157
+
158
+ get config(): Promise<C>
159
+ }
160
+ ```
161
+
162
+ ### Context Methods Detailed Reference
163
+
164
+ #### Lifecycle Methods
165
+
166
+ **`waitForConfigured(): Promise<boolean>`**
167
+ - **Purpose**: Returns a promise that resolves when the context has completed its configuration stage
168
+ - **Usage**: Useful for waiting for configuration to complete before proceeding
169
+ - **Returns**: Promise that resolves to `true` when configuration is complete
170
+
171
+ **`waitForInitialized(): Promise<boolean>`**
172
+ - **Purpose**: Returns a promise that resolves when the context has completed initialization and reached the Ready stage
173
+ - **Usage**: Essential for ensuring all services and resources are initialized before use
174
+ - **Returns**: Promise that resolves to `true` when initialization is complete
175
+
176
+ **`configure<T extends BasicContext<C>>(): T`**
177
+ - **Purpose**: Transitions the context from Configuration stage to Loading stage
178
+ - **Behavior**: Applies configuration middlewares and prepares the context for initialization
179
+ - **Usage**: Must be called after registering all components and before `init()`
180
+ - **Returns**: The context instance for method chaining
181
+
182
+ **`init<T extends BasicContext<C>>(): Promise<T>`**
183
+ - **Purpose**: Initializes all registered services and resources, transitioning context to Ready stage
184
+ - **Behavior**:
185
+ - Executes `init()` methods on all registered services
186
+ - Initializes all resources according to their layer availability
187
+ - Applies loading and ready stage middlewares
188
+ - Marks context as ready for use
189
+ - **Usage**: Must be called after `configure()` to make the context operational
190
+ - **Returns**: Promise that resolves to the initialized context instance
191
+
192
+ #### Registration Methods
193
+
194
+ **`registerService<T extends BasicContext<C>>(service: Service): T`**
195
+ - **Purpose**: Registers a service with the context for dependency injection
196
+ - **Behavior**:
197
+ - Associates the service with the current context
198
+ - Stores the service in the appropriate layer
199
+ - Makes the service available for retrieval via `service()`
200
+ - **Usage**: Call during configuration stage to register services
201
+ - **Returns**: The context instance for method chaining
202
+
203
+ **`registerModule<T extends BasicContext<C>>(module: BasicModule): T`**
204
+ - **Purpose**: Registers a module (URL unit) with the context
205
+ - **Behavior**:
206
+ - Associates the module with the current context
207
+ - Makes the module available for route resolution and navigation
208
+ - **Usage**: Register modules that define URL structures and routing
209
+ - **Returns**: The context instance for method chaining
210
+
211
+ **`registerModules<T extends BasicContext<C>>(modules: BasicModule[]): T`**
212
+ - **Purpose**: Convenience method to register multiple modules at once
213
+ - **Behavior**: Iterates through the array and registers each module
214
+ - **Usage**: Efficient way to register multiple modules simultaneously
215
+ - **Returns**: The context instance for method chaining
216
+
217
+ **`registerResource<T extends BasicContext<C>>(resource: BasicResource): T`**
218
+ - **Purpose**: Registers a resource (data source or external service) with the context
219
+ - **Behavior**:
220
+ - Associates the resource with the current context
221
+ - Resources are initialized during context initialization based on layer availability
222
+ - **Usage**: Register resources that provide data or external functionality
223
+ - **Returns**: The context instance for method chaining
224
+
225
+ **`registerMiddleware<T extends BasicContext<C>>(middleware: Middleware): T`**
226
+ - **Purpose**: Registers middleware for cross-cutting concerns during context lifecycle
227
+ - **Behavior**:
228
+ - Middleware is applied at specific stages (Configuration, Loading, Ready, Switching)
229
+ - Multiple middlewares can be registered for the same stage
230
+ - **Usage**: Register middleware for logging, validation, or other cross-cutting functionality
231
+ - **Returns**: The context instance for method chaining
232
+
233
+ #### Access Methods
234
+
235
+ **`service<T extends Service>(alias: string): T`**
236
+ - **Purpose**: Retrieves a registered service by its alias
237
+ - **Behavior**:
238
+ - Looks up the service in the current layer and falls back to Global layer
239
+ - Handles lazy initialization if the service is not yet initialized
240
+ - Throws `SyntaxError` if service is not found or not initialized
241
+ - **Usage**: Primary way to access services for dependency injection
242
+ - **Returns**: The requested service instance
243
+ - **Throws**: `SyntaxError` if service not found or not initialized
244
+
245
+ **`module<T extends BasicModule>(alias: string): T`**
246
+ - **Purpose**: Retrieves a registered module by its alias
247
+ - **Behavior**:
248
+ - Looks up the module in the current layer
249
+ - Throws `SyntaxError` if module is not found
250
+ - **Usage**: Access modules for route resolution and navigation
251
+ - **Returns**: The requested module instance
252
+ - **Throws**: `SyntaxError` if module not found
253
+
254
+ **`resource<T extends BasicResource>(alias: string): T`**
255
+ - **Purpose**: Retrieves a registered resource by its alias
256
+ - **Behavior**:
257
+ - Looks up the resource in the current layer
258
+ - Throws `SyntaxError` if resource is not found
259
+ - **Usage**: Access resources for data operations or external service calls
260
+ - **Returns**: The requested resource instance
261
+ - **Throws**: `SyntaxError` if resource not found
262
+
263
+ **`modules<T extends BasicModule>(): T[]`**
264
+ - **Purpose**: Retrieves all registered modules as an array
265
+ - **Behavior**: Returns all modules registered in the current layer
266
+ - **Usage**: Useful for iterating over all available modules
267
+ - **Returns**: Array of all registered modules
268
+
269
+ #### Utility Methods
270
+
271
+ **`hasResource(alias: string): boolean`**
272
+ - **Purpose**: Checks if a resource with the given alias exists
273
+ - **Behavior**: Searches across all layers for the resource
274
+ - **Usage**: Defensive programming to check resource availability before access
275
+ - **Returns**: `true` if resource exists, `false` otherwise
276
+
277
+ **`hasService(alias: string): boolean`**
278
+ - **Purpose**: Checks if a service with the given alias exists
279
+ - **Behavior**: Searches across all layers for the service
280
+ - **Usage**: Defensive programming to check service availability before access
281
+ - **Returns**: `true` if service exists, `false` otherwise
282
+
283
+ #### Configuration Access
284
+
285
+ **`get config(): Promise<C>`**
286
+ - **Purpose**: Provides access to the context configuration after it's been configured
287
+ - **Behavior**: Returns a promise that resolves to the configuration object once context is configured
288
+ - **Usage**: Access configuration settings after context setup
289
+ - **Returns**: Promise that resolves to the configuration object
290
+
291
+ #### Properties
292
+
293
+ **`cfg: C`**
294
+ - **Purpose**: Direct access to the context configuration object
295
+ - **Usage**: Access configuration settings synchronously
296
+ - **Type**: The configuration object of type `C extends BasicConfig`
297
+
298
+ **`stage: ContextStage`**
299
+ - **Purpose**: Indicates the current lifecycle stage of the context
300
+ - **Values**: `Configuration`, `Loading`, or `Ready`
301
+ - **Usage**: Check context readiness before performing operations
302
+
303
+ #### `BasicConfig`
304
+
305
+ Configuration interface for contexts:
306
+
307
+ ```typescript
308
+ interface BasicConfig {
309
+ ready: boolean
310
+ service: string
311
+ alias?: string
312
+ layer: Layer
313
+ type: AppType
314
+ layerId?: string
315
+ services?: Record<string, Object>
316
+ debug?: {
317
+ all?: boolean
318
+ [section: string]: boolean | undefined
319
+ }
320
+ }
321
+ ```
322
+
323
+ #### `Service`
324
+
325
+ Interface for services:
326
+
327
+ ```typescript
328
+ interface Service extends Contextual {
329
+ layers?: Layer[]
330
+ initialized: boolean
331
+ init?: () => Promise<void>
332
+ lazyInit?: () => Promise<void>
333
+ ready?: () => Promise<boolean>
334
+ }
335
+ ```
336
+
337
+ #### `BasicModule`
338
+
339
+ Interface for modules:
340
+
341
+ ```typescript
342
+ interface BasicModule extends Contextual {
343
+ _module: true
344
+ }
345
+ ```
346
+
347
+ #### `BasicResource`
348
+
349
+ Interface for resources:
350
+
351
+ ```typescript
352
+ interface BasicResource extends Contextual {
353
+ layers?: Layer[]
354
+ init?: () => Promise<void>
355
+ }
356
+ ```
357
+
358
+ #### `Middleware`
359
+
360
+ Interface for middlewares:
361
+
362
+ ```typescript
363
+ interface Middleware {
364
+ type: MiddlewareType
365
+ stage: MiddlewareStage
366
+ apply: <C extends BasicConfig, T extends BasicContext<C>>(
367
+ context: T,
368
+ args?: Record<string, string | undefined>
369
+ ) => Promise<void>
370
+ }
371
+ ```
372
+
373
+ ### Enums
374
+
375
+ #### `Layer`
376
+ ```typescript
377
+ enum Layer {
378
+ System = 'system',
379
+ Global = 'global',
380
+ Service = 'service',
381
+ Entity = 'entity',
382
+ User = 'user'
383
+ }
384
+ ```
385
+
386
+ #### `AppType`
387
+ ```typescript
388
+ enum AppType {
389
+ Backend = 'backend',
390
+ Frontend = 'frontend'
391
+ }
392
+ ```
393
+
394
+ #### `ContextStage`
395
+ ```typescript
396
+ enum ContextStage {
397
+ Configuration = 'configuration',
398
+ Loading = 'loading',
399
+ Ready = 'ready'
400
+ }
401
+ ```
402
+
403
+ #### `MiddlewareType`
404
+ ```typescript
405
+ enum MiddlewareType {
406
+ Config = 'config',
407
+ Context = 'context'
408
+ }
409
+ ```
410
+
411
+ #### `MiddlewareStage`
412
+ ```typescript
413
+ enum MiddlewareStage {
414
+ Configuration = 'configuration',
415
+ Loading = 'loading',
416
+ Ready = 'ready',
417
+ Switching = 'switching'
418
+ }
419
+ ```
420
+
421
+ ## Usage Examples
422
+
423
+ ### Basic Usage
424
+
425
+ ```typescript
426
+ import {
427
+ makeBasicContext,
428
+ makeBasicConfig,
429
+ createService,
430
+ AppType,
431
+ Layer
432
+ } from '@owlmeans/context'
433
+
434
+ // Create configuration
435
+ const config = makeBasicConfig(AppType.Backend, 'my-app', {
436
+ layer: Layer.System,
437
+ debug: { all: true }
438
+ })
439
+
440
+ // Create context
441
+ const context = makeBasicContext(config)
442
+
443
+ // Create and register a service
444
+ const myService = createService('database', {
445
+ connect: () => console.log('Connected to database')
446
+ }, (service) => async () => {
447
+ // Initialize the service
448
+ service.connect()
449
+ service.initialized = true
450
+ })
451
+
452
+ context.registerService(myService)
453
+
454
+ // Configure and initialize context
455
+ const configuredContext = context.configure()
456
+ await configuredContext.init()
457
+
458
+ // Use the service
459
+ const dbService = context.service('database')
460
+ ```
461
+
462
+ ### Advanced Context Method Usage
463
+
464
+ ```typescript
465
+ import {
466
+ makeBasicContext,
467
+ makeBasicConfig,
468
+ createService,
469
+ createLazyService,
470
+ AppType,
471
+ Layer,
472
+ ContextStage
473
+ } from '@owlmeans/context'
474
+
475
+ const config = makeBasicConfig(AppType.Backend, 'advanced-app')
476
+ const context = makeBasicContext(config)
477
+
478
+ // Register multiple services
479
+ const cacheService = createService('cache', {
480
+ get: (key: string) => `cached-${key}`,
481
+ set: (key: string, value: any) => console.log(`Set ${key}=${value}`)
482
+ })
483
+
484
+ const logService = createLazyService('logger', {
485
+ log: (message: string) => console.log(`[LOG] ${message}`)
486
+ }, (service) => async () => {
487
+ console.log('Logger initialized lazily')
488
+ service.initialized = true
489
+ })
490
+
491
+ context.registerService(cacheService)
492
+ context.registerService(logService)
493
+
494
+ // Check service availability before use
495
+ if (context.hasService('cache')) {
496
+ console.log('Cache service is available')
497
+ }
498
+
499
+ // Wait for specific lifecycle stages
500
+ await context.waitForConfigured()
501
+ console.log('Context configured')
502
+
503
+ // Configure and initialize
504
+ context.configure()
505
+ await context.init()
506
+
507
+ // Check current stage
508
+ console.log('Current stage:', context.stage) // ContextStage.Ready
509
+
510
+ // Access configuration after initialization
511
+ const finalConfig = await context.config
512
+ console.log('Final config:', finalConfig.service)
513
+
514
+ // Service access - cache service is already initialized
515
+ const cache = context.service('cache')
516
+ cache.set('key1', 'value1')
517
+
518
+ // Lazy service access - will initialize on first access
519
+ const logger = context.service('logger') // Triggers lazy initialization
520
+ logger.log('Application ready')
521
+ ```
522
+
523
+ ### Method Chaining and Error Handling
524
+
525
+ ```typescript
526
+ import {
527
+ makeBasicContext,
528
+ makeBasicConfig,
529
+ createService,
530
+ appendContextual,
531
+ AppType
532
+ } from '@owlmeans/context'
533
+
534
+ const config = makeBasicConfig(AppType.Backend, 'chaining-example')
535
+ const context = makeBasicContext(config)
536
+
537
+ // Method chaining for registration
538
+ const service1 = createService('service1', { value: 1 })
539
+ const service2 = createService('service2', { value: 2 })
540
+ const module1 = appendContextual('module1', { _module: true, routes: {} })
541
+ const resource1 = appendContextual('resource1', { data: 'test' })
542
+
543
+ // Chain multiple registrations
544
+ context
545
+ .registerService(service1)
546
+ .registerService(service2)
547
+ .registerModule(module1)
548
+ .registerResource(resource1)
549
+
550
+ // Error handling for service access
551
+ try {
552
+ const nonExistentService = context.service('non-existent')
553
+ } catch (error) {
554
+ console.error('Service not found:', error.message)
555
+ // Output: Service non-existent not found in layer service
556
+ }
557
+
558
+ // Safe service access using hasService
559
+ if (context.hasService('service1')) {
560
+ const service = context.service('service1')
561
+ console.log('Service value:', service.value)
562
+ }
563
+
564
+ // Error handling for uninitialized services
565
+ await context.configure().init()
566
+
567
+ // Now services are accessible
568
+ const service = context.service('service1')
569
+ console.log('Service accessible after init:', service.value)
570
+ ```
571
+
572
+ ### Context Lifecycle Management
573
+
574
+ ```typescript
575
+ const context = makeBasicContext(config)
576
+
577
+ // Register components during Configuration stage
578
+ console.log('Stage:', context.stage) // ContextStage.Configuration
579
+
580
+ context.registerService(myService)
581
+ context.registerModule(myModule)
582
+
583
+ // Move to Loading stage
584
+ context.configure()
585
+ console.log('Stage:', context.stage) // ContextStage.Loading
586
+
587
+ // Move to Ready stage
588
+ await context.init()
589
+ console.log('Stage:', context.stage) // ContextStage.Ready
590
+
591
+ // Context lifecycle promises
592
+ const configuredPromise = context.waitForConfigured()
593
+ const initializedPromise = context.waitForInitialized()
594
+
595
+ // Both promises resolve immediately if context is already ready
596
+ await configuredPromise // Resolves to true
597
+ await initializedPromise // Resolves to true
598
+ ```
599
+
600
+ ### Module Registration
601
+
602
+ ```typescript
603
+ import { appendContextual } from '@owlmeans/context'
604
+
605
+ // Create a module
606
+ const userModule = appendContextual('user', {
607
+ _module: true,
608
+ routes: {
609
+ login: '/login',
610
+ profile: '/profile'
611
+ }
612
+ })
613
+
614
+ // Register the module
615
+ context.registerModule(userModule)
616
+
617
+ // Access the module
618
+ const module = context.module('user')
619
+ ```
620
+
621
+ ### Resource Management
622
+
623
+ ```typescript
624
+ const dbResource = appendContextual('db-connection', {
625
+ connection: null,
626
+ init: async () => {
627
+ // Initialize database connection
628
+ console.log('Database connection initialized')
629
+ }
630
+ })
631
+
632
+ context.registerResource(dbResource)
633
+
634
+ // Resource will be initialized during context initialization
635
+ await context.init()
636
+
637
+ // Access the resource
638
+ const db = context.resource('db-connection')
639
+ ```
640
+
641
+ ### Middleware Usage
642
+
643
+ ```typescript
644
+ const loggingMiddleware = {
645
+ type: MiddlewareType.Context,
646
+ stage: MiddlewareStage.Ready,
647
+ apply: async (context) => {
648
+ console.log(`Context ${context.cfg.service} is ready`)
649
+ }
650
+ }
651
+
652
+ context.registerMiddleware(loggingMiddleware)
653
+ ```
654
+
655
+ ## Context Lifecycle
656
+
657
+ 1. **Configuration Stage**: Register services, modules, resources, and middlewares
658
+ 2. **Loading Stage**: Initialize services and resources
659
+ 3. **Ready Stage**: Context is ready for use
660
+
661
+ ```typescript
662
+ // Configuration stage
663
+ const context = makeBasicContext(config)
664
+ context.registerService(myService)
665
+ context.registerModule(myModule)
666
+
667
+ // Move to loading stage
668
+ context.configure()
669
+
670
+ // Initialize and move to ready stage
671
+ await context.init()
672
+
673
+ // Context is now ready
674
+ console.log(context.stage) // ContextStage.Ready
675
+ ```
676
+
677
+ ## Integration with Other Packages
678
+
679
+ The context package integrates seamlessly with other OwlMeans packages:
680
+
681
+ ```typescript
682
+ import { makeServerContext } from '@owlmeans/server-context'
683
+ import { makeClientContext } from '@owlmeans/client-context'
684
+
685
+ // Server-side context with additional capabilities
686
+ const serverContext = makeServerContext(serverConfig)
687
+
688
+ // Client-side context with additional capabilities
689
+ const clientContext = makeClientContext(clientConfig)
690
+ ```
691
+
692
+ ## Helper Functions
693
+
694
+ ### `assertContext<C extends BasicConfig, T extends BasicContext<C>>(ctx: T | undefined, location?: string): T`
695
+
696
+ Asserts that a context is defined and throws an error if not.
697
+
698
+ ```typescript
699
+ import { assertContext } from '@owlmeans/context'
700
+
701
+ const context = assertContext(maybeContext, 'MyService')
702
+ ```
703
+
704
+ ### `isContextWithoutIds<C extends BasicConfig, T extends BasicContext<C>>(context: T): boolean`
705
+
706
+ Checks if a context operates without IDs (System, Global, or Service layers).
707
+
708
+ ```typescript
709
+ import { isContextWithoutIds } from '@owlmeans/context'
710
+
711
+ const needsIds = !isContextWithoutIds(context)
712
+ ```
713
+
714
+ ## Error Handling
715
+
716
+ The package throws `SyntaxError` for common issues:
717
+
718
+ - Service not found: When accessing an unregistered service
719
+ - Module not found: When accessing an unregistered module
720
+ - Resource not found: When accessing an unregistered resource
721
+ - Context not found: When context is undefined in a contextual object
722
+ - Service not initialized: When accessing a non-initialized service
723
+
724
+ ## Best Practices
725
+
726
+ 1. **Use Factory Functions**: Always use the provided factory functions instead of constructors
727
+ 2. **Layer Organization**: Organize your components by appropriate layers
728
+ 3. **Service Initialization**: Choose between immediate and lazy initialization based on your needs
729
+ 4. **Error Handling**: Always handle potential errors when accessing services, modules, or resources
730
+ 5. **Context Lifecycle**: Respect the context lifecycle stages
731
+ 6. **Middleware Order**: Be mindful of middleware execution order and stages
732
+
733
+ ## TypeScript Support
734
+
735
+ The package is written in TypeScript and provides full type safety:
736
+
737
+ ```typescript
738
+ import type { BasicContext, BasicConfig, Service } from '@owlmeans/context'
739
+
740
+ interface MyConfig extends BasicConfig {
741
+ customOption: string
742
+ }
743
+
744
+ interface MyService extends Service {
745
+ customMethod(): void
746
+ }
747
+
748
+ const context: BasicContext<MyConfig> = makeBasicContext(config)
749
+ const service: MyService = context.service('my-service')
750
+ ```