@platformatic/service 0.22.0 → 0.23.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.
Files changed (38) hide show
  1. package/fixtures/hello-client-ts/platformatic.service.json +2 -1
  2. package/index.js +118 -169
  3. package/lib/load-config.js +6 -1
  4. package/lib/plugins/clients.js +12 -0
  5. package/lib/plugins/cors.js +29 -0
  6. package/lib/plugins/file-watcher.js +44 -0
  7. package/lib/plugins/health-check.js +17 -0
  8. package/lib/plugins/plugins.js +56 -0
  9. package/lib/plugins/typescript.js +46 -0
  10. package/lib/root-endpoint/index.js +1 -0
  11. package/lib/schema.js +8 -1
  12. package/lib/start.mjs +27 -136
  13. package/lib/utils.js +2 -2
  14. package/package.json +9 -8
  15. package/test/autoload.test.js +77 -59
  16. package/test/cli/compile.test.mjs +45 -33
  17. package/test/cli/watch.test.mjs +39 -0
  18. package/test/clients.test.js +24 -17
  19. package/test/config.test.js +58 -86
  20. package/test/cors.test.js +48 -30
  21. package/test/fixtures/bad-typescript-plugin/platformatic.service.json +3 -1
  22. package/test/fixtures/typescript-autoload/platformatic.service.json +3 -1
  23. package/test/fixtures/typescript-plugin/platformatic.service.json +3 -1
  24. package/test/fixtures/typescript-plugin-nocompile/platformatic.service.json +2 -1
  25. package/test/graphql.test.js +18 -14
  26. package/test/healthcheck.test.js +22 -13
  27. package/test/https.test.js +11 -8
  28. package/test/lambda.test.js +103 -0
  29. package/test/load-and-reload-files.test.js +97 -112
  30. package/test/load-plugin.test.js +8 -4
  31. package/test/metrics.test.js +59 -39
  32. package/test/routes.test.js +43 -25
  33. package/test/utils.test.js +2 -2
  34. package/test/watch.test.js +182 -0
  35. /package/lib/{graphql.js → plugins/graphql.js} +0 -0
  36. /package/lib/{metrics-plugin.js → plugins/metrics.js} +0 -0
  37. /package/lib/{openapi.js → plugins/openapi.js} +0 -0
  38. /package/lib/{sandbox-wrapper.js → plugins/sandbox-wrapper.js} +0 -0
@@ -7,7 +7,7 @@ const { request } = require('undici')
7
7
  const { join } = require('path')
8
8
 
