@platformatic/runtime 3.38.1 → 3.40.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
@@ -90,6 +90,12 @@ export type PlatformaticRuntimeConfig = {
90
90
  */
91
91
  directory?: string;
92
92
  };
93
+ management?:
94
+ | boolean
95
+ | {
96
+ enabled?: boolean;
97
+ operations?: string[];
98
+ };
93
99
  };
94
100
  };
95
101
  };
@@ -167,6 +173,10 @@ export type PlatformaticRuntimeConfig = {
167
173
  customLevels?: {
168
174
  [k: string]: unknown;
169
175
  };
176
+ openTelemetryExporter?: {
177
+ protocol: "grpc" | "http";
178
+ url: string;
179
+ };
170
180
  captureStdio?: boolean;
171
181
  [k: string]: unknown;
172
182
  };
@@ -306,6 +316,12 @@ export type PlatformaticRuntimeConfig = {
306
316
  */
307
317
  socket?: string;
308
318
  };
319
+ management?:
320
+ | boolean
321
+ | {
322
+ enabled?: boolean;
323
+ operations?: string[];
324
+ };
309
325
  metrics?:
310
326
  | boolean
311
327
  | {
package/index.d.ts CHANGED
@@ -65,6 +65,77 @@ export module symbols {
65
65
  export declare const kWorkersBroadcast: unique symbol
66
66
  }
67
67
 
68
+ export interface InjectParams {
69
+ method?: string
70
+ url: string
71
+ headers?: Record<string, string>
72
+ query?: Record<string, string>
73
+ body?: unknown
74
+ }
75
+
76
+ export interface InjectResponse {
77
+ statusCode: number
78
+ statusMessage: string
79
+ headers: Record<string, string>
80
+ body: string
81
+ payload: string
82
+ rawPayload: ArrayBuffer
83
+ }
84
+
85
+ export interface ApplicationDetails {
86
+ id: string
87
+ type?: string
88
+ config?: string
89
+ path?: string
90
+ status?: string
91
+ dependencies?: string[]
92
+ version?: string
93
+ localUrl?: string
94
+ entrypoint?: boolean
95
+ sourceMaps?: boolean
96
+ workers?: number
97
+ url?: string | null
98
+ }
99
+
100
+ export interface RuntimeMetadata {
101
+ pid: number
102
+ cwd: string
103
+ argv: string[]
104
+ uptimeSeconds: number
105
+ execPath: string
106
+ nodeVersion: string
107
+ projectDir: string
108
+ packageName: string | null
109
+ packageVersion: string | null
110
+ url: string | null
111
+ platformaticVersion: string
112
+ }
113
+
114
+ export declare class ManagementClient {
115
+ constructor (allowedOperations?: string[])
116
+
117
+ getRuntimeStatus (): Promise<string>
118
+ getRuntimeMetadata (): Promise<RuntimeMetadata>
119
+ getRuntimeConfig (): Promise<Record<string, unknown>>
120
+ getRuntimeEnv (): Promise<Record<string, string>>
121
+ getApplicationsIds (): Promise<string[]>
122
+ getApplications (): Promise<{ entrypoint: string; production: boolean; applications: ApplicationDetails[] }>
123
+ getWorkers (): Promise<Record<string, unknown>>
124
+ getApplicationDetails (id: string): Promise<ApplicationDetails>
125
+ getApplicationConfig (id: string): Promise<Record<string, unknown>>
126
+ getApplicationEnv (id: string): Promise<Record<string, string>>
127
+ getApplicationOpenapiSchema (id: string): Promise<unknown>
128
+ getApplicationGraphqlSchema (id: string): Promise<unknown>
129
+ getMetrics (format?: string): Promise<{ metrics: unknown }>
130
+ startApplication (id: string): Promise<void>
131
+ stopApplication (id: string): Promise<void>
132
+ restartApplication (id: string): Promise<void>
133
+ restart (applications?: string[]): Promise<string>
134
+ addApplications (applications: unknown[], start?: boolean): Promise<ApplicationDetails[]>
135
+ removeApplications (ids: string[]): Promise<ApplicationDetails[]>
136
+ inject (id: string, injectParams: InjectParams): Promise<InjectResponse>
137
+ }
138
+
68
139
  export class Generator extends BaseGenerator {}
69
140
 
70
141
  export class WrappedGenerator extends BaseGenerator {}
package/index.js CHANGED
@@ -82,14 +82,22 @@ export async function loadConfiguration (configOrRoot, sourceOrConfig, context)
82
82
  })
