@platformatic/runtime 1.53.3 → 2.0.0-alpha.10

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.
Files changed (178) hide show
  1. package/config.d.ts +284 -0
  2. package/eslint.config.js +8 -0
  3. package/fixtures/botched-start/platformatic.runtime.json +1 -1
  4. package/fixtures/botched-start/services/a/platformatic.service.json +1 -1
  5. package/fixtures/composerApp/platformatic.composer.json +1 -1
  6. package/fixtures/configs/{monorepo-hotreload.json → invalid-autoload-with-services.json} +8 -8
  7. package/fixtures/configs/invalid-entrypoint.json +1 -1
  8. package/fixtures/configs/invalid-schema-type.config.json +1 -1
  9. package/fixtures/configs/missing-property.config.json +1 -1
  10. package/fixtures/configs/missing-service-config.json +1 -1
  11. package/fixtures/configs/monorepo-composer-no-autoload.json +32 -0
  12. package/fixtures/configs/monorepo-composer.json +2 -2
  13. package/fixtures/configs/monorepo-create-cycle.json +2 -3
  14. package/fixtures/configs/monorepo-missing-dependencies.json +9 -0
  15. package/fixtures/configs/monorepo-no-cycles.json +2 -3
  16. package/fixtures/configs/monorepo-openapi.json +2 -2
  17. package/fixtures/configs/{hotreload.json → monorepo-watch-env.json} +2 -3
  18. package/fixtures/configs/monorepo-watch-single.json +12 -0
  19. package/fixtures/configs/monorepo-watch.json +26 -9
  20. package/fixtures/configs/monorepo-with-dependencies.json +2 -2
  21. package/fixtures/configs/{monorepo-client-without-id.json → monorepo-with-management-api-without-metrics.json} +5 -8
  22. package/fixtures/configs/monorepo-with-management-api.json +2 -3
  23. package/fixtures/configs/monorepo-with-metrics.json +1 -2
  24. package/fixtures/configs/monorepo.json +2 -3
  25. package/fixtures/configs/no-services.config.json +1 -1
  26. package/fixtures/configs/no-sources.config.json +1 -1
  27. package/fixtures/configs/service-throws-on-start.json +1 -1
  28. package/fixtures/configs/service-with-env-port.json +2 -3
  29. package/fixtures/configs/service-with-stdio.json +12 -0
  30. package/fixtures/configs/{monorepo-hotreload-env.json → watch.json} +2 -3
  31. package/fixtures/crash-on-bootstrap/platformatic.runtime.json +15 -0
  32. package/fixtures/crash-on-bootstrap/services/service-1/platformatic.service.json +14 -0
  33. package/fixtures/crash-on-bootstrap/services/service-1/plugin.js +5 -0
  34. package/fixtures/crash-on-bootstrap/services/service-2/platformatic.service.json +14 -0
  35. package/fixtures/crash-on-bootstrap/services/service-2/plugin.js +5 -0
  36. package/fixtures/dbApp/platformatic.db.json +1 -1
  37. package/fixtures/dbAppNoName/platformatic.db.json +1 -1
  38. package/fixtures/dbAppNoPackageJson/platformatic.db.json +1 -1
  39. package/fixtures/dbAppWithMigrationError/platformatic.db.json +1 -1
  40. package/fixtures/do-not-reload-dependencies/platformatic.service.json +1 -1
  41. package/fixtures/do-not-restart-on-crash/platformatic.runtime.json +3 -2
  42. package/fixtures/do-not-restart-on-crash/services/a/platformatic.service.json +1 -1
  43. package/fixtures/express/platformatic.runtime.json +1 -1
  44. package/fixtures/express/services/a/platformatic.service.json +1 -1
  45. package/fixtures/express/services/b/platformatic.service.json +1 -1
  46. package/fixtures/external-client/platformatic.service.json +1 -1
  47. package/fixtures/interceptors/idp.js +2 -2
  48. package/fixtures/interceptors/platformatic.runtime.json +1 -1
  49. package/fixtures/interceptors/services/a/platformatic.service.json +1 -1
  50. package/fixtures/interceptors-2/platformatic.runtime.json +1 -1
  51. package/fixtures/interceptors-2/services/a/platformatic.service.json +1 -1
  52. package/fixtures/leven/platformatic.runtime.json +2 -3
  53. package/fixtures/leven/services/deeply-spittle/platformatic.service.json +1 -1
  54. package/fixtures/leven/services/rainy-empire/platformatic.composer.json +1 -1
  55. package/fixtures/management-api/platformatic.json +8 -4
  56. package/fixtures/management-api/services/service-1/platformatic.json +1 -1
  57. package/fixtures/management-api/services/service-1/plugin.js +4 -3
  58. package/fixtures/management-api/services/service-2/platformatic.json +1 -1
  59. package/fixtures/management-api/services/service-db/platformatic.db.json +1 -1
  60. package/fixtures/management-api-custom-labels/platformatic.json +2 -3
  61. package/fixtures/management-api-custom-labels/services/service-1/platformatic.json +1 -1
  62. package/fixtures/management-api-custom-labels/services/service-1/plugin.js +4 -3
  63. package/fixtures/management-api-custom-labels/services/service-2/platformatic.json +1 -1
  64. package/fixtures/management-api-custom-labels/services/service-db/platformatic.db.json +1 -1
  65. package/fixtures/management-api-without-metrics/platformatic.json +3 -3
  66. package/fixtures/management-api-without-metrics/services/service-1/platformatic.json +1 -1
  67. package/fixtures/monorepo/composerApp/platformatic.composer.json +1 -2
  68. package/fixtures/monorepo/dbApp/platformatic.db.json +1 -1
  69. package/fixtures/monorepo/serviceApp/platformatic.service.json +3 -2
  70. package/fixtures/monorepo/serviceApp/with-logger/with-logger.cjs +2 -2
  71. package/fixtures/monorepo/serviceApp/with-logger/with-logger.d.ts +7 -7
  72. package/fixtures/monorepo/serviceAppWithLogger/platformatic.service.json +1 -1
  73. package/fixtures/monorepo/serviceAppWithLogger/plugin.js +12 -0
  74. package/fixtures/monorepo/serviceAppWithMultiplePlugins/platformatic.service.json +3 -2
  75. package/fixtures/monorepo-missing-dependencies/composer/platformatic.json +24 -0
  76. package/fixtures/monorepo-openapi/serviceAppWithoutOpenapi/platformatic.service.json +1 -1
  77. package/fixtures/monorepo-watch/service1/platformatic.service.json +1 -1
  78. package/fixtures/monorepo-with-dependencies/main/platformatic.json +1 -1
  79. package/fixtures/monorepo-with-dependencies/service-1/platformatic.json +1 -1
  80. package/fixtures/monorepo-with-dependencies/service-2/platformatic.json +1 -1
  81. package/fixtures/no-env.service.json +1 -1
  82. package/fixtures/preload/platformatic.runtime.json +1 -1
  83. package/fixtures/preload/services/a/platformatic.service.json +1 -1
  84. package/fixtures/prom-server/platformatic.json +2 -3
  85. package/fixtures/prom-server/services/service-1/platformatic.json +1 -1
  86. package/fixtures/prom-server/services/service-2/platformatic.json +1 -1
  87. package/fixtures/restart-on-crash/platformatic.runtime.json +1 -1
  88. package/fixtures/restart-on-crash/services/a/platformatic.service.json +1 -1
  89. package/fixtures/sample-runtime/package.json +1 -1
  90. package/fixtures/sample-runtime/platformatic.json +2 -3
  91. package/fixtures/sample-runtime/services/rival/package.json +1 -1
  92. package/fixtures/sample-runtime/services/rival/platformatic.json +1 -1
  93. package/fixtures/sample-runtime-with-2-services/package.json +1 -1
  94. package/fixtures/sample-runtime-with-2-services/platformatic.json +2 -3
  95. package/fixtures/sample-runtime-with-2-services/services/foobar/package.json +1 -1
  96. package/fixtures/sample-runtime-with-2-services/services/foobar/platformatic.json +1 -1
  97. package/fixtures/sample-runtime-with-2-services/services/rival/package.json +1 -1
  98. package/fixtures/sample-runtime-with-2-services/services/rival/platformatic.json +1 -1
  99. package/fixtures/server/logger-transport/platformatic.runtime.json +2 -3
  100. package/fixtures/server/logger-transport/services/echo/platformatic.service.json +1 -1
  101. package/fixtures/server/overrides-service/platformatic.runtime.json +2 -3
  102. package/fixtures/server/overrides-service/services/echo/platformatic.service.json +1 -1
  103. package/fixtures/server/runtime-server/platformatic.runtime.json +2 -3
  104. package/fixtures/server/runtime-server/services/echo/platformatic.service.json +1 -1
  105. package/fixtures/serviceAppThrowsOnStart/platformatic.service.json +1 -1
  106. package/fixtures/stackables/node_modules/foo/foo.js +2 -1
  107. package/fixtures/start-command-in-runtime.js +1 -1
  108. package/fixtures/stdio/platformatic.service.json +6 -0
  109. package/fixtures/stdio/plugin.js +24 -0
  110. package/fixtures/telemetry/platformatic.runtime.json +2 -3
  111. package/fixtures/telemetry/services/echo/platformatic.service.json +1 -1
  112. package/fixtures/telemetry/services/echo/routes/span.js +16 -2
  113. package/fixtures/telemetry/services/service-1/platformatic.service.json +19 -0
  114. package/fixtures/telemetry/services/service-1/routes/echo.js +7 -0
  115. package/fixtures/typescript/platformatic.runtime.json +2 -3
  116. package/fixtures/typescript/services/composer/platformatic.composer.json +1 -1
  117. package/fixtures/typescript/services/movies/global.d.ts +2 -3
  118. package/fixtures/typescript/services/movies/platformatic.db.json +1 -1
  119. package/fixtures/typescript/services/movies/types/Movie.d.ts +3 -3
  120. package/fixtures/typescript/services/movies/types/index.d.ts +6 -6
  121. package/fixtures/typescript/services/titles/client/client.d.ts +35 -35
  122. package/fixtures/typescript/services/titles/platformatic.service.json +1 -1
  123. package/fixtures/typescript-custom-flags/platformatic.runtime.json +2 -3
  124. package/fixtures/typescript-custom-flags/services/composer/platformatic.composer.json +1 -1
  125. package/fixtures/typescript-custom-flags/services/movies/global.d.ts +2 -3
  126. package/fixtures/typescript-custom-flags/services/movies/platformatic.db.json +1 -1
  127. package/fixtures/typescript-custom-flags/services/movies/types/Movie.d.ts +3 -3
  128. package/fixtures/typescript-custom-flags/services/movies/types/index.d.ts +6 -6
  129. package/fixtures/typescript-custom-flags/services/titles/client/client.d.ts +35 -35
  130. package/fixtures/typescript-custom-flags/services/titles/platformatic.service.json +1 -1
  131. package/fixtures/typescript-no-env/platformatic.runtime.json +2 -3
  132. package/fixtures/typescript-no-env/services/composer/platformatic.composer.json +1 -1
  133. package/fixtures/typescript-no-env/services/movies/global.d.ts +2 -3
  134. package/fixtures/typescript-no-env/services/movies/platformatic.db.json +1 -1
  135. package/fixtures/typescript-no-env/services/movies/types/Movie.d.ts +3 -3
  136. package/fixtures/typescript-no-env/services/movies/types/index.d.ts +6 -6
  137. package/fixtures/typescript-no-env/services/titles/client/client.d.ts +35 -35
  138. package/fixtures/typescript-no-env/services/titles/platformatic.service.json +1 -1
  139. package/index.d.ts +7 -8
  140. package/index.js +15 -10
  141. package/index.test-d.ts +10 -12
  142. package/lib/build-server.js +23 -15
  143. package/lib/compile.js +56 -13
  144. package/lib/config.js +27 -139
  145. package/lib/dependencies.js +59 -0
  146. package/lib/errors.js +6 -2
  147. package/lib/generator/errors.js +1 -1
  148. package/lib/generator/runtime-generator.d.ts +15 -15
  149. package/lib/generator/runtime-generator.js +81 -66
  150. package/lib/logger.js +55 -0
  151. package/lib/management-api.js +29 -44
  152. package/lib/prom-server.js +5 -9
  153. package/lib/runtime.js +1005 -0
  154. package/lib/schema.js +46 -44
  155. package/lib/start.js +49 -117
  156. package/lib/upgrade.js +4 -3
  157. package/lib/utils.js +49 -1
  158. package/lib/versions/v1.36.0.js +1 -1
  159. package/lib/versions/v1.5.0.js +1 -1
  160. package/lib/versions/v2.0.0.js +17 -0
  161. package/lib/worker/app.js +266 -0
  162. package/lib/worker/default-stackable.js +32 -0
  163. package/lib/worker/itc.js +149 -0
  164. package/lib/worker/main.js +129 -0
  165. package/lib/worker/metrics.js +106 -0
  166. package/lib/worker/symbols.js +7 -0
  167. package/package.json +44 -44
  168. package/runtime.mjs +11 -6
  169. package/schema.json +25 -13
  170. package/fixtures/monorepo/serviceApp/platformatic.service-client-without-id.json +0 -21
  171. package/lib/api-client.js +0 -497
  172. package/lib/api.js +0 -397
  173. package/lib/app.js +0 -365
  174. package/lib/load-config.js +0 -20
  175. package/lib/loader.mjs +0 -103
  176. package/lib/message-port-writable.js +0 -50
  177. package/lib/worker.js +0 -182
  178. /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, rm } = require('node:fs/promises')
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((svc) => svc.name === entryPoint)
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')).devDependencies.typescript
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
- PLT_SERVER_HOSTNAME: '127.0.0.1',
94
- PORT: this.config.port || 3042,
95
- PLT_SERVER_LOGGER_LEVEL: this.config.logLevel || 'info',
96
- PLT_MANAGEMENT_API: true
97
- }, { overwrite: false, default: true })
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((kv) => {
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((svc) => svc.entrypoint)
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,22 +158,21 @@ class RuntimeGenerator extends BaseGenerator {
153
158
 
154
159
  async _getConfigFileContents () {
155
160
  const config = {
156
- $schema: `https://platformatic.dev/schemas/v${this.platformaticVersion}/runtime`,
161
+ $schema: `https://schemas.platformatic.dev/@platformatic/runtime/${this.platformaticVersion}.json`,
157
162
  entrypoint: this.entryPoint.name,
158
- allowCycles: false,
159
- hotReload: true,
163
+ watch: true,
160
164
  autoload: {
161
165
  path: 'services',
162
- exclude: ['docs']
166
+ exclude: ['docs'],
163
167
  },
164
168
  server: {
165
169
  hostname: '{PLT_SERVER_HOSTNAME}',
166
170
  port: '{PORT}',
167
171
  logger: {
168
- level: '{PLT_SERVER_LOGGER_LEVEL}'
169
- }
172
+ level: '{PLT_SERVER_LOGGER_LEVEL}',
173
+ },
170
174
  },
171
- managementApi: '{PLT_MANAGEMENT_API}'
175
+ managementApi: '{PLT_MANAGEMENT_API}',
172
176
  }
173
177
 
174
178
  return config
@@ -182,28 +186,28 @@ class RuntimeGenerator extends BaseGenerator {
182
186
  this.addEnvVars({
183
187
  ...this.config.env,
184
188
  ...this.getRuntimeEnv(),
185
- ...servicesEnv
189
+ ...servicesEnv,
186
190
  })
187
191
 
188
192
  this.addFile({
189
193
  path: '',
190
194
  file: '.env',
191
- contents: envObjectToString(this.config.env)
195
+ contents: envObjectToString(this.config.env),
192
196
  })
193
197
 
194
198
  this.addFile({
195
199
  path: '',
196
200
  file: '.env.sample',
197
- contents: envObjectToString(this.config.env)
201
+ contents: envObjectToString(this.config.env),
198
202
  })
199
203
 
200
204
  if (!this.existingConfig) {
201
- this.addFile({ path: '', file: 'README.md', contents: await readFile(join(__dirname, 'README.md')) })
205
+ this.addFile({ path: '', file: 'README.md', contents: await readFile(join(__dirname, 'README.md'), 'utf-8') })
202
206
  }
203
207
 
204
208
  return {
205
209
  targetDirectory: this.targetDirectory,
206
- env: servicesEnv
210
+ env: servicesEnv,
207
211
  }
208
212
  }
209
213
 
@@ -225,7 +229,10 @@ class RuntimeGenerator extends BaseGenerator {
225
229
  name: 'typescript',
226
230
  message: 'Do you want to use TypeScript?',
227
231
  default: false,
228
- choices: [{ name: 'yes', value: true }, { name: 'no', value: false }]
232
+ choices: [
233
+ { name: 'yes', value: true },
234
+ { name: 'no', value: false },
235
+ ],
229
236
  })
230
237
 
231
238
  if (this.existingConfig) {
@@ -237,7 +244,7 @@ class RuntimeGenerator extends BaseGenerator {
237
244
  type: 'input',
238
245
  name: 'port',
239
246
  default: 3042,
240
- message: 'What port do you want to use?'
247
+ message: 'What port do you want to use?',
241
248
  })
242
249
  }
243
250
 
@@ -252,11 +259,11 @@ class RuntimeGenerator extends BaseGenerator {
252
259
  }
253
260
 
254
261
  setServicesConfig (configToOverride) {
255
- this.services.forEach((service) => {
262
+ this.services.forEach(service => {
256
263
  const originalConfig = service.config
257
264
  service.setConfig({
258
265
  ...originalConfig,
259
- ...configToOverride
266
+ ...configToOverride,
260
267
  })
261
268
  })
262
269
  }
@@ -267,12 +274,12 @@ class RuntimeGenerator extends BaseGenerator {
267
274
  // Propagate TypeScript
268
275
  svc.service.setConfig({
269
276
  ...svc.service.config,
270
- typescript: this.config.typescript
277
+ typescript: this.config.typescript,
271
278
  })
272
279
  const svcEnv = await svc.service.prepare()
273
280
  servicesEnv = {
274
281
  ...servicesEnv,
275
- ...svcEnv.env
282
+ ...svcEnv.env,
276
283
  }
277
284
  }
278
285
  return servicesEnv
@@ -288,7 +295,7 @@ class RuntimeGenerator extends BaseGenerator {
288
295
 
289
296
  getRuntimeEnv () {
290
297
  return {
291
- PORT: this.config.port
298
+ PORT: this.config.port,
292
299
  }
293
300
  }
294
301
 
@@ -306,9 +313,11 @@ class RuntimeGenerator extends BaseGenerator {
306
313
 
307
314
  async loadFromDir () {
308
315
  const output = {
309
- services: []
316
+ services: [],
310
317
  }
311
- const runtimePkgConfigFileData = JSON.parse(await readFile(join(this.targetDirectory, 'platformatic.json'), 'utf-8'))
318
+ const runtimePkgConfigFileData = JSON.parse(
319
+ await readFile(join(this.targetDirectory, 'platformatic.json'), 'utf-8')
320
+ )
312
321
  const servicesPath = join(this.targetDirectory, runtimePkgConfigFileData.autoload.path)
313
322
 
314
323
  // load all services
@@ -324,7 +333,7 @@ class RuntimeGenerator extends BaseGenerator {
324
333
  const template = servicePltJson.module || getServiceTemplateFromSchemaUrl(servicePltJson.$schema)
325
334
  const Generator = await this._getGeneratorForTemplate(currentServicePath, template)
326
335
  const instance = new Generator({
327
- logger: this.logger
336
+ logger: this.logger,
328
337
  })
329
338
  this.addService(instance, s)
330
339
  output.services.push(await instance.loadFromDir(s, this.targetDirectory))
@@ -341,11 +350,11 @@ class RuntimeGenerator extends BaseGenerator {
341
350
  const currrentPackageJson = JSON.parse(await readFile(join(this.targetDirectory, 'package.json'), 'utf-8'))
342
351
  const currentRuntimeDependencies = currrentPackageJson.dependencies
343
352
  // check all services are present with the same template
344
- const allCurrentServicesNames = this.services.map((s) => s.name)
345
- const allNewServicesNames = newConfig.services.map((s) => s.name)
353
+ const allCurrentServicesNames = this.services.map(s => s.name)
354
+ const allNewServicesNames = newConfig.services.map(s => s.name)
346
355
  // load dotenv tool
347
356
  const envTool = new DotEnvTool({
348
- path: join(this.targetDirectory, '.env')
357
+ path: join(this.targetDirectory, '.env'),
349
358
  })
350
359
 
351
360
  await envTool.load()
@@ -356,24 +365,25 @@ class RuntimeGenerator extends BaseGenerator {
356
365
  // handle service delete
357
366
 
358
367
  // delete env variables
359
- const s = this.services.find((f) => f.name === removedService)
368
+ const s = this.services.find(f => f.name === removedService)
360
369
  const allKeys = envTool.getKeys()
361
- allKeys.forEach((k) => {
370
+ allKeys.forEach(k => {
362
371
  if (k.startsWith(`PLT_${s.service.config.envPrefix}`)) {
363
372
  envTool.deleteKey(k)
364
373
  }
365
374
  })
366
375
 
367
376
  // delete dependencies
368
- const servicePackageJson = JSON.parse(await readFile(join(this.targetDirectory, 'services', s.name, 'platformatic.json')))
377
+ const servicePackageJson = JSON.parse(
378
+ await readFile(join(this.targetDirectory, 'services', s.name, 'platformatic.json'), 'utf-8')
379
+ )
369
380
  if (servicePackageJson.plugins && servicePackageJson.plugins.packages) {
370
- servicePackageJson.plugins.packages
371
- .forEach((p) => {
372
- delete (currrentPackageJson.dependencies[p.name])
373
- })
381
+ servicePackageJson.plugins.packages.forEach(p => {
382
+ delete currrentPackageJson.dependencies[p.name]
383
+ })
374
384
  }
375
385
  // delete directory
376
- await rm(join(this.targetDirectory, 'services', s.name), { recursive: true })
386
+ await safeRemove(join(this.targetDirectory, 'services', s.name))
377
387
  }
378
388
  // throw new CannotRemoveServiceOnUpdateError(removedServices.join(', '))
379
389
  }
@@ -381,15 +391,18 @@ class RuntimeGenerator extends BaseGenerator {
381
391
  // handle new services
382
392
  for (const newService of newConfig.services) {
383
393
  // create generator for the service
384
- const ServiceGenerator = await this._getGeneratorForTemplate(join(this.targetDirectory, 'package.json'), newService.template)
394
+ const ServiceGenerator = await this._getGeneratorForTemplate(
395
+ join(this.targetDirectory, 'package.json'),
396
+ newService.template
397
+ )
385
398
  const serviceInstance = new ServiceGenerator({
386
- logger: this.logger
399
+ logger: this.logger,
387
400
  })
388
401
  const baseConfig = {
389
402
  isRuntimeContext: true,
390
403
  targetDirectory: join(this.targetDirectory, 'services', newService.name),
391
404
  serviceName: newService.name,
392
- plugin: true
405
+ plugin: true,
393
406
  }
394
407
  if (allCurrentServicesNames.includes(newService.name)) {
395
408
  // update existing services env values
@@ -398,15 +411,15 @@ class RuntimeGenerator extends BaseGenerator {
398
411
 
399
412
  // handle service's plugin differences
400
413
  const oldServiceMetadata = await serviceInstance.loadFromDir(newService.name, this.targetDirectory)
401
- const oldServicePackages = oldServiceMetadata.plugins.map((meta) => meta.name)
402
- const newServicePackages = newService.plugins.map((meta) => meta.name)
414
+ const oldServicePackages = oldServiceMetadata.plugins.map(meta => meta.name)
415
+ const newServicePackages = newService.plugins.map(meta => meta.name)
403
416
  const pluginsToRemove = getArrayDifference(oldServicePackages, newServicePackages)
404
- pluginsToRemove.forEach((p) => delete currentRuntimeDependencies[p])
417
+ pluginsToRemove.forEach(p => delete currentRuntimeDependencies[p])
405
418
  } else {
406
419
  // add service to the generator
407
420
  this.services.push({
408
421
  name: newService.name,
409
- service: serviceInstance
422
+ service: serviceInstance,
410
423
  })
411
424
  }
412
425
  serviceInstance.setConfig(baseConfig)
@@ -431,7 +444,7 @@ class RuntimeGenerator extends BaseGenerator {
431
444
  await serviceInstance.writeFiles()
432
445
  // cleanup runtime env removing keys not present anymore in service plugins
433
446
  const allKeys = envTool.getKeys()
434
- allKeys.forEach((k) => {
447
+ allKeys.forEach(k => {
435
448
  if (k.startsWith(`${serviceEnvPrefix}_FST_PLUGIN`) && !runtimeAddedEnvKeys.includes(k)) {
436
449
  envTool.deleteKey(k)
437
450
  }
@@ -445,26 +458,28 @@ class RuntimeGenerator extends BaseGenerator {
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
 
456
469
  // set new entrypoint if specified
457
470
  const newEntrypoint = newConfig.entrypoint
458
471
  if (newEntrypoint) {
459
472
  // load platformatic.json runtime config
460
- const runtimePkgConfigFileData = JSON.parse(await readFile(join(this.targetDirectory, 'platformatic.json'), 'utf-8'))
473
+ const runtimePkgConfigFileData = JSON.parse(
474
+ await readFile(join(this.targetDirectory, 'platformatic.json'), 'utf-8')
475
+ )
461
476
 
462
477
  this.setEntryPoint(newEntrypoint)
463
478
  runtimePkgConfigFileData.entrypoint = newEntrypoint
464
479
  this.addFile({
465
480
  path: '',
466
481
  file: 'platformatic.json',
467
- contents: JSON.stringify(runtimePkgConfigFileData, null, 2)
482
+ contents: JSON.stringify(runtimePkgConfigFileData, null, 2),
468
483
  })
469
484
  }
470
485
  await this.writeFiles()
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 }
@@ -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 { mkdir, rm } = require('node:fs/promises')
5
+ const { createDirectory, safeRemove } = require('@platformatic/utils')
6
+
7
7
  const fastify = require('fastify')
8
8
  const ws = require('ws')
9
- const { getRuntimeLogsDir } = require('./api-client.js')
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
- 'The feature is not subject to semantic versioning rules. ' +
18
- 'Non-backward compatible changes or removal may occur in any future release. ' +
19
- 'Use of the feature is not recommended in production environments.'
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 (request) => {
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 (request) => {
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 (request) => {
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 (request) => {
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 (request) => {
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 (request) => {
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.stopService(id)
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 (socket) => {
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 = (metrics) => {
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 (req) => {
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 (req) => {
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 rm(runtimePIDDir, { recursive: true, force: true }).catch()
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 rm(runtimeLogsDir, { recursive: true, force: true }).catch()
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 rm(runtimePIDDir, { recursive: true, force: true }).catch()
209
+ await safeRemove(runtimePIDDir)
225
210
  }
226
211
  })
227
212
 
228
213
  await managementApi.listen({ path: socketPath })
229
214
  return managementApi
230
- /* c8 ignore next 4 */
215
+ /* c8 ignore next 4 */
231
216
  } catch (err) {
232
217
  console.error(err)
233
218
  process.exit(1)