@platformatic/service 0.22.0 → 0.23.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.
Files changed (38) hide show
  1. package/fixtures/hello-client-ts/platformatic.service.json +2 -1
  2. package/index.js +118 -169
  3. package/lib/load-config.js +6 -1
  4. package/lib/plugins/clients.js +12 -0
  5. package/lib/plugins/cors.js +29 -0
  6. package/lib/plugins/file-watcher.js +44 -0
  7. package/lib/plugins/health-check.js +17 -0
  8. package/lib/plugins/plugins.js +56 -0
  9. package/lib/plugins/typescript.js +46 -0
  10. package/lib/root-endpoint/index.js +1 -0
  11. package/lib/schema.js +8 -1
  12. package/lib/start.mjs +27 -136
  13. package/lib/utils.js +2 -2
  14. package/package.json +9 -8
  15. package/test/autoload.test.js +77 -59
  16. package/test/cli/compile.test.mjs +45 -33
  17. package/test/cli/watch.test.mjs +39 -0
  18. package/test/clients.test.js +24 -17
  19. package/test/config.test.js +58 -86
  20. package/test/cors.test.js +48 -30
  21. package/test/fixtures/bad-typescript-plugin/platformatic.service.json +3 -1
  22. package/test/fixtures/typescript-autoload/platformatic.service.json +3 -1
  23. package/test/fixtures/typescript-plugin/platformatic.service.json +3 -1
  24. package/test/fixtures/typescript-plugin-nocompile/platformatic.service.json +2 -1
  25. package/test/graphql.test.js +18 -14
  26. package/test/healthcheck.test.js +22 -13
  27. package/test/https.test.js +11 -8
  28. package/test/lambda.test.js +103 -0
  29. package/test/load-and-reload-files.test.js +97 -112
  30. package/test/load-plugin.test.js +8 -4
  31. package/test/metrics.test.js +59 -39
  32. package/test/routes.test.js +43 -25
  33. package/test/utils.test.js +2 -2
  34. package/test/watch.test.js +182 -0
  35. /package/lib/{graphql.js → plugins/graphql.js} +0 -0
  36. /package/lib/{metrics-plugin.js → plugins/metrics.js} +0 -0
  37. /package/lib/{openapi.js → plugins/openapi.js} +0 -0
  38. /package/lib/{sandbox-wrapper.js → plugins/sandbox-wrapper.js} +0 -0
@@ -5,7 +5,8 @@
5
5
  "logger": {
6
6
  "level": "warn",
7
7
  "name": "hello client ts"
8
- }
8
+ },
9
+ "pluginTimeout": 30000
9
10
  },
