@platformatic/service 0.32.0 → 0.33.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 ADDED
@@ -0,0 +1,390 @@
1
+ /* eslint-disable */
2
+ /**
3
+ * This file was automatically generated by json-schema-to-typescript.
4
+ * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
5
+ * and run json-schema-to-typescript to regenerate this file.
6
+ */
7
+
8
+ export interface PlatformaticService {
9
+ server: {
10
+ hostname: string;
11
+ port: number | string;
12
+ pluginTimeout?: number;
13
+ healthCheck?:
14
+ | boolean
15
+ | {
16
+ enabled?: boolean;
17
+ interval?: number;
18
+ [k: string]: unknown;
19
+ };
20
+ ignoreTrailingSlash?: boolean;
21
+ ignoreDuplicateSlashes?: boolean;
22
+ connectionTimeout?: number;
23
+ keepAliveTimeout?: number;
24
+ maxRequestsPerSocket?: number;
25
+ forceCloseConnections?: boolean | string;
26
+ requestTimeout?: number;
27
+ bodyLimit?: number;
28
+ maxParamLength?: number;
29
+ disableRequestLogging?: boolean;
30
+ exposeHeadRoutes?: boolean;
31
+ logger?:
32
+ | boolean
33
+ | {
34
+ level?: string;
35
+ [k: string]: unknown;
36
+ };
37
+ serializerOpts?: {
38
+ schema?: {
39
+ [k: string]: unknown;
40
+ };
41
+ ajv?: {
42
+ [k: string]: unknown;
43
+ };
44
+ rounding?: "floor" | "ceil" | "round" | "trunc";
45
+ debugMode?: boolean;
46
+ mode?: "debug" | "standalone";
47
+ largeArraySize?: number | string;
48
+ largeArrayMechanism?: "default" | "json-stringify";
49
+ [k: string]: unknown;
50
+ };
51
+ caseSensitive?: boolean;
52
+ requestIdHeader?: string | false;
53
+ requestIdLogLabel?: string;
54
+ jsonShorthand?: boolean;
55
+ trustProxy?: boolean | string | string[] | number;
56
+ https?: {
57
+ key:
58
+ | string
59
+ | {
60
+ path?: string;
61
+ }
62
+ | (
63
+ | string
64
+ | {
65
+ path?: string;
66
+ }
67
+ )[];
68
+ cert:
69
+ | string
70
+ | {
71
+ path?: string;
72
+ }
73
+ | (
74
+ | string
75
+ | {
76
+ path?: string;
77
+ }
78
+ )[];
79
+ requestCert?: boolean;
80
+ rejectUnauthorized?: boolean;
81
+ };
82
+ cors?: {
83
+ origin?:
84
+ | boolean
85
+ | string
86
+ | (
87
+ | string
88
+ | {
89
+ regexp: string;
90
+ [k: string]: unknown;
91
+ }
92
+ )[]
93
+ | {
94
+ regexp: string;
95
+ [k: string]: unknown;
96
+ };
97
+ methods?: string[];
98
+ /**
99
+ * Comma separated string of allowed headers.
100
+ */
101
+ allowedHeaders?: string;
102
+ exposedHeaders?: string[] | string;
103
+ credentials?: boolean;
104
+ maxAge?: number;
105
+ preflightContinue?: boolean;
106
+ optionsSuccessStatus?: number;
107
+ preflight?: boolean;
108
+ strictPreflight?: boolean;
109
+ hideOptionsRoute?: boolean;
110
+ };
111
+ [k: string]: unknown;
112
+ };
113
+ plugins?: Plugins;
114
+ metrics?:
115
+ | boolean
116
+ | {
117
+ port?: number | string;
118
+ hostname?: string;
119
+ auth?: {
120
+ username: string;
121
+ password: string;
122
+ };
123
+ };
124
+ watch?:
125
+ | {
126
+ /**
127
+ * @minItems 1
128
+ */
129
+ allow?: [string, ...string[]];
130
+ ignore?: string[];
131
+ }
132
+ | boolean
133
+ | string;
134
+ $schema?: string;
135
+ service?: {
136
+ openapi?:
137
+ | {
138
+ info?: Info;
139
+ jsonSchemaDialect?: string;
140
+ servers?: Server[];
141
+ paths?: Paths;
142
+ webhooks?: {
143
+ [k: string]: PathItemOrReference;
144
+ };
145
+ components?: Components;
146
+ security?: SecurityRequirement[];
147
+ tags?: Tag[];
148
+ externalDocs?: ExternalDocumentation;
149
+ /**
150
+ * Base URL for the OpenAPI
151
+ */
152
+ prefix?: string;
153
+ }
154
+ | boolean;
155
+ graphql?:
156
+ | boolean
157
+ | {
158
+ graphiql?: boolean;
159
+ [k: string]: unknown;
160
+ };
161
+ };
162
+ clients?: {
163
+ serviceId?: string;
164
+ name?: string;
165
+ type?: "openapi" | "graphql";
166
+ path?: string;
167
+ schema?: string;
168
+ url?: string;
169
+ }[];
170
+ }
171
+ export interface Plugins {
172
+ paths: (
173
+ | string
174
+ | {
175
+ path?: string;
176
+ encapsulate?: boolean;
177
+ maxDepth?: number;
178
+ options?: {
179
+ [k: string]: unknown;
180
+ };
181
+ [k: string]: unknown;
182
+ }
183
+ )[];
184
+ stopTimeout?: number;
185
+ typescript?:
186
+ | {
187
+ enabled?: boolean | string;
188
+ tsConfig?: string;
189
+ outDir?: string;
190
+ flags?: string[];
191
+ [k: string]: unknown;
192
+ }
193
+ | boolean
194
+ | string;
195
+ }
196
+ export interface Info {
197
+ title: string;
198
+ summary?: string;
199
+ description?: string;
200
+ termsOfService?: string;
201
+ contact?: Contact;
202
+ license?: License;
203
+ version: string;
204
+ /**
205
+ * This interface was referenced by `Info`'s JSON-Schema definition
206
+ * via the `patternProperty` "^x-".
207
+ */
208
+ [k: string]: unknown;
209
+ }
210
+ export interface Contact {
211
+ name?: string;
212
+ url?: string;
213
+ email?: string;
214
+ /**
215
+ * This interface was referenced by `Contact`'s JSON-Schema definition
216
+ * via the `patternProperty` "^x-".
217
+ */
218
+ [k: string]: unknown;
219
+ }
220
+ export interface License {
221
+ name: string;
222
+ identifier?: string;
223
+ url?: string;
224
+ /**
225
+ * This interface was referenced by `License`'s JSON-Schema definition
226
+ * via the `patternProperty` "^x-".
227
+ */
228
+ [k: string]: unknown;
229
+ }
230
+ export interface Server {
231
+ url: string;
232
+ description?: string;
233
+ variables?: {
234
+ [k: string]: ServerVariable;
235
+ };
236
+ /**
237
+ * This interface was referenced by `Server`'s JSON-Schema definition
238
+ * via the `patternProperty` "^x-".
239
+ */
240
+ [k: string]: unknown;
241
+ }
242
+ export interface ServerVariable {
243
+ /**
244
+ * @minItems 1
245
+ */
246
+ enum?: [string, ...string[]];
247
+ default: string;
248
+ description?: string;
249
+ /**
250
+ * This interface was referenced by `ServerVariable`'s JSON-Schema definition
251
+ * via the `patternProperty` "^x-".
252
+ */
253
+ [k: string]: unknown;
254
+ }
255
+ export interface Paths {
256
+ [k: string]: PathItem;
257
+ }
258
+ /**
259
+ * This interface was referenced by `Paths`'s JSON-Schema definition
260
+ * via the `patternProperty` "^/".
261
+ */
262
+ export interface PathItem {
263
+ summary?: string;
264
+ description?: string;
265
+ servers?: Server[];
266
+ parameters?: ParameterOrReference[];
267
+ get?: Operation;
268
+ put?: Operation;
269
+ post?: Operation;
270
+ delete?: Operation;
271
+ options?: Operation;
272
+ head?: Operation;
273
+ patch?: Operation;
274
+ trace?: Operation;
275
+ /**
276
+ * This interface was referenced by `PathItem`'s JSON-Schema definition
277
+ * via the `patternProperty` "^x-".
278
+ */
279
+ [k: string]: unknown;
280
+ }
281
+ export interface ParameterOrReference {
282
+ [k: string]: unknown;
283
+ }
284
+ export interface Operation {
285
+ tags?: string[];
286
+ summary?: string;
287
+ description?: string;
288
+ externalDocs?: ExternalDocumentation;
289
+ operationId?: string;
290
+ parameters?: ParameterOrReference[];
291
+ requestBody?: RequestBodyOrReference;
292
+ responses?: Responses;
293
+ callbacks?: {
294
+ [k: string]: CallbacksOrReference;
295
+ };
296
+ deprecated?: boolean;
297
+ security?: SecurityRequirement[];
298
+ servers?: Server[];
299
+ /**
300
+ * This interface was referenced by `Operation`'s JSON-Schema definition
301
+ * via the `patternProperty` "^x-".
302
+ */
303
+ [k: string]: unknown;
304
+ }
305
+ export interface ExternalDocumentation {
306
+ description?: string;
307
+ url: string;
308
+ /**
309
+ * This interface was referenced by `ExternalDocumentation`'s JSON-Schema definition
310
+ * via the `patternProperty` "^x-".
311
+ */
312
+ [k: string]: unknown;
313
+ }
314
+ export interface RequestBodyOrReference {
315
+ [k: string]: unknown;
316
+ }
317
+ export interface Responses {
318
+ [k: string]: ResponseOrReference;
319
+ }
320
+ export interface ResponseOrReference {
321
+ [k: string]: unknown;
322
+ }
323
+ export interface CallbacksOrReference {
324
+ [k: string]: unknown;
325
+ }
326
+ export interface SecurityRequirement {
327
+ [k: string]: string[];
328
+ }
329
+ export interface PathItemOrReference {
330
+ [k: string]: unknown;
331
+ }
332
+ export interface Components {
333
+ schemas?: {
334
+ [k: string]: unknown;
335
+ };
336
+ responses?: {
337
+ [k: string]: ResponseOrReference;
338
+ };
339
+ parameters?: {
340
+ [k: string]: ParameterOrReference;
341
+ };
342
+ examples?: {
343
+ [k: string]: ExampleOrReference;
344
+ };
345
+ requestBodies?: {
346
+ [k: string]: RequestBodyOrReference;
347
+ };
348
+ headers?: {
349
+ [k: string]: HeaderOrReference;
350
+ };
351
+ securitySchemes?: {
352
+ [k: string]: SecuritySchemeOrReference;
353
+ };
354
+ links?: {
355
+ [k: string]: LinkOrReference;
356
+ };
357
+ callbacks?: {
358
+ [k: string]: CallbacksOrReference;
359
+ };
360
+ pathItems?: {
361
+ [k: string]: PathItemOrReference;
362
+ };
363
+ /**
364
+ * This interface was referenced by `Components`'s JSON-Schema definition
365
+ * via the `patternProperty` "^x-".
366
+ */
367
+ [k: string]: unknown;
368
+ }
369
+ export interface ExampleOrReference {
370
+ [k: string]: unknown;
371
+ }
372
+ export interface HeaderOrReference {
373
+ [k: string]: unknown;
374
+ }
375
+ export interface SecuritySchemeOrReference {
376
+ [k: string]: unknown;
377
+ }
378
+ export interface LinkOrReference {
379
+ [k: string]: unknown;
380
+ }
381
+ export interface Tag {
382
+ name: string;
383
+ description?: string;
384
+ externalDocs?: ExternalDocumentation;
385
+ /**
386
+ * This interface was referenced by `Tag`'s JSON-Schema definition
387
+ * via the `patternProperty` "^x-".
388
+ */
389
+ [k: string]: unknown;
390
+ }
package/index.d.ts CHANGED
@@ -4,11 +4,12 @@
4
4
  /// <reference types="@fastify/swagger" />
