@platformatic/service 3.4.1 → 3.5.0

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 (54) hide show
  1. package/LICENSE +1 -1
  2. package/config.d.ts +450 -94
  3. package/eslint.config.js +4 -6
  4. package/index.d.ts +55 -48
  5. package/index.js +44 -179
  6. package/lib/application.js +35 -0
  7. package/lib/capability.js +281 -0
  8. package/lib/compile.js +2 -52
  9. package/lib/generator.js +426 -0
  10. package/lib/plugins/cors.js +5 -8
  11. package/lib/plugins/graphql.js +16 -14
  12. package/lib/plugins/health-check.js +6 -8
  13. package/lib/plugins/openapi.js +43 -32
  14. package/lib/plugins/plugins.js +6 -53
  15. package/lib/{root-endpoint/index.js → plugins/root.js} +9 -8
  16. package/lib/plugins/sandbox-wrapper.js +65 -63
  17. package/lib/schema.js +1075 -203
  18. package/lib/upgrade.js +6 -8
  19. package/lib/utils.js +30 -83
  20. package/lib/versions/0.16.0.js +14 -15
  21. package/lib/versions/{from-zero-twenty-eight-to-will-see.js → 0.28.0.js} +3 -6
  22. package/lib/versions/2.0.0.js +4 -7
  23. package/lib/versions/3.0.0.js +14 -0
  24. package/package.json +28 -36
  25. package/schema.json +1452 -165
  26. package/tsconfig.json +16 -6
  27. package/.c8rc +0 -6
  28. package/help/compile.txt +0 -19
  29. package/help/create.txt +0 -11
  30. package/help/help.txt +0 -8
  31. package/help/schema.txt +0 -9
  32. package/help/start.txt +0 -23
  33. package/index.test-d.ts +0 -107
  34. package/lib/create.mjs +0 -85
  35. package/lib/gen-schema.js +0 -15
  36. package/lib/gen-types.mjs +0 -38
  37. package/lib/generator/README.md +0 -31
  38. package/lib/generator/service-generator.d.ts +0 -11
  39. package/lib/generator/service-generator.js +0 -126
  40. package/lib/openapi-schema-defs.js +0 -1108
  41. package/lib/plugins/clients.js +0 -16
  42. package/lib/plugins/metrics.js +0 -244
  43. package/lib/plugins/typescript.js +0 -20
  44. package/lib/stackable.js +0 -306
  45. package/lib/start.js +0 -175
  46. package/service.mjs +0 -71
  47. /package/{lib/root-endpoint/public → public}/images/dark_mode.svg +0 -0
  48. /package/{lib/root-endpoint/public → public}/images/favicon.ico +0 -0
  49. /package/{lib/root-endpoint/public → public}/images/light_mode.svg +0 -0
  50. /package/{lib/root-endpoint/public → public}/images/platformatic-logo-dark.svg +0 -0
  51. /package/{lib/root-endpoint/public → public}/images/platformatic-logo-light.svg +0 -0
  52. /package/{lib/root-endpoint/public → public}/images/triangle_dark.svg +0 -0
  53. /package/{lib/root-endpoint/public → public}/images/triangle_light.svg +0 -0
  54. /package/{lib/root-endpoint/public → public}/index.html +0 -0
package/lib/compile.js CHANGED
@@ -1,56 +1,6 @@
1
- 'use strict'
2
-
3
- const { compile } = require('@platformatic/ts-compiler')
4
- const { loadConfig } = require('@platformatic/config')
5
- const pino = require('pino')
6
- const pretty = require('pino-pretty')
7
- const { dirname } = require('path')
8
-
9
- function buildCompileCmd (app) {
10
- return async function compileCmd (_args) {
11
- let fullPath = null
12
- let config = null
13
-
14
- try {
15
- const { configManager } = await loadConfig({}, _args, app, {
16
- watch: false,
17
- })
18
- await configManager.parseAndValidate()
19
- config = configManager.current
20
- fullPath = dirname(configManager.fullPath)
21
- /* c8 ignore next 4 */
22
- } catch (err) {
23
- console.error(err)
24
- process.exit(1)
25
- }
26
-
27
- const logger = pino(
28
- pretty({
29
- translateTime: 'SYS:HH:MM:ss',
30
- ignore: 'hostname,pid',
31
- })
32
- )
33
-
34
- const compileOptions = {
35
- ...extractTypeScriptCompileOptionsFromConfig(config),
36
- cwd: fullPath,
37
- logger,
38
- clean: _args.includes('--clean'),
39
- }
40
-
41
- if (!await compile(compileOptions)) {
42
- process.exit(1)
43
- }
44
- }
45
- }
46
-
47
- module.exports.buildCompileCmd = buildCompileCmd
48
-
49
- function extractTypeScriptCompileOptionsFromConfig (config) {
1
+ export function getTypescriptCompilationOptions (config) {
50
2
  return {
51
3
  tsConfig: config.plugins?.typescript?.tsConfig,
52
- flags: config.plugins?.typescript?.flags,
4
+ flags: config.plugins?.typescript?.flags
53
5
  }
54
6
  }
55
-
56
- module.exports.extractTypeScriptCompileOptionsFromConfig = extractTypeScriptCompileOptionsFromConfig
@@ -0,0 +1,426 @@
1
+ import { BaseGenerator } from '@platformatic/generators'
2
+ import { join } from 'node:path'
3
+
4
+ const JS_PLUGIN_WITH_TYPES_SUPPORT = `\
5
+ 'use strict'
6
+
7
+ /** @param {import('fastify').FastifyInstance} fastify */
8
+ module.exports = async function (fastify, opts) {
9
+ fastify.decorate('example', 'foobar')
10
+ }
11
+ `
12
+
13
+ const TS_PLUGIN_WITH_TYPES_SUPPORT = `\
14
+ import { type FastifyInstance, type FastifyPluginOptions } from 'fastify'
15
+
16
+ export default async function (fastify: FastifyInstance, opts: FastifyPluginOptions) {
17
+ fastify.decorate('example', 'foobar')
18
+ }
19
+ `
20
+
21
+ const JS_ROUTES_WITH_TYPES_SUPPORT = `\
22
+ 'use strict'
23
+
24
+ /** @param {import('fastify').FastifyInstance} fastify */
25
+ module.exports = async function (fastify, opts) {
26
+ fastify.get('/example', async (request, reply) => {
27
+ return { hello: fastify.example }
28
+ })
29
+ }
30
+ `
31
+
32
+ const TS_ROUTES_WITH_TYPES_SUPPORT = `\
33
+ import { type FastifyInstance, type FastifyPluginOptions } from 'fastify'
34
+
35
+ declare module 'fastify' {
36
+ interface FastifyInstance {
37
+ example: string
38
+ }
39
+ }
40
+
41
+ export default async function (fastify: FastifyInstance, opts: FastifyPluginOptions) {
42
+ fastify.get('/example', async (request, reply) => {
43
+ return { hello: fastify.example }
44
+ })
45
+ }
46
+ `
47
+
48
+ const TEST_ROUTES_JS = `\
49
+ 'use strict'
50
+
51
+ const test = require('node:test')
52
+ const assert = require('node:assert')
53
+ const { getServer } = require('../helper')
54
+
55
+ test('example', async (t) => {
56
+ const server = await getServer(t)
57
+ const res = await server.inject({
58
+ method: 'GET',
59
+ url: '/example'
60
+ })
61
+
62
+ assert.strictEqual(res.statusCode, 200)
63
+ assert.deepStrictEqual(res.json(), {
64
+ hello: 'foobar'
65
+ })
66
+ })
67
+ `
68
+
69
+ const TEST_PLUGIN_JS = `\
70
+ 'use strict'
71
+
72
+ const test = require('node:test')
73
+ const assert = require('node:assert')
74
+ const { getServer } = require('../helper')
75
+
76
+ test('example decorator', async (t) => {
77
+ const server = await getServer(t)
78
+
79
+ assert.strictEqual(server.example, 'foobar')
80
+ })
81
+ `
82
+
83
+ const TEST_ROUTES_TS = `\
84
+ import test from 'node:test'
85
+ import assert from 'node:assert'
86
+ import { getServer } from '../helper'
87
+
88
+ test('root', async (t) => {
89
+ const server = await getServer(t)
90
+ const res = await server.inject({
91
+ method: 'GET',
92
+ url: '/example'
93
+ })
94
+
95
+ assert.strictEqual(res.statusCode, 200)
96
+ assert.deepStrictEqual(res.json(), {
97
+ hello: 'foobar'
98
+ })
99
+ })
100
+ `
101
+
102
+ const TEST_PLUGIN_TS = `\
103
+ import test from 'node:test'
104
+ import assert from 'node:assert'
105
+ import { getServer } from '../helper'
106
+
107
+ test('example decorator', async (t) => {
108
+ const server = await getServer(t)
109
+
110
+ assert.strictEqual(server.example, 'foobar')
111
+ })
112
+ `
113
+
114
+ const TEST_HELPER_JS = `
115
+ 'use strict'
116
+
117
+ const { join } = require('node:path')
118
+ const { readFile } = require('node:fs/promises')
119
+ const { create } = require('$__MOD__')
120
+ $__REQUIRES__
121
+
122
+ async function getServer (t) {
123
+ $__PRE__
124
+ const config = JSON.parse(await readFile(join(__dirname, '..', 'watt.json'), 'utf8'))
125
+ // Add your config customizations here. For example you want to set
126
+ // all things that are set in the config file to read from an env variable
127
+ config.server ||= {}
128
+ config.server.logger ||= {}
129
+ config.watch = false
130
+ $__CONFIG__
131
+ // Add your config customizations here
132
+ const server = await create(join(__dirname, '../'),config)
133
+ await server.start({}) // sets .getApplication()
134
+ t.after(() => server.stop())
135
+ $__POST__
136
+ return server.getApplication()
137
+ }
138
+
139
+ module.exports.getServer = getServer
140
+ `
141
+
142
+ const TEST_HELPER_TS = `
143
+ import { join } from 'node:path'
144
+ import { readFile } from 'node:fs/promises'
145
+ import { create } from '$__MOD__'
146
+ import { test } from 'node:test'
147
+ $__REQUIRES__
148
+
149
+ type testfn = Parameters<typeof test>[0]
150
+ type TestContext = Parameters<Exclude<testfn, undefined>>[0]
151
+
152
+ export async function getServer (t: TestContext) {
153
+ $__PRE__
154
+ // We go up two folder because this files executes in the dist folder
155
+ const config = JSON.parse(await readFile(join(import.meta.dirname, "..", "watt.json"), 'utf8'))
156
+ // Add your config customizations here. For example you want to set
157
+ // all things that are set in the config file to read from an env variable
158
+ config.server ||= {}
159
+ config.server.logger ||= {}
160
+ config.server.logger.level = 'warn'
161
+ config.watch = false
162
+ $__CONFIG__
163
+ // Add your config customizations here
164
+ const server = await create(join(import.meta.dirname, "../"), config)
165
+ await server.start({}) // sets .getApplication()
166
+ t.after(() => server.stop())
167
+ $__POST__
168
+ return server.getApplication();
169
+ }
170
+ `
171
+
172
+ const TS_CONFIG = `
173
+ {
174
+ compilerOptions: {
175
+ module: 'commonjs',
176
+ esModuleInterop: true,
177
+ target: 'es2020',
178
+ sourceMap: true,
179
+ pretty: true,
180
+ noEmitOnError: true,
181
+ incremental: true,
182
+ strict: true,
183
+ outDir: 'dist',
184
+ skipLibCheck: true
185
+ },
186
+ watchOptions: {
187
+ watchFile: 'fixedPollingInterval',
188
+ watchDirectory: 'fixedPollingInterval',
189
+ fallbackPolling: 'dynamicPriority',
190
+ synchronousWatchDirectory: true,
191
+ excludeDirectories: ['**/node_modules', 'dist']
192
+ }
193
+ }
194
+ `
195
+
196
+ const PLT_ENVIRONMENT_TEMPLATE = `
197
+ import { type FastifyInstance } from 'fastify'
198
+ import { PlatformaticApplication, PlatformaticServiceConfig } from '@platformatic/service'
199
+
200
+ declare module 'fastify' {
201
+ interface FastifyInstance {
202
+ platformatic: PlatformaticApplication<PlatformaticServiceConfig>
203
+ }
204
+ }
205
+ `
206
+
207
+ const README = `
208
+ # Platformatic Service API
209
+
210
+ This is a generated [Platformatic Service](https://docs.platformatic.dev/docs/service/overview) application.
211
+
212
+ ## Requirements
213
+
214
+ Platformatic supports macOS, Linux and Windows ([WSL](https://docs.microsoft.com/windows/wsl/) recommended).
215
+ You'll need to have [Node.js](https://nodejs.org/) >= v18.8.0 or >= v20.6.0
216
+
217
+ ## Setup
218
+
219
+ Install dependencies:
220
+
221
+ \`\`\`bash
222
+ npm install
223
+ \`\`\`
224
+
225
+ ## Usage
226
+
227
+ Run the API with:
228
+
229
+ \`\`\`bash
230
+ npm start
231
+ \`\`\`
232
+
233
+ ### Explore
234
+ - ⚡ The Platformatic DB server is running at http://localhost:3042/
235
+ - 📔 View the REST API's Swagger documentation at http://localhost:3042/documentation/
236
+ - 🔍 Try out the GraphiQL web UI at http://localhost:3042/graphiql
237
+ `
238
+
239
+ export function applyTestHelperCustomizations (testHelper, mod, customizations) {
240
+ return testHelper
241
+ .replaceAll('$__MOD__', mod || '@platformatic/service')
242
+ .replaceAll('$__REQUIRES__', customizations.requires || '')
243
+ .replaceAll('$__PRE__', customizations.pre || '')
244
+ .replaceAll('$__CONFIG__', customizations.config || '')
245
+ .replaceAll('$__POST__', customizations.post || '')
246
+ }
247
+
248
+ export class Generator extends BaseGenerator {
249
+ constructor (opts = {}) {
250
+ super({
251
+ module: '@platformatic/service',
252
+ ...opts
253
+ })
254
+ }
255
+
256
+ getConfigFieldsDefinitions () {
257
+ if (this.config.isRuntimeContext) {
258
+ return []
259
+ }
260
+
261
+ return [
262
+ {
263
+ var: 'PLT_SERVER_HOSTNAME',
264
+ label: 'What is the hostname?',
265
+ default: '0.0.0.0',
266
+ type: 'string',
267
+ configValue: 'hostname'
268
+ },
269
+ {
270
+ var: 'PLT_SERVER_LOGGER_LEVEL',
271
+ label: 'What is the logger level?',
272
+ default: 'info',
273
+ type: 'string',
274
+ configValue: ''
275
+ },
276
+ {
277
+ label: 'Which port do you want to use?',
278
+ var: 'PORT',
279
+ default: 3042,
280
+ type: 'number',
281
+ configValue: 'port'
282
+ }
283
+ ]
284
+ }
285
+
286
+ getDefaultConfig () {
287
+ const defaultBaseConfig = super.getDefaultConfig()
288
+
289
+ return {
290
+ ...defaultBaseConfig,
291
+ plugin: true,
292
+ tests: true
293
+ }
294
+ }
295
+
296
+ async prepareQuestions () {
297
+ await super.prepareQuestions()
298
+
299
+ if (!this.config.skipTypescript) {
300
+ this.questions.push({
301
+ type: 'list',
302
+ name: 'typescript',
303
+ message: 'Do you want to use TypeScript?',
304
+ default: false,
305
+ choices: [
306
+ { name: 'yes', value: true },
307
+ { name: 'no', value: false }
308
+ ]
309
+ })
310
+ }
311
+ }
312
+
313
+ async _beforePrepare () {
314
+ if (this.config.isUpdating) {
315
+ return
316
+ }
317
+
318
+ if (!this.config.isRuntimeContext) {
319
+ this.addEnvVars(
320
+ {
321
+ PLT_SERVER_HOSTNAME: this.config.hostname,
322
+ PLT_SERVER_LOGGER_LEVEL: 'info',
323
+ PORT: 3042
324
+ },
325
+ { overwrite: false }
326
+ )
327
+ }
328
+
329
+ this.config.dependencies = {
330
+ '@platformatic/service': `^${this.platformaticVersion}`
331
+ }
332
+ }
333
+
334
+ async _afterPrepare () {
335
+ // if we are NOT updating, create env and files, otherwise leave as it is
336
+ if (this.config.isUpdating) {
337
+ return
338
+ }
339
+
340
+ if (this.config.typescript) {
341
+ this.addFile({ path: '', file: 'tsconfig.json', contents: TS_CONFIG })
342
+ }
343
+
344
+ this.addFile({ path: '', file: 'plt-env.d.ts', contents: PLT_ENVIRONMENT_TEMPLATE })
345
+ this.addFile({ path: '', file: 'README.md', contents: README })
346
+
347
+ if (this.config.plugin) {
348
+ // create plugin
349
+ this.files.push({
350
+ path: 'plugins',
351
+ file: this.config.typescript ? 'example.ts' : 'example.js',
352
+ contents: this.config.typescript ? TS_PLUGIN_WITH_TYPES_SUPPORT : JS_PLUGIN_WITH_TYPES_SUPPORT
353
+ })
354
+
355
+ this.files.push({
356
+ path: 'routes',
357
+ file: this.config.typescript ? 'root.ts' : 'root.js',
358
+ contents: this.config.typescript ? TS_ROUTES_WITH_TYPES_SUPPORT : JS_ROUTES_WITH_TYPES_SUPPORT
359
+ })
360
+
361
+ if (this.config.tests) {
362
+ if (this.config.typescript) {
363
+ this.files.push({
364
+ path: 'test',
365
+ file: 'helper.ts',
366
+ contents: applyTestHelperCustomizations(TEST_HELPER_TS, this.module, this.testHelperCustomizations ?? {})
367
+ })
368
+ this.files.push({
369
+ path: join('test', 'plugins'),
370
+ file: 'example.test.ts',
371
+ contents: TEST_PLUGIN_TS
372
+ })
373
+ this.files.push({
374
+ path: join('test', 'routes'),
375
+ file: 'root.test.ts',
376
+ contents: TEST_ROUTES_TS
377
+ })
378
+ } else {
379
+ this.files.push({
380
+ path: 'test',
381
+ file: 'helper.js',
382
+ contents: applyTestHelperCustomizations(TEST_HELPER_JS, this.module, this.testHelperCustomizations ?? {})
383
+ })
384
+ this.files.push({
385
+ path: join('test', 'plugins'),
386
+ file: 'example.test.js',
387
+ contents: TEST_PLUGIN_JS
388
+ })
389
+ this.files.push({
390
+ path: join('test', 'routes'),
391
+ file: 'root.test.js',
392
+ contents: TEST_ROUTES_JS
393
+ })
394
+ }
395
+ }
396
+ }
397
+ }
398
+
399
+ async _getConfigFileContents () {
400
+ const config = {
401
+ $schema: `https://schemas.platformatic.dev/@platformatic/service/${this.platformaticVersion}.json`,
402
+ service: {
403
+ openapi: true
404
+ },
405
+ watch: true
406
+ }
407
+
408
+ if (this.config.plugin) {
409
+ config.plugins = {
410
+ paths: [{ path: './plugins', encapsulate: false }, './routes']
411
+ }
412
+ }
413
+
414
+ if (!this.config.isRuntimeContext) {
415
+ config.server = {
416
+ hostname: '{PLT_SERVER_HOSTNAME}',
417
+ port: '{PORT}',
418
+ logger: {
419
+ level: '{PLT_SERVER_LOGGER_LEVEL}'
420
+ }
421
+ }
422
+ }
423
+
424
+ return config
425
+ }
426
+ }
@@ -1,6 +1,5 @@
1
- 'use strict'
2
-
3
- const fp = require('fastify-plugin')
1
+ import fastifyCors from '@fastify/cors'
2
+ import fp from 'fastify-plugin'
4
3
 
5
4
  function originToRegexp (origin) {
6
5
  if (typeof origin === 'object') {
@@ -12,9 +11,7 @@ function originToRegexp (origin) {
12
11
  return origin
13
12
  }
14
13
 
15
- async function setupClients (app, opts) {
16
- const cors = opts
17
-
14
+ async function setupCorsPlugin (app, cors) {
18
15
  let origin = cors.origin
19
16
  if (Array.isArray(origin)) {
20
17
  origin = origin.map(originToRegexp)
@@ -23,7 +20,7 @@ async function setupClients (app, opts) {
23
20
  }
24
21
 
25
22
  cors.origin = origin
26
- app.register(require('@fastify/cors'), cors)
23
+ app.register(fastifyCors, cors)
27
24
  }
28
25
 
29
- module.exports = fp(setupClients)
26
+ export const setupCors = fp(setupCorsPlugin)
@@ -1,24 +1,26 @@
1
- 'use strict'
2
-
3
- const mercurius = require('mercurius')
4
- const deepmerge = require('@fastify/deepmerge')({ all: true })
5
- const fp = require('fastify-plugin')
1
+ import { deepmerge } from '@platformatic/foundation'
2
+ import fp from 'fastify-plugin'
3
+ import mercurius from 'mercurius'
6
4
 
7
5
  // For some unknown reason, c8 is not detecting any of this
8
6
  // despite being covered by test/graphql.test.js
9
7
  /* c8 ignore next 12 */
10
- async function setupGraphQL (app, opts) {
11
- if (typeof opts !== 'object') {
12
- opts = {}
8
+ async function setupGraphQLPlugin (app, options) {
9
+ if (typeof options !== 'object') {
10
+ options = {}
13
11
  }
14
- const graphqlOptions = deepmerge({
15
- graphiql: true,
16
- additionalRouteOptions: {
17
- schema: { hide: true },
12
+
13
+ const graphqlOptions = deepmerge(
14
+ {
15
+ graphiql: true,
16
+ additionalRouteOptions: {
17
+ schema: { hide: true }
18
+ }
18
19
  },
19
- }, opts)
20
+ options
21
+ )
20
22
 
21
23
  app.register(mercurius, graphqlOptions)
22
24
  }
23
25
 
24
- module.exports = fp(setupGraphQL)
26
+ export const setupGraphQL = fp(setupGraphQLPlugin)
@@ -1,17 +1,15 @@
1
- 'use strict'
1
+ import underPressure from '@fastify/under-pressure'
2
+ import fp from 'fastify-plugin'
2
3
 
3
- const underPressure = require('@fastify/under-pressure')
4
- const fp = require('fastify-plugin')
5
-
6
- async function setupClients (app, opts) {
7
- const healthCheck = opts
4
+ async function setupHealthCheckPlugin (app, options) {
5
+ const healthCheck = options
8
6
 
9
7
  app.register(underPressure, {
10
8
  exposeStatusRoute: '/status',
11
9
  healthCheckInterval: healthCheck.interval !== undefined ? healthCheck.interval : 5000,
12
10
  ...healthCheck,
13
- healthCheck: healthCheck.fn,
11
+ healthCheck: healthCheck.fn
14
12
  })
15
13
  }
16
14
 
17
- module.exports = fp(setupClients)
15
+ export const setupHealthCheck = fp(setupHealthCheckPlugin)
@@ -1,70 +1,81 @@
1
- 'use strict'
2
-
3
- const Swagger = require('@fastify/swagger')
4
- const ScalarApiReference = require('@scalar/fastify-api-reference')
5
- const deepmerge = require('@fastify/deepmerge')({ all: true })
6
- const fp = require('fastify-plugin')
1
+ import Swagger from '@fastify/swagger'
2
+ import { deepmerge } from '@platformatic/foundation'
3
+ import fp from 'fastify-plugin'
7
4
 
8
5
  // For some unknown reason, c8 is not detecting any of this
9
6
  // pf
10
7
  // despite being covered by test/routes.test.js
11
8
  /* c8 ignore next 33 */
12
- async function setupOpenAPI (app, opts) {
13
- const { openapi } = opts
14
- const openapiConfig = deepmerge({
15
- exposeRoute: true,
16
- info: {
17
- title: 'Platformatic',
18
- description: 'This is a service built on top of Platformatic',
19
- version: '1.0.0',
9
+ async function setupOpenAPIPlugin (app, options) {
10
+ const { openapi } = options
11
+ const openapiConfig = deepmerge(
12
+ {
13
+ exposeRoute: true,
14
+ info: {
15
+ title: 'Platformatic',
16
+ description: 'This is a service built on top of Platformatic',
17
+ version: '1.0.0'
18
+ },
19
+ servers: [{ url: globalThis.platformatic?.runtimeBasePath ?? '/' }]
20
20
  },
21
- }, typeof openapi === 'object' ? openapi : {})
21
+ typeof openapi === 'object' ? openapi : {}
22
+ )
22
23
  app.log.trace({ openapi: openapiConfig })
23
24
  const swaggerOptions = {
24
25
  exposeRoute: openapiConfig.exposeRoute,
25
26
  openapi: {
26
- ...openapiConfig,
27
+ ...openapiConfig
27
28
  },
28
29
  refResolver: {
29
30
  buildLocalReference (json, baseUri, fragment, i) {
30
31
  // TODO figure out if we need def-${i}
31
32
  /* istanbul ignore next */
32
33
  return json.$id || `def-${i}`
33
- },
34
- },
34
+ }
35
+ }
35
36
  }
36
37
 
37
38
  if (openapi.path) {
38
39
  swaggerOptions.mode = 'static'
39
40
  swaggerOptions.specification = {
40
- path: openapi.path,
41
+ path: openapi.path
41
42
  }
42
43
  }
43
44
 
44
45
  await app.register(Swagger, swaggerOptions)
45
46
 
46
47
  const { default: scalarTheme } = await import('@platformatic/scalar-theme')
48
+ const { default: scalarApiReference } = await import('@scalar/fastify-api-reference')
49
+
47
50
  const routePrefix = openapi.swaggerPrefix || '/documentation'
48
51
 
49
52
  /** Serve spec file in yaml and json */
50
- app.get(`${routePrefix}/json`, {
51
- schema: { hide: true },
52
- logLevel: 'warn',
53
- }, async () => app.swagger())
54
- app.get(`${routePrefix}/yaml`, {
55
- schema: { hide: true },
56
- logLevel: 'warn',
57
- }, async () => app.swagger({ yaml: true }))
53
+ app.get(
54
+ `${routePrefix}/json`,
55
+ {
56
+ schema: { hide: true },
57
+ logLevel: 'warn'
58
+ },
59
+ async () => app.swagger()
60
+ )
61
+ app.get(
62
+ `${routePrefix}/yaml`,
63
+ {
64
+ schema: { hide: true },
65
+ logLevel: 'warn'
66
+ },
67
+ async () => app.swagger({ yaml: true })
68
+ )
58
69
 
59
- app.register(ScalarApiReference, {
60
- ...opts,
70
+ app.register(scalarApiReference, {
71
+ ...options,
61
72
  ...openapi,
62
73
  routePrefix,
63
74
  publicPath: './',
64
75
  configuration: {
65
- customCss: scalarTheme.theme,
66
- },
76
+ customCss: scalarTheme.theme
77
+ }
67
78
  })
68
79
  }
69
80
 
70
- module.exports = fp(setupOpenAPI)
81
+ export const setupOpenAPI = fp(setupOpenAPIPlugin)