@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.
- package/LICENSE +21 -0
- package/README.md +750 -0
- package/build/.gitkeep +0 -0
- package/build/config.d.ts +4 -0
- package/build/config.d.ts.map +1 -0
- package/build/config.js +15 -0
- package/build/config.js.map +1 -0
- package/build/consts.d.ts +50 -0
- package/build/consts.d.ts.map +1 -0
- package/build/consts.js +56 -0
- package/build/consts.js.map +1 -0
- package/build/context.d.ts +3 -0
- package/build/context.d.ts.map +1 -0
- package/build/context.js +203 -0
- package/build/context.js.map +1 -0
- package/build/helper.d.ts +8 -0
- package/build/helper.d.ts.map +1 -0
- package/build/helper.js +31 -0
- package/build/helper.js.map +1 -0
- package/build/index.d.ts +7 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +6 -0
- package/build/index.js.map +1 -0
- package/build/service.d.ts +7 -0
- package/build/service.d.ts.map +1 -0
- package/build/service.js +27 -0
- package/build/service.js.map +1 -0
- package/build/types.d.ts +80 -0
- package/build/types.d.ts.map +1 -0
- package/build/types.js +2 -0
- package/build/types.js.map +1 -0
- package/build/utils/context.d.ts +11 -0
- package/build/utils/context.d.ts.map +1 -0
- package/build/utils/context.js +15 -0
- package/build/utils/context.js.map +1 -0
- package/build/utils/index.d.ts +3 -0
- package/build/utils/index.d.ts.map +1 -0
- package/build/utils/index.js +3 -0
- package/build/utils/index.js.map +1 -0
- package/build/utils/layer.d.ts +6 -0
- package/build/utils/layer.d.ts.map +1 -0
- package/build/utils/layer.js +12 -0
- package/build/utils/layer.js.map +1 -0
- package/package.json +31 -0
- package/src/config.ts +17 -0
- package/src/consts.ts +58 -0
- package/src/context.ts +261 -0
- package/src/helper.ts +43 -0
- package/src/index.ts +7 -0
- package/src/service.ts +49 -0
- package/src/types.ts +96 -0
- package/src/utils/context.ts +34 -0
- package/src/utils/index.ts +3 -0
- package/src/utils/layer.ts +17 -0
- package/tsconfig.json +14 -0
- 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
|
+
```
|