@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.
- package/README.md +2 -0
- package/cli.js +85 -91
- package/lib/start.js +72 -12
- package/package.json +49 -44
- package/tsconfig.json +22 -0
- package/watt.json +1 -1
- package/web/backend/platformatic.json +2 -3
- package/web/backend/tsconfig.json +4 -1
- package/web/composer/platformatic.json +3 -3
- package/web/frontend/dist/index.html +2977 -6
- package/web/frontend/index.html +0 -1
- package/web/frontend/tsconfig.json +2 -1
- package/web/frontend/watt.json +2 -2
- package/web/backend/dist/plugins/metrics.js +0 -13
- package/web/backend/dist/plugins/metrics.js.map +0 -1
- package/web/backend/dist/plugins/websocket.js +0 -11
- package/web/backend/dist/plugins/websocket.js.map +0 -1
- package/web/backend/dist/routes/metrics.js +0 -45
- package/web/backend/dist/routes/metrics.js.map +0 -1
- package/web/backend/dist/routes/proxy.js +0 -34
- package/web/backend/dist/routes/proxy.js.map +0 -1
- package/web/backend/dist/routes/root.js +0 -174
- package/web/backend/dist/routes/root.js.map +0 -1
- package/web/backend/dist/routes/ws.js +0 -38
- package/web/backend/dist/routes/ws.js.map +0 -1
- package/web/backend/dist/schemas/index.js +0 -184
- package/web/backend/dist/schemas/index.js.map +0 -1
- package/web/backend/dist/utils/bytes.js +0 -6
- package/web/backend/dist/utils/bytes.js.map +0 -1
- package/web/backend/dist/utils/calc.js +0 -248
- package/web/backend/dist/utils/calc.js.map +0 -1
- package/web/backend/dist/utils/client.openapi.js +0 -31
- package/web/backend/dist/utils/client.openapi.js.map +0 -1
- package/web/backend/dist/utils/log.js +0 -29
- package/web/backend/dist/utils/log.js.map +0 -1
- package/web/backend/dist/utils/metrics-helpers.js +0 -72
- package/web/backend/dist/utils/metrics-helpers.js.map +0 -1
- package/web/backend/dist/utils/metrics.js +0 -183
- package/web/backend/dist/utils/metrics.js.map +0 -1
- package/web/backend/dist/utils/rps.js +0 -6
- package/web/backend/dist/utils/rps.js.map +0 -1
- package/web/backend/openapi.json +0 -1119
- package/web/frontend/dist/assets/Collection.vue-3bb6N9VS.js +0 -2
- package/web/frontend/dist/assets/Collection.vue-3bb6N9VS.js.map +0 -1
- package/web/frontend/dist/assets/CollectionAuthentication.vue-BUiBAnw8.js +0 -2
- package/web/frontend/dist/assets/CollectionAuthentication.vue-BUiBAnw8.js.map +0 -1
- package/web/frontend/dist/assets/CollectionCookies.vue-VpQ7oUfB.js +0 -2
- package/web/frontend/dist/assets/CollectionCookies.vue-VpQ7oUfB.js.map +0 -1
- package/web/frontend/dist/assets/CollectionEnvironment.vue-B9aL6C1f.js +0 -2
- package/web/frontend/dist/assets/CollectionEnvironment.vue-B9aL6C1f.js.map +0 -1
- package/web/frontend/dist/assets/CollectionOverview.vue-Gs4h2k55.js +0 -2
- package/web/frontend/dist/assets/CollectionOverview.vue-Gs4h2k55.js.map +0 -1
- package/web/frontend/dist/assets/CollectionScripts.vue-DI73bgJP.js +0 -2
- package/web/frontend/dist/assets/CollectionScripts.vue-DI73bgJP.js.map +0 -1
- package/web/frontend/dist/assets/CollectionServers.vue-CTh_DkWz.js +0 -2
- package/web/frontend/dist/assets/CollectionServers.vue-CTh_DkWz.js.map +0 -1
- package/web/frontend/dist/assets/CollectionSettings.vue--aJQ9wMq.js +0 -2
- package/web/frontend/dist/assets/CollectionSettings.vue--aJQ9wMq.js.map +0 -1
- package/web/frontend/dist/assets/CollectionSync.vue-CwmTdwlV.js +0 -2
- package/web/frontend/dist/assets/CollectionSync.vue-CwmTdwlV.js.map +0 -1
- package/web/frontend/dist/assets/CommandActionInput.vue-TK77rD5U.js +0 -2
- package/web/frontend/dist/assets/CommandActionInput.vue-TK77rD5U.js.map +0 -1
- package/web/frontend/dist/assets/Cookies.vue-C3PhNsCO.js +0 -2
- package/web/frontend/dist/assets/Cookies.vue-C3PhNsCO.js.map +0 -1
- package/web/frontend/dist/assets/DataTableHeader.vue-DbIRXelw.js +0 -2
- package/web/frontend/dist/assets/DataTableHeader.vue-DbIRXelw.js.map +0 -1
- package/web/frontend/dist/assets/DeleteSidebarListElement.vue-B9hc23j9.js +0 -2
- package/web/frontend/dist/assets/DeleteSidebarListElement.vue-B9hc23j9.js.map +0 -1
- package/web/frontend/dist/assets/Draggable.vue-CgQ5Rr6l.js +0 -2
- package/web/frontend/dist/assets/Draggable.vue-CgQ5Rr6l.js.map +0 -1
- package/web/frontend/dist/assets/EditSidebarListElement.vue-fx233eKQ.js +0 -2
- package/web/frontend/dist/assets/EditSidebarListElement.vue-fx233eKQ.js.map +0 -1
- package/web/frontend/dist/assets/EmptyState.vue-CCWl6cFt.js +0 -23
- package/web/frontend/dist/assets/EmptyState.vue-CCWl6cFt.js.map +0 -1
- package/web/frontend/dist/assets/Environment.vue-BAgAaWzP.js +0 -2
- package/web/frontend/dist/assets/Environment.vue-BAgAaWzP.js.map +0 -1
- package/web/frontend/dist/assets/EnvironmentModal.vue-CoGQ0HVI.js +0 -2
- package/web/frontend/dist/assets/EnvironmentModal.vue-CoGQ0HVI.js.map +0 -1
- package/web/frontend/dist/assets/Form.vue-CPOtQXvw.js +0 -2
- package/web/frontend/dist/assets/Form.vue-CPOtQXvw.js.map +0 -1
- package/web/frontend/dist/assets/IconSelector.vue-s7y-7Ty-.js +0 -2
- package/web/frontend/dist/assets/IconSelector.vue-s7y-7Ty-.js.map +0 -1
- package/web/frontend/dist/assets/LibraryIcon.vue-CrkyDYXJ.js +0 -2
- package/web/frontend/dist/assets/LibraryIcon.vue-CrkyDYXJ.js.map +0 -1
- package/web/frontend/dist/assets/Request.vue-Cd99DAq4.js +0 -33
- package/web/frontend/dist/assets/Request.vue-Cd99DAq4.js.map +0 -1
- package/web/frontend/dist/assets/RequestRoot.vue-BVpdY64H.js +0 -20
- package/web/frontend/dist/assets/RequestRoot.vue-BVpdY64H.js.map +0 -1
- package/web/frontend/dist/assets/ScalarAsciiArt.vue-Bm66XRod.js +0 -3
- package/web/frontend/dist/assets/ScalarAsciiArt.vue-Bm66XRod.js.map +0 -1
- package/web/frontend/dist/assets/ScalarHotkey.vue-DGRaosjl.js +0 -2
- package/web/frontend/dist/assets/ScalarHotkey.vue-DGRaosjl.js.map +0 -1
- package/web/frontend/dist/assets/ScalarIconTrash.vue-BzkMDpLH.js +0 -2
- package/web/frontend/dist/assets/ScalarIconTrash.vue-BzkMDpLH.js.map +0 -1
- package/web/frontend/dist/assets/ScalarPopover.vue-DvIo_Yzb.js +0 -2
- package/web/frontend/dist/assets/ScalarPopover.vue-DvIo_Yzb.js.map +0 -1
- package/web/frontend/dist/assets/ScalarToggle.vue-C4n7WrpG.js +0 -2
- package/web/frontend/dist/assets/ScalarToggle.vue-C4n7WrpG.js.map +0 -1
- package/web/frontend/dist/assets/Settings.vue-vE6bOazq.js +0 -2
- package/web/frontend/dist/assets/Settings.vue-vE6bOazq.js.map +0 -1
- package/web/frontend/dist/assets/SidebarButton.vue-DAR-mVH7.js +0 -2
- package/web/frontend/dist/assets/SidebarButton.vue-DAR-mVH7.js.map +0 -1
- package/web/frontend/dist/assets/SidebarListElement.vue-CnWyRVB0.js +0 -2
- package/web/frontend/dist/assets/SidebarListElement.vue-CnWyRVB0.js.map +0 -1
- package/web/frontend/dist/assets/ViewLayout.vue-CEr_C1hG.js +0 -2
- package/web/frontend/dist/assets/ViewLayout.vue-CEr_C1hG.js.map +0 -1
- package/web/frontend/dist/assets/ViewLayoutContent.vue-t9k9noSS.js +0 -2
- package/web/frontend/dist/assets/ViewLayoutContent.vue-t9k9noSS.js.map +0 -1
- package/web/frontend/dist/assets/ViewLayoutSection.vue-BYrAaBmf.js +0 -2
- package/web/frontend/dist/assets/ViewLayoutSection.vue-BYrAaBmf.js.map +0 -1
- package/web/frontend/dist/assets/index-DN39RFTG.js +0 -2327
- package/web/frontend/dist/assets/index-DN39RFTG.js.map +0 -1
- package/web/frontend/dist/assets/index-DrvlsJch.css +0 -1
- package/web/frontend/dist/assets/mediaTypes-DEhrbNXe.js +0 -2
- package/web/frontend/dist/assets/mediaTypes-DEhrbNXe.js.map +0 -1
- 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
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
43
|
+
let client
|
|
44
|
+
export default async function main () {
|
|
43
45
|
try {
|
|
44
46
|
// Get available runtimes
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
|
|
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({
|
|
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
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
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.
|
|
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/
|
|
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
|
|
13
|
-
"test:backend": "
|
|
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.
|
|
24
|
-
"@inquirer/prompts": "^7.
|
|
25
|
-
"@platformatic/
|
|
26
|
-
"@platformatic/
|
|
27
|
-
"@platformatic/runtime": "^
|
|
28
|
-
"@platformatic/service": "^
|
|
29
|
-
"@platformatic/
|
|
30
|
-
"@
|
|
31
|
-
"
|
|
32
|
-
"
|
|
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
|
-
"
|
|
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
|
-
"@
|
|
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/
|
|
45
|
-
"@types/react-dom": "^19.
|
|
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
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
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/@platformatic/service/
|
|
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/
|
|
3
|
-
"
|
|
4
|
-
"
|
|
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": {
|