@platformatic/service 0.13.0 → 0.14.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.
- package/index.js +9 -2
- package/lib/metrics-plugin.js +1 -1
- package/lib/root-endpoint/index.js +26 -0
- package/lib/root-endpoint/public/index.html +99 -0
- package/lib/root-endpoint/public/logo-512x512.png +0 -0
- package/package.json +4 -5
- package/test/config.test.js +113 -1
- package/test/fixtures/root-endpoint-plugin.js +8 -0
- package/test/helper.js +11 -0
- package/test/load-and-reload-files.test.js +19 -7
- package/test/routes.test.js +79 -0
package/index.js
CHANGED
|
@@ -90,6 +90,10 @@ async function platformaticService (app, opts, toLoad = []) {
|
|
|
90
90
|
healthCheck: opts.healthCheck.fn
|
|
91
91
|
})
|
|
92
92
|
}
|
|
93
|
+
|
|
94
|
+
if (!app.hasRoute({ url: '/', method: 'GET' }) && !Array.isArray(toLoad)) {
|
|
95
|
+
await app.register(require('./lib/root-endpoint'), opts)
|
|
96
|
+
}
|
|
93
97
|
}
|
|
94
98
|
|
|
95
99
|
async function loadPlugin (app, config, pluginOptions) {
|
|
@@ -179,10 +183,13 @@ function adjustConfigAfterMerge (options, stash) {
|
|
|
179
183
|
}
|
|
180
184
|
}
|
|
181
185
|
|
|
182
|
-
async function buildServer (options, app
|
|
186
|
+
async function buildServer (options, app, ConfigManagerContructor) {
|
|
187
|
+
app = app || platformaticService
|
|
188
|
+
ConfigManagerContructor = ConfigManagerContructor || ConfigManager
|
|
189
|
+
|
|
183
190
|
if (!options.configManager) {
|
|
184
191
|
// instantiate a new config manager from current options
|
|
185
|
-
const cm = new
|
|
192
|
+
const cm = new ConfigManagerContructor({
|
|
186
193
|
source: options,
|
|
187
194
|
schema: app?.schema ?? schema
|
|
188
195
|
})
|
package/lib/metrics-plugin.js
CHANGED
|
@@ -87,7 +87,7 @@ module.exports = fp(async function (app, opts) {
|
|
|
87
87
|
const metricsEndpointOptions = {
|
|
88
88
|
url: '/metrics',
|
|
89
89
|
method: 'GET',
|
|
90
|
-
logLevel: '
|
|
90
|
+
logLevel: 'warn',
|
|
91
91
|
handler: async (req, reply) => {
|
|
92
92
|
const promRegistry = app.metrics.client.register
|
|
93
93
|
const accepts = req.accepts()
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
const path = require('path')
|
|
3
|
+
const fastifyStatic = require('@fastify/static')
|
|
4
|
+
const userAgentParser = require('ua-parser-js')
|
|
5
|
+
|
|
6
|
+
module.exports = async (app, opts) => {
|
|
7
|
+
app.register(fastifyStatic, {
|
|
8
|
+
root: path.join(__dirname, 'public')
|
|
9
|
+
})
|
|
10
|
+
// root endpoint
|
|
11
|
+
app.route({
|
|
12
|
+
method: 'GET',
|
|
13
|
+
path: '/',
|
|
14
|
+
schema: { hide: true },
|
|
15
|
+
handler: (req, reply) => {
|
|
16
|
+
const uaString = req.headers['user-agent']
|
|
17
|
+
if (uaString) {
|
|
18
|
+
const parsed = userAgentParser(uaString)
|
|
19
|
+
if (parsed.browser.name !== undefined) {
|
|
20
|
+
return reply.sendFile('./index.html')
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return { message: 'Welcome to Platformatic! Please visit https://oss.platformatic.dev' }
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/svg+xml" href="/images/favicon.ico" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>Platformatic DB</title>
|
|
8
|
+
<style>
|
|
9
|
+
:root {
|
|
10
|
+
width: 100%;
|
|
11
|
+
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
|
|
12
|
+
font-size: 16px;
|
|
13
|
+
line-height: 24px;
|
|
14
|
+
font-weight: 400;
|
|
15
|
+
|
|
16
|
+
color-scheme: light dark;
|
|
17
|
+
color: rgba(255, 255, 255, 0.87);
|
|
18
|
+
background-color: #092339;
|
|
19
|
+
|
|
20
|
+
font-synthesis: none;
|
|
21
|
+
text-rendering: optimizeLegibility;
|
|
22
|
+
-webkit-font-smoothing: antialiased;
|
|
23
|
+
-moz-osx-font-smoothing: grayscale;
|
|
24
|
+
-webkit-text-size-adjust: 100%;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
a {
|
|
28
|
+
font-weight: 500;
|
|
29
|
+
color: #21f190;
|
|
30
|
+
text-decoration: inherit;
|
|
31
|
+
}
|
|
32
|
+
a:hover {
|
|
33
|
+
color: #007B82;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
body {
|
|
37
|
+
width: 50%;
|
|
38
|
+
display: flex;
|
|
39
|
+
align-items: center;
|
|
40
|
+
justify-content: center;
|
|
41
|
+
flex-direction: column;
|
|
42
|
+
margin: auto;
|
|
43
|
+
min-height: 100vh;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
h1 {
|
|
47
|
+
font-size: 3.2em;
|
|
48
|
+
line-height: 1.1;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
button {
|
|
52
|
+
border-radius: 8px;
|
|
53
|
+
border: 1px solid transparent;
|
|
54
|
+
padding: 0.6em 1.2em;
|
|
55
|
+
font-size: 1em;
|
|
56
|
+
font-weight: 500;
|
|
57
|
+
font-family: inherit;
|
|
58
|
+
background-color: #1a1a1a;
|
|
59
|
+
cursor: pointer;
|
|
60
|
+
transition: border-color 0.25s;
|
|
61
|
+
}
|
|
62
|
+
button:hover {
|
|
63
|
+
border-color: #646cff;
|
|
64
|
+
}
|
|
65
|
+
button:focus,
|
|
66
|
+
button:focus-visible {
|
|
67
|
+
outline: 4px auto -webkit-focus-ring-color;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@media (prefers-color-scheme: light) {
|
|
71
|
+
:root {
|
|
72
|
+
color: #213547;
|
|
73
|
+
background-color: #ffffff;
|
|
74
|
+
}
|
|
75
|
+
a:hover {
|
|
76
|
+
color: #747bff;
|
|
77
|
+
}
|
|
78
|
+
button {
|
|
79
|
+
background-color: #f9f9f9;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
#root {
|
|
84
|
+
display: flex;
|
|
85
|
+
flex-direction: column;
|
|
86
|
+
align-items: center;
|
|
87
|
+
justify-content: center;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
</style>
|
|
91
|
+
</head>
|
|
92
|
+
<body>
|
|
93
|
+
<div id="root">
|
|
94
|
+
<img height="256" src="logo-512x512.png"/>
|
|
95
|
+
<h1>Welcome to Platformatic Service</h1>
|
|
96
|
+
<h2><a href="https://oss.platformatic.dev" target="_blank">Documentation</a></h2>
|
|
97
|
+
</div>
|
|
98
|
+
</body>
|
|
99
|
+
</html>
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/service",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"author": "Matteo Collina <hello@matteocollina.com>",
|
|
@@ -49,14 +49,13 @@
|
|
|
49
49
|
"fastify-sandbox": "^0.11.0",
|
|
50
50
|
"graphql": "^16.6.0",
|
|
51
51
|
"help-me": "^4.2.0",
|
|
52
|
-
"mercurius": "^11.4.0",
|
|
53
|
-
"minimatch": "^5.1.1",
|
|
54
52
|
"minimist": "^1.2.7",
|
|
55
53
|
"pino": "^8.8.0",
|
|
56
54
|
"pino-pretty": "^9.1.1",
|
|
57
55
|
"rfdc": "^1.3.0",
|
|
58
|
-
"
|
|
59
|
-
"@platformatic/
|
|
56
|
+
"ua-parser-js": "^1.0.32",
|
|
57
|
+
"@platformatic/config": "0.14.0",
|
|
58
|
+
"@platformatic/utils": "0.14.0"
|
|
60
59
|
},
|
|
61
60
|
"standard": {
|
|
62
61
|
"ignore": [
|
package/test/config.test.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require('./helper')
|
|
4
4
|
const { test } = require('tap')
|
|
5
|
-
const { buildServer } = require('..')
|
|
5
|
+
const { buildServer, ConfigManager } = require('..')
|
|
6
6
|
const { request } = require('undici')
|
|
7
7
|
const { join } = require('path')
|
|
8
8
|
const os = require('os')
|
|
@@ -212,3 +212,115 @@ test('config is adjusted to handle custom loggers', async (t) => {
|
|
|
212
212
|
await buildServer(options)
|
|
213
213
|
t.equal(called, true)
|
|
214
214
|
})
|
|
215
|
+
|
|
216
|
+
test('custom ConfigManager', async ({ teardown, equal, pass, same }) => {
|
|
217
|
+
const file = join(os.tmpdir(), `${process.pid}-2.js`)
|
|
218
|
+
|
|
219
|
+
await writeFile(file, `
|
|
220
|
+
module.exports = async function (app, options) {
|
|
221
|
+
app.get('/', () => options.message)
|
|
222
|
+
}`)
|
|
223
|
+
|
|
224
|
+
class MyConfigManager extends ConfigManager {
|
|
225
|
+
_transformConfig () {
|
|
226
|
+
super._transformConfig.call(this)
|
|
227
|
+
this.current.plugin = {
|
|
228
|
+
path: file,
|
|
229
|
+
options: {
|
|
230
|
+
message: 'hello'
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const server = await buildServer({
|
|
237
|
+
server: {
|
|
238
|
+
hostname: '127.0.0.1',
|
|
239
|
+
port: 0
|
|
240
|
+
},
|
|
241
|
+
metrics: false
|
|
242
|
+
}, null, MyConfigManager)
|
|
243
|
+
teardown(server.stop)
|
|
244
|
+
await server.listen()
|
|
245
|
+
|
|
246
|
+
{
|
|
247
|
+
const res = await request(`${server.url}/`)
|
|
248
|
+
equal(res.statusCode, 200, 'add status code')
|
|
249
|
+
same(await res.body.text(), 'hello', 'response')
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
await server.app.platformatic.configManager.update({
|
|
253
|
+
server: {
|
|
254
|
+
hostname: '127.0.0.1',
|
|
255
|
+
port: 0
|
|
256
|
+
},
|
|
257
|
+
plugin: {
|
|
258
|
+
path: file,
|
|
259
|
+
options: {
|
|
260
|
+
message: 'ciao mondo'
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
metrics: false
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
await server.restart()
|
|
267
|
+
|
|
268
|
+
{
|
|
269
|
+
const res = await request(`${server.url}/`)
|
|
270
|
+
equal(res.statusCode, 200, 'add status code')
|
|
271
|
+
same(await res.body.text(), 'ciao mondo', 'response')
|
|
272
|
+
}
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
test('config reloads', async ({ teardown, equal, pass, same }) => {
|
|
276
|
+
const file = join(os.tmpdir(), `${process.pid}-1.js`)
|
|
277
|
+
|
|
278
|
+
await writeFile(file, `
|
|
279
|
+
module.exports = async function (app, options) {
|
|
280
|
+
app.get('/', () => options.message)
|
|
281
|
+
}`)
|
|
282
|
+
|
|
283
|
+
const server = await buildServer({
|
|
284
|
+
server: {
|
|
285
|
+
hostname: '127.0.0.1',
|
|
286
|
+
port: 0
|
|
287
|
+
},
|
|
288
|
+
plugin: {
|
|
289
|
+
path: file,
|
|
290
|
+
options: {
|
|
291
|
+
message: 'hello'
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
metrics: false
|
|
295
|
+
})
|
|
296
|
+
teardown(server.stop)
|
|
297
|
+
await server.listen()
|
|
298
|
+
|
|
299
|
+
{
|
|
300
|
+
const res = await request(`${server.url}/`)
|
|
301
|
+
equal(res.statusCode, 200, 'add status code')
|
|
302
|
+
same(await res.body.text(), 'hello', 'response')
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
await server.app.platformatic.configManager.update({
|
|
306
|
+
server: {
|
|
307
|
+
hostname: '127.0.0.1',
|
|
308
|
+
port: 0
|
|
309
|
+
},
|
|
310
|
+
plugin: {
|
|
311
|
+
path: file,
|
|
312
|
+
options: {
|
|
313
|
+
message: 'ciao mondo'
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
metrics: false
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
await server.restart()
|
|
320
|
+
|
|
321
|
+
{
|
|
322
|
+
const res = await request(`${server.url}/`)
|
|
323
|
+
equal(res.statusCode, 200, 'add status code')
|
|
324
|
+
same(await res.body.text(), 'ciao mondo', 'response')
|
|
325
|
+
}
|
|
326
|
+
})
|
package/test/helper.js
CHANGED
|
@@ -31,7 +31,9 @@ test('load and reload', async ({ teardown, equal, pass, same }) => {
|
|
|
31
31
|
|
|
32
32
|
{
|
|
33
33
|
const res = await request(`${server.url}/`)
|
|
34
|
-
equal(res.statusCode,
|
|
34
|
+
equal(res.statusCode, 200, 'status code')
|
|
35
|
+
const data = await res.body.json()
|
|
36
|
+
same(data, { message: 'Welcome to Platformatic! Please visit https://oss.platformatic.dev' })
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
await writeFile(file, `
|
|
@@ -97,7 +99,9 @@ test('update config', async ({ teardown, equal, pass, same }) => {
|
|
|
97
99
|
|
|
98
100
|
{
|
|
99
101
|
const res = await request(`${server.url}/`)
|
|
100
|
-
equal(res.statusCode,
|
|
102
|
+
equal(res.statusCode, 200, 'status code')
|
|
103
|
+
const data = await res.body.json()
|
|
104
|
+
same(data, { message: 'Welcome to Platformatic! Please visit https://oss.platformatic.dev' })
|
|
101
105
|
}
|
|
102
106
|
|
|
103
107
|
const file2 = join(os.tmpdir(), `some-plugin-${process.pid}-2.js`)
|
|
@@ -184,7 +188,9 @@ test('load and reload with the fallback', async ({ teardown, equal, pass, same }
|
|
|
184
188
|
|
|
185
189
|
{
|
|
186
190
|
const res = await request(`${server.url}/`)
|
|
187
|
-
equal(res.statusCode,
|
|
191
|
+
equal(res.statusCode, 200, 'status code')
|
|
192
|
+
const data = await res.body.json()
|
|
193
|
+
same(data, { message: 'Welcome to Platformatic! Please visit https://oss.platformatic.dev' })
|
|
188
194
|
}
|
|
189
195
|
|
|
190
196
|
await writeFile(file, `
|
|
@@ -223,7 +229,9 @@ test('load and reload ESM', async ({ teardown, equal, pass, same }) => {
|
|
|
223
229
|
|
|
224
230
|
{
|
|
225
231
|
const res = await request(`${server.url}/`)
|
|
226
|
-
equal(res.statusCode,
|
|
232
|
+
equal(res.statusCode, 200, 'status code')
|
|
233
|
+
const data = await res.body.json()
|
|
234
|
+
same(data, { message: 'Welcome to Platformatic! Please visit https://oss.platformatic.dev' })
|
|
227
235
|
}
|
|
228
236
|
|
|
229
237
|
await writeFile(file, `
|
|
@@ -240,7 +248,7 @@ test('load and reload ESM', async ({ teardown, equal, pass, same }) => {
|
|
|
240
248
|
}
|
|
241
249
|
})
|
|
242
250
|
|
|
243
|
-
test('server should be available after reload a compromised plugin', async ({ teardown, equal, pass }) => {
|
|
251
|
+
test('server should be available after reload a compromised plugin', async ({ teardown, equal, pass, same }) => {
|
|
244
252
|
const file = join(os.tmpdir(), `some-plugin-${process.pid}.js`)
|
|
245
253
|
|
|
246
254
|
const workingModule = `
|
|
@@ -271,7 +279,9 @@ test('server should be available after reload a compromised plugin', async ({ te
|
|
|
271
279
|
|
|
272
280
|
{
|
|
273
281
|
const res = await request(`${server.url}/`, { method: 'GET' })
|
|
274
|
-
equal(res.statusCode,
|
|
282
|
+
equal(res.statusCode, 200, 'status code')
|
|
283
|
+
const data = await res.body.json()
|
|
284
|
+
same(data, { message: 'Welcome to Platformatic! Please visit https://oss.platformatic.dev' })
|
|
275
285
|
}
|
|
276
286
|
|
|
277
287
|
await writeFile(file, workingModule)
|
|
@@ -279,7 +289,9 @@ test('server should be available after reload a compromised plugin', async ({ te
|
|
|
279
289
|
|
|
280
290
|
{
|
|
281
291
|
const res = await request(`${server.url}/`, { method: 'GET' })
|
|
282
|
-
equal(res.statusCode,
|
|
292
|
+
equal(res.statusCode, 200, 'add status code')
|
|
293
|
+
const data = await res.body.json()
|
|
294
|
+
same(data, { message: 'Welcome to Platformatic! Please visit https://oss.platformatic.dev' })
|
|
283
295
|
}
|
|
284
296
|
|
|
285
297
|
teardown(server.stop)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('tap')
|
|
4
|
+
const { buildServer } = require('..')
|
|
5
|
+
const { buildConfig, connInfo } = require('./helper')
|
|
6
|
+
const { request } = require('undici')
|
|
7
|
+
const { join } = require('path')
|
|
8
|
+
|
|
9
|
+
test('should respond 200 on root endpoint', async ({ teardown, equal, same }) => {
|
|
10
|
+
const server = await buildServer(buildConfig({
|
|
11
|
+
server: {
|
|
12
|
+
hostname: '127.0.0.1',
|
|
13
|
+
port: 0,
|
|
14
|
+
healthCheck: {
|
|
15
|
+
enabled: true,
|
|
16
|
+
interval: 2000
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
core: {
|
|
20
|
+
...connInfo
|
|
21
|
+
},
|
|
22
|
+
authorization: {
|
|
23
|
+
adminSecret: 'secret'
|
|
24
|
+
},
|
|
25
|
+
dashboard: false
|
|
26
|
+
}))
|
|
27
|
+
teardown(server.stop)
|
|
28
|
+
|
|
29
|
+
await server.listen()
|
|
30
|
+
{
|
|
31
|
+
// No browser (i.e. curl)
|
|
32
|
+
const res = await (request(`${server.url}/`))
|
|
33
|
+
equal(res.statusCode, 200)
|
|
34
|
+
const body = await res.body.json()
|
|
35
|
+
same(body, { message: 'Welcome to Platformatic! Please visit https://oss.platformatic.dev' })
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
{
|
|
39
|
+
// browser
|
|
40
|
+
const res = await (request(`${server.url}/`, {
|
|
41
|
+
headers: {
|
|
42
|
+
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36'
|
|
43
|
+
}
|
|
44
|
+
}))
|
|
45
|
+
|
|
46
|
+
equal(res.statusCode, 200)
|
|
47
|
+
equal(res.headers['content-type'], 'text/html; charset=UTF-8')
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
test('should not overwrite a plugin which define a root endpoint', async ({ teardown, equal, same }) => {
|
|
52
|
+
const server = await buildServer(buildConfig({
|
|
53
|
+
server: {
|
|
54
|
+
hostname: '127.0.0.1',
|
|
55
|
+
port: 0,
|
|
56
|
+
healthCheck: {
|
|
57
|
+
enabled: true,
|
|
58
|
+
interval: 2000
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
core: {
|
|
62
|
+
...connInfo
|
|
63
|
+
},
|
|
64
|
+
authorization: {
|
|
65
|
+
adminSecret: 'secret'
|
|
66
|
+
},
|
|
67
|
+
dashboard: false,
|
|
68
|
+
plugin: {
|
|
69
|
+
path: join(__dirname, 'fixtures', 'root-endpoint-plugin.js')
|
|
70
|
+
}
|
|
71
|
+
}))
|
|
72
|
+
teardown(server.stop)
|
|
73
|
+
|
|
74
|
+
await server.listen()
|
|
75
|
+
const res = await (request(`${server.url}/`))
|
|
76
|
+
equal(res.statusCode, 200)
|
|
77
|
+
const body = await res.body.json()
|
|
78
|
+
same(body, { message: 'Root Plugin' })
|
|
79
|
+
})
|