@platformatic/runtime 2.0.0-alpha.1 → 2.0.0-alpha.3
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/config.d.ts +285 -0
- package/eslint.config.js +8 -0
- package/fixtures/botched-start/platformatic.runtime.json +1 -1
- package/fixtures/botched-start/services/a/platformatic.service.json +1 -1
- package/fixtures/composerApp/platformatic.composer.json +1 -1
- package/fixtures/configs/invalid-autoload-with-services.json +1 -1
- package/fixtures/configs/invalid-entrypoint.json +1 -1
- package/fixtures/configs/invalid-schema-type.config.json +1 -1
- package/fixtures/configs/missing-property.config.json +1 -1
- package/fixtures/configs/missing-service-config.json +1 -1
- package/fixtures/configs/monorepo-composer-no-autoload.json +2 -2
- package/fixtures/configs/monorepo-composer.json +2 -2
- package/fixtures/configs/monorepo-create-cycle.json +2 -2
- package/fixtures/configs/monorepo-missing-dependencies.json +2 -2
- package/fixtures/configs/monorepo-no-cycles.json +2 -2
- package/fixtures/configs/monorepo-openapi.json +2 -2
- package/fixtures/configs/{monorepo-hotreload-env.json → monorepo-watch-env.json} +2 -2
- package/fixtures/configs/monorepo-watch-single.json +12 -0
- package/fixtures/configs/monorepo-watch.json +26 -9
- package/fixtures/configs/monorepo-with-dependencies.json +2 -2
- package/fixtures/configs/monorepo-with-management-api-without-metrics.json +21 -0
- package/fixtures/configs/monorepo-with-management-api.json +2 -2
- package/fixtures/configs/{monorepo-hotreload.json → monorepo-with-metrics.json} +5 -4
- package/fixtures/configs/monorepo.json +2 -2
- package/fixtures/configs/no-services.config.json +1 -1
- package/fixtures/configs/no-sources.config.json +1 -1
- package/fixtures/configs/service-throws-on-start.json +1 -1
- package/fixtures/configs/service-with-env-port.json +2 -2
- package/fixtures/configs/service-with-stdio.json +12 -0
- package/fixtures/configs/{hotreload.json → watch.json} +2 -2
- package/fixtures/dbApp/platformatic.db.json +1 -1
- package/fixtures/dbAppNoName/platformatic.db.json +1 -1
- package/fixtures/dbAppNoPackageJson/platformatic.db.json +1 -1
- package/fixtures/dbAppWithMigrationError/platformatic.db.json +1 -1
- package/fixtures/do-not-reload-dependencies/platformatic.service.json +1 -1
- package/fixtures/do-not-restart-on-crash/platformatic.runtime.json +3 -2
- package/fixtures/do-not-restart-on-crash/services/a/platformatic.service.json +1 -1
- package/fixtures/express/platformatic.runtime.json +1 -1
- package/fixtures/express/services/a/platformatic.service.json +1 -1
- package/fixtures/express/services/b/platformatic.service.json +1 -1
- package/fixtures/external-client/platformatic.service.json +1 -1
- package/fixtures/interceptors/idp.js +2 -2
- package/fixtures/interceptors/platformatic.runtime.json +1 -1
- package/fixtures/interceptors/services/a/platformatic.service.json +1 -1
- package/fixtures/interceptors-2/platformatic.runtime.json +1 -1
- package/fixtures/interceptors-2/services/a/platformatic.service.json +1 -1
- package/fixtures/leven/platformatic.runtime.json +2 -2
- package/fixtures/leven/services/deeply-spittle/platformatic.service.json +1 -1
- package/fixtures/leven/services/rainy-empire/platformatic.composer.json +1 -1
- package/fixtures/management-api/platformatic.json +3 -3
- package/fixtures/management-api/services/service-1/platformatic.json +1 -1
- package/fixtures/management-api/services/service-1/plugin.js +4 -3
- package/fixtures/management-api/services/service-2/platformatic.json +1 -1
- package/fixtures/management-api/services/service-db/platformatic.db.json +1 -1
- package/fixtures/management-api-custom-labels/platformatic.json +2 -2
- package/fixtures/management-api-custom-labels/services/service-1/platformatic.json +1 -1
- package/fixtures/management-api-custom-labels/services/service-1/plugin.js +4 -3
- package/fixtures/management-api-custom-labels/services/service-2/platformatic.json +1 -1
- package/fixtures/management-api-custom-labels/services/service-db/platformatic.db.json +1 -1
- package/fixtures/management-api-without-metrics/platformatic.json +3 -2
- package/fixtures/management-api-without-metrics/services/service-1/platformatic.json +1 -1
- package/fixtures/monorepo/composerApp/platformatic.composer.json +1 -1
- package/fixtures/monorepo/dbApp/platformatic.db.json +1 -1
- package/fixtures/monorepo/serviceApp/platformatic.service.json +3 -2
- package/fixtures/monorepo/serviceApp/with-logger/with-logger.cjs +2 -2
- package/fixtures/monorepo/serviceApp/with-logger/with-logger.d.ts +7 -7
- package/fixtures/monorepo/serviceAppWithLogger/platformatic.service.json +1 -1
- package/fixtures/monorepo/serviceAppWithLogger/plugin.js +12 -0
- package/fixtures/monorepo/serviceAppWithMultiplePlugins/platformatic.service.json +3 -2
- package/fixtures/monorepo-missing-dependencies/composer/platformatic.json +1 -1
- package/fixtures/monorepo-openapi/serviceAppWithoutOpenapi/platformatic.service.json +1 -1
- package/fixtures/monorepo-watch/service1/platformatic.service.json +1 -1
- package/fixtures/monorepo-with-dependencies/main/platformatic.json +1 -1
- package/fixtures/monorepo-with-dependencies/service-1/platformatic.json +1 -1
- package/fixtures/monorepo-with-dependencies/service-2/platformatic.json +1 -1
- package/fixtures/no-env.service.json +1 -1
- package/fixtures/preload/platformatic.runtime.json +1 -1
- package/fixtures/preload/services/a/platformatic.service.json +1 -1
- package/fixtures/prom-server/platformatic.json +2 -2
- package/fixtures/prom-server/services/service-1/platformatic.json +1 -1
- package/fixtures/prom-server/services/service-2/platformatic.json +1 -1
- package/fixtures/restart-on-crash/platformatic.runtime.json +1 -1
- package/fixtures/restart-on-crash/services/a/platformatic.service.json +1 -1
- package/fixtures/sample-runtime/package.json +1 -1
- package/fixtures/sample-runtime/platformatic.json +2 -2
- package/fixtures/sample-runtime/services/rival/package.json +1 -1
- package/fixtures/sample-runtime/services/rival/platformatic.json +1 -1
- package/fixtures/sample-runtime-with-2-services/package.json +1 -1
- package/fixtures/sample-runtime-with-2-services/platformatic.json +2 -2
- package/fixtures/sample-runtime-with-2-services/services/foobar/package.json +1 -1
- package/fixtures/sample-runtime-with-2-services/services/foobar/platformatic.json +1 -1
- package/fixtures/sample-runtime-with-2-services/services/rival/package.json +1 -1
- package/fixtures/sample-runtime-with-2-services/services/rival/platformatic.json +1 -1
- package/fixtures/server/logger-transport/platformatic.runtime.json +2 -2
- package/fixtures/server/logger-transport/services/echo/platformatic.service.json +1 -1
- package/fixtures/server/overrides-service/platformatic.runtime.json +2 -2
- package/fixtures/server/overrides-service/services/echo/platformatic.service.json +1 -1
- package/fixtures/server/runtime-server/platformatic.runtime.json +2 -2
- package/fixtures/server/runtime-server/services/echo/platformatic.service.json +1 -1
- package/fixtures/serviceAppThrowsOnStart/platformatic.service.json +1 -1
- package/fixtures/stackables/node_modules/foo/foo.js +2 -1
- package/fixtures/start-command-in-runtime.js +1 -1
- package/fixtures/stdio/platformatic.service.json +6 -0
- package/fixtures/stdio/plugin.js +24 -0
- package/fixtures/telemetry/platformatic.runtime.json +2 -2
- package/fixtures/telemetry/services/echo/platformatic.service.json +1 -1
- package/fixtures/typescript/platformatic.runtime.json +2 -2
- package/fixtures/typescript/services/composer/platformatic.composer.json +1 -1
- package/fixtures/typescript/services/movies/global.d.ts +2 -3
- package/fixtures/typescript/services/movies/platformatic.db.json +1 -1
- package/fixtures/typescript/services/movies/types/Movie.d.ts +3 -3
- package/fixtures/typescript/services/movies/types/index.d.ts +6 -6
- package/fixtures/typescript/services/titles/client/client.d.ts +35 -35
- package/fixtures/typescript/services/titles/platformatic.service.json +1 -1
- package/fixtures/typescript-custom-flags/platformatic.runtime.json +2 -2
- package/fixtures/typescript-custom-flags/services/composer/platformatic.composer.json +1 -1
- package/fixtures/typescript-custom-flags/services/movies/global.d.ts +2 -3
- package/fixtures/typescript-custom-flags/services/movies/platformatic.db.json +1 -1
- package/fixtures/typescript-custom-flags/services/movies/types/Movie.d.ts +3 -3
- package/fixtures/typescript-custom-flags/services/movies/types/index.d.ts +6 -6
- package/fixtures/typescript-custom-flags/services/titles/client/client.d.ts +35 -35
- package/fixtures/typescript-custom-flags/services/titles/platformatic.service.json +1 -1
- package/fixtures/typescript-no-env/platformatic.runtime.json +2 -2
- package/fixtures/typescript-no-env/services/composer/platformatic.composer.json +1 -1
- package/fixtures/typescript-no-env/services/movies/global.d.ts +2 -3
- package/fixtures/typescript-no-env/services/movies/platformatic.db.json +1 -1
- package/fixtures/typescript-no-env/services/movies/types/Movie.d.ts +3 -3
- package/fixtures/typescript-no-env/services/movies/types/index.d.ts +6 -6
- package/fixtures/typescript-no-env/services/titles/client/client.d.ts +35 -35
- package/fixtures/typescript-no-env/services/titles/platformatic.service.json +1 -1
- package/index.d.ts +7 -8
- package/index.js +14 -10
- package/index.test-d.ts +10 -12
- package/lib/build-server.js +5 -11
- package/lib/compile.js +11 -10
- package/lib/config.js +21 -14
- package/lib/dependencies.js +2 -1
- package/lib/errors.js +3 -2
- package/lib/generator/errors.js +1 -1
- package/lib/generator/runtime-generator.d.ts +15 -15
- package/lib/generator/runtime-generator.js +92 -63
- package/lib/logger.js +55 -0
- package/lib/management-api.js +29 -44
- package/lib/prom-server.js +5 -9
- package/lib/runtime.js +885 -0
- package/lib/schema.js +79 -76
- package/lib/start.js +35 -113
- package/lib/streams/message-port-writable.js +44 -0
- package/lib/streams/pino-writable.js +30 -0
- package/lib/upgrade.js +4 -3
- package/lib/utils.js +49 -1
- package/lib/versions/v1.36.0.js +1 -1
- package/lib/versions/v1.5.0.js +1 -1
- package/lib/versions/v2.0.0.js +17 -0
- package/lib/worker/app.js +224 -0
- package/lib/worker/default-stackable.js +27 -0
- package/lib/worker/itc.js +128 -0
- package/lib/worker/main.js +120 -0
- package/lib/worker/symbols.js +7 -0
- package/package.json +23 -25
- package/runtime.mjs +4 -4
- package/schema.json +824 -0
- package/lib/api-client.js +0 -500
- package/lib/api.js +0 -420
- package/lib/app.js +0 -397
- package/lib/load-config.js +0 -12
- package/lib/loader.mjs +0 -103
- package/lib/message-port-writable.js +0 -50
- package/lib/worker.js +0 -182
- /package/lib/{interceptors.js → worker/interceptors.js} +0 -0
|
@@ -5,7 +5,7 @@ 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
|
|
8
|
+
const { readFile, readdir, stat } = require('node:fs/promises')
|
|
9
9
|
const { ConfigManager } = require('@platformatic/config')
|
|
10
10
|
const { platformaticRuntime } = require('../config')
|
|
11
11
|
const { getServiceTemplateFromSchemaUrl } = require('@platformatic/generators/lib/utils')
|
|
@@ -13,12 +13,13 @@ const { DotEnvTool } = require('dotenv-tool')
|
|
|
13
13
|
const { getArrayDifference } = require('../utils')
|
|
14
14
|
const { createRequire } = require('node:module')
|
|
15
15
|
const { pathToFileURL } = require('node:url')
|
|
16
|
+
const { safeRemove } = require('@platformatic/utils')
|
|
16
17
|
|
|
17
18
|
class RuntimeGenerator extends BaseGenerator {
|
|
18
19
|
constructor (opts) {
|
|
19
20
|
super({
|
|
20
21
|
...opts,
|
|
21
|
-
module: '@platformatic/runtime'
|
|
22
|
+
module: '@platformatic/runtime',
|
|
22
23
|
})
|
|
23
24
|
this.runtimeName = opts.name
|
|
24
25
|
this.services = []
|
|
@@ -32,14 +33,14 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
32
33
|
const newConfig = {
|
|
33
34
|
...originalConfig,
|
|
34
35
|
isRuntimeContext: true,
|
|
35
|
-
serviceName
|
|
36
|
+
serviceName,
|
|
36
37
|
}
|
|
37
38
|
// reset all files previously generated by the service
|
|
38
39
|
service.reset()
|
|
39
40
|
service.setConfig(newConfig)
|
|
40
41
|
this.services.push({
|
|
41
42
|
name: serviceName,
|
|
42
|
-
service
|
|
43
|
+
service,
|
|
43
44
|
})
|
|
44
45
|
|
|
45
46
|
if (typeof service.setRuntime === 'function') {
|
|
@@ -48,7 +49,7 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
setEntryPoint (entryPoint) {
|
|
51
|
-
const service = this.services.find(
|
|
52
|
+
const service = this.services.find(svc => svc.name === entryPoint)
|
|
52
53
|
if (!service) {
|
|
53
54
|
throw new NoServiceNamedError(entryPoint)
|
|
54
55
|
}
|
|
@@ -60,23 +61,24 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
60
61
|
name: `${this.runtimeName}`,
|
|
61
62
|
workspaces: ['services/*'],
|
|
62
63
|
scripts: {
|
|
63
|
-
start: 'platformatic start'
|
|
64
|
+
start: 'platformatic start',
|
|
64
65
|
},
|
|
65
66
|
devDependencies: {
|
|
66
67
|
fastify: `^${this.fastifyVersion}`,
|
|
67
|
-
borp: `${this.pkgData.devDependencies.borp}
|
|
68
|
+
borp: `${this.pkgData.devDependencies.borp}`,
|
|
68
69
|
},
|
|
69
70
|
dependencies: {
|
|
70
71
|
'@platformatic/runtime': `^${this.platformaticVersion}`,
|
|
71
72
|
platformatic: `^${this.platformaticVersion}`,
|
|
72
|
-
...this.config.dependencies
|
|
73
|
+
...this.config.dependencies,
|
|
73
74
|
},
|
|
74
75
|
engines: {
|
|
75
|
-
node: '^18.8.0 || >=20.6.0'
|
|
76
|
-
}
|
|
76
|
+
node: '^18.8.0 || >=20.6.0',
|
|
77
|
+
},
|
|
77
78
|
}
|
|
78
79
|
if (this.config.typescript) {
|
|
79
|
-
const typescriptVersion = JSON.parse(await readFile(join(__dirname, '..', '..', 'package.json'), 'utf-8'))
|
|
80
|
+
const typescriptVersion = JSON.parse(await readFile(join(__dirname, '..', '..', 'package.json'), 'utf-8'))
|
|
81
|
+
.devDependencies.typescript
|
|
80
82
|
template.scripts.clean = 'rm -fr ./dist'
|
|
81
83
|
template.scripts.build = 'platformatic compile'
|
|
82
84
|
template.devDependencies.typescript = typescriptVersion
|
|
@@ -89,18 +91,21 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
89
91
|
this.setServicesConfigValues()
|
|
90
92
|
this.addServicesDependencies()
|
|
91
93
|
|
|
92
|
-
this.addEnvVars(
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
94
|
+
this.addEnvVars(
|
|
95
|
+
{
|
|
96
|
+
PLT_SERVER_HOSTNAME: '127.0.0.1',
|
|
97
|
+
PORT: this.config.port || 3042,
|
|
98
|
+
PLT_SERVER_LOGGER_LEVEL: this.config.logLevel || 'info',
|
|
99
|
+
PLT_MANAGEMENT_API: true,
|
|
100
|
+
},
|
|
101
|
+
{ overwrite: false, default: true }
|
|
102
|
+
)
|
|
98
103
|
}
|
|
99
104
|
|
|
100
105
|
addServicesDependencies () {
|
|
101
106
|
this.services.forEach(({ service }) => {
|
|
102
107
|
if (service.config.dependencies) {
|
|
103
|
-
Object.entries(service.config.dependencies).forEach(
|
|
108
|
+
Object.entries(service.config.dependencies).forEach(kv => {
|
|
104
109
|
this.config.dependencies[kv[0]] = kv[1]
|
|
105
110
|
})
|
|
106
111
|
}
|
|
@@ -116,13 +121,13 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
116
121
|
if (existingConfigFile) {
|
|
117
122
|
const configManager = new ConfigManager({
|
|
118
123
|
...platformaticRuntime.configManagerConfig,
|
|
119
|
-
source: join(this.targetDirectory, existingConfigFile)
|
|
124
|
+
source: join(this.targetDirectory, existingConfigFile),
|
|
120
125
|
})
|
|
121
126
|
await configManager.parse()
|
|
122
127
|
this.existingConfig = configManager.current
|
|
123
128
|
this.config.env = configManager.env
|
|
124
129
|
this.config.port = configManager.env.PORT
|
|
125
|
-
this.entryPoint = configManager.current.services.find(
|
|
130
|
+
this.entryPoint = configManager.current.services.find(svc => svc.entrypoint)
|
|
126
131
|
}
|
|
127
132
|
}
|
|
128
133
|
|
|
@@ -134,7 +139,7 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
134
139
|
await this._afterPrepare()
|
|
135
140
|
return {
|
|
136
141
|
env: this.config.env,
|
|
137
|
-
targetDirectory: this.targetDirectory
|
|
142
|
+
targetDirectory: this.targetDirectory,
|
|
138
143
|
}
|
|
139
144
|
} else {
|
|
140
145
|
return await super.prepare()
|
|
@@ -153,21 +158,21 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
153
158
|
|
|
154
159
|
async _getConfigFileContents () {
|
|
155
160
|
const config = {
|
|
156
|
-
$schema: `https://platformatic.dev/
|
|
161
|
+
$schema: `https://schemas.platformatic.dev/@platformatic/runtime/${this.platformaticVersion}.json`,
|
|
157
162
|
entrypoint: this.entryPoint.name,
|
|
158
|
-
|
|
163
|
+
watch: true,
|
|
159
164
|
autoload: {
|
|
160
165
|
path: 'services',
|
|
161
|
-
exclude: ['docs']
|
|
166
|
+
exclude: ['docs'],
|
|
162
167
|
},
|
|
163
168
|
server: {
|
|
164
169
|
hostname: '{PLT_SERVER_HOSTNAME}',
|
|
165
170
|
port: '{PORT}',
|
|
166
171
|
logger: {
|
|
167
|
-
level: '{PLT_SERVER_LOGGER_LEVEL}'
|
|
168
|
-
}
|
|
172
|
+
level: '{PLT_SERVER_LOGGER_LEVEL}',
|
|
173
|
+
},
|
|
169
174
|
},
|
|
170
|
-
managementApi: '{PLT_MANAGEMENT_API}'
|
|
175
|
+
managementApi: '{PLT_MANAGEMENT_API}',
|
|
171
176
|
}
|
|
172
177
|
|
|
173
178
|
return config
|
|
@@ -181,19 +186,19 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
181
186
|
this.addEnvVars({
|
|
182
187
|
...this.config.env,
|
|
183
188
|
...this.getRuntimeEnv(),
|
|
184
|
-
...servicesEnv
|
|
189
|
+
...servicesEnv,
|
|
185
190
|
})
|
|
186
191
|
|
|
187
192
|
this.addFile({
|
|
188
193
|
path: '',
|
|
189
194
|
file: '.env',
|
|
190
|
-
contents: envObjectToString(this.config.env)
|
|
195
|
+
contents: envObjectToString(this.config.env),
|
|
191
196
|
})
|
|
192
197
|
|
|
193
198
|
this.addFile({
|
|
194
199
|
path: '',
|
|
195
200
|
file: '.env.sample',
|
|
196
|
-
contents: envObjectToString(this.config.env)
|
|
201
|
+
contents: envObjectToString(this.config.env),
|
|
197
202
|
})
|
|
198
203
|
|
|
199
204
|
if (!this.existingConfig) {
|
|
@@ -202,7 +207,7 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
202
207
|
|
|
203
208
|
return {
|
|
204
209
|
targetDirectory: this.targetDirectory,
|
|
205
|
-
env: servicesEnv
|
|
210
|
+
env: servicesEnv,
|
|
206
211
|
}
|
|
207
212
|
}
|
|
208
213
|
|
|
@@ -224,7 +229,10 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
224
229
|
name: 'typescript',
|
|
225
230
|
message: 'Do you want to use TypeScript?',
|
|
226
231
|
default: false,
|
|
227
|
-
choices: [
|
|
232
|
+
choices: [
|
|
233
|
+
{ name: 'yes', value: true },
|
|
234
|
+
{ name: 'no', value: false },
|
|
235
|
+
],
|
|
228
236
|
})
|
|
229
237
|
|
|
230
238
|
if (this.existingConfig) {
|
|
@@ -236,7 +244,7 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
236
244
|
type: 'input',
|
|
237
245
|
name: 'port',
|
|
238
246
|
default: 3042,
|
|
239
|
-
message: 'What port do you want to use?'
|
|
247
|
+
message: 'What port do you want to use?',
|
|
240
248
|
})
|
|
241
249
|
}
|
|
242
250
|
|
|
@@ -251,11 +259,11 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
251
259
|
}
|
|
252
260
|
|
|
253
261
|
setServicesConfig (configToOverride) {
|
|
254
|
-
this.services.forEach(
|
|
262
|
+
this.services.forEach(service => {
|
|
255
263
|
const originalConfig = service.config
|
|
256
264
|
service.setConfig({
|
|
257
265
|
...originalConfig,
|
|
258
|
-
...configToOverride
|
|
266
|
+
...configToOverride,
|
|
259
267
|
})
|
|
260
268
|
})
|
|
261
269
|
}
|
|
@@ -266,12 +274,12 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
266
274
|
// Propagate TypeScript
|
|
267
275
|
svc.service.setConfig({
|
|
268
276
|
...svc.service.config,
|
|
269
|
-
typescript: this.config.typescript
|
|
277
|
+
typescript: this.config.typescript,
|
|
270
278
|
})
|
|
271
279
|
const svcEnv = await svc.service.prepare()
|
|
272
280
|
servicesEnv = {
|
|
273
281
|
...servicesEnv,
|
|
274
|
-
...svcEnv.env
|
|
282
|
+
...svcEnv.env,
|
|
275
283
|
}
|
|
276
284
|
}
|
|
277
285
|
return servicesEnv
|
|
@@ -287,7 +295,7 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
287
295
|
|
|
288
296
|
getRuntimeEnv () {
|
|
289
297
|
return {
|
|
290
|
-
PORT: this.config.port
|
|
298
|
+
PORT: this.config.port,
|
|
291
299
|
}
|
|
292
300
|
}
|
|
293
301
|
|
|
@@ -305,9 +313,11 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
305
313
|
|
|
306
314
|
async loadFromDir () {
|
|
307
315
|
const output = {
|
|
308
|
-
services: []
|
|
316
|
+
services: [],
|
|
309
317
|
}
|
|
310
|
-
const runtimePkgConfigFileData = JSON.parse(
|
|
318
|
+
const runtimePkgConfigFileData = JSON.parse(
|
|
319
|
+
await readFile(join(this.targetDirectory, 'platformatic.json'), 'utf-8')
|
|
320
|
+
)
|
|
311
321
|
const servicesPath = join(this.targetDirectory, runtimePkgConfigFileData.autoload.path)
|
|
312
322
|
|
|
313
323
|
// load all services
|
|
@@ -323,7 +333,7 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
323
333
|
const template = servicePltJson.module || getServiceTemplateFromSchemaUrl(servicePltJson.$schema)
|
|
324
334
|
const Generator = await this._getGeneratorForTemplate(currentServicePath, template)
|
|
325
335
|
const instance = new Generator({
|
|
326
|
-
logger: this.logger
|
|
336
|
+
logger: this.logger,
|
|
327
337
|
})
|
|
328
338
|
this.addService(instance, s)
|
|
329
339
|
output.services.push(await instance.loadFromDir(s, this.targetDirectory))
|
|
@@ -340,11 +350,11 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
340
350
|
const currrentPackageJson = JSON.parse(await readFile(join(this.targetDirectory, 'package.json'), 'utf-8'))
|
|
341
351
|
const currentRuntimeDependencies = currrentPackageJson.dependencies
|
|
342
352
|
// check all services are present with the same template
|
|
343
|
-
const allCurrentServicesNames = this.services.map(
|
|
344
|
-
const allNewServicesNames = newConfig.services.map(
|
|
353
|
+
const allCurrentServicesNames = this.services.map(s => s.name)
|
|
354
|
+
const allNewServicesNames = newConfig.services.map(s => s.name)
|
|
345
355
|
// load dotenv tool
|
|
346
356
|
const envTool = new DotEnvTool({
|
|
347
|
-
path: join(this.targetDirectory, '.env')
|
|
357
|
+
path: join(this.targetDirectory, '.env'),
|
|
348
358
|
})
|
|
349
359
|
|
|
350
360
|
await envTool.load()
|
|
@@ -355,24 +365,25 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
355
365
|
// handle service delete
|
|
356
366
|
|
|
357
367
|
// delete env variables
|
|
358
|
-
const s = this.services.find(
|
|
368
|
+
const s = this.services.find(f => f.name === removedService)
|
|
359
369
|
const allKeys = envTool.getKeys()
|
|
360
|
-
allKeys.forEach(
|
|
370
|
+
allKeys.forEach(k => {
|
|
361
371
|
if (k.startsWith(`PLT_${s.service.config.envPrefix}`)) {
|
|
362
372
|
envTool.deleteKey(k)
|
|
363
373
|
}
|
|
364
374
|
})
|
|
365
375
|
|
|
366
376
|
// delete dependencies
|
|
367
|
-
const servicePackageJson = JSON.parse(
|
|
377
|
+
const servicePackageJson = JSON.parse(
|
|
378
|
+
await readFile(join(this.targetDirectory, 'services', s.name, 'platformatic.json'))
|
|
379
|
+
)
|
|
368
380
|
if (servicePackageJson.plugins && servicePackageJson.plugins.packages) {
|
|
369
|
-
servicePackageJson.plugins.packages
|
|
370
|
-
.
|
|
371
|
-
|
|
372
|
-
})
|
|
381
|
+
servicePackageJson.plugins.packages.forEach(p => {
|
|
382
|
+
delete currrentPackageJson.dependencies[p.name]
|
|
383
|
+
})
|
|
373
384
|
}
|
|
374
385
|
// delete directory
|
|
375
|
-
await
|
|
386
|
+
await safeRemove(join(this.targetDirectory, 'services', s.name))
|
|
376
387
|
}
|
|
377
388
|
// throw new CannotRemoveServiceOnUpdateError(removedServices.join(', '))
|
|
378
389
|
}
|
|
@@ -380,15 +391,18 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
380
391
|
// handle new services
|
|
381
392
|
for (const newService of newConfig.services) {
|
|
382
393
|
// create generator for the service
|
|
383
|
-
const ServiceGenerator = await this._getGeneratorForTemplate(
|
|
394
|
+
const ServiceGenerator = await this._getGeneratorForTemplate(
|
|
395
|
+
join(this.targetDirectory, 'package.json'),
|
|
396
|
+
newService.template
|
|
397
|
+
)
|
|
384
398
|
const serviceInstance = new ServiceGenerator({
|
|
385
|
-
logger: this.logger
|
|
399
|
+
logger: this.logger,
|
|
386
400
|
})
|
|
387
401
|
const baseConfig = {
|
|
388
402
|
isRuntimeContext: true,
|
|
389
403
|
targetDirectory: join(this.targetDirectory, 'services', newService.name),
|
|
390
404
|
serviceName: newService.name,
|
|
391
|
-
plugin: true
|
|
405
|
+
plugin: true,
|
|
392
406
|
}
|
|
393
407
|
if (allCurrentServicesNames.includes(newService.name)) {
|
|
394
408
|
// update existing services env values
|
|
@@ -397,15 +411,15 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
397
411
|
|
|
398
412
|
// handle service's plugin differences
|
|
399
413
|
const oldServiceMetadata = await serviceInstance.loadFromDir(newService.name, this.targetDirectory)
|
|
400
|
-
const oldServicePackages = oldServiceMetadata.plugins.map(
|
|
401
|
-
const newServicePackages = newService.plugins.map(
|
|
414
|
+
const oldServicePackages = oldServiceMetadata.plugins.map(meta => meta.name)
|
|
415
|
+
const newServicePackages = newService.plugins.map(meta => meta.name)
|
|
402
416
|
const pluginsToRemove = getArrayDifference(oldServicePackages, newServicePackages)
|
|
403
|
-
pluginsToRemove.forEach(
|
|
417
|
+
pluginsToRemove.forEach(p => delete currentRuntimeDependencies[p])
|
|
404
418
|
} else {
|
|
405
419
|
// add service to the generator
|
|
406
420
|
this.services.push({
|
|
407
421
|
name: newService.name,
|
|
408
|
-
service: serviceInstance
|
|
422
|
+
service: serviceInstance,
|
|
409
423
|
})
|
|
410
424
|
}
|
|
411
425
|
serviceInstance.setConfig(baseConfig)
|
|
@@ -430,7 +444,7 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
430
444
|
await serviceInstance.writeFiles()
|
|
431
445
|
// cleanup runtime env removing keys not present anymore in service plugins
|
|
432
446
|
const allKeys = envTool.getKeys()
|
|
433
|
-
allKeys.forEach(
|
|
447
|
+
allKeys.forEach(k => {
|
|
434
448
|
if (k.startsWith(`${serviceEnvPrefix}_FST_PLUGIN`) && !runtimeAddedEnvKeys.includes(k)) {
|
|
435
449
|
envTool.deleteKey(k)
|
|
436
450
|
}
|
|
@@ -441,18 +455,33 @@ class RuntimeGenerator extends BaseGenerator {
|
|
|
441
455
|
envTool.addKey(key, value)
|
|
442
456
|
})
|
|
443
457
|
}
|
|
444
|
-
|
|
445
458
|
// update runtime package.json dependencies
|
|
446
459
|
currrentPackageJson.dependencies = {
|
|
447
460
|
...currrentPackageJson.dependencies,
|
|
448
|
-
...allServicesDependencies
|
|
461
|
+
...allServicesDependencies,
|
|
449
462
|
}
|
|
450
463
|
this.addFile({
|
|
451
464
|
path: '',
|
|
452
465
|
file: 'package.json',
|
|
453
|
-
contents: JSON.stringify(currrentPackageJson, null, 2)
|
|
466
|
+
contents: JSON.stringify(currrentPackageJson, null, 2),
|
|
454
467
|
})
|
|
455
468
|
|
|
469
|
+
// set new entrypoint if specified
|
|
470
|
+
const newEntrypoint = newConfig.entrypoint
|
|
471
|
+
if (newEntrypoint) {
|
|
472
|
+
// load platformatic.json runtime config
|
|
473
|
+
const runtimePkgConfigFileData = JSON.parse(
|
|
474
|
+
await readFile(join(this.targetDirectory, 'platformatic.json'), 'utf-8')
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
this.setEntryPoint(newEntrypoint)
|
|
478
|
+
runtimePkgConfigFileData.entrypoint = newEntrypoint
|
|
479
|
+
this.addFile({
|
|
480
|
+
path: '',
|
|
481
|
+
file: 'platformatic.json',
|
|
482
|
+
contents: JSON.stringify(runtimePkgConfigFileData, null, 2),
|
|
483
|
+
})
|
|
484
|
+
}
|
|
456
485
|
await this.writeFiles()
|
|
457
486
|
// save new env
|
|
458
487
|
await envTool.save()
|
package/lib/logger.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { join } = require('node:path')
|
|
4
|
+
const { isatty } = require('node:tty')
|
|
5
|
+
|
|
6
|
+
const pino = require('pino')
|
|
7
|
+
const pretty = require('pino-pretty')
|
|
8
|
+
|
|
9
|
+
function createLogger (config, runtimeLogsDir) {
|
|
10
|
+
const loggerConfig = { ...config.server?.logger }
|
|
11
|
+
const cliStream = isatty(1) ? pretty() : pino.destination(1)
|
|
12
|
+
|
|
13
|
+
if (!config.managementApi) {
|
|
14
|
+
return [pino(loggerConfig, cliStream), cliStream]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const multiStream = pino.multistream([
|
|
18
|
+
{ stream: cliStream, level: loggerConfig.level || 'info' },
|
|
19
|
+
])
|
|
20
|
+
|
|
21
|
+
if (loggerConfig.transport) {
|
|
22
|
+
const transport = pino.transport(loggerConfig.transport)
|
|
23
|
+
multiStream.add({ level: loggerConfig.level || 'info', stream: transport })
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (config.managementApi) {
|
|
27
|
+
const logsFileMb = 5
|
|
28
|
+
const logsLimitMb = config.managementApi?.logs?.maxSize || 200
|
|
29
|
+
|
|
30
|
+
let logsLimitCount = Math.ceil(logsLimitMb / logsFileMb) - 1
|
|
31
|
+
if (logsLimitCount < 1) {
|
|
32
|
+
logsLimitCount = 1
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const pinoRoll = pino.transport({
|
|
36
|
+
target: 'pino-roll',
|
|
37
|
+
options: {
|
|
38
|
+
file: join(runtimeLogsDir, 'logs'),
|
|
39
|
+
mode: 0o600,
|
|
40
|
+
size: logsFileMb + 'm',
|
|
41
|
+
mkdir: true,
|
|
42
|
+
fsync: true,
|
|
43
|
+
limit: {
|
|
44
|
+
count: logsLimitCount,
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
multiStream.add({ level: 'trace', stream: pinoRoll })
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return [pino({ level: 'trace' }, multiStream), multiStream]
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
module.exports = { createLogger }
|
package/lib/management-api.js
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { tmpdir } = require('node:os')
|
|
4
|
-
const { platform } = require('node:os')
|
|
3
|
+
const { platform, tmpdir } = require('node:os')
|
|
5
4
|
const { join } = require('node:path')
|
|
6
|
-
const {
|
|
5
|
+
const { createDirectory, safeRemove } = require('@platformatic/utils')
|
|
6
|
+
|
|
7
7
|
const fastify = require('fastify')
|
|
8
8
|
const ws = require('ws')
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
const errors = require('./errors')
|
|
11
|
+
const { getRuntimeLogsDir } = require('./utils')
|
|
11
12
|
|
|
12
13
|
const PLATFORMATIC_TMP_DIR = join(tmpdir(), 'platformatic', 'runtimes')
|
|
13
14
|
|
|
14
15
|
async function managementApiPlugin (app, opts) {
|
|
15
16
|
app.log.warn(
|
|
16
17
|
'Runtime Management API is in the experimental stage. ' +
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
'The feature is not subject to semantic versioning rules. ' +
|
|
19
|
+
'Non-backward compatible changes or removal may occur in any future release. ' +
|
|
20
|
+
'Use of the feature is not recommended in production environments.'
|
|
20
21
|
)
|
|
21
22
|
|
|
22
23
|
const runtime = opts.runtime
|
|
@@ -35,7 +36,7 @@ async function managementApiPlugin (app, opts) {
|
|
|
35
36
|
|
|
36
37
|
app.post('/stop', async () => {
|
|
37
38
|
app.log.debug('stop services')
|
|
38
|
-
await runtime.close()
|
|
39
|
+
await runtime.close(true)
|
|
39
40
|
})
|
|
40
41
|
|
|
41
42
|
app.post('/reload', async () => {
|
|
@@ -47,40 +48,40 @@ async function managementApiPlugin (app, opts) {
|
|
|
47
48
|
return runtime.getServices()
|
|
48
49
|
})
|
|
49
50
|
|
|
50
|
-
app.get('/services/:id', async
|
|
51
|
+
app.get('/services/:id', async request => {
|
|
51
52
|
const { id } = request.params
|
|
52
53
|
app.log.debug('get service details', { id })
|
|
53
54
|
return runtime.getServiceDetails(id)
|
|
54
55
|
})
|
|
55
56
|
|
|
56
|
-
app.get('/services/:id/config', async
|
|
57
|
+
app.get('/services/:id/config', async request => {
|
|
57
58
|
const { id } = request.params
|
|
58
59
|
app.log.debug('get service config', { id })
|
|
59
60
|
return runtime.getServiceConfig(id)
|
|
60
61
|
})
|
|
61
62
|
|
|
62
|
-
app.get('/services/:id/openapi-schema', async
|
|
63
|
+
app.get('/services/:id/openapi-schema', async request => {
|
|
63
64
|
const { id } = request.params
|
|
64
65
|
app.log.debug('get openapi-schema', { id })
|
|
65
66
|
return runtime.getServiceOpenapiSchema(id)
|
|
66
67
|
})
|
|
67
68
|
|
|
68
|
-
app.get('/services/:id/graphql-schema', async
|
|
69
|
+
app.get('/services/:id/graphql-schema', async request => {
|
|
69
70
|
const { id } = request.params
|
|
70
71
|
app.log.debug('get graphql-schema', { id })
|
|
71
72
|
return runtime.getServiceGraphqlSchema(id)
|
|
72
73
|
})
|
|
73
74
|
|
|
74
|
-
app.post('/services/:id/start', async
|
|
75
|
+
app.post('/services/:id/start', async request => {
|
|
75
76
|
const { id } = request.params
|
|
76
77
|
app.log.debug('start service', { id })
|
|
77
78
|
await runtime.startService(id)
|
|
78
79
|
})
|
|
79
80
|
|
|
80
|
-
app.post('/services/:id/stop', async
|
|
81
|
+
app.post('/services/:id/stop', async request => {
|
|
81
82
|
const { id } = request.params
|
|
82
83
|
app.log.debug('stop service', { id })
|
|
83
|
-
await runtime.
|
|
84
|
+
await runtime._stopService(id)
|
|
84
85
|
})
|
|
85
86
|
|
|
86
87
|
app.all('/services/:id/proxy/*', async (request, reply) => {
|
|
@@ -97,27 +98,22 @@ async function managementApiPlugin (app, opts) {
|
|
|
97
98
|
url: requestUrl || '/',
|
|
98
99
|
headers: request.headers,
|
|
99
100
|
query: request.query,
|
|
100
|
-
body: request.body
|
|
101
|
+
body: request.body,
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
const res = await runtime.inject(id, injectParams)
|
|
104
105
|
|
|
105
|
-
reply
|
|
106
|
-
.code(res.statusCode)
|
|
107
|
-
.headers(res.headers)
|
|
108
|
-
.send(res.body)
|
|
106
|
+
reply.code(res.statusCode).headers(res.headers).send(res.body)
|
|
109
107
|
})
|
|
110
108
|
|
|
111
|
-
app.get('/metrics/live', { websocket: true }, async
|
|
109
|
+
app.get('/metrics/live', { websocket: true }, async socket => {
|
|
112
110
|
const cachedMetrics = runtime.getCachedMetrics()
|
|
113
111
|
if (cachedMetrics.length > 0) {
|
|
114
|
-
const serializedMetrics = cachedMetrics
|
|
115
|
-
.map((metric) => JSON.stringify(metric))
|
|
116
|
-
.join('\n')
|
|
112
|
+
const serializedMetrics = cachedMetrics.map(metric => JSON.stringify(metric)).join('\n')
|
|
117
113
|
socket.send(serializedMetrics + '\n')
|
|
118
114
|
}
|
|
119
115
|
|
|
120
|
-
const eventHandler =
|
|
116
|
+
const eventHandler = metrics => {
|
|
121
117
|
const serializedMetrics = JSON.stringify(metrics)
|
|
122
118
|
socket.send(serializedMetrics + '\n')
|
|
123
119
|
}
|
|
@@ -147,7 +143,7 @@ async function managementApiPlugin (app, opts) {
|
|
|
147
143
|
runtime.pipeLogsStream(stream, req.log, startLogId)
|
|
148
144
|
})
|
|
149
145
|
|
|
150
|
-
app.get('/logs/indexes', async
|
|
146
|
+
app.get('/logs/indexes', async req => {
|
|
151
147
|
const returnAllIds = req.query.all === 'true'
|
|
152
148
|
|
|
153
149
|
if (returnAllIds) {
|
|
@@ -168,16 +164,10 @@ async function managementApiPlugin (app, opts) {
|
|
|
168
164
|
|
|
169
165
|
reply.hijack()
|
|
170
166
|
|
|
171
|
-
runtime.pipeLogsStream(
|
|
172
|
-
reply.raw,
|
|
173
|
-
req.log,
|
|
174
|
-
startLogId,
|
|
175
|
-
endLogId,
|
|
176
|
-
runtimePID
|
|
177
|
-
)
|
|
167
|
+
runtime.pipeLogsStream(reply.raw, req.log, startLogId, endLogId, runtimePID)
|
|
178
168
|
})
|
|
179
169
|
|
|
180
|
-
app.get('/logs/:id', async
|
|
170
|
+
app.get('/logs/:id', async req => {
|
|
181
171
|
const logId = parseInt(req.params.id)
|
|
182
172
|
const runtimePID = parseInt(req.query.pid) || process.pid
|
|
183
173
|
|
|
@@ -186,10 +176,7 @@ async function managementApiPlugin (app, opts) {
|
|
|
186
176
|
throw new errors.LogFileNotFound(logId)
|
|
187
177
|
}
|
|
188
178
|
|
|
189
|
-
const logFileStream = await runtime.getLogFileStream(
|
|
190
|
-
logId,
|
|
191
|
-
runtimePID
|
|
192
|
-
)
|
|
179
|
+
const logFileStream = await runtime.getLogFileStream(logId, runtimePID)
|
|
193
180
|
return logFileStream
|
|
194
181
|
})
|
|
195
182
|
}
|
|
@@ -200,13 +187,11 @@ async function startManagementApi (runtime, configManager) {
|
|
|
200
187
|
try {
|
|
201
188
|
const runtimePIDDir = join(PLATFORMATIC_TMP_DIR, runtimePID.toString())
|
|
202
189
|
if (platform() !== 'win32') {
|
|
203
|
-
await
|
|
204
|
-
await mkdir(runtimePIDDir, { recursive: true })
|
|
190
|
+
await createDirectory(runtimePIDDir, true)
|
|
205
191
|
}
|
|
206
192
|
|
|
207
193
|
const runtimeLogsDir = getRuntimeLogsDir(configManager.dirname, process.pid)
|
|
208
|
-
await
|
|
209
|
-
await mkdir(runtimeLogsDir, { recursive: true })
|
|
194
|
+
await createDirectory(runtimeLogsDir, true)
|
|
210
195
|
|
|
211
196
|
let socketPath = null
|
|
212
197
|
if (platform() === 'win32') {
|
|
@@ -221,13 +206,13 @@ async function startManagementApi (runtime, configManager) {
|
|
|
221
206
|
|
|
222
207
|
managementApi.addHook('onClose', async () => {
|
|
223
208
|
if (platform() !== 'win32') {
|
|
224
|
-
await
|
|
209
|
+
await safeRemove(runtimePIDDir)
|
|
225
210
|
}
|
|
226
211
|
})
|
|
227
212
|
|
|
228
213
|
await managementApi.listen({ path: socketPath })
|
|
229
214
|
return managementApi
|
|
230
|
-
|
|
215
|
+
/* c8 ignore next 4 */
|
|
231
216
|
} catch (err) {
|
|
232
217
|
console.error(err)
|
|
233
218
|
process.exit(1)
|