83
83
  }
84
84
 
85
- export async function loadApplicationsCommands () {
85
+ export async function loadApplicationsCommands (executableName = '') {
86
86
  const applications = {}
87
87
  const commands = {}
88
88
  const help = {}
89
89
 
90
90
  let config
91
91
  try {
92
- const file = await findRuntimeConfigurationFile(abstractLogger, process.cwd(), null, false, false)
92
+ const file = await findRuntimeConfigurationFile(
93
+ abstractLogger,
94
+ process.cwd(),
95
+ null,
96
+ false,
97
+ false,
98
+ true,
99
+ executableName
100
+ )
93
101
 
94
102
  /* c8 ignore next 3 - Hard to test */
95
103
  if (!file) {
package/lib/config.js CHANGED
@@ -281,6 +281,10 @@ export async function prepareApplication (config, application, defaultWorkers) {
281
281
  application.watch = config.watch
282
282
  }
283
283
 
284
+ if (typeof application.management === 'undefined' && config.management) {
285
+ application.management = config.management
286
+ }
287
+
284
288
  return application
285
289
  }
286
290
 
package/lib/logger.js CHANGED
@@ -1,4 +1,4 @@
1
- import { buildPinoFormatters, buildPinoTimestamp, usePrettyPrint } from '@platformatic/foundation'
1
+ import { buildPinoFormatters, buildPinoTimestamp } from '@platformatic/foundation'
2
2
  import { isatty } from 'node:tty'
3
3
  import pino from 'pino'
4
4
  import pretty from 'pino-pretty'
@@ -158,7 +158,7 @@ export async function createLogger (config) {
158
158
 
159
159
  if (config.logger.transport) {
160
160
  cliStream = pino.transport(config.logger.transport)
161
- } else if ((process.env.FORCE_TTY || isatty(1)) && usePrettyPrint()) {
161
+ } else if ((process.env.FORCE_TTY || isatty(1)) && process.env.PLT_PRETTY_PRINT !== 'false') {
162
162
  cliStream = createPrettifier(context)
163
163
  } else {
164
164
  cliStream = pino.destination(1)
@@ -178,6 +178,31 @@ export async function createLogger (config) {
178
178
 
179
179
  const multiStream = pino.multistream([{ stream: cliStream, level: loggerConfig.level }])
180
180
 
181
+ if (config.telemetry && config.logger.openTelemetryExporter) {
182
+ multiStream.add(
183
+ pino.transport({
184
+ target: 'pino-opentelemetry-transport',
185
+ options: {
186
+ resourceAttributes: {
187
+ 'service.name': config.telemetry.applicationName,
188
+ 'service.version': config.telemetry.version
189
+ },
190
+ logRecordProcessorOptions: [
191
+ {
192
+ recordProcessorType: 'simple',
193
+ exporterOptions: {
194
+ protocol: config.logger.openTelemetryExporter.protocol,
195
+ httpExporterOptions: {
196
+ url: config.logger.openTelemetryExporter.url
197
+ }
198
+ }
199
+ }
200
+ ]
201
+ }
202
+ })
203
+ )
204
+ }
205
+
181
206
  const logsFileMb = 5
182
207
  const logsLimitMb = config.managementApi?.logs?.maxSize || 200
183
208
 
@@ -0,0 +1,139 @@
1
+ import {
2
+ applications as applicationSchema,
3
+ kMetadata,
4
+ validate
5
+ } from '@platformatic/foundation'
6
+ import { prepareApplication } from './config.js'
7
+
8
+ const allOperations = [
9
+ 'getRuntimeStatus',
10
+ 'getRuntimeMetadata',
11
+ 'getRuntimeConfig',
12
+ 'getRuntimeEnv',
13
+ 'getApplicationsIds',
14
+ 'getApplications',
15
+ 'getWorkers',
16
+ 'getApplicationDetails',
17
+ 'getApplicationConfig',
18
+ 'getApplicationEnv',
19
+ 'getApplicationOpenapiSchema',
20
+ 'getApplicationGraphqlSchema',
21
+ 'getMetrics',
22
+ 'startApplication',
23
+ 'stopApplication',
24
+ 'restartApplication',
25
+ 'restart',
26
+ 'addApplications',
27
+ 'removeApplications',
28
+ 'inject'
29
+ ]
30
+
31
+ export function createManagementHandlers (runtime, allowedOperations) {
32
+ const allowed = allowedOperations
33
+ ? new Set(allowedOperations)
34
+ : new Set(allOperations)
35
+
36
+ const handlers = new Map()
37
+
38
+ function register (name, fn) {
39
+ if (allowed.has(name)) {
40
+ handlers.set('management:' + name, fn)
41
+ }
42
+ }
43
+
44
+ // Read operations - no arguments
45
+ register('getRuntimeStatus', async () => {
46
+ return runtime.getRuntimeStatus()
47
+ })
48
+
49
+ register('getRuntimeMetadata', async () => {
50
+ return runtime.getRuntimeMetadata()
51
+ })
52
+
53
+ register('getRuntimeConfig', async () => {
54
+ return runtime.getRuntimeConfig()
55
+ })
56
+
57
+ register('getRuntimeEnv', async () => {
58
+ return runtime.getRuntimeEnv()
59
+ })
60
+
61
+ register('getApplicationsIds', async () => {
62
+ return runtime.getApplicationsIds()
63
+ })
64
+
65
+ register('getApplications', async () => {
66
+ return runtime.getApplications()
67
+ })
68
+
69
+ register('getWorkers', async () => {
70
+ return runtime.getWorkers()
71
+ })
72
+
73
+ // Read operations - with application id
74
+ register('getApplicationDetails', async ({ id }) => {
75
+ return runtime.getApplicationDetails(id)
76
+ })
77
+
78
+ register('getApplicationConfig', async ({ id }) => {
79
+ return runtime.getApplicationConfig(id)
80
+ })
81
+
82
+ register('getApplicationEnv', async ({ id }) => {
83
+ return runtime.getApplicationEnv(id)
84
+ })
85
+
86
+ register('getApplicationOpenapiSchema', async ({ id }) => {
87
+ return runtime.getApplicationOpenapiSchema(id)
88
+ })
89
+
90
+ register('getApplicationGraphqlSchema', async ({ id }) => {
91
+ return runtime.getApplicationGraphqlSchema(id)
92
+ })
93
+
94
+ // Metrics
95
+ register('getMetrics', async ({ format } = {}) => {
96
+ return runtime.getMetrics(format)
97
+ })
98
+
99
+ // Write operations
100
+ register('startApplication', async ({ id }) => {
101
+ await runtime.startApplication(id)
102
+ })
103
+
104
+ register('stopApplication', async ({ id }) => {
105
+ await runtime.stopApplication(id)
106
+ })
107
+
108
+ register('restartApplication', async ({ id }) => {
109
+ await runtime.restartApplication(id)
110
+ })
111
+
112
+ register('restart', async ({ applications } = {}) => {
113
+ return runtime.restart(applications)
114
+ })
115
+
116
+ register('addApplications', async ({ applications, start }) => {
117
+ const config = runtime.getRuntimeConfig(true)
118
+
119
+ validate(applicationSchema, applications, {}, true, config[kMetadata].root)
120
+
121
+ for (let i = 0; i < applications.length; i++) {
122
+ applications[i] = await prepareApplication(config, applications[i], config.workers)
123
+ }
124
+
125
+ return runtime.addApplications(applications, start)
126
+ })
127
+
128
+ register('removeApplications', async ({ ids }) => {
129
+ return runtime.removeApplications(ids)
130
+ })
131
+
132
+ register('inject', async ({ id, injectParams }) => {
133
+ return runtime.inject(id, injectParams)
134
+ })
135
+
136
+ return handlers
137
+ }
138
+
139
+ export { allOperations }
package/lib/runtime.js CHANGED
@@ -42,11 +42,12 @@ import {
42
42
  } from './errors.js'
43
43
  import { abstractLogger, createLogger } from './logger.js'
44
44
  import { startManagementApi } from './management-api.js'
45
+ import { createManagementHandlers } from './management-handlers.js'
45
46
  import { createChannelCreationHook } from './policies.js'
46
47
  import { startPrometheusServer } from './prom-server.js'
47
48
  import { startScheduler } from './scheduler.js'
48
49
  import { createSharedStore } from './shared-http-cache.js'
49
- import { topologicalSort } from './utils.js'
50
+ import { topologicalLevels, topologicalSort } from './utils.js'
50
51
  import { version } from './version.js'
51
52
  import { DynamicWorkersScaler } from './worker-scaler.js'
52
53
  import { HealthSignalsQueue } from './worker/health-signals.js'
@@ -560,12 +561,15 @@ export class Runtime extends EventEmitter {
560
561
  // If circular dependencies are detected, an error with proper error code is thrown.
561
562
  applications = topologicalSort(dependencies)
562
563
 
563
- const startInvocations = []
564
- for (const application of applications) {
565
- startInvocations.push([application, silent])
566
- }
564
+ // Group into dependency levels so that each level's dependencies are all
565
+ // in previous levels. Levels are started sequentially, but applications
566
+ // within the same level start in parallel.
567
+ const levels = topologicalLevels(applications, dependencies)
567
568
 
568
- return executeInParallel(this.startApplication.bind(this), startInvocations, this.#concurrency)
569
+ for (const level of levels) {
570
+ const startInvocations = level.map(app => [app, silent])
571
+ await executeInParallel(this.startApplication.bind(this), startInvocations, this.#concurrency)
572
+ }
569
573
  }
570
574
 
571
575
  async stopApplications (applicationsToStop, silent = false, skipDependencies = false) {
@@ -1792,6 +1796,25 @@ export class Runtime extends EventEmitter {
1792
1796
  port: worker,
1793
1797
  handlers: this.#workerITCHandlers
1794
1798
  })
1799
+
1800
+ // Register management ITC handlers for privileged applications
1801
+ if (applicationConfig.management) {
1802
+ const mgmtEnabled = typeof applicationConfig.management === 'boolean'
1803
+ ? applicationConfig.management
1804
+ : applicationConfig.management.enabled !== false
1805
+
1806
+ if (mgmtEnabled) {
1807
+ const allowedOps = typeof applicationConfig.management === 'object'
1808
+ ? applicationConfig.management.operations
1809
+ : undefined
1810
+
1811
+ const handlers = createManagementHandlers(this, allowedOps)
1812
+ for (const [name, handler] of handlers) {
1813
+ worker[kITC].handle(name, handler)
1814
+ }
1815
+ }
1816
+ }
1817
+
1795
1818
  worker[kITC].listen()
1796
1819
 
1797
1820
  // Forward events from the worker
package/lib/utils.js CHANGED
@@ -19,6 +19,35 @@ export function getRuntimeTmpDir (runtimeDir) {
19
19
  return join(platformaticTmpDir, runtimeDirHash)
20
20
  }
21
21
 
22
+ // Given a topologically sorted list and the dependency graph,
23
+ // group nodes into levels where each level's dependencies are all in previous levels.
24
+ // This allows starting each level in parallel while respecting dependency order.
25
+ export function topologicalLevels (sorted, graph) {
26
+ const levels = []
27
+ const levelOf = new Map()
28
+
29
+ for (const node of sorted) {
30
+ const deps = graph.get(node) ?? []
31
+ let level = 0
32
+
33
+ for (const dep of deps) {
34
+ if (levelOf.has(dep)) {
35
+ level = Math.max(level, levelOf.get(dep) + 1)
36
+ }
37
+ }
38
+
39
+ levelOf.set(node, level)
40
+
41
+ while (levels.length <= level) {
42
+ levels.push([])
43
+ }
44
+
45
+ levels[level].push(node)
46
+ }
47
+
48
+ return levels
49
+ }
50
+
22
51
  // Graph: Map<string, string[]>
23
52
  export function topologicalSort (graph) {
24
53
  const result = []
@@ -19,6 +19,7 @@ export async function setDispatcher (runtimeConfig) {
19
19
  }
20
20
 
21
21
  let userInterceptors = []
22
+
22
23
  if (Array.isArray(runtimeConfig.undici?.interceptors)) {
23
24
  const _require = createRequire(join(workerData.dirname, 'package.json'))
24
25
  userInterceptors = await loadInterceptors(_require, runtimeConfig.undici.interceptors)
@@ -104,7 +105,7 @@ async function loadInterceptor (_require, interceptorConfig, key) {
104
105
 
105
106
  const url = pathToFileURL(_require.resolve(module))
106
107
  const createInterceptor = (await import(url)).default
107
- const interceptor = createInterceptor(options)
108
+ const interceptor = await createInterceptor(options)
108
109
 
109
110
  const { updatableInterceptor, updateInterceptor } = createUpdatableInterceptor(interceptor)
110
111
 
@@ -5,6 +5,7 @@ import {
5
5
  ensureLoggableError,
6
6
  getPrivateSymbol
7
7
  } from '@platformatic/foundation'
8
+ import { addPinoInstrumentation } from '@platformatic/telemetry'
8
9
  import { subscribe } from 'node:diagnostics_channel'
9
10
  import { EventEmitter } from 'node:events'
10
11
  import { ServerResponse } from 'node:http'
@@ -93,6 +94,10 @@ function createLogger () {
93
94
  pinoOptions.timestamp = buildPinoTimestamp(pinoOptions.timestamp)
94
95
  }
95
96
 
97
+ if (workerData.config.logger?.openTelemetryExporter && workerData.applicationConfig.telemetry?.enabled !== false) {
98
+ addPinoInstrumentation(pinoOptions)
99
+ }
100
+
96
101
  return pino(pinoOptions)
97
102
  }
98
103
 
@@ -270,6 +275,21 @@ async function main () {
270
275
  globalThis[kITC] = itc
271
276
  globalThis.platformatic.itc = itc
272
277
 
278
+ // Setup management client for privileged applications
279
+ if (applicationConfig.management) {
280
+ const mgmtEnabled = typeof applicationConfig.management === 'boolean'
281
+ ? applicationConfig.management
282
+ : applicationConfig.management.enabled !== false
283
+
284
+ if (mgmtEnabled) {
285
+ const { ManagementClient } = await import('./management.js')
286
+ const ops = typeof applicationConfig.management === 'object'
287
+ ? applicationConfig.management.operations
288
+ : undefined
289
+ globalThis.platformatic.management = new ManagementClient(ops)
290
+ }
291
+ }
292
+
273
293
  initHealthSignalsApi({
274
294
  workerId: workerData.worker.id,
275
295
  applicationId: applicationConfig.id
@@ -0,0 +1,99 @@
1
+ import { kITC } from './symbols.js'
2
+
3
+ export class ManagementClient {
4
+ #allowedOperations
5
+
6
+ constructor (allowedOperations) {
7
+ this.#allowedOperations = allowedOperations
8
+ ? new Set(allowedOperations)
9
+ : null
10
+ }
11
+
12
+ #send (operation, data) {
13
+ if (this.#allowedOperations && !this.#allowedOperations.has(operation)) {
14
+ throw new Error(`Operation "${operation}" is not allowed`)
15
+ }
16
+
17
+ return globalThis[kITC].send('management:' + operation, data)
18
+ }
19
+
20
+ getRuntimeStatus () {
21
+ return this.#send('getRuntimeStatus')
22
+ }
23
+
24
+ getRuntimeMetadata () {
25
+ return this.#send('getRuntimeMetadata')
26
+ }
27
+
28
+ getRuntimeConfig () {
29
+ return this.#send('getRuntimeConfig')
30
+ }
31
+
32
+ getRuntimeEnv () {
33
+ return this.#send('getRuntimeEnv')
34
+ }
35
+
36
+ getApplicationsIds () {
37
+ return this.#send('getApplicationsIds')
38
+ }
39
+
40
+ getApplications () {
41
+ return this.#send('getApplications')
42
+ }
43
+
44
+ getWorkers () {
45
+ return this.#send('getWorkers')
46
+ }
47
+
48
+ getApplicationDetails (id) {
49
+ return this.#send('getApplicationDetails', { id })
50
+ }
51
+
52
+ getApplicationConfig (id) {
53
+ return this.#send('getApplicationConfig', { id })
54
+ }
55
+
56
+ getApplicationEnv (id) {
57
+ return this.#send('getApplicationEnv', { id })
58
+ }
59
+
60
+ getApplicationOpenapiSchema (id) {
61
+ return this.#send('getApplicationOpenapiSchema', { id })
62
+ }
63
+
64
+ getApplicationGraphqlSchema (id) {
65
+ return this.#send('getApplicationGraphqlSchema', { id })
66
+ }
67
+
68
+ getMetrics (format) {
69
+ return this.#send('getMetrics', { format })
70
+ }
71
+
72
+ startApplication (id) {
73
+ return this.#send('startApplication', { id })
74
+ }
75
+
76
+ stopApplication (id) {
77
+ return this.#send('stopApplication', { id })
78
+ }
79
+
80
+ restartApplication (id) {
81
+ return this.#send('restartApplication', { id })
82
+ }
83
+
84
+ restart (applications) {
85
+ return this.#send('restart', { applications })
86
+ }
87
+
88
+ addApplications (applications, start) {
89
+ return this.#send('addApplications', { applications, start })
90
+ }
91
+
92
+ removeApplications (ids) {
93
+ return this.#send('removeApplications', { ids })
94
+ }
95
+
96
+ inject (id, injectParams) {
97
+ return this.#send('inject', { id, injectParams })
98
+ }
99
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/runtime",
3
- "version": "3.38.1",
3
+ "version": "3.40.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -35,14 +35,14 @@
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/db": "3.38.1",
39
- "@platformatic/gateway": "3.38.1",
40
- "@platformatic/composer": "3.38.1",
41
- "@platformatic/node": "3.38.1",
42
- "@platformatic/service": "3.38.1",
43
- "@platformatic/sql-graphql": "3.38.1",
44
- "@platformatic/sql-mapper": "3.38.1",
45
- "@platformatic/wattpm-pprof-capture": "3.38.1"
38
+ "@platformatic/composer": "3.40.0",
39
+ "@platformatic/service": "3.40.0",
40
+ "@platformatic/gateway": "3.40.0",
41
+ "@platformatic/db": "3.40.0",
42
+ "@platformatic/sql-mapper": "3.40.0",
43
+ "@platformatic/wattpm-pprof-capture": "3.40.0",
44
+ "@platformatic/sql-graphql": "3.40.0",
45
+ "@platformatic/node": "3.40.0"
46
46
  },
47
47
  "dependencies": {
48
48
  "@fastify/accepts": "^5.0.0",
@@ -50,6 +50,7 @@
50
50
  "@fastify/error": "^4.0.0",
51
51
  "@fastify/websocket": "^11.0.0",
52
52
  "@opentelemetry/api": "^1.9.0",
53
+ "@platformatic/prom-client": "^1.0.0",
53
54
  "@platformatic/undici-cache-memory": "^0.8.1",
54
55
  "@watchable/unpromise": "^1.0.2",
55
56
  "change-case-all": "^2.1.0",
@@ -63,20 +64,20 @@
63
64
  "help-me": "^5.0.0",
64
65
  "minimist": "^1.2.8",
65
66
  "pino": "^9.9.0",
67
+ "pino-opentelemetry-transport": "^2.0.0",
66
68
  "pino-pretty": "^13.0.0",
67
- "@platformatic/prom-client": "^1.0.0",
68
69
  "semgrator": "^0.3.0",
69
70
  "sonic-boom": "^4.2.0",
70
71
  "systeminformation": "^5.27.11",
71
72
  "undici": "^7.0.0",
72
73
  "undici-thread-interceptor": "^1.3.1",
73
74
  "ws": "^8.16.0",
74
- "@platformatic/basic": "3.38.1",
75
- "@platformatic/foundation": "3.38.1",
76
- "@platformatic/generators": "3.38.1",
77
- "@platformatic/metrics": "3.38.1",
78
- "@platformatic/itc": "3.38.1",
79
- "@platformatic/telemetry": "3.38.1"
75
+ "@platformatic/foundation": "3.40.0",
76
+ "@platformatic/generators": "3.40.0",
77
+ "@platformatic/basic": "3.40.0",
78
+ "@platformatic/itc": "3.40.0",
79
+ "@platformatic/metrics": "3.40.0",
80
+ "@platformatic/telemetry": "3.40.0"
80
81
  },
81
82
  "engines": {
82
83
  "node": ">=22.19.0"
package/schema.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://schemas.platformatic.dev/@platformatic/runtime/3.38.1.json",
2
+ "$id": "https://schemas.platformatic.dev/@platformatic/runtime/3.40.0.json",
3
3
  "$schema": "http://json-schema.org/draft-07/schema#",
4
4
  "title": "Platformatic Runtime Config",
5
5
  "type": "object",
@@ -354,6 +354,29 @@
354
354
  "additionalProperties": false
355
355
  }
356
356
  ]
357
+ },
358
+ "management": {
359
+ "anyOf": [
360
+ {
361
+ "type": "boolean"
362
+ },
363
+ {
364
+ "type": "object",
365
+ "properties": {
366
+ "enabled": {
367
+ "type": "boolean",
368
+ "default": true
369
+ },
370
+ "operations": {
371
+ "type": "array",
372
+ "items": {
373
+ "type": "string"
374
+ }
375
+ }
376
+ },
377
+ "additionalProperties": false
378
+ }
379
+ ]
357
380
  }
358
381
  }
359
382
  }
@@ -690,6 +713,29 @@
690
713
  "additionalProperties": false
691
714
  }
692
715
  ]
716
+ },
717
+ "management": {
718
+ "anyOf": [
719
+ {
720
+ "type": "boolean"
721
+ },
722
+ {
723
+ "type": "object",
724
+ "properties": {
725
+ "enabled": {
726
+ "type": "boolean",
727
+ "default": true
728
+ },
729
+ "operations": {
730
+ "type": "array",
731
+ "items": {
732
+ "type": "string"
733
+ }
734
+ }
735
+ },
736
+ "additionalProperties": false
737
+ }
738
+ ]
693
739
  }
694
740
  }
695
741
  }
@@ -1024,6 +1070,29 @@
1024
1070
  "additionalProperties": false
1025
1071
  }
1026
1072
  ]
1073
+ },
1074
+ "management": {
1075
+ "anyOf": [
1076
+ {
1077
+ "type": "boolean"
1078
+ },
1079
+ {
1080
+ "type": "object",
1081
+ "properties": {
1082
+ "enabled": {
1083
+ "type": "boolean",
1084
+ "default": true
1085
+ },
1086
+ "operations": {
1087
+ "type": "array",
1088
+ "items": {
1089
+ "type": "string"
1090
+ }
1091
+ }
1092
+ },
1093
+ "additionalProperties": false
1094
+ }
1095
+ ]
1027
1096
  }
