Skip to content

Commit 2efa636

Browse files
committed
feat: complete refactoring to ESM
and mocha/chai replaced by native node test runner
1 parent 86e0921 commit 2efa636

File tree

13 files changed

+679
-958
lines changed

13 files changed

+679
-958
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ TODO.md
99
/MusicBee_Export.csv
1010
/navidrome.db
1111
/backups/
12+
index.cjs

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ All commands have these options available:
7777
* `--db <path>` : Navidrome SQLITE .db source file path. By default if not passed, will look for a file named `navidrome.db` in the same folder as `musicbee-navidrome-sync.exe`
7878
* `-u, --user <user_name>` : selects Navidrome username (by default if not used, the first found user will be used)
7979
* `--verbose` : verbose debugging
80-
* `--show-not-found` : output that were not found in Navidrome database (useful for troubleshooting missing tracks without verbose output noise)
80+
* `--show-not-found` : display tracks that were not found in Navidrome database (useful for troubleshooting missing tracks without verbose output noise)
8181
* `-h, --help` : displays help for command
8282

8383

build.config.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { build } from 'esbuild';
2+
3+
const buildConfig = {
4+
entryPoints: ['index.js'],
5+
bundle: true,
6+
platform: 'node',
7+
target: 'node22',
8+
format: 'cjs', // for pkg compatibility
9+
outfile: '.dist/index.cjs',
10+
external: ['node:*'],
11+
packages: 'bundle',
12+
minify: true,
13+
sourcemap: false,
14+
banner: {
15+
js: `// Generated by esbuild - all dependencies bundled
16+
// Suppress SQLite experimental warnings before any imports
17+
const originalProcessEmitWarning = process.emitWarning;
18+
process.emitWarning = function(warning, type, code) {
19+
if (type === 'ExperimentalWarning' && warning.includes('SQLite')) {
20+
return;
21+
}
22+
return originalProcessEmitWarning.call(this, warning, type, code);
23+
};`
24+
}
25+
};
26+
27+
try {
28+
await build(buildConfig);
29+
console.log('✅ ESM → CommonJS bundling completed successfully');
30+
} catch (error) {
31+
console.error('❌ Build failed:', error);
32+
process.exit(1);
33+
}

build.sh

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ set -e
22

33
rm -rf .dist
44
mkdir -p .dist
5-
cp -r index.js package*.json lib .dist
6-
cd .dist
75

8-
echo "Installing dependencies..."
9-
npm install --omit=dev --omit=optional --no-fund --loglevel=error
6+
echo "Installing dependencies for bundling..."
7+
npm install --no-fund --loglevel=error
8+
9+
echo "Bundling ESM to CommonJS (with all dependencies)..."
10+
node build.config.js
11+
12+
cd .dist
1013

1114
echo "Building MBNDS exe..."
12-
pkg . --compress Brotli -o musicbee-navidrome-sync.exe
15+
npx @yao-pkg/pkg index.cjs --target node22-win-x64 --compress Brotli -o musicbee-navidrome-sync.exe

index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
const { program } = require('commander');
2-
const { MBNDSynchronizer } = require('./lib/MBNDSynchronizer.js');
3-
const packageJson = require('./package.json');
1+
import { program } from 'commander';
2+
import { MBNDSynchronizer } from './lib/MBNDSynchronizer.js';
3+
import packageJson from './package.json' with { type: 'json' };
44

55
const runAction = async (options, command) => {
66
const synchronizer = new MBNDSynchronizer(options);

lib/Database.js

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,8 @@
1-
// Suppress SQLite experimental warnings by setting warning filter first
2-
const originalProcessEmitWarning = process.emitWarning;
3-
process.emitWarning = function (warning, type, code) {
4-
if (type === 'ExperimentalWarning' && warning.includes('SQLite')) {
5-
return;
6-
}
7-
return originalProcessEmitWarning.call(this, warning, type, code);
8-
};
1+
import { randomUUID } from 'node:crypto';
2+
import { DatabaseSync } from 'node:sqlite';
3+
import dayjs from 'dayjs';
4+
import utc from 'dayjs/plugin/utc.js';
95

10-
const { DatabaseSync } = require('node:sqlite');
11-
const { randomUUID } = require('node:crypto');
12-
const dayjs = require('dayjs');
13-
const utc = require('dayjs/plugin/utc');
146
dayjs.extend(utc);
157

168
/**
@@ -162,7 +154,7 @@ class Database {
162154
}
163155
}
164156

165-
exports.init = dbFilePath => {
157+
export const init = async dbFilePath => {
166158
try {
167159
const database = new Database(dbFilePath);
168160
console.log('Connection has been established successfully.');

lib/MBNDSynchronizer.js

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
1-
const fs = require('node:fs');
2-
const path = require('node:path');
3-
const csv2json = require('csvtojson');
4-
const pLimit = require('p-limit');
5-
const cliProgress = require('cli-progress');
6-
const camelCase = require('camelcase');
7-
const dayjs = require('dayjs');
8-
const customParseFormat = require('dayjs/plugin/customParseFormat');
9-
const duration = require('dayjs/plugin/duration');
10-
const relativeTime = require('dayjs/plugin/relativeTime');
11-
const utc = require('dayjs/plugin/utc');
1+
import fs from 'node:fs';
2+
import path from 'node:path';
3+
import camelCase from 'camelcase';
4+
import cliProgress from 'cli-progress';
5+
import csv2json from 'csvtojson';
6+
import dayjs from 'dayjs';
7+
import customParseFormat from 'dayjs/plugin/customParseFormat.js';
8+
import duration from 'dayjs/plugin/duration.js';
9+
import relativeTime from 'dayjs/plugin/relativeTime.js';
10+
import utc from 'dayjs/plugin/utc.js';
11+
import pLimit from 'p-limit';
12+
1213
dayjs.extend(utc);
1314
dayjs.extend(customParseFormat);
1415
dayjs.extend(duration);
1516
dayjs.extend(relativeTime);
1617

17-
const dbManager = require('./Database');
18-
const { findBestMatch, isDateAfter } = require('./helpers');
19-
const packageJson = require('../package.json');
18+
import packageJson from '../package.json' with { type: 'json' };
19+
import * as dbManager from './Database.js';
20+
import { findBestMatch, isDateAfter } from './helpers.js';
2021

2122
class MBNDSynchronizer {
2223
constructor(options) {
@@ -670,4 +671,4 @@ class MBNDSynchronizer {
670671
};
671672
}
672673

673-
exports.MBNDSynchronizer = MBNDSynchronizer;
674+
export { MBNDSynchronizer };

lib/helpers.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
const dayjs = require('dayjs');
2-
const utc = require('dayjs/plugin/utc');
1+
import dayjs from 'dayjs';
2+
import utc from 'dayjs/plugin/utc.js';
3+
34
dayjs.extend(utc);
45

56
/**
@@ -75,4 +76,4 @@ const isDateAfter = (dateA, dateB) => {
7576
return dayjsA.isAfter(dayjsB);
7677
};
7778

78-
module.exports = { findBestMatch, isDateAfter };
79+
export { findBestMatch, isDateAfter };

0 commit comments

Comments
 (0)