@platformatic/runtime 0.46.1 → 0.47.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.
@@ -1,230 +0,0 @@
1
- 'use strict'
2
-
3
- const assert = require('node:assert')
4
- const { join } = require('node:path')
5
- const { test } = require('node:test')
6
- const { loadConfig } = require('@platformatic/config')
7
- const { platformaticService } = require('@platformatic/service')
8
- const { parseInspectorOptions, platformaticRuntime } = require('../lib/config')
9
- const fixturesDir = join(__dirname, '..', 'fixtures')
10
-
11
- test('throws if no entrypoint is found', async (t) => {
12
- const configFile = join(fixturesDir, 'configs', 'invalid-entrypoint.json')
13
-
14
- platformaticRuntime() // Coverage cheat.
15
-
16
- await assert.rejects(async () => {
17
- await loadConfig({}, ['-c', configFile], platformaticRuntime)
18
- }, /Invalid entrypoint: 'invalid' does not exist/)
19
- })
20
-
21
- test('throws if a config file is not found for an individual service', async (t) => {
22
- const configFile = join(fixturesDir, 'configs', 'missing-service-config.json')
23
-
24
- await assert.rejects(async () => {
25
- await loadConfig({}, ['-c', configFile], platformaticRuntime)
26
- }, /No config file found for service 'docs'/)
27
- })
28
-
29
- test('performs a topological sort on services depending on allowCycles', async (t) => {
30
- await t.test('does not sort if allowCycles is true', async () => {
31
- const configFile = join(fixturesDir, 'configs', 'monorepo.json')
32
- const loaded = await loadConfig({}, ['-c', configFile], platformaticRuntime)
33
- const services = loaded.configManager.current.services
34
-
35
- assert.strictEqual(services.length, 3)
36
- assert.strictEqual(services[0].id, 'serviceApp')
37
- assert.strictEqual(services[1].id, 'with-logger')
38
- assert.strictEqual(services[2].id, 'multi-plugin-service')
39
- })
40
-
41
- await t.test('sorts if allowCycles is false', async () => {
42
- const configFile = join(fixturesDir, 'configs', 'monorepo-no-cycles.json')
43
- const loaded = await loadConfig({}, ['-c', configFile], platformaticRuntime)
44
- const services = loaded.configManager.current.services
45
-
46
- assert.strictEqual(services.length, 3)
47
- assert.strictEqual(services[0].id, 'with-logger')
48
- assert.strictEqual(services[1].id, 'serviceApp')
49
- assert.strictEqual(services[2].id, 'multi-plugin-service')
50
- })
51
-
52
- await t.test('throws if a cycle is present when not allowed', async () => {
53
- const configFile = join(fixturesDir, 'configs', 'monorepo-create-cycle.json')
54
-
55
- await assert.rejects(async () => {
56
- await loadConfig({}, ['-c', configFile], platformaticRuntime)
57
- })
58
- })
59
-
60
- await t.test('throws by adding the most probable service ', async () => {
61
- const configFile = join(fixturesDir, 'leven', 'platformatic.runtime.json')
62
-
63
- await assert.rejects(async () => {
64
- await loadConfig({}, ['-c', configFile], platformaticRuntime)
65
- }, 'service \'rainy-empire\' has unordered dependency: \'deeply-splitte\'. Did you mean \'deeply-spittle\'?')
66
- })
67
- })
68
-
69
- test('can resolve service id from client package.json if not provided', async () => {
70
- const configFile = join(fixturesDir, 'configs', 'monorepo-client-without-id.json')
71
- const config = await loadConfig({}, ['-c', configFile], platformaticRuntime)
72
- const entry = config.configManager.current.serviceMap.get('serviceApp')
73
-
74
- assert.strictEqual(entry.dependencies.length, 1)
75
- assert.strictEqual(entry.dependencies[0].id, 'with-logger')
76
- })
77
-
78
- test('parseInspectorOptions()', async (t) => {
79
- await t.test('throws if --inspect and --inspect-brk are both used', () => {
80
- assert.throws(() => {
81
- const cm = {
82
- args: { inspect: '', 'inspect-brk': '' },
83
- current: {}
84
- }
85
-
86
- parseInspectorOptions(cm)
87
- }, /--inspect and --inspect-brk cannot be used together/)
88
- })
89
-
90
- await t.test('--inspect default settings', () => {
91
- const cm = {
92
- args: { inspect: '' },
93
- current: {}
94
- }
95
-
96
- parseInspectorOptions(cm)
97
- assert.deepStrictEqual(cm.current.inspectorOptions, {
98
- host: '127.0.0.1',
99
- port: 9229,
100
- breakFirstLine: false,
101
- hotReloadDisabled: false
102
- })
103
- })
104
-
105
- await t.test('--inspect-brk default settings', () => {
106
- const cm = {
107
- args: { 'inspect-brk': '' },
108
- current: {}
109
- }
110
-
111
- parseInspectorOptions(cm)
112
- assert.deepStrictEqual(cm.current.inspectorOptions, {
113
- host: '127.0.0.1',
114
- port: 9229,
115
- breakFirstLine: true,
116
- hotReloadDisabled: false
117
- })
118
- })
119
-
120
- await t.test('hot reloading is disabled if the inspector is used', () => {
121
- const cm1 = {
122
- args: { 'inspect-brk': '' },
123
- current: { hotReload: true }
124
- }
125
-
126
- parseInspectorOptions(cm1)
127
- assert.strictEqual(cm1.current.hotReload, false)
128
-
129
- const cm2 = {
130
- args: {},
131
- current: { hotReload: true }
132
- }
133
-
134
- parseInspectorOptions(cm2)
135
- assert.strictEqual(cm2.current.hotReload, true)
136
- })
137
-
138
- await t.test('sets port to a custom value', () => {
139
- const cm = {
140
- args: { inspect: '6666' },
141
- current: {}
142
- }
143
-
144
- parseInspectorOptions(cm)
145
- assert.deepStrictEqual(cm.current.inspectorOptions, {
146
- host: '127.0.0.1',
147
- port: 6666,
148
- breakFirstLine: false,
149
- hotReloadDisabled: false
150
- })
151
- })
152
-
153
- await t.test('sets host and port to custom values', () => {
154
- const cm = {
155
- args: { inspect: '0.0.0.0:6666' },
156
- current: {}
157
- }
158
-
159
- parseInspectorOptions(cm)
160
- assert.deepStrictEqual(cm.current.inspectorOptions, {
161
- host: '0.0.0.0',
162
- port: 6666,
163
- breakFirstLine: false,
164
- hotReloadDisabled: false
165
- })
166
- })
167
-
168
- await t.test('throws if the host is empty', () => {
169
- assert.throws(() => {
170
- const cm = {
171
- args: { inspect: ':9229' },
172
- current: {}
173
- }
174
-
175
- parseInspectorOptions(cm)
176
- }, /Inspector host cannot be empty/)
177
- })
178
-
179
- await t.test('differentiates valid and invalid ports', () => {
180
- ['127.0.0.1:', 'foo', '1', '-1', '1023', '65536'].forEach((inspectFlag) => {
181
- assert.throws(() => {
182
- const cm = {
183
- args: { inspect: inspectFlag },
184
- current: {}
185
- }
186
-
187
- parseInspectorOptions(cm)
188
- }, /Inspector port must be 0 or in range 1024 to 65535/)
189
- })
190
-
191
- const cm = {
192
- args: {},
193
- current: {}
194
- }
195
-
196
- cm.args.inspect = '0'
197
- parseInspectorOptions(cm)
198
- assert.strictEqual(cm.current.inspectorOptions.port, 0)
199
- cm.args.inspect = '1024'
200
- parseInspectorOptions(cm)
201
- assert.strictEqual(cm.current.inspectorOptions.port, 1024)
202
- cm.args.inspect = '1025'
203
- parseInspectorOptions(cm)
204
- assert.strictEqual(cm.current.inspectorOptions.port, 1025)
205
- cm.args.inspect = '65534'
206
- parseInspectorOptions(cm)
207
- assert.strictEqual(cm.current.inspectorOptions.port, 65534)
208
- cm.args.inspect = '65535'
209
- parseInspectorOptions(cm)
210
- assert.strictEqual(cm.current.inspectorOptions.port, 65535)
211
- })
212
- })
213
-
214
- test('same schemaOptions as platformatic service', async () => {
215
- assert.deepStrictEqual(platformaticRuntime.schemaOptions, platformaticService.schemaOptions)
216
- })
217
-
218
- test('correctly loads the hotReload value from a string', async () => {
219
- const configFile = join(fixturesDir, 'configs', 'monorepo-hotreload-env.json')
220
- process.env.PLT_HOT_RELOAD = 'true'
221
- const loaded = await loadConfig({}, ['-c', configFile], platformaticRuntime)
222
- assert.strictEqual(loaded.configManager.current.hotReload, true)
223
- })
224
-
225
- test('correctly loads the hotReload value from a string', async () => {
226
- const configFile = join(fixturesDir, 'configs', 'monorepo-hotreload-env.json')
227
- process.env.PLT_HOT_RELOAD = 'false'
228
- const loaded = await loadConfig({}, ['-c', configFile], platformaticRuntime)
229
- assert.strictEqual(loaded.configManager.current.hotReload, false)
230
- })
@@ -1,13 +0,0 @@
1
- 'use strict'
2
-
3
- const assert = require('node:assert')
4
- const { join } = require('node:path')
5
- const { test } = require('node:test')
6
- const { schema } = require('../lib/schema')
7
-
8
- test('schema output', async (t) => {
9
- const { execa } = await import('execa')
10
- const { stdout } = await execa(process.execPath, [join(__dirname, '..', 'lib', 'schema.js')])
11
-
12
- assert.deepStrictEqual(stdout, JSON.stringify(schema, null, 2))
13
- })
@@ -1,187 +0,0 @@
1
- 'use strict'
2
- const assert = require('node:assert')
3
- const { spawn } = require('node:child_process')
4
- const { once } = require('node:events')
5
- const { join } = require('node:path')
6
- const { test } = require('node:test')
7
- const { MessageChannel } = require('node:worker_threads')
8
- const { request } = require('undici')
9
- const { loadConfig } = require('@platformatic/config')
10
- const { platformaticDB } = require('@platformatic/db')
11
- const { buildServer, platformaticRuntime } = require('..')
12
- const { wrapConfigInRuntimeConfig } = require('../lib/config')
13
- const { startWithConfig } = require('../lib/start')
14
- const fixturesDir = join(__dirname, '..', 'fixtures')
15
-
16
- test('can start applications programmatically from object', async (t) => {
17
- const configFile = join(fixturesDir, 'configs', 'monorepo.json')
18
- const config = await loadConfig({}, ['-c', configFile], platformaticRuntime)
19
- const app = await buildServer(config.configManager.current)
20
- const entryUrl = await app.start()
21
-
22
- t.after(async () => {
23
- await app.close()
24
- })
25
-
26
- const res = await request(entryUrl)
27
-
28
- assert.strictEqual(res.statusCode, 200)
29
- assert.deepStrictEqual(await res.body.json(), { hello: 'hello123' })
30
- })
31
-
32
- test('can start applications programmatically from string', async (t) => {
33
- const configFile = join(fixturesDir, 'configs', 'monorepo.json')
34
- const app = await buildServer(configFile)
35
- const entryUrl = await app.start()
36
-
37
- t.after(async () => {
38
- await app.close()
39
- })
40
-
41
- {
42
- // Basic URL on the entrypoint.
43
- const res = await request(entryUrl)
44
-
45
- assert.strictEqual(res.statusCode, 200)
46
- assert.deepStrictEqual(await res.body.json(), { hello: 'hello123' })
47
- }
48
-
49
- {
50
- // URL on the entrypoint that uses internal message passing.
51
- const res = await request(entryUrl + '/upstream')
52
-
53
- assert.strictEqual(res.statusCode, 200)
54
- assert.deepStrictEqual(await res.body.json(), { hello: 'world' })
55
- }
56
- })
57
-
58
- test('composer', async (t) => {
59
- const configFile = join(fixturesDir, 'configs', 'monorepo-composer.json')
60
- const config = await loadConfig({}, ['-c', configFile], platformaticRuntime)
61
- const app = await buildServer(config.configManager.current)
62
- const entryUrl = await app.start()
63
-
64
- t.after(async () => {
65
- await app.close()
66
- })
67
-
68
- {
69
- const res = await request(entryUrl)
70
-
71
- assert.strictEqual(res.statusCode, 200)
72
- assert.deepStrictEqual(await res.body.json(), { message: 'Welcome to Platformatic! Please visit https://docs.platformatic.dev' })
73
- }
74
-
75
- {
76
- const res = await request(entryUrl + '/service-app/')
77
-
78
- assert.strictEqual(res.statusCode, 200)
79
- assert.deepStrictEqual(await res.body.json(), { hello: 'hello123' })
80
- }
81
- })
82
-
83
- test('can restart the runtime apps', async (t) => {
84
- const configFile = join(fixturesDir, 'configs', 'monorepo.json')
85
- const app = await buildServer(configFile)
86
- const entryUrl = await app.start()
87
-
88
- t.after(async () => {
89
- await app.close()
90
- })
91
-
92
- {
93
- const res = await request(entryUrl + '/upstream')
94
-
95
- assert.strictEqual(res.statusCode, 200)
96
- assert.deepStrictEqual(await res.body.json(), { hello: 'world' })
97
- }
98
-
99
- await app.restart()
100
-
101
- {
102
- const res = await request(entryUrl + '/upstream')
103
-
104
- assert.strictEqual(res.statusCode, 200)
105
- assert.deepStrictEqual(await res.body.json(), { hello: 'world' })
106
- }
107
- })
108
-
109
- test('supports logging via message port', async (t) => {
110
- const configFile = join(fixturesDir, 'configs', 'monorepo.json')
111
- const config = await loadConfig({}, ['-c', configFile], platformaticRuntime)
112
- const { port1, port2 } = new MessageChannel()
113
- config.configManager.current.loggingPort = port2
114
- config.configManager.current.loggingMetadata = { foo: 1, bar: 2 }
115
- const app = await buildServer(config.configManager.current)
116
- await app.start()
117
-
118
- t.after(async () => {
119
- await app.close()
120
- })
121
-
122
- const [msg] = await once(port1, 'message')
123
-
124
- assert.deepStrictEqual(msg.metadata, { foo: 1, bar: 2 })
125
- assert(Array.isArray(msg.logs))
126
- assert(msg.logs.length > 0)
127
-
128
- for (let i = 0; i < msg.logs.length; ++i) {
129
- // Verify that each log is valid JSON.
130
- JSON.parse(msg.logs[i])
131
- }
132
- })
133
-
134
- test('can start with a custom environment', async (t) => {
135
- const configFile = join(fixturesDir, 'configs', 'monorepo.json')
136
- const config = await loadConfig({}, ['-c', configFile], platformaticRuntime)
137
- const app = await startWithConfig(config.configManager, { A_CUSTOM_ENV_VAR: 'foobar' })
138
-
139
- t.after(async () => {
140
- await app.close()
141
- })
142
-
143
- const entryUrl = await app.start()
144
- const res = await request(entryUrl + '/env')
145
-
146
- assert.strictEqual(res.statusCode, 200)
147
- assert.deepStrictEqual(await res.body.json(), { A_CUSTOM_ENV_VAR: 'foobar' })
148
- })
149
-
150
- test('handles uncaught exceptions with db app', async (t) => {
151
- // Test for https://github.com/platformatic/platformatic/issues/1193
152
- const scriptFile = join(fixturesDir, 'start-command-in-runtime.js')
153
- const configFile = join(fixturesDir, 'dbApp', 'platformatic.db.json')
154
- const child = spawn(process.execPath, [scriptFile, configFile, '/async_crash'])
155
- child.stdout.pipe(process.stdout)
156
- child.stderr.pipe(process.stderr)
157
- const [exitCode] = await once(child, 'exit')
158
-
159
- assert.strictEqual(exitCode, 42)
160
- })
161
-
162
- test('logs errors during db migrations', async (t) => {
163
- const configFile = join(fixturesDir, 'dbAppWithMigrationError', 'platformatic.db.json')
164
- const config = await loadConfig({}, ['-c', configFile], platformaticDB)
165
- const runtimeConfig = await wrapConfigInRuntimeConfig(config)
166
- const { port1, port2 } = new MessageChannel()
167
- runtimeConfig.current.loggingPort = port2
168
- runtimeConfig.current.loggingMetadata = { foo: 1, bar: 2 }
169
- const runtime = await startWithConfig(runtimeConfig)
170
- const messages = []
171
-
172
- port1.on('message', (msg) => {
173
- messages.push(msg)
174
- })
175
-
176
- await assert.rejects(async () => {
177
- await runtime.start()
178
- }, /The runtime exited before the operation completed/)
179
-
180
- assert.strictEqual(messages.length, 2)
181
- assert.deepStrictEqual(messages[0].metadata, runtimeConfig.current.loggingMetadata)
182
- assert.strictEqual(messages[0].logs.length, 1)
183
- assert.match(messages[0].logs[0], /running 001.do.sql/)
184
- assert.deepStrictEqual(messages[1].metadata, runtimeConfig.current.loggingMetadata)
185
- assert.strictEqual(messages[1].logs.length, 1)
186
- assert.match(messages[1].logs[0], /near \\"fiddlesticks\\": syntax error/)
187
- })
@@ -1,37 +0,0 @@
1
- 'use strict'
2
-
3
- const assert = require('node:assert')
4
- const { request } = require('undici')
5
- const { test } = require('node:test')
6
- const { join } = require('node:path')
7
- const { loadConfig } = require('@platformatic/config')
8
- const { platformaticRuntime } = require('..')
9
- const { startWithConfig } = require('../lib/start')
10
- const fixturesDir = join(__dirname, '..', 'fixtures')
11
-
12
- test('propagate the traceId correctly to runtime services', async (t) => {
13
- const configFile = join(fixturesDir, 'telemetry', 'platformatic.runtime.json')
14
- const config = await loadConfig({}, ['-c', configFile], platformaticRuntime)
15
- const app = await startWithConfig(config.configManager)
16
-
17
- t.after(async () => {
18
- await app.close()
19
- })
20
-
21
- const entryUrl = await app.start()
22
-
23
- const traceId = '5e994e8fb53b27c91dcd2fec22771d15'
24
- const spanId = '166f3ab30f21800b'
25
- const traceparent = `00-${traceId}-${spanId}-01`
26
- const res = await request(entryUrl, {
27
- method: 'GET',
28
- path: '/',
29
- headers: {
30
- traceparent
31
- }
32
- })
33
-
34
- assert.strictEqual(res.statusCode, 200)
35
- const response = await res.body.json()
36
- assert.strictEqual(response.traceId, traceId)
37
- })