@platformatic/runtime 3.15.0 → 3.17.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/index.js +6 -0
- package/lib/generator.js +3 -8
- package/lib/management-api.js +87 -4
- package/lib/runtime.js +19 -3
- package/lib/worker/main.js +5 -4
- package/package.json +15 -17
- package/schema.json +1 -1
package/index.js
CHANGED
|
@@ -143,6 +143,12 @@ export async function create (configOrRoot, sourceOrConfig, context) {
|
|
|
143
143
|
if (context?.start) {
|
|
144
144
|
let port = config.server?.port
|
|
145
145
|
|
|
146
|
+
await runtime.init()
|
|
147
|
+
|
|
148
|
+
if (context.reloaded) {
|
|
149
|
+
runtime.logger.info('The application has been successfully reloaded.')
|
|
150
|
+
}
|
|
151
|
+
|
|
146
152
|
while (true) {
|
|
147
153
|
try {
|
|
148
154
|
await runtime.start()
|
package/lib/generator.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import createError from '@fastify/error'
|
|
2
2
|
import {
|
|
3
|
+
createEnvFileTool,
|
|
3
4
|
defaultPackageManager,
|
|
4
5
|
findConfigurationFile,
|
|
5
6
|
generateDashedName,
|
|
@@ -50,12 +51,6 @@ function getRuntimeBaseEnvVars (config) {
|
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
// This is needed as dotenv-tool is not loading with ESM currently
|
|
54
|
-
export function createDotenvTool (...args) {
|
|
55
|
-
const { DotEnvTool } = createRequire(import.meta.url)('dotenv-tool')
|
|
56
|
-
return new DotEnvTool(...args)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
54
|
export class RuntimeGenerator extends BaseGenerator {
|
|
60
55
|
constructor (opts) {
|
|
61
56
|
super({
|
|
@@ -371,8 +366,8 @@ export class RuntimeGenerator extends BaseGenerator {
|
|
|
371
366
|
// check all applications are present with the same template
|
|
372
367
|
const allCurrentApplicationsNames = this.applications.map(s => s.name)
|
|
373
368
|
const allNewApplicationsNames = newConfig.applications.map(s => s.name)
|
|
374
|
-
// load
|
|
375
|
-
const envTool =
|
|
369
|
+
// load env file tool
|
|
370
|
+
const envTool = createEnvFileTool({
|
|
376
371
|
path: join(this.targetDirectory, '.env')
|
|
377
372
|
})
|
|
378
373
|
|
package/lib/management-api.js
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import fastifyAccepts from '@fastify/accepts'
|
|
2
2
|
import fastifyWebsocket from '@fastify/websocket'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
applications as applicationSchema,
|
|
5
|
+
createDirectory,
|
|
6
|
+
kMetadata,
|
|
7
|
+
safeRemove,
|
|
8
|
+
validate
|
|
9
|
+
} from '@platformatic/foundation'
|
|
4
10
|
import fastify from 'fastify'
|
|
5
11
|
import { platform, tmpdir } from 'node:os'
|
|
6
12
|
import { join } from 'node:path'
|
|
7
13
|
import { setTimeout as sleep } from 'node:timers/promises'
|
|
8
14
|
import { createWebSocketStream } from 'ws'
|
|
15
|
+
import { prepareApplication } from './config.js'
|
|
9
16
|
|
|
10
17
|
const PLATFORMATIC_TMP_DIR = join(tmpdir(), 'platformatic', 'runtimes')
|
|
11
18
|
|
|
@@ -14,6 +21,26 @@ export async function managementApiPlugin (app, opts) {
|
|
|
14
21
|
|
|
15
22
|
const runtime = opts.runtime
|
|
16
23
|
|
|
24
|
+
async function deleteApplications (ids, reply) {
|
|
25
|
+
const validIds = runtime.getApplicationsIds()
|
|
26
|
+
|
|
27
|
+
for (const id of ids) {
|
|
28
|
+
if (!validIds.includes(id)) {
|
|
29
|
+
reply.code(404)
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
error: 'Not Found',
|
|
33
|
+
message: `Application with id "${id}" not found.`,
|
|
34
|
+
statusCode: 404
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const removed = await runtime.removeApplications(ids)
|
|
40
|
+
reply.code(202)
|
|
41
|
+
return removed
|
|
42
|
+
}
|
|
43
|
+
|
|
17
44
|
app.get('/status', async () => {
|
|
18
45
|
const status = runtime.getRuntimeStatus()
|
|
19
46
|
return { status }
|
|
@@ -23,8 +50,16 @@ export async function managementApiPlugin (app, opts) {
|
|
|
23
50
|
return runtime.getRuntimeMetadata()
|
|
24
51
|
})
|
|
25
52
|
|
|
26
|
-
app.get('/config', async
|
|
27
|
-
|
|
53
|
+
app.get('/config', async request => {
|
|
54
|
+
const metadata = request.query.metadata === 'true'
|
|
55
|
+
const rawConfig = await runtime.getRuntimeConfig(metadata)
|
|
56
|
+
|
|
57
|
+
if (metadata) {
|
|
58
|
+
const { [kMetadata]: __metadata, ...config } = rawConfig
|
|
59
|
+
return { ...config, __metadata }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return rawConfig
|
|
28
63
|
})
|
|
29
64
|
|
|
30
65
|
app.get('/env', async () => {
|
|
@@ -46,12 +81,60 @@ export async function managementApiPlugin (app, opts) {
|
|
|
46
81
|
return runtime.getApplications()
|
|
47
82
|
})
|
|
48
83
|
|
|
84
|
+
app.post('/applications', async (request, reply) => {
|
|
85
|
+
let applications = request.body
|
|
86
|
+
|
|
87
|
+
if (!Array.isArray(applications)) {
|
|
88
|
+
applications = [applications]
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const config = runtime.getRuntimeConfig(true)
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
validate(applicationSchema, applications, {}, true, config[kMetadata].root)
|
|
95
|
+
} catch (err) {
|
|
96
|
+
reply.code(400)
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
statusCode: 400,
|
|
100
|
+
error: 'Bad Request',
|
|
101
|
+
message: 'Invalid applications configuration.',
|
|
102
|
+
validationErrors: err.validationErrors
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
for (let i = 0; i < applications.length; i++) {
|
|
107
|
+
applications[i] = await prepareApplication(config, applications[i])
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const created = await runtime.addApplications(applications, request.query.start !== 'false')
|
|
111
|
+
reply.code(201)
|
|
112
|
+
return created
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
app.delete('/applications', async (request, reply) => {
|
|
116
|
+
if (!Array.isArray(request.body)) {
|
|
117
|
+
reply.code(404)
|
|
118
|
+
return {
|
|
119
|
+
statusCode: 404,
|
|
120
|
+
error: 'Bad Request',
|
|
121
|
+
message: 'Invalid applications IDs.'
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return deleteApplications(request.body, reply)
|
|
126
|
+
})
|
|
127
|
+
|
|
49
128
|
app.get('/applications/:id', async request => {
|
|
50
129
|
const { id } = request.params
|
|
51
130
|
app.log.debug('get application details', { id })
|
|
52
131
|
return runtime.getApplicationDetails(id)
|
|
53
132
|
})
|
|
54
133
|
|
|
134
|
+
app.delete('/applications/:id', async (request, reply) => {
|
|
135
|
+
return deleteApplications([request.params.id], reply)
|
|
136
|
+
})
|
|
137
|
+
|
|
55
138
|
app.get('/applications/:id/config', async request => {
|
|
56
139
|
const { id } = request.params
|
|
57
140
|
app.log.debug('get application config', { id })
|
|
@@ -195,7 +278,7 @@ export async function managementApiPlugin (app, opts) {
|
|
|
195
278
|
})
|
|
196
279
|
})
|
|
197
280
|
|
|
198
|
-
app.get('/logs/live', { websocket: true }, async
|
|
281
|
+
app.get('/logs/live', { websocket: true }, async socket => {
|
|
199
282
|
runtime.addLoggerDestination(createWebSocketStream(socket))
|
|
200
283
|
})
|
|
201
284
|
}
|
package/lib/runtime.js
CHANGED
|
@@ -222,7 +222,7 @@ export class Runtime extends EventEmitter {
|
|
|
222
222
|
await this.addApplications(this.#config.applications)
|
|
223
223
|
await this.#setDispatcher(config.undici)
|
|
224
224
|
|
|
225
|
-
if (config.scheduler) {
|
|
225
|
+
if (config.scheduler && !this.#context.build) {
|
|
226
226
|
this.#scheduler = startScheduler(config.scheduler, this.#dispatcher, logger)
|
|
227
227
|
}
|
|
228
228
|
|
|
@@ -477,7 +477,13 @@ export class Runtime extends EventEmitter {
|
|
|
477
477
|
await this.startApplications(toStart)
|
|
478
478
|
}
|
|
479
479
|
|
|
480
|
+
const created = []
|
|
481
|
+
for (const { id } of applications) {
|
|
482
|
+
created.push(await this.getApplicationDetails(id))
|
|
483
|
+
}
|
|
484
|
+
|
|
480
485
|
this.#updateLoggingPrefixes()
|
|
486
|
+
return created
|
|
481
487
|
}
|
|
482
488
|
|
|
483
489
|
async removeApplications (applications, silent = false) {
|
|
@@ -485,6 +491,13 @@ export class Runtime extends EventEmitter {
|
|
|
485
491
|
throw new CannotRemoveEntrypointError()
|
|
486
492
|
}
|
|
487
493
|
|
|
494
|
+
const removed = []
|
|
495
|
+
for (const application of applications) {
|
|
496
|
+
const details = await this.getApplicationDetails(application)
|
|
497
|
+
details.status = 'removed'
|
|
498
|
+
removed.push(details)
|
|
499
|
+
}
|
|
500
|
+
|
|
488
501
|
await this.stopApplications(applications, silent, true)
|
|
489
502
|
|
|
490
503
|
for (const application of applications) {
|
|
@@ -498,6 +511,7 @@ export class Runtime extends EventEmitter {
|
|
|
498
511
|
}
|
|
499
512
|
|
|
500
513
|
this.#updateLoggingPrefixes()
|
|
514
|
+
return removed
|
|
501
515
|
}
|
|
502
516
|
|
|
503
517
|
async startApplications (applicationsToStart, silent = false) {
|
|
@@ -1191,7 +1205,7 @@ export class Runtime extends EventEmitter {
|
|
|
1191
1205
|
throw e
|
|
1192
1206
|
}
|
|
1193
1207
|
|
|
1194
|
-
const { entrypoint, localUrl } = application[kConfig]
|
|
1208
|
+
const { entrypoint, localUrl, config, path } = application[kConfig]
|
|
1195
1209
|
|
|
1196
1210
|
const status = await sendViaITC(application, 'getStatus')
|
|
1197
1211
|
const { type, version, dependencies } = await sendViaITC(application, 'getApplicationInfo')
|
|
@@ -1199,6 +1213,8 @@ export class Runtime extends EventEmitter {
|
|
|
1199
1213
|
const applicationDetails = {
|
|
1200
1214
|
id,
|
|
1201
1215
|
type,
|
|
1216
|
+
config,
|
|
1217
|
+
path,
|
|
1202
1218
|
status,
|
|
1203
1219
|
dependencies,
|
|
1204
1220
|
version,
|
|
@@ -1596,7 +1612,7 @@ export class Runtime extends EventEmitter {
|
|
|
1596
1612
|
await this.startApplication(applicationId)
|
|
1597
1613
|
}
|
|
1598
1614
|
|
|
1599
|
-
this.logger.info(`The application "${applicationId}" has been successfully reloaded
|
|
1615
|
+
this.logger.info(`The application "${applicationId}" has been successfully reloaded.`)
|
|
1600
1616
|
this.emitAndNotify('application:worker:reloaded', eventPayload)
|
|
1601
1617
|
|
|
1602
1618
|
if (applicationConfig.entrypoint) {
|
package/lib/worker/main.js
CHANGED
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
disablePinoDirectWrite,
|
|
5
5
|
getPrivateSymbol
|
|
6
6
|
} from '@platformatic/foundation'
|
|
7
|
-
import dotenv from 'dotenv'
|
|
8
7
|
import { subscribe } from 'node:diagnostics_channel'
|
|
9
8
|
import { EventEmitter } from 'node:events'
|
|
10
9
|
import { ServerResponse } from 'node:http'
|
|
@@ -110,9 +109,11 @@ async function main () {
|
|
|
110
109
|
|
|
111
110
|
globalThis.platformatic.logger.debug({ envfile }, 'Loading envfile...')
|
|
112
111
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
112
|
+
try {
|
|
113
|
+
process.loadEnvFile(envfile)
|
|
114
|
+
} catch {
|
|
115
|
+
// Ignore if the file doesn't exist, similar to dotenv behavior
|
|
116
|
+
}
|
|
116
117
|
|
|
117
118
|
if (runtimeConfig.env) {
|
|
118
119
|
Object.assign(process.env, runtimeConfig.env)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/runtime",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.17.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -35,14 +35,14 @@
|
|
|
35
35
|
"typescript": "^5.5.4",
|
|
36
36
|
"undici-oidc-interceptor": "^0.5.0",
|
|
37
37
|
"why-is-node-running": "^2.2.2",
|
|
38
|
-
"@platformatic/
|
|
39
|
-
"@platformatic/
|
|
40
|
-
"@platformatic/gateway": "3.
|
|
41
|
-
"@platformatic/node": "3.
|
|
42
|
-
"@platformatic/
|
|
43
|
-
"@platformatic/
|
|
44
|
-
"@platformatic/sql-mapper": "3.
|
|
45
|
-
"@platformatic/wattpm-pprof-capture": "3.
|
|
38
|
+
"@platformatic/db": "3.17.0",
|
|
39
|
+
"@platformatic/composer": "3.17.0",
|
|
40
|
+
"@platformatic/gateway": "3.17.0",
|
|
41
|
+
"@platformatic/node": "3.17.0",
|
|
42
|
+
"@platformatic/service": "3.17.0",
|
|
43
|
+
"@platformatic/sql-graphql": "3.17.0",
|
|
44
|
+
"@platformatic/sql-mapper": "3.17.0",
|
|
45
|
+
"@platformatic/wattpm-pprof-capture": "3.17.0"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@fastify/accepts": "^5.0.0",
|
|
@@ -57,8 +57,6 @@
|
|
|
57
57
|
"colorette": "^2.0.20",
|
|
58
58
|
"cron": "^4.1.0",
|
|
59
59
|
"debounce": "^2.0.0",
|
|
60
|
-
"dotenv": "^16.4.5",
|
|
61
|
-
"dotenv-tool": "^0.1.1",
|
|
62
60
|
"fastest-levenshtein": "^1.0.16",
|
|
63
61
|
"fastify": "^5.0.0",
|
|
64
62
|
"graphql": "^16.8.1",
|
|
@@ -73,12 +71,12 @@
|
|
|
73
71
|
"undici": "^7.0.0",
|
|
74
72
|
"undici-thread-interceptor": "^0.15.0",
|
|
75
73
|
"ws": "^8.16.0",
|
|
76
|
-
"@platformatic/basic": "3.
|
|
77
|
-
"@platformatic/
|
|
78
|
-
"@platformatic/
|
|
79
|
-
"@platformatic/
|
|
80
|
-
"@platformatic/
|
|
81
|
-
"@platformatic/telemetry": "3.
|
|
74
|
+
"@platformatic/basic": "3.17.0",
|
|
75
|
+
"@platformatic/itc": "3.17.0",
|
|
76
|
+
"@platformatic/generators": "3.17.0",
|
|
77
|
+
"@platformatic/foundation": "3.17.0",
|
|
78
|
+
"@platformatic/metrics": "3.17.0",
|
|
79
|
+
"@platformatic/telemetry": "3.17.0"
|
|
82
80
|
},
|
|
83
81
|
"engines": {
|
|
84
82
|
"node": ">=22.19.0"
|
package/schema.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://schemas.platformatic.dev/@platformatic/runtime/3.
|
|
2
|
+
"$id": "https://schemas.platformatic.dev/@platformatic/runtime/3.17.0.json",
|
|
3
3
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
4
4
|
"title": "Platformatic Runtime Config",
|
|
5
5
|
"type": "object",
|