@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.
Files changed (170) hide show
  1. package/config.d.ts +285 -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/invalid-autoload-with-services.json +1 -1
  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 +2 -2
  12. package/fixtures/configs/monorepo-composer.json +2 -2
  13. package/fixtures/configs/monorepo-create-cycle.json +2 -2
  14. package/fixtures/configs/monorepo-missing-dependencies.json +2 -2
  15. package/fixtures/configs/monorepo-no-cycles.json +2 -2
  16. package/fixtures/configs/monorepo-openapi.json +2 -2
  17. package/fixtures/configs/{monorepo-hotreload-env.json → monorepo-watch-env.json} +2 -2
  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-with-management-api-without-metrics.json +21 -0
  22. package/fixtures/configs/monorepo-with-management-api.json +2 -2
  23. package/fixtures/configs/{monorepo-hotreload.json → monorepo-with-metrics.json} +5 -4
  24. package/fixtures/configs/monorepo.json +2 -2
  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 -2
  29. package/fixtures/configs/service-with-stdio.json +12 -0
  30. package/fixtures/configs/{hotreload.json → watch.json} +2 -2
  31. package/fixtures/dbApp/platformatic.db.json +1 -1
  32. package/fixtures/dbAppNoName/platformatic.db.json +1 -1
  33. package/fixtures/dbAppNoPackageJson/platformatic.db.json +1 -1
  34. package/fixtures/dbAppWithMigrationError/platformatic.db.json +1 -1
  35. package/fixtures/do-not-reload-dependencies/platformatic.service.json +1 -1
  36. package/fixtures/do-not-restart-on-crash/platformatic.runtime.json +3 -2
  37. package/fixtures/do-not-restart-on-crash/services/a/platformatic.service.json +1 -1
  38. package/fixtures/express/platformatic.runtime.json +1 -1
  39. package/fixtures/express/services/a/platformatic.service.json +1 -1
  40. package/fixtures/express/services/b/platformatic.service.json +1 -1
  41. package/fixtures/external-client/platformatic.service.json +1 -1
  42. package/fixtures/interceptors/idp.js +2 -2
  43. package/fixtures/interceptors/platformatic.runtime.json +1 -1
  44. package/fixtures/interceptors/services/a/platformatic.service.json +1 -1
  45. package/fixtures/interceptors-2/platformatic.runtime.json +1 -1
  46. package/fixtures/interceptors-2/services/a/platformatic.service.json +1 -1
  47. package/fixtures/leven/platformatic.runtime.json +2 -2
  48. package/fixtures/leven/services/deeply-spittle/platformatic.service.json +1 -1
  49. package/fixtures/leven/services/rainy-empire/platformatic.composer.json +1 -1
  50. package/fixtures/management-api/platformatic.json +3 -3
  51. package/fixtures/management-api/services/service-1/platformatic.json +1 -1
  52. package/fixtures/management-api/services/service-1/plugin.js +4 -3
  53. package/fixtures/management-api/services/service-2/platformatic.json +1 -1
  54. package/fixtures/management-api/services/service-db/platformatic.db.json +1 -1
  55. package/fixtures/management-api-custom-labels/platformatic.json +2 -2
  56. package/fixtures/management-api-custom-labels/services/service-1/platformatic.json +1 -1
  57. package/fixtures/management-api-custom-labels/services/service-1/plugin.js +4 -3
  58. package/fixtures/management-api-custom-labels/services/service-2/platformatic.json +1 -1
  59. package/fixtures/management-api-custom-labels/services/service-db/platformatic.db.json +1 -1
  60. package/fixtures/management-api-without-metrics/platformatic.json +3 -2
  61. package/fixtures/management-api-without-metrics/services/service-1/platformatic.json +1 -1
  62. package/fixtures/monorepo/composerApp/platformatic.composer.json +1 -1
  63. package/fixtures/monorepo/dbApp/platformatic.db.json +1 -1
  64. package/fixtures/monorepo/serviceApp/platformatic.service.json +3 -2
  65. package/fixtures/monorepo/serviceApp/with-logger/with-logger.cjs +2 -2
  66. package/fixtures/monorepo/serviceApp/with-logger/with-logger.d.ts +7 -7
  67. package/fixtures/monorepo/serviceAppWithLogger/platformatic.service.json +1 -1
  68. package/fixtures/monorepo/serviceAppWithLogger/plugin.js +12 -0
  69. package/fixtures/monorepo/serviceAppWithMultiplePlugins/platformatic.service.json +3 -2
  70. package/fixtures/monorepo-missing-dependencies/composer/platformatic.json +1 -1
  71. package/fixtures/monorepo-openapi/serviceAppWithoutOpenapi/platformatic.service.json +1 -1
  72. package/fixtures/monorepo-watch/service1/platformatic.service.json +1 -1
  73. package/fixtures/monorepo-with-dependencies/main/platformatic.json +1 -1
  74. package/fixtures/monorepo-with-dependencies/service-1/platformatic.json +1 -1
  75. package/fixtures/monorepo-with-dependencies/service-2/platformatic.json +1 -1
  76. package/fixtures/no-env.service.json +1 -1
  77. package/fixtures/preload/platformatic.runtime.json +1 -1
  78. package/fixtures/preload/services/a/platformatic.service.json +1 -1
  79. package/fixtures/prom-server/platformatic.json +2 -2
  80. package/fixtures/prom-server/services/service-1/platformatic.json +1 -1
  81. package/fixtures/prom-server/services/service-2/platformatic.json +1 -1
  82. package/fixtures/restart-on-crash/platformatic.runtime.json +1 -1
  83. package/fixtures/restart-on-crash/services/a/platformatic.service.json +1 -1
  84. package/fixtures/sample-runtime/package.json +1 -1
  85. package/fixtures/sample-runtime/platformatic.json +2 -2
  86. package/fixtures/sample-runtime/services/rival/package.json +1 -1
  87. package/fixtures/sample-runtime/services/rival/platformatic.json +1 -1
  88. package/fixtures/sample-runtime-with-2-services/package.json +1 -1
  89. package/fixtures/sample-runtime-with-2-services/platformatic.json +2 -2
  90. package/fixtures/sample-runtime-with-2-services/services/foobar/package.json +1 -1
  91. package/fixtures/sample-runtime-with-2-services/services/foobar/platformatic.json +1 -1
  92. package/fixtures/sample-runtime-with-2-services/services/rival/package.json +1 -1
  93. package/fixtures/sample-runtime-with-2-services/services/rival/platformatic.json +1 -1
  94. package/fixtures/server/logger-transport/platformatic.runtime.json +2 -2
  95. package/fixtures/server/logger-transport/services/echo/platformatic.service.json +1 -1
  96. package/fixtures/server/overrides-service/platformatic.runtime.json +2 -2
  97. package/fixtures/server/overrides-service/services/echo/platformatic.service.json +1 -1
  98. package/fixtures/server/runtime-server/platformatic.runtime.json +2 -2
  99. package/fixtures/server/runtime-server/services/echo/platformatic.service.json +1 -1
  100. package/fixtures/serviceAppThrowsOnStart/platformatic.service.json +1 -1
  101. package/fixtures/stackables/node_modules/foo/foo.js +2 -1
  102. package/fixtures/start-command-in-runtime.js +1 -1
  103. package/fixtures/stdio/platformatic.service.json +6 -0
  104. package/fixtures/stdio/plugin.js +24 -0
  105. package/fixtures/telemetry/platformatic.runtime.json +2 -2
  106. package/fixtures/telemetry/services/echo/platformatic.service.json +1 -1
  107. package/fixtures/typescript/platformatic.runtime.json +2 -2
  108. package/fixtures/typescript/services/composer/platformatic.composer.json +1 -1
  109. package/fixtures/typescript/services/movies/global.d.ts +2 -3
  110. package/fixtures/typescript/services/movies/platformatic.db.json +1 -1
  111. package/fixtures/typescript/services/movies/types/Movie.d.ts +3 -3
  112. package/fixtures/typescript/services/movies/types/index.d.ts +6 -6
  113. package/fixtures/typescript/services/titles/client/client.d.ts +35 -35
  114. package/fixtures/typescript/services/titles/platformatic.service.json +1 -1
  115. package/fixtures/typescript-custom-flags/platformatic.runtime.json +2 -2
  116. package/fixtures/typescript-custom-flags/services/composer/platformatic.composer.json +1 -1
  117. package/fixtures/typescript-custom-flags/services/movies/global.d.ts +2 -3
  118. package/fixtures/typescript-custom-flags/services/movies/platformatic.db.json +1 -1
  119. package/fixtures/typescript-custom-flags/services/movies/types/Movie.d.ts +3 -3
  120. package/fixtures/typescript-custom-flags/services/movies/types/index.d.ts +6 -6
  121. package/fixtures/typescript-custom-flags/services/titles/client/client.d.ts +35 -35
  122. package/fixtures/typescript-custom-flags/services/titles/platformatic.service.json +1 -1
  123. package/fixtures/typescript-no-env/platformatic.runtime.json +2 -2
  124. package/fixtures/typescript-no-env/services/composer/platformatic.composer.json +1 -1
  125. package/fixtures/typescript-no-env/services/movies/global.d.ts +2 -3
  126. package/fixtures/typescript-no-env/services/movies/platformatic.db.json +1 -1
  127. package/fixtures/typescript-no-env/services/movies/types/Movie.d.ts +3 -3
  128. package/fixtures/typescript-no-env/services/movies/types/index.d.ts +6 -6
  129. package/fixtures/typescript-no-env/services/titles/client/client.d.ts +35 -35
  130. package/fixtures/typescript-no-env/services/titles/platformatic.service.json +1 -1
  131. package/index.d.ts +7 -8
  132. package/index.js +14 -10
  133. package/index.test-d.ts +10 -12
  134. package/lib/build-server.js +5 -11
  135. package/lib/compile.js +11 -10
  136. package/lib/config.js +21 -14
  137. package/lib/dependencies.js +2 -1
  138. package/lib/errors.js +3 -2
  139. package/lib/generator/errors.js +1 -1
  140. package/lib/generator/runtime-generator.d.ts +15 -15
  141. package/lib/generator/runtime-generator.js +92 -63
  142. package/lib/logger.js +55 -0
  143. package/lib/management-api.js +29 -44
  144. package/lib/prom-server.js +5 -9
  145. package/lib/runtime.js +885 -0
  146. package/lib/schema.js +79 -76
  147. package/lib/start.js +35 -113
  148. package/lib/streams/message-port-writable.js +44 -0
  149. package/lib/streams/pino-writable.js +30 -0
  150. package/lib/upgrade.js +4 -3
  151. package/lib/utils.js +49 -1
  152. package/lib/versions/v1.36.0.js +1 -1
  153. package/lib/versions/v1.5.0.js +1 -1
  154. package/lib/versions/v2.0.0.js +17 -0
  155. package/lib/worker/app.js +224 -0
  156. package/lib/worker/default-stackable.js +27 -0
  157. package/lib/worker/itc.js +128 -0
  158. package/lib/worker/main.js +120 -0
  159. package/lib/worker/symbols.js +7 -0
  160. package/package.json +23 -25
  161. package/runtime.mjs +4 -4
  162. package/schema.json +824 -0
  163. package/lib/api-client.js +0 -500
  164. package/lib/api.js +0 -420
  165. package/lib/app.js +0 -397
  166. package/lib/load-config.js +0 -12
  167. package/lib/loader.mjs +0 -103
  168. package/lib/message-port-writable.js +0 -50
  169. package/lib/worker.js +0 -182
  170. /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,21 +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
- hotReload: true,
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: [{ name: 'yes', value: true }, { name: 'no', value: false }]
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((service) => {
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(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
+ )
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((s) => s.name)
344
- 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)
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((f) => f.name === removedService)
368
+ const s = this.services.find(f => f.name === removedService)
359
369
  const allKeys = envTool.getKeys()
360
- allKeys.forEach((k) => {
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(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'))
379
+ )
368
380
  if (servicePackageJson.plugins && servicePackageJson.plugins.packages) {
369
- servicePackageJson.plugins.packages
370
- .forEach((p) => {
371
- delete (currrentPackageJson.dependencies[p.name])
372
- })
381
+ servicePackageJson.plugins.packages.forEach(p => {
382
+ delete currrentPackageJson.dependencies[p.name]
383
+ })
373
384
  }
374
385
  // delete directory
375
- await rm(join(this.targetDirectory, 'services', s.name), { recursive: true })
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(join(this.targetDirectory, 'package.json'), newService.template)
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((meta) => meta.name)
401
- 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)
402
416
  const pluginsToRemove = getArrayDifference(oldServicePackages, newServicePackages)
403
- pluginsToRemove.forEach((p) => delete currentRuntimeDependencies[p])
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((k) => {
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 }
@@ -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)