@onlineapps/service-wrapper 2.0.6 → 2.0.8
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 +11 -0
- package/docs/API_STRUCTURE_STANDARD.md +132 -0
- package/docs/CONFIGURATION_GUIDE.md +261 -0
- package/docs/OPERATIONS_SCHEMA.md +363 -0
- package/docs/SERVICE_TESTING_STANDARD.md +389 -0
- package/package.json +9 -7
- package/src/ServiceWrapper.js +39 -6
- package/test/e2e/full-flow.test.js +293 -0
- package/test/monitoring-integration.test.js +150 -0
package/README.md
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
# @onlineapps/service-wrapper
|
|
2
2
|
|
|
3
|
+
**Main orchestration package for microservices - NO prefix as it's the primary integration point**
|
|
4
|
+
|
|
3
5
|
Infrastructure wrapper that handles all workflow processing, message queue operations, and service registration for microservices.
|
|
4
6
|
|
|
7
|
+
## Naming Convention
|
|
8
|
+
|
|
9
|
+
This package uses `@onlineapps/service-wrapper` WITHOUT any connector prefix because:
|
|
10
|
+
- It's the main orchestration layer, not a specific connector
|
|
11
|
+
- All services depend on it directly
|
|
12
|
+
- It aggregates all other connectors (base, infra, orch)
|
|
13
|
+
|
|
14
|
+
Directory: `/shared/connector/conn-app-service-wrapper/` (historical, kept for backward compatibility)
|
|
15
|
+
|
|
5
16
|
## Purpose
|
|
6
17
|
|
|
7
18
|
This package provides the infrastructure layer that sits between:
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# API Structure Standard for Microservices
|
|
2
|
+
|
|
3
|
+
## Endpoint Structure
|
|
4
|
+
|
|
5
|
+
All microservices follow a simple, unversioned API structure.
|
|
6
|
+
|
|
7
|
+
### URL Pattern
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
/ # Service discovery
|
|
11
|
+
/health # Health check
|
|
12
|
+
/status # Service status
|
|
13
|
+
/metrics # Prometheus metrics
|
|
14
|
+
/specification # Operations specification
|
|
15
|
+
/api/{operation} # Business operations
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Endpoint Categories
|
|
19
|
+
|
|
20
|
+
- **System endpoints**: Health, status, metrics, specification
|
|
21
|
+
- **Business endpoints** (`/api/*`): Application-specific operations
|
|
22
|
+
|
|
23
|
+
## Standard Endpoints
|
|
24
|
+
|
|
25
|
+
### Discovery Endpoint
|
|
26
|
+
|
|
27
|
+
**GET /**
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"service": "service-name",
|
|
31
|
+
"version": "1.0.0",
|
|
32
|
+
"description": "Service description",
|
|
33
|
+
"specification": "/specification",
|
|
34
|
+
"health": "/health",
|
|
35
|
+
"status": "/status"
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### System Endpoints
|
|
40
|
+
|
|
41
|
+
| Endpoint | Purpose | Response |
|
|
42
|
+
|----------|---------|----------|
|
|
43
|
+
| `GET /health` | Basic health check | `{"status": "healthy", "timestamp": "..."}` |
|
|
44
|
+
| `GET /status` | Detailed service status | Service metrics and dependencies |
|
|
45
|
+
| `GET /specification` | Operations specification | Operations JSON schema |
|
|
46
|
+
| `GET /metrics` | Prometheus metrics | Metrics in Prometheus format |
|
|
47
|
+
|
|
48
|
+
### Business Endpoints
|
|
49
|
+
|
|
50
|
+
Service-specific operations under `/api/*`:
|
|
51
|
+
- `POST /api/create-user`
|
|
52
|
+
- `POST /api/process-order`
|
|
53
|
+
- `GET /api/get-product`
|
|
54
|
+
|
|
55
|
+
## Implementation Guide
|
|
56
|
+
|
|
57
|
+
### Express.js Structure
|
|
58
|
+
|
|
59
|
+
```javascript
|
|
60
|
+
const express = require('express');
|
|
61
|
+
const app = express();
|
|
62
|
+
|
|
63
|
+
// Root endpoint - service discovery
|
|
64
|
+
app.get('/', (req, res) => {
|
|
65
|
+
res.json({
|
|
66
|
+
service: process.env.SERVICE_NAME,
|
|
67
|
+
version: require('./package.json').version,
|
|
68
|
+
specification: '/specification',
|
|
69
|
+
health: '/health',
|
|
70
|
+
status: '/status'
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// System endpoints
|
|
75
|
+
app.get('/health', healthHandler);
|
|
76
|
+
app.get('/status', statusHandler);
|
|
77
|
+
app.get('/specification', specificationHandler);
|
|
78
|
+
app.get('/metrics', metricsHandler);
|
|
79
|
+
|
|
80
|
+
// Business endpoints under /api
|
|
81
|
+
app.post('/api/create-user', createUserHandler);
|
|
82
|
+
app.post('/api/process-order', processOrderHandler);
|
|
83
|
+
app.get('/api/get-product', getProductHandler);
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Configuration Structure
|
|
87
|
+
|
|
88
|
+
All service configurations are stored in `conn-config/` directory:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
/your-service
|
|
92
|
+
/conn-config
|
|
93
|
+
/config.json # Main configuration
|
|
94
|
+
/operations.json # Operations specification
|
|
95
|
+
/middleware.json # Middleware configuration
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
See [Configuration Guide](./CONFIGURATION_GUIDE.md) for details.
|
|
99
|
+
|
|
100
|
+
## Migration Guide
|
|
101
|
+
|
|
102
|
+
### From OpenAPI to Operations
|
|
103
|
+
|
|
104
|
+
| Old | New | Purpose |
|
|
105
|
+
|-----|-----|------|
|
|
106
|
+
| `/api/v1/specification` | `/specification` | Operations schema |
|
|
107
|
+
| `/v1/system/health` | `/health` | Health check |
|
|
108
|
+
| `/v1/system/status` | `/status` | Service status |
|
|
109
|
+
| `/v1/{operation}` | `/api/{operation}` | Business operations |
|
|
110
|
+
|
|
111
|
+
### Simple Migration Steps
|
|
112
|
+
|
|
113
|
+
1. Create `operations.json` from OpenAPI
|
|
114
|
+
2. Remove version prefixes from endpoints
|
|
115
|
+
3. Move business endpoints under `/api`
|
|
116
|
+
4. Update service discovery response
|
|
117
|
+
|
|
118
|
+
## Testing Requirements
|
|
119
|
+
|
|
120
|
+
Tests must verify:
|
|
121
|
+
|
|
122
|
+
1. **Discovery endpoint** returns service info and specification link
|
|
123
|
+
2. **System endpoints** work correctly
|
|
124
|
+
3. **Business endpoints** under `/api` process operations
|
|
125
|
+
4. **Operations schema** is valid and complete
|
|
126
|
+
|
|
127
|
+
## Benefits
|
|
128
|
+
|
|
129
|
+
1. **Simplicity** - No version complexity
|
|
130
|
+
2. **Clear structure** - System vs business separation
|
|
131
|
+
3. **Direct mapping** - Operations to Cookbook steps
|
|
132
|
+
4. **Lightweight** - Minimal configuration needed
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# Service Configuration Guide
|
|
2
|
+
|
|
3
|
+
## Configuration Directory Structure
|
|
4
|
+
|
|
5
|
+
Every service must have a `conn-config/` directory with these configuration files:
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
/service-root
|
|
9
|
+
/conn-config
|
|
10
|
+
config.json # Main service configuration
|
|
11
|
+
operations.json # Operations specification
|
|
12
|
+
middleware.json # Middleware stack configuration
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Configuration Files
|
|
16
|
+
|
|
17
|
+
### 1. config.json - Main Configuration
|
|
18
|
+
|
|
19
|
+
Primary service configuration with environment overrides:
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"service": {
|
|
24
|
+
"name": "hello-service",
|
|
25
|
+
"version": "1.0.0",
|
|
26
|
+
"description": "Greeting service",
|
|
27
|
+
"environment": "${NODE_ENV:development}"
|
|
28
|
+
},
|
|
29
|
+
"server": {
|
|
30
|
+
"port": "${PORT:3000}",
|
|
31
|
+
"host": "${HOST:0.0.0.0}",
|
|
32
|
+
"timeout": 30000
|
|
33
|
+
},
|
|
34
|
+
"api": {
|
|
35
|
+
"versions": {
|
|
36
|
+
"available": ["v1"],
|
|
37
|
+
"current": "v1",
|
|
38
|
+
"deprecated": []
|
|
39
|
+
},
|
|
40
|
+
"rateLimit": {
|
|
41
|
+
"enabled": true,
|
|
42
|
+
"windowMs": 60000,
|
|
43
|
+
"max": 100
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"monitoring": {
|
|
47
|
+
"healthCheck": {
|
|
48
|
+
"interval": 30000,
|
|
49
|
+
"timeout": 5000
|
|
50
|
+
},
|
|
51
|
+
"metrics": {
|
|
52
|
+
"enabled": "${METRICS_ENABLED:true}",
|
|
53
|
+
"port": "${METRICS_PORT:9090}"
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"dependencies": {
|
|
57
|
+
"rabbitmq": {
|
|
58
|
+
"url": "${RABBITMQ_URL:amqp://localhost:5672}",
|
|
59
|
+
"enabled": "${MQ_ENABLED:true}"
|
|
60
|
+
},
|
|
61
|
+
"redis": {
|
|
62
|
+
"url": "${REDIS_URL:redis://localhost:6379}",
|
|
63
|
+
"enabled": "${CACHE_ENABLED:false}"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 2. operations.json - Service Operations
|
|
70
|
+
|
|
71
|
+
Defines all operations the service provides:
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"operations": {
|
|
76
|
+
"create-greeting": {
|
|
77
|
+
"description": "Generate a greeting message",
|
|
78
|
+
"handler": "handlers.greetings.create",
|
|
79
|
+
"endpoint": "/api/create-greeting",
|
|
80
|
+
"method": "POST",
|
|
81
|
+
"input": {
|
|
82
|
+
"name": {
|
|
83
|
+
"type": "string",
|
|
84
|
+
"required": true,
|
|
85
|
+
"description": "Name to greet"
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
"output": {
|
|
89
|
+
"message": {
|
|
90
|
+
"type": "string",
|
|
91
|
+
"description": "Generated greeting"
|
|
92
|
+
},
|
|
93
|
+
"timestamp": {
|
|
94
|
+
"type": "datetime"
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 3. middleware.json - Middleware Configuration
|
|
103
|
+
|
|
104
|
+
Middleware stack and configuration:
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"global": [
|
|
109
|
+
{
|
|
110
|
+
"name": "cors",
|
|
111
|
+
"enabled": true,
|
|
112
|
+
"config": {
|
|
113
|
+
"origin": "${CORS_ORIGIN:*}",
|
|
114
|
+
"credentials": true
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"name": "helmet",
|
|
119
|
+
"enabled": true,
|
|
120
|
+
"config": {}
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"name": "requestLogger",
|
|
124
|
+
"enabled": true,
|
|
125
|
+
"config": {
|
|
126
|
+
"level": "info"
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"name": "bodyParser",
|
|
131
|
+
"enabled": true,
|
|
132
|
+
"config": {
|
|
133
|
+
"limit": "10mb"
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
],
|
|
137
|
+
"routes": {
|
|
138
|
+
"authenticate": {
|
|
139
|
+
"handler": "middleware/auth.authenticate",
|
|
140
|
+
"config": {
|
|
141
|
+
"required": true
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
"authorize": {
|
|
145
|
+
"handler": "middleware/auth.authorize",
|
|
146
|
+
"config": {
|
|
147
|
+
"roles": ["admin", "user"]
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
"validate": {
|
|
151
|
+
"handler": "middleware/validation.validate"
|
|
152
|
+
},
|
|
153
|
+
"rateLimit": {
|
|
154
|
+
"handler": "middleware/rateLimit",
|
|
155
|
+
"config": {
|
|
156
|
+
"max": 100,
|
|
157
|
+
"windowMs": 60000
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
"error": [
|
|
162
|
+
{
|
|
163
|
+
"name": "notFound",
|
|
164
|
+
"handler": "middleware/errors.notFound"
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
"name": "errorHandler",
|
|
168
|
+
"handler": "middleware/errors.handler"
|
|
169
|
+
}
|
|
170
|
+
]
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
## Environment Variables
|
|
176
|
+
|
|
177
|
+
Configuration supports environment variable substitution:
|
|
178
|
+
|
|
179
|
+
- Format: `${VARIABLE_NAME:default_value}`
|
|
180
|
+
- Example: `${PORT:3000}` uses PORT env var or defaults to 3000
|
|
181
|
+
|
|
182
|
+
### Standard Environment Variables
|
|
183
|
+
|
|
184
|
+
| Variable | Purpose | Default |
|
|
185
|
+
|----------|---------|---------|
|
|
186
|
+
| `NODE_ENV` | Environment (development/production) | development |
|
|
187
|
+
| `SERVICE_NAME` | Service name | From config.json |
|
|
188
|
+
| `PORT` | Server port | 3000 |
|
|
189
|
+
| `LOG_LEVEL` | Logging level | info |
|
|
190
|
+
| `RABBITMQ_URL` | RabbitMQ connection | amqp://localhost:5672 |
|
|
191
|
+
| `REDIS_URL` | Redis connection | redis://localhost:6379 |
|
|
192
|
+
| `METRICS_ENABLED` | Enable metrics | true |
|
|
193
|
+
|
|
194
|
+
## Loading Configuration
|
|
195
|
+
|
|
196
|
+
Service wrapper automatically loads configuration:
|
|
197
|
+
|
|
198
|
+
```javascript
|
|
199
|
+
const ServiceWrapper = require('@onlineapps/service-wrapper');
|
|
200
|
+
|
|
201
|
+
// Automatically loads from ./conn-config/
|
|
202
|
+
const wrapper = new ServiceWrapper();
|
|
203
|
+
|
|
204
|
+
// Or specify custom path
|
|
205
|
+
const wrapper = new ServiceWrapper({
|
|
206
|
+
configPath: './custom-config/'
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// Access configuration
|
|
210
|
+
const config = wrapper.config;
|
|
211
|
+
console.log(config.service.name);
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Validation
|
|
215
|
+
|
|
216
|
+
Configuration is validated on startup:
|
|
217
|
+
|
|
218
|
+
1. Required files exist
|
|
219
|
+
2. JSON syntax is valid
|
|
220
|
+
3. Required fields are present
|
|
221
|
+
4. Environment variables are resolved
|
|
222
|
+
5. Operations schema is valid
|
|
223
|
+
|
|
224
|
+
## Best Practices
|
|
225
|
+
|
|
226
|
+
1. **Keep sensitive data in environment variables** - Never commit secrets
|
|
227
|
+
2. **Use defaults** - Provide sensible defaults for all configs
|
|
228
|
+
3. **Document all options** - Include descriptions in configs
|
|
229
|
+
4. **Validate early** - Fail fast on invalid configuration
|
|
230
|
+
5. **Version your configs** - Track configuration changes
|
|
231
|
+
|
|
232
|
+
## Service Configuration Example
|
|
233
|
+
|
|
234
|
+
### config.json with Execution Mode
|
|
235
|
+
```json
|
|
236
|
+
{
|
|
237
|
+
"service": {
|
|
238
|
+
"name": "hello-service",
|
|
239
|
+
"version": "1.0.0",
|
|
240
|
+
"execution": {
|
|
241
|
+
"mode": "${EXECUTION_MODE:direct}",
|
|
242
|
+
"direct": {
|
|
243
|
+
"handler": "./src/handlers"
|
|
244
|
+
},
|
|
245
|
+
"http": {
|
|
246
|
+
"baseUrl": "${SERVICE_URL:http://localhost:3000}"
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
"monitoring": {
|
|
251
|
+
"healthCheck": {
|
|
252
|
+
"interval": 30000
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Execution Modes
|
|
259
|
+
|
|
260
|
+
- **direct**: Service Wrapper calls handlers directly (50% memory savings)
|
|
261
|
+
- **http**: Service Wrapper makes HTTP calls (for external services)
|