@platformatic/service 2.0.0-alpha.6 → 2.0.0-alpha.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/index.js CHANGED
@@ -80,9 +80,9 @@ async function platformaticService (app, opts) {
80
80
  }
81
81
 
82
82
  if (registerTsCompiler) {
83
- app.register(setupTsCompiler)
83
+ app.register(setupTsCompiler, { context: opts.context })
84
84
  }
85
- app.register(loadPlugins)
85
+ app.register(loadPlugins, { context: opts.context })
86
86
  }
87
87
 
88
88
  if (isKeyEnabled('cors', config.server)) {
@@ -168,7 +168,7 @@ async function buildStackable (
168
168
  }
169
169
 
170
170
  const stackable = new Stackable({
171
- init: () => buildServer(configManager.current, app),
171
+ init: () => buildServer(configManager.current, app, options.context),
172
172
  stackable: app,
173
173
  configManager,
174
174
  context: options.context,
@@ -7,14 +7,14 @@ const wrapper = require('./sandbox-wrapper')
7
7
 
8
8
  const { getJSPluginPath, isFileAccessible } = require('../utils')
9
9
 
10
- async function loadPlugins (app) {
10
+ async function loadPlugins (app, opts) {
11
11
  const configManager = app.platformatic.configManager
12
12
  const config = configManager.current
13
13
 
14
14
  let isOutDirAccessible = false
15
15
  let outDir = null
16
16
 
17
- const workingDir = configManager.dirname
17
+ const workingDir = opts?.context?.directory ?? configManager.dirname
18
18
  const tsConfigPath = configManager.current.plugins.typescript?.tsConfig || join(workingDir, 'tsconfig.json')
19
19
 
20
20
  // If the tsconfig.json file exists, then we need to adjust the plugin paths
@@ -34,12 +34,19 @@ async function loadPlugins (app) {
34
34
  isOutDirAccessible = await isFileAccessible(outDir)
35
35
  }
36
36
 
37
+ if (opts.context?.isProduction && !isOutDirAccessible) {
38
+ throw new Error(
39
+ `Cannot access directory '${outDir}'. Please run the 'build' command before running in production mode.`
40
+ )
41
+ }
42
+
37
43
  if (config.plugins.paths && isOutDirAccessible) {
38
- config.plugins.paths = config.plugins.paths.map((plugin) => {
44
+ config.plugins.paths = config.plugins.paths.map(plugin => {
39
45
  /* c8 ignore next 3 */
40
- const tmp = typeof plugin === 'string'
41
- ? getJSPluginPath(workingDir, plugin, outDir)
42
- : { ...plugin, path: getJSPluginPath(workingDir, plugin.path, outDir) }
46
+ const tmp =
47
+ typeof plugin === 'string'
48
+ ? getJSPluginPath(workingDir, plugin, outDir)
49
+ : { ...plugin, path: getJSPluginPath(workingDir, plugin.path, outDir) }
43
50
  return tmp
44
51
  })
45
52
  }
@@ -4,10 +4,10 @@ const fp = require('fastify-plugin')
4
4
  const compiler = require('@platformatic/ts-compiler')
5
5
  const { extractTypeScriptCompileOptionsFromConfig } = require('../compile')
6
6
 
7
- async function setupTsCompiler (app) {
7
+ async function setupTsCompiler (app, opts) {
8
8
  const configManager = app.platformatic.configManager
9
9
  const config = configManager.current
10
- const workingDir = configManager.dirname
10
+ const workingDir = opts?.context?.directory ?? configManager.dirname
11
11
 
12
12
  await compiler.compile({
13
13
  ...extractTypeScriptCompileOptionsFromConfig(config),
package/lib/schema.js CHANGED
@@ -5,7 +5,7 @@
5
5
  const pkg = require('../package.json')
6
6
  const openApiDefs = require('./openapi-schema-defs')
7
7
  const telemetry = require('@platformatic/telemetry').schema
8
- const { server, cors, watch } = require('@platformatic/utils').schemas
8
+ const { server, cors, watch } = require('@platformatic/utils').schemaComponents
9
9
 
10
10
  const plugins = {
11
11
  type: 'object',
@@ -15,23 +15,23 @@ const plugins = {
15
15
  items: {
16
16
  anyOf: [
17
17
  {
18
- type: 'string',
18
+ type: 'string'
19
19
  },
20
20
  {
21
21
  type: 'object',
22
22
  properties: {
23
23
  name: {
24
- type: 'string',
24
+ type: 'string'
25
25
  },
26
26
  options: {
27
27
  type: 'object',
28
- additionalProperties: true,
29
- },
28
+ additionalProperties: true
29
+ }
30
30
  },
31
- required: ['name'],
32
- },
33
- ],
34
- },
31
+ required: ['name']
32
+ }
33
+ ]
34
+ }
35
35
  },
36
36
  paths: {
37
37
  type: 'array',
@@ -39,63 +39,63 @@ const plugins = {
39
39
  anyOf: [
40
40
  {
41
41
  type: 'string',
42
- resolvePath: true,
42
+ resolvePath: true
43
43
  },
44
44
  {
45
45
  type: 'object',
46
46
  properties: {
47
47
  path: {
48
48
  type: 'string',
49
- resolvePath: true,
49
+ resolvePath: true
50
50
  },
51
51
  encapsulate: {
52
52
  type: 'boolean',
53
- default: true,
53
+ default: true
54
54
  },
55
55
  maxDepth: {
56
- type: 'integer',
56
+ type: 'integer'
57
57
  },
58
58
  autoHooks: {
59
- type: 'boolean',
59
+ type: 'boolean'
60
60
  },
61
61
  autoHooksPattern: {
62
- type: 'string',
62
+ type: 'string'
63
63
  },
64
64
  cascadeHooks: {
65
- type: 'boolean',
65
+ type: 'boolean'
66
66
  },
67
67
  overwriteHooks: {
68
- type: 'boolean',
68
+ type: 'boolean'
69
69
  },
70
70
  routeParams: {
71
- type: 'boolean',
71
+ type: 'boolean'
72
72
  },
73
73
  forceESM: {
74
- type: 'boolean',
74
+ type: 'boolean'
75
75
  },
76
76
  ignoreFilter: {
77
- type: 'string',
77
+ type: 'string'
78
78
  },
79
79
  matchFilter: {
80
- type: 'string',
80
+ type: 'string'
81
81
  },
82
82
  ignorePattern: {
83
- type: 'string',
83
+ type: 'string'
84
84
  },
85
85
  scriptPattern: {
86
- type: 'string',
86
+ type: 'string'
87
87
  },
88
88
  indexPattern: {
89
- type: 'string',
89
+ type: 'string'
90
90
  },
91
91
  options: {
92
92
  type: 'object',
93
- additionalProperties: true,
94
- },
95
- },
96
- },
97
- ],
98
- },
93
+ additionalProperties: true
94
+ }
95
+ }
96
+ }
97
+ ]
98
+ }
99
99
  },
100
100
  typescript: {
101
101
  anyOf: [
@@ -105,47 +105,47 @@ const plugins = {
105
105
  enabled: {
106
106
  anyOf: [
107
107
  {
108
- type: 'boolean',
108
+ type: 'boolean'
109
109
  },
110
110
  {
111
- type: 'string',
112
- },
113
- ],
111
+ type: 'string'
112
+ }
113
+ ]
114
114
  },
115
115
  tsConfig: {
116
116
  type: 'string',
117
- resolvePath: true,
117
+ resolvePath: true
118
118
  },
119
119
  outDir: {
120
120
  type: 'string',
121
- resolvePath: true,
121
+ resolvePath: true
122
122
  },
123
123
  flags: {
124
124
  type: 'array',
125
125
  items: {
126
- type: 'string',
127
- },
128
- },
129
- },
126
+ type: 'string'
127
+ }
128
+ }
129
+ }
130
130
  },