5
5
  import { FastifyInstance } from 'fastify'
6
6
  import ConfigManager from '@platformatic/config'
7
+ import { PlatformaticService } from './config'
7
8
 
8
9
  declare module '@platformatic/types' {
9
10
  interface PlatformaticApp {
10
- configManager: ConfigManager
11
- config: object
11
+ configManager: ConfigManager<PlatformaticService>
12
+ config: PlatformaticService
12
13
  }
13
14
  }
14
15
 
package/index.js CHANGED
@@ -11,6 +11,7 @@ const setupMetrics = require('./lib/plugins/metrics')
11
11
  const setupTsCompiler = require('./lib/plugins/typescript')
12
12
  const setupHealthCheck = require('./lib/plugins/health-check')
13
13
  const loadPlugins = require('./lib/plugins/plugins')
14
+ const { telemetry } = require('@platformatic/telemetry')
14
15
 
15
16
  const { schema } = require('./lib/schema')
16
17
  const { loadConfig } = require('./lib/load-config')
@@ -41,6 +42,10 @@ async function platformaticService (app, opts, toLoad = []) {
41
42
  await app.register(setupGraphQL, serviceConfig.graphql)
42
43
  }
43
44
 
45
+ if (config.telemetry) {
46
+ app.register(telemetry, config.telemetry)
47
+ }
48
+
44
49
  if (isKeyEnabled('clients', config)) {
45
50
  app.register(setupClients, config.clients)
46
51
  }
