@platformatic/runtime 2.19.0-alpha.9 → 2.20.0-alpha.1

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,7 +5,7 @@
5
5
  * and run json-schema-to-typescript to regenerate this file.
6
6
  */
7
7
 
8
- export type HttpsSchemasPlatformaticDevPlatformaticRuntime2190Alpha9Json = {
8
+ export type HttpsSchemasPlatformaticDevPlatformaticRuntime2200Alpha1Json = {
9
9
  [k: string]: unknown;
10
10
  } & {
11
11
  $schema?: string;
@@ -176,6 +176,7 @@ export type HttpsSchemasPlatformaticDevPlatformaticRuntime2190Alpha9Json = {
176
176
  [k: string]: unknown;
177
177
  };
178
178
  serviceTimeout?: number | string;
179
+ resolvedServicesBasePath?: string;
179
180
  };
180
181
 
181
182
  export interface UndiciInterceptor {
package/lib/config.js CHANGED
@@ -87,8 +87,9 @@ async function _transformConfig (configManager, args) {
87
87
  for (let i = 0; i < services.length; ++i) {
88
88
  const service = services[i]
89
89
 
90
- // We need to have absolut paths here, ot the `loadConfig` will fail
91
- if (!isAbsolute(service.path)) {
90
+ // We need to have absolute paths here, ot the `loadConfig` will fail
91
+ // Make sure we don't resolve if env var was not replaced
92
+ if (service.path && !isAbsolute(service.path) && !service.path.match(/^\{.*\}$/)) {
92
93
  service.path = pathResolve(configManager.dirname, service.path)
93
94
  }
94
95
 
package/lib/errors.js CHANGED
@@ -7,6 +7,7 @@ const ERROR_PREFIX = 'PLT_RUNTIME'
7
7
  module.exports = {
8
8
  AddressInUseError: createError(`${ERROR_PREFIX}_EADDR_IN_USE`, 'The current port is in use by another application'),
9
9
  RuntimeExitedError: createError(`${ERROR_PREFIX}_RUNTIME_EXIT`, 'The runtime exited before the operation completed'),
10
+ RuntimeAbortedError: createError(`${ERROR_PREFIX}_RUNTIME_ABORT`, 'The runtime aborted the operation'),
10
11
  // The following two use the same code as we only need to differentiate the label
11
12
  ServiceExitedError: createError(`${ERROR_PREFIX}_SERVICE_EXIT`, 'The service "%s" exited prematurely with error code %d'),
12
13
  WorkerExitedError: createError(`${ERROR_PREFIX}_SERVICE_EXIT`, 'The worker %s of the service "%s" exited prematurely with error code %d'),
package/lib/runtime.js CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const { once, EventEmitter } = require('node:events')
4
- const { createReadStream, watch } = require('node:fs')
4
+ const { createReadStream, watch, existsSync } = require('node:fs')
5
5
  const { readdir, readFile, stat, access } = require('node:fs/promises')
6
6
  const { join } = require('node:path')
7
7
  const { setTimeout: sleep } = require('node:timers/promises')
@@ -124,6 +124,31 @@ class Runtime extends EventEmitter {
124
124
 
125
125
  // Create all services, each in is own worker thread
126
126
  for (const serviceConfig of config.services) {
127
+ // If there is no service path, check if the service was resolved
128
+ if (!serviceConfig.path) {
129
+ if (serviceConfig.url) {
130
+ // Try to backfill the path for external services
131
+ serviceConfig.path = join(this.#configManager.dirname, config.resolvedServicesBasePath, serviceConfig.id)
132
+
133
+ if (!existsSync(serviceConfig.path)) {
134
+ const executable = globalThis.platformatic?.executable ?? 'platformatic'
135
+ this.logger.error(
136
+ `The path for service "%s" does not exist. Please run "${executable} resolve" and try again.`,
137
+ serviceConfig.id
138
+ )
139
+
140
+ throw new errors.RuntimeAbortedError()
141
+ }
142
+ } else {
143
+ this.logger.error(
144
+ 'The service "%s" has no path defined. Please check your configuration and try again.',
145
+ serviceConfig.id
146
+ )
147
+
148
+ throw new errors.RuntimeAbortedError()
149
+ }
150
+ }
151
+
127
152
  await this.#setupService(serviceConfig)
128
153
  }
129
154
 
@@ -137,6 +162,21 @@ class Runtime extends EventEmitter {
137
162
 
138
163
  // Recompute the list of services after sorting
139
164
  this.#servicesIds = config.services.map(service => service.id)
165
+
166
+ // When autoloading is disabled, add a warning if a service is defined before its dependencies
167
+ if (!autoloadEnabled) {
168
+ for (let i = 0; i < config.services.length; i++) {
169
+ const current = config.services[i]
170
+
171
+ for (const dep of current.dependencies ?? []) {
172
+ if (config.services.findIndex(s => s.id === dep.id) > i) {
173
+ this.logger.warn(
174
+ `Service "${current.id}" depends on service "${dep.id}", but it is defined and it will be started before it. Please check your configuration file.`
175
+ )
176
+ }
177
+ }
178
+ }
179
+ }
140
180
  } catch (e) {
141
181
  await this.close()
142
182
  throw e
@@ -282,7 +322,7 @@ class Runtime extends EventEmitter {
282
322
  this.#updateStatus('closed')
283
323
  }
284
324
 
285
- async startService (id, silent) {
325
+ async startService (id, silent = false) {
286
326
  // Since when a service is stopped the worker is deleted, we consider a service start if its first service
287
327
  // is no longer in the init phase
288
328
  const firstWorker = this.#workers.get(`${id}:0`)
@@ -304,7 +344,7 @@ class Runtime extends EventEmitter {
304
344
  }
305
345
  }
306
346
 
307
- async stopService (id, silent) {
347
+ async stopService (id, silent = false) {
308
348
  const config = this.#configManager.current
309
349
  const serviceConfig = config.services.find(s => s.id === id)
310
350
 
@@ -795,7 +835,7 @@ class Runtime extends EventEmitter {
795
835
  }
796
836
 
797
837
  async #setupWorker (config, serviceConfig, workersCount, serviceId, index) {
798
- const { autoload, restartOnError } = config
838
+ const { restartOnError } = config
799
839
  const workerId = `${serviceId}:${index}`
800
840
 
801
841
  const { port1: loggerDestination, port2: loggingPort } = new MessageChannel()
@@ -969,12 +1009,10 @@ class Runtime extends EventEmitter {
969
1009
  // Store dependencies
970
1010
  const [{ dependencies }] = await waitEventFromITC(worker, 'init')
971
1011
 
972
- if (autoload) {
973
- serviceConfig.dependencies = dependencies
974
- for (const { envVar, url } of dependencies) {
975
- if (envVar) {
976
- serviceConfig.localServiceEnvVars.set(envVar, url)
977
- }
1012
+ serviceConfig.dependencies = dependencies
1013
+ for (const { envVar, url } of dependencies) {
1014
+ if (envVar) {
1015
+ serviceConfig.localServiceEnvVars.set(envVar, url)
978
1016
  }
979
1017
  }
980
1018
 
package/lib/schema.js CHANGED
@@ -27,6 +27,8 @@ const services = {
27
27
  },
28
28
  path: {
29
29
  type: 'string',
30
+ // This is required for the resolve command to allow empty paths after environment variable replacement
31
+ allowEmptyPaths: true,
30
32
  resolvePath: true
31
33
  },
32
34
  config: {
@@ -310,6 +312,10 @@ const platformaticRuntimeSchema = {
310
312
  { type: 'string' }
311
313
  ],
312
314
  default: 300000 // 5 minutes
315
+ },
316
+ resolvedServicesBasePath: {
317
+ type: 'string',
318
+ default: 'external'
313
319
  }
314
320
  },
315
321
  anyOf: [{ required: ['autoload'] }, { required: ['services'] }, { required: ['web'] }],
package/lib/start.js CHANGED
@@ -146,7 +146,7 @@ async function startCommand (args, throwAllErrors = false, returnRuntime = false
146
146
 
147
147
  return returnRuntime ? runtime : res
148
148
  } catch (err) {
149
- if (throwAllErrors) {
149
+ if (throwAllErrors && err.code !== 'PLT_RUNTIME_RUNTIME_ABORT') {
150
150
  throw err
151
151
  }
152
152
 
@@ -187,7 +187,9 @@ async function startCommand (args, throwAllErrors = false, returnRuntime = false
187
187
  process.exit(1)
188
188
  }
189
189
 
190
- console.error(err)
190
+ if (err.code !== 'PLT_RUNTIME_RUNTIME_ABORT') {
191
+ console.error(err)
192
+ }
191
193
 
192
194
  process.exit(1)
193
195
  }
@@ -1,5 +1,6 @@
1
1
  'use strict'
2
2
 
3
+ const { EventEmitter } = require('node:events')
3
4
  const { createRequire } = require('node:module')
4
5
  const { hostname } = require('node:os')
5
6
  const { join } = require('node:path')
@@ -37,7 +38,10 @@ globalThis[kId] = threadId
37
38
  let app
38
39
 
39
40
  const config = workerData.config
40
- globalThis.platformatic = Object.assign(globalThis.platformatic ?? {}, { logger: createLogger() })
41
+ globalThis.platformatic = Object.assign(globalThis.platformatic ?? {}, {
42
+ logger: createLogger(),
43
+ events: new EventEmitter()
44
+ })
41
45
 
42
46
  function handleUnhandled (type, err) {
43
47
  const label =
@@ -200,7 +204,7 @@ async function main () {
200
204
  globalThis[kITC] = itc
201
205
 
202
206
  // Get the dependencies
203
- const dependencies = config.autoload ? await app.getBootstrapDependencies() : []
207
+ const dependencies = await app.getBootstrapDependencies()
204
208
  itc.notify('init', { dependencies })
205
209
  }
206
210
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/runtime",
3
- "version": "2.19.0-alpha.9",
3
+ "version": "2.20.0-alpha.1",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -35,12 +35,12 @@
35
35
  "typescript": "^5.5.4",
36
36
  "undici-oidc-interceptor": "^0.5.0",
37
37
  "why-is-node-running": "^2.2.2",
38
- "@platformatic/composer": "2.19.0-alpha.9",
39
- "@platformatic/db": "2.19.0-alpha.9",
40
- "@platformatic/service": "2.19.0-alpha.9",
41
- "@platformatic/sql-mapper": "2.19.0-alpha.9",
42
- "@platformatic/sql-graphql": "2.19.0-alpha.9",
43
- "@platformatic/node": "2.19.0-alpha.9"
38
+ "@platformatic/composer": "2.20.0-alpha.1",
39
+ "@platformatic/db": "2.20.0-alpha.1",
40
+ "@platformatic/node": "2.20.0-alpha.1",
41
+ "@platformatic/service": "2.20.0-alpha.1",
42
+ "@platformatic/sql-graphql": "2.20.0-alpha.1",
43
+ "@platformatic/sql-mapper": "2.20.0-alpha.1"
44
44
  },
45
45
  "dependencies": {
46
46
  "@fastify/error": "^4.0.0",
@@ -72,13 +72,13 @@
72
72
  "undici": "^7.0.0",
73
73
  "undici-thread-interceptor": "^0.10.0",
74
74
  "ws": "^8.16.0",
75
- "@platformatic/basic": "2.19.0-alpha.9",
76
- "@platformatic/telemetry": "2.19.0-alpha.9",
77
- "@platformatic/generators": "2.19.0-alpha.9",
78
- "@platformatic/config": "2.19.0-alpha.9",
79
- "@platformatic/itc": "2.19.0-alpha.9",
80
- "@platformatic/ts-compiler": "2.19.0-alpha.9",
81
- "@platformatic/utils": "2.19.0-alpha.9"
75
+ "@platformatic/basic": "2.20.0-alpha.1",
76
+ "@platformatic/config": "2.20.0-alpha.1",
77
+ "@platformatic/generators": "2.20.0-alpha.1",
78
+ "@platformatic/itc": "2.20.0-alpha.1",
79
+ "@platformatic/telemetry": "2.20.0-alpha.1",
80
+ "@platformatic/ts-compiler": "2.20.0-alpha.1",
81
+ "@platformatic/utils": "2.20.0-alpha.1"
82
82
  },
83
83
  "scripts": {
84
84
  "test": "npm run lint && borp --concurrency=1 --timeout=300000 && tsd",
package/schema.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://schemas.platformatic.dev/@platformatic/runtime/2.19.0-alpha.9.json",
2
+ "$id": "https://schemas.platformatic.dev/@platformatic/runtime/2.20.0-alpha.1.json",
3
3
  "$schema": "http://json-schema.org/draft-07/schema#",
4
4
  "type": "object",
5
5
  "properties": {
@@ -183,6 +183,7 @@
183
183
  },
184
184
  "path": {
185
185
  "type": "string",
186
+ "allowEmptyPaths": true,
186
187
  "resolvePath": true
187
188
  },
188
189
  "config": {
@@ -335,6 +336,7 @@
335
336
  },
336
337
  "path": {
337
338
  "type": "string",
339
+ "allowEmptyPaths": true,
338
340
  "resolvePath": true
339
341
  },
340
342
  "config": {
@@ -1107,6 +1109,10 @@
1107
1109
  }
1108
1110
  ],
1109
1111
  "default": 300000
1112
+ },
1113
+ "resolvedServicesBasePath": {
1114
+ "type": "string",
1115
+ "default": "external"
1110
1116
  }
1111
1117
  },
1112
1118
  "anyOf": [