131
131
  {
132
- type: 'boolean',
132
+ type: 'boolean'
133
133
  },
134
134
  {
135
- type: 'string',
136
- },
137
- ],
138
- },
135
+ type: 'string'
136
+ }
137
+ ]
138
+ }
139
139
  },
140
140
  additionalProperties: false,
141
141
  anyOf: [
142
142
  {
143
- required: ['paths'],
143
+ required: ['paths']
144
144
  },
145
145
  {
146
- required: ['packages'],
147
- },
148
- ],
146
+ required: ['packages']
147
+ }
148
+ ]
149
149
  }
150
150
 
151
151
  const metrics = {
@@ -155,143 +155,143 @@ const metrics = {
155
155
  type: 'object',
156
156
  properties: {
157
157
  port: {
158
- anyOf: [{ type: 'integer' }, { type: 'string' }],
158
+ anyOf: [{ type: 'integer' }, { type: 'string' }]
159
159
  },
160
160
  hostname: { type: 'string' },
161
161
  endpoint: { type: 'string' },
162
162
  server: {
163
163
  type: 'string',
164
- enum: ['own', 'parent', 'hide'],
164
+ enum: ['own', 'parent', 'hide']
165
165
  },
166
166
  defaultMetrics: {
167
167
  type: 'object',
168
168
  properties: {
169
- enabled: { type: 'boolean' },
169
+ enabled: { type: 'boolean' }
170
170
  },
171
171
  required: ['enabled'],
172
- additionalProperties: false,
172
+ additionalProperties: false
173
173
  },
174
174
  auth: {
175
175
  type: 'object',
176
176
  properties: {
177
177
  username: { type: 'string' },
178
- password: { type: 'string' },
178
+ password: { type: 'string' }
179
179
  },
180
180
  additionalProperties: false,
181
- required: ['username', 'password'],
181
+ required: ['username', 'password']
182
182
  },
183
183
  labels: {
184
184
  type: 'object',
185
- additionalProperties: { type: 'string' },
186
- },
185
+ additionalProperties: { type: 'string' }
186
+ }
187
187
  },
188
- additionalProperties: false,
189
- },
190
- ],
188
+ additionalProperties: false
189
+ }
190
+ ]
191
191
  }