9
9
  test('should respond 200 on root endpoint', async ({ teardown, equal, same }) => {
10
- const server = await buildServer(buildConfig({
10
+ const app = await buildServer(buildConfig({
11
11
  server: {
12
12
  hostname: '127.0.0.1',
13
13
  port: 0,
@@ -17,12 +17,15 @@ test('should respond 200 on root endpoint', async ({ teardown, equal, same }) =>
17
17
  }
18
18
  }
19
19
  }))
20
- teardown(server.stop)
21
20
 
22
- await server.listen()
21
+ teardown(async () => {
22
+ await app.close()
23
+ })
24
+ await app.start()
25
+
23
26
  {
24
27
  // No browser (i.e. curl)
25
- const res = await (request(`${server.url}/`))
28
+ const res = await (request(`${app.url}/`))
26
29
  equal(res.statusCode, 200)
27
30
  const body = await res.body.json()
28
31
  same(body, { message: 'Welcome to Platformatic! Please visit https://oss.platformatic.dev' })
@@ -30,7 +33,7 @@ test('should respond 200 on root endpoint', async ({ teardown, equal, same }) =>
30
33
 
31
34
  {
32
35
  // browser
33
- const res = await (request(`${server.url}/`, {
36
+ const res = await (request(`${app.url}/`, {
34
37
  headers: {
35
38
  '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'
36
39
  }
@@ -42,7 +45,7 @@ test('should respond 200 on root endpoint', async ({ teardown, equal, same }) =>
42
45
  })
43
46
 
44
47
  test('should not overwrite a plugin which define a root endpoint', async ({ teardown, equal, same }) => {
45
- const server = await buildServer(buildConfig({
48
+ const app = await buildServer(buildConfig({
46
49
  server: {
47
50
  hostname: '127.0.0.1',
48
51
  port: 0,
@@ -55,17 +58,20 @@ test('should not overwrite a plugin which define a root endpoint', async ({ tear
55
58
  paths: [join(__dirname, 'fixtures', 'root-endpoint-plugin.js')]
56
59
  }
57
60
  }))
58
- teardown(server.stop)
59
61
 
60
- await server.listen()
61
- const res = await (request(`${server.url}/`))
62
+ teardown(async () => {
63
+ await app.close()
64
+ })
65
+ await app.start()
66
+
67
+ const res = await (request(`${app.url}/`))
62
68
  equal(res.statusCode, 200)
63
69
  const body = await res.body.json()
64
70
  same(body, { message: 'Root Plugin' })
65
71
  })
66
72
 
67
73
  test('openapi enabled', async ({ teardown, equal, same }) => {
68
- const server = await buildServer(buildConfig({
74
+ const app = await buildServer(buildConfig({
69
75
  server: {
70
76
  hostname: '127.0.0.1',
71
77
  port: 0,
@@ -81,12 +87,15 @@ test('openapi enabled', async ({ teardown, equal, same }) => {
81
87
  paths: [join(__dirname, 'fixtures', 'root-endpoint-plugin.js')]
82
88
  }
83
89
  }))
84
- teardown(server.stop)
85
90
 
86
- await server.listen()
91
+ teardown(async () => {
92
+ await app.close()
93
+ })
94
+ await app.start()
95
+
87
96
  {
88
97
  // No browser (i.e. curl)
89
- const res = await (request(`${server.url}/documentation/json`))
98
+ const res = await (request(`${app.url}/documentation/json`))
90
99
  equal(res.statusCode, 200)
91
100
  const body = await res.body.json()
92
101
 
@@ -98,7 +107,7 @@ test('openapi enabled', async ({ teardown, equal, same }) => {
98
107
  })
99
108
 
100
109
  test('openapi config', async ({ teardown, equal, same }) => {
101
- const server = await buildServer(buildConfig({
110
+ const app = await buildServer(buildConfig({
102
111
  server: {
103
112
  hostname: '127.0.0.1',
104
113
  port: 0
@@ -116,12 +125,15 @@ test('openapi config', async ({ teardown, equal, same }) => {
116
125
  paths: [join(__dirname, 'fixtures', 'root-endpoint-plugin.js')]
117
126
  }
118
127
  }))
119
- teardown(server.stop)
120
128
 
121
- await server.listen()
129
+ teardown(async () => {
130
+ await app.close()
131
+ })
132
+ await app.start()
133
+
122
134
  {
123
135
  // No browser (i.e. curl)
124
- const res = await (request(`${server.url}/documentation/json`))
136
+ const res = await (request(`${app.url}/documentation/json`))
125
137
  equal(res.statusCode, 200)
126
138
  const body = await res.body.json()
127
139
 
@@ -134,7 +146,7 @@ test('openapi config', async ({ teardown, equal, same }) => {
134
146
  })
135
147
 
136
148
  test('openapi disabled', async ({ teardown, equal, same }) => {
137
- const server = await buildServer(buildConfig({
149
+ const app = await buildServer(buildConfig({
138
150
  server: {
139
151
  hostname: '127.0.0.1',
140
152
  port: 0,
@@ -150,19 +162,22 @@ test('openapi disabled', async ({ teardown, equal, same }) => {
150
162
  paths: [join(__dirname, 'fixtures', 'root-endpoint-plugin.js')]
151
163
  }
152
164
  }))
153
- teardown(server.stop)
154
165
 
155
- await server.listen()
166
+ teardown(async () => {
167
+ await app.close()
168
+ })
169
+ await app.start()
170
+
156
171
  {
157
172
  // No browser (i.e. curl)
158
- const res = await (request(`${server.url}/documentation/json`))
173
+ const res = await (request(`${app.url}/documentation/json`))
159
174
  equal(res.statusCode, 404)
160
175
  await res.body.text()
161
176
  }
162
177
  })
163
178
 
164
179
  test('openapi disabled by default', async ({ teardown, equal, same }) => {
165
- const server = await buildServer(buildConfig({
180
+ const app = await buildServer(buildConfig({
166
181
  server: {
167
182
  hostname: '127.0.0.1',
168
183
  port: 0,
@@ -175,12 +190,15 @@ test('openapi disabled by default', async ({ teardown, equal, same }) => {
175
190
  paths: [join(__dirname, 'fixtures', 'root-endpoint-plugin.js')]
176
191
  }
177
192
  }))
178
- teardown(server.stop)
179
193
 
180
- await server.listen()
194
+ teardown(async () => {
195
+ await app.close()
196
+ })
197
+ await app.start()
198
+
181
199
  {
182
200
  // No browser (i.e. curl)
183
- const res = await (request(`${server.url}/documentation/json`))
201
+ const res = await (request(`${app.url}/documentation/json`))
184
202
  equal(res.statusCode, 404)
185
203
  await res.body.text()
186
204
  }
@@ -7,7 +7,7 @@ const { join, resolve } = require('path')
7
7
  test('should get the path of a TS plugin', (t) => {
8
8
  t.plan(1)
9
9
 
10
- const result = getJSPluginPath('/something/platformatic.service.json', '/something/plugin.ts', '/something/dist')
10
+ const result = getJSPluginPath('/something', '/something/plugin.ts', '/something/dist')
11
11
  const expected = join('/something', 'dist', 'plugin.js')
12
12
  t.equal(result, expected)
13
13
  })
@@ -15,7 +15,7 @@ test('should get the path of a TS plugin', (t) => {
15
15
  test('should get the path of a JS plugin', (t) => {
16
16
  t.plan(1)
17
17
 
18
- const result = getJSPluginPath('/something/platformatic.service.json', '/something/plugin.js', '/something/dist')
18
+ const result = getJSPluginPath('/something', '/something/plugin.js', '/something/dist')
19
19
  t.equal(result, '/something/plugin.js')
20
20
  })
21
21
 
@@ -0,0 +1,182 @@
1
+ 'use strict'
2
+
3
+ const { join } = require('path')
4
+ const { tmpdir } = require('os')
5
+ const { writeFile, mkdtemp, rm } = require('fs/promises')
6
+
7
+ const { test } = require('tap')
8
+ const { request } = require('undici')
9
+
10
+ const { buildServer } = require('..')
11
+ require('./helper')
12
+
13
+ test('should stop watching files after disabling watch option', async ({ teardown, equal, pass, same }) => {
14
+ const tmpDir = await mkdtemp(join(tmpdir(), 'platformatic.service.test-'))
15
+ const pathToPlugin = join(tmpDir, 'plugin.js')
16
+ const pathToConfig = join(tmpDir, 'platformatic.service.json')
17
+
18
+ teardown(async () => {
19
+ await rm(tmpDir, { recursive: true, force: true })
20
+ })
21
+
22
+ await writeFile(pathToPlugin, `
23
+ module.exports = async function plugin (app) {
24
+ app.get('/test', {}, async function (request, response) {
25
+ return { res: "plugin, version 1"}
26
+ })
27
+ }`)
28
+
29
+ const config = {
30
+ server: {
31
+ hostname: '127.0.0.1',
32
+ port: 0
33
+ },
34
+ plugins: {
35
+ paths: [pathToPlugin],
36
+ stopTimeout: 1000,
37
+ hotReload: true
38
+ },
39
+ watch: true,
40
+ metrics: false
41
+ }
42
+
43
+ await writeFile(pathToConfig, JSON.stringify(config, null, 2))
44
+ const app = await buildServer(pathToConfig)
45
+
46
+ teardown(async () => {
47
+ await app.close()
48
+ })
49
+ await app.start()
50
+
51
+ {
52
+ const res = await request(`${app.url}/test`, {
53
+ method: 'GET'
54
+ })
55
+ same(await res.body.json(), { res: 'plugin, version 1' }, 'get rest plugin')
56
+ }
57
+
58
+ equal(app.fileWatcher.isWatching, true)
59
+
60
+ await app.platformatic.configManager.update({ ...config, watch: false })
61
+ await app.restart()
62
+
63
+ await writeFile(pathToPlugin, `
64
+ module.exports = async function plugin (app) {
65
+ app.get('/test', {}, async function (request, response) {
66
+ return { res: "plugin, version 2"}
67
+ })
68
+ }`)
69
+
70
+ // wait to be sure that app is not watching files anymore
71
+ await new Promise((resolve) => setTimeout(resolve, 5000))
72
+
73
+ equal(app.fileWatcher, undefined)
74
+
75
+ {
76
+ const res = await request(`${app.url}/test`, {
77
+ method: 'GET'
78
+ })
79
+ equal(res.statusCode, 200)
80
+ // must be unchanged
81
+ same(await res.body.json(), { res: 'plugin, version 1' }, 'get rest plugin')
82
+ }
83
+ })
84
+
85
+ test('should stop watching typescript files after disabling watch option', async ({ teardown, equal, ok, same }) => {
86
+ const tmpDir = await mkdtemp(join(tmpdir(), 'platformatic.service.test-'))
87
+ const pathToPlugin = join(tmpDir, 'plugin.ts')
88
+ const pathToConfig = join(tmpDir, 'platformatic.service.json')
89
+ const pathToTsConfig = join(tmpDir, 'tsconfig.json')
90
+
91
+ teardown(async () => {
92
+ await rm(tmpDir, { recursive: true, force: true })
93
+ })
94
+
95
+ const tsConfig = {
96
+ compilerOptions: {
97
+ module: 'commonjs',
98
+ esModuleInterop: true,
99
+ target: 'es6',
100
+ moduleResolution: 'node',
101
+ sourceMap: true,
102
+ pretty: true,
103
+ noEmitOnError: true,
104
+ outDir: 'dist'
105
+ },
106
+ watchOptions: {
107
+ watchFile: 'fixedPollingInterval',
108
+ watchDirectory: 'fixedPollingInterval',
109
+ fallbackPolling: 'dynamicPriority',
110
+ synchronousWatchDirectory: true,
111
+ excludeDirectories: [
112
+ '**/node_modules',
113
+ 'dist'
114
+ ]
115
+ }
116
+ }
117
+
118
+ await writeFile(pathToPlugin, `
119
+ export default async function plugin (app) {
120
+ app.get('/test', {}, async function (request, response) {
121
+ return { res: "plugin, version 1"}
122
+ })
123
+ }`)
124
+
125
+ const config = {
126
+ server: {
127
+ hostname: '127.0.0.1',
128
+ port: 0
129
+ },
130
+ plugins: {
131
+ paths: [pathToPlugin],
132
+ stopTimeout: 1000,
133
+ hotReload: true,
134
+ typescript: true
135
+ },
136
+ watch: true,
137
+ metrics: false
138
+ }
139
+
140
+ await writeFile(pathToConfig, JSON.stringify(config, null, 2))
141
+ await writeFile(pathToTsConfig, JSON.stringify(tsConfig, null, 2))
142
+
143
+ const app = await buildServer(pathToConfig)
144
+
145
+ teardown(async () => {
146
+ await app.close()
147
+ })
148
+ await app.start()
149
+
150
+ {
151
+ const res = await request(`${app.url}/test`, {
152
+ method: 'GET'
153
+ })
154
+ same(await res.body.json(), { res: 'plugin, version 1' }, 'get rest plugin')
155
+ }
156
+
157
+ ok(app.tsCompilerWatcher)
158
+
159
+ await app.platformatic.configManager.update({ ...config, watch: false })
160
+ await app.restart()
161
+
162
+ await writeFile(pathToPlugin, `
163
+ export default async function plugin (app) {
164
+ app.get('/test', {}, async function (request, response) {
165
+ return { res: "plugin, version 2"}
166
+ })
167
+ }`)
168
+
169
+ // wait to be sure that app is not watching files anymore
170
+ await new Promise((resolve) => setTimeout(resolve, 10000))
171
+
172
+ equal(app.tsCompilerWatcher, undefined)
173
+
174
+ {
175
+ const res = await request(`${app.url}/test`, {
176
+ method: 'GET'
177
+ })
178
+ equal(res.statusCode, 200)
179
+ // must be unchanged
180
+ same(await res.body.json(), { res: 'plugin, version 1' }, 'get rest plugin')
181
+ }
182
+ })
File without changes
File without changes
File without changes