govon 0.1.0 → 1.1.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 +17 -17
- package/bin/govon.js +6 -6
- package/lib/python-check.js +99 -32
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,44 +2,44 @@
|
|
|
2
2
|
|
|
3
3
|
npm wrapper for the [GovOn](https://github.com/umyunsang/GovOn) CLI.
|
|
4
4
|
|
|
5
|
-
GovOn
|
|
5
|
+
GovOn is a shell-first local agent runtime for administrative support and civil complaint processing workflows.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Requirements
|
|
8
8
|
|
|
9
|
-
- **Node.js** 18
|
|
10
|
-
- **Python** 3.10
|
|
11
|
-
- **pip** (Python
|
|
9
|
+
- **Node.js** 18 or later
|
|
10
|
+
- **Python** 3.10 or later
|
|
11
|
+
- **pip** (Python package manager)
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## Installation
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
16
|
npm install -g govon
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
`govon` Python
|
|
19
|
+
After installation the Python environment is automatically verified.
|
|
20
|
+
If the `govon` Python package is not installed, install it with:
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
23
|
pip install govon
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
##
|
|
26
|
+
## Usage
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
29
|
govon --help
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
##
|
|
32
|
+
## How It Works
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
This package is a thin wrapper around the Python CLI (`govon`).
|
|
35
35
|
|
|
36
|
-
1. `govon`
|
|
37
|
-
2. `govon` CLI(`pip install govon`)
|
|
38
|
-
3.
|
|
39
|
-
4.
|
|
36
|
+
1. When the `govon` command is run, it checks whether Python 3.10+ is installed.
|
|
37
|
+
2. It verifies that the `govon` CLI (`pip install govon`) is installed.
|
|
38
|
+
3. If all conditions are met, execution is delegated to the Python CLI via `child_process.spawn`.
|
|
39
|
+
4. If conditions are not met, a clear installation guide message is printed and the process exits.
|
|
40
40
|
|
|
41
|
-
> Python
|
|
41
|
+
> Automatic Python installation is not supported due to security and permission concerns.
|
|
42
42
|
|
|
43
|
-
##
|
|
43
|
+
## License
|
|
44
44
|
|
|
45
45
|
MIT
|
package/bin/govon.js
CHANGED
|
@@ -6,18 +6,18 @@ const { printEnvironmentStatus, isGovonInstalled } = require('../lib/python-chec
|
|
|
6
6
|
|
|
7
7
|
const args = process.argv.slice(2);
|
|
8
8
|
|
|
9
|
-
// postinstall
|
|
9
|
+
// On postinstall or direct invocation with --check-install, only run environment check and exit
|
|
10
10
|
if (args[0] === '--check-install') {
|
|
11
11
|
const ok = printEnvironmentStatus();
|
|
12
12
|
process.exit(ok ? 0 : 1);
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
//
|
|
15
|
+
// Actual CLI execution path: if environment is not valid, print guidance and exit
|
|
16
16
|
if (!printEnvironmentStatus()) {
|
|
17
17
|
process.exit(1);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
// govon CLI
|
|
20
|
+
// Launch the govon CLI
|
|
21
21
|
const child = spawn('govon', args, {
|
|
22
22
|
stdio: 'inherit',
|
|
23
23
|
shell: false,
|
|
@@ -28,13 +28,13 @@ child.on('error', (err) => {
|
|
|
28
28
|
console.error(
|
|
29
29
|
[
|
|
30
30
|
'',
|
|
31
|
-
' [govon]
|
|
32
|
-
' pip install govon
|
|
31
|
+
' [govon] Unable to execute the govon command.',
|
|
32
|
+
' Please verify it is installed via: pip install govon',
|
|
33
33
|
'',
|
|
34
34
|
].join('\n')
|
|
35
35
|
);
|
|
36
36
|
} else {
|
|
37
|
-
console.error(`[govon]
|
|
37
|
+
console.error(`[govon] Execution error: ${err.message}`);
|
|
38
38
|
}
|
|
39
39
|
process.exit(1);
|
|
40
40
|
});
|
package/lib/python-check.js
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const { execSync, spawnSync } = require('child_process');
|
|
4
|
+
const { realpathSync } = require('fs');
|
|
5
|
+
const path = require('path');
|
|
4
6
|
|
|
5
7
|
const MIN_PYTHON_MAJOR = 3;
|
|
6
8
|
const MIN_PYTHON_MINOR = 10;
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
|
-
* Python
|
|
11
|
+
* List of Python executable candidates in priority order
|
|
10
12
|
*/
|
|
11
13
|
const PYTHON_CANDIDATES = ['python3', 'python'];
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* @param {string} cmd -
|
|
16
|
+
* Returns the version of the given Python executable.
|
|
17
|
+
* Returns null if the executable cannot be run or version parsing fails.
|
|
18
|
+
* @param {string} cmd - Python command to execute
|
|
17
19
|
* @returns {{ major: number, minor: number } | null}
|
|
18
20
|
*/
|
|
19
21
|
function getPythonVersion(cmd) {
|
|
@@ -21,7 +23,7 @@ function getPythonVersion(cmd) {
|
|
|
21
23
|
const result = spawnSync(cmd, ['--version'], { encoding: 'utf8', timeout: 5000 });
|
|
22
24
|
if (result.status !== 0 || result.error) return null;
|
|
23
25
|
|
|
24
|
-
// "Python 3.11.4"
|
|
26
|
+
// Output may appear as "Python 3.11.4" or on stderr (Python 2)
|
|
25
27
|
const output = (result.stdout || result.stderr || '').trim();
|
|
26
28
|
const match = output.match(/Python\s+(\d+)\.(\d+)/i);
|
|
27
29
|
if (!match) return null;
|
|
@@ -33,7 +35,7 @@ function getPythonVersion(cmd) {
|
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
/**
|
|
36
|
-
*
|
|
38
|
+
* Finds a Python 3.10+ executable available on the system.
|
|
37
39
|
* @returns {{ cmd: string, major: number, minor: number } | null}
|
|
38
40
|
*/
|
|
39
41
|
function findPython() {
|
|
@@ -51,22 +53,29 @@ function findPython() {
|
|
|
51
53
|
}
|
|
52
54
|
|
|
53
55
|
/**
|
|
54
|
-
* `govon` CLI
|
|
55
|
-
*
|
|
56
|
+
* Checks whether the `govon` CLI is installed in PATH.
|
|
57
|
+
* Looks for the Python govon binary, not the npm govon.js wrapper.
|
|
56
58
|
* @returns {boolean}
|
|
57
59
|
*/
|
|
58
60
|
function isGovonInstalled() {
|
|
59
61
|
try {
|
|
60
|
-
// which/where
|
|
62
|
+
// Verify govon path via which/where to confirm it is a Python binary
|
|
61
63
|
const whichCmd = process.platform === 'win32' ? 'where' : 'which';
|
|
62
64
|
const which = spawnSync(whichCmd, ['govon'], { encoding: 'utf8', timeout: 5000 });
|
|
63
65
|
if (which.error || which.status !== 0) return false;
|
|
64
66
|
|
|
65
67
|
const govonPath = (which.stdout || '').trim().split('\n')[0];
|
|
66
|
-
//
|
|
67
|
-
|
|
68
|
+
// Resolve symlinks to detect npm wrapper even behind /usr/local/bin symlinks
|
|
69
|
+
let resolvedPath;
|
|
70
|
+
try {
|
|
71
|
+
resolvedPath = realpathSync(govonPath);
|
|
72
|
+
} catch {
|
|
73
|
+
resolvedPath = govonPath;
|
|
74
|
+
}
|
|
75
|
+
// If the resolved path is under node_modules/.bin it is the npm wrapper — ignore it
|
|
76
|
+
if (resolvedPath.includes('node_modules')) return false;
|
|
68
77
|
|
|
69
|
-
// Python module
|
|
78
|
+
// Confirm directly via Python module
|
|
70
79
|
const python = findPython();
|
|
71
80
|
if (!python) return false;
|
|
72
81
|
|
|
@@ -81,7 +90,21 @@ function isGovonInstalled() {
|
|
|
81
90
|
}
|
|
82
91
|
|
|
83
92
|
/**
|
|
84
|
-
*
|
|
93
|
+
* Reads the npm package version from package.json for version pinning.
|
|
94
|
+
* @returns {string} - version string (e.g. "1.0.6"), or empty string on failure
|
|
95
|
+
*/
|
|
96
|
+
function getNpmPackageVersion() {
|
|
97
|
+
try {
|
|
98
|
+
const pkgPath = path.join(__dirname, '..', 'package.json');
|
|
99
|
+
const pkg = require(pkgPath);
|
|
100
|
+
return pkg.version || '';
|
|
101
|
+
} catch {
|
|
102
|
+
return '';
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Inspects the entire Python environment and returns the result.
|
|
85
108
|
* @returns {{
|
|
86
109
|
* pythonFound: boolean,
|
|
87
110
|
* pythonCmd: string | null,
|
|
@@ -102,55 +125,99 @@ function checkEnvironment() {
|
|
|
102
125
|
}
|
|
103
126
|
|
|
104
127
|
/**
|
|
105
|
-
*
|
|
106
|
-
*
|
|
128
|
+
* Automatically installs the Python govon package via pip.
|
|
129
|
+
* Pins to the same version as the npm package to prevent version drift.
|
|
130
|
+
* @param {string} pythonCmd - path to the python executable
|
|
131
|
+
* @returns {boolean} - true if installation succeeded
|
|
107
132
|
*/
|
|
108
|
-
function
|
|
109
|
-
const
|
|
133
|
+
function autoInstallGovon(pythonCmd) {
|
|
134
|
+
const version = getNpmPackageVersion();
|
|
135
|
+
const spec = version ? `govon==${version}` : 'govon';
|
|
110
136
|
|
|
111
|
-
|
|
137
|
+
console.log('\n [govon] Auto-installing the Python govon package…');
|
|
138
|
+
console.log(` → ${pythonCmd} -m pip install ${spec}\n`);
|
|
139
|
+
|
|
140
|
+
const result = spawnSync(pythonCmd, ['-m', 'pip', 'install', spec], {
|
|
141
|
+
stdio: 'inherit',
|
|
142
|
+
timeout: 120000,
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
if (result.error || result.status !== 0) {
|
|
112
146
|
console.error(
|
|
113
147
|
[
|
|
114
148
|
'',
|
|
115
|
-
' [govon]
|
|
149
|
+
' [govon] Auto-installation failed.',
|
|
116
150
|
'',
|
|
117
|
-
'
|
|
118
|
-
|
|
151
|
+
' Please install manually with:',
|
|
152
|
+
` ${pythonCmd} -m pip install ${spec}`,
|
|
119
153
|
'',
|
|
120
|
-
'
|
|
121
|
-
|
|
122
|
-
' Ubuntu: sudo apt install python3.12',
|
|
123
|
-
' Windows: winget install Python.Python.3.12',
|
|
154
|
+
' If you encounter a permission error:',
|
|
155
|
+
` ${pythonCmd} -m pip install --user ${spec}`,
|
|
124
156
|
'',
|
|
125
157
|
].join('\n')
|
|
126
158
|
);
|
|
127
159
|
return false;
|
|
128
160
|
}
|
|
129
161
|
|
|
130
|
-
|
|
162
|
+
console.log('\n [govon] ✓ Python govon package installed successfully.\n');
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Prints the environment check result to stdout and displays guidance if issues are found.
|
|
168
|
+
* Attempts auto-installation if Python govon is not found.
|
|
169
|
+
* @returns {boolean} - true if all conditions are met
|
|
170
|
+
*/
|
|
171
|
+
function printEnvironmentStatus() {
|
|
172
|
+
const { pythonFound, pythonCmd, pythonVersion, govonInstalled } = checkEnvironment();
|
|
173
|
+
|
|
174
|
+
if (!pythonFound) {
|
|
131
175
|
console.error(
|
|
132
176
|
[
|
|
133
177
|
'',
|
|
134
|
-
|
|
178
|
+
' [govon] Python 3.10 or later is required.',
|
|
135
179
|
'',
|
|
136
|
-
'
|
|
137
|
-
|
|
180
|
+
' Please install Python and try again:',
|
|
181
|
+
' https://www.python.org/downloads/',
|
|
138
182
|
'',
|
|
139
|
-
'
|
|
140
|
-
'
|
|
141
|
-
|
|
183
|
+
' Or install via a package manager:',
|
|
184
|
+
' macOS: brew install python@3.12',
|
|
185
|
+
' Ubuntu: sudo apt install python3.12',
|
|
186
|
+
' Windows: winget install Python.Python.3.12',
|
|
142
187
|
'',
|
|
143
188
|
].join('\n')
|
|
144
189
|
);
|
|
145
190
|
return false;
|
|
146
191
|
}
|
|
147
192
|
|
|
193
|
+
if (!govonInstalled) {
|
|
194
|
+
// Attempt auto-installation
|
|
195
|
+
if (!autoInstallGovon(pythonCmd)) {
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
// Re-verify after installation (resolve symlinks for accurate detection)
|
|
199
|
+
if (!isGovonInstalled()) {
|
|
200
|
+
console.error(
|
|
201
|
+
[
|
|
202
|
+
'',
|
|
203
|
+
' [govon] govon CLI could not be found even after installation.',
|
|
204
|
+
'',
|
|
205
|
+
' Please ensure the pip install path is included in your PATH.',
|
|
206
|
+
` Or run directly: ${pythonCmd} -m govon`,
|
|
207
|
+
'',
|
|
208
|
+
].join('\n')
|
|
209
|
+
);
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
148
214
|
return true;
|
|
149
215
|
}
|
|
150
216
|
|
|
151
217
|
module.exports = {
|
|
152
218
|
findPython,
|
|
153
219
|
isGovonInstalled,
|
|
220
|
+
autoInstallGovon,
|
|
154
221
|
checkEnvironment,
|
|
155
222
|
printEnvironmentStatus,
|
|
156
223
|
};
|