@open-xchange/fastify-sdk 0.1.0 → 0.2.1
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 +33 -16
- package/lib/app.js +42 -35
- package/lib/database/{mysql.js → mariadb.js} +12 -12
- package/lib/dotenv.js +22 -0
- package/lib/health.js +1 -1
- package/lib/index.js +3 -3
- package/lib/logger.js +2 -13
- package/lib/metrics-server.js +3 -1
- package/lib/testing/index.js +1 -0
- package/package.json +11 -18
- package/lib/lint/index.js +0 -5
package/README.md
CHANGED
|
@@ -32,14 +32,13 @@ That single call replaces ~500 lines of boilerplate (logger, CORS, Helmet, metri
|
|
|
32
32
|
|
|
33
33
|
| Import path | What it provides |
|
|
34
34
|
|---|---|
|
|
35
|
-
| `@open-xchange/fastify-sdk` | `createApp`, `createMetricsServer`, `createLogger`, `
|
|
36
|
-
| `@open-xchange/fastify-sdk/
|
|
35
|
+
| `@open-xchange/fastify-sdk` | `createApp`, `createMetricsServer`, `createLogger`, `logger`, `loadEnv`, `requireEnv`, `jwtAuthHook`, health check helpers, re-exports of `fastify`, `fp`, `pino`, `promClient`, `createError`, `jose` |
|
|
36
|
+
| `@open-xchange/fastify-sdk/mariadb` | `createMariaDBPool`, `createMariaDBPoolFromEnv`, `getMariaDBPools`, `mariadbReadyCheck`, `createUUID` |
|
|
37
37
|
| `@open-xchange/fastify-sdk/postgres` | `createPostgresPool`, `createPostgresPoolFromEnv` |
|
|
38
38
|
| `@open-xchange/fastify-sdk/migrations` | `createMigrationRunner`, `executeMigrations` |
|
|
39
39
|
| `@open-xchange/fastify-sdk/config` | `createConfigRegistry`, `readConfigurationFile`, Joi helpers (`defaultTrue`, `defaultFalse`, `customString`, `customURL`), `Joi` |
|
|
40
40
|
| `@open-xchange/fastify-sdk/redis` | `createRedisClient`, `createRedisClientFromEnv`, `redisReadyCheck` |
|
|
41
41
|
| `@open-xchange/fastify-sdk/testing` | `createTestApp`, `generateTokenForJwks`, `getJwks` |
|
|
42
|
-
| `@open-xchange/fastify-sdk/lint` | ESLint flat config with `@open-xchange/lint` |
|
|
43
42
|
|
|
44
43
|
## API reference
|
|
45
44
|
|
|
@@ -66,7 +65,7 @@ Creates a configured Fastify instance with standard OX defaults.
|
|
|
66
65
|
static: false | true | { root, preCompressed, ... }, // Default: false
|
|
67
66
|
},
|
|
68
67
|
metricsServer: true, // Default: true (separate Fastify on port 9000)
|
|
69
|
-
database: {
|
|
68
|
+
database: { mariadb: true }, // Auto-manages pool readiness, health checks, shutdown
|
|
70
69
|
config: { // YAML config file watching
|
|
71
70
|
filename: 'config.yaml',
|
|
72
71
|
schema, // Joi schema for validation
|
|
@@ -98,35 +97,51 @@ Pass custom options to override defaults (e.g. `createLogger({ level: 'debug' })
|
|
|
98
97
|
|
|
99
98
|
Loads environment variables from `.env.defaults` then `.env` using Node's built-in `process.loadEnvFile()`. No external dependency needed.
|
|
100
99
|
|
|
100
|
+
### `requireEnv(keys)`
|
|
101
|
+
|
|
102
|
+
Validates that the given environment variables are set and non-empty. Prints a clear error message and exits the process if any are missing. Call after `loadEnv()` and before `createApp()`.
|
|
103
|
+
|
|
104
|
+
```js
|
|
105
|
+
import { loadEnv, requireEnv } from '@open-xchange/fastify-sdk'
|
|
106
|
+
|
|
107
|
+
loadEnv()
|
|
108
|
+
|
|
109
|
+
requireEnv(['PORT', 'ORIGINS', 'REDIS_HOSTS'])
|
|
110
|
+
|
|
111
|
+
if (process.env.SQL_ENABLED === 'true') {
|
|
112
|
+
requireEnv(['SQL_HOST', 'SQL_USER', 'SQL_PASS', 'SQL_DB'])
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
101
116
|
### Health check helpers
|
|
102
117
|
|
|
103
118
|
```js
|
|
104
|
-
import { registerReadinessCheck, registerHealthCheck,
|
|
119
|
+
import { registerReadinessCheck, registerHealthCheck, mariadbHealthCheck } from '@open-xchange/fastify-sdk'
|
|
105
120
|
|
|
106
|
-
registerReadinessCheck(async () => { await
|
|
107
|
-
registerHealthCheck(async () => { await
|
|
121
|
+
registerReadinessCheck(async () => { await mariadbHealthCheck(pool) })
|
|
122
|
+
registerHealthCheck(async () => { await mariadbHealthCheck(pool) })
|
|
108
123
|
```
|
|
109
124
|
|
|
110
125
|
Registered checks are run by the metrics server (`GET /ready` and `GET /live` on port 9000). See [Metrics server](#metrics-server-default-enabled) below.
|
|
111
126
|
|
|
112
|
-
###
|
|
127
|
+
### MariaDB
|
|
113
128
|
|
|
114
129
|
```js
|
|
115
|
-
import {
|
|
130
|
+
import { createMariaDBPool, createMariaDBPoolFromEnv, mariadbReadyCheck, createUUID } from '@open-xchange/fastify-sdk/mariadb'
|
|
116
131
|
|
|
117
132
|
// From explicit options
|
|
118
|
-
const pool =
|
|
133
|
+
const pool = createMariaDBPool({ host: 'localhost', database: 'mydb', user: 'root', password: '' })
|
|
119
134
|
|
|
120
135
|
// From env vars (SQL_HOST, SQL_PORT, SQL_DB, SQL_USER, SQL_PASS, SQL_CONNECTIONS)
|
|
121
|
-
const pool =
|
|
136
|
+
const pool = createMariaDBPoolFromEnv()
|
|
122
137
|
|
|
123
138
|
// Multi-database from env (DB_<NAME>_HOST, DB_<NAME>_PORT, etc.)
|
|
124
|
-
const pools =
|
|
139
|
+
const pools = createMariaDBPoolFromEnv({ names: 'users,analytics' })
|
|
125
140
|
|
|
126
141
|
// Retry-based readiness check
|
|
127
|
-
await
|
|
142
|
+
await mariadbReadyCheck(pool, { retries: 12, delay: 10_000, logger })
|
|
128
143
|
|
|
129
|
-
//
|
|
144
|
+
// MariaDB UUID generation
|
|
130
145
|
const uuid = await createUUID(pool)
|
|
131
146
|
```
|
|
132
147
|
|
|
@@ -140,7 +155,7 @@ import { createPostgresPool, createPostgresPoolFromEnv } from '@open-xchange/fas
|
|
|
140
155
|
const pool = createPostgresPoolFromEnv()
|
|
141
156
|
```
|
|
142
157
|
|
|
143
|
-
### Migrations (Umzug +
|
|
158
|
+
### Migrations (Umzug + MariaDB)
|
|
144
159
|
|
|
145
160
|
```js
|
|
146
161
|
import { createMigrationRunner, executeMigrations } from '@open-xchange/fastify-sdk/migrations'
|
|
@@ -201,9 +216,11 @@ const jwks = await getJwks('kid')
|
|
|
201
216
|
|
|
202
217
|
### Lint
|
|
203
218
|
|
|
219
|
+
Use `@open-xchange/lint` directly as a devDependency:
|
|
220
|
+
|
|
204
221
|
```js
|
|
205
222
|
// eslint.config.js
|
|
206
|
-
import config from '@open-xchange/
|
|
223
|
+
import config from '@open-xchange/lint'
|
|
207
224
|
|
|
208
225
|
export default [
|
|
209
226
|
...config
|
package/lib/app.js
CHANGED
|
@@ -5,7 +5,7 @@ import fastify from 'fastify'
|
|
|
5
5
|
import autoLoad from '@fastify/autoload'
|
|
6
6
|
import ajvErrors from 'ajv-errors'
|
|
7
7
|
import { loadEnv } from './dotenv.js'
|
|
8
|
-
import {
|
|
8
|
+
import { logger } from './logger.js'
|
|
9
9
|
|
|
10
10
|
import sensible from '@fastify/sensible'
|
|
11
11
|
import corsPlugin from './plugins/cors.js'
|
|
@@ -41,7 +41,7 @@ import metricsPlugin from './plugins/metrics.js'
|
|
|
41
41
|
* @property {boolean} [preCompressed=true] Whether to serve pre-compressed `.gz`/`.br` files when available.
|
|
42
42
|
* @property {string} [prefix] URL prefix for static files (e.g. `'/assets'`).
|
|
43
43
|
* @property {string} [logLevel] Fastify log level for static file requests. Defaults to `'warn'` when `LOG_LEVEL` is `debug` or `info` (to reduce noise), otherwise uses `LOG_LEVEL`.
|
|
44
|
-
* @property {(res: import('http').ServerResponse, path: string, stat: import('fs').Stats) => void} [setHeaders] Function to set custom headers on static file responses.
|
|
44
|
+
* @property {(res: import('http').ServerResponse, path: string, stat: import('fs').Stats) => void} [setHeaders] Function to set custom headers on static file responses. Defaults to setting a `version` header from `CI_COMMIT_SHA` (or `'main'`).
|
|
45
45
|
*/
|
|
46
46
|
|
|
47
47
|
/**
|
|
@@ -69,7 +69,7 @@ import metricsPlugin from './plugins/metrics.js'
|
|
|
69
69
|
* @property {FastifyServerOptions} [fastify] Options passed directly to the Fastify constructor.
|
|
70
70
|
* @property {PluginsConfig} [plugins] Plugin configuration.
|
|
71
71
|
* @property {boolean} [metricsServer=true] Start a metrics/health server on port 9000 (`/live`, `/ready`, `/metrics`).
|
|
72
|
-
* @property {{
|
|
72
|
+
* @property {{ mariadb?: true | Record<string, import('mariadb').Pool> }} [database] Database pools to manage. Pass `{ mariadb: true }` to create pools from the `DATABASES` env var, or pass pre-created pools. Foundation waits for readiness, registers health checks, and closes pools on shutdown.
|
|
73
73
|
* @property {ConfigFileRegistration | ConfigFileRegistration[]} [config] YAML configuration files to watch. Foundation creates the config registry, registers files on ready, and closes the watcher on shutdown.
|
|
74
74
|
* @property {() => void | Promise<void>} [onReady] Hook called when the Fastify instance is ready.
|
|
75
75
|
* @property {() => void | Promise<void>} [onClose] Hook called when the Fastify instance is closing (before shutdown).
|
|
@@ -106,7 +106,8 @@ export async function createApp (options = {}) {
|
|
|
106
106
|
database: databaseOptions,
|
|
107
107
|
config: configOptions,
|
|
108
108
|
onReady,
|
|
109
|
-
onClose
|
|
109
|
+
onClose,
|
|
110
|
+
processHandlers = true
|
|
110
111
|
} = options
|
|
111
112
|
|
|
112
113
|
// Load env vars
|
|
@@ -115,7 +116,7 @@ export async function createApp (options = {}) {
|
|
|
115
116
|
const app = fastify({
|
|
116
117
|
requestIdLogLabel: 'requestId',
|
|
117
118
|
disableRequestLogging: true,
|
|
118
|
-
loggerInstance:
|
|
119
|
+
loggerInstance: logger,
|
|
119
120
|
connectionTimeout: 30000,
|
|
120
121
|
genReqId: () => randomUUID(),
|
|
121
122
|
ajv: {
|
|
@@ -172,12 +173,16 @@ export async function createApp (options = {}) {
|
|
|
172
173
|
const { default: fastifyStatic } = await import('@fastify/static')
|
|
173
174
|
const logLevelEnv = process.env.LOG_LEVEL
|
|
174
175
|
const defaultLogLevel = logLevelEnv === 'debug' || logLevelEnv === 'info' ? 'warn' : logLevelEnv
|
|
175
|
-
const
|
|
176
|
+
const defaultSetHeaders = (res) => {
|
|
177
|
+
res.setHeader('version', process.env.CI_COMMIT_SHA || 'main')
|
|
178
|
+
}
|
|
179
|
+
const { root = 'public', preCompressed = true, logLevel = defaultLogLevel, setHeaders = defaultSetHeaders, ...restStaticConfig } = staticConfig === true ? {} : staticConfig
|
|
176
180
|
const isAbsolute = root.startsWith('/')
|
|
177
181
|
await app.register(fastifyStatic, {
|
|
178
182
|
root: isAbsolute ? root : join(dir, root),
|
|
179
183
|
preCompressed,
|
|
180
184
|
logLevel,
|
|
185
|
+
setHeaders,
|
|
181
186
|
...restStaticConfig
|
|
182
187
|
})
|
|
183
188
|
}
|
|
@@ -212,20 +217,20 @@ export async function createApp (options = {}) {
|
|
|
212
217
|
}
|
|
213
218
|
|
|
214
219
|
// Database lifecycle: readiness checks, health probes, graceful shutdown
|
|
215
|
-
if (databaseOptions?.
|
|
216
|
-
const {
|
|
217
|
-
const { registerReadinessCheck,
|
|
218
|
-
const pools = databaseOptions.
|
|
220
|
+
if (databaseOptions?.mariadb) {
|
|
221
|
+
const { mariadbReadyCheck, getMariaDBPools } = await import('./database/mariadb.js')
|
|
222
|
+
const { registerReadinessCheck, mariadbHealthCheck } = await import('./health.js')
|
|
223
|
+
const pools = databaseOptions.mariadb === true ? getMariaDBPools() : databaseOptions.mariadb
|
|
219
224
|
const entries = Object.entries(pools)
|
|
220
225
|
|
|
221
226
|
// Register health checks for each pool
|
|
222
227
|
for (const [, pool] of entries) {
|
|
223
|
-
registerReadinessCheck(() =>
|
|
228
|
+
registerReadinessCheck(() => mariadbHealthCheck(pool))
|
|
224
229
|
}
|
|
225
230
|
|
|
226
231
|
// Wait for all pools to be ready
|
|
227
232
|
for (const [name, pool] of entries) {
|
|
228
|
-
await
|
|
233
|
+
await mariadbReadyCheck(pool, { logger: app.log })
|
|
229
234
|
app.log.info(`Database "${name}" is ready`)
|
|
230
235
|
}
|
|
231
236
|
|
|
@@ -273,34 +278,36 @@ export async function createApp (options = {}) {
|
|
|
273
278
|
}
|
|
274
279
|
|
|
275
280
|
// Register process signal handlers for graceful shutdown
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
281
|
+
if (processHandlers) {
|
|
282
|
+
async function shutdown () {
|
|
283
|
+
await app.close()
|
|
284
|
+
}
|
|
279
285
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
286
|
+
async function onUncaughtException (err) {
|
|
287
|
+
app.log.fatal({ err }, `Uncaught Exception: ${err.message}`)
|
|
288
|
+
await shutdown()
|
|
289
|
+
}
|
|
284
290
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
291
|
+
async function onUnhandledRejection (err) {
|
|
292
|
+
app.log.fatal({ err }, `Unhandled Rejection: ${err.message}`)
|
|
293
|
+
await shutdown()
|
|
294
|
+
}
|
|
289
295
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
296
|
+
async function onSigint () {
|
|
297
|
+
app.log.info('SIGINT received, initiating graceful shutdown...')
|
|
298
|
+
await shutdown()
|
|
299
|
+
}
|
|
294
300
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
301
|
+
process.on('uncaughtException', onUncaughtException)
|
|
302
|
+
process.on('unhandledRejection', onUnhandledRejection)
|
|
303
|
+
process.on('SIGINT', onSigint)
|
|
298
304
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
305
|
+
app.addHook('onClose', () => {
|
|
306
|
+
process.removeListener('uncaughtException', onUncaughtException)
|
|
307
|
+
process.removeListener('unhandledRejection', onUnhandledRejection)
|
|
308
|
+
process.removeListener('SIGINT', onSigint)
|
|
309
|
+
})
|
|
310
|
+
}
|
|
304
311
|
|
|
305
312
|
/**
|
|
306
313
|
* Start the app server. Reads `BIND_ADDR` and `PORT` (default 8080) from
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as mariadb from 'mariadb'
|
|
2
2
|
|
|
3
3
|
const defaults = {
|
|
4
4
|
dateStrings: ['DATE', 'DATETIME'],
|
|
5
|
-
timezone: '
|
|
5
|
+
timezone: '+00:00',
|
|
6
6
|
namedPlaceholders: true
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
export function
|
|
10
|
-
const pool =
|
|
9
|
+
export function createMariaDBPool (options = {}) {
|
|
10
|
+
const pool = mariadb.createPool({ ...defaults, ...options })
|
|
11
11
|
pool.on('connection', (connection) => {
|
|
12
12
|
connection.query('SET SESSION time_zone="+00:00"')
|
|
13
13
|
})
|
|
14
14
|
return pool
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export function
|
|
17
|
+
export function createMariaDBPoolFromEnv ({ prefix = 'SQL', names } = {}) {
|
|
18
18
|
if (names) {
|
|
19
19
|
const dbNames = typeof names === 'string'
|
|
20
20
|
? names.split(',').map(n => n.trim().toLowerCase()).filter(Boolean)
|
|
@@ -23,7 +23,7 @@ export function createMySQLPoolFromEnv ({ prefix = 'SQL', names } = {}) {
|
|
|
23
23
|
const pools = {}
|
|
24
24
|
for (const name of dbNames) {
|
|
25
25
|
const envPrefix = `DB_${name.toUpperCase()}`
|
|
26
|
-
pools[name] =
|
|
26
|
+
pools[name] = createMariaDBPool({
|
|
27
27
|
host: process.env[`${envPrefix}_HOST`],
|
|
28
28
|
port: Number(process.env[`${envPrefix}_PORT`]) || 3306,
|
|
29
29
|
database: process.env[`${envPrefix}_NAME`],
|
|
@@ -36,7 +36,7 @@ export function createMySQLPoolFromEnv ({ prefix = 'SQL', names } = {}) {
|
|
|
36
36
|
return pools
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
return
|
|
39
|
+
return createMariaDBPool({
|
|
40
40
|
host: process.env[`${prefix}_HOST`],
|
|
41
41
|
port: Number(process.env[`${prefix}_PORT`]) || 3306,
|
|
42
42
|
database: process.env[`${prefix}_DB`],
|
|
@@ -46,7 +46,7 @@ export function createMySQLPoolFromEnv ({ prefix = 'SQL', names } = {}) {
|
|
|
46
46
|
})
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
export async function
|
|
49
|
+
export async function mariadbReadyCheck (pool, { retries = 12, delay = 10_000, logger } = {}) {
|
|
50
50
|
for (let i = 1; i <= retries; i++) {
|
|
51
51
|
try {
|
|
52
52
|
await pool.query('SELECT 1')
|
|
@@ -64,13 +64,13 @@ let _pools
|
|
|
64
64
|
|
|
65
65
|
/**
|
|
66
66
|
* Returns a singleton pool map created from the `DATABASES` env var.
|
|
67
|
-
* Calls `
|
|
68
|
-
* @returns {Record<string, import('
|
|
67
|
+
* Calls `createMariaDBPoolFromEnv({ names: process.env.DATABASES })` on first access.
|
|
68
|
+
* @returns {Record<string, import('mariadb').Pool>}
|
|
69
69
|
*/
|
|
70
|
-
export function
|
|
70
|
+
export function getMariaDBPools () {
|
|
71
71
|
if (!_pools) {
|
|
72
72
|
const names = process.env.DATABASES
|
|
73
|
-
_pools = names ?
|
|
73
|
+
_pools = names ? createMariaDBPoolFromEnv({ names }) : {}
|
|
74
74
|
}
|
|
75
75
|
return _pools
|
|
76
76
|
}
|
package/lib/dotenv.js
CHANGED
|
@@ -4,3 +4,25 @@ export function loadEnv () {
|
|
|
4
4
|
try { process.loadEnvFile('.env') } catch {}
|
|
5
5
|
try { process.loadEnvFile('.env.defaults') } catch {}
|
|
6
6
|
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Validates that the given environment variables are set and non-empty.
|
|
10
|
+
* Throws an error listing all missing variables if any are not set.
|
|
11
|
+
*
|
|
12
|
+
* @param {string[]} keys — Environment variable names to check.
|
|
13
|
+
* @throws {Error} If one or more variables are missing or empty.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* requireEnv(['PORT', 'ORIGINS', 'REDIS_HOSTS'])
|
|
17
|
+
*
|
|
18
|
+
* if (process.env.SQL_ENABLED === 'true') {
|
|
19
|
+
* requireEnv(['SQL_HOST', 'SQL_USER', 'SQL_PASS', 'SQL_DB'])
|
|
20
|
+
* }
|
|
21
|
+
*/
|
|
22
|
+
export function requireEnv (keys) {
|
|
23
|
+
const missing = keys.filter(key => !process.env[key])
|
|
24
|
+
if (missing.length > 0) {
|
|
25
|
+
console.error(`Missing required environment variables: ${missing.join(', ')}`)
|
|
26
|
+
process.exit(1)
|
|
27
|
+
}
|
|
28
|
+
}
|
package/lib/health.js
CHANGED
package/lib/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export { createApp } from './app.js'
|
|
2
2
|
export { createMetricsServer } from './metrics-server.js'
|
|
3
|
-
export { createLogger,
|
|
4
|
-
export { loadEnv } from './dotenv.js'
|
|
5
|
-
export { registerHealthCheck, registerReadinessCheck, clearChecks,
|
|
3
|
+
export { createLogger, logger, pinoConfig } from './logger.js'
|
|
4
|
+
export { loadEnv, requireEnv } from './dotenv.js'
|
|
5
|
+
export { registerHealthCheck, registerReadinessCheck, clearChecks, mariadbHealthCheck, postgresHealthCheck, redisHealthCheck } from './health.js'
|
|
6
6
|
export { default as metricsPlugin } from './plugins/metrics.js'
|
|
7
7
|
|
|
8
8
|
/**
|
package/lib/logger.js
CHANGED
|
@@ -43,18 +43,7 @@ export function createLogger (options = {}) {
|
|
|
43
43
|
return pino({ ...pinoConfig, ...options })
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Returns a shared logger singleton. Creates it on first call
|
|
50
|
-
* (calling loadEnv() to ensure env vars like LOG_LEVEL are loaded).
|
|
51
|
-
*/
|
|
52
|
-
export function getLogger () {
|
|
53
|
-
if (!_defaultLogger) {
|
|
54
|
-
loadEnv()
|
|
55
|
-
_defaultLogger = createLogger()
|
|
56
|
-
}
|
|
57
|
-
return _defaultLogger
|
|
58
|
-
}
|
|
46
|
+
loadEnv()
|
|
47
|
+
export const logger = createLogger()
|
|
59
48
|
|
|
60
49
|
export { pinoConfig }
|
package/lib/metrics-server.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fastify from 'fastify'
|
|
2
2
|
import promClient from 'prom-client'
|
|
3
3
|
import { getReadinessChecks, getHealthChecks } from './health.js'
|
|
4
|
+
import { logger } from './logger.js'
|
|
4
5
|
|
|
5
6
|
export function createMetricsServer () {
|
|
6
7
|
const app = fastify({ logger: false })
|
|
@@ -26,7 +27,8 @@ async function handleChecks (reply, checks) {
|
|
|
26
27
|
try {
|
|
27
28
|
await Promise.all(checks.map(fn => fn()))
|
|
28
29
|
return { status: 'ok' }
|
|
29
|
-
} catch {
|
|
30
|
+
} catch (err) {
|
|
31
|
+
logger.debug({ err }, 'Health check failed')
|
|
30
32
|
reply.code(503)
|
|
31
33
|
return { status: 'error' }
|
|
32
34
|
}
|
package/lib/testing/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,23 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-xchange/fastify-sdk",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Shared foundation package for OX App Suite Node.js services",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": "./lib/index.js",
|
|
9
|
-
"./
|
|
9
|
+
"./mariadb": "./lib/database/mariadb.js",
|
|
10
10
|
"./postgres": "./lib/database/postgres.js",
|
|
11
11
|
"./migrations": "./lib/database/migrations.js",
|
|
12
12
|
"./config": "./lib/config/index.js",
|
|
13
13
|
"./redis": "./lib/redis/index.js",
|
|
14
|
-
"./testing": "./lib/testing/index.js"
|
|
15
|
-
"./lint": "./lib/lint/index.js"
|
|
16
|
-
},
|
|
17
|
-
"scripts": {
|
|
18
|
-
"lint": "eslint . --cache --fix",
|
|
19
|
-
"test": "vitest run",
|
|
20
|
-
"test:coverage": "vitest run --coverage"
|
|
14
|
+
"./testing": "./lib/testing/index.js"
|
|
21
15
|
},
|
|
22
16
|
"author": "Open-Xchange",
|
|
23
17
|
"license": "AGPL-3.0-or-later",
|
|
@@ -45,7 +39,7 @@
|
|
|
45
39
|
},
|
|
46
40
|
"peerDependencies": {
|
|
47
41
|
"ioredis": "^5.9.0",
|
|
48
|
-
"
|
|
42
|
+
"mariadb": "^3.0.0",
|
|
49
43
|
"pg": "^8.16.0",
|
|
50
44
|
"umzug": "^3.8.2"
|
|
51
45
|
},
|
|
@@ -53,7 +47,7 @@
|
|
|
53
47
|
"ioredis": {
|
|
54
48
|
"optional": true
|
|
55
49
|
},
|
|
56
|
-
"
|
|
50
|
+
"mariadb": {
|
|
57
51
|
"optional": true
|
|
58
52
|
},
|
|
59
53
|
"pg": {
|
|
@@ -68,7 +62,7 @@
|
|
|
68
62
|
"@vitest/coverage-v8": "^4.0.18",
|
|
69
63
|
"eslint": "^9.39.2",
|
|
70
64
|
"ioredis": "^5.9.2",
|
|
71
|
-
"
|
|
65
|
+
"mariadb": "^3.4.1",
|
|
72
66
|
"pg": "^8.18.0",
|
|
73
67
|
"umzug": "^3.8.2",
|
|
74
68
|
"vitest": "^4.0.18"
|
|
@@ -76,10 +70,9 @@
|
|
|
76
70
|
"engines": {
|
|
77
71
|
"node": ">=20"
|
|
78
72
|
},
|
|
79
|
-
"
|
|
80
|
-
|
|
81
|
-
"
|
|
82
|
-
|
|
83
|
-
]
|
|
73
|
+
"scripts": {
|
|
74
|
+
"lint": "eslint . --cache --fix",
|
|
75
|
+
"test": "vitest run",
|
|
76
|
+
"test:coverage": "vitest run --coverage"
|
|
84
77
|
}
|
|
85
|
-
}
|
|
78
|
+
}
|