192
192
 
193
193
  const openApiBase = {
194
194
  type: 'object',
195
195
  properties: {
196
196
  info: {
197
- $ref: '#/$defs/info',
197
+ $ref: '#/$defs/info'
198
198
  },
199
199
  jsonSchemaDialect: {
200
200
  type: 'string',
201
201
 
202
- default: 'https://spec.openapis.org/oas/3.1/dialect/base',
202
+ default: 'https://spec.openapis.org/oas/3.1/dialect/base'
203
203
  },
204
204
  servers: {
205
205
  type: 'array',
206
206
  items: {
207
- $ref: '#/$defs/server',
207
+ $ref: '#/$defs/server'
208
208
  },
209
209
  default: [
210
210
  {
211
- url: '/',
212
- },
213
- ],
211
+ url: '/'
212
+ }
213
+ ]
214
214
  },
215
215
  paths: {
216
- $ref: '#/$defs/paths',
216
+ $ref: '#/$defs/paths'
217
217
  },
218
218
  webhooks: {
219
219
  type: 'object',
220
220
  additionalProperties: {
221
- $ref: '#/$defs/path-item-or-reference',
222
- },
221
+ $ref: '#/$defs/path-item-or-reference'
222
+ }
223
223
  },
224
224
  components: {
225
- $ref: '#/$defs/components',
225
+ $ref: '#/$defs/components'
226
226
  },
227
227
  security: {
228
228
  type: 'array',
229
229
  items: {
230
- $ref: '#/$defs/security-requirement',
231
- },
230
+ $ref: '#/$defs/security-requirement'
231
+ }
232
232
  },
233
233
  tags: {
234
234
  type: 'array',
235
235
  items: {
236
- $ref: '#/$defs/tag',
237
- },
236
+ $ref: '#/$defs/tag'
237
+ }
238
238
  },
239
239
  externalDocs: {
240
- $ref: '#/$defs/external-documentation',
240
+ $ref: '#/$defs/external-documentation'
241
241
  },
242
242
  swaggerPrefix: {
243
243
  type: 'string',
244
- description: 'Base URL for the OpenAPI Swagger Documentation',
244
+ description: 'Base URL for the OpenAPI Swagger Documentation'
245
245
  },
246
246
  path: {
247
247
  type: 'string',
248
248
  description: 'Path to an OpenAPI spec file',
249
- resolvePath: true,
250
- },
251
- },
249
+ resolvePath: true
250
+ }
251
+ }
252
252
  }
253
253
 
