sharp 0.32.6 → 0.33.0-alpha.4

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/lib/utility.js CHANGED
@@ -3,13 +3,11 @@
3
3
 
4
4
  'use strict';
5
5
 
6
- const fs = require('fs');
7
- const path = require('path');
8
- const events = require('events');
6
+ const events = require('node:events');
9
7
  const detectLibc = require('detect-libc');
10
8
 
11
9
  const is = require('./is');
12
- const platformAndArch = require('./platform')();
10
+ const { runtimePlatformArch } = require('./libvips');
13
11
  const sharp = require('./sharp');
14
12
 
15
13
  /**
@@ -55,25 +53,14 @@ let versions = {
55
53
  vips: sharp.libvipsVersion()
56
54
  };
57
55
  try {
58
- versions = require(`../vendor/${versions.vips}/${platformAndArch}/versions.json`);
59
- } catch (_err) { /* ignore */ }
56
+ versions = require(`@sharpen/sharp-${runtimePlatformArch()}/versions`);
57
+ } catch (_) {
58
+ try {
59
+ versions = require(`@sharpen/sharp-libvips-${runtimePlatformArch()}/versions`);
60
+ } catch (_) {}
61
+ }
60
62
  versions.sharp = require('../package.json').version;
61
63
 
62
- /**
63
- * An Object containing the platform and architecture
64
- * of the current and installed vendored binaries.
65
- * @member
66
- * @example
67
- * console.log(sharp.vendor);
68
- */
69
- const vendor = {
70
- current: platformAndArch,
71
- installed: []
72
- };
73
- try {
74
- vendor.installed = fs.readdirSync(path.join(__dirname, `../vendor/${versions.vips}`));
75
- } catch (_err) { /* ignore */ }
76
-
77
64
  /**
78
65
  * Gets or, when options are provided, sets the limits of _libvips'_ operation cache.
79
66
  * Existing entries in the cache will be trimmed after any change in limits.
@@ -280,7 +267,6 @@ module.exports = function (Sharp) {
280
267
  Sharp.format = format;
281
268
  Sharp.interpolators = interpolators;
282
269
  Sharp.versions = versions;
283
- Sharp.vendor = vendor;
284
270
  Sharp.queue = queue;
285
271
  Sharp.block = block;
286
272
  Sharp.unblock = unblock;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sharp",
3
3
  "description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, GIF, AVIF and TIFF images",
4
- "version": "0.32.6",
4
+ "version": "0.33.0-alpha.4",
5
5
  "author": "Lovell Fuller <npm@lovell.info>",
6
6
  "homepage": "https://github.com/lovell/sharp",
7
7
  "contributors": [
@@ -89,29 +89,32 @@
89
89
  "Lachlan Newman <lachnewman007@gmail.com>"
90
90
  ],
91
91
  "scripts": {
92
- "install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node install/can-compile && node-gyp rebuild && node install/dll-copy)",
93
- "clean": "rm -rf node_modules/ build/ vendor/ .nyc_output/ coverage/ test/fixtures/output.*",
92
+ "install": "node install/check",
93
+ "clean": "rm -rf build/ .nyc_output/ coverage/ test/fixtures/output.*",
94
94
  "test": "npm run test-lint && npm run test-unit && npm run test-licensing && npm run test-types",
95
95
  "test-lint": "semistandard && cpplint",
96
96
  "test-unit": "nyc --reporter=lcov --reporter=text --check-coverage --branches=100 mocha",
97
- "test-licensing": "license-checker --production --summary --onlyAllow=\"Apache-2.0;BSD;ISC;MIT\"",
97
+ "test-licensing": "license-checker --production --summary --onlyAllow=\"Apache-2.0;BSD;ISC;LGPL-3.0-or-later;MIT\"",
98
98
  "test-leak": "./test/leak/leak.sh",
99
99
  "test-types": "tsd",
100
+ "package-from-local-build": "node npm/from-local-build",
101
+ "package-from-github-release": "node npm/from-github-release",
100
102
  "docs-build": "node docs/build && node docs/search-index/build",
101
103
  "docs-serve": "cd docs && npx serve",
102
104
  "docs-publish": "cd docs && npx firebase-tools deploy --project pixelplumbing --only hosting:pixelplumbing-sharp"
103
105
  },
106
+ "type": "commonjs",
104
107
  "main": "lib/index.js",
105
108
  "types": "lib/index.d.ts",
106
109
  "files": [
107
110
  "binding.gyp",
108
- "install/**",
109
- "lib/**",
110
- "src/**"
111
+ "install",
112
+ "lib",
113
+ "src"
111
114
  ],
112
115
  "repository": {
113
116
  "type": "git",
114
- "url": "git://github.com/lovell/sharp"
117
+ "url": "git://github.com/lovell/sharp.git"
115
118
  },
116
119
  "keywords": [
117
120
  "jpeg",
@@ -134,57 +137,57 @@
134
137
  "dependencies": {
135
138
  "color": "^4.2.3",
136
139
  "detect-libc": "^2.0.2",
137
- "node-addon-api": "^6.1.0",
138
- "prebuild-install": "^7.1.1",
139
- "semver": "^7.5.4",
140
- "simple-get": "^4.0.1",
141
- "tar-fs": "^3.0.4",
142
- "tunnel-agent": "^0.6.0"
140
+ "node-addon-api": "^7.0.0",
141
+ "semver": "^7.5.4"
142
+ },
143
+ "optionalDependencies": {
144
+ "@sharpen/sharp-darwin-arm64": "0.0.1-alpha.4",
145
+ "@sharpen/sharp-darwin-x64": "0.0.1-alpha.4",
146
+ "@sharpen/sharp-libvips-darwin-arm64": "0.0.1-alpha.2",
147
+ "@sharpen/sharp-libvips-darwin-x64": "0.0.1-alpha.2",
148
+ "@sharpen/sharp-libvips-linux-arm": "0.0.1-alpha.2",
149
+ "@sharpen/sharp-libvips-linux-arm64": "0.0.1-alpha.2",
150
+ "@sharpen/sharp-libvips-linux-x64": "0.0.1-alpha.2",
151
+ "@sharpen/sharp-libvips-linuxmusl-arm64": "0.0.1-alpha.2",
152
+ "@sharpen/sharp-libvips-linuxmusl-x64": "0.0.1-alpha.2",
153
+ "@sharpen/sharp-linux-arm": "0.0.1-alpha.4",
154
+ "@sharpen/sharp-linux-arm64": "0.0.1-alpha.4",
155
+ "@sharpen/sharp-linux-x64": "0.0.1-alpha.4",
156
+ "@sharpen/sharp-linuxmusl-arm64": "0.0.1-alpha.4",
157
+ "@sharpen/sharp-linuxmusl-x64": "0.0.1-alpha.4",
158
+ "@sharpen/sharp-win32-ia32": "0.0.1-alpha.4",
159
+ "@sharpen/sharp-win32-x64": "0.0.1-alpha.4"
143
160
  },
144
161
  "devDependencies": {
162
+ "@sharpen/sharp-libvips-dev": "0.0.1-alpha.2",
163
+ "@sharpen/sharp-libvips-win32-ia32": "0.0.1-alpha.2",
164
+ "@sharpen/sharp-libvips-win32-x64": "0.0.1-alpha.2",
145
165
  "@types/node": "*",
146
166
  "async": "^3.2.4",
147
167
  "cc": "^3.0.1",
148
- "exif-reader": "^1.2.0",
168
+ "exif-reader": "^2.0.0",
149
169
  "extract-zip": "^2.0.1",
150
170
  "icc": "^3.0.0",
151
171
  "jsdoc-to-markdown": "^8.0.0",
152
172
  "license-checker": "^25.0.1",
153
173
  "mocha": "^10.2.0",
154
- "mock-fs": "^5.2.0",
155
174
  "nyc": "^15.1.0",
156
- "prebuild": "^12.0.0",
157
- "semistandard": "^16.0.1",
175
+ "prebuild": "^12.1.0",
176
+ "semistandard": "^17.0.0",
177
+ "tar-fs": "^3.0.4",
158
178
  "tsd": "^0.29.0"
159
179
  },
160
180
  "license": "Apache-2.0",
161
- "config": {
162
- "libvips": "8.14.5",
163
- "integrity": {
164
- "darwin-arm64v8": "sha512-1QZzICfCJd4wAO0P6qmYI5e5VFMt9iCE4QgefI8VMMbdSzjIXA9L/ARN6pkMQPZ3h20Y9RtJ2W1skgCsvCIccw==",
165
- "darwin-x64": "sha512-sMIKMYXsdU9FlIfztj6Kt/SfHlhlDpP0Ups7ftVFqwjaszmYmpI9y/d/q3mLb4jrzuSiSUEislSWCwBnW7MPTw==",
166
- "linux-arm64v8": "sha512-CD8owELzkDumaom+O3jJ8fKamILAQdj+//KK/VNcHK3sngUcFpdjx36C8okwbux9sml/T7GTB/gzpvReDrAejQ==",
167
- "linux-armv6": "sha512-wk6IPHatDFVWKJy7lI1TJezHGHPQut1wF2bwx256KlZwXUQU3fcVcMpV1zxXjgLFewHq2+uhyMkoSGBPahWzlA==",
168
- "linux-armv7": "sha512-HEZC9KYtkmBK5rUR2MqBhrVarnQVZ/TwLUeLkKq0XuoM2pc/eXI6N0Fh5NGEFwdXI2XE8g1ySf+OYS6DDi+xCQ==",
169
- "linux-x64": "sha512-SlFWrITSW5XVUkaFPQOySAaSGXnhkGJCj8X2wGYYta9hk5piZldQyMp4zwy0z6UeRu1qKTKtZvmq28W3Gnh9xA==",
170
- "linuxmusl-arm64v8": "sha512-ga9iX7WUva3sG/VsKkOD318InLlCfPIztvzCZKZ2/+izQXRbQi8VoXWMHgEN4KHACv45FTl7mJ/8CRqUzhS8wQ==",
171
- "linuxmusl-x64": "sha512-yeaHnpfee1hrZLok2l4eFceHzlfq8gN3QOu0R4Mh8iMK5O5vAUu97bdtxeZZeJJvHw8tfh2/msGi0qysxKN8bw==",
172
- "win32-arm64v8": "sha512-kR91hy9w1+GEXK56hLh51+hBCBo7T+ijM4Slkmvb/2PsYZySq5H7s61n99iDYl6kTJP2y9sW5Xcvm3uuXDaDgg==",
173
- "win32-ia32": "sha512-HrnofEbzHNpHJ0vVnjsTj5yfgVdcqdWshXuwFO2zc8xlEjA83BvXZ0lVj9MxPxkxJ2ta+/UlLr+CFzc5bOceMw==",
174
- "win32-x64": "sha512-BwKckinJZ0Fu/EcunqiLPwOLEBWp4xf8GV7nvmVuKKz5f6B+GxoA2k9aa2wueqv4r4RJVgV/aWXZWFKOIjre/Q=="
175
- },
176
- "runtime": "napi",
177
- "target": 7
178
- },
179
181
  "engines": {
180
- "node": ">=14.15.0"
182
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
183
+ "libvips": ">=8.14.5"
181
184
  },
182
185
  "funding": {
183
186
  "url": "https://opencollective.com/libvips"
184
187
  },
185
188
  "binary": {
186
189
  "napi_versions": [
187
- 7
190
+ 9
188
191
  ]
189
192
  },
190
193
  "semistandard": {
package/src/common.cc CHANGED
@@ -166,10 +166,10 @@ namespace sharp {
166
166
  }
167
167
 
168
168
  // How many tasks are in the queue?
169
- volatile int counterQueue = 0;
169
+ std::atomic<int> counterQueue{0};
170
170
 
171
171
  // How many tasks are being processed?
172
- volatile int counterProcess = 0;
172
+ std::atomic<int> counterProcess{0};
173
173
 
174
174
  // Filename extension checkers
175
175
  static bool EndsWith(std::string const &str, std::string const &end) {
@@ -363,12 +363,13 @@ namespace sharp {
363
363
  if (descriptor->isBuffer) {
364
364
  if (descriptor->rawChannels > 0) {
365
365
  // Raw, uncompressed pixel data
366
+ bool const is8bit = vips_band_format_is8bit(descriptor->rawDepth);
366
367
  image = VImage::new_from_memory(descriptor->buffer, descriptor->bufferLength,
367
368
  descriptor->rawWidth, descriptor->rawHeight, descriptor->rawChannels, descriptor->rawDepth);
368
369
  if (descriptor->rawChannels < 3) {
369
- image.get_image()->Type = VIPS_INTERPRETATION_B_W;
370
+ image.get_image()->Type = is8bit ? VIPS_INTERPRETATION_B_W : VIPS_INTERPRETATION_GREY16;
370
371
  } else {
371
- image.get_image()->Type = VIPS_INTERPRETATION_sRGB;
372
+ image.get_image()->Type = is8bit ? VIPS_INTERPRETATION_sRGB : VIPS_INTERPRETATION_RGB16;
372
373
  }
373
374
  if (descriptor->rawPremultiplied) {
374
375
  image = image.unpremultiply();
package/src/common.h CHANGED
@@ -7,6 +7,7 @@
7
7
  #include <string>
8
8
  #include <tuple>
9
9
  #include <vector>
10
+ #include <atomic>
10
11
 
11
12
  #include <napi.h>
12
13
  #include <vips/vips8>
@@ -161,10 +162,10 @@ namespace sharp {
161
162
  };
162
163
 
163
164
  // How many tasks are in the queue?
164
- extern volatile int counterQueue;
165
+ extern std::atomic<int> counterQueue;
165
166
 
166
167
  // How many tasks are being processed?
167
- extern volatile int counterProcess;
168
+ extern std::atomic<int> counterProcess;
168
169
 
169
170
  // Filename extension checkers
170
171
  bool IsJpeg(std::string const &str);
package/src/metadata.cc CHANGED
@@ -18,7 +18,7 @@ class MetadataWorker : public Napi::AsyncWorker {
18
18
 
19
19
  void Execute() {
20
20
  // Decrement queued task counter
21
- g_atomic_int_dec_and_test(&sharp::counterQueue);
21
+ sharp::counterQueue--;
22
22
 
23
23
  vips::VImage image;
24
24
  sharp::ImageType imageType = sharp::ImageType::UNKNOWN;
@@ -281,7 +281,7 @@ Napi::Value metadata(const Napi::CallbackInfo& info) {
281
281
  worker->Queue();
282
282
 
283
283
  // Increment queued task counter
284
- g_atomic_int_inc(&sharp::counterQueue);
284
+ sharp::counterQueue++;
285
285
 
286
286
  return info.Env().Undefined();
287
287
  }
package/src/pipeline.cc CHANGED
@@ -44,9 +44,9 @@ class PipelineWorker : public Napi::AsyncWorker {
44
44
  // libuv worker
45
45
  void Execute() {
46
46
  // Decrement queued task counter
47
- g_atomic_int_dec_and_test(&sharp::counterQueue);
47
+ sharp::counterQueue--;
48
48
  // Increment processing task counter
49
- g_atomic_int_inc(&sharp::counterProcess);
49
+ sharp::counterProcess++;
50
50
 
51
51
  try {
52
52
  // Open input
@@ -1289,8 +1289,8 @@ class PipelineWorker : public Napi::AsyncWorker {
1289
1289
  delete baton;
1290
1290
 
1291
1291
  // Decrement processing task counter
1292
- g_atomic_int_dec_and_test(&sharp::counterProcess);
1293
- Napi::Number queueLength = Napi::Number::New(env, static_cast<double>(sharp::counterQueue));
1292
+ sharp::counterProcess--;
1293
+ Napi::Number queueLength = Napi::Number::New(env, static_cast<int>(sharp::counterQueue));
1294
1294
  queueListener.MakeCallback(Receiver().Value(), { queueLength });
1295
1295
  }
1296
1296
 
@@ -1707,8 +1707,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
1707
1707
  worker->Queue();
1708
1708
 
1709
1709
  // Increment queued task counter
1710
- g_atomic_int_inc(&sharp::counterQueue);
1711
- Napi::Number queueLength = Napi::Number::New(info.Env(), static_cast<double>(sharp::counterQueue));
1710
+ Napi::Number queueLength = Napi::Number::New(info.Env(), static_cast<int>(++sharp::counterQueue));
1712
1711
  queueListener.MakeCallback(info.This(), { queueLength });
1713
1712
 
1714
1713
  return info.Env().Undefined();
package/src/sharp.cc CHANGED
@@ -1,6 +1,8 @@
1
1
  // Copyright 2013 Lovell Fuller and others.
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
+ #include <mutex> // NOLINT(build/c++11)
5
+
4
6
  #include <napi.h>
5
7
  #include <vips/vips8>
6
8
 
@@ -10,14 +12,11 @@
10
12
  #include "utilities.h"
11
13
  #include "stats.h"
12
14
 
13
- static void* sharp_vips_init(void*) {
14
- vips_init("sharp");
15
- return nullptr;
16
- }
17
-
18
15
  Napi::Object init(Napi::Env env, Napi::Object exports) {
19
- static GOnce sharp_vips_init_once = G_ONCE_INIT;
20
- g_once(&sharp_vips_init_once, static_cast<GThreadFunc>(sharp_vips_init), nullptr);
16
+ static std::once_flag sharp_vips_init_once;
17
+ std::call_once(sharp_vips_init_once, []() {
18
+ vips_init("sharp");
19
+ });
21
20
 
22
21
  g_log_set_handler("VIPS", static_cast<GLogLevelFlags>(G_LOG_LEVEL_WARNING),
23
22
  static_cast<GLogFunc>(sharp::VipsWarningCallback), nullptr);
package/src/stats.cc CHANGED
@@ -30,7 +30,7 @@ class StatsWorker : public Napi::AsyncWorker {
30
30
 
31
31
  void Execute() {
32
32
  // Decrement queued task counter
33
- g_atomic_int_dec_and_test(&sharp::counterQueue);
33
+ sharp::counterQueue--;
34
34
 
35
35
  vips::VImage image;
36
36
  sharp::ImageType imageType = sharp::ImageType::UNKNOWN;
@@ -177,7 +177,7 @@ Napi::Value stats(const Napi::CallbackInfo& info) {
177
177
  worker->Queue();
178
178
 
179
179
  // Increment queued task counter
180
- g_atomic_int_inc(&sharp::counterQueue);
180
+ sharp::counterQueue++;
181
181
 
182
182
  return info.Env().Undefined();
183
183
  }
package/src/utilities.cc CHANGED
@@ -70,8 +70,8 @@ Napi::Value concurrency(const Napi::CallbackInfo& info) {
70
70
  */
