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.
Files changed (3) hide show
  1. package/README.md +169 -0
  2. package/dist/index.js +28 -1
  3. 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 u,unlinkSync as d,chmodSync as w}from"fs";import{tmpdir as x,platform as m}from"os";import{join as g}from"path";import{pipeline as b}from"stream/promises";function S(){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 y(r){return r.toLowerCase().endsWith(".yml")||r.toLowerCase().endsWith(".yaml")}function E(r,e){return new Promise((o,s)=>{let t=["@go-task/cli","--dir",process.cwd(),"--taskfile",r,...e],i=f("npx",t,{stdio:"inherit",shell:!1});i.on("close",n=>{o(n)}),i.on("error",n=>{s(n)})})}async function $(r,e){let o=await fetch(r,{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 s=u(e);await b(o.body,s)}async function W(r){for(let e of r)try{let o=f(e.command,["--version"],{stdio:"pipe",shell:!1});return await new Promise((s,t)=>{let i=setTimeout(()=>{o.kill(),t(new Error("Timeout"))},3e3);o.on("close",n=>{clearTimeout(i),n===0||n===null?s():t(new Error(`Exit code: ${n}`))}),o.on("error",t)}),e}catch(o){console.error(`${e.name} not available: ${o.message}`);continue}throw new Error("No compatible shell found. Please install bash, Git for Windows, or WSL.")}function P(r,e,o){return new Promise((s,t)=>{let i;if(o.extension===".ps1"){t(new Error("PowerShell execution not yet implemented. Please install Git Bash or WSL."));return}else i=[...o.args,r,...e];let n=f(o.command,i,{stdio:"inherit",shell:!1,cwd:process.cwd()});n.on("close",c=>{s(c)}),n.on("error",c=>{t(c)})})}async function L(){let r=process.argv.slice(2);r.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[e,...o]=r,s;if(e.startsWith("http://")||e.startsWith("https://"))s=e;else if(e.includes("/")){let[l,...p]=e.split("/"),h=p.join("/");s=`https://raw.githubusercontent.com/n-p-x/${l}/main/${h}`}else s=`https://raw.githubusercontent.com/n-p-x/e/main/${e}`;let t=S(),i=x(),n=y(s),c=n?".yml":t.scriptExtension,a=g(i,`nipox-${Date.now()}${c}`);try{if(console.error(`Platform: ${m()}`),console.error(`Downloading: ${s}`),await $(s,a),m()!=="win32"&&w(a,493),n){console.error("Detected YAML file. Executing with Taskfile...");let h=await E(a,o);d(a),process.exit(h)}console.error("Finding compatible shell...");let l=await W(t.shells);console.error(`Using: ${l.name}`),console.error(`Executing: ${e} ${o.join(" ")}`);let p=await P(a,o,l);d(a),process.exit(p)}catch(l){try{d(a)}catch{}console.error(`Error: ${l.message}`),l.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 L())();
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())();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nipox",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Download and execute bash scripts.",
5
5
  "type": "module",
6
6
  "bin": "./dist/index.js",