254
254
  const openapi = {
255
255
  anyOf: [
256
256
  {
257
257
  ...openApiBase,
258
- additionalProperties: false,
258
+ additionalProperties: false
259
259
  },
260
260
  {
261
- type: 'boolean',
262
- },
263
- ],
261
+ type: 'boolean'
262
+ }
263
+ ]
264
264
  }
265
265
 
266
266
  const graphqlBase = {
267
267
  type: 'object',
268
268
  properties: {
269
269
  graphiql: {
270
- type: 'boolean',
271
- },
270
+ type: 'boolean'
271
+ }
272
272
  },
273
- additionalProperties: false,
273
+ additionalProperties: false
274
274
  }
275
275
 
276
276
  const graphql = {
277
277
  anyOf: [
278
278
  {
279
279
  ...graphqlBase,
280
- additionalProperties: false,
280
+ additionalProperties: false
281
281
  },
282
282
  {
283
- type: 'boolean',
284
- },
285
- ],
283
+ type: 'boolean'
284
+ }
285
+ ]
286
286
  }
287
287
 
288
288
  const service = {
289
289
  type: 'object',
290
290
  properties: {
291
291
  openapi,
292
- graphql,
292
+ graphql
293
293
  },
294
- additionalProperties: false,
294
+ additionalProperties: false
295
295
  }
296
296
 
297
297
  const clients = {
@@ -300,32 +300,32 @@ const clients = {
300
300
  type: 'object',
301
301
  properties: {
302
302
  serviceId: {
303
- type: 'string',
303
+ type: 'string'
304
304
  },
305
305
  name: {
306
- type: 'string',
306
+ type: 'string'
307
307
  },
308
308
  type: {
309
309
  type: 'string',
310
- enum: ['openapi', 'graphql'],
310
+ enum: ['openapi', 'graphql']
311
311
  },
312
312
  path: {
313
313
  type: 'string',
314
- resolvePath: true,
314
+ resolvePath: true
315
315
  },
316
316
  schema: {
317
317
  type: 'string',
318
- resolvePath: true,
318
+ resolvePath: true
319
319
  },
320
320
  url: {
321
- type: 'string',
321
+ type: 'string'
322
322
  },
323
323
  fullResponse: { type: 'boolean' },
324
324
  fullRequest: { type: 'boolean' },
325
- validateResponse: { type: 'boolean' },
325
+ validateResponse: { type: 'boolean' }
326
326
  },
327
- additionalProperties: false,
328
- },
327
+ additionalProperties: false
328
+ }
329
329
  }
330
330
 
331
331
  const platformaticServiceSchema = {
@@ -342,24 +342,24 @@ const platformaticServiceSchema = {
342
342
  anyOf: [
343
343
  watch,
344
344
  {
345
- type: 'boolean',
345
+ type: 'boolean'
346
346
  },
347
347
  {
348
- type: 'string',
349
- },
350
- ],
348
+ type: 'string'
349
+ }
350
+ ]
351
351
  },
352
352
  $schema: {
353
- type: 'string',
353
+ type: 'string'
354
354
  },
355
355
  module: {
356
- type: 'string',
356
+ type: 'string'
357
357
  },
358
358
  service,
359
- clients,
359
+ clients
360
360
  },
361
361
  additionalProperties: false,
362
- $defs: openApiDefs,
362
+ $defs: openApiDefs
363
363
  }
364
364
 
365
365
  /*
@@ -368,52 +368,52 @@ const platformaticServiceSchema = {
368
368
  */
369
369
  Object.defineProperty(platformaticServiceSchema, 'schema', {
370
370
  enumerable: false,
371
- value: platformaticServiceSchema,
371
+ value: platformaticServiceSchema
372
372
  })
373
373
 
374
374
  Object.defineProperty(platformaticServiceSchema, 'server', {
375
375
  enumerable: false,
376
- value: server,
376
+ value: server
377
377
  })
378
378
 
379
379
  Object.defineProperty(platformaticServiceSchema, 'cors', {
380
380
  enumerable: false,
381
- value: cors,
381
+ value: cors
382
382
  })
383
383
 
384
384
  Object.defineProperty(platformaticServiceSchema, 'metrics', {
385
385
  enumerable: false,
386
- value: metrics,
386
+ value: metrics
387
387
  })
