wattpm 2.30.2 → 2.32.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/index.js CHANGED
@@ -6,8 +6,9 @@ import { helpCommand } from './lib/commands/help.js'
6
6
  import { initCommand } from './lib/commands/init.js'
7
7
  import { injectCommand } from './lib/commands/inject.js'
8
8
  import { logsCommand } from './lib/commands/logs.js'
9
- import { metricsCommand } from './lib/commands/metrics.js'
10
9
  import { configCommand, envCommand, psCommand, servicesCommand } from './lib/commands/management.js'
10
+ import { metricsCommand } from './lib/commands/metrics.js'
11
+ import { patchConfigCommand } from './lib/commands/patch-config.js'
11
12
  import { version } from './lib/schema.js'
12
13
  import { createLogger, overrideFatal, parseArgs, setVerbose } from './lib/utils.js'
13
14
 
@@ -95,6 +96,9 @@ export async function main () {
95
96
  case 'resolve':
96
97
  command = resolveCommand
97
98
  break
99
+ case 'patch-config':
100
+ command = patchConfigCommand
101
+ break
98
102
  case 'install':
99
103
  command = installCommand
100
104
  break
@@ -117,3 +121,4 @@ export async function main () {
117
121
  export * from './lib/schema.js'
118
122
 
119
123
  export { resolveServices } from './lib/commands/external.js'
124
+ export { patchConfig } from './lib/commands/patch-config.js'
@@ -4,7 +4,17 @@ import { logo } from '../logo.js'
4
4
  async function loadCommands () {
5
5
  const commands = {}
6
6
 
7
- for (const file of ['init', 'build', 'execution', 'management', 'logs', 'inject', 'external', 'metrics']) {
7
+ for (const file of [
8
+ 'init',
9
+ 'build',
10
+ 'execution',
11
+ 'management',
12
+ 'logs',
13
+ 'inject',
14
+ 'external',
15
+ 'patch-config',
16
+ 'metrics'
17
+ ]) {
8
18
  const category = await import(`./${file}.js`)
9
19
  Object.assign(commands, category.help)
10
20
  }
@@ -0,0 +1,122 @@
1
+ import { getParser, getStringifier } from '@platformatic/config'
2
+ import { ensureLoggableError, loadModule } from '@platformatic/utils'
3
+ import jsonPatch from 'fast-json-patch'
4
+ import { readFile, writeFile } from 'node:fs/promises'
5
+ import { createRequire } from 'node:module'
6
+ import { buildRuntime, findConfigurationFile, getRoot, parseArgs } from '../utils.js'
7
+
8
+ async function patchFile (path, patch) {
9
+ let config = getParser(path)(await readFile(path, 'utf-8'))
10
+ config = jsonPatch.applyPatch(config, patch).newDocument
11
+ await writeFile(path, getStringifier(path)(config))
12
+ }
13
+
14
+ export async function patchConfig (logger, configurationFile, patchPath) {
15
+ let runtime
16
+ try {
17
+ const patchFunction = await loadModule(createRequire(import.meta.url), patchPath)
18
+
19
+ if (typeof patchFunction !== 'function') {
20
+ throw new Error('Patch file must export a function.')
21
+ }
22
+
23
+ // Create the runtime
24
+ runtime = await buildRuntime(logger, configurationFile)
25
+
26
+ // Prepare the structure for original and modified configurations files
27
+ const original = {
28
+ runtime: getParser(configurationFile)(await readFile(configurationFile, 'utf-8')),
29
+ services: {}
30
+ }
31
+
32
+ const loaded = {
33
+ runtime: runtime.getRuntimeConfig(),
34
+ services: {}
35
+ }
36
+
37
+ const services = Object.fromEntries(loaded.runtime.services.map(service => [service.id, service]))
38
+
39
+ // Load configuration for all services
40
+ for (const { id, config } of loaded.runtime.services) {
41
+ const parser = getParser(config)
42
+
43
+ original.services[id] = parser(await readFile(configurationFile, 'utf-8'))
44
+ loaded.services[id] = await runtime.getServiceConfig(id, false)
45
+ }
46
+
47
+ // Execute the patch function
48
+ const patches = await patchFunction(runtime, services, loaded, original)
49
+
50
+ // Apply patches
51
+ if (typeof patches !== 'object') {
52
+ return
53
+ }
54
+
55
+ if (Array.isArray(patches.runtime)) {
56
+ await patchFile(configurationFile, patches.runtime)
57
+ }
58
+
59
+ if (typeof patches.services === 'object') {
60
+ for (const [id, patch] of Object.entries(patches.services)) {
61
+ const config = services[id].config
62
+
63
+ if (Array.isArray(patch)) {
64
+ await patchFile(config, patch)
65
+ }
66
+ }
67
+ }
68
+ } finally {
69
+ await runtime?.close?.(false, true)
70
+ }
71
+ }
72
+
73
+ export async function patchConfigCommand (logger, args) {
74
+ const { positionals } = parseArgs(args, {}, false)
75
+
76
+ let root
77
+ let patch
78
+
79
+ /*
80
+ One argument = patch file
81
+ Two arguments = root and patch file
82
+ */
83
+
84
+ /* c8 ignore next 7 */
85
+ if (positionals.length === 1) {
86
+ root = getRoot()
87
+ patch = positionals[0]
88
+ } else {
89
+ root = getRoot(positionals)
90
+ patch = positionals[1]
91
+ }
92
+
93
+ const configurationFile = await findConfigurationFile(logger, root)
94
+
95
+ try {
96
+ await patchConfig(logger, configurationFile, patch)
97
+ } catch (error) {
98
+ logger.error({ err: ensureLoggableError(error) }, `Patching configuration has throw an exception: ${error.message}`)
99
+
100
+ process.exit(1)
101
+ }
102
+
103
+ logger.done('Patch executed correctly.')
104
+ }
105
+
106
+ export const help = {
107
+ 'patch-config': {
108
+ usage: 'patch-config [root] [patch]',
109
+ description: 'Applies a patch file to the runtime and services configurations.',
110
+ args: [
111
+ {
112
+ name: 'root',
113
+ description:
114
+ 'The process ID of the application (it can be omitted only if there is a single application running)'
115
+ },
116
+ {
117
+ name: 'patch',
118
+ description: 'The file containing the patch to execute.'
119
+ }
120
+ ]
121
+ }
122
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wattpm",
3
- "version": "2.30.2",
3
+ "version": "2.32.0",
4
4
  "description": "The Node.js Application Server",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -35,11 +35,11 @@
35
35
  "pino-pretty": "^13.0.0",
36
36
  "split2": "^4.2.0",
37
37
  "table": "^6.8.2",
38
- "@platformatic/basic": "2.30.2",
39
- "@platformatic/control": "2.30.2",
40
- "@platformatic/config": "2.30.2",
41
- "@platformatic/runtime": "2.30.2",
42
- "@platformatic/utils": "2.30.2"
38
+ "@platformatic/basic": "2.32.0",
39
+ "@platformatic/control": "2.32.0",
40
+ "@platformatic/runtime": "2.32.0",
41
+ "@platformatic/config": "2.32.0",
42
+ "@platformatic/utils": "2.32.0"
43
43
  },
44
44
  "devDependencies": {
45
45
  "borp": "^0.19.0",
@@ -49,7 +49,7 @@
49
49
  "neostandard": "^0.12.0",
50
50
  "typescript": "^5.5.4",
51
51
  "undici": "^7.0.0",
52
- "@platformatic/node": "2.30.2"
52
+ "@platformatic/node": "2.32.0"
53
53
  },
54
54
  "scripts": {
55
55
  "test": "npm run lint && borp --concurrency=1 --timeout=300000",
package/schema.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://schemas.platformatic.dev/wattpm/2.30.2.json",
2
+ "$id": "https://schemas.platformatic.dev/wattpm/2.32.0.json",
3
3
  "$schema": "http://json-schema.org/draft-07/schema#",
4
4
  "type": "object",
5
5
  "properties": {