-
Notifications
You must be signed in to change notification settings - Fork 130
/
mod.js
137 lines (128 loc) · 4.55 KB
/
mod.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/**
* Copyright (c) 2016-present Alibaba Group Holding Limited
* @author Houfeng <admin@xhou.net>
*/
const exec = require('./common/exec');
const path = require('path');
const utils = require('ntils');
const Stamp = require('./stamp');
const download = require('./common/download');
const fs = require('fs');
const del = require('del');
const fetch = require('./common/fetch');
const store = require('./store');
const debug = require('debug')('mod');
const save = require('./common/save');
const configs = require('./configs');
const trim = require('./common/trim');
const console = require('./common/console');
const pkgname = require('./common/pkgname');
const FETCT_TIMEOUT = 30000;
const OFFICIAL_NPM_PKG_URL_PREFIX = 'https://www.npmjs.com/package';
exports.exec = async function (cmd, opts) {
opts = Object.assign({}, opts);
opts.cwd = opts.cwd || process.cwd();
opts.flag = opts.flag || {};
opts.flag.registry = decodeURIComponent(
opts.flag.registry || await configs.getRc('registry')
);
const flags = [];
utils.each(opts.flag, (name, value) => {
const flagName = (name.length > 1 ? '--' : '-') + name;
const flagValue = utils.isString(value) ? `=${value}` : '';
flags.push(`${flagName}${flagValue}`);
});
const npmBin = await configs.getRc('npm') || 'npm';
const script = `${npmBin} ${cmd || ''} ${flags.join(' ')}`;
debug('exec script', script);
await exec(script, { cwd: opts.cwd });
};
exports.install = async function (name, opts) {
opts = Object.assign({}, opts);
opts.flag = opts.flag || {};
const pkgFile = path.normalize(`${process.cwd()}/package.json`);
if (!opts.flag.global && !opts.flag.g && !fs.existsSync(pkgFile)) {
return;
}
console.info(`Installing '${name || 'dependencies'}' ...`);
const nameInfo = pkgname(name, opts.prefix);
delete opts.prefix;
await this.exec(`i ${nameInfo.fullNameAndVersion || ''}`, opts);
console.info('Done');
};
exports.getInfo = async function (name) {
const registryUri = trim(await configs.getRc('registry'), '/');
debug('serverUri', registryUri);
const url = `${registryUri}/${name}`;
debug('getInfo', url);
const res = await fetch(url, { timeout: FETCT_TIMEOUT });
const info = await res.json();
debug('getInfo', 'ok');
if (!info || !info.versions || info.error) {
debug('Module Info', info);
throw new Error(`Cannot find module '${name}'`);
}
return info;
};
exports.getVersionInfo = async function (name, version) {
debug('getVersionInfo', name, version);
const modInfo = await this.getInfo(name) || {};
const distTags = modInfo['dist-tags'] || {};
version = version || 'latest';
version = distTags[version] || version;
debug('version', version);
const looseVersion = Object.keys(modInfo.versions).pop();
debug('looseVersion', looseVersion);
return modInfo.versions[version] || modInfo.versions[looseVersion];
};
exports.download = async function (name, prefix) {
if (!name) return;
console.info(`Downloading '${name}' ...`);
const nameInfo = pkgname(name, prefix);
debug('download', name, nameInfo.fullName);
const stamp = new Stamp(`${nameInfo.fullName}.module`);
const storeDir = await store.getPath('modules');
const filename = path.normalize(
`${storeDir}/${nameInfo.fullName.replace(/\//, '-')}.tgz`
);
const isExists = fs.existsSync(filename);
if (!isExists || await stamp.isExpire()) {
const verInfo = await this.getVersionInfo(nameInfo.fullName);
if (!verInfo || !verInfo.dist || !verInfo.dist.tarball) {
throw new Error(`Cannot download ${nameInfo.fullName}`);
}
debug('download url', verInfo.dist.tarball);
let res;
try {
res = await download(verInfo.dist.tarball);
} catch (err) {
console.info('Done');
if (isExists) return filename;
throw err;
}
if (res.status < 200 || res.status > 299) {
if (isExists) return filename;
throw new Error('Download error:', name);
}
await Promise.all([save(filename, res), stamp.write()]);
}
console.info('Done');
return filename;
};
exports.getDocUrl = async function (name, prefix) {
const nameInfo = pkgname(name, prefix);
const registryUri = decodeURIComponent(trim(
await configs.getRc('registry'), '/'
));
debug('registryUri', registryUri);
const url = `${OFFICIAL_NPM_PKG_URL_PREFIX}/${nameInfo.fullName}`;
debug('docUrl', url);
return url;
};
exports.clean = async function (cleanLock) {
const items = [path.normalize(`${process.cwd()}/node_modules/`)];
if (cleanLock) {
items.push(path.normalize(`${process.cwd()}/package-lock.json`));
}
await del(items, { force: true });
};