Skip to content

Commit

Permalink
Fix #83 eslint 9.0 config
Browse files Browse the repository at this point in the history
- upd tests
  • Loading branch information
boly38 committed Apr 18, 2024
1 parent f1ea9fa commit 813c63b
Show file tree
Hide file tree
Showing 16 changed files with 7,191 additions and 5,472 deletions.
6 changes: 0 additions & 6 deletions .eslintrc

This file was deleted.

1 change: 1 addition & 0 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ If you're interested in an existing issue, please contribute by up-voting for it

If you want to push some code :
- fork and prepare a feature-git-branch, then create a [pull request](https://github.com/boly38/node-mongotools/pulls) that link your issue.
- execute test and linter using `npm test` and `npm run lint`.

You could also be critic with existing ticket/PR : all constructive feedbacks are welcome.

Expand Down
26 changes: 26 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// https://eslint.org/docs/latest
import js from "@eslint/js";
import globals from "globals";
import mochaPlugin from 'eslint-plugin-mocha'; // https://www.npmjs.com/package/eslint-plugin-mocha
export default [
js.configs.recommended, // Recommended config applied to all files
mochaPlugin.configs.flat.recommended, // or `mochaPlugin.configs.flat.all` to enable all
{
files: ["lib/**/*.js", "examples/**/*.js", "tests/**/*.js"],
"parserOptions": {
"sourceType": "module",
},
languageOptions: {
ecmaVersion: 2022,
sourceType: "module",
globals: {
...globals.node,
"process": true,
myCustomGlobal: "readonly"
}
},
rules: {
"mocha/no-mocha-arrows": "off"/* pff */
}
}
];
37 changes: 18 additions & 19 deletions examples/sample_backup_and_rotate.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,27 @@ import os from "os";

// node-mongotools users must use this line
// import { MongoTools, MTOptions, MTCommand } from "node-mongotools";

// import from inside project
import { MongoTools, MTOptions, MTCommand } from "../lib/mt.js";
import {MongoTools, MTCommand} from "../lib/mt.js";

async function dumpAndRotate(uri, path){
var mt = new MongoTools();
var mtc = new MTCommand();// to reuse log methods
// mongodump
const dumpResult = await mt.mongodump({ uri, path })
.catch(mtc.logError.bind(mtc));
if (dumpResult === undefined) {// error case
process.exit(1);
}
mtc.logSuccess(dumpResult);
async function dumpAndRotate(uri, path) {
const mt = new MongoTools();
const mtc = new MTCommand();// to reuse log methods
// mongodump
const dumpResult = await mt.mongodump({uri, path})
.catch(mtc.logError.bind(mtc));
if (dumpResult === undefined) {// error case
process.exit(1);
}
mtc.logSuccess(dumpResult);

// backups rotation
const rotationResult = await mt.rotation({path, rotationWindowsDays: 5, rotationMinCount:1})
.catch(mtc.logError.bind(mtc));
if (rotationResult === undefined) {// error case
process.exit(1);
}
mtc.logSuccess(rotationResult);
// backups rotation
const rotationResult = await mt.rotation({path, rotationWindowsDays: 5, rotationMinCount: 1})
.catch(mtc.logError.bind(mtc));
if (rotationResult === undefined) {// error case
process.exit(1);
}
mtc.logSuccess(rotationResult);
}

const uri = process.env.MY_MONGO_URI
Expand Down
26 changes: 13 additions & 13 deletions examples/sample_restore.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,29 @@
// import { MongoTools, MTOptions, MTCommand } from "node-mongotools";

// import from inside project
import { MongoTools, MTOptions, MTCommand } from "../lib/mt.js";
import {MongoTools, MTCommand} from "../lib/mt.js";

async function restore(uri, dumpFile){
var mt = new MongoTools();
var mtc = new MTCommand();// to reuse log methods
// mongorestore
const restoreResult = await mt.mongorestore({
async function restore(uri, dumpFile) {
const mt = new MongoTools();
const mtc = new MTCommand();// to reuse log methods
// mongorestore
const restoreResult = await mt.mongorestore({
uri,
dumpFile,
dropBeforeRestore: true,
deleteDumpAfterRestore: true
})
.catch(mtc.logError.bind(mtc));
if (restoreResult === undefined) {// error case
process.exit(1);
}
mtc.logSuccess(restoreResult);
.catch(mtc.logError.bind(mtc));
if (restoreResult === undefined) {// error case
process.exit(1);
}
mtc.logSuccess(restoreResult);
}

// take first command line argument
if (process.argv.slice(2).length !== 1) {
console.log("please provide backup full filename as argument");
process.exit(1);
console.log("please provide backup full filename as argument");
process.exit(1);
}
var backupFilePath = process.argv.slice(2)[0];
const uri = process.env.MY_MONGO_URI
Expand Down
75 changes: 38 additions & 37 deletions lib/MTEncrypt.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,49 @@
import fs from 'fs';
import crypto from 'crypto';

const algorithm = 'aes-256-ctr';
const iv = "NODE-MONGOTOOLS_";// crypto.randomBytes(16);

// credit - July 30, 2020 - Atta : https://attacomsian.com/blog/nodejs-encrypt-decrypt-data
class MTEncrypt {

encrypt(source, destination, secretKey, removeSource=true) {
return new Promise(async function(resolve, reject) {
// input file
const inStream = fs.createReadStream(source);
// encrypt content
const encrypt = crypto.createCipheriv(algorithm, secretKey, iv);
// write file
const outFileStream = fs.createWriteStream(destination);

inStream.pipe(encrypt).pipe(outFileStream);

inStream.on('end', () => {
if (removeSource === true) {
fs.unlinkSync(source);
}
resolve();
});
});
}

decrypt(source, destination, secretKey) {
return new Promise(async function(resolve, reject) {
console.info("decrypt " + source + " into " + destination);
// input file
const inStream = fs.createReadStream(source);
// decrypt content
const decrypt = crypto.createDecipheriv(algorithm, secretKey, iv);
// write file
const outFileStream = fs.createWriteStream(destination);

inStream.pipe(decrypt).pipe(outFileStream);

inStream.on('end', () => {
resolve();
});
});
}
encrypt(source, destination, secretKey, removeSource = true) {
return new Promise(resolve => {
// input file
const inStream = fs.createReadStream(source);
// encrypt content
const encrypt = crypto.createCipheriv(algorithm, secretKey, iv);
// write file
const outFileStream = fs.createWriteStream(destination);

inStream.pipe(encrypt).pipe(outFileStream);

inStream.on('end', () => {
if (removeSource === true) {
fs.unlinkSync(source);
}
resolve();
});
});
}

decrypt(source, destination, secretKey) {
return new Promise(resolve => {
console.info("decrypt " + source + " into " + destination);
// input file
const inStream = fs.createReadStream(source);
// decrypt content
const decrypt = crypto.createDecipheriv(algorithm, secretKey, iv);
// write file
const outFileStream = fs.createWriteStream(destination);

inStream.pipe(decrypt).pipe(outFileStream);

inStream.on('end', () => {
resolve();
});
});
}

}

Expand Down
161 changes: 84 additions & 77 deletions lib/MTFilesystem.js
Original file line number Diff line number Diff line change
@@ -1,92 +1,99 @@
import fs from 'fs';
import path from "path";

const fsPromise = fs.promises;

class MTFilesystem {

listFromFilesystem(path) {
return new Promise(async function(resolve, reject) {
if (!fs.existsSync(path)) {
return reject(`no dump path ${path}`)
}
fs.readdir(path, (err, files) => {
if (err) {
return reject(err);
}
return resolve(files.map(f => path+'/'+f));
});
});
}

fileSystemRotation(dryMode, path, ctimeMsMax, cleanCount, minCount) {
const mt = this;
return new Promise(async function(resolve, reject) {
if (!fs.existsSync(path)) {
return reject(`no dump path ${path}`)
}
const existingBackupsWithStats = await mt.walk(path);
const initialBackupsCount = existingBackupsWithStats.length;

const deprecatedBackups = mt.filterByDate(existingBackupsWithStats, ctimeMsMax);
const deprecatedBackupsCount = deprecatedBackups.length;

const deletedBackups = await mt.backupsToClean(dryMode, deprecatedBackups, cleanCount, minCount);
const cleanedCount = deletedBackups.length;
const cleanedFiles = deletedBackups.map(db => db.filePath);
// DEBUG // console.log(JSON.stringify({deletedBackups}))
resolve({initialBackupsCount, deprecatedBackupsCount, cleanedCount, cleanedFiles});
});
}
listFromFilesystem(path) {
return new Promise((resolve, reject) => {
if (!fs.existsSync(path)) {
return reject(new Error(`no dump path ${path}`));
}
fs.readdir(path, (err, files) => {
if (err) {
return reject(err);
}
return resolve(files.map(f => path + '/' + f));
});
});
}

async backupsToClean(dryMode, deprecatedBackups, cleanCount, minCount) {
if (deprecatedBackups === null || deprecatedBackups === undefined || deprecatedBackups.length <= minCount) {
return [];
}
// sort by creation date asc
deprecatedBackups = deprecatedBackups.sort((a, b)=>{
return (a.stats.ctimeMs > b.stats.ctimeMs) - (a.stats.ctimeMs < b.stats.ctimeMs);// ctimeMs asc
});
// DEBUG // console.log("fs backupsToClean", {deprecatedBackups, cleanCount, minCount});
// keep nb to clean
var toDelete = deprecatedBackups.length > minCount ?
deprecatedBackups.slice(minCount, Math.min(minCount+cleanCount, deprecatedBackups.length))
: [];
// DEBUG // console.log("toDelete", {toDelete});
for (const toDeleteEntry of toDelete) {
if (!dryMode) {
await fsPromise.unlink(toDeleteEntry.filePath);
} else {
console.log("*dry mode* DELETE", toDeleteEntry.filePath );
}
}
return toDelete;
}
fileSystemRotation(dryMode, path, ctimeMsMax, cleanCount, minCount) {
const mt = this;
return new Promise((resolve, reject) => {
if (!fs.existsSync(path)) {
return reject(new Error(`no dump path ${path}`));
}
mt.walk(path)
.then(existingBackupsWithStats => {
const initialBackupsCount = existingBackupsWithStats.length;
const deprecatedBackups = mt.filterByDate(existingBackupsWithStats, ctimeMsMax);
const deprecatedBackupsCount = deprecatedBackups.length;
mt.backupsToClean(dryMode, deprecatedBackups, cleanCount, minCount)
.then(deletedBackups => {
const cleanedCount = deletedBackups.length;
const cleanedFiles = deletedBackups.map(db => db.filePath);
// DEBUG // console.log(JSON.stringify({deletedBackups}))
resolve({initialBackupsCount, deprecatedBackupsCount, cleanedCount, cleanedFiles});
});
})
.catch(err => reject(err));

filterByDate(filesWithStat, ctimeMsMax) {
if (filesWithStat === null || filesWithStat === undefined || filesWithStat.length < 1) {
return filesWithStat;
}
if (ctimeMsMax === null || ctimeMsMax === undefined) {
return filesWithStat;
});
}
return filesWithStat.filter(fws => fws.stats.ctimeMs < ctimeMsMax);
}

// https://nodejs.org/api/fs.html#fs_dir_read_callback
// https://stackoverflow.com/questions/2727167/how-do-you-get-a-list-of-the-names-of-all-files-present-in-a-directory-in-node-j
async walk(dir) {
let files = await fsPromise.readdir(dir);
files = await Promise.all(files.map(async file => {
const filePath = path.join(dir, file);
const stats = await fsPromise.stat(filePath);
if(stats.isFile()) return {filePath, stats};
return null;
}));
async backupsToClean(dryMode, deprecatedBackups, cleanCount, minCount) {
if (deprecatedBackups === null || deprecatedBackups === undefined || deprecatedBackups.length <= minCount) {
return [];
}
// sort by creation date asc
deprecatedBackups = deprecatedBackups.sort((a, b) => {
return (a.stats.ctimeMs > b.stats.ctimeMs) - (a.stats.ctimeMs < b.stats.ctimeMs);// ctimeMs asc
});
// DEBUG // console.log("fs backupsToClean", {deprecatedBackups, cleanCount, minCount});
// keep nb to clean
var toDelete = deprecatedBackups.length > minCount ?
deprecatedBackups.slice(minCount, Math.min(minCount + cleanCount, deprecatedBackups.length))
: [];
// DEBUG // console.log("toDelete", {toDelete});
for (const toDeleteEntry of toDelete) {
if (!dryMode) {
await fsPromise.unlink(toDeleteEntry.filePath);
} else {
console.log("*dry mode* DELETE", toDeleteEntry.filePath);
}
}
return toDelete;
}

const allEntries = files.reduce((all, folderContents) => all.concat(folderContents), [])
filterByDate(filesWithStat, ctimeMsMax) {
if (filesWithStat === null || filesWithStat === undefined || filesWithStat.length < 1) {
return filesWithStat;
}
if (ctimeMsMax === null || ctimeMsMax === undefined) {
return filesWithStat;
}
return filesWithStat.filter(fws => fws.stats.ctimeMs < ctimeMsMax);
}

return allEntries.filter( e => e !== null);
}
// https://nodejs.org/api/fs.html#fs_dir_read_callback
// https://stackoverflow.com/questions/2727167/how-do-you-get-a-list-of-the-names-of-all-files-present-in-a-directory-in-node-j
walk(dir) {
return new Promise((resolve, reject) => {
fsPromise.readdir(dir).then(readFiles => {
Promise.all(readFiles.map(async file => {
const filePath = path.join(dir, file);
const stats = await fsPromise.stat(filePath);
if (stats.isFile()) return {filePath, stats};
return null;
})).then(files => {
const allEntries = files.reduce((all, folderContents) => all.concat(folderContents), [])
resolve(allEntries.filter(e => e !== null));
}).catch(err => reject(err));
}).catch(err => reject(err));
});
}

}

Expand Down
Loading

0 comments on commit 813c63b

Please sign in to comment.