package/index.test-d.ts CHANGED
@@ -4,13 +4,15 @@ import { buildServer } from '.'
4
4
  import ConfigManager from '@platformatic/config'
5
5
  import { OpenAPI } from 'openapi-types'
6
6
  import type { MercuriusPlugin } from 'mercurius'
7
+ import { PlatformaticService } from './config'
7
8
 
8
9
  const server = await buildServer({
9
10
  })
10
11
 
11
12
  expectType<FastifyInstance>(server)
12
- expectType<ConfigManager>(server.platformatic.configManager)
13
- expectType<ConfigManager>(server.platformatic.configManager)
13
+ expectType<ConfigManager<PlatformaticService>>(server.platformatic.configManager)
14
+ expectType<PlatformaticService>(server.platformatic.configManager.current)
15
+ expectType<PlatformaticService>(server.platformatic.config)
14
16
  expectType<OpenAPI.Document>(server.swagger())
15
17
  expectType<MercuriusPlugin>(server.graphql)
16
18
  expectType<Promise<void>>(server.restart())
@@ -545,31 +545,11 @@ const $defs = {
545
545
  responses: {
546
546
  $comment: 'https://spec.openapis.org/oas/v3.1.0#responses-object',
547
547
  type: 'object',
548
- properties: {
549
- default: {
550
- $ref: '#/$defs/response-or-reference'
551
- }
552
- },
553
- patternProperties: {
554
- '^[1-5](?:[0-9]{2}|XX)$': {
555
- $ref: '#/$defs/response-or-reference'
556
- }
548
+ additionalProperties: {
549
+ $ref: '#/$defs/response-or-reference'
557
550
  },
558
551
  minProperties: 1,
559
- $ref: '#/$defs/specification-extensions',
560
-
561
- if: {
562
- $comment: 'either default, or at least one response code property must exist',
563
- type: 'object',
564
- patternProperties: {
565
- '^[1-5](?:[0-9]{2}|XX)$': false
566
- }
567
- },
568
- then: {
569
- required: [
570
- 'default'
571
- ]
572
- }
552
+ $ref: '#/$defs/specification-extensions'
573
553
  },
574
554
  response: {
575
555
  $comment: 'https://spec.openapis.org/oas/v3.1.0#response-object',
package/lib/schema.js CHANGED
@@ -5,6 +5,7 @@
5
5
  const pkg = require('../package.json')
6
6
  const version = 'v' + pkg.version
7
7
  const openApiDefs = require('./openapi-schema-defs')
8
+ const telemetry = require('@platformatic/telemetry').schema
8
9
 
9
10
  const cors = {
10
11
  type: 'object',
@@ -574,11 +575,13 @@ const clients = {
574
575
 
575
576
  const platformaticServiceSchema = {
576
577
  $id: `https://platformatic.dev/schemas/${version}/service`,
578
+ title: 'Platformatic Service',
577
579
  type: 'object',
578
580
  properties: {
579
581
  server,
580
582
  plugins,
581
583
  metrics,
584
+ telemetry,
582
585
  watch: {
583
586
  anyOf: [watch, {
584
587
  type: 'boolean'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/service",
3
- "version": "0.32.0",
3
+ "version": "0.33.1",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -20,6 +20,7 @@
20
20
  "@fastify/aws-lambda": "^3.2.0",
21
21
  "bindings": "^1.5.0",
22
22
  "c8": "^8.0.0",
23
+ "json-schema-to-typescript": "^13.0.2",
23
24
  "openapi-types": "^12.1.3",
24
25
  "self-cert": "^2.0.0",
25
26
  "snazzy": "^9.0.0",
@@ -64,11 +65,12 @@
64
65
  "pino-pretty": "^10.0.0",
65
66
  "rfdc": "^1.3.0",
66
67
  "ua-parser-js": "^1.0.35",
67
- "@platformatic/client": "0.32.0",
68
- "@platformatic/config": "0.32.0",
69
- "@platformatic/swagger-ui-theme": "0.32.0",
70
- "@platformatic/types": "0.32.0",
71
- "@platformatic/utils": "0.32.0"
68
+ "@platformatic/client": "0.33.1",
69
+ "@platformatic/config": "0.33.1",
70
+ "@platformatic/swagger-ui-theme": "0.33.1",
71
+ "@platformatic/types": "0.33.1",
72
+ "@platformatic/utils": "0.33.1",
73
+ "@platformatic/telemetry": "0.33.1"
72
74
  },
73
75
  "standard": {
74
76
  "ignore": [
@@ -84,6 +86,7 @@
84
86
  },
85
87
  "scripts": {
86
88
  "test": "pnpm run lint && c8 --100 tap test/*test.js test/*/*.test.mjs && tsd",
89
+ "build": "node lib/schema.js | json2ts > config.d.ts",
87
90
  "lint": "standard | snazzy && ts-standard | snazzy"
88
91
  }
89
92
  }
@@ -0,0 +1,87 @@
1
+ 'use strict'
2
+
3
+ const { buildConfig } = require('./helper')
4
+ const { test } = require('tap')
5
+ const { buildServer } = require('..')
6
+ const { request } = require('undici')
7
+ const { join } = require('path')
8
+ const os = require('os')
9
+ const { writeFile } = require('fs/promises')
10
+
11
+ test('should not configure telemetry if not configured', async ({ teardown, equal, pass, same }) => {
12
+ const app = await buildServer(buildConfig({
13
+ server: {
14
+ hostname: '127.0.0.1',
15
+ port: 0
16
+ }
17
+ }))
18
+
19
+ teardown(async () => {
20
+ await app.close()
21
+ })
22
+ await app.start()
23
+ equal(app.openTelemetry, undefined)
24
+ })
25
+
26
+ test('should setup telemetry if configured', async ({ teardown, equal, pass, same }) => {
27
+ const file = join(os.tmpdir(), `${process.pid}-1.js`)
28
+
29
+ await writeFile(file, `
30
+ module.exports = async function (app, options) {
31
+ app.get('/', () => options.message)
32
+ }`)
33
+
34
+ const app = await buildServer(buildConfig({
35
+ server: {
36
+ hostname: '127.0.0.1',
37
+ port: 0
38
+ },
39
+
40
+ telemetry: {
41
+ serviceName: 'test-service',
42
+ version: '1.0.0',
43
+ exporter: {
44
+ type: 'memory'
45
+ }
46
+ },
47
+ plugins: {
48
+ paths: [{
49
+ path: file,
50
+ options: {
51
+ message: 'hello'
52
+ }
53
+ }]
54
+ }
55
+ }))
56
+
57
+ teardown(async () => {
58
+ await app.close()
59
+ })
60
+ await app.start()
61
+
62
+ const res = await request(`${app.url}/`, {
63
+ method: 'GET',
64
+ headers: {
65
+ 'Content-Type': 'application/json'
66
+ },
67
+ body: JSON.stringify({
68
+ query: `
69
+ mutation {
70
+ savePage(input: { title: "Hello" }) {
71
+ id
72
+ title
73
+ }
74
+ }
75
+ `
76
+ })
77
+ })
78
+ equal(res.statusCode, 200, 'savePage status code')
79
+ const { exporter } = app.openTelemetry
80
+ const finishedSpans = exporter.getFinishedSpans()
81
+ equal(finishedSpans.length, 1)
82
+ const span = finishedSpans[0]
83
+ equal(span.name, 'GET /')
84
+ equal(span.attributes['req.method'], 'GET')
85
+ equal(span.attributes['req.url'], '/')
86
+ equal(span.attributes['reply.statusCode'], 200)
87
+ })