@owlmeans/api-config 0.1.2 → 0.1.4
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/README.md +19 -515
- package/build/modules.d.ts +1 -1
- package/build/modules.d.ts.map +1 -1
- package/build/modules.js +2 -2
- package/build/modules.js.map +1 -1
- package/package.json +7 -5
- package/src/modules.ts +2 -2
- package/tsconfig.json +5 -9
package/README.md
CHANGED
|
@@ -1,540 +1,44 @@
|
|
|
1
1
|
# @owlmeans/api-config
|
|
2
2
|
|
|
3
|
-
Shared
|
|
3
|
+
Shared module for advertising safe config values from server to client via a REST endpoint.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
- **Type Safety**: TypeScript interfaces for API-safe configuration
|
|
12
|
-
- **Selective Exposure**: Granular control over what configuration is exposed
|
|
13
|
-
- **Module Integration**: Ready-to-use modules for configuration endpoints
|
|
14
|
-
- **Cross-Environment Support**: Works with both server-side and client-side implementations
|
|
15
|
-
|
|
16
|
-
This package is part of the OwlMeans configuration ecosystem:
|
|
17
|
-
- **@owlmeans/config**: Core configuration management
|
|
18
|
-
- **@owlmeans/api-config**: Shared API configuration *(this package)*
|
|
19
|
-
- **@owlmeans/api-config-server**: Server-side API configuration
|
|
20
|
-
- **@owlmeans/api-config-client**: Client-side API configuration consumption
|
|
7
|
+
- Exposes a `GET /assets/config.json` module that returns non-sensitive config fields
|
|
8
|
+
- `ApiConfig` — the advertised config type (subset of `CommonConfig`)
|
|
9
|
+
- `API_CONFIG` — module alias for the config endpoint
|
|
10
|
+
- `notAdvertizedConfigKeys` / `allowedConfigRecords` — lists controlling what is/isn't exposed
|
|
21
11
|
|
|
22
12
|
## Installation
|
|
23
13
|
|
|
24
14
|
```bash
|
|
25
|
-
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## Dependencies
|
|
29
|
-
|
|
30
|
-
This package extends:
|
|
31
|
-
- `@owlmeans/config`: Core configuration system
|
|
32
|
-
- `@owlmeans/module`: Module system for API endpoints
|
|
33
|
-
- `@owlmeans/route`: Routing infrastructure
|
|
34
|
-
|
|
35
|
-
## Core Concepts
|
|
36
|
-
|
|
37
|
-
### API-Safe Configuration
|
|
38
|
-
|
|
39
|
-
API configuration removes sensitive server-side details like database connections, trusted entities, and internal service configurations while preserving client-relevant settings.
|
|
40
|
-
|
|
41
|
-
### Configuration Filtering
|
|
42
|
-
|
|
43
|
-
The package automatically filters out sensitive configuration keys and only exposes safe configuration data through the API.
|
|
44
|
-
|
|
45
|
-
### Standardized Endpoint
|
|
46
|
-
|
|
47
|
-
The `/assets/config.json` endpoint provides a standard location for clients to retrieve configuration data.
|
|
48
|
-
|
|
49
|
-
## API Reference
|
|
50
|
-
|
|
51
|
-
### Types
|
|
52
|
-
|
|
53
|
-
#### `ApiConfig`
|
|
54
|
-
|
|
55
|
-
Interface for API-safe configuration that extends CommonConfig while omitting sensitive fields.
|
|
56
|
-
|
|
57
|
-
```typescript
|
|
58
|
-
interface ApiConfig extends Omit<
|
|
59
|
-
CommonConfig,
|
|
60
|
-
'dbs' | 'trusted' | 'ready' | 'service' | 'layer' | 'type' | 'layerId'
|
|
61
|
-
> {}
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
**Excluded Fields:**
|
|
65
|
-
- `dbs`: Database configurations (sensitive)
|
|
66
|
-
- `trusted`: Trusted entity configurations (sensitive)
|
|
67
|
-
- `ready`: Internal readiness state (internal)
|
|
68
|
-
- `service`: Service name (internal)
|
|
69
|
-
- `layer`: Service layer (internal)
|
|
70
|
-
- `type`: Application type (internal)
|
|
71
|
-
- `layerId`: Layer identifier (internal)
|
|
72
|
-
|
|
73
|
-
**Included Fields:**
|
|
74
|
-
- `debug`: Debug configuration settings
|
|
75
|
-
- `security`: Public security settings
|
|
76
|
-
- `brand`: Branding configuration
|
|
77
|
-
- `defaultEntityId`: Default entity identifier
|
|
78
|
-
- `plugins`: Public plugin configurations
|
|
79
|
-
- Configuration records marked as safe
|
|
80
|
-
|
|
81
|
-
### Constants
|
|
82
|
-
|
|
83
|
-
#### Configuration Filtering
|
|
84
|
-
|
|
85
|
-
```typescript
|
|
86
|
-
const API_CONFIG = 'api-config:advertise' // Module alias for config endpoint
|
|
87
|
-
|
|
88
|
-
const notAdvertizedConfigKeys = [
|
|
89
|
-
'dbs', // Database configurations
|
|
90
|
-
'trusted', // Trusted entities
|
|
91
|
-
'ready', // Readiness state
|
|
92
|
-
'service', // Service name
|
|
93
|
-
'layer', // Service layer
|
|
94
|
-
'type', // Application type
|
|
95
|
-
'layerId', // Layer ID
|
|
96
|
-
'records', // Internal records
|
|
97
|
-
'webService', // Web service configs
|
|
98
|
-
'oidc', // OIDC configurations
|
|
99
|
-
'storageBuckets' // Storage bucket configs
|
|
100
|
-
]
|
|
101
|
-
|
|
102
|
-
const allowedConfigRecords = [
|
|
103
|
-
'plan', // Subscription/plan information
|
|
104
|
-
'product', // Product configuration
|
|
105
|
-
'l10n' // Localization settings
|
|
106
|
-
]
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
### Modules
|
|
110
|
-
|
|
111
|
-
#### Configuration Endpoint Module
|
|
112
|
-
|
|
113
|
-
The package provides a ready-to-use module for serving configuration through the standard endpoint.
|
|
114
|
-
|
|
115
|
-
```typescript
|
|
116
|
-
import { modules } from '@owlmeans/api-config'
|
|
117
|
-
|
|
118
|
-
// The modules array contains:
|
|
119
|
-
// - API config endpoint at /assets/config.json (sticky: true)
|
|
120
|
-
|
|
121
|
-
export const modules = [
|
|
122
|
-
module(route(API_CONFIG, '/assets/config.json'), { sticky: true })
|
|
123
|
-
]
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
**Module Properties:**
|
|
127
|
-
- **Route**: `/assets/config.json` - Standard configuration endpoint
|
|
128
|
-
- **Sticky**: `true` - Applied to all requests regardless of other routing
|
|
129
|
-
- **Method**: `GET` (default) - Standard HTTP GET endpoint
|
|
130
|
-
|
|
131
|
-
## Usage Examples
|
|
132
|
-
|
|
133
|
-
### Basic Module Registration
|
|
134
|
-
|
|
135
|
-
```typescript
|
|
136
|
-
import { modules } from '@owlmeans/api-config'
|
|
137
|
-
import { makeServerContext } from '@owlmeans/server-context'
|
|
138
|
-
|
|
139
|
-
// Create server context
|
|
140
|
-
const context = makeServerContext(config)
|
|
141
|
-
|
|
142
|
-
// Register API config modules
|
|
143
|
-
context.registerModules(modules)
|
|
144
|
-
|
|
145
|
-
// Initialize context
|
|
146
|
-
await context.configure().init()
|
|
147
|
-
|
|
148
|
-
// The /assets/config.json endpoint is now available
|
|
15
|
+
bun add @owlmeans/api-config
|
|
149
16
|
```
|
|
150
17
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
```typescript
|
|
154
|
-
import { ApiConfig, notAdvertizedConfigKeys, allowedConfigRecords } from '@owlmeans/api-config'
|
|
155
|
-
import { CommonConfig } from '@owlmeans/config'
|
|
156
|
-
|
|
157
|
-
// Function to create API-safe configuration
|
|
158
|
-
function createApiConfig(fullConfig: CommonConfig): ApiConfig {
|
|
159
|
-
const apiConfig: Partial<ApiConfig> = {}
|
|
160
|
-
|
|
161
|
-
// Copy all non-sensitive configuration
|
|
162
|
-
Object.entries(fullConfig).forEach(([key, value]) => {
|
|
163
|
-
if (!notAdvertizedConfigKeys.includes(key)) {
|
|
164
|
-
(apiConfig as any)[key] = value
|
|
165
|
-
}
|
|
166
|
-
})
|
|
167
|
-
|
|
168
|
-
// Filter configuration records to only allowed types
|
|
169
|
-
if (fullConfig.records) {
|
|
170
|
-
const safeRecords = Object.entries(fullConfig.records)
|
|
171
|
-
.filter(([recordType]) => allowedConfigRecords.includes(recordType))
|
|
172
|
-
.reduce((acc, [recordType, records]) => ({
|
|
173
|
-
...acc,
|
|
174
|
-
[recordType]: records
|
|
175
|
-
}), {})
|
|
176
|
-
|
|
177
|
-
if (Object.keys(safeRecords).length > 0) {
|
|
178
|
-
apiConfig.records = safeRecords
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
return apiConfig as ApiConfig
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// Usage
|
|
186
|
-
const fullConfig = makeConfig(AppType.Backend, 'my-service', {
|
|
187
|
-
// Full server configuration with sensitive data
|
|
188
|
-
dbs: [{ /* database config */ }],
|
|
189
|
-
trusted: [{ /* trusted entities */ }],
|
|
190
|
-
brand: { home: '/dashboard' },
|
|
191
|
-
debug: { enabled: true }
|
|
192
|
-
})
|
|
18
|
+
## Usage
|
|
193
19
|
|
|
194
|
-
|
|
195
|
-
// apiConfig only contains safe configuration for API exposure
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
### Server-Side Implementation
|
|
20
|
+
Use with server and client counterparts — this package provides the shared types and module alias:
|
|
199
21
|
|
|
200
22
|
```typescript
|
|
201
|
-
import {
|
|
202
|
-
import {
|
|
203
|
-
|
|
204
|
-
// Create custom handler for configuration endpoint
|
|
205
|
-
const configHandler = handleRequest(async (req, ctx) => {
|
|
206
|
-
const fullConfig = ctx.cfg
|
|
207
|
-
|
|
208
|
-
// Create API-safe configuration
|
|
209
|
-
const apiConfig: ApiConfig = {
|
|
210
|
-
debug: fullConfig.debug,
|
|
211
|
-
security: fullConfig.security ? {
|
|
212
|
-
// Only expose public security settings
|
|
213
|
-
auth: fullConfig.security.auth
|
|
214
|
-
} : undefined,
|
|
215
|
-
brand: fullConfig.brand,
|
|
216
|
-
defaultEntityId: fullConfig.defaultEntityId,
|
|
217
|
-
plugins: fullConfig.plugins?.filter(plugin => !plugin.internal)
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// Add allowed configuration records
|
|
221
|
-
if (fullConfig.records) {
|
|
222
|
-
const allowedRecords = ['plan', 'product', 'l10n']
|
|
223
|
-
apiConfig.records = Object.entries(fullConfig.records)
|
|
224
|
-
.filter(([type]) => allowedRecords.includes(type))
|
|
225
|
-
.reduce((acc, [type, records]) => ({ ...acc, [type]: records }), {})
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
return apiConfig
|
|
229
|
-
})
|
|
230
|
-
|
|
231
|
-
// Register module with custom handler
|
|
232
|
-
const configModule = module(
|
|
233
|
-
route('api-config', '/assets/config.json'),
|
|
234
|
-
{ handle: configHandler, sticky: true }
|
|
235
|
-
)
|
|
236
|
-
|
|
237
|
-
context.registerModule(configModule)
|
|
23
|
+
import { API_CONFIG } from '@owlmeans/api-config'
|
|
24
|
+
import type { ApiConfig } from '@owlmeans/api-config'
|
|
238
25
|
```
|
|
239
26
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
```typescript
|
|
243
|
-
// Example of how clients would consume the API config
|
|
244
|
-
// (Implementation would be in @owlmeans/api-config-client)
|
|
27
|
+
## API
|
|
245
28
|
|
|
246
|
-
|
|
247
|
-
loadConfig(): Promise<ApiConfig>
|
|
248
|
-
getDebugSettings(): boolean
|
|
249
|
-
getBrandSettings(): BrandSettings
|
|
250
|
-
getSecuritySettings(): SecurityConfig
|
|
251
|
-
}
|
|
29
|
+
### `ApiConfig`
|
|
252
30
|
|
|
253
|
-
|
|
254
|
-
private config?: ApiConfig
|
|
31
|
+
Subset of `CommonConfig` safe to expose to clients (no db credentials, secrets, etc.).
|
|
255
32
|
|
|
256
|
-
|
|
257
|
-
const response = await fetch('/assets/config.json')
|
|
258
|
-
this.config = await response.json()
|
|
259
|
-
return this.config
|
|
260
|
-
}
|
|
33
|
+
### `API_CONFIG`
|
|
261
34
|
|
|
262
|
-
|
|
263
|
-
return this.config?.debug?.enabled ?? false
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
getBrandSettings(): BrandSettings {
|
|
267
|
-
return this.config?.brand ?? {}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
getSecuritySettings(): SecurityConfig {
|
|
271
|
-
return this.config?.security ?? {}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
### Multi-Environment Configuration
|
|
277
|
-
|
|
278
|
-
```typescript
|
|
279
|
-
import { ApiConfig } from '@owlmeans/api-config'
|
|
280
|
-
|
|
281
|
-
// Different API configurations for different environments
|
|
282
|
-
const createEnvironmentApiConfig = (
|
|
283
|
-
env: 'development' | 'staging' | 'production',
|
|
284
|
-
baseConfig: CommonConfig
|
|
285
|
-
): ApiConfig => {
|
|
286
|
-
const apiConfig: ApiConfig = {
|
|
287
|
-
debug: env === 'development' ? { enabled: true, all: true } : { enabled: false },
|
|
288
|
-
security: {
|
|
289
|
-
auth: baseConfig.security?.auth
|
|
290
|
-
},
|
|
291
|
-
brand: baseConfig.brand
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// Add environment-specific settings
|
|
295
|
-
if (env === 'development') {
|
|
296
|
-
apiConfig.debug = { ...apiConfig.debug, i18n: true }
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
return apiConfig
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
// Usage in different environments
|
|
303
|
-
const devApiConfig = createEnvironmentApiConfig('development', serverConfig)
|
|
304
|
-
const prodApiConfig = createEnvironmentApiConfig('production', serverConfig)
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
### Configuration Record Filtering
|
|
308
|
-
|
|
309
|
-
```typescript
|
|
310
|
-
import { allowedConfigRecords } from '@owlmeans/api-config'
|
|
311
|
-
|
|
312
|
-
// Example configuration with various record types
|
|
313
|
-
const serverConfig = {
|
|
314
|
-
records: {
|
|
315
|
-
// Allowed records (will be exposed)
|
|
316
|
-
plan: [
|
|
317
|
-
{ id: 'basic', name: 'Basic Plan', features: ['feature1'] },
|
|
318
|
-
{ id: 'premium', name: 'Premium Plan', features: ['feature1', 'feature2'] }
|
|
319
|
-
],
|
|
320
|
-
product: [
|
|
321
|
-
{ id: 'main', name: 'Main Product', version: '1.0.0' }
|
|
322
|
-
],
|
|
323
|
-
l10n: [
|
|
324
|
-
{ locale: 'en', name: 'English' },
|
|
325
|
-
{ locale: 'es', name: 'Spanish' }
|
|
326
|
-
],
|
|
327
|
-
|
|
328
|
-
// Not allowed records (will be filtered out)
|
|
329
|
-
internal: [
|
|
330
|
-
{ secret: 'sensitive-data' }
|
|
331
|
-
],
|
|
332
|
-
database: [
|
|
333
|
-
{ connection: 'mongodb://secret' }
|
|
334
|
-
]
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
// Function to filter records
|
|
339
|
-
const filterConfigRecords = (records: any) => {
|
|
340
|
-
return Object.entries(records)
|
|
341
|
-
.filter(([recordType]) => allowedConfigRecords.includes(recordType))
|
|
342
|
-
.reduce((acc, [type, data]) => ({ ...acc, [type]: data }), {})
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
const safeRecords = filterConfigRecords(serverConfig.records)
|
|
346
|
-
// Only contains: plan, product, l10n records
|
|
347
|
-
```
|
|
348
|
-
|
|
349
|
-
### Plugin Configuration Exposure
|
|
350
|
-
|
|
351
|
-
```typescript
|
|
352
|
-
import { ApiConfig } from '@owlmeans/api-config'
|
|
353
|
-
|
|
354
|
-
// Example of exposing safe plugin configurations
|
|
355
|
-
const createApiConfigWithPlugins = (serverConfig: CommonConfig): ApiConfig => {
|
|
356
|
-
return {
|
|
357
|
-
debug: serverConfig.debug,
|
|
358
|
-
brand: serverConfig.brand,
|
|
359
|
-
|
|
360
|
-
// Filter plugins to only expose public ones
|
|
361
|
-
plugins: serverConfig.plugins?.filter(plugin => {
|
|
362
|
-
// Only expose plugins explicitly marked as public
|
|
363
|
-
return plugin.public === true && !plugin.internal
|
|
364
|
-
}).map(plugin => ({
|
|
365
|
-
// Remove sensitive plugin data
|
|
366
|
-
id: plugin.id,
|
|
367
|
-
type: plugin.type,
|
|
368
|
-
value: plugin.publicValue || plugin.value,
|
|
369
|
-
config: plugin.publicConfig
|
|
370
|
-
}))
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
```
|
|
374
|
-
|
|
375
|
-
### Security Considerations
|
|
376
|
-
|
|
377
|
-
```typescript
|
|
378
|
-
import { ApiConfig, notAdvertizedConfigKeys } from '@owlmeans/api-config'
|
|
379
|
-
|
|
380
|
-
// Ensure sensitive data is never exposed
|
|
381
|
-
const secureApiConfigFilter = (config: any): ApiConfig => {
|
|
382
|
-
// Double-check sensitive keys are removed
|
|
383
|
-
const filtered = { ...config }
|
|
384
|
-
|
|
385
|
-
notAdvertizedConfigKeys.forEach(key => {
|
|
386
|
-
delete filtered[key]
|
|
387
|
-
})
|
|
388
|
-
|
|
389
|
-
// Additional security checks
|
|
390
|
-
if (filtered.security) {
|
|
391
|
-
// Remove sensitive security settings
|
|
392
|
-
delete filtered.security.keys
|
|
393
|
-
delete filtered.security.secrets
|
|
394
|
-
delete filtered.security.internalAuth
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
// Remove any remaining sensitive patterns
|
|
398
|
-
const sanitized = JSON.parse(JSON.stringify(filtered, (key, value) => {
|
|
399
|
-
// Filter out any keys containing sensitive terms
|
|
400
|
-
if (key.toLowerCase().includes('secret') ||
|
|
401
|
-
key.toLowerCase().includes('password') ||
|
|
402
|
-
key.toLowerCase().includes('token') ||
|
|
403
|
-
key.toLowerCase().includes('key')) {
|
|
404
|
-
return undefined
|
|
405
|
-
}
|
|
406
|
-
return value
|
|
407
|
-
}))
|
|
408
|
-
|
|
409
|
-
return sanitized
|
|
410
|
-
}
|
|
411
|
-
```
|
|
412
|
-
|
|
413
|
-
## Integration Patterns
|
|
414
|
-
|
|
415
|
-
### With Server API
|
|
416
|
-
|
|
417
|
-
```typescript
|
|
418
|
-
import { modules } from '@owlmeans/api-config'
|
|
419
|
-
import { createApiServer } from '@owlmeans/server-api'
|
|
420
|
-
|
|
421
|
-
const apiServer = createApiServer('main')
|
|
422
|
-
const context = makeServerContext(config)
|
|
423
|
-
|
|
424
|
-
// Register API server and config modules
|
|
425
|
-
context.registerService(apiServer)
|
|
426
|
-
context.registerModules(modules)
|
|
427
|
-
|
|
428
|
-
await context.configure().init()
|
|
429
|
-
await apiServer.listen()
|
|
430
|
-
|
|
431
|
-
// Config available at: GET /assets/config.json
|
|
432
|
-
```
|
|
433
|
-
|
|
434
|
-
### With Authentication
|
|
435
|
-
|
|
436
|
-
```typescript
|
|
437
|
-
import { module, guard } from '@owlmeans/module'
|
|
438
|
-
import { route } from '@owlmeans/route'
|
|
439
|
-
|
|
440
|
-
// Protected configuration endpoint
|
|
441
|
-
const protectedConfigModule = module(
|
|
442
|
-
route('protected-config', '/admin/config.json'),
|
|
443
|
-
{
|
|
444
|
-
...guard('admin'),
|
|
445
|
-
handle: handleRequest(async (req, ctx) => {
|
|
446
|
-
// Return full configuration for admin users
|
|
447
|
-
return createFullApiConfig(ctx.cfg)
|
|
448
|
-
})
|
|
449
|
-
}
|
|
450
|
-
)
|
|
451
|
-
|
|
452
|
-
// Public configuration endpoint (using standard module)
|
|
453
|
-
const publicConfigModule = modules[0] // Standard config module
|
|
454
|
-
```
|
|
455
|
-
|
|
456
|
-
### With Caching
|
|
457
|
-
|
|
458
|
-
```typescript
|
|
459
|
-
import { module } from '@owlmeans/module'
|
|
460
|
-
import { handleRequest } from '@owlmeans/server-api'
|
|
461
|
-
|
|
462
|
-
// Cached configuration endpoint
|
|
463
|
-
const cachedConfigModule = module(
|
|
464
|
-
route('cached-config', '/assets/config.json'),
|
|
465
|
-
{
|
|
466
|
-
sticky: true,
|
|
467
|
-
handle: handleRequest(async (req, ctx) => {
|
|
468
|
-
// Check cache first
|
|
469
|
-
const cacheKey = 'api-config'
|
|
470
|
-
const cached = await ctx.service('cache').get(cacheKey)
|
|
471
|
-
|
|
472
|
-
if (cached) {
|
|
473
|
-
return cached
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
// Generate fresh config
|
|
477
|
-
const apiConfig = createApiConfig(ctx.cfg)
|
|
478
|
-
|
|
479
|
-
// Cache for 5 minutes
|
|
480
|
-
await ctx.service('cache').set(cacheKey, apiConfig, 300)
|
|
481
|
-
|
|
482
|
-
return apiConfig
|
|
483
|
-
})
|
|
484
|
-
}
|
|
485
|
-
)
|
|
486
|
-
```
|
|
487
|
-
|
|
488
|
-
## Best Practices
|
|
489
|
-
|
|
490
|
-
1. **Security First**: Always verify sensitive data is filtered out
|
|
491
|
-
2. **Environment Awareness**: Adapt configuration exposure based on environment
|
|
492
|
-
3. **Minimal Exposure**: Only expose configuration data that clients actually need
|
|
493
|
-
4. **Validation**: Validate API configuration before exposure
|
|
494
|
-
5. **Caching**: Consider caching configuration for performance
|
|
495
|
-
6. **Versioning**: Consider versioning configuration APIs for compatibility
|
|
496
|
-
7. **Documentation**: Document what configuration is available to clients
|
|
497
|
-
|
|
498
|
-
## Error Handling
|
|
499
|
-
|
|
500
|
-
```typescript
|
|
501
|
-
import { handleRequest } from '@owlmeans/server-api'
|
|
502
|
-
|
|
503
|
-
const configHandler = handleRequest(async (req, ctx) => {
|
|
504
|
-
try {
|
|
505
|
-
const apiConfig = createApiConfig(ctx.cfg)
|
|
506
|
-
|
|
507
|
-
// Validate the configuration before sending
|
|
508
|
-
if (!apiConfig || typeof apiConfig !== 'object') {
|
|
509
|
-
throw new Error('Invalid configuration generated')
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
return apiConfig
|
|
513
|
-
} catch (error) {
|
|
514
|
-
// Log error but don't expose details
|
|
515
|
-
console.error('Config generation error:', error)
|
|
516
|
-
|
|
517
|
-
// Return minimal safe config
|
|
518
|
-
return {
|
|
519
|
-
debug: { enabled: false },
|
|
520
|
-
brand: {},
|
|
521
|
-
error: 'Configuration temporarily unavailable'
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
})
|
|
525
|
-
```
|
|
35
|
+
Module alias `'api-config:advertise'` used to register/call the config endpoint.
|
|
526
36
|
|
|
527
|
-
|
|
37
|
+
### `modules`
|
|
528
38
|
|
|
529
|
-
|
|
530
|
-
- **Size**: Keep API configuration minimal to reduce transfer size
|
|
531
|
-
- **Compression**: Use gzip compression for the JSON endpoint
|
|
532
|
-
- **CDN**: Consider CDN caching for static configuration
|
|
39
|
+
Array of route definitions for the config advertisement endpoint.
|
|
533
40
|
|
|
534
41
|
## Related Packages
|
|
535
42
|
|
|
536
|
-
- [`@owlmeans/config`](../config) -
|
|
537
|
-
- [`@owlmeans/api-config-
|
|
538
|
-
- [`@owlmeans/api-config-client`](../api-config-client) - Client-side consumption
|
|
539
|
-
- [`@owlmeans/module`](../module) - Module system for endpoints
|
|
540
|
-
- [`@owlmeans/route`](../route) - Routing infrastructure
|
|
43
|
+
- [`@owlmeans/api-config-server`](../api-config-server) — server-side module that serves the config
|
|
44
|
+
- [`@owlmeans/api-config-client`](../api-config-client) — client middleware that fetches and merges config
|
package/build/modules.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const modules: import("@owlmeans/
|
|
1
|
+
export declare const modules: import("@owlmeans/entrypoint").CommonEntrypoint[];
|
|
2
2
|
//# sourceMappingURL=modules.d.ts.map
|
package/build/modules.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modules.d.ts","sourceRoot":"","sources":["../src/modules.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,OAAO,
|
|
1
|
+
{"version":3,"file":"modules.d.ts","sourceRoot":"","sources":["../src/modules.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,OAAO,mDAEnB,CAAA"}
|
package/build/modules.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { entrypoint } from '@owlmeans/entrypoint';
|
|
2
2
|
import { route } from '@owlmeans/route';
|
|
3
3
|
import { API_CONFIG } from './consts.js';
|
|
4
4
|
export const modules = [
|
|
5
|
-
|
|
5
|
+
entrypoint(route(API_CONFIG, '/assets/config.json'), { sticky: true }),
|
|
6
6
|
];
|
|
7
7
|
//# sourceMappingURL=modules.js.map
|
package/build/modules.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modules.js","sourceRoot":"","sources":["../src/modules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"modules.js","sourceRoot":"","sources":["../src/modules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAExC,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,UAAU,CAAC,KAAK,CAAC,UAAU,EAAE,qBAAqB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;CACvE,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owlmeans/api-config",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"license": "MIT",
|
|
4
5
|
"type": "module",
|
|
5
6
|
"scripts": {
|
|
6
7
|
"build": "tsc -b",
|
|
@@ -20,13 +21,14 @@
|
|
|
20
21
|
}
|
|
21
22
|
},
|
|
22
23
|
"dependencies": {
|
|
23
|
-
"@owlmeans/config": "^0.1.
|
|
24
|
-
"@owlmeans/
|
|
25
|
-
"@owlmeans/route": "^0.1.
|
|
24
|
+
"@owlmeans/config": "^0.1.4",
|
|
25
|
+
"@owlmeans/entrypoint": "^0.1.4",
|
|
26
|
+
"@owlmeans/route": "^0.1.4"
|
|
26
27
|
},
|
|
27
28
|
"devDependencies": {
|
|
29
|
+
"@owlmeans/dep-config": "workspace:*",
|
|
28
30
|
"nodemon": "^3.1.11",
|
|
29
|
-
"typescript": "^
|
|
31
|
+
"typescript": "^6.0.2"
|
|
30
32
|
},
|
|
31
33
|
"publishConfig": {
|
|
32
34
|
"access": "public"
|
package/src/modules.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { entrypoint } from '@owlmeans/entrypoint'
|
|
2
2
|
import { route } from '@owlmeans/route'
|
|
3
3
|
import { API_CONFIG } from './consts.js'
|
|
4
4
|
|
|
5
5
|
export const modules = [
|
|
6
|
-
|
|
6
|
+
entrypoint(route(API_CONFIG, '/assets/config.json'), { sticky: true }),
|
|
7
7
|
]
|
package/tsconfig.json
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"extends": [
|
|
3
|
-
"
|
|
3
|
+
"@owlmeans/dep-config/tsconfig.base.json"
|
|
4
4
|
],
|
|
5
5
|
"compilerOptions": {
|
|
6
|
-
"rootDir": "./src/",
|
|
7
|
-
"outDir": "./build/"
|
|
6
|
+
"rootDir": "./src/",
|
|
7
|
+
"outDir": "./build/"
|
|
8
8
|
},
|
|
9
|
-
"exclude": [
|
|
10
|
-
|
|
11
|
-
"./build/**/*",
|
|
12
|
-
"./*.ts"
|
|
13
|
-
]
|
|
14
|
-
}
|
|
9
|
+
"exclude": ["./dist/**/*", "./build/**/*", "./*.ts"]
|
|
10
|
+
}
|