hedgequantx 1.3.2 → 1.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/app.js +45 -21
- package/src/services/projectx/index.js +118 -3
- package/src/services/rithmic/accounts.js +57 -16
- package/src/services/tradovate/index.js +24 -7
- package/src/ui/index.js +4 -2
package/package.json
CHANGED
package/src/app.js
CHANGED
|
@@ -70,30 +70,40 @@ const banner = async () => {
|
|
|
70
70
|
const version = require('../package.json').version;
|
|
71
71
|
|
|
72
72
|
// Get stats if connected (only active accounts: status === 0)
|
|
73
|
+
// STRICT: Only display values from API, no estimation
|
|
73
74
|
let statsInfo = null;
|
|
74
75
|
if (connections.count() > 0) {
|
|
75
76
|
try {
|
|
76
77
|
const allAccounts = await connections.getAllAccounts();
|
|
77
78
|
const activeAccounts = allAccounts.filter(acc => acc.status === 0);
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
let
|
|
79
|
+
|
|
80
|
+
// Sum only non-null values from API
|
|
81
|
+
let totalBalance = null;
|
|
82
|
+
let totalPnl = null;
|
|
83
|
+
let hasBalanceData = false;
|
|
84
|
+
let hasPnlData = false;
|
|
81
85
|
|
|
82
86
|
activeAccounts.forEach(account => {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
87
|
+
// Balance: only sum if API returned a value
|
|
88
|
+
if (account.balance !== null && account.balance !== undefined) {
|
|
89
|
+
totalBalance = (totalBalance || 0) + account.balance;
|
|
90
|
+
hasBalanceData = true;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// P&L: only sum if API returned a value
|
|
94
|
+
if (account.profitAndLoss !== null && account.profitAndLoss !== undefined) {
|
|
95
|
+
totalPnl = (totalPnl || 0) + account.profitAndLoss;
|
|
96
|
+
hasPnlData = true;
|
|
97
|
+
}
|
|
86
98
|
});
|
|
87
99
|
|
|
88
|
-
const pnl = totalPnl !== 0 ? totalPnl : (totalBalance - totalStartingBalance);
|
|
89
|
-
const pnlPercent = totalStartingBalance > 0 ? ((pnl / totalStartingBalance) * 100).toFixed(1) : '0.0';
|
|
90
|
-
|
|
91
100
|
statsInfo = {
|
|
92
101
|
connections: connections.count(),
|
|
93
102
|
accounts: activeAccounts.length,
|
|
94
|
-
balance: totalBalance,
|
|
95
|
-
pnl:
|
|
96
|
-
|
|
103
|
+
balance: hasBalanceData ? totalBalance : null,
|
|
104
|
+
pnl: hasPnlData ? totalPnl : null,
|
|
105
|
+
// No percentage calculation if no verified data
|
|
106
|
+
pnlPercent: null
|
|
97
107
|
};
|
|
98
108
|
} catch (e) {
|
|
99
109
|
// Ignore errors
|
|
@@ -168,19 +178,33 @@ const banner = async () => {
|
|
|
168
178
|
console.log(chalk.cyan('║') + chalk.white(centerText(tagline, innerWidth)) + chalk.cyan('║'));
|
|
169
179
|
|
|
170
180
|
// Stats bar if connected
|
|
181
|
+
// STRICT: Only display verified values from API, show '--' for unavailable data
|
|
171
182
|
if (statsInfo) {
|
|
172
183
|
console.log(chalk.cyan('╠' + '═'.repeat(innerWidth) + '╣'));
|
|
173
184
|
|
|
174
|
-
const pnlColor = statsInfo.pnl >= 0 ? chalk.green : chalk.red;
|
|
175
|
-
const pnlSign = statsInfo.pnl >= 0 ? '+' : '';
|
|
176
|
-
|
|
177
185
|
const connStr = `Connections: ${statsInfo.connections}`;
|
|
178
186
|
const accStr = `Accounts: ${statsInfo.accounts}`;
|
|
179
|
-
|
|
180
|
-
|
|
187
|
+
|
|
188
|
+
// Balance: show '--' if not available from API
|
|
189
|
+
const balStr = statsInfo.balance !== null
|
|
190
|
+
? `Balance: $${statsInfo.balance.toLocaleString()}`
|
|
191
|
+
: `Balance: --`;
|
|
192
|
+
const balColor = statsInfo.balance !== null ? chalk.green : chalk.gray;
|
|
193
|
+
|
|
194
|
+
// P&L: show '--' if not available from API
|
|
195
|
+
let pnlDisplay;
|
|
196
|
+
let pnlColor;
|
|
197
|
+
if (statsInfo.pnl !== null) {
|
|
198
|
+
const pnlSign = statsInfo.pnl >= 0 ? '+' : '';
|
|
199
|
+
pnlColor = statsInfo.pnl >= 0 ? chalk.green : chalk.red;
|
|
200
|
+
pnlDisplay = `$${statsInfo.pnl.toLocaleString()} (${pnlSign}${statsInfo.pnl.toFixed(1)})`;
|
|
201
|
+
} else {
|
|
202
|
+
pnlColor = chalk.gray;
|
|
203
|
+
pnlDisplay = '--';
|
|
204
|
+
}
|
|
181
205
|
|
|
182
206
|
// Build full stats text and calculate padding
|
|
183
|
-
const statsText = `${connStr} ${accStr} ${balStr} ${
|
|
207
|
+
const statsText = `${connStr} ${accStr} ${balStr} P&L: ${pnlDisplay}`;
|
|
184
208
|
const statsLen = statsText.length;
|
|
185
209
|
const statsLeftPad = Math.floor((innerWidth - statsLen) / 2);
|
|
186
210
|
const statsRightPad = innerWidth - statsLen - statsLeftPad;
|
|
@@ -188,9 +212,9 @@ const banner = async () => {
|
|
|
188
212
|
console.log(chalk.cyan('║') + ' '.repeat(statsLeftPad) +
|
|
189
213
|
chalk.white(connStr) + ' ' +
|
|
190
214
|
chalk.white(accStr) + ' ' +
|
|
191
|
-
chalk.white('Balance: ') +
|
|
192
|
-
chalk.white('P&L: ') + pnlColor(
|
|
193
|
-
' '.repeat(statsRightPad) + chalk.cyan('║')
|
|
215
|
+
chalk.white('Balance: ') + balColor(statsInfo.balance !== null ? `$${statsInfo.balance.toLocaleString()}` : '--') + ' ' +
|
|
216
|
+
chalk.white('P&L: ') + pnlColor(pnlDisplay) +
|
|
217
|
+
' '.repeat(Math.max(0, statsRightPad)) + chalk.cyan('║')
|
|
194
218
|
);
|
|
195
219
|
}
|
|
196
220
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ProjectX API Service
|
|
3
3
|
* Main service for ProjectX prop firm connections
|
|
4
|
+
*
|
|
5
|
+
* STRICT RULE: Display ONLY values returned by API. No estimation, no simulation.
|
|
4
6
|
*/
|
|
5
7
|
|
|
6
8
|
const https = require('https');
|
|
@@ -145,18 +147,131 @@ class ProjectXService {
|
|
|
145
147
|
|
|
146
148
|
// ==================== ACCOUNTS ====================
|
|
147
149
|
|
|
150
|
+
/**
|
|
151
|
+
* Get trading accounts - ONLY returns values from API
|
|
152
|
+
* P&L comes from: today's trades + open positions (both from API)
|
|
153
|
+
*/
|
|
148
154
|
async getTradingAccounts() {
|
|
149
155
|
try {
|
|
150
156
|
const response = await this._request(this.propfirm.userApi, '/TradingAccount', 'GET');
|
|
151
|
-
if (response.statusCode
|
|
152
|
-
return { success:
|
|
157
|
+
if (response.statusCode !== 200) {
|
|
158
|
+
return { success: false, accounts: [], error: 'Failed to get accounts' };
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const accounts = Array.isArray(response.data) ? response.data : [];
|
|
162
|
+
const enrichedAccounts = [];
|
|
163
|
+
|
|
164
|
+
for (const account of accounts) {
|
|
165
|
+
// Start with RAW API data only
|
|
166
|
+
const enriched = {
|
|
167
|
+
accountId: account.accountId,
|
|
168
|
+
accountName: account.accountName,
|
|
169
|
+
balance: account.balance, // From API
|
|
170
|
+
status: account.status, // From API
|
|
171
|
+
type: account.type, // From API
|
|
172
|
+
platform: 'ProjectX',
|
|
173
|
+
propfirm: this.propfirm.name,
|
|
174
|
+
// P&L fields - will be populated from API calls
|
|
175
|
+
todayPnL: null,
|
|
176
|
+
openPnL: null,
|
|
177
|
+
profitAndLoss: null,
|
|
178
|
+
startingBalance: null,
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
// Only fetch P&L for active accounts
|
|
182
|
+
if (account.status === 0) {
|
|
183
|
+
// Get today's realized P&L from trades API
|
|
184
|
+
const todayPnL = await this._getTodayRealizedPnL(account.accountId);
|
|
185
|
+
enriched.todayPnL = todayPnL;
|
|
186
|
+
|
|
187
|
+
// Get unrealized P&L from open positions API
|
|
188
|
+
const openPnL = await this._getOpenPositionsPnL(account.accountId);
|
|
189
|
+
enriched.openPnL = openPnL;
|
|
190
|
+
|
|
191
|
+
// Total P&L = realized + unrealized (both from API)
|
|
192
|
+
if (todayPnL !== null || openPnL !== null) {
|
|
193
|
+
enriched.profitAndLoss = (todayPnL || 0) + (openPnL || 0);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
enrichedAccounts.push(enriched);
|
|
153
198
|
}
|
|
154
|
-
|
|
199
|
+
|
|
200
|
+
return { success: true, accounts: enrichedAccounts };
|
|
155
201
|
} catch (error) {
|
|
156
202
|
return { success: false, accounts: [], error: error.message };
|
|
157
203
|
}
|
|
158
204
|
}
|
|
159
205
|
|
|
206
|
+
/**
|
|
207
|
+
* Get today's realized P&L from Trade API
|
|
208
|
+
* Returns null if API fails (not 0)
|
|
209
|
+
* @private
|
|
210
|
+
*/
|
|
211
|
+
async _getTodayRealizedPnL(accountId) {
|
|
212
|
+
try {
|
|
213
|
+
const now = new Date();
|
|
214
|
+
const startOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
|
215
|
+
|
|
216
|
+
const response = await this._request(
|
|
217
|
+
this.propfirm.gatewayApi, '/api/Trade/search', 'POST',
|
|
218
|
+
{
|
|
219
|
+
accountId: accountId,
|
|
220
|
+
startTimestamp: startOfDay.toISOString(),
|
|
221
|
+
endTimestamp: now.toISOString()
|
|
222
|
+
}
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
if (response.statusCode === 200 && response.data) {
|
|
226
|
+
const trades = Array.isArray(response.data)
|
|
227
|
+
? response.data
|
|
228
|
+
: (response.data.trades || []);
|
|
229
|
+
|
|
230
|
+
// Sum P&L from API response only
|
|
231
|
+
let totalPnL = 0;
|
|
232
|
+
for (const trade of trades) {
|
|
233
|
+
if (trade.profitAndLoss !== undefined && trade.profitAndLoss !== null) {
|
|
234
|
+
totalPnL += trade.profitAndLoss;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return totalPnL;
|
|
238
|
+
}
|
|
239
|
+
return null; // API failed - return null, not 0
|
|
240
|
+
} catch (e) {
|
|
241
|
+
return null;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Get unrealized P&L from open positions API
|
|
247
|
+
* Returns null if API fails (not 0)
|
|
248
|
+
* @private
|
|
249
|
+
*/
|
|
250
|
+
async _getOpenPositionsPnL(accountId) {
|
|
251
|
+
try {
|
|
252
|
+
const response = await this._request(
|
|
253
|
+
this.propfirm.gatewayApi, '/api/Position/searchOpen', 'POST',
|
|
254
|
+
{ accountId: accountId }
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
if (response.statusCode === 200 && response.data) {
|
|
258
|
+
const positions = response.data.positions || response.data || [];
|
|
259
|
+
if (Array.isArray(positions)) {
|
|
260
|
+
let totalPnL = 0;
|
|
261
|
+
for (const pos of positions) {
|
|
262
|
+
if (pos.profitAndLoss !== undefined && pos.profitAndLoss !== null) {
|
|
263
|
+
totalPnL += pos.profitAndLoss;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return totalPnL;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return null;
|
|
270
|
+
} catch (e) {
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
160
275
|
// ==================== TRADING ====================
|
|
161
276
|
|
|
162
277
|
async getPositions(accountId) {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Rithmic Accounts Module
|
|
3
3
|
* Account fetching, PnL, and positions
|
|
4
|
+
*
|
|
5
|
+
* STRICT RULE: Display ONLY values returned by API. No estimation, no simulation.
|
|
4
6
|
*/
|
|
5
7
|
|
|
6
8
|
const { REQ } = require('./constants');
|
|
@@ -60,10 +62,13 @@ const fetchAccounts = async (service) => {
|
|
|
60
62
|
};
|
|
61
63
|
|
|
62
64
|
/**
|
|
63
|
-
* Get trading accounts
|
|
65
|
+
* Get trading accounts - ONLY returns values from API
|
|
66
|
+
* No estimation, no simulation
|
|
67
|
+
*
|
|
64
68
|
* @param {RithmicService} service - The Rithmic service instance
|
|
65
69
|
*/
|
|
66
70
|
const getTradingAccounts = async (service) => {
|
|
71
|
+
// Fetch accounts if not already loaded
|
|
67
72
|
if (service.accounts.length === 0 && service.orderConn && service.loginInfo) {
|
|
68
73
|
try {
|
|
69
74
|
await fetchAccounts(service);
|
|
@@ -72,40 +77,72 @@ const getTradingAccounts = async (service) => {
|
|
|
72
77
|
}
|
|
73
78
|
}
|
|
74
79
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
+
// Request fresh P&L data from API
|
|
81
|
+
if (service.pnlConn && service.accounts.length > 0) {
|
|
82
|
+
await requestPnLSnapshot(service);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const tradingAccounts = service.accounts.map((acc) => {
|
|
86
|
+
// Get P&L data from API (stored in accountPnL map from handlers.js)
|
|
87
|
+
const pnlData = service.accountPnL.get(acc.accountId);
|
|
88
|
+
|
|
89
|
+
// ONLY use values that came from API - null if not available
|
|
90
|
+
let balance = null;
|
|
91
|
+
let todayPnL = null;
|
|
92
|
+
let openPnL = null;
|
|
93
|
+
let closedPnL = null;
|
|
94
|
+
|
|
95
|
+
if (pnlData) {
|
|
96
|
+
// These values come directly from Rithmic API via handleAccountPnLUpdate
|
|
97
|
+
balance = pnlData.accountBalance !== undefined ? pnlData.accountBalance : null;
|
|
98
|
+
openPnL = pnlData.openPositionPnl !== undefined ? pnlData.openPositionPnl : null;
|
|
99
|
+
closedPnL = pnlData.closedPositionPnl !== undefined ? pnlData.closedPositionPnl : null;
|
|
100
|
+
todayPnL = pnlData.dayPnl !== undefined ? pnlData.dayPnl : null;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Total P&L from API only
|
|
104
|
+
let profitAndLoss = null;
|
|
105
|
+
if (todayPnL !== null) {
|
|
106
|
+
profitAndLoss = todayPnL;
|
|
107
|
+
} else if (openPnL !== null || closedPnL !== null) {
|
|
108
|
+
profitAndLoss = (openPnL || 0) + (closedPnL || 0);
|
|
109
|
+
}
|
|
80
110
|
|
|
81
111
|
return {
|
|
82
112
|
accountId: hashAccountId(acc.accountId),
|
|
83
113
|
rithmicAccountId: acc.accountId,
|
|
84
114
|
accountName: acc.accountName || acc.accountId,
|
|
85
115
|
name: acc.accountName || acc.accountId,
|
|
116
|
+
// From API only - null if not available
|
|
86
117
|
balance: balance,
|
|
87
|
-
|
|
118
|
+
todayPnL: closedPnL, // Realized P&L from API
|
|
119
|
+
openPnL: openPnL, // Unrealized P&L from API
|
|
88
120
|
profitAndLoss: profitAndLoss,
|
|
121
|
+
// No estimation - these are null
|
|
122
|
+
startingBalance: null,
|
|
89
123
|
status: 0,
|
|
90
124
|
platform: 'Rithmic',
|
|
91
125
|
propfirm: service.propfirm.name,
|
|
92
126
|
};
|
|
93
127
|
});
|
|
94
128
|
|
|
129
|
+
// Fallback if no accounts found
|
|
95
130
|
if (tradingAccounts.length === 0 && service.user) {
|
|
96
131
|
const userName = service.user.userName || 'Unknown';
|
|
97
|
-
tradingAccounts
|
|
132
|
+
tradingAccounts.push({
|
|
98
133
|
accountId: hashAccountId(userName),
|
|
99
134
|
rithmicAccountId: userName,
|
|
100
135
|
accountName: userName,
|
|
101
136
|
name: userName,
|
|
102
|
-
balance:
|
|
103
|
-
startingBalance:
|
|
104
|
-
|
|
137
|
+
balance: null,
|
|
138
|
+
startingBalance: null,
|
|
139
|
+
todayPnL: null,
|
|
140
|
+
openPnL: null,
|
|
141
|
+
profitAndLoss: null,
|
|
105
142
|
status: 0,
|
|
106
143
|
platform: 'Rithmic',
|
|
107
144
|
propfirm: service.propfirm.name,
|
|
108
|
-
}
|
|
145
|
+
});
|
|
109
146
|
}
|
|
110
147
|
|
|
111
148
|
return { success: true, accounts: tradingAccounts };
|
|
@@ -128,7 +165,8 @@ const requestPnLSnapshot = async (service) => {
|
|
|
128
165
|
});
|
|
129
166
|
}
|
|
130
167
|
|
|
131
|
-
|
|
168
|
+
// Wait for P&L data to arrive
|
|
169
|
+
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
132
170
|
};
|
|
133
171
|
|
|
134
172
|
/**
|
|
@@ -151,10 +189,11 @@ const subscribePnLUpdates = (service) => {
|
|
|
151
189
|
};
|
|
152
190
|
|
|
153
191
|
/**
|
|
154
|
-
* Get positions
|
|
192
|
+
* Get positions - ONLY returns values from API
|
|
155
193
|
* @param {RithmicService} service - The Rithmic service instance
|
|
156
194
|
*/
|
|
157
195
|
const getPositions = async (service) => {
|
|
196
|
+
// Ensure PnL connection is active
|
|
158
197
|
if (!service.pnlConn && service.credentials) {
|
|
159
198
|
await service.connectPnL(service.credentials.username, service.credentials.password);
|
|
160
199
|
await requestPnLSnapshot(service);
|
|
@@ -165,8 +204,10 @@ const getPositions = async (service) => {
|
|
|
165
204
|
exchange: pos.exchange,
|
|
166
205
|
quantity: pos.quantity,
|
|
167
206
|
averagePrice: pos.averagePrice,
|
|
168
|
-
|
|
169
|
-
|
|
207
|
+
// From API only
|
|
208
|
+
unrealizedPnl: pos.openPnl !== undefined ? pos.openPnl : null,
|
|
209
|
+
realizedPnl: pos.closedPnl !== undefined ? pos.closedPnl : null,
|
|
210
|
+
dayPnl: pos.dayPnl !== undefined ? pos.dayPnl : null,
|
|
170
211
|
side: pos.quantity > 0 ? 'LONG' : 'SHORT',
|
|
171
212
|
}));
|
|
172
213
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tradovate Service
|
|
3
3
|
* Main service for Tradovate prop firm connections (Apex, TakeProfitTrader)
|
|
4
|
+
*
|
|
5
|
+
* STRICT RULE: Display ONLY values returned by API. No estimation, no simulation.
|
|
4
6
|
*/
|
|
5
7
|
|
|
6
8
|
const https = require('https');
|
|
@@ -112,7 +114,8 @@ class TradovateService extends EventEmitter {
|
|
|
112
114
|
}
|
|
113
115
|
|
|
114
116
|
/**
|
|
115
|
-
* Get trading accounts
|
|
117
|
+
* Get trading accounts - ONLY returns values from API
|
|
118
|
+
* No estimation, no simulation
|
|
116
119
|
*/
|
|
117
120
|
async getTradingAccounts() {
|
|
118
121
|
if (this.accounts.length === 0) {
|
|
@@ -121,20 +124,34 @@ class TradovateService extends EventEmitter {
|
|
|
121
124
|
|
|
122
125
|
const tradingAccounts = this.accounts.map((acc) => {
|
|
123
126
|
const cb = acc.cashBalance || {};
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const
|
|
127
|
-
|
|
127
|
+
|
|
128
|
+
// ONLY use values from API - null if not available
|
|
129
|
+
const balance = cb.totalCashValue !== undefined ? cb.totalCashValue :
|
|
130
|
+
(cb.netLiquidatingValue !== undefined ? cb.netLiquidatingValue : null);
|
|
131
|
+
|
|
132
|
+
// P&L from API only - null if not available
|
|
133
|
+
const realizedPnL = cb.realizedPnL !== undefined ? cb.realizedPnL : null;
|
|
134
|
+
const openPnL = cb.openPnL !== undefined ? cb.openPnL : null;
|
|
135
|
+
|
|
136
|
+
// Total P&L from API
|
|
137
|
+
let profitAndLoss = null;
|
|
138
|
+
if (cb.totalPnL !== undefined) {
|
|
139
|
+
profitAndLoss = cb.totalPnL;
|
|
140
|
+
} else if (realizedPnL !== null || openPnL !== null) {
|
|
141
|
+
profitAndLoss = (realizedPnL || 0) + (openPnL || 0);
|
|
142
|
+
}
|
|
128
143
|
|
|
129
144
|
return {
|
|
130
145
|
accountId: acc.id,
|
|
131
146
|
tradovateAccountId: acc.id,
|
|
132
147
|
accountName: acc.name,
|
|
133
148
|
name: acc.name,
|
|
149
|
+
// From API only - null if not available
|
|
134
150
|
balance: balance,
|
|
135
|
-
|
|
136
|
-
profitAndLoss: profitAndLoss,
|
|
151
|
+
todayPnL: realizedPnL,
|
|
137
152
|
openPnL: openPnL,
|
|
153
|
+
profitAndLoss: profitAndLoss,
|
|
154
|
+
startingBalance: null, // API doesn't provide this
|
|
138
155
|
status: acc.active ? 0 : 3,
|
|
139
156
|
platform: 'Tradovate',
|
|
140
157
|
propfirm: this.propfirm.name,
|
package/src/ui/index.js
CHANGED
|
@@ -37,8 +37,10 @@ const prepareStdin = () => {
|
|
|
37
37
|
// Remove any lingering keypress listeners
|
|
38
38
|
process.stdin.removeAllListeners('keypress');
|
|
39
39
|
process.stdin.removeAllListeners('data');
|
|
40
|
-
//
|
|
41
|
-
process.stdin.
|
|
40
|
+
// Resume stdin so inquirer can take control
|
|
41
|
+
if (process.stdin.isPaused()) {
|
|
42
|
+
process.stdin.resume();
|
|
43
|
+
}
|
|
42
44
|
} catch (e) {
|
|
43
45
|
// Ignore errors
|
|
44
46
|
}
|