hookreplay 1.0.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 +78 -0
- package/package.json +43 -0
- package/scripts/install.js +158 -0
- package/scripts/uninstall.js +13 -0
package/README.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# HookReplay CLI
|
|
2
|
+
|
|
3
|
+
Debug webhooks locally. Capture, inspect, and replay webhooks to your local development server.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# npm
|
|
9
|
+
npm install -g hookreplay
|
|
10
|
+
|
|
11
|
+
# yarn
|
|
12
|
+
yarn global add hookreplay
|
|
13
|
+
|
|
14
|
+
# pnpm
|
|
15
|
+
pnpm add -g hookreplay
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
1. **Get an API key** from [hookreplay.com/settings/api-keys](https://hookreplay.com/settings/api-keys)
|
|
21
|
+
|
|
22
|
+
2. **Configure and connect:**
|
|
23
|
+
```bash
|
|
24
|
+
hookreplay
|
|
25
|
+
> config api-key YOUR_API_KEY
|
|
26
|
+
> connect
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
3. **Receive webhooks** - Click "Send to CLI" in the web interface to forward requests to your local server.
|
|
30
|
+
|
|
31
|
+
## Commands
|
|
32
|
+
|
|
33
|
+
| Command | Description |
|
|
34
|
+
|---------|-------------|
|
|
35
|
+
| `help` | Show available commands |
|
|
36
|
+
| `config api-key <key>` | Set your API key |
|
|
37
|
+
| `config server <url>` | Set server URL |
|
|
38
|
+
| `connect` | Connect and wait for replays |
|
|
39
|
+
| `disconnect` | Disconnect from server |
|
|
40
|
+
| `status` | Show connection status |
|
|
41
|
+
| `history` | Show received requests |
|
|
42
|
+
| `replay <id> [url]` | Replay a request |
|
|
43
|
+
| `quit` | Exit the CLI |
|
|
44
|
+
|
|
45
|
+
## How It Works
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
Webhook Provider → HookReplay → CLI → localhost:3000
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
1. Create a webhook endpoint at [hookreplay.com](https://hookreplay.com)
|
|
52
|
+
2. Point your webhook provider to your HookReplay URL
|
|
53
|
+
3. Webhooks are captured and stored
|
|
54
|
+
4. Connect CLI and click "Send to CLI" to forward to localhost
|
|
55
|
+
5. Debug with your IDE's breakpoints
|
|
56
|
+
|
|
57
|
+
## Alternative Installation
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# .NET Tool (requires .NET 9+)
|
|
61
|
+
dotnet tool install --global HookReplay.Cli
|
|
62
|
+
|
|
63
|
+
# Homebrew (macOS)
|
|
64
|
+
brew install hookreplay/tap/hookreplay
|
|
65
|
+
|
|
66
|
+
# Direct download
|
|
67
|
+
# https://github.com/hookreplay/hookreplay/releases
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Links
|
|
71
|
+
|
|
72
|
+
- **Website:** https://hookreplay.com
|
|
73
|
+
- **GitHub:** https://github.com/hookreplay/hookreplay
|
|
74
|
+
- **Issues:** https://github.com/hookreplay/hookreplay/issues
|
|
75
|
+
|
|
76
|
+
## License
|
|
77
|
+
|
|
78
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "hookreplay",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Debug webhooks locally - capture, inspect, and replay webhooks to your local server",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"webhook",
|
|
7
|
+
"debugging",
|
|
8
|
+
"cli",
|
|
9
|
+
"developer-tools",
|
|
10
|
+
"api",
|
|
11
|
+
"http",
|
|
12
|
+
"tunnel"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://hookreplay.com",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/hookreplay/hookreplay/issues"
|
|
17
|
+
},
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "https://github.com/hookreplay/hookreplay.git"
|
|
21
|
+
},
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"author": "HookReplay",
|
|
24
|
+
"bin": {
|
|
25
|
+
"hookreplay": "bin/hookreplay"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"postinstall": "node scripts/install.js",
|
|
29
|
+
"preuninstall": "node scripts/uninstall.js"
|
|
30
|
+
},
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=14"
|
|
33
|
+
},
|
|
34
|
+
"os": [
|
|
35
|
+
"darwin",
|
|
36
|
+
"linux",
|
|
37
|
+
"win32"
|
|
38
|
+
],
|
|
39
|
+
"cpu": [
|
|
40
|
+
"x64",
|
|
41
|
+
"arm64"
|
|
42
|
+
]
|
|
43
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const https = require('https');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const { execSync } = require('child_process');
|
|
7
|
+
const zlib = require('zlib');
|
|
8
|
+
|
|
9
|
+
const VERSION = require('../package.json').version;
|
|
10
|
+
const GITHUB_REPO = 'hookreplay/hookreplay';
|
|
11
|
+
|
|
12
|
+
// Platform mapping
|
|
13
|
+
const PLATFORMS = {
|
|
14
|
+
'darwin-x64': 'osx-x64',
|
|
15
|
+
'darwin-arm64': 'osx-arm64',
|
|
16
|
+
'linux-x64': 'linux-x64',
|
|
17
|
+
'linux-arm64': 'linux-arm64',
|
|
18
|
+
'win32-x64': 'win-x64',
|
|
19
|
+
'win32-arm64': 'win-arm64'
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
function getPlatformKey() {
|
|
23
|
+
const platform = process.platform;
|
|
24
|
+
const arch = process.arch;
|
|
25
|
+
return `${platform}-${arch}`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function getBinaryName() {
|
|
29
|
+
return process.platform === 'win32' ? 'hookreplay.exe' : 'hookreplay';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function getDownloadUrl(platformKey) {
|
|
33
|
+
const rid = PLATFORMS[platformKey];
|
|
34
|
+
if (!rid) {
|
|
35
|
+
throw new Error(`Unsupported platform: ${platformKey}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const ext = process.platform === 'win32' ? 'zip' : 'tar.gz';
|
|
39
|
+
return `https://github.com/${GITHUB_REPO}/releases/download/cli-v${VERSION}/hookreplay-${VERSION}-${rid}.${ext}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function downloadFile(url) {
|
|
43
|
+
return new Promise((resolve, reject) => {
|
|
44
|
+
const handleResponse = (response) => {
|
|
45
|
+
// Handle redirects
|
|
46
|
+
if (response.statusCode === 302 || response.statusCode === 301) {
|
|
47
|
+
https.get(response.headers.location, handleResponse).on('error', reject);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (response.statusCode !== 200) {
|
|
52
|
+
reject(new Error(`Failed to download: ${response.statusCode}`));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const chunks = [];
|
|
57
|
+
response.on('data', chunk => chunks.push(chunk));
|
|
58
|
+
response.on('end', () => resolve(Buffer.concat(chunks)));
|
|
59
|
+
response.on('error', reject);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
https.get(url, handleResponse).on('error', reject);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async function extractTarGz(buffer, destDir) {
|
|
67
|
+
const tar = require('tar');
|
|
68
|
+
const tmpFile = path.join(destDir, 'temp.tar.gz');
|
|
69
|
+
|
|
70
|
+
fs.writeFileSync(tmpFile, buffer);
|
|
71
|
+
|
|
72
|
+
await tar.extract({
|
|
73
|
+
file: tmpFile,
|
|
74
|
+
cwd: destDir
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
fs.unlinkSync(tmpFile);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function extractZip(buffer, destDir) {
|
|
81
|
+
const AdmZip = require('adm-zip');
|
|
82
|
+
const zip = new AdmZip(buffer);
|
|
83
|
+
zip.extractAllTo(destDir, true);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function install() {
|
|
87
|
+
const platformKey = getPlatformKey();
|
|
88
|
+
const binDir = path.join(__dirname, '..', 'bin');
|
|
89
|
+
const binaryName = getBinaryName();
|
|
90
|
+
const binaryPath = path.join(binDir, binaryName);
|
|
91
|
+
|
|
92
|
+
console.log(`Installing HookReplay CLI v${VERSION} for ${platformKey}...`);
|
|
93
|
+
|
|
94
|
+
// Check if binary already exists
|
|
95
|
+
if (fs.existsSync(binaryPath)) {
|
|
96
|
+
console.log('Binary already exists, skipping download.');
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
const url = getDownloadUrl(platformKey);
|
|
102
|
+
console.log(`Downloading from: ${url}`);
|
|
103
|
+
|
|
104
|
+
const buffer = await downloadFile(url);
|
|
105
|
+
console.log('Download complete. Extracting...');
|
|
106
|
+
|
|
107
|
+
// Ensure bin directory exists
|
|
108
|
+
if (!fs.existsSync(binDir)) {
|
|
109
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Extract based on platform
|
|
113
|
+
if (process.platform === 'win32') {
|
|
114
|
+
extractZip(buffer, binDir);
|
|
115
|
+
} else {
|
|
116
|
+
// For tar.gz, we need to use a simple extraction
|
|
117
|
+
const gunzip = zlib.gunzipSync(buffer);
|
|
118
|
+
|
|
119
|
+
// Simple tar extraction (single file)
|
|
120
|
+
// tar format: 512 byte header + file content
|
|
121
|
+
let offset = 0;
|
|
122
|
+
while (offset < gunzip.length) {
|
|
123
|
+
const header = gunzip.slice(offset, offset + 512);
|
|
124
|
+
if (header[0] === 0) break; // End of archive
|
|
125
|
+
|
|
126
|
+
const fileName = header.slice(0, 100).toString('utf8').replace(/\0/g, '').trim();
|
|
127
|
+
const fileSize = parseInt(header.slice(124, 136).toString('utf8').trim(), 8);
|
|
128
|
+
|
|
129
|
+
if (fileName && fileSize > 0) {
|
|
130
|
+
const content = gunzip.slice(offset + 512, offset + 512 + fileSize);
|
|
131
|
+
const destPath = path.join(binDir, path.basename(fileName));
|
|
132
|
+
fs.writeFileSync(destPath, content);
|
|
133
|
+
|
|
134
|
+
// Make executable on Unix
|
|
135
|
+
if (process.platform !== 'win32') {
|
|
136
|
+
fs.chmodSync(destPath, 0o755);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
offset += 512 + Math.ceil(fileSize / 512) * 512;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
console.log('HookReplay CLI installed successfully!');
|
|
145
|
+
console.log(`Run 'hookreplay' to get started.`);
|
|
146
|
+
|
|
147
|
+
} catch (error) {
|
|
148
|
+
console.error('Installation failed:', error.message);
|
|
149
|
+
console.error('');
|
|
150
|
+
console.error('Alternative installation methods:');
|
|
151
|
+
console.error(' - dotnet tool install --global HookReplay.Cli');
|
|
152
|
+
console.error(' - brew install hookreplay/tap/hookreplay (macOS)');
|
|
153
|
+
console.error(' - Download from https://github.com/hookreplay/hookreplay/releases');
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
install();
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
const binDir = path.join(__dirname, '..', 'bin');
|
|
7
|
+
const binaryName = process.platform === 'win32' ? 'hookreplay.exe' : 'hookreplay';
|
|
8
|
+
const binaryPath = path.join(binDir, binaryName);
|
|
9
|
+
|
|
10
|
+
if (fs.existsSync(binaryPath)) {
|
|
11
|
+
fs.unlinkSync(binaryPath);
|
|
12
|
+
console.log('HookReplay CLI uninstalled.');
|
|
13
|
+
}
|