10
11
  "plugins": {
11
12
  "paths": ["./plugin.ts"],
package/index.js CHANGED
@@ -1,36 +1,32 @@
1
1
  'use strict'
2
2
 
3
- const { start } = require('@fastify/restartable')
4
- const sandbox = require('fastify-sandbox')
5
- const underPressure = require('@fastify/under-pressure')
6
- const { schema } = require('./lib/schema')
3
+ const { readFile } = require('fs/promises')
4
+
7
5
  const ConfigManager = require('@platformatic/config')
8
- const { loadConfig, generateDefaultConfig } = require('./lib/load-config')
9
- const { addLoggerToTheConfig, getJSPluginPath, isFileAccessible } = require('./lib/utils')
6
+ const { restartable } = require('@fastify/restartable')
10
7
  const { isKeyEnabled } = require('@platformatic/utils')
8
+
11
9
  const compiler = require('./lib/compile')
12
- const { join, dirname, resolve } = require('path')
13
- const { readFile } = require('fs/promises')
14
- const wrapperPath = join(__dirname, 'lib', 'sandbox-wrapper.js')
15
- const setupOpenAPI = require('./lib/openapi.js')
16
- const setupGraphQL = require('./lib/graphql.js')
17
-
18
- function originToRegexp (origin) {
19
- if (typeof origin === 'object') {
20
- if (origin.regexp) {
21
- origin = new RegExp(origin.regexp)
22
- }
23
- }
10
+ const setupCors = require('./lib/plugins/cors')
11
+ const setupOpenAPI = require('./lib/plugins/openapi.js')
12
+ const setupGraphQL = require('./lib/plugins/graphql.js')
13
+ const setupClients = require('./lib/plugins/clients')
14
+ const setupMetrics = require('./lib/plugins/metrics')
15
+ const setupTsCompiler = require('./lib/plugins/typescript')
16
+ const setupFileWatcher = require('./lib/plugins/file-watcher')
17
+ const setupHealthCheck = require('./lib/plugins/health-check')
18
+ const loadPlugins = require('./lib/plugins/plugins')
24
19
 
25
- return origin
26
- }
20
+ const { schema } = require('./lib/schema')
21
+ const { loadConfig, generateDefaultConfig } = require('./lib/load-config')
22
+ const { addLoggerToTheConfig } = require('./lib/utils')
27
23
 
28
24
  async function platformaticService (app, opts, toLoad = []) {
29
25
  const configManager = app.platformatic.configManager
30
26
  const config = configManager.current
31
27
 
32
28
  if (isKeyEnabled('metrics', config)) {
33
- app.register(require('./lib/metrics-plugin'), config.metrics)
29
+ app.register(setupMetrics, config.metrics)
34
30
  }
35
31
 
36
32
  if (Array.isArray(toLoad)) {
@@ -39,99 +35,37 @@ async function platformaticService (app, opts, toLoad = []) {
39
35
  }
40
36
  }
41
37
 
42
- const serviceConfig = app.platformatic.config?.service
38
+ const serviceConfig = config.service || {}
43
39
 
44
- if (serviceConfig?.openapi) {
45
- await setupOpenAPI(app, serviceConfig.openapi)
40
+ if (isKeyEnabled('openapi', serviceConfig)) {
41
+ await app.register(setupOpenAPI, serviceConfig.openapi)
46
42
  }
47
43
 
48
- if (serviceConfig?.graphql) {
49
- await setupGraphQL(app, serviceConfig.graphql)
44
+ if (isKeyEnabled('graphql', serviceConfig)) {
45
+ await app.register(setupGraphQL, serviceConfig.graphql)
50
46
  }
51
47
 
52
- for (const plugin of (config.clients || [])) {
53
- app.register(require(plugin.path), {
54
- url: plugin.url
55
- })
48
+ if (isKeyEnabled('clients', config)) {
49
+ app.register(setupClients, config.clients)
56
50
  }
57
51
 
58
52
  if (config.plugins) {
59
- // if we don't have a fullPath, let's assume we are in a test and we can use the current working directory
60
- const configPath = configManager.fullPath || join(process.cwd(), 'platformatic.db.json')
61
- const tsConfigPath = join(dirname(configPath), 'tsconfig.json')
62
- /* c8 ignore next 21 */
63
- if (await isFileAccessible(tsConfigPath)) {
64
- const tsConfig = JSON.parse(await readFile(tsConfigPath, 'utf8'))
65
- const outDir = resolve(dirname(tsConfigPath), tsConfig.compilerOptions.outDir)
66
- config.plugins.paths = config.plugins.paths.map((plugin) => {
67
- if (typeof plugin === 'string') {
68
- return getJSPluginPath(configPath, plugin, outDir)
69
- } else {
70
- return {
71
- path: getJSPluginPath(configPath, plugin.path, outDir),
72
- options: plugin.options
73
- }
74
- }
75
- })
76
- } else {
77
- for (const plugin of config.plugins.paths) {
78
- const path = typeof plugin === 'string' ? plugin : plugin.path
79
- if (path.endsWith('.ts')) {
80
- throw new Error(`Cannot load plugin ${path}, tsconfig.json not found`)
81
- }
82
- }
53
+ if (config.plugins.typescript) {
54
+ await app.register(setupTsCompiler)
83
55
  }
56
+ await app.register(loadPlugins)
57
+ }
84
58
 
85
- // if not defined, we default to true (which can happen only if config is set programmatically,
86
- // that's why we ignore the coverage of the `undefined` case, which cannot be covered in cli tests)
87
- // all individual plugin hot reload settings will be overloaded by global hot reload
88
- /* c8 ignore next 1 */
89
- const hotReload = config.plugins.hotReload !== false
90
- const isWatchEnabled = config.watch !== false
91
-
92
- app.log.debug({ plugins: config.plugins.paths, hotReload, isWatchEnabled }, 'loading plugins')
93
-
94
- if (isWatchEnabled && hotReload) {
95
- await app.register(sandbox, {
96
- path: wrapperPath,
97
- options: { paths: config.plugins.paths },
98
- customizeGlobalThis (_globalThis) {
99
- // Taken from https://github.com/nodejs/undici/blob/fa9fd9066569b6357acacffb806aa804b688c9d8/lib/global.js#L5
100
- const globalDispatcher = Symbol.for('undici.globalDispatcher.1')
101
- const dispatcher = globalThis[globalDispatcher]
102
- /* istanbul ignore else */
103
- if (dispatcher) {
104
- _globalThis[globalDispatcher] = dispatcher
105
- }
106
- }
107
- })
108
- } else {
109
- await app.register(require(wrapperPath), { paths: config.plugins.paths })
110
- }
59
+ if (isKeyEnabled('watch', config)) {
60
+ await app.register(setupFileWatcher, { onFilesUpdated })
111
61
  }
112
62
 
113
- // Enable CORS
114
63
  if (config.server.cors) {
115
- let origin = config.server.cors.origin
116
- if (Array.isArray(origin)) {
117
- origin = origin.map(originToRegexp)
118
- } else {
119
- origin = originToRegexp(origin)
120
- }
121
-
122
- config.server.cors.origin = origin
123
-
124
- app.register(require('@fastify/cors'), config.server.cors)
64
+ app.register(setupCors, config.server.cors)
125
65
  }
126
66
 
127
67
  if (isKeyEnabled('healthCheck', config.server)) {
128
- const healthCheck = config.server.healthCheck
129
- app.register(underPressure, {
130
- exposeStatusRoute: '/status',
131
- healthCheckInterval: healthCheck.interval !== undefined ? healthCheck.interval : 5000,
132
- ...healthCheck,
133
- healthCheck: healthCheck.fn
134
- })
68
+ app.register(setupHealthCheck, config.server.healthCheck)
135
69
  }
136
70
 
137
71
  if (!app.hasRoute({ url: '/', method: 'GET' }) && !Array.isArray(toLoad)) {
@@ -178,107 +112,122 @@ function defaultConfig (app, source) {
178
112
 
179
113
  async function buildServer (options, app) {
180
114
  app = app || platformaticService
181
- let cm
182
115
 
183
- if (!options.configManager) {
116
+ let configManager = options.configManager
117
+ if (!configManager) {
184
118
  // instantiate a new config manager from current options
185
- cm = new ConfigManager(defaultConfig(app, options))
186
- await cm.parseAndValidate()
187
- } else {
188
- cm = options.configManager
119
+ configManager = new ConfigManager(defaultConfig(app, options))
120
+ await configManager.parseAndValidate()
189
121
  }
190
122
 
191
123
  // options is a path
192
124
  if (typeof options === 'string') {
193
- options = cm.current
125
+ options = configManager.current
194
126
  }
195
127
 
196
- async function jumpApp (root) {
197
- root.decorate('platformatic', {})
128
+ let url = null
198
129
 
199
- const fileWatcher = options.fileWatcher
200
- /* c8 ignore next 3 */
201
- if (fileWatcher !== undefined) {
202
- root.platformatic.fileWatcher = fileWatcher
203
- }
204
- root.platformatic.configManager = cm
205
- root.platformatic.config = cm.current
130
+ async function createRestartable (fastify) {
131
+ const config = configManager.current
132
+ const root = fastify(config.server)
133
+
134
+ root.decorate('platformatic', { configManager, config })
206
135
  root.register(app)
207
- }
208
- jumpApp[Symbol.for('skip-override')] = true
209
136
 
210
- const serverConfig = {
211
- ...(options.server),
212
- configManager: cm,
213
- app: jumpApp
137
+ root.decorate('url', {
138
+ getter () {
139
+ return url
140
+ }
141
+ })
142
+
143
+ if (root.restarted) {
144
+ root.log.info('restarted')
145
+ }
146
+
147
+ return root
214
148
  }
215
149
 
216
- if (serverConfig.https) {
217
- serverConfig.key = await adjustHttpsKeyAndCert(options.server.https.key)
218
- serverConfig.cert = await adjustHttpsKeyAndCert(options.server.https.cert)
219
- delete serverConfig.https
220
- serverConfig.protocol = 'https'
221
- } else if (options.server) {
222
- serverConfig.protocol = 'http'
150
+ const { port, hostname, ...serverOptions } = options.server
151
+
152
+ if (serverOptions.https) {
153
+ serverOptions.https.key = await adjustHttpsKeyAndCert(serverOptions.https.key)
154
+ serverOptions.https.cert = await adjustHttpsKeyAndCert(serverOptions.https.cert)
223
155
  }
224
156
 
225
- const handler = await start(serverConfig)
157
+ const handler = await restartable(createRestartable)
158
+
159
+ configManager.on('update', async (newConfig) => {
160
+ handler.log.debug('config changed')
161
+ handler.log.trace({ newConfig }, 'new config')
162
+
163
+ if (newConfig.watch === false) {
164
+ /* c8 ignore next 4 */
165
+ if (handler.tsCompilerWatcher) {
166
+ handler.tsCompilerWatcher.kill('SIGTERM')
167
+ handler.log.debug('stop watching typescript files')
168
+ }
226
169
 
227
- Object.defineProperty(handler, 'url', {
228
- get () {
229
- const protocol = serverConfig.protocol
230
- const address = handler.address
231
- const port = handler.port
232
- const url = `${protocol}://${address}:${port}`
233
- return url
170
+ if (handler.fileWatcher) {
171
+ await handler.fileWatcher.stopWatching()
172
+ handler.log.debug('stop watching files')
173
+ }
234
174
  }
175
+
176
+ await safeRestart(handler)
177
+ /* c8 ignore next 1 */
235
178
  })
236
179
 
237
- restarter(handler, cm, jumpApp)
180
+ configManager.on('error', function (err) {
181
+ /* c8 ignore next 1 */
182
+ handler.log.error({ err }, 'error reloading the configuration')
183
+ })
184
+
185
+ handler.decorate('start', async () => {
186
+ url = await handler.listen({ host: hostname, port })
187
+ return url
188
+ })
238
189
 
239
190
  return handler
240
191
  }
241
192
 
242
- function restarter (handler, cm, jumpApp) {
243
- let debounce = null
244
- const _restart = handler.restart
245
- handler.restart = restart
246
- handler.app.restart = restart
247
-
248
- // This is covered by tests but c8 doesn't see it
249
- /* c8 ignore next 30 */
250
- async function restart (opts) {
251
- if (debounce) {
252
- return debounce
253
- }
254
-
255
- if (opts && !await cm.update(opts)) {
256
- const err = new Error('Invalid config')
257
- err.validationErrors = cm.validationErrors
258
- throw err
259
- }
260
-
261
- const restartOpts = {
262
- ...(cm.current.server),
263
- fileWatcher: handler.app.platformatic.fileWatcher,
264
- configManager: cm,
265
- app: jumpApp
266
- }
193
+ async function onFilesUpdated (app) {
194
+ // Reload the config as well, otherwise we will have problems
195
+ // in case the files watcher triggers the config watcher too
196
+ const configManager = app.platformatic.configManager
197
+ try {
198
+ app.log.debug('files changed')
199
+ await configManager.parse()
200
+ await app.restart()
201
+ /* c8 ignore next 8 */
202
+ } catch (err) {
203
+ app.log.error({
204
+ err: {
205
+ message: err.message,
206
+ stack: err.stack
207
+ }
208
+ }, 'failed to reload server')
209
+ }
210
+ }
267
211
 
268
- debounce = _restart(restartOpts).then(() => {
269
- handler.app.log.info('restarted')
270
- }).finally(() => {
271
- debounce = null
272
- })
273
- return debounce
212
+ async function safeRestart (app) {
213
+ try {
214
+ await app.restart()
215
+ /* c8 ignore next 8 */
216
+ } catch (err) {
217
+ app.log.error({
218
+ err: {
219
+ message: err.message,
220
+ stack: err.stack
221
+ }
222
+ }, 'failed to reload server')
274
223
  }
275
224
  }
276
225
 
277
226
  // This is for @platformatic/db to use
278
227
  /* c8 ignore next 4 */
279
- async function buildStart (loadConfig, buildServer) {
228
+ async function buildStart (loadConfig, buildServer, configManagerConfig) {
280
229
  const { buildStart } = await import('./lib/start.mjs')
281
- return buildStart(loadConfig, buildServer)
230
+ return buildStart(loadConfig, buildServer, configManagerConfig)
282
231
  }
283
232
 
284
233
  module.exports.buildServer = buildServer
@@ -21,7 +21,12 @@ function generateDefaultConfig () {
21
21
  // Unfortunately c8 does not see those on Windows
22
22
  /* c8 ignore next 70 */
23
23
  async function loadConfig (minimistConfig, _args, defaultConfig, configType = 'service') {
24
- defaultConfig ??= generateDefaultConfig()
24
+ if (defaultConfig === undefined) {
25
+ defaultConfig = generateDefaultConfig()
26
+ } else if (defaultConfig?.mergeDefaults) {
27
+ defaultConfig = { ...generateDefaultConfig(), ...defaultConfig }
28
+ }
29
+
25
30
  const args = parseArgs(_args, deepmerge({ all: true })({
26
31
  string: ['allow-env'],
27
32
  boolean: ['hotReload'],
@@ -0,0 +1,12 @@
1
+ 'use strict'
2
+
3
+ const fp = require('fastify-plugin')
4
+
5
+ async function setupClients (app, opts) {
6
+ const clientsConfig = opts
7
+ for (const { path, url } of clientsConfig) {
8
+ app.register(require(path), { url })
9
+ }
10
+ }
11
+
12
+ module.exports = fp(setupClients)
@@ -0,0 +1,29 @@
1
+ 'use strict'
2
+
3
+ const fp = require('fastify-plugin')
4
+
5
+ function originToRegexp (origin) {
6
+ if (typeof origin === 'object') {
7
+ if (origin.regexp) {
8
+ origin = new RegExp(origin.regexp)
9
+ }
10
+ }
11
+
12
+ return origin
13
+ }
14
+
15
+ async function setupClients (app, opts) {
16
+ const cors = opts
17
+
18
+ let origin = cors.origin
19
+ if (Array.isArray(origin)) {
20
+ origin = origin.map(originToRegexp)
21
+ } else {
22
+ origin = originToRegexp(origin)
23
+ }
24
+
25
+ cors.origin = origin
26
+ app.register(require('@fastify/cors'), cors)
27
+ }
28
+
29
+ module.exports = fp(setupClients)
@@ -0,0 +1,44 @@
1
+ 'use strict'
2
+
3
+ const { FileWatcher } = require('@platformatic/utils')
4
+ const fp = require('fastify-plugin')
5
+
6
+ async function setupFileWatcher (app, opts) {
7
+ // TODO: move params to opts
8
+
9
+ const configManager = app.platformatic.configManager
10
+ const config = configManager.current
11
+
12
+ const isRestartableApp = app.restarted !== undefined
13
+
14
+ // to run the plugin without restartable
15
+ /* c8 ignore next 1 */
16
+ const persistentRef = isRestartableApp ? app.persistentRef : app
17
+
18
+ let fileWatcher = persistentRef.fileWatcher
19
+ if (!fileWatcher) {
20
+ fileWatcher = new FileWatcher({
21
+ path: configManager.dirname,
22
+ allowToWatch: config.watch?.allow,
23
+ watchIgnore: config.watch?.ignore
24
+ })
25
+
26
+ fileWatcher.on('update', () => {
27
+ opts.onFilesUpdated(persistentRef)
28
+ })
29
+
30
+ app.log.debug('start watching files')
31
+ fileWatcher.startWatching()
32
+ }
33
+
34
+ app.decorate('fileWatcher', fileWatcher)
35
+
36
+ app.addHook('onClose', async () => {
37
+ if (!isRestartableApp || app.closingRestartable) {
38
+ app.fileWatcher.stopWatching()
39
+ app.log.debug('stop watching files')
40
+ }
41
+ })
42
+ }
43
+
44
+ module.exports = fp(setupFileWatcher)
@@ -0,0 +1,17 @@
1
+ 'use strict'
2
+
3
+ const underPressure = require('@fastify/under-pressure')
4
+ const fp = require('fastify-plugin')
5
+
6
+ async function setupClients (app, opts) {
7
+ const healthCheck = opts
8
+
9
+ app.register(underPressure, {
10
+ exposeStatusRoute: '/status',
11
+ healthCheckInterval: healthCheck.interval !== undefined ? healthCheck.interval : 5000,
12
+ ...healthCheck,
13
+ healthCheck: healthCheck.fn
14
+ })
15
+ }
16
+
17
+ module.exports = fp(setupClients)
@@ -0,0 +1,56 @@
1
+ 'use strict'
2
+
3
+ const { join, resolve } = require('path')
4
+ const { readFile } = require('fs/promises')
5
+
6
+ const sandbox = require('fastify-sandbox')
7
+ const fp = require('fastify-plugin')
8
+
9
+ const { getJSPluginPath, isFileAccessible } = require('../utils')
10
+
11
+ const wrapperPath = join(__dirname, 'sandbox-wrapper.js')
12
+
13
+ async function loadPlugins (app) {
14
+ const configManager = app.platformatic.configManager
15
+ const config = configManager.current
16
+
17
+ if (config.plugins.typescript) {
18
+ const workingDir = configManager.dirname
19
+ const tsConfigPath = join(workingDir, 'tsconfig.json')
20
+
21
+ const isTsConfigAccessible = await isFileAccessible(tsConfigPath)
22
+ if (!isTsConfigAccessible) {
23
+ throw new Error('Cannot load typescript plugin, tsconfig.json not found')
24
+ }
25
+
26
+ const tsConfig = JSON.parse(await readFile(tsConfigPath, 'utf8'))
27
+ const outDir = resolve(workingDir, tsConfig.compilerOptions.outDir)
28
+
29
+ config.plugins.paths = config.plugins.paths.map((plugin) => {
30
+ /* c8 ignore next 3 */
31
+ return typeof plugin === 'string'
32
+ ? getJSPluginPath(workingDir, plugin, outDir)
33
+ : { ...plugin, path: getJSPluginPath(workingDir, plugin.path, outDir) }
34
+ })
35
+ }
36
+
37
+ if (config.plugins.hotReload !== false) {
38
+ await app.register(sandbox, {
39
+ path: wrapperPath,
40
+ options: { paths: config.plugins.paths },
41
+ customizeGlobalThis (_globalThis) {
42
+ // Taken from https://github.com/nodejs/undici/blob/fa9fd9066569b6357acacffb806aa804b688c9d8/lib/global.js#L5
43
+ const globalDispatcher = Symbol.for('undici.globalDispatcher.1')
44
+ const dispatcher = globalThis[globalDispatcher]
45
+ /* istanbul ignore else */
46
+ if (dispatcher) {
47
+ _globalThis[globalDispatcher] = dispatcher
48
+ }
49
+ }
50
+ })
51
+ } else {
52
+ await app.register(require(wrapperPath), { paths: config.plugins.paths })
53
+ }
54
+ }
55
+
56
+ module.exports = fp(loadPlugins)
@@ -0,0 +1,46 @@
1
+ 'use strict'
2
+
3
+ const { isKeyEnabled } = require('@platformatic/utils')
4
+ const fp = require('fastify-plugin')
5
+
6
+ const compiler = require('../compile')
7
+
8
+ async function setupTsCompiler (app) {
9
+ // TODO: move params to opts
10
+
11
+ const configManager = app.platformatic.configManager
12
+ const config = configManager.current
13
+
14
+ const isRestartableApp = app.restarted !== undefined
15
+
16
+ // to run the plugin without restartable
17
+ /* c8 ignore next 1 */
18
+ const persistentRef = isRestartableApp ? app.persistentRef : app
19
+
20
+ const workingDir = configManager.dirname
21
+
22
+ if (isKeyEnabled('watch', config)) {
23
+ let tsCompilerWatcher = persistentRef.tsCompilerWatcher
24
+ if (!tsCompilerWatcher) {
25
+ /* c8 ignore next 5 */
26
+ const { child } = await compiler.compileWatch(workingDir, config)
27
+ app.log.debug('start watching typescript files')
28
+ tsCompilerWatcher = child
29
+ }
30
+ app.decorate('tsCompilerWatcher', tsCompilerWatcher)
31
+ } else {
32
+ await compiler.compile(workingDir, config)
33
+ }
34
+
35
+ app.addHook('onClose', async () => {
36
+ if (!isRestartableApp || app.closingRestartable) {
37
+ /* c8 ignore next 4 */
38
+ if (app.tsCompilerWatcher) {
39
+ app.tsCompilerWatcher.kill('SIGTERM')
40
+ app.log.debug('stop watching typescript files')
41
+ }
42
+ }
43
+ })
44
+ }
45
+
46
+ module.exports = fp(setupTsCompiler)
@@ -1,4 +1,5 @@
1
1
  'use strict'
2
+
2
3
  const path = require('path')
3
4
  const fastifyStatic = require('@fastify/static')
4
5
  const userAgentParser = require('ua-parser-js')
package/lib/schema.js CHANGED
@@ -134,7 +134,8 @@ const server = {
134
134
  type: 'integer'
135
135
  },
136
136
  keepAliveTimeout: {
137
- type: 'integer'
137
+ type: 'integer',
138
+ default: 5000
138
139
  },
139
140
  maxRequestsPerSocket: {
140
141
  type: 'integer'
@@ -313,6 +314,12 @@ const server = {
313
314
  }
314
315
  }
315
316
  ]
317
+ },
318
+ requestCert: {
319
+ type: 'boolean'
320
+ },
321
+ rejectUnauthorized: {
322
+ type: 'boolean'
316
323
  }
317
324
  },
318
325
  additionalProperties: false,