1 | "use strict";
|
2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
3 | return new (P || (P = Promise))(function (resolve, reject) {
|
4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
6 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
7 | step((generator = generator.apply(thisArg, _arguments || [])).next());
|
8 | });
|
9 | };
|
10 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
11 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
12 | };
|
13 | Object.defineProperty(exports, "__esModule", { value: true });
|
14 | const react_1 = __importDefault(require("react"));
|
15 | const ink_1 = require("ink");
|
16 | const algolia_1 = require("./algolia");
|
17 | const Footer_1 = require("./components/Footer");
|
18 | const Install_1 = __importDefault(require("./components/Install"));
|
19 | const Overview_1 = __importDefault(require("./components/Overview"));
|
20 | const Package_1 = __importDefault(require("./components/Package"));
|
21 | const Scroll_1 = __importDefault(require("./components/Scroll"));
|
22 | const Search_1 = __importDefault(require("./components/Search"));
|
23 | const installer_1 = require("./installer");
|
24 | const utils_1 = require("./utils");
|
25 | const SPACE = ' ';
|
26 | const ARROW_UP = '\u001B[A';
|
27 | const ARROW_DOWN = '\u001B[B';
|
28 | const ENTER = '\r';
|
29 | const CTRL_C = '\x03';
|
30 | class Emma extends react_1.default.Component {
|
31 | constructor(props) {
|
32 | super(props);
|
33 | this.state = {
|
34 | view: 'SEARCH',
|
35 | query: '',
|
36 | page: 0,
|
37 | hits: [],
|
38 | loading: false,
|
39 | dependencies: {},
|
40 | status: 'NOT_STARTED',
|
41 | };
|
42 | |
43 |
|
44 |
|
45 | this.toggleDependency = (pkg) => {
|
46 | const { dependencies } = this.state;
|
47 | const dependency = dependencies[pkg.name];
|
48 | if (dependency === undefined) {
|
49 | this.setState({
|
50 | dependencies: Object.assign({}, dependencies, { [pkg.name]: { name: pkg.name, type: 'dependency' } }),
|
51 | });
|
52 | }
|
53 | else {
|
54 | const nextType = installer_1.getNextDependencyType(dependency.type);
|
55 | if (nextType) {
|
56 | this.setState({
|
57 | dependencies: Object.assign({}, dependencies, { [pkg.name]: { name: pkg.name, type: nextType } }),
|
58 | });
|
59 | }
|
60 | else {
|
61 | this.setState({
|
62 | dependencies: utils_1.removeKey(pkg.name, dependencies),
|
63 | });
|
64 | }
|
65 | }
|
66 | };
|
67 | this.handleQueryChange = this.handleQueryChange.bind(this);
|
68 | this.handleInput = this.handleInput.bind(this);
|
69 | this.handleWillReachEnd = this.handleWillReachEnd.bind(this);
|
70 | this.installDependencies = this.installDependencies.bind(this);
|
71 | }
|
72 | componentDidMount() {
|
73 | const { stdin, setRawMode } = this.props;
|
74 | if (setRawMode)
|
75 | setRawMode(true);
|
76 | stdin.on('data', this.handleInput);
|
77 | }
|
78 | componentWillUnmount() {
|
79 | const { stdin, setRawMode } = this.props;
|
80 | stdin.removeListener('data', this.handleInput);
|
81 | if (setRawMode)
|
82 | setRawMode(false);
|
83 | }
|
84 | |
85 |
|
86 |
|
87 | handleInput(data) {
|
88 | return __awaiter(this, void 0, void 0, function* () {
|
89 | const s = String(data);
|
90 | |
91 |
|
92 |
|
93 | if (s === CTRL_C) {
|
94 | process.exit(0);
|
95 | }
|
96 | switch (this.state.view) {
|
97 | case 'SEARCH': {
|
98 | if (s === ARROW_DOWN || s === ENTER || SPACE) {
|
99 | this.setState({ view: 'SCROLL' });
|
100 | }
|
101 | return;
|
102 | }
|
103 | case 'SCROLL': {
|
104 | if (s === ENTER) {
|
105 | this.setState({ view: 'OVERVIEW' });
|
106 | }
|
107 | return;
|
108 | }
|
109 | case 'OVERVIEW': {
|
110 | if (s === ARROW_UP || ARROW_DOWN) {
|
111 | this.setState({ view: 'SCROLL' });
|
112 | }
|
113 | if (s === ENTER) {
|
114 | if (Object.values(this.state.dependencies).length > 0) {
|
115 | this.setState({ view: 'INSTALL' });
|
116 | try {
|
117 | yield this.installDependencies();
|
118 | process.exit(0);
|
119 | }
|
120 | catch (err) {
|
121 | process.exit(1);
|
122 | }
|
123 | }
|
124 | else {
|
125 | process.exit(0);
|
126 | }
|
127 | }
|
128 | return;
|
129 | }
|
130 | case 'INSTALL': {
|
131 | return;
|
132 | }
|
133 | }
|
134 | });
|
135 | }
|
136 | |
137 |
|
138 |
|
139 |
|
140 | handleQueryChange(value) {
|
141 | return __awaiter(this, void 0, void 0, function* () {
|
142 | this.setState({
|
143 | query: value,
|
144 | page: 0,
|
145 | view: 'SEARCH',
|
146 | loading: true,
|
147 | });
|
148 | const res = yield algolia_1.search(value);
|
149 | if (res.query === this.state.query) {
|
150 | this.setState({ hits: res.hits, loading: false });
|
151 | }
|
152 | });
|
153 | }
|
154 | |
155 |
|
156 |
|
157 |
|
158 | handleWillReachEnd() {
|
159 | return __awaiter(this, void 0, void 0, function* () {
|
160 | const { query, hits, page } = this.state;
|
161 | if (page > 10)
|
162 | return;
|
163 | const res = yield algolia_1.search(query, page + 1);
|
164 | if (res.query === this.state.query && res.page - 1 === this.state.page) {
|
165 | this.setState({
|
166 | page: res.page,
|
167 | hits: [...hits, ...res.hits],
|
168 | });
|
169 | }
|
170 | });
|
171 | }
|
172 | installDependencies() {
|
173 | return __awaiter(this, void 0, void 0, function* () {
|
174 | this.setState({ status: 'LOADING' });
|
175 | try {
|
176 | yield installer_1.install(Object.values(this.state.dependencies), 'dependency');
|
177 | yield installer_1.install(Object.values(this.state.dependencies), 'devDependency');
|
178 | this.setState({ status: 'INSTALLED' });
|
179 | }
|
180 | catch (err) {
|
181 | this.setState({ status: 'ERROR' });
|
182 | throw err;
|
183 | }
|
184 | });
|
185 | }
|
186 | render() {
|
187 | const { view, query, loading, hits, dependencies, status } = this.state;
|
188 | return (react_1.default.createElement(algolia_1.SearchContext.Provider, { value: hits },
|
189 | react_1.default.createElement(ink_1.Box, { flexDirection: "column" },
|
190 | react_1.default.createElement(Search_1.default, { value: query, onChange: this.handleQueryChange, loading: loading, active: true }),
|
191 | react_1.default.createElement(Scroll_1.default, { values: this.state.hits, onWillReachEnd: this.handleWillReachEnd, active: view === 'SCROLL' }, pkg => (react_1.default.createElement(Package_1.default, { key: pkg.objectID, pkg: pkg, onClick: this.toggleDependency, active: pkg.active, type: (dependencies[pkg.name] || {}).type }))),
|
192 | react_1.default.createElement(Overview_1.default, { dependencies: Object.values(dependencies), active: view === 'OVERVIEW' }),
|
193 | react_1.default.createElement(Install_1.default, { dependencies: Object.values(dependencies), status: status, active: view === 'INSTALL' }),
|
194 | react_1.default.createElement(Footer_1.Footer, null))));
|
195 | }
|
196 | }
|
197 | class EmmaWithStdin extends react_1.default.Component {
|
198 | render() {
|
199 | return (react_1.default.createElement(ink_1.StdinContext.Consumer, null, ({ stdin, setRawMode }) => (react_1.default.createElement(Emma, Object.assign({}, this.props, { stdin: stdin, setRawMode: setRawMode })))));
|
200 | }
|
201 | }
|
202 | exports.default = EmmaWithStdin;
|
203 |
|
\ | No newline at end of file |