wattpm 3.4.1 → 3.5.1
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 +46 -0
- package/bin/cli.js +11 -0
- package/index.js +60 -23
- package/lib/commands/admin.js +40 -0
- package/lib/commands/build.js +72 -30
- package/lib/commands/create.js +139 -0
- package/lib/commands/execution.js +101 -36
- package/lib/commands/help.js +75 -30
- package/lib/commands/inject.js +30 -27
- package/lib/commands/logs.js +18 -18
- package/lib/commands/management.js +60 -50
- package/lib/commands/metrics.js +46 -0
- package/lib/commands/pprof.js +142 -0
- package/package.json +20 -22
- package/schema.json +1383 -55
- package/bin/wattpm.js +0 -9
- package/lib/commands/external.js +0 -439
- package/lib/commands/init.js +0 -98
- package/lib/defaults.js +0 -24
- package/lib/gitignore.js +0 -132
- package/lib/logo.js +0 -36
- package/lib/utils.js +0 -133
package/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
3
|
+
# Watt, the Application Server for Node.js
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/wattpm)
|
|
6
|
+
[](https://github.com/platformatic/platformatic/actions/workflows/ci.yml)
|
|
7
|
+
[](https://www.npmjs.com/package/platformatic)
|
|
8
|
+
[](https://discord.gg/platformatic)
|
|
9
|
+
|
|
10
|
+
Watt, Platformatic's Node.js application server, allows you to run multiple Node.js applications that are centrally managed.
|
|
11
|
+
|
|
12
|
+
By using Watt, you gain access to a virtual mesh network, fast logging via [Pino](https://getpino.io/),
|
|
13
|
+
monitoring through [Prometheus](https://prometheus.io/), and [OpenTelemetry](https://opentelemetry.io/) integrations.
|
|
14
|
+
|
|
15
|
+
Watt supports the stacks you love most, including [Next.js](https://nextjs.org/), [Astro](https://astro.build/),
|
|
16
|
+
[Express](https://expressjs.com/), and [Fastify](https://fastify.dev/).
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Create a new application
|
|
22
|
+
npx wattpm@latest init
|
|
23
|
+
|
|
24
|
+
# Or install manually:
|
|
25
|
+
npm install wattpm
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Follow our [Quick Start Guide](https://docs.platformatic.dev/docs/getting-started/quick-start)
|
|
29
|
+
guide to get up and running with Platformatic.
|
|
30
|
+
|
|
31
|
+
## Documentation
|
|
32
|
+
|
|
33
|
+
- [Getting Started](https://docs.platformatic.dev/docs/getting-started/quick-start)
|
|
34
|
+
- [Reference](https://docs.platformatic.dev/docs/reference/wattpm/overview)
|
|
35
|
+
- [Guides](https://docs.platformatic.dev/docs/guides/build-modular-monolith)
|
|
36
|
+
|
|
37
|
+
Check out our full documentation at [platformatic.dev](https://platformatic.dev).
|
|
38
|
+
|
|
39
|
+
## Support
|
|
40
|
+
|
|
41
|
+
If you run into a bug, issues or have a suggestion for improvement, please raise an
|
|
42
|
+
[issue on GitHub](https://github.com/platformatic/platformatic/issues/new) or join our [Discord feedback](https://discord.gg/platformatic) channel.
|
|
43
|
+
|
|
44
|
+
## License
|
|
45
|
+
|
|
46
|
+
[Apache 2.0](../../LICENSE)
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { checkNodeVersionForApplications, setExecutableId, setExecutableName } from '@platformatic/foundation'
|
|
4
|
+
|
|
5
|
+
checkNodeVersionForApplications()
|
|
6
|
+
setExecutableId('wattpm')
|
|
7
|
+
setExecutableName('Watt')
|
|
8
|
+
|
|
9
|
+
// Use await import here so that we can throw a proper error on unsupported Node.js version
|
|
10
|
+
const { main } = await import('../index.js')
|
|
11
|
+
await main()
|
package/index.js
CHANGED
|
@@ -1,19 +1,25 @@
|
|
|
1
|
+
import { createCliLogger, getExecutableId, logFatalError, parseArgs, setVerbose } from '@platformatic/foundation'
|
|
2
|
+
import { loadApplicationsCommands } from '@platformatic/runtime'
|
|
3
|
+
import * as colorette from 'colorette'
|
|
1
4
|
import { bold } from 'colorette'
|
|
5
|
+
import { adminCommand } from './lib/commands/admin.js'
|
|
2
6
|
import { buildCommand } from './lib/commands/build.js'
|
|
7
|
+
import { createCommand } from './lib/commands/create.js'
|
|
3
8
|
import { devCommand, reloadCommand, restartCommand, startCommand, stopCommand } from './lib/commands/execution.js'
|
|
4
|
-
import { importCommand, resolveCommand } from './lib/commands/external.js'
|
|
5
9
|
import { helpCommand } from './lib/commands/help.js'
|
|
6
|
-
import { initCommand } from './lib/commands/init.js'
|
|
7
10
|
import { injectCommand } from './lib/commands/inject.js'
|
|
8
11
|
import { logsCommand } from './lib/commands/logs.js'
|
|
9
|
-
import { configCommand, envCommand, psCommand
|
|
12
|
+
import { applicationsCommand, configCommand, envCommand, psCommand } from './lib/commands/management.js'
|
|
13
|
+
import { metricsCommand } from './lib/commands/metrics.js'
|
|
14
|
+
import { pprofCommand } from './lib/commands/pprof.js'
|
|
10
15
|
import { version } from './lib/schema.js'
|
|
11
|
-
|
|
16
|
+
|
|
17
|
+
export * from './lib/schema.js'
|
|
12
18
|
|
|
13
19
|
export async function main () {
|
|
14
|
-
|
|
20
|
+
globalThis.platformatic = { executable: getExecutableId() }
|
|
15
21
|
|
|
16
|
-
|
|
22
|
+
const logger = createCliLogger('info')
|
|
17
23
|
|
|
18
24
|
const options = {
|
|
19
25
|
verbose: {
|
|
@@ -25,6 +31,7 @@ export async function main () {
|
|
|
25
31
|
type: 'boolean'
|
|
26
32
|
},
|
|
27
33
|
help: {
|
|
34
|
+
short: 'h',
|
|
28
35
|
type: 'boolean'
|
|
29
36
|
}
|
|
30
37
|
}
|
|
@@ -37,7 +44,10 @@ export async function main () {
|
|
|
37
44
|
}
|
|
38
45
|
|
|
39
46
|
if (values.help) {
|
|
40
|
-
helpCommand([])
|
|
47
|
+
helpCommand(logger, [])
|
|
48
|
+
return
|
|
49
|
+
} else if (unparsed.includes('-h') || unparsed.includes('--help')) {
|
|
50
|
+
helpCommand(logger, unparsed)
|
|
41
51
|
return
|
|
42
52
|
}
|
|
43
53
|
|
|
@@ -46,10 +56,9 @@ export async function main () {
|
|
|
46
56
|
}
|
|
47
57
|
|
|
48
58
|
let command
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
break
|
|
59
|
+
const requestedCommand = unparsed[0] || 'help'
|
|
60
|
+
let applicationCommandContext
|
|
61
|
+
switch (requestedCommand) {
|
|
53
62
|
case 'build':
|
|
54
63
|
command = buildCommand
|
|
55
64
|
break
|
|
@@ -71,8 +80,8 @@ export async function main () {
|
|
|
71
80
|
case 'ps':
|
|
72
81
|
command = psCommand
|
|
73
82
|
break
|
|
74
|
-
case '
|
|
75
|
-
command =
|
|
83
|
+
case 'applications':
|
|
84
|
+
command = applicationsCommand
|
|
76
85
|
break
|
|
77
86
|
case 'config':
|
|
78
87
|
command = configCommand
|
|
@@ -86,23 +95,51 @@ export async function main () {
|
|
|
86
95
|
case 'inject':
|
|
87
96
|
command = injectCommand
|
|
88
97
|
break
|
|
89
|
-
case '
|
|
90
|
-
command =
|
|
98
|
+
case 'metrics':
|
|
99
|
+
command = metricsCommand
|
|
91
100
|
break
|
|
92
|
-
case '
|
|
93
|
-
command =
|
|
101
|
+
case 'pprof':
|
|
102
|
+
command = pprofCommand
|
|
103
|
+
break
|
|
104
|
+
case 'admin':
|
|
105
|
+
command = adminCommand
|
|
106
|
+
break
|
|
107
|
+
/* c8 ignore next 2 - aliases */
|
|
108
|
+
case 'init':
|
|
109
|
+
case 'add':
|
|
110
|
+
case 'create':
|
|
111
|
+
command = createCommand
|
|
94
112
|
break
|
|
95
113
|
case 'help':
|
|
96
114
|
command = helpCommand
|
|
97
115
|
break
|
|
98
116
|
default:
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
117
|
+
if (requestedCommand) {
|
|
118
|
+
const applicationsCommands = await loadApplicationsCommands()
|
|
119
|
+
const applicationCommand = applicationsCommands.commands[requestedCommand]
|
|
120
|
+
|
|
121
|
+
if (applicationCommand) {
|
|
122
|
+
applicationCommandContext = applicationsCommands.applications[requestedCommand]
|
|
123
|
+
command = applicationCommand
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
102
127
|
break
|
|
103
128
|
}
|
|
104
129
|
|
|
105
|
-
|
|
106
|
-
|
|
130
|
+
if (!command) {
|
|
131
|
+
logFatalError(
|
|
132
|
+
logger,
|
|
133
|
+
`Unknown command ${bold(requestedCommand)}. Please run ${bold(`"${getExecutableId()} help"`)} to see available commands.`
|
|
134
|
+
)
|
|
107
135
|
|
|
108
|
-
|
|
136
|
+
return
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (applicationCommandContext) {
|
|
140
|
+
process.chdir(applicationCommandContext.path)
|
|
141
|
+
return command(logger, applicationCommandContext.config, unparsed.slice(1), { colorette, parseArgs, logFatalError })
|
|
142
|
+
} else {
|
|
143
|
+
await command(logger, unparsed.slice(1))
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { parseArgs } from '@platformatic/foundation'
|
|
2
|
+
import { runDelegatedCommand } from './create.js'
|
|
3
|
+
|
|
4
|
+
export async function adminCommand (logger, args) {
|
|
5
|
+
const {
|
|
6
|
+
values: { latest, 'package-manager': packageManager }
|
|
7
|
+
} = parseArgs(
|
|
8
|
+
args,
|
|
9
|
+
{
|
|
10
|
+
latest: {
|
|
11
|
+
type: 'boolean',
|
|
12
|
+
short: 'l'
|
|
13
|
+
},
|
|
14
|
+
'package-manager': {
|
|
15
|
+
type: 'string',
|
|
16
|
+
short: 'P'
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
false
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
return runDelegatedCommand(logger, packageManager, ['@platformatic/watt-admin' + (latest ? '@latest' : '')])
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const help = {
|
|
26
|
+
admin: {
|
|
27
|
+
usage: 'admin',
|
|
28
|
+
description: 'Start the admin interface',
|
|
29
|
+
options: [
|
|
30
|
+
{
|
|
31
|
+
usage: '-l --latest',
|
|
32
|
+
description: 'Use the latest version of @platformatic/watt-admin from'
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
usage: 'P, --package-manager <executable>',
|
|
36
|
+
description: 'Use an alternative package manager (the default is to autodetect it)'
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
}
|
package/lib/commands/build.js
CHANGED
|
@@ -1,53 +1,95 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
ensureLoggableError,
|
|
3
|
+
findRuntimeConfigurationFile,
|
|
4
|
+
getRoot,
|
|
5
|
+
logFatalError,
|
|
6
|
+
parseArgs
|
|
7
|
+
} from '@platformatic/foundation'
|
|
8
|
+
import { create } from '@platformatic/runtime'
|
|
2
9
|
import { bold } from 'colorette'
|
|
3
|
-
import { resolve } from 'node:path'
|
|
4
|
-
import { buildRuntime, findConfigurationFile, overrideFatal, parseArgs } from '../utils.js'
|
|
5
10
|
|
|
6
11
|
export async function buildCommand (logger, args) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const root = resolve(process.cwd(), positionals[0] ?? '')
|
|
12
|
+
let runtime
|
|
13
|
+
let configurationFile
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
try {
|
|
16
|
+
const {
|
|
17
|
+
values: { config },
|
|
18
|
+
positionals
|
|
19
|
+
} = parseArgs(
|
|
20
|
+
args,
|
|
21
|
+
{
|
|
22
|
+
config: {
|
|
23
|
+
type: 'string',
|
|
24
|
+
short: 'c'
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
false
|
|
28
|
+
)
|
|
29
|
+
const root = getRoot(positionals)
|
|
12
30
|
|
|
13
|
-
|
|
14
|
-
// Gather informations for all services before starting
|
|
15
|
-
const { services } = await runtime.getServices()
|
|
31
|
+
configurationFile = await findRuntimeConfigurationFile(logger, root, config)
|
|
16
32
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
33
|
+
/* c8 ignore next 3 - Hard to test */
|
|
34
|
+
if (!configurationFile) {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
21
37
|
|
|
22
38
|
try {
|
|
23
|
-
await
|
|
39
|
+
runtime = await create(configurationFile)
|
|
40
|
+
await runtime.init()
|
|
41
|
+
/* c8 ignore next 4 - Hard to test */
|
|
24
42
|
} catch (error) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
43
|
+
logFatalError(logger, { err: ensureLoggableError(error) }, `Cannot load the runtime: ${error.message}`)
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Gather informations for all applications before starting
|
|
48
|
+
const { applications } = await runtime.getApplications()
|
|
49
|
+
|
|
50
|
+
for (const { id } of applications) {
|
|
51
|
+
const currentLogger = logger.child({ name: id })
|
|
52
|
+
currentLogger.debug(`Building application ${bold(id)} ...`)
|
|
34
53
|
|
|
35
|
-
|
|
54
|
+
try {
|
|
55
|
+
await runtime.buildApplication(id)
|
|
56
|
+
} catch (error) {
|
|
57
|
+
if (error.code === 'PLT_BASIC_NON_ZERO_EXIT_CODE') {
|
|
58
|
+
logFatalError(currentLogger, `Building application "${id}" has failed with exit code ${error.exitCode}.`)
|
|
59
|
+
/* c8 ignore next 6 */
|
|
60
|
+
} else {
|
|
61
|
+
logFatalError(
|
|
62
|
+
currentLogger,
|
|
63
|
+
{ err: ensureLoggableError(error) },
|
|
64
|
+
`Building application "${id}" has throw an exception: ${error.message}`
|
|
65
|
+
)
|
|
66
|
+
/* c8 ignore next 3 - Mistakenly reported as uncovered by C8 */
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return
|
|
70
|
+
}
|
|
36
71
|
}
|
|
37
|
-
}
|
|
38
72
|
|
|
39
|
-
|
|
40
|
-
|
|
73
|
+
logger.done('All applications have been built.')
|
|
74
|
+
} finally {
|
|
75
|
+
await runtime?.close?.(true)
|
|
76
|
+
}
|
|
41
77
|
}
|
|
42
78
|
|
|
43
79
|
export const help = {
|
|
44
80
|
build: {
|
|
45
81
|
usage: 'build [root]',
|
|
46
|
-
description: 'Builds all
|
|
82
|
+
description: 'Builds all applications of the project',
|
|
47
83
|
args: [
|
|
48
84
|
{
|
|
49
85
|
name: 'root',
|
|
50
|
-
description: 'The directory containing the
|
|
86
|
+
description: 'The directory containing the project (the default is the current directory)'
|
|
87
|
+
}
|
|
88
|
+
],
|
|
89
|
+
options: [
|
|
90
|
+
{
|
|
91
|
+
usage: '-c, --config <config>',
|
|
92
|
+
description: 'Name of the configuration file to use (the default is to autodetect it)'
|
|
51
93
|
}
|
|
52
94
|
]
|
|
53
95
|
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { getExecutableName, getPackageManager, parseArgs } from '@platformatic/foundation'
|
|
2
|
+
import { bold } from 'colorette'
|
|
3
|
+
import { spawn } from 'node:child_process'
|
|
4
|
+
import { platform } from 'node:os'
|
|
5
|
+
|
|
6
|
+
export async function runDelegatedCommand (logger, packageManager, args) {
|
|
7
|
+
if (!packageManager) {
|
|
8
|
+
packageManager = await getPackageManager(process.cwd())
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
let runner = 'npx'
|
|
12
|
+
if (packageManager === 'pnpm') {
|
|
13
|
+
runner = 'pnpx'
|
|
14
|
+
} else {
|
|
15
|
+
args.unshift('-y')
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
logger.info(`Running ${bold(runner)} ${bold(args.join(' '))} ...`)
|
|
19
|
+
|
|
20
|
+
const options = { stdio: 'inherit' }
|
|
21
|
+
|
|
22
|
+
if (platform() === 'win32') {
|
|
23
|
+
options.shell = true
|
|
24
|
+
options.windowsVerbatimArguments = true
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const proc = spawn(runner, args, options)
|
|
28
|
+
|
|
29
|
+
proc.on('exit', code => {
|
|
30
|
+
process.exit(code)
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function createCommand (logger, args) {
|
|
35
|
+
const {
|
|
36
|
+
values: {
|
|
37
|
+
latest,
|
|
38
|
+
config,
|
|
39
|
+
'package-manager': packageManager,
|
|
40
|
+
'skip-dependencies': skipDependencies,
|
|
41
|
+
module: modules
|
|
42
|
+
}
|
|
43
|
+
} = parseArgs(
|
|
44
|
+
args,
|
|
45
|
+
{
|
|
46
|
+
latest: {
|
|
47
|
+
type: 'boolean',
|
|
48
|
+
short: 'l'
|
|
49
|
+
},
|
|
50
|
+
// Keep following options in sync with the create command from wattpm-utils
|
|
51
|
+
config: {
|
|
52
|
+
type: 'string',
|
|
53
|
+
short: 'c',
|
|
54
|
+
default: 'watt.json'
|
|
55
|
+
},
|
|
56
|
+
'package-manager': {
|
|
57
|
+
type: 'string',
|
|
58
|
+
short: 'P'
|
|
59
|
+
},
|
|
60
|
+
'skip-dependencies': {
|
|
61
|
+
type: 'boolean',
|
|
62
|
+
short: 's',
|
|
63
|
+
default: false
|
|
64
|
+
},
|
|
65
|
+
module: {
|
|
66
|
+
short: 'M',
|
|
67
|
+
type: 'string',
|
|
68
|
+
multiple: true,
|
|
69
|
+
default: []
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
false,
|
|
73
|
+
false
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
const runArgs = ['wattpm-utils' + (latest ? '@latest' : ''), '--', 'create']
|
|
77
|
+
|
|
78
|
+
runArgs.push('-c', config)
|
|
79
|
+
|
|
80
|
+
if (packageManager) {
|
|
81
|
+
runArgs.push('-P', packageManager)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (skipDependencies) {
|
|
85
|
+
runArgs.push('-s')
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (modules.length > 0) {
|
|
89
|
+
for (const m of modules) {
|
|
90
|
+
runArgs.push('-M', m)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return runDelegatedCommand(logger, packageManager, runArgs)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const createHelp = {
|
|
98
|
+
description () {
|
|
99
|
+
return `Creates a new ${getExecutableName()} project`
|
|
100
|
+
},
|
|
101
|
+
options: [
|
|
102
|
+
{
|
|
103
|
+
usage: '-l --latest',
|
|
104
|
+
description: 'Use the latest version of @platformatic/watt-admin from'
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
usage: '-c, --config <config>',
|
|
108
|
+
description: 'Name of the configuration file to use (the default is watt.json)'
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
usage: '-s, --skip-dependencies',
|
|
112
|
+
description: 'Do not install dependencies after creating the files'
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
usage: '-P, --package-manager <executable>',
|
|
116
|
+
description: 'Use an alternative package manager (the default is to autodetect it)'
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
usage: '-M, --module <name>',
|
|
120
|
+
description:
|
|
121
|
+
'An additional module (or a comma separated list of modules) to use as application generator (it can be used multiple times)'
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export const help = {
|
|
127
|
+
init: {
|
|
128
|
+
usage: 'init',
|
|
129
|
+
...createHelp
|
|
130
|
+
},
|
|
131
|
+
create: {
|
|
132
|
+
usage: 'create',
|
|
133
|
+
...createHelp
|
|
134
|
+
},
|
|
135
|
+
add: {
|
|
136
|
+
usage: 'add',
|
|
137
|
+
...createHelp
|
|
138
|
+
}
|
|
139
|
+
}
|