@platformatic/runtime 2.0.0-alpha.15 → 2.0.0-alpha.17

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 CHANGED
@@ -5,11 +5,12 @@
5
5
  * and run json-schema-to-typescript to regenerate this file.
6
6
  */
7
7
 
8
- export type HttpsSchemasPlatformaticDevPlatformaticRuntime200Alpha15Json = {
8
+ export type HttpsSchemasPlatformaticDevPlatformaticRuntime200Alpha17Json = {
9
9
  [k: string]: unknown;
10
10
  } & {
11
11
  $schema?: string;
12
12
  preload?: string;
13
+ entrypoint?: string;
13
14
  autoload?: {
14
15
  path: string;
15
16
  exclude?: string[];
@@ -21,87 +22,54 @@ export type HttpsSchemasPlatformaticDevPlatformaticRuntime200Alpha15Json = {
21
22
  };
22
23
  };
23
24
  };
24
- telemetry?: OpenTelemetry;
25
- server?: {
26
- hostname?: string;
27
- port?: number | string;
28
- pluginTimeout?: number;
29
- healthCheck?:
30
- | boolean
25
+ services?: {
26
+ [k: string]: unknown;
27
+ }[];
28
+ web?: {
29
+ [k: string]: unknown;
30
+ }[];
31
+ logger?: {
32
+ level: (
33
+ | ("fatal" | "error" | "warn" | "info" | "debug" | "trace" | "silent")
31
34
  | {
32
- enabled?: boolean;
33
- interval?: number;
34
35
  [k: string]: unknown;
35
- };
36
- ignoreTrailingSlash?: boolean;
37
- ignoreDuplicateSlashes?: boolean;
38
- connectionTimeout?: number;
39
- keepAliveTimeout?: number;
40
- maxRequestsPerSocket?: number;
41
- forceCloseConnections?: boolean | string;
42
- requestTimeout?: number;
43
- bodyLimit?: number;
44
- maxParamLength?: number;
45
- disableRequestLogging?: boolean;
46
- exposeHeadRoutes?: boolean;
47
- logger?:
48
- | boolean
36
+ }
37
+ ) &
38
+ string;
39
+ transport?:
49
40
  | {
50
- level?: string;
51
- transport?:
52
- | {
53
- target?: string;
54
- options?: {
55
- [k: string]: unknown;
56
- };
57
- }
58
- | {
59
- targets?: {
60
- target?: string;
61
- options?: {
62
- [k: string]: unknown;
63
- };
64
- level?: string;
65
- additionalProperties?: never;
66
- [k: string]: unknown;
67
- }[];
68
- options?: {
69
- [k: string]: unknown;
70
- };
71
- };
72
- pipeline?: {
41
+ target?: string;
42
+ options?: {
43
+ [k: string]: unknown;
44
+ };
45
+ }
46
+ | {
47
+ targets?: {
73
48
  target?: string;
74
49
  options?: {
75
50
  [k: string]: unknown;
76
51
  };
52
+ level?: string;
53
+ additionalProperties?: never;
54
+ [k: string]: unknown;
55
+ }[];
56
+ options?: {
57
+ [k: string]: unknown;
77
58
  };
78
- [k: string]: unknown;
79
59
  };
80
- loggerInstance?: {
81
- [k: string]: unknown;
82
- };
83
- serializerOpts?: {
84
- schema?: {
85
- [k: string]: unknown;
86
- };
87
- ajv?: {
60
+ pipeline?: {
61
+ target?: string;
62
+ options?: {
88
63
  [k: string]: unknown;
89
64
  };
90
- rounding?: "floor" | "ceil" | "round" | "trunc";
91
- debugMode?: boolean;
92
- mode?: "debug" | "standalone";
93
- largeArraySize?: number | string;
94
- largeArrayMechanism?: "default" | "json-stringify";
95
- [k: string]: unknown;
96
65
  };
97
- caseSensitive?: boolean;
98
- requestIdHeader?: string | false;
99
- requestIdLogLabel?: string;
100
- jsonShorthand?: boolean;
101
- trustProxy?: boolean | string | string[] | number;
66
+ [k: string]: unknown;
67
+ };
68
+ server?: {
69
+ hostname?: string;
70
+ port?: number | string;
102
71
  http2?: boolean;
103
72
  https?: {
104
- allowHTTP1?: boolean;
105
73
  key:
106
74
  | string
107
75
  | {
@@ -124,48 +92,9 @@ export type HttpsSchemasPlatformaticDevPlatformaticRuntime200Alpha15Json = {
124
92
  path?: string;
125
93
  }
126
94
  )[];
127
- requestCert?: boolean;
128
- rejectUnauthorized?: boolean;
129
95
  };
130
- cors?: {
131
- origin?:
132
- | boolean
133
- | string
134
- | (
135
- | string
136
- | {
137
- regexp: string;
138
- [k: string]: unknown;
139
- }
140
- )[]
141
- | {
142
- regexp: string;
143
- [k: string]: unknown;
144
- };
145
- methods?: string[];
146
- /**
147
- * Comma separated string of allowed headers.
148
- */
149
- allowedHeaders?: string;
150
- exposedHeaders?: string[] | string;
151
- credentials?: boolean;
152
- maxAge?: number;
153
- preflightContinue?: boolean;
154
- optionsSuccessStatus?: number;
155
- preflight?: boolean;
156
- strictPreflight?: boolean;
157
- hideOptionsRoute?: boolean;
158
- };
159
- };
160
- entrypoint?: string;
161
- watch?: boolean | string;
162
- inspectorOptions?: {
163
- host?: string;
164
- port?: number;
165
- breakFirstLine?: boolean;
166
- watchDisabled?: boolean;
167
- [k: string]: unknown;
168
96
  };
97
+ restartOnError?: boolean | number;
169
98
  undici?: {
170
99
  agentOptions?: {
171
100
  [k: string]: unknown;
@@ -180,12 +109,13 @@ export type HttpsSchemasPlatformaticDevPlatformaticRuntime200Alpha15Json = {
180
109
  };
181
110
  [k: string]: unknown;
182
111
  };
112
+ watch?: boolean | string;
183
113
  managementApi?:
184
114
  | boolean
185
115
  | string
186
116
  | {
187
117
  logs?: {
188
- [k: string]: unknown;
118
+ maxSize?: number;
189
119
  };
190
120
  };
191
121
  metrics?:
@@ -202,12 +132,23 @@ export type HttpsSchemasPlatformaticDevPlatformaticRuntime200Alpha15Json = {
202
132
  [k: string]: string;
203
133
  };
204
134
  };
205
- restartOnError?: boolean | number;
206
- services?: {
135
+ telemetry?: OpenTelemetry;
136
+ inspectorOptions?: {
137
+ host?: string;
138
+ port?: number;
139
+ breakFirstLine?: boolean;
140
+ watchDisabled?: boolean;
207
141
  [k: string]: unknown;
208
- }[];
142
+ };
209
143
  };
210
144
 
145
+ export interface UndiciInterceptor {
146
+ module: string;
147
+ options: {
148
+ [k: string]: unknown;
149
+ };
150
+ [k: string]: unknown;
151
+ }
211
152
  export interface OpenTelemetry {
212
153
  /**
213
154
  * The name of the service. Defaults to the folder name if not specified.
@@ -275,10 +216,3 @@ export interface OpenTelemetry {
275
216
  [k: string]: unknown;
276
217
  };
277
218
  }
278
- export interface UndiciInterceptor {
279
- module: string;
280
- options: {
281
- [k: string]: unknown;
282
- };
283
- [k: string]: unknown;
284
- }
@@ -3,10 +3,7 @@
3
3
  "entrypoint": "db-app",
4
4
  "autoload": {
5
5
  "path": "../monorepo",
6
- "exclude": [
7
- "docs",
8
- "composerApp"
9
- ],
6
+ "exclude": ["docs", "composerApp"],
10
7
  "mappings": {
11
8
  "serviceAppWithLogger": {
12
9
  "id": "with-logger",
@@ -28,5 +25,12 @@
28
25
  "path": "../monorepo/serviceAppWithLogger",
29
26
  "config": "platformatic.service.json"
30
27
  }
28
+ ],
29
+ "web": [
30
+ {
31
+ "id": "with-logger",
32
+ "path": "../monorepo/serviceAppWithLogger",
33
+ "config": "platformatic.service.json"
34
+ }
31
35
  ]
32
36
  }
@@ -20,10 +20,8 @@
20
20
  }
21
21
  }
22
22
  },
23
- "server": {
24
- "logger": {
25
- "level": "trace"
26
- }
23
+ "logger": {
24
+ "level": "trace"
27
25
  },
28
26
  "restartOnError": 1000
29
27
  }
@@ -2,13 +2,15 @@
2
2
  "$schema": "https://schemas.platformatic.dev/@platformatic/service/1.52.0.json",
3
3
  "server": {
4
4
  "logger": {
5
- "level": "warn"
5
+ "level": "info"
6
6
  }
7
7
  },
8
8
  "plugins": {
9
- "paths": [{
10
- "path": "plugin.js",
11
- "encapsulate": false
12
- }]
9
+ "paths": [
10
+ {
11
+ "path": "plugin.js",
12
+ "encapsulate": false
13
+ }
14
+ ]
13
15
  }
14
16
  }
@@ -4,9 +4,12 @@
4
4
  "openapi": true
5
5
  },
6
6
  "plugins": {
7
- "paths": [
8
- "plugin.js"
9
- ]
7
+ "paths": ["plugin.js"]
10
8
  },
11
- "watch": true
9
+ "watch": true,
10
+ "server": {
11
+ "logger": {
12
+ "level": "trace"
13
+ }
14
+ }
12
15
  }
@@ -2,13 +2,15 @@
2
2
  "$schema": "https://schemas.platformatic.dev/@platformatic/service/1.52.0.json",
3
3
  "server": {
4
4
  "logger": {
5
- "level": "warn"
5
+ "level": "info"
6
6
  }
7
7
  },
8
8
  "plugins": {
9
- "paths": [{
10
- "path": "plugin.js",
11
- "encapsulate": false
12
- }]
9
+ "paths": [
10
+ {
11
+ "path": "plugin.js",
12
+ "encapsulate": false
13
+ }
14
+ ]
13
15
  }
14
16
  }
package/index.js CHANGED
@@ -10,6 +10,8 @@ const { buildRuntime, start, startCommand } = require('./lib/start')
10
10
  const symbols = require('./lib/worker/symbols')
11
11
  const { loadConfig, getRuntimeLogsDir } = require('./lib/utils')
12
12
 
13
+ const platformaticVersion = require('./package.json').version
14
+
13
15
  module.exports.buildServer = buildServer
14
16
  module.exports.buildRuntime = buildRuntime
15
17
  module.exports.compile = compile
@@ -24,3 +26,4 @@ module.exports.startCommand = startCommand
24
26
  module.exports.symbols = symbols
25
27
  module.exports.Runtime = Runtime
26
28
  module.exports.wrapConfigInRuntimeConfig = wrapConfigInRuntimeConfig
29
+ module.exports.version = platformaticVersion
package/lib/config.js CHANGED
@@ -9,17 +9,21 @@ const errors = require('./errors')
9
9
  const { schema } = require('./schema')
10
10
  const upgrade = require('./upgrade')
11
11
 
12
- const kServicesAutoloaded = Symbol('plt.servicesAutoloaded')
13
-
14
12
  async function _transformConfig (configManager) {
15
13
  const config = configManager.current
16
- const services = config.services ?? []
17
14
 
18
- if (config.autoload) {
19
- if (config.services && !config.services[kServicesAutoloaded]) {
20
- throw new errors.InvalidAutoloadWithServicesError()
15
+ let services
16
+ if (config.web?.length) {
17
+ if (config.services?.length) {
18
+ throw new errors.InvalidServicesWithWebError()
21
19
  }
22
20
 
21
+ services = config.web
22
+ } else {
23
+ services = config.services ?? []
24
+ }
25
+
26
+ if (config.autoload) {
23
27
  const { exclude = [], mappings = {} } = config.autoload
24
28
  let { path } = config.autoload
25
29
 
@@ -41,13 +45,13 @@ async function _transformConfig (configManager) {
41
45
  const mapping = mappings[entry.name] ?? {}
42
46
  const id = mapping.id ?? entry.name
43
47
  const entryPath = join(path, entry.name)
44
- const configFilename = mapping.config ?? await ConfigManager.findConfigFile(entryPath)
45
48
 
46
- if (typeof configFilename !== 'string') {
47
- throw new errors.NoConfigFileFoundError(id)
48
- }
49
+ let config
50
+ const configFilename = mapping.config ?? (await ConfigManager.findConfigFile(entryPath))
49
51
 
50
- const config = join(entryPath, configFilename)
52
+ if (typeof configFilename === 'string') {
53
+ config = join(entryPath, configFilename)
54
+ }
51
55
 
52
56
  const service = { id, config, path: entryPath, useHttp: !!mapping.useHttp }
53
57
  const existingServiceId = services.findIndex(service => service.id === id)
@@ -89,7 +93,7 @@ async function _transformConfig (configManager) {
89
93
  }
90
94
 
91
95
  configManager.current.services = services
92
- configManager.current.services[kServicesAutoloaded] = true
96
+ configManager.current.web = undefined
93
97
 
94
98
  if (configManager.current.restartOnError === true) {
95
99
  configManager.current.restartOnError = 5000
@@ -111,12 +115,12 @@ platformaticRuntime.configManagerConfig = {
111
115
  useDefaults: true,
112
116
  coerceTypes: true,
113
117
  allErrors: true,
114
- strict: false,
118
+ strict: false
115
119
  },
116
120
  async transformConfig () {
117
121
  await _transformConfig(this)
118
122
  },
119
- upgrade,
123
+ upgrade
120
124
  }
121
125
 
122
126
  async function wrapConfigInRuntimeConfig ({ configManager, args }) {
@@ -140,9 +144,9 @@ async function wrapConfigInRuntimeConfig ({ configManager, args }) {
140
144
  {
141
145
  id: serviceId,
142
146
  path: configManager.dirname,
143
- config: configManager.fullPath,
144
- },
145
- ],
147
+ config: configManager.fullPath
148
+ }
149
+ ]
146
150
  }
147
151
  const cm = new ConfigManager({
148
152
  source: wrapperConfig,
@@ -151,9 +155,11 @@ async function wrapConfigInRuntimeConfig ({ configManager, args }) {
151
155
  useDefaults: true,
152
156
  coerceTypes: true,
153
157
  allErrors: true,
154
- strict: false,
158
+ strict: false
155
159
  },
156
- transformConfig () { return _transformConfig(this) },
160
+ transformConfig () {
161
+ return _transformConfig(this)
162
+ }
157
163
  })
158
164
 
159
165
  await cm.parseAndValidate()
@@ -205,7 +211,7 @@ function parseInspectorOptions (configManager) {
205
211
  host,
206
212
  port,
207
213
  breakFirstLine: hasInspectBrk,
208
- watchDisabled: !!current.watch,
214
+ watchDisabled: !!current.watch
209
215
  }
210
216
 
211
217
  current.watch = false
@@ -215,5 +221,5 @@ function parseInspectorOptions (configManager) {
215
221
  module.exports = {
216
222
  parseInspectorOptions,
217
223
  platformaticRuntime,
218
- wrapConfigInRuntimeConfig,
224
+ wrapConfigInRuntimeConfig
219
225
  }
package/lib/errors.js CHANGED
@@ -20,7 +20,7 @@ module.exports = {
20
20
  ConfigPathMustBeStringError: createError(`${ERROR_PREFIX}_CONFIG_PATH_MUST_BE_STRING`, 'Config path must be a string'),
21
21
  NoConfigFileFoundError: createError(`${ERROR_PREFIX}_NO_CONFIG_FILE_FOUND`, "No config file found for service '%s'"),
22
22
  InvalidEntrypointError: createError(`${ERROR_PREFIX}_INVALID_ENTRYPOINT`, "Invalid entrypoint: '%s' does not exist"),
23
- InvalidAutoloadWithServicesError: createError(`${ERROR_PREFIX}_INVALID_AUTOLOAD_WITH_SERVICES`, 'Autoload cannot be used when services is defined'),
23
+ InvalidServicesWithWebError: createError(`${ERROR_PREFIX}_INVALID_SERVICES_WITH_WEB`, 'The "services" property cannot be used when the "web" property is also defined'),
24
24
  MissingDependencyError: createError(`${ERROR_PREFIX}_MISSING_DEPENDENCY`, 'Missing dependency: "%s"'),
25
25
  InspectAndInspectBrkError: createError(`${ERROR_PREFIX}_INSPECT_AND_INSPECT_BRK`, '--inspect and --inspect-brk cannot be used together'),
26
26
  InspectorPortError: createError(`${ERROR_PREFIX}_INSPECTOR_PORT`, 'Inspector port must be 0 or in range 1024 to 65535'),
@@ -165,12 +165,12 @@ class RuntimeGenerator extends BaseGenerator {
165
165
  path: 'services',
166
166
  exclude: ['docs'],
167
167
  },
168
+ logger: {
169
+ level: '{PLT_SERVER_LOGGER_LEVEL}',
170
+ },
168
171
  server: {
169
172
  hostname: '{PLT_SERVER_HOSTNAME}',
170
- port: '{PORT}',
171
- logger: {
172
- level: '{PLT_SERVER_LOGGER_LEVEL}',
173
- },
173
+ port: '{PORT}'
174
174
  },
175
175
  managementApi: '{PLT_MANAGEMENT_API}',
176
176
  }
package/lib/logger.js CHANGED
@@ -7,7 +7,7 @@ const pino = require('pino')
7
7
  const pretty = require('pino-pretty')
8
8
 
9
9
  function createLogger (config, runtimeLogsDir) {
10
- const loggerConfig = { ...config.server?.logger }
10
+ const loggerConfig = { ...config.logger }
11
11
  const cliStream = isatty(1) ? pretty() : pino.destination(1)
12
12
 
13
13
  if (!config.managementApi) {
@@ -31,7 +31,7 @@ async function managementApiPlugin (app, opts) {
31
31
  })
32
32
 
33
33
  app.get('/env', async () => {
34
- return process.env
34
+ return { ...process.env, ...runtime.getRuntimeEnv() }
35
35
  })
36
36
 
37
37
  app.post('/stop', async () => {
@@ -39,8 +39,8 @@ async function managementApiPlugin (app, opts) {
39
39
  await runtime.close(true)
40
40
  })
41
41
 
42
- app.post('/reload', async () => {
43
- app.log.debug('reload services')
42
+ app.post('/restart', async () => {
43
+ app.log.debug('restart services')
44
44
  await runtime.restart()
45
45
  })
46
46
 
@@ -60,6 +60,12 @@ async function managementApiPlugin (app, opts) {
60
60
  return runtime.getServiceConfig(id)
61
61
  })
62
62
 
63
+ app.get('/services/:id/env', async request => {
64
+ const { id } = request.params
65
+ app.log.debug('get service config', { id })
66
+ return runtime.getServiceEnv(id)
67
+ })
68
+
63
69
  app.get('/services/:id/openapi-schema', async request => {
64
70
  const { id } = request.params
65
71
  app.log.debug('get openapi-schema', { id })
@@ -98,11 +104,14 @@ async function managementApiPlugin (app, opts) {
98
104
  url: requestUrl || '/',
99
105
  headers: request.headers,
100
106
  query: request.query,
101
- body: request.body,
107
+ body: request.body
102
108
  }
103
109
 
104
110
  const res = await runtime.inject(id, injectParams)
105
111
 
112
+ delete res.headers['content-length']
113
+ delete res.headers['transfer-encoding']
114
+
106
115
  reply.code(res.statusCode).headers(res.headers).send(res.body)
107
116
  })
108
117
 
package/lib/runtime.js CHANGED
@@ -7,12 +7,8 @@ const inspector = require('node:inspector')
7
7
  const { join } = require('node:path')
8
8
  const { setTimeout: sleep } = require('node:timers/promises')
9
9
  const { Worker } = require('node:worker_threads')
10
-
11
10
  const { ITC } = require('@platformatic/itc')
12
- const {
13
- errors: { ensureLoggableError },
14
- executeWithTimeout
15
- } = require('@platformatic/utils')
11
+ const { ensureLoggableError, executeWithTimeout } = require('@platformatic/utils')
16
12
  const ts = require('tail-file-stream')
17
13
  const { createThreadInterceptor } = require('undici-thread-interceptor')
18
14
 
@@ -22,7 +18,7 @@ const { createLogger } = require('./logger')
22
18
  const { startManagementApi } = require('./management-api')
23
19
  const { startPrometheusServer } = require('./prom-server')
24
20
  const { getRuntimeTmpDir } = require('./utils')
25
- const { sendViaITC } = require('./worker/itc')
21
+ const { sendViaITC, waitEventFromITC } = require('./worker/itc')
26
22
  const { kId, kITC, kConfig } = require('./worker/symbols')
27
23
 
28
24
  const platformaticVersion = require('../package.json').version
@@ -176,7 +172,6 @@ class Runtime extends EventEmitter {
176
172
 
177
173
  this.emit('restarted')
178
174
 
179
- this.logger.info(`Platformatic is now listening at ${this.#url}`)
180
175
  return this.#url
181
176
  }
182
177
 
@@ -458,6 +453,10 @@ class Runtime extends EventEmitter {
458
453
  }
459
454
  }
460
455
 
456
+ getRuntimeEnv () {
457
+ return this.#configManager.env
458
+ }
459
+
461
460
  getRuntimeConfig () {
462
461
  return this.#configManager.current
463
462
  }
@@ -530,6 +529,12 @@ class Runtime extends EventEmitter {
530
529
  return sendViaITC(service, 'getServiceConfig')
531
530
  }
532
531
 
532
+ async getServiceEnv (id) {
533
+ const service = await this.#getServiceById(id, true)
534
+
535
+ return sendViaITC(service, 'getServiceEnv')
536
+ }
537
+
533
538
  async getServiceOpenapiSchema (id) {
534
539
  const service = await this.#getServiceById(id, true)
535
540
 
@@ -778,7 +783,9 @@ class Runtime extends EventEmitter {
778
783
 
779
784
  // Wait for the next tick so that crashed from the thread are logged first
780
785
  setImmediate(() => {
781
- this.logger.warn(`Service "${id}" unexpectedly exited with code ${code}.`)
786
+ if (!config.watch || code !== 0) {
787
+ this.logger.warn(`Service "${id}" unexpectedly exited with code ${code}.`)
788
+ }
782
789
 
783
790
  // Restart the service if it was started
784
791
  if (started && this.#status === 'started') {
@@ -839,7 +846,7 @@ class Runtime extends EventEmitter {
839
846
  this.#interceptor.route(id, service)
840
847
 
841
848
  // Store dependencies
842
- const [{ dependencies }] = await once(service[kITC], 'init')
849
+ const [{ dependencies }] = await waitEventFromITC(service, 'init')
843
850
 
844
851
  if (autoload) {
845
852
  serviceConfig.dependencies = dependencies