388
388
 
389
389
  Object.defineProperty(platformaticServiceSchema, 'plugins', {
390
390
  enumerable: false,
391
- value: plugins,
391
+ value: plugins
392
392
  })
393
393
 
394
394
  Object.defineProperty(platformaticServiceSchema, 'watch', {
395
395
  enumerable: false,
396
- value: watch,
396
+ value: watch
397
397
  })
398
398
 
399
399
  Object.defineProperty(platformaticServiceSchema, 'openApiDefs', {
400
400
  enumerable: false,
401
- value: openApiDefs,
401
+ value: openApiDefs
402
402
  })
403
403
 
404
404
  Object.defineProperty(platformaticServiceSchema, 'openApiBase', {
405
405
  enumerable: false,
406
- value: openApiBase,
406
+ value: openApiBase
407
407
  })
408
408
 
409
409
  Object.defineProperty(platformaticServiceSchema, 'graphqlBase', {
410
410
  enumerable: false,
411
- value: graphqlBase,
411
+ value: graphqlBase
412
412
  })
413
413
 
414
414
  Object.defineProperty(platformaticServiceSchema, 'clients', {
415
415
  enumerable: false,
416
- value: clients,
416
+ value: clients
417
417
  })
418
418
 
419
419
  /* end */
package/lib/stackable.js CHANGED
@@ -3,21 +3,26 @@
3
3
  const { dirname } = require('node:path')
4
4
  const { printSchema } = require('graphql')
5
5
  const pino = require('pino')
6
+ const httpMetrics = require('@platformatic/fastify-http-metrics')
7
+ const { extractTypeScriptCompileOptionsFromConfig } = require('./compile')
8
+ const { compile } = require('@platformatic/ts-compiler')
6
9
 
