@owlmeans/server-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 +516 -0
- package/build/.gitkeep +0 -0
- package/build/config.d.ts +3 -0
- package/build/config.d.ts.map +1 -0
- package/build/config.js +7 -0
- package/build/config.js.map +1 -0
- package/build/consts.d.ts +1 -0
- package/build/consts.d.ts.map +1 -0
- package/build/consts.js +2 -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 +17 -0
- package/build/context.js.map +1 -0
- package/build/index.d.ts +4 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +4 -0
- package/build/index.js.map +1 -0
- package/build/types.d.ts +11 -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 +3 -0
- package/build/utils/context.d.ts.map +1 -0
- package/build/utils/context.js +26 -0
- package/build/utils/context.js.map +1 -0
- package/build/utils/index.d.ts +2 -0
- package/build/utils/index.d.ts.map +1 -0
- package/build/utils/index.js +2 -0
- package/build/utils/index.js.map +1 -0
- package/package.json +45 -0
- package/src/config.ts +10 -0
- package/src/consts.ts +1 -0
- package/src/context.ts +22 -0
- package/src/index.ts +5 -0
- package/src/types.ts +12 -0
- package/src/utils/context.ts +32 -0
- package/src/utils/index.ts +2 -0
- package/tsconfig.json +14 -0
- package/tsconfig.tsbuildinfo +1 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 OwlMeans Common — Fullstack typescript framework
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
# @owlmeans/server-context
|
|
2
|
+
|
|
3
|
+
Server-side context and dependency injection system for OwlMeans Common applications. This package extends the base OwlMeans context system with server-specific functionality, configuration management, and authentication capabilities for building secure backend services.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The `@owlmeans/server-context` package provides server-specific extensions to the OwlMeans context system, offering:
|
|
8
|
+
|
|
9
|
+
- **Server Context Management**: Enhanced context with server-specific capabilities
|
|
10
|
+
- **Configuration Integration**: Built-in configuration resource management
|
|
11
|
+
- **Authentication Guards**: Pre-configured Ed25519 authentication guards
|
|
12
|
+
- **Middleware System**: Server-optimized middleware for request processing
|
|
13
|
+
- **Service Registration**: Streamlined service registration for server components
|
|
14
|
+
- **File Configuration**: File-based configuration reading capabilities
|
|
15
|
+
- **Security Defaults**: Secure-by-default configuration for production servers
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @owlmeans/server-context
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Core Concepts
|
|
24
|
+
|
|
25
|
+
### Server Context
|
|
26
|
+
|
|
27
|
+
The `ServerContext` extends the basic OwlMeans context with server-specific functionality, including configuration resource management and enhanced service capabilities.
|
|
28
|
+
|
|
29
|
+
### Server Configuration
|
|
30
|
+
|
|
31
|
+
The `ServerConfig` combines server and client configuration options, providing a unified configuration structure for fullstack applications.
|
|
32
|
+
|
|
33
|
+
### Security Integration
|
|
34
|
+
|
|
35
|
+
Built-in integration with authentication guards and middleware for secure service-to-service communication.
|
|
36
|
+
|
|
37
|
+
## API Reference
|
|
38
|
+
|
|
39
|
+
### Types
|
|
40
|
+
|
|
41
|
+
#### `ServerConfig`
|
|
42
|
+
Extended configuration interface for server applications.
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
interface ServerConfig extends BasicServerConfig, BasicClientConfig {
|
|
46
|
+
services: Record<string, ServiceRoute>
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
#### `ServerContext<C extends ServerConfig>`
|
|
51
|
+
Enhanced context interface with server capabilities.
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
interface ServerContext<C extends ServerConfig> extends BasicContext<C>, ConfigResourceAppend {
|
|
55
|
+
// Inherits all BasicContext functionality plus configuration resource management
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Factory Functions
|
|
60
|
+
|
|
61
|
+
#### `makeServerContext<C, T>(cfg: C): T`
|
|
62
|
+
Creates a server context with enhanced capabilities.
|
|
63
|
+
|
|
64
|
+
**Parameters:**
|
|
65
|
+
- `cfg`: Server configuration object
|
|
66
|
+
|
|
67
|
+
**Returns:** Configured server context instance
|
|
68
|
+
|
|
69
|
+
**Features:**
|
|
70
|
+
- Registers file configuration reader middleware
|
|
71
|
+
- Adds configuration resource management
|
|
72
|
+
- Sets up trusted entity resource
|
|
73
|
+
- Configures plugin resource management
|
|
74
|
+
- Registers Ed25519 authentication guard
|
|
75
|
+
- Adds authentication middleware
|
|
76
|
+
|
|
77
|
+
#### `config<C>(service: string, cfg?: Partial<C>): C`
|
|
78
|
+
Creates a server configuration with default settings.
|
|
79
|
+
|
|
80
|
+
**Parameters:**
|
|
81
|
+
- `service`: Service name identifier
|
|
82
|
+
- `cfg`: Optional partial configuration
|
|
83
|
+
|
|
84
|
+
**Returns:** Complete server configuration
|
|
85
|
+
|
|
86
|
+
## Usage Examples
|
|
87
|
+
|
|
88
|
+
### Basic Server Setup
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
import { makeServerContext, config } from '@owlmeans/server-context'
|
|
92
|
+
|
|
93
|
+
// Create server configuration
|
|
94
|
+
const serverConfig = config('my-service', {
|
|
95
|
+
port: 3000,
|
|
96
|
+
host: 'localhost',
|
|
97
|
+
services: {
|
|
98
|
+
database: {
|
|
99
|
+
protocol: 'mongodb',
|
|
100
|
+
host: 'localhost',
|
|
101
|
+
port: 27017
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
// Create server context
|
|
107
|
+
const context = makeServerContext(serverConfig)
|
|
108
|
+
|
|
109
|
+
// Initialize the context
|
|
110
|
+
await context.init()
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Configuration with Resources
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
import { makeServerContext, config } from '@owlmeans/server-context'
|
|
117
|
+
|
|
118
|
+
const serverConfig = config('api-server', {
|
|
119
|
+
// Database configurations
|
|
120
|
+
dbs: [
|
|
121
|
+
{
|
|
122
|
+
service: 'mongo',
|
|
123
|
+
alias: 'primary',
|
|
124
|
+
host: 'localhost',
|
|
125
|
+
port: 27017,
|
|
126
|
+
schema: 'myapp'
|
|
127
|
+
}
|
|
128
|
+
],
|
|
129
|
+
|
|
130
|
+
// Trusted services for authentication
|
|
131
|
+
trusted: [
|
|
132
|
+
{
|
|
133
|
+
id: 'internal-service',
|
|
134
|
+
recordType: 'trusted-source',
|
|
135
|
+
name: 'Internal Service',
|
|
136
|
+
entityId: 'internal',
|
|
137
|
+
scopes: ['api:*']
|
|
138
|
+
}
|
|
139
|
+
],
|
|
140
|
+
|
|
141
|
+
// Service routes
|
|
142
|
+
services: {
|
|
143
|
+
'user-service': {
|
|
144
|
+
protocol: 'https',
|
|
145
|
+
host: 'user-service.internal',
|
|
146
|
+
port: 443
|
|
147
|
+
},
|
|
148
|
+
'auth-service': {
|
|
149
|
+
protocol: 'https',
|
|
150
|
+
host: 'auth-service.internal',
|
|
151
|
+
port: 443
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
const context = makeServerContext(serverConfig)
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Service Registration
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
import { makeServerContext, config } from '@owlmeans/server-context'
|
|
163
|
+
import { createDbService } from '@owlmeans/mongo'
|
|
164
|
+
|
|
165
|
+
const context = makeServerContext(config('my-service'))
|
|
166
|
+
|
|
167
|
+
// Register database service
|
|
168
|
+
const dbService = createDbService('primary')
|
|
169
|
+
context.registerService(dbService)
|
|
170
|
+
|
|
171
|
+
// Register custom service
|
|
172
|
+
const customService = {
|
|
173
|
+
alias: 'custom-logic',
|
|
174
|
+
initialized: false,
|
|
175
|
+
init: async () => {
|
|
176
|
+
console.log('Custom service initialized')
|
|
177
|
+
return true
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
context.registerService(customService)
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Authentication Setup
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
import { makeServerContext, config } from '@owlmeans/server-context'
|
|
187
|
+
|
|
188
|
+
const serverConfig = config('secure-service', {
|
|
189
|
+
trusted: [
|
|
190
|
+
{
|
|
191
|
+
id: 'client-app',
|
|
192
|
+
recordType: 'trusted-source',
|
|
193
|
+
name: 'Client Application',
|
|
194
|
+
credential: 'base64-encoded-public-key',
|
|
195
|
+
scopes: ['read', 'write']
|
|
196
|
+
}
|
|
197
|
+
]
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
const context = makeServerContext(serverConfig)
|
|
201
|
+
|
|
202
|
+
// The Ed25519 guard is automatically registered
|
|
203
|
+
// Authentication middleware is automatically added
|
|
204
|
+
// Requests with valid signatures will be authenticated
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Custom Middleware Registration
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
import { makeServerContext, config } from '@owlmeans/server-context'
|
|
211
|
+
import { MiddlewareType, MiddlewareStage } from '@owlmeans/context'
|
|
212
|
+
|
|
213
|
+
const context = makeServerContext(config('my-service'))
|
|
214
|
+
|
|
215
|
+
// Add custom middleware
|
|
216
|
+
context.registerMiddleware({
|
|
217
|
+
type: MiddlewareType.Context,
|
|
218
|
+
stage: MiddlewareStage.Loading,
|
|
219
|
+
apply: async (ctx) => {
|
|
220
|
+
console.log('Custom middleware executed')
|
|
221
|
+
// Custom logic here
|
|
222
|
+
}
|
|
223
|
+
})
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Configuration File Reading
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
// config.json
|
|
230
|
+
{
|
|
231
|
+
"service": "file-config-service",
|
|
232
|
+
"port": 8080,
|
|
233
|
+
"dbs": [
|
|
234
|
+
{
|
|
235
|
+
"service": "mongo",
|
|
236
|
+
"host": "mongodb://localhost:27017",
|
|
237
|
+
"schema": "production"
|
|
238
|
+
}
|
|
239
|
+
]
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
import { makeServerContext } from '@owlmeans/server-context'
|
|
245
|
+
|
|
246
|
+
// File configuration is automatically read via middleware
|
|
247
|
+
const context = makeServerContext({} as any)
|
|
248
|
+
|
|
249
|
+
// Configuration will be populated from files
|
|
250
|
+
await context.init()
|
|
251
|
+
|
|
252
|
+
// Access configuration
|
|
253
|
+
const config = context.cfg
|
|
254
|
+
console.log(`Service running on port ${config.port}`)
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Resource Management
|
|
258
|
+
|
|
259
|
+
```typescript
|
|
260
|
+
import { makeServerContext, config } from '@owlmeans/server-context'
|
|
261
|
+
|
|
262
|
+
const context = makeServerContext(config('resource-service'))
|
|
263
|
+
|
|
264
|
+
// Access configuration resources
|
|
265
|
+
const configResource = context.getConfigResource()
|
|
266
|
+
const trustedResource = context.getConfigResource('trusted')
|
|
267
|
+
const pluginResource = context.getConfigResource('plugin')
|
|
268
|
+
|
|
269
|
+
// Create new configuration records
|
|
270
|
+
await configResource.create({
|
|
271
|
+
id: 'feature-flag',
|
|
272
|
+
recordType: 'feature',
|
|
273
|
+
enabled: true,
|
|
274
|
+
description: 'Enable new feature'
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
// Query trusted entities
|
|
278
|
+
const trustedEntities = await trustedResource.list({
|
|
279
|
+
criteria: { scopes: ['admin'] }
|
|
280
|
+
})
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Plugin System Integration
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
import { makeServerContext, config } from '@owlmeans/server-context'
|
|
287
|
+
|
|
288
|
+
const serverConfig = config('plugin-host', {
|
|
289
|
+
plugins: [
|
|
290
|
+
{
|
|
291
|
+
id: 'auth-plugin',
|
|
292
|
+
recordType: 'plugin',
|
|
293
|
+
name: 'Authentication Plugin',
|
|
294
|
+
version: '1.0.0',
|
|
295
|
+
enabled: true,
|
|
296
|
+
config: {
|
|
297
|
+
provider: 'oauth2',
|
|
298
|
+
clientId: 'app-client-id'
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
]
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
const context = makeServerContext(serverConfig)
|
|
305
|
+
|
|
306
|
+
// Access plugin configuration
|
|
307
|
+
const pluginResource = context.getConfigResource('plugin')
|
|
308
|
+
const authPlugin = await pluginResource.get('auth-plugin')
|
|
309
|
+
|
|
310
|
+
if (authPlugin.enabled) {
|
|
311
|
+
// Initialize plugin
|
|
312
|
+
console.log(`Loading ${authPlugin.name} v${authPlugin.version}`)
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Multi-Service Architecture
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
import { makeServerContext, config } from '@owlmeans/server-context'
|
|
320
|
+
|
|
321
|
+
// Gateway service configuration
|
|
322
|
+
const gatewayConfig = config('api-gateway', {
|
|
323
|
+
services: {
|
|
324
|
+
'user-service': {
|
|
325
|
+
protocol: 'http',
|
|
326
|
+
host: 'user-service',
|
|
327
|
+
port: 3001
|
|
328
|
+
},
|
|
329
|
+
'order-service': {
|
|
330
|
+
protocol: 'http',
|
|
331
|
+
host: 'order-service',
|
|
332
|
+
port: 3002
|
|
333
|
+
},
|
|
334
|
+
'payment-service': {
|
|
335
|
+
protocol: 'https',
|
|
336
|
+
host: 'payment-service.external',
|
|
337
|
+
port: 443
|
|
338
|
+
}
|
|
339
|
+
},
|
|
340
|
+
|
|
341
|
+
trusted: [
|
|
342
|
+
{
|
|
343
|
+
id: 'user-service',
|
|
344
|
+
recordType: 'trusted-source',
|
|
345
|
+
name: 'User Service',
|
|
346
|
+
scopes: ['users:*']
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
id: 'order-service',
|
|
350
|
+
recordType: 'trusted-source',
|
|
351
|
+
name: 'Order Service',
|
|
352
|
+
scopes: ['orders:*', 'users:read']
|
|
353
|
+
}
|
|
354
|
+
]
|
|
355
|
+
})
|
|
356
|
+
|
|
357
|
+
const gateway = makeServerContext(gatewayConfig)
|
|
358
|
+
|
|
359
|
+
// Service can now route to other services with authentication
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
### Error Handling
|
|
363
|
+
|
|
364
|
+
```typescript
|
|
365
|
+
import { makeServerContext, config } from '@owlmeans/server-context'
|
|
366
|
+
|
|
367
|
+
try {
|
|
368
|
+
const context = makeServerContext(config('error-service'))
|
|
369
|
+
await context.init()
|
|
370
|
+
} catch (error) {
|
|
371
|
+
console.error('Failed to initialize server context:', error)
|
|
372
|
+
|
|
373
|
+
// Handle specific initialization errors
|
|
374
|
+
if (error.message.includes('database')) {
|
|
375
|
+
console.error('Database connection failed')
|
|
376
|
+
} else if (error.message.includes('config')) {
|
|
377
|
+
console.error('Configuration error')
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
process.exit(1)
|
|
381
|
+
}
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
## Advanced Features
|
|
385
|
+
|
|
386
|
+
### Custom Context Extensions
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
import { makeServerContext, ServerContext, ServerConfig } from '@owlmeans/server-context'
|
|
390
|
+
|
|
391
|
+
interface CustomConfig extends ServerConfig {
|
|
392
|
+
customFeature: boolean
|
|
393
|
+
apiKeys: string[]
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
interface CustomContext extends ServerContext<CustomConfig> {
|
|
397
|
+
customMethod: () => void
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
const createCustomContext = (cfg: CustomConfig): CustomContext => {
|
|
401
|
+
const context = makeServerContext(cfg) as CustomContext
|
|
402
|
+
|
|
403
|
+
context.customMethod = () => {
|
|
404
|
+
console.log('Custom context method')
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
return context
|
|
408
|
+
}
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### Dynamic Service Discovery
|
|
412
|
+
|
|
413
|
+
```typescript
|
|
414
|
+
import { makeServerContext, config } from '@owlmeans/server-context'
|
|
415
|
+
|
|
416
|
+
const context = makeServerContext(config('discovery-service'))
|
|
417
|
+
|
|
418
|
+
// Dynamic service registration
|
|
419
|
+
const discoverServices = async () => {
|
|
420
|
+
const services = await fetchAvailableServices()
|
|
421
|
+
|
|
422
|
+
services.forEach(service => {
|
|
423
|
+
context.cfg.services[service.name] = {
|
|
424
|
+
protocol: service.protocol,
|
|
425
|
+
host: service.host,
|
|
426
|
+
port: service.port
|
|
427
|
+
}
|
|
428
|
+
})
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
await discoverServices()
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
### Health Checks
|
|
435
|
+
|
|
436
|
+
```typescript
|
|
437
|
+
import { makeServerContext, config } from '@owlmeans/server-context'
|
|
438
|
+
|
|
439
|
+
const context = makeServerContext(config('health-service'))
|
|
440
|
+
|
|
441
|
+
const healthCheck = async () => {
|
|
442
|
+
try {
|
|
443
|
+
// Check all registered services
|
|
444
|
+
const services = Object.keys(context.cfg.services)
|
|
445
|
+
const healthStatuses = await Promise.all(
|
|
446
|
+
services.map(async service => {
|
|
447
|
+
try {
|
|
448
|
+
await context.service(service)
|
|
449
|
+
return { service, status: 'healthy' }
|
|
450
|
+
} catch (error) {
|
|
451
|
+
return { service, status: 'unhealthy', error: error.message }
|
|
452
|
+
}
|
|
453
|
+
})
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
return healthStatuses
|
|
457
|
+
} catch (error) {
|
|
458
|
+
return { status: 'error', message: error.message }
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
## Integration with OwlMeans Ecosystem
|
|
464
|
+
|
|
465
|
+
The `@owlmeans/server-context` package integrates with:
|
|
466
|
+
|
|
467
|
+
- **@owlmeans/context**: Base context and dependency injection system
|
|
468
|
+
- **@owlmeans/config**: Configuration management and resource handling
|
|
469
|
+
- **@owlmeans/server-config**: Server-specific configuration structures
|
|
470
|
+
- **@owlmeans/client-config**: Client configuration for fullstack apps
|
|
471
|
+
- **@owlmeans/server-route**: Service routing and discovery
|
|
472
|
+
- **@owlmeans/auth-common**: Authentication middleware and guards
|
|
473
|
+
- **@owlmeans/mongo**: Database service integration
|
|
474
|
+
- **@owlmeans/redis**: Cache service integration
|
|
475
|
+
|
|
476
|
+
## Security Features
|
|
477
|
+
|
|
478
|
+
### Built-in Authentication
|
|
479
|
+
- Ed25519 signature-based authentication guard
|
|
480
|
+
- Automatic authentication middleware
|
|
481
|
+
- Trusted entity management
|
|
482
|
+
- Secure service-to-service communication
|
|
483
|
+
|
|
484
|
+
### Configuration Security
|
|
485
|
+
- Secure file configuration reading
|
|
486
|
+
- Environment variable support
|
|
487
|
+
- Secret management integration
|
|
488
|
+
- Access control for configuration resources
|
|
489
|
+
|
|
490
|
+
## Best Practices
|
|
491
|
+
|
|
492
|
+
### Configuration Management
|
|
493
|
+
- Use environment-specific configuration files
|
|
494
|
+
- Store secrets in secure environment variables
|
|
495
|
+
- Implement configuration validation
|
|
496
|
+
- Use typed configuration interfaces
|
|
497
|
+
|
|
498
|
+
### Service Architecture
|
|
499
|
+
- Register services during context initialization
|
|
500
|
+
- Implement proper service lifecycle management
|
|
501
|
+
- Use dependency injection for service access
|
|
502
|
+
- Handle service failures gracefully
|
|
503
|
+
|
|
504
|
+
### Security
|
|
505
|
+
- Always use authentication guards for protected services
|
|
506
|
+
- Implement proper authorization checks
|
|
507
|
+
- Validate all incoming requests
|
|
508
|
+
- Use secure communication protocols
|
|
509
|
+
|
|
510
|
+
### Performance
|
|
511
|
+
- Initialize context once during application startup
|
|
512
|
+
- Cache frequently accessed configuration
|
|
513
|
+
- Use lazy service initialization where appropriate
|
|
514
|
+
- Monitor resource usage and optimize accordingly
|
|
515
|
+
|
|
516
|
+
Fixes #32.
|
package/build/.gitkeep
ADDED
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,eAAO,MAAM,MAAM,GAAI,CAAC,SAAS,YAAY,WAAW,MAAM,QAAQ,OAAO,CAAC,CAAC,CAAC,KAAG,CAKlF,CAAA"}
|
package/build/config.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { AppType, makeBasicConfig } from '@owlmeans/context';
|
|
2
|
+
export const config = (service, cfg) => {
|
|
3
|
+
const config = makeBasicConfig(AppType.Backend, service, cfg);
|
|
4
|
+
config.trusted = config.trusted ?? [];
|
|
5
|
+
return config;
|
|
6
|
+
};
|
|
7
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAG5D,MAAM,CAAC,MAAM,MAAM,GAAG,CAAyB,OAAe,EAAE,GAAgB,EAAK,EAAE;IACrF,MAAM,MAAM,GAAM,eAAe,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;IAChE,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,EAAE,CAAA;IAErC,OAAO,MAAM,CAAA;AACf,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=consts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":""}
|
package/build/consts.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consts.js","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAMxD,eAAO,MAAM,iBAAiB,GAAI,CAAC,SAAS,YAAY,EAAE,CAAC,SAAS,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,KAAG,CAc9F,CAAA"}
|
package/build/context.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { appendConfigResource, PLUGIN_RECORD } from '@owlmeans/config';
|
|
2
|
+
import { fileConfigReader } from './utils/context.js';
|
|
3
|
+
import { makeBasicContext } from '@owlmeans/context';
|
|
4
|
+
import { PLUGINS, TRUSTED } from '@owlmeans/config';
|
|
5
|
+
import { authMiddleware, makeBasicEd25519Guard } from '@owlmeans/auth-common';
|
|
6
|
+
export const makeServerContext = (cfg) => {
|
|
7
|
+
const context = makeBasicContext(cfg);
|
|
8
|
+
context.registerMiddleware(fileConfigReader);
|
|
9
|
+
context.makeContext = makeServerContext;
|
|
10
|
+
appendConfigResource(context);
|
|
11
|
+
appendConfigResource(context, TRUSTED, TRUSTED);
|
|
12
|
+
appendConfigResource(context, PLUGINS, PLUGIN_RECORD);
|
|
13
|
+
context.registerService(makeBasicEd25519Guard(TRUSTED));
|
|
14
|
+
context.registerMiddleware(authMiddleware);
|
|
15
|
+
return context;
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAEtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAE7E,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAqD,GAAM,EAAK,EAAE;IACjG,MAAM,OAAO,GAAG,gBAAgB,CAAC,GAAG,CAAM,CAAA;IAE1C,OAAO,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,CAAA;IAE5C,OAAO,CAAC,WAAW,GAAG,iBAA+C,CAAA;IAErE,oBAAoB,CAAO,OAAO,CAAC,CAAA;IACnC,oBAAoB,CAAO,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IACrD,oBAAoB,CAAO,OAAO,EAAE,OAAO,EAAE,aAAa,CAAC,CAAA;IAC3D,OAAO,CAAC,eAAe,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC,CAAA;IACvD,OAAO,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAA;IAE1C,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
|
package/build/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAA;AAE5B,cAAc,aAAa,CAAA;AAC3B,mBAAmB,YAAY,CAAA"}
|
package/build/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAA;AAC5B,8BAA8B;AAC9B,cAAc,aAAa,CAAA"}
|
package/build/types.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ServiceRoute } from '@owlmeans/server-route';
|
|
2
|
+
import type { ConfigResourceAppend } from '@owlmeans/config';
|
|
3
|
+
import type { BasicServerConfig } from '@owlmeans/server-config';
|
|
4
|
+
import type { BasicClientConfig } from '@owlmeans/client-config';
|
|
5
|
+
import type { BasicContext } from '@owlmeans/context';
|
|
6
|
+
export interface ServerConfig extends BasicServerConfig, BasicClientConfig {
|
|
7
|
+
services: Record<string, ServiceRoute>;
|
|
8
|
+
}
|
|
9
|
+
export interface ServerContext<C extends ServerConfig> extends BasicContext<C>, ConfigResourceAppend {
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAC1D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAChE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAErD,MAAM,WAAW,YAAa,SAAQ,iBAAiB,EAAE,iBAAiB;IACxE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;CACvC;AAED,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,YAAY,CAAE,SAAQ,YAAY,CAAC,CAAC,CAAC,EAAE,oBAAoB;CACnG"}
|
package/build/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/utils/context.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAGnD,eAAO,MAAM,gBAAgB,EAAE,UAO9B,CAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { MiddlewareStage, MiddlewareType } from '@owlmeans/context';
|
|
2
|
+
import { readConfigValue } from '@owlmeans/server-config';
|
|
3
|
+
export const fileConfigReader = {
|
|
4
|
+
type: MiddlewareType.Config,
|
|
5
|
+
stage: MiddlewareStage.Configuration,
|
|
6
|
+
apply: async (context) => {
|
|
7
|
+
const tree = context.cfg;
|
|
8
|
+
visitConfigLeafs(tree);
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
// @TODO Move to server config
|
|
12
|
+
const visitConfigLeafs = (tree) => tree != null ? Object.entries(tree).forEach(([key, value]) => {
|
|
13
|
+
if (typeof value === 'string') {
|
|
14
|
+
const descriptor = Object.getOwnPropertyDescriptor(tree, key);
|
|
15
|
+
if (descriptor?.writable) {
|
|
16
|
+
tree[key] = readConfigValue(value);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
else if (Array.isArray(value)) {
|
|
20
|
+
value.forEach(tree => { visitConfigLeafs(tree); });
|
|
21
|
+
}
|
|
22
|
+
else if (typeof value === 'object') {
|
|
23
|
+
visitConfigLeafs(value);
|
|
24
|
+
}
|
|
25
|
+
}) : tree;
|
|
26
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/utils/context.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAEnE,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAEzD,MAAM,CAAC,MAAM,gBAAgB,GAAe;IAC1C,IAAI,EAAE,cAAc,CAAC,MAAM;IAC3B,KAAK,EAAE,eAAe,CAAC,aAAa;IACpC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QACvB,MAAM,IAAI,GAAS,OAAO,CAAC,GAAsB,CAAA;QACjD,gBAAgB,CAAC,IAAI,CAAC,CAAA;IACxB,CAAC;CACF,CAAA;AAED,8BAA8B;AAC9B,MAAM,gBAAgB,GAAG,CAAC,IAAU,EAAE,EAAE,CACtC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;IAC3D,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,UAAU,GAAG,MAAM,CAAC,wBAAwB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QAC7D,IAAI,UAAU,EAAE,QAAQ,EAAE,CAAC;YACzB,IAAI,CAAC,GAAG,CAAC,GAAG,eAAe,CAAC,KAAK,CAAC,CAAA;QACpC,CAAC;IACH,CAAC;SAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAChC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,gBAAgB,CAAC,IAAY,CAAC,CAAA,CAAC,CAAC,CAAC,CAAA;IAC3D,CAAC;SAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACrC,gBAAgB,CAAC,KAAa,CAAC,CAAA;IACjC,CAAC;AACH,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@owlmeans/server-context",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "tsc -b",
|
|
7
|
+
"dev": "sleep 288 && nodemon -e ts,tsx,json --watch src --exec \"tsc -p ./tsconfig.json\"",
|
|
8
|
+
"watch": "tsc -b -w --preserveWatchOutput --pretty"
|
|
9
|
+
},
|
|
10
|
+
"main": "build/index.js",
|
|
11
|
+
"module": "build/index.js",
|
|
12
|
+
"types": "build/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"import": "./build/index.js",
|
|
16
|
+
"require": "./build/index.js",
|
|
17
|
+
"default": "./build/index.js",
|
|
18
|
+
"module": "./build/index.js",
|
|
19
|
+
"types": "./build/index.d.ts"
|
|
20
|
+
},
|
|
21
|
+
"./utils": {
|
|
22
|
+
"import": "./build/utils/index.js",
|
|
23
|
+
"require": "./build/utils/index.js",
|
|
24
|
+
"default": "./build/utils/index.js",
|
|
25
|
+
"module": "./build/utils/index.js",
|
|
26
|
+
"types": "./build/utils/index.d.ts"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@owlmeans/client-config": "^0.1.0",
|
|
31
|
+
"@owlmeans/config": "^0.1.0",
|
|
32
|
+
"@owlmeans/context": "^0.1.0",
|
|
33
|
+
"@owlmeans/route": "^0.1.0",
|
|
34
|
+
"@owlmeans/server-config": "^0.1.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/node": "^22.5.0",
|
|
38
|
+
"nodemon": "^3.1.7",
|
|
39
|
+
"typescript": "^5.6.3"
|
|
40
|
+
},
|
|
41
|
+
"private": false,
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
}
|
|
45
|
+
}
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
|
|
2
|
+
import { AppType, makeBasicConfig } from '@owlmeans/context'
|
|
3
|
+
import type { ServerConfig } from './types.js'
|
|
4
|
+
|
|
5
|
+
export const config = <C extends ServerConfig>(service: string, cfg?: Partial<C>): C => {
|
|
6
|
+
const config: C = makeBasicConfig(AppType.Backend, service, cfg)
|
|
7
|
+
config.trusted = config.trusted ?? []
|
|
8
|
+
|
|
9
|
+
return config
|
|
10
|
+
}
|
package/src/consts.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
package/src/context.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { appendConfigResource, PLUGIN_RECORD } from '@owlmeans/config'
|
|
2
|
+
import { ServerConfig, ServerContext } from './types.js'
|
|
3
|
+
import { fileConfigReader } from './utils/context.js'
|
|
4
|
+
import { makeBasicContext } from '@owlmeans/context'
|
|
5
|
+
import { PLUGINS, TRUSTED } from '@owlmeans/config'
|
|
6
|
+
import { authMiddleware, makeBasicEd25519Guard } from '@owlmeans/auth-common'
|
|
7
|
+
|
|
8
|
+
export const makeServerContext = <C extends ServerConfig, T extends ServerContext<C>>(cfg: C): T => {
|
|
9
|
+
const context = makeBasicContext(cfg) as T
|
|
10
|
+
|
|
11
|
+
context.registerMiddleware(fileConfigReader)
|
|
12
|
+
|
|
13
|
+
context.makeContext = makeServerContext as typeof context.makeContext
|
|
14
|
+
|
|
15
|
+
appendConfigResource<C, T>(context)
|
|
16
|
+
appendConfigResource<C, T>(context, TRUSTED, TRUSTED)
|
|
17
|
+
appendConfigResource<C, T>(context, PLUGINS, PLUGIN_RECORD)
|
|
18
|
+
context.registerService(makeBasicEd25519Guard(TRUSTED))
|
|
19
|
+
context.registerMiddleware(authMiddleware)
|
|
20
|
+
|
|
21
|
+
return context
|
|
22
|
+
}
|
package/src/index.ts
ADDED
package/src/types.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ServiceRoute } from '@owlmeans/server-route'
|
|
2
|
+
import type { ConfigResourceAppend } from '@owlmeans/config'
|
|
3
|
+
import type { BasicServerConfig } from '@owlmeans/server-config'
|
|
4
|
+
import type { BasicClientConfig } from '@owlmeans/client-config'
|
|
5
|
+
import type { BasicContext } from '@owlmeans/context'
|
|
6
|
+
|
|
7
|
+
export interface ServerConfig extends BasicServerConfig, BasicClientConfig {
|
|
8
|
+
services: Record<string, ServiceRoute>
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface ServerContext<C extends ServerConfig> extends BasicContext<C>, ConfigResourceAppend {
|
|
12
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
|
|
2
|
+
import { MiddlewareStage, MiddlewareType } from '@owlmeans/context'
|
|
3
|
+
import type { Middleware } from '@owlmeans/context'
|
|
4
|
+
import { readConfigValue } from '@owlmeans/server-config'
|
|
5
|
+
|
|
6
|
+
export const fileConfigReader: Middleware = {
|
|
7
|
+
type: MiddlewareType.Config,
|
|
8
|
+
stage: MiddlewareStage.Configuration,
|
|
9
|
+
apply: async (context) => {
|
|
10
|
+
const tree: Tree = context.cfg as unknown as Tree
|
|
11
|
+
visitConfigLeafs(tree)
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// @TODO Move to server config
|
|
16
|
+
const visitConfigLeafs = (tree: Tree) =>
|
|
17
|
+
tree != null ? Object.entries(tree).forEach(([key, value]) => {
|
|
18
|
+
if (typeof value === 'string') {
|
|
19
|
+
const descriptor = Object.getOwnPropertyDescriptor(tree, key)
|
|
20
|
+
if (descriptor?.writable) {
|
|
21
|
+
tree[key] = readConfigValue(value)
|
|
22
|
+
}
|
|
23
|
+
} else if (Array.isArray(value)) {
|
|
24
|
+
value.forEach(tree => { visitConfigLeafs(tree as Tree) })
|
|
25
|
+
} else if (typeof value === 'object') {
|
|
26
|
+
visitConfigLeafs(value as Tree)
|
|
27
|
+
}
|
|
28
|
+
}) : tree
|
|
29
|
+
|
|
30
|
+
type TreeKey = string | number | symbol
|
|
31
|
+
type TreeValue = unknown | Array<unknown> | string
|
|
32
|
+
interface Tree extends Record<TreeKey, TreeValue | Tree> { }
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": [
|
|
3
|
+
"../tsconfig.default.json",
|
|
4
|
+
],
|
|
5
|
+
"compilerOptions": {
|
|
6
|
+
"rootDir": "./src/", /* Specify the root folder within your source files. */
|
|
7
|
+
"outDir": "./build/", /* Specify an output folder for all emitted files. */
|
|
8
|
+
},
|
|
9
|
+
"exclude": [
|
|
10
|
+
"./dist/**/*",
|
|
11
|
+
"./build/**/*",
|
|
12
|
+
"./*.ts"
|
|
13
|
+
]
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"root":["./src/config.ts","./src/consts.ts","./src/context.ts","./src/index.ts","./src/types.ts","./src/utils/context.ts","./src/utils/index.ts"],"version":"5.6.3"}
|