1028
1097
  }
1029
1098
  }
@@ -1358,6 +1427,29 @@
1358
1427
  "additionalProperties": false
1359
1428
  }
1360
1429
  ]
1430
+ },
1431
+ "management": {
1432
+ "anyOf": [
1433
+ {
1434
+ "type": "boolean"
1435
+ },
1436
+ {
1437
+ "type": "object",
1438
+ "properties": {
1439
+ "enabled": {
1440
+ "type": "boolean",
1441
+ "default": true
1442
+ },
1443
+ "operations": {
1444
+ "type": "array",
1445
+ "items": {
1446
+ "type": "string"
1447
+ }
1448
+ }
1449
+ },
1450
+ "additionalProperties": false
1451
+ }
1452
+ ]
1361
1453
  }
1362
1454
  }
1363
1455
  }
@@ -1578,6 +1670,26 @@
1578
1670
  "type": "object",
1579
1671
  "additionalProperties": true
1580
1672
  },
1673
+ "openTelemetryExporter": {
1674
+ "type": "object",
1675
+ "properties": {
1676
+ "protocol": {
1677
+ "type": "string",
1678
+ "enum": [
1679
+ "grpc",
1680
+ "http"
1681
+ ]
1682
+ },
1683
+ "url": {
1684
+ "type": "string"
1685
+ }
1686
+ },
1687
+ "required": [
1688
+ "protocol",
1689
+ "url"
1690
+ ],
1691
+ "additionalProperties": false
1692
+ },
1581
1693
  "captureStdio": {
1582
1694
  "type": "boolean",
1583
1695
  "default": true
@@ -2081,6 +2193,29 @@
2081
2193
  ],
2082
2194
  "default": true
2083
2195
  },
2196
+ "management": {
2197
+ "anyOf": [
2198
+ {
2199
+ "type": "boolean"
2200
+ },
2201
+ {
2202
+ "type": "object",
2203
+ "properties": {
2204
+ "enabled": {
2205
+ "type": "boolean",
2206
+ "default": true
2207
+ },
2208
+ "operations": {
2209
+ "type": "array",
2210
+ "items": {
2211
+ "type": "string"
2212
+ }
2213
+ }
2214
+ },
2215
+ "additionalProperties": false
2216
+ }
2217
+ ]
2218
+ },
2084
2219
  "metrics": {
2085
2220
  "anyOf": [
2086
2221
  {