UNPKG

3.59 kBJavaScriptView Raw
1/* eslint-env node */
2const { ensureDirSync } = require('fs-extra');
3const fs = require('fs');
4const path = require('path');
5
6const canConnect = require('./can-connect');
7const { getGitHubClient } = require('./get-github-client');
8const messages = require('./messages');
9const selectComponents = require('./select-components');
10const readGhPath = require('./read-github-path');
11
12const getRemainingAPIUsage = client =>
13 new Promise(resolve => {
14 client.limit((error, left, max, reset) => {
15 resolve({ requestsLeft: left, resetTime: reset });
16 });
17 });
18
19module.exports = async function(localComponentsPath) {
20 const canConnectToGitHub = await canConnect('www.github.com');
21
22 if (!canConnectToGitHub) {
23 messages.gitHubRequestTimeout();
24 messages.emptyLine();
25 return;
26 }
27
28 try {
29 messages.connectingToGitHub();
30 messages.emptyLine();
31
32 const client = await getGitHubClient();
33 const { requestsLeft, resetTime } = await getRemainingAPIUsage(client);
34
35 if (requestsLeft === 0) {
36 messages.githubRateLimitExceeded(resetTime);
37 return;
38 }
39
40 const repo = client.repo('Creuna-Oslo/react-components');
41
42 messages.searchingForComponents();
43
44 // Get names of available components from directory names in the 'components' folder in the repository
45 const componentNames = await readGhPath(repo, 'components').then(
46 componentPaths =>
47 // Remove first slug ('components/')
48 componentPaths.map(({ path }) => path.substring(path.indexOf('/') + 1))
49 );
50
51 // Get selected components from user input (checkboxes)
52 const selectedComponents = await selectComponents(componentNames);
53
54 messages.emptyLine();
55
56 if (selectedComponents.length === 0) {
57 messages.noComponentsSelected();
58 return;
59 }
60
61 // Filter out components that already exists on disk
62 const filteredComponents = selectedComponents.filter(componentName => {
63 if (fs.existsSync(path.join(localComponentsPath, componentName))) {
64 messages.componentAlreadyExists(componentName);
65 return false;
66 }
67 return true;
68 }, []);
69
70 if (filteredComponents.length === 0) {
71 messages.noComponentsToWrite();
72 messages.emptyLine();
73 return;
74 }
75
76 const filteredPaths = filteredComponents.map(name => `components/${name}`);
77
78 messages.downloadingComponents();
79
80 // Get list of file paths for all filtered components
81 const allFilePaths = await Promise.all(
82 filteredPaths.map(componentPath => readGhPath(repo, componentPath))
83 ).then(components => [].concat(...components)); // Merge 2D array to single array
84
85 // Get file contents for all file paths
86 const allFiles = await Promise.all(
87 allFilePaths.map(file => readGhPath(repo, file.path))
88 ).then(filesData =>
89 filesData.map(({ path, content }) => ({
90 path: path && path.substring(path.indexOf('/') + 1), // remove first slug ('components/')
91 content: content && new Buffer(content, 'base64').toString('utf-8')
92 }))
93 );
94
95 messages.writingFiles();
96
97 // Write files to disk
98 allFiles.forEach(file => {
99 if (!file) {
100 messages.missingFile();
101 return;
102 }
103 const content = file.content;
104 const filePath = path.join(
105 localComponentsPath,
106 file.path.replace('/', path.sep)
107 );
108 const directory = filePath.substring(0, filePath.lastIndexOf(path.sep));
109 ensureDirSync(directory);
110 fs.writeFileSync(filePath, content);
111 });
112
113 messages.componentsAdded();
114 } catch (error) {
115 messages.error(error);
116 }
117};