diff --git a/.gitignore b/.gitignore index c20d627..ca750c8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,268 +1,267 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. - -# User-specific files -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ - -# Visual Studio 2015 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUNIT -*.VisualState.xml -TestResult.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# DNX -project.lock.json -project.fragment.lock.json -artifacts/ - -*_i.c -*_p.c -*_i.h -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# JustCode is a .NET coding add-in -.JustCode - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# TODO: Comment the next line if you want to checkin your web deploy settings -# but database connection strings (with potential passwords) will be unencrypted -#*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# The packages folder can be ignored because of Package Restore -**/packages/* -# except build/, which is used as an MSBuild target. -!**/packages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/packages/repositories.config -# NuGet v3's project.json files produces more ignoreable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -node_modules/ -orleans.codegen.cs - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm - -# SQL Server files -*.mdf -*.ldf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# JetBrains Rider -.idea/ -*.sln.iml - -# CodeRush -.cr/ - -# Python Tools for Visual Studio (PTVS) -__pycache__/ -*.pyc - -*.sln -*.njsproj -node_modules/ -*.snyk -advisories.json -*.licenseheader +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +#*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +*.sln +*.njsproj +node_modules/ +*.snyk +advisories.json diff --git a/CHANGELOG.md b/CHANGELOG.md index febb11c..85bf696 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,15 @@   -#### *v3.8.4 - 07/10/2019 +#### *v3.8.5 - 21/10/2019 + + - Refactored the import parser and made multiple optimisations. + - Updated dependencies. + - Added more testing. + +  + +#### v3.8.4 - 07/10/2019 - The output of `merger update` is now printed on the console. diff --git a/VERSION.md b/VERSION.md index 291dd97..ae07af9 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1,3 +1,3 @@ # Current Branch Version -**v3.8.4** +**v3.8.5** diff --git a/enums/importType.js b/enums/importType.js new file mode 100644 index 0000000..c23664e --- /dev/null +++ b/enums/importType.js @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2018-2019 João Pedro Martins Neves - All Rights Reserved. + * + * MergerJS (merger-js) is licensed under the MIT license, located in + * the root of this project, under the name "LICENSE.md". + * + */ + + +const ImportType = Object.freeze( { + Unknown: -1, + RelativePath: 1, + NodeModules: 2, + SpecificURL: 3, + GitHub: 4 +} ); + +module.exports = ImportType; diff --git a/enums/promptResponseType.js b/enums/promptResponseType.js index cafaf5a..18b530e 100644 --- a/enums/promptResponseType.js +++ b/enums/promptResponseType.js @@ -1,4 +1,12 @@ -const promptResponseType = Object.freeze( { +/* + * Copyright (c) 2018-2019 João Pedro Martins Neves - All Rights Reserved. + * + * MergerJS (merger-js) is licensed under the MIT license, located in + * the root of this project, under the name "LICENSE.md". + * + */ + +const promptResponseType = Object.freeze( { Afirmative: 'Yes', Negative: 'No' } ); diff --git a/enums/tokenType.js b/enums/tokenType.js index 5e5343a..20f4593 100644 --- a/enums/tokenType.js +++ b/enums/tokenType.js @@ -1,25 +1,40 @@ -const StaticClass = require( '../models/staticClassBase' ); +/* + * Copyright (c) 2018-2019 João Pedro Martins Neves - All Rights Reserved. + * + * MergerJS (merger-js) is licensed under the MIT license, located in + * the root of this project, under the name "LICENSE.md". + * + */ + +const StaticClass = require( '../models/staticClassBase' ); class TokenType extends StaticClass { constructor() { super( 'TokenType' ); } - static get token_push() { return '<<' } - static get token_DIR() { return `${TokenType.token_push}DIR` } - static get token_DIRECTORY() { return `${TokenType.token_push}DIRECTORY` } - static get token_dir() { return `${TokenType.token_push}dir` } - static get token_directory() { return `${TokenType.token_push}directory` } - static get token_GH() { return `${TokenType.token_push}GH` } - static get token_gh() { return `${TokenType.token_push}gh` } - static get token_github() { return `${TokenType.token_push}github` } - static get token_GITHUB() { return `${TokenType.token_push}GITHUB` } - static get token_importPath_simbol() { return "@" } - static get token_importPath() { return `${TokenType.token_importPath_simbol}import` } - static get token_importNodeModules_simbol() { return "$" } - static get token_importNodeModules() { return `${TokenType.token_importNodeModules_simbol}import` } - static get token_importUrl_simbol() { return "%" } - static get token_importUrl() { return `${TokenType.token_importUrl_simbol}import` } + static get importPath_simbol() { return '@'; } + static get importPath() { return `${TokenType.importPath_simbol}import`; } + + static get importNodeModules_simbol() { return '$'; } + static get importNodeModules() { return `${TokenType.importNodeModules_simbol}import`; } + + static get importUrl_simbol() { return '%'; } + static get doubleImportUrl_simbol() { return TokenType.importUrl_simbol + TokenType.importUrl_simbol; } + static get importUrl() { return `${TokenType.importUrl_simbol}import`; } + + static get push_symbol() { return '<<'; } + + static get push_DIR() { return `${TokenType.push_symbol}DIR`; } + static get push_DIRECTORY() { return `${TokenType.push_symbol}DIRECTORY`; } + static get push_dir() { return `${TokenType.push_symbol}dir`; } + static get push_directory() { return `${TokenType.push_symbol}directory`; } + + static get push_GH() { return `${TokenType.push_symbol}GH`; } + static get push_gh() { return `${TokenType.push_symbol}gh`; } + static get push_github() { return `${TokenType.push_symbol}github`; } + static get push_GITHUB() { return `${TokenType.push_symbol}GITHUB`; } + } module.exports = Object.freeze( TokenType ); diff --git a/merger-js.sln.licenseheader b/merger-js.sln.licenseheader new file mode 100644 index 0000000..1c7df3b --- /dev/null +++ b/merger-js.sln.licenseheader @@ -0,0 +1,8 @@ +extensions: .js +/* + * Copyright (c) 2018-2019 João Pedro Martins Neves - All Rights Reserved. + * + * MergerJS (merger-js) is licensed under the MIT license, located in + * the root of this project, under the name "LICENSE.md". + * + */ diff --git a/models/configKeysEnum.js b/models/configKeysEnum.js new file mode 100644 index 0000000..f6a854a --- /dev/null +++ b/models/configKeysEnum.js @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2018-2019 João Pedro Martins Neves - All Rights Reserved. + * + * MergerJS (merger-js) is licensed under the MIT license, located in + * the root of this project, under the name "LICENSE.md". + * + */ + +const configKeys = Object.freeze( { + minify: 'uglify', + autoBuild: 'autoBuild', + notifs: 'notifications', + updateOnLaunch: 'updateOnLaunch', + lastUpdateCheck: 'lastUpdateCheck', + nodeModulesPath: 'nodeModulesPath' +} ); + +module.exports = configKeys; diff --git a/models/parsedLineModel.js b/models/parsedLineModel.js new file mode 100644 index 0000000..7d77ea8 --- /dev/null +++ b/models/parsedLineModel.js @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018-2019 João Pedro Martins Neves - All Rights Reserved. + * + * MergerJS (merger-js) is licensed under the MIT license, located in + * the root of this project, under the name "LICENSE.md". + * + */ + +const ImportType = require( '../enums/importType' ); + +class ParsedLine { + + constructor() { + /** + * @type { boolean } + */ + this.isComment = null; + + /** + * @type { boolean } + */ + this.isDir = false; + + /** ImportType enum + * @type { number } ImportType enum + */ + this.importType = ImportType.Unknown; + + /** + * @type { boolean } + */ + this.forceInstall = false; + + /** + * @type { string | null } + */ + this.path = null; + + /** + * @type { string | null } + */ + this.directory = null; + + /** + * @type { string | null } + */ + this.branchName = null; + + /** + * @type { boolean | null } + **/ + this.isGithubNewSyntax = null; + } + +} + +module.exports = ParsedLine; diff --git a/models/promptResponseType.js b/models/promptResponseType.js new file mode 100644 index 0000000..39be905 --- /dev/null +++ b/models/promptResponseType.js @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2018-2019 João Pedro Martins Neves - All Rights Reserved. + * + * MergerJS (merger-js) is licensed under the MIT license, located in + * the root of this project, under the name "LICENSE.md". + * + */ + +const promptResponseType = Object.freeze( { + Afirmative: 'Yes', + Negative: 'No' +} ); + +module.exports = promptResponseType; diff --git a/models/staticClassBase.js b/models/staticClassBase.js index 76f19cb..5c2976e 100644 --- a/models/staticClassBase.js +++ b/models/staticClassBase.js @@ -1,4 +1,12 @@ -module.exports = class StaticClass { +/* + * Copyright (c) 2018-2019 João Pedro Martins Neves - All Rights Reserved. + * + * MergerJS (merger-js) is licensed under the MIT license, located in + * the root of this project, under the name "LICENSE.md". + * + */ + +module.exports = class StaticClass { /** * Throws an Error when instantiated. * diff --git a/modules/buildModules/importLineParser.js b/modules/buildModules/importLineParser.js new file mode 100644 index 0000000..53a8771 --- /dev/null +++ b/modules/buildModules/importLineParser.js @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2018-2019 João Pedro Martins Neves - All Rights Reserved. + * + * MergerJS (merger-js) is licensed under the MIT license, located in + * the root of this project, under the name "LICENSE.md". + * + */ + +const Utils = require( '../utils' ); +const TokenType = require( '../../enums/tokenType' ); +const ImportType = require( '../../enums/importType' ); +const ParsedLine = require( '../../models/parsedLineModel' ); + +class ImportLineParser { + + constructor() { + throw new Error( 'Can not intantiate a static class' ); + } + + /** + * + * @param { string } line + * + * @return { ParsedLine } + */ + static parse( line ) { + const parsedLine = new ParsedLine(); + parsedLine.isComment = line.trimStart().startsWith( '//' ); + + line = line.replace( /\s/g, '' ); + + if ( !parsedLine.isComment ) { + return parsedLine; + } + + // #region IMPORT FROM RELATIVE PATH OR DIRECTORY + + if ( line.startsWith( TokenType.importPath, 2 ) || line.startsWith( TokenType.importPath_simbol, 2 ) ) { + parsedLine.importType = ImportType.RelativePath; + line = Utils.removeImportFromInput( line ); + + // #endregion IMPORT FROM RELATIVE PATH OR DIRECTORY + + // #region IMPORT FROM node_modules + + } else if ( line.startsWith( TokenType.importNodeModules, 2 ) || line.startsWith( TokenType.importNodeModules_simbol, 2 ) ) { + parsedLine.importType = ImportType.NodeModules; + line = Utils.removeImportFromInput( line ); + + // #endregion IMPORT FROM node_modules + + // #region IMPORT FROM AN URL + + } else if ( line.startsWith( TokenType.importUrl, 2 ) || line.startsWith( TokenType.importUrl_simbol, 2 ) || line.startsWith( TokenType.doubleImportUrl_simbol, 2 ) ) { + parsedLine.forceInstall = line.startsWith( TokenType.doubleImportUrl_simbol, 2 ); + line = Utils.removeImportFromInput( line ); + + // #region GITHUB SYNTAX DEFENITION COMMENTS + + // SINTAX: + // // %import< } */ module.exports = ( Path, Callback ) => { - let NODE_MODULES_PATH = global.config.nodeModulesPath; - let lineNum = 0; - let lastLineWasComment = false; - let buildOrder = []; - buildOrder.push( path.basename( Path ) ); - - const rl = new lineByLine( Path, { - encoding: 'utf8', - skipEmptyLines: true - } ); + return new Promise( async ( _res, _rej ) => { + + let NODE_MODULES_PATH = global.config.nodeModulesPath; + let lineNum = 0; + let lastLineWasComment = false; + let buildOrder = []; + buildOrder.push( path.basename( Path ) ); + + const rl = new lineByLine( Path, { + encoding: 'utf8', + skipEmptyLines: true + } ); + + rl.on( 'line', async ( line ) => { + rl.pause(); + let thisFile = null; + /** @type { string } */ + let directotyPath = ''; + + const parsedLine = ImportLineParser.parse( line ); + + switch ( parsedLine.importType ) { + case ImportType.NodeModules: + case ImportType.SpecificURL: + case ImportType.GitHub: - rl.on( 'line', async ( line ) => { - rl.pause(); - let thisFile; - let treatedLine = line.replace( /\s/g, '' ); + try { + const createdNodeModules = await Utils.createNodeModulesIfNeeded(); - lastLineWasComment = treatedLine.trimStart().startsWith( '//' ); + if ( createdNodeModules ) { + NODE_MODULES_PATH = global.config.nodeModulesPath; + await addPropertyToConfig( ConfigKeysType.nodeModulesPath, NODE_MODULES_PATH ); + } - // #region IMPORT FROM RELATIVE PATH OR DIRECTORY + } catch ( e ) { + return ____nodeModulesCreationError( line ); + } - if ( treatedLine.startsWith( '@import', 2 ) || treatedLine.startsWith( '@', 2 ) ) { - treatedLine = Utils.removeImportFromInput( treatedLine ); + break; - // FROM A DIRECTORY. - const wasDir = await ____addAllDirectoryToBuildOrder( buildOrder, Path, treatedLine ); - if ( wasDir ) - thisFile = null; - else - // FROM A RELATIVE FILE PATH. - thisFile = Utils.cleanImportFileInput( treatedLine ); + default: + break; + } - ++lineNum; + switch ( parsedLine.importType ) { - // #endregion + case ImportType.RelativePath: + directotyPath = Path; + break; - // #region IMPORT FROM node_modules + case ImportType.NodeModules: + directotyPath = NODE_MODULES_PATH; + break; - } else if ( treatedLine.startsWith( '$import', 2 ) || treatedLine.startsWith( '$', 2 ) ) { - treatedLine = Utils.removeImportFromInput( treatedLine ); + case ImportType.SpecificURL: + directotyPath = NODE_MODULES_PATH; + const fileName = Utils.getFileNameFromUrl( parsedLine.path ); - try { - const createdNodeModules = await Utils.createNodeModulesIfNeeded(); - if ( createdNodeModules ) { - NODE_MODULES_PATH = global.config.nodeModulesPath; - await addPropertyToConfig( ConfigKeysType.nodeModulesPath, NODE_MODULES_PATH ); - } + let fileExists = true; + if ( !parsedLine.forceInstall ) { + fileExists = await Utils.fileExists( path.join( NODE_MODULES_PATH, fileName ) ); + } - // AN ENTIRE DIRECTORY. - const wasDir = await ____addAllDirectoryToBuildOrder( buildOrder, NODE_MODULES_PATH, treatedLine ); - if ( wasDir ) - thisFile = null; - else { - // A FILE. - thisFile = Utils.cleanImportFileInput( treatedLine ); - thisFile = path.join( NODE_MODULES_PATH, thisFile ); - } + if ( !fileExists || parsedLine.forceInstall ) { + try { + await fileDownloader.fromUrl( parsedLine.path ); - } catch ( e ) { - return ____nodeModulesCreationError( thisFile ); - } + } catch ( e ) { + console.error( style.styledError, `There was an error while downloading a file from url ("${url}")\n`, e ); + } + } - ++lineNum; + parsedLine.path = fileName; + break; - // #endregion + case ImportType.GitHub: + const splitedPath = parsedLine.path.split( '/' ); + const pathToFile = splitedPath.slice( 2 ).join( '/' ); - // #region IMPORT FROM AN URL + /** + * The name of the folder where the file(s) will be stored on node_modules. + * @type { string } + */ + const repoDirName = path.join( Utils.buildGithubRepoDirName( splitedPath[0], splitedPath[1] ) ); + directotyPath = path.join( NODE_MODULES_PATH, repoDirName ); - } else if ( treatedLine.startsWith( '%import', 2 ) || treatedLine.startsWith( '%', 2 ) || treatedLine.startsWith( '%%', 2 ) ) { - const forceInstall = treatedLine.startsWith( '%%', 2 ); - treatedLine = Utils.removeImportFromInput( treatedLine ); + // #region GITHUB FILES - try { - const createdNodeModules = await Utils.createNodeModulesIfNeeded(); - if ( createdNodeModules ) { - NODE_MODULES_PATH = global.config.nodeModulesPath; - await addPropertyToConfig( ConfigKeysType.nodeModulesPath, NODE_MODULES_PATH ); - } + if ( !parsedLine.isDir ) { + const fileName = path.basename( parsedLine.path ); + let alreadyDowloadedDeprecatedSyntax = false; + let alreadyDowloadedNewSyntax = false; - } catch ( e ) { - return ____nodeModulesCreationError( line ); - } + if ( !parsedLine.forceInstall && parsedLine.isGithubNewSyntax ) { + alreadyDowloadedNewSyntax = await Utils.fileExists( path.join( directotyPath, pathToFile ) ); - //#region FROM GITHUB - // // %import<= 20 && !lastLineWasComment ) { + rl.close(); + } - rl.resume(); + } ); - if ( lineNum >= 20 && !lastLineWasComment ) - rl.close(); + rl.on( 'end', () => { + if ( Callback ) { + return Callback( buildOrder ); + } - } ); + return _res( buildOrder ); + } ); - rl.on( 'end', () => { - return Callback( buildOrder ); } ); }; -const ____pathIsDir = ( treatedLine ) => { - return treatedLine.startsWith( '< { - if ( !____pathIsDir( treatedLine ) ) - return false; - - treatedLine = Utils.removeDirTokenFromImport( treatedLine ); - treatedLine = Utils.cleanImportFileInput( treatedLine ); // treatedLine now holds the directory inputed by the user. const thisDir = path.join( path.dirname( thePath ), treatedLine ); @@ -282,18 +260,30 @@ const ____addAllDirectoryToBuildOrder = async ( buildOrder, thePath, treatedLine const files = await Utils.readDir( thisDir ); for ( let i = 0; i < files.length; ++i ) { - if ( path.extname( files[i] ) === '.js' ) + if ( path.extname( files[i] ) === '.js' ) { buildOrder.push( path.join( treatedLine, files[i] ) ); + } } } catch ( e ) { - console.error( style.styledError, `There was an error while reading the file names from the directory: "${thisDir}". Probably it does not exist.\n\n`, e ); - killProcess(); + console.error( + style.styledError, + `There was an error while reading the file names from the directory: "${thisDir}". Probably it does not exist.\n\n`, + e + ); + + return killProcess(); } return true; }; +/** + * Prinsts the node_modules file creation error. + * @param { string } fileName The file name where the error occured. + * + * @returns { void } Logs the error to the console. + */ const ____nodeModulesCreationError = ( fileName ) => { return console.error( style.styledError, @@ -307,5 +297,10 @@ const killProcess = () => { process.kill( process.pid, 'SIGINT' ); setTimeout( () => { process.kill( process.pid, 'SIGKILL' ); + return false; }, 5000 ); + + return false; }; + +// #endregion HELPER FUNCTIONS diff --git a/modules/config.js b/modules/config.js index 1df323a..f7b1d7c 100644 --- a/modules/config.js +++ b/modules/config.js @@ -52,7 +52,7 @@ module.exports = ( newConfig, Callback ) => { } } - // TODO: Remove on v4, along with all other methods of not adding breaking changes (if there is one). + // TODO: Remove on v4 (if there is one), along with all other methods of not adding breaking changes. // This was add in order to not add breaking changes. } else { // Set to true by default. diff --git a/modules/fileDownloader.js b/modules/fileDownloader.js index c216540..be6796f 100644 --- a/modules/fileDownloader.js +++ b/modules/fileDownloader.js @@ -57,16 +57,11 @@ class FileDownloader { * @returns { Promise } * @deprecated */ - static fromGitHub_deprecated( path, branch, Callback ) { + static fromGitHub_deprecated( path, Callback ) { return new Promise( async ( resolve, reject ) => { - if ( path.startsWith( '/' ) ) + if ( path.startsWith( '/' ) ) { path = path.substring( 1 ); - - if ( branch !== '' ) { - path = path.split( '/' ); - path.splice( 2, 0, branch ); - path = path.join( '/' ); } let url = HOST_RAW_GITHUB + path; @@ -78,16 +73,19 @@ class FileDownloader { if ( fileContent.statusCode === 404 ) { path = path.split( '/' ); + // If the download was not successfull, try to add the master branch. path.splice( 2, 0, 'master' ); url = HOST_RAW_GITHUB + path.join( '/' ); try { fileContent = await httpClient.getAsync( url, false ); - if ( fileContent.statusCode === 404 ) + if ( fileContent.statusCode === 404 ) { FileDownloader.githubDownloadError( new URL( url ).pathname, 'The file was not found (404).' ); - else if ( fileContent.statusCode !== 200 ) + + } else if ( fileContent.statusCode !== 200 ) { FileDownloader.githubDownloadError( new URL( url ).pathname ); + } } catch ( e ) { FileDownloader.githubDownloadError( new URL( url ).pathname, e ); @@ -121,6 +119,7 @@ class FileDownloader { // https://api.github.com/repos/{user}/{repoName}/contents{pathToFile}?ref={branch} /** * Downloads a file or directory of files from github and save it/them to node_modules. + * Returns all the files with a complete directory relative to node_modules. * * @param { string[] } buildOrder * @param { string } user @@ -157,6 +156,7 @@ class FileDownloader { currentFilePath = path_join( thisRepoDirName, jsonApiResponse[i].path ); currentFileContent = await httpClient.getAsync( jsonApiResponse[i].download_url ); + await Utils.saveFileInNodeModules( currentFilePath, currentFileContent.body ); currentFilePath = path_join( NODE_MODULES_PATH, currentFilePath ); allFilePaths.push( currentFilePath ); diff --git a/modules/utils.js b/modules/utils.js index 2d9b599..525d2ff 100644 --- a/modules/utils.js +++ b/modules/utils.js @@ -20,6 +20,7 @@ class Utils extends StaticClass { } /** + * Reads the requested directory and returns an array of all its file names. * @param { string } path The directory path. * @param { Function } Callback Optional. (err, files[]) * @@ -81,6 +82,46 @@ class Utils extends StaticClass { } ); } + /** + * + * @param { string } filePath + * + * @returns { Promise } + */ + static fileStat( filePath ) { + return new Promise( ( _res, _rej ) => { + fs.stat( filePath, async ( err, stats ) => { + if ( err ) { + return _rej( err ); + } + + return _res( stats ); + } ); + } ); + } + + /** + * Deletes the requested file. + * @param { string } filePath + * + * @returns { Promise } + */ + static deleteFile( filePath ) { + return new Promise( ( _res, _rej ) => { + fs.unlink( filePath, ( err ) => { + if ( err ) { + return _rej( err ); + } + + return _res(); + } ); + } ); + } + + static isNullOrEmptyStr( str ) { + return str === null || str === undefined || str === ''; + } + // Based on npm's strip-bom. /** * Remove unicode character FEFF (UTF-16 BOM) from a string block. diff --git a/package-lock.json b/package-lock.json index 142bd3b..ddab4dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "merger-js", - "version": "3.8.4", + "version": "3.8.5", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -79,18 +79,18 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" }, "chokidar": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.2.1.tgz", - "integrity": "sha512-/j5PPkb5Feyps9e+jo07jUZGvkB5Aj953NrI4s8xSVScrAo/RHeILrtdb4uzR7N6aaFFxxJ+gt8mA8HfNpw76w==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.2.2.tgz", + "integrity": "sha512-bw3pm7kZ2Wa6+jQWYP/c7bAZy3i4GwiIiMO2EeRjrE48l8vBqC/WvFhSF0xyM8fQiPEGvwMY/5bqDG7sSEOuhg==", "requires": { "anymatch": "~3.1.1", "braces": "~3.0.2", - "fsevents": "~2.1.0", + "fsevents": "~2.1.1", "glob-parent": "~5.1.0", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.1.3" + "readdirp": "~3.2.0" } }, "cli-cursor": { @@ -173,9 +173,9 @@ "dev": true }, "fsevents": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.0.tgz", - "integrity": "sha512-+iXhW3LuDQsno8dOIrCIT/CBjeBWuP7PXe8w9shnj9Lebny/Gx1ZjVBYwexLz36Ri2jKuXMNpV6CYNh8lHHgrQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.1.tgz", + "integrity": "sha512-4FRPXWETxtigtJW/gxzEDsX1LVbPAM93VleB83kZB+ellqbHMkyt2aJfuzNLRvFPnGi6bcE5SvfxgbXPeKteJw==", "optional": true }, "glob": { @@ -406,9 +406,9 @@ "integrity": "sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==" }, "readdirp": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.1.3.tgz", - "integrity": "sha512-ZOsfTGkjO2kqeR5Mzr5RYDbTGYneSkdNKX2fOX2P5jF7vMrd/GNnIAUtDldeHHumHUCQ3V05YfWUdxMPAsRu9Q==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", + "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", "requires": { "picomatch": "^2.0.4" } diff --git a/package.json b/package.json index b3e22fb..5ea943f 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "merger-js", "displayName": "MergerJS", - "version": "3.8.4", - "description": "Yet another lightweight and simple cross-platform CLI build tool to bundle JavaScript files, with file imports, ES6+ minification, auto build capabilities, and native OS notifications.", + "version": "3.8.5", + "description": "Yet another simple cross-platform CLI build tool to bundle JavaScript files, with a custom file import syntax, ES8+ minification, auto build capabilities, and native OS notifications.", "readme": "https://github.com/joao-neves95/merger-js/blob/master/README.md", "main": "merger.js", "bin": { @@ -16,7 +16,8 @@ }, "scripts": { "start": "merger init", - "test": "npm audit && node tests/test.js" + "test": "npm audit && node tests/test.js", + "update": "merger update" }, "author": { "name": "shivayl", @@ -34,7 +35,7 @@ "deprecated": false, "dependencies": { "chalk": "^2.4.2", - "chokidar": "^3.0.1", + "chokidar": "^3.2.1", "commander": "^3.0.2", "inquirer": "^7.0.0", "js.system.collections": "^1.0.0", diff --git a/tests/data/mockImports.js b/tests/data/mockImports.js index cf88236..547b63f 100644 --- a/tests/data/mockImports.js +++ b/tests/data/mockImports.js @@ -6,12 +6,12 @@ module.exports = class MockImports extends StaticClass { super( 'MockImports' ); } - static relative_DIR( path ) { return `// ${TokenType.token_importPath}${TokenType.token_DIR} '${path}'`; } - static relative_dir( path ) { return `// ${TokenType.token_importPath}${TokenType.token_dir} '${path}'`; } - static relative_DIRECTORY( path ) { return `// ${TokenType.token_importPath}${TokenType.token_DIRECTORY} '${path}'`; } - static relative_directory( path ) { return `// ${TokenType.token_importPath}${TokenType.token_directory} '${path}'`; } + static relative_DIR( path ) { return `// ${TokenType.importPath}${TokenType.push_DIR} '${path}'`; } + static relative_dir( path ) { return `// ${TokenType.importPath}${TokenType.push_dir} '${path}'`; } + static relative_DIRECTORY( path ) { return `// ${TokenType.importPath}${TokenType.push_DIRECTORY} '${path}'`; } + static relative_directory( path ) { return `// ${TokenType.importPath}${TokenType.push_directory} '${path}'`; } - static github_DIR( path ) { return `// ${TokenType.token_importUrl_simbol}${TokenType.token_github}${TokenType.token_DIR} '${path}'` } - static GH_dir( path ) { return `// ${TokenType.token_importUrl}${TokenType.token_GH}${TokenType.token_dir} '${path}'` } + static github_DIR( path ) { return `// ${TokenType.importUrl_simbol}${TokenType.push_github}${TokenType.push_DIR} '${path}'` } + static GH_dir( path ) { return `// ${TokenType.importUrl}${TokenType.push_GH}${TokenType.push_dir} '${path}'` } }; diff --git a/tests/spec/config_spec.js b/tests/spec/config_spec.js index 5f28270..236a224 100644 --- a/tests/spec/config_spec.js +++ b/tests/spec/config_spec.js @@ -1 +1,8 @@ - \ No newline at end of file +/* + * Copyright (c) 2018-2019 João Pedro Martins Neves - All Rights Reserved. + * + * MergerJS (merger-js) is licensed under the MIT license, located in + * the root of this project, under the name "LICENSE.md". + * + */ + diff --git a/tests/spec/fileDownloader_spec.js b/tests/spec/fileDownloader_spec.js index 5f28270..236a224 100644 --- a/tests/spec/fileDownloader_spec.js +++ b/tests/spec/fileDownloader_spec.js @@ -1 +1,8 @@ - \ No newline at end of file +/* + * Copyright (c) 2018-2019 João Pedro Martins Neves - All Rights Reserved. + * + * MergerJS (merger-js) is licensed under the MIT license, located in + * the root of this project, under the name "LICENSE.md". + * + */ + diff --git a/tests/spec/httpClient_spec.js b/tests/spec/httpClient_spec.js index 5f28270..236a224 100644 --- a/tests/spec/httpClient_spec.js +++ b/tests/spec/httpClient_spec.js @@ -1 +1,8 @@ - \ No newline at end of file +/* + * Copyright (c) 2018-2019 João Pedro Martins Neves - All Rights Reserved. + * + * MergerJS (merger-js) is licensed under the MIT license, located in + * the root of this project, under the name "LICENSE.md". + * + */ + diff --git a/tests/spec/minifyCode_spec.js b/tests/spec/minifyCode_spec.js index cccab32..dde2137 100644 --- a/tests/spec/minifyCode_spec.js +++ b/tests/spec/minifyCode_spec.js @@ -1,4 +1,12 @@ -const minifyCode = require( '../../modules/buildModules/minifyCode' ); +/* + * Copyright (c) 2018-2019 João Pedro Martins Neves - All Rights Reserved. + * + * MergerJS (merger-js) is licensed under the MIT license, located in + * the root of this project, under the name "LICENSE.md". + * + */ + +const minifyCode = require( '../../modules/buildModules/minifyCode' ); const UNMINIFIED_CODE = 'function f(a, b, x, y) { return a < b && x > y; }'; const MINIFIED_CODE = 'function f(n,f,r,t){return nt}'; diff --git a/tests/spec/parseImports_spec.js b/tests/spec/parseImports_spec.js index c5e2b51..0c897a0 100644 --- a/tests/spec/parseImports_spec.js +++ b/tests/spec/parseImports_spec.js @@ -1,8 +1,15 @@ +/* + * Copyright (c) 2018-2019 João Pedro Martins Neves - All Rights Reserved. + * + * MergerJS (merger-js) is licensed under the MIT license, located in + * the root of this project, under the name "LICENSE.md". + * + */ + const path = require( 'path' ); const fs = require( 'fs' ); const parseImports = require( '../../modules/buildModules/parseImports' ); -const { fileExists } = require( '../../modules/utils' ); - +const Utils = require( '../../modules/utils' ); const DATA_DIR_PATH = path.join( __dirname, path.normalize( '../data' ) ); const HEADER_FILES_DIR_PATH = path.join( DATA_DIR_PATH, '/headerFiles' ); const NODE_MODULES_PATH = path.join( DATA_DIR_PATH, '/node_modules' ); @@ -19,8 +26,6 @@ describe( 'ParseImports', () => { } ); - // TODO: (Tests) Add the token tests on all the buildOrder files output (reuse between utils_spec.js). - it( 'Should parse file path imports, relative to the header file.', () => { parseImports( path.join( HEADER_FILES_DIR_PATH, 'relativeFilePaths.header.js' ), ( buildOrder ) => { @@ -76,28 +81,50 @@ describe( 'ParseImports', () => { } ); it( 'Should parse a URL file import, download the file and cache it in the node_modules folder.', async () => { - await __parseImportsUrlsTest( 'specificUrlPaths.header.js', [path.join( NODE_MODULES_PATH, 'jquery.min.js' )] ); + const filePath = path.join( NODE_MODULES_PATH, 'jquery.min.js' ); + await __parseImportsUrlsTest( 'specificUrlPaths.header.js', [filePath] ); + await Utils.deleteFile( filePath ); } ); it( 'Should parse a GitHub file path, download it and cache it into the node_modules folder.', async () => { - await __parseImportsUrlsTest( 'githubFilePath.header.js', [path.join( NODE_MODULES_PATH, 'twbs@bootstrap/dist/js/bootstrap.min.js' )] ); - await ____removeBootsrapFolder(); + await ____removeBootsrapFolder( await __parseImportsUrlsTest( + 'githubFilePath.header.js', + [path.join( NODE_MODULES_PATH, 'twbs@bootstrap/dist/js/bootstrap.min.js' )] + ) ); } ); - it( 'Should parse an entire GitHub directory path, download it and cache it into the node_modules folder.', async () => { - await __parseImportsUrlsTest( 'githubDirPath.header.js', - [ - path.join( NODE_MODULES_PATH, 'twbs@bootstrap/dist/js/bootstrap.js' ), - path.join( NODE_MODULES_PATH, 'twbs@bootstrap/dist/js/bootstrap.min.js' ), - path.join( NODE_MODULES_PATH, 'twbs@bootstrap/dist/js/bootstrap.esm.min.js' ), - path.join( NODE_MODULES_PATH, 'twbs@bootstrap/dist/js/bootstrap.esm.js' ), - path.join( NODE_MODULES_PATH, 'twbs@bootstrap/dist/js/bootstrap.bundle.js' ), - path.join( NODE_MODULES_PATH, 'twbs@bootstrap/dist/js/bootstrap.bundle.min.js' ) - ] - ); - - await ____removeBootsrapFolder(); - } ); + it( 'Should parse an entire GitHub directory path, download it and cache it into the node_modules folder.\n' + + 'After that, it should parse an existing GitHub directory path cached in the node_modules folder, not downloading it.', + async () => { + const headerFilePath = 'githubDirPath.header.js'; + const cacheFolderPath = path.join( NODE_MODULES_PATH, 'twbs@bootstrap/dist/js/' ); + + await __parseImportsUrlsTest( headerFilePath, + [ + path.join( NODE_MODULES_PATH, 'twbs@bootstrap/dist/js/bootstrap.js' ), + path.join( NODE_MODULES_PATH, 'twbs@bootstrap/dist/js/bootstrap.min.js' ), + path.join( NODE_MODULES_PATH, 'twbs@bootstrap/dist/js/bootstrap.esm.min.js' ), + path.join( NODE_MODULES_PATH, 'twbs@bootstrap/dist/js/bootstrap.esm.js' ), + path.join( NODE_MODULES_PATH, 'twbs@bootstrap/dist/js/bootstrap.bundle.js' ), + path.join( NODE_MODULES_PATH, 'twbs@bootstrap/dist/js/bootstrap.bundle.min.js' ) + ] + ); + + const buildOrder = await parseImports( path.join( HEADER_FILES_DIR_PATH, headerFilePath ) ); + + const stats = await Utils.fileStat( buildOrder[1] ); + + expect( stats.mtime ).toEqual( stats.ctime ); + expect( stats.mtimeMs ).toEqual( stats.ctimeMs ); + + const allFileNames = await Utils.readDir( cacheFolderPath ); + allFileNames.forEach( ( item, i ) => { + allFileNames[i] = cacheFolderPath + item; + } ); + + await ____removeBootsrapFolder( allFileNames ); + } + ); afterAll( () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout; @@ -105,10 +132,15 @@ describe( 'ParseImports', () => { } ); +// #region HELPER FUNCTIONS + /** + * Checks if the files exists to confirm if it was successfull. * * @param { string } headerFile The header file path, with all the imports. * @param { string[] } downloadedFilePaths The path location where the downloaded file should be. + * + * @return { Promise } */ const __parseImportsUrlsTest = ( headerFile, downloadedFilePaths ) => { return new Promise( ( _resolve, _reject ) => { @@ -121,12 +153,16 @@ const __parseImportsUrlsTest = ( headerFile, downloadedFilePaths ) => { let downloadSuccessful = false; let downloadFileError = null; + let currentLink = ''; try { for ( let i = 0; i < downloadedFilePaths.length; ++i ) { - downloadSuccessful = await fileExists( downloadedFilePaths[i] ); + currentLink = downloadedFilePaths[i]; + downloadSuccessful = await Utils.fileExists( downloadedFilePaths[i] ); - if ( !downloadSuccessful ) break; + if ( !downloadSuccessful ) { + break; + } } } catch ( e ) { @@ -134,32 +170,25 @@ const __parseImportsUrlsTest = ( headerFile, downloadedFilePaths ) => { downloadFileError = e; } - expect( downloadSuccessful ).toEqual( true, 'ParseImports > URL file import > Download file : FAILED, Error:\n' + downloadFileError ); + expect( downloadSuccessful ).toEqual( true, `ParseImports > URL file import > URL: ${currentLink} ; Download file : FAILED, Error:\n ${downloadFileError}` ); if ( downloadSuccessful ) { - const ____validateFileAsync = ( downloadedFilePath) => { + const ____validateFileAsync = ( downloadedFilePath ) => { return new Promise( ( _res, _rej ) => { + fs.readFile( downloadedFilePath, 'utf8', ( err, data ) => { if ( err ) - return _reject( err ); + return _rej( err ); expect( data ).not.toBeNull(); expect( data ).toBeDefined(); expect( data ).not.toEqual( '404: Not Found\n' ); expect( data.length ).toBeGreaterThan( 50 ); - // Delete the downloaded file. - fs.unlink( downloadedFilePath, ( err ) => { - if ( err ) { - console.error( 'ParseImports > URL file import > (delete downloaded file) : FAILED, Error:' ); - console.error( err ); - return _rej( err ); - } - - return _res(); - } ); + return _res(); } ); + } ); }; @@ -167,7 +196,7 @@ const __parseImportsUrlsTest = ( headerFile, downloadedFilePaths ) => { await ____validateFileAsync( downloadedFilePaths[i] ); } - return _resolve(); + return _resolve( downloadedFilePaths ); } return _reject( downloadFileError ); @@ -176,10 +205,15 @@ const __parseImportsUrlsTest = ( headerFile, downloadedFilePaths ) => { } ); }; -const ____removeBootsrapFolder = () => { - return new Promise( ( _res, _rej ) => { +const ____removeBootsrapFolder = ( allFiles ) => { + return new Promise( async ( _res, _rej ) => { // This is orrible and all hardcoded as #uck. // TODO: Redo this test data removal part. + + for ( let i = 0; i < allFiles.length; ++i ) { + await Utils.deleteFile( allFiles[i] ); + } + fs.rmdir( path.join( NODE_MODULES_PATH, 'twbs@bootstrap/dist/js' ), ( err ) => { fs.rmdir( path.join( NODE_MODULES_PATH, 'twbs@bootstrap/dist/' ), ( errr ) => { fs.rmdir( path.join( NODE_MODULES_PATH, 'twbs@bootstrap/' ), ( errrr ) => { @@ -193,5 +227,8 @@ const ____removeBootsrapFolder = () => { } ); } ); } ); + } ); }; + +// #endregion HELPER FUNCTIONS diff --git a/tests/spec/utils_spec.js b/tests/spec/utils_spec.js index c4b5e67..b727f7d 100644 --- a/tests/spec/utils_spec.js +++ b/tests/spec/utils_spec.js @@ -1,4 +1,12 @@ -const Utils = require( '../../modules/utils' ); +/* + * Copyright (c) 2018-2019 João Pedro Martins Neves - All Rights Reserved. + * + * MergerJS (merger-js) is licensed under the MIT license, located in + * the root of this project, under the name "LICENSE.md". + * + */ + +const Utils = require( '../../modules/utils' ); const TokenType = require( '../../enums/tokenType' ); const MockImports = require( '../data/mockImports' ); @@ -12,22 +20,22 @@ describe( 'Utils', () => { } ); it( 'Should remove all "import" tokens types from the import input.', () => { - expect( Utils.removeImportFromInput( MockImports.relative_DIR( RANDOM_PATH_1 ) ) ).not.toContain( TokenType.token_importPath ); - expect( Utils.removeImportFromInput( MockImports.github_DIR( RANDOM_LINK_1 ) ) ).not.toContain( TokenType.token_importUrl_simbol ); - expect( Utils.removeImportFromInput( MockImports.GH_dir( RANDOM_LINK_1 ) ) ).not.toContain( TokenType.token_importUrl ); + expect( Utils.removeImportFromInput( MockImports.relative_DIR( RANDOM_PATH_1 ) ) ).not.toContain( TokenType.importPath ); + expect( Utils.removeImportFromInput( MockImports.github_DIR( RANDOM_LINK_1 ) ) ).not.toContain( TokenType.importUrl_simbol ); + expect( Utils.removeImportFromInput( MockImports.GH_dir( RANDOM_LINK_1 ) ) ).not.toContain( TokenType.importUrl ); } ); it( 'Should remove all GITHUB tokens from the import input.', () => { - expect( Utils.removeGithubTokenFromImport( MockImports.github_DIR( RANDOM_LINK_1 ) ) ).not.toContain( TokenType.token_github ); - expect( Utils.removeGithubTokenFromImport( MockImports.GH_dir( RANDOM_LINK_1 ) ) ).not.toContain( TokenType.token_GH ); + expect( Utils.removeGithubTokenFromImport( MockImports.github_DIR( RANDOM_LINK_1 ) ) ).not.toContain( TokenType.push_symbol_github ); + expect( Utils.removeGithubTokenFromImport( MockImports.GH_dir( RANDOM_LINK_1 ) ) ).not.toContain( TokenType.push_symbol_GH ); } ); it( 'Should remove all DIRECTORY tokens from the import input.', () => { - expect( Utils.removeDirTokenFromImport( MockImports.relative_dir( RANDOM_PATH_1 )) ).not.toContain( TokenType.token_dir ); - expect( Utils.removeDirTokenFromImport( MockImports.relative_DIR( RANDOM_PATH_1 ) ) ).not.toContain( TokenType.token_DIR ); - expect( Utils.removeDirTokenFromImport( MockImports.github_DIR( RANDOM_LINK_1 ) ) ).not.toContain( TokenType.token_DIR ); - expect( Utils.removeDirTokenFromImport( MockImports.relative_DIRECTORY( RANDOM_PATH_1 ) ) ).not.toContain( TokenType.token_DIRECTORY ); - expect( Utils.removeDirTokenFromImport( MockImports.relative_directory( RANDOM_PATH_1 ) ) ).not.toContain( TokenType.token_directory ); + expect( Utils.removeDirTokenFromImport( MockImports.relative_dir( RANDOM_PATH_1 ) ) ).not.toContain( TokenType.push_symbol_dir ); + expect( Utils.removeDirTokenFromImport( MockImports.relative_DIR( RANDOM_PATH_1 ) ) ).not.toContain( TokenType.push_symbol_DIR ); + expect( Utils.removeDirTokenFromImport( MockImports.github_DIR( RANDOM_LINK_1 ) ) ).not.toContain( TokenType.push_symbol_DIR ); + expect( Utils.removeDirTokenFromImport( MockImports.relative_DIRECTORY( RANDOM_PATH_1 ) ) ).not.toContain( TokenType.push_symbol_DIRECTORY ); + expect( Utils.removeDirTokenFromImport( MockImports.relative_directory( RANDOM_PATH_1 ) ) ).not.toContain( TokenType.push_symbol_directory ); } ); it( 'Should read an entire directory.', async () => {