nipox 0.0.1 → 0.0.2
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 +169 -0
- package/dist/index.js +28 -1
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# nipox
|
|
2
|
+
|
|
3
|
+
Download and execute bash scripts from URLs or GitHub repositories with cross-platform support.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
nipox is a command-line tool that allows you to download and execute bash scripts directly from URLs or from the n-p-x GitHub organization repositories. It provides cross-platform support for Linux, macOS, and Windows (with Git Bash/WSL), and can also execute YAML Taskfiles.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
### Global Installation
|
|
12
|
+
```bash
|
|
13
|
+
npm install -g nipox
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### One-time Execution
|
|
17
|
+
```bash
|
|
18
|
+
npx nipox <url|script-name> [args...]
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
### Basic Syntax
|
|
24
|
+
```bash
|
|
25
|
+
nipox <url|script-name> [args...]
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Examples
|
|
29
|
+
|
|
30
|
+
#### 1. Execute a script from a direct URL
|
|
31
|
+
```bash
|
|
32
|
+
nipox https://example.com/setup.sh
|
|
33
|
+
nipox https://raw.githubusercontent.com/user/repo/main/install.sh --verbose
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
#### 2. Execute a script from the n-p-x/e repository (default)
|
|
37
|
+
```bash
|
|
38
|
+
nipox my-script
|
|
39
|
+
nipox deploy-app production
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
#### 3. Execute a script from a specific n-p-x repository
|
|
43
|
+
```bash
|
|
44
|
+
nipox docker/setup-container
|
|
45
|
+
nipox terraform/deploy-infrastructure us-east-1
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
#### 4. Execute YAML Taskfiles
|
|
49
|
+
```bash
|
|
50
|
+
nipox https://example.com/Taskfile.yml build
|
|
51
|
+
nipox tasks/build-project
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Platform Support
|
|
55
|
+
|
|
56
|
+
### Linux & macOS
|
|
57
|
+
- **bash** (preferred)
|
|
58
|
+
- **sh** (fallback)
|
|
59
|
+
|
|
60
|
+
### Windows
|
|
61
|
+
- **Git Bash** (recommended)
|
|
62
|
+
- **WSL bash** (Windows Subsystem for Linux)
|
|
63
|
+
- **PowerShell** (limited support, not yet implemented)
|
|
64
|
+
|
|
65
|
+
## Features
|
|
66
|
+
|
|
67
|
+
- **Cross-platform compatibility** - Works on Linux, macOS, and Windows
|
|
68
|
+
- **Multiple shell support** - Automatically detects and uses available shells
|
|
69
|
+
- **GitHub integration** - Easy execution of scripts from n-p-x repositories
|
|
70
|
+
- **Taskfile support** - Execute YAML-based task files using @go-task/cli
|
|
71
|
+
- **Temporary execution** - Scripts are downloaded to temp directory and cleaned up
|
|
72
|
+
- **Error handling** - Comprehensive error messages and troubleshooting guidance
|
|
73
|
+
- **Cache-busting** - Always downloads fresh copies of scripts
|
|
74
|
+
|
|
75
|
+
## Repository Structure
|
|
76
|
+
|
|
77
|
+
The tool supports scripts from the n-p-x GitHub organization:
|
|
78
|
+
|
|
79
|
+
- Default repository: `n-p-x/e`
|
|
80
|
+
- Custom repositories: `n-p-x/{repo-name}`
|
|
81
|
+
|
|
82
|
+
### URL Resolution Examples
|
|
83
|
+
|
|
84
|
+
| Input | Resolved URL |
|
|
85
|
+
|-------|-------------|
|
|
86
|
+
| `my-script` | `https://raw.githubusercontent.com/n-p-x/e/main/my-script` |
|
|
87
|
+
| `docker/setup` | `https://raw.githubusercontent.com/n-p-x/docker/main/setup` |
|
|
88
|
+
| `https://example.com/script.sh` | `https://example.com/script.sh` |
|
|
89
|
+
|
|
90
|
+
## Requirements
|
|
91
|
+
|
|
92
|
+
### Linux/macOS
|
|
93
|
+
- Node.js (for nipox)
|
|
94
|
+
- bash or sh shell
|
|
95
|
+
|
|
96
|
+
### Windows
|
|
97
|
+
- Node.js (for nipox)
|
|
98
|
+
- One of the following:
|
|
99
|
+
- **Git for Windows** (includes Git Bash) - Recommended
|
|
100
|
+
- **Windows Subsystem for Linux (WSL)**
|
|
101
|
+
- PowerShell (limited support)
|
|
102
|
+
|
|
103
|
+
## Troubleshooting
|
|
104
|
+
|
|
105
|
+
### "No compatible shell found" Error
|
|
106
|
+
|
|
107
|
+
**On Windows:**
|
|
108
|
+
1. Install [Git for Windows](https://git-scm.com/download/win) (includes Git Bash)
|
|
109
|
+
2. Install [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/install)
|
|
110
|
+
|
|
111
|
+
**On Linux:**
|
|
112
|
+
```bash
|
|
113
|
+
# Ubuntu/Debian
|
|
114
|
+
sudo apt install bash
|
|
115
|
+
|
|
116
|
+
# CentOS/RHEL/Fedora
|
|
117
|
+
sudo yum install bash
|
|
118
|
+
# or
|
|
119
|
+
sudo dnf install bash
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**On macOS:**
|
|
123
|
+
```bash
|
|
124
|
+
# Using Homebrew
|
|
125
|
+
brew install bash
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Download Errors
|
|
129
|
+
- Check your internet connection
|
|
130
|
+
- Verify the URL is accessible
|
|
131
|
+
- Ensure the script exists in the specified repository
|
|
132
|
+
|
|
133
|
+
## Development
|
|
134
|
+
|
|
135
|
+
### Building from Source
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
git clone https://github.com/asfandyarsheikh/nipox.git
|
|
139
|
+
cd nipox
|
|
140
|
+
npm install
|
|
141
|
+
npm run build
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Project Structure
|
|
145
|
+
```
|
|
146
|
+
├── src/
|
|
147
|
+
│ └── index.js # Main application logic
|
|
148
|
+
├── dist/ # Compiled output (generated)
|
|
149
|
+
├── package.json # Package configuration
|
|
150
|
+
├── tsup.config.js # Build configuration
|
|
151
|
+
└── README.md # This file
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## License
|
|
155
|
+
|
|
156
|
+
ISC License
|
|
157
|
+
|
|
158
|
+
## Author
|
|
159
|
+
|
|
160
|
+
Asfandyar Sheikh
|
|
161
|
+
|
|
162
|
+
## Contributing
|
|
163
|
+
|
|
164
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
165
|
+
|
|
166
|
+
## Related Projects
|
|
167
|
+
|
|
168
|
+
- [@go-task/cli](https://taskfile.dev/) - Task runner used for YAML file execution
|
|
169
|
+
- [n-p-x organization](https://github.com/n-p-x) - Default source for scripts
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,29 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{spawn as f}from"child_process";import{createWriteStream as
|
|
2
|
+
import{spawn as f}from"child_process";import{createWriteStream as x,unlinkSync as h,chmodSync as S}from"fs";import{tmpdir as g,platform as m}from"os";import{join as u}from"path";import{pipeline as y}from"stream/promises";function E(){return m()==="win32"?{shells:[{command:"bash",args:[],name:"Git Bash/WSL"},{command:"wsl",args:["bash"],name:"WSL bash"},{command:"powershell",args:["-File"],name:"PowerShell",extension:".ps1"}],scriptExtension:".sh"}:{shells:[{command:"bash",args:[],name:"bash"},{command:"sh",args:[],name:"sh"}],scriptExtension:".sh"}}function b(e){return e.toLowerCase().endsWith(".yml")||e.toLowerCase().endsWith(".yaml")}function P(e){return e.toLowerCase().endsWith(".js")}function $(e,r){return new Promise((o,t)=>{let n=["@go-task/cli","--dir",process.cwd(),"--taskfile",e,...r],i=f("npx",n,{stdio:"inherit",shell:!1});i.on("close",s=>{o(s)}),i.on("error",s=>{t(s)})})}function v(scriptPath,args){return new Promise(async(resolve,reject)=>{try{let fs=await import("fs"),path=await import("path"),scriptContent=fs.readFileSync(scriptPath,"utf8"),hasES6Modules=/^\s*(import|export)\s+/m.test(scriptContent),dependencies=[];try{let depsMatch=scriptContent.match(/(?:const|let|var|export\s+const)\s+deps\s*=\s*(\[[^\]]*\])/);if(depsMatch)try{dependencies=JSON.parse(depsMatch[1])}catch(parseError){try{dependencies=eval(depsMatch[1])}catch(e){console.error(`Debug: Failed to eval deps array: ${e.message}`)}}}catch(e){console.error(`Debug: Exception during extraction: ${e.message}`)}let tempProjectDir=u(g(),`nipox-project-${Date.now()}`);fs.mkdirSync(tempProjectDir);let packageJson={name:"nipox-temp-project",version:"1.0.0",type:hasES6Modules?"module":"commonjs",dependencies:{}};for(let e of dependencies)packageJson.dependencies[e]="latest";fs.writeFileSync(u(tempProjectDir,"package.json"),JSON.stringify(packageJson,null,2));let tempScriptName="script.js",tempScriptPath=u(tempProjectDir,tempScriptName),modifiedContent=`${scriptContent}
|
|
3
|
+
|
|
4
|
+
// Parse command line arguments (added by nipox)
|
|
5
|
+
const scriptArgs = process.argv.slice(2);
|
|
6
|
+
const positional = [];
|
|
7
|
+
const named = {};
|
|
8
|
+
|
|
9
|
+
for (let i = 0; i < scriptArgs.length; i++) {
|
|
10
|
+
const arg = scriptArgs[i];
|
|
11
|
+
if (arg.startsWith('--')) {
|
|
12
|
+
const key = arg.substring(2);
|
|
13
|
+
const nextArg = scriptArgs[i + 1];
|
|
14
|
+
if (nextArg && !nextArg.startsWith('--')) {
|
|
15
|
+
named[key] = nextArg;
|
|
16
|
+
i++; // Skip the next argument as it's the value
|
|
17
|
+
} else {
|
|
18
|
+
named[key] = true;
|
|
19
|
+
}
|
|
20
|
+
} else {
|
|
21
|
+
positional.push(arg);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Execute the script function if it exists (added by nipox)
|
|
26
|
+
if (typeof script === 'function') {
|
|
27
|
+
script({ positional, named });
|
|
28
|
+
}
|
|
29
|
+
`;fs.writeFileSync(tempScriptPath,modifiedContent),console.error(`Executing JavaScript${hasES6Modules?" (ES6)":""} with dependencies: ${dependencies.join(", ")||"none"}`);let child=f("npx",["--yes","--","npm","install","&&","node",tempScriptName,...args],{stdio:"inherit",shell:!0,cwd:tempProjectDir});child.on("close",e=>{try{fs.rmSync(tempProjectDir,{recursive:!0,force:!0})}catch(r){console.error(`Cleanup warning: ${r.message}`)}resolve(e)}),child.on("error",e=>{try{fs.rmSync(tempProjectDir,{recursive:!0,force:!0})}catch(r){console.error(`Cleanup warning: ${r.message}`)}reject(e)})}catch(e){reject(e)}})}async function W(e,r){let o=await fetch(e,{headers:{"Cache-Control":"no-cache, no-store, must-revalidate",Pragma:"no-cache",Expires:"0"}});if(!o.ok)throw new Error(`Failed to download: ${o.status} ${o.statusText}`);let t=x(r);await y(o.body,t)}async function j(e){for(let r of e)try{let o=f(r.command,["--version"],{stdio:"pipe",shell:!1});return await new Promise((t,n)=>{let i=setTimeout(()=>{o.kill(),n(new Error("Timeout"))},3e3);o.on("close",s=>{clearTimeout(i),s===0||s===null?t():n(new Error(`Exit code: ${s}`))}),o.on("error",n)}),r}catch(o){console.error(`${r.name} not available: ${o.message}`);continue}throw new Error("No compatible shell found. Please install bash, Git for Windows, or WSL.")}function k(e,r,o){return new Promise((t,n)=>{let i;if(o.extension===".ps1"){n(new Error("PowerShell execution not yet implemented. Please install Git Bash or WSL."));return}else i=[...o.args,e,...r];let s=f(o.command,i,{stdio:"inherit",shell:!1,cwd:process.cwd()});s.on("close",l=>{t(l)}),s.on("error",l=>{n(l)})})}async function D(){let e=process.argv.slice(2);e.length===0&&(console.error("Usage: npx nipox <url|script-name> [args...]"),console.error(""),console.error("Examples:"),console.error(" npx nipox https://example.com/script.sh arg1 arg2"),console.error(" npx nipox my-script arg1 arg2 # downloads from n-p-x/e repo"),console.error(" npx nipox repo/my-script arg1 arg2 # downloads from n-p-x/repo"),console.error(""),console.error("Platform:",m()),process.exit(1));let[r,...o]=e,t;if(r.startsWith("http://")||r.startsWith("https://"))t=r;else if(r.includes("/")){let[a,...d]=r.split("/"),p=d.join("/");t=`https://raw.githubusercontent.com/n-p-x/${a}/main/${p}`}else t=`https://raw.githubusercontent.com/n-p-x/e/main/${r}`;let n=E(),i=g(),s=b(t),l=P(t),w=s?".yml":l?".js":n.scriptExtension,c=u(i,`nipox-${Date.now()}${w}`);try{if(console.error(`Platform: ${m()}`),console.error(`Downloading: ${t}`),await W(t,c),m()!=="win32"&&S(c,493),s){console.error("Detected YAML file. Executing with Taskfile...");let p=await $(c,o);h(c),process.exit(p)}if(l){console.error("Detected JavaScript file. Executing with dependencies...");let p=await v(c,o);h(c),process.exit(p)}console.error("Finding compatible shell...");let a=await j(n.shells);console.error(`Using: ${a.name}`),console.error(`Executing: ${r} ${o.join(" ")}`);let d=await k(c,o,a);h(c),process.exit(d)}catch(a){try{h(c)}catch{}console.error(`Error: ${a.message}`),a.message.includes("No compatible shell found")&&(console.error(""),console.error("Solutions:"),m()==="win32"?(console.error(" - Install Git for Windows (includes Git Bash)"),console.error(" - Install Windows Subsystem for Linux (WSL)"),console.error(" - Use PowerShell (limited support)")):(console.error(" - Install bash: sudo apt install bash (Ubuntu/Debian)"),console.error(" - Install bash: brew install bash (macOS)"))),process.exit(1)}}(async()=>await D())();
|