@platformatic/control 1.24.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/lib/logs.js CHANGED
@@ -1,8 +1,18 @@
1
1
  'use strict'
2
2
 
3
3
  const { parseArgs } = require('node:util')
4
+ const { prettyFactory } = require('pino-pretty')
4
5
  const RuntimeApiClient = require('./runtime-api-client')
5
6
 
7
+ const pinoLogLevels = {
8
+ fatal: 60,
9
+ error: 50,
10
+ warn: 40,
11
+ info: 30,
12
+ debug: 20,
13
+ trace: 10
14
+ }
15
+
6
16
  async function streamRuntimeLogsCommand (argv) {
7
17
  const args = parseArgs({
8
18
  args: argv,
@@ -10,7 +20,7 @@ async function streamRuntimeLogsCommand (argv) {
10
20
  pid: { type: 'string', short: 'p' },
11
21
  name: { type: 'string', short: 'n' },
12
22
  level: { type: 'string', short: 'l', default: 'info' },
13
- pretty: { type: 'boolean', default: true },
23
+ pretty: { type: 'string', default: 'true' },
14
24
  service: { type: 'string', short: 's' }
15
25
  },
16
26
  strict: false
@@ -19,19 +29,30 @@ async function streamRuntimeLogsCommand (argv) {
19
29
  const client = new RuntimeApiClient()
20
30
  const runtime = await client.getMatchingRuntime(args)
21
31
 
22
- const options = {}
23
- if (args.level !== undefined) {
24
- options.level = args.level
25
- }
26
- if (args.pretty !== undefined) {
27
- options.pretty = args.pretty
28
- }
29
- if (args.service !== undefined) {
30
- options.serviceId = args.service
31
- }
32
-
33
- const logsStream = client.getRuntimeLogsStream(runtime.pid, options)
34
- logsStream.pipe(process.stdout)
32
+ const logLevelNumber = pinoLogLevels[args.level]
33
+ const prettify = prettyFactory()
34
+
35
+ const logsStream = client.getRuntimeLogsStream(runtime.pid)
36
+
37
+ logsStream.on('data', (data) => {
38
+ const logs = data.toString().split('\n')
39
+
40
+ for (let log of logs) {
41
+ try {
42
+ const parsedLog = JSON.parse(log)
43
+ if (parsedLog.level < logLevelNumber) continue
44
+ if (args.service && parsedLog.name !== args.service) continue
45
+ if (args.pretty !== 'false') {
46
+ log = prettify(parsedLog)
47
+ } else {
48
+ log += '\n'
49
+ }
50
+ process.stdout.write(log)
51
+ } catch (err) {
52
+ console.error('Failed to parse log message: ', log, err)
53
+ }
54
+ }
55
+ })
35
56
 
36
57
  process.on('SIGINT', () => {
37
58
  logsStream.destroy()
@@ -3,7 +3,7 @@
3
3
  const { tmpdir, platform, EOL } = require('node:os')
4
4
  const { join } = require('node:path')
5
5
  const { exec, spawn } = require('node:child_process')
6
- const { readdir } = require('node:fs/promises')
6
+ const { readdir, unlink, access } = require('node:fs/promises')
7
7
  const { Readable } = require('node:stream')
8
8
  const { Client } = require('undici')
9
9
  const WebSocket = require('ws')
@@ -44,16 +44,25 @@ class RuntimeApiClient {
44
44
  })
45
45
  )
46
46
 
47
- return getMetadataRequests
48
- .filter(result => result.status === 'fulfilled')
49
- .map(result => result.value)
47
+ const runtimes = []
48
+ for (let i = 0; i < runtimePIDs.length; i++) {
49
+ const runtimePID = runtimePIDs[i]
50
+ const metadataRequest = getMetadataRequests[i]
51
+
52
+ if (metadataRequest.status === 'rejected') {
53
+ await this.#removeRuntimeSocket(runtimePID).catch(() => {})
54
+ } else {
55
+ runtimes.push(metadataRequest.value)
56
+ }
57
+ }
58
+ return runtimes
50
59
  }
51
60
 
52
61
  async getRuntimeMetadata (pid) {
53
62
  const client = this.#getUndiciClient(pid)
54
63
 
55
64
  const { statusCode, body } = await client.request({
56
- path: '/api/metadata',
65
+ path: '/api/v1/metadata',
57
66
  method: 'GET'
58
67
  })
59
68
 
@@ -70,7 +79,7 @@ class RuntimeApiClient {
70
79
  const client = this.#getUndiciClient(pid)
71
80
 
72
81
  const { statusCode, body } = await client.request({
73
- path: '/api/services',
82
+ path: '/api/v1/services',
74
83
  method: 'GET'
75
84
  })
76
85
 
@@ -87,7 +96,7 @@ class RuntimeApiClient {
87
96
  const client = this.#getUndiciClient(pid)
88
97
 
89
98
  const { statusCode, body } = await client.request({
90
- path: `/api/services/${serviceId}/config`,
99
+ path: `/api/v1/services/${serviceId}/config`,
91
100
  method: 'GET'
92
101
  })
93
102
 
@@ -104,7 +113,7 @@ class RuntimeApiClient {
104
113
  const client = this.#getUndiciClient(pid)
105
114
 
106
115
  const { statusCode, body } = await client.request({
107
- path: '/api/config',
116
+ path: '/api/v1/config',
108
117
  method: 'GET'
109
118
  })
110
119
 
@@ -121,7 +130,7 @@ class RuntimeApiClient {
121
130
  const client = this.#getUndiciClient(pid)
122
131
 
123
132
  const { statusCode, body } = await client.request({
124
- path: '/api/env',
133
+ path: '/api/v1/env',
125
134
  method: 'GET'
126
135
  })
127
136
 
@@ -148,7 +157,7 @@ class RuntimeApiClient {
148
157
  const client = this.#getUndiciClient(pid)
149
158
 
150
159
  const { statusCode, body } = await client.request({
151
- path: '/api/reload',
160
+ path: '/api/v1/reload',
152
161
  method: 'POST'
153
162
  })
154
163
 
@@ -162,7 +171,7 @@ class RuntimeApiClient {
162
171
  const client = this.#getUndiciClient(pid)
163
172
 
164
173
  const { statusCode, body } = await client.request({
165
- path: '/api/stop',
174
+ path: '/api/v1/stop',
166
175
  method: 'POST'
167
176
  })
168
177
 
@@ -172,15 +181,11 @@ class RuntimeApiClient {
172
181
  }
173
182
  }
174
183
 
175
- getRuntimeLogsStream (pid, options) {
184
+ getRuntimeLogsStream (pid) {
176
185
  const socketPath = this.#getSocketPathFromPid(pid)
177
- let query = ''
178
- if (options.level || options.pretty || options.serviceId) {
179
- query = '?' + new URLSearchParams(options).toString()
180
- }
181
186
 
182
187
  const protocol = platform() === 'win32' ? 'ws+unix:' : 'ws+unix://'
183
- const webSocketUrl = protocol + socketPath + ':/api/logs' + query
188
+ const webSocketUrl = protocol + socketPath + ':/api/v1/logs'
184
189
  const webSocketStream = new WebSocketStream(webSocketUrl)
185
190
  this.#webSockets.add(webSocketStream.ws)
186
191
 
@@ -191,7 +196,7 @@ class RuntimeApiClient {
191
196
  const client = this.#getUndiciClient(pid)
192
197
 
193
198
  const response = await client.request({
194
- path: `/api/services/${serviceId}/proxy` + options.url,
199
+ path: `/api/v1/services/${serviceId}/proxy` + options.url,
195
200
  method: options.method,
196
201
  headers: options.headers,
197
202
  query: options.query,
@@ -231,6 +236,11 @@ class RuntimeApiClient {
231
236
  }
232
237
 
233
238
  async #getUnixRuntimePIDs () {
239
+ try {
240
+ await access(PLATFORMATIC_TMP_DIR)
241
+ } catch {
242
+ return []
243
+ }
234
244
  const socketNames = await readdir(PLATFORMATIC_TMP_DIR)
235
245
  const runtimePIDs = []
236
246
  for (const socketName of socketNames) {
@@ -268,6 +278,13 @@ class RuntimeApiClient {
268
278
  )
269
279
  })
270
280
  }
281
+
282
+ async #removeRuntimeSocket (pid) {
283
+ if (platform() !== 'win32') {
284
+ const socketPath = this.#getSocketPathFromPid(pid)
285
+ await unlink(socketPath)
286
+ }
287
+ }
271
288
  }
272
289
 
273
290
  class WebSocketStream extends Readable {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/control",
3
- "version": "1.24.0",
3
+ "version": "1.25.0",
4
4
  "description": "Platformatic Control",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -24,14 +24,14 @@
24
24
  "split2": "^4.2.0",
25
25
  "standard": "^17.1.0",
26
26
  "tsd": "^0.30.4",
27
- "@platformatic/runtime": "1.24.0"
27
+ "@platformatic/runtime": "1.25.0"
28
28
  },
29
29
  "dependencies": {
30
30
  "@fastify/error": "^3.4.1",
31
31
  "commist": "^3.2.0",
32
+ "help-me": "^5.0.0",
32
33
  "pino": "^8.17.2",
33
34
  "pino-pretty": "^10.3.1",
34
- "help-me": "^5.0.0",
35
35
  "table": "^6.8.1",
36
36
  "undici": "^6.6.0",
37
37
  "ws": "^8.16.0"