@platformatic/runtime 1.23.0 → 1.25.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/configs/monorepo-hotreload.json +32 -0
- package/fixtures/management-api/package.json +4 -0
- package/fixtures/management-api/platformatic.json +14 -0
- package/fixtures/management-api/services/service-1/platformatic.json +13 -0
- package/fixtures/management-api/services/service-1/plugin.js +8 -0
- package/fixtures/management-api/services/service-2/platformatic.json +9 -0
- package/fixtures/management-api/services/service-2/plugin.js +8 -0
- package/lib/api-client.js +21 -5
- package/lib/api.js +34 -3
- package/lib/app.js +9 -4
- package/lib/management-api.js +98 -27
- package/lib/start.js +19 -39
- package/lib/worker.js +15 -16
- package/package.json +13 -10
- package/runtime.mjs +1 -1
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://platformatic.dev/schemas/v0.20.0/runtime",
|
|
3
|
+
"entrypoint": "serviceApp",
|
|
4
|
+
"allowCycles": true,
|
|
5
|
+
"hotReload": true,
|
|
6
|
+
"autoload": {
|
|
7
|
+
"path": "../monorepo",
|
|
8
|
+
"exclude": [
|
|
9
|
+
"docs",
|
|
10
|
+
"composerApp"
|
|
11
|
+
],
|
|
12
|
+
"mappings": {
|
|
13
|
+
"serviceAppWithLogger": {
|
|
14
|
+
"id": "with-logger",
|
|
15
|
+
"config": "platformatic.service.json"
|
|
16
|
+
},
|
|
17
|
+
"serviceAppWithMultiplePlugins": {
|
|
18
|
+
"id": "multi-plugin-service",
|
|
19
|
+
"config": "platformatic.service.json"
|
|
20
|
+
},
|
|
21
|
+
"dbApp": {
|
|
22
|
+
"id": "db-app",
|
|
23
|
+
"config": "platformatic.db.json"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"server": {
|
|
28
|
+
"logger": {
|
|
29
|
+
"level": "trace"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://platformatic.dev/schemas/v1.22.0/runtime",
|
|
3
|
+
"entrypoint": "service-1",
|
|
4
|
+
"allowCycles": true,
|
|
5
|
+
"hotReload": false,
|
|
6
|
+
"autoload": {
|
|
7
|
+
"path": "./services"
|
|
8
|
+
},
|
|
9
|
+
"server": {
|
|
10
|
+
"hostname": "127.0.0.1",
|
|
11
|
+
"port": 0
|
|
12
|
+
},
|
|
13
|
+
"managementApi": true
|
|
14
|
+
}
|
package/lib/api-client.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const { once, EventEmitter } = require('node:events')
|
|
4
4
|
const { randomUUID } = require('node:crypto')
|
|
5
5
|
const errors = require('./errors')
|
|
6
|
+
const { setTimeout: sleep } = require('node:timers/promises')
|
|
6
7
|
|
|
7
8
|
const MAX_LISTENERS_COUNT = 100
|
|
8
9
|
|
|
@@ -27,21 +28,36 @@ class RuntimeApiClient extends EventEmitter {
|
|
|
27
28
|
return this.#sendCommand('plt:start-services')
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
async stop () {
|
|
31
|
-
await this.#sendCommand('plt:stop-services')
|
|
32
|
-
}
|
|
33
|
-
|
|
34
31
|
async close () {
|
|
35
32
|
await this.#sendCommand('plt:stop-services')
|
|
36
33
|
|
|
37
34
|
this.worker.postMessage({ command: 'plt:close' })
|
|
38
|
-
await
|
|
35
|
+
const res = await Promise.race([
|
|
36
|
+
this.#exitPromise,
|
|
37
|
+
// We must kill the worker if it doesn't exit in 10 seconds
|
|
38
|
+
// because it may be stuck in an infinite loop.
|
|
39
|
+
// This is a workaround for
|
|
40
|
+
// https://github.com/nodejs/node/issues/47748
|
|
41
|
+
// https://github.com/nodejs/node/issues/49344
|
|
42
|
+
// Remove once https://github.com/nodejs/node/pull/51290 is released
|
|
43
|
+
// on all lines.
|
|
44
|
+
// Likely to be removed when we drop support for Node.js 18.
|
|
45
|
+
sleep(10000, 'timeout', { ref: false })
|
|
46
|
+
])
|
|
47
|
+
|
|
48
|
+
if (res === 'timeout') {
|
|
49
|
+
this.worker.unref()
|
|
50
|
+
}
|
|
39
51
|
}
|
|
40
52
|
|
|
41
53
|
async restart () {
|
|
42
54
|
return this.#sendCommand('plt:restart-services')
|
|
43
55
|
}
|
|
44
56
|
|
|
57
|
+
async getEntrypointDetails () {
|
|
58
|
+
return this.#sendCommand('plt:get-entrypoint-details')
|
|
59
|
+
}
|
|
60
|
+
|
|
45
61
|
async getServices () {
|
|
46
62
|
return this.#sendCommand('plt:get-services')
|
|
47
63
|
}
|
package/lib/api.js
CHANGED
|
@@ -9,9 +9,11 @@ const { printSchema } = require('graphql')
|
|
|
9
9
|
class RuntimeApi {
|
|
10
10
|
#services
|
|
11
11
|
#dispatcher
|
|
12
|
+
#logger
|
|
12
13
|
|
|
13
14
|
constructor (config, logger, loaderPort) {
|
|
14
15
|
this.#services = new Map()
|
|
16
|
+
this.#logger = logger
|
|
15
17
|
const telemetryConfig = config.telemetry
|
|
16
18
|
|
|
17
19
|
for (let i = 0; i < config.services.length; ++i) {
|
|
@@ -48,8 +50,19 @@ class RuntimeApi {
|
|
|
48
50
|
const command = message?.command
|
|
49
51
|
if (command) {
|
|
50
52
|
if (command === 'plt:close') {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
+
// We close everything because they might be using
|
|
54
|
+
// a FinalizationRegistry and it may stuck us in an infinite loop.
|
|
55
|
+
// This is a workaround for
|
|
56
|
+
// https://github.com/nodejs/node/issues/47748
|
|
57
|
+
// https://github.com/nodejs/node/issues/49344
|
|
58
|
+
// Remove once https://github.com/nodejs/node/pull/51290 is released
|
|
59
|
+
// on all lines.
|
|
60
|
+
// Likely to be removed when we drop support for Node.js 18.
|
|
61
|
+
if (this.#dispatcher) {
|
|
62
|
+
await this.#dispatcher.close()
|
|
63
|
+
}
|
|
64
|
+
setImmediate(process.exit) // Exit the worker thread.
|
|
65
|
+
return
|
|
53
66
|
}
|
|
54
67
|
|
|
55
68
|
const res = await this.#executeCommand(message)
|
|
@@ -97,6 +110,8 @@ class RuntimeApi {
|
|
|
97
110
|
return this.stopServices(params)
|
|
98
111
|
case 'plt:restart-services':
|
|
99
112
|
return this.#restartServices(params)
|
|
113
|
+
case 'plt:get-entrypoint-details':
|
|
114
|
+
return this.#getEntrypointDetails(params)
|
|
100
115
|
case 'plt:get-services':
|
|
101
116
|
return this.#getServices(params)
|
|
102
117
|
case 'plt:get-service-details':
|
|
@@ -162,6 +177,15 @@ class RuntimeApi {
|
|
|
162
177
|
return entrypointUrl
|
|
163
178
|
}
|
|
164
179
|
|
|
180
|
+
#getEntrypointDetails () {
|
|
181
|
+
for (const service of this.#services.values()) {
|
|
182
|
+
if (service.appConfig.entrypoint) {
|
|
183
|
+
return this.#getServiceDetails({ id: service.appConfig.id })
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return null
|
|
187
|
+
}
|
|
188
|
+
|
|
165
189
|
#getServices () {
|
|
166
190
|
const services = { services: [] }
|
|
167
191
|
|
|
@@ -191,8 +215,15 @@ class RuntimeApi {
|
|
|
191
215
|
const service = this.#getServiceById(id)
|
|
192
216
|
const status = service.getStatus()
|
|
193
217
|
|
|
218
|
+
const type = service.config.configType
|
|
194
219
|
const { entrypoint, dependencies, localUrl } = service.appConfig
|
|
195
|
-
|
|
220
|
+
const serviceDetails = { id, type, status, localUrl, entrypoint, dependencies }
|
|
221
|
+
|
|
222
|
+
if (entrypoint) {
|
|
223
|
+
serviceDetails.url = status === 'started' ? service.server.url : null
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return serviceDetails
|
|
196
227
|
}
|
|
197
228
|
|
|
198
229
|
#getServiceConfig ({ id }) {
|
package/lib/app.js
CHANGED
|
@@ -73,7 +73,10 @@ class PlatformaticApp {
|
|
|
73
73
|
this.#setuplogger(this.config.configManager)
|
|
74
74
|
await this.server.restart()
|
|
75
75
|
} catch (err) {
|
|
76
|
-
|
|
76
|
+
// The restart failed. Log the error and
|
|
77
|
+
// wait for another event.
|
|
78
|
+
// The old app is still available
|
|
79
|
+
this.#logger.error({ err })
|
|
77
80
|
}
|
|
78
81
|
|
|
79
82
|
this.#restarting = false
|
|
@@ -245,10 +248,12 @@ class PlatformaticApp {
|
|
|
245
248
|
}
|
|
246
249
|
|
|
247
250
|
#setuplogger (configManager) {
|
|
248
|
-
// Set the logger if not present
|
|
249
251
|
configManager.current.server = configManager.current.server || {}
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
+
const level = configManager.current.server.logger?.level
|
|
253
|
+
|
|
254
|
+
configManager.current.server.logger = level
|
|
255
|
+
? this.#logger.child({ level })
|
|
256
|
+
: this.#logger
|
|
252
257
|
}
|
|
253
258
|
|
|
254
259
|
#startFileWatching () {
|
package/lib/management-api.js
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const { tmpdir, platform } = require('node:os')
|
|
4
|
+
const { join } = require('node:path')
|
|
5
|
+
const { readFile, mkdir, unlink } = require('node:fs/promises')
|
|
3
6
|
const fastify = require('fastify')
|
|
4
|
-
const
|
|
7
|
+
const errors = require('./errors')
|
|
5
8
|
const platformaticVersion = require('../package.json').version
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
const PLATFORMATIC_TMP_DIR = join(tmpdir(), 'platformatic', 'pids')
|
|
11
|
+
|
|
12
|
+
async function createManagementApi (configManager, runtimeApiClient, loggingPort) {
|
|
13
|
+
let apiConfig = configManager.current.managementApi
|
|
14
|
+
if (!apiConfig || apiConfig === true) {
|
|
15
|
+
apiConfig = {}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const app = fastify(apiConfig)
|
|
10
19
|
app.log.warn(
|
|
11
20
|
'Runtime Management API is in the experimental stage. ' +
|
|
12
21
|
'The feature is not subject to semantic versioning rules. ' +
|
|
@@ -14,36 +23,57 @@ async function createManagementApi (config, runtimeApiClient) {
|
|
|
14
23
|
'Use of the feature is not recommended in production environments.'
|
|
15
24
|
)
|
|
16
25
|
|
|
26
|
+
async function getRuntimePackageJson (cwd) {
|
|
27
|
+
const packageJsonPath = join(cwd, 'package.json')
|
|
28
|
+
const packageJsonFile = await readFile(packageJsonPath, 'utf8')
|
|
29
|
+
const packageJson = JSON.parse(packageJsonFile)
|
|
30
|
+
return packageJson
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
app.register(require('@fastify/websocket'))
|
|
34
|
+
|
|
17
35
|
app.register(async (app) => {
|
|
18
36
|
app.get('/metadata', async () => {
|
|
37
|
+
const packageJson = await getRuntimePackageJson(configManager.dirname).catch(() => ({}))
|
|
38
|
+
const entrypointDetails = await runtimeApiClient.getEntrypointDetails().catch(() => null)
|
|
39
|
+
|
|
19
40
|
return {
|
|
20
41
|
pid: process.pid,
|
|
21
42
|
cwd: process.cwd(),
|
|
43
|
+
argv: process.argv,
|
|
44
|
+
uptimeSeconds: Math.floor(process.uptime()),
|
|
22
45
|
execPath: process.execPath,
|
|
23
46
|
nodeVersion: process.version,
|
|
47
|
+
projectDir: configManager.dirname,
|
|
48
|
+
packageName: packageJson.name ?? null,
|
|
49
|
+
packageVersion: packageJson.version ?? null,
|
|
50
|
+
url: entrypointDetails?.url ?? null,
|
|
24
51
|
platformaticVersion
|
|
25
52
|
}
|
|
26
53
|
})
|
|
27
54
|
|
|
28
|
-
app.get('/
|
|
29
|
-
return
|
|
55
|
+
app.get('/config', async () => {
|
|
56
|
+
return configManager.current
|
|
30
57
|
})
|
|
31
58
|
|
|
32
|
-
app.
|
|
33
|
-
|
|
34
|
-
await runtimeApiClient.start()
|
|
59
|
+
app.get('/env', async () => {
|
|
60
|
+
return process.env
|
|
35
61
|
})
|
|
36
62
|
|
|
37
|
-
app.post('/
|
|
63
|
+
app.post('/stop', async () => {
|
|
38
64
|
app.log.debug('stop services')
|
|
39
|
-
await runtimeApiClient.
|
|
65
|
+
await runtimeApiClient.close()
|
|
40
66
|
})
|
|
41
67
|
|
|
42
|
-
app.post('/
|
|
43
|
-
app.log.debug('
|
|
68
|
+
app.post('/reload', async () => {
|
|
69
|
+
app.log.debug('reload services')
|
|
44
70
|
await runtimeApiClient.restart()
|
|
45
71
|
})
|
|
46
72
|
|
|
73
|
+
app.get('/services', async () => {
|
|
74
|
+
return runtimeApiClient.getServices()
|
|
75
|
+
})
|
|
76
|
+
|
|
47
77
|
app.get('/services/:id', async (request) => {
|
|
48
78
|
const { id } = request.params
|
|
49
79
|
app.log.debug('get service details', { id })
|
|
@@ -87,27 +117,68 @@ async function createManagementApi (config, runtimeApiClient) {
|
|
|
87
117
|
.headers(res.headers)
|
|
88
118
|
.send(res.body)
|
|
89
119
|
})
|
|
90
|
-
|
|
120
|
+
|
|
121
|
+
app.get('/logs', { websocket: true }, async (connection, req) => {
|
|
122
|
+
const handler = (message) => {
|
|
123
|
+
for (const log of message.logs) {
|
|
124
|
+
connection.socket.send(log)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
loggingPort.on('message', handler)
|
|
129
|
+
connection.socket.on('close', () => {
|
|
130
|
+
loggingPort.off('message', handler)
|
|
131
|
+
})
|
|
132
|
+
connection.socket.on('error', () => {
|
|
133
|
+
loggingPort.off('message', handler)
|
|
134
|
+
})
|
|
135
|
+
connection.socket.on('end', () => {
|
|
136
|
+
loggingPort.off('message', handler)
|
|
137
|
+
})
|
|
138
|
+
})
|
|
139
|
+
}, { prefix: '/api/v1' })
|
|
91
140
|
|
|
92
141
|
return app
|
|
93
142
|
}
|
|
94
143
|
|
|
95
|
-
function
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
144
|
+
async function startManagementApi (configManager, runtimeApiClient, loggingPort) {
|
|
145
|
+
const runtimePID = process.pid
|
|
146
|
+
|
|
147
|
+
let socketPath = null
|
|
148
|
+
if (platform() === 'win32') {
|
|
149
|
+
socketPath = '\\\\.\\pipe\\platformatic-' + runtimePID
|
|
150
|
+
} else {
|
|
151
|
+
await mkdir(PLATFORMATIC_TMP_DIR, { recursive: true })
|
|
152
|
+
socketPath = join(PLATFORMATIC_TMP_DIR, `${runtimePID}.sock`)
|
|
103
153
|
}
|
|
104
154
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
155
|
+
try {
|
|
156
|
+
await mkdir(PLATFORMATIC_TMP_DIR, { recursive: true })
|
|
157
|
+
await unlink(socketPath).catch((err) => {
|
|
158
|
+
if (err.code !== 'ENOENT') {
|
|
159
|
+
throw new errors.FailedToUnlinkManagementApiSocket(err.message)
|
|
160
|
+
}
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
const managementApi = await createManagementApi(
|
|
164
|
+
configManager,
|
|
165
|
+
runtimeApiClient,
|
|
166
|
+
loggingPort
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
if (platform() !== 'win32') {
|
|
170
|
+
managementApi.addHook('onClose', async () => {
|
|
171
|
+
await unlink(socketPath).catch(() => {})
|
|
172
|
+
})
|
|
109
173
|
}
|
|
174
|
+
|
|
175
|
+
await managementApi.listen({ path: socketPath })
|
|
176
|
+
return managementApi
|
|
177
|
+
/* c8 ignore next 4 */
|
|
178
|
+
} catch (err) {
|
|
179
|
+
console.error(err)
|
|
180
|
+
process.exit(1)
|
|
110
181
|
}
|
|
111
182
|
}
|
|
112
183
|
|
|
113
|
-
module.exports = { createManagementApi }
|
|
184
|
+
module.exports = { startManagementApi, createManagementApi }
|
package/lib/start.js
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { tmpdir, platform } = require('node:os')
|
|
4
3
|
const { once } = require('node:events')
|
|
5
4
|
const inspector = require('node:inspector')
|
|
6
5
|
const { join, resolve, dirname } = require('node:path')
|
|
7
|
-
const { writeFile
|
|
6
|
+
const { writeFile } = require('node:fs/promises')
|
|
8
7
|
const { pathToFileURL } = require('node:url')
|
|
9
8
|
const { Worker } = require('node:worker_threads')
|
|
10
9
|
const { start: serviceStart } = require('@platformatic/service')
|
|
11
10
|
const { printConfigValidationErrors } = require('@platformatic/config')
|
|
12
11
|
const closeWithGrace = require('close-with-grace')
|
|
13
12
|
const { loadConfig } = require('./load-config')
|
|
14
|
-
const {
|
|
13
|
+
const { startManagementApi } = require('./management-api')
|
|
15
14
|
const { parseInspectorOptions, wrapConfigInRuntimeConfig } = require('./config')
|
|
16
15
|
const RuntimeApiClient = require('./api-client.js')
|
|
17
16
|
const errors = require('./errors')
|
|
@@ -25,8 +24,6 @@ const kWorkerExecArgv = [
|
|
|
25
24
|
kLoaderFile
|
|
26
25
|
]
|
|
27
26
|
|
|
28
|
-
const PLATFORMATIC_TMP_DIR = join(tmpdir(), 'platformatic', 'pids')
|
|
29
|
-
|
|
30
27
|
async function startWithConfig (configManager, env = process.env) {
|
|
31
28
|
const config = configManager.current
|
|
32
29
|
|
|
@@ -47,10 +44,21 @@ async function startWithConfig (configManager, env = process.env) {
|
|
|
47
44
|
// The configManager cannot be transferred to the worker, so remove it.
|
|
48
45
|
delete config.configManager
|
|
49
46
|
|
|
47
|
+
let mainLoggingPort = null
|
|
48
|
+
let childLoggingPort = config.loggingPort
|
|
49
|
+
|
|
50
|
+
if (!childLoggingPort && config.managementApi) {
|
|
51
|
+
const { port1, port2 } = new MessageChannel()
|
|
52
|
+
mainLoggingPort = port1
|
|
53
|
+
childLoggingPort = port2
|
|
54
|
+
|
|
55
|
+
config.loggingPort = childLoggingPort
|
|
56
|
+
}
|
|
57
|
+
|
|
50
58
|
const worker = new Worker(kWorkerFile, {
|
|
51
59
|
/* c8 ignore next */
|
|
52
60
|
execArgv: config.hotReload ? kWorkerExecArgv : [],
|
|
53
|
-
transferList:
|
|
61
|
+
transferList: childLoggingPort ? [childLoggingPort] : [],
|
|
54
62
|
workerData: { config, dirname },
|
|
55
63
|
env
|
|
56
64
|
})
|
|
@@ -106,7 +114,11 @@ async function startWithConfig (configManager, env = process.env) {
|
|
|
106
114
|
const runtimeApiClient = new RuntimeApiClient(worker)
|
|
107
115
|
|
|
108
116
|
if (config.managementApi) {
|
|
109
|
-
managementApi = await startManagementApi(
|
|
117
|
+
managementApi = await startManagementApi(
|
|
118
|
+
configManager,
|
|
119
|
+
runtimeApiClient,
|
|
120
|
+
mainLoggingPort
|
|
121
|
+
)
|
|
110
122
|
runtimeApiClient.managementApi = managementApi
|
|
111
123
|
}
|
|
112
124
|
|
|
@@ -126,38 +138,6 @@ async function start (args) {
|
|
|
126
138
|
return serviceStart(config.app, args)
|
|
127
139
|
}
|
|
128
140
|
|
|
129
|
-
async function startManagementApi (managementApiConfig, runtimeApiClient) {
|
|
130
|
-
const runtimePID = process.pid
|
|
131
|
-
|
|
132
|
-
let socketPath = null
|
|
133
|
-
if (platform() === 'win32') {
|
|
134
|
-
socketPath = '\\\\.\\pipe\\' + join(PLATFORMATIC_TMP_DIR, `${runtimePID}.sock`)
|
|
135
|
-
} else {
|
|
136
|
-
await mkdir(PLATFORMATIC_TMP_DIR, { recursive: true })
|
|
137
|
-
socketPath = join(PLATFORMATIC_TMP_DIR, `${runtimePID}.sock`)
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
try {
|
|
141
|
-
await mkdir(PLATFORMATIC_TMP_DIR, { recursive: true })
|
|
142
|
-
await unlink(socketPath).catch((err) => {
|
|
143
|
-
if (err.code !== 'ENOENT') {
|
|
144
|
-
throw new errors.FailedToUnlinkManagementApiSocket(err.message)
|
|
145
|
-
}
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
const managementApi = await createManagementApi(
|
|
149
|
-
managementApiConfig,
|
|
150
|
-
runtimeApiClient
|
|
151
|
-
)
|
|
152
|
-
await managementApi.listen({ path: socketPath })
|
|
153
|
-
return managementApi
|
|
154
|
-
/* c8 ignore next 4 */
|
|
155
|
-
} catch (err) {
|
|
156
|
-
console.error(err)
|
|
157
|
-
process.exit(1)
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
141
|
async function startCommand (args) {
|
|
162
142
|
try {
|
|
163
143
|
const config = await loadConfig({}, args)
|
package/lib/worker.js
CHANGED
|
@@ -12,6 +12,7 @@ const {
|
|
|
12
12
|
} = require('node:worker_threads')
|
|
13
13
|
const undici = require('undici')
|
|
14
14
|
const pino = require('pino')
|
|
15
|
+
const pretty = require('pino-pretty')
|
|
15
16
|
const { setGlobalDispatcher, Agent } = require('undici')
|
|
16
17
|
const RuntimeApi = require('./api')
|
|
17
18
|
const { MessagePortWritable } = require('./message-port-writable')
|
|
@@ -33,30 +34,28 @@ globalThis.fetch = undici.fetch
|
|
|
33
34
|
|
|
34
35
|
const config = workerData.config
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
const loggerConfig = { ...config.server?.logger }
|
|
38
|
+
const cliStream = isatty(1) ? pretty() : pino.destination(1)
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
loggerConfig = { ...loggerConfig }
|
|
41
|
-
} else {
|
|
42
|
-
loggerConfig = {}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/* c8 ignore next 10 */
|
|
40
|
+
let logger = null
|
|
46
41
|
if (config.loggingPort) {
|
|
47
|
-
|
|
42
|
+
const portStream = new MessagePortWritable({
|
|
48
43
|
metadata: config.loggingMetadata,
|
|
49
44
|
port: config.loggingPort
|
|
50
45
|
})
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
46
|
+
const multiStream = pino.multistream([
|
|
47
|
+
{ stream: portStream, level: 'trace' },
|
|
48
|
+
{ stream: cliStream, level: loggerConfig.level || 'info' }
|
|
49
|
+
])
|
|
50
|
+
if (loggerConfig.transport) {
|
|
51
|
+
const transport = pino.transport(loggerConfig.transport)
|
|
52
|
+
multiStream.add({ level: loggerConfig.level || 'info', stream: transport })
|
|
55
53
|
}
|
|
54
|
+
logger = pino({ level: 'trace' }, multiStream)
|
|
55
|
+
} else {
|
|
56
|
+
logger = pino(loggerConfig, cliStream)
|
|
56
57
|
}
|
|
57
58
|
|
|
58
|
-
const logger = pino(loggerConfig, destination)
|
|
59
|
-
|
|
60
59
|
if (config.server) {
|
|
61
60
|
config.server.logger = logger
|
|
62
61
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/runtime",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.25.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"homepage": "https://github.com/platformatic/platformatic#readme",
|
|
19
19
|
"devDependencies": {
|
|
20
20
|
"@fastify/express": "^2.3.0",
|
|
21
|
+
"@matteo.collina/tspl": "^0.1.1",
|
|
21
22
|
"borp": "^0.9.0",
|
|
22
23
|
"c8": "^9.1.0",
|
|
23
24
|
"execa": "^8.0.1",
|
|
@@ -30,11 +31,13 @@
|
|
|
30
31
|
"tsd": "^0.30.4",
|
|
31
32
|
"typescript": "^5.3.3",
|
|
32
33
|
"undici-oauth-interceptor": "^0.4.2",
|
|
33
|
-
"
|
|
34
|
-
"@platformatic/sql-mapper": "1.
|
|
34
|
+
"ws": "^8.16.0",
|
|
35
|
+
"@platformatic/sql-mapper": "1.25.0",
|
|
36
|
+
"@platformatic/sql-graphql": "1.25.0"
|
|
35
37
|
},
|
|
36
38
|
"dependencies": {
|
|
37
39
|
"@fastify/error": "^3.4.1",
|
|
40
|
+
"@fastify/websocket": "^9.0.0",
|
|
38
41
|
"@hapi/topo": "^6.0.2",
|
|
39
42
|
"boring-name-generator": "^1.0.3",
|
|
40
43
|
"close-with-grace": "^1.2.0",
|
|
@@ -52,13 +55,13 @@
|
|
|
52
55
|
"pino-pretty": "^10.3.1",
|
|
53
56
|
"undici": "^6.6.0",
|
|
54
57
|
"why-is-node-running": "^2.2.2",
|
|
55
|
-
"@platformatic/composer": "1.
|
|
56
|
-
"@platformatic/config": "1.
|
|
57
|
-
"@platformatic/
|
|
58
|
-
"@platformatic/service": "1.
|
|
59
|
-
"@platformatic/
|
|
60
|
-
"@platformatic/
|
|
61
|
-
"@platformatic/utils": "1.
|
|
58
|
+
"@platformatic/composer": "1.25.0",
|
|
59
|
+
"@platformatic/config": "1.25.0",
|
|
60
|
+
"@platformatic/generators": "1.25.0",
|
|
61
|
+
"@platformatic/service": "1.25.0",
|
|
62
|
+
"@platformatic/telemetry": "1.25.0",
|
|
63
|
+
"@platformatic/db": "1.25.0",
|
|
64
|
+
"@platformatic/utils": "1.25.0"
|
|
62
65
|
},
|
|
63
66
|
"standard": {
|
|
64
67
|
"ignore": [
|
package/runtime.mjs
CHANGED