@platformatic/watt-extra 0.1.1 → 0.1.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.
@@ -0,0 +1,58 @@
1
+ name: Test
2
+ on:
3
+ pull_request:
4
+ paths-ignore:
5
+ - "**.md"
6
+ workflow_dispatch:
7
+
8
+ concurrency:
9
+ group: "${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}"
10
+ cancel-in-progress: true
11
+
12
+ permissions:
13
+ packages: write
14
+ contents: read
15
+
16
+ jobs:
17
+ test:
18
+ name: Test
19
+ runs-on: ubuntu-latest
20
+ timeout-minutes: 15
21
+
22
+ services:
23
+ valkey:
24
+ image: "valkey/valkey:9.0"
25
+ ports:
26
+ - "6379:6379"
27
+ options: >-
28
+ --health-cmd "valkey-cli ping"
29
+ --health-interval 10s
30
+ --health-timeout 5s
31
+ --health-retries 5
32
+
33
+ strategy:
34
+ matrix:
35
+ node-version: [22.x, 24.x]
36
+
37
+ steps:
38
+ - uses: actions/checkout@v5
39
+ - uses: pnpm/action-setup@v4.1.0
40
+ with:
41
+ version: 10
42
+
43
+ - name: Use Node.js ${{ matrix.node-version }}
44
+ uses: actions/setup-node@v4
45
+ with:
46
+ node-version: ${{ matrix.node-version }}
47
+ # https://github.com/actions/setup-node/blob/main/docs/advanced-usage.md#use-private-packages
48
+ registry-url: "https://registry.npmjs.org"
49
+
50
+ - name: Install
51
+ run: |
52
+ pnpm install
53
+ env:
54
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
55
+
56
+ - name: Test
57
+ run: |
58
+ pnpm run test
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
- # WattPro
1
+ # Watt-Extra
2
2
 
3
- WattPro is an enterprise-ready runtime manager for Platformatic applications that provides production-grade capabilities including monitoring, compliance checking, caching, authentication, and integration with Infrastructure Control Center (ICC) services.
3
+ Watt-Extra is an enterprise-ready runtime manager for Platformatic applications that provides production-grade capabilities including monitoring, compliance checking, caching, authentication, and integration with Infrastructure Control Center (ICC) services.
4
4
 
5
5
  ## Overview
6
6
 
7
- WattPro wraps existing Platformatic applications (Service, Composer, Node, or Next.js) to enhance them with enterprise features without requiring any code changes. It acts as a transparent layer that:
7
+ Watt-Extra wraps existing Platformatic applications (Service, Composer, Node, or Next.js) to enhance them with enterprise features without requiring any code changes. It acts as a transparent layer that:
8
8
 
9
9
  - **Monitors** application performance and health metrics
10
10
  - **Enforces** compliance policies and security rules
@@ -23,7 +23,7 @@ None.
23
23
 
24
24
  ### Optional
25
25
 
26
- - `PLT_ICC_URL` - Infrastructure Control Center URL for connecting to control plane services. When not set, WattPro runs in standalone mode without ICC integration
26
+ - `PLT_ICC_URL` - Infrastructure Control Center URL for connecting to control plane services. When not set, Watt-Extra runs in standalone mode without ICC integration
27
27
  - `PLT_APP_NAME` - Unique identifier for your application instance. Optional when `PLT_ICC_URL` is set - if not provided, it will be automatically determined from Kubernetes labels following these rules:
28
28
  1. Uses `app.kubernetes.io/instance` label first
29
29
  2. Falls back to ReplicaSet naming convention (`{app-name}-{hash}`)
@@ -34,7 +34,7 @@ None.
34
34
 
35
35
  ### Standalone Mode
36
36
 
37
- WattPro can run without connecting to an Infrastructure Control Center (ICC). When `PLT_ICC_URL` is not set:
37
+ Watt-Extra can run without connecting to an Infrastructure Control Center (ICC). When `PLT_ICC_URL` is not set:
38
38
 
39
39
  - No ICC connection attempts are made
40
40
  - All ICC-dependent plugins (alerts, compliance, metadata, scheduler) skip their operations
@@ -43,7 +43,7 @@ WattPro can run without connecting to an Infrastructure Control Center (ICC). Wh
43
43
  ## Installation
44
44
 
45
45
  ```bash
46
- npm install @platformatic/wattpro
46
+ npm install @platformatic/watt-extra
47
47
  ```
48
48
 
49
49
  ## Usage
@@ -52,36 +52,36 @@ Add a script to your package.json:
52
52
 
53
53
  ```json
54
54
  "scripts": {
55
- "wattpro": "wattpro start"
55
+ "watt-extra": "watt-extra start"
56
56
  }
57
57
  ```
58
58
 
59
59
  Then run:
60
60
 
61
61
  ```bash
62
- npm run wattpro
62
+ npm run watt-extra
63
63
  ```
64
64
 
65
65
  ### Command Line Interface
66
66
 
67
- WattPro provides a command-line interface:
67
+ Watt-Extra provides a command-line interface:
68
68
 
69
69
  ```bash
70
70
  # Show help
71
- wattpro --help
71
+ watt-extra --help
72
72
 
73
73
  # Start the runtime manager
74
- wattpro start
74
+ watt-extra start
75
75
 
76
76
  # Set log level
77
- wattpro start --log-level=debug
77
+ watt-extra start --log-level=debug
78
78
 
79
79
  # Set ICC URL
80
- wattpro start --icc-url=http://icc-server:3000
80
+ watt-extra start --icc-url=http://icc-server:3000
81
81
 
82
82
  # Set application name
83
- wattpro start --app-name=my-application
83
+ watt-extra start --app-name=my-application
84
84
 
85
85
  # Set application directory. This is useful for development and test
86
- wattpro start --app-dir=/path/to/application
86
+ watt-extra start --app-dir=/path/to/application
87
87
  ```
package/app.js CHANGED
@@ -34,7 +34,7 @@ async function buildApp (logger) {
34
34
  app.log.info('Starting Runtime -app')
35
35
  try {
36
36
  app.log.info('Spawning the app')
37
- await app.wattpro.spawn()
37
+ await app.watt.spawn()
38
38
  } catch (err) {
39
39
  app.log.error(err, 'Failed to spawn the app')
40
40
  throw new Error('Failed to spawn the app: ' + err.message)
@@ -48,7 +48,7 @@ async function buildApp (logger) {
48
48
  return
49
49
  }
50
50
 
51
- if (!app.wattpro.runtime) {
51
+ if (!app.watt.runtime) {
52
52
  throw new Error('Runtime not started, cannot send to ICC')
53
53
  }
54
54
  try {
@@ -112,8 +112,8 @@ async function buildApp (logger) {
112
112
 
113
113
  app.close = async function close () {
114
114
  app.log.info('Closing runtime')
115
- if (app.wattpro.runtime) {
116
- await app.wattpro.close()
115
+ if (app.watt.runtime) {
116
+ await app.watt.close()
117
117
  }
118
118
  await app.closeUpdates()
119
119
  }
@@ -26,7 +26,7 @@ async function restartRuntime (runtime) {
26
26
  }
27
27
  }
28
28
 
29
- class WattPro {
29
+ class Watt {
30
30
  #env
31
31
  #logger
32
32
  #require
@@ -258,7 +258,7 @@ class WattPro {
258
258
  this.#instanceConfig.iccServices.trafficante.url
259
259
  )
260
260
  return {
261
- module: this.#require.resolve(
261
+ module: require.resolve(
262
262
  'undici-traffic-interceptor'
263
263
  ),
264
264
  options: {
@@ -340,7 +340,7 @@ class WattPro {
340
340
  }
341
341
 
342
342
  return {
343
- module: this.#require.resolve('@platformatic/slicer-interceptor'),
343
+ module: require.resolve('undici-slicer-interceptor'),
344
344
  options: cacheConfig,
345
345
  }
346
346
  }
@@ -406,7 +406,7 @@ class WattPro {
406
406
  config.httpCache = {
407
407
  ...config.httpCache,
408
408
  cacheTagsHeader,
409
- store: this.#require.resolve('@platformatic/undici-cache-redis'),
409
+ store: require.resolve('undici-cache-redis'),
410
410
  clientOpts: httpCache,
411
411
  }
412
412
  }
@@ -577,4 +577,4 @@ class WattPro {
577
577
  }
578
578
  }
579
579
 
580
- export default WattPro
580
+ export default Watt
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/watt-extra",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "The Platformatic runtime manager",
5
5
  "type": "module",
6
6
  "scripts": {
package/plugins/alerts.js CHANGED
@@ -16,7 +16,7 @@ async function alerts (app, _opts) {
16
16
  }
17
17
 
18
18
  const scalerUrl = app.instanceConfig?.iccServices?.scaler?.url
19
- const runtime = app.wattpro.runtime
19
+ const runtime = app.watt.runtime
20
20
 
21
21
  if (!scalerUrl) {
22
22
  app.log.warn(
package/plugins/auth.js CHANGED
@@ -52,7 +52,7 @@ async function authPlugin (app) {
52
52
  app.log.info('JWT token expired, reloading')
53
53
  app.token = await loadToken()
54
54
 
55
- app.wattpro?.updateSharedContext({
55
+ app.watt?.updateSharedContext({
56
56
  iccAuthHeaders: { authorization: `Bearer ${app.token}` }
57
57
  }).catch((err) => {
58
58
  app.log.error({ err }, 'Failed to update jwt token in shared context')
@@ -14,7 +14,7 @@ async function compliancy (app, _opts) {
14
14
  return
15
15
  }
16
16
 
17
- const runtime = app.wattpro.runtime
17
+ const runtime = app.watt.runtime
18
18
  const applicationId = app.instanceConfig?.applicationId
19
19
  const appDir = app.env.PLT_APP_DIR
20
20
 
@@ -16,7 +16,7 @@ async function flamegraphs (app, _opts) {
16
16
 
17
17
  app.log.info('Start profiling services')
18
18
 
19
- const runtime = app.wattpro.runtime
19
+ const runtime = app.watt.runtime
20
20
  const { applications } = await runtime.getApplications()
21
21
 
22
22
  const promises = []
@@ -52,7 +52,7 @@ async function flamegraphs (app, _opts) {
52
52
  }
53
53
 
54
54
  const podId = app.instanceId
55
- const runtime = app.wattpro.runtime
55
+ const runtime = app.watt.runtime
56
56
 
57
57
  if (!serviceIds) {
58
58
  const { applications } = await runtime.getApplications()
package/plugins/init.js CHANGED
@@ -1,4 +1,4 @@
1
- import WattPro from '../lib/wattpro.js'
1
+ import Watt from '../lib/watt.js'
2
2
  import os from 'node:os'
3
3
 
4
4
  async function initPlugin (app) {
@@ -17,13 +17,13 @@ async function initPlugin (app) {
17
17
  }
18
18
 
19
19
  async function initApplication () {
20
- app.log.info('Starting WattPro runtime manager')
20
+ app.log.info('Starting Watt-Extra runtime manager')
21
21
 
22
22
  let applicationName = app.env.PLT_APP_NAME
23
23
  const applicationDir = app.env.PLT_APP_DIR
24
24
  const instanceId = os.hostname()
25
25
 
26
- app.log.info({ applicationName, applicationDir }, 'Loading wattpro application')
26
+ app.log.info({ applicationName, applicationDir }, 'Loading watt-extra application')
27
27
 
28
28
  // Skip ICC initialization if PLT_ICC_URL is not set
29
29
  if (!app.env.PLT_ICC_URL) {
@@ -59,12 +59,12 @@ async function initPlugin (app) {
59
59
  app.instanceId = os.hostname()
60
60
  }
61
61
  }
62
- const wattpro = new WattPro(app)
63
- app.wattpro = wattpro
62
+ const watt = new Watt(app)
63
+ app.watt = watt
64
64
  app.initApplication = initApplication
65
65
 
66
66
  const headers = await app.getAuthorizationHeader()
67
- await app.wattpro.updateSharedContext({ iccAuthHeaders: headers })
67
+ await app.watt.updateSharedContext({ iccAuthHeaders: headers })
68
68
  }
69
69
 
70
70
  export default initPlugin
@@ -15,7 +15,7 @@ async function metadata (app, _opts) {
15
15
  }
16
16
 
17
17
  const applicationId = app.instanceConfig?.applicationId
18
- const runtime = app.wattpro.runtime
18
+ const runtime = app.watt.runtime
19
19
  if (!applicationId) {
20
20
  app.log.warn('Cannot process metadata: no applicationId available')
21
21
  throw new MetadataAppIdError()
@@ -8,7 +8,7 @@ async function scheduler (app, _opts) {
8
8
 
9
9
  try {
10
10
  const applicationId = app.instanceConfig?.applicationId
11
- const runtime = app.wattpro.runtime
11
+ const runtime = app.watt.runtime
12
12
  const config = await runtime.getRuntimeConfig()
13
13
  const { default: build, setDefaultHeaders } = await import('../clients/cron/cron.mjs')
14
14
 
package/plugins/update.js CHANGED
@@ -112,7 +112,7 @@ async function updatePlugin (app) {
112
112
  }
113
113
 
114
114
  app.updateConfig = async (message) => {
115
- await app.wattpro.applyIccConfigUpdates(message.data)
115
+ await app.watt.applyIccConfigUpdates(message.data)
116
116
  }
117
117
 
118
118
  app.connectToUpdates = connectToUpdates
@@ -82,7 +82,7 @@ test('should send alert when service becomes unhealthy', async (t) => {
82
82
  }
83
83
  }
84
84
 
85
- app.wattpro.runtime.emit('health', healthInfo)
85
+ app.watt.runtime.emit('health', healthInfo)
86
86
 
87
87
  await sleep(200)
88
88
 
@@ -158,7 +158,7 @@ test('should not send alert when service is healthy', async (t) => {
158
158
  }
159
159
  }
160
160
 
161
- app.wattpro.runtime.emit('health', healthInfo)
161
+ app.watt.runtime.emit('health', healthInfo)
162
162
 
163
163
  await sleep(200)
164
164
 
@@ -227,7 +227,7 @@ test('should cache health data and include it in alerts', async (t) => {
227
227
  }
228
228
  }
229
229
 
230
- app.wattpro.runtime.emit('health', healthyInfo)
230
+ app.watt.runtime.emit('health', healthyInfo)
231
231
  await sleep(100) // Small delay between events
232
232
  }
233
233
 
@@ -252,7 +252,7 @@ test('should cache health data and include it in alerts', async (t) => {
252
252
  }
253
253
  }
254
254
 
255
- app.wattpro.runtime.emit('health', unhealthyInfo)
255
+ app.watt.runtime.emit('health', unhealthyInfo)
256
256
  await sleep(200)
257
257
 
258
258
  assert.ok(alertReceived, 'Alert should have been received')
@@ -320,7 +320,7 @@ test('should not fail when health info is missing', async (t) => {
320
320
  await icc.close()
321
321
  })
322
322
 
323
- app.wattpro.runtime.emit('health', null)
323
+ app.watt.runtime.emit('health', null)
324
324
 
325
325
  await sleep(200)
326
326
 
@@ -393,11 +393,11 @@ test('should respect alert retention window', async (t) => {
393
393
  })
394
394
 
395
395
  // Send first unhealthy event - should trigger alert
396
- app.wattpro.runtime.emit('health', createHealthInfo(true))
396
+ app.watt.runtime.emit('health', createHealthInfo(true))
397
397
  await sleep(100)
398
398
 
399
399
  // Send second unhealthy event immediately - should be ignored due to retention window
400
- app.wattpro.runtime.emit('health', createHealthInfo(true))
400
+ app.watt.runtime.emit('health', createHealthInfo(true))
401
401
  await sleep(100)
402
402
 
403
403
  assert.strictEqual(alertsReceived.length, 1, 'Only one alert should be sent within retention window')
@@ -405,7 +405,7 @@ test('should respect alert retention window', async (t) => {
405
405
  await sleep(500)
406
406
 
407
407
  // Send third unhealthy event - should trigger second alert
408
- app.wattpro.runtime.emit('health', createHealthInfo(true))
408
+ app.watt.runtime.emit('health', createHealthInfo(true))
409
409
  await sleep(100)
410
410
 
411
411
  assert.strictEqual(alertsReceived.length, 2, 'Second alert should be sent after retention window expires')
@@ -514,7 +514,7 @@ test('should send alert when flamegraphs are disabled', async (t) => {
514
514
  }
515
515
  }
516
516
 
517
- app.wattpro.runtime.emit('health', healthInfo)
517
+ app.watt.runtime.emit('health', healthInfo)
518
518
 
519
519
  await sleep(200)
520
520
 
@@ -593,7 +593,7 @@ test('should send alert when failed to send a flamegraph', async (t) => {
593
593
  }
594
594
  }
595
595
 
596
- app.wattpro.runtime.emit('health', healthInfo)
596
+ app.watt.runtime.emit('health', healthInfo)
597
597
 
598
598
  await sleep(200)
599
599
 
@@ -35,7 +35,7 @@ test('check that health is configured in runtime', async (t) => {
35
35
  await icc.close()
36
36
  })
37
37
 
38
- const runtimeConfig = await app.wattpro.runtime.getRuntimeConfig()
38
+ const runtimeConfig = await app.watt.runtime.getRuntimeConfig()
39
39
 
40
40
  assert.ok(runtimeConfig.health, 'Health configuration should be present')
41
41
  assert.strictEqual(runtimeConfig.health.enabled, true, 'Health monitoring should be enabled')
@@ -35,7 +35,7 @@ test('should spawn a service app settings labels for metrics', async (t) => {
35
35
  await icc.close()
36
36
  })
37
37
 
38
- const mainConfig = app.wattpro.runtime.getRuntimeConfig(true)
38
+ const mainConfig = app.watt.runtime.getRuntimeConfig(true)
39
39
 
40
40
  const { metrics, telemetry } = mainConfig
41
41
 
@@ -122,7 +122,7 @@ test('should configure system resources', async (t) => {
122
122
  await app.close()
123
123
  await icc.close()
124
124
  })
125
- const config = await app.wattpro.runtime.getRuntimeConfig(true)
125
+ const config = await app.watt.runtime.getRuntimeConfig(true)
126
126
 
127
127
  // Check generic resources
128
128
  assert.strictEqual(config.workers, 1)
@@ -162,13 +162,13 @@ test('should remove server https configs', async (t) => {
162
162
  })
163
163
 
164
164
  {
165
- const mainConfig = app.wattpro.runtime.getRuntimeConfig(true)
165
+ const mainConfig = app.watt.runtime.getRuntimeConfig(true)
166
166
  const { server } = mainConfig
167
167
  assert.strictEqual(server.https, undefined)
168
168
  }
169
169
 
170
170
  {
171
- const runtimeConfig = await app.wattpro.runtime.getRuntimeConfig(true)
171
+ const runtimeConfig = await app.watt.runtime.getRuntimeConfig(true)
172
172
 
173
173
  const { server } = runtimeConfig
174
174
  assert.strictEqual(server.https, undefined)
@@ -199,7 +199,7 @@ test('should configure health options', async (t) => {
199
199
  await icc.close()
200
200
  })
201
201
 
202
- const runtimeConfig = await app.wattpro.runtime.getRuntimeConfig(true)
202
+ const runtimeConfig = await app.watt.runtime.getRuntimeConfig(true)
203
203
 
204
204
  const { health } = runtimeConfig
205
205
  assert.strictEqual(health.enabled, true)
@@ -233,12 +233,12 @@ test('should call updateServicesResources with maxHeapTotal', async (t) => {
233
233
 
234
234
  const updateCalls = []
235
235
  const originalUpdateServicesResources =
236
- app.wattpro.runtime.updateServicesResources
237
- app.wattpro.runtime.updateServicesResources = async (resourceUpdates) => {
236
+ app.watt.runtime.updateServicesResources
237
+ app.watt.runtime.updateServicesResources = async (resourceUpdates) => {
238
238
  updateCalls.push(resourceUpdates)
239
239
  if (originalUpdateServicesResources) {
240
240
  return originalUpdateServicesResources.call(
241
- app.wattpro.runtime,
241
+ app.watt.runtime,
242
242
  resourceUpdates
243
243
  )
244
244
  }
@@ -253,7 +253,7 @@ test('should call updateServicesResources with maxHeapTotal', async (t) => {
253
253
  },
254
254
  }
255
255
 
256
- await app.wattpro.applyIccConfigUpdates(config)
256
+ await app.watt.applyIccConfigUpdates(config)
257
257
 
258
258
  assert.strictEqual(
259
259
  updateCalls.length,
@@ -302,7 +302,7 @@ test('should handle updateServicesResources with different heap sizes', async (t
302
302
  })
303
303
 
304
304
  const updateCalls = []
305
- app.wattpro.runtime.updateServicesResources = async (resourceUpdates) => {
305
+ app.watt.runtime.updateServicesResources = async (resourceUpdates) => {
306
306
  updateCalls.push(resourceUpdates)
307
307
  }
308
308
 
@@ -318,7 +318,7 @@ test('should handle updateServicesResources with different heap sizes', async (t
318
318
  ]
319
319
 
320
320
  for (const config of configs) {
321
- await app.wattpro.applyIccConfigUpdates(config)
321
+ await app.watt.applyIccConfigUpdates(config)
322
322
  }
323
323
 
324
324
  assert.strictEqual(updateCalls.length, 1)
@@ -353,7 +353,7 @@ test('should handle updateServicesResources error gracefully', async (t) => {
353
353
  })
354
354
 
355
355
  let errorThrown = false
356
- app.wattpro.runtime.updateServicesResources = async (resourceUpdates) => {
356
+ app.watt.runtime.updateServicesResources = async (resourceUpdates) => {
357
357
  assert.strictEqual(resourceUpdates[0].health.maxHeapTotal, '256MB')
358
358
  errorThrown = true
359
359
  throw new Error('Mock update error')
@@ -365,7 +365,7 @@ test('should handle updateServicesResources error gracefully', async (t) => {
365
365
  },
366
366
  }
367
367
 
368
- await app.wattpro.applyIccConfigUpdates(config)
368
+ await app.watt.applyIccConfigUpdates(config)
369
369
 
370
370
  assert.strictEqual(
371
371
  errorThrown,
@@ -42,7 +42,7 @@ test('should spawn a runtime disabling all the scheduler jobs', async (t) => {
42
42
  await icc.close()
43
43
  })
44
44
 
45
- const config = await app.wattpro.runtime.getRuntimeConfig()
45
+ const config = await app.watt.runtime.getRuntimeConfig()
46
46
 
47
47
  const { scheduler } = config
48
48
 
@@ -36,7 +36,7 @@ function setupMockIccServer (wss, receivedMessages, validateAuth = false) {
36
36
  }
37
37
 
38
38
  function createMockApp (port, includeScalerUrl = true) {
39
- const mockWattPro = {
39
+ const mockWatt = {
40
40
  runtime: {
41
41
  getApplications: () => ({
42
42
  applications: [{ id: 'service-1' }, { id: 'service-2' }],
@@ -65,7 +65,7 @@ function createMockApp (port, includeScalerUrl = true) {
65
65
  PLT_DISABLE_FLAMEGRAPHS: false,
66
66
  PLT_FLAMEGRAPHS_INTERVAL_SEC: 1
67
67
  },
68
- wattpro: mockWattPro,
68
+ watt: mockWatt,
69
69
  }
70
70
 
71
71
  if (includeScalerUrl) {
@@ -102,7 +102,7 @@ test('should handle trigger-flamegraph command and upload flamegraphs from servi
102
102
 
103
103
  const app = createMockApp(port)
104
104
 
105
- app.wattpro.runtime.sendCommandToApplication = async (
105
+ app.watt.runtime.sendCommandToApplication = async (
106
106
  serviceId,
107
107
  command
108
108
  ) => {
@@ -162,7 +162,7 @@ test('should handle trigger-flamegraph when no runtime is available', async (t)
162
162
  )
163
163
 
164
164
  const app = createMockApp(port + 1)
165
- app.wattpro.runtime = null
165
+ app.watt.runtime = null
166
166
 
167
167
  await updatePlugin(app)
168
168
  await app.connectToUpdates()
@@ -195,7 +195,7 @@ test('should handle trigger-flamegraph when flamegraph upload fails', async (t)
195
195
 
196
196
  const app = createMockApp(port + 2)
197
197
 
198
- app.wattpro.runtime.sendCommandToApplication = async (
198
+ app.watt.runtime.sendCommandToApplication = async (
199
199
  serviceId,
200
200
  command,
201
201
  options