UNPKG

9.57 kBJavaScriptView Raw
1const open = require('open');
2const chalk = require('chalk');
3const fetch = require('node-fetch');
4
5const {
6 exit,
7 readFile,
8 writeFile,
9 geneDashLine,
10 printMessages,
11 printSuccess,
12 getCurrentRegistry,
13 getRegistries,
14 isLowerCaseEqual,
15 isRegistryNotFound,
16 isInternalRegistry,
17} = require('./helpers');
18
19const { NRMRC, NPMRC, AUTH, EMAIL, ALWAYS_AUTH, REPOSITORY, REGISTRY, HOME } = require('./constants');
20
21async function onList() {
22 const currentRegistry = await getCurrentRegistry();
23 const registries = await getRegistries();
24 const keys = Object.keys(registries);
25 const length = Math.max(...keys.map(key => key.length)) + 3;
26
27 const messages = keys.map(key => {
28 const registry = registries[key];
29 const prefix = isLowerCaseEqual(registry[REGISTRY], currentRegistry) ? chalk.green.bold('* ') : ' ';
30 return prefix + key + geneDashLine(key, length) + registry[REGISTRY];
31 });
32
33 printMessages(messages);
34}
35
36async function onCurrent({ showUrl }) {
37 const currentRegistry = await getCurrentRegistry();
38 let usingUnknownRegistry = true;
39 const registries = await getRegistries();
40 for (const name in registries) {
41 const registry = registries[name];
42 if (isLowerCaseEqual(registry[REGISTRY], currentRegistry)) {
43 usingUnknownRegistry = false;
44 printMessages([`You are using ${chalk.green(showUrl ? registry[REGISTRY] : name)} registry.`]);
45 }
46 }
47 if (usingUnknownRegistry) {
48 printMessages([
49 `Your current registry(${currentRegistry}) is not included in the nrm registries.`,
50 `Use the ${chalk.green('nrm add <registry> <url> [home]')} command to add your registry.`,
51 ]);
52 }
53}
54
55async function onUse(name) {
56 if (await isRegistryNotFound(name)) {
57 return;
58 }
59
60 const registries = await getRegistries();
61 const registry = registries[name];
62 const npmrc = await readFile(NPMRC);
63 await writeFile(NPMRC, Object.assign(npmrc, registry));
64
65 printSuccess(`The registry has been changed to '${name}'.`);
66}
67
68async function onDelete(name) {
69 if (await isRegistryNotFound(name) || await isInternalRegistry(name, 'delete')) {
70 return;
71 }
72
73 const customRegistries = await readFile(NRMRC);
74 const registry = customRegistries[name];
75 delete customRegistries[name];
76 await writeFile(NRMRC, customRegistries);
77 printSuccess(`The registry '${name}' has been deleted successfully.`);
78
79 const currentRegistry = await getCurrentRegistry();
80 if (currentRegistry === registry[REGISTRY]) {
81 await onUse('npm');
82 }
83}
84
85async function onAdd(name, url, home) {
86 const registries = await getRegistries();
87 const registryNames = Object.keys(registries);
88 const registryUrls = registryNames.map(name => registries[name][REGISTRY]);
89 if (registryNames.includes(name) || registryUrls.some(eachUrl => isLowerCaseEqual(eachUrl, url))) {
90 return exit('The registry name or url is already included in the nrm registries. Please make sure that the name and url are unique.');
91 }
92
93 const newRegistry = {};
94 newRegistry[REGISTRY] = /\/$/.test(url) ? url : url + '/';
95 if (home) {
96 newRegistry[HOME] = home;
97 }
98 const customRegistries = await readFile(NRMRC);
99 const newCustomRegistries = Object.assign(customRegistries, { [name]: newRegistry });
100 await writeFile(NRMRC, newCustomRegistries);
101 printSuccess(`Add registry ${name} success, run ${chalk.green('nrm use ' + name)} command to use ${name} registry.`);
102}
103
104async function onLogin(name, base64, { alwaysAuth, username, password, email }) {
105 if (await isRegistryNotFound(name) || await isInternalRegistry(name, 'set authorization information of')) {
106 return;
107 }
108
109 const customRegistries = await readFile(NRMRC);
110 const registry = customRegistries[name];
111 if (base64) {
112 registry[AUTH] = base64;
113 } else if (username && password) {
114 registry[AUTH] = Buffer.from(`${username}:${password}`).toString('base64');
115 } else {
116 return exit('Authorization information in base64 format or username & password is required');
117 }
118
119 if (alwaysAuth) {
120 registry[ALWAYS_AUTH] = true;
121 }
122
123 if (email) {
124 registry[EMAIL] = email;
125 }
126
127 Object.assign(customRegistries, { [name]: registry });
128 await writeFile(NRMRC, customRegistries);
129 printSuccess(`Set the authorization information of the registry '${name}' success.`);
130
131 const currentRegistry = await getCurrentRegistry();
132 if (currentRegistry === registry[REGISTRY]) {
133 const npmrc = await readFile(NPMRC);
134 await writeFile(NPMRC, Object.assign(npmrc, {
135 [AUTH]: registry[AUTH],
136 [ALWAYS_AUTH]: registry[ALWAYS_AUTH],
137 [EMAIL]: registry[EMAIL],
138 }));
139 }
140}
141
142async function onSetRepository(name, repo) {
143 if (await isRegistryNotFound(name) || await isInternalRegistry(name, 'set repository of')) {
144 return;
145 }
146
147 const customRegistries = await readFile(NRMRC);
148 const registry = customRegistries[name];
149 registry[REPOSITORY] = repo;
150 await writeFile(NRMRC, customRegistries);
151 printSuccess(`Set the ${REPOSITORY} of registry '${name}' successfully.`);
152
153 const currentRegistry = await getCurrentRegistry();
154 if (currentRegistry && registry[REGISTRY] === currentRegistry) {
155 const npmrc = await readFile(NPMRC);
156 Object.assign(npmrc, { [REPOSITORY]: repo });
157 await writeFile(NPMRC, npmrc);
158 printSuccess(`Set repository attribute of npmrc successfully`);
159 }
160}
161
162async function onSetScope(scopeName, url) {
163 const scopeRegistryKey = `${scopeName}:${REGISTRY}`;
164 const npmrc = await readFile(NPMRC);
165 Object.assign(npmrc, { [scopeRegistryKey]: url });
166 await writeFile(NPMRC, npmrc);
167 printSuccess(`Set scope '${scopeRegistryKey}=${url}' success.`);
168}
169
170async function onDeleteScope(scopeName) {
171 const scopeRegistryKey = `${scopeName}:${REGISTRY}`;
172 const npmrc = await readFile(NPMRC);
173 if (npmrc[scopeRegistryKey]) {
174 delete npmrc[scopeRegistryKey];
175 await writeFile(NPMRC, npmrc);
176 printSuccess(`Delete scope '${scopeRegistryKey}' success.`);
177 }
178}
179
180async function onSetAttribute(name, { attr, value }) {
181 if (await isRegistryNotFound(name) || await isInternalRegistry(name, 'set attribute of')) {
182 return;
183 }
184
185 if (REPOSITORY === attr) {
186 return exit(`Use the ${chalk.green('nrm set-hosted-repo <name> <repo>')} command to set repository.`);
187 }
188 const customRegistries = await readFile(NRMRC);
189 const registry = customRegistries[name];
190 Object.assign(registry, { [attr]: value });
191 await writeFile(NRMRC, customRegistries);
192 printSuccess(`Set attribute '${attr}=${value}' of the registry '${name}' successfully.`);
193
194 const currentRegistry = await getCurrentRegistry();
195 if (currentRegistry === registry[REGISTRY]) {
196 const npmrc = await readFile(NPMRC);
197 await writeFile(NPMRC, Object.assign(npmrc, { [attr]: value }));
198 }
199}
200
201async function onRename(name, newName) {
202 if (await isRegistryNotFound(name) || await isInternalRegistry(name, 'rename')) {
203 return;
204 }
205 if (name === newName) {
206 return exit('The names cannot be the same.');
207 }
208
209 if (!await isRegistryNotFound(newName, false)) {
210 return exit(`The new registry name '${newName}' is already exist.`);
211 }
212 const customRegistries = await readFile(NRMRC);
213 customRegistries[newName] = JSON.parse(JSON.stringify(customRegistries[name]));
214 delete customRegistries[name];
215 await writeFile(NRMRC, customRegistries);
216 printSuccess(`The registry '${name}' has been renamed to '${newName}'.`);
217}
218
219async function onHome(name, browser) {
220 if (await isRegistryNotFound(name)) {
221 return;
222 }
223
224 const registries = await getRegistries();
225 if (!registries[name][HOME]) {
226 return exit(`The homepage of registry '${name}' is not found.`);
227 }
228 open(registries[name][HOME], browser ? { app: { name: browser } } : undefined);
229}
230
231async function onTest(target) {
232 const registries = await getRegistries();
233 const timeout = 5000;
234
235 if (target && await isRegistryNotFound(target)) {
236 return exit();
237 }
238
239 const sources = target ? { [target]: registries[target] } : registries;
240
241 const results = await Promise.all(Object.keys(sources).map(async name => {
242 const { registry } = sources[name];
243 const start = Date.now();
244 let status = false;
245 let isTimeout = false;
246 try {
247 const response = await fetch(registry + 'nrm', { timeout });
248 status = response.ok;
249 } catch (error) {
250 isTimeout = error.type === 'request-timeout';
251 }
252 return {
253 name,
254 registry,
255 success: status,
256 time: Date.now() - start,
257 isTimeout
258 };
259 }));
260
261 const [fastest] = results.filter(each => each.success).map(each => each.time).sort((a, b) => a - b);
262
263 const messages = [];
264 const currentRegistry = await getCurrentRegistry();
265 const errorMsg = chalk.red(' (Fetch error, if this is your private registry, please ignore)');
266 const timeoutMsg = chalk.yellow(` (Fetch timeout over ${timeout} ms)`);
267 const length = Math.max(...Object.keys(sources).map(key => key.length)) + 3;
268 results.forEach(({ registry, success, time, name, isTimeout }) => {
269 const isFastest = time === fastest;
270 const prefix = registry === currentRegistry ? chalk.green('* ') : ' ';
271 let suffix = (isFastest && !target) ? chalk.bgGreenBright(time + ' ms') : isTimeout ? 'timeout' : `${time} ms`;
272 if (!success) {
273 suffix += isTimeout ? timeoutMsg : errorMsg;
274 }
275 messages.push(prefix + name + geneDashLine(name, length) + suffix);
276 });
277 printMessages(messages);
278 return messages;
279}
280
281module.exports = {
282 onList,
283 onCurrent,
284 onUse,
285 onAdd,
286 onDelete,
287 onRename,
288 onHome,
289 onSetRepository,
290 onSetScope,
291 onDeleteScope,
292 onSetAttribute,
293 onTest,
294 onLogin,
295};