UNPKG

install-module-linked

Version:
180 lines 8.79 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "default", { enumerable: true, get: function() { return ensureCached; } }); var _fs = /*#__PURE__*/ _interop_require_default(require("fs")); var _fsremovecompat = require("fs-remove-compat"); var _lockfile = /*#__PURE__*/ _interop_require_default(require("lockfile")); var _mkdirpclassic = /*#__PURE__*/ _interop_require_default(require("mkdirp-classic")); var _path = /*#__PURE__*/ _interop_require_default(require("path")); var _queuecb = /*#__PURE__*/ _interop_require_default(require("queue-cb")); var _tempsuffix = /*#__PURE__*/ _interop_require_default(require("temp-suffix")); var _getSpecifierts = /*#__PURE__*/ _interop_require_default(require("./getSpecifier.js")); var _installts = /*#__PURE__*/ _interop_require_default(require("./install.js")); var _parseInstallStringts = /*#__PURE__*/ _interop_require_default(require("./parseInstallString.js")); var _renameWithFallbackts = /*#__PURE__*/ _interop_require_default(require("./renameWithFallback.js")); function _array_like_to_array(arr, len) { if (len == null || len > arr.length) len = arr.length; for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i]; return arr2; } function _array_without_holes(arr) { if (Array.isArray(arr)) return _array_like_to_array(arr); } function _define_property(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _interop_require_default(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _iterable_to_array(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } function _non_iterable_spread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _object_spread(target) { for(var i = 1; i < arguments.length; i++){ var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === "function") { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function(key) { _define_property(target, key, source[key]); }); } return target; } function _to_consumable_array(arr) { return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread(); } function _unsupported_iterable_to_array(o, minLen) { if (!o) return; if (typeof o === "string") return _array_like_to_array(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen); } var LOCK_OPTIONS = { wait: 600000, pollPeriod: 100, stale: 660000, retries: 3 }; function ensureCached(installString, cachePath, callback) { (0, _getSpecifierts.default)(installString, function(err, specifier) { var doLockedInstall = function doLockedInstall() { // Ensure lock file's parent directory exists (handles scoped packages like @scope/pkg) (0, _mkdirpclassic.default)(_path.default.dirname(lockPath), function(mkdirErr) { if (mkdirErr) return callback(mkdirErr); var startTime = Date.now(); // Retry loop for Windows EPERM - treat it like EEXIST (lock held by another process) function tryLock(cb) { _lockfile.default.lock(lockPath, _object_spread({}, LOCK_OPTIONS), function(lockErr) { if (lockErr && lockErr.code === 'EPERM' && Date.now() - startTime < LOCK_OPTIONS.wait) { setTimeout(function() { return tryLock(cb); }, LOCK_OPTIONS.pollPeriod); return; } cb(lockErr); }); } tryLock(function(lockErr) { var done = // Single exit point - always unlock before calling back function done(err) { _lockfile.default.unlock(lockPath, function() { return callback(err, err ? undefined : cachedAt); }); }; if (lockErr) return callback(lockErr); // Re-check cache (another process may have completed while we waited for lock) _fs.default.stat(readyPath, function(readyErr) { if (!readyErr) return done(); // Cache appeared while we waited // Clean up any incomplete cache before installing (0, _fsremovecompat.safeRm)(cachedAt, function(rmErr) { if (rmErr) return done(rmErr); doInstall(done); }); }); }); }); }; var doInstall = function doInstall(cb) { var _path1; var tmp = "".concat(cachedAt, "-").concat((0, _tempsuffix.default)()); var tmpModulePath = (_path1 = _path.default).join.apply(_path1, [ tmp, 'node_modules' ].concat(_to_consumable_array(name.split('/')))); var queue = new _queuecb.default(1); queue.defer(function(cb) { return (0, _mkdirpclassic.default)(tmp, function(err) { return cb(err); }); }); queue.defer(function(cb) { return _fs.default.writeFile(_path.default.join(tmp, 'package.json'), '{}', 'utf8', function(err) { return cb(err); }); }); queue.defer(_installts.default.bind(null, specifier, tmp)); queue.defer(function(qcb) { // Verify npm actually created the package directory - npm may silently skip // installation (exit 0) when platform doesn't match (os/cpu/libc fields) _fs.default.stat(tmpModulePath, function(statErr) { if (statErr) return qcb(new Error("Package directory not created by npm. This may happen when the package has platform restrictions (os/cpu/libc) that don't match the current system: ".concat(tmpModulePath))); qcb(); }); }); queue.defer(_renameWithFallbackts.default.bind(null, tmpModulePath, cachedAt)); queue.defer(_renameWithFallbackts.default.bind(null, _path.default.join(tmp, 'node_modules'), _path.default.join(cachedAt, 'node_modules'))); // Write .ready marker after both renames succeed queue.defer(function(cb) { return _fs.default.writeFile(readyPath, '', 'utf8', function(err) { return cb(err); }); }); queue.await(function(queueErr) { // Clean up temp directory whether installed or not (0, _fsremovecompat.safeRm)(tmp, function() { return cb(queueErr); }); }); }; if (err) return callback(err); var cachedAt = _path.default.join(cachePath, specifier); var lockPath = "".concat(cachedAt, ".lock"); var readyPath = _path.default.join(cachedAt, '.ready'); var name = (0, _parseInstallStringts.default)(installString).name; // Check if already cached AND complete (fast path, no lock needed) _fs.default.stat(readyPath, function(readyErr) { if (!readyErr) return callback(undefined, cachedAt); // Valid cache // Not cached or incomplete - acquire lock and install doLockedInstall(); }); }); } /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }