@platformatic/runtime 3.66.0 → 3.67.0

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
@@ -17,6 +17,7 @@ export type PlatformaticRuntimeConfig = {
17
17
  options?: {
18
18
  [k: string]: unknown;
19
19
  };
20
+ build?: boolean;
20
21
  }
21
22
  | (
22
23
  | string
@@ -25,6 +26,7 @@ export type PlatformaticRuntimeConfig = {
25
26
  options?: {
26
27
  [k: string]: unknown;
27
28
  };
29
+ build?: boolean;
28
30
  }
29
31
  )[];
30
32
  entrypoint?: string;
package/index.d.ts CHANGED
@@ -344,7 +344,20 @@ export interface RuntimeExtensionContext {
344
344
  health: RuntimeExtensionHealth
345
345
  }
346
346
 
347
+ export interface RuntimeExtensionBuildContext {
348
+ applicationId: string
349
+ applicationPath: string
350
+ }
351
+
352
+ export type RuntimeExtensionBuild = () => Promise<unknown>
353
+
347
354
  export interface RuntimeExtensionInstance {
355
+ preBuild?: (context: RuntimeExtensionBuildContext) => void | Promise<void>
356
+ onBuild?: (
357
+ context: RuntimeExtensionBuildContext,
358
+ build: RuntimeExtensionBuild
359
+ ) => unknown | Promise<unknown>
360
+ postBuild?: (context: RuntimeExtensionBuildContext, result: unknown) => void | Promise<void>
348
361
  start?: () => void | Promise<void>
349
362
  stop?: () => void | Promise<void>
350
363
  close?: () => void | Promise<void>
package/lib/errors.js CHANGED
@@ -191,6 +191,11 @@ export const DuplicateITCHandlerNameError = createError(
191
191
  'The ITC command "%s" has already been registered'
192
192
  )
193
193
 
194
+ export const RuntimeExtensionBuildAlreadyCalledError = createError(
195
+ `${ERROR_PREFIX}_EXTENSION_BUILD_ALREADY_CALLED`,
196
+ 'The build function can only be called once by each runtime extension.'
197
+ )
198
+
194
199
  export const MetricFamilyCollisionError = createError(
195
200
  `${ERROR_PREFIX}_METRIC_FAMILY_COLLISION`,
196
201
  'Extension "%s" registered metric family "%s" which collides with %s'
package/lib/runtime.js CHANGED
@@ -54,6 +54,7 @@ import {
54
54
  MissingPprofCapture,
55
55
  ReservedITCHandlerNameError,
56
56
  RuntimeAbortedError,
57
+ RuntimeExtensionBuildAlreadyCalledError,
57
58
  WorkerInterceptorJoinTimeoutError,
58
59
  WorkerNotFoundError
59
60
  } from './errors.js'
@@ -921,19 +922,63 @@ export class Runtime extends EventEmitter {
921
922
 
922
923
  async buildApplication (id) {
923
924
  const application = await this.#getApplicationById(id)
925
+ const applicationConfig = this.#applications.get(id)
926
+ const context = Object.freeze({
927
+ applicationId: id,
928
+ applicationPath: applicationConfig.path
929
+ })
924
930
 
925
931
  this.emitAndNotify('application:building', id)
926
- try {
927
- await sendViaITC(application, 'build')
928
- this.emitAndNotify('application:built', id)
929
- } catch (e) {
930
- // The application exports no meta, return an empty object
931
- if (e.code === 'PLT_ITC_HANDLER_NOT_FOUND') {
932
- return {}
932
+ for (const extension of this.#extensions) {
933
+ await extension.instance?.preBuild?.(context)
934
+ }
935
+
936
+ let buildHandlerMissing = false
937
+ const build = this.#extensions.reduceRight(
938
+ (next, extension) => {
939
+ if (typeof extension.instance?.onBuild !== 'function') {
940
+ return next
941
+ }
942
+
943
+ return () => {
944
+ let called = false
945
+ const build = () => {
946
+ if (called) {
947
+ throw new RuntimeExtensionBuildAlreadyCalledError()
948
+ }
949
+
950
+ called = true
951
+ return next()
952
+ }
953
+
954
+ return extension.instance.onBuild(context, build)
955
+ }
956
+ },
957
+ async () => {
958
+ try {
959
+ return await sendViaITC(application, 'build')
960
+ } catch (e) {
961
+ // The application exports no meta, return an empty object
962
+ if (e.code === 'PLT_ITC_HANDLER_NOT_FOUND') {
963
+ buildHandlerMissing = true
964
+ return {}
965
+ }
966
+
967
+ throw e
968
+ }
933
969
  }
970
+ )
934
971
 
935
- throw e
972
+ const result = await build()
973
+
974
+ for (const extension of [...this.#extensions].reverse()) {
975
+ await extension.instance?.postBuild?.(context, result)
936
976
  }
977
+
978
+ if (!buildHandlerMissing) {
979
+ this.emitAndNotify('application:built', id)
980
+ }
981
+ return result
937
982
  }
938
983
 
939
984
  async startApplicationProfiling (id, options = {}, ensureStarted = true) {
@@ -4343,8 +4388,7 @@ export class Runtime extends EventEmitter {
4343
4388
  async #loadExtensions () {
4344
4389
  let extensions = this.#config.extensions
4345
4390
 
4346
- // Do not load extensions when building applications
4347
- if (!extensions || this.#context.build) {
4391
+ if (!extensions) {
4348
4392
  return
4349
4393
  }
4350
4394
 
@@ -4353,7 +4397,14 @@ export class Runtime extends EventEmitter {
4353
4397
  }
4354
4398
 
4355
4399
  for (const extension of extensions) {
4356
- const { path, options } = typeof extension === 'string' ? { path: extension } : extension
4400
+ const { path, options, build } = typeof extension === 'string' ? { path: extension } : extension
4401
+
4402
+ // Runtime extensions historically were not loaded by `wattpm build`.
4403
+ // Preserve that behavior unless an extension explicitly opts into the
4404
+ // build lifecycle.
4405
+ if (this.#context.build && !build) {
4406
+ continue
4407
+ }
4357
4408
 
4358
4409
  let imported
4359
4410
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/runtime",
3
- "version": "3.66.0",
3
+ "version": "3.67.0",
4
4
  "description": "Platformatic runtime",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -36,17 +36,17 @@
36
36
  "pino-sentry-transport": "^1.6.0",
37
37
  "split2": "^4.2.0",
38
38
  "tstyche": "^6.2.0",
39
- "typescript": "^5.9.3",
39
+ "typescript": "~6.0.3",
40
40
  "undici-oidc-interceptor": "^0.9.0",
41
41
  "why-is-node-running": "^2.2.2",
42
- "@platformatic/composer": "3.66.0",
43
- "@platformatic/gateway": "3.66.0",
44
- "@platformatic/service": "3.66.0",
45
- "@platformatic/sql-graphql": "3.66.0",
46
- "@platformatic/db": "3.66.0",
47
- "@platformatic/sql-mapper": "3.66.0",
48
- "@platformatic/wattpm-pprof-capture": "3.66.0",
49
- "@platformatic/node": "3.66.0"
42
+ "@platformatic/composer": "3.67.0",
43
+ "@platformatic/db": "3.67.0",
44
+ "@platformatic/node": "3.67.0",
45
+ "@platformatic/service": "3.67.0",
46
+ "@platformatic/sql-graphql": "3.67.0",
47
+ "@platformatic/sql-mapper": "3.67.0",
48
+ "@platformatic/wattpm-pprof-capture": "3.67.0",
49
+ "@platformatic/gateway": "3.67.0"
50
50
  },
51
51
  "dependencies": {
52
52
  "@fastify/accepts": "^5.0.0",
@@ -77,13 +77,13 @@
77
77
  "undici": "^7.27.2",
78
78
  "undici-thread-interceptor": "^1.3.1",
79
79
  "ws": "^8.16.0",
80
- "@platformatic/basic": "3.66.0",
81
- "@platformatic/foundation": "3.66.0",
82
- "@platformatic/itc": "3.66.0",
83
- "@platformatic/metrics": "3.66.0",
84
- "@platformatic/globals": "3.66.0",
85
- "@platformatic/generators": "3.66.0",
86
- "@platformatic/telemetry": "3.66.0"
80
+ "@platformatic/basic": "3.67.0",
81
+ "@platformatic/generators": "3.67.0",
82
+ "@platformatic/foundation": "3.67.0",
83
+ "@platformatic/itc": "3.67.0",
84
+ "@platformatic/globals": "3.67.0",
85
+ "@platformatic/telemetry": "3.67.0",
86
+ "@platformatic/metrics": "3.67.0"
87
87
  },
88
88
  "engines": {
89
89
  "node": ">=22.19.0"
package/schema.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://schemas.platformatic.dev/@platformatic/runtime/3.66.0.json",
2
+ "$id": "https://schemas.platformatic.dev/@platformatic/runtime/3.67.0.json",
3
3
  "$schema": "http://json-schema.org/draft-07/schema#",
4
4
  "title": "Platformatic Runtime Config",
5
5
  "type": "object",
@@ -42,6 +42,10 @@
42
42
  "options": {
43
43
  "type": "object",
44
44
  "additionalProperties": true
45
+ },
46
+ "build": {
47
+ "type": "boolean",
48
+ "default": false
45
49
  }
46
50
  }
47
51
  },
@@ -67,6 +71,10 @@
67
71
  "options": {
68
72
  "type": "object",
69
73
  "additionalProperties": true
74
+ },
75
+ "build": {
76
+ "type": "boolean",
77
+ "default": false
70
78
  }
71
79
  }
72
80
  }