You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

205 lines
6.7 KiB

"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.downloadAndExtractNpmModuleAsync = downloadAndExtractNpmModuleAsync;
exports.extractLocalNpmTarballAsync = extractLocalNpmTarballAsync;
exports.extractNpmTarballAsync = extractNpmTarballAsync;
exports.extractNpmTarballFromUrlAsync = extractNpmTarballFromUrlAsync;
exports.npmPackAsync = npmPackAsync;
exports.sanitizeNpmPackageName = sanitizeNpmPackageName;
function _spawnAsync() {
const data = _interopRequireDefault(require("@expo/spawn-async"));
_spawnAsync = function () {
return data;
};
return data;
}
function _fsExtra() {
const data = _interopRequireDefault(require("fs-extra"));
_fsExtra = function () {
return data;
};
return data;
}
function _path() {
const data = _interopRequireDefault(require("path"));
_path = function () {
return data;
};
return data;
}
function _slugify() {
const data = _interopRequireDefault(require("slugify"));
_slugify = function () {
return data;
};
return data;
}
function _stream() {
const data = require("stream");
_stream = function () {
return data;
};
return data;
}
function _tar() {
const data = _interopRequireDefault(require("tar"));
_tar = function () {
return data;
};
return data;
}
function _util() {
const data = require("util");
_util = function () {
return data;
};
return data;
}
function _xdl() {
const data = require("xdl");
_xdl = function () {
return data;
};
return data;
}
function _log() {
const data = _interopRequireDefault(require("../../log"));
_log = function () {
return data;
};
return data;
}
function _createFileTransform() {
const data = require("./createFileTransform");
_createFileTransform = function () {
return data;
};
return data;
}
function _FileSystemCache() {
const data = require("./fetch-cache/FileSystemCache");
_FileSystemCache = function () {
return data;
};
return data;
}
function _fetch() {
const data = _interopRequireDefault(require("./fetch-cache/fetch"));
_fetch = function () {
return data;
};
return data;
}
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const cachedFetch = (0, _fetch().default)(new (_FileSystemCache().FileSystemCache)({
cacheDirectory: getCacheFilePath()
// Time to live. How long (in ms) responses remain cached before being automatically ejected. If undefined, responses are never automatically ejected from the cache.
// ttl: 1000,
}));
function sanitizeNpmPackageName(name) {
// https://github.com/npm/validate-npm-package-name/#naming-rules
return applyKnownNpmPackageNameRules(name) || applyKnownNpmPackageNameRules((0, _slugify().default)(name)) ||
// If nothing is left use 'app' like we do in Xcode projects.
'app';
}
function applyKnownNpmPackageNameRules(name) {
// https://github.com/npm/validate-npm-package-name/#naming-rules
// package name cannot start with '.' or '_'.
while (/^(\.|_)/.test(name)) {
name = name.substring(1);
}
name = name.toLowerCase().replace(/[^a-zA-Z0-9._\-/@]/g, '');
return name
// .replace(/![a-z0-9-._~]+/g, '')
// Remove special characters
.normalize('NFD').replace(/[\u0300-\u036f]/g, '') || null;
}
async function npmPackAsync(packageName, cwd = undefined, ...props) {
var _await$spawnAsync$std;
const cmd = ['pack', packageName, ...props];
const cmdString = `npm ${cmd.join(' ')}`;
_log().default.debug('Run:', cmdString);
const results = (_await$spawnAsync$std = (await (0, _spawnAsync().default)('npm', [...cmd, '--json'], {
cwd
})).stdout) === null || _await$spawnAsync$std === void 0 ? void 0 : _await$spawnAsync$std.trim();
if (!results) {
return null;
}
try {
const parsedResults = JSON.parse(results);
const filename = parsedResults[0].filename;
// Transform filename for scoped packages.
// See issue https://github.com/npm/cli/issues/3405
if (filename !== null && filename !== void 0 && filename.startsWith('@') && packageName.startsWith('@')) {
parsedResults[0].filename = filename.replace(/^@/, '').replace(/\//, '-');
}
return parsedResults;
} catch (error) {
throw new Error(`Could not parse JSON returned from "${cmdString}".\n\n${results}\n\nError: ${error.message}`);
}
}
// @ts-ignore
const pipeline = (0, _util().promisify)(_stream().Stream.pipeline);
async function downloadAndExtractNpmModuleAsync(npmName, props) {
_log().default.debug(`Looking for tarball for ${npmName} in ${getCacheFilePath()}...`);
try {
var _await$fs$stat$catch$, _await$fs$stat$catch;
const cachePath = getCacheFilePath();
await _fsExtra().default.ensureDir(cachePath);
// Perform dry-run to get actual filename for resolved version
const filename = (await npmPackAsync(npmName, cachePath, '--dry-run'))[0].filename;
const cacheFilename = _path().default.join(cachePath, filename);
// TODO: This cache does not expire, but neither does the FileCache at the top of this file.
if ((_await$fs$stat$catch$ = !((_await$fs$stat$catch = await _fsExtra().default.stat(cacheFilename).catch(() => null)) !== null && _await$fs$stat$catch !== void 0 && _await$fs$stat$catch.isFile())) !== null && _await$fs$stat$catch$ !== void 0 ? _await$fs$stat$catch$ : false) {
_log().default.debug(`Downloading tarball for ${npmName} to ${cachePath}...`);
await npmPackAsync(npmName, cachePath);
}
await extractLocalNpmTarballAsync(cacheFilename, {
cwd: props.cwd,
name: props.name
});
} catch (error) {
_log().default.error('Error downloading and extracting template package:', error);
}
}
async function extractLocalNpmTarballAsync(tarFilePath, props) {
const readStream = _fsExtra().default.createReadStream(tarFilePath);
await extractNpmTarballAsync(readStream, props);
}
function getCacheFilePath() {
return _path().default.join(_xdl().UserSettings.dotExpoHomeDirectory(), 'template-cache');
}
async function createUrlStreamAsync(url) {
const response = await cachedFetch(url);
if (!response.ok) {
throw new Error(`Unexpected response: ${response.statusText}. From url: ${url}`);
}
return response.body;
}
async function extractNpmTarballFromUrlAsync(url, props) {
await extractNpmTarballAsync(await createUrlStreamAsync(url), props);
}
async function extractNpmTarballAsync(stream, props) {
const {
cwd,
strip,
name,
fileList = []
} = props;
await _fsExtra().default.ensureDir(cwd);
return pipeline(stream, _tar().default.extract({
cwd,
transform: (0, _createFileTransform().createFileTransform)(name),
onentry: (0, _createFileTransform().createEntryResolver)(name),
strip: strip !== null && strip !== void 0 ? strip : 1
}, fileList));
}
//# sourceMappingURL=npm.js.map