7
10
  class ServiceStackable {
8
11
  constructor (options) {
9
12
  this.app = null
10
13
  this._init = options.init
11
14
  this.stackable = options.stackable
15
+ this.metricsRegistry = null
12
16
 
13
17
  this.configManager = options.configManager
14
- this.context = options.context
18
+ this.context = options.context ?? {}
19
+ this.context.stackable = this
15
20
 
16
- this.configManager.on('error', (err) => {
21
+ this.configManager.on('error', err => {
17
22
  /* c8 ignore next */
18
23
  this.stackable.log({
19
24
  message: 'error reloading the configuration' + err,
20
- level: 'error',
25
+ level: 'error'
21
26
  })
22
27
  })
23
28
 
@@ -29,6 +34,10 @@ class ServiceStackable {
29
34
 
30
35
  if (this.app === null) {
31
36
  this.app = await this._init()
37
+
38
+ if (this.metricsRegistry) {
39
+ this.#setHttpMetrics()
40
+ }
32
41
  }
33
42
  return this.app
34
43
  }
@@ -48,6 +57,20 @@ class ServiceStackable {
48
57
  await this.app.close()
49
58
  }
50
59
 
60
+ async build () {
61
+ this.#initLogger()
62
+ const typeScriptCompileOptions = extractTypeScriptCompileOptionsFromConfig(this.configManager.current)
63
+ const cwd = dirname(this.configManager.fullPath)
64
+ const compileOptions = {
65
+ ...typeScriptCompileOptions,
66
+ cwd,
67
+ logger: this.configManager.current.server.logger,
68
+ }
69
+ if (!await compile(compileOptions)) {
70
+ throw new Error(`Failed to compile ${cwd}`)
71
+ }
72
+ }
73
+
51
74
  getUrl () {
52
75
  return this.app !== null ? this.app.url : null
53
76
  }
@@ -76,15 +99,13 @@ class ServiceStackable {
76
99
  async getWatchConfig () {
77
100
  const config = this.configManager.current
78
101
 
79
- const enabled =
80
- config.watch?.enabled !== false &&
81
- config.plugins !== undefined
102
+ const enabled = config.watch?.enabled !== false && config.plugins !== undefined
82
103
 
83
104
  return {
84
105
  enabled,
85
106
  path: dirname(this.configManager.fullPath),
86
107
  allow: config.watch?.allow,
87
- ignore: config.watch?.ignore,
108
+ ignore: config.watch?.ignore
88
109
  }
89
110
  }
90
111
 
@@ -105,15 +126,13 @@ class ServiceStackable {
105
126
  return this.app.graphql ? printSchema(this.app.graphql.schema) : null
106
127
  }
107
128
 
108
- async getMetrics ({ format }) {
109
- await this.init()
110
-
111
- const promRegister = this.app.metrics?.client?.register
112
- if (!promRegister) return null
129
+ async collectMetrics ({ registry }) {
130
+ this.metricsRegistry = registry
113
131
 
114
- return format === 'json'
115
- ? promRegister.getMetricsAsJSON()
116
- : promRegister.metrics()
132
+ return {
133
+ defaultMetrics: true,
134
+ httpMetrics: false
135
+ }
117
136
  }
118
137
 
119
138
  async inject (injectParams) {
@@ -139,18 +158,45 @@ class ServiceStackable {
139
158
  this.#updateConfig()
140
159
  }
141
160
 
161
+ #setHttpMetrics () {
162
+ this.app.register(httpMetrics, {
163
+ registry: this.metricsRegistry,
164
+ customLabels: ['telemetry_id'],
165
+ getCustomLabels: req => {
166
+ const telemetryId = req.headers['x-plt-telemetry-id'] ?? 'unknown'
167
+ return { telemetry_id: telemetryId }
168
+ }
169
+ })
170
+
171
+ this.app.register(httpMetrics, {
172
+ registry: this.metricsRegistry,
173
+ customLabels: ['telemetry_id'],
174
+ getCustomLabels: req => {
175
+ const telemetryId = req.headers['x-plt-telemetry-id'] ?? 'unknown'
176
+ return { telemetry_id: telemetryId }
177
+ },
178
+ histogram: {
179
+ name: 'http_request_all_duration_seconds',
180
+ help: 'request duration in seconds summary for all requests',
181
+ collect: function () {
182
+ process.nextTick(() => this.reset())
183
+ }
184
+ },
185
+ summary: {
186
+ name: 'http_request_all_summary_seconds',
187
+ help: 'request duration in seconds histogram for all requests',
188
+ collect: function () {
189
+ process.nextTick(() => this.reset())
190
+ }
191
+ }
192
+ })
193
+ }
194
+
142
195
  #updateConfig () {
143
196
  if (!this.context) return
144
197
 
145
- const {
146
- serviceId,
147
- telemetryConfig,
148
- metricsConfig,
149
- serverConfig,
150
- hasManagementApi,
151
- isEntrypoint,
152
- isProduction,
153
- } = this.context
198
+ const { serviceId, telemetryConfig, metricsConfig, serverConfig, hasManagementApi, isEntrypoint, isProduction } =
199
+ this.context
154
200
 
155
201
  const config = this.configManager.current
156
202
 
@@ -164,15 +210,13 @@ class ServiceStackable {
164
210
  config.server = serverConfig
165
211
  }
166
212
 
167
- if (
168
- (hasManagementApi && config.metrics === undefined) || config.metrics
169
- ) {
213
+ if ((hasManagementApi && config.metrics === undefined) || config.metrics) {
170
214
  const labels = config.metrics?.labels || {}
171
215
  config.metrics = {
172
216
  server: 'hide',
173
217
  defaultMetrics: { enabled: isEntrypoint },
174
218
  ...config.metrics,
175
- labels: { serviceId, ...labels },
219
+ labels: { serviceId, ...labels }
176
220
  }
177
221
  }
178
222
 
@@ -196,7 +240,7 @@ class ServiceStackable {
196
240
  const level = this.configManager.current.server.logger?.level
197
241
 
198
242
  const pinoOptions = {
199
- level: level ?? 'trace',
243
+ level: level ?? 'trace'
200
244
  }
201
245
 
202
246
  if (this.context?.serviceId) {
package/lib/start.js CHANGED
@@ -25,8 +25,8 @@ async function adjustHttpsKeyAndCert (arg) {
25
25
  return arg
26
26
  }
27
27
 
28
- async function createServer (context) {
29
- const { app, configManager } = context
28
+ async function createServer (serverContext) {
29
+ const { app, configManager, context } = serverContext
30
30
  const config = configManager.current
31
31
  let fastifyOptions = {}
32
32
 
@@ -42,14 +42,14 @@ async function createServer (context) {
42
42
  fastifyOptions.genReqId = function (req) { return randomUUID() }
43
43
  const root = fastify(fastifyOptions)
44
44
  root.decorate('platformatic', { configManager, config })
45
- await root.register(app)
45
+ await root.register(app, { context })
46
46
  if (!root.hasRoute({ url: '/', method: 'GET' })) {
47
47
  await root.register(require('./root-endpoint'))
48
48
  }
49
49
 
50
50
  root.decorate('url', {
51
51
  getter () {
52
- return context.url
52
+ return serverContext.url
53
53
  },
54
54
  })
55
55
 
@@ -65,7 +65,7 @@ async function buildConfigManager (options, app) {
65
65
  return configManager
66
66
  }
67
67
 
68
- async function buildServer (options, app) {
68
+ async function buildServer (options, app, context) {
69
69
  const configManager = await buildConfigManager(options, app)
70
70
  const config = configManager.current
71
71
 
@@ -84,17 +84,18 @@ async function buildServer (options, app) {
84
84
  }
85
85
  }
86
86
 
87
- const context = {
87
+ const serverContext = {
88
88
  app: typeof app === 'function' ? app : app.app,
89
89
  configManager,
90
+ context
90
91
  }
91
- const handler = await createServer(context)
92
+ const handler = await createServer(serverContext)
92
93
  handler.decorate('start', async () => {
93
- context.url = await handler.listen({
94
+ serverContext.url = await handler.listen({
94
95
  host: options.server?.hostname || '127.0.0.1',
95
96
  port: options.server?.port || 0,
96
97
  })
97
- return context.url
98
+ return serverContext.url
98
99
  })
99
100
  configManager.on('error', function (err) {
100
101
  /* c8 ignore next 1 */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/service",
3
- "version": "2.0.0-alpha.6",
3
+ "version": "2.0.0-alpha.8",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -47,6 +47,7 @@
47
47
  "@fastify/swagger": "^8.14.0",
48
48
  "@fastify/under-pressure": "^8.3.0",
49
49
  "@mercuriusjs/federation": "^3.0.0",
50
+ "@platformatic/fastify-http-metrics": "^0.1.0",
50
51
  "@scalar/fastify-api-reference": "^1.19.5",
51
52
  "@types/ws": "^8.5.10",
52
53
  "ajv": "^8.12.0",
@@ -76,13 +77,13 @@
76
77
  "rfdc": "^1.3.1",
77
78
  "semgrator": "^0.3.0",
78
79
  "undici": "^6.9.0",
79
- "@platformatic/client": "2.0.0-alpha.6",
80
- "@platformatic/config": "2.0.0-alpha.6",
81
- "@platformatic/scalar-theme": "2.0.0-alpha.6",
82
- "@platformatic/telemetry": "2.0.0-alpha.6",
83
- "@platformatic/generators": "2.0.0-alpha.6",
84
- "@platformatic/ts-compiler": "2.0.0-alpha.6",
85
- "@platformatic/utils": "2.0.0-alpha.6"
80
+ "@platformatic/client": "2.0.0-alpha.8",
81
+ "@platformatic/generators": "2.0.0-alpha.8",
82
+ "@platformatic/scalar-theme": "2.0.0-alpha.8",
83
+ "@platformatic/config": "2.0.0-alpha.8",
84
+ "@platformatic/telemetry": "2.0.0-alpha.8",
85
+ "@platformatic/ts-compiler": "2.0.0-alpha.8",
86
+ "@platformatic/utils": "2.0.0-alpha.8"
86
87
  },
87
88
  "scripts": {
88
89
  "test": "pnpm run lint && borp -T --concurrency=1 --timeout=180000 && tsd",
package/schema.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
- "$id": "https://schemas.platformatic.dev/@platformatic/service/2.0.0-alpha.6.json",
3
- "version": "2.0.0-alpha.6",
2
+ "$id": "https://schemas.platformatic.dev/@platformatic/service/2.0.0-alpha.8.json",
3
+ "version": "2.0.0-alpha.8",
4
4
  "title": "Platformatic Service",
5
5
  "type": "object",
6
6
  "properties": {