diff --git a/.editorconfig b/.editorconfig new file mode 100755 index 0000000..b14689f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,40 @@ +# This file is for unifying the coding style for different editors and IDEs +# editorconfig.org + +root = true + +[*] +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +# Spaces in coffee +[**.coffee] +indent_style = tab +indent_size = 2 + +[**.js] +indent_style = tab +indent_size = 2 + +[**.ts] +indent_style = tab +indent_size = 2 + +# Tabs in less +[**.less] +indent_style = tab +indent_size = 2 + +[**.css] +indent_style = tab +indent_size = 2 + +[**.php] +indent_style = tab +indent_size = 2 + +[**.html] +indent_style = tab +indent_size = 2 diff --git a/babel.config.js b/babel.config.js index 246d56b..d082361 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,12 +1,12 @@ const presets = [ [ - "@babel/preset-env", + '@babel/preset-env', { targets: { node: 'current' } } ] -]; +] -module.exports = { presets }; \ No newline at end of file +module.exports = { presets } \ No newline at end of file diff --git a/conf/configs.ts b/conf/configs.ts index ccb0129..58e8c71 100644 --- a/conf/configs.ts +++ b/conf/configs.ts @@ -6,55 +6,55 @@ import cv from './controlled_vocabulary' import log, {LogLevelDesc} from 'loglevel' interface ConfigOverride { - iso_date_format?: string, - log_actions?: string, - log_level?: 'debug' | 'warn' | 'info', + iso_date_format?: string, + log_actions?: string, + log_level?: 'debug' | 'warn' | 'info', } /** * configuration générale à importer dans les utilitaires */ class config_rangement { - log_level: LogLevelDesc = 'debug' // 'debug' | 'warn' |'info' + log_level: LogLevelDesc = 'debug' // 'debug' | 'warn' |'info' - version = '1.0.0' - iso_date_format = 'yyyy-MM-DDTHH.mm.ss' // target format for dates in file names - tagSeparator = ' ' - tagSectionSeparator = '--' - keepFreeText = true - keepTags = true - replaceUnderscoreWithSpaces = true - renameFolders = false - enableTestsLocally = false - reportStatistics = true - controlled_vocabulary = cv - constants = constants - base_archive_folder = constants.base_archive_folder - templates = mainTemplates; - statistics = {}; - keepOriginalNameInRename = false; - log_actions = true; + version = '1.0.0' + iso_date_format = 'yyyy-MM-DDTHH.mm.ss' // target format for dates in file names + tagSeparator = ' ' + tagSectionSeparator = '--' + keepFreeText = true + keepTags = true + replaceUnderscoreWithSpaces = true + renameFolders = false + enableTestsLocally = false + reportStatistics = true + controlled_vocabulary = cv + constants = constants + base_archive_folder = constants.base_archive_folder + templates = mainTemplates; + statistics = {}; + keepOriginalNameInRename = false; + log_actions = true; - /** - * override config if we want - * @param overridingConfig - */ - constructor(overridingConfig?: ConfigOverride) { + /** + * override config if we want + * @param overridingConfig + */ + constructor(overridingConfig?: ConfigOverride) { - log.setLevel('info') - if (overridingConfig) { - log.debug('configuration is overrided') - let keys = Object.keys(overridingConfig) - let self: any = this; - keys.forEach((elem, index) => { - if (self[keys[index]]) { - self[keys[index]] = elem - } - }) - } + log.setLevel('info') + if (overridingConfig) { + log.debug('configuration is overrided') + let keys = Object.keys(overridingConfig) + let self: any = this; + keys.forEach((elem, index) => { + if (self[keys[index]]) { + self[keys[index]] = elem + } + }) + } - } + } } const rangement_instance = new config_rangement({}); diff --git a/conf/folders.ts b/conf/folders.ts index e8554f6..7d396a4 100644 --- a/conf/folders.ts +++ b/conf/folders.ts @@ -19,4 +19,4 @@ const folders = { orgmode_folder: syncronized_folder + 'textes/orgmode', } -export default folders \ No newline at end of file +export default folders diff --git a/conf/mainTemplates.ts b/conf/mainTemplates.ts index df2d00a..9a4feaf 100644 --- a/conf/mainTemplates.ts +++ b/conf/mainTemplates.ts @@ -1,10 +1,12 @@ import constants from './folders' -interface fileDetectionTemplate{ + +interface fileDetectionTemplate { 'example': string, 'pattern': any, - 'auto_tag'?:string, - 'auto_sort_folder'?:string + 'auto_tag'?: string, + 'auto_sort_folder'?: string } + interface AssemblyOfFileDetection { downloaded_pic: fileDetectionTemplate, telegram_pic: fileDetectionTemplate, @@ -12,50 +14,50 @@ interface AssemblyOfFileDetection { open_camera_custom: fileDetectionTemplate, screenshot: fileDetectionTemplate, gopro_front: fileDetectionTemplate, - gopro_back : fileDetectionTemplate + gopro_back: fileDetectionTemplate } -const setOfFileDetections : AssemblyOfFileDetection= { - 'downloaded_pic':{ +const setOfFileDetections: AssemblyOfFileDetection = { + 'downloaded_pic': { 'example': 'FyB8cZnWIAc21rw.jpg', 'pattern': /^\-\w{15}\.jpg/, - 'auto_tag':'', + 'auto_tag': '', 'auto_sort_folder': constants.bazar_sub_folder }, 'telegram_pic': { 'example': '-4900281569878475578_1109.jpg', 'pattern': /^\-\d{19}_\d{4}/, - 'auto_tag':'', + 'auto_tag': '', 'auto_sort_folder': constants.bazar_sub_folder }, 'open_camera_default': { 'example': 'IMG_20230617_092120_3.jpg', 'pattern': /^IMG_\d{8}/i, - 'auto_tag':'', + 'auto_tag': '', 'auto_sort_folder': constants.panoramax_captures_folder }, 'open_camera_custom': { 'example': 'IMG_OC_20230617_092120_3.jpg', 'pattern': /^IMG_OC_\d{8}/i, - 'auto_tag':'', + 'auto_tag': '', 'auto_sort_folder': constants.panoramax_captures_folder }, 'screenshot': { 'example': 'Screenshot 2023-06-15 at 15-26-04 Instance Panoramax OSM-FR.png', 'pattern': /^Screenshot/i, - 'auto_tag':'screenshots', + 'auto_tag': 'screenshots', 'auto_sort_folder': 'photos/captures écran screenshots' }, 'gopro_front': { 'example': 'GF010041.jpg', 'pattern': /^GP?F\d+\.jpg/i, - 'auto_tag':'gopro-front gopro', + 'auto_tag': 'gopro-front gopro', 'auto_sort_folder': constants.gopro_capture_folder }, 'gopro_back': { 'example': 'GB010041.jpg', 'pattern': /^GP?B\d+\.jpg/i, - 'auto_tag':'gopro-back gopro', + 'auto_tag': 'gopro-back gopro', 'auto_sort_folder': constants.gopro_capture_folder }, } diff --git a/create_folders.mjs b/create_folders.mjs index 2819eae..a1c937e 100644 --- a/create_folders.mjs +++ b/create_folders.mjs @@ -3,10 +3,11 @@ */ import config_rangement from './conf/configs.js' + let my_conf = new config_rangement({}) console.log('config', my_conf.version) -function createFoldersFromConfig(){ +function createFoldersFromConfig () { // TODO } \ No newline at end of file diff --git a/index.ts b/index.ts index a6f8766..5711497 100644 --- a/index.ts +++ b/index.ts @@ -6,10 +6,7 @@ /** --------------------- libs --------------------- */ -import fs from 'node-fs' -import minimist from 'minimist' import log from 'loglevel' -import * as path from 'node:path' /** --------------------- custom utilities and configuration --------------------- */ @@ -21,7 +18,6 @@ log.setLevel(rangement_instance.log_level) log.info(' ') - finder.parseArguments() finder.guessFileNameOnAllFilesFromArguments() diff --git a/jest.config.ts b/jest.config.ts index 9a9366a..477f26c 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -3,12 +3,12 @@ * https://jestjs.io/docs/configuration */ module.exports = { - testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|js?|tsx?|ts?)$", - transform: { - "^.+\\.jsx?$": "babel-jest", - "^.+\\.mjs$": "babel-jest", - "^.+\\.ts$": "babel-jest", - }, - testPathIgnorePatterns: ["/build/", "/node_modules/"], - moduleFileExtensions: ["js", "jsx", "mjs"] + testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|js?|tsx?|ts?)$", + transform: { + "^.+\\.jsx?$": "babel-jest", + "^.+\\.mjs$": "babel-jest", + "^.+\\.ts$": "babel-jest", + }, + testPathIgnorePatterns: ["/build/", "/node_modules/"], + moduleFileExtensions: ["js", "jsx", "mjs"] } diff --git a/old_index.mjs b/old_index.mjs index c6bec89..e5ec76c 100644 --- a/old_index.mjs +++ b/old_index.mjs @@ -6,10 +6,7 @@ /** --------------------- libs --------------------- */ -import fs from 'node-fs' -import minimist from 'minimist' import log from 'loglevel' -import path from 'node:path' /** --------------------- custom utilities and configuration --------------------- */ @@ -21,9 +18,6 @@ let mini_arguments log.setLevel(rangement_instance.log_level) log.info(' ') - - - finder.parseArguments() finder.guessFileNameOnAllFilesFromArguments() diff --git a/tests/finder.test.js b/tests/finder.test.js index 83bab6f..7aebc91 100644 --- a/tests/finder.test.js +++ b/tests/finder.test.js @@ -44,8 +44,6 @@ describe('detection in file name', () => { describe('modification in file name', () => { - - test('should append to file name in the right place', () => { let fileNameOriginal = 'mon texte -- famille vacances plage.jpg' let properties = finder.destructurateFileName(fileNameOriginal) diff --git a/tests/main.test.js b/tests/main.test.js index 12b6fd8..310860f 100644 --- a/tests/main.test.js +++ b/tests/main.test.js @@ -1,15 +1,12 @@ -import finder from "../utils/finder.ts"; -import { Jest as mockUpload } from '@jest/environment' - xdescribe('rangement file detection', () => { - // find how to mock process.env arguments - // const call = mockUpload.mock.calls[0][0] + // find how to mock process.env arguments + // const call = mockUpload.mock.calls[0][0] - test('returns a list of 2 files to parse when given the folder testFiles/meme_base', () => { - }); - test('returns a list of 1 file to parse when given the argument testFiles/image.jpg', () => { - }); - test('returns a list of 0 file to parse when given the null argument', () => { - }); + test('returns a list of 2 files to parse when given the folder testFiles/meme_base', () => { + }) + test('returns a list of 1 file to parse when given the argument testFiles/image.jpg', () => { + }) + test('returns a list of 0 file to parse when given the null argument', () => { + }) }) diff --git a/tests/pdf.test.js b/tests/pdf.test.js index 1c29ea9..b28533e 100644 --- a/tests/pdf.test.js +++ b/tests/pdf.test.js @@ -1,4 +1,3 @@ - xdescribe('detection and tagging with content found in PDF content', () => { xtest('should find invoice hint in pdf', () => { diff --git a/tests/templates.test.js b/tests/templates.test.js index c308ac1..763151a 100644 --- a/tests/templates.test.js +++ b/tests/templates.test.js @@ -1,4 +1,3 @@ - xdescribe('detection and renaming of templated file names', () => { xtest('should detect screenshot pattern', () => { diff --git a/tsconfig.json b/tsconfig.json index 9b702eb..4780dfc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,15 +1,12 @@ { // This is an alias to @tsconfig/node16: https://github.com/tsconfig/bases "extends": "ts-node/node16/tsconfig.json", - // Most ts-node options can be specified here using their programmatic names. "ts-node": { // It is faster to skip typechecking. // Remove if you want ts-node to do typechecking. "transpileOnly": true, - "files": true, - "compilerOptions": { // compilerOptions specified here will override those declared below, // but *only* in ts-node. Useful if you want ts-node and tsc to use @@ -18,5 +15,6 @@ }, "compilerOptions": { // typescript options here + "allowSyntheticDefaultImports": true } } \ No newline at end of file diff --git a/utils/finder.ts b/utils/finder.ts index b7670a8..1d2c7c4 100644 --- a/utils/finder.ts +++ b/utils/finder.ts @@ -21,545 +21,546 @@ let cwd = path.dirname(process.cwd()) + '/' + path.basename(process.cwd()) */ export default class finder { - static statistics = { - filesModified: 0, - filesNotModified: 0, - } - private static otherRenames: any = []; - private static fileList: any = []; - private static expandedFileList: any = []; - private static mini_arguments: any; - - - static readSubdirectories(baseDir: string) { - fs.readdir(baseDir, (err, filesList) => { - if (err) throw err - - log.debug('readSubdirectories - files', filesList) - - filesList.forEach((subDirOrFile) => { - const newFullPath = cwd + '/' + subDirOrFile - - if (fs.existsSync(newFullPath)) { - const s = fs.statSync(newFullPath) - - if (s.isFile()) { - this.expandedFileList.push(cwd + '/' + subDirOrFile) - } - } - }) - - return filesList; - }) - } - - static isFolderOrFile(filePathName: string) { - const stat = fs.statSync(filePathName) - - if (stat.isDirectory()) { - this.fileList = this.readSubdirectories(filePathName) - log.debug('fileList in directory ', filePathName, '\n', this.fileList) - if (this.fileList.length) { - this.expandedFileList.push(...this.fileList) - } - } else if (stat.isFile()) { - this.expandedFileList.push(filePathName) - } - } - - - /** - * guess file name on one file which is not a directory - * @param fullPath - */ - - static guessFileNameOnOnefile(fullPath: string): void { - - log.info('go guess file name on file: ', fullPath) - - fs.stat(fullPath, (err, stats) => { - - if (err) { - log.error('échec fichier', err) - log.error('ce fichier n existe pas: ', fullPath) - return - } else { - - log.debug(' -------- le fichier existe bien, déstructuration') - let structureForFile = this.destructurateFileName(fullPath) - log.debug(' -------- ', fullPath) - log.debug(' -------- ', structureForFile) - - // examiner les infos exif de chaque fichier pour proposer un nouveau nom - if (!structureForFile.dateStampInFileNameOriginal) { - log.info(' le nom de fichier "' + structureForFile.freeText + '" ne contient pas de date formatée au début') - } else { - log.debug(' -------- dateStampInFileNameOriginal: ', structureForFile.dateStampInFileNameOriginal) - } - - log.debug(' -------- trouver les infos exif', structureForFile.fullPath) - this.findExifCreationDate(structureForFile.fullPath) - .then(data => { - log.info(' ... chercher la date de création : "' + structureForFile.freeText + '"') - log.debug('data', data) - let foundDate = this.findEarliestDateInExifData(data) - - log.info(' =>>>>>>> foundDate : ', foundDate) - if (foundDate) { - structureForFile.dateStampExif = foundDate - } else { - log.info('pas de date trouvée dans le nom') - } - this.shouldWeChangeName(structureForFile) - } - , - (error) => { - log.warn('/////////// Error in reading exif of file: ' + error.message) - return '' - }) - - - } - }) - } - - - /** - * if there is no original file name free text into the new name, append it to the free text part - * @param originalFileName - * @param fileMixedNewName - */ - static addOriginalFileNameIfMissing(originalFileName: string, fileMixedNewName: string) { - - if (!fileMixedNewName.includes(originalFileName)) { - let properties = finder.destructurateFileName(fileMixedNewName) - return properties.freeText + ' ' + originalFileName - } else { - return fileMixedNewName - } - } - - static reportStatistics() { - log.info('\n --------- statistics', - this.statistics) - } - - static renameFile(originalFileName: string, fileMixedNewName: string) { - if (rangement_instance.keepOriginalNameInRename) { - log.debug(' +++++++++ on ajoute le nom original dans le free text +++++++',originalFileName ) - fileMixedNewName = this.addOriginalFileNameIfMissing(originalFileName, fileMixedNewName) - log.debug(' +++++++++ nouveau nom', fileMixedNewName) - } - - let self = this; - fs.rename(originalFileName, fileMixedNewName, function (err) { - log.info(' ✅ name changed', fileMixedNewName) - if (err) { - log.info('rename ERROR: ' + err) - } else { - self.otherRenames.push(fileMixedNewName) - - finder.statistics['filesModified']++ - } - }) - } - - static guessFileNameOnAllFilesFromArguments(): void { - - // parcourir les fichiers - log.debug('_____________ liste des fichiers', this.mini_arguments._) - let fileList = this.mini_arguments._ - - // test file exists - fileList.forEach((fullPath: string) => { - log.debug('file list element: ', fullPath) - // parcourir les dossiers - this.isFolderOrFile(`${fullPath}`) - } - ) - - log.info('expanded file list :', this.expandedFileList) - this.expandedFileList.forEach((filePath: string) => { - this.guessFileNameOnOnefile(filePath) - }) - - if (rangement_instance.reportStatistics || this.mini_arguments.stats) { - finder.reportStatistics() - } } - - - static makeFileNameFromProperties(fileProperties: fileDestructuration) { - - let tagPlace = '' - log.info('fileProperties.tags', fileProperties.tags) - if (fileProperties.tags.length && rangement_instance.keepTags) { - tagPlace = ' ' + rangement_instance.tagSectionSeparator + ' ' + fileProperties.tags.join(rangement_instance.tagSeparator) - } - log.debug('fileProperties.dateStampExif', fileProperties.dateStampExif) - let spacer = ''; - if(fileProperties.dateStampExif && fileProperties.freeText && rangement_instance.keepFreeText){ - spacer = ' ' - } - let newName = '' - + fileProperties.dateStampExif - + spacer - + (rangement_instance.keepFreeText ? fileProperties.freeText : '') - + tagPlace.trim() - + fileProperties.extension.trim() - - if (rangement_instance.replaceUnderscoreWithSpaces) { - newName = newName.replace('_', ' ') - } - - newName = finder.cleanSpaces(newName) - - return newName - } - - static parseArguments() { - this.mini_arguments = minimist(process.argv.slice(2)) - log.debug('arguments', this.mini_arguments) - if (!this.mini_arguments._.length) { - log.info('pas de fichier ou de dossier demandé, veuillez spécifier un chemin en argument') - } - } - - static shouldWeChangeName(structureForFile: fileDestructuration) { - log.info(' ______ shouldWeChangeName ', structureForFile.fileNameOriginal) - let newName = this.makeFileNameFromProperties(structureForFile) - log.debug('newName', newName) - if(this.otherRenames.includes(newName)){ - log.debug('nouveau nom déjà présent dans les fichiers déjà renommés, on garde en état actuel') - return; - } - if (structureForFile.fileNameOriginal !== newName) { - - log.info('\n ancien nom :', structureForFile.fileNameOriginal) - - log.info(' nouveau nom:', newName) - if (!this.mini_arguments['dry-run']) { - - log.debug('___________ structureForFile.folderPath', structureForFile.folderPath) - log.debug('___________ newName', newName) - - this.renameFile(structureForFile.fullPath, - structureForFile.folderPath + newName) - } else { - log.info('no renaming for real, this is a dry run') - finder.statistics['filesNotModified']++ - } - } else { - log.info(' rien à changer') - } - } - - static findScreenshot(inputString: string) { - return inputString.match(/screenshot/i) || inputString.match(/capture d'écran/i) - } - - static findFormattedDate(filepath: string) { - let match = filepath.match(/\d{4}-\d{2}-\d{2}T\d{2}\.\d{2}\.\d{2}/ig) - log.debug(' finder - match findFormattedDate', match) - let result = '' - if (match && match[0]) { - result = match[0] - } - return result - } - - static findFileExtension(inputString: string): string { - let result = inputString.match(/\.\w{3,4}$/i) - if (result && result.length) { - return result[0] - } - return '' - } - - /** - * find the section of file name which contains the free text to describe the picture - * @param fileName - * @returns {*|string} - */ - static findFileNameFreeTextPart(fileName: string) { - fileName = fileName.replace(this.findFileExtension(fileName), '') - let boom = fileName.split(rangement_instance.tagSectionSeparator) - if (boom.length) { - let freeTextPart = boom[0].trim() - // remove date - let foundDate = this.findFormattedDate(freeTextPart) - if (foundDate) { - freeTextPart = freeTextPart.replace(foundDate, '').trim() - } - log.debug(' finder - freeTextPart:', freeTextPart) - return freeTextPart - } - return fileName.trim() - } - - /** - * find an array of tags - * @param inputString - * @returns {[]} - */ - static findTagSectionInString(inputString: string) { - let listOfTags: Array = [] - // remove extension - let extensionFile = finder.findFileExtension(inputString) - - if (extensionFile) { - - inputString = inputString.replace(extensionFile, '') - } else { - log.debug(' finder - no extensionFile', extensionFile, inputString) - extensionFile = '' - } - inputString = inputString.replace(extensionFile, '') - - log.debug(' finder - extensionFile', extensionFile) - if (inputString.includes(rangement_instance.tagSectionSeparator)) { - log.debug(' finder - inputString', inputString) - if (inputString.length) { - - let boom = inputString.split(rangement_instance.tagSectionSeparator) - log.debug(' finder - boom', boom) - if (boom.length) { - listOfTags = [...boom[1].trim().split(rangement_instance.tagSeparator)] - log.debug(' finder - listOfTags', listOfTags) - } else { - log.debug(' finder - no boom', boom) - } - } - } - return listOfTags - } - - static removeTagInProperties(properties: fileDestructuration, tagName: string) { - - let foundTagNameIndex = properties.tags.indexOf(tagName) - if (foundTagNameIndex) { - delete properties.tags[foundTagNameIndex] - } - return properties - } - - static cleanSpaces(inputString: string) { - return inputString.replace(/ *g/, ' ').replace(/ /, ' ').trim() - } - - static searchAndReplaceInFileName(searchString: string, replaceString: string, fileName: string): string { - return this.cleanSpaces(fileName.replace(searchString, replaceString)) - } - - /** - * search screenshot clues and rename - */ - static searchAndRenameScreenshots(fileName: string) { - if (finder.findScreenshot(fileName)) { - let tags = this.findTagSectionInString(fileName) - log.debug(' finder - tags', tags) - if (!tags.includes('screenshot')) { - - fileName = this.addTagInFileName('screenshot', fileName) - fileName = this.searchAndReplaceInFileName('Screenshot', '', fileName) - log.debug(' finder - screenShotMockFileName:', fileName) - return this.cleanSpaces(fileName) - } - log.debug(' finder - is a screenshot, remove screenshot in name, and add tag screenshot') - } else { - return null - } - } - - /** - * determines if we must add or remove new tags - * @param tagCommand - * @returns {{tagsToAdd: [], tagCommand: *, tagsToRemove: []}} - */ - static addOrRemoveTagsParsing(tagCommand: string): taggingCommand { - let tagsToAdd: Array = [] - let tagsToRemove: Array = [] - - // split all tags - let listOfTags = tagCommand.split(' ') - listOfTags.forEach(elem => { - // remove when a minus is present* - if (elem.indexOf('-')) { - tagsToRemove.push(elem) - } else { - // add tag otherwise - tagsToAdd.push(elem) - } - }) - - return {tagCommand, tagsToAdd, tagsToRemove} - } - - static applyTagChangesOnProperties(tagChange: any, properties: fileDestructuration) { - // add new tags - properties.tags = [...properties.tags, tagChange.tagsToAdd] - properties.tags.forEach((elem, index) => { - if (tagChange.tagsToRemove.includes(elem)) { - delete properties.tags[index] - } - }) - properties.tags = [...new Set(properties.tags)]; - - return properties - } - - /** - * add a tag and gives new filename with extension - * @param tagName - * @param fileName - * @returns {*} - */ - static addTagInFileName(tagName: string, fileName: string) { - - let tags: any = this.findTagSectionInString(fileName) - let firstPart = this.findFileNameFreeTextPart(fileName) - - tags.push(tagName) - // @ts-ignore - let uniqueArray = [...new Set(tags)] - - let newFileName = firstPart + ' ' + rangement_instance.tagSectionSeparator + ' ' + uniqueArray.join(rangement_instance.tagSeparator) - newFileName = newFileName.replace(/ {*}/, '') + this.findFileExtension(fileName) - return this.cleanSpaces(newFileName) - } - - /** - * convertit un nom de fichier en une structure décrivant plusieurs parties correspondant au pattern d'archivage - * @param fullPath - * @returns {{extension: *, dateStamp: string, freeText: (*|string), tags: *[]}} - */ - static destructurateFileName(fullPath: string): fileDestructuration { - let [folderPath, fileNameOriginal] = this.findFolderPath(fullPath) - - // if path is relative, add the current working directory as full path part - if (/^\\(?!\\)/.test(fullPath)) { - fullPath = cwd + '/' + fullPath - } - - return { - fullPath, - folderPath, - fileNameOriginal, - dateStampInFileNameOriginal: this.findFormattedDate(fileNameOriginal), - dateStampExif: '', - freeText: this.findFileNameFreeTextPart(fileNameOriginal), - tags: this.findTagSectionInString(fileNameOriginal), - extension: this.findFileExtension(fileNameOriginal), - } as fileDestructuration - - } - - /** - * finds the earliest part in several exif date info - * @param exifData - * @returns {string} - */ - static findEarliestDateInExifData(exifData: any) { - log.debug(' finder - findEarliestDateInExifData') - if (exifData) { - - let moments = [] - - console.log(' finder - exif data : ', exifData) - log.info(' finder - exif data : ', exifData) - if (exifData.DateTimeOriginal) { - log.debug(' finder - image créée le : DateTimeOriginal : ', exifData.DateTimeOriginal) - moments.push(exifData.DateTimeOriginal) - } - if (exifData.FileModificationDateTime) { - log.debug(' finder - image créée le : File Modification Date/Time : ', exifData.FileModificationDateTime) - moments.push(exifData.FileModificationDateTime) - } - if (exifData.FileModificationDate) { - log.debug(' finder - image créée le : File Modification Date/Time : ', exifData.FileModificationDate) - moments.push(exifData.FileModificationDate) - } - if (exifData.ModificationDateTime) { - log.debug(' finder - image créée le : ModificationDateTime : ', exifData.ModificationDateTime) - moments.push(exifData.ModificationDateTime) - } - if (exifData.ModifyDate) { - log.debug(' finder - image créée le : ModifyDate : ', exifData.ModifyDate) - moments.push(exifData.ModifyDate) - } - if (exifData.FileAccessDateTime) { - moments.push(exifData.FileAccessDateTime) - } - if (exifData.DateTime) { - moments.push(exifData.DateTime) - } - if (exifData.FileInodeChangeDateTime) { - moments.push(exifData.FileInodeChangeDateTime) - } - if (exifData.FileModificationDateTime) { - log.debug(' finder - image créée le : FileModificationDateTime : ', exifData.FileModificationDateTime) - moments.push(exifData.FileModificationDateTime) - } - if (exifData.CreateDate) { - log.debug(' finder - image créée le : CreateDate : ', exifData.CreateDate) - moments.push(exifData.CreateDate) - } - - moments = moments.map(d => { - let newdate = moment(d) - return newdate - }) - let minDate = moment.min(moments) - - log.debug(' finder - minDate :::::::::', minDate) - log.info(' finder - minDate :::::::::', minDate.format(rangement_instance.iso_date_format)) - - return minDate.format(rangement_instance.iso_date_format) - } else { - log.debug(' finder - 😥 /!\\ pas de exif data') - return '' - } - } - - - static appendFileName(fileProperties: fileDestructuration, newText: string) { - fileProperties.freeText = finder.cleanSpaces(fileProperties.freeText + ' ' + newText) - return fileProperties - } - - static prependFileName(fileProperties: fileDestructuration, newText: string) { - fileProperties.freeText = finder.cleanSpaces(newText + ' ' + fileProperties.freeText) - return fileProperties - } - - /** - * examine plusieurs propriétés exif de date et retourne la plus ancienne - * @param filepath - */ - static async findExifCreationDate(filepath: string) { - - log.debug(' -------- findExifCreationDate') - let dateAlreadyInFileName = finder.findFormattedDate(filepath) - if (dateAlreadyInFileName) { - log.debug(' finder - ------ dateAlreadyInFileName', dateAlreadyInFileName) - } else { - log.debug(' -------- pas de date présente') - } - - let exifPromise = await exifr.parse(filepath); - log.debug(' -------- exifdata', exifPromise) - - return exifPromise - - } - - static findFolderPath(filePath: string) { - let folders: any = filePath.split('/') - let fileName: any = folders.pop() - folders = filePath.replace(fileName, '') - - log.debug(' finder - \n - folders', folders) - log.debug(' finder - - fileName', fileName, '\n') - return [folders, fileName] - - } -} \ No newline at end of file + static statistics = { + filesModified: 0, + filesNotModified: 0, + } + private static otherRenames: any = []; + private static fileList: any = []; + private static expandedFileList: any = []; + private static mini_arguments: any; + + + static readSubdirectories(baseDir: string) { + fs.readdir(baseDir, (err, filesList) => { + if (err) throw err + + log.debug('readSubdirectories - files', filesList) + + filesList.forEach((subDirOrFile) => { + const newFullPath = cwd + '/' + subDirOrFile + + if (fs.existsSync(newFullPath)) { + const s = fs.statSync(newFullPath) + + if (s.isFile()) { + this.expandedFileList.push(cwd + '/' + subDirOrFile) + } + } + }) + + return filesList; + }) + } + + static isFolderOrFile(filePathName: string) { + const stat = fs.statSync(filePathName) + + if (stat.isDirectory()) { + this.fileList = this.readSubdirectories(filePathName) + log.debug('fileList in directory ', filePathName, '\n', this.fileList) + if (this.fileList.length) { + this.expandedFileList.push(...this.fileList) + } + } else if (stat.isFile()) { + this.expandedFileList.push(filePathName) + } + } + + + /** + * guess file name on one file which is not a directory + * @param fullPath + */ + + static guessFileNameOnOnefile(fullPath: string): void { + + log.info('go guess file name on file: ', fullPath) + + fs.stat(fullPath, (err, stats) => { + + if (err) { + log.error('échec fichier', err) + log.error('ce fichier n existe pas: ', fullPath) + return + } else { + + log.debug(' -------- le fichier existe bien, déstructuration') + let structureForFile = this.destructurateFileName(fullPath) + log.debug(' -------- ', fullPath) + log.debug(' -------- ', structureForFile) + + // examiner les infos exif de chaque fichier pour proposer un nouveau nom + if (!structureForFile.dateStampInFileNameOriginal) { + log.info(' le nom de fichier "' + structureForFile.freeText + '" ne contient pas de date formatée au début') + } else { + log.debug(' -------- dateStampInFileNameOriginal: ', structureForFile.dateStampInFileNameOriginal) + } + + log.debug(' -------- trouver les infos exif', structureForFile.fullPath) + this.findExifCreationDate(structureForFile.fullPath) + .then(data => { + log.info(' ... chercher la date de création : "' + structureForFile.freeText + '"') + log.debug('data', data) + let foundDate = this.findEarliestDateInExifData(data) + + log.info(' =>>>>>>> foundDate : ', foundDate) + if (foundDate) { + structureForFile.dateStampExif = foundDate + } else { + log.info('pas de date trouvée dans le nom') + } + this.shouldWeChangeName(structureForFile) + } + , + (error) => { + log.warn('/////////// Error in reading exif of file: ' + error.message) + return '' + }) + + + } + }) + } + + + /** + * if there is no original file name free text into the new name, append it to the free text part + * @param originalFileName + * @param fileMixedNewName + */ + static addOriginalFileNameIfMissing(originalFileName: string, fileMixedNewName: string) { + + if (!fileMixedNewName.includes(originalFileName)) { + let properties = finder.destructurateFileName(fileMixedNewName) + return properties.freeText + ' ' + originalFileName + } else { + return fileMixedNewName + } + } + + static reportStatistics() { + log.info('\n --------- statistics', + this.statistics) + } + + static renameFile(originalFileName: string, fileMixedNewName: string) { + if (rangement_instance.keepOriginalNameInRename) { + log.debug(' +++++++++ on ajoute le nom original dans le free text +++++++', originalFileName) + fileMixedNewName = this.addOriginalFileNameIfMissing(originalFileName, fileMixedNewName) + log.debug(' +++++++++ nouveau nom', fileMixedNewName) + } + + let self = this; + fs.rename(originalFileName, fileMixedNewName, function (err) { + log.info(' ✅ name changed', fileMixedNewName) + if (err) { + log.info('rename ERROR: ' + err) + } else { + self.otherRenames.push(fileMixedNewName) + + finder.statistics['filesModified']++ + } + }) + } + + static guessFileNameOnAllFilesFromArguments(): void { + + // parcourir les fichiers + log.debug('_____________ liste des fichiers', this.mini_arguments._) + let fileList = this.mini_arguments._ + + // test file exists + fileList.forEach((fullPath: string) => { + log.debug('file list element: ', fullPath) + // parcourir les dossiers + this.isFolderOrFile(`${fullPath}`) + } + ) + + log.info('expanded file list :', this.expandedFileList) + this.expandedFileList.forEach((filePath: string) => { + this.guessFileNameOnOnefile(filePath) + }) + + if (rangement_instance.reportStatistics || this.mini_arguments.stats) { + finder.reportStatistics() + } + } + + + static makeFileNameFromProperties(fileProperties: fileDestructuration) { + + let tagPlace = '' + log.info('fileProperties.tags', fileProperties.tags) + if (fileProperties.tags.length && rangement_instance.keepTags) { + tagPlace = ' ' + rangement_instance.tagSectionSeparator + ' ' + fileProperties.tags.join(rangement_instance.tagSeparator) + } + log.debug('fileProperties.dateStampExif', fileProperties.dateStampExif) + let spacer = ''; + if (fileProperties.dateStampExif && fileProperties.freeText && rangement_instance.keepFreeText) { + spacer = ' ' + } + let newName = '' + + fileProperties.dateStampExif + + spacer + + (rangement_instance.keepFreeText ? fileProperties.freeText : '') + + tagPlace.trim() + + fileProperties.extension.trim() + + if (rangement_instance.replaceUnderscoreWithSpaces) { + newName = newName.replace('_', ' ') + } + + newName = finder.cleanSpaces(newName) + + return newName + } + + static parseArguments() { + this.mini_arguments = minimist(process.argv.slice(2)) + log.debug('arguments', this.mini_arguments) + if (!this.mini_arguments._.length) { + log.info('pas de fichier ou de dossier demandé, veuillez spécifier un chemin en argument') + } + } + + static shouldWeChangeName(structureForFile: fileDestructuration) { + log.info(' ______ shouldWeChangeName ', structureForFile.fileNameOriginal) + let newName = this.makeFileNameFromProperties(structureForFile) + log.debug('newName', newName) + if (this.otherRenames.includes(newName)) { + log.debug('nouveau nom déjà présent dans les fichiers déjà renommés, on garde en état actuel') + return; + } + if (structureForFile.fileNameOriginal !== newName) { + + log.info('\n ancien nom :', structureForFile.fileNameOriginal) + + log.info(' nouveau nom:', newName) + if (!this.mini_arguments['dry-run']) { + + log.debug('___________ structureForFile.folderPath', structureForFile.folderPath) + log.debug('___________ newName', newName) + + this.renameFile(structureForFile.fullPath, + structureForFile.folderPath + newName) + } else { + log.info('no renaming for real, this is a dry run') + finder.statistics['filesNotModified']++ + } + } else { + log.info(' rien à changer') + } + } + + static findScreenshot(inputString: string) { + return inputString.match(/screenshot/i) || inputString.match(/capture d'écran/i) + } + + static findFormattedDate(filepath: string) { + let match = filepath.match(/\d{4}-\d{2}-\d{2}T\d{2}\.\d{2}\.\d{2}/ig) + log.debug(' finder - match findFormattedDate', match) + let result = '' + if (match && match[0]) { + result = match[0] + } + return result + } + + static findFileExtension(inputString: string): string { + let result = inputString.match(/\.\w{3,4}$/i) + if (result && result.length) { + return result[0] + } + return '' + } + + /** + * find the section of file name which contains the free text to describe the picture + * @param fileName + * @returns {*|string} + */ + static findFileNameFreeTextPart(fileName: string) { + fileName = fileName.replace(this.findFileExtension(fileName), '') + let boom = fileName.split(rangement_instance.tagSectionSeparator) + if (boom.length) { + let freeTextPart = boom[0].trim() + // remove date + let foundDate = this.findFormattedDate(freeTextPart) + if (foundDate) { + freeTextPart = freeTextPart.replace(foundDate, '').trim() + } + log.debug(' finder - freeTextPart:', freeTextPart) + return freeTextPart + } + return fileName.trim() + } + + /** + * find an array of tags + * @param inputString + * @returns {[]} + */ + static findTagSectionInString(inputString: string) { + let listOfTags: Array = [] + // remove extension + let extensionFile = finder.findFileExtension(inputString) + + if (extensionFile) { + + inputString = inputString.replace(extensionFile, '') + } else { + log.debug(' finder - no extensionFile', extensionFile, inputString) + extensionFile = '' + } + inputString = inputString.replace(extensionFile, '') + + log.debug(' finder - extensionFile', extensionFile) + if (inputString.includes(rangement_instance.tagSectionSeparator)) { + log.debug(' finder - inputString', inputString) + if (inputString.length) { + + let boom = inputString.split(rangement_instance.tagSectionSeparator) + log.debug(' finder - boom', boom) + if (boom.length) { + listOfTags = [...boom[1].trim().split(rangement_instance.tagSeparator)] + log.debug(' finder - listOfTags', listOfTags) + } else { + log.debug(' finder - no boom', boom) + } + } + } + return listOfTags + } + + static removeTagInProperties(properties: fileDestructuration, tagName: string) { + + let foundTagNameIndex = properties.tags.indexOf(tagName) + if (foundTagNameIndex) { + delete properties.tags[foundTagNameIndex] + } + return properties + } + + static cleanSpaces(inputString: string) { + return inputString.replace(/ *g/, ' ').replace(/ /, ' ').trim() + } + + static searchAndReplaceInFileName(searchString: string, replaceString: string, fileName: string): string { + return this.cleanSpaces(fileName.replace(searchString, replaceString)) + } + + /** + * search screenshot clues and rename + */ + static searchAndRenameScreenshots(fileName: string) { + if (finder.findScreenshot(fileName)) { + let tags = this.findTagSectionInString(fileName) + log.debug(' finder - tags', tags) + if (!tags.includes('screenshot')) { + + fileName = this.addTagInFileName('screenshot', fileName) + fileName = this.searchAndReplaceInFileName('Screenshot', '', fileName) + log.debug(' finder - screenShotMockFileName:', fileName) + return this.cleanSpaces(fileName) + } + log.debug(' finder - is a screenshot, remove screenshot in name, and add tag screenshot') + } else { + return null + } + } + + /** + * determines if we must add or remove new tags + * @param tagCommand + * @returns {{tagsToAdd: [], tagCommand: *, tagsToRemove: []}} + */ + static addOrRemoveTagsParsing(tagCommand: string): taggingCommand { + let tagsToAdd: Array = [] + let tagsToRemove: Array = [] + + // split all tags + let listOfTags = tagCommand.split(' ') + listOfTags.forEach(elem => { + // remove when a minus is present* + if (elem.indexOf('-')) { + tagsToRemove.push(elem) + } else { + // add tag otherwise + tagsToAdd.push(elem) + } + }) + + return {tagCommand, tagsToAdd, tagsToRemove} + } + + static applyTagChangesOnProperties(tagChange: any, properties: fileDestructuration) { + // add new tags + properties.tags = [...properties.tags, tagChange.tagsToAdd] + properties.tags.forEach((elem, index) => { + if (tagChange.tagsToRemove.includes(elem)) { + delete properties.tags[index] + } + }) + properties.tags = [...new Set(properties.tags)]; + + return properties + } + + /** + * add a tag and gives new filename with extension + * @param tagName + * @param fileName + * @returns {*} + */ + static addTagInFileName(tagName: string, fileName: string) { + + let tags: any = this.findTagSectionInString(fileName) + let firstPart = this.findFileNameFreeTextPart(fileName) + + tags.push(tagName) + // @ts-ignore + let uniqueArray = [...new Set(tags)] + + let newFileName = firstPart + ' ' + rangement_instance.tagSectionSeparator + ' ' + uniqueArray.join(rangement_instance.tagSeparator) + newFileName = newFileName.replace(/ {*}/, '') + this.findFileExtension(fileName) + return this.cleanSpaces(newFileName) + } + + /** + * convertit un nom de fichier en une structure décrivant plusieurs parties correspondant au pattern d'archivage + * @param fullPath + * @returns {{extension: *, dateStamp: string, freeText: (*|string), tags: *[]}} + */ + static destructurateFileName(fullPath: string): fileDestructuration { + let [folderPath, fileNameOriginal] = this.findFolderPath(fullPath) + + // if path is relative, add the current working directory as full path part + if (/^\\(?!\\)/.test(fullPath)) { + fullPath = cwd + '/' + fullPath + } + + return { + fullPath, + folderPath, + fileNameOriginal, + dateStampInFileNameOriginal: this.findFormattedDate(fileNameOriginal), + dateStampExif: '', + freeText: this.findFileNameFreeTextPart(fileNameOriginal), + tags: this.findTagSectionInString(fileNameOriginal), + extension: this.findFileExtension(fileNameOriginal), + } as fileDestructuration + + } + + /** + * finds the earliest part in several exif date info + * @param exifData + * @returns {string} + */ + static findEarliestDateInExifData(exifData: any) { + log.debug(' finder - findEarliestDateInExifData') + if (exifData) { + + let moments = [] + + console.log(' finder - exif data : ', exifData) + log.info(' finder - exif data : ', exifData) + if (exifData.DateTimeOriginal) { + log.debug(' finder - image créée le : DateTimeOriginal : ', exifData.DateTimeOriginal) + moments.push(exifData.DateTimeOriginal) + } + if (exifData.FileModificationDateTime) { + log.debug(' finder - image créée le : File Modification Date/Time : ', exifData.FileModificationDateTime) + moments.push(exifData.FileModificationDateTime) + } + if (exifData.FileModificationDate) { + log.debug(' finder - image créée le : File Modification Date/Time : ', exifData.FileModificationDate) + moments.push(exifData.FileModificationDate) + } + if (exifData.ModificationDateTime) { + log.debug(' finder - image créée le : ModificationDateTime : ', exifData.ModificationDateTime) + moments.push(exifData.ModificationDateTime) + } + if (exifData.ModifyDate) { + log.debug(' finder - image créée le : ModifyDate : ', exifData.ModifyDate) + moments.push(exifData.ModifyDate) + } + if (exifData.FileAccessDateTime) { + moments.push(exifData.FileAccessDateTime) + } + if (exifData.DateTime) { + moments.push(exifData.DateTime) + } + if (exifData.FileInodeChangeDateTime) { + moments.push(exifData.FileInodeChangeDateTime) + } + if (exifData.FileModificationDateTime) { + log.debug(' finder - image créée le : FileModificationDateTime : ', exifData.FileModificationDateTime) + moments.push(exifData.FileModificationDateTime) + } + if (exifData.CreateDate) { + log.debug(' finder - image créée le : CreateDate : ', exifData.CreateDate) + moments.push(exifData.CreateDate) + } + + moments = moments.map(d => { + let newdate = moment(d) + return newdate + }) + let minDate = moment.min(moments) + + log.debug(' finder - minDate :::::::::', minDate) + log.info(' finder - minDate :::::::::', minDate.format(rangement_instance.iso_date_format)) + + return minDate.format(rangement_instance.iso_date_format) + } else { + log.debug(' finder - 😥 /!\\ pas de exif data') + return '' + } + } + + + static appendFileName(fileProperties: fileDestructuration, newText: string) { + fileProperties.freeText = finder.cleanSpaces(fileProperties.freeText + ' ' + newText) + return fileProperties + } + + static prependFileName(fileProperties: fileDestructuration, newText: string) { + fileProperties.freeText = finder.cleanSpaces(newText + ' ' + fileProperties.freeText) + return fileProperties + } + + /** + * examine plusieurs propriétés exif de date et retourne la plus ancienne + * @param filepath + */ + static async findExifCreationDate(filepath: string) { + + log.debug(' -------- findExifCreationDate') + let dateAlreadyInFileName = finder.findFormattedDate(filepath) + if (dateAlreadyInFileName) { + log.debug(' finder - ------ dateAlreadyInFileName', dateAlreadyInFileName) + } else { + log.debug(' -------- pas de date présente') + } + + let exifPromise = await exifr.parse(filepath); + log.debug(' -------- exifdata', exifPromise) + + return exifPromise + + } + + static findFolderPath(filePath: string) { + let folders: any = filePath.split('/') + let fileName: any = folders.pop() + folders = filePath.replace(fileName, '') + + log.debug(' finder - \n - folders', folders) + log.debug(' finder - - fileName', fileName, '\n') + return [folders, fileName] + + } +} diff --git a/utils/interfaces.ts b/utils/interfaces.ts index 6db4fe6..59fb22f 100644 --- a/utils/interfaces.ts +++ b/utils/interfaces.ts @@ -1,16 +1,16 @@ export interface fileDestructuration { - fullPath: string - folderPath: string - fileNameOriginal: string - dateStampInFileNameOriginal: string - dateStampExif: string, - freeText: string, - tags: string[], - extension: string, + fullPath: string + folderPath: string + fileNameOriginal: string + dateStampInFileNameOriginal: string + dateStampExif: string, + freeText: string, + tags: string[], + extension: string, } export interface taggingCommand { - tagCommand: string, - tagsToAdd: Array, - tagsToRemove: Array -} \ No newline at end of file + tagCommand: string, + tagsToAdd: Array, + tagsToRemove: Array +} diff --git a/utils/testFunctions.mjs b/utils/testFunctions.mjs index e99e815..a065b0e 100644 --- a/utils/testFunctions.mjs +++ b/utils/testFunctions.mjs @@ -1,5 +1,4 @@ -import finder from './finder.js' - +import finder from './finder.js' const pathFolder = '/home/poule/encrypted/stockage-syncable/photos/a_dispatcher/tout' const sortingFolder = '/home/poule/encrypted/stockage-syncable/photos/a_dispatcher' @@ -11,7 +10,7 @@ const fileDefinition = { extension: '', } -export function TestScreenShotIsFoundAndRenamed() { +export function TestScreenShotIsFoundAndRenamed () { let screenShotMockFileName = 'Screenshot 2023-06-15 at 15-28-21 Instance Panoramax OSM-FR.png' let screenShotMockFileNameExpected = '2023-06-15 at 15-28-21 Instance Panoramax OSM-FR -- screenshot.png' @@ -26,7 +25,7 @@ export function TestScreenShotIsFoundAndRenamed() { } } -export function TestTagsAreDetectedInFileName() { +export function TestTagsAreDetectedInFileName () { let mockFileName = '2023-06-15T10:11:12 -- screeenshot festival.png' let expectedResult = ['screeenshot', 'festival'] let found = finder.findTagSectionInString(mockFileName) @@ -35,8 +34,7 @@ export function TestTagsAreDetectedInFileName() { } } - -export function TestFindFormattedDate() { +export function TestFindFormattedDate () { let mockFileName = 'Capture d\'écran 2023-06-15T10:11:12.png' let expectedResult = '2023-06-15T10:11:12' let found = finder.findFormattedDate(mockFileName) diff --git a/utils/workInProgress/not_ready_functions.mjs b/utils/workInProgress/not_ready_functions.mjs index 9b17641..138bf91 100644 --- a/utils/workInProgress/not_ready_functions.mjs +++ b/utils/workInProgress/not_ready_functions.mjs @@ -134,7 +134,6 @@ class notReadyFunctions { } - // run tests if (rangement_instance.enableTestsLocally) { @@ -143,7 +142,4 @@ if (rangement_instance.enableTestsLocally) { TestScreenShotIsFoundAndRenamed() } - - - export default notReadyFunctions \ No newline at end of file diff --git a/utils/workInProgress/setup.mjs b/utils/workInProgress/setup.mjs index 2baa43f..070970b 100644 --- a/utils/workInProgress/setup.mjs +++ b/utils/workInProgress/setup.mjs @@ -2,37 +2,36 @@ création de la config */ // import i18next from 'i18next' -import config_rangement from "../../conf/configs.js"; +import config_rangement from '../../conf/configs.js' -const { stdin, stdout } = process; +const { stdin, stdout } = process -function prompt(question) { - return new Promise((resolve, reject) => { - stdin.resume(); - stdout.write(question); +function prompt (question) { + return new Promise((resolve, reject) => { + stdin.resume() + stdout.write(question) - stdin.on('data', data => resolve(data.toString().trim())); - stdin.on('error', err => reject(err)); - }); + stdin.on('data', data => resolve(data.toString().trim())) + stdin.on('error', err => reject(err)) + }) } +async function main () { + try { + // const name = await prompt(i18next.t("home.title")) + const name = await prompt(`squoi le dossier de base des archives? [${config_rangement.base_archive_folder}]`) + // const age = await prompt("What's your age? "); + // const email = await prompt("What's your email address? "); + // const user = { name, age, email }; + console.log('le dossier de base des archives est : ', name) -async function main() { - try { - // const name = await prompt(i18next.t("home.title")) - const name = await prompt(`squoi le dossier de base des archives? [${config_rangement.base_archive_folder}]`) - // const age = await prompt("What's your age? "); - // const email = await prompt("What's your email address? "); - // const user = { name, age, email }; - console.log('le dossier de base des archives est : ',name); - - stdin.pause(); - } catch(error) { - console.log("There's an error!"); - console.log(error); - } - process.exit(); + stdin.pause() + } catch (error) { + console.log('There\'s an error!') + console.log(error) + } + process.exit() } -main(); +main()