Skip to content

Commit 8c29ff0

Browse files
committed
Release 2.1.6
1 parent 752845f commit 8c29ff0

File tree

8 files changed

+93
-15
lines changed

8 files changed

+93
-15
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "mage-db-sync",
3-
"version": "2.1.5",
3+
"version": "2.1.6",
44
"description": "Database synchronizer for Magento, based on Magerun",
55
"license": "MIT",
66
"author": {

src/controllers/MainController.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,13 @@ class MainController {
1313
protected services: ServiceContainer;
1414
public list = new Listr(
1515
[],
16-
{concurrent: false}
16+
{
17+
concurrent: false,
18+
exitOnError: true,
19+
rendererOptions: {
20+
collapseErrors: false
21+
}
22+
}
1723
);
1824
public ssh = new NodeSSH();
1925
public sshSecondDatabase = new NodeSSH();

src/controllers/StartController.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,18 @@ class StartController extends MainController {
3636
process.exit(0);
3737
} catch (e) {
3838
const error = e as Error;
39+
const logger = this.services.getLogger();
40+
41+
// Log error for debugging
42+
logger.error('Operation failed', error);
43+
44+
// Display user-friendly error message
45+
console.log('\n');
3946
UI.error(`Operation failed: ${error.message}`);
4047

41-
if (error.stack) {
42-
console.log('\n' + error.stack);
48+
if (error.stack && process.env.DEBUG) {
49+
console.log('\nStack trace:');
50+
console.log(error.stack);
4351
}
4452

4553
// Try to close SSH connections on error (might already be closed)
@@ -49,6 +57,8 @@ class StartController extends MainController {
4957
// Ignore cleanup errors during error handling
5058
}
5159

60+
// Force exit with error code
61+
process.exitCode = 1;
5262
process.exit(1);
5363
}
5464
};

src/tasks/ChecksTask.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { Listr } from 'listr2';
66
import { consoleCommand, localhostMagentoRootExec } from '../utils/Console';
77
import { ServiceContainer } from '../core/ServiceContainer';
88
import { ConfigPathResolver } from '../utils/ConfigPathResolver';
9+
import { UI } from '../utils/UI';
910

1011
interface CheckResult {
1112
success: boolean;
@@ -186,6 +187,28 @@ class ChecksTask {
186187
config.settings.import === 'yes' ||
187188
(config.settings.wordpressImport === 'yes' && config.settings.currentFolderhasWordpress)
188189
) {
190+
// Check if DDEV is running when isDdevActive is true
191+
if (config.settings.isDdevActive) {
192+
this.checkTasks.push({
193+
title: 'Checking DDEV project status',
194+
task: async (ctx: any, task: any): Promise<boolean> => {
195+
task.output = 'Verifying DDEV is running...';
196+
const commandService = this.services.getCommand();
197+
const isRunning = await commandService.isDdevActive();
198+
199+
if (!isRunning) {
200+
throw UI.createError(
201+
`DDEV project is not running in this directory\n` +
202+
`[TIP] Start your DDEV project with: ddev start`
203+
);
204+
}
205+
206+
task.output = 'DDEV project is running';
207+
return true;
208+
}
209+
});
210+
}
211+
189212
// Check Magerun 2 version (requires command execution)
190213
this.checkTasks.push({
191214
title: 'Checking Magerun2 version',

src/tasks/DownloadTask.ts

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,25 @@ class DownloadTask {
9696
try {
9797
await SSHConnectionPool.getConnection(host, sshConfig, async () => {
9898
await ssh.connect(sshConfig);
99+
100+
// Add error handler to prevent unhandled ECONNRESET errors
101+
if (ssh && ssh.connection) {
102+
const logger = this.services.getLogger();
103+
ssh.connection.on('error', (err: Error) => {
104+
// Catch and log connection errors to prevent process crash
105+
if (err.message && err.message.includes('ECONNRESET')) {
106+
logger.debug('SSH connection reset', { host });
107+
} else {
108+
logger.error('SSH connection error', err, { host });
109+
}
110+
});
111+
}
112+
99113
return ssh;
100114
});
101115
} catch (error) {
102116
const err = error as Error;
103-
throw new Error(
117+
throw UI.createError(
104118
`Failed to connect to ${host}\n` +
105119
`[TIP] Check your SSH credentials and key format\n` +
106120
`Error: ${err.message}`
@@ -255,7 +269,7 @@ class DownloadTask {
255269
database: config.serverVariables.databaseName
256270
});
257271
} catch (_e) {
258-
throw new Error(
272+
throw UI.createError(
259273
`Could not retrieve database name from server.\n` +
260274
`Magerun output: ${output}\n` +
261275
`[TIP] Check if Magerun can connect to the database on the server`
@@ -264,7 +278,7 @@ class DownloadTask {
264278
}
265279

266280
if (!config.serverVariables.databaseName) {
267-
throw new Error(
281+
throw UI.createError(
268282
`Database name could not be determined.\n` +
269283
`[TIP] Check server Magento configuration and database connectivity`
270284
);
@@ -507,7 +521,7 @@ class DownloadTask {
507521
clearInterval(sizeCheckInterval);
508522

509523
if (result.code && result.code !== 0) {
510-
throw new Error(
524+
throw UI.createError(
511525
`Database dump failed\n[TIP] Check database permissions and disk space\nError: ${result.stderr}`
512526
);
513527
}
@@ -628,7 +642,7 @@ class DownloadTask {
628642
rsync.on('exit', function (code: any) {
629643
if (code !== 0) {
630644
reject(
631-
new Error(
645+
UI.createError(
632646
`Download failed with code ${code}\n[TIP] Check SSH connection and file permissions`
633647
)
634648
);
@@ -711,13 +725,13 @@ class DownloadTask {
711725
});
712726
}
713727
}).catch((error: any) => {
714-
throw new Error(
728+
throw UI.createError(
715729
`Could not read wp-config.php from server\n[TIP] Make sure WordPress is installed in wp/, blog/, or wordpress/ folder\nError: ${error.message}`
716730
);
717731
});
718732

719733
if (!config.wordpressConfig.database) {
720-
throw new Error(
734+
throw UI.createError(
721735
`Could not parse WordPress database configuration from wp-config.php\n[TIP] Check if wp-config.php is properly formatted`
722736
);
723737
}
@@ -766,7 +780,7 @@ class DownloadTask {
766780

767781
await ssh.execCommand(dumpCommand).then(function (result: any) {
768782
if (result.code && result.code !== 0) {
769-
throw new Error(
783+
throw UI.createError(
770784
`WordPress database dump failed\n[TIP] Check WordPress database credentials and permissions\nError: ${result.stderr}`
771785
);
772786
}

src/utils/Performance.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,14 @@ export class SSHConnectionPool {
104104
.filter(conn => conn && conn !== null && typeof conn.dispose === 'function')
105105
.map(conn => {
106106
try {
107+
// Add error handler before disposal to catch ECONNRESET
108+
if (conn.connection && typeof conn.connection.on === 'function') {
109+
conn.connection.removeAllListeners('error');
110+
conn.connection.on('error', () => {
111+
// Silently ignore errors during disposal
112+
});
113+
}
114+
107115
const disposeResult = conn.dispose();
108116
return disposeResult && typeof disposeResult.catch === 'function'
109117
? disposeResult.catch(() => {})

src/utils/UI.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,28 @@ export class UI {
6060
console.log(chalk.green('[OK]') + ' ' + chalk.white(message));
6161
}
6262

63+
/**
64+
* Format error message with colored [TIP] sections
65+
*/
66+
static formatErrorMessage(message: string): string {
67+
// Replace [TIP] with colored version (magenta/purple)
68+
return message.replace(/\[TIP\]/g, chalk.magenta.bold('[TIP]'));
69+
}
70+
71+
/**
72+
* Create an Error with formatted message (colored [TIP])
73+
* Use this when throwing errors that contain [TIP] sections
74+
*/
75+
static createError(message: string): Error {
76+
return new Error(this.formatErrorMessage(message));
77+
}
78+
6379
/**
6480
* Show error message
6581
*/
6682
static error(message: string): void {
67-
console.log(chalk.red('[ERROR]') + ' ' + chalk.white(message));
83+
const formattedMessage = this.formatErrorMessage(message);
84+
console.log(chalk.red('[ERROR]') + ' ' + chalk.white(formattedMessage));
6885
}
6986

7087
/**

0 commit comments

Comments
 (0)