@platformatic/service 2.71.1-alpha.0 → 3.0.0-alpha.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/config.d.ts +1 -19
- package/eslint.config.js +4 -6
- package/index.d.ts +51 -47
- package/index.js +44 -199
- package/lib/application.js +57 -0
- package/lib/compile.js +1 -52
- package/lib/generator.js +154 -0
- package/lib/plugins/clients.js +9 -8
- package/lib/plugins/cors.js +5 -8
- package/lib/plugins/graphql.js +16 -14
- package/lib/plugins/health-check.js +6 -8
- package/lib/plugins/openapi.js +40 -31
- package/lib/plugins/plugins.js +15 -18
- package/lib/{root-endpoint/index.js → plugins/root.js} +9 -8
- package/lib/plugins/sandbox-wrapper.js +62 -55
- package/lib/plugins/typescript.js +10 -13
- package/lib/schema.js +1030 -132
- package/lib/stackable.js +180 -337
- package/lib/upgrade.js +6 -8
- package/lib/utils.js +39 -74
- package/lib/versions/0.16.0.js +14 -14
- package/lib/versions/{from-zero-twenty-eight-to-will-see.js → 0.28.0.js} +3 -5
- package/lib/versions/2.0.0.js +4 -6
- package/package.json +17 -22
- package/schema.json +3 -74
- package/tsconfig.json +16 -6
- package/.c8rc +0 -6
- package/help/compile.txt +0 -19
- package/help/create.txt +0 -11
- package/help/help.txt +0 -8
- package/help/schema.txt +0 -9
- package/help/start.txt +0 -23
- package/index.test-d.ts +0 -107
- package/lib/create.mjs +0 -85
- package/lib/gen-schema.js +0 -15
- package/lib/gen-types.mjs +0 -38
- package/lib/generator/README.md +0 -31
- package/lib/generator/service-generator.d.ts +0 -11
- package/lib/generator/service-generator.js +0 -126
- package/lib/openapi-schema-defs.js +0 -1108
- package/lib/plugins/metrics.js +0 -244
- package/lib/start.js +0 -190
- package/service.mjs +0 -71
- /package/{lib/root-endpoint/public → public}/images/dark_mode.svg +0 -0
- /package/{lib/root-endpoint/public → public}/images/favicon.ico +0 -0
- /package/{lib/root-endpoint/public → public}/images/light_mode.svg +0 -0
- /package/{lib/root-endpoint/public → public}/images/platformatic-logo-dark.svg +0 -0
- /package/{lib/root-endpoint/public → public}/images/platformatic-logo-light.svg +0 -0
- /package/{lib/root-endpoint/public → public}/images/triangle_dark.svg +0 -0
- /package/{lib/root-endpoint/public → public}/images/triangle_light.svg +0 -0
- /package/{lib/root-endpoint/public → public}/index.html +0 -0
package/lib/stackable.js
CHANGED
|
@@ -1,414 +1,239 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
this.
|
|
22
|
-
|
|
23
|
-
this.configManager = options.configManager
|
|
24
|
-
this.context = options.context ?? {}
|
|
25
|
-
this.context.stackable = this
|
|
26
|
-
|
|
27
|
-
this.serviceId = this.context.serviceId
|
|
28
|
-
this.context.worker ??= { count: 1, index: 0 }
|
|
29
|
-
this.workerId = this.context.worker.count > 1 ? this.context.worker.index : undefined
|
|
30
|
-
|
|
31
|
-
this.runtimeConfig = deepmerge(this.context.runtimeConfig ?? {}, workerData?.config ?? {})
|
|
32
|
-
|
|
33
|
-
this.customHealthCheck = null
|
|
34
|
-
|
|
35
|
-
this.configManager.on('error', err => {
|
|
36
|
-
/* c8 ignore next */
|
|
37
|
-
this.stackable.log({
|
|
38
|
-
message: 'error reloading the configuration' + err,
|
|
39
|
-
level: 'error'
|
|
40
|
-
})
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
this.#updateConfig()
|
|
44
|
-
|
|
45
|
-
// Setup globals
|
|
46
|
-
this.registerGlobals({
|
|
47
|
-
serviceId: this.serviceId,
|
|
48
|
-
workerId: this.workerId,
|
|
49
|
-
// Always use URL to avoid serialization problem in Windows
|
|
50
|
-
root: this.context.directory ? pathToFileURL(this.context.directory).toString() : undefined,
|
|
51
|
-
setOpenapiSchema: this.setOpenapiSchema.bind(this),
|
|
52
|
-
setGraphqlSchema: this.setGraphqlSchema.bind(this),
|
|
53
|
-
setConnectionString: this.setConnectionString.bind(this),
|
|
54
|
-
setBasePath: this.setBasePath.bind(this),
|
|
55
|
-
runtimeBasePath: this.runtimeConfig?.basePath ?? null,
|
|
56
|
-
invalidateHttpCache: this.#invalidateHttpCache.bind(this),
|
|
57
|
-
prometheus: { client, registry: this.metricsRegistry },
|
|
58
|
-
setCustomHealthCheck: this.setCustomHealthCheck.bind(this),
|
|
59
|
-
setCustomReadinessCheck: this.setCustomReadinessCheck.bind(this)
|
|
60
|
-
})
|
|
1
|
+
import { BaseStackable, cleanBasePath, ensureTrailingSlash, getServerUrl } from '@platformatic/basic'
|
|
2
|
+
import { telemetry } from '@platformatic/telemetry'
|
|
3
|
+
import { compile } from '@platformatic/ts-compiler'
|
|
4
|
+
import { buildPinoFormatters, buildPinoTimestamp, deepmerge, features, isKeyEnabled } from '@platformatic/utils'
|
|
5
|
+
import fastify from 'fastify'
|
|
6
|
+
import { printSchema } from 'graphql'
|
|
7
|
+
import { randomUUID } from 'node:crypto'
|
|
8
|
+
import { hostname } from 'node:os'
|
|
9
|
+
import pino from 'pino'
|
|
10
|
+
import { platformaticService } from './application.js'
|
|
11
|
+
import { setupRoot } from './plugins/root.js'
|
|
12
|
+
import { version } from './schema.js'
|
|
13
|
+
import { sanitizeHTTPSArgument } from './utils.js'
|
|
14
|
+
|
|
15
|
+
export class ServiceStackable extends BaseStackable {
|
|
16
|
+
#app
|
|
17
|
+
#basePath
|
|
18
|
+
|
|
19
|
+
constructor (root, config, context) {
|
|
20
|
+
super('service', version, root, config, context)
|
|
21
|
+
this.applicationFactory = this.context.applicationFactory ?? platformaticService
|
|
61
22
|
}
|
|
62
23
|
|
|
63
24
|
async init () {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (this.app === null) {
|
|
67
|
-
this.app = await this._init()
|
|
68
|
-
await this.#collectMetrics()
|
|
69
|
-
}
|
|
70
|
-
return this.app
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
async start (options = {}) {
|
|
74
|
-
await this.init()
|
|
25
|
+
await super.init()
|
|
75
26
|
|
|
76
|
-
if (
|
|
77
|
-
await this.app.ready()
|
|
27
|
+
if (this.#app) {
|
|
78
28
|
return
|
|
79
29
|
}
|
|
80
|
-
await this.app.start()
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
async stop () {
|
|
84
|
-
if (this.app === null) return
|
|
85
|
-
await this.app.close()
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
async build () {
|
|
89
|
-
this.#initLogger()
|
|
90
|
-
const typeScriptCompileOptions = extractTypeScriptCompileOptionsFromConfig(this.configManager.current)
|
|
91
|
-
const cwd = dirname(this.configManager.fullPath)
|
|
92
|
-
const compileOptions = {
|
|
93
|
-
...typeScriptCompileOptions,
|
|
94
|
-
cwd,
|
|
95
|
-
logger: this.logger
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
await compile(compileOptions)
|
|
99
|
-
}
|
|
100
30
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
31
|
+
const config = this.config
|
|
32
|
+
this.#basePath = ensureTrailingSlash(cleanBasePath(config.basePath ?? this.serviceId))
|
|
104
33
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
34
|
+
// Create the application
|
|
35
|
+
this.#app = fastify({
|
|
36
|
+
...this.serverConfig,
|
|
37
|
+
...this.fastifyOptions,
|
|
38
|
+
genReqId () {
|
|
39
|
+
return randomUUID()
|
|
40
|
+
}
|
|
41
|
+
})
|
|
110
42
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
43
|
+
// This must be done before loading the plugins, so they can inspect if the
|
|
44
|
+
// openTelemetry decorator exists and then configure accordingly.
|
|
45
|
+
if (isKeyEnabled('telemetry', config)) {
|
|
46
|
+
await this.#app.register(telemetry, config.telemetry)
|
|
47
|
+
}
|
|
114
48
|
|
|
115
|
-
|
|
49
|
+
this.#app.decorate('platformatic', { config: this.config })
|
|
116
50
|
|
|
117
|
-
|
|
118
|
-
config.server.logger = {}
|
|
51
|
+
await this.#app.register(this.applicationFactory, this)
|
|
119
52
|
|
|
120
|
-
|
|
121
|
-
|
|
53
|
+
if (Array.isArray(this.context.fastifyPlugins)) {
|
|
54
|
+
for (const plugin of this.context.fastifyPlugins) {
|
|
55
|
+
await this.#app.register(plugin)
|
|
122
56
|
}
|
|
123
57
|
}
|
|
124
58
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
return config
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
async getEnv () {
|
|
131
|
-
return this.configManager.env
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
getMeta () {
|
|
135
|
-
const config = this.configManager.current
|
|
136
|
-
|
|
137
|
-
return {
|
|
138
|
-
composer: {
|
|
139
|
-
prefix: config.basePath ?? this.basePath ?? this.context?.serviceId,
|
|
140
|
-
wantsAbsoluteUrls: false,
|
|
141
|
-
needsRootTrailingSlash: false,
|
|
142
|
-
tcp: !!this.app?.url,
|
|
143
|
-
url: this.app?.url
|
|
144
|
-
},
|
|
145
|
-
connectionStrings: [this.connectionString]
|
|
59
|
+
if (!this.#app.hasRoute({ url: '/', method: 'GET' }) && !this.#app.hasRoute({ url: '/*', method: 'GET' })) {
|
|
60
|
+
await this.#app.register(setupRoot)
|
|
146
61
|
}
|
|
147
62
|
}
|
|
148
63
|
|
|
149
|
-
async
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const enabled = config.watch?.enabled !== false && config.plugins !== undefined
|
|
64
|
+
async start (startOptions) {
|
|
65
|
+
// Compatibility with v2 service
|
|
66
|
+
const { listen } = startOptions ?? { listen: true }
|
|
153
67
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
allow: config.watch?.allow,
|
|
158
|
-
ignore: config.watch?.ignore
|
|
68
|
+
// Make this idempotent
|
|
69
|
+
if (this.url) {
|
|
70
|
+
return this.url
|
|
159
71
|
}
|
|
160
|
-
}
|
|
161
72
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
async getDispatchTarget () {
|
|
168
|
-
return this.getUrl() ?? (await this.getDispatchFunc())
|
|
169
|
-
}
|
|
73
|
+
// Create the application if needed
|
|
74
|
+
if (!this.#app) {
|
|
75
|
+
await this.init()
|
|
76
|
+
await this.#app.ready()
|
|
77
|
+
}
|
|
170
78
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
return this.app.swagger ? this.app.swagger() : null
|
|
175
|
-
}
|
|
79
|
+
if (listen) {
|
|
80
|
+
await this._listen()
|
|
81
|
+
}
|
|
176
82
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
await this.app.ready()
|
|
180
|
-
return this.app.graphql ? printSchema(this.app.graphql.schema) : null
|
|
83
|
+
await this._collectMetrics()
|
|
84
|
+
return this.url
|
|
181
85
|
}
|
|
182
86
|
|
|
183
|
-
|
|
184
|
-
this
|
|
87
|
+
async stop () {
|
|
88
|
+
return this.#app?.close()
|
|
185
89
|
}
|
|
186
90
|
|
|
187
|
-
async
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
91
|
+
async build () {
|
|
92
|
+
return compile({
|
|
93
|
+
tsConfig: this.config.plugins?.typescript?.tsConfig,
|
|
94
|
+
flags: this.config.plugins?.typescript?.flags,
|
|
95
|
+
cwd: this.root,
|
|
96
|
+
logger: this.logger
|
|
97
|
+
})
|
|
192
98
|
}
|
|
193
99
|
|
|
194
|
-
|
|
195
|
-
this.
|
|
196
|
-
}
|
|
100
|
+
async inject (injectParams, onInject) {
|
|
101
|
+
const response = await this.#app.inject(injectParams, onInject)
|
|
197
102
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
return true
|
|
103
|
+
if (onInject) {
|
|
104
|
+
return
|
|
201
105
|
}
|
|
202
|
-
return await this.customReadinessCheck()
|
|
203
|
-
}
|
|
204
106
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
async #collectMetrics () {
|
|
208
|
-
const metricsConfig = this.context.metricsConfig
|
|
209
|
-
|
|
210
|
-
if (metricsConfig !== false) {
|
|
211
|
-
await collectMetrics(
|
|
212
|
-
this.serviceId,
|
|
213
|
-
this.workerId,
|
|
214
|
-
{
|
|
215
|
-
defaultMetrics: true,
|
|
216
|
-
httpMetrics: true,
|
|
217
|
-
...metricsConfig
|
|
218
|
-
},
|
|
219
|
-
this.metricsRegistry
|
|
220
|
-
)
|
|
221
|
-
|
|
222
|
-
this.#setHttpCacheMetrics()
|
|
223
|
-
}
|
|
107
|
+
const { statusCode, statusMessage, headers, body } = response
|
|
108
|
+
return { statusCode, statusMessage, headers, body }
|
|
224
109
|
}
|
|
225
110
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
return format === 'json' ? await this.metricsRegistry.getMetricsAsJSON() : await this.metricsRegistry.metrics()
|
|
111
|
+
getApplication () {
|
|
112
|
+
return this.#app
|
|
229
113
|
}
|
|
230
114
|
|
|
231
|
-
async
|
|
115
|
+
async getDispatchFunc () {
|
|
232
116
|
await this.init()
|
|
233
|
-
|
|
234
|
-
const { statusCode, statusMessage, headers, body } = await this.app.inject(injectParams)
|
|
235
|
-
return { statusCode, statusMessage, headers, body }
|
|
117
|
+
return this.#app
|
|
236
118
|
}
|
|
237
119
|
|
|
238
|
-
async
|
|
239
|
-
await
|
|
120
|
+
async getConfig (includeMeta = false) {
|
|
121
|
+
let config = await super.getConfig(includeMeta)
|
|
122
|
+
const loggerInstance = this.serverConfig?.loggerInstance
|
|
240
123
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
124
|
+
if (loggerInstance) {
|
|
125
|
+
config = Object.assign({}, config)
|
|
126
|
+
const { loggerInstance: _, ...serverConfig } = this.serverConfig
|
|
127
|
+
config.server = { ...serverConfig, logger: { level: loggerInstance.level } }
|
|
128
|
+
}
|
|
245
129
|
|
|
246
|
-
|
|
130
|
+
return config
|
|
247
131
|
}
|
|
248
132
|
|
|
249
|
-
async
|
|
250
|
-
|
|
251
|
-
this.#updateConfig()
|
|
252
|
-
}
|
|
133
|
+
async getWatchConfig () {
|
|
134
|
+
const config = this.config
|
|
253
135
|
|
|
254
|
-
|
|
255
|
-
this.openapiSchema = schema
|
|
256
|
-
}
|
|
136
|
+
const enabled = config.watch?.enabled !== false && config.plugins !== undefined
|
|
257
137
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
138
|
+
if (!enabled) {
|
|
139
|
+
return { enabled, path: this.root }
|
|
140
|
+
}
|
|
261
141
|
|
|
262
|
-
|
|
263
|
-
|
|
142
|
+
return {
|
|
143
|
+
enabled,
|
|
144
|
+
path: this.root,
|
|
145
|
+
allow: config.watch?.allow,
|
|
146
|
+
ignore: config.watch?.ignore
|
|
147
|
+
}
|
|
264
148
|
}
|
|
265
149
|
|
|
266
|
-
|
|
267
|
-
|
|
150
|
+
getMeta () {
|
|
151
|
+
return {
|
|
152
|
+
composer: {
|
|
153
|
+
tcp: typeof this.url !== 'undefined',
|
|
154
|
+
url: this.url,
|
|
155
|
+
prefix: this.basePath ?? this.#basePath,
|
|
156
|
+
wantsAbsoluteUrls: false,
|
|
157
|
+
needsRootTrailingSlash: false
|
|
158
|
+
},
|
|
159
|
+
connectionStrings: [this.connectionString]
|
|
160
|
+
}
|
|
268
161
|
}
|
|
269
162
|
|
|
270
|
-
|
|
271
|
-
|
|
163
|
+
async getOpenapiSchema () {
|
|
164
|
+
await this.init()
|
|
165
|
+
await this.#app.ready()
|
|
166
|
+
return this.#app.swagger ? this.#app.swagger() : null
|
|
272
167
|
}
|
|
273
168
|
|
|
274
|
-
async
|
|
275
|
-
await
|
|
169
|
+
async getGraphqlSchema () {
|
|
170
|
+
await this.init()
|
|
171
|
+
await this.#app.ready()
|
|
172
|
+
return this.#app.graphql ? printSchema(this.#app.graphql.schema) : null
|
|
276
173
|
}
|
|
277
174
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
const cacheHitMetric = new client.Counter({
|
|
282
|
-
name: 'http_cache_hit_count',
|
|
283
|
-
help: 'Number of http cache hits',
|
|
284
|
-
registers: [registry]
|
|
285
|
-
})
|
|
286
|
-
|
|
287
|
-
const cacheMissMetric = new client.Counter({
|
|
288
|
-
name: 'http_cache_miss_count',
|
|
289
|
-
help: 'Number of http cache misses',
|
|
290
|
-
registers: [registry]
|
|
291
|
-
})
|
|
292
|
-
|
|
293
|
-
globalThis.platformatic.onHttpCacheHit = () => {
|
|
294
|
-
cacheHitMetric.inc()
|
|
295
|
-
}
|
|
296
|
-
globalThis.platformatic.onHttpCacheMiss = () => {
|
|
297
|
-
cacheMissMetric.inc()
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
const httpStatsFreeMetric = new client.Gauge({
|
|
301
|
-
name: 'http_client_stats_free',
|
|
302
|
-
help: 'Number of free (idle) http clients (sockets)',
|
|
303
|
-
labelNames: ['dispatcher_stats_url'],
|
|
304
|
-
registers: [registry]
|
|
305
|
-
})
|
|
306
|
-
globalThis.platformatic.onHttpStatsFree = (url, val) => {
|
|
307
|
-
httpStatsFreeMetric.set({ dispatcher_stats_url: url }, val)
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
const httpStatsConnectedMetric = new client.Gauge({
|
|
311
|
-
name: 'http_client_stats_connected',
|
|
312
|
-
help: 'Number of open socket connections',
|
|
313
|
-
labelNames: ['dispatcher_stats_url'],
|
|
314
|
-
registers: [registry]
|
|
315
|
-
})
|
|
316
|
-
globalThis.platformatic.onHttpStatsConnected = (url, val) => {
|
|
317
|
-
httpStatsConnectedMetric.set({ dispatcher_stats_url: url }, val)
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
const httpStatsPendingMetric = new client.Gauge({
|
|
321
|
-
name: 'http_client_stats_pending',
|
|
322
|
-
help: 'Number of pending requests across all clients',
|
|
323
|
-
labelNames: ['dispatcher_stats_url'],
|
|
324
|
-
registers: [registry]
|
|
325
|
-
})
|
|
326
|
-
globalThis.platformatic.onHttpStatsPending = (url, val) => {
|
|
327
|
-
httpStatsPendingMetric.set({ dispatcher_stats_url: url }, val)
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
const httpStatsQueuedMetric = new client.Gauge({
|
|
331
|
-
name: 'http_client_stats_queued',
|
|
332
|
-
help: 'Number of queued requests across all clients',
|
|
333
|
-
labelNames: ['dispatcher_stats_url'],
|
|
334
|
-
registers: [registry]
|
|
335
|
-
})
|
|
336
|
-
globalThis.platformatic.onHttpStatsQueued = (url, val) => {
|
|
337
|
-
httpStatsQueuedMetric.set({ dispatcher_stats_url: url }, val)
|
|
338
|
-
}
|
|
175
|
+
async updateContext (context) {
|
|
176
|
+
super.updateContext(context)
|
|
339
177
|
|
|
340
|
-
|
|
341
|
-
name: 'http_client_stats_running',
|
|
342
|
-
help: 'Number of currently active requests across all clients',
|
|
343
|
-
labelNames: ['dispatcher_stats_url'],
|
|
344
|
-
registers: [registry]
|
|
345
|
-
})
|
|
346
|
-
globalThis.platformatic.onHttpStatsRunning = (url, val) => {
|
|
347
|
-
httpStatsRunningMetric.set({ dispatcher_stats_url: url }, val)
|
|
348
|
-
}
|
|
178
|
+
this.context = { ...this.context, ...context }
|
|
349
179
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
help: 'Number of active, pending, or queued requests across all clients',
|
|
353
|
-
labelNames: ['dispatcher_stats_url'],
|
|
354
|
-
registers: [registry]
|
|
355
|
-
})
|
|
356
|
-
globalThis.platformatic.onHttpStatsSize = (url, val) => {
|
|
357
|
-
httpStatsSizeMetric.set({ dispatcher_stats_url: url }, val)
|
|
180
|
+
if (!this.context) {
|
|
181
|
+
return
|
|
358
182
|
}
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
#updateConfig () {
|
|
362
|
-
if (!this.context) return
|
|
363
183
|
|
|
364
|
-
const {
|
|
365
|
-
this.context
|
|
184
|
+
const { telemetryConfig, serverConfig, isEntrypoint, isProduction, logger } = this.context
|
|
366
185
|
|
|
367
|
-
const config = this.
|
|
186
|
+
const config = { ...this.config }
|
|
368
187
|
|
|
369
188
|
if (telemetryConfig) {
|
|
370
189
|
config.telemetry = telemetryConfig
|
|
371
190
|
}
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
191
|
+
|
|
192
|
+
const loggerInstance = logger ?? serverConfig?.loggerInstance ?? this.serverConfig?.loggerInstance
|
|
193
|
+
|
|
375
194
|
if (serverConfig) {
|
|
376
|
-
config.server = deepmerge(
|
|
195
|
+
config.server = deepmerge(this.serverConfig, serverConfig ?? {})
|
|
377
196
|
}
|
|
378
197
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
...config.metrics,
|
|
385
|
-
labels: { serviceId, ...labels }
|
|
198
|
+
config.server ??= {}
|
|
199
|
+
|
|
200
|
+
if (isProduction) {
|
|
201
|
+
if (config.plugins) {
|
|
202
|
+
config.plugins.typescript = false
|
|
386
203
|
}
|
|
204
|
+
config.watch = { enabled: false }
|
|
387
205
|
}
|
|
388
206
|
|
|
207
|
+
// Adjust server options
|
|
389
208
|
if (!isEntrypoint) {
|
|
390
|
-
config.server = config.server ?? {}
|
|
391
209
|
config.server.trustProxy = true
|
|
392
210
|
}
|
|
393
211
|
|
|
394
|
-
if (
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
212
|
+
if (config.server.https) {
|
|
213
|
+
config.server.https.key = await sanitizeHTTPSArgument(config.server.https.key)
|
|
214
|
+
config.server.https.cert = await sanitizeHTTPSArgument(config.server.https.cert)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Assign the logger instance if it exists
|
|
218
|
+
if (loggerInstance) {
|
|
219
|
+
config.server = { ...config.server }
|
|
220
|
+
config.server.loggerInstance = loggerInstance
|
|
221
|
+
delete config.server.logger
|
|
399
222
|
}
|
|
400
223
|
|
|
401
|
-
this.
|
|
224
|
+
this.serverConfig = config.server
|
|
225
|
+
this.config = config
|
|
402
226
|
}
|
|
403
227
|
|
|
404
|
-
|
|
405
|
-
if (this.
|
|
406
|
-
|
|
407
|
-
|
|
228
|
+
_initializeLogger () {
|
|
229
|
+
if (this.context?.logger) {
|
|
230
|
+
return this.context.logger
|
|
231
|
+
} else if (this.config.server?.loggerInstance) {
|
|
232
|
+
return this.config.server?.loggerInstance
|
|
408
233
|
}
|
|
409
234
|
|
|
410
|
-
this.
|
|
411
|
-
this.loggerConfig = deepmerge(this.context.loggerConfig ?? {}, this.
|
|
235
|
+
this.serverConfig ??= {}
|
|
236
|
+
this.loggerConfig = deepmerge(this.context.loggerConfig ?? {}, this.serverConfig?.logger ?? {})
|
|
412
237
|
|
|
413
238
|
const pinoOptions = {
|
|
414
239
|
...(this.loggerConfig ?? {}),
|
|
@@ -436,12 +261,30 @@ class ServiceStackable {
|
|
|
436
261
|
pinoOptions.timestamp = buildPinoTimestamp(this.loggerConfig?.timestamp)
|
|
437
262
|
}
|
|
438
263
|
|
|
439
|
-
|
|
264
|
+
const logger = pino(pinoOptions)
|
|
440
265
|
|
|
441
266
|
// Only one of logger and loggerInstance should be set
|
|
442
|
-
|
|
443
|
-
this.
|
|
267
|
+
this.serverConfig.loggerInstance = logger
|
|
268
|
+
delete this.serverConfig.logger
|
|
269
|
+
|
|
270
|
+
return logger
|
|
444
271
|
}
|
|
445
|
-
}
|
|
446
272
|
|
|
447
|
-
|
|
273
|
+
async _listen () {
|
|
274
|
+
const serverOptions = this.serverConfig
|
|
275
|
+
const listenOptions = { host: serverOptions?.hostname || '127.0.0.1', port: serverOptions?.port || 0 }
|
|
276
|
+
|
|
277
|
+
if (this.isProduction && features.node.reusePort) {
|
|
278
|
+
listenOptions.reusePort = true
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
await this.#app.listen(listenOptions)
|
|
282
|
+
this.url = getServerUrl(this.#app.server)
|
|
283
|
+
|
|
284
|
+
if (this.serverConfig.http2 || this.serverConfig.https?.key) {
|
|
285
|
+
this.url = this.url.replace('http://', 'https://')
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return this.url
|
|
289
|
+
}
|
|
290
|
+
}
|
package/lib/upgrade.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
module.exports = async function upgrade (config, version) {
|
|
6
|
-
const { semgrator } = await import('semgrator')
|
|
1
|
+
import { abstractLogger } from '@platformatic/utils'
|
|
2
|
+
import { resolve } from 'node:path'
|
|
3
|
+
import { semgrator } from 'semgrator'
|
|
7
4
|
|
|
5
|
+
export async function upgrade (logger, config, version) {
|
|
8
6
|
const iterator = semgrator({
|
|
9
7
|
version,
|
|
10
|
-
path:
|
|
8
|
+
path: resolve(import.meta.dirname, 'versions'),
|
|
11
9
|
input: config,
|
|
12
|
-
logger:
|
|
10
|
+
logger: logger?.child({ name: '@platformatic/service' }) ?? abstractLogger
|
|
13
11
|
})
|
|
14
12
|
|
|
15
13
|
let result
|