@platformatic/runtime 1.29.0 → 1.31.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.json +1 -0
- package/fixtures/management-api/services/service-1/platformatic.json +1 -4
- package/fixtures/management-api/services/service-1/plugin.js +2 -2
- package/fixtures/management-api/services/service-2/platformatic.json +1 -2
- package/fixtures/sample-runtime-with-2-services/.env +10 -0
- package/fixtures/sample-runtime-with-2-services/package.json +16 -0
- package/fixtures/sample-runtime-with-2-services/platformatic.json +19 -0
- package/fixtures/sample-runtime-with-2-services/services/foobar/package.json +16 -0
- package/fixtures/sample-runtime-with-2-services/services/foobar/platformatic.json +18 -0
- package/fixtures/sample-runtime-with-2-services/services/foobar/routes/root.js +7 -0
- package/fixtures/sample-runtime-with-2-services/services/rival/package.json +16 -0
- package/fixtures/sample-runtime-with-2-services/services/rival/platformatic.json +33 -0
- package/fixtures/sample-runtime-with-2-services/services/rival/routes/root.js +7 -0
- package/lib/app.js +44 -37
- package/lib/errors.js +2 -0
- package/lib/generator/runtime-generator.js +64 -18
- package/lib/logs.js +14 -3
- package/lib/management-api.js +22 -12
- package/lib/schema.js +3 -1
- package/lib/utils.js +10 -0
- package/package.json +11 -11
|
@@ -7,8 +7,8 @@ module.exports = async function (app) {
|
|
|
7
7
|
})
|
|
8
8
|
|
|
9
9
|
app.get('/large-logs', async (req) => {
|
|
10
|
-
const largeLog = 'a'.repeat(
|
|
11
|
-
for (let i = 0; i <
|
|
10
|
+
const largeLog = 'a'.repeat(100)
|
|
11
|
+
for (let i = 0; i < 500000; i++) {
|
|
12
12
|
app.log.trace(largeLog)
|
|
13
13
|
}
|
|
14
14
|
})
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
PLT_SERVER_HOSTNAME=0.0.0.0
|
|
2
|
+
PORT=3042
|
|
3
|
+
PLT_SERVER_LOGGER_LEVEL=info
|
|
4
|
+
PLT_RIVAL_TYPESCRIPT=true
|
|
5
|
+
PLT_RIVAL_FST_PLUGIN_OAUTH2_NAME=googleOAuth2
|
|
6
|
+
PLT_RIVAL_FST_PLUGIN_OAUTH2_CREDENTIALS_CLIENT_ID=sample_client_id
|
|
7
|
+
PLT_RIVAL_FST_PLUGIN_OAUTH2_CREDENTIALS_CLIENT_SECRET=sample_client_secret
|
|
8
|
+
PLT_RIVAL_FST_PLUGIN_OAUTH2_REDIRECT_PATH=/login/google
|
|
9
|
+
PLT_RIVAL_FST_PLUGIN_OAUTH2_CALLBACK_URI=http://localhost:3000/login/google/callback
|
|
10
|
+
PLT_FOOBAR_TYPESCRIPT=true
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"scripts": {
|
|
3
|
+
"start": "platformatic start",
|
|
4
|
+
"test": "node --test test/*/*.test.js"
|
|
5
|
+
},
|
|
6
|
+
"devDependencies": {
|
|
7
|
+
"fastify": "^4.26.0"
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"platformatic": "^1.25.0",
|
|
11
|
+
"@fastify/oauth2": "7.8.0"
|
|
12
|
+
},
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": "^18.8.0 || >=20.6.0"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://platformatic.dev/schemas/v1.25.0/runtime",
|
|
3
|
+
"entrypoint": "rival",
|
|
4
|
+
"allowCycles": false,
|
|
5
|
+
"hotReload": true,
|
|
6
|
+
"autoload": {
|
|
7
|
+
"path": "services",
|
|
8
|
+
"exclude": [
|
|
9
|
+
"docs"
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
"server": {
|
|
13
|
+
"hostname": "{PLT_SERVER_HOSTNAME}",
|
|
14
|
+
"port": "{PORT}",
|
|
15
|
+
"logger": {
|
|
16
|
+
"level": "{PLT_SERVER_LOGGER_LEVEL}"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"scripts": {
|
|
3
|
+
"start": "platformatic start",
|
|
4
|
+
"test": "node --test test/**"
|
|
5
|
+
},
|
|
6
|
+
"devDependencies": {
|
|
7
|
+
"fastify": "^4.26.0"
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"platformatic": "^1.25.0",
|
|
11
|
+
"@platformatic/service": "^1.25.0"
|
|
12
|
+
},
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": "^18.8.0 || >=20.6.0"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://platformatic.dev/schemas/v1.25.0/service",
|
|
3
|
+
"service": {
|
|
4
|
+
"openapi": true
|
|
5
|
+
},
|
|
6
|
+
"watch": true,
|
|
7
|
+
"plugins": {
|
|
8
|
+
"paths": [
|
|
9
|
+
{
|
|
10
|
+
"path": "./plugins",
|
|
11
|
+
"encapsulate": false
|
|
12
|
+
},
|
|
13
|
+
"./routes"
|
|
14
|
+
],
|
|
15
|
+
"typescript": "{PLT_FOOBAR_TYPESCRIPT}",
|
|
16
|
+
"packages": []
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"scripts": {
|
|
3
|
+
"start": "platformatic start",
|
|
4
|
+
"test": "node --test test/**"
|
|
5
|
+
},
|
|
6
|
+
"devDependencies": {
|
|
7
|
+
"fastify": "^4.26.0"
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"platformatic": "^1.25.0",
|
|
11
|
+
"@platformatic/service": "^1.25.0"
|
|
12
|
+
},
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": "^18.8.0 || >=20.6.0"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://platformatic.dev/schemas/v1.25.0/service",
|
|
3
|
+
"service": {
|
|
4
|
+
"openapi": true
|
|
5
|
+
},
|
|
6
|
+
"watch": true,
|
|
7
|
+
"plugins": {
|
|
8
|
+
"paths": [
|
|
9
|
+
{
|
|
10
|
+
"path": "./plugins",
|
|
11
|
+
"encapsulate": false
|
|
12
|
+
},
|
|
13
|
+
"./routes"
|
|
14
|
+
],
|
|
15
|
+
"typescript": "{PLT_RIVAL_TYPESCRIPT}",
|
|
16
|
+
"packages": [
|
|
17
|
+
{
|
|
18
|
+
"name": "@fastify/oauth2",
|
|
19
|
+
"options": {
|
|
20
|
+
"name": "{PLT_RIVAL_FST_PLUGIN_OAUTH2_NAME}",
|
|
21
|
+
"credentials": {
|
|
22
|
+
"client": {
|
|
23
|
+
"id": "{PLT_RIVAL_FST_PLUGIN_OAUTH2_CREDENTIALS_CLIENT_ID}",
|
|
24
|
+
"secret": "{PLT_RIVAL_FST_PLUGIN_OAUTH2_CREDENTIALS_CLIENT_SECRET}"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"startRedirectPath": "{PLT_RIVAL_FST_PLUGIN_OAUTH2_REDIRECT_PATH}",
|
|
28
|
+
"callbackUri": "{PLT_RIVAL_FST_PLUGIN_OAUTH2_CALLBACK_URI}"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
}
|
package/lib/app.js
CHANGED
|
@@ -73,6 +73,8 @@ class PlatformaticApp {
|
|
|
73
73
|
|
|
74
74
|
try {
|
|
75
75
|
await this.config.configManager.parseAndValidate()
|
|
76
|
+
await this.#updateConfig()
|
|
77
|
+
|
|
76
78
|
this.#setuplogger(this.config.configManager)
|
|
77
79
|
await this.server.restart()
|
|
78
80
|
} catch (err) {
|
|
@@ -93,44 +95,9 @@ class PlatformaticApp {
|
|
|
93
95
|
this.#started = true
|
|
94
96
|
|
|
95
97
|
await this.#initializeConfig()
|
|
96
|
-
this.#
|
|
97
|
-
this.config.configManager.current.watch = { enabled: false }
|
|
98
|
-
|
|
99
|
-
const { configManager } = this.config
|
|
100
|
-
configManager.update({
|
|
101
|
-
...configManager.current,
|
|
102
|
-
telemetry: this.#telemetryConfig
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
if (this.#serverConfig) {
|
|
106
|
-
configManager.update({
|
|
107
|
-
...configManager.current,
|
|
108
|
-
server: this.#serverConfig
|
|
109
|
-
})
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if (this.#hasManagementApi || configManager.current.metrics) {
|
|
113
|
-
configManager.update({
|
|
114
|
-
...configManager.current,
|
|
115
|
-
metrics: {
|
|
116
|
-
server: 'parent',
|
|
117
|
-
defaultMetrics: { enabled: this.appConfig.entrypoint },
|
|
118
|
-
prefix: snakeCase(this.appConfig.id) + '_',
|
|
119
|
-
...configManager.current.metrics
|
|
120
|
-
}
|
|
121
|
-
})
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (!this.appConfig.entrypoint) {
|
|
125
|
-
configManager.update({
|
|
126
|
-
...configManager.current,
|
|
127
|
-
server: {
|
|
128
|
-
...(configManager.current.server || {}),
|
|
129
|
-
trustProxy: true
|
|
130
|
-
}
|
|
131
|
-
})
|
|
132
|
-
}
|
|
98
|
+
await this.#updateConfig()
|
|
133
99
|
|
|
100
|
+
const configManager = this.config.configManager
|
|
134
101
|
const config = configManager.current
|
|
135
102
|
|
|
136
103
|
this.#setuplogger(configManager)
|
|
@@ -262,6 +229,46 @@ class PlatformaticApp {
|
|
|
262
229
|
})
|
|
263
230
|
}
|
|
264
231
|
|
|
232
|
+
async #updateConfig () {
|
|
233
|
+
this.#originalWatch = this.config.configManager.current.watch
|
|
234
|
+
this.config.configManager.current.watch = { enabled: false }
|
|
235
|
+
|
|
236
|
+
const { configManager } = this.config
|
|
237
|
+
configManager.update({
|
|
238
|
+
...configManager.current,
|
|
239
|
+
telemetry: this.#telemetryConfig
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
if (this.#serverConfig) {
|
|
243
|
+
configManager.update({
|
|
244
|
+
...configManager.current,
|
|
245
|
+
server: this.#serverConfig
|
|
246
|
+
})
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (this.#hasManagementApi || configManager.current.metrics) {
|
|
250
|
+
configManager.update({
|
|
251
|
+
...configManager.current,
|
|
252
|
+
metrics: {
|
|
253
|
+
server: 'hide',
|
|
254
|
+
defaultMetrics: { enabled: this.appConfig.entrypoint },
|
|
255
|
+
prefix: snakeCase(this.appConfig.id) + '_',
|
|
256
|
+
...configManager.current.metrics
|
|
257
|
+
}
|
|
258
|
+
})
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (!this.appConfig.entrypoint) {
|
|
262
|
+
configManager.update({
|
|
263
|
+
...configManager.current,
|
|
264
|
+
server: {
|
|
265
|
+
...(configManager.current.server || {}),
|
|
266
|
+
trustProxy: true
|
|
267
|
+
}
|
|
268
|
+
})
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
265
272
|
#setuplogger (configManager) {
|
|
266
273
|
configManager.current.server = configManager.current.server || {}
|
|
267
274
|
const level = configManager.current.server.logger?.level
|
package/lib/errors.js
CHANGED
|
@@ -25,5 +25,7 @@ module.exports = {
|
|
|
25
25
|
FailedToUnlinkManagementApiSocket: createError(`${ERROR_PREFIX}_FAILED_TO_UNLINK_MANAGEMENT_API_SOCKET`, 'Failed to unlink management API socket "%s"'),
|
|
26
26
|
LogFileNotFound: createError(`${ERROR_PREFIX}_LOG_FILE_NOT_FOUND`, 'Log file with index %s not found', 404),
|
|
27
27
|
CannotFindGeneratorForTemplateError: createError(`${ERROR_PREFIX}_CANNOT_FIND_GENERATOR_FOR_TEMPLATE`, 'Cannot find a generator for template "%s"'),
|
|
28
|
+
|
|
29
|
+
// TODO: should remove next one as it's not used anymore
|
|
28
30
|
CannotRemoveServiceOnUpdateError: createError(`${ERROR_PREFIX}_CANNOT_REMOVE_SERVICE_ON_UPDATE`, 'Cannot remove service "%s" when updating a Runtime')
|
|
29
31
|
}
|
|
@@ -5,15 +5,16 @@ const { NoEntryPointError, NoServiceNamedError } = require('./errors')
|
|
|
5
5
|
const generateName = require('boring-name-generator')
|
|
6
6
|
const { join } = require('node:path')
|
|
7
7
|
const { envObjectToString } = require('@platformatic/generators/lib/utils')
|
|
8
|
-
const { readFile, readdir, stat } = require('node:fs/promises')
|
|
8
|
+
const { readFile, readdir, stat, rm } = require('node:fs/promises')
|
|
9
9
|
const { ConfigManager } = require('@platformatic/config')
|
|
10
10
|
const { platformaticRuntime } = require('../config')
|
|
11
11
|
const ServiceGenerator = require('@platformatic/service/lib/generator/service-generator')
|
|
12
12
|
const DBGenerator = require('@platformatic/db/lib/generator/db-generator')
|
|
13
13
|
const ComposerGenerator = require('@platformatic/composer/lib/generator/composer-generator')
|
|
14
|
-
const { CannotFindGeneratorForTemplateError
|
|
14
|
+
const { CannotFindGeneratorForTemplateError } = require('../errors')
|
|
15
15
|
const { getServiceTemplateFromSchemaUrl } = require('@platformatic/generators/lib/utils')
|
|
16
16
|
const { DotEnvTool } = require('dotenv-tool')
|
|
17
|
+
const { getArrayDifference } = require('../utils')
|
|
17
18
|
|
|
18
19
|
class RuntimeGenerator extends BaseGenerator {
|
|
19
20
|
constructor (opts) {
|
|
@@ -91,7 +92,8 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
91
92
|
this.addEnvVars({
|
|
92
93
|
PLT_SERVER_HOSTNAME: '0.0.0.0',
|
|
93
94
|
PORT: this.config.port || 3042,
|
|
94
|
-
PLT_SERVER_LOGGER_LEVEL: this.config.logLevel || 'info'
|
|
95
|
+
PLT_SERVER_LOGGER_LEVEL: this.config.logLevel || 'info',
|
|
96
|
+
PLT_MANAGEMENT_API: true
|
|
95
97
|
}, { overwrite: false })
|
|
96
98
|
}
|
|
97
99
|
|
|
@@ -165,7 +167,8 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
165
167
|
logger: {
|
|
166
168
|
level: '{PLT_SERVER_LOGGER_LEVEL}'
|
|
167
169
|
}
|
|
168
|
-
}
|
|
170
|
+
},
|
|
171
|
+
managementApi: '{PLT_MANAGEMENT_API}'
|
|
169
172
|
}
|
|
170
173
|
|
|
171
174
|
return config
|
|
@@ -337,13 +340,11 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
337
340
|
|
|
338
341
|
async update (newConfig) {
|
|
339
342
|
let allServicesDependencies = {}
|
|
340
|
-
|
|
341
|
-
return a.filter(element => {
|
|
342
|
-
return !b.includes(element)
|
|
343
|
-
})
|
|
344
|
-
}
|
|
345
|
-
this.config.isUpdating = true
|
|
343
|
+
const runtimeAddedEnvKeys = []
|
|
346
344
|
|
|
345
|
+
this.config.isUpdating = true
|
|
346
|
+
const currrentPackageJson = JSON.parse(await readFile(join(this.targetDirectory, 'package.json'), 'utf-8'))
|
|
347
|
+
const currentRuntimeDependencies = currrentPackageJson.dependencies
|
|
347
348
|
// check all services are present with the same template
|
|
348
349
|
const allCurrentServicesNames = this.services.map((s) => s.name)
|
|
349
350
|
const allNewServicesNames = newConfig.services.map((s) => s.name)
|
|
@@ -354,9 +355,32 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
354
355
|
|
|
355
356
|
await envTool.load()
|
|
356
357
|
|
|
357
|
-
const removedServices =
|
|
358
|
+
const removedServices = getArrayDifference(allCurrentServicesNames, allNewServicesNames)
|
|
358
359
|
if (removedServices.length > 0) {
|
|
359
|
-
|
|
360
|
+
for (const removedService of removedServices) {
|
|
361
|
+
// handle service delete
|
|
362
|
+
|
|
363
|
+
// delete env variables
|
|
364
|
+
const s = this.services.find((f) => f.name === removedService)
|
|
365
|
+
const allKeys = envTool.getKeys()
|
|
366
|
+
allKeys.forEach((k) => {
|
|
367
|
+
if (k.startsWith(`PLT_${s.service.config.envPrefix}`)) {
|
|
368
|
+
envTool.deleteKey(k)
|
|
369
|
+
}
|
|
370
|
+
})
|
|
371
|
+
|
|
372
|
+
// delete dependencies
|
|
373
|
+
const servicePackageJson = JSON.parse(await readFile(join(this.targetDirectory, 'services', s.name, 'platformatic.json')))
|
|
374
|
+
if (servicePackageJson.plugins && servicePackageJson.plugins.packages) {
|
|
375
|
+
servicePackageJson.plugins.packages
|
|
376
|
+
.forEach((p) => {
|
|
377
|
+
delete (currrentPackageJson.dependencies[p.name])
|
|
378
|
+
})
|
|
379
|
+
}
|
|
380
|
+
// delete directory
|
|
381
|
+
await rm(join(this.targetDirectory, 'services', s.name), { recursive: true })
|
|
382
|
+
}
|
|
383
|
+
// throw new CannotRemoveServiceOnUpdateError(removedServices.join(', '))
|
|
360
384
|
}
|
|
361
385
|
|
|
362
386
|
// handle new services
|
|
@@ -367,18 +391,30 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
367
391
|
const baseConfig = {
|
|
368
392
|
isRuntimeContext: true,
|
|
369
393
|
targetDirectory: join(this.targetDirectory, 'services', newService.name),
|
|
370
|
-
serviceName: newService.name
|
|
394
|
+
serviceName: newService.name,
|
|
395
|
+
plugin: true
|
|
371
396
|
}
|
|
372
397
|
if (allCurrentServicesNames.includes(newService.name)) {
|
|
373
398
|
// update existing services env values
|
|
374
399
|
// otherwise, is a new service
|
|
375
400
|
baseConfig.isUpdating = true
|
|
401
|
+
|
|
402
|
+
// handle service's plugin differences
|
|
403
|
+
const oldServiceMetadata = await serviceInstance.loadFromDir(newService.name, this.targetDirectory)
|
|
404
|
+
const oldServicePackages = oldServiceMetadata.plugins.map((meta) => meta.name)
|
|
405
|
+
const newServicePackages = newService.plugins.map((meta) => meta.name)
|
|
406
|
+
const pluginsToRemove = getArrayDifference(oldServicePackages, newServicePackages)
|
|
407
|
+
pluginsToRemove.forEach((p) => delete currentRuntimeDependencies[p])
|
|
376
408
|
}
|
|
377
409
|
serviceInstance.setConfig(baseConfig)
|
|
410
|
+
serviceInstance.setConfigFields(newService.fields)
|
|
411
|
+
|
|
412
|
+
const serviceEnvPrefix = `PLT_${serviceInstance.config.envPrefix}`
|
|
378
413
|
for (const plug of newService.plugins) {
|
|
379
414
|
await serviceInstance.addPackage(plug)
|
|
380
415
|
for (const opt of plug.options) {
|
|
381
|
-
const key =
|
|
416
|
+
const key = `${serviceEnvPrefix}_${opt.name}`
|
|
417
|
+
runtimeAddedEnvKeys.push(key)
|
|
382
418
|
const value = opt.value
|
|
383
419
|
if (envTool.hasKey(key)) {
|
|
384
420
|
envTool.updateKey(key, value)
|
|
@@ -388,13 +424,23 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
388
424
|
}
|
|
389
425
|
}
|
|
390
426
|
allServicesDependencies = { ...allServicesDependencies, ...serviceInstance.config.dependencies }
|
|
391
|
-
await serviceInstance.prepare()
|
|
427
|
+
const afterPrepareMetadata = await serviceInstance.prepare()
|
|
392
428
|
await serviceInstance.writeFiles()
|
|
429
|
+
// cleanup runtime env removing keys not present anymore in service plugins
|
|
430
|
+
const allKeys = envTool.getKeys()
|
|
431
|
+
allKeys.forEach((k) => {
|
|
432
|
+
if (k.startsWith(serviceEnvPrefix) && !runtimeAddedEnvKeys.includes(k)) {
|
|
433
|
+
envTool.deleteKey(k)
|
|
434
|
+
}
|
|
435
|
+
})
|
|
436
|
+
|
|
437
|
+
// add service env variables to runtime env
|
|
438
|
+
Object.entries(afterPrepareMetadata.env).forEach(([key, value]) => {
|
|
439
|
+
envTool.addKey(key, value)
|
|
440
|
+
})
|
|
393
441
|
}
|
|
394
442
|
|
|
395
443
|
// update runtime package.json dependencies
|
|
396
|
-
// read current package.json file
|
|
397
|
-
const currrentPackageJson = JSON.parse(await readFile(join(this.targetDirectory, 'package.json'), 'utf-8'))
|
|
398
444
|
currrentPackageJson.dependencies = {
|
|
399
445
|
...currrentPackageJson.dependencies,
|
|
400
446
|
...allServicesDependencies
|
|
@@ -402,7 +448,7 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
402
448
|
this.addFile({
|
|
403
449
|
path: '',
|
|
404
450
|
file: 'package.json',
|
|
405
|
-
contents: JSON.stringify(currrentPackageJson)
|
|
451
|
+
contents: JSON.stringify(currrentPackageJson, null, 2)
|
|
406
452
|
})
|
|
407
453
|
|
|
408
454
|
await this.writeFiles()
|
package/lib/logs.js
CHANGED
|
@@ -21,7 +21,9 @@ async function getLogFiles () {
|
|
|
21
21
|
return runtimeLogFiles
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
async function
|
|
24
|
+
async function pipeLogsStream (writableStream, logger, startLogIndex, endLogIndex) {
|
|
25
|
+
endLogIndex = endLogIndex || Infinity
|
|
26
|
+
|
|
25
27
|
const runtimeLogFiles = await getLogFiles()
|
|
26
28
|
if (runtimeLogFiles.length === 0) {
|
|
27
29
|
writableStream.end()
|
|
@@ -47,6 +49,11 @@ async function pipeLiveLogs (writableStream, logger, startLogIndex) {
|
|
|
47
49
|
}).unref()
|
|
48
50
|
|
|
49
51
|
const streamLogFile = () => {
|
|
52
|
+
if (fileIndex > endLogIndex) {
|
|
53
|
+
writableStream.end()
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
|
|
50
57
|
const fileName = 'logs.' + fileIndex
|
|
51
58
|
const filePath = join(runtimeTmpDir, fileName)
|
|
52
59
|
|
|
@@ -61,7 +68,7 @@ async function pipeLiveLogs (writableStream, logger, startLogIndex) {
|
|
|
61
68
|
}
|
|
62
69
|
|
|
63
70
|
fileStream.on('error', (err) => {
|
|
64
|
-
logger.
|
|
71
|
+
logger.error(err, 'Error streaming log file')
|
|
65
72
|
fileStream.destroy()
|
|
66
73
|
watcher.close()
|
|
67
74
|
writableStream.end()
|
|
@@ -72,6 +79,10 @@ async function pipeLiveLogs (writableStream, logger, startLogIndex) {
|
|
|
72
79
|
})
|
|
73
80
|
|
|
74
81
|
fileStream.on('eof', () => {
|
|
82
|
+
if (fileIndex >= endLogIndex) {
|
|
83
|
+
writableStream.end()
|
|
84
|
+
return
|
|
85
|
+
}
|
|
75
86
|
if (latestFileIndex > fileIndex) {
|
|
76
87
|
streamLogFile(++fileIndex)
|
|
77
88
|
} else {
|
|
@@ -106,7 +117,7 @@ async function getLogFileStream (logFileIndex) {
|
|
|
106
117
|
}
|
|
107
118
|
|
|
108
119
|
module.exports = {
|
|
109
|
-
|
|
120
|
+
pipeLogsStream,
|
|
110
121
|
getLogFileStream,
|
|
111
122
|
getLogIndexes
|
|
112
123
|
}
|
package/lib/management-api.js
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
const { tmpdir, platform } = require('node:os')
|
|
4
4
|
const { join } = require('node:path')
|
|
5
|
-
const { readFile, mkdir,
|
|
5
|
+
const { readFile, mkdir, rm } = require('node:fs/promises')
|
|
6
6
|
const fastify = require('fastify')
|
|
7
7
|
const ws = require('ws')
|
|
8
8
|
const errors = require('./errors')
|
|
9
|
-
const {
|
|
9
|
+
const { pipeLogsStream, getLogFileStream, getLogIndexes } = require('./logs')
|
|
10
10
|
const platformaticVersion = require('../package.json').version
|
|
11
11
|
|
|
12
12
|
const PLATFORMATIC_TMP_DIR = join(tmpdir(), 'platformatic', 'runtimes')
|
|
@@ -118,14 +118,16 @@ async function createManagementApi (configManager, runtimeApiClient) {
|
|
|
118
118
|
|
|
119
119
|
app.get('/metrics/live', { websocket: true }, async (socket) => {
|
|
120
120
|
const cachedMetrics = runtimeApiClient.getCachedMetrics()
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
121
|
+
if (cachedMetrics.length > 0) {
|
|
122
|
+
const serializedMetrics = cachedMetrics
|
|
123
|
+
.map((metric) => JSON.stringify(metric))
|
|
124
|
+
.join('\n')
|
|
125
|
+
socket.send(serializedMetrics + '\n')
|
|
126
|
+
}
|
|
125
127
|
|
|
126
128
|
const eventHandler = (metrics) => {
|
|
127
129
|
const serializedMetrics = JSON.stringify(metrics)
|
|
128
|
-
socket.send(serializedMetrics)
|
|
130
|
+
socket.send(serializedMetrics + '\n')
|
|
129
131
|
}
|
|
130
132
|
|
|
131
133
|
runtimeApiClient.on('metrics', eventHandler)
|
|
@@ -150,8 +152,7 @@ async function createManagementApi (configManager, runtimeApiClient) {
|
|
|
150
152
|
}
|
|
151
153
|
|
|
152
154
|
const stream = ws.createWebSocketStream(socket)
|
|
153
|
-
|
|
154
|
-
pipeLiveLogs(stream, req.log, startLogIndex)
|
|
155
|
+
pipeLogsStream(stream, req.log, startLogIndex)
|
|
155
156
|
})
|
|
156
157
|
|
|
157
158
|
app.get('/logs/indexes', async () => {
|
|
@@ -159,6 +160,15 @@ async function createManagementApi (configManager, runtimeApiClient) {
|
|
|
159
160
|
return { indexes: logIndexes }
|
|
160
161
|
})
|
|
161
162
|
|
|
163
|
+
app.get('/logs/all', async (req, reply) => {
|
|
164
|
+
const logIndexes = await getLogIndexes()
|
|
165
|
+
const startLogIndex = logIndexes.at(0)
|
|
166
|
+
const endLogIndex = logIndexes.at(-1)
|
|
167
|
+
|
|
168
|
+
reply.hijack()
|
|
169
|
+
pipeLogsStream(reply.raw, req.log, startLogIndex, endLogIndex)
|
|
170
|
+
})
|
|
171
|
+
|
|
162
172
|
app.get('/logs/:id', async (req) => {
|
|
163
173
|
const { id } = req.params
|
|
164
174
|
|
|
@@ -187,12 +197,12 @@ async function startManagementApi (configManager, runtimeApiClient) {
|
|
|
187
197
|
}
|
|
188
198
|
|
|
189
199
|
try {
|
|
190
|
-
await
|
|
191
|
-
await unlink(socketPath).catch((err) => {
|
|
200
|
+
await rm(runtimeTmpDir, { recursive: true, force: true }).catch((err) => {
|
|
192
201
|
if (err.code !== 'ENOENT') {
|
|
193
202
|
throw new errors.FailedToUnlinkManagementApiSocket(err.message)
|
|
194
203
|
}
|
|
195
204
|
})
|
|
205
|
+
await mkdir(runtimeTmpDir, { recursive: true })
|
|
196
206
|
|
|
197
207
|
const managementApi = await createManagementApi(
|
|
198
208
|
configManager,
|
|
@@ -201,7 +211,7 @@ async function startManagementApi (configManager, runtimeApiClient) {
|
|
|
201
211
|
|
|
202
212
|
if (platform() !== 'win32') {
|
|
203
213
|
managementApi.addHook('onClose', async () => {
|
|
204
|
-
await
|
|
214
|
+
await rm(runtimeTmpDir, { recursive: true, force: true }).catch()
|
|
205
215
|
})
|
|
206
216
|
}
|
|
207
217
|
|
package/lib/schema.js
CHANGED
|
@@ -150,6 +150,7 @@ const platformaticRuntimeSchema = {
|
|
|
150
150
|
managementApi: {
|
|
151
151
|
anyOf: [
|
|
152
152
|
{ type: 'boolean' },
|
|
153
|
+
{ type: 'string' },
|
|
153
154
|
{
|
|
154
155
|
type: 'object',
|
|
155
156
|
properties: {
|
|
@@ -163,7 +164,8 @@ const platformaticRuntimeSchema = {
|
|
|
163
164
|
},
|
|
164
165
|
additionalProperties: false
|
|
165
166
|
}
|
|
166
|
-
]
|
|
167
|
+
],
|
|
168
|
+
default: true
|
|
167
169
|
},
|
|
168
170
|
metrics: {
|
|
169
171
|
anyOf: [
|
package/lib/utils.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/runtime",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.31.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"typescript": "^5.4.2",
|
|
34
34
|
"undici-oidc-interceptor": "^0.5.0",
|
|
35
35
|
"why-is-node-running": "^2.2.2",
|
|
36
|
-
"@platformatic/sql-graphql": "1.
|
|
37
|
-
"@platformatic/sql-mapper": "1.
|
|
36
|
+
"@platformatic/sql-graphql": "1.31.0",
|
|
37
|
+
"@platformatic/sql-mapper": "1.31.0"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"ws": "^8.16.0",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"commist": "^3.2.0",
|
|
48
48
|
"debounce": "^2.0.0",
|
|
49
49
|
"desm": "^1.3.1",
|
|
50
|
-
"dotenv-tool": "^0.
|
|
50
|
+
"dotenv-tool": "^0.1.1",
|
|
51
51
|
"es-main": "^1.3.0",
|
|
52
52
|
"fastest-levenshtein": "^1.0.16",
|
|
53
53
|
"fastify": "^4.26.2",
|
|
@@ -62,13 +62,13 @@
|
|
|
62
62
|
"tail-file-stream": "^0.1.0",
|
|
63
63
|
"undici": "^6.9.0",
|
|
64
64
|
"why-is-node-running": "^2.2.2",
|
|
65
|
-
"@platformatic/composer": "1.
|
|
66
|
-
"@platformatic/
|
|
67
|
-
"@platformatic/
|
|
68
|
-
"@platformatic/
|
|
69
|
-
"@platformatic/
|
|
70
|
-
"@platformatic/
|
|
71
|
-
"@platformatic/
|
|
65
|
+
"@platformatic/composer": "1.31.0",
|
|
66
|
+
"@platformatic/db": "1.31.0",
|
|
67
|
+
"@platformatic/generators": "1.31.0",
|
|
68
|
+
"@platformatic/config": "1.31.0",
|
|
69
|
+
"@platformatic/service": "1.31.0",
|
|
70
|
+
"@platformatic/utils": "1.31.0",
|
|
71
|
+
"@platformatic/telemetry": "1.31.0"
|
|
72
72
|
},
|
|
73
73
|
"standard": {
|
|
74
74
|
"ignore": [
|