71
71
  Napi::Value counters(const Napi::CallbackInfo& info) {
72
72
  Napi::Object counters = Napi::Object::New(info.Env());
73
- counters.Set("queue", sharp::counterQueue);
74
- counters.Set("process", sharp::counterProcess);
73
+ counters.Set("queue", static_cast<int>(sharp::counterQueue));
74
+ counters.Set("process", static_cast<int>(sharp::counterProcess));
75
75
  return counters;
76
76
  }
77
77
 
@@ -1,14 +0,0 @@
1
- // Copyright 2013 Lovell Fuller and others.
2
- // SPDX-License-Identifier: Apache-2.0
3
-
4
- 'use strict';
5
-
6
- const libvips = require('../lib/libvips');
7
-
8
- try {
9
- if (!(libvips.useGlobalLibvips() || libvips.hasVendoredLibvips())) {
10
- process.exitCode = 1;
11
- }
12
- } catch (err) {
13
- process.exitCode = 1;
14
- }
@@ -1,40 +0,0 @@
1
- // Copyright 2013 Lovell Fuller and others.
2
- // SPDX-License-Identifier: Apache-2.0
3
-
4
- 'use strict';
5
-
6
- const fs = require('fs');
7
- const path = require('path');
8
-
9
- const libvips = require('../lib/libvips');
10
- const platform = require('../lib/platform');
11
-
12
- const minimumLibvipsVersion = libvips.minimumLibvipsVersion;
13
-
14
- const platformAndArch = platform();
15
-
16
- if (platformAndArch.startsWith('win32')) {
17
- const buildReleaseDir = path.join(__dirname, '..', 'build', 'Release');
18
- libvips.log(`Creating ${buildReleaseDir}`);
19
- try {
20
- libvips.mkdirSync(buildReleaseDir);
21
- } catch (err) {}
22
- const vendorLibDir = path.join(__dirname, '..', 'vendor', minimumLibvipsVersion, platformAndArch, 'lib');
23
- libvips.log(`Copying DLLs from ${vendorLibDir} to ${buildReleaseDir}`);
24
- try {
25
- fs
26
- .readdirSync(vendorLibDir)
27
- .filter(function (filename) {
28
- return /\.dll$/.test(filename);
29
- })
30
- .forEach(function (filename) {
31
- fs.copyFileSync(
32
- path.join(vendorLibDir, filename),
33
- path.join(buildReleaseDir, filename)
34
- );
35
- });
36
- } catch (err) {
37
- libvips.log(err);
38
- process.exit(1);
39
- }
40
- }
@@ -1,222 +0,0 @@
1
- // Copyright 2013 Lovell Fuller and others.
2
- // SPDX-License-Identifier: Apache-2.0
3
-
4
- 'use strict';
5
-
6
- const fs = require('fs');
7
- const os = require('os');
8
- const path = require('path');
9
- const stream = require('stream');
10
- const zlib = require('zlib');
11
- const { createHash } = require('crypto');
12
-
13
- const detectLibc = require('detect-libc');
14
- const semverCoerce = require('semver/functions/coerce');
15
- const semverLessThan = require('semver/functions/lt');
16
- const semverSatisfies = require('semver/functions/satisfies');
17
- const simpleGet = require('simple-get');
18
- const tarFs = require('tar-fs');
19
-
20
- const agent = require('../lib/agent');
21
- const libvips = require('../lib/libvips');
22
- const platform = require('../lib/platform');
23
-
24
- const minimumGlibcVersionByArch = {
25
- arm: '2.28',
26
- arm64: '2.17',
27
- x64: '2.17'
28
- };
29
-
30
- const hasSharpPrebuild = [
31
- 'darwin-x64',
32
- 'darwin-arm64',
33
- 'linux-arm64',
34
- 'linux-x64',
35
- 'linuxmusl-x64',
36
- 'linuxmusl-arm64',
37
- 'win32-ia32',
38
- 'win32-x64'
39
- ];
40
-
41
- const { minimumLibvipsVersion, minimumLibvipsVersionLabelled } = libvips;
42
- const localLibvipsDir = process.env.npm_config_sharp_libvips_local_prebuilds || '';
43
- const distHost = process.env.npm_config_sharp_libvips_binary_host || 'https://github.com/lovell/sharp-libvips/releases/download';
44
- const distBaseUrl = process.env.npm_config_sharp_dist_base_url || process.env.SHARP_DIST_BASE_URL || `${distHost}/v${minimumLibvipsVersionLabelled}/`;
45
- const installationForced = !!(process.env.npm_config_sharp_install_force || process.env.SHARP_INSTALL_FORCE);
46
-
47
- const fail = function (err) {
48
- libvips.log(err);
49
- if (err.code === 'EACCES') {
50
- libvips.log('Are you trying to install as a root or sudo user?');
51
- libvips.log('- For npm <= v6, try again with the "--unsafe-perm" flag');
52
- libvips.log('- For npm >= v8, the user must own the directory "npm install" is run in');
53
- }
54
- libvips.log('Please see https://sharp.pixelplumbing.com/install for required dependencies');
55
- process.exit(1);
56
- };
57
-
58
- const handleError = function (err) {
59
- if (installationForced) {
60
- libvips.log(`Installation warning: ${err.message}`);
61
- } else {
62
- throw err;
63
- }
64
- };
65
-
66
- const verifyIntegrity = function (platformAndArch) {
67
- const expected = libvips.integrity(platformAndArch);
68
- if (installationForced || !expected) {
69
- libvips.log(`Integrity check skipped for ${platformAndArch}`);
70
- return new stream.PassThrough();
71
- }
72
- const hash = createHash('sha512');
73
- return new stream.Transform({
74
- transform: function (chunk, _encoding, done) {
75
- hash.update(chunk);
76
- done(null, chunk);
77
- },
78
- flush: function (done) {
79
- const digest = `sha512-${hash.digest('base64')}`;
80
- if (expected !== digest) {
81
- try {
82
- libvips.removeVendoredLibvips();
83
- } catch (err) {
84
- libvips.log(err.message);
85
- }
86
- libvips.log(`Integrity expected: ${expected}`);
87
- libvips.log(`Integrity received: ${digest}`);
88
- done(new Error(`Integrity check failed for ${platformAndArch}`));
89
- } else {
90
- libvips.log(`Integrity check passed for ${platformAndArch}`);
91
- done();
92
- }
93
- }
94
- });
95
- };
96
-
97
- const extractTarball = function (tarPath, platformAndArch) {
98
- const versionedVendorPath = path.join(__dirname, '..', 'vendor', minimumLibvipsVersion, platformAndArch);
99
- libvips.mkdirSync(versionedVendorPath);
100
-
101
- const ignoreVendorInclude = hasSharpPrebuild.includes(platformAndArch) && !process.env.npm_config_build_from_source;
102
- const ignore = function (name) {
103
- return ignoreVendorInclude && name.includes('include/');
104
- };
105
-
106
- stream.pipeline(
107
- fs.createReadStream(tarPath),
108
- verifyIntegrity(platformAndArch),
109
- new zlib.BrotliDecompress(),
110
- tarFs.extract(versionedVendorPath, { ignore }),
111
- function (err) {
112
- if (err) {
113
- if (/unexpected end of file/.test(err.message)) {
114
- fail(new Error(`Please delete ${tarPath} as it is not a valid tarball`));
115
- }
116
- fail(err);
117
- }
118
- }
119
- );
120
- };
121
-
122
- try {
123
- const useGlobalLibvips = libvips.useGlobalLibvips();
124
-
125
- if (useGlobalLibvips) {
126
- const globalLibvipsVersion = libvips.globalLibvipsVersion();
127
- libvips.log(`Detected globally-installed libvips v${globalLibvipsVersion}`);
128
- libvips.log('Building from source via node-gyp');
129
- process.exit(1);
130
- } else if (libvips.hasVendoredLibvips()) {
131
- libvips.log(`Using existing vendored libvips v${minimumLibvipsVersion}`);
132
- } else {
133
- // Is this arch/platform supported?
134
- const arch = process.env.npm_config_arch || process.arch;
135
- const platformAndArch = platform();
136
- if (arch === 'ia32' && !platformAndArch.startsWith('win32')) {
137
- throw new Error(`Intel Architecture 32-bit systems require manual installation of libvips >= ${minimumLibvipsVersion}`);
138
- }
139
- if (platformAndArch === 'freebsd-x64' || platformAndArch === 'openbsd-x64' || platformAndArch === 'sunos-x64') {
140
- throw new Error(`BSD/SunOS systems require manual installation of libvips >= ${minimumLibvipsVersion}`);
141
- }
142
- // Linux libc version check
143
- const libcVersionRaw = detectLibc.versionSync();
144
- if (libcVersionRaw) {
145
- const libcFamily = detectLibc.familySync();
146
- const libcVersion = semverCoerce(libcVersionRaw).version;
147
- if (libcFamily === detectLibc.GLIBC && minimumGlibcVersionByArch[arch]) {
148
- if (semverLessThan(libcVersion, semverCoerce(minimumGlibcVersionByArch[arch]).version)) {
149
- handleError(new Error(`Use with glibc ${libcVersionRaw} requires manual installation of libvips >= ${minimumLibvipsVersion}`));
150
- }
151
- }
152
- if (libcFamily === detectLibc.MUSL) {
153
- if (semverLessThan(libcVersion, '1.1.24')) {
154
- handleError(new Error(`Use with musl ${libcVersionRaw} requires manual installation of libvips >= ${minimumLibvipsVersion}`));
155
- }
156
- }
157
- }
158
- // Node.js minimum version check
159
- const supportedNodeVersion = process.env.npm_package_engines_node || require('../package.json').engines.node;
160
- if (!semverSatisfies(process.versions.node, supportedNodeVersion)) {
161
- handleError(new Error(`Expected Node.js version ${supportedNodeVersion} but found ${process.versions.node}`));
162
- }
163
- // Download to per-process temporary file
164
- const tarFilename = ['libvips', minimumLibvipsVersionLabelled, platformAndArch].join('-') + '.tar.br';
165
- const tarPathCache = path.join(libvips.cachePath(), tarFilename);
166
- if (fs.existsSync(tarPathCache)) {
167
- libvips.log(`Using cached ${tarPathCache}`);
168
- extractTarball(tarPathCache, platformAndArch);
169
- } else if (localLibvipsDir) {
170
- // If localLibvipsDir is given try to use binaries from local directory
171
- const tarPathLocal = path.join(path.resolve(localLibvipsDir), `v${minimumLibvipsVersionLabelled}`, tarFilename);
172
- libvips.log(`Using local libvips from ${tarPathLocal}`);
173
- extractTarball(tarPathLocal, platformAndArch);
174
- } else {
175
- const url = distBaseUrl + tarFilename;
176
- libvips.log(`Downloading ${url}`);
177
- simpleGet({ url: url, agent: agent(libvips.log) }, function (err, response) {
178
- if (err) {
179
- fail(err);
180
- } else if (response.statusCode === 404) {
181
- fail(new Error(`Prebuilt libvips ${minimumLibvipsVersion} binaries are not yet available for ${platformAndArch}`));
182
- } else if (response.statusCode !== 200) {
183
- fail(new Error(`Status ${response.statusCode} ${response.statusMessage}`));
184
- } else {
185
- const tarPathTemp = path.join(os.tmpdir(), `${process.pid}-${tarFilename}`);
186
- const tmpFileStream = fs.createWriteStream(tarPathTemp);
187
- response
188
- .on('error', function (err) {
189
- tmpFileStream.destroy(err);
190
- })
191
- .on('close', function () {
192
- if (!response.complete) {
193
- tmpFileStream.destroy(new Error('Download incomplete (connection was terminated)'));
194
- }
195
- })
196
- .pipe(tmpFileStream);
197
- tmpFileStream
198
- .on('error', function (err) {
199
- // Clean up temporary file
200
- try {
201
- fs.unlinkSync(tarPathTemp);
202
- } catch (e) {}
203
- fail(err);
204
- })
205
- .on('close', function () {
206
- try {
207
- // Attempt to rename
208
- fs.renameSync(tarPathTemp, tarPathCache);
209
- } catch (err) {
210
- // Fall back to copy and unlink
211
- fs.copyFileSync(tarPathTemp, tarPathCache);
212
- fs.unlinkSync(tarPathTemp);
213
- }
214
- extractTarball(tarPathCache, platformAndArch);
215
- });
216
- }
217
- });
218
- }
219
- }
220
- } catch (err) {
221
- fail(err);
222
- }