@onlineapps/service-wrapper 2.0.11 → 2.0.13
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 +31 -5
- package/package.json +1 -1
- package/src/ServiceWrapper.js +24 -5
package/README.md
CHANGED
|
@@ -101,6 +101,22 @@ NO infrastructure code needed in your service!
|
|
|
101
101
|
|
|
102
102
|
## Configuration
|
|
103
103
|
|
|
104
|
+
### Environment Variable Parsing
|
|
105
|
+
|
|
106
|
+
**ServiceWrapper handles environment variable parsing directly** rather than delegating to a separate connector. This design decision is based on:
|
|
107
|
+
|
|
108
|
+
1. **Core Responsibility** - Configuration loading is fundamental to the wrapper's initialization, not a specialized concern
|
|
109
|
+
2. **Simplicity** - Avoids creating a separate connector for ~20 lines of parsing logic
|
|
110
|
+
3. **Performance** - Eliminates unnecessary abstraction layers for a trivial operation
|
|
111
|
+
4. **Universal Need** - All connectors (MQ, Registry, Cache) require parsed configuration
|
|
112
|
+
|
|
113
|
+
The wrapper parses `${VAR:default}` syntax in configuration files:
|
|
114
|
+
- `${RABBITMQ_URL}` - Uses environment variable, fails if not set
|
|
115
|
+
- `${PORT:3000}` - Uses environment variable, defaults to 3000 if not set
|
|
116
|
+
- `${ENABLED:true}` - Uses environment variable, defaults to true
|
|
117
|
+
|
|
118
|
+
This follows Docker/Kubernetes best practices for configuration management while keeping the wrapper architecture clean and focused.
|
|
119
|
+
|
|
104
120
|
### operations.json
|
|
105
121
|
```json
|
|
106
122
|
{
|
|
@@ -121,13 +137,23 @@ NO infrastructure code needed in your service!
|
|
|
121
137
|
{
|
|
122
138
|
"service": {
|
|
123
139
|
"name": "my-service",
|
|
124
|
-
"port": 3000
|
|
140
|
+
"port": "${PORT:3000}"
|
|
125
141
|
},
|
|
126
142
|
"wrapper": {
|
|
127
|
-
"mq": {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
143
|
+
"mq": {
|
|
144
|
+
"url": "${RABBITMQ_URL:amqp://localhost:5672}",
|
|
145
|
+
"enabled": "${MQ_ENABLED:true}"
|
|
146
|
+
},
|
|
147
|
+
"registry": {
|
|
148
|
+
"url": "${REGISTRY_URL}",
|
|
149
|
+
"enabled": "${REGISTRY_ENABLED:false}"
|
|
150
|
+
},
|
|
151
|
+
"monitoring": {
|
|
152
|
+
"enabled": "${MONITORING_ENABLED:true}"
|
|
153
|
+
},
|
|
154
|
+
"health": {
|
|
155
|
+
"endpoint": "/health"
|
|
156
|
+
}
|
|
131
157
|
}
|
|
132
158
|
}
|
|
133
159
|
```
|
package/package.json
CHANGED
package/src/ServiceWrapper.js
CHANGED
|
@@ -82,10 +82,25 @@ class ServiceWrapper {
|
|
|
82
82
|
_processConfig(config) {
|
|
83
83
|
// Replace environment variables in config
|
|
84
84
|
const processValue = (value) => {
|
|
85
|
-
if (typeof value === 'string'
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
if (typeof value === 'string') {
|
|
86
|
+
// Support ${VAR:default} format anywhere in string
|
|
87
|
+
return value.replace(/\$\{([^:}]+)(?::([^}]*))?\}/g, (match, varName, defaultValue) => {
|
|
88
|
+
const envValue = process.env[varName];
|
|
89
|
+
|
|
90
|
+
// Use env value if exists (even if empty string)
|
|
91
|
+
if (envValue !== undefined) {
|
|
92
|
+
return envValue;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Use default if provided
|
|
96
|
+
if (defaultValue !== undefined) {
|
|
97
|
+
return defaultValue;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Log warning and return empty string
|
|
101
|
+
console.warn(`[ServiceWrapper] Missing env variable: ${varName}`);
|
|
102
|
+
return '';
|
|
103
|
+
});
|
|
89
104
|
}
|
|
90
105
|
return value;
|
|
91
106
|
};
|
|
@@ -96,6 +111,10 @@ class ServiceWrapper {
|
|
|
96
111
|
for (const [key, value] of Object.entries(obj)) {
|
|
97
112
|
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
98
113
|
result[key] = processObject(value);
|
|
114
|
+
} else if (Array.isArray(value)) {
|
|
115
|
+
result[key] = value.map(item =>
|
|
116
|
+
typeof item === 'object' && item !== null ? processObject(item) : processValue(item)
|
|
117
|
+
);
|
|
99
118
|
} else {
|
|
100
119
|
result[key] = processValue(value);
|
|
101
120
|
}
|
|
@@ -183,7 +202,7 @@ class ServiceWrapper {
|
|
|
183
202
|
|
|
184
203
|
res.on('finish', () => {
|
|
185
204
|
const duration = Date.now() - start;
|
|
186
|
-
this.monitoring.info('Request processed', {
|
|
205
|
+
this.monitoring?.info && this.monitoring.info('Request processed', {
|
|
187
206
|
method: req.method,
|
|
188
207
|
path: req.path,
|
|
189
208
|
statusCode: res.statusCode,
|