@platformatic/service 2.74.3 → 3.0.0-alpha.2
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 +2 -30
- package/eslint.config.js +4 -6
- package/index.d.ts +55 -47
- package/index.js +44 -199
- package/lib/application.js +35 -0
- package/lib/compile.js +1 -52
- package/lib/generator.js +424 -0
- 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 +6 -53
- package/lib/{root-endpoint/index.js → plugins/root.js} +9 -8
- package/lib/plugins/sandbox-wrapper.js +62 -55
- package/lib/schema.js +1028 -203
- package/lib/stackable.js +171 -338
- package/lib/upgrade.js +6 -8
- package/lib/utils.js +30 -93
- package/lib/versions/0.16.0.js +14 -15
- package/lib/versions/{from-zero-twenty-eight-to-will-see.js → 0.28.0.js} +3 -6
- package/lib/versions/2.0.0.js +4 -7
- package/lib/versions/3.0.0.js +14 -0
- package/package.json +18 -25
- package/schema.json +10 -155
- 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/clients.js +0 -16
- package/lib/plugins/metrics.js +0 -244
- package/lib/plugins/typescript.js +0 -20
- 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/generator.js
ADDED
|
@@ -0,0 +1,424 @@
|
|
|
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 { buildServer } = 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 buildServer(config)
|
|
133
|
+
t.after(() => server.close())
|
|
134
|
+
$__POST__
|
|
135
|
+
return server
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
module.exports.getServer = getServer
|
|
139
|
+
`
|
|
140
|
+
|
|
141
|
+
const TEST_HELPER_TS = `
|
|
142
|
+
import { join } from 'node:path'
|
|
143
|
+
import { readFile } from 'node:fs/promises'
|
|
144
|
+
import { buildServer } from '$__MOD__'
|
|
145
|
+
import { test } from 'node:test'
|
|
146
|
+
$__REQUIRES__
|
|
147
|
+
|
|
148
|
+
type testfn = Parameters<typeof test>[0]
|
|
149
|
+
type TestContext = Parameters<Exclude<testfn, undefined>>[0]
|
|
150
|
+
|
|
151
|
+
export async function getServer (t: TestContext) {
|
|
152
|
+
$__PRE__
|
|
153
|
+
// We go up two folder because this files executes in the dist folder
|
|
154
|
+
const config = JSON.parse(await readFile(join(__dirname, '..', '..', 'watt.json'), 'utf8'))
|
|
155
|
+
// Add your config customizations here. For example you want to set
|
|
156
|
+
// all things that are set in the config file to read from an env variable
|
|
157
|
+
config.server ||= {}
|
|
158
|
+
config.server.logger ||= {}
|
|
159
|
+
config.server.logger.level = 'warn'
|
|
160
|
+
config.watch = false
|
|
161
|
+
$__CONFIG__
|
|
162
|
+
// Add your config customizations here
|
|
163
|
+
const server = await buildServer(config)
|
|
164
|
+
t.after(() => server.close())
|
|
165
|
+
$__POST__
|
|
166
|
+
return server
|
|
167
|
+
}
|
|
168
|
+
`
|
|
169
|
+
|
|
170
|
+
const TS_CONFIG = `
|
|
171
|
+
{
|
|
172
|
+
compilerOptions: {
|
|
173
|
+
module: 'commonjs',
|
|
174
|
+
esModuleInterop: true,
|
|
175
|
+
target: 'es2020',
|
|
176
|
+
sourceMap: true,
|
|
177
|
+
pretty: true,
|
|
178
|
+
noEmitOnError: true,
|
|
179
|
+
incremental: true,
|
|
180
|
+
strict: true,
|
|
181
|
+
outDir: 'dist',
|
|
182
|
+
skipLibCheck: true
|
|
183
|
+
},
|
|
184
|
+
watchOptions: {
|
|
185
|
+
watchFile: 'fixedPollingInterval',
|
|
186
|
+
watchDirectory: 'fixedPollingInterval',
|
|
187
|
+
fallbackPolling: 'dynamicPriority',
|
|
188
|
+
synchronousWatchDirectory: true,
|
|
189
|
+
excludeDirectories: ['**/node_modules', 'dist']
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
`
|
|
193
|
+
|
|
194
|
+
const PLT_ENVIRONMENT_TEMPLATE = `
|
|
195
|
+
import { type FastifyInstance } from 'fastify'
|
|
196
|
+
import { PlatformaticApplication, PlatformaticServiceConfig } from '@platformatic/service'
|
|
197
|
+
|
|
198
|
+
declare module 'fastify' {
|
|
199
|
+
interface FastifyInstance {
|
|
200
|
+
platformatic: PlatformaticApplication<PlatformaticServiceConfig>
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
`
|
|
204
|
+
|
|
205
|
+
const README = `
|
|
206
|
+
# Platformatic Service API
|
|
207
|
+
|
|
208
|
+
This is a generated [Platformatic Service](https://docs.platformatic.dev/docs/service/overview) application.
|
|
209
|
+
|
|
210
|
+
## Requirements
|
|
211
|
+
|
|
212
|
+
Platformatic supports macOS, Linux and Windows ([WSL](https://docs.microsoft.com/windows/wsl/) recommended).
|
|
213
|
+
You'll need to have [Node.js](https://nodejs.org/) >= v18.8.0 or >= v20.6.0
|
|
214
|
+
|
|
215
|
+
## Setup
|
|
216
|
+
|
|
217
|
+
Install dependencies:
|
|
218
|
+
|
|
219
|
+
\`\`\`bash
|
|
220
|
+
npm install
|
|
221
|
+
\`\`\`
|
|
222
|
+
|
|
223
|
+
## Usage
|
|
224
|
+
|
|
225
|
+
Run the API with:
|
|
226
|
+
|
|
227
|
+
\`\`\`bash
|
|
228
|
+
npm start
|
|
229
|
+
\`\`\`
|
|
230
|
+
|
|
231
|
+
### Explore
|
|
232
|
+
- ⚡ The Platformatic DB server is running at http://localhost:3042/
|
|
233
|
+
- 📔 View the REST API's Swagger documentation at http://localhost:3042/documentation/
|
|
234
|
+
- 🔍 Try out the GraphiQL web UI at http://localhost:3042/graphiql
|
|
235
|
+
`
|
|
236
|
+
|
|
237
|
+
export function applyTestHelperCustomizations (testHelper, mod, customizations) {
|
|
238
|
+
return testHelper
|
|
239
|
+
.replaceAll('$__MOD__', mod || '@platformatic/service')
|
|
240
|
+
.replaceAll('$__REQUIRES__', customizations.requires || '')
|
|
241
|
+
.replaceAll('$__PRE__', customizations.pre || '')
|
|
242
|
+
.replaceAll('$__CONFIG__', customizations.config || '')
|
|
243
|
+
.replaceAll('$__POST__', customizations.post || '')
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export class Generator extends BaseGenerator {
|
|
247
|
+
constructor (opts = {}) {
|
|
248
|
+
super({
|
|
249
|
+
module: '@platformatic/service',
|
|
250
|
+
...opts
|
|
251
|
+
})
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
getConfigFieldsDefinitions () {
|
|
255
|
+
if (this.config.isRuntimeContext) {
|
|
256
|
+
return []
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return [
|
|
260
|
+
{
|
|
261
|
+
var: 'PLT_SERVER_HOSTNAME',
|
|
262
|
+
label: 'What is the hostname?',
|
|
263
|
+
default: '0.0.0.0',
|
|
264
|
+
type: 'string',
|
|
265
|
+
configValue: 'hostname'
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
var: 'PLT_SERVER_LOGGER_LEVEL',
|
|
269
|
+
label: 'What is the logger level?',
|
|
270
|
+
default: 'info',
|
|
271
|
+
type: 'string',
|
|
272
|
+
configValue: ''
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
label: 'Which port do you want to use?',
|
|
276
|
+
var: 'PORT',
|
|
277
|
+
default: 3042,
|
|
278
|
+
type: 'number',
|
|
279
|
+
configValue: 'port'
|
|
280
|
+
}
|
|
281
|
+
]
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
getDefaultConfig () {
|
|
285
|
+
const defaultBaseConfig = super.getDefaultConfig()
|
|
286
|
+
|
|
287
|
+
return {
|
|
288
|
+
...defaultBaseConfig,
|
|
289
|
+
plugin: true,
|
|
290
|
+
tests: true
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
async prepareQuestions () {
|
|
295
|
+
await super.prepareQuestions()
|
|
296
|
+
|
|
297
|
+
if (!this.config.skipTypescript) {
|
|
298
|
+
this.questions.push({
|
|
299
|
+
type: 'list',
|
|
300
|
+
name: 'typescript',
|
|
301
|
+
message: 'Do you want to use TypeScript?',
|
|
302
|
+
default: false,
|
|
303
|
+
choices: [
|
|
304
|
+
{ name: 'yes', value: true },
|
|
305
|
+
{ name: 'no', value: false }
|
|
306
|
+
]
|
|
307
|
+
})
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
async _beforePrepare () {
|
|
312
|
+
if (this.config.isUpdating) {
|
|
313
|
+
return
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (!this.config.isRuntimeContext) {
|
|
317
|
+
this.addEnvVars(
|
|
318
|
+
{
|
|
319
|
+
PLT_SERVER_HOSTNAME: this.config.hostname,
|
|
320
|
+
PLT_SERVER_LOGGER_LEVEL: 'info',
|
|
321
|
+
PORT: 3042
|
|
322
|
+
},
|
|
323
|
+
{ overwrite: false }
|
|
324
|
+
)
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
this.config.dependencies = {
|
|
328
|
+
'@platformatic/service': `^${this.platformaticVersion}`
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
async _afterPrepare () {
|
|
333
|
+
// if we are NOT updating, create env and files, otherwise leave as it is
|
|
334
|
+
if (this.config.isUpdating) {
|
|
335
|
+
return
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
if (this.config.typescript) {
|
|
339
|
+
this.addFile({ path: '', file: 'tsconfig.json', contents: TS_CONFIG })
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
this.addFile({ path: '', file: 'plt-env.d.ts', contents: PLT_ENVIRONMENT_TEMPLATE })
|
|
343
|
+
this.addFile({ path: '', file: 'README.md', contents: README })
|
|
344
|
+
|
|
345
|
+
if (this.config.plugin) {
|
|
346
|
+
// create plugin
|
|
347
|
+
this.files.push({
|
|
348
|
+
path: 'plugins',
|
|
349
|
+
file: this.config.typescript ? 'example.ts' : 'example.js',
|
|
350
|
+
contents: this.config.typescript ? TS_PLUGIN_WITH_TYPES_SUPPORT : JS_PLUGIN_WITH_TYPES_SUPPORT
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
this.files.push({
|
|
354
|
+
path: 'routes',
|
|
355
|
+
file: this.config.typescript ? 'root.ts' : 'root.js',
|
|
356
|
+
contents: this.config.typescript ? TS_ROUTES_WITH_TYPES_SUPPORT : JS_ROUTES_WITH_TYPES_SUPPORT
|
|
357
|
+
})
|
|
358
|
+
|
|
359
|
+
if (this.config.tests) {
|
|
360
|
+
if (this.config.typescript) {
|
|
361
|
+
this.files.push({
|
|
362
|
+
path: 'test',
|
|
363
|
+
file: 'helper.ts',
|
|
364
|
+
contents: applyTestHelperCustomizations(TEST_HELPER_TS, this.module, this.testHelperCustomizations ?? {})
|
|
365
|
+
})
|
|
366
|
+
this.files.push({
|
|
367
|
+
path: join('test', 'plugins'),
|
|
368
|
+
file: 'example.test.ts',
|
|
369
|
+
contents: TEST_PLUGIN_TS
|
|
370
|
+
})
|
|
371
|
+
this.files.push({
|
|
372
|
+
path: join('test', 'routes'),
|
|
373
|
+
file: 'root.test.ts',
|
|
374
|
+
contents: TEST_ROUTES_TS
|
|
375
|
+
})
|
|
376
|
+
} else {
|
|
377
|
+
this.files.push({
|
|
378
|
+
path: 'test',
|
|
379
|
+
file: 'helper.js',
|
|
380
|
+
contents: applyTestHelperCustomizations(TEST_HELPER_JS, this.module, this.testHelperCustomizations ?? {})
|
|
381
|
+
})
|
|
382
|
+
this.files.push({
|
|
383
|
+
path: join('test', 'plugins'),
|
|
384
|
+
file: 'example.test.js',
|
|
385
|
+
contents: TEST_PLUGIN_JS
|
|
386
|
+
})
|
|
387
|
+
this.files.push({
|
|
388
|
+
path: join('test', 'routes'),
|
|
389
|
+
file: 'root.test.js',
|
|
390
|
+
contents: TEST_ROUTES_JS
|
|
391
|
+
})
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
async _getConfigFileContents () {
|
|
398
|
+
const config = {
|
|
399
|
+
$schema: `https://schemas.platformatic.dev/@platformatic/service/${this.platformaticVersion}.json`,
|
|
400
|
+
service: {
|
|
401
|
+
openapi: true
|
|
402
|
+
},
|
|
403
|
+
watch: true
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
if (this.config.plugin) {
|
|
407
|
+
config.plugins = {
|
|
408
|
+
paths: [{ path: './plugins', encapsulate: false }, './routes']
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
if (!this.config.isRuntimeContext) {
|
|
413
|
+
config.server = {
|
|
414
|
+
hostname: '{PLT_SERVER_HOSTNAME}',
|
|
415
|
+
port: '{PORT}',
|
|
416
|
+
logger: {
|
|
417
|
+
level: '{PLT_SERVER_LOGGER_LEVEL}'
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
return config
|
|
423
|
+
}
|
|
424
|
+
}
|
package/lib/plugins/cors.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
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
|
|
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(
|
|
23
|
+
app.register(fastifyCors, cors)
|
|
27
24
|
}
|
|
28
25
|
|
|
29
|
-
|
|
26
|
+
export const setupCors = fp(setupCorsPlugin)
|
package/lib/plugins/graphql.js
CHANGED
|
@@ -1,24 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
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
|
|
11
|
-
if (typeof
|
|
12
|
-
|
|
8
|
+
async function setupGraphQLPlugin (app, options) {
|
|
9
|
+
if (typeof options !== 'object') {
|
|
10
|
+
options = {}
|
|
13
11
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
|
|
13
|
+
const graphqlOptions = deepmerge(
|
|
14
|
+
{
|
|
15
|
+
graphiql: true,
|
|
16
|
+
additionalRouteOptions: {
|
|
17
|
+
schema: { hide: true }
|
|
18
|
+
}
|
|
18
19
|
},
|
|
19
|
-
|
|
20
|
+
options
|
|
21
|
+
)
|
|
20
22
|
|
|
21
23
|
app.register(mercurius, graphqlOptions)
|
|
22
24
|
}
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
export const setupGraphQL = fp(setupGraphQLPlugin)
|
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
import underPressure from '@fastify/under-pressure'
|
|
2
|
+
import fp from 'fastify-plugin'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
const
|
|
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
|
-
|
|
15
|
+
export const setupHealthCheck = fp(setupHealthCheckPlugin)
|
package/lib/plugins/openapi.js
CHANGED
|
@@ -1,43 +1,44 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const deepmerge = require('@fastify/deepmerge')({ all: true })
|
|
5
|
-
const fp = require('fastify-plugin')
|
|
1
|
+
import Swagger from '@fastify/swagger'
|
|
2
|
+
import { deepmerge } from '@platformatic/foundation'
|
|
3
|
+
import fp from 'fastify-plugin'
|
|
6
4
|
|
|
7
5
|
// For some unknown reason, c8 is not detecting any of this
|
|
8
6
|
// pf
|
|
9
7
|
// despite being covered by test/routes.test.js
|
|
10
8
|
/* c8 ignore next 33 */
|
|
11
|
-
async function
|
|
12
|
-
const { openapi } =
|
|
13
|
-
const openapiConfig = deepmerge(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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 ?? '/' }]
|
|
19
20
|
},
|
|
20
|
-
|
|
21
|
-
|
|
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
|
|
|
@@ -49,24 +50,32 @@ async function setupOpenAPI (app, opts) {
|
|
|
49
50
|
const routePrefix = openapi.swaggerPrefix || '/documentation'
|
|
50
51
|
|
|
51
52
|
/** Serve spec file in yaml and json */
|
|
52
|
-
app.get(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
+
)
|
|
60
69
|
|
|
61
70
|
app.register(scalarApiReference, {
|
|
62
|
-
...
|
|
71
|
+
...options,
|
|
63
72
|
...openapi,
|
|
64
73
|
routePrefix,
|
|
65
74
|
publicPath: './',
|
|
66
75
|
configuration: {
|
|
67
|
-
customCss: scalarTheme.theme
|
|
68
|
-
}
|
|
76
|
+
customCss: scalarTheme.theme
|
|
77
|
+
}
|
|
69
78
|
})
|
|
70
79
|
}
|
|
71
80
|
|
|
72
|
-
|
|
81
|
+
export const setupOpenAPI = fp(setupOpenAPIPlugin)
|
package/lib/plugins/plugins.js
CHANGED
|
@@ -1,57 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import fp from 'fastify-plugin'
|
|
2
|
+
import { sandboxWrapper } from './sandbox-wrapper.js'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const fp = require('fastify-plugin')
|
|
6
|
-
const wrapper = require('./sandbox-wrapper')
|
|
4
|
+
async function loadPluginsPlugin (app, context) {
|
|
5
|
+
const config = app.platformatic.config
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
async function loadPlugins (app, opts) {
|
|
11
|
-
const configManager = app.platformatic.configManager
|
|
12
|
-
const config = configManager.current
|
|
13
|
-
|
|
14
|
-
let isOutDirAccessible = false
|
|
15
|
-
let outDir = null
|
|
16
|
-
|
|
17
|
-
const workingDir = opts?.context?.directory ?? configManager.dirname
|
|
18
|
-
const tsConfigPath = configManager.current.plugins.typescript?.tsConfig || join(workingDir, 'tsconfig.json')
|
|
19
|
-
|
|
20
|
-
// If the tsconfig.json file exists, then we need to adjust the plugin paths
|
|
21
|
-
// to point to the compiled JS files.
|
|
22
|
-
const isTsConfigAccessible = await isFileAccessible(tsConfigPath)
|
|
23
|
-
if (isTsConfigAccessible) {
|
|
24
|
-
const tsConfig = JSON.parse(await readFile(tsConfigPath, 'utf8'))
|
|
25
|
-
outDir = resolve(workingDir, tsConfig.compilerOptions.outDir)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/* c8 ignore next 3 */
|
|
29
|
-
if (configManager.current.plugins.typescript?.outDir) {
|
|
30
|
-
outDir = configManager.current.plugins.typescript.outDir
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (outDir) {
|
|
34
|
-
isOutDirAccessible = await isFileAccessible(outDir)
|
|
35
|
-
|
|
36
|
-
if (opts.context?.isProduction && !isOutDirAccessible) {
|
|
37
|
-
throw new Error(
|
|
38
|
-
`Cannot access directory '${outDir}'. Please run the 'build' command before running in production mode.`
|
|
39
|
-
)
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if (config.plugins.paths && isOutDirAccessible) {
|
|
44
|
-
config.plugins.paths = config.plugins.paths.map(plugin => {
|
|
45
|
-
/* c8 ignore next 3 */
|
|
46
|
-
const tmp =
|
|
47
|
-
typeof plugin === 'string'
|
|
48
|
-
? getJSPluginPath(workingDir, plugin, outDir)
|
|
49
|
-
: { ...plugin, path: getJSPluginPath(workingDir, plugin.path, outDir) }
|
|
50
|
-
return tmp
|
|
51
|
-
})
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
await app.register(wrapper, { packages: config.plugins.packages, paths: config.plugins.paths })
|
|
7
|
+
await app.register(sandboxWrapper, { packages: config.plugins.packages, paths: config.plugins.paths })
|
|
55
8
|
}
|
|
56
9
|
|
|
57
|
-
|
|
10
|
+
export const loadPlugins = fp(loadPluginsPlugin)
|