@platformatic/watt-admin 0.5.0 → 0.6.0-alpha.2

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.
Files changed (116) hide show
  1. package/README.md +2 -0
  2. package/cli.js +85 -91
  3. package/lib/start.js +72 -12
  4. package/package.json +49 -44
  5. package/tsconfig.json +22 -0
  6. package/watt.json +1 -1
  7. package/web/backend/platformatic.json +2 -3
  8. package/web/backend/tsconfig.json +4 -1
  9. package/web/composer/platformatic.json +3 -3
  10. package/web/frontend/dist/index.html +2977 -6
  11. package/web/frontend/index.html +0 -1
  12. package/web/frontend/tsconfig.json +2 -1
  13. package/web/frontend/watt.json +2 -2
  14. package/web/backend/dist/plugins/metrics.js +0 -13
  15. package/web/backend/dist/plugins/metrics.js.map +0 -1
  16. package/web/backend/dist/plugins/websocket.js +0 -11
  17. package/web/backend/dist/plugins/websocket.js.map +0 -1
  18. package/web/backend/dist/routes/metrics.js +0 -45
  19. package/web/backend/dist/routes/metrics.js.map +0 -1
  20. package/web/backend/dist/routes/proxy.js +0 -34
  21. package/web/backend/dist/routes/proxy.js.map +0 -1
  22. package/web/backend/dist/routes/root.js +0 -174
  23. package/web/backend/dist/routes/root.js.map +0 -1
  24. package/web/backend/dist/routes/ws.js +0 -38
  25. package/web/backend/dist/routes/ws.js.map +0 -1
  26. package/web/backend/dist/schemas/index.js +0 -184
  27. package/web/backend/dist/schemas/index.js.map +0 -1
  28. package/web/backend/dist/utils/bytes.js +0 -6
  29. package/web/backend/dist/utils/bytes.js.map +0 -1
  30. package/web/backend/dist/utils/calc.js +0 -248
  31. package/web/backend/dist/utils/calc.js.map +0 -1
  32. package/web/backend/dist/utils/client.openapi.js +0 -31
  33. package/web/backend/dist/utils/client.openapi.js.map +0 -1
  34. package/web/backend/dist/utils/log.js +0 -29
  35. package/web/backend/dist/utils/log.js.map +0 -1
  36. package/web/backend/dist/utils/metrics-helpers.js +0 -72
  37. package/web/backend/dist/utils/metrics-helpers.js.map +0 -1
  38. package/web/backend/dist/utils/metrics.js +0 -183
  39. package/web/backend/dist/utils/metrics.js.map +0 -1
  40. package/web/backend/dist/utils/rps.js +0 -6
  41. package/web/backend/dist/utils/rps.js.map +0 -1
  42. package/web/backend/openapi.json +0 -1119
  43. package/web/frontend/dist/assets/Collection.vue-3bb6N9VS.js +0 -2
  44. package/web/frontend/dist/assets/Collection.vue-3bb6N9VS.js.map +0 -1
  45. package/web/frontend/dist/assets/CollectionAuthentication.vue-BUiBAnw8.js +0 -2
  46. package/web/frontend/dist/assets/CollectionAuthentication.vue-BUiBAnw8.js.map +0 -1
  47. package/web/frontend/dist/assets/CollectionCookies.vue-VpQ7oUfB.js +0 -2
  48. package/web/frontend/dist/assets/CollectionCookies.vue-VpQ7oUfB.js.map +0 -1
  49. package/web/frontend/dist/assets/CollectionEnvironment.vue-B9aL6C1f.js +0 -2
  50. package/web/frontend/dist/assets/CollectionEnvironment.vue-B9aL6C1f.js.map +0 -1
  51. package/web/frontend/dist/assets/CollectionOverview.vue-Gs4h2k55.js +0 -2
  52. package/web/frontend/dist/assets/CollectionOverview.vue-Gs4h2k55.js.map +0 -1
  53. package/web/frontend/dist/assets/CollectionScripts.vue-DI73bgJP.js +0 -2
  54. package/web/frontend/dist/assets/CollectionScripts.vue-DI73bgJP.js.map +0 -1
  55. package/web/frontend/dist/assets/CollectionServers.vue-CTh_DkWz.js +0 -2
  56. package/web/frontend/dist/assets/CollectionServers.vue-CTh_DkWz.js.map +0 -1
  57. package/web/frontend/dist/assets/CollectionSettings.vue--aJQ9wMq.js +0 -2
  58. package/web/frontend/dist/assets/CollectionSettings.vue--aJQ9wMq.js.map +0 -1
  59. package/web/frontend/dist/assets/CollectionSync.vue-CwmTdwlV.js +0 -2
  60. package/web/frontend/dist/assets/CollectionSync.vue-CwmTdwlV.js.map +0 -1
  61. package/web/frontend/dist/assets/CommandActionInput.vue-TK77rD5U.js +0 -2
  62. package/web/frontend/dist/assets/CommandActionInput.vue-TK77rD5U.js.map +0 -1
  63. package/web/frontend/dist/assets/Cookies.vue-C3PhNsCO.js +0 -2
  64. package/web/frontend/dist/assets/Cookies.vue-C3PhNsCO.js.map +0 -1
  65. package/web/frontend/dist/assets/DataTableHeader.vue-DbIRXelw.js +0 -2
  66. package/web/frontend/dist/assets/DataTableHeader.vue-DbIRXelw.js.map +0 -1
  67. package/web/frontend/dist/assets/DeleteSidebarListElement.vue-B9hc23j9.js +0 -2
  68. package/web/frontend/dist/assets/DeleteSidebarListElement.vue-B9hc23j9.js.map +0 -1
  69. package/web/frontend/dist/assets/Draggable.vue-CgQ5Rr6l.js +0 -2
  70. package/web/frontend/dist/assets/Draggable.vue-CgQ5Rr6l.js.map +0 -1
  71. package/web/frontend/dist/assets/EditSidebarListElement.vue-fx233eKQ.js +0 -2
  72. package/web/frontend/dist/assets/EditSidebarListElement.vue-fx233eKQ.js.map +0 -1
  73. package/web/frontend/dist/assets/EmptyState.vue-CCWl6cFt.js +0 -23
  74. package/web/frontend/dist/assets/EmptyState.vue-CCWl6cFt.js.map +0 -1
  75. package/web/frontend/dist/assets/Environment.vue-BAgAaWzP.js +0 -2
  76. package/web/frontend/dist/assets/Environment.vue-BAgAaWzP.js.map +0 -1
  77. package/web/frontend/dist/assets/EnvironmentModal.vue-CoGQ0HVI.js +0 -2
  78. package/web/frontend/dist/assets/EnvironmentModal.vue-CoGQ0HVI.js.map +0 -1
  79. package/web/frontend/dist/assets/Form.vue-CPOtQXvw.js +0 -2
  80. package/web/frontend/dist/assets/Form.vue-CPOtQXvw.js.map +0 -1
  81. package/web/frontend/dist/assets/IconSelector.vue-s7y-7Ty-.js +0 -2
  82. package/web/frontend/dist/assets/IconSelector.vue-s7y-7Ty-.js.map +0 -1
  83. package/web/frontend/dist/assets/LibraryIcon.vue-CrkyDYXJ.js +0 -2
  84. package/web/frontend/dist/assets/LibraryIcon.vue-CrkyDYXJ.js.map +0 -1
  85. package/web/frontend/dist/assets/Request.vue-Cd99DAq4.js +0 -33
  86. package/web/frontend/dist/assets/Request.vue-Cd99DAq4.js.map +0 -1
  87. package/web/frontend/dist/assets/RequestRoot.vue-BVpdY64H.js +0 -20
  88. package/web/frontend/dist/assets/RequestRoot.vue-BVpdY64H.js.map +0 -1
  89. package/web/frontend/dist/assets/ScalarAsciiArt.vue-Bm66XRod.js +0 -3
  90. package/web/frontend/dist/assets/ScalarAsciiArt.vue-Bm66XRod.js.map +0 -1
  91. package/web/frontend/dist/assets/ScalarHotkey.vue-DGRaosjl.js +0 -2
  92. package/web/frontend/dist/assets/ScalarHotkey.vue-DGRaosjl.js.map +0 -1
  93. package/web/frontend/dist/assets/ScalarIconTrash.vue-BzkMDpLH.js +0 -2
  94. package/web/frontend/dist/assets/ScalarIconTrash.vue-BzkMDpLH.js.map +0 -1
  95. package/web/frontend/dist/assets/ScalarPopover.vue-DvIo_Yzb.js +0 -2
  96. package/web/frontend/dist/assets/ScalarPopover.vue-DvIo_Yzb.js.map +0 -1
  97. package/web/frontend/dist/assets/ScalarToggle.vue-C4n7WrpG.js +0 -2
  98. package/web/frontend/dist/assets/ScalarToggle.vue-C4n7WrpG.js.map +0 -1
  99. package/web/frontend/dist/assets/Settings.vue-vE6bOazq.js +0 -2
  100. package/web/frontend/dist/assets/Settings.vue-vE6bOazq.js.map +0 -1
  101. package/web/frontend/dist/assets/SidebarButton.vue-DAR-mVH7.js +0 -2
  102. package/web/frontend/dist/assets/SidebarButton.vue-DAR-mVH7.js.map +0 -1
  103. package/web/frontend/dist/assets/SidebarListElement.vue-CnWyRVB0.js +0 -2
  104. package/web/frontend/dist/assets/SidebarListElement.vue-CnWyRVB0.js.map +0 -1
  105. package/web/frontend/dist/assets/ViewLayout.vue-CEr_C1hG.js +0 -2
  106. package/web/frontend/dist/assets/ViewLayout.vue-CEr_C1hG.js.map +0 -1
  107. package/web/frontend/dist/assets/ViewLayoutContent.vue-t9k9noSS.js +0 -2
  108. package/web/frontend/dist/assets/ViewLayoutContent.vue-t9k9noSS.js.map +0 -1
  109. package/web/frontend/dist/assets/ViewLayoutSection.vue-BYrAaBmf.js +0 -2
  110. package/web/frontend/dist/assets/ViewLayoutSection.vue-BYrAaBmf.js.map +0 -1
  111. package/web/frontend/dist/assets/index-DN39RFTG.js +0 -2327
  112. package/web/frontend/dist/assets/index-DN39RFTG.js.map +0 -1
  113. package/web/frontend/dist/assets/index-DrvlsJch.css +0 -1
  114. package/web/frontend/dist/assets/mediaTypes-DEhrbNXe.js +0 -2
  115. package/web/frontend/dist/assets/mediaTypes-DEhrbNXe.js.map +0 -1
  116. package/web/frontend/postcss.config.cjs +0 -11
package/README.md CHANGED
@@ -14,6 +14,8 @@ After installing the project dependencies, you can run the tool directly:
14
14
 
15
15
  To run the CLI on a custom port, you can just pass it as an argument with `./cli.js --port 4321`.
16
16
 
17
+ To record a flamegraph session, and choose to profile either the `cpu` or the `heap`, you can run the CLI with `./cli.js --record --profile heap`. Once you will stop the process, an HTML one-file bundle will be auto-generated, and you will be able to navigate (even offline) the `watt-admin` app, looking at the flamegraph and at the metrics stored for the whole time you have run the CLI.
18
+
17
19
  The tool is also available as a binary when installed globally or linked:
18
20
 
19
21
  ```bash
package/cli.js CHANGED
@@ -2,9 +2,10 @@
2
2
 
3
3
  'use strict'
4
4
 
5
- const { RuntimeApiClient } = require('@platformatic/control')
6
- const { select } = require('@inquirer/prompts')
7
- const { start } = require('./lib/start')
5
+ import esmain from 'es-main'
6
+ import { RuntimeApiClient } from '@platformatic/control'
7
+ import { select } from '@inquirer/prompts'
8
+ import { start } from './lib/start.js'
8
9
 
9
10
  async function getLocationDetails (client, runtime) {
10
11
  try {
@@ -39,99 +40,95 @@ async function getLocationDetails (client, runtime) {
39
40
  }
40
41
  }
41
42
 
42
- async function main () {
43
+ let client
44
+ export default async function main () {
43
45
  try {
44
46
  // Get available runtimes
45
- const client = new RuntimeApiClient()
46
-
47
- try {
48
- const runtimes = await client.getRuntimes()
49
-
50
- if (runtimes.length === 0) {
51
- console.log('No runtimes available. Please start a Platformatic runtime first.')
52
- return null
53
- } else if (runtimes.length === 1) {
54
- // Only one runtime, no need to prompt
55
- const runtime = runtimes[0]
56
- const locationDetails = await getLocationDetails(client, runtime)
57
- // Display information about the runtime
58
- console.log(`Name: ${runtime.packageName || 'unnamed'}`)
59
- console.log(`PID: ${runtime.pid}`)
60
- console.log(`Working directory: ${locationDetails.cwd}`)
61
-
62
- if (locationDetails.configPath !== 'Unknown' &&
63
- locationDetails.configPath !== 'Unknown (config not available)') {
64
- console.log(`Configuration path: ${locationDetails.configPath}`)
65
- }
47
+ client = new RuntimeApiClient()
48
+
49
+ const runtimes = await client.getRuntimes()
50
+
51
+ if (runtimes.length === 0) {
52
+ console.log('No runtimes available. Please start a Platformatic runtime first.')
53
+ return null
54
+ } else if (runtimes.length === 1) {
55
+ // Only one runtime, no need to prompt
56
+ const runtime = runtimes[0]
57
+ const locationDetails = await getLocationDetails(client, runtime)
58
+ // Display information about the runtime
59
+ console.log(`Name: ${runtime.packageName || 'unnamed'}`)
60
+ console.log(`PID: ${runtime.pid}`)
61
+ console.log(`Working directory: ${locationDetails.cwd}`)
62
+
63
+ if (locationDetails.configPath !== 'Unknown' &&
64
+ locationDetails.configPath !== 'Unknown (config not available)') {
65
+ console.log(`Configuration path: ${locationDetails.configPath}`)
66
+ }
66
67
 
67
- // If we have any command line arguments, display them
68
- if (runtime.argv && runtime.argv.length > 0) {
69
- console.log(`Command: ${runtime.argv.join(' ')}`)
70
- }
68
+ // If we have any command line arguments, display them
69
+ if (runtime.argv && runtime.argv.length > 0) {
70
+ console.log(`Command: ${runtime.argv.join(' ')}`)
71
+ }
72
+
73
+ // If we have a start time, display it
74
+ if (runtime.startTime) {
75
+ console.log(`Started at: ${new Date(runtime.startTime).toLocaleString()}`)
76
+ }
77
+ return runtime
78
+ } else {
79
+ // Multiple runtimes, prompt user to select one
80
+
81
+ // Prepare the runtime choices with async map
82
+ const choicesPromises = runtimes.map(async (runtime) => {
83
+ // Create a concise description that helps identify this runtime
84
+ const description = []
71
85
 
72
- // If we have a start time, display it
86
+ // Show working directory as it's usually the most useful identifier
87
+ description.push(`Dir: ${runtime.cwd || 'Unknown'}`)
88
+
89
+ // Add the start time if available
73
90
  if (runtime.startTime) {
74
- console.log(`Started at: ${new Date(runtime.startTime).toLocaleString()}`)
75
- }
76
- return runtime
77
- } else {
78
- // Multiple runtimes, prompt user to select one
79
-
80
- // Prepare the runtime choices with async map
81
- const choicesPromises = runtimes.map(async runtime => {
82
- // Create a concise description that helps identify this runtime
83
- const description = []
84
-
85
- // Show working directory as it's usually the most useful identifier
86
- description.push(`Dir: ${runtime.cwd || 'Unknown'}`)
87
-
88
- // Add the start time if available
89
- if (runtime.startTime) {
90
- description.push(`Started: ${new Date(runtime.startTime).toLocaleString()}`)
91
- }
92
-
93
- return {
94
- name: `${runtime.packageName || 'unnamed'} (PID: ${runtime.pid})`,
95
- value: runtime,
96
- description: description.join(', ')
97
- }
98
- })
99
-
100
- // Wait for all async operations to complete
101
- const choices = await Promise.all(choicesPromises)
102
-
103
- // Prompt the user to select a runtime
104
- const selectedRuntime = await select({
105
- message: 'Select a runtime:',
106
- choices
107
- })
108
-
109
- const locationDetails = await getLocationDetails(client, selectedRuntime)
110
- // Display information about the selected runtime
111
- console.log('\nRuntime Details:')
112
- console.log(`Name: ${selectedRuntime.packageName || 'unnamed'}`)
113
- console.log(`PID: ${selectedRuntime.pid}`)
114
- console.log(`Working directory: ${locationDetails.cwd}`)
115
-
116
- if (locationDetails.configPath !== 'Unknown' &&
117
- locationDetails.configPath !== 'Unknown (config not available)') {
118
- console.log(`Configuration path: ${locationDetails.configPath}`)
91
+ description.push(`Started: ${new Date(runtime.startTime).toLocaleString()}`)
119
92
  }
120
93
 
121
- // If we have any command line arguments, display them
122
- if (selectedRuntime.argv && selectedRuntime.argv.length > 0) {
123
- console.log(`Command: ${selectedRuntime.argv.join(' ')}`)
94
+ return {
95
+ name: `${runtime.packageName || 'unnamed'} (PID: ${runtime.pid})`,
96
+ value: runtime,
97
+ description: description.join(', ')
124
98
  }
99
+ })
100
+
101
+ // Wait for all async operations to complete
102
+ const choices = await Promise.all(choicesPromises)
103
+
104
+ // Prompt the user to select a runtime
105
+ const selectedRuntime = await select({
106
+ message: 'Select a runtime:',
107
+ choices
108
+ })
109
+
110
+ const locationDetails = await getLocationDetails(client, selectedRuntime)
111
+ // Display information about the selected runtime
112
+ console.log('\nRuntime Details:')
113
+ console.log(`Name: ${selectedRuntime.packageName || 'unnamed'}`)
114
+ console.log(`PID: ${selectedRuntime.pid}`)
115
+ console.log(`Working directory: ${locationDetails.cwd}`)
116
+
117
+ if (locationDetails.configPath !== 'Unknown' &&
118
+ locationDetails.configPath !== 'Unknown (config not available)') {
119
+ console.log(`Configuration path: ${locationDetails.configPath}`)
120
+ }
125
121
 
126
- // If we have a start time, display it
127
- if (selectedRuntime.startTime) {
128
- console.log(`Started at: ${new Date(selectedRuntime.startTime).toLocaleString()}`)
129
- }
130
- return selectedRuntime
122
+ // If we have any command line arguments, display them
123
+ if (selectedRuntime.argv && selectedRuntime.argv.length > 0) {
124
+ console.log(`Command: ${selectedRuntime.argv.join(' ')}`)
125
+ }
126
+
127
+ // If we have a start time, display it
128
+ if (selectedRuntime.startTime) {
129
+ console.log(`Started at: ${new Date(selectedRuntime.startTime).toLocaleString()}`)
131
130
  }
132
- } finally {
133
- // Always clean up the client
134
- await client.close()
131
+ return selectedRuntime
135
132
  }
136
133
  } catch (error) {
137
134
  console.error('Error:', error.message)
@@ -140,19 +137,16 @@ async function main () {
140
137
  }
141
138
 
142
139
  // Execute the main function if this script is run directly
143
- if (require.main === module) {
140
+ if (esmain(import.meta)) {
144
141
  main().then((selectedRuntime) => {
145
142
  if (!selectedRuntime) {
146
143
  return
147
144
  }
148
145
  console.log('Starting Watt admin...')
149
146
  console.log('--------')
150
- return start(selectedRuntime.pid)
147
+ return start(client, selectedRuntime.pid)
151
148
  }).catch(error => {
152
149
  console.error('Fatal error:', error)
153
150
  process.exit(1)
154
151
  })
155
- } else {
156
- // Export for use as a module
157
- module.exports = main
158
152
  }
package/lib/start.js CHANGED
@@ -1,20 +1,80 @@
1
1
  'use strict'
2
2
 
3
- const { buildRuntime, loadConfig } = require('@platformatic/runtime')
4
- const { join } = require('path')
5
- const { parseArgs } = require('util')
3
+ import { create } from '@platformatic/runtime'
4
+ import { join } from 'path'
5
+ import { parseArgs, promisify } from 'util'
6
+ import { request } from 'undici'
7
+ import { exec } from 'child_process'
8
+ import closeWithGrace from 'close-with-grace'
6
9
 
7
- async function start (selectedRuntime) {
10
+ const __dirname = import.meta.dirname
11
+
12
+ const execAsync = promisify(exec)
13
+
14
+ const msOneMinute = 1000 * 60
15
+ let recordTimeout
16
+ let entrypointUrl
17
+
18
+ export async function start (client, selectedRuntime) {
8
19
  process.env.SELECTED_RUNTIME = selectedRuntime
9
- const { values: { port } } = parseArgs({ options: { port: { type: 'string' } } })
20
+ const { values: { port, record, profile } } = parseArgs({
21
+ options: {
22
+ port: { type: 'string' },
23
+ profile: { type: 'string' },
24
+ record: { type: 'boolean' },
25
+ }
26
+ })
27
+
10
28
  process.env.PORT = port || 4042
11
29
 
30
+ const requestRecord = async (mode) => {
31
+ return await request(`${entrypointUrl}/api/record/${selectedRuntime}`, {
32
+ method: 'POST',
33
+ headers: { 'Content-Type': 'application/json' },
34
+ body: JSON.stringify({ mode, profile: profile ?? 'cpu' })
35
+ })
36
+ }
37
+
38
+ const recordMetrics = async () => {
39
+ try {
40
+ const { statusCode, body } = await requestRecord('stop')
41
+ if (statusCode === 200) {
42
+ await body.dump()
43
+ const bundlePath = join(__dirname, '..', 'web', 'frontend', 'dist', 'index.html')
44
+ await execAsync(`${process.platform === 'win32' ? 'start' : 'open'} ${bundlePath}`)
45
+ } else {
46
+ console.error(`Failure triggering the stop command: ${await body.text()}`)
47
+ }
48
+ } catch (error) {
49
+ console.error('Error on record metrics', { error, entrypointUrl })
50
+ clearTimeout(recordTimeout)
51
+ }
52
+ }
53
+
12
54
  const configFile = join(__dirname, '..', 'watt.json')
13
- const { configManager, args } = await loadConfig({
14
- }, ['--production', '--config', configFile], { production: true, disableEnvLoad: true })
15
- configManager.args = args
16
- const server = await buildRuntime(configManager)
17
- await server.start()
18
- }
55
+ const server = await create(configFile)
56
+ entrypointUrl = await server.start()
57
+
58
+ if (record) {
59
+ closeWithGrace({ delay: msOneMinute }, async ({ signal }) => {
60
+ if (signal === 'SIGINT') {
61
+ clearTimeout(recordTimeout)
62
+ await recordMetrics(entrypointUrl)
63
+ }
64
+
65
+ // Always clean up the client
66
+ await client.close()
67
+ })
19
68
 
20
- module.exports.start = start
69
+ const { statusCode, body } = await requestRecord('start')
70
+ if (statusCode === 200) {
71
+ await body.dump()
72
+
73
+ recordTimeout = setTimeout(async () => {
74
+ await recordMetrics(entrypointUrl)
75
+ }, msOneMinute * 10)
76
+ } else {
77
+ console.log(`Failure triggering the start command: ${await body.text()}`)
78
+ }
79
+ }
80
+ }
package/package.json CHANGED
@@ -1,69 +1,74 @@
1
1
  {
2
+ "type": "module",
2
3
  "name": "@platformatic/watt-admin",
3
- "version": "0.5.0",
4
+ "version": "0.6.0-alpha.2",
4
5
  "scripts": {
5
- "prepublishOnly": "npm run build",
6
+ "prepublishOnly": "npm run clean && npm run build",
6
7
  "dev": "wattpm dev",
7
8
  "build": "wattpm build",
8
9
  "start": "wattpm start",
10
+ "typecheck": "cd web/backend && tsc && cd ../frontend && tsc",
9
11
  "client:openapi": "cd web/backend && node --experimental-strip-types utils/client.openapi.ts",
10
- "client:generate": "./node_modules/.bin/plt-client ./web/backend/openapi.json --name backend --folder web/frontend/src/client --language ts --frontend --full --skip-config-update --props-optional",
12
+ "client:generate": "./node_modules/.bin/massimo ./web/backend/openapi.json --name backend --folder web/frontend/src/client --language ts --frontend --full --skip-config-update --props-optional",
11
13
  "test": "npm run test:cli && npm run test:e2e && npm run test:backend && npm run test:frontend",
12
- "test:cli": "node --test test/cli.test.js test/start.test.js test/cli-integration.test.js",
13
- "test:backend": "cd web/backend && borp --concurrency 1",
14
+ "test:cli": "node --test --experimental-test-module-mocks --test-timeout 60000 test/*.test.ts",
15
+ "test:backend": "node --test --experimental-test-module-mocks --test-timeout 60000 --test-concurrency 1 web/backend/**/*.test.ts",
14
16
  "test:frontend": "cd web/frontend && vitest run",
15
17
  "pretest:e2e": "./node_modules/.bin/playwright install chromium",
16
18
  "test:e2e": "cd web/frontend && playwright test",
17
19
  "test:e2e:ui": "npm run test:e2e -- --ui",
18
- "clean": "rm -rf ./web/*/dist",
20
+ "clean": "rm -rf ./web/*/dist ./playwright-report ./test-results",
19
21
  "lint": "eslint .",
20
22
  "lint:fix": "eslint . --fix"
21
23
  },
22
24
  "dependencies": {
23
- "@fastify/websocket": "^11.1.0",
24
- "@inquirer/prompts": "^7.3.3",
25
- "@platformatic/composer": "^2.72.0",
26
- "@platformatic/control": "^2.72.0",
27
- "@platformatic/runtime": "^2.72.0",
28
- "@platformatic/service": "^2.72.0",
29
- "@platformatic/vite": "^2.72.0",
30
- "@scalar/api-reference-react": "^0.7.13",
31
- "fastify": "^5.0.0",
32
- "proxyquire": "^2.1.3",
25
+ "@fastify/websocket": "^11.2.0",
26
+ "@inquirer/prompts": "^7.8.6",
27
+ "@platformatic/control": "^3.11.0",
28
+ "@platformatic/gateway": "^3.11.0",
29
+ "@platformatic/runtime": "^3.11.0",
30
+ "@platformatic/service": "^3.11.0",
31
+ "@platformatic/ui-components": "^0.19.1",
32
+ "@platformatic/vite": "^3.11.0",
33
+ "@platformatic/wattpm-pprof-capture": "^3.13.0",
34
+ "@scalar/api-reference-react": "^0.7.55",
35
+ "@vitejs/plugin-react": "^5.0.4",
36
+ "autoprefixer": "^10.4.21",
37
+ "close-with-grace": "^2.3.0",
38
+ "d3": "^7.9.0",
39
+ "dayjs": "^1.11.18",
40
+ "es-main": "^1.4.0",
41
+ "fastify": "^5.6.1",
42
+ "pprof-format": "^2.2.1",
43
+ "react": "^19.2.0",
44
+ "react-dom": "^19.2.0",
45
+ "react-pprof": "^1.1.0",
46
+ "react-router-dom": "^7.9.3",
33
47
  "react-use-websocket": "^4.13.0",
34
- "split2": "4.2.0",
35
- "wattpm": "^2.72.0"
48
+ "split2": "^4.2.0",
49
+ "tailwindcss": "^3.4.18",
50
+ "undici": "^7.16.0",
51
+ "use-error-boundary": "^2.0.6",
52
+ "vite": "^7.1.9",
53
+ "vite-plugin-singlefile": "^2.3.0",
54
+ "wattpm": "^3.11.0",
55
+ "zustand": "^5.0.8"
36
56
  },
37
57
  "devDependencies": {
38
58
  "@fastify/type-provider-json-schema-to-ts": "^5.0.0",
39
- "@inquirer/testing": "^2.1.45",
40
- "@platformatic/client-cli": "^2.58.0",
41
- "@platformatic/ui-components": "^0.15.2",
42
- "@playwright/test": "^1.52.0",
59
+ "@playwright/test": "^1.56.0",
43
60
  "@types/d3": "^7.4.3",
44
- "@types/proxyquire": "1.3.31",
45
- "@types/react-dom": "^19.0.4",
46
- "@types/split2": "4.2.3",
61
+ "@types/node": "^22",
62
+ "@types/react-dom": "^19.2.1",
63
+ "@types/split2": "^4.2.3",
47
64
  "@types/ws": "^8.18.1",
48
- "@vitejs/plugin-react": "^4.3.3",
49
- "autoprefixer": "^10.4.20",
50
- "borp": "^0.19.0",
51
- "d3": "~7.9.0",
52
- "dayjs": "^1.11.13",
53
- "eslint": "^9.22.0",
54
- "fastify-tsconfig": "^2.0.0",
55
- "neostandard": "^0.12.1",
56
- "playwright": "^1.52.0",
57
- "react": "^19.0.0",
58
- "react-dom": "^19.0.0",
59
- "react-router-dom": "^7.0.0",
60
- "source-map-support": "^0.5.21",
61
- "tailwindcss": "^3.4.15",
62
- "typescript": "^5.5.4",
63
- "use-error-boundary": "^2.0.6",
64
- "vite": "^5.4.11",
65
- "vitest": "^3.0.8",
66
- "zustand": "^5.0.2"
65
+ "eslint": "^9.37.0",
66
+ "fastify-tsconfig": "^3.0.0",
67
+ "massimo-cli": "^1.0.1",
68
+ "neostandard": "^0.12.2",
69
+ "playwright": "^1.56.0",
70
+ "typescript": "^5.9.3",
71
+ "vitest": "^3.2.4"
67
72
  },
68
73
  "bin": {
69
74
  "watt-admin": "./cli.js"
package/tsconfig.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "extends": "fastify-tsconfig",
3
+ "compilerOptions": {
4
+ "sourceMap": true,
5
+ "pretty": true,
6
+ "noEmitOnError": true,
7
+ "incremental": true,
8
+ "outDir": "dist",
9
+ "noUnusedParameters": true,
10
+ "verbatimModuleSyntax": true
11
+ },
12
+ "watchOptions": {
13
+ "watchFile": "fixedPollingInterval",
14
+ "watchDirectory": "fixedPollingInterval",
15
+ "fallbackPolling": "dynamicPriority",
16
+ "synchronousWatchDirectory": true,
17
+ "excludeDirectories": [
18
+ "**/node_modules",
19
+ "dist"
20
+ ]
21
+ }
22
+ }
package/watt.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://schemas.platformatic.dev/wattpm/2.72.0.json",
2
+ "$schema": "https://schemas.platformatic.dev/wattpm/3.11.0.json",
3
3
  "server": {
4
4
  "hostname": "127.0.0.1",
5
5
  "port": "{PORT}"
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://schemas.platformatic.dev/@platformatic/service/2.72.0.json",
2
+ "$schema": "https://schemas.platformatic.dev/@platformatic/service/3.11.0.json",
3
3
  "service": {
4
4
  "openapi": true
5
5
  },
@@ -11,7 +11,6 @@
11
11
  "encapsulate": false
12
12
  },
13
13
  "./routes"
14
- ],
15
- "typescript": "{PLT_BACKEND_TYPESCRIPT}"
14
+ ]
16
15
  }
17
16
  }
@@ -3,10 +3,13 @@
3
3
  "compilerOptions": {
4
4
  "sourceMap": true,
5
5
  "pretty": true,
6
+ "noEmit": true,
7
+ "allowImportingTsExtensions": true,
6
8
  "noEmitOnError": true,
7
9
  "incremental": true,
8
10
  "outDir": "dist",
9
- "noUnusedParameters": true
11
+ "noUnusedParameters": true,
12
+ "verbatimModuleSyntax": true
10
13
  },
11
14
  "watchOptions": {
12
15
  "watchFile": "fixedPollingInterval",
@@ -1,7 +1,7 @@
1
1
  {
2
- "$schema": "https://schemas.platformatic.dev/@platformatic/composer/2.72.0.json",
3
- "composer": {
4
- "services": [
2
+ "$schema": "https://schemas.platformatic.dev/@platformatic/gateway/3.11.0.json",
3
+ "gateway": {
4
+ "applications": [
5
5
  {
6
6
  "id": "backend",
7
7
  "openapi": {