@xhmikosr/bin-wrapper 14.2.3 → 14.2.5
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/index.js +91 -65
- package/package.json +4 -5
- package/readme.md +1 -1
package/index.js
CHANGED
|
@@ -2,34 +2,42 @@ import {promises as fs} from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import binCheck from '@xhmikosr/bin-check';
|
|
4
4
|
import binaryVersionCheck from 'binary-version-check';
|
|
5
|
-
import
|
|
5
|
+
import downloader from '@xhmikosr/downloader';
|
|
6
6
|
import osFilterObject from '@xhmikosr/os-filter-obj';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* @
|
|
12
|
-
* @api public
|
|
9
|
+
* @typedef {Object} BinWrapperOptions
|
|
10
|
+
* @property {number} [strip=1] - Number of leading paths to strip from the archive.
|
|
11
|
+
* @property {boolean} [skipCheck=false] - Skip binary checks.
|
|
13
12
|
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @typedef {Object} SourceFile
|
|
16
|
+
* @property {string} url - The URL of the file.
|
|
17
|
+
* @property {string} [os] - The operating system the file is for.
|
|
18
|
+
* @property {string} [arch] - The architecture the file is for.
|
|
19
|
+
*/
|
|
20
|
+
|
|
14
21
|
export default class BinWrapper {
|
|
22
|
+
/**
|
|
23
|
+
* @param {BinWrapperOptions} [options]
|
|
24
|
+
*/
|
|
15
25
|
constructor(options = {}) {
|
|
16
|
-
|
|
26
|
+
const {strip = 1, skipCheck = false} = options;
|
|
17
27
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
this.options.strip = 1;
|
|
23
|
-
}
|
|
28
|
+
this.options = {
|
|
29
|
+
strip: Math.max(0, strip),
|
|
30
|
+
skipCheck,
|
|
31
|
+
};
|
|
24
32
|
}
|
|
25
33
|
|
|
26
34
|
/**
|
|
27
35
|
* Get or set files to download
|
|
28
36
|
*
|
|
29
|
-
* @param {
|
|
30
|
-
* @param {
|
|
31
|
-
* @param {
|
|
32
|
-
* @
|
|
37
|
+
* @param {string} [src] - The source URL of the file.
|
|
38
|
+
* @param {string} [os] - The operating system the file is for.
|
|
39
|
+
* @param {string} [arch] - The architecture the file is for.
|
|
40
|
+
* @returns {SourceFile[]|undefined|this} - Returns the source files if no arguments are provided, otherwise returns `this`.
|
|
33
41
|
*/
|
|
34
42
|
src(src, os, arch) {
|
|
35
43
|
if (arguments.length === 0) {
|
|
@@ -45,8 +53,8 @@ export default class BinWrapper {
|
|
|
45
53
|
/**
|
|
46
54
|
* Get or set the destination
|
|
47
55
|
*
|
|
48
|
-
* @param {
|
|
49
|
-
* @
|
|
56
|
+
* @param {string} [dest] - The destination path.
|
|
57
|
+
* @returns {string|undefined|this} - Returns the destination if no arguments are provided, otherwise returns `this`.
|
|
50
58
|
*/
|
|
51
59
|
dest(dest) {
|
|
52
60
|
if (arguments.length === 0) {
|
|
@@ -54,14 +62,15 @@ export default class BinWrapper {
|
|
|
54
62
|
}
|
|
55
63
|
|
|
56
64
|
this._dest = dest;
|
|
65
|
+
|
|
57
66
|
return this;
|
|
58
67
|
}
|
|
59
68
|
|
|
60
69
|
/**
|
|
61
70
|
* Get or set the binary
|
|
62
71
|
*
|
|
63
|
-
* @param {
|
|
64
|
-
* @
|
|
72
|
+
* @param {string} [bin] - The binary name.
|
|
73
|
+
* @returns {string|undefined|this} - Returns the binary name if no arguments are provided, otherwise returns `this`.
|
|
65
74
|
*/
|
|
66
75
|
use(bin) {
|
|
67
76
|
if (arguments.length === 0) {
|
|
@@ -69,14 +78,15 @@ export default class BinWrapper {
|
|
|
69
78
|
}
|
|
70
79
|
|
|
71
80
|
this._use = bin;
|
|
81
|
+
|
|
72
82
|
return this;
|
|
73
83
|
}
|
|
74
84
|
|
|
75
85
|
/**
|
|
76
86
|
* Get or set a semver range to test the binary against
|
|
77
87
|
*
|
|
78
|
-
* @param {
|
|
79
|
-
* @
|
|
88
|
+
* @param {string} [range] - The semver range.
|
|
89
|
+
* @returns {string|undefined|this} - Returns the semver range if no arguments are provided, otherwise returns `this`.
|
|
80
90
|
*/
|
|
81
91
|
version(range) {
|
|
82
92
|
if (arguments.length === 0) {
|
|
@@ -84,100 +94,116 @@ export default class BinWrapper {
|
|
|
84
94
|
}
|
|
85
95
|
|
|
86
96
|
this._version = range;
|
|
97
|
+
|
|
87
98
|
return this;
|
|
88
99
|
}
|
|
89
100
|
|
|
90
101
|
/**
|
|
91
102
|
* Get path to the binary
|
|
92
103
|
*
|
|
93
|
-
* @
|
|
104
|
+
* @returns {string} - The full path to the binary.
|
|
94
105
|
*/
|
|
95
106
|
path() {
|
|
96
107
|
return path.join(this.dest(), this.use());
|
|
97
108
|
}
|
|
98
109
|
|
|
99
110
|
/**
|
|
100
|
-
*
|
|
111
|
+
* Check for the binary and download it if missing, then optionally verify it works.
|
|
101
112
|
*
|
|
102
|
-
* @param {
|
|
103
|
-
* @
|
|
113
|
+
* @param {string[]} [cmd=['--version']] - Arguments passed to the binary when checking it.
|
|
114
|
+
* @returns {Promise<void>}
|
|
104
115
|
*/
|
|
105
|
-
run(cmd = ['--version']) {
|
|
106
|
-
|
|
107
|
-
if (this.options.skipCheck) {
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
116
|
+
async run(cmd = ['--version']) {
|
|
117
|
+
await this.findExisting();
|
|
110
118
|
|
|
111
|
-
|
|
112
|
-
|
|
119
|
+
if (this.options.skipCheck) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
await this.runCheck(cmd);
|
|
113
124
|
}
|
|
114
125
|
|
|
115
126
|
/**
|
|
116
127
|
* Run binary check
|
|
117
128
|
*
|
|
118
|
-
* @param {
|
|
129
|
+
* @param {string[]} cmd - Arguments to pass to the binary.
|
|
130
|
+
* @returns {Promise<void>}
|
|
119
131
|
* @api private
|
|
120
132
|
*/
|
|
121
|
-
runCheck(cmd) {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
133
|
+
async runCheck(cmd) {
|
|
134
|
+
const works = await binCheck(this.path(), cmd);
|
|
135
|
+
if (!works) {
|
|
136
|
+
throw new Error(`The "${this.path()}" binary doesn't seem to work correctly`);
|
|
137
|
+
}
|
|
126
138
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
});
|
|
139
|
+
if (this.version()) {
|
|
140
|
+
await binaryVersionCheck(this.path(), this.version());
|
|
141
|
+
}
|
|
131
142
|
}
|
|
132
143
|
|
|
133
144
|
/**
|
|
134
|
-
*
|
|
145
|
+
* Check whether the binary exists; download it if not.
|
|
135
146
|
*
|
|
147
|
+
* @returns {Promise<void>}
|
|
136
148
|
* @api private
|
|
137
149
|
*/
|
|
138
|
-
findExisting() {
|
|
139
|
-
|
|
150
|
+
async findExisting() {
|
|
151
|
+
try {
|
|
152
|
+
await fs.access(this.path());
|
|
153
|
+
} catch (error) {
|
|
140
154
|
if (error?.code === 'ENOENT') {
|
|
141
|
-
|
|
155
|
+
await this.download();
|
|
156
|
+
} else {
|
|
157
|
+
throw error;
|
|
142
158
|
}
|
|
143
|
-
|
|
144
|
-
throw error;
|
|
145
|
-
});
|
|
159
|
+
}
|
|
146
160
|
}
|
|
147
161
|
|
|
148
162
|
/**
|
|
149
|
-
* Download files
|
|
163
|
+
* Download files matching the current OS/arch and make them executable.
|
|
150
164
|
*
|
|
165
|
+
* @returns {Promise<void>}
|
|
151
166
|
* @api private
|
|
152
167
|
*/
|
|
153
|
-
download() {
|
|
168
|
+
async download() {
|
|
154
169
|
const files = osFilterObject(this.src() || []);
|
|
155
170
|
|
|
156
171
|
if (files.length === 0) {
|
|
157
|
-
|
|
172
|
+
throw new Error('No binary found matching your system. It\'s probably not supported.');
|
|
158
173
|
}
|
|
159
174
|
|
|
160
175
|
const urls = files.map(file => file.url);
|
|
161
176
|
|
|
162
|
-
|
|
163
|
-
|
|
177
|
+
const results = await Promise.all(urls.map(url =>
|
|
178
|
+
downloader(url, this.dest(), {
|
|
164
179
|
extract: true,
|
|
165
180
|
decompress: {
|
|
166
181
|
strip: this.options.strip,
|
|
167
182
|
},
|
|
168
|
-
})))
|
|
169
|
-
const resultFiles = result.flatMap((item, index) => {
|
|
170
|
-
if (Array.isArray(item)) {
|
|
171
|
-
return item.map(file => file.path);
|
|
172
|
-
}
|
|
183
|
+
})));
|
|
173
184
|
|
|
174
|
-
|
|
175
|
-
|
|
185
|
+
const resultFiles = results.flatMap((item, index) => {
|
|
186
|
+
if (Array.isArray(item)) {
|
|
187
|
+
return item.map(file => file.path);
|
|
188
|
+
}
|
|
176
189
|
|
|
177
|
-
|
|
178
|
-
});
|
|
190
|
+
const parsedUrl = new URL(files[index].url);
|
|
179
191
|
|
|
180
|
-
return
|
|
192
|
+
return path.parse(parsedUrl.pathname).base;
|
|
181
193
|
});
|
|
194
|
+
|
|
195
|
+
await Promise.all(resultFiles
|
|
196
|
+
.filter(Boolean)
|
|
197
|
+
.map(async file => {
|
|
198
|
+
try {
|
|
199
|
+
await fs.chmod(path.join(this.dest(), file), 0o755);
|
|
200
|
+
} catch (error) {
|
|
201
|
+
// We guess the saved name from the URL, but the downloader may
|
|
202
|
+
// have used a different one, so skip a missing file.
|
|
203
|
+
if (error?.code !== 'ENOENT') {
|
|
204
|
+
throw error;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}));
|
|
182
208
|
}
|
|
183
209
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xhmikosr/bin-wrapper",
|
|
3
|
-
"version": "14.2.
|
|
3
|
+
"version": "14.2.5",
|
|
4
4
|
"description": "Binary wrapper that makes your programs seamlessly available as local dependencies",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -42,21 +42,20 @@
|
|
|
42
42
|
],
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@xhmikosr/bin-check": "^8.2.1",
|
|
45
|
-
"@xhmikosr/downloader": "^16.1.
|
|
46
|
-
"@xhmikosr/os-filter-obj": "^4.
|
|
45
|
+
"@xhmikosr/downloader": "^16.1.3",
|
|
46
|
+
"@xhmikosr/os-filter-obj": "^4.1.0",
|
|
47
47
|
"binary-version-check": "^6.1.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"ava": "^7.0.0",
|
|
51
51
|
"c8": "^11.0.0",
|
|
52
52
|
"isexe": "^4.0.0",
|
|
53
|
-
"nock": "^14.0.
|
|
53
|
+
"nock": "^14.0.15",
|
|
54
54
|
"tempy": "^3.2.0",
|
|
55
55
|
"xo": "^2.0.2"
|
|
56
56
|
},
|
|
57
57
|
"xo": {
|
|
58
58
|
"rules": {
|
|
59
|
-
"promise/prefer-await-to-then": "off",
|
|
60
59
|
"unicorn/prevent-abbreviations": "off"
|
|
61
60
|
}
|
|
62
61
|
}
|
package/readme.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# bin-wrapper [](https://www.npmjs.com/package/@xhmikosr/bin-wrapper) [](https://github.com/XhmikosR/bin-wrapper/actions/workflows/ci.yml?query=branch%3Amaster)
|
|
1
|
+
# @xhmikosr/bin-wrapper [](https://www.npmjs.com/package/@xhmikosr/bin-wrapper) [](https://github.com/XhmikosR/bin-wrapper/actions/workflows/ci.yml?query=branch%3Amaster)
|
|
2
2
|
|
|
3
3
|
> Binary wrapper that makes your programs seamlessly available as local dependencies
|
|
4
4
|
|