recker 1.0.98 → 1.0.99

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/dist/version.js CHANGED
@@ -1,4 +1,4 @@
1
- const VERSION = '1.0.98';
1
+ const VERSION = '1.0.99';
2
2
  let _version = null;
3
3
  export async function getVersion() {
4
4
  if (_version)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "recker",
3
- "version": "1.0.98",
3
+ "version": "1.0.99",
4
4
  "description": "Multi-Protocol SDK for the AI Era - HTTP, WebSocket, DNS, FTP, SFTP, Telnet, HLS unified with AI providers and MCP tools",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -66,6 +66,7 @@
66
66
  "files": [
67
67
  "dist/**/*.js",
68
68
  "dist/**/*.d.ts",
69
+ "scripts/postinstall.cjs",
69
70
  "!dist/bin/**",
70
71
  "!dist/**/*.js.map",
71
72
  "!dist/browser/index.iife.js",
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const { promises: fs, constants, createWriteStream } = require('node:fs');
5
+ const { join, resolve } = require('node:path');
6
+ const { platform, arch } = require('node:os');
7
+ const { spawn } = require('node:child_process');
8
+ const { Readable } = require('node:stream');
9
+ const { finished } = require('node:stream/promises');
10
+
11
+ const SKIP_TOKEN = '1';
12
+ const DEFAULT_VERSION = 'v0.6.1';
13
+ const BIN_NAME = 'curl-impersonate-chrome';
14
+ const BIN_DIR = join(__dirname, '..', '.curl', 'bin');
15
+
16
+ const version = process.env.CURL_IMPERSONATE_VERSION || DEFAULT_VERSION;
17
+ const githubToken = process.env.GITHUB_TOKEN;
18
+
19
+ function getDownloadUrl() {
20
+ const p = platform();
21
+ const a = arch();
22
+ const base = `https://github.com/lwthiker/curl-impersonate/releases/download/${version}`;
23
+
24
+ if (p === 'linux') {
25
+ if (a === 'x64') return `${base}/curl-impersonate-${version}.x86_64-linux-gnu.tar.gz`;
26
+ if (a === 'arm64') return `${base}/curl-impersonate-${version}.aarch64-linux-gnu.tar.gz`;
27
+ }
28
+
29
+ // macOS and Windows: skip silently (not supported for auto-install)
30
+ return null;
31
+ }
32
+
33
+ async function exists(filePath) {
34
+ try {
35
+ await fs.access(filePath, constants.X_OK);
36
+ return true;
37
+ } catch {
38
+ return false;
39
+ }
40
+ }
41
+
42
+ async function verifyBinary(filePath) {
43
+ if (!await exists(filePath)) return false;
44
+
45
+ return new Promise((resolve) => {
46
+ let settled = false;
47
+ const child = spawn(filePath, ['--version']);
48
+
49
+ const settle = (ok) => {
50
+ if (!settled) {
51
+ settled = true;
52
+ resolve(ok);
53
+ }
54
+ };
55
+
56
+ child.on('error', () => settle(false));
57
+ child.on('close', (code) => settle(code === 0));
58
+
59
+ setTimeout(() => {
60
+ if (child.exitCode === null) child.kill();
61
+ settle(false);
62
+ }, 5_000);
63
+
64
+ child.on('close', () => {});
65
+ });
66
+ }
67
+
68
+ async function install() {
69
+ const url = getDownloadUrl();
70
+ if (!url) {
71
+ process.stdout.write(`recker: postinstall skipped (unsupported platform: ${platform()} ${arch()})\n`);
72
+ return;
73
+ }
74
+
75
+ const binPath = join(BIN_DIR, BIN_NAME);
76
+
77
+ // Already installed?
78
+ if (await verifyBinary(binPath)) {
79
+ process.stdout.write(`recker: curl-impersonate already installed at ${binPath}\n`);
80
+ return;
81
+ }
82
+
83
+ await fs.mkdir(BIN_DIR, { recursive: true });
84
+
85
+ process.stdout.write(`recker: downloading curl-impersonate ${version}...\n`);
86
+
87
+ const headers = githubToken ? { Authorization: `Bearer ${githubToken}` } : {};
88
+ const res = await fetch(url, { headers });
89
+ if (!res.ok) throw new Error(`Download failed: ${res.statusText}`);
90
+ if (!res.body) throw new Error('Empty response body');
91
+
92
+ const tarPath = join(BIN_DIR, 'curl-impersonate.tar.gz');
93
+ const fileStream = createWriteStream(tarPath);
94
+ await finished(Readable.fromWeb(res.body).pipe(fileStream));
95
+
96
+ // Extract
97
+ await new Promise((resolve, reject) => {
98
+ const tar = spawn('tar', ['-xzf', tarPath, '-C', BIN_DIR]);
99
+ tar.on('close', (code) => {
100
+ if (code === 0) resolve();
101
+ else reject(new Error(`tar exited with code ${code}`));
102
+ });
103
+ tar.on('error', reject);
104
+ });
105
+
106
+ // Cleanup tar
107
+ await fs.unlink(tarPath).catch(() => {});
108
+
109
+ // Verify
110
+ if (await verifyBinary(binPath)) {
111
+ process.stdout.write(`recker: installed curl-impersonate at ${binPath}\n`);
112
+ } else {
113
+ throw new Error('Binary not functional after extraction');
114
+ }
115
+ }
116
+
117
+ // Main
118
+ if (process.env.RECKER_SKIP_POSTINSTALL === SKIP_TOKEN) {
119
+ process.stdout.write('recker: postinstall skipped by RECKER_SKIP_POSTINSTALL=1\n');
120
+ process.exit(0);
121
+ }
122
+
123
+ install().catch((error) => {
124
+ process.stderr.write(`recker: postinstall skipped because download failed (${error.message})\n`);
125
+ process.exit(0); // Never break install
126
+ });