@platformatic/control 2.0.0-alpha.9 → 2.0.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.
- package/lib/errors.js +2 -0
- package/lib/reload.js +4 -4
- package/lib/runtime-api-client.js +80 -29
- package/package.json +5 -5
package/lib/errors.js
CHANGED
|
@@ -6,6 +6,7 @@ const ERROR_PREFIX = 'PLT_CTR'
|
|
|
6
6
|
|
|
7
7
|
module.exports = {
|
|
8
8
|
RuntimeNotFound: createError(`${ERROR_PREFIX}_RUNTIME_NOT_FOUND`, 'Runtime not found.'),
|
|
9
|
+
ServiceNotFound: createError(`${ERROR_PREFIX}_SERVICE_NOT_FOUND`, 'Service not found.'),
|
|
9
10
|
MissingRuntimeIdentifier: createError(`${ERROR_PREFIX}_MISSING_RUNTIME_IDENTIFIER`, 'Runtime name or PID is required.'),
|
|
10
11
|
MissingRequestURL: createError(`${ERROR_PREFIX}_MISSING_REQUEST_URL`, 'Request URL is required.'),
|
|
11
12
|
FailedToGetRuntimeMetadata: createError(`${ERROR_PREFIX}_FAILED_TO_GET_RUNTIME_METADATA`, 'Failed to get runtime metadata %s.'),
|
|
@@ -17,6 +18,7 @@ module.exports = {
|
|
|
17
18
|
FailedToStopRuntime: createError(`${ERROR_PREFIX}_FAILED_TO_STOP_RUNTIME`, 'Failed to stop the runtime %s.'),
|
|
18
19
|
FailedToReloadRuntime: createError(`${ERROR_PREFIX}_FAILED_TO_RELOAD_RUNTIME`, 'Failed to reload the runtime %s.'),
|
|
19
20
|
FailedToGetRuntimeConfig: createError(`${ERROR_PREFIX}_FAILED_TO_GET_RUNTIME_CONFIG`, 'Failed to get runtime config %s.'),
|
|
21
|
+
FailedToGetRuntimeServiceEnv: createError(`${ERROR_PREFIX}_FAILED_TO_GET_RUNTIME_SERVICE_ENV`, 'Failed to get runtime service environment variables %s.'),
|
|
20
22
|
FailedToGetRuntimeServiceConfig: createError(`${ERROR_PREFIX}_FAILED_TO_GET_RUNTIME_SERVICE_CONFIG`, 'Failed to get runtime service config %s.'),
|
|
21
23
|
FailedToGetRuntimeHistoryLogs: createError(`${ERROR_PREFIX}_FAILED_TO_GET_HISTORY_LOGS`, 'Failed to get history logs %s.'),
|
|
22
24
|
FailedToGetRuntimeAllLogs: createError(`${ERROR_PREFIX}_FAILED_TO_GET_RUNTIME_ALL_LOGS`, 'Failed to get runtime all logs %s.'),
|
package/lib/reload.js
CHANGED
|
@@ -8,16 +8,16 @@ async function reloadRuntimeCommand (argv) {
|
|
|
8
8
|
args: argv,
|
|
9
9
|
options: {
|
|
10
10
|
pid: { type: 'string', short: 'p' },
|
|
11
|
-
name: { type: 'string', short: 'n' }
|
|
11
|
+
name: { type: 'string', short: 'n' }
|
|
12
12
|
},
|
|
13
|
-
strict: false
|
|
13
|
+
strict: false
|
|
14
14
|
}).values
|
|
15
15
|
|
|
16
16
|
const client = new RuntimeApiClient()
|
|
17
17
|
const runtime = await client.getMatchingRuntime(args)
|
|
18
18
|
|
|
19
|
-
await client.reloadRuntime(runtime.pid)
|
|
20
|
-
console.log(`Reloaded runtime "${runtime.packageName}".`)
|
|
19
|
+
const child = await client.reloadRuntime(runtime.pid)
|
|
20
|
+
console.log(`Reloaded runtime "${runtime.packageName}". The new PID is ${child.pid}.`)
|
|
21
21
|
|
|
22
22
|
await client.close()
|
|
23
23
|
}
|
|
@@ -62,7 +62,7 @@ class RuntimeApiClient {
|
|
|
62
62
|
|
|
63
63
|
const { statusCode, body } = await client.request({
|
|
64
64
|
path: '/api/v1/metadata',
|
|
65
|
-
method: 'GET'
|
|
65
|
+
method: 'GET'
|
|
66
66
|
})
|
|
67
67
|
|
|
68
68
|
if (statusCode !== 200) {
|
|
@@ -79,7 +79,7 @@ class RuntimeApiClient {
|
|
|
79
79
|
|
|
80
80
|
const { statusCode, body } = await client.request({
|
|
81
81
|
path: '/api/v1/services',
|
|
82
|
-
method: 'GET'
|
|
82
|
+
method: 'GET'
|
|
83
83
|
})
|
|
84
84
|
|
|
85
85
|
if (statusCode !== 200) {
|
|
@@ -91,38 +91,49 @@ class RuntimeApiClient {
|
|
|
91
91
|
return runtimeServices
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
async
|
|
94
|
+
async getRuntimeConfig (pid) {
|
|
95
95
|
const client = this.#getUndiciClient(pid)
|
|
96
96
|
|
|
97
97
|
const { statusCode, body } = await client.request({
|
|
98
|
-
path:
|
|
99
|
-
method: 'GET'
|
|
98
|
+
path: '/api/v1/config',
|
|
99
|
+
method: 'GET'
|
|
100
100
|
})
|
|
101
101
|
|
|
102
102
|
if (statusCode !== 200) {
|
|
103
103
|
const error = await body.text()
|
|
104
|
-
throw new errors.
|
|
104
|
+
throw new errors.FailedToGetRuntimeConfig(error)
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
const
|
|
108
|
-
return
|
|
107
|
+
const runtimeConfig = await body.json()
|
|
108
|
+
return runtimeConfig
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
async
|
|
111
|
+
async getRuntimeServiceConfig (pid, serviceId) {
|
|
112
112
|
const client = this.#getUndiciClient(pid)
|
|
113
113
|
|
|
114
114
|
const { statusCode, body } = await client.request({
|
|
115
|
-
path:
|
|
116
|
-
method: 'GET'
|
|
115
|
+
path: `/api/v1/services/${serviceId}/config`,
|
|
116
|
+
method: 'GET'
|
|
117
117
|
})
|
|
118
118
|
|
|
119
119
|
if (statusCode !== 200) {
|
|
120
120
|
const error = await body.text()
|
|
121
|
-
|
|
121
|
+
let jsonError
|
|
122
|
+
try {
|
|
123
|
+
jsonError = JSON.parse(error)
|
|
124
|
+
} catch {
|
|
125
|
+
// No-op
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (jsonError?.code === 'PLT_RUNTIME_SERVICE_NOT_FOUND') {
|
|
129
|
+
throw new errors.ServiceNotFound(error)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
throw new errors.FailedToGetRuntimeServiceConfig(error)
|
|
122
133
|
}
|
|
123
134
|
|
|
124
|
-
const
|
|
125
|
-
return
|
|
135
|
+
const serviceConfig = await body.json()
|
|
136
|
+
return serviceConfig
|
|
126
137
|
}
|
|
127
138
|
|
|
128
139
|
async getRuntimeEnv (pid) {
|
|
@@ -130,7 +141,7 @@ class RuntimeApiClient {
|
|
|
130
141
|
|
|
131
142
|
const { statusCode, body } = await client.request({
|
|
132
143
|
path: '/api/v1/env',
|
|
133
|
-
method: 'GET'
|
|
144
|
+
method: 'GET'
|
|
134
145
|
})
|
|
135
146
|
|
|
136
147
|
if (statusCode !== 200) {
|
|
@@ -142,22 +153,57 @@ class RuntimeApiClient {
|
|
|
142
153
|
return runtimeEnv
|
|
143
154
|
}
|
|
144
155
|
|
|
145
|
-
async
|
|
156
|
+
async getRuntimeServiceEnv (pid, serviceId) {
|
|
157
|
+
const client = this.#getUndiciClient(pid)
|
|
158
|
+
|
|
159
|
+
const { statusCode, body } = await client.request({
|
|
160
|
+
path: `/api/v1/services/${serviceId}/env`,
|
|
161
|
+
method: 'GET'
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
if (statusCode !== 200) {
|
|
165
|
+
const error = await body.text()
|
|
166
|
+
let jsonError
|
|
167
|
+
try {
|
|
168
|
+
jsonError = JSON.parse(error)
|
|
169
|
+
} catch {
|
|
170
|
+
// No-op
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (jsonError?.code === 'PLT_RUNTIME_SERVICE_NOT_FOUND') {
|
|
174
|
+
throw new errors.ServiceNotFound(error)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
throw new errors.FailedToGetRuntimeServiceEnv(error)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const serviceConfig = await body.json()
|
|
181
|
+
return serviceConfig
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async reloadRuntime (pid, options = {}) {
|
|
146
185
|
const runtime = await this.getMatchingRuntime({ pid })
|
|
147
186
|
|
|
148
187
|
await this.stopRuntime(pid)
|
|
149
188
|
|
|
150
189
|
const [startCommand, ...startArgs] = runtime.argv
|
|
151
|
-
const child = spawn(startCommand, startArgs, { cwd: runtime.cwd, ...options })
|
|
190
|
+
const child = spawn(startCommand, startArgs, { cwd: runtime.cwd, ...options, stdio: 'ignore', detached: true })
|
|
191
|
+
|
|
192
|
+
await new Promise((resolve, reject) => {
|
|
193
|
+
child.on('spawn', resolve)
|
|
194
|
+
child.on('error', reject)
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
child.unref()
|
|
152
198
|
return child
|
|
153
199
|
}
|
|
154
200
|
|
|
155
|
-
async
|
|
201
|
+
async restartRuntime (pid) {
|
|
156
202
|
const client = this.#getUndiciClient(pid)
|
|
157
203
|
|
|
158
204
|
const { statusCode, body } = await client.request({
|
|
159
|
-
path: '/api/v1/
|
|
160
|
-
method: 'POST'
|
|
205
|
+
path: '/api/v1/restart',
|
|
206
|
+
method: 'POST'
|
|
161
207
|
})
|
|
162
208
|
|
|
163
209
|
if (statusCode !== 200) {
|
|
@@ -171,7 +217,7 @@ class RuntimeApiClient {
|
|
|
171
217
|
|
|
172
218
|
const { statusCode, body } = await client.request({
|
|
173
219
|
path: '/api/v1/stop',
|
|
174
|
-
method: 'POST'
|
|
220
|
+
method: 'POST'
|
|
175
221
|
})
|
|
176
222
|
|
|
177
223
|
if (statusCode !== 200) {
|
|
@@ -210,7 +256,7 @@ class RuntimeApiClient {
|
|
|
210
256
|
const { statusCode, body } = await client.request({
|
|
211
257
|
path: '/api/v1/logs/' + logsId,
|
|
212
258
|
method: 'GET',
|
|
213
|
-
query: { pid: runtimePID }
|
|
259
|
+
query: { pid: runtimePID }
|
|
214
260
|
})
|
|
215
261
|
|
|
216
262
|
if (statusCode !== 200) {
|
|
@@ -228,7 +274,7 @@ class RuntimeApiClient {
|
|
|
228
274
|
const { statusCode, body } = await client.request({
|
|
229
275
|
path: '/api/v1/logs/all',
|
|
230
276
|
method: 'GET',
|
|
231
|
-
query: { pid: runtimePID }
|
|
277
|
+
query: { pid: runtimePID }
|
|
232
278
|
})
|
|
233
279
|
|
|
234
280
|
if (statusCode !== 200) {
|
|
@@ -246,7 +292,7 @@ class RuntimeApiClient {
|
|
|
246
292
|
const { statusCode, body } = await client.request({
|
|
247
293
|
path: '/api/v1/logs/indexes',
|
|
248
294
|
method: 'GET',
|
|
249
|
-
query: { all }
|
|
295
|
+
query: { all }
|
|
250
296
|
})
|
|
251
297
|
|
|
252
298
|
if (statusCode !== 200) {
|
|
@@ -268,7 +314,7 @@ class RuntimeApiClient {
|
|
|
268
314
|
method: options.method,
|
|
269
315
|
headers: options.headers,
|
|
270
316
|
query: options.query,
|
|
271
|
-
body: options.body
|
|
317
|
+
body: options.body
|
|
272
318
|
})
|
|
273
319
|
return response
|
|
274
320
|
}
|
|
@@ -289,7 +335,7 @@ class RuntimeApiClient {
|
|
|
289
335
|
undiciClient = new Client(
|
|
290
336
|
{
|
|
291
337
|
hostname: 'localhost',
|
|
292
|
-
protocol: 'http:'
|
|
338
|
+
protocol: 'http:'
|
|
293
339
|
},
|
|
294
340
|
{ socketPath }
|
|
295
341
|
)
|
|
@@ -312,10 +358,15 @@ class RuntimeApiClient {
|
|
|
312
358
|
} catch {
|
|
313
359
|
return []
|
|
314
360
|
}
|
|
315
|
-
|
|
361
|
+
|
|
362
|
+
const runtimeDirs = await readdir(PLATFORMATIC_TMP_DIR, { withFileTypes: true })
|
|
316
363
|
const runtimePIDs = []
|
|
317
|
-
|
|
318
|
-
|
|
364
|
+
|
|
365
|
+
for (const runtimeDir of runtimeDirs) {
|
|
366
|
+
// Only consider directory that can be a PID
|
|
367
|
+
if (runtimeDir.isDirectory() && runtimeDir.name.match(/^\d+$/)) {
|
|
368
|
+
runtimePIDs.push(parseInt(runtimeDir.name))
|
|
369
|
+
}
|
|
319
370
|
}
|
|
320
371
|
return runtimePIDs
|
|
321
372
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/control",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Platformatic Control",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -25,19 +25,19 @@
|
|
|
25
25
|
"split2": "^4.2.0",
|
|
26
26
|
"tsd": "^0.31.0",
|
|
27
27
|
"typescript": "^5.5.4",
|
|
28
|
-
"@platformatic/
|
|
29
|
-
"@platformatic/
|
|
28
|
+
"@platformatic/service": "2.0.1",
|
|
29
|
+
"@platformatic/runtime": "2.0.1"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@fastify/error": "^4.0.0",
|
|
33
33
|
"commist": "^3.2.0",
|
|
34
34
|
"help-me": "^5.0.0",
|
|
35
|
-
"pino": "^
|
|
35
|
+
"pino": "^9.0.0",
|
|
36
36
|
"pino-pretty": "^11.0.0",
|
|
37
37
|
"table": "^6.8.1",
|
|
38
38
|
"undici": "^6.9.0",
|
|
39
39
|
"ws": "^8.16.0",
|
|
40
|
-
"@platformatic/utils": "2.0.
|
|
40
|
+
"@platformatic/utils": "2.0.1"
|
|
41
41
|
},
|
|
42
42
|
"scripts": {
|
|
43
43
|
"test": "pnpm run lint && pnpm run unit",
|