wattpm 3.41.0 → 3.42.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/README.md CHANGED
@@ -19,18 +19,19 @@ Watt supports the stacks you love most, including [Next.js](https://nextjs.org/)
19
19
 
20
20
  ```bash
21
21
  # Create a new application
22
- npx wattpm@latest init
22
+ npx wattpm@latest create
23
23
 
24
24
  # Or install manually:
25
25
  npm install wattpm
26
26
  ```
27
27
 
28
28
  Follow our [Quick Start Guide](https://docs.platformatic.dev/docs/getting-started/quick-start)
29
- guide to get up and running with Platformatic.
29
+ to get up and running with Watt.
30
30
 
31
31
  ## Documentation
32
32
 
33
- - [Getting Started](https://docs.platformatic.dev/docs/getting-started/quick-start)
33
+ - [Quick Start](https://docs.platformatic.dev/docs/getting-started/quick-start)
34
+ - [Running Your Project in Watt](https://docs.platformatic.dev/docs/getting-started/port-your-app)
34
35
  - [Reference](https://docs.platformatic.dev/docs/reference/wattpm/overview)
35
36
  - [Guides](https://docs.platformatic.dev/docs/guides/build-modular-monolith)
36
37
 
package/index.js CHANGED
@@ -14,6 +14,7 @@ import { applicationsCommand, configCommand, envCommand, psCommand } from './lib
14
14
  import { metricsCommand } from './lib/commands/metrics.js'
15
15
  import { pprofCommand } from './lib/commands/pprof.js'
16
16
  import { replCommand } from './lib/commands/repl.js'
17
+ import { heapSnapshotCommand } from './lib/commands/snapshot.js'
17
18
  import { version } from './lib/schema.js'
18
19
 
19
20
  export * from './lib/schema.js'
@@ -116,6 +117,9 @@ export async function main () {
116
117
  case 'pprof':
117
118
  command = pprofCommand
118
119
  break
120
+ case 'heap-snapshot':
121
+ command = heapSnapshotCommand
122
+ break
119
123
  case 'repl':
120
124
  command = replCommand
121
125
  break
@@ -20,7 +20,8 @@ async function loadCommands () {
20
20
  'inject',
21
21
  'metrics',
22
22
  'pprof',
23
- 'repl'
23
+ 'repl',
24
+ 'snapshot'
24
25
  ]) {
25
26
  const category = await import(`./${file}.js`)
26
27
  Object.assign(commands, category.help)
@@ -0,0 +1,99 @@
1
+ import { RuntimeApiClient, getMatchingRuntime } from '@platformatic/control'
2
+ import { ensureLoggableError, logFatalError, parseArgs } from '@platformatic/foundation'
3
+ import { bold } from 'colorette'
4
+ import { createWriteStream } from 'node:fs'
5
+ import { resolve } from 'node:path'
6
+ import { pipeline } from 'node:stream/promises'
7
+
8
+ export async function heapSnapshotCommand (logger, args) {
9
+ const client = new RuntimeApiClient({ logger, socket: this.socket })
10
+
11
+ try {
12
+ const { positionals, values } = parseArgs(
13
+ args,
14
+ {
15
+ dir: { type: 'string', short: 'd' }
16
+ },
17
+ false
18
+ )
19
+
20
+ const [runtime, remainingPositionals] = await getMatchingRuntime(client, positionals)
21
+ const { applications: runtimeApplications } = await client.getRuntimeApplications(runtime.pid)
22
+
23
+ const applicationId = remainingPositionals[0]
24
+ const timestamp = new Date().toISOString().replace(/:/g, '-').replace(/\./g, '-')
25
+ const outputDir = values.dir || process.cwd()
26
+
27
+ if (applicationId) {
28
+ const application = runtimeApplications.find(s => s.id === applicationId)
29
+ if (!application) {
30
+ return logFatalError(logger, `Application not found: ${applicationId}`)
31
+ }
32
+
33
+ logger.info(`Taking heap snapshot for application ${bold(applicationId)}...`)
34
+ const body = await client.takeApplicationHeapSnapshot(runtime.pid, applicationId)
35
+ const filename = `heap-${applicationId}-${timestamp}.heapsnapshot`
36
+ const filepath = resolve(outputDir, filename)
37
+ await pipeline(body, createWriteStream(filepath))
38
+ logger.info(`Heap snapshot saved to ${bold(filepath)}`)
39
+ } else {
40
+ for (const application of runtimeApplications) {
41
+ try {
42
+ logger.info(`Taking heap snapshot for application ${bold(application.id)}...`)
43
+ const body = await client.takeApplicationHeapSnapshot(runtime.pid, application.id)
44
+ const filename = `heap-${application.id}-${timestamp}.heapsnapshot`
45
+ const filepath = resolve(outputDir, filename)
46
+ await pipeline(body, createWriteStream(filepath))
47
+ logger.info(`Heap snapshot saved to ${bold(filepath)}`)
48
+ } catch (error) {
49
+ logger.warn(`Failed to take heap snapshot for application ${application.id}: ${error.message}`)
50
+ }
51
+ }
52
+ }
53
+ } catch (error) {
54
+ if (error.code === 'PLT_CTR_RUNTIME_NOT_FOUND') {
55
+ return logFatalError(logger, 'Cannot find a matching runtime.')
56
+ } else if (error.message && error.message.includes('Application not found')) {
57
+ return logFatalError(logger, error.message)
58
+ } else {
59
+ return logFatalError(
60
+ logger,
61
+ { error: ensureLoggableError(error) },
62
+ `Cannot take heap snapshot: ${error.message}`
63
+ )
64
+ }
65
+ } finally {
66
+ await client.close()
67
+ }
68
+ }
69
+
70
+ export const help = {
71
+ 'heap-snapshot': {
72
+ usage: 'heap-snapshot [id] [application] [options]',
73
+ description: 'Take a heap snapshot of a running application',
74
+ options: [
75
+ {
76
+ name: '--dir, -d',
77
+ description: 'Directory to save the heap snapshot to (default: current working directory)'
78
+ }
79
+ ],
80
+ args: [
81
+ {
82
+ name: 'id',
83
+ description:
84
+ 'The process ID or the name of the application (it can be omitted only if there is a single application running)'
85
+ },
86
+ {
87
+ name: 'application',
88
+ description: 'The application ID to snapshot (if omitted, snapshots all applications)'
89
+ }
90
+ ],
91
+ footer:
92
+ 'Takes a V8 heap snapshot of a running application and saves it as a .heapsnapshot file.\n' +
93
+ 'The resulting file can be loaded in Chrome DevTools (Memory tab) for analysis.\n\n' +
94
+ 'Examples:\n' +
95
+ ' wattpm heap-snapshot my-app # Take heap snapshot of my-app\n' +
96
+ ' wattpm heap-snapshot --dir=/tmp/snapshots my-app # Save to specific directory\n' +
97
+ ' wattpm heap-snapshot # Snapshot all applications'
98
+ }
99
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wattpm",
3
- "version": "3.41.0",
3
+ "version": "3.42.0",
4
4
  "description": "The Node.js Application Server",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -30,9 +30,9 @@
30
30
  "pino-pretty": "^13.0.0",
31
31
  "split2": "^4.2.0",
32
32
  "table": "^6.8.2",
33
- "@platformatic/foundation": "3.41.0",
34
- "@platformatic/runtime": "3.41.0",
35
- "@platformatic/control": "3.41.0"
33
+ "@platformatic/control": "3.42.0",
34
+ "@platformatic/foundation": "3.42.0",
35
+ "@platformatic/runtime": "3.42.0"
36
36
  },
37
37
  "devDependencies": {
38
38
  "cleaner-spec-reporter": "^0.5.0",
@@ -44,7 +44,7 @@
44
44
  "neostandard": "^0.12.0",
45
45
  "typescript": "^5.5.4",
46
46
  "undici": "^7.0.0",
47
- "@platformatic/node": "3.41.0"
47
+ "@platformatic/node": "3.42.0"
48
48
  },
49
49
  "engines": {
50
50
  "node": ">=22.19.0"
package/schema.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://schemas.platformatic.dev/wattpm/3.41.0.json",
2
+ "$id": "https://schemas.platformatic.dev/wattpm/3.42.0.json",
3
3
  "$schema": "http://json-schema.org/draft-07/schema#",
4
4
  "title": "Platformatic Runtime Config",
5
5
  "type": "object",