@gox-lang/cli 0.0.0-stage → 0.1.3
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/CONTRIBUTING.md +79 -0
- package/LICENSE +21 -0
- package/README.md +98 -2
- package/SECURITY.md +53 -0
- package/bin/gox.cjs +48 -0
- package/lib/install.cjs +124 -0
- package/package.json +38 -4
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Contributing to GOX
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to GOX.
|
|
4
|
+
|
|
5
|
+
GOX recognizes that contributing to an open source project does not necessarily mean writing code. Bug reports, proposals for new features, and other contributions that materially help improve the project may be recognized as contributions.
|
|
6
|
+
|
|
7
|
+
At this stage of the project, GOX primarily accepts contributions through **bug reports** and **proposals**. Direct implementation and modification of the source code are handled by the project maintainers.
|
|
8
|
+
|
|
9
|
+
This model may evolve in the future as the project, its community, and its resources grow.
|
|
10
|
+
|
|
11
|
+
## Bug Reports
|
|
12
|
+
|
|
13
|
+
If you find incorrect behavior in GOX, you can report it through **GitHub Issues**.
|
|
14
|
+
|
|
15
|
+
A good bug report should include, when possible:
|
|
16
|
+
|
|
17
|
+
- A clear description of the problem.
|
|
18
|
+
- The expected behavior.
|
|
19
|
+
- The observed behavior.
|
|
20
|
+
- The steps required to reproduce it.
|
|
21
|
+
- The GOX version being used.
|
|
22
|
+
- Relevant information about the environment.
|
|
23
|
+
- A minimal example or reproduction code, when useful.
|
|
24
|
+
- Logs, error messages, or other information that may help investigate the problem.
|
|
25
|
+
|
|
26
|
+
A report that materially contributes to identifying, reproducing, or resolving an issue may be recognized as a contribution to the project.
|
|
27
|
+
|
|
28
|
+
The implementation of the fix will be handled by the GOX maintainers.
|
|
29
|
+
|
|
30
|
+
Issues that may have security implications **must not be published as public GitHub Issues**. See [`SECURITY.md`](SECURITY.md) for the reporting process using GitHub Private Vulnerability Reporting.
|
|
31
|
+
|
|
32
|
+
## Proposals
|
|
33
|
+
|
|
34
|
+
Proposals for new features, APIs, syntax, or significant changes to GOX behavior are welcome.
|
|
35
|
+
|
|
36
|
+
A proposal should clearly explain:
|
|
37
|
+
|
|
38
|
+
- The problem or need it is intended to address.
|
|
39
|
+
- The proposed behavior.
|
|
40
|
+
- Why it would be useful to GOX or its users.
|
|
41
|
+
- Examples that help explain the proposal, when necessary.
|
|
42
|
+
|
|
43
|
+
Proposals will be evaluated with consideration for the architecture, consistency, philosophy, and goals of GOX.
|
|
44
|
+
|
|
45
|
+
An accepted proposal does not necessarily mean that its original design will be implemented exactly as presented. The maintainers may adapt, modify, or redesign the solution to ensure that it integrates correctly with the rest of GOX.
|
|
46
|
+
|
|
47
|
+
When a proposal materially contributes to a feature that is ultimately incorporated into the project, its author may be recognized for their contribution.
|
|
48
|
+
|
|
49
|
+
The final implementation will be handled by the GOX maintainers.
|
|
50
|
+
|
|
51
|
+
## Code Contributions
|
|
52
|
+
|
|
53
|
+
At this stage, GOX **does not accept Pull Requests containing direct code contributions**.
|
|
54
|
+
|
|
55
|
+
Development and modifications to the source code are handled by the maintainers. This helps maintain a consistent architecture, API, syntax, and technical direction while the project is in its early stages.
|
|
56
|
+
|
|
57
|
+
This does not prevent contributors from including code as part of a bug report or proposal. Contributors may provide code examples, minimal reproducible cases, proofs of concept, or possible API and syntax designs when they help explain or demonstrate a contribution.
|
|
58
|
+
|
|
59
|
+
These examples are considered supporting material for evaluating and developing the contribution. The implementation ultimately incorporated into GOX will be designed and written by the maintainers.
|
|
60
|
+
|
|
61
|
+
The policy regarding direct code contributions and Pull Requests may change in the future as the project evolves.
|
|
62
|
+
|
|
63
|
+
## Recognition
|
|
64
|
+
|
|
65
|
+
GOX may recognize as contributors people who have made significant contributions to the project even if they did not directly write the code that is ultimately incorporated.
|
|
66
|
+
|
|
67
|
+
This may include, among other things:
|
|
68
|
+
|
|
69
|
+
- Bug reports that materially contribute to identifying or resolving an issue.
|
|
70
|
+
- Proposals that materially contribute to the design or introduction of a new feature.
|
|
71
|
+
- Other technical or documentation contributions that have a significant impact on the project.
|
|
72
|
+
|
|
73
|
+
Recognition of a contribution **does not imply authorship or ownership of code written by the GOX maintainers**.
|
|
74
|
+
|
|
75
|
+
## Security
|
|
76
|
+
|
|
77
|
+
Potential security vulnerabilities must not be reported through public GitHub Issues.
|
|
78
|
+
|
|
79
|
+
See [`SECURITY.md`](SECURITY.md) for the vulnerability reporting process using **GitHub Private Vulnerability Reporting**.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Javier Marquez
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,99 @@
|
|
|
1
|
-
#
|
|
1
|
+
# GOX CLI for npm
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
One JavaScript package installs the official GOX executable from **GitHub Releases**.
|
|
4
|
+
No native binaries are committed to this repository or included in the npm package.
|
|
5
|
+
No Python, Go compiler, curl, tar or unzip command is needed by this installer.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Node.js 20 or newer is required.
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install -g @gox-lang/cli --ignore-scripts=false --foreground-scripts
|
|
13
|
+
gox version
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Installation scripts must be enabled. On npm versions that require explicit script
|
|
17
|
+
approval, also allow this package (for global installs, supported npm versions offer
|
|
18
|
+
`--allow-scripts=@gox-lang/cli`). Do not disable organization security policies globally.
|
|
19
|
+
See [npm configuration](https://docs.npmjs.com/cli/using-npm/config/) for your version.
|
|
20
|
+
|
|
21
|
+
npm places `gox` in its global command directory, which must be on PATH. The installer
|
|
22
|
+
does not modify shell profiles or create a second installation outside this package.
|
|
23
|
+
|
|
24
|
+
Linux/glibc, macOS and Windows releases support x64 and arm64. Native Windows can run
|
|
25
|
+
the CLI/LSP; use WSL for application development because Go plugins require it.
|
|
26
|
+
Alpine/musl is not supported by the official Linux binaries.
|
|
27
|
+
|
|
28
|
+
## How it works
|
|
29
|
+
|
|
30
|
+
`postinstall` detects the platform, downloads the exact release matching this package's
|
|
31
|
+
version from `gox-lang/server`, verifies the archive against that release's SHA-256
|
|
32
|
+
checksums, extracts only the executable, and checks `gox version` before installing.
|
|
33
|
+
The downloaded executable and receipt live in `.vendor/`, excluded from Git and npm.
|
|
34
|
+
The launcher checks the receipt and binary digest, then forwards arguments and stdio.
|
|
35
|
+
It never downloads during ordinary command execution.
|
|
36
|
+
|
|
37
|
+
Internet access to GitHub and its release-asset CDN is required during installation.
|
|
38
|
+
A failed download or verification fails installation; it never falls back to another
|
|
39
|
+
binary source. HTTPS and release checksums are used, not an independent signing system.
|
|
40
|
+
|
|
41
|
+
## Scripts disabled or incomplete installation
|
|
42
|
+
|
|
43
|
+
The command prints instructions and exits without downloading. To complete a global
|
|
44
|
+
installation explicitly:
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
npm rebuild -g @gox-lang/cli --ignore-scripts=false --foreground-scripts
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
For a local project dependency, omit `-g`. If your npm version requires package-specific
|
|
51
|
+
approval, approve this package before rebuilding.
|
|
52
|
+
|
|
53
|
+
## Updates
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
npm install -g @gox-lang/cli@latest --ignore-scripts=false --foreground-scripts
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Use npm to manage this installation. `gox update` prints npm update instructions; LSP
|
|
60
|
+
auto-update is disabled in the child environment so it cannot replace npm's executable.
|
|
61
|
+
GOX v0.1.3 native update notices may still recommend `gox update`; the launcher redirects
|
|
62
|
+
that command. Future server releases can improve the wording. Invoking the nested
|
|
63
|
+
binary directly bypasses these launcher rules.
|
|
64
|
+
|
|
65
|
+
## Development
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
npm ci --ignore-scripts
|
|
69
|
+
npm test
|
|
70
|
+
npm run test:install
|
|
71
|
+
npm pack --dry-run
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The smoke test installs a tarball in a temporary global prefix, checks the missing-script
|
|
75
|
+
message, explicitly rebuilds from GitHub, runs GOX, and checks corruption detection.
|
|
76
|
+
No developer installation or shell configuration is changed.
|
|
77
|
+
|
|
78
|
+
- `bin/gox.cjs`: command launcher.
|
|
79
|
+
- `lib/install.cjs`: installation, verification and archive handling in JavaScript.
|
|
80
|
+
- `tests/`: JavaScript unit and isolated installation tests.
|
|
81
|
+
- `package-lock.json`: locked development dependency tree.
|
|
82
|
+
|
|
83
|
+
The package version pins the corresponding GOX release, not a moving latest download.
|
|
84
|
+
Before each publication, run the cross-platform CI checks and inspect the tarball.
|
|
85
|
+
Publication requires maintainer access to the npm organization and is not automated here.
|
|
86
|
+
|
|
87
|
+
## Contributing
|
|
88
|
+
|
|
89
|
+
Bug reports and proposals are welcome. Please read [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
90
|
+
for the current GOX contribution policy.
|
|
91
|
+
|
|
92
|
+
## Security
|
|
93
|
+
|
|
94
|
+
Report potential vulnerabilities privately through GitHub Private Vulnerability Reporting.
|
|
95
|
+
See [SECURITY.md](SECURITY.md) for the reporting process.
|
|
96
|
+
|
|
97
|
+
## License
|
|
98
|
+
|
|
99
|
+
MIT — see [LICENSE](LICENSE).
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
The security of GOX is a priority. If you discover a potential security vulnerability in GOX, report it through **GitHub Private Vulnerability Reporting**, available in the **Security** section of this repository, so it can be investigated before being made public.
|
|
4
|
+
|
|
5
|
+
## Reporting a Vulnerability
|
|
6
|
+
|
|
7
|
+
Potential security vulnerabilities should be reported using **GitHub Private Vulnerability Reporting** in the **Security** section of the repository.
|
|
8
|
+
|
|
9
|
+
Please **do not publish vulnerabilities or potential vulnerabilities as public GitHub Issues**.
|
|
10
|
+
|
|
11
|
+
When possible, include:
|
|
12
|
+
|
|
13
|
+
- A clear description of the issue.
|
|
14
|
+
- The steps required to reproduce it.
|
|
15
|
+
- The affected GOX versions.
|
|
16
|
+
- The security impact you believe it may have.
|
|
17
|
+
- Any examples, proof of concept, or additional information that may help reproduce and investigate the issue.
|
|
18
|
+
|
|
19
|
+
You do not need to determine the severity of the vulnerability beforehand. GOX will evaluate the report and determine its impact and severity during the investigation.
|
|
20
|
+
|
|
21
|
+
If you are unsure whether an issue has security implications, **report it through GitHub Private Vulnerability Reporting in the Security section of the repository**.
|
|
22
|
+
|
|
23
|
+
## What Should Be Reported Through GitHub Private Vulnerability Reporting
|
|
24
|
+
|
|
25
|
+
Use GitHub Private Vulnerability Reporting for issues that may have security implications, including but not limited to:
|
|
26
|
+
|
|
27
|
+
- Unauthorized access or actions.
|
|
28
|
+
- Authentication or authorization issues.
|
|
29
|
+
- Exposure of sensitive information.
|
|
30
|
+
- Session-related manipulation or vulnerabilities.
|
|
31
|
+
- Unintended code execution.
|
|
32
|
+
- Vulnerabilities related to paths or filesystem access.
|
|
33
|
+
- Security issues related to WebSockets or other communications.
|
|
34
|
+
- Vulnerabilities that could cause a denial of service through abnormal or exploitable GOX behavior.
|
|
35
|
+
- Any other behavior that could compromise the security of a GOX application, server, or user.
|
|
36
|
+
|
|
37
|
+
## What Should Not Be Reported as a Vulnerability
|
|
38
|
+
|
|
39
|
+
Issues that do not have security implications should be reported through **GitHub Issues**.
|
|
40
|
+
|
|
41
|
+
This includes compilation errors, incorrect API behavior, CLI issues, hot reload issues, tooling problems, framework compatibility issues, performance issues, documentation problems, and other functional bugs that do not represent a security risk.
|
|
42
|
+
|
|
43
|
+
## Supported Versions
|
|
44
|
+
|
|
45
|
+
Security vulnerabilities will be evaluated for versions of GOX that are currently supported.
|
|
46
|
+
|
|
47
|
+
Versions that have reached the end of their support period may not receive security fixes.
|
|
48
|
+
|
|
49
|
+
## Disclosure
|
|
50
|
+
|
|
51
|
+
Please do not publicly disclose the details of a vulnerability while it is being investigated and, when applicable, fixed.
|
|
52
|
+
|
|
53
|
+
Once the issue has been resolved, GOX may publish information about the vulnerability, the affected versions, and the corresponding fix.
|
package/bin/gox.cjs
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const { spawn } = require('node:child_process');
|
|
5
|
+
const { installed } = require('../lib/install.cjs');
|
|
6
|
+
|
|
7
|
+
async function main(args) {
|
|
8
|
+
if (args[0] === 'update') {
|
|
9
|
+
console.error('This GOX installation is managed by npm.\nGlobal installation: npm install -g @gox-lang/cli@latest\nProject dependency: npm install @gox-lang/cli@latest');
|
|
10
|
+
process.exitCode = 1;
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
let executable;
|
|
14
|
+
try {
|
|
15
|
+
executable = await installed();
|
|
16
|
+
} catch (error) {
|
|
17
|
+
console.error('GOX is not installed or its installation is incomplete. Installation scripts must be enabled.\nRun: npm rebuild -g @gox-lang/cli --ignore-scripts=false --foreground-scripts\nFor a project dependency, omit -g. If npm requires script approval, approve @gox-lang/cli before rebuilding.');
|
|
18
|
+
process.exitCode = 1;
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const child = spawn(executable, args, {
|
|
22
|
+
stdio: 'inherit',
|
|
23
|
+
env: { ...process.env, GOX_LSP_AUTO_UPDATE: '0' },
|
|
24
|
+
});
|
|
25
|
+
const signals = ['SIGINT', 'SIGTERM', 'SIGHUP'];
|
|
26
|
+
const handlers = new Map();
|
|
27
|
+
for (const signal of signals) {
|
|
28
|
+
const handler = () => { if (!child.killed) child.kill(signal); };
|
|
29
|
+
handlers.set(signal, handler);
|
|
30
|
+
process.on(signal, handler);
|
|
31
|
+
}
|
|
32
|
+
const cleanup = () => {
|
|
33
|
+
for (const [signal, handler] of handlers) process.removeListener(signal, handler);
|
|
34
|
+
};
|
|
35
|
+
child.once('error', (error) => {
|
|
36
|
+
cleanup();
|
|
37
|
+
console.error(`Could not start GOX: ${error.message}`);
|
|
38
|
+
process.exitCode = 1;
|
|
39
|
+
});
|
|
40
|
+
child.once('exit', (code, signal) => {
|
|
41
|
+
cleanup();
|
|
42
|
+
if (signal) process.kill(process.pid, signal);
|
|
43
|
+
else process.exitCode = code ?? 1;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = { main };
|
|
48
|
+
if (require.main === module) main(process.argv.slice(2));
|
package/lib/install.cjs
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs/promises');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
const { createHash } = require('node:crypto');
|
|
6
|
+
const { execFileSync } = require('node:child_process');
|
|
7
|
+
const tar = require('tar');
|
|
8
|
+
const AdmZip = require('adm-zip');
|
|
9
|
+
const { version } = require('../package.json');
|
|
10
|
+
const root = path.resolve(__dirname, '..');
|
|
11
|
+
const LIMIT = 256 * 1024 * 1024;
|
|
12
|
+
|
|
13
|
+
function target(platform = process.platform, arch = process.arch) {
|
|
14
|
+
const systems = { linux: 'linux', darwin: 'darwin', win32: 'windows' };
|
|
15
|
+
const arches = { x64: 'amd64', arm64: 'arm64' };
|
|
16
|
+
if (!systems[platform] || !arches[arch]) throw new Error(`Unsupported platform: ${platform}/${arch}.`);
|
|
17
|
+
if (!/^\d+\.\d+\.\d+$/.test(version)) throw new Error('Invalid pinned GOX version.');
|
|
18
|
+
return {
|
|
19
|
+
id: `${version}-${platform}-${arch}`,
|
|
20
|
+
binary: platform === 'win32' ? 'gox.exe' : 'gox',
|
|
21
|
+
archive: `gox_${version}_${systems[platform]}_${arches[arch]}.${platform === 'win32' ? 'zip' : 'tar.gz'}`,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function download(url, limit = LIMIT) {
|
|
26
|
+
// GitHub serves release assets through its HTTPS release CDN.
|
|
27
|
+
for (let redirects = 0; redirects <= 5; redirects++) {
|
|
28
|
+
const parsed = new URL(url);
|
|
29
|
+
if (parsed.protocol !== 'https:' || !['github.com', 'release-assets.githubusercontent.com', 'objects.githubusercontent.com'].includes(parsed.hostname)) {
|
|
30
|
+
throw new Error('Refusing an untrusted release URL.');
|
|
31
|
+
}
|
|
32
|
+
const response = await fetch(url, { redirect: 'manual', signal: AbortSignal.timeout(120000) });
|
|
33
|
+
if ([301, 302, 303, 307, 308].includes(response.status)) {
|
|
34
|
+
await response.body?.cancel();
|
|
35
|
+
url = new URL(response.headers.get('location'), url).href;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (!response.ok) { await response.body?.cancel(); throw new Error(`GitHub download failed: HTTP ${response.status}`); }
|
|
39
|
+
const chunks = [];
|
|
40
|
+
let length = 0;
|
|
41
|
+
for await (const chunk of response.body) {
|
|
42
|
+
length += chunk.length;
|
|
43
|
+
if (length > limit) throw new Error('Release download exceeds the size limit.');
|
|
44
|
+
chunks.push(chunk);
|
|
45
|
+
}
|
|
46
|
+
return Buffer.concat(chunks);
|
|
47
|
+
}
|
|
48
|
+
throw new Error('Too many release redirects.');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function digest(data) { return createHash('sha256').update(data).digest('hex'); }
|
|
52
|
+
function verify(data, checksums, filename) {
|
|
53
|
+
const matches = checksums.toString().split(/\r?\n/).map(line => line.trim().split(/\s+/)).filter(fields => fields.length === 2 && fields[1] === filename);
|
|
54
|
+
if (matches.length !== 1 || !/^[a-f\d]{64}$/i.test(matches[0][0])) throw new Error('Missing, duplicate or invalid release checksum.');
|
|
55
|
+
if (digest(data) !== matches[0][0].toLowerCase()) throw new Error('Release checksum mismatch. Nothing was installed.');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function extract(data, filename) {
|
|
59
|
+
if (filename === 'gox.exe') {
|
|
60
|
+
const matches = new AdmZip(data).getEntries().filter(entry => entry.entryName === filename);
|
|
61
|
+
if (matches.length !== 1 || matches[0].isDirectory || matches[0].header.size > LIMIT) throw new Error('Invalid executable in ZIP archive.');
|
|
62
|
+
return matches[0].getData();
|
|
63
|
+
}
|
|
64
|
+
return new Promise((resolve, reject) => {
|
|
65
|
+
const chunks = [];
|
|
66
|
+
let count = 0;
|
|
67
|
+
let size = 0;
|
|
68
|
+
let invalid = false;
|
|
69
|
+
const parser = tar.t({ strict: true, onReadEntry(entry) {
|
|
70
|
+
if (entry.path !== filename) { entry.resume(); return; }
|
|
71
|
+
count++;
|
|
72
|
+
if (entry.type !== 'File' || entry.size > LIMIT) { invalid = true; entry.resume(); return; }
|
|
73
|
+
entry.on('data', chunk => {
|
|
74
|
+
size += chunk.length;
|
|
75
|
+
if (size > LIMIT) invalid = true;
|
|
76
|
+
else chunks.push(chunk);
|
|
77
|
+
});
|
|
78
|
+
} });
|
|
79
|
+
parser.on('error', reject);
|
|
80
|
+
parser.on('end', () => {
|
|
81
|
+
if (invalid || count !== 1 || !size) reject(new Error('Invalid executable in TAR archive.'));
|
|
82
|
+
else resolve(Buffer.concat(chunks));
|
|
83
|
+
});
|
|
84
|
+
parser.end(data);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function installed(packageRoot = root) {
|
|
89
|
+
const platform = target();
|
|
90
|
+
const directory = path.join(packageRoot, '.vendor', platform.id);
|
|
91
|
+
const binary = path.join(directory, platform.binary);
|
|
92
|
+
const metadata = JSON.parse(await fs.readFile(path.join(directory, 'receipt.json'), 'utf8'));
|
|
93
|
+
if (metadata.id !== platform.id || digest(await fs.readFile(binary)) !== metadata.sha256) throw new Error('Installed GOX binary is incomplete or has changed.');
|
|
94
|
+
return binary;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async function install(packageRoot = root, get = download) {
|
|
98
|
+
const platform = target();
|
|
99
|
+
if (process.platform === 'linux' && !process.report.getReport().header.glibcVersionRuntime) {
|
|
100
|
+
throw new Error('Official GOX Linux binaries require glibc. Alpine/musl is not supported.');
|
|
101
|
+
}
|
|
102
|
+
const base = `https://github.com/gox-lang/server/releases/download/v${version}`;
|
|
103
|
+
console.error(`Downloading GOX v${version} from GitHub Releases...`);
|
|
104
|
+
const checksums = await get(`${base}/checksums.sha256`, 1024 * 1024);
|
|
105
|
+
const archive = await get(`${base}/${platform.archive}`);
|
|
106
|
+
verify(archive, checksums, platform.archive);
|
|
107
|
+
const executable = await extract(archive, platform.binary);
|
|
108
|
+
const directory = path.join(packageRoot, '.vendor', platform.id);
|
|
109
|
+
await fs.mkdir(directory, { recursive: true });
|
|
110
|
+
const staging = await fs.mkdtemp(path.join(packageRoot, '.gox-install-'));
|
|
111
|
+
try {
|
|
112
|
+
const candidate = path.join(staging, platform.binary);
|
|
113
|
+
await fs.writeFile(candidate, executable, { mode: 0o755 });
|
|
114
|
+
const output = execFileSync(candidate, ['version'], { encoding: 'utf8', timeout: 15000 });
|
|
115
|
+
if (!output.includes(`v${version}`)) throw new Error('Downloaded executable reported an unexpected version.');
|
|
116
|
+
await fs.writeFile(path.join(staging, 'receipt.json'), JSON.stringify({ id: platform.id, sha256: digest(executable) }));
|
|
117
|
+
await fs.rename(candidate, path.join(directory, platform.binary));
|
|
118
|
+
await fs.rename(path.join(staging, 'receipt.json'), path.join(directory, 'receipt.json'));
|
|
119
|
+
} finally { await fs.rm(staging, { recursive: true, force: true }); }
|
|
120
|
+
console.error(`GOX v${version} installed successfully. Run: gox version`);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
module.exports = { target, verify, extract, install, installed };
|
|
124
|
+
if (require.main === module) install().catch(error => { console.error(`GOX installation failed: ${error.message}`); process.exitCode = 1; });
|
package/package.json
CHANGED
|
@@ -1,6 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gox-lang/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "Install and run the official GOX binary from GitHub Releases.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=20"
|
|
8
|
+
},
|
|
9
|
+
"bin": {
|
|
10
|
+
"gox": "bin/gox.cjs"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"bin/",
|
|
14
|
+
"lib/",
|
|
15
|
+
"README.md",
|
|
16
|
+
"LICENSE",
|
|
17
|
+
"CONTRIBUTING.md",
|
|
18
|
+
"SECURITY.md"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"postinstall": "node lib/install.cjs",
|
|
22
|
+
"test": "node --test tests/*.test.cjs",
|
|
23
|
+
"test:install": "node tests/smoke-install.cjs"
|
|
24
|
+
},
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"adm-zip": "0.6.1",
|
|
30
|
+
"tar": "7.5.22"
|
|
31
|
+
},
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "git+https://github.com/gox-lang/npm.git"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://gox-lang.dev",
|
|
37
|
+
"bugs": {
|
|
38
|
+
"url": "https://github.com/gox-lang/npm/issues"
|
|
39
|
+
}
|
|
40
|
+
}
|