@platformatic/runtime 0.29.0 → 0.30.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/fixtures/dbApp/platformatic.db.json +5 -0
- package/fixtures/dbApp/plugin.js +12 -0
- package/fixtures/start-command-in-runtime.js +2 -1
- package/lib/api-client.js +21 -4
- package/package.json +8 -8
- package/test/api.test.js +10 -0
- package/test/cli/compile.test.mjs +15 -2
- package/test/cli/watch.test.mjs +4 -1
- package/test/start.test.js +13 -0
- package/fixtures/typescript/services/movies/package.json +0 -17
|
@@ -5,7 +5,8 @@ const { startCommandInRuntime } = require('../lib/unified-api')
|
|
|
5
5
|
|
|
6
6
|
async function main () {
|
|
7
7
|
const entrypoint = await startCommandInRuntime(['-c', process.argv[2]])
|
|
8
|
-
const
|
|
8
|
+
const endpoint = process.argv[3] ?? '/'
|
|
9
|
+
const res = await request(entrypoint + endpoint)
|
|
9
10
|
|
|
10
11
|
assert.strictEqual(res.statusCode, 200)
|
|
11
12
|
process.exit(42)
|
package/lib/api-client.js
CHANGED
|
@@ -6,11 +6,15 @@ const { randomUUID } = require('node:crypto')
|
|
|
6
6
|
const MAX_LISTENERS_COUNT = 100
|
|
7
7
|
|
|
8
8
|
class RuntimeApiClient extends EventEmitter {
|
|
9
|
+
#exitCode
|
|
10
|
+
#exitPromise
|
|
11
|
+
|
|
9
12
|
constructor (worker) {
|
|
10
13
|
super()
|
|
11
14
|
this.setMaxListeners(MAX_LISTENERS_COUNT)
|
|
12
15
|
|
|
13
16
|
this.worker = worker
|
|
17
|
+
this.#exitPromise = this.#exitHandler()
|
|
14
18
|
this.worker.on('message', (message) => {
|
|
15
19
|
if (message.operationId) {
|
|
16
20
|
this.emit(message.operationId, message)
|
|
@@ -24,7 +28,7 @@ class RuntimeApiClient extends EventEmitter {
|
|
|
24
28
|
|
|
25
29
|
async close () {
|
|
26
30
|
await this.#sendCommand('plt:stop-services')
|
|
27
|
-
await
|
|
31
|
+
await this.#exitPromise
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
async restart () {
|
|
@@ -59,16 +63,29 @@ class RuntimeApiClient extends EventEmitter {
|
|
|
59
63
|
const operationId = randomUUID()
|
|
60
64
|
|
|
61
65
|
this.worker.postMessage({ operationId, command, params })
|
|
62
|
-
const [message] = await
|
|
66
|
+
const [message] = await Promise.race(
|
|
67
|
+
[once(this, operationId), this.#exitPromise]
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
if (this.#exitCode !== undefined) {
|
|
71
|
+
throw new Error('The runtime exited before the operation completed')
|
|
72
|
+
}
|
|
63
73
|
|
|
64
74
|
const { error, data } = message
|
|
65
75
|
if (error !== null) {
|
|
66
|
-
|
|
67
|
-
return
|
|
76
|
+
throw new Error(error)
|
|
68
77
|
}
|
|
69
78
|
|
|
70
79
|
return JSON.parse(data)
|
|
71
80
|
}
|
|
81
|
+
|
|
82
|
+
async #exitHandler () {
|
|
83
|
+
this.#exitCode = undefined
|
|
84
|
+
return once(this.worker, 'exit').then((msg) => {
|
|
85
|
+
this.#exitCode = msg[0]
|
|
86
|
+
return msg
|
|
87
|
+
})
|
|
88
|
+
}
|
|
72
89
|
}
|
|
73
90
|
|
|
74
91
|
module.exports = RuntimeApiClient
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.30.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
"standard": "^17.1.0",
|
|
25
25
|
"tsd": "^0.28.1",
|
|
26
26
|
"typescript": "^5.1.6",
|
|
27
|
-
"@platformatic/sql-mapper": "0.
|
|
28
|
-
"@platformatic/sql-graphql": "0.
|
|
27
|
+
"@platformatic/sql-mapper": "0.30.0",
|
|
28
|
+
"@platformatic/sql-graphql": "0.30.0"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@hapi/topo": "^6.0.2",
|
|
@@ -40,11 +40,11 @@
|
|
|
40
40
|
"pino": "^8.14.1",
|
|
41
41
|
"pino-pretty": "^10.0.0",
|
|
42
42
|
"undici": "^5.22.1",
|
|
43
|
-
"@platformatic/composer": "0.
|
|
44
|
-
"@platformatic/config": "0.
|
|
45
|
-
"@platformatic/db": "0.
|
|
46
|
-
"@platformatic/service": "0.
|
|
47
|
-
"@platformatic/utils": "0.
|
|
43
|
+
"@platformatic/composer": "0.30.0",
|
|
44
|
+
"@platformatic/config": "0.30.0",
|
|
45
|
+
"@platformatic/db": "0.30.0",
|
|
46
|
+
"@platformatic/service": "0.30.0",
|
|
47
|
+
"@platformatic/utils": "0.30.0"
|
|
48
48
|
},
|
|
49
49
|
"standard": {
|
|
50
50
|
"ignore": [
|
package/test/api.test.js
CHANGED
|
@@ -275,6 +275,16 @@ test('should fail inject request is service is not started', async (t) => {
|
|
|
275
275
|
}
|
|
276
276
|
})
|
|
277
277
|
|
|
278
|
+
test('does not wait forever if worker exits during api operation', async (t) => {
|
|
279
|
+
const configFile = join(fixturesDir, 'configs', 'service-throws-on-start.json')
|
|
280
|
+
const config = await loadConfig({}, ['-c', configFile], platformaticRuntime)
|
|
281
|
+
const app = await buildServer(config.configManager.current)
|
|
282
|
+
|
|
283
|
+
await assert.rejects(async () => {
|
|
284
|
+
await app.start()
|
|
285
|
+
}, /The runtime exited before the operation completed/)
|
|
286
|
+
})
|
|
287
|
+
|
|
278
288
|
test('should handle a lot of runtime api requests', async (t) => {
|
|
279
289
|
const configFile = join(fixturesDir, 'configs', 'monorepo.json')
|
|
280
290
|
const config = await loadConfig({}, ['-c', configFile], platformaticRuntime)
|
|
@@ -5,6 +5,7 @@ import path from 'node:path'
|
|
|
5
5
|
import { cliPath } from './helper.mjs'
|
|
6
6
|
import { execa } from 'execa'
|
|
7
7
|
import { mkdtemp, rm, cp, mkdir } from 'node:fs/promises'
|
|
8
|
+
import { setTimeout as sleep } from 'node:timers/promises'
|
|
8
9
|
|
|
9
10
|
const base = join(import.meta.url, '..', 'tmp')
|
|
10
11
|
|
|
@@ -20,7 +21,6 @@ test('compile without tsconfigs', async () => {
|
|
|
20
21
|
|
|
21
22
|
test('compile with tsconfig', async (t) => {
|
|
22
23
|
const tmpDir = await mkdtemp(path.join(base, 'test-runtime-compile-'))
|
|
23
|
-
|
|
24
24
|
const prev = process.cwd()
|
|
25
25
|
process.chdir(tmpDir)
|
|
26
26
|
t.after(() => {
|
|
@@ -28,7 +28,20 @@ test('compile with tsconfig', async (t) => {
|
|
|
28
28
|
})
|
|
29
29
|
|
|
30
30
|
t.after(async () => {
|
|
31
|
-
|
|
31
|
+
// We give up after 10s.
|
|
32
|
+
// This is because on Windows, it's very hard to delete files if the file
|
|
33
|
+
// system is not collaborating.
|
|
34
|
+
for (let i = 0; i < 10; i++) {
|
|
35
|
+
try {
|
|
36
|
+
await rm(tmpDir, { recursive: true, force: true })
|
|
37
|
+
break
|
|
38
|
+
} catch (err) {
|
|
39
|
+
if (err.code === 'EBUSY') {
|
|
40
|
+
await sleep(1000)
|
|
41
|
+
continue
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
32
45
|
})
|
|
33
46
|
|
|
34
47
|
const folder = join(import.meta.url, '..', '..', 'fixtures', 'typescript')
|
package/test/cli/watch.test.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import assert from 'node:assert'
|
|
2
|
-
import { cp, writeFile, mkdtemp, mkdir } from 'node:fs/promises'
|
|
2
|
+
import { cp, writeFile, mkdtemp, mkdir, rm } from 'node:fs/promises'
|
|
3
3
|
import { join } from 'node:path'
|
|
4
4
|
import { test } from 'node:test'
|
|
5
5
|
import { setTimeout as sleep } from 'node:timers/promises'
|
|
@@ -49,6 +49,7 @@ function createEsmLoggingPlugin (text, reloaded) {
|
|
|
49
49
|
|
|
50
50
|
test('watches CommonJS files', async (t) => {
|
|
51
51
|
const tmpDir = await mkdtemp(join(base, 'watch-'))
|
|
52
|
+
t.after(() => rm(tmpDir, { recursive: true, force: true }))
|
|
52
53
|
t.diagnostic(`using ${tmpDir}`)
|
|
53
54
|
const configFileSrc = join(fixturesDir, 'configs', 'monorepo.json')
|
|
54
55
|
const configFileDst = join(tmpDir, 'configs', 'monorepo.json')
|
|
@@ -78,6 +79,7 @@ test('watches CommonJS files', async (t) => {
|
|
|
78
79
|
|
|
79
80
|
test('watches ESM files', async (t) => {
|
|
80
81
|
const tmpDir = await mkdtemp(join(base, 'watch-'))
|
|
82
|
+
t.after(() => rm(tmpDir, { recursive: true, force: true }))
|
|
81
83
|
t.diagnostic(`using ${tmpDir}`)
|
|
82
84
|
const configFileSrc = join(fixturesDir, 'configs', 'monorepo.json')
|
|
83
85
|
const configFileDst = join(tmpDir, 'configs', 'monorepo.json')
|
|
@@ -106,6 +108,7 @@ test('watches ESM files', async (t) => {
|
|
|
106
108
|
|
|
107
109
|
test('should not hot reload files with `--hot-reload false', async (t) => {
|
|
108
110
|
const tmpDir = await mkdtemp(join(base, 'watch-'))
|
|
111
|
+
t.after(() => rm(tmpDir, { recursive: true, force: true }))
|
|
109
112
|
t.diagnostic(`using ${tmpDir}`)
|
|
110
113
|
const configFileSrc = join(fixturesDir, 'configs', 'monorepo.json')
|
|
111
114
|
const configFileDst = join(tmpDir, 'configs', 'monorepo.json')
|
package/test/start.test.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
const assert = require('node:assert')
|
|
3
|
+
const { spawn } = require('node:child_process')
|
|
3
4
|
const { once } = require('node:events')
|
|
4
5
|
const { join } = require('node:path')
|
|
5
6
|
const { test } = require('node:test')
|
|
@@ -143,3 +144,15 @@ test('can start with a custom environment', async (t) => {
|
|
|
143
144
|
assert.strictEqual(res.statusCode, 200)
|
|
144
145
|
assert.deepStrictEqual(await res.body.json(), { A_CUSTOM_ENV_VAR: 'foobar' })
|
|
145
146
|
})
|
|
147
|
+
|
|
148
|
+
test('handles uncaught exceptions with db app', async (t) => {
|
|
149
|
+
// Test for https://github.com/platformatic/platformatic/issues/1193
|
|
150
|
+
const scriptFile = join(fixturesDir, 'start-command-in-runtime.js')
|
|
151
|
+
const configFile = join(fixturesDir, 'dbApp', 'platformatic.db.json')
|
|
152
|
+
const child = spawn(process.execPath, [scriptFile, configFile, '/async_crash'])
|
|
153
|
+
child.stdout.pipe(process.stdout)
|
|
154
|
+
child.stderr.pipe(process.stderr)
|
|
155
|
+
const [exitCode] = await once(child, 'exit')
|
|
156
|
+
|
|
157
|
+
assert.strictEqual(exitCode, 42)
|
|
158
|
+
})
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"scripts": {
|
|
3
|
-
"start": "npm run clean && platformatic start",
|
|
4
|
-
"clean": "rm -fr ./dist",
|
|
5
|
-
"build": "npx tsc",
|
|
6
|
-
"migrate": "platformatic db migrations apply"
|
|
7
|
-
},
|
|
8
|
-
"devDependencies": {
|
|
9
|
-
"fastify": "^4.18.0"
|
|
10
|
-
},
|
|
11
|
-
"dependencies": {
|
|
12
|
-
"platformatic": "^0.28.1"
|
|
13
|
-
},
|
|
14
|
-
"engines": {
|
|
15
|
-
"node": "^18.8.0 || >=19"
|
|
16
|
-
}
|
|